diff --git a/.annotaterb.yml b/.annotaterb.yml new file mode 100644 index 0000000000..df8e92b247 --- /dev/null +++ b/.annotaterb.yml @@ -0,0 +1,59 @@ +--- +:position: before +:position_in_additional_file_patterns: before +:position_in_class: before +:position_in_factory: before +:position_in_fixture: before +:position_in_routes: before +:position_in_serializer: before +:position_in_test: before +:classified_sort: true +:exclude_controllers: true +:exclude_factories: true +:exclude_fixtures: true +:exclude_helpers: true +:exclude_scaffolds: true +:exclude_serializers: true +:exclude_sti_subclasses: true +:exclude_tests: true +:force: false +:format_markdown: false +:format_rdoc: false +:format_yard: false +:frozen: false +:ignore_model_sub_dir: false +:ignore_unknown_models: false +:include_version: false +:show_complete_foreign_keys: false +:show_foreign_keys: false +:show_indexes: false +:simple_indexes: false +:sort: false +:timestamp: false +:trace: false +:with_comment: true +:with_column_comments: true +:with_table_comments: true +:active_admin: false +:command: +:debug: false +:hide_default_column_types: '' +:hide_limit_column_types: 'integer,boolean' +:ignore_columns: +:ignore_routes: +:models: true +:routes: false +:skip_on_db_migrate: false +:target_action: :do_annotations +:wrapper: +:wrapper_close: +:wrapper_open: +:classes_default_to_s: [] +:additional_file_patterns: [] +:model_dir: + - app/models +:require: [] +:root_dir: + - '' + +:show_check_constraints: false diff --git a/.devcontainer/compose.yaml b/.devcontainer/compose.yaml index 5c7263c874..705d26e0ab 100644 --- a/.devcontainer/compose.yaml +++ b/.devcontainer/compose.yaml @@ -69,7 +69,7 @@ services: hard: -1 libretranslate: - image: libretranslate/libretranslate:v1.6.1 + image: libretranslate/libretranslate:v1.6.2 restart: unless-stopped volumes: - lt-data:/home/libretranslate/.local diff --git a/.github/workflows/build-container-image.yml b/.github/workflows/build-container-image.yml index 03a0f5bf37..6204319a63 100644 --- a/.github/workflows/build-container-image.yml +++ b/.github/workflows/build-container-image.yml @@ -92,6 +92,7 @@ jobs: build-args: | MASTODON_VERSION_PRERELEASE=${{ inputs.version_prerelease }} MASTODON_VERSION_METADATA=${{ inputs.version_metadata }} + SOURCE_COMMIT=${{ github.sha }} platforms: ${{ inputs.platforms }} provenance: false builder: ${{ steps.buildx.outputs.name || steps.buildx-native.outputs.name }} 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 0fc5291d72..0696f0b31c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,48 @@ All notable changes to this project will be documented in this file. +## [4.3.1] - 2024-10-21 + +### Added + +- Add more explicit explanations about author attribution and `fediverse:creator` (#32383 by @ClearlyClaire) +- Add ability to group follow notifications in WebUI, can be disabled in the column settings (#32520 by @renchap) +- Add back a 6 hours mute duration option (#32522 by @renchap) +- Add note about not changing ActiveRecord encryption secrets once they are set (#32413, #32476, #32512, and #32537 by @ClearlyClaire and @mjankowski) + +### Changed + +- Change translation feature to translate to selected regional variant (e.g. pt-BR) if available (#32428 by @c960657) + +### Removed + +- Remove ability to get embed code for remote posts (#32578 by @ClearlyClaire)\ + Getting the embed code is only reliable for local posts.\ + It never worked for non-Mastodon servers, and stopped working correctly with the changes made in 4.3.0.\ + We have therefore decided to remove the menu entry while we investigate solutions. + +### Fixed + +- Fix follow recommendation moderation page default language when using regional variant (#32580 by @ClearlyClaire) +- Fix column-settings spacing in local timeline in advanced view (#32567 by @lindwurm) +- Fix broken i18n in text welcome mailer tags area (#32571 by @mjankowski) +- Fix missing or incorrect cache-control headers for Streaming server (#32551 by @ThisIsMissEm) +- Fix only the first paragraph being displayed in some notifications (#32348 by @ClearlyClaire) +- Fix reblog icons on account media view (#32506 by @tribela) +- Fix Content-Security-Policy not allowing OpenStack SWIFT object storage URI (#32439 by @kenkiku1021) +- Fix back arrow pointing to the incorrect direction in RTL languages (#32485 by @renchap) +- Fix streaming server using `REDIS_USERNAME` instead of `REDIS_USER` (#32493 by @ThisIsMissEm) +- Fix follow recommendation carrousel scrolling on RTL layouts (#32462 and #32505 by @ClearlyClaire) +- Fix follow recommendation suppressions not applying immediately (#32392 by @ClearlyClaire) +- Fix language of push notifications (#32415 by @ClearlyClaire) +- Fix mute duration not being shown in list of muted accounts in web UI (#32388 by @ClearlyClaire) +- Fix “Mark every notification as read” not updating the read marker if scrolled down (#32385 by @ClearlyClaire) +- Fix “Mention” appearing for otherwise filtered posts (#32356 by @ClearlyClaire) +- Fix notification requests from suspended accounts still being listed (#32354 by @ClearlyClaire) +- Fix list edition modal styling (#32358 and #32367 by @ClearlyClaire and @vmstan) +- Fix 4 columns barely not fitting on 1920px screen (#32361 by @ClearlyClaire) +- Fix icon alignment in applications list (#32293 by @mjankowski) + ## [4.3.0] - 2024-10-08 The following changelog entries focus on changes visible to users, administrators, client developers or federated software developers, but there has also been a lot of code modernization, refactoring, and tooling work, in particular by @mjankowski. diff --git a/Dockerfile b/Dockerfile index c6d8466f43..c91f10de0f 100644 --- a/Dockerfile +++ b/Dockerfile @@ -12,7 +12,7 @@ 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="22" @@ -29,6 +29,8 @@ FROM docker.io/ruby:${RUBY_VERSION}-slim-${DEBIAN_VERSION} AS ruby ARG MASTODON_VERSION_PRERELEASE="" # Append build metadata or fork information to version.rb [--build-arg MASTODON_VERSION_METADATA="pr-123456"] ARG MASTODON_VERSION_METADATA="" +# Will be available as Mastodon::Version.source_commit +ARG SOURCE_COMMIT="" # Allow Ruby on Rails to serve static files # See: https://docs.joinmastodon.org/admin/config/#rails_serve_static_files @@ -45,30 +47,31 @@ ARG GID="991" # Apply Mastodon build options based on options above ENV \ -# Apply Mastodon version information + # Apply Mastodon version information MASTODON_VERSION_PRERELEASE="${MASTODON_VERSION_PRERELEASE}" \ MASTODON_VERSION_METADATA="${MASTODON_VERSION_METADATA}" \ -# Apply Mastodon static files and YJIT options + SOURCE_COMMIT="${SOURCE_COMMIT}" \ + # Apply Mastodon static files and YJIT options RAILS_SERVE_STATIC_FILES=${RAILS_SERVE_STATIC_FILES} \ RUBY_YJIT_ENABLE=${RUBY_YJIT_ENABLE} \ -# Apply timezone + # Apply timezone TZ=${TZ} ENV \ -# Configure the IP to bind Mastodon to when serving traffic + # Configure the IP to bind Mastodon to when serving traffic BIND="0.0.0.0" \ -# Use production settings for Yarn, Node and related nodejs based tools + # Use production settings for Yarn, Node and related nodejs based tools NODE_ENV="production" \ -# Use production settings for Ruby on Rails + # Use production settings for Ruby on Rails RAILS_ENV="production" \ -# Add Ruby and Mastodon installation to the PATH + # Add Ruby and Mastodon installation to the PATH DEBIAN_FRONTEND="noninteractive" \ PATH="${PATH}:/opt/ruby/bin:/opt/mastodon/bin" \ -# Optimize jemalloc 5.x performance + # Optimize jemalloc 5.x performance MALLOC_CONF="narenas:2,background_thread:true,thp:never,dirty_decay_ms:1000,muzzy_decay_ms:0" \ -# Enable libvips, should not be changed + # Enable libvips, should not be changed MASTODON_USE_LIBVIPS=true \ -# Sidekiq will touch tmp/sidekiq_process_has_started_and_will_begin_processing_jobs to indicate it is ready. This can be used for a readiness check in Kubernetes + # Sidekiq will touch tmp/sidekiq_process_has_started_and_will_begin_processing_jobs to indicate it is ready. This can be used for a readiness check in Kubernetes MASTODON_SIDEKIQ_READY_FILENAME=sidekiq_process_has_started_and_will_begin_processing_jobs # Set default shell used for running commands @@ -79,14 +82,14 @@ ARG TARGETPLATFORM RUN echo "Target platform is $TARGETPLATFORM" RUN \ -# Remove automatic apt cache Docker cleanup scripts + # Remove automatic apt cache Docker cleanup scripts rm -f /etc/apt/apt.conf.d/docker-clean; \ -# Sets timezone + # Sets timezone echo "${TZ}" > /etc/localtime; \ -# Creates mastodon user/group and sets home directory + # Creates mastodon user/group and sets home directory groupadd -g "${GID}" mastodon; \ useradd -l -u "${UID}" -g "${GID}" -m -d /opt/mastodon mastodon; \ -# Creates /mastodon symlink to /opt/mastodon + # Creates /mastodon symlink to /opt/mastodon ln -s /opt/mastodon /mastodon; # Set /opt/mastodon as working directory @@ -94,28 +97,28 @@ WORKDIR /opt/mastodon # hadolint ignore=DL3008,DL3005 RUN \ -# Mount Apt cache and lib directories from Docker buildx caches ---mount=type=cache,id=apt-cache-${TARGETPLATFORM},target=/var/cache/apt,sharing=locked \ ---mount=type=cache,id=apt-lib-${TARGETPLATFORM},target=/var/lib/apt,sharing=locked \ -# Apt update & upgrade to check for security updates to Debian image + # Mount Apt cache and lib directories from Docker buildx caches + --mount=type=cache,id=apt-cache-${TARGETPLATFORM},target=/var/cache/apt,sharing=locked \ + --mount=type=cache,id=apt-lib-${TARGETPLATFORM},target=/var/lib/apt,sharing=locked \ + # Apt update & upgrade to check for security updates to Debian image apt-get update; \ apt-get dist-upgrade -yq; \ -# Install jemalloc, curl and other necessary components + # Install jemalloc, curl and other necessary components apt-get install -y --no-install-recommends \ - curl \ - file \ - libjemalloc2 \ - patchelf \ - procps \ - tini \ - tzdata \ - wget \ + curl \ + file \ + libjemalloc2 \ + patchelf \ + procps \ + tini \ + tzdata \ + wget \ ; \ -# Patch Ruby to use jemalloc + # Patch Ruby to use jemalloc patchelf --add-needed libjemalloc.so.2 /usr/local/bin/ruby; \ -# Discard patchelf after use + # Discard patchelf after use apt-get purge -y \ - patchelf \ + patchelf \ ; # Create temporary build layer from base image @@ -132,56 +135,56 @@ ARG TARGETPLATFORM # hadolint ignore=DL3008 RUN \ -# Mount Apt cache and lib directories from Docker buildx caches ---mount=type=cache,id=apt-cache-${TARGETPLATFORM},target=/var/cache/apt,sharing=locked \ ---mount=type=cache,id=apt-lib-${TARGETPLATFORM},target=/var/lib/apt,sharing=locked \ -# Install build tools and bundler dependencies from APT + # Mount Apt cache and lib directories from Docker buildx caches + --mount=type=cache,id=apt-cache-${TARGETPLATFORM},target=/var/cache/apt,sharing=locked \ + --mount=type=cache,id=apt-lib-${TARGETPLATFORM},target=/var/lib/apt,sharing=locked \ + # Install build tools and bundler dependencies from APT apt-get install -y --no-install-recommends \ - autoconf \ - automake \ - build-essential \ - cmake \ - git \ - libgdbm-dev \ - libglib2.0-dev \ - libgmp-dev \ - libicu-dev \ - libidn-dev \ - libpq-dev \ - libssl-dev \ - libtool \ - meson \ - nasm \ - pkg-config \ - shared-mime-info \ - xz-utils \ - # libvips components - libcgif-dev \ - libexif-dev \ - libexpat1-dev \ - libgirepository1.0-dev \ - libheif-dev \ - libimagequant-dev \ - libjpeg62-turbo-dev \ - liblcms2-dev \ - liborc-dev \ - libspng-dev \ - libtiff-dev \ - libwebp-dev \ + autoconf \ + automake \ + build-essential \ + cmake \ + git \ + libgdbm-dev \ + libglib2.0-dev \ + libgmp-dev \ + libicu-dev \ + libidn-dev \ + libpq-dev \ + libssl-dev \ + libtool \ + meson \ + nasm \ + pkg-config \ + shared-mime-info \ + xz-utils \ + # libvips components + libcgif-dev \ + libexif-dev \ + libexpat1-dev \ + libgirepository1.0-dev \ + libheif-dev \ + libimagequant-dev \ + libjpeg62-turbo-dev \ + liblcms2-dev \ + liborc-dev \ + libspng-dev \ + libtiff-dev \ + libwebp-dev \ # ffmpeg components - libdav1d-dev \ - liblzma-dev \ - libmp3lame-dev \ - libopus-dev \ - libsnappy-dev \ - libvorbis-dev \ - libvpx-dev \ - libx264-dev \ - libx265-dev \ + libdav1d-dev \ + liblzma-dev \ + libmp3lame-dev \ + libopus-dev \ + libsnappy-dev \ + libvorbis-dev \ + libvpx-dev \ + libx264-dev \ + libx265-dev \ ; RUN \ -# Configure Corepack + # Configure Corepack rm /usr/local/bin/yarn*; \ corepack enable; \ corepack prepare --activate; @@ -228,28 +231,28 @@ WORKDIR /usr/local/ffmpeg/src/ffmpeg-${FFMPEG_VERSION} # Configure and compile ffmpeg RUN \ ./configure \ - --prefix=/usr/local/ffmpeg \ - --toolchain=hardened \ - --disable-debug \ - --disable-devices \ - --disable-doc \ - --disable-ffplay \ - --disable-network \ - --disable-static \ - --enable-ffmpeg \ - --enable-ffprobe \ - --enable-gpl \ - --enable-libdav1d \ - --enable-libmp3lame \ - --enable-libopus \ - --enable-libsnappy \ - --enable-libvorbis \ - --enable-libvpx \ - --enable-libwebp \ - --enable-libx264 \ - --enable-libx265 \ - --enable-shared \ - --enable-version3 \ + --prefix=/usr/local/ffmpeg \ + --toolchain=hardened \ + --disable-debug \ + --disable-devices \ + --disable-doc \ + --disable-ffplay \ + --disable-network \ + --disable-static \ + --enable-ffmpeg \ + --enable-ffprobe \ + --enable-gpl \ + --enable-libdav1d \ + --enable-libmp3lame \ + --enable-libopus \ + --enable-libsnappy \ + --enable-libvorbis \ + --enable-libvpx \ + --enable-libwebp \ + --enable-libx264 \ + --enable-libx265 \ + --enable-shared \ + --enable-version3 \ ; \ make -j$(nproc); \ make install; @@ -263,17 +266,17 @@ ARG TARGETPLATFORM COPY Gemfile* /opt/mastodon/ RUN \ -# Mount Ruby Gem caches ---mount=type=cache,id=gem-cache-${TARGETPLATFORM},target=/usr/local/bundle/cache/,sharing=locked \ -# Configure bundle to prevent changes to Gemfile and Gemfile.lock + # Mount Ruby Gem caches + --mount=type=cache,id=gem-cache-${TARGETPLATFORM},target=/usr/local/bundle/cache/,sharing=locked \ + # Configure bundle to prevent changes to Gemfile and Gemfile.lock bundle config set --global frozen "true"; \ -# Configure bundle to not cache downloaded Gems + # Configure bundle to not cache downloaded Gems bundle config set --global cache_all "false"; \ -# Configure bundle to only process production Gems + # Configure bundle to only process production Gems bundle config set --local without "development test"; \ -# Configure bundle to not warn about root user + # Configure bundle to not warn about root user bundle config set silence_root_warning "true"; \ -# Download and install required Gems + # Download and install required Gems bundle install -j"$(nproc)"; # Create temporary node specific build layer from build layer @@ -288,9 +291,9 @@ COPY .yarn /opt/mastodon/.yarn # hadolint ignore=DL3008 RUN \ ---mount=type=cache,id=corepack-cache-${TARGETPLATFORM},target=/usr/local/share/.cache/corepack,sharing=locked \ ---mount=type=cache,id=yarn-cache-${TARGETPLATFORM},target=/usr/local/share/.cache/yarn,sharing=locked \ -# Install Node packages + --mount=type=cache,id=corepack-cache-${TARGETPLATFORM},target=/usr/local/share/.cache/corepack,sharing=locked \ + --mount=type=cache,id=yarn-cache-${TARGETPLATFORM},target=/usr/local/share/.cache/yarn,sharing=locked \ + # Install Node packages yarn workspaces focus --production @mastodon/mastodon; # Create temporary assets build layer from build layer @@ -311,10 +314,10 @@ ARG TARGETPLATFORM RUN \ ldconfig; \ -# Use Ruby on Rails to create Mastodon assets + # Use Ruby on Rails to create Mastodon assets SECRET_KEY_BASE_DUMMY=1 \ bundle exec rails assets:precompile; \ -# Cleanup temporary files + # Cleanup temporary files rm -fr /opt/mastodon/tmp; # Prep final Mastodon Ruby layer @@ -324,49 +327,49 @@ ARG TARGETPLATFORM # hadolint ignore=DL3008 RUN \ -# Mount Apt cache and lib directories from Docker buildx caches ---mount=type=cache,id=apt-cache-${TARGETPLATFORM},target=/var/cache/apt,sharing=locked \ ---mount=type=cache,id=apt-lib-${TARGETPLATFORM},target=/var/lib/apt,sharing=locked \ -# Mount Corepack and Yarn caches from Docker buildx caches ---mount=type=cache,id=corepack-cache-${TARGETPLATFORM},target=/usr/local/share/.cache/corepack,sharing=locked \ ---mount=type=cache,id=yarn-cache-${TARGETPLATFORM},target=/usr/local/share/.cache/yarn,sharing=locked \ -# Apt update install non-dev versions of necessary components + # Mount Apt cache and lib directories from Docker buildx caches + --mount=type=cache,id=apt-cache-${TARGETPLATFORM},target=/var/cache/apt,sharing=locked \ + --mount=type=cache,id=apt-lib-${TARGETPLATFORM},target=/var/lib/apt,sharing=locked \ + # Mount Corepack and Yarn caches from Docker buildx caches + --mount=type=cache,id=corepack-cache-${TARGETPLATFORM},target=/usr/local/share/.cache/corepack,sharing=locked \ + --mount=type=cache,id=yarn-cache-${TARGETPLATFORM},target=/usr/local/share/.cache/yarn,sharing=locked \ + # Apt update install non-dev versions of necessary components apt-get install -y --no-install-recommends \ - libexpat1 \ - libglib2.0-0 \ - libicu72 \ - libidn12 \ - libpq5 \ - libreadline8 \ - libssl3 \ - libyaml-0-2 \ + libexpat1 \ + libglib2.0-0 \ + libicu72 \ + libidn12 \ + libpq5 \ + libreadline8 \ + libssl3 \ + libyaml-0-2 \ # libvips components - libcgif0 \ - libexif12 \ - libheif1 \ - libimagequant0 \ - libjpeg62-turbo \ - liblcms2-2 \ - liborc-0.4-0 \ - libspng0 \ - libtiff6 \ - libwebp7 \ - libwebpdemux2 \ - libwebpmux3 \ + libcgif0 \ + libexif12 \ + libheif1 \ + libimagequant0 \ + libjpeg62-turbo \ + liblcms2-2 \ + liborc-0.4-0 \ + libspng0 \ + libtiff6 \ + libwebp7 \ + libwebpdemux2 \ + libwebpmux3 \ # ffmpeg components - libdav1d6 \ - libmp3lame0 \ - libopencore-amrnb0 \ - libopencore-amrwb0 \ - libopus0 \ - libsnappy1v5 \ - libtheora0 \ - libvorbis0a \ - libvorbisenc2 \ - libvorbisfile3 \ - libvpx7 \ - libx264-164 \ - libx265-199 \ + libdav1d6 \ + libmp3lame0 \ + libopencore-amrnb0 \ + libopencore-amrwb0 \ + libopus0 \ + libsnappy1v5 \ + libtheora0 \ + libvorbis0a \ + libvorbisenc2 \ + libvorbisfile3 \ + libvpx7 \ + libx264-164 \ + libx265-199 \ ; # Copy Mastodon sources into final layer @@ -386,7 +389,7 @@ COPY --from=ffmpeg /usr/local/ffmpeg/lib /usr/local/lib RUN \ ldconfig; \ -# Smoketest media processors + # Smoketest media processors vips -v; \ ffmpeg -version; \ ffprobe -version; @@ -396,10 +399,10 @@ RUN \ bundle exec bootsnap precompile --gemfile app/ lib/; RUN \ -# Pre-create and chown system volume to Mastodon user + # Pre-create and chown system volume to Mastodon user mkdir -p /opt/mastodon/public/system; \ chown mastodon:mastodon /opt/mastodon/public/system; \ -# Set Mastodon user as owner of tmp folder + # Set Mastodon user as owner of tmp folder chown -R mastodon:mastodon /opt/mastodon/tmp; # Set the running user for resulting container diff --git a/Gemfile b/Gemfile index 0c3484a7aa..6abb075c1c 100644 --- a/Gemfile +++ b/Gemfile @@ -6,7 +6,7 @@ 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' @@ -25,7 +25,7 @@ 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' @@ -62,6 +63,7 @@ gem 'kaminari', '~> 1.2' gem 'link_header', '~> 0.0' gem 'mario-redis-lock', '~> 1.2', require: 'redis_lock' 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' @@ -112,7 +114,7 @@ group :opentelemetry do gem 'opentelemetry-instrumentation-net_http', '~> 0.22.4', require: false gem 'opentelemetry-instrumentation-pg', '~> 0.29.0', require: false gem 'opentelemetry-instrumentation-rack', '~> 0.25.0', require: false - gem 'opentelemetry-instrumentation-rails', '~> 0.32.0', require: false + gem 'opentelemetry-instrumentation-rails', '~> 0.33.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 @@ -170,7 +172,7 @@ group :development do gem 'rubocop-rspec_rails', require: false # Annotates modules with schema - gem 'annotate', '~> 3.2' + gem 'annotaterb', '~> 4.13' # Enhanced error message pages for development gem 'better_errors', '~> 2.9' @@ -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 c714838170..471795a7e7 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -10,51 +10,46 @@ GIT GEM remote: https://rubygems.org/ specs: - actioncable (7.1.4.2) - actionpack (= 7.1.4.2) - activesupport (= 7.1.4.2) + 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.2) - actionpack (= 7.1.4.2) - activejob (= 7.1.4.2) - activerecord (= 7.1.4.2) - activestorage (= 7.1.4.2) - activesupport (= 7.1.4.2) - mail (>= 2.7.1) - net-imap - net-pop - net-smtp - actionmailer (7.1.4.2) - actionpack (= 7.1.4.2) - actionview (= 7.1.4.2) - activejob (= 7.1.4.2) - activesupport (= 7.1.4.2) - 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.2) - actionview (= 7.1.4.2) - activesupport (= 7.1.4.2) + 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.2) - actionpack (= 7.1.4.2) - activerecord (= 7.1.4.2) - activestorage (= 7.1.4.2) - activesupport (= 7.1.4.2) + 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.2) - activesupport (= 7.1.4.2) + actionview (7.2.2) + activesupport (= 7.2.2) builder (~> 3.1) erubi (~> 1.11) rails-dom-testing (~> 2.2) @@ -64,62 +59,63 @@ GEM activemodel (>= 4.1) case_transform (>= 0.2) jsonapi-renderer (>= 0.1.1.beta1, < 0.3) - activejob (7.1.4.2) - activesupport (= 7.1.4.2) + activejob (7.2.2) + activesupport (= 7.2.2) globalid (>= 0.3.6) - activemodel (7.1.4.2) - activesupport (= 7.1.4.2) - activerecord (7.1.4.2) - activemodel (= 7.1.4.2) - activesupport (= 7.1.4.2) + 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.2) - actionpack (= 7.1.4.2) - activejob (= 7.1.4.2) - activerecord (= 7.1.4.2) - activesupport (= 7.1.4.2) + 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.2) + 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) android_key_attestation (0.3.0) - annotate (3.2.0) - activerecord (>= 3.2, < 8.0) - rake (>= 10.4, < 14.0) + annotaterb (4.13.0) ast (2.4.2) attr_required (1.0.2) awrence (1.2.1) aws-eventstream (1.3.0) - aws-partitions (1.997.0) - aws-sdk-core (3.211.0) + aws-partitions (1.1012.0) + aws-sdk-core (3.213.0) aws-eventstream (~> 1, >= 1.3.0) aws-partitions (~> 1, >= 1.992.0) aws-sigv4 (~> 1.9) jmespath (~> 1, >= 1.6.1) - aws-sdk-kms (1.95.0) + aws-sdk-kms (1.96.0) aws-sdk-core (~> 3, >= 3.210.0) aws-sigv4 (~> 1.5) - aws-sdk-s3 (1.169.0) + aws-sdk-s3 (1.173.0) aws-sdk-core (~> 3, >= 3.210.0) aws-sdk-kms (~> 1) aws-sigv4 (~> 1.5) aws-sigv4 (1.10.1) aws-eventstream (~> 1, >= 1.0.2) - azure-blob (0.5.2) + azure-blob (0.5.3) rexml base64 (0.2.0) bcp47_spec (0.2.1) bcrypt (3.1.20) + benchmark (0.4.0) better_errors (2.10.1) erubi (>= 1.0.0) rack (>= 0.9.0) @@ -133,7 +129,7 @@ GEM msgpack (~> 1.2) brakeman (6.2.2) racc - browser (5.3.1) + browser (6.1.0) brpoplpush-redis_script (0.1.3) concurrent-ruby (~> 1.0, >= 1.0.5) redis (>= 1.0, < 6) @@ -180,7 +176,7 @@ GEM activerecord (>= 5.a) database_cleaner-core (~> 2.0.0) database_cleaner-core (2.0.1) - date (3.3.4) + date (3.4.0) debug (1.9.2) irb (~> 1.10) reline (>= 0.3.8) @@ -191,20 +187,20 @@ GEM railties (>= 4.1.0) responders warden (~> 1.2.3) - devise-two-factor (6.0.0) - activesupport (~> 7.0) + devise-two-factor (6.1.0) + activesupport (>= 7.0, < 8.1) devise (~> 4.0) - railties (~> 7.0) + railties (>= 7.0, < 8.1) rotp (~> 6.0) devise_pam_authenticatable2 (9.2.0) 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) + doorkeeper (5.8.0) railties (>= 5) dotenv (3.1.4) drb (2.2.1) @@ -229,29 +225,14 @@ GEM fabrication (2.31.0) 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 (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.17.0) @@ -347,7 +328,7 @@ GEM azure-blob (~> 0.5.2) hashie (~> 5.0) jmespath (1.6.2) - json (2.7.4) + json (2.8.1) json-canonicalization (1.0.0) json-jwt (1.15.3.1) activesupport (>= 4.2) @@ -362,10 +343,10 @@ 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) + json-schema (5.1.0) addressable (~> 2.8) jsonapi-renderer (0.2.2) jwt (2.7.1) @@ -424,17 +405,16 @@ GEM mime-types (3.6.0) logger mime-types-data (~> 3.2015) - mime-types-data (3.2024.1001) + mime-types-data (3.2024.1105) mini_mime (1.1.5) mini_portile2 (2.8.7) minitest (5.25.1) - msgpack (1.7.3) + msgpack (1.7.5) 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-imap (0.5.0) + net-imap (0.5.1) date net-protocol net-ldap (0.19.0) @@ -448,7 +428,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) @@ -498,13 +478,13 @@ GEM opentelemetry-api (~> 1.0) opentelemetry-instrumentation-active_support (~> 0.1) opentelemetry-instrumentation-base (~> 0.22.1) - opentelemetry-instrumentation-action_pack (0.9.0) + opentelemetry-instrumentation-action_pack (0.10.0) opentelemetry-api (~> 1.0) opentelemetry-instrumentation-base (~> 0.22.1) opentelemetry-instrumentation-rack (~> 0.21) - opentelemetry-instrumentation-action_view (0.7.2) + opentelemetry-instrumentation-action_view (0.7.3) opentelemetry-api (~> 1.0) - opentelemetry-instrumentation-active_support (~> 0.1) + opentelemetry-instrumentation-active_support (~> 0.6) opentelemetry-instrumentation-base (~> 0.22.1) opentelemetry-instrumentation-active_job (0.7.8) opentelemetry-api (~> 1.0) @@ -547,10 +527,10 @@ GEM opentelemetry-instrumentation-rack (0.25.0) opentelemetry-api (~> 1.0) opentelemetry-instrumentation-base (~> 0.22.1) - opentelemetry-instrumentation-rails (0.32.0) + opentelemetry-instrumentation-rails (0.33.0) opentelemetry-api (~> 1.0) opentelemetry-instrumentation-action_mailer (~> 0.2.0) - opentelemetry-instrumentation-action_pack (~> 0.9.0) + opentelemetry-instrumentation-action_pack (~> 0.10.0) opentelemetry-instrumentation-action_view (~> 0.7.0) opentelemetry-instrumentation-active_job (~> 0.7.0) opentelemetry-instrumentation-active_record (~> 0.8.0) @@ -572,10 +552,10 @@ GEM opentelemetry-semantic_conventions (1.10.1) opentelemetry-api (~> 1.0) orm_adapter (0.5.0) - ostruct (0.6.0) + ostruct (0.6.1) ox (2.14.18) parallel (1.26.3) - parser (3.3.5.0) + parser (3.3.6.0) ast (~> 2.4.1) racc parslet (2.0.0) @@ -597,7 +577,7 @@ GEM activesupport (>= 7.0.0) rack railties (>= 7.0.0) - psych (5.1.2) + psych (5.2.0) stringio public_suffix (6.0.1) puma (6.4.3) @@ -629,20 +609,20 @@ GEM rackup (1.0.0) rack (< 3) webrick - rails (7.1.4.2) - actioncable (= 7.1.4.2) - actionmailbox (= 7.1.4.2) - actionmailer (= 7.1.4.2) - actionpack (= 7.1.4.2) - actiontext (= 7.1.4.2) - actionview (= 7.1.4.2) - activejob (= 7.1.4.2) - activemodel (= 7.1.4.2) - activerecord (= 7.1.4.2) - activestorage (= 7.1.4.2) - activesupport (= 7.1.4.2) + 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.2) + railties (= 7.2.2) rails-controller-testing (1.0.5) actionpack (>= 5.0.1.rc1) actionview (>= 5.0.1.rc1) @@ -657,10 +637,10 @@ GEM rails-i18n (7.0.10) i18n (>= 0.7, < 2) railties (>= 6.0.0, < 8) - railties (7.1.4.2) - actionpack (= 7.1.4.2) - activesupport (= 7.1.4.2) - 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) @@ -682,7 +662,7 @@ GEM redlock (1.3.2) redis (>= 3.0.0, < 6.0) regexp_parser (2.9.2) - reline (0.5.10) + reline (0.5.11) io-console (~> 0.5) request_store (1.6.0) rack (>= 1.4) @@ -691,7 +671,7 @@ GEM railties (>= 5.2) rexml (3.3.9) rotp (6.3.0) - rouge (4.4.0) + rouge (4.5.1) rpam2 (4.0.2) rqrcode (2.2.0) chunky_png (~> 1.0) @@ -711,7 +691,7 @@ GEM rspec-mocks (3.13.2) diff-lcs (>= 1.2.0, < 2.0) rspec-support (~> 3.13.0) - rspec-rails (7.0.1) + rspec-rails (7.1.0) actionpack (>= 7.0) activesupport (>= 7.0) railties (>= 7.0) @@ -760,7 +740,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) @@ -772,6 +751,7 @@ GEM scenic (1.8.0) activerecord (>= 4.0.0) railties (>= 4.0.0) + securerandom (0.3.2) selenium-webdriver (4.26.0) base64 (~> 0.2) logger (~> 1.4) @@ -812,8 +792,8 @@ GEM stackprof (0.2.26) stoplight (4.1.0) redlock (~> 1.0) - stringio (3.1.1) - strong_migrations (2.0.2) + stringio (3.1.2) + strong_migrations (2.1.0) activerecord (>= 6.1) swd (1.3.0) activesupport (>= 3) @@ -828,7 +808,7 @@ GEM test-prof (1.4.2) thor (1.3.2) tilt (2.4.0) - timeout (0.4.1) + timeout (0.4.2) tpm-key_attestation (0.12.1) bindata (~> 2.4) openssl (> 2.0) @@ -855,6 +835,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) @@ -884,7 +865,7 @@ GEM rack-proxy (>= 0.6.1) railties (>= 5.2) semantic_range (>= 2.3.0) - webrick (1.8.2) + webrick (1.9.0) websocket (1.2.11) websocket-driver (0.7.6) websocket-extensions (>= 0.1.0) @@ -901,14 +882,14 @@ PLATFORMS DEPENDENCIES active_model_serializers (~> 0.10) addressable (~> 2.8) - annotate (~> 3.2) + annotaterb (~> 4.13) aws-sdk-s3 (~> 1.123) better_errors (~> 2.9) binding_of_caller (~> 1.0) 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) @@ -930,6 +911,7 @@ DEPENDENCIES email_spec fabrication (~> 2.30) faker (~> 3.2) + faraday-httpclient fast_blank (~> 1.0) fastimage flatware-rspec @@ -962,7 +944,8 @@ DEPENDENCIES mario-redis-lock (~> 1.2) memory_profiler mime-types (~> 3.6.0) - net-http (~> 0.4.0) + mutex_m + net-http (~> 0.5.0) net-ldap (~> 0.18) nokogiri (~> 1.15) oj (~> 3.14) @@ -983,7 +966,7 @@ DEPENDENCIES opentelemetry-instrumentation-net_http (~> 0.22.4) opentelemetry-instrumentation-pg (~> 0.29.0) opentelemetry-instrumentation-rack (~> 0.25.0) - opentelemetry-instrumentation-rails (~> 0.32.0) + opentelemetry-instrumentation-rails (~> 0.33.0) opentelemetry-instrumentation-redis (~> 0.25.3) opentelemetry-instrumentation-sidekiq (~> 0.25.2) opentelemetry-sdk (~> 1.4) @@ -1000,7 +983,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) 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/admin/email_domain_blocks_controller.rb b/app/controllers/admin/email_domain_blocks_controller.rb index faa0a061a6..9501ebd63a 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 @@ -58,10 +58,7 @@ module Admin private def set_resolved_records - Resolv::DNS.open do |dns| - dns.timeouts = 5 - @resolved_records = dns.getresources(@email_domain_block.domain, Resolv::DNS::Resource::IN::MX).to_a - end + @resolved_records = DomainResource.new(@email_domain_block.domain).mx end def resource_params diff --git a/app/controllers/admin/instances_controller.rb b/app/controllers/admin/instances_controller.rb index d7f88a71f3..a48c4773ed 100644 --- a/app/controllers/admin/instances_controller.rb +++ b/app/controllers/admin/instances_controller.rb @@ -5,6 +5,8 @@ module Admin before_action :set_instances, only: :index before_action :set_instance, except: :index + LOGS_LIMIT = 5 + def index authorize :instance, :index? preload_delivery_failures! @@ -13,7 +15,7 @@ module Admin def show authorize :instance, :show? @time_period = (6.days.ago.to_date...Time.now.utc.to_date) - @action_logs = Admin::ActionLogFilter.new(target_domain: @instance.domain).results.limit(5) + @action_logs = Admin::ActionLogFilter.new(target_domain: @instance.domain).results.limit(LOGS_LIMIT) end def destroy 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/relays_controller.rb b/app/controllers/admin/relays_controller.rb index c893802159..f05255adb6 100644 --- a/app/controllers/admin/relays_controller.rb +++ b/app/controllers/admin/relays_controller.rb @@ -21,6 +21,7 @@ module Admin @relay = Relay.new(resource_params) if @relay.save + log_action :create, @relay @relay.enable! redirect_to admin_relays_path else @@ -31,18 +32,21 @@ module Admin def destroy authorize :relay, :update? @relay.destroy + log_action :destroy, @relay redirect_to admin_relays_path end def enable authorize :relay, :update? @relay.enable! + log_action :enable, @relay redirect_to admin_relays_path end def disable authorize :relay, :update? @relay.disable! + log_action :disable, @relay redirect_to admin_relays_path end diff --git a/app/controllers/admin/statuses_controller.rb b/app/controllers/admin/statuses_controller.rb index e53b22dca3..40d1a481b2 100644 --- a/app/controllers/admin/statuses_controller.rb +++ b/app/controllers/admin/statuses_controller.rb @@ -16,6 +16,8 @@ module Admin def show authorize [:admin, @status], :show? + + @status_batch_action = Admin::StatusBatchAction.new end def batch diff --git a/app/controllers/api/v1/accounts/familiar_followers_controller.rb b/app/controllers/api/v1/accounts/familiar_followers_controller.rb index a49eb2eb27..81f0a9ed0f 100644 --- a/app/controllers/api/v1/accounts/familiar_followers_controller.rb +++ b/app/controllers/api/v1/accounts/familiar_followers_controller.rb @@ -12,7 +12,7 @@ class Api::V1::Accounts::FamiliarFollowersController < Api::BaseController private def set_accounts - @accounts = Account.without_suspended.where(id: account_ids).select('id, hide_collections') + @accounts = Account.without_suspended.where(id: account_ids).select(:id, :hide_collections) end def familiar_followers 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/featured_tags/suggestions_controller.rb b/app/controllers/api/v1/featured_tags/suggestions_controller.rb index 9c72e4380d..d533b1af7b 100644 --- a/app/controllers/api/v1/featured_tags/suggestions_controller.rb +++ b/app/controllers/api/v1/featured_tags/suggestions_controller.rb @@ -5,6 +5,8 @@ class Api::V1::FeaturedTags::SuggestionsController < Api::BaseController before_action :require_user! before_action :set_recently_used_tags, only: :index + RECENT_TAGS_LIMIT = 10 + def index render json: @recently_used_tags, each_serializer: REST::TagSerializer, relationships: TagRelationshipsPresenter.new(@recently_used_tags, current_user&.account_id) end @@ -12,6 +14,6 @@ class Api::V1::FeaturedTags::SuggestionsController < Api::BaseController private def set_recently_used_tags - @recently_used_tags = Tag.suggestions_for_account(current_account).limit(10) + @recently_used_tags = Tag.suggestions_for_account(current_account).limit(RECENT_TAGS_LIMIT) end end diff --git a/app/controllers/api/v1/lists/accounts_controller.rb b/app/controllers/api/v1/lists/accounts_controller.rb index b1c0e609d0..616159f05f 100644 --- a/app/controllers/api/v1/lists/accounts_controller.rb +++ b/app/controllers/api/v1/lists/accounts_controller.rb @@ -15,17 +15,12 @@ class Api::V1::Lists::AccountsController < Api::BaseController end def create - ApplicationRecord.transaction do - list_accounts.each do |account| - @list.accounts << account - end - end - + AddAccountsToListService.new.call(@list, Account.find(account_ids)) render_empty end def destroy - ListAccount.where(list: @list, account_id: account_ids).destroy_all + RemoveAccountsFromListService.new.call(@list, Account.where(id: account_ids)) render_empty end @@ -43,10 +38,6 @@ class Api::V1::Lists::AccountsController < Api::BaseController end end - def list_accounts - Account.find(account_ids) - end - def account_ids Array(resource_params[:account_ids]) end diff --git a/app/controllers/concerns/web_app_controller_concern.rb b/app/controllers/concerns/web_app_controller_concern.rb index 9485ecda49..249bb20a25 100644 --- a/app/controllers/concerns/web_app_controller_concern.rb +++ b/app/controllers/concerns/web_app_controller_concern.rb @@ -7,7 +7,6 @@ module WebAppControllerConcern vary_by 'Accept, Accept-Language, Cookie' before_action :redirect_unauthenticated_to_permalinks! - before_action :set_app_body_class content_security_policy do |p| policy = ContentSecurityPolicy.new @@ -24,10 +23,6 @@ module WebAppControllerConcern !(ENV['ONE_CLICK_SSO_LOGIN'] == 'true' && ENV['OMNIAUTH_ONLY'] == 'true' && Devise.omniauth_providers.length == 1) && current_user.nil? end - def set_app_body_class - @body_classes = 'app-body' - end - def redirect_unauthenticated_to_permalinks! return if user_signed_in? && current_account.moved_to_account_id.nil? diff --git a/app/controllers/oauth/authorized_applications_controller.rb b/app/controllers/oauth/authorized_applications_controller.rb index 267409a9ce..9e541e5e3c 100644 --- a/app/controllers/oauth/authorized_applications_controller.rb +++ b/app/controllers/oauth/authorized_applications_controller.rb @@ -35,12 +35,6 @@ class Oauth::AuthorizedApplicationsController < Doorkeeper::AuthorizedApplicatio end def set_last_used_at_by_app - @last_used_at_by_app = Doorkeeper::AccessToken - .select('DISTINCT ON (application_id) application_id, last_used_at') - .where(resource_owner_id: current_resource_owner.id) - .where.not(last_used_at: nil) - .order(application_id: :desc, last_used_at: :desc) - .pluck(:application_id, :last_used_at) - .to_h + @last_used_at_by_app = current_resource_owner.applications_last_used end end diff --git a/app/controllers/settings/featured_tags_controller.rb b/app/controllers/settings/featured_tags_controller.rb index 90c112e219..7e29dd1d29 100644 --- a/app/controllers/settings/featured_tags_controller.rb +++ b/app/controllers/settings/featured_tags_controller.rb @@ -5,6 +5,8 @@ class Settings::FeaturedTagsController < Settings::BaseController before_action :set_featured_tag, except: [:index, :create] before_action :set_recently_used_tags, only: :index + RECENT_TAGS_LIMIT = 10 + def index @featured_tag = FeaturedTag.new end @@ -38,7 +40,7 @@ class Settings::FeaturedTagsController < Settings::BaseController end def set_recently_used_tags - @recently_used_tags = Tag.suggestions_for_account(current_account).limit(10) + @recently_used_tags = Tag.suggestions_for_account(current_account).limit(RECENT_TAGS_LIMIT) end def featured_tag_params diff --git a/app/controllers/settings/imports_controller.rb b/app/controllers/settings/imports_controller.rb index 569aa07c53..5346a448a3 100644 --- a/app/controllers/settings/imports_controller.rb +++ b/app/controllers/settings/imports_controller.rb @@ -24,6 +24,8 @@ class Settings::ImportsController < Settings::BaseController lists: false, }.freeze + RECENT_IMPORTS_LIMIT = 10 + def index @import = Form::Import.new(current_account: current_account) end @@ -96,6 +98,6 @@ class Settings::ImportsController < Settings::BaseController end def set_recent_imports - @recent_imports = current_account.bulk_imports.reorder(id: :desc).limit(10) + @recent_imports = current_account.bulk_imports.reorder(id: :desc).limit(RECENT_IMPORTS_LIMIT) end end diff --git a/app/helpers/admin/account_moderation_notes_helper.rb b/app/helpers/admin/account_moderation_notes_helper.rb index 2a3d954a35..7c931c1157 100644 --- a/app/helpers/admin/account_moderation_notes_helper.rb +++ b/app/helpers/admin/account_moderation_notes_helper.rb @@ -12,12 +12,12 @@ module Admin::AccountModerationNotesHelper ) end - def admin_account_inline_link_to(account) + def admin_account_inline_link_to(account, path: nil) return if account.nil? link_to( account_inline_text(account), - admin_account_path(account.id), + path || admin_account_path(account.id), class: class_names('inline-name-tag', suspended: suspended_account?(account)), title: account.acct ) diff --git a/app/helpers/admin/action_logs_helper.rb b/app/helpers/admin/action_logs_helper.rb index 51e28d8b4e..859f924687 100644 --- a/app/helpers/admin/action_logs_helper.rb +++ b/app/helpers/admin/action_logs_helper.rb @@ -33,6 +33,8 @@ module Admin::ActionLogsHelper else I18n.t('admin.action_logs.deleted_account') end + when 'Relay' + link_to log.human_identifier, admin_relays_path end end diff --git a/app/helpers/application_helper.rb b/app/helpers/application_helper.rb index e36de19255..3d5025724f 100644 --- a/app/helpers/application_helper.rb +++ b/app/helpers/application_helper.rb @@ -79,7 +79,7 @@ module ApplicationHelper def html_title safe_join( - [content_for(:page_title).to_s.chomp, title] + [content_for(:page_title), title] .compact_blank, ' - ' ) 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/self_destruct_helper.rb b/app/helpers/self_destruct_helper.rb index 78557c25e5..f1927b1e04 100644 --- a/app/helpers/self_destruct_helper.rb +++ b/app/helpers/self_destruct_helper.rb @@ -1,9 +1,11 @@ # frozen_string_literal: true module SelfDestructHelper + VERIFY_PURPOSE = 'self-destruct' + def self.self_destruct? - value = ENV.fetch('SELF_DESTRUCT', nil) - value.present? && Rails.application.message_verifier('self-destruct').verify(value) == ENV['LOCAL_DOMAIN'] + value = Rails.configuration.x.mastodon.self_destruct_value + value.present? && Rails.application.message_verifier(VERIFY_PURPOSE).verify(value) == ENV['LOCAL_DOMAIN'] rescue ActiveSupport::MessageVerifier::InvalidSignature false end diff --git a/app/helpers/statuses_helper.rb b/app/helpers/statuses_helper.rb index 9bbb03fd82..16b9d3fb53 100644 --- a/app/helpers/statuses_helper.rb +++ b/app/helpers/statuses_helper.rb @@ -1,9 +1,6 @@ # frozen_string_literal: true module StatusesHelper - EMBEDDED_CONTROLLER = 'statuses' - EMBEDDED_ACTION = 'embed' - VISIBLITY_ICONS = { public: 'globe', unlisted: 'lock_open', @@ -60,18 +57,10 @@ module StatusesHelper components.compact_blank.join("\n\n") end - def stream_link_target - embedded_view? ? '_blank' : nil - end - def visibility_icon(status) VISIBLITY_ICONS[status.visibility.to_sym] end - def embedded_view? - params[:controller] == EMBEDDED_CONTROLLER && params[:action] == EMBEDDED_ACTION - end - def prefers_autoplay? ActiveModel::Type::Boolean.new.cast(params[:autoplay]) || current_user&.setting_auto_play_gif end 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/mastodon/actions/lists.js b/app/javascript/mastodon/actions/lists.js index 9956059387..f9abc2e769 100644 --- a/app/javascript/mastodon/actions/lists.js +++ b/app/javascript/mastodon/actions/lists.js @@ -1,8 +1,5 @@ import api from '../api'; -import { showAlertForError } from './alerts'; -import { importFetchedAccounts } from './importer'; - export const LIST_FETCH_REQUEST = 'LIST_FETCH_REQUEST'; export const LIST_FETCH_SUCCESS = 'LIST_FETCH_SUCCESS'; export const LIST_FETCH_FAIL = 'LIST_FETCH_FAIL'; @@ -11,45 +8,10 @@ export const LISTS_FETCH_REQUEST = 'LISTS_FETCH_REQUEST'; export const LISTS_FETCH_SUCCESS = 'LISTS_FETCH_SUCCESS'; export const LISTS_FETCH_FAIL = 'LISTS_FETCH_FAIL'; -export const LIST_EDITOR_TITLE_CHANGE = 'LIST_EDITOR_TITLE_CHANGE'; -export const LIST_EDITOR_RESET = 'LIST_EDITOR_RESET'; -export const LIST_EDITOR_SETUP = 'LIST_EDITOR_SETUP'; - -export const LIST_CREATE_REQUEST = 'LIST_CREATE_REQUEST'; -export const LIST_CREATE_SUCCESS = 'LIST_CREATE_SUCCESS'; -export const LIST_CREATE_FAIL = 'LIST_CREATE_FAIL'; - -export const LIST_UPDATE_REQUEST = 'LIST_UPDATE_REQUEST'; -export const LIST_UPDATE_SUCCESS = 'LIST_UPDATE_SUCCESS'; -export const LIST_UPDATE_FAIL = 'LIST_UPDATE_FAIL'; - export const LIST_DELETE_REQUEST = 'LIST_DELETE_REQUEST'; export const LIST_DELETE_SUCCESS = 'LIST_DELETE_SUCCESS'; export const LIST_DELETE_FAIL = 'LIST_DELETE_FAIL'; -export const LIST_ACCOUNTS_FETCH_REQUEST = 'LIST_ACCOUNTS_FETCH_REQUEST'; -export const LIST_ACCOUNTS_FETCH_SUCCESS = 'LIST_ACCOUNTS_FETCH_SUCCESS'; -export const LIST_ACCOUNTS_FETCH_FAIL = 'LIST_ACCOUNTS_FETCH_FAIL'; - -export const LIST_EDITOR_SUGGESTIONS_CHANGE = 'LIST_EDITOR_SUGGESTIONS_CHANGE'; -export const LIST_EDITOR_SUGGESTIONS_READY = 'LIST_EDITOR_SUGGESTIONS_READY'; -export const LIST_EDITOR_SUGGESTIONS_CLEAR = 'LIST_EDITOR_SUGGESTIONS_CLEAR'; - -export const LIST_EDITOR_ADD_REQUEST = 'LIST_EDITOR_ADD_REQUEST'; -export const LIST_EDITOR_ADD_SUCCESS = 'LIST_EDITOR_ADD_SUCCESS'; -export const LIST_EDITOR_ADD_FAIL = 'LIST_EDITOR_ADD_FAIL'; - -export const LIST_EDITOR_REMOVE_REQUEST = 'LIST_EDITOR_REMOVE_REQUEST'; -export const LIST_EDITOR_REMOVE_SUCCESS = 'LIST_EDITOR_REMOVE_SUCCESS'; -export const LIST_EDITOR_REMOVE_FAIL = 'LIST_EDITOR_REMOVE_FAIL'; - -export const LIST_ADDER_RESET = 'LIST_ADDER_RESET'; -export const LIST_ADDER_SETUP = 'LIST_ADDER_SETUP'; - -export const LIST_ADDER_LISTS_FETCH_REQUEST = 'LIST_ADDER_LISTS_FETCH_REQUEST'; -export const LIST_ADDER_LISTS_FETCH_SUCCESS = 'LIST_ADDER_LISTS_FETCH_SUCCESS'; -export const LIST_ADDER_LISTS_FETCH_FAIL = 'LIST_ADDER_LISTS_FETCH_FAIL'; - export const fetchList = id => (dispatch, getState) => { if (getState().getIn(['lists', id])) { return; @@ -100,89 +62,6 @@ export const fetchListsFail = error => ({ error, }); -export const submitListEditor = shouldReset => (dispatch, getState) => { - const listId = getState().getIn(['listEditor', 'listId']); - const title = getState().getIn(['listEditor', 'title']); - - if (listId === null) { - dispatch(createList(title, shouldReset)); - } else { - dispatch(updateList(listId, title, shouldReset)); - } -}; - -export const setupListEditor = listId => (dispatch, getState) => { - dispatch({ - type: LIST_EDITOR_SETUP, - list: getState().getIn(['lists', listId]), - }); - - dispatch(fetchListAccounts(listId)); -}; - -export const changeListEditorTitle = value => ({ - type: LIST_EDITOR_TITLE_CHANGE, - value, -}); - -export const createList = (title, shouldReset) => (dispatch) => { - dispatch(createListRequest()); - - api().post('/api/v1/lists', { title }).then(({ data }) => { - dispatch(createListSuccess(data)); - - if (shouldReset) { - dispatch(resetListEditor()); - } - }).catch(err => dispatch(createListFail(err))); -}; - -export const createListRequest = () => ({ - type: LIST_CREATE_REQUEST, -}); - -export const createListSuccess = list => ({ - type: LIST_CREATE_SUCCESS, - list, -}); - -export const createListFail = error => ({ - type: LIST_CREATE_FAIL, - error, -}); - -export const updateList = (id, title, shouldReset, isExclusive, replies_policy) => (dispatch) => { - dispatch(updateListRequest(id)); - - api().put(`/api/v1/lists/${id}`, { title, replies_policy, exclusive: typeof isExclusive === 'undefined' ? undefined : !!isExclusive }).then(({ data }) => { - dispatch(updateListSuccess(data)); - - if (shouldReset) { - dispatch(resetListEditor()); - } - }).catch(err => dispatch(updateListFail(id, err))); -}; - -export const updateListRequest = id => ({ - type: LIST_UPDATE_REQUEST, - id, -}); - -export const updateListSuccess = list => ({ - type: LIST_UPDATE_SUCCESS, - list, -}); - -export const updateListFail = (id, error) => ({ - type: LIST_UPDATE_FAIL, - id, - error, -}); - -export const resetListEditor = () => ({ - type: LIST_EDITOR_RESET, -}); - export const deleteList = id => (dispatch) => { dispatch(deleteListRequest(id)); @@ -206,167 +85,3 @@ export const deleteListFail = (id, error) => ({ id, error, }); - -export const fetchListAccounts = listId => (dispatch) => { - dispatch(fetchListAccountsRequest(listId)); - - api().get(`/api/v1/lists/${listId}/accounts`, { params: { limit: 0 } }).then(({ data }) => { - dispatch(importFetchedAccounts(data)); - dispatch(fetchListAccountsSuccess(listId, data)); - }).catch(err => dispatch(fetchListAccountsFail(listId, err))); -}; - -export const fetchListAccountsRequest = id => ({ - type: LIST_ACCOUNTS_FETCH_REQUEST, - id, -}); - -export const fetchListAccountsSuccess = (id, accounts, next) => ({ - type: LIST_ACCOUNTS_FETCH_SUCCESS, - id, - accounts, - next, -}); - -export const fetchListAccountsFail = (id, error) => ({ - type: LIST_ACCOUNTS_FETCH_FAIL, - id, - error, -}); - -export const fetchListSuggestions = q => (dispatch) => { - const params = { - q, - resolve: false, - limit: 4, - following: true, - }; - - api().get('/api/v1/accounts/search', { params }).then(({ data }) => { - dispatch(importFetchedAccounts(data)); - dispatch(fetchListSuggestionsReady(q, data)); - }).catch(error => dispatch(showAlertForError(error))); -}; - -export const fetchListSuggestionsReady = (query, accounts) => ({ - type: LIST_EDITOR_SUGGESTIONS_READY, - query, - accounts, -}); - -export const clearListSuggestions = () => ({ - type: LIST_EDITOR_SUGGESTIONS_CLEAR, -}); - -export const changeListSuggestions = value => ({ - type: LIST_EDITOR_SUGGESTIONS_CHANGE, - value, -}); - -export const addToListEditor = accountId => (dispatch, getState) => { - dispatch(addToList(getState().getIn(['listEditor', 'listId']), accountId)); -}; - -export const addToList = (listId, accountId) => (dispatch) => { - dispatch(addToListRequest(listId, accountId)); - - api().post(`/api/v1/lists/${listId}/accounts`, { account_ids: [accountId] }) - .then(() => dispatch(addToListSuccess(listId, accountId))) - .catch(err => dispatch(addToListFail(listId, accountId, err))); -}; - -export const addToListRequest = (listId, accountId) => ({ - type: LIST_EDITOR_ADD_REQUEST, - listId, - accountId, -}); - -export const addToListSuccess = (listId, accountId) => ({ - type: LIST_EDITOR_ADD_SUCCESS, - listId, - accountId, -}); - -export const addToListFail = (listId, accountId, error) => ({ - type: LIST_EDITOR_ADD_FAIL, - listId, - accountId, - error, -}); - -export const removeFromListEditor = accountId => (dispatch, getState) => { - dispatch(removeFromList(getState().getIn(['listEditor', 'listId']), accountId)); -}; - -export const removeFromList = (listId, accountId) => (dispatch) => { - dispatch(removeFromListRequest(listId, accountId)); - - api().delete(`/api/v1/lists/${listId}/accounts`, { params: { account_ids: [accountId] } }) - .then(() => dispatch(removeFromListSuccess(listId, accountId))) - .catch(err => dispatch(removeFromListFail(listId, accountId, err))); -}; - -export const removeFromListRequest = (listId, accountId) => ({ - type: LIST_EDITOR_REMOVE_REQUEST, - listId, - accountId, -}); - -export const removeFromListSuccess = (listId, accountId) => ({ - type: LIST_EDITOR_REMOVE_SUCCESS, - listId, - accountId, -}); - -export const removeFromListFail = (listId, accountId, error) => ({ - type: LIST_EDITOR_REMOVE_FAIL, - listId, - accountId, - error, -}); - -export const resetListAdder = () => ({ - type: LIST_ADDER_RESET, -}); - -export const setupListAdder = accountId => (dispatch, getState) => { - dispatch({ - type: LIST_ADDER_SETUP, - account: getState().getIn(['accounts', accountId]), - }); - dispatch(fetchLists()); - dispatch(fetchAccountLists(accountId)); -}; - -export const fetchAccountLists = accountId => (dispatch) => { - dispatch(fetchAccountListsRequest(accountId)); - - api().get(`/api/v1/accounts/${accountId}/lists`) - .then(({ data }) => dispatch(fetchAccountListsSuccess(accountId, data))) - .catch(err => dispatch(fetchAccountListsFail(accountId, err))); -}; - -export const fetchAccountListsRequest = id => ({ - type:LIST_ADDER_LISTS_FETCH_REQUEST, - id, -}); - -export const fetchAccountListsSuccess = (id, lists) => ({ - type: LIST_ADDER_LISTS_FETCH_SUCCESS, - id, - lists, -}); - -export const fetchAccountListsFail = (id, err) => ({ - type: LIST_ADDER_LISTS_FETCH_FAIL, - id, - err, -}); - -export const addToListAdder = listId => (dispatch, getState) => { - dispatch(addToList(listId, getState().getIn(['listAdder', 'accountId']))); -}; - -export const removeFromListAdder = listId => (dispatch, getState) => { - dispatch(removeFromList(listId, getState().getIn(['listAdder', 'accountId']))); -}; diff --git a/app/javascript/mastodon/actions/lists_typed.ts b/app/javascript/mastodon/actions/lists_typed.ts new file mode 100644 index 0000000000..ccc5c11c89 --- /dev/null +++ b/app/javascript/mastodon/actions/lists_typed.ts @@ -0,0 +1,13 @@ +import { apiCreate, apiUpdate } from 'mastodon/api/lists'; +import type { List } from 'mastodon/models/list'; +import { createDataLoadingThunk } from 'mastodon/store/typed_functions'; + +export const createList = createDataLoadingThunk( + 'list/create', + (list: Partial) => apiCreate(list), +); + +export const updateList = createDataLoadingThunk( + 'list/update', + (list: Partial) => apiUpdate(list), +); diff --git a/app/javascript/mastodon/actions/notification_groups.ts b/app/javascript/mastodon/actions/notification_groups.ts index a3c8095ac4..aa7f50da4e 100644 --- a/app/javascript/mastodon/actions/notification_groups.ts +++ b/app/javascript/mastodon/actions/notification_groups.ts @@ -141,6 +141,9 @@ export const pollRecentNotifications = createDataLoadingThunk( return { notifications }; }, + { + useLoadingBar: false, + }, ); export const processNewNotificationForGroups = createAppAsyncThunk( diff --git a/app/javascript/mastodon/api.ts b/app/javascript/mastodon/api.ts index 51cbe0b695..f0663ded40 100644 --- a/app/javascript/mastodon/api.ts +++ b/app/javascript/mastodon/api.ts @@ -68,6 +68,7 @@ export async function apiRequest( method: Method, url: string, args: { + signal?: AbortSignal; params?: RequestParamsOrData; data?: RequestParamsOrData; timeout?: number; diff --git a/app/javascript/mastodon/api/lists.ts b/app/javascript/mastodon/api/lists.ts new file mode 100644 index 0000000000..a5586eb6d4 --- /dev/null +++ b/app/javascript/mastodon/api/lists.ts @@ -0,0 +1,32 @@ +import { + apiRequestPost, + apiRequestPut, + apiRequestGet, + apiRequestDelete, +} from 'mastodon/api'; +import type { ApiAccountJSON } from 'mastodon/api_types/accounts'; +import type { ApiListJSON } from 'mastodon/api_types/lists'; + +export const apiCreate = (list: Partial) => + apiRequestPost('v1/lists', list); + +export const apiUpdate = (list: Partial) => + apiRequestPut(`v1/lists/${list.id}`, list); + +export const apiGetAccounts = (listId: string) => + apiRequestGet(`v1/lists/${listId}/accounts`, { + limit: 0, + }); + +export const apiGetAccountLists = (accountId: string) => + apiRequestGet(`v1/accounts/${accountId}/lists`); + +export const apiAddAccountToList = (listId: string, accountId: string) => + apiRequestPost(`v1/lists/${listId}/accounts`, { + account_ids: [accountId], + }); + +export const apiRemoveAccountFromList = (listId: string, accountId: string) => + apiRequestDelete(`v1/lists/${listId}/accounts`, { + account_ids: [accountId], + }); diff --git a/app/javascript/mastodon/api_types/lists.ts b/app/javascript/mastodon/api_types/lists.ts new file mode 100644 index 0000000000..6984cf9b19 --- /dev/null +++ b/app/javascript/mastodon/api_types/lists.ts @@ -0,0 +1,10 @@ +// See app/serializers/rest/list_serializer.rb + +export type RepliesPolicyType = 'list' | 'followed' | 'none'; + +export interface ApiListJSON { + id: string; + title: string; + exclusive: boolean; + replies_policy: RepliesPolicyType; +} 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/check_box.tsx b/app/javascript/mastodon/components/check_box.tsx index 9bd137abf5..73fdb2f97b 100644 --- a/app/javascript/mastodon/components/check_box.tsx +++ b/app/javascript/mastodon/components/check_box.tsx @@ -7,11 +7,11 @@ import { Icon } from './icon'; interface Props { value: string; - checked: boolean; - indeterminate: boolean; - name: string; - onChange: (event: React.ChangeEvent) => void; - label: React.ReactNode; + checked?: boolean; + indeterminate?: boolean; + name?: string; + onChange?: (event: React.ChangeEvent) => void; + label?: React.ReactNode; } export const CheckBox: React.FC = ({ @@ -30,6 +30,7 @@ export const CheckBox: React.FC = ({ value={value} checked={checked} onChange={onChange} + readOnly={!onChange} /> = ({ )} - {label} + {label && {label}} ); }; 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/scrollable_list.jsx b/app/javascript/mastodon/components/scrollable_list.jsx index 29439fdf55..35cd86ea1a 100644 --- a/app/javascript/mastodon/components/scrollable_list.jsx +++ b/app/javascript/mastodon/components/scrollable_list.jsx @@ -80,6 +80,7 @@ class ScrollableList extends PureComponent { children: PropTypes.node, bindToDocument: PropTypes.bool, preventScroll: PropTypes.bool, + footer: PropTypes.node, }; static defaultProps = { @@ -324,7 +325,7 @@ class ScrollableList extends PureComponent { }; render () { - const { children, scrollKey, trackScroll, showLoading, isLoading, hasMore, numPending, prepend, alwaysPrepend, append, emptyMessage, onLoadMore } = this.props; + const { children, scrollKey, trackScroll, showLoading, isLoading, hasMore, numPending, prepend, alwaysPrepend, append, footer, emptyMessage, onLoadMore } = this.props; const { fullscreen } = this.state; const childrenCount = Children.count(children); @@ -342,11 +343,13 @@ class ScrollableList extends PureComponent {
+ + {footer}
); } else if (isLoading || childrenCount > 0 || numPending > 0 || hasMore || !emptyMessage) { scrollableArea = ( -
+
{prepend} @@ -375,6 +378,8 @@ class ScrollableList extends PureComponent { {!hasMore && append}
+ + {footer}
); } else { @@ -385,6 +390,8 @@ class ScrollableList extends PureComponent {
{emptyMessage}
+ + {footer}
); } diff --git a/app/javascript/mastodon/components/status.jsx b/app/javascript/mastodon/components/status.jsx index 4792136368..669eb22cb6 100644 --- a/app/javascript/mastodon/components/status.jsx +++ b/app/javascript/mastodon/components/status.jsx @@ -3,6 +3,8 @@ import PropTypes from 'prop-types'; import { injectIntl, defineMessages, FormattedMessage } from 'react-intl'; import classNames from 'classnames'; +import { Link } from 'react-router-dom'; + import ImmutablePropTypes from 'react-immutable-proptypes'; import ImmutablePureComponent from 'react-immutable-pure-component'; @@ -164,32 +166,18 @@ class Status extends ImmutablePureComponent { }; handleClick = e => { - if (e && (e.button !== 0 || e.ctrlKey || e.metaKey)) { + e.preventDefault(); + this.handleHotkeyOpen(e); + }; + + handleMouseUp = e => { + // Only handle clicks on the empty space above the content + + if (e.target !== e.currentTarget) { return; } - if (e) { - e.preventDefault(); - } - - this.handleHotkeyOpen(); - }; - - handlePrependAccountClick = e => { - this.handleAccountClick(e, false); - }; - - handleAccountClick = (e, proper = true) => { - if (e && (e.button !== 0 || e.ctrlKey || e.metaKey)) { - return; - } - - if (e) { - e.preventDefault(); - e.stopPropagation(); - } - - this._openProfile(proper); + this.handleClick(e); }; handleExpandedToggle = () => { @@ -287,7 +275,7 @@ class Status extends ImmutablePureComponent { this.props.onMention(this._properStatus().get('account')); }; - handleHotkeyOpen = () => { + handleHotkeyOpen = (e) => { if (this.props.onClick) { this.props.onClick(); return; @@ -300,7 +288,13 @@ class Status extends ImmutablePureComponent { return; } - history.push(`/@${status.getIn(['account', 'acct'])}/${status.get('id')}`); + const path = `/@${status.getIn(['account', 'acct'])}/${status.get('id')}`; + + if (e?.button === 0 && !(e?.ctrlKey || e?.metaKey)) { + history.push(path); + } else if (e?.button === 1 || (e?.button === 0 && (e?.ctrlKey || e?.metaKey))) { + window.open(path, '_blank', 'noreferrer noopener'); + } }; handleHotkeyOpenProfile = () => { @@ -394,17 +388,6 @@ class Status extends ImmutablePureComponent { let media, statusAvatar, prepend, rebloggedByText; - if (hidden) { - return ( - -
- {status.getIn(['account', 'display_name']) || status.getIn(['account', 'username'])} - {status.get('content')} -
-
- ); - } - 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'); @@ -423,7 +406,7 @@ class Status extends ImmutablePureComponent { prepend = (
- }} /> + }} />
); @@ -444,6 +427,20 @@ class Status extends ImmutablePureComponent { ); } + 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('spoiler_text').length > 0 && ({status.get('spoiler_text')})} + {expanded && {status.get('content')}} +
+
+ ); + } + if (pictureInPicture.get('inUse')) { media = ; } else if (status.get('media_attachments').size > 0) { @@ -538,7 +535,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 ( @@ -548,20 +544,19 @@ class Status extends ImmutablePureComponent {
{(connectReply || connectUp || connectToRoot) &&
} - {/* eslint-disable-next-line jsx-a11y/no-static-element-interactions */} -
- + {matchedFilters && } diff --git a/app/javascript/mastodon/components/status_content.jsx b/app/javascript/mastodon/components/status_content.jsx index 4950c896f9..fe485eb3ac 100644 --- a/app/javascript/mastodon/components/status_content.jsx +++ b/app/javascript/mastodon/components/status_content.jsx @@ -204,8 +204,8 @@ class StatusContent extends PureComponent { element = element.parentNode; } - if (deltaX + deltaY < 5 && e.button === 0 && this.props.onClick) { - this.props.onClick(); + if (deltaX + deltaY < 5 && (e.button === 0 || e.button === 1) && this.props.onClick) { + this.props.onClick(e); } this.startXY = null; diff --git a/app/javascript/mastodon/containers/dropdown_menu_container.js b/app/javascript/mastodon/containers/dropdown_menu_container.js index bc9124c041..dc2a9648ff 100644 --- a/app/javascript/mastodon/containers/dropdown_menu_container.js +++ b/app/javascript/mastodon/containers/dropdown_menu_container.js @@ -15,6 +15,13 @@ const mapStateToProps = state => ({ openedViaKeyboard: state.dropdownMenu.keyboard, }); +/** + * @param {any} dispatch + * @param {Object} root0 + * @param {any} [root0.status] + * @param {any} root0.items + * @param {any} [root0.scrollKey] + */ const mapDispatchToProps = (dispatch, { status, items, scrollKey }) => ({ onOpen(id, onItemClick, keyboard) { if (status) { 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..4b59b89737 --- /dev/null +++ b/app/javascript/mastodon/features/annual_report/most_used_hashtag.tsx @@ -0,0 +1,30 @@ +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]; + + return ( +
+
+ {hashtag ? ( + <>#{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..22962019a1 --- /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/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 ( - + { - const getAccount = makeGetAccount(); - - const mapStateToProps = (state, { accountId }) => ({ - account: getAccount(state, accountId), - }); - - return mapStateToProps; -}; - -class Account extends ImmutablePureComponent { - - static propTypes = { - account: ImmutablePropTypes.record.isRequired, - }; - - render () { - const { account } = this.props; - return ( -
-
-
-
- -
-
-
- ); - } - -} - -export default connect(makeMapStateToProps)(injectIntl(Account)); diff --git a/app/javascript/mastodon/features/list_adder/components/list.jsx b/app/javascript/mastodon/features/list_adder/components/list.jsx deleted file mode 100644 index a7cfd60bf3..0000000000 --- a/app/javascript/mastodon/features/list_adder/components/list.jsx +++ /dev/null @@ -1,75 +0,0 @@ -import PropTypes from 'prop-types'; - -import { defineMessages, injectIntl } from 'react-intl'; - -import ImmutablePropTypes from 'react-immutable-proptypes'; -import ImmutablePureComponent from 'react-immutable-pure-component'; -import { connect } from 'react-redux'; - -import AddIcon from '@/material-icons/400-24px/add.svg?react'; -import CloseIcon from '@/material-icons/400-24px/close.svg?react'; -import ListAltIcon from '@/material-icons/400-24px/list_alt.svg?react'; -import { Icon } from 'mastodon/components/icon'; - -import { removeFromListAdder, addToListAdder } from '../../../actions/lists'; -import { IconButton } from '../../../components/icon_button'; - -const messages = defineMessages({ - remove: { id: 'lists.account.remove', defaultMessage: 'Remove from list' }, - add: { id: 'lists.account.add', defaultMessage: 'Add to list' }, -}); - -const MapStateToProps = (state, { listId, added }) => ({ - list: state.get('lists').get(listId), - added: typeof added === 'undefined' ? state.getIn(['listAdder', 'lists', 'items']).includes(listId) : added, -}); - -const mapDispatchToProps = (dispatch, { listId }) => ({ - onRemove: () => dispatch(removeFromListAdder(listId)), - onAdd: () => dispatch(addToListAdder(listId)), -}); - -class List extends ImmutablePureComponent { - - static propTypes = { - list: ImmutablePropTypes.map.isRequired, - intl: PropTypes.object.isRequired, - onRemove: PropTypes.func.isRequired, - onAdd: PropTypes.func.isRequired, - added: PropTypes.bool, - }; - - static defaultProps = { - added: false, - }; - - render () { - const { list, intl, onRemove, onAdd, added } = this.props; - - let button; - - if (added) { - button = ; - } else { - button = ; - } - - return ( -
-
-
- - {list.get('title')} -
- -
- {button} -
-
-
- ); - } - -} - -export default connect(MapStateToProps, mapDispatchToProps)(injectIntl(List)); diff --git a/app/javascript/mastodon/features/list_adder/index.jsx b/app/javascript/mastodon/features/list_adder/index.jsx deleted file mode 100644 index 4e7bd46bdf..0000000000 --- a/app/javascript/mastodon/features/list_adder/index.jsx +++ /dev/null @@ -1,76 +0,0 @@ -import PropTypes from 'prop-types'; - -import { injectIntl } from 'react-intl'; - -import { createSelector } from '@reduxjs/toolkit'; -import ImmutablePropTypes from 'react-immutable-proptypes'; -import ImmutablePureComponent from 'react-immutable-pure-component'; -import { connect } from 'react-redux'; - -import { setupListAdder, resetListAdder } from '../../actions/lists'; -import NewListForm from '../lists/components/new_list_form'; - -import Account from './components/account'; -import List from './components/list'; -// hack - -const getOrderedLists = createSelector([state => state.get('lists')], lists => { - if (!lists) { - return lists; - } - - return lists.toList().filter(item => !!item).sort((a, b) => a.get('title').localeCompare(b.get('title'))); -}); - -const mapStateToProps = state => ({ - listIds: getOrderedLists(state).map(list=>list.get('id')), -}); - -const mapDispatchToProps = dispatch => ({ - onInitialize: accountId => dispatch(setupListAdder(accountId)), - onReset: () => dispatch(resetListAdder()), -}); - -class ListAdder extends ImmutablePureComponent { - - static propTypes = { - accountId: PropTypes.string.isRequired, - onClose: PropTypes.func.isRequired, - intl: PropTypes.object.isRequired, - onInitialize: PropTypes.func.isRequired, - onReset: PropTypes.func.isRequired, - listIds: ImmutablePropTypes.list.isRequired, - }; - - componentDidMount () { - const { onInitialize, accountId } = this.props; - onInitialize(accountId); - } - - componentWillUnmount () { - const { onReset } = this.props; - onReset(); - } - - render () { - const { accountId, listIds } = this.props; - - return ( -
-
- -
- - - - -
- {listIds.map(ListId => )} -
-
- ); - } - -} - -export default connect(mapStateToProps, mapDispatchToProps)(injectIntl(ListAdder)); diff --git a/app/javascript/mastodon/features/list_adder/index.tsx b/app/javascript/mastodon/features/list_adder/index.tsx new file mode 100644 index 0000000000..5429c24aed --- /dev/null +++ b/app/javascript/mastodon/features/list_adder/index.tsx @@ -0,0 +1,213 @@ +import { useEffect, useState, useCallback } from 'react'; + +import { FormattedMessage, useIntl, defineMessages } from 'react-intl'; + +import { isFulfilled } from '@reduxjs/toolkit'; + +import CloseIcon from '@/material-icons/400-24px/close.svg?react'; +import ListAltIcon from '@/material-icons/400-24px/list_alt.svg?react'; +import { fetchLists } from 'mastodon/actions/lists'; +import { createList } from 'mastodon/actions/lists_typed'; +import { + apiGetAccountLists, + apiAddAccountToList, + apiRemoveAccountFromList, +} from 'mastodon/api/lists'; +import type { ApiListJSON } from 'mastodon/api_types/lists'; +import { Button } from 'mastodon/components/button'; +import { CheckBox } from 'mastodon/components/check_box'; +import { Icon } from 'mastodon/components/icon'; +import { IconButton } from 'mastodon/components/icon_button'; +import { getOrderedLists } from 'mastodon/selectors/lists'; +import { useAppDispatch, useAppSelector } from 'mastodon/store'; + +const messages = defineMessages({ + newList: { + id: 'lists.new_list_name', + defaultMessage: 'New list name', + }, + createList: { + id: 'lists.create', + defaultMessage: 'Create', + }, + close: { + id: 'lightbox.close', + defaultMessage: 'Close', + }, +}); + +const ListItem: React.FC<{ + id: string; + title: string; + checked: boolean; + onChange: (id: string, checked: boolean) => void; +}> = ({ id, title, checked, onChange }) => { + const handleChange = useCallback( + (e: React.ChangeEvent) => { + onChange(id, e.target.checked); + }, + [id, onChange], + ); + + return ( + // eslint-disable-next-line jsx-a11y/label-has-associated-control + + ); +}; + +const NewListItem: React.FC<{ + onCreate: (list: ApiListJSON) => void; +}> = ({ onCreate }) => { + const intl = useIntl(); + const dispatch = useAppDispatch(); + const [title, setTitle] = useState(''); + + const handleChange = useCallback( + ({ target: { value } }: React.ChangeEvent) => { + setTitle(value); + }, + [setTitle], + ); + + const handleSubmit = useCallback(() => { + if (title.trim().length === 0) { + return; + } + + void dispatch(createList({ title })).then((result) => { + if (isFulfilled(result)) { + onCreate(result.payload); + setTitle(''); + } + + return ''; + }); + }, [setTitle, dispatch, onCreate, title]); + + return ( +
+ + +
+ - -
-
- - -
-
- - {replies_policy !== undefined && ( -
-

- -
- { ['none', 'list', 'followed'].map(policy => ( - - ))} -
-
- )}
@@ -229,4 +178,4 @@ class ListTimeline extends PureComponent { } -export default withRouter(connect(mapStateToProps)(injectIntl(ListTimeline))); +export default withRouter(connect(mapStateToProps)(ListTimeline)); diff --git a/app/javascript/mastodon/features/lists/components/new_list_form.jsx b/app/javascript/mastodon/features/lists/components/new_list_form.jsx deleted file mode 100644 index 0fed9d70a2..0000000000 --- a/app/javascript/mastodon/features/lists/components/new_list_form.jsx +++ /dev/null @@ -1,80 +0,0 @@ -import PropTypes from 'prop-types'; -import { PureComponent } from 'react'; - -import { defineMessages, injectIntl } from 'react-intl'; - -import { connect } from 'react-redux'; - -import { changeListEditorTitle, submitListEditor } from 'mastodon/actions/lists'; -import { Button } from 'mastodon/components/button'; - -const messages = defineMessages({ - label: { id: 'lists.new.title_placeholder', defaultMessage: 'New list title' }, - title: { id: 'lists.new.create', defaultMessage: 'Add list' }, -}); - -const mapStateToProps = state => ({ - value: state.getIn(['listEditor', 'title']), - disabled: state.getIn(['listEditor', 'isSubmitting']), -}); - -const mapDispatchToProps = dispatch => ({ - onChange: value => dispatch(changeListEditorTitle(value)), - onSubmit: () => dispatch(submitListEditor(true)), -}); - -class NewListForm extends PureComponent { - - static propTypes = { - value: PropTypes.string.isRequired, - disabled: PropTypes.bool, - intl: PropTypes.object.isRequired, - onChange: PropTypes.func.isRequired, - onSubmit: PropTypes.func.isRequired, - }; - - handleChange = e => { - this.props.onChange(e.target.value); - }; - - handleSubmit = e => { - e.preventDefault(); - this.props.onSubmit(); - }; - - handleClick = () => { - this.props.onSubmit(); - }; - - render () { - const { value, disabled, intl } = this.props; - - const label = intl.formatMessage(messages.label); - const title = intl.formatMessage(messages.title); - - return ( -
- - -
+ + + + + ); +}; + +const AccountItem: React.FC<{ + accountId: string; + listId: string; + partOfList: boolean; + onToggle: (accountId: string) => void; +}> = ({ accountId, listId, partOfList, onToggle }) => { + const intl = useIntl(); + const account = useAppSelector((state) => state.accounts.get(accountId)); + + const handleClick = useCallback(() => { + if (partOfList) { + void apiRemoveAccountFromList(listId, accountId); + } else { + void apiAddAccountToList(listId, accountId); + } + + onToggle(accountId); + }, [accountId, listId, partOfList, onToggle]); + + if (!account) { + return null; + } + + const firstVerifiedField = account.fields.find((item) => !!item.verified_at); + + return ( +
+
+ +
+ +
+ +
+ + +
+ {' '} + {firstVerifiedField && ( + + )} +
+
+ + +
+
+
+
+ ); +}; + +const ListMembers: React.FC<{ + multiColumn?: boolean; +}> = ({ multiColumn }) => { + const dispatch = useAppDispatch(); + const { id } = useParams<{ id: string }>(); + const intl = useIntl(); + + const followingAccountIds = useAppSelector( + (state) => state.user_lists.getIn(['following', me, 'items']) as string[], + ); + const [searching, setSearching] = useState(false); + const [accountIds, setAccountIds] = useState([]); + const [searchAccountIds, setSearchAccountIds] = useState([]); + const [loading, setLoading] = useState(true); + const [mode, setMode] = useState('remove'); + + useEffect(() => { + if (id) { + setLoading(true); + dispatch(fetchList(id)); + + void apiGetAccounts(id) + .then((data) => { + dispatch(importFetchedAccounts(data)); + setAccountIds(data.map((a) => a.id)); + setLoading(false); + return ''; + }) + .catch(() => { + setLoading(false); + }); + + dispatch(fetchFollowing(me)); + } + }, [dispatch, id]); + + const handleSearchClick = useCallback(() => { + setMode('add'); + }, [setMode]); + + const handleDismissSearchClick = useCallback(() => { + setMode('remove'); + setSearching(false); + }, [setMode]); + + const handleAccountToggle = useCallback( + (accountId: string) => { + const partOfList = accountIds.includes(accountId); + + if (partOfList) { + setAccountIds(accountIds.filter((id) => id !== accountId)); + } else { + setAccountIds([accountId, ...accountIds]); + } + }, + [accountIds, setAccountIds], + ); + + const searchRequestRef = useRef(null); + + const handleSearch = useDebouncedCallback( + (value: string) => { + if (searchRequestRef.current) { + searchRequestRef.current.abort(); + } + + if (value.trim().length === 0) { + setSearching(false); + return; + } + + setLoading(true); + + searchRequestRef.current = new AbortController(); + + void apiRequest('GET', 'v1/accounts/search', { + signal: searchRequestRef.current.signal, + params: { + q: value, + resolve: false, + following: true, + }, + }) + .then((data) => { + dispatch(importFetchedAccounts(data)); + setSearchAccountIds(data.map((a) => a.id)); + setLoading(false); + setSearching(true); + return ''; + }) + .catch(() => { + setSearching(true); + setLoading(false); + }); + }, + 500, + { leading: true, trailing: true }, + ); + + let displayedAccountIds: string[]; + + if (mode === 'add') { + displayedAccountIds = searching ? searchAccountIds : followingAccountIds; + } else { + displayedAccountIds = accountIds; + } + + return ( + + {mode === 'remove' ? ( + + + + } + /> + ) : ( + + )} + + +
+ +
+ + + +
+ + ) + } + emptyMessage={ + mode === 'remove' ? ( + <> + + +
+ +
+ + + + ) : ( + + ) + } + > + {displayedAccountIds.map((accountId) => ( + + ))} + + + + {intl.formatMessage(messages.heading)} + + + + ); +}; + +// eslint-disable-next-line import/no-default-export +export default ListMembers; diff --git a/app/javascript/mastodon/features/lists/new.tsx b/app/javascript/mastodon/features/lists/new.tsx new file mode 100644 index 0000000000..cf39331d7c --- /dev/null +++ b/app/javascript/mastodon/features/lists/new.tsx @@ -0,0 +1,296 @@ +import { useCallback, useState, useEffect } from 'react'; + +import { defineMessages, useIntl, FormattedMessage } from 'react-intl'; + +import { Helmet } from 'react-helmet'; +import { useParams, useHistory, Link } from 'react-router-dom'; + +import { isFulfilled } from '@reduxjs/toolkit'; + +import Toggle from 'react-toggle'; + +import ListAltIcon from '@/material-icons/400-24px/list_alt.svg?react'; +import { fetchList } from 'mastodon/actions/lists'; +import { createList, updateList } from 'mastodon/actions/lists_typed'; +import { apiGetAccounts } from 'mastodon/api/lists'; +import type { RepliesPolicyType } from 'mastodon/api_types/lists'; +import Column from 'mastodon/components/column'; +import { ColumnHeader } from 'mastodon/components/column_header'; +import { LoadingIndicator } from 'mastodon/components/loading_indicator'; +import { useAppDispatch, useAppSelector } from 'mastodon/store'; + +const messages = defineMessages({ + edit: { id: 'column.edit_list', defaultMessage: 'Edit list' }, + create: { id: 'column.create_list', defaultMessage: 'Create list' }, +}); + +const MembersLink: React.FC<{ + id: string; +}> = ({ id }) => { + const [count, setCount] = useState(0); + const [avatars, setAvatars] = useState([]); + + useEffect(() => { + void apiGetAccounts(id) + .then((data) => { + setCount(data.length); + setAvatars(data.slice(0, 3).map((a) => a.avatar)); + return ''; + }) + .catch(() => { + // Nothing + }); + }, [id, setCount, setAvatars]); + + return ( + +
+ + + + +
+ +
+ {avatars.map((url) => ( + + ))} +
+ + ); +}; + +const NewList: React.FC<{ + multiColumn?: boolean; +}> = ({ multiColumn }) => { + const dispatch = useAppDispatch(); + const { id } = useParams<{ id?: string }>(); + const intl = useIntl(); + const history = useHistory(); + + const list = useAppSelector((state) => + id ? state.lists.get(id) : undefined, + ); + const [title, setTitle] = useState(''); + const [exclusive, setExclusive] = useState(false); + const [repliesPolicy, setRepliesPolicy] = useState('list'); + const [submitting, setSubmitting] = useState(false); + + useEffect(() => { + if (id) { + dispatch(fetchList(id)); + } + }, [dispatch, id]); + + useEffect(() => { + if (id && list) { + setTitle(list.title); + setExclusive(list.exclusive); + setRepliesPolicy(list.replies_policy); + } + }, [setTitle, setExclusive, setRepliesPolicy, id, list]); + + const handleTitleChange = useCallback( + ({ target: { value } }: React.ChangeEvent) => { + setTitle(value); + }, + [setTitle], + ); + + const handleExclusiveChange = useCallback( + ({ target: { checked } }: React.ChangeEvent) => { + setExclusive(checked); + }, + [setExclusive], + ); + + const handleRepliesPolicyChange = useCallback( + ({ target: { value } }: React.ChangeEvent) => { + setRepliesPolicy(value as RepliesPolicyType); + }, + [setRepliesPolicy], + ); + + const handleSubmit = useCallback(() => { + setSubmitting(true); + + if (id) { + void dispatch( + updateList({ + id, + title, + exclusive, + replies_policy: repliesPolicy, + }), + ).then(() => { + setSubmitting(false); + return ''; + }); + } else { + void dispatch( + createList({ + title, + exclusive, + replies_policy: repliesPolicy, + }), + ).then((result) => { + setSubmitting(false); + + if (isFulfilled(result)) { + history.replace(`/lists/${result.payload.id}/edit`); + history.push(`/lists/${result.payload.id}/members`); + } + + return ''; + }); + } + }, [history, dispatch, setSubmitting, id, title, exclusive, repliesPolicy]); + + return ( + + + +
+
+
+
+
+ + +
+ +
+
+
+
+ +
+
+
+ + +
+ +
+
+
+
+ + {id && ( +
+ +
+ )} + +
+ {/* eslint-disable-next-line jsx-a11y/label-has-associated-control */} + +
+ +
+ +
+
+
+ + + + {intl.formatMessage(id ? messages.edit : messages.create)} + + + +
+ ); +}; + +// eslint-disable-next-line import/no-default-export +export default NewList; diff --git a/app/javascript/mastodon/features/notifications_v2/components/embedded_status.tsx b/app/javascript/mastodon/features/notifications_v2/components/embedded_status.tsx index 65ea9b5d5e..ca0d1bc850 100644 --- a/app/javascript/mastodon/features/notifications_v2/components/embedded_status.tsx +++ b/app/javascript/mastodon/features/notifications_v2/components/embedded_status.tsx @@ -43,7 +43,7 @@ export const EmbeddedStatus: React.FC<{ statusId: string }> = ({ ); const handleMouseUp = useCallback>( - ({ clientX, clientY, target, button }) => { + ({ clientX, clientY, target, button, ctrlKey, metaKey }) => { const [startX, startY] = clickCoordinatesRef.current ?? [0, 0]; const [deltaX, deltaY] = [ Math.abs(clientX - startX), @@ -64,8 +64,14 @@ export const EmbeddedStatus: React.FC<{ statusId: string }> = ({ element = element.parentNode as HTMLDivElement | null; } - if (deltaX + deltaY < 5 && button === 0 && account) { - history.push(`/@${account.acct}/${statusId}`); + if (deltaX + deltaY < 5 && account) { + const path = `/@${account.acct}/${statusId}`; + + if (button === 0 && !(ctrlKey || metaKey)) { + history.push(path); + } else if (button === 1 || (button === 0 && (ctrlKey || metaKey))) { + window.open(path, '_blank', 'noreferrer noopener'); + } } clickCoordinatesRef.current = null; 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_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/status/components/detailed_status.tsx b/app/javascript/mastodon/features/status/components/detailed_status.tsx index 5811efb190..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, @@ -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/boost_modal.tsx b/app/javascript/mastodon/features/ui/components/boost_modal.tsx index cdf7138d49..72a28a01f9 100644 --- a/app/javascript/mastodon/features/ui/components/boost_modal.tsx +++ b/app/javascript/mastodon/features/ui/components/boost_modal.tsx @@ -128,6 +128,8 @@ export const BoostModal: React.FC<{ ? messages.cancel_reblog : messages.reblog, )} + /* eslint-disable-next-line jsx-a11y/no-autofocus -- We are in the modal */ + autoFocus />
diff --git a/app/javascript/mastodon/features/ui/components/modal_root.jsx b/app/javascript/mastodon/features/ui/components/modal_root.jsx index 64933fd1ae..8a97ec4565 100644 --- a/app/javascript/mastodon/features/ui/components/modal_root.jsx +++ b/app/javascript/mastodon/features/ui/components/modal_root.jsx @@ -10,7 +10,6 @@ import { DomainBlockModal, ReportModal, EmbedModal, - ListEditor, ListAdder, CompareHistoryModal, FilterModal, @@ -18,6 +17,7 @@ import { SubscribedLanguagesModal, ClosedRegistrationsModal, IgnoreNotificationsModal, + AnnualReportModal, } from 'mastodon/features/ui/util/async-components'; import { getScrollbarWidth } from 'mastodon/utils/scrollbar'; @@ -63,7 +63,6 @@ export const MODAL_COMPONENTS = { 'REPORT': ReportModal, 'ACTIONS': () => Promise.resolve({ default: ActionsModal }), 'EMBED': EmbedModal, - 'LIST_EDITOR': ListEditor, 'FOCAL_POINT': () => Promise.resolve({ default: FocalPointModal }), 'LIST_ADDER': ListAdder, 'COMPARE_HISTORY': CompareHistoryModal, @@ -72,6 +71,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/index.jsx b/app/javascript/mastodon/features/ui/index.jsx index 2f9f962b81..daa4585ead 100644 --- a/app/javascript/mastodon/features/ui/index.jsx +++ b/app/javascript/mastodon/features/ui/index.jsx @@ -58,11 +58,13 @@ import { FollowedTags, LinkTimeline, ListTimeline, + Lists, + ListEdit, + ListMembers, Blocks, DomainBlocks, Mutes, PinnedStatuses, - Lists, Directory, Explore, Onboarding, @@ -205,6 +207,9 @@ class SwitchingColumnsArea extends PureComponent { + + + @@ -482,7 +487,9 @@ class UI extends PureComponent { } }; - handleHotkeyBack = () => { + handleHotkeyBack = e => { + e.preventDefault(); + const { history } = this.props; if (history.location?.state?.fromMastodon) { diff --git a/app/javascript/mastodon/features/ui/util/async-components.js b/app/javascript/mastodon/features/ui/util/async-components.js index 7e9a7af00a..5a85c856d2 100644 --- a/app/javascript/mastodon/features/ui/util/async-components.js +++ b/app/javascript/mastodon/features/ui/util/async-components.js @@ -150,10 +150,6 @@ export function EmbedModal () { return import(/* webpackChunkName: "modals/embed_modal" */'../components/embed_modal'); } -export function ListEditor () { - return import(/* webpackChunkName: "features/list_editor" */'../../list_editor'); -} - export function ListAdder () { return import(/*webpackChunkName: "features/list_adder" */'../../list_adder'); } @@ -217,3 +213,15 @@ 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'); +} + +export function ListEdit () { + return import(/*webpackChunkName: "features/lists" */'../../lists/new'); +} + +export function ListMembers () { + return import(/* webpackChunkName: "features/lists" */'../../lists/members'); +} diff --git a/app/javascript/mastodon/locales/af.json b/app/javascript/mastodon/locales/af.json index a506b99654..bf84cff111 100644 --- a/app/javascript/mastodon/locales/af.json +++ b/app/javascript/mastodon/locales/af.json @@ -154,7 +154,6 @@ "empty_column.hashtag": "Daar is nog niks vir hierdie hutsetiket nie.", "empty_column.home": "Your home timeline is empty! Follow more people to fill it up. {suggestions}", "empty_column.list": "Hierdie lys is nog leeg. Nuwe plasings deur lyslede sal voortaan hier verskyn.", - "empty_column.lists": "Jy het nog geen lyste nie. Wanneer jy een skep, sal dit hier vertoon.", "empty_column.notifications": "Jy het nog geen kennisgewings nie. Interaksie van ander mense met jou, sal hier vertoon.", "explore.search_results": "Soekresultate", "explore.suggested_follows": "Mense", @@ -222,15 +221,8 @@ "limited_account_hint.action": "Vertoon profiel in elk geval", "limited_account_hint.title": "Hierdie profiel is deur moderators van {domain} versteek.", "link_preview.author": "Deur {name}", - "lists.account.add": "Voeg by lys", - "lists.account.remove": "Verwyder vanaf lys", "lists.delete": "Verwyder lys", "lists.edit": "Redigeer lys", - "lists.edit.submit": "Verander titel", - "lists.new.create": "Voeg lys by", - "lists.new.title_placeholder": "Nuwe lys titel", - "lists.search": "Soek tussen mense wat jy volg", - "lists.subheading": "Jou lyste", "moved_to_account_banner.text": "Jou rekening {disabledAccount} is tans gedeaktiveer omdat jy na {movedToAccount} verhuis het.", "navigation_bar.about": "Oor", "navigation_bar.bookmarks": "Boekmerke", diff --git a/app/javascript/mastodon/locales/an.json b/app/javascript/mastodon/locales/an.json index be303985ee..11be07e990 100644 --- a/app/javascript/mastodon/locales/an.json +++ b/app/javascript/mastodon/locales/an.json @@ -186,7 +186,6 @@ "empty_column.hashtag": "No i hai cosa en este hashtag encara.", "empty_column.home": "La tuya linia temporal ye vueda! Sigue a mas personas pa replenar-la. {suggestions}", "empty_column.list": "No i hai cosa en esta lista encara. Quan miembros d'esta lista publiquen nuevos estatus, estes amaneixerán qui.", - "empty_column.lists": "No tiens garra lista. Quan en crees una, s'amostrará aquí.", "empty_column.mutes": "Encara no has silenciau a garra usuario.", "empty_column.notifications": "No tiens garra notificación encara. Interactúa con atros pa empecipiar una conversación.", "empty_column.public": "No i hai cosa aquí! Escribe bella cosa publicament, u sigue usuarios d'atras instancias manualment pa emplir-lo", @@ -292,19 +291,11 @@ "lightbox.previous": "Anterior", "limited_account_hint.action": "Amostrar perfil de totz modos", "limited_account_hint.title": "Este perfil ha estau amagau per los moderadors de {domain}.", - "lists.account.add": "Anyadir a lista", - "lists.account.remove": "Sacar de lista", "lists.delete": "Borrar lista", "lists.edit": "Editar lista", - "lists.edit.submit": "Cambiar titol", - "lists.new.create": "Anyadir lista", - "lists.new.title_placeholder": "Titol d'a nueva lista", "lists.replies_policy.followed": "Qualsequier usuario seguiu", "lists.replies_policy.list": "Miembros d'a lista", "lists.replies_policy.none": "Dengún", - "lists.replies_policy.title": "Amostrar respuestas a:", - "lists.search": "Buscar entre la chent a la quala sigues", - "lists.subheading": "Las tuyas listas", "load_pending": "{count, plural, one {# nuevo elemento} other {# nuevos elementos}}", "moved_to_account_banner.text": "La tuya cuenta {disabledAccount} ye actualment deshabilitada perque t'has mudau a {movedToAccount}.", "navigation_bar.about": "Sobre", diff --git a/app/javascript/mastodon/locales/ar.json b/app/javascript/mastodon/locales/ar.json index 54ed1cb8c8..f17d3dae22 100644 --- a/app/javascript/mastodon/locales/ar.json +++ b/app/javascript/mastodon/locales/ar.json @@ -86,6 +86,7 @@ "alert.unexpected.title": "المعذرة!", "alt_text_badge.title": "نص بديل", "announcement.announcement": "إعلان", + "annual_report.summary.archetype.booster": "The cool-hunter", "attachments_list.unprocessed": "(غير معالَج)", "audio.hide": "إخفاء المقطع الصوتي", "block_modal.remote_users_caveat": "سوف نطلب من الخادم {domain} أن يحترم قرارك، لكن الالتزام غير مضمون لأن بعض الخواديم قد تتعامل مع نصوص الكتل بشكل مختلف. قد تظل المنشورات العامة مرئية للمستخدمين غير المسجلين الدخول.", @@ -268,7 +269,6 @@ "empty_column.hashtag": "ليس هناك بعدُ أي محتوى ذو علاقة بهذا الوسم.", "empty_column.home": "إنّ الخيط الزمني لصفحتك الرئيسة فارغ. قم بمتابعة المزيد من الناس كي يمتلأ.", "empty_column.list": "هذه القائمة فارغة مؤقتا و لكن سوف تمتلئ تدريجيا عندما يبدأ الأعضاء المُنتَمين إليها بنشر منشورات.", - "empty_column.lists": "ليس عندك أية قائمة بعد. سوف تظهر قوائمك هنا إن قمت بإنشاء واحدة.", "empty_column.mutes": "لم تقم بكتم أي مستخدم بعد.", "empty_column.notification_requests": "لا يوجد شيء هنا. عندما تتلقى إشعارات جديدة، سوف تظهر هنا وفقًا لإعداداتك.", "empty_column.notifications": "لم تتلق أي إشعار بعدُ. تفاعل مع المستخدمين الآخرين لإنشاء محادثة.", @@ -424,20 +424,11 @@ "limited_account_hint.title": "تم إخفاء هذا الملف الشخصي من قبل مشرفي {domain}.", "link_preview.author": "مِن {name}", "link_preview.more_from_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.followed": "أي مستخدم متابَع", "lists.replies_policy.list": "أعضاء القائمة", "lists.replies_policy.none": "لا أحد", - "lists.replies_policy.title": "عرض الردود لـ:", - "lists.search": "إبحث في قائمة الحسابات التي تُتابِعها", - "lists.subheading": "قوائمك", "load_pending": "{count, plural, one {# عنصر جديد} other {# عناصر جديدة}}", "loading_indicator.label": "جاري التحميل…", "media_gallery.hide": "إخفاء", @@ -489,6 +480,7 @@ "notification.label.private_reply": "رد خاص", "notification.label.reply": "ردّ", "notification.mention": "إشارة", + "notification.mentioned_you": "{name} mentioned you", "notification.moderation-warning.learn_more": "اعرف المزيد", "notification.moderation_warning": "لقد تلقيت تحذيرًا بالإشراف", "notification.moderation_warning.action_delete_statuses": "تم حذف بعض من منشوراتك.", diff --git a/app/javascript/mastodon/locales/ast.json b/app/javascript/mastodon/locales/ast.json index e5b1168bea..e6659510d2 100644 --- a/app/javascript/mastodon/locales/ast.json +++ b/app/javascript/mastodon/locales/ast.json @@ -155,7 +155,6 @@ "empty_column.hashtag": "Entá nun hai nada con esta etiqueta.", "empty_column.home": "¡La to llinia de tiempu ta balera! Sigui a cuentes pa enllenala.", "empty_column.list": "Nun hai nada nesta llista. Cuando los perfiles d'esta llista espublicen artículos nuevos, apaecen equí.", - "empty_column.lists": "Nun tienes nenguna llista. Cuando crees dalguna, apaez equí.", "empty_column.mutes": "Nun tienes nengún perfil colos avisos desactivaos.", "empty_column.notifications": "Nun tienes nengún avisu. Cuando otros perfiles interactúen contigo, apaez equí.", "empty_column.public": "¡Equí nun hai nada! Escribi daqué públicamente o sigui a perfiles d'otros sirvidores pa enllenar esta seición", @@ -260,15 +259,9 @@ "limited_account_hint.action": "Amosar el perfil de toes toes", "lists.delete": "Desaniciar la llista", "lists.edit": "Editar la llista", - "lists.edit.submit": "Camudar el títulu", - "lists.new.create": "Amestar la llista", - "lists.new.title_placeholder": "Títulu", "lists.replies_policy.followed": "Cualesquier perfil siguíu", "lists.replies_policy.list": "Perfiles de la llista", "lists.replies_policy.none": "Naide", - "lists.replies_policy.title": "Amosar les rempuestes a:", - "lists.search": "Buscar ente los perfiles que sigues", - "lists.subheading": "Les tos llistes", "load_pending": "{count, plural, one {# elementu nuevu} other {# elementos nuevos}}", "navigation_bar.about": "Tocante a", "navigation_bar.blocks": "Perfiles bloquiaos", diff --git a/app/javascript/mastodon/locales/be.json b/app/javascript/mastodon/locales/be.json index 97d4dc4b4c..26a42ebc69 100644 --- a/app/javascript/mastodon/locales/be.json +++ b/app/javascript/mastodon/locales/be.json @@ -154,7 +154,7 @@ "compose_form.hashtag_warning": "Гэты допіс не будзе паказаны пад аніякім хэштэгам, бо ён не публічны. Толькі публічныя допісы можна знайсці па хэштэгу.", "compose_form.lock_disclaimer": "Ваш уліковы запіс не {locked}. Усе могуць падпісацца на вас, каб бачыць допісы толькі для падпісчыкаў.", "compose_form.lock_disclaimer.lock": "закрыты", - "compose_form.placeholder": "Што здарылася?", + "compose_form.placeholder": "Што ў вас новага?", "compose_form.poll.duration": "Працягласць апытання", "compose_form.poll.multiple": "Множны выбар", "compose_form.poll.option_placeholder": "Варыянт {number}", @@ -273,7 +273,6 @@ "empty_column.hashtag": "Па гэтаму хэштэгу пакуль што нічога няма.", "empty_column.home": "Галоўная стужка пустая! Падпішыцеся на іншых людзей, каб запоўніць яе. {suggestions}", "empty_column.list": "У гэтым спісе пакуль што нічога няма. Калі члены лісту апублікуюць новыя запісы, яны з'явяцца тут.", - "empty_column.lists": "Як толькі вы створыце новы спіс ён будзе захоўвацца тут, але пакуль што тут пуста.", "empty_column.mutes": "Вы яшчэ нікога не ігнаруеце.", "empty_column.notification_requests": "Чысціня! Тут нічога няма. Калі вы будзеце атрымліваць новыя апавяшчэння, яны будуць з'яўляцца тут у адпаведнасці з вашымі наладамі.", "empty_column.notifications": "У вас няма ніякіх апавяшчэнняў. Калі іншыя людзі ўзаемадзейнічаюць з вамі, вы ўбачыце гэта тут.", @@ -427,20 +426,11 @@ "link_preview.author": "Ад {name}", "link_preview.more_from_author": "Больш ад {name}", "link_preview.shares": "{count, plural, one {{counter} допіс} few {{counter} допісы} many {{counter} допісаў} other {{counter} допісу}}", - "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.followed": "Любы карыстальнік, на якога вы падпісаліся", "lists.replies_policy.list": "Удзельнікі гэтага спісу", "lists.replies_policy.none": "Нікога", - "lists.replies_policy.title": "Паказваць адказы:", - "lists.search": "Шукайце сярод людзей, на якіх Вы падпісаны", - "lists.subheading": "Вашыя спісы", "load_pending": "{count, plural, one {# новы элемент} few {# новыя элементы} many {# новых элементаў} other {# новых элементаў}}", "loading_indicator.label": "Загрузка…", "media_gallery.hide": "Схаваць", diff --git a/app/javascript/mastodon/locales/bg.json b/app/javascript/mastodon/locales/bg.json index 3d5d8a8585..32d61423d6 100644 --- a/app/javascript/mastodon/locales/bg.json +++ b/app/javascript/mastodon/locales/bg.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": "Това ви слага най-отгоресред потребителите на Mastodon.", + "annual_report.summary.percentile.we_wont_tell_bernie": "Няма да кажем на Бърни Сандърс.", + "annual_report.summary.thanks": "Благодарим, че сте част от Mastodon!", "attachments_list.unprocessed": "(необработено)", "audio.hide": "Скриване на звука", "block_modal.remote_users_caveat": "Ще поискаме сървърът {domain} да почита решението ви. Съгласието обаче не се гарантира откак някои сървъри могат да боравят с блоковете по различен начин. Обществените публикации още може да се виждат от невлезли в системата потребители.", @@ -121,13 +139,16 @@ "column.blocks": "Блокирани потребители", "column.bookmarks": "Отметки", "column.community": "Локален инфопоток", + "column.create_list": "Създаване на списък", "column.direct": "Частни споменавания", "column.directory": "Разглеждане на профили", "column.domain_blocks": "Блокирани домейни", + "column.edit_list": "Промяна на списъка", "column.favourites": "Любими", "column.firehose": "Инфоканали на живо", "column.follow_requests": "Заявки за последване", "column.home": "Начало", + "column.list_members": "Управление на списъка с участници", "column.lists": "Списъци", "column.mutes": "Заглушени потребители", "column.notifications": "Известия", @@ -158,6 +179,7 @@ "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": "Стил", @@ -195,6 +217,8 @@ "confirmations.unfollow.message": "Наистина ли искате да не следвате {name}?", "confirmations.unfollow.title": "Спирате ли да следвате потребителя?", "content_warning.hide": "Скриване на публ.", + "content_warning.show": "Нека се покаже", + "content_warning.show_more": "Показване на още", "conversation.delete": "Изтриване на разговора", "conversation.mark_as_read": "Маркиране като прочетено", "conversation.open": "Преглед на разговора", @@ -268,7 +292,6 @@ "empty_column.hashtag": "Още няма нищо в този хаштаг.", "empty_column.home": "Вашата начална часова ос е празна! Последвайте повече хора, за да я запълните. {suggestions}", "empty_column.list": "Все още списъкът е празен. Членуващите на списъка, публикуващи нови публикации, ще се появят тук.", - "empty_column.lists": "Все още нямате списъци. Когато създадете такъв, той ще се покаже тук.", "empty_column.mutes": "Още не сте заглушавали потребители.", "empty_column.notification_requests": "Всичко е чисто! Тук няма нищо. Получавайки нови известия, те ще се появят тук според настройките ви.", "empty_column.notifications": "Все още нямате известия. Взаимодействайте с другите, за да започнете разговора.", @@ -365,10 +388,19 @@ "home.pending_critical_update.link": "Преглед на обновяванията", "home.pending_critical_update.title": "Налично критично обновяване на сигурността!", "home.show_announcements": "Показване на оповестяванията", + "ignore_notifications_modal.disclaimer": "Mastodon не може да осведоми потребители, че сте пренебрегнали известията им. Пренебрегването на известията няма да спре самите съобщения да не бъдат изпращани.", + "ignore_notifications_modal.filter_to_act_users": "Вие все още ще може да приемате, отхвърляте или докладвате потребители", + "ignore_notifications_modal.filter_to_avoid_confusion": "Прецеждането помага за избягване на възможно объркване", + "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": "Пренебрегвате ли известията от хора, които не сте последвали?", "interaction_modal.description.favourite": "Имайки акаунт в 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": "Още не е в Мастодон?", @@ -380,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 {# ден} other {# дни}}", "intervals.full.hours": "{number, plural, one {# час} other {# часа}}", "intervals.full.minutes": "{number, plural, one {# минута} other {# минути}}", @@ -420,27 +453,32 @@ "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}", "link_preview.more_from_author": "Още от {name}", "link_preview.shares": "{count, plural, one {{counter} публикация} other {{counter} публикации}}", - "lists.account.add": "Добавяне към списък", - "lists.account.remove": "Премахване от списъка", + "lists.create_list": "Създаване на списък", "lists.delete": "Изтриване на списъка", + "lists.done": "Готово", "lists.edit": "Промяна на списъка", - "lists.edit.submit": "Промяна на заглавие", - "lists.exclusive": "Скриване на тези публикации от началото", - "lists.new.create": "Добавяне на списък", - "lists.new.title_placeholder": "Ново заглавие на списъка", + "lists.find_users_to_add": "Намерете потребители за добавяне", + "lists.list_members": "Списък членуващи", + "lists.list_name": "Име на списък", + "lists.no_lists_yet": "Още няма списъци.", + "lists.no_members_yet": "Още няма членуващи.", + "lists.no_results_found": "Няма намерени резултати.", + "lists.remove_member": "Премахване", "lists.replies_policy.followed": "Някой последван потребител", "lists.replies_policy.list": "Членуващите в списъка", "lists.replies_policy.none": "Никого", - "lists.replies_policy.title": "Показване на отговори на:", - "lists.search": "Търсене измежду последваните", - "lists.subheading": "Вашите списъци", + "lists.save": "Запазване", + "lists.search_placeholder": "Търсене сред, които сте последвали", "load_pending": "{count, plural, one {# нов елемент} other {# нови елемента}}", "loading_indicator.label": "Зареждане…", + "media_gallery.hide": "Скриване", "moved_to_account_banner.text": "Вашият акаунт {disabledAccount} сега е изключен, защото се преместихте в {movedToAccount}.", "mute_modal.hide_from_notifications": "Скриване от известията", "mute_modal.hide_options": "Скриване на възможностите", @@ -489,6 +527,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_request": "{name} поиска да ви последва", "notification.follow_request.name_and_others": "{name} и {count, plural, one {# друг} other {# други}} поискаха да ви последват", "notification.label.mention": "Споменаване", @@ -496,6 +535,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": "Някои от публикациите ви са премахнати.", @@ -566,6 +606,7 @@ "notifications.permission_required": "Известията на работния плот ги няма, щото няма дадено нужното позволение.", "notifications.policy.accept": "Приемам", "notifications.policy.accept_hint": "Показване в известия", + "notifications.policy.drop_hint": "Изпращане в празнотата, за да не се видим никога пак", "notifications.policy.filter": "Филтър", "notifications.policy.filter_limited_accounts_hint": "Ограничено от модераторите на сървъра", "notifications.policy.filter_limited_accounts_title": "Модерирани акаунти", @@ -611,7 +652,7 @@ "onboarding.steps.follow_people.title": "Персонализиране на началния ви инфоканал", "onboarding.steps.publish_status.body": "Поздравете целия свят.", "onboarding.steps.publish_status.title": "Направете първата си публикация", - "onboarding.steps.setup_profile.body": "Други са по-вероятно да взаимодействат с вас с попълнения профил.", + "onboarding.steps.setup_profile.body": "Подсилете взаимодействията си, имайки изчерпателен профил.", "onboarding.steps.setup_profile.title": "Пригодете профила си", "onboarding.steps.share_profile.body": "Позволете на приятелите си да знаят как да ви намират в Mastodon!", "onboarding.steps.share_profile.title": "Споделяне на профила ви", @@ -752,6 +793,7 @@ "status.bookmark": "Отмятане", "status.cancel_reblog_private": "Край на подсилването", "status.cannot_reblog": "Публикацията не може да се подсилва", + "status.continued_thread": "Продължена нишка", "status.copy": "Копиране на връзката към публикация", "status.delete": "Изтриване", "status.detailed_status": "Подробен изглед на разговора", @@ -760,6 +802,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": "Филтриране на публ.", @@ -784,6 +827,7 @@ "status.reblogs.empty": "Още никого не е подсилвал публикацията. Подсилващият ще се покаже тук.", "status.redraft": "Изтриване и преработване", "status.remove_bookmark": "Премахване на отметката", + "status.replied_in_thread": "Отговорено в нишката", "status.replied_to": "В отговор до {name}", "status.reply": "Отговор", "status.replyAll": "Отговор на нишка", @@ -821,6 +865,11 @@ "upload_error.poll": "Качването на файлове не е позволено с анкети.", "upload_form.audio_description": "Опишете за хора, които са глухи или трудно чуват", "upload_form.description": "Опишете за хора, които са слепи или имат слабо зрение", + "upload_form.drag_and_drop.instructions": "Натиснете интервал или enter, за да подберете мултимедийно прикачване. Провлачвайки, ползвайте клавишите със стрелки, за да премествате мултимедията във всяка дадена посока. Натиснете пак интервал или enter, за да се стовари мултимедийното прикачване в новото си положение или натиснете Esc за отмяна.", + "upload_form.drag_and_drop.on_drag_cancel": "Провлачването е отменено. Мултимедийното прикачване {item} е спуснато.", + "upload_form.drag_and_drop.on_drag_end": "Мултимедийното прикачване {item} е спуснато.", + "upload_form.drag_and_drop.on_drag_over": "Мултимедийното прикачване {item} е преместено.", + "upload_form.drag_and_drop.on_drag_start": "Избрано мултимедийно прикачване {item}.", "upload_form.edit": "Редактиране", "upload_form.thumbnail": "Промяна на миниобраза", "upload_form.video_description": "Опишете за хора, които са глухи или трудно чуват, слепи или имат слабо зрение", diff --git a/app/javascript/mastodon/locales/bn.json b/app/javascript/mastodon/locales/bn.json index 9512f6a92b..03f59e1db4 100644 --- a/app/javascript/mastodon/locales/bn.json +++ b/app/javascript/mastodon/locales/bn.json @@ -202,7 +202,6 @@ "empty_column.hashtag": "এই হেসটাগে এখনো কিছু নেই।", "empty_column.home": "আপনার বাড়ির সময়রেখা এখনো খালি! {public} এ ঘুরে আসুন অথবা অনুসন্ধান বেবহার করে শুরু করতে পারেন এবং অন্য ব্যবহারকারীদের সাথে সাক্ষাৎ করতে পারেন।", "empty_column.list": "এই তালিকাতে এখনো কিছু নেই. যখন এই তালিকায় থাকা ব্যবহারকারী নতুন কিছু লিখবে, সেগুলো এখানে পাওয়া যাবে।", - "empty_column.lists": "আপনার এখনো কোনো তালিকা তৈরী নেই। যদি বা যখন তৈরী করেন, সেগুলো এখানে পাওয়া যাবে।", "empty_column.mutes": "আপনি এখনো কোনো ব্যবহারকারীকে নিঃশব্দ করেননি।", "empty_column.notifications": "আপনার এখনো কোনো প্রজ্ঞাপন নেই। কথোপকথন শুরু করতে, অন্যদের সাথে মেলামেশা করতে পারেন।", "empty_column.public": "এখানে এখনো কিছু নেই! প্রকাশ্য ভাবে কিছু লিখুন বা অন্য সার্ভার থেকে কাওকে অনুসরণ করে এই জায়গা ভরে ফেলুন", @@ -277,16 +276,9 @@ "lightbox.next": "পরবর্তী", "lightbox.previous": "পূর্ববর্তী", "link_preview.author": "{name} এর লিখা", - "lists.account.add": "তালিকাতে যুক্ত করতে", - "lists.account.remove": "তালিকা থেকে বাদ দিতে", "lists.delete": "তালিকা মুছে ফেলতে", "lists.edit": "তালিকা সম্পাদনা করতে", - "lists.edit.submit": "শিরোনাম সম্পাদনা করতে", - "lists.new.create": "তালিকাতে যুক্ত করতে", - "lists.new.title_placeholder": "তালিকার নতুন শিরোনাম দিতে", "lists.replies_policy.none": "কেউ না", - "lists.search": "যাদের অনুসরণ করেন তাদের ভেতরে খুঁজুন", - "lists.subheading": "আপনার তালিকা", "load_pending": "{count, plural, one {# নতুন জিনিস} other {# নতুন জিনিস}}", "navigation_bar.about": "পরিচিতি", "navigation_bar.blocks": "বন্ধ করা ব্যবহারকারী", diff --git a/app/javascript/mastodon/locales/br.json b/app/javascript/mastodon/locales/br.json index 575bc56724..da99874f0b 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", @@ -221,7 +223,6 @@ "empty_column.hashtag": "N'eus netra en hashtag-mañ c'hoazh.", "empty_column.home": "Goullo eo ho red-amzer degemer! Kit da weladenniñ {public} pe implijit ar c'hlask evit kregiñ ganti ha kejañ gant implijer·ien·ezed all.", "empty_column.list": "Goullo eo al listenn-mañ evit c'hoazh. Pa vo embannet toudoù nevez gant e izili e teuint war wel amañ.", - "empty_column.lists": "N'ho peus roll ebet c'hoazh. Pa vo krouet unan ganeoc'h e vo diskouezet amañ.", "empty_column.mutes": "N'ho peus kuzhet implijer ebet c'hoazh.", "empty_column.notifications": "N'ho peus kemenn ebet c'hoazh. Grit gant implijer·ezed·ien all evit loc'hañ ar gomz.", "empty_column.public": "N'eus netra amañ! Skrivit un dra bennak foran pe heuilhit implijer·ien·ezed eus dafariadoù all evit leuniañ", @@ -344,19 +345,11 @@ "limited_account_hint.action": "Diskouez an aelad memes tra", "limited_account_hint.title": "Kuzhet eo bet ar profil-mañ gant an evezhierien eus {domain}.", "link_preview.author": "Gant {name}", - "lists.account.add": "Ouzhpennañ d'al listenn", - "lists.account.remove": "Lemel kuit eus al listenn", "lists.delete": "Dilemel al listenn", "lists.edit": "Kemmañ al listenn", - "lists.edit.submit": "Cheñch an titl", - "lists.new.create": "Ouzhpennañ ul listenn", - "lists.new.title_placeholder": "Titl nevez al listenn", "lists.replies_policy.followed": "Pep implijer.ez heuliet", "lists.replies_policy.list": "Izili ar roll", "lists.replies_policy.none": "Den ebet", - "lists.replies_policy.title": "Diskouez ar respontoù:", - "lists.search": "Klask e-touez tud heuliet ganeoc'h", - "lists.subheading": "Ho listennoù", "load_pending": "{count, plural, one {# dra nevez} other {# dra nevez}}", "loading_indicator.label": "O kargañ…", "navigation_bar.about": "Diwar-benn", diff --git a/app/javascript/mastodon/locales/ca.json b/app/javascript/mastodon/locales/ca.json index e5c8440236..fc100d7c01 100644 --- a/app/javascript/mastodon/locales/ca.json +++ b/app/javascript/mastodon/locales/ca.json @@ -87,6 +87,19 @@ "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.most_used_hashtag.none": "Cap", + "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.", @@ -273,7 +286,6 @@ "empty_column.hashtag": "Encara no hi ha res en aquesta etiqueta.", "empty_column.home": "La teva línia de temps és buida! Segueix més gent per a emplenar-la. {suggestions}", "empty_column.list": "Encara no hi ha res en aquesta llista. Quan els membres facin nous tuts, apareixeran aquí.", - "empty_column.lists": "Encara no tens cap llista. Quan en facis una, apareixerà aquí.", "empty_column.mutes": "Encara no has silenciat cap usuari.", "empty_column.notification_requests": "Tot net, ja no hi ha res aquí! Quan rebeu notificacions noves, segons la vostra configuració, apareixeran aquí.", "empty_column.notifications": "Encara no tens notificacions. Quan altre gent interactuï amb tu, les veuràs aquí.", @@ -446,20 +458,11 @@ "link_preview.author": "Per {name}", "link_preview.more_from_author": "Més de {name}", "link_preview.shares": "{count, plural, one {{counter} publicació} other {{counter} publicacions}}", - "lists.account.add": "Afegeix a la llista", - "lists.account.remove": "Elimina de la llista", "lists.delete": "Elimina la llista", "lists.edit": "Edita la llista", - "lists.edit.submit": "Canvia el títol", - "lists.exclusive": "Amaga aquests tuts a Inici", - "lists.new.create": "Afegeix una llista", - "lists.new.title_placeholder": "Nou títol de la llista", "lists.replies_policy.followed": "Qualsevol usuari que segueixis", "lists.replies_policy.list": "Membres de la llista", "lists.replies_policy.none": "Ningú", - "lists.replies_policy.title": "Mostra respostes a:", - "lists.search": "Cerca entre les persones que segueixes", - "lists.subheading": "Les teves llistes", "load_pending": "{count, plural, one {# element nou} other {# elements nous}}", "loading_indicator.label": "Es carrega…", "media_gallery.hide": "Amaga", diff --git a/app/javascript/mastodon/locales/ckb.json b/app/javascript/mastodon/locales/ckb.json index 469cf4410d..292aefb4cf 100644 --- a/app/javascript/mastodon/locales/ckb.json +++ b/app/javascript/mastodon/locales/ckb.json @@ -221,7 +221,6 @@ "empty_column.hashtag": "هێشتا هیچ شتێک لەم هاشتاگەدا نییە.", "empty_column.home": "تایم لاینی ماڵەوەت بەتاڵە! سەردانی {public} بکە یان گەڕان بەکاربێنە بۆ دەستپێکردن و بینینی بەکارهێنەرانی تر.", "empty_column.list": "هێشتا هیچ شتێک لەم لیستەدا نییە. کاتێک ئەندامانی ئەم لیستە دەنگی نوێ بڵاودەکەن، لێرە دەردەکەون.", - "empty_column.lists": "تۆ هێشتا هیچ لیستت دروست نەکردووە، کاتێک دانەیەک دروست دەکەیت، لێرە پیشان دەدرێت.", "empty_column.mutes": "تۆ هێشتا هیچ بەکارهێنەرێکت بێدەنگ نەکردووە.", "empty_column.notifications": "تۆ هێشتا هیچ ئاگانامێکت نیە. چالاکی لەگەڵ کەسانی دیکە بکە بۆ دەستپێکردنی گفتوگۆکە.", "empty_column.public": "لێرە هیچ نییە! شتێک بە ئاشکرا بنووسە(بەگشتی)، یان بە دەستی شوێن بەکارهێنەران بکەوە لە ڕاژەکانی ترەوە بۆ پڕکردنەوەی", @@ -338,19 +337,11 @@ "lightbox.previous": "پێشوو", "limited_account_hint.action": "بەهەر حاڵ پڕۆفایلی پیشان بدە", "limited_account_hint.title": "ئەم پرۆفایلە لەلایەن بەڕێوەبەرانی {domain} شاراوەتەوە.", - "lists.account.add": "زیادکردن بۆ لیست", - "lists.account.remove": "لابردن لە لیست", "lists.delete": "سڕینەوەی لیست", "lists.edit": "دەستکاری لیست", - "lists.edit.submit": "گۆڕینی ناونیشان", - "lists.new.create": "زیادکردنی لیست", - "lists.new.title_placeholder": "ناونیشانی لیستی نوێ", "lists.replies_policy.followed": "هەر بەکارهێنەرێکی بەدواکەوتوو", "lists.replies_policy.list": "ئەندامانی لیستەکە", "lists.replies_policy.none": "هیچکەس", - "lists.replies_policy.title": "پیشاندانی وەڵامەکان بۆ:", - "lists.search": "بگەڕێ لەناو ئەو کەسانەی کە شوێنیان کەوتویت", - "lists.subheading": "لیستەکانت", "load_pending": "{count, plural, one {# بەڕگەی نوێ} other {# بەڕگەی نوێ}}", "moved_to_account_banner.text": "ئەکاونتەکەت {disabledAccount} لە ئێستادا لەکارخراوە چونکە تۆ چوویتە {movedToAccount}.", "navigation_bar.about": "دەربارە", diff --git a/app/javascript/mastodon/locales/co.json b/app/javascript/mastodon/locales/co.json index 043061769b..033f3fc80b 100644 --- a/app/javascript/mastodon/locales/co.json +++ b/app/javascript/mastodon/locales/co.json @@ -132,7 +132,6 @@ "empty_column.hashtag": "Ùn c'hè ancu nunda quì.", "empty_column.home": "A vostr'accolta hè viota! Pudete andà nant'à {public} o pruvà a ricerca per truvà parsone da siguità.", "empty_column.list": "Ùn c'hè ancu nunda quì. Quandu membri di sta lista manderanu novi statuti, i vidarete quì.", - "empty_column.lists": "Ùn avete manc'una lista. Quandu farete una, sarà mustrata quì.", "empty_column.mutes": "Per avà ùn avete manc'un utilizatore piattatu.", "empty_column.notifications": "Ùn avete ancu nisuna nutificazione. Interact with others to start the conversation.", "empty_column.public": "Ùn c'hè nunda quì! Scrivete qualcosa in pubblicu o seguitate utilizatori d'altri servori per empie a linea pubblica", @@ -198,19 +197,11 @@ "lightbox.close": "Chjudà", "lightbox.next": "Siguente", "lightbox.previous": "Pricidente", - "lists.account.add": "Aghjunghje à a lista", - "lists.account.remove": "Toglie di a lista", "lists.delete": "Toglie a lista", "lists.edit": "Mudificà a lista", - "lists.edit.submit": "Cambià u titulu", - "lists.new.create": "Aghjunghje", - "lists.new.title_placeholder": "Titulu di a lista", "lists.replies_policy.followed": "Tutti i vostri abbunamenti", "lists.replies_policy.list": "Membri di a lista", "lists.replies_policy.none": "Nimu", - "lists.replies_policy.title": "Vede e risposte à:", - "lists.search": "Circà indè i vostr'abbunamenti", - "lists.subheading": "E vo liste", "load_pending": "{count, plural, one {# entrata nova} other {# entrate nove}}", "navigation_bar.blocks": "Utilizatori bluccati", "navigation_bar.bookmarks": "Segnalibri", diff --git a/app/javascript/mastodon/locales/cs.json b/app/javascript/mastodon/locales/cs.json index 7198bcab58..89db6c5cb3 100644 --- a/app/javascript/mastodon/locales/cs.json +++ b/app/javascript/mastodon/locales/cs.json @@ -267,7 +267,6 @@ "empty_column.hashtag": "Pod tímto hashtagem zde zatím nic není.", "empty_column.home": "Vaše domovská časová osa je prázdná! Naplňte ji sledováním dalších lidí.", "empty_column.list": "V tomto seznamu zatím nic není. Až nějaký člen z tohoto seznamu zveřejní nový příspěvek, objeví se zde.", - "empty_column.lists": "Zatím nemáte žádné seznamy. Až nějaký vytvoříte, zobrazí se zde.", "empty_column.mutes": "Zatím jste neskryli žádného uživatele.", "empty_column.notification_requests": "Vyčištěno! Nic tu není. Jakmile obdržíš nové notifikace, objeví se zde podle tvého nastavení.", "empty_column.notifications": "Zatím nemáte žádná oznámení. Až s vámi někdo bude interagovat, uvidíte to zde.", @@ -415,20 +414,11 @@ "link_preview.author": "Podle {name}", "link_preview.more_from_author": "Více od {name}", "link_preview.shares": "{count, plural, one {{counter} příspěvek} few {{counter} příspěvky} many {{counter} příspěvků} other {{counter} příspěvků}}", - "lists.account.add": "Přidat do seznamu", - "lists.account.remove": "Odebrat ze seznamu", "lists.delete": "Smazat seznam", "lists.edit": "Upravit seznam", - "lists.edit.submit": "Změnit název", - "lists.exclusive": "Skrýt tyto příspěvky z domovské stránky", - "lists.new.create": "Přidat seznam", - "lists.new.title_placeholder": "Název nového seznamu", "lists.replies_policy.followed": "Sledovaným uživatelům", "lists.replies_policy.list": "Členům seznamu", "lists.replies_policy.none": "Nikomu", - "lists.replies_policy.title": "Odpovědi zobrazovat:", - "lists.search": "Hledejte mezi lidmi, které sledujete", - "lists.subheading": "Vaše seznamy", "load_pending": "{count, plural, one {# nová položka} few {# nové položky} many {# nových položek} other {# nových položek}}", "loading_indicator.label": "Načítání…", "moved_to_account_banner.text": "Váš účet {disabledAccount} je momentálně deaktivován, protože jste se přesunul/a na {movedToAccount}.", diff --git a/app/javascript/mastodon/locales/cy.json b/app/javascript/mastodon/locales/cy.json index 675f7a203e..c4f79da43a 100644 --- a/app/javascript/mastodon/locales/cy.json +++ b/app/javascript/mastodon/locales/cy.json @@ -87,11 +87,30 @@ "alert.unexpected.title": "Wps!", "alt_text_badge.title": "Testun Amgen", "announcement.announcement": "Cyhoeddiad", + "annual_report.summary.archetype.booster": "Y hyrwyddwr", + "annual_report.summary.archetype.lurker": "Yr arsylwr", + "annual_report.summary.archetype.oracle": "Yr oracl", + "annual_report.summary.archetype.pollster": "Yr arholwr", + "annual_report.summary.archetype.replier": "Y sbardunwr", + "annual_report.summary.followers.followers": "dilynwyr", + "annual_report.summary.followers.total": "{count} cyfanswm", + "annual_report.summary.here_it_is": "Dyma eich {year} yn gryno:", + "annual_report.summary.highlighted_post.by_favourites": "postiad wedi'i ffefrynu fwyaf", + "annual_report.summary.highlighted_post.by_reblogs": "postiad wedi'i hybu fwyaf", + "annual_report.summary.highlighted_post.by_replies": "postiad gyda'r ymatebion mwyaf", + "annual_report.summary.highlighted_post.possessive": "{name}", + "annual_report.summary.most_used_app.most_used_app": "ap a ddefnyddiwyd fwyaf", + "annual_report.summary.most_used_hashtag.most_used_hashtag": "hashnod a ddefnyddiwyd fwyaf", + "annual_report.summary.most_used_hashtag.none": "Dim", + "annual_report.summary.new_posts.new_posts": "postiadau newydd", + "annual_report.summary.percentile.text": "Rydych chi yn y mwyaf o ddefnyddwyr Mastodon.", + "annual_report.summary.percentile.we_wont_tell_bernie": "Ni fyddwn yn dweud wrth Bernie.", + "annual_report.summary.thanks": "Diolch am fod yn rhan o Mastodon!", "attachments_list.unprocessed": "(heb eu prosesu)", "audio.hide": "Cuddio sain", "block_modal.remote_users_caveat": "Byddwn yn gofyn i'r gweinydd {domain} barchu eich penderfyniad. Fodd bynnag, nid yw cydymffurfiad wedi'i warantu gan y gall rhai gweinyddwyr drin rhwystro mewn ffyrdd gwahanol. Mae'n bosibl y bydd postiadau cyhoeddus yn dal i fod yn weladwy i ddefnyddwyr nad ydynt wedi mewngofnodi.", "block_modal.show_less": "Dangos llai", - "block_modal.show_more": "Dangos mwy", + "block_modal.show_more": "Dangos rhagor", "block_modal.they_cant_mention": "Nid ydynt yn gallu eich crybwyll na'ch dilyn.", "block_modal.they_cant_see_posts": "Nid ydynt yn gallu gweld eich postiadau ac ni fyddwch yn gweld eu rhai hwy.", "block_modal.they_will_know": "Gallant weld eu bod wedi'u rhwystro.", @@ -163,9 +182,9 @@ "compose_form.poll.switch_to_single": "Newid pleidlais i gyfyngu i un dewis", "compose_form.poll.type": "Arddull", "compose_form.publish": "Postiad", - "compose_form.publish_form": "Cyhoeddi", + "compose_form.publish_form": "Postiad newydd", "compose_form.reply": "Ateb", - "compose_form.save_changes": "Diweddariad", + "compose_form.save_changes": "Diweddaru", "compose_form.spoiler.marked": "Dileu rhybudd cynnwys", "compose_form.spoiler.unmarked": "Ychwanegu rhybudd cynnwys", "compose_form.spoiler_placeholder": "Rhybudd cynnwys (dewisol)", @@ -273,7 +292,6 @@ "empty_column.hashtag": "Nid oes dim ar yr hashnod hwn eto.", "empty_column.home": "Mae eich ffrwd gartref yn wag! Dilynwch fwy o bobl i'w llenwi.", "empty_column.list": "Does dim yn y rhestr yma eto. Pan fydd aelodau'r rhestr yn cyhoeddi postiad newydd, mi fydd yn ymddangos yma.", - "empty_column.lists": "Nid oes gennych unrhyw restrau eto. Pan fyddwch yn creu un, mi fydd yn ymddangos yma.", "empty_column.mutes": "Nid ydych wedi tewi unrhyw ddefnyddwyr eto.", "empty_column.notification_requests": "Dim i boeni amdano! Does dim byd yma. Pan fyddwch yn derbyn hysbysiadau newydd, byddan nhw'n ymddangos yma yn ôl eich gosodiadau.", "empty_column.notifications": "Nid oes gennych unrhyw hysbysiadau eto. Rhyngweithiwch ag eraill i ddechrau'r sgwrs.", @@ -446,20 +464,11 @@ "link_preview.author": "Gan {name}", "link_preview.more_from_author": "Mwy gan {name}", "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", "lists.edit": "Golygu rhestr", - "lists.edit.submit": "Newid teitl", - "lists.exclusive": "Cuddio'r postiadau hyn o'r ffrwd gartref", - "lists.new.create": "Ychwanegu rhestr", - "lists.new.title_placeholder": "Teitl rhestr newydd", "lists.replies_policy.followed": "Unrhyw ddefnyddiwr sy'n cael ei ddilyn", "lists.replies_policy.list": "Aelodau'r rhestr", "lists.replies_policy.none": "Neb", - "lists.replies_policy.title": "Dangos atebion i:", - "lists.search": "Chwilio ymysg pobl rydych yn eu dilyn", - "lists.subheading": "Eich rhestrau", "load_pending": "{count, plural, one {# eitem newydd} other {# eitem newydd}}", "loading_indicator.label": "Yn llwytho…", "media_gallery.hide": "Cuddio", @@ -508,6 +517,8 @@ "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 # arall}}", + "notification.annual_report.message": "Mae eich #Wrapstodon {year} yn aros i chi! Gwelwch eich uchafbwyntiau ac amseroedd i'w cofio o'r flwyddyn hon ar Mastodon!", + "notification.annual_report.view": "Gweld #Wrapstodon", "notification.favourite": "Ffafriodd {name} 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", diff --git a/app/javascript/mastodon/locales/da.json b/app/javascript/mastodon/locales/da.json index 5531576447..9f0f27b804 100644 --- a/app/javascript/mastodon/locales/da.json +++ b/app/javascript/mastodon/locales/da.json @@ -87,6 +87,25 @@ "alert.unexpected.title": "Ups!", "alt_text_badge.title": "Alt text", "announcement.announcement": "Bekendtgørelse", + "annual_report.summary.archetype.booster": "Cool-hunter", + "annual_report.summary.archetype.lurker": "Lurker", + "annual_report.summary.archetype.oracle": "Oracle", + "annual_report.summary.archetype.pollster": "Pollster", + "annual_report.summary.archetype.replier": "Social butterfly", + "annual_report.summary.followers.followers": "følgere", + "annual_report.summary.followers.total": "{count} i alt", + "annual_report.summary.here_it_is": "Her er {year} i sammendrag:", + "annual_report.summary.highlighted_post.by_favourites": "mest favoritmarkerede indlæg", + "annual_report.summary.highlighted_post.by_reblogs": "mest boostede indlæg", + "annual_report.summary.highlighted_post.by_replies": "indlæg med flest svar", + "annual_report.summary.highlighted_post.possessive": "{name}s", + "annual_report.summary.most_used_app.most_used_app": "mest benyttede app", + "annual_report.summary.most_used_hashtag.most_used_hashtag": "mest benyttede hashtag", + "annual_report.summary.most_used_hashtag.none": "Intet", + "annual_report.summary.new_posts.new_posts": "nye indlæg", + "annual_report.summary.percentile.text": "Det betyder, at man er i topaf Mastodon-brugere.", + "annual_report.summary.percentile.we_wont_tell_bernie": "Vi fortæller det ikke til Bernie.", + "annual_report.summary.thanks": "Tak for at være en del af Mastodon!", "attachments_list.unprocessed": "(ubehandlet)", "audio.hide": "Skjul lyd", "block_modal.remote_users_caveat": "Serveren {domain} vil blive bedt om at respektere din beslutning. Overholdelse er dog ikke garanteret, da nogle servere kan håndtere blokke forskelligt. Offentlige indlæg kan stadig være synlige for ikke-indloggede brugere.", @@ -121,13 +140,16 @@ "column.blocks": "Blokerede brugere", "column.bookmarks": "Bogmærker", "column.community": "Lokal tidslinje", + "column.create_list": "Opret liste", "column.direct": "Private omtaler", "column.directory": "Tjek profiler", "column.domain_blocks": "Blokerede domæner", + "column.edit_list": "Redigér liste", "column.favourites": "Favoritter", "column.firehose": "Live feeds", "column.follow_requests": "Følgeanmodninger", "column.home": "Hjem", + "column.list_members": "Håndtér listemedlemmer", "column.lists": "Lister", "column.mutes": "Skjulte brugere (mutede)", "column.notifications": "Notifikationer", @@ -158,6 +180,7 @@ "compose_form.poll.duration": "Afstemningens varighed", "compose_form.poll.multiple": "Multivalg", "compose_form.poll.option_placeholder": "Valgmulighed {number}", + "compose_form.poll.single": "Enkeltvalg", "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", @@ -272,7 +295,6 @@ "empty_column.hashtag": "Der er intet med dette hashtag endnu.", "empty_column.home": "Din hjemmetidslinje er tom! Følg nogle personer, for at udfylde den. {suggestions}", "empty_column.list": "Der er ikke noget på denne liste endnu. Når medlemmer af listen udgiver nye indlæg vil de fremgå hér.", - "empty_column.lists": "Du har endnu ingen lister. Når du opretter én, vil den fremgå hér.", "empty_column.mutes": "Du har endnu ikke skjult (muted) nogle brugere.", "empty_column.notification_requests": "Alt er klar! Der er intet her. Når der modtages nye notifikationer, fremgår de her jf. dine indstillinger.", "empty_column.notifications": "Du har endnu ingen notifikationer. Når andre interagerer med dig, vil det fremgå hér.", @@ -445,20 +467,31 @@ "link_preview.author": "Af {name}", "link_preview.more_from_author": "Mere fra {name}", "link_preview.shares": "{count, plural, one {{counter} indlæg} other {{counter} indlæg}}", - "lists.account.add": "Føj til liste", - "lists.account.remove": "Fjern fra liste", + "lists.add_member": "Tilføj", + "lists.add_to_list": "Føj til liste", + "lists.add_to_lists": "Føj {name} til lister", + "lists.create": "Opret", + "lists.create_a_list_to_organize": "Opret en ny liste til organisering af hjemmefeed", + "lists.create_list": "Opret liste", "lists.delete": "Slet liste", + "lists.done": "Færdig", "lists.edit": "Redigér liste", - "lists.edit.submit": "Skift titel", - "lists.exclusive": "Skjul disse indlæg hjemmefra", - "lists.new.create": "Tilføj liste", - "lists.new.title_placeholder": "Ny listetitel", + "lists.exclusive": "Skjul medlemmer i Hjem", + "lists.exclusive_hint": "Er nogen er på denne liste, skjul personen i hjemme-feeds for at undgå at se vedkommendes indlæg to gange.", + "lists.find_users_to_add": "Find brugere at tilføje", + "lists.list_members_count": "{count, plural, one {# medlem} other {# medlemmer}}", + "lists.list_name": "Listetitel", + "lists.new_list_name": "Ny listetitel", + "lists.no_lists_yet": "Ingen lister endnu.", + "lists.no_members_yet": "Ingen medlemmer endnu.", + "lists.no_results_found": "Ingen resultater fundet.", + "lists.remove_member": "Fjern", "lists.replies_policy.followed": "Enhver bruger, der følges", "lists.replies_policy.list": "Listemedlemmer", "lists.replies_policy.none": "Ingen", - "lists.replies_policy.title": "Vis svar til:", - "lists.search": "Søg blandt personer, som følges", - "lists.subheading": "Dine lister", + "lists.save": "Gem", + "lists.search_placeholder": "Søg efter folk, man følger", + "lists.show_replies_to": "Medtag svar fra listemedlemmer til", "load_pending": "{count, plural, one {# nyt emne} other {# nye emner}}", "loading_indicator.label": "Indlæser…", "media_gallery.hide": "Skjul", @@ -507,6 +540,8 @@ "notification.admin.report_statuses_other": "{name} anmeldte {target}", "notification.admin.sign_up": "{name} tilmeldte sig", "notification.admin.sign_up.name_and_others": "{name} og {count, plural, one {# anden} other {# andre}} tilmeldte sig", + "notification.annual_report.message": "{year} #Wrapstodon venter! Afslør årets højdepunkter og mindeværdige øjeblikke på Mastodon!", + "notification.annual_report.view": "Vis #Wrapstodon", "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", diff --git a/app/javascript/mastodon/locales/de.json b/app/javascript/mastodon/locales/de.json index 1d59b14724..b47007522b 100644 --- a/app/javascript/mastodon/locales/de.json +++ b/app/javascript/mastodon/locales/de.json @@ -87,6 +87,25 @@ "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.most_used_hashtag.none": "Keiner", + "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.", @@ -121,13 +140,16 @@ "column.blocks": "Blockierte Profile", "column.bookmarks": "Lesezeichen", "column.community": "Lokale Timeline", + "column.create_list": "Liste erstellen", "column.direct": "Private Erwähnungen", "column.directory": "Profile durchsuchen", "column.domain_blocks": "Blockierte Domains", + "column.edit_list": "Liste bearbeiten", "column.favourites": "Favoriten", "column.firehose": "Live-Feeds", "column.follow_requests": "Follower-Anfragen", "column.home": "Startseite", + "column.list_members": "Listenmitglieder verwalten", "column.lists": "Listen", "column.mutes": "Stummgeschaltete Profile", "column.notifications": "Benachrichtigungen", @@ -273,7 +295,6 @@ "empty_column.hashtag": "Unter diesem Hashtag gibt es noch nichts.", "empty_column.home": "Die Timeline deiner Startseite ist leer! Folge mehr Leuten, um sie zu füllen.", "empty_column.list": "Diese Liste ist derzeit leer. Wenn Konten auf dieser Liste neue Beiträge veröffentlichen, werden sie hier erscheinen.", - "empty_column.lists": "Du hast noch keine Listen. Sobald du eine anlegst, wird sie hier erscheinen.", "empty_column.mutes": "Du hast keine Profile stummgeschaltet.", "empty_column.notification_requests": "Alles klar! Hier gibt es nichts. Wenn Sie neue Mitteilungen erhalten, werden diese entsprechend Ihren Einstellungen hier angezeigt.", "empty_column.notifications": "Du hast noch keine Benachrichtigungen. Sobald andere Personen mit dir interagieren, wirst du hier darüber informiert.", @@ -446,20 +467,32 @@ "link_preview.author": "Von {name}", "link_preview.more_from_author": "Mehr von {name}", "link_preview.shares": "{count, plural, one {{counter} Beitrag} other {{counter} Beiträge}}", - "lists.account.add": "Zur Liste hinzufügen", - "lists.account.remove": "Von der Liste entfernen", + "lists.add_member": "Hinzufügen", + "lists.add_to_list": "Zur Liste hinzufügen", + "lists.add_to_lists": "{name} zu Listen hinzufügen", + "lists.create": "Erstellen", + "lists.create_a_list_to_organize": "Erstelle eine neue Liste, um deine Startseite zu organisieren", + "lists.create_list": "Liste erstellen", "lists.delete": "Liste löschen", + "lists.done": "Fertig", "lists.edit": "Liste bearbeiten", - "lists.edit.submit": "Titel ändern", - "lists.exclusive": "Diese Beiträge in der Startseite ausblenden", - "lists.new.create": "Neue Liste erstellen", - "lists.new.title_placeholder": "Titel der neuen Liste", + "lists.exclusive": "Mitglieder auf der Startseite ausblenden", + "lists.exclusive_hint": "Profile, die sich auf dieser Liste befinden, werden nicht auf deiner Startseite angezeigt, damit deren Beiträge nicht doppelt erscheinen.", + "lists.find_users_to_add": "Suche nach Profilen, um sie hinzuzufügen", + "lists.list_members": "Listenmitglieder", + "lists.list_members_count": "{count, plural, one {# Mitglied} other {# Mitglieder}}", + "lists.list_name": "Titel der Liste", + "lists.new_list_name": "Neuer Listentitel", + "lists.no_lists_yet": "Noch keine Listen vorhanden.", + "lists.no_members_yet": "Keine Mitglieder vorhanden.", + "lists.no_results_found": "Keine Suchergebnisse.", + "lists.remove_member": "Entfernen", "lists.replies_policy.followed": "Alle folgenden Profile", "lists.replies_policy.list": "Mitglieder der Liste", "lists.replies_policy.none": "Niemanden", - "lists.replies_policy.title": "Antworten anzeigen für:", - "lists.search": "Suche nach Leuten, denen du folgst", - "lists.subheading": "Deine Listen", + "lists.save": "Speichern", + "lists.search_placeholder": "Nach Profilen suchen, denen du folgst", + "lists.show_replies_to": "Antworten von Listenmitgliedern anzeigen für …", "load_pending": "{count, plural, one {# neuer Beitrag} other {# neue Beiträge}}", "loading_indicator.label": "Wird geladen …", "media_gallery.hide": "Ausblenden", @@ -467,12 +500,12 @@ "mute_modal.hide_from_notifications": "Benachrichtigungen ausblenden", "mute_modal.hide_options": "Einstellungen ausblenden", "mute_modal.indefinite": "Bis ich die Stummschaltung aufhebe", - "mute_modal.show_options": "Einstellungen anzeigen", + "mute_modal.show_options": "Optionen anzeigen", "mute_modal.they_can_mention_and_follow": "Das Profil wird dich weiterhin erwähnen und dir folgen können, aber du wirst davon nichts sehen.", - "mute_modal.they_wont_know": "Es wird nicht erkennbar sein, dass dieses Profil stummgeschaltet wurde.", + "mute_modal.they_wont_know": "Das Profil wird nicht erkennen können, dass du es stummgeschaltet hast.", "mute_modal.title": "Profil stummschalten?", "mute_modal.you_wont_see_mentions": "Du wirst keine Beiträge sehen, die dieses Profil erwähnen.", - "mute_modal.you_wont_see_posts": "Deine Beiträge können weiterhin angesehen werden, aber du wirst deren Beiträge nicht mehr sehen.", + "mute_modal.you_wont_see_posts": "Deine Beiträge können von diesem stummgeschalteten Profil weiterhin gesehen werden, aber du wirst dessen Beiträge nicht mehr sehen.", "navigation_bar.about": "Über", "navigation_bar.administration": "Administration", "navigation_bar.advanced_interface": "Im erweiterten Webinterface öffnen", @@ -507,13 +540,15 @@ "notification.admin.report_statuses": "{name} meldete {target} wegen {category}", "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.admin.sign_up.name_and_others": "{name} und {count, plural, one {# weiteres Profil} other {# weitere Profile}} 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.favourite.name_and_others_with_link": "{name} und {count, plural, one {# weiteres Profil} other {# weitere Profile}} 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 {# weiteres Profil} other {# weitere Profile}} 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.follow_request.name_and_others": "{name} und {count, plural, one {# weiteres Profil} other {# weitere Profile}} möchten dir folgen", "notification.label.mention": "Erwähnung", "notification.label.private_mention": "Private Erwähnung", "notification.label.private_reply": "Private Antwort", @@ -532,7 +567,7 @@ "notification.own_poll": "Deine Umfrage ist beendet", "notification.poll": "Eine Umfrage, an der du teilgenommen hast, ist beendet", "notification.reblog": "{name} teilte deinen Beitrag", - "notification.reblog.name_and_others_with_link": "{name} und {count, plural, one {# weitere Person} other {# weitere Personen}} teilten deinen Beitrag", + "notification.reblog.name_and_others_with_link": "{name} und {count, plural, one {# weiteres Profil} other {# weitere Profile}} teilten deinen Beitrag", "notification.relationships_severance_event": "Verbindungen mit {name} verloren", "notification.relationships_severance_event.account_suspension": "Ein Admin von {from} hat {target} gesperrt. Du wirst von diesem Profil keine Updates mehr erhalten und auch nicht mit ihm interagieren können.", "notification.relationships_severance_event.domain_block": "Ein Admin von {from} hat {target} blockiert – darunter {followersCount} deiner Follower und {followingCount, plural, one {# Konto, dem} other {# Konten, denen}} du folgst.", @@ -667,7 +702,7 @@ "poll_button.remove_poll": "Umfrage entfernen", "privacy.change": "Sichtbarkeit anpassen", "privacy.direct.long": "Alle in diesem Beitrag erwähnten Profile", - "privacy.direct.short": "Bestimmte Profile", + "privacy.direct.short": "Ausgewählte Profile", "privacy.private.long": "Nur deine Follower", "privacy.private.short": "Follower", "privacy.public.long": "Alle in und außerhalb von Mastodon", diff --git a/app/javascript/mastodon/locales/el.json b/app/javascript/mastodon/locales/el.json index 40517f8340..57f47dda7b 100644 --- a/app/javascript/mastodon/locales/el.json +++ b/app/javascript/mastodon/locales/el.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": "Αυτό σε βάζει στην κορυφή του των χρηστών του 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} να σεβαστεί την απόφασή σου. Ωστόσο, η συμμόρφωση δεν είναι εγγυημένη δεδομένου ότι ορισμένοι διακομιστές ενδέχεται να χειρίζονται τους αποκλεισμούς διαφορετικά. Οι δημόσιες αναρτήσεις ενδέχεται να είναι ορατές σε μη συνδεδεμένους χρήστες.", @@ -158,6 +176,7 @@ "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": "Στυλ", @@ -196,6 +215,7 @@ "confirmations.unfollow.title": "Άρση ακολούθησης;", "content_warning.hide": "Απόκρυψη ανάρτησης", "content_warning.show": "Εμφάνιση ούτως ή άλλως", + "content_warning.show_more": "Εμφάνιση περισσότερων", "conversation.delete": "Διαγραφή συζήτησης", "conversation.mark_as_read": "Σήμανση ως αναγνωσμένο", "conversation.open": "Προβολή συνομιλίας", @@ -271,7 +291,6 @@ "empty_column.hashtag": "Δεν υπάρχει ακόμα κάτι για αυτή την ετικέτα.", "empty_column.home": "Η τοπική σου ροή είναι κενή! Πήγαινε στο {public} ή κάνε αναζήτηση για να ξεκινήσεις και να γνωρίσεις άλλους χρήστες.", "empty_column.list": "Δεν υπάρχει τίποτα σε αυτή τη λίστα ακόμα. Όταν τα μέλη της δημοσιεύσουν νέες καταστάσεις, θα εμφανιστούν εδώ.", - "empty_column.lists": "Δεν έχεις καμία λίστα ακόμα. Μόλις φτιάξεις μια, θα εμφανιστεί εδώ.", "empty_column.mutes": "Δεν έχεις κανένα χρήστη σε σίγαση ακόμα.", "empty_column.notification_requests": "Όλα καθαρά! Δεν υπάρχει τίποτα εδώ. Όταν λαμβάνεις νέες ειδοποιήσεις, αυτές θα εμφανίζονται εδώ σύμφωνα με τις ρυθμίσεις σου.", "empty_column.notifications": "Δεν έχεις ειδοποιήσεις ακόμα. Όταν άλλα άτομα αλληλεπιδράσουν μαζί σου, θα το δεις εδώ.", @@ -304,6 +323,7 @@ "filter_modal.select_filter.subtitle": "Χρησιμοποιήστε μια υπάρχουσα κατηγορία ή δημιουργήστε μια νέα", "filter_modal.select_filter.title": "Φιλτράρισμα αυτής της ανάρτησης", "filter_modal.title.status": "Φιλτράρισμα μιας ανάρτησης", + "filter_warning.matches_filter": "Ταιριάζει με το φίλτρο “{title}”", "filtered_notifications_banner.pending_requests": "Από {count, plural, =0 {κανένα} one {ένα άτομο} other {# άτομα}} που μπορεί να ξέρεις", "filtered_notifications_banner.title": "Φιλτραρισμένες ειδοποιήσεις", "firehose.all": "Όλα", @@ -383,9 +403,10 @@ "interaction_modal.description.follow": "Με έναν λογαριασμό Mastodon, μπορείς να ακολουθήσεις τον/την {name} ώστε να λαμβάνεις τις αναρτήσεις του/της στη δική σου ροή.", "interaction_modal.description.reblog": "Με ένα λογαριασμό Mastodon, μπορείς να ενισχύσεις αυτή την ανάρτηση για να τη μοιραστείς με τους δικούς σου ακολούθους.", "interaction_modal.description.reply": "Με ένα λογαριασμό Mastodon, μπορείς να απαντήσεις σε αυτή την ανάρτηση.", - "interaction_modal.login.action": "Take me home\nΠήγαινέ με στην αρχική σελίδα", + "interaction_modal.description.vote": "Με ένα λογαριασμό Mastodon, μπορείς να απαντήσεις σ' αυτή την ανάρτηση.", + "interaction_modal.login.action": "Πήγαινέ με στην αρχική σελίδα", "interaction_modal.login.prompt": "Τομέας του οικιακού σου διακομιστή, πχ. mastodon.social", - "interaction_modal.no_account_yet": "Not on Mastodon?\nΔεν είστε στο Mastodon;", + "interaction_modal.no_account_yet": "Δεν είστε στο Mastodon;", "interaction_modal.on_another_server": "Σε διαφορετικό διακομιστή", "interaction_modal.on_this_server": "Σε αυτόν τον διακομιστή", "interaction_modal.sign_in": "Δεν είσαι συνδεδεμένος σε αυτόν το διακομιστή. Πού φιλοξενείται ο λογαριασμός σου;", @@ -394,6 +415,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 {# λεπτά}}", @@ -441,20 +463,11 @@ "link_preview.author": "Από {name}", "link_preview.more_from_author": "Περισσότερα από {name}", "link_preview.shares": "{count, plural, one {{counter} ανάρτηση} other {{counter} αναρτήσεις}}", - "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.followed": "Οποιοσδήποτε χρήστης που ακολουθείς", "lists.replies_policy.list": "Μέλη της λίστας", "lists.replies_policy.none": "Κανένας", - "lists.replies_policy.title": "Εμφάνιση απαντήσεων σε:", - "lists.search": "Αναζήτησε μεταξύ των ανθρώπων που ακουλουθείς", - "lists.subheading": "Οι λίστες σου", "load_pending": "{count, plural, one {# νέο στοιχείο} other {# νέα στοιχεία}}", "loading_indicator.label": "Φόρτωση…", "media_gallery.hide": "Απόκρυψη", @@ -503,9 +516,12 @@ "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.annual_report.message": "Το #Wrapstodon {year} σε περιμένει! Αποκάλυψε τα στιγμιότυπα της χρονιάς και αξέχαστες στιγμές σου στο Mastodon!", + "notification.annual_report.view": "Προβολή #Wrapstodon", "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": "Επισήμανση", @@ -513,6 +529,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": "Ορισμένες από τις αναρτήσεις σου έχουν αφαιρεθεί.", @@ -563,6 +580,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/en-GB.json b/app/javascript/mastodon/locales/en-GB.json index d482ec21dd..8d4201484d 100644 --- a/app/javascript/mastodon/locales/en-GB.json +++ b/app/javascript/mastodon/locales/en-GB.json @@ -87,6 +87,25 @@ "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.most_used_hashtag.none": "None", + "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,6 +177,7 @@ "compose_form.poll.duration": "Poll duration", "compose_form.poll.multiple": "Multiple choice", "compose_form.poll.option_placeholder": "Option {number}", + "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", @@ -196,6 +216,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", @@ -271,7 +292,6 @@ "empty_column.hashtag": "There is nothing in this hashtag yet.", "empty_column.home": "Your home timeline is empty! Follow more people to fill it up.", "empty_column.list": "There is nothing in this list yet. When members of this list post new statuses, they will appear here.", - "empty_column.lists": "You don't have any lists yet. When you create one, it will show up here.", "empty_column.mutes": "You haven't muted any users yet.", "empty_column.notification_requests": "All clear! There is nothing here. When you receive new notifications, they will appear here according to your settings.", "empty_column.notifications": "You don't have any notifications yet. When other people interact with you, you will see it here.", @@ -304,6 +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}\"", "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", @@ -383,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?", @@ -394,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}}", @@ -441,20 +464,11 @@ "link_preview.author": "By {name}", "link_preview.more_from_author": "More from {name}", "link_preview.shares": "{count, plural, one {{counter} post} other {{counter} posts}}", - "lists.account.add": "Add to list", - "lists.account.remove": "Remove from list", "lists.delete": "Delete list", "lists.edit": "Edit list", - "lists.edit.submit": "Change title", - "lists.exclusive": "Hide these posts from home", - "lists.new.create": "Add list", - "lists.new.title_placeholder": "New list title", "lists.replies_policy.followed": "Any followed user", "lists.replies_policy.list": "Members of the list", "lists.replies_policy.none": "No one", - "lists.replies_policy.title": "Show replies to:", - "lists.search": "Search among people you follow", - "lists.subheading": "Your lists", "load_pending": "{count, plural, one {# new item} other {# new items}}", "loading_indicator.label": "Loading…", "media_gallery.hide": "Hide", @@ -503,9 +517,11 @@ "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.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", @@ -513,6 +529,7 @@ "notification.label.private_reply": "Private reply", "notification.label.reply": "Reply", "notification.mention": "Mention", + "notification.mentioned_you": "{name} mentioned you", "notification.moderation-warning.learn_more": "Learn more", "notification.moderation_warning": "You have received a moderation warning", "notification.moderation_warning.action_delete_statuses": "Some of your posts have been removed.", @@ -563,6 +580,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/en.json b/app/javascript/mastodon/locales/en.json index e91d6e52fc..142b7f1770 100644 --- a/app/javascript/mastodon/locales/en.json +++ b/app/javascript/mastodon/locales/en.json @@ -87,6 +87,25 @@ "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.most_used_hashtag.none": "None", + "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.", @@ -121,13 +140,16 @@ "column.blocks": "Blocked users", "column.bookmarks": "Bookmarks", "column.community": "Local timeline", + "column.create_list": "Create list", "column.direct": "Private mentions", "column.directory": "Browse profiles", "column.domain_blocks": "Blocked domains", + "column.edit_list": "Edit list", "column.favourites": "Favorites", "column.firehose": "Live feeds", "column.follow_requests": "Follow requests", "column.home": "Home", + "column.list_members": "Manage list members", "column.lists": "Lists", "column.mutes": "Muted users", "column.notifications": "Notifications", @@ -273,7 +295,6 @@ "empty_column.hashtag": "There is nothing in this hashtag yet.", "empty_column.home": "Your home timeline is empty! Follow more people to fill it up.", "empty_column.list": "There is nothing in this list yet. When members of this list publish new posts, they will appear here.", - "empty_column.lists": "You don't have any lists yet. When you create one, it will show up here.", "empty_column.mutes": "You haven't muted any users yet.", "empty_column.notification_requests": "All clear! There is nothing here. When you receive new notifications, they will appear here according to your settings.", "empty_column.notifications": "You don't have any notifications yet. When other people interact with you, you will see it here.", @@ -446,20 +467,32 @@ "link_preview.author": "By {name}", "link_preview.more_from_author": "More from {name}", "link_preview.shares": "{count, plural, one {{counter} post} other {{counter} posts}}", - "lists.account.add": "Add to list", - "lists.account.remove": "Remove from list", + "lists.add_member": "Add", + "lists.add_to_list": "Add to list", + "lists.add_to_lists": "Add {name} to lists", + "lists.create": "Create", + "lists.create_a_list_to_organize": "Create a new list to organize your Home feed", + "lists.create_list": "Create list", "lists.delete": "Delete list", + "lists.done": "Done", "lists.edit": "Edit list", - "lists.edit.submit": "Change title", - "lists.exclusive": "Hide these posts from home", - "lists.new.create": "Add list", - "lists.new.title_placeholder": "New list title", + "lists.exclusive": "Hide members in Home", + "lists.exclusive_hint": "If someone is on this list, hide them in your Home feed to avoid seeing their posts twice.", + "lists.find_users_to_add": "Find users to add", + "lists.list_members": "List members", + "lists.list_members_count": "{count, plural, one {# member} other {# members}}", + "lists.list_name": "List name", + "lists.new_list_name": "New list name", + "lists.no_lists_yet": "No lists yet.", + "lists.no_members_yet": "No members yet.", + "lists.no_results_found": "No results found.", + "lists.remove_member": "Remove", "lists.replies_policy.followed": "Any followed user", "lists.replies_policy.list": "Members of the list", "lists.replies_policy.none": "No one", - "lists.replies_policy.title": "Show replies to:", - "lists.search": "Search among people you follow", - "lists.subheading": "Your lists", + "lists.save": "Save", + "lists.search_placeholder": "Search people you follow", + "lists.show_replies_to": "Include replies from list members to", "load_pending": "{count, plural, one {# new item} other {# new items}}", "loading_indicator.label": "Loading…", "media_gallery.hide": "Hide", @@ -508,6 +541,8 @@ "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.favourite.name_and_others_with_link": "{name} and {count, plural, one {# other} other {# others}} favorited your post", "notification.follow": "{name} followed you", diff --git a/app/javascript/mastodon/locales/eo.json b/app/javascript/mastodon/locales/eo.json index 7abe0783c3..730c301769 100644 --- a/app/javascript/mastodon/locales/eo.json +++ b/app/javascript/mastodon/locales/eo.json @@ -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}", @@ -87,6 +87,13 @@ "alert.unexpected.title": "Aj!", "alt_text_badge.title": "Alt-teksto", "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.most_used_app.most_used_app": "plej uzita apo", + "annual_report.summary.most_used_hashtag.none": "Nenio", + "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.", @@ -142,7 +149,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...", @@ -214,7 +221,7 @@ "dismissable_banner.community_timeline": "Jen la plej novaj publikaj afiŝoj de uzantoj, kies kontojn gastigas {domain}.", "dismissable_banner.dismiss": "Eksigi", "dismissable_banner.explore_links": "Tiuj novaĵoj estas aktuale priparolataj de uzantoj en tiu ĉi kaj aliaj serviloj, sur la malcentrigita reto.", - "dismissable_banner.explore_statuses": "Ĉi tiuj estas afiŝoj de la tuta socia reto, kiuj populariĝas hodiaŭ. Pli novaj afiŝoj kun pli da diskonigoj kaj plej ŝatataj estas rangigitaj pli alte.", + "dismissable_banner.explore_statuses": "Jen afiŝoj en la socia reto kiuj populariĝis hodiaŭ. Novaj afiŝoj kun pli da diskonigoj kaj stelumoj aperas pli alte.", "dismissable_banner.explore_tags": "Ĉi tiuj kradvostoj populariĝas en ĉi tiu kaj aliaj serviloj en la malcentraliza reto nun.", "dismissable_banner.public_timeline": "Ĉi tiuj estas la plej lastatempaj publikaj afiŝoj de homoj en la socia reto, kiujn homoj sur {domain} sekvas.", "domain_block_modal.block": "Bloki servilon", @@ -273,7 +280,6 @@ "empty_column.hashtag": "Ankoraŭ estas nenio per ĉi tiu kradvorto.", "empty_column.home": "Via hejma tempolinio estas malplena! Vizitu {public} aŭ uzu la serĉilon por renkonti aliajn uzantojn.", "empty_column.list": "Ankoraŭ estas nenio en ĉi tiu listo. Kiam membroj de ĉi tiu listo afiŝos novajn afiŝojn, ili aperos ĉi tie.", - "empty_column.lists": "Vi ankoraŭ ne havas liston. Kiam vi kreos iun, ĝi aperos ĉi tie.", "empty_column.mutes": "Vi ne ankoraŭ silentigis iun uzanton.", "empty_column.notification_requests": "Ĉio klara! Estas nenio tie ĉi. Kiam vi ricevas novajn sciigojn, ili aperos ĉi tie laŭ viaj agordoj.", "empty_column.notifications": "Vi ankoraŭ ne havas sciigojn. Interagu kun aliaj por komenci konversacion.", @@ -333,7 +339,7 @@ "followed_tags": "Sekvataj kradvortoj", "footer.about": "Pri", "footer.directory": "Profilujo", - "footer.get_app": "Akiru la Programon", + "footer.get_app": "Akiri la apon", "footer.invite": "Inviti homojn", "footer.keyboard_shortcuts": "Fulmoklavoj", "footer.privacy_policy": "Politiko de privateco", @@ -382,7 +388,7 @@ "ignore_notifications_modal.not_followers_title": "Ĉu ignori sciigojn de homoj, kiuj ne sekvas vin?", "ignore_notifications_modal.not_following_title": "Ĉu ignori sciigojn de homoj, kiujn vi ne sekvas?", "ignore_notifications_modal.private_mentions_title": "Ĉu ignori sciigojn de nepetitaj privataj mencioj?", - "interaction_modal.description.favourite": "Per konto ĉe Mastodon, vi povas stelumiti ĉi tiun afiŝon por sciigi la afiŝanton ke vi aprezigas ŝin kaj konservas por la estonteco.", + "interaction_modal.description.favourite": "Per konto ĉe Mastodon, vi povas stelumi ĉi tiun afiŝon por sciigi la afiŝanton ke vi sâtas kaj konservas ĝin por poste.", "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.", @@ -446,20 +452,11 @@ "link_preview.author": "De {name}", "link_preview.more_from_author": "Pli de {name}", "link_preview.shares": "{count, plural, one {{counter} afiŝo} other {{counter} afiŝoj}}", - "lists.account.add": "Aldoni al la listo", - "lists.account.remove": "Forigi de la listo", "lists.delete": "Forigi la liston", "lists.edit": "Redakti la liston", - "lists.edit.submit": "Ŝanĝi titolon", - "lists.exclusive": "Kaŝi ĉi tiujn afiŝojn de hejmo", - "lists.new.create": "Aldoni liston", - "lists.new.title_placeholder": "Titolo de la nova listo", "lists.replies_policy.followed": "Iu sekvanta uzanto", "lists.replies_policy.list": "Membroj de la listo", "lists.replies_policy.none": "Neniu", - "lists.replies_policy.title": "Montri respondojn al:", - "lists.search": "Serĉi inter la homoj, kiujn vi sekvas", - "lists.subheading": "Viaj listoj", "load_pending": "{count,plural, one {# nova elemento} other {# novaj elementoj}}", "loading_indicator.label": "Ŝargado…", "media_gallery.hide": "Kaŝi", @@ -508,6 +505,7 @@ "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", @@ -640,7 +638,7 @@ "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": "Sekvi interesajn homojn estas pri kio Mastodonto temas.", + "onboarding.steps.follow_people.body": "You curate your own feed. Lets fill it with interesting people.", "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", @@ -774,9 +772,9 @@ "server_banner.is_one_of_many": "{domain} estas unu el la multaj sendependaj Mastodon-serviloj, kiujn vi povas uzi por partopreni en la fediverso.", "server_banner.server_stats": "Statistikoj de la servilo:", "sign_in_banner.create_account": "Krei konton", - "sign_in_banner.follow_anyone": "Sekvi iun ajn tra la fediverso kaj vidi ĉion en kronologia ordo. Neniuj algoritmoj, reklamoj aŭ klakbetoj videblas.", - "sign_in_banner.mastodon_is": "Mastodonto estas la plej bona maniero por resti flank-al-flanke kun kio okazas.", - "sign_in_banner.sign_in": "Saluti", + "sign_in_banner.follow_anyone": "Sekvu iun ajn tra la fediverso kaj vidu ĉion laŭ templinio. Nul algoritmo, reklamo aŭ kliklogilo ĉeestas.", + "sign_in_banner.mastodon_is": "Mastodon estas la plej bona maniero resti ĝisdata pri aktualaĵoj.", + "sign_in_banner.sign_in": "Ensaluti", "sign_in_banner.sso_redirect": "Ensalutu aŭ Registriĝi", "status.admin_account": "Malfermi fasadon de moderigado por @{name}", "status.admin_domain": "Malfermu moderigan interfacon por {domain}", diff --git a/app/javascript/mastodon/locales/es-AR.json b/app/javascript/mastodon/locales/es-AR.json index e8302a4c75..2dea704a72 100644 --- a/app/javascript/mastodon/locales/es-AR.json +++ b/app/javascript/mastodon/locales/es-AR.json @@ -87,6 +87,25 @@ "alert.unexpected.title": "¡Epa!", "alt_text_badge.title": "Texto alternativo", "announcement.announcement": "Anuncio", + "annual_report.summary.archetype.booster": "Corrió la voz", + "annual_report.summary.archetype.lurker": "El acechador", + "annual_report.summary.archetype.oracle": "El oráculo", + "annual_report.summary.archetype.pollster": "Estuvo consultando", + "annual_report.summary.archetype.replier": "Respondió un montón", + "annual_report.summary.followers.followers": "seguidores", + "annual_report.summary.followers.total": "{count} en total", + "annual_report.summary.here_it_is": "Acá está tu resumen de {year}:", + "annual_report.summary.highlighted_post.by_favourites": "el mensaje más veces marcado como favorito", + "annual_report.summary.highlighted_post.by_reblogs": "el mensaje que más adhesiones recibió", + "annual_report.summary.highlighted_post.by_replies": "el mensaje que más respuestas recibió", + "annual_report.summary.highlighted_post.possessive": "{name}", + "annual_report.summary.most_used_app.most_used_app": "la aplicación más usada", + "annual_report.summary.most_used_hashtag.most_used_hashtag": "la etiqueta más usada", + "annual_report.summary.most_used_hashtag.none": "Ninguna", + "annual_report.summary.new_posts.new_posts": "nuevos mensajes", + "annual_report.summary.percentile.text": "Eso te pone en la cimade los 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.", @@ -273,7 +292,6 @@ "empty_column.hashtag": "Todavía no hay nada con esta etiqueta.", "empty_column.home": "¡Tu línea temporal principal está vacía! Seguí a más cuentas para llenarla.", "empty_column.list": "Todavía no hay nada en esta lista. Cuando miembros de esta lista envíen nuevos mensaje, se mostrarán acá.", - "empty_column.lists": "Todavía no tenés ninguna lista. Cuando creés una, se mostrará acá.", "empty_column.mutes": "Todavía no silenciaste a ningún usuario.", "empty_column.notification_requests": "¡Todo limpio! No hay nada acá. Cuando recibás nuevas notificaciones, aparecerán acá, acorde a tu configuración.", "empty_column.notifications": "Todavía no tenés ninguna notificación. Cuando otras cuentas interactúen con vos, vas a ver la notificación acá.", @@ -446,20 +464,11 @@ "link_preview.author": "Por {name}", "link_preview.more_from_author": "Más de {name}", "link_preview.shares": "{count, plural, one {{counter} mensaje} other {{counter} mensajes}}", - "lists.account.add": "Agregar a lista", - "lists.account.remove": "Quitar de lista", "lists.delete": "Eliminar lista", "lists.edit": "Editar lista", - "lists.edit.submit": "Cambiar título", - "lists.exclusive": "Ocultar estos mensajes del inicio", - "lists.new.create": "Agregar lista", - "lists.new.title_placeholder": "Título de nueva lista", "lists.replies_policy.followed": "Cualquier cuenta seguida", "lists.replies_policy.list": "Miembros de la lista", "lists.replies_policy.none": "Nadie", - "lists.replies_policy.title": "Mostrar respuestas a:", - "lists.search": "Buscar entre la gente que seguís", - "lists.subheading": "Tus listas", "load_pending": "{count, plural, one {# elemento nuevo} other {# elementos nuevos}}", "loading_indicator.label": "Cargando…", "media_gallery.hide": "Ocultar", @@ -508,6 +517,8 @@ "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", diff --git a/app/javascript/mastodon/locales/es-MX.json b/app/javascript/mastodon/locales/es-MX.json index c73a64c4e0..d863873418 100644 --- a/app/javascript/mastodon/locales/es-MX.json +++ b/app/javascript/mastodon/locales/es-MX.json @@ -87,6 +87,25 @@ "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 oraculo", + "annual_report.summary.archetype.pollster": "El encuestador", + "annual_report.summary.archetype.replier": "La mariposa 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.most_used_hashtag.none": "Ninguna", + "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.", @@ -273,7 +292,6 @@ "empty_column.hashtag": "No hay nada en esta etiqueta aún.", "empty_column.home": "No estás siguiendo a nadie aún. Visita {public} o haz búsquedas para empezar y conocer gente nueva.", "empty_column.list": "No hay nada en esta lista aún. Cuando miembros de esta lista publiquen nuevos estatus, estos aparecerán qui.", - "empty_column.lists": "No tienes ninguna lista. cuando crees una, se mostrará aquí.", "empty_column.mutes": "Aún no has silenciado a ningún usuario.", "empty_column.notification_requests": "¡Todo limpio! No hay nada aquí. Cuando recibas nuevas notificaciones, aparecerán aquí conforme a tu configuración.", "empty_column.notifications": "No tienes ninguna notificación aún. Interactúa con otros para empezar una conversación.", @@ -446,20 +464,11 @@ "link_preview.author": "Por {name}", "link_preview.more_from_author": "Más de {name}", "link_preview.shares": "{count, plural, one {{counter} publicación} other {{counter} publicaciones}}", - "lists.account.add": "Añadir a lista", - "lists.account.remove": "Quitar de lista", "lists.delete": "Borrar lista", "lists.edit": "Editar lista", - "lists.edit.submit": "Cambiar título", - "lists.exclusive": "Ocultar estas publicaciones en inicio", - "lists.new.create": "Añadir lista", - "lists.new.title_placeholder": "Título de la nueva lista", "lists.replies_policy.followed": "Cualquier usuario seguido", "lists.replies_policy.list": "Miembros de la lista", "lists.replies_policy.none": "Nadie", - "lists.replies_policy.title": "Mostrar respuestas a:", - "lists.search": "Buscar entre la gente a la que sigues", - "lists.subheading": "Tus listas", "load_pending": "{count, plural, one {# nuevo elemento} other {# nuevos elementos}}", "loading_indicator.label": "Cargando…", "media_gallery.hide": "Ocultar", @@ -508,6 +517,8 @@ "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", diff --git a/app/javascript/mastodon/locales/es.json b/app/javascript/mastodon/locales/es.json index dea526f8a0..bfb16e9fd8 100644 --- a/app/javascript/mastodon/locales/es.json +++ b/app/javascript/mastodon/locales/es.json @@ -87,6 +87,25 @@ "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.most_used_hashtag.none": "Ninguna", + "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.", @@ -273,7 +292,6 @@ "empty_column.hashtag": "No hay nada en esta etiqueta todavía.", "empty_column.home": "¡Tu línea temporal está vacía! Sigue a más personas para rellenarla.", "empty_column.list": "Aún no hay nada en esta lista. Cuando los miembros de esta lista publiquen nuevos estados, estos aparecerán aquí.", - "empty_column.lists": "No tienes ninguna lista. Cuando crees una, se mostrará aquí.", "empty_column.mutes": "Aún no has silenciado a ningún usuario.", "empty_column.notification_requests": "¡Todo limpio! No hay nada aquí. Cuando recibas nuevas notificaciones, aparecerán aquí conforme a tu configuración.", "empty_column.notifications": "Aún no tienes ninguna notificación. Cuando otras personas interactúen contigo, aparecerán aquí.", @@ -446,20 +464,11 @@ "link_preview.author": "Por {name}", "link_preview.more_from_author": "Más de {name}", "link_preview.shares": "{count, plural, one {{counter} publicación} other {{counter} publicaciones}}", - "lists.account.add": "Añadir a lista", - "lists.account.remove": "Quitar de lista", "lists.delete": "Borrar lista", "lists.edit": "Editar lista", - "lists.edit.submit": "Cambiar título", - "lists.exclusive": "Ocultar estas publicaciones de inicio", - "lists.new.create": "Añadir lista", - "lists.new.title_placeholder": "Título de la nueva lista", "lists.replies_policy.followed": "Cualquier usuario seguido", "lists.replies_policy.list": "Miembros de la lista", "lists.replies_policy.none": "Nadie", - "lists.replies_policy.title": "Mostrar respuestas a:", - "lists.search": "Buscar entre las personas a las que sigues", - "lists.subheading": "Tus listas", "load_pending": "{count, plural, one {# nuevo elemento} other {# nuevos elementos}}", "loading_indicator.label": "Cargando…", "media_gallery.hide": "Ocultar", @@ -508,6 +517,8 @@ "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", diff --git a/app/javascript/mastodon/locales/et.json b/app/javascript/mastodon/locales/et.json index 8376641179..1db32efe09 100644 --- a/app/javascript/mastodon/locales/et.json +++ b/app/javascript/mastodon/locales/et.json @@ -273,7 +273,6 @@ "empty_column.hashtag": "Selle sildi all ei ole ühtegi postitust.", "empty_column.home": "Su koduajajoon on tühi. Jälgi rohkemaid inimesi, et seda täita {suggestions}", "empty_column.list": "Siin loetelus pole veel midagi. Kui loetelu liikmed teevad uusi postitusi, näed neid siin.", - "empty_column.lists": "Pole veel ühtegi nimekirja. Kui lood mõne, näed neid siin.", "empty_column.mutes": "Sa pole veel ühtegi kasutajat vaigistanud.", "empty_column.notification_requests": "Kõik tühi! Siin pole mitte midagi. Kui saad uusi teavitusi, ilmuvad need siin vastavalt sinu seadistustele.", "empty_column.notifications": "Ei ole veel teateid. Kui keegi suhtleb sinuga, näed seda siin.", @@ -446,20 +445,11 @@ "link_preview.author": "{name} poolt", "link_preview.more_from_author": "Veel kasutajalt {name}", "link_preview.shares": "{count, plural, one {{counter} postitus} other {{counter} postitust}}", - "lists.account.add": "Lisa nimekirja", - "lists.account.remove": "Eemalda nimekirjast", "lists.delete": "Kustuta nimekiri", "lists.edit": "Muuda nimekirja", - "lists.edit.submit": "Pealkirja muutmine", - "lists.exclusive": "Peida koduvaatest need postitused", - "lists.new.create": "Lisa nimekiri", - "lists.new.title_placeholder": "Uue nimekirja pealkiri", "lists.replies_policy.followed": "Igalt jälgitud kasutajalt", "lists.replies_policy.list": "Listi liikmetelt", "lists.replies_policy.none": "Mitte kelleltki", - "lists.replies_policy.title": "Näita vastuseid nendele:", - "lists.search": "Otsi enda jälgitavate inimeste hulgast", - "lists.subheading": "Sinu nimekirjad", "load_pending": "{count, plural, one {# uus kirje} other {# uut kirjet}}", "loading_indicator.label": "Laadimine…", "media_gallery.hide": "Peida", diff --git a/app/javascript/mastodon/locales/eu.json b/app/javascript/mastodon/locales/eu.json index c8349dc6a1..c77ca93f9e 100644 --- a/app/javascript/mastodon/locales/eu.json +++ b/app/javascript/mastodon/locales/eu.json @@ -269,7 +269,6 @@ "empty_column.hashtag": "Ez dago ezer traola honetan oraindik.", "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.", "empty_column.notification_requests": "Garbi-garbi! Ezertxo ere ez hemen. Jakinarazpenak jasotzen dituzunean, hemen agertuko dira zure ezarpenen arabera.", "empty_column.notifications": "Ez duzu jakinarazpenik oraindik. Jarri besteekin harremanetan elkarrizketa abiatzeko.", @@ -437,20 +436,11 @@ "link_preview.author": "Egilea: {name}", "link_preview.more_from_author": "{name} erabiltzaileaz gehiago jakin", "link_preview.shares": "{count, plural, one {{counter} bidalketa} other {{counter} bidalketa}}", - "lists.account.add": "Gehitu zerrendara", - "lists.account.remove": "Kendu zerrendatik", "lists.delete": "Ezabatu zerrenda", "lists.edit": "Editatu zerrenda", - "lists.edit.submit": "Aldatu izenburua", - "lists.exclusive": "Ezkutatu argitalpen hauek hasieratik", - "lists.new.create": "Gehitu zerrenda", - "lists.new.title_placeholder": "Zerrenda berriaren izena", "lists.replies_policy.followed": "Jarraitutako edozein erabiltzaile", "lists.replies_policy.list": "Zerrendako kideak", "lists.replies_policy.none": "Bat ere ez", - "lists.replies_policy.title": "Erakutsi erantzunak:", - "lists.search": "Bilatu jarraitzen dituzun pertsonen artean", - "lists.subheading": "Zure zerrendak", "load_pending": "{count, plural, one {elementu berri #} other {# elementu berri}}", "loading_indicator.label": "Kargatzen…", "media_gallery.hide": "Ezkutatu", diff --git a/app/javascript/mastodon/locales/fa.json b/app/javascript/mastodon/locales/fa.json index 3bc96cf9f2..608c1321b7 100644 --- a/app/javascript/mastodon/locales/fa.json +++ b/app/javascript/mastodon/locales/fa.json @@ -272,7 +272,6 @@ "empty_column.hashtag": "هنوز هیچ چیزی در این برچسب نیست.", "empty_column.home": "خط زمانی خانگیتان خالی است! برای پر کردنش، افراد بیشتری را پی بگیرید. {suggestions}", "empty_column.list": "هنوز چیزی در این سیاهه نیست. هنگامی که اعضایش فرسته‌های جدیدی بفرستند، این‌جا ظاهر خواهند شد.", - "empty_column.lists": "هنوز هیچ سیاهه‌ای ندارید. هنگامی که یکی بسازید، این‌جا نشان داده خواهد شد.", "empty_column.mutes": "هنوز هیچ کاربری را خموش نکرده‌اید.", "empty_column.notifications": "هنوز هیچ آگاهی‌آی ندارید. هنگامی که دیگران با شما برهم‌کنش داشته باشند،‌این‌حا خواهید دیدش.", "empty_column.public": "این‌جا هنوز چیزی نیست! خودتان چیزی بنویسید یا کاربران کارسازهای دیگر را پی‌گیری کنید تا این‌جا پُر شود", @@ -437,20 +436,11 @@ "link_preview.author": "از {name}", "link_preview.more_from_author": "بیش‌تر از {name}", "link_preview.shares": "{count, plural, one {{counter} فرسته} other {{counter} فرسته}}", - "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.followed": "هر کاربر پی‌گرفته", "lists.replies_policy.list": "اعضای سیاهه", "lists.replies_policy.none": "هیچ کدام", - "lists.replies_policy.title": "نمایش پاسخ‌ها به:", - "lists.search": "جست‌وجو بین کسانی که پی‌گرفته‌اید", - "lists.subheading": "سیاهه‌هایتان", "load_pending": "{count, plural, one {# مورد جدید} other {# مورد جدید}}", "loading_indicator.label": "در حال بارگذاری…", "media_gallery.hide": "نهفتن", diff --git a/app/javascript/mastodon/locales/fi.json b/app/javascript/mastodon/locales/fi.json index 2222e6038c..a987c4bad2 100644 --- a/app/javascript/mastodon/locales/fi.json +++ b/app/javascript/mastodon/locales/fi.json @@ -38,7 +38,7 @@ "account.following": "Seuratut", "account.following_counter": "{count, plural, one {{counter} seurattu} other {{counter} seurattua}}", "account.follows.empty": "Tämä käyttäjä ei vielä seuraa ketään.", - "account.go_to_profile": "Mene profiiliin", + "account.go_to_profile": "Siirry profiiliin", "account.hide_reblogs": "Piilota käyttäjän @{name} tehostukset", "account.in_memoriam": "Muistoissamme.", "account.joined_short": "Liittynyt", @@ -87,6 +87,24 @@ "alert.unexpected.title": "Hups!", "alt_text_badge.title": "Vaihtoehtoinen teksti", "announcement.announcement": "Tiedote", + "annual_report.summary.archetype.booster": "Tehostaja", + "annual_report.summary.archetype.lurker": "Lymyilijä", + "annual_report.summary.archetype.oracle": "Oraakkeli", + "annual_report.summary.archetype.pollster": "Mielipidetutkija", + "annual_report.summary.archetype.replier": "Sosiaalinen perhonen", + "annual_report.summary.followers.followers": "seuraajaa", + "annual_report.summary.followers.total": "{count} yhteensä", + "annual_report.summary.here_it_is": "Tässä on katsaus vuoteesi {year}:", + "annual_report.summary.highlighted_post.by_favourites": "suosikkeihin lisätyin julkaisu", + "annual_report.summary.highlighted_post.by_reblogs": "tehostetuin julkaisu", + "annual_report.summary.highlighted_post.by_replies": "julkaisu, jolla on eniten vastauksia", + "annual_report.summary.highlighted_post.possessive": "Käyttäjän {name}", + "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.most_used_hashtag.none": "Ei mitään", + "annual_report.summary.new_posts.new_posts": "uutta julkaisua", + "annual_report.summary.percentile.text": "Olet osa huippujoukkoa, johon kuuluuMastodon-käyttäjistä.", + "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.", @@ -121,13 +139,16 @@ "column.blocks": "Estetyt käyttäjät", "column.bookmarks": "Kirjanmerkit", "column.community": "Paikallinen aikajana", + "column.create_list": "Luo lista", "column.direct": "Yksityismaininnat", "column.directory": "Selaa profiileja", "column.domain_blocks": "Estetyt verkkotunnukset", + "column.edit_list": "Muokkaa listaa", "column.favourites": "Suosikit", "column.firehose": "Livesyötteet", "column.follow_requests": "Seurantapyynnöt", "column.home": "Koti", + "column.list_members": "Hallitse listan jäseniä", "column.lists": "Listat", "column.mutes": "Mykistetyt käyttäjät", "column.notifications": "Ilmoitukset", @@ -158,7 +179,7 @@ "compose_form.poll.duration": "Äänestyksen kesto", "compose_form.poll.multiple": "Monivalinta", "compose_form.poll.option_placeholder": "Vaihtoehto {number}", - "compose_form.poll.single": "Yksi vaihtoehto", + "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", @@ -273,7 +294,6 @@ "empty_column.hashtag": "Tällä aihetunnisteella ei löydy vielä sisältöä.", "empty_column.home": "Kotiaikajanasi on tyhjä! Seuraa useampia käyttäjiä, niin näet enemmän sisältöä.", "empty_column.list": "Tällä listalla ei ole vielä mitään. Kun tämän listan jäsenet lähettävät uusia julkaisuja, ne näkyvät tässä.", - "empty_column.lists": "Sinulla ei ole vielä yhtään listaa. Kun luot sellaisen, näkyy se tässä.", "empty_column.mutes": "Et ole mykistänyt vielä yhtään käyttäjää.", "empty_column.notification_requests": "Olet ajan tasalla! Täällä ei ole mitään uutta kerrottavaa. Kun saat uusia ilmoituksia, ne näkyvät täällä asetustesi mukaisesti.", "empty_column.notifications": "Sinulla ei ole vielä ilmoituksia. Kun muut ovat vuorovaikutuksessa kanssasi, näet sen täällä.", @@ -386,7 +406,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": "Osallistuminen äänestykseen onnistuu Mastodon-tilillä.", + "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?", @@ -446,20 +466,32 @@ "link_preview.author": "Tehnyt {name}", "link_preview.more_from_author": "Lisää tekijältä {name}", "link_preview.shares": "{count, plural, one {{counter} julkaisu} other {{counter} julkaisua}}", - "lists.account.add": "Lisää listalle", - "lists.account.remove": "Poista listalta", + "lists.add_member": "Lisää", + "lists.add_to_list": "Lisää listalle", + "lists.add_to_lists": "Lisää {name} listalle", + "lists.create": "Luo", + "lists.create_a_list_to_organize": "Luo uusi lista kotisyötteesi järjestämiseksi", + "lists.create_list": "Luo lista", "lists.delete": "Poista lista", + "lists.done": "Valmis", "lists.edit": "Muokkaa listaa", - "lists.edit.submit": "Vaihda nimi", - "lists.exclusive": "Piilota nämä julkaisut kotisyötteestä", - "lists.new.create": "Lisää lista", - "lists.new.title_placeholder": "Uuden listan nimi", + "lists.exclusive": "Piilota jäsenet kotisyötteestä", + "lists.exclusive_hint": "Jos joku on tällä listalla, piilota hänet kotisyötteestäsi, jotta et näe hänen julkaisujaan kahteen kertaan.", + "lists.find_users_to_add": "Etsi lisättäviä käyttäjiä", + "lists.list_members": "Listan jäsenet", + "lists.list_members_count": "{count, plural, one {# jäsen} other {# jäsentä}}", + "lists.list_name": "Listan nimi", + "lists.new_list_name": "Uuden listan nimi", + "lists.no_lists_yet": "Ei vielä listoja.", + "lists.no_members_yet": "Ei vielä jäseniä.", + "lists.no_results_found": "Tuloksia ei löytynyt.", + "lists.remove_member": "Poista", "lists.replies_policy.followed": "Jokaiselle seuratulle käyttäjälle", "lists.replies_policy.list": "Listan jäsenille", "lists.replies_policy.none": "Ei kellekään", - "lists.replies_policy.title": "Näytä vastaukset:", - "lists.search": "Hae seuraamistasi käyttäjistä", - "lists.subheading": "Omat listasi", + "lists.save": "Tallenna", + "lists.search_placeholder": "Hae käyttäjiä seurattavaksi", + "lists.show_replies_to": "Sisällytä listan jäsenten vastaukset kohteeseen", "load_pending": "{count, plural, one {# uusi kohde} other {# uutta kohdetta}}", "loading_indicator.label": "Ladataan…", "media_gallery.hide": "Piilota", @@ -508,6 +540,8 @@ "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.message": "Vuoden {year} #Wrapstodon odottaa! Paljasta vuotesi kohokohdat ikimuistoiset hetket Mastodonissa!", + "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", diff --git a/app/javascript/mastodon/locales/fil.json b/app/javascript/mastodon/locales/fil.json index 14c7b70bd2..1ccc6f036d 100644 --- a/app/javascript/mastodon/locales/fil.json +++ b/app/javascript/mastodon/locales/fil.json @@ -184,7 +184,6 @@ "empty_column.hashtag": "Wala pang laman ang hashtag na ito.", "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", @@ -234,15 +233,8 @@ "lightbox.next": "Susunod", "lightbox.previous": "Nakaraan", "link_preview.author": "Ni/ng {name}", - "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", diff --git a/app/javascript/mastodon/locales/fo.json b/app/javascript/mastodon/locales/fo.json index e15385725a..bc56152f37 100644 --- a/app/javascript/mastodon/locales/fo.json +++ b/app/javascript/mastodon/locales/fo.json @@ -87,6 +87,25 @@ "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.most_used_hashtag.none": "Einki", + "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.", @@ -273,7 +292,6 @@ "empty_column.hashtag": "Einki er í hesum frámerkinum enn.", "empty_column.home": "Heima-tíðarlinjan hjá tær er tóm! Fylg fleiri fyri at fylla hana. {suggestions}", "empty_column.list": "Einki er í hesum listanum enn. Tá limir í hesum listanum posta nýggjar postar, so síggjast teir her.", - "empty_column.lists": "Tú hevur ongar goymdar listar enn. Tá tú gert ein lista, so sært tú hann her.", "empty_column.mutes": "Tú hevur enn ikki doyvt nakran brúkara.", "empty_column.notification_requests": "Alt er klárt! Her er einki. Tá tú fært nýggjar fráboðanir, síggjast tær her sambært tínum stillingum.", "empty_column.notifications": "Tú hevur ongar fráboðanir enn. Tá onnur samskifta við teg, so sær tú fráboðaninar her.", @@ -446,20 +464,11 @@ "link_preview.author": "Av {name}", "link_preview.more_from_author": "Meira frá {name}", "link_preview.shares": "{count, plural, one {{counter} postur} other {{counter} postar}}", - "lists.account.add": "Legg afturat lista", - "lists.account.remove": "Tak av lista", "lists.delete": "Strika lista", "lists.edit": "Broyt lista", - "lists.edit.submit": "Broyt heiti", - "lists.exclusive": "Fjal hesar postarnar frá heima", - "lists.new.create": "Ger nýggjan lista", - "lists.new.title_placeholder": "Nýtt navn á lista", "lists.replies_policy.followed": "Øllum fylgdum brúkarum", "lists.replies_policy.list": "Listalimunum", "lists.replies_policy.none": "Eingin", - "lists.replies_policy.title": "Vís svarini fyri:", - "lists.search": "Leita millum fólk, sum tú fylgir", - "lists.subheading": "Tínir listar", "load_pending": "{count, plural, one {# nýtt evni} other {# nýggj evni}}", "loading_indicator.label": "Innlesur…", "media_gallery.hide": "Fjal", @@ -508,6 +517,8 @@ "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", diff --git a/app/javascript/mastodon/locales/fr-CA.json b/app/javascript/mastodon/locales/fr-CA.json index 65bbc25c21..a1134e0de3 100644 --- a/app/javascript/mastodon/locales/fr-CA.json +++ b/app/javascript/mastodon/locales/fr-CA.json @@ -87,6 +87,9 @@ "alert.unexpected.title": "Oups!", "alt_text_badge.title": "Texte Alt", "announcement.announcement": "Annonce", + "annual_report.summary.archetype.oracle": "L’oracle", + "annual_report.summary.here_it_is": "Voici votre récap de {year} :", + "annual_report.summary.most_used_app.most_used_app": "appli la plus utilisée", "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 utilisateur·rice·s non connecté·e·s.", @@ -272,7 +275,6 @@ "empty_column.hashtag": "Il n’y a pas encore de contenu associé à ce hashtag.", "empty_column.home": "Votre fil d'accueil est vide! Suivez plus de personnes pour la remplir. {suggestions}", "empty_column.list": "Il n’y a rien dans cette liste pour l’instant. Quand des membres de cette liste publieront de nouvelles publications, elles apparaîtront ici.", - "empty_column.lists": "Vous n’avez pas encore de liste. Lorsque vous en créerez une, elle apparaîtra ici.", "empty_column.mutes": "Vous n’avez masqué aucun compte pour le moment.", "empty_column.notification_requests": "C'est fini ! Il n'y a plus rien ici. Lorsque vous recevez de nouvelles notifications, elles apparaitront ici conformément à vos préférences.", "empty_column.notifications": "Vous n'avez pas encore de notifications. Quand d'autres personnes interagissent avec vous, vous en verrez ici.", @@ -442,20 +444,11 @@ "link_preview.author": "Par {name}", "link_preview.more_from_author": "Plus via {name}", "link_preview.shares": "{count, plural, one {{counter} message} other {{counter} messages}}", - "lists.account.add": "Ajouter à une liste", - "lists.account.remove": "Retirer d'une liste", "lists.delete": "Supprimer la liste", "lists.edit": "Modifier la liste", - "lists.edit.submit": "Modifier le titre", - "lists.exclusive": "Cacher ces publications depuis la page d'accueil", - "lists.new.create": "Ajouter une liste", - "lists.new.title_placeholder": "Titre de la nouvelle liste", "lists.replies_policy.followed": "N'importe quel compte suivi", "lists.replies_policy.list": "Membres de la liste", "lists.replies_policy.none": "Personne", - "lists.replies_policy.title": "Afficher les réponses à:", - "lists.search": "Rechercher parmi les gens que vous suivez", - "lists.subheading": "Vos listes", "load_pending": "{count, plural, one {# nouvel élément} other {# nouveaux éléments}}", "loading_indicator.label": "Chargement…", "media_gallery.hide": "Masquer", diff --git a/app/javascript/mastodon/locales/fr.json b/app/javascript/mastodon/locales/fr.json index ed751c244b..8597152f00 100644 --- a/app/javascript/mastodon/locales/fr.json +++ b/app/javascript/mastodon/locales/fr.json @@ -87,6 +87,9 @@ "alert.unexpected.title": "Oups !", "alt_text_badge.title": "Texte Alt", "announcement.announcement": "Annonce", + "annual_report.summary.archetype.oracle": "L’oracle", + "annual_report.summary.here_it_is": "Voici votre récap de {year} :", + "annual_report.summary.most_used_app.most_used_app": "appli la plus utilisée", "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 utilisateur·rice·s non connecté·e·s.", @@ -272,7 +275,6 @@ "empty_column.hashtag": "Il n’y a encore aucun contenu associé à ce hashtag.", "empty_column.home": "Votre fil principal est vide ! Suivez plus de personnes pour le remplir.", "empty_column.list": "Il n’y a rien dans cette liste pour l’instant. Quand des membres de cette liste publieront de nouveaux messages, ils apparaîtront ici.", - "empty_column.lists": "Vous n’avez pas encore de liste. Lorsque vous en créerez une, elle apparaîtra ici.", "empty_column.mutes": "Vous n’avez masqué aucun compte pour le moment.", "empty_column.notification_requests": "C'est fini ! Il n'y a plus rien ici. Lorsque vous recevez de nouvelles notifications, elles apparaitront ici conformément à vos préférences.", "empty_column.notifications": "Vous n’avez pas encore de notification. Interagissez avec d’autres personnes pour débuter la conversation.", @@ -442,20 +444,11 @@ "link_preview.author": "Par {name}", "link_preview.more_from_author": "Plus via {name}", "link_preview.shares": "{count, plural, one {{counter} message} other {{counter} messages}}", - "lists.account.add": "Ajouter à la liste", - "lists.account.remove": "Supprimer de la liste", "lists.delete": "Supprimer la liste", "lists.edit": "Modifier la liste", - "lists.edit.submit": "Modifier le titre", - "lists.exclusive": "Cacher ces publications sur le fil principal", - "lists.new.create": "Ajouter une liste", - "lists.new.title_placeholder": "Titre de la nouvelle liste", "lists.replies_policy.followed": "N'importe quel compte suivi", "lists.replies_policy.list": "Membres de la liste", "lists.replies_policy.none": "Personne", - "lists.replies_policy.title": "Afficher les réponses à :", - "lists.search": "Rechercher parmi les gens que vous suivez", - "lists.subheading": "Vos listes", "load_pending": "{count, plural, one {# nouvel élément} other {# nouveaux éléments}}", "loading_indicator.label": "Chargement…", "media_gallery.hide": "Masquer", diff --git a/app/javascript/mastodon/locales/fy.json b/app/javascript/mastodon/locales/fy.json index e1c090cb0c..a5e8f924dd 100644 --- a/app/javascript/mastodon/locales/fy.json +++ b/app/javascript/mastodon/locales/fy.json @@ -158,6 +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": "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", @@ -196,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", @@ -271,7 +273,6 @@ "empty_column.hashtag": "Der is noch neat te finen ûnder dizze hashtag.", "empty_column.home": "Dizze tiidline is leech! Folgje mear minsken om it te foljen. {suggestions}", "empty_column.list": "There is nothing in this list yet. When members of this list post new statuses, they will appear here.", - "empty_column.lists": "Jo hawwe noch gjin inkelde list. Wannear’t jo der ien oanmakke hawwe, falt dat hjir te sjen.", "empty_column.mutes": "Jo hawwe noch gjin brûkers negearre.", "empty_column.notification_requests": "Hielendal leech! Der is hjir neat. Wannear’t jo nije meldingen ûntfange, ferskine dizze hjir neffens jo ynstellingen.", "empty_column.notifications": "Jo hawwe noch gjin meldingen. Ynteraksjes mei oare minsken sjogge jo hjir.", @@ -304,6 +305,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}’", "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", @@ -383,6 +385,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?", @@ -394,6 +397,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", @@ -441,20 +445,11 @@ "link_preview.author": "Troch {name}", "link_preview.more_from_author": "Mear fan {name}", "link_preview.shares": "{count, plural, one {{counter} berjocht} other {{counter} berjochten}}", - "lists.account.add": "Oan list tafoegje", - "lists.account.remove": "Ut list fuortsmite", "lists.delete": "List fuortsmite", "lists.edit": "List bewurkje", - "lists.edit.submit": "Titel wizigje", - "lists.exclusive": "Ferstopje dizze berjochten op jo startside", - "lists.new.create": "List tafoegje", - "lists.new.title_placeholder": "Nije listtitel", "lists.replies_policy.followed": "Elke folge brûker", "lists.replies_policy.list": "Leden fan de list", "lists.replies_policy.none": "Net ien", - "lists.replies_policy.title": "Reaksjes toane oan:", - "lists.search": "Sykje nei minsken dy’t jo folgje", - "lists.subheading": "Jo listen", "load_pending": "{count, plural, one {# nij item} other {# nije items}}", "loading_indicator.label": "Lade…", "media_gallery.hide": "Ferstopje", @@ -506,6 +501,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 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", @@ -564,6 +560,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 aa7892163b..31418c8e72 100644 --- a/app/javascript/mastodon/locales/ga.json +++ b/app/javascript/mastodon/locales/ga.json @@ -87,6 +87,25 @@ "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.most_used_hashtag.none": "Dada", + "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.", @@ -273,7 +292,6 @@ "empty_column.hashtag": "Níl rud ar bith faoin haischlib seo go fóill.", "empty_column.home": "Tá d'amlíne baile folamh! B'fhiú duit cúpla duine eile a leanúint lena líonadh! {suggestions}", "empty_column.list": "Níl aon rud ar an liosta seo fós. Nuair a fhoilseoidh baill an liosta seo postálacha nua, beidh siad le feiceáil anseo.", - "empty_column.lists": "Níl aon liostaí fós agat. Nuair a chruthaíonn tú ceann, feicfear anseo é.", "empty_column.mutes": "Níl aon úsáideoir balbhaithe agat fós.", "empty_column.notification_requests": "Gach soiléir! Níl aon rud anseo. Nuair a gheobhaidh tú fógraí nua, beidh siad le feiceáil anseo de réir do shocruithe.", "empty_column.notifications": "Níl aon fógraí agat fós. Nuair a dhéanann daoine eile idirghníomhú leat, feicfear anseo é.", @@ -386,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?", @@ -397,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}}", @@ -444,20 +464,11 @@ "link_preview.author": "Le {name}", "link_preview.more_from_author": "Tuilleadh ó {name}", "link_preview.shares": "{count, plural, one {{counter} post} other {{counter} poist}}", - "lists.account.add": "Cuir leis an liosta", - "lists.account.remove": "Scrios as an liosta", "lists.delete": "Scrios liosta", "lists.edit": "Cuir an liosta in eagar", - "lists.edit.submit": "Athraigh teideal", - "lists.exclusive": "Folaigh na poist seo ón mbaile", - "lists.new.create": "Cruthaigh liosta", - "lists.new.title_placeholder": "Teideal liosta nua", "lists.replies_policy.followed": "Úsáideoir ar bith atá á leanúint", "lists.replies_policy.list": "Baill an liosta", "lists.replies_policy.none": "Duine ar bith", - "lists.replies_policy.title": "Taispeáin freagraí:", - "lists.search": "Cuardaigh i measc daoine atá á leanúint agat", - "lists.subheading": "Do liostaí", "load_pending": "{count, plural, one {# mír nua} two {# mír nua} few {# mír nua} many {# mír nua} other {# mír nua}}", "loading_indicator.label": "Á lódáil…", "media_gallery.hide": "Folaigh", @@ -506,6 +517,8 @@ "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ú", diff --git a/app/javascript/mastodon/locales/gd.json b/app/javascript/mastodon/locales/gd.json index 4f68737b14..17dbfc30e4 100644 --- a/app/javascript/mastodon/locales/gd.json +++ b/app/javascript/mastodon/locales/gd.json @@ -87,6 +87,25 @@ "alert.unexpected.title": "Oich!", "alt_text_badge.title": "Roghainn teacsa", "announcement.announcement": "Brath-fios", + "annual_report.summary.archetype.booster": "Brosnaiche", + "annual_report.summary.archetype.lurker": "Eala-bhalbh", + "annual_report.summary.archetype.oracle": "Coinneach Odhar", + "annual_report.summary.archetype.pollster": "Cunntair nam beachd", + "annual_report.summary.archetype.replier": "Ceatharnach nam freagairt", + "annual_report.summary.followers.followers": "luchd-leantainn", + "annual_report.summary.followers.total": "{count} gu h-iomlan", + "annual_report.summary.here_it_is": "Seo mar a chaidh {year} leat:", + "annual_report.summary.highlighted_post.by_favourites": "am post as annsa", + "annual_report.summary.highlighted_post.by_reblogs": "am post air a bhrosnachadh as trice", + "annual_report.summary.highlighted_post.by_replies": "am post dhan deach fhreagairt as trice", + "annual_report.summary.highlighted_post.possessive": "Aig {name},", + "annual_report.summary.most_used_app.most_used_app": "an aplacaid a chaidh a cleachdadh as trice", + "annual_report.summary.most_used_hashtag.most_used_hashtag": "an taga hais a chaidh a cleachdadh as trice", + "annual_report.summary.most_used_hashtag.none": "Chan eil gin", + "annual_report.summary.new_posts.new_posts": "postaichean ùra", + "annual_report.summary.percentile.text": "Tha thu am measg brod nandhen luchd-cleachdaidh Mhastodon.", + "annual_report.summary.percentile.we_wont_tell_bernie": "Ainmeil ’nad latha ’s ’nad linn.", + "annual_report.summary.thanks": "Mòran taing airson conaltradh air Mastodon.", "attachments_list.unprocessed": "(gun phròiseasadh)", "audio.hide": "Falaich an fhuaim", "block_modal.remote_users_caveat": "Iarraidh sinn air an fhrithealaiche {domain} gun gèill iad ri do cho-dhùnadh. Gidheadh, chan eil barantas gun gèill iad on a làimhsicheas cuid a fhrithealaichean bacaidhean air dòigh eadar-dhealaichte. Dh’fhaoidte gum faic daoine gun chlàradh a-steach na postaichean poblach agad fhathast.", @@ -273,7 +292,6 @@ "empty_column.hashtag": "Chan eil dad san taga hais seo fhathast.", "empty_column.home": "Tha loidhne-ama na dachaigh agad falamh! Lean barrachd dhaoine gus a lìonadh.", "empty_column.list": "Chan eil dad air an liosta seo fhathast. Nuair a phostaicheas buill a tha air an liosta seo postaichean ùra, nochdaidh iad an-seo.", - "empty_column.lists": "Chan eil liosta agad fhathast. Nuair chruthaicheas tu tè, nochdaidh i an-seo.", "empty_column.mutes": "Cha do mhùch thu cleachdaiche sam bith fhathast.", "empty_column.notification_requests": "Glan! Chan eil dad an-seo. Nuair a gheibh thu brathan ùra, nochdaidh iad an-seo a-rèir nan roghainnean agad.", "empty_column.notifications": "Cha d’ fhuair thu brath sam bith fhathast. Nuair a nì càch conaltradh leat, chì thu an-seo e.", @@ -446,20 +464,11 @@ "link_preview.author": "Le {name}", "link_preview.more_from_author": "Barrachd le {name}", "link_preview.shares": "{count, plural, one {{counter} phost} two {{counter} phost} few {{counter} postaichean} other {{counter} post}}", - "lists.account.add": "Cuir ris an liosta", - "lists.account.remove": "Thoir air falbh on liosta", "lists.delete": "Sguab às an liosta", "lists.edit": "Deasaich an liosta", - "lists.edit.submit": "Atharraich an tiotal", - "lists.exclusive": "Falaich na postaichean seo air an dachaigh", - "lists.new.create": "Cuir liosta ris", - "lists.new.title_placeholder": "Tiotal na liosta ùir", "lists.replies_policy.followed": "Cleachdaiche sam bith a leanas mi", "lists.replies_policy.list": "Buill na liosta", "lists.replies_policy.none": "Na seall idir", - "lists.replies_policy.title": "Seall freagairtean do:", - "lists.search": "Lorg am measg nan daoine a leanas tu", - "lists.subheading": "Na liostaichean agad", "load_pending": "{count, plural, one {# nì ùr} two {# nì ùr} few {# nithean ùra} other {# nì ùr}}", "loading_indicator.label": "’Ga luchdadh…", "media_gallery.hide": "Falaich", @@ -508,6 +517,8 @@ "notification.admin.report_statuses_other": "Rinn {name} gearan mu {target}", "notification.admin.sign_up": "Chlàraich {name}", "notification.admin.sign_up.name_and_others": "Chlàraich {name} ’s {count, plural, one {# eile} two {# eile} few {# eile} other {# eile}}", + "notification.annual_report.message": "Tha #Wrapstodon {year} deiseil dhut! Thoir sùil air mar a chaidh leat air Mastodon am bliadhna!", + "notification.annual_report.view": "Seall #Wrapstodon", "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", diff --git a/app/javascript/mastodon/locales/gl.json b/app/javascript/mastodon/locales/gl.json index e89d386c85..e77aaade6b 100644 --- a/app/javascript/mastodon/locales/gl.json +++ b/app/javascript/mastodon/locales/gl.json @@ -87,6 +87,24 @@ "alert.unexpected.title": "Vaites!", "alt_text_badge.title": "Texto Alt", "announcement.announcement": "Anuncio", + "annual_report.summary.archetype.booster": "A axencia de noticias", + "annual_report.summary.archetype.lurker": "Volleur", + "annual_report.summary.archetype.oracle": "Sabichón/e", + "annual_report.summary.archetype.pollster": "O INE", + "annual_report.summary.archetype.replier": "Lareteire", + "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.most_used_hashtag.none": "Nada", + "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.", @@ -273,7 +291,6 @@ "empty_column.hashtag": "Aínda non hai nada con este cancelo.", "empty_column.home": "A túa cronoloxía inicial está baleira! Sigue a outras usuarias para enchela.", "empty_column.list": "Aínda non hai nada nesta listaxe. Cando as usuarias incluídas na listaxe publiquen mensaxes, amosaranse aquí.", - "empty_column.lists": "Aínda non tes listaxes. Cando crees unha, amosarase aquí.", "empty_column.mutes": "Aínda non silenciaches a ningúnha usuaria.", "empty_column.notification_requests": "Todo ben! Nada por aquí. Cando recibas novas notificacións aparecerán aquí seguindo o criterio dos teus axustes.", "empty_column.notifications": "Aínda non tes notificacións. Aparecerán cando outras persoas interactúen contigo.", @@ -446,20 +463,11 @@ "link_preview.author": "Por {name}", "link_preview.more_from_author": "Máis de {name}", "link_preview.shares": "{count, plural, one {{counter} publicación} other {{counter} publicacións}}", - "lists.account.add": "Engadir á listaxe", - "lists.account.remove": "Eliminar da listaxe", "lists.delete": "Eliminar listaxe", "lists.edit": "Editar listaxe", - "lists.edit.submit": "Mudar o título", - "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": "Calquera usuaria que siga", "lists.replies_policy.list": "Membros da lista", "lists.replies_policy.none": "Ninguén", - "lists.replies_policy.title": "Mostrar respostas a:", - "lists.search": "Procurar entre as persoas que segues", - "lists.subheading": "As túas listaxes", "load_pending": "{count, plural, one {# novo elemento} other {# novos elementos}}", "loading_indicator.label": "Estase a cargar…", "media_gallery.hide": "Agochar", @@ -508,6 +516,8 @@ "notification.admin.report_statuses_other": "{name} denunciou a {target}", "notification.admin.sign_up": "{name} rexistrouse", "notification.admin.sign_up.name_and_others": "{name} e {count, plural, one {# máis} other {# máis}} crearon unha conta", + "notification.annual_report.message": "A #VidaEnMastodon de {year} agarda por ti! Desvela os momentos máis destacados e historias reseñables en Mastodon!", + "notification.annual_report.view": "Ver #VidaEnMastodon", "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", diff --git a/app/javascript/mastodon/locales/he.json b/app/javascript/mastodon/locales/he.json index ed08a9aba3..57f0ee9e5e 100644 --- a/app/javascript/mastodon/locales/he.json +++ b/app/javascript/mastodon/locales/he.json @@ -87,6 +87,25 @@ "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.most_used_hashtag.none": "אף אחד", + "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} לכבד את החלטתך. עם זאת, ציות למוסכמות איננו מובטח כיוון ששרתים מסויימים עשויים לטפל בחסימות בצורה אחרת. הודעות פומביות עדיין יהיו גלויות לעיני משתמשים שאינם מחוברים.", @@ -121,13 +140,16 @@ "column.blocks": "משתמשים חסומים", "column.bookmarks": "סימניות", "column.community": "פיד שרת מקומי", + "column.create_list": "יצירת רשימה", "column.direct": "הודעות פרטיות", "column.directory": "עיין בפרופילים", "column.domain_blocks": "קהילות (שמות מתחם) מוסתרות", + "column.edit_list": "עריכת רשימה", "column.favourites": "חיבובים", "column.firehose": "פידים עדכניים", "column.follow_requests": "בקשות מעקב", "column.home": "פיד הבית", + "column.list_members": "ניהול חברי הרשימה", "column.lists": "רשימות", "column.mutes": "משתמשים בהשתקה", "column.notifications": "התראות", @@ -273,7 +295,6 @@ "empty_column.hashtag": "אין כלום בתגית הזאת עדיין.", "empty_column.home": "פיד הבית ריק ! אפשר לבקר ב{public} או להשתמש בחיפוש כדי להתחיל ולהכיר משתמשים/ות אחרים/ות. {suggestions}", "empty_column.list": "אין עדיין פריטים ברשימה. כאשר חברים ברשימה הזאת יפרסמו הודעות חדשות, הן יופיעו פה.", - "empty_column.lists": "אין לך שום רשימות עדיין. לכשיהיו, הן תופענה כאן.", "empty_column.mutes": "עוד לא השתקת שום משתמש.", "empty_column.notification_requests": "בום! אין פה כלום. כשיווצרו עוד התראות, הן יופיעו כאן על בסיס ההעדפות שלך.", "empty_column.notifications": "אין התראות עדיין. יאללה, הגיע הזמן להתחיל להתערבב.", @@ -446,20 +467,32 @@ "link_preview.author": "מאת {name}", "link_preview.more_from_author": "עוד מאת {name}", "link_preview.shares": "{count, plural, one {הודעה אחת} two {הודעותיים} many {{counter} הודעות} other {{counter} הודעות}}", - "lists.account.add": "הוסף לרשימה", - "lists.account.remove": "הסר מרשימה", + "lists.add_member": "הוספה", + "lists.add_to_list": "הוספה לרשימה", + "lists.add_to_lists": "הוספת {name} לרשימות", + "lists.create": "יצירה", + "lists.create_a_list_to_organize": "יצירת רשימה חדשה לארגון פיד הבית שלך", + "lists.create_list": "יצירת רשימה", "lists.delete": "מחיקת רשימה", + "lists.done": "בוצע", "lists.edit": "עריכת רשימה", - "lists.edit.submit": "שנה/י כותרת", - "lists.exclusive": "להסתיר את ההודעות האלו מפיד הבית", - "lists.new.create": "הוספת רשימה", - "lists.new.title_placeholder": "כותרת הרשימה החדשה", + "lists.exclusive": "הסתרת החברים בפיד הבית", + "lists.exclusive_hint": "אם שם כלשהו ברשימה זו, נסתיר אותי בפיד הבית כדי למנוע כפילות.", + "lists.find_users_to_add": "חיפוש משתמשים להוספה", + "lists.list_members": "פירוט חברי הרשימה", + "lists.list_members_count": "{count, plural, one {חבר רשימה אחד} other {# חברי רשימה}}", + "lists.list_name": "שם הרשימה", + "lists.new_list_name": "שם רשימה חדשה", + "lists.no_lists_yet": "אין רשימות עדיין.", + "lists.no_members_yet": "עוד אין חברים ברשימה.", + "lists.no_results_found": "לא נמצאו תוצאות.", + "lists.remove_member": "הסרה", "lists.replies_policy.followed": "משתמשים שאני עוקב אחריהם", "lists.replies_policy.list": "משתמשים שברשימה", "lists.replies_policy.none": "אף אחד", - "lists.replies_policy.title": "הצג תגובות ל:", - "lists.search": "חיפוש בין אנשים שאני עוקב\\ת אחריהם", - "lists.subheading": "הרשימות שלך", + "lists.save": "שמירה", + "lists.search_placeholder": "חיפוש אנשים שאני עוקב\\ת אחריהם", + "lists.show_replies_to": "לכלול תשובות מחברי הרשימה אל", "load_pending": "{count, plural, one {# פריט חדש} other {# פריטים חדשים}}", "loading_indicator.label": "בטעינה…", "media_gallery.hide": "להסתיר", @@ -508,6 +541,8 @@ "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.annual_report.message": "ה- #סיכומודון שלך לשנת {year} מחכה! גלו את רגעי השיא והזכרונות ממסטודון!", + "notification.annual_report.view": "לצפייה ב- #סיכומודון", "notification.favourite": "הודעתך חובבה על ידי {name}", "notification.favourite.name_and_others_with_link": "{name} ועוד {count, plural,one {אחד נוסף}other {# נוספים}} חיבבו את הודעתך", "notification.follow": "{name} במעקב אחרייך", diff --git a/app/javascript/mastodon/locales/hi.json b/app/javascript/mastodon/locales/hi.json index e0de4c8452..eebf0dd9da 100644 --- a/app/javascript/mastodon/locales/hi.json +++ b/app/javascript/mastodon/locales/hi.json @@ -237,7 +237,6 @@ "empty_column.hashtag": "यह हैशटैग अभी तक खाली है।", "empty_column.home": "आपकी मुख्य कालक्रम अभी खली है. अन्य उपयोगकर्ताओं से मिलने के लिए और अपनी गतिविधियां शुरू करने के लिए या तो {public} पर जाएं या खोज का उपयोग करें।", "empty_column.list": "यह सूची अभी खाली है. जब इसके सदस्य कोई अभिव्यक्ति देंगे, तो वो यहां दिखाई देंगी.", - "empty_column.lists": "आपके पास अभी तक कोई सूची नहीं है। जब आप एक बनाते हैं, तो यह यहां दिखाई देगा।", "empty_column.mutes": "आपने अभी तक किसी भी उपयोगकर्ता को म्यूट नहीं किया है।", "empty_column.notifications": "आपके पास अभी तक कोई सूचना नहीं है। बातचीत शुरू करने के लिए दूसरों के साथ बातचीत करें।", "empty_column.public": "यहां कुछ नहीं है! सार्वजनिक रूप से कुछ लिखें, या इसे भरने के लिए अन्य सर्वर से उपयोगकर्ताओं का मैन्युअल रूप से अनुसरण करें", @@ -352,18 +351,11 @@ "lightbox.previous": "पिछला", "limited_account_hint.action": "फिर भी प्रोफाइल दिखाओ", "limited_account_hint.title": "यह प्रोफ़ाइल {domain} के मॉडरेटर द्वारा छिपाई गई है.", - "lists.account.add": "ऐड तो लिस्ट", - "lists.account.remove": "सूची से निकालें", "lists.delete": "सूची हटाएँ", "lists.edit": "सूची संपादित करें", - "lists.edit.submit": "शीर्षक बदलें", - "lists.new.create": "सूची जोड़ें", - "lists.new.title_placeholder": "नये सूची का शीर्षक", "lists.replies_policy.followed": "अन्य फोल्लोवेद यूजर", "lists.replies_policy.list": "सूची के सदस्य", "lists.replies_policy.none": "कोई नहीं", - "lists.replies_policy.title": "इसके जवाब दिखाएं:", - "lists.subheading": "आपकी सूचियाँ", "media_gallery.hide": "छिपाएं", "navigation_bar.about": "विवरण", "navigation_bar.blocks": "ब्लॉक्ड यूज़र्स", diff --git a/app/javascript/mastodon/locales/hr.json b/app/javascript/mastodon/locales/hr.json index 26c527f2fe..f09cd71c7c 100644 --- a/app/javascript/mastodon/locales/hr.json +++ b/app/javascript/mastodon/locales/hr.json @@ -199,7 +199,6 @@ "empty_column.hashtag": "Još ne postoji ništa s ovim hashtagom.", "empty_column.home": "Vaša početna vremenska crta je prazna! Posjetite {public} ili koristite tražilicu kako biste započeli i upoznali druge korisnike.", "empty_column.list": "Na ovoj listi još nema ničega. Kada članovi ove liste objave nove tootove, oni će se pojaviti ovdje.", - "empty_column.lists": "Nemaš niti jednu listu. Kada je kreiraš, prikazat će se ovdje.", "empty_column.mutes": "Niste utišali nijednog korisnika.", "empty_column.notifications": "Još nemate obavijesti. Komunicirajte s drugima kako biste započeli razgovor.", "empty_column.public": "Ovdje nema ništa! Napišite nešto javno ili ručno pratite korisnike s drugi poslužitelja da biste ovo popunili", @@ -298,18 +297,11 @@ "lightbox.next": "Sljedeće", "lightbox.previous": "Prethodno", "limited_account_hint.action": "Svejedno prikaži profil", - "lists.account.add": "Dodaj na listu", - "lists.account.remove": "Ukloni s liste", "lists.delete": "Izbriši listu", "lists.edit": "Uredi listu", - "lists.edit.submit": "Promijeni naslov", - "lists.new.create": "Dodaj listu", - "lists.new.title_placeholder": "Naziv nove liste", "lists.replies_policy.followed": "Bilo koji praćeni korisnik", "lists.replies_policy.list": "Članovi liste", "lists.replies_policy.none": "Nitko", - "lists.search": "Traži među praćenim ljudima", - "lists.subheading": "Vaše liste", "navigation_bar.about": "O aplikaciji", "navigation_bar.advanced_interface": "Otvori u naprednom web sučelju", "navigation_bar.blocks": "Blokirani korisnici", diff --git a/app/javascript/mastodon/locales/hu.json b/app/javascript/mastodon/locales/hu.json index 0933a7c256..9a76a21e93 100644 --- a/app/javascript/mastodon/locales/hu.json +++ b/app/javascript/mastodon/locales/hu.json @@ -87,6 +87,25 @@ "alert.unexpected.title": "Hoppá!", "alt_text_badge.title": "Helyettesítő szöveg", "announcement.announcement": "Közlemény", + "annual_report.summary.archetype.booster": "A cool-vadász", + "annual_report.summary.archetype.lurker": "A settenkedő", + "annual_report.summary.archetype.oracle": "Az orákulum", + "annual_report.summary.archetype.pollster": "A közvélemény-kutató", + "annual_report.summary.archetype.replier": "A társasági pillangó", + "annual_report.summary.followers.followers": "követő", + "annual_report.summary.followers.total": "{count} összesen", + "annual_report.summary.here_it_is": "Itt a {year}. év értékelése:", + "annual_report.summary.highlighted_post.by_favourites": "legkedvencebb bejegyzés", + "annual_report.summary.highlighted_post.by_reblogs": "legtöbbet megtolt bejegyzés", + "annual_report.summary.highlighted_post.by_replies": "bejegyzés a legtöbb válasszal", + "annual_report.summary.highlighted_post.possessive": "{name} fióktól", + "annual_report.summary.most_used_app.most_used_app": "legtöbbet használt app", + "annual_report.summary.most_used_hashtag.most_used_hashtag": "legtöbbet használt hashtag", + "annual_report.summary.most_used_hashtag.none": "Nincs", + "annual_report.summary.new_posts.new_posts": "új bejegyzés", + "annual_report.summary.percentile.text": "Ezzel acsúcs Mastodon felhasználó között vagy.", + "annual_report.summary.percentile.we_wont_tell_bernie": "Nem mondjuk el Bernie-nek.", + "annual_report.summary.thanks": "Kösz, hogy a Mastodon része vagy!", "attachments_list.unprocessed": "(feldolgozatlan)", "audio.hide": "Hang elrejtése", "block_modal.remote_users_caveat": "Arra kérjük a {domain} kiszolgálót, hogy tartsa tiszteletben a döntésedet. Ugyanakkor az együttműködés nem garantált, mivel néhány kiszolgáló másképp kezelheti a letiltásokat. A nyilvános bejegyzések a be nem jelentkezett felhasználók számára továbbra is látszódhatnak.", @@ -273,7 +292,6 @@ "empty_column.hashtag": "Jelenleg nem található semmi ezzel a hashtaggel.", "empty_column.home": "A saját idővonalad üres! Kövess további embereket ennek megtöltéséhez.", "empty_column.list": "A lista jelenleg üres. Ha a listatagok bejegyzést tesznek közzé, itt fog megjelenni.", - "empty_column.lists": "Még nincs egyetlen listád sem. Ha létrehozol egyet, itt fog megjelenni.", "empty_column.mutes": "Még egy felhasználót sem némítottál le.", "empty_column.notification_requests": "Minden tiszta! Itt nincs semmi. Ha új értesítéseket kapsz, azok itt jelennek meg a beállításoknak megfelelően.", "empty_column.notifications": "Jelenleg még nincsenek értesítéseid. Ha mások kapcsolatba lépnek veled, ezek itt lesznek láthatóak.", @@ -446,20 +464,11 @@ "link_preview.author": "{name} szerint", "link_preview.more_from_author": "Több tőle: {name}", "link_preview.shares": "{count, plural, one {{counter} bejegyzés} other {{counter} bejegyzés}}", - "lists.account.add": "Hozzáadás a listához", - "lists.account.remove": "Eltávolítás a listából", "lists.delete": "Lista törlése", "lists.edit": "Lista szerkesztése", - "lists.edit.submit": "Cím megváltoztatása", - "lists.exclusive": "Ezen bejegyzések elrejtése a kezdőoldalról", - "lists.new.create": "Lista hozzáadása", - "lists.new.title_placeholder": "Új lista címe", "lists.replies_policy.followed": "Bármely követett felhasználó", "lists.replies_policy.list": "A lista tagjai", "lists.replies_policy.none": "Senki", - "lists.replies_policy.title": "Nekik mutassuk a válaszokat:", - "lists.search": "Keresés a követett emberek között", - "lists.subheading": "Saját listák", "load_pending": "{count, plural, one {# új elem} other {# új elem}}", "loading_indicator.label": "Betöltés…", "media_gallery.hide": "Elrejtés", @@ -508,6 +517,8 @@ "notification.admin.report_statuses_other": "{name} jelentette: {target}", "notification.admin.sign_up": "{name} regisztrált", "notification.admin.sign_up.name_and_others": "{name} és {count, plural, one {# másik} other {# másik}} regisztrált", + "notification.annual_report.message": "Vár a {year}. év #Wrapstodon jelentése! Fedd fel az éved jelentős eseményeit és emlékezetes pillanatait a Mastodonon!", + "notification.annual_report.view": "#Wrapstodon Megtekintése", "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", diff --git a/app/javascript/mastodon/locales/hy.json b/app/javascript/mastodon/locales/hy.json index 9e5ae79045..b5faf7e720 100644 --- a/app/javascript/mastodon/locales/hy.json +++ b/app/javascript/mastodon/locales/hy.json @@ -174,7 +174,6 @@ "empty_column.hashtag": "Այս պիտակով դեռ ոչինչ չկայ։", "empty_column.home": "Քո հիմնական հոսքը դատարկ է։ Այցելի՛ր {public}ը կամ օգտուիր որոնումից՝ այլ մարդկանց հանդիպելու համար։", "empty_column.list": "Այս ցանկում դեռ ոչինչ չկայ։ Երբ ցանկի անդամներից որեւէ մէկը նոր գրառում անի, այն կը յայտնուի այստեղ։", - "empty_column.lists": "Դուք դեռ չունէք ստեղծած ցանկ։ Ցանկ ստեղծելուն պէս այն կը յայտնուի այստեղ։", "empty_column.mutes": "Առայժմ ոչ ոքի չէք լռեցրել։", "empty_column.notifications": "Ոչ մի ծանուցում դեռ չունես։ Բզիր միւսներին՝ խօսակցութիւնը սկսելու համար։", "empty_column.public": "Այստեղ բան չկա՛յ։ Հրապարակային մի բան գրիր կամ հետեւիր այլ հանգոյցներից էակների՝ այն լցնելու համար։", @@ -273,19 +272,11 @@ "lightbox.close": "Փակել", "lightbox.next": "Յաջորդ", "lightbox.previous": "Նախորդ", - "lists.account.add": "Աւելացնել ցանկին", - "lists.account.remove": "Հանել ցանկից", "lists.delete": "Ջնջել ցանկը", "lists.edit": "Փոփոխել ցանկը", - "lists.edit.submit": "Փոխել վերնագիրը", - "lists.new.create": "Աւելացնել ցանկ", - "lists.new.title_placeholder": "Նոր ցանկի վերնագիր", "lists.replies_policy.followed": "Ցանկացած հետեւող օգտատէր", "lists.replies_policy.list": "Ցանկի անդամներ", "lists.replies_policy.none": "Ոչ ոք", - "lists.replies_policy.title": "Ցուցադրել պատասխանները՝", - "lists.search": "Փնտրել քո հետեւած մարդկանց մէջ", - "lists.subheading": "Քո ցանկերը", "load_pending": "{count, plural, one {# նոր նիւթ} other {# նոր նիւթ}}", "navigation_bar.about": "Մասին", "navigation_bar.blocks": "Արգելափակուած օգտատէրեր", diff --git a/app/javascript/mastodon/locales/ia.json b/app/javascript/mastodon/locales/ia.json index e41d390a3f..891c293d50 100644 --- a/app/javascript/mastodon/locales/ia.json +++ b/app/javascript/mastodon/locales/ia.json @@ -87,6 +87,25 @@ "alert.unexpected.title": "Ups!", "alt_text_badge.title": "Texto alt", "announcement.announcement": "Annuncio", + "annual_report.summary.archetype.booster": "Le impulsator", + "annual_report.summary.archetype.lurker": "Le lector", + "annual_report.summary.archetype.oracle": "Le oraculo", + "annual_report.summary.archetype.pollster": "Le sondagista", + "annual_report.summary.archetype.replier": "Le responditor", + "annual_report.summary.followers.followers": "sequitores", + "annual_report.summary.followers.total": "{count} in total", + "annual_report.summary.here_it_is": "Ecce tu summario de {year}:", + "annual_report.summary.highlighted_post.by_favourites": "message le plus favorite", + "annual_report.summary.highlighted_post.by_reblogs": "message le plus impulsate", + "annual_report.summary.highlighted_post.by_replies": "message le plus respondite", + "annual_report.summary.highlighted_post.possessive": "{name}, ecce tu…", + "annual_report.summary.most_used_app.most_used_app": "application le plus usate", + "annual_report.summary.most_used_hashtag.most_used_hashtag": "hashtag le plus usate", + "annual_report.summary.most_used_hashtag.none": "Necun", + "annual_report.summary.new_posts.new_posts": "nove messages", + "annual_report.summary.percentile.text": "Isto te pone in le primedel usatores de Mastodon.", + "annual_report.summary.percentile.we_wont_tell_bernie": "Tu es un primo inter pares.", + "annual_report.summary.thanks": "Gratias pro facer parte de Mastodon!", "attachments_list.unprocessed": "(non processate)", "audio.hide": "Celar audio", "block_modal.remote_users_caveat": "Nos demandera al servitor {domain} de respectar tu decision. Nonobstante, le conformitate non es garantite perque alcun servitores pote tractar le blocadas de maniera differente. Le messages public pote esser totevia visibile pro le usatores non authenticate.", @@ -158,6 +177,7 @@ "compose_form.poll.duration": "Durata del sondage", "compose_form.poll.multiple": "Selection multiple", "compose_form.poll.option_placeholder": "Option {number}", + "compose_form.poll.single": "Option singule", "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", @@ -196,6 +216,7 @@ "confirmations.unfollow.title": "Cessar de sequer le usator?", "content_warning.hide": "Celar le message", "content_warning.show": "Monstrar in omne caso", + "content_warning.show_more": "Monstrar plus", "conversation.delete": "Deler conversation", "conversation.mark_as_read": "Marcar como legite", "conversation.open": "Vider conversation", @@ -271,7 +292,6 @@ "empty_column.hashtag": "Il non ha ancora alcun cosa in iste hashtag.", "empty_column.home": "Tu chronologia de initio es vacue! Seque plus personas pro plenar lo.", "empty_column.list": "Iste lista es ancora vacue. Quando le membros de iste lista publica nove messages, illos apparera hic.", - "empty_column.lists": "Tu non ha ancora listas. Quando tu crea un, illo apparera hic.", "empty_column.mutes": "Tu non ha ancora silentiate alcun usator.", "empty_column.notification_requests": "Iste lista es toto vacue! Quando tu recipe notificationes, illos apparera hic como configurate in tu parametros.", "empty_column.notifications": "Tu non ha ancora notificationes. Quando altere personas interage con te, tu lo videra hic.", @@ -304,6 +324,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", @@ -383,6 +404,7 @@ "interaction_modal.description.follow": "Con un conto sur Mastodon, tu pote sequer {name} e reciper su messages in tu fluxo de initio.", "interaction_modal.description.reblog": "Con un conto sur Mastodon, tu pote impulsar iste message pro condivider lo con tu proprie sequitores.", "interaction_modal.description.reply": "Con un conto sur Mastodon, tu pote responder a iste message.", + "interaction_modal.description.vote": "Con un conto sur Mastodon, tu pote votar in iste sondage.", "interaction_modal.login.action": "Porta me a casa", "interaction_modal.login.prompt": "Dominio de tu servitor, p.ex. mastodon.social", "interaction_modal.no_account_yet": "Non sur Mstodon?", @@ -394,6 +416,7 @@ "interaction_modal.title.follow": "Sequer {name}", "interaction_modal.title.reblog": "Impulsar le message de {name}", "interaction_modal.title.reply": "Responder al message de {name}", + "interaction_modal.title.vote": "Votar in le sondage de {name}", "intervals.full.days": "{number, plural, one {# die} other {# dies}}", "intervals.full.hours": "{number, plural, one {# hora} other {# horas}}", "intervals.full.minutes": "{number, plural, one {# minuta} other {# minutas}}", @@ -441,20 +464,11 @@ "link_preview.author": "Per {name}", "link_preview.more_from_author": "Plus de {name}", "link_preview.shares": "{count, plural, one {{counter} message} other {{counter} messages}}", - "lists.account.add": "Adder al lista", - "lists.account.remove": "Remover del lista", "lists.delete": "Deler lista", "lists.edit": "Modificar lista", - "lists.edit.submit": "Cambiar titulo", - "lists.exclusive": "Celar iste messages sur le pagina de initio", - "lists.new.create": "Adder lista", - "lists.new.title_placeholder": "Nove titulo del lista", "lists.replies_policy.followed": "Qualcunque usator sequite", "lists.replies_policy.list": "Membros del lista", "lists.replies_policy.none": "Nemo", - "lists.replies_policy.title": "Monstrar responsas a:", - "lists.search": "Cercar inter le gente que tu seque", - "lists.subheading": "Tu listas", "load_pending": "{count, plural, one {# nove entrata} other {# nove entratas}}", "loading_indicator.label": "Cargante…", "media_gallery.hide": "Celar", @@ -503,9 +517,12 @@ "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.annual_report.message": "Tu summario #Wrapstodon pro {year} attende! Revela le momentos saliente e memorabile de tu anno sur Mastodon!", + "notification.annual_report.view": "Visitar summario #Wrapstodon", "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.name_and_others": "{name} e {count, plural, one {# other} other {# alteres}} 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", @@ -564,6 +581,7 @@ "notifications.column_settings.filter_bar.category": "Barra de filtro rapide", "notifications.column_settings.follow": "Nove sequitores:", "notifications.column_settings.follow_request": "Nove requestas de sequimento:", + "notifications.column_settings.group": "Gruppo", "notifications.column_settings.mention": "Mentiones:", "notifications.column_settings.poll": "Resultatos del sondage:", "notifications.column_settings.push": "Notificationes push", diff --git a/app/javascript/mastodon/locales/id.json b/app/javascript/mastodon/locales/id.json index 4b43363960..c966ea0ab0 100644 --- a/app/javascript/mastodon/locales/id.json +++ b/app/javascript/mastodon/locales/id.json @@ -267,7 +267,6 @@ "empty_column.hashtag": "Tidak ada apa pun dalam hashtag ini.", "empty_column.home": "Linimasa anda kosong! Kunjungi {public} atau gunakan pencarian untuk memulai dan bertemu pengguna lain.", "empty_column.list": "Belum ada apa pun di daftar ini. Ketika anggota dari daftar ini mengirim kiriman baru, mereka akan tampil di sini.", - "empty_column.lists": "Anda belum memiliki daftar. Ketika Anda membuatnya, maka akan muncul di sini.", "empty_column.mutes": "Anda belum membisukan siapa pun.", "empty_column.notifications": "Anda belum memiliki notifikasi. Ketika orang lain berinteraksi dengan Anda, Anda akan melihatnya di sini.", "empty_column.public": "Tidak ada apa pun di sini! Tulis sesuatu, atau ikuti pengguna lain dari server lain untuk mengisi ini", @@ -393,19 +392,11 @@ "limited_account_hint.action": "Tetap tampilkan profil", "limited_account_hint.title": "Profil ini telah disembunyikan oleh moderator {domain}.", "link_preview.author": "Oleh {name}", - "lists.account.add": "Tambah ke daftar", - "lists.account.remove": "Hapus dari daftar", "lists.delete": "Hapus daftar", "lists.edit": "Sunting daftar", - "lists.edit.submit": "Ubah judul", - "lists.new.create": "Tambah daftar", - "lists.new.title_placeholder": "Judul daftar baru", "lists.replies_policy.followed": "Siapa pun pengguna yang diikuti", "lists.replies_policy.list": "Anggota di daftar tersebut", "lists.replies_policy.none": "Tidak ada satu pun", - "lists.replies_policy.title": "Tampilkan balasan ke:", - "lists.search": "Cari di antara orang yang Anda ikuti", - "lists.subheading": "Daftar Anda", "load_pending": "{count, plural, other {# item baru}}", "loading_indicator.label": "Memuat…", "moved_to_account_banner.text": "Akun {disabledAccount} Anda kini dinonaktifkan karena Anda pindah ke {movedToAccount}.", diff --git a/app/javascript/mastodon/locales/ie.json b/app/javascript/mastodon/locales/ie.json index f58cf1c71c..2be72b0488 100644 --- a/app/javascript/mastodon/locales/ie.json +++ b/app/javascript/mastodon/locales/ie.json @@ -253,7 +253,6 @@ "empty_column.hashtag": "Hay nullcos en ti-ci hashtag ancor.", "empty_column.home": "Tui hemal témpor-linea es vacui! Sequer plu gente por plenar it.", "empty_column.list": "Ancor ne hay quocunc in ti-ci liste. Quande membres de ti-ci liste publica nov postas, ili va aparir ci.", - "empty_column.lists": "Tu ancor have null listes. Quande tu crea un, it va aparir ci.", "empty_column.mutes": "Tu ancor ha silentiat null usatores.", "empty_column.notification_requests": "Omnicos clar! Hay necos ci. Nov notificationes va venir ci quande tu recive les secun tui parametres.", "empty_column.notifications": "Tu have null notificationes. Quande altri persones interacte con te, tu va vider it ci.", @@ -399,20 +398,11 @@ "limited_account_hint.action": "Monstrar profil totvez", "limited_account_hint.title": "Ti-ci profil ha esset celat del moderatores de {domain}.", "link_preview.author": "De {name}", - "lists.account.add": "Adjunter a liste", - "lists.account.remove": "Remover de liste", "lists.delete": "Deleter liste", "lists.edit": "Redacter liste", - "lists.edit.submit": "Changear titul", - "lists.exclusive": "Celar ti-ci postas del hemal témpor-linea", - "lists.new.create": "Adjunter liste", - "lists.new.title_placeholder": "Titul del nov liste", "lists.replies_policy.followed": "Quelcunc sequet usator", "lists.replies_policy.list": "Membres del liste", "lists.replies_policy.none": "Nequi", - "lists.replies_policy.title": "Monstrar responses a:", - "lists.search": "Serchar inter li persones quem tu seque", - "lists.subheading": "Tui listes", "load_pending": "{count, plural, one {# nov element} other {# nov elementes}}", "loading_indicator.label": "Cargant…", "moved_to_account_banner.text": "Tui conto {disabledAccount} es actualmen desactivisat pro que tu movet te a {movedToAccount}.", diff --git a/app/javascript/mastodon/locales/ig.json b/app/javascript/mastodon/locales/ig.json index b8b0f1084d..60cb9b7c36 100644 --- a/app/javascript/mastodon/locales/ig.json +++ b/app/javascript/mastodon/locales/ig.json @@ -6,10 +6,14 @@ "account.follow": "Soro", "account.followers": "Ndị na-eso", "account.following": "Na-eso", + "account.go_to_profile": "Jee na profaịlụ", "account.mute": "Mee ogbi @{name}", + "account.posts": "Edemede", + "account.posts_with_replies": "Edemede na nzaghachị", "account.unfollow": "Kwụsị iso", "account_note.placeholder": "Click to add a note", "admin.dashboard.retention.cohort_size": "Ojiarụ ọhụrụ", + "annual_report.summary.new_posts.new_posts": "edemede ọhụrụ", "audio.hide": "Zoo ụda", "bundle_column_error.retry": "Nwaa ọzọ", "bundle_column_error.routing.title": "404", @@ -46,6 +50,7 @@ "confirmations.reply.confirm": "Zaa", "confirmations.unfollow.confirm": "Kwụsị iso", "conversation.delete": "Hichapụ nkata", + "conversation.open": "Lelee nkata", "disabled_account_banner.account_settings": "Mwube akaụntụ", "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.", @@ -62,8 +67,10 @@ "empty_column.list": "There is nothing in this list yet. When members of this list post new statuses, they will appear here.", "errors.unexpected_crash.report_issue": "Kpesa nsogbu", "explore.trending_links": "Akụkọ", + "filter_modal.added.review_and_configure_title": "Mwube myọ", "firehose.all": "Ha niine", "follow_request.authorize": "Nye ikike", + "follow_suggestions.view_all": "Lelee ha ncha", "footer.privacy_policy": "Iwu nzuzu", "getting_started.heading": "Mbido", "hashtag.column_settings.tag_toggle": "Include additional tags in this column", @@ -85,7 +92,7 @@ "keyboard_shortcuts.local": "to open local timeline", "keyboard_shortcuts.mention": "to mention author", "keyboard_shortcuts.muted": "to open muted users list", - "keyboard_shortcuts.my_profile": "to open your profile", + "keyboard_shortcuts.my_profile": "Mepe profaịlụ gị", "keyboard_shortcuts.notifications": "to open notifications column", "keyboard_shortcuts.open_media": "to open media", "keyboard_shortcuts.pinned": "to open pinned posts list", @@ -103,7 +110,6 @@ "lightbox.close": "Mechie", "lists.delete": "Hichapụ ndepụta", "lists.edit": "Dezie ndepụta", - "lists.subheading": "Ndepụta gị", "navigation_bar.about": "Maka", "navigation_bar.bookmarks": "Ebenrụtụakā", "navigation_bar.discover": "Chọpụta", @@ -112,6 +118,7 @@ "navigation_bar.lists": "Ndepụta", "not_signed_in_indicator.not_signed_in": "You need to sign in to access this resource.", "notification.reblog": "{name} boosted your status", + "notifications.column_settings.status": "Edemede ọhụrụ:", "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!", @@ -124,7 +131,7 @@ "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.share_profile.title": "Kekọrịta profaịlụ Mastọdọnụ gị", "privacy.change": "Adjust status privacy", "relative_time.full.just_now": "kịta", "relative_time.just_now": "kịta", @@ -132,6 +139,7 @@ "reply_indicator.cancel": "Kagbuo", "report.categories.other": "Ọzọ", "report.categories.spam": "Nzipụ Ozièlètrọniìk Nkeāchọghị", + "report.category.title_account": "profaịlụ", "report.mute": "Mee ogbi", "report.placeholder": "Type or paste additional comments", "report.submit": "Submit report", @@ -139,6 +147,7 @@ "report_notification.attached_statuses": "{count, plural, one {# post} other {# posts}} attached", "report_notification.categories.other": "Ọzọ", "search.placeholder": "Chọọ", + "search_results.accounts": "Profaịlụ", "server_banner.active_users": "ojiarụ dị ìrè", "sign_in_banner.sign_in": "Sign in", "status.admin_status": "Open this status in the moderation interface", diff --git a/app/javascript/mastodon/locales/io.json b/app/javascript/mastodon/locales/io.json index f9173b65f9..8e2ea3dea4 100644 --- a/app/javascript/mastodon/locales/io.json +++ b/app/javascript/mastodon/locales/io.json @@ -271,7 +271,6 @@ "empty_column.hashtag": "Esas ankore nulo en ta gretovorto.", "empty_column.home": "Vua hemtempolineo esas vakua! Sequez plu multa personi por plenigar lu. {suggestions}", "empty_column.list": "There is nothing in this list yet.", - "empty_column.lists": "Vu ne havas irga listi til nun. Kande vu kreas talo, ol montresos hike.", "empty_column.mutes": "Vu ne silencigis irga uzanti til nun.", "empty_column.notification_requests": "Finis. Kande vu recevas nova savigi, oli aparos hike segun vua preferaji.", "empty_column.notifications": "Tu havas ankore nula savigo. Komunikez kun altri por debutar la konverso.", @@ -441,20 +440,11 @@ "link_preview.author": "Da {name}", "link_preview.more_from_author": "Plua de {name}", "link_preview.shares": "{count, plural,one {{counter} posto} other {{counter} posti}}", - "lists.account.add": "Insertez a listo", - "lists.account.remove": "Efacez de listo", "lists.delete": "Efacez listo", "lists.edit": "Modifikez listo", - "lists.edit.submit": "Chanjez titulo", - "lists.exclusive": "Celar ca posti del hemo", - "lists.new.create": "Insertez listo", - "lists.new.title_placeholder": "Nova listotitulo", "lists.replies_policy.followed": "Irga sequita uzanto", "lists.replies_policy.list": "Membro di listo", "lists.replies_policy.none": "Nulu", - "lists.replies_policy.title": "Montrez respondi a:", - "lists.search": "Trovez inter personi quon vu sequas", - "lists.subheading": "Vua listi", "load_pending": "{count, plural, one {# nova kozo} other {# nova kozi}}", "loading_indicator.label": "Kargante…", "media_gallery.hide": "Celez", diff --git a/app/javascript/mastodon/locales/is.json b/app/javascript/mastodon/locales/is.json index 8c87298910..ce4c21e18b 100644 --- a/app/javascript/mastodon/locales/is.json +++ b/app/javascript/mastodon/locales/is.json @@ -87,6 +87,25 @@ "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.most_used_hashtag.none": "Ekkert", + "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.", @@ -121,13 +140,16 @@ "column.blocks": "Útilokaðir notendur", "column.bookmarks": "Bókamerki", "column.community": "Staðvær tímalína", + "column.create_list": "Búa til lista", "column.direct": "Einkaspjall", "column.directory": "Skoða notendasnið", "column.domain_blocks": "Útilokuð lén", + "column.edit_list": "Breyta lista", "column.favourites": "Eftirlæti", "column.firehose": "Bein streymi", "column.follow_requests": "Beiðnir um að fylgjast með", "column.home": "Heim", + "column.list_members": "Sýsla með meðlimi listans", "column.lists": "Listar", "column.mutes": "Þaggaðir notendur", "column.notifications": "Tilkynningar", @@ -273,7 +295,6 @@ "empty_column.hashtag": "Það er ekkert ennþá undir þessu myllumerki.", "empty_column.home": "Heimatímalínan þín er tóm! Fylgstu með fleira fólki til að fylla hana. {suggestions}", "empty_column.list": "Það er ennþá ekki neitt á þessum lista. Þegar meðlimir á listanum senda inn nýjar færslur, munu þær birtast hér.", - "empty_column.lists": "Þú ert ennþá ekki með neina lista. Þegar þú býrð til einhvern lista, munu hann birtast hér.", "empty_column.mutes": "Þú hefur ekki þaggað niður í neinum notendum ennþá.", "empty_column.notification_requests": "Allt hreint! Það er ekkert hér. Þegar þú færð nýjar tilkynningar, munu þær birtast hér í samræmi við stillingarnar þínar.", "empty_column.notifications": "Þú ert ekki ennþá með neinar tilkynningar. Vertu í samskiptum við aðra til að umræður fari af stað.", @@ -446,20 +467,32 @@ "link_preview.author": "Frá {name}", "link_preview.more_from_author": "Meira frá {name}", "link_preview.shares": "{count, plural, one {{counter} færsla} other {{counter} færslur}}", - "lists.account.add": "Bæta á lista", - "lists.account.remove": "Fjarlægja af lista", + "lists.add_member": "Bæta við", + "lists.add_to_list": "Bæta á lista", + "lists.add_to_lists": "Bæta {name} á lista", + "lists.create": "Búa til", + "lists.create_a_list_to_organize": "Búðu til nýjan lista til að skipuleggja heimastreymið þitt", + "lists.create_list": "Búa til lista", "lists.delete": "Eyða lista", + "lists.done": "Lokið", "lists.edit": "Breyta lista", - "lists.edit.submit": "Breyta titli", - "lists.exclusive": "Hylja þessar færslur í heimastreymi", - "lists.new.create": "Bæta við lista", - "lists.new.title_placeholder": "Titill á nýjum lista", + "lists.exclusive": "Fela meðlimi í heimastreyminu", + "lists.exclusive_hint": "Ef einhver er á þessum lista, geturðu falið viðkomandi í heimastreyminu þínu til að komast hjá því að sjá færslurnar þeirra í tvígang.", + "lists.find_users_to_add": "Finndu notendur til að bæta við", + "lists.list_members": "Meðlimir lista", + "lists.list_members_count": "{count, plural, one {# meðlimur} other {# meðlimir}}", + "lists.list_name": "Heiti lista", + "lists.new_list_name": "Heiti á nýjum lista", + "lists.no_lists_yet": "Ennþá engir listar.", + "lists.no_members_yet": "Ennþá engir meðlimir.", + "lists.no_results_found": "Engar niðurstöður fundust.", + "lists.remove_member": "Fjarlægja", "lists.replies_policy.followed": "Allra notenda sem fylgst er með", "lists.replies_policy.list": "Meðlima listans", "lists.replies_policy.none": "Engra", - "lists.replies_policy.title": "Sýna svör til:", - "lists.search": "Leita meðal þeirra sem þú fylgist með", - "lists.subheading": "Listarnir þínir", + "lists.save": "Vista", + "lists.search_placeholder": "Leitaðu að fólki sem þú fylgist með", + "lists.show_replies_to": "Hafa með svör frá meðlimum lista til", "load_pending": "{count, plural, one {# nýtt atriði} other {# ný atriði}}", "loading_indicator.label": "Hleð inn…", "media_gallery.hide": "Fela", @@ -508,6 +541,8 @@ "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", diff --git a/app/javascript/mastodon/locales/it.json b/app/javascript/mastodon/locales/it.json index a692fb7fd3..d947b59eae 100644 --- a/app/javascript/mastodon/locales/it.json +++ b/app/javascript/mastodon/locales/it.json @@ -87,6 +87,22 @@ "alert.unexpected.title": "Oops!", "alt_text_badge.title": "Testo alternativo", "announcement.announcement": "Annuncio", + "annual_report.summary.archetype.oracle": "L'oracolo", + "annual_report.summary.archetype.pollster": "Sondaggista", + "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.most_used_hashtag.none": "Nessuno", + "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.", + "annual_report.summary.thanks": "Grazie per far parte di Mastodon!", "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.", @@ -273,7 +289,6 @@ "empty_column.hashtag": "Non c'è ancora nulla in questo hashtag.", "empty_column.home": "La cronologia della tua home è vuota! Segui altre persone per riempirla. {suggestions}", "empty_column.list": "Non c'è ancora nulla in questo elenco. Quando i membri di questo elenco pubblicheranno nuovi post, appariranno qui.", - "empty_column.lists": "Non hai ancora nessun elenco. Quando ne creerai uno, apparirà qui.", "empty_column.mutes": "Non hai ancora silenziato alcun utente.", "empty_column.notification_requests": "Tutto chiaro! Non c'è niente qui. Quando ricevi nuove notifiche, verranno visualizzate qui in base alle tue impostazioni.", "empty_column.notifications": "Non hai ancora nessuna notifica. Quando altre persone interagiranno con te, le vedrai qui.", @@ -446,20 +461,11 @@ "link_preview.author": "Di {name}", "link_preview.more_from_author": "Altro da {name}", "link_preview.shares": "{count, plural, one {{counter} post} other {{counter} post}}", - "lists.account.add": "Aggiungi all'elenco", - "lists.account.remove": "Rimuovi dall'elenco", "lists.delete": "Elimina elenco", "lists.edit": "Modifica elenco", - "lists.edit.submit": "Cambia il titolo", - "lists.exclusive": "Nascondi questi post dalla home", - "lists.new.create": "Aggiungi lista", - "lists.new.title_placeholder": "Titolo del nuovo elenco", "lists.replies_policy.followed": "Qualsiasi utente seguito", "lists.replies_policy.list": "Membri dell'elenco", "lists.replies_policy.none": "Nessuno", - "lists.replies_policy.title": "Mostra risposte a:", - "lists.search": "Cerca tra le persone che segui", - "lists.subheading": "Le tue liste", "load_pending": "{count, plural, one {# nuovo oggetto} other {# nuovi oggetti}}", "loading_indicator.label": "Caricamento…", "media_gallery.hide": "Nascondi", @@ -508,6 +514,8 @@ "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", diff --git a/app/javascript/mastodon/locales/ja.json b/app/javascript/mastodon/locales/ja.json index 6f319dbb10..1f891b9f90 100644 --- a/app/javascript/mastodon/locales/ja.json +++ b/app/javascript/mastodon/locales/ja.json @@ -87,6 +87,24 @@ "alert.unexpected.title": "エラー!", "alt_text_badge.title": "代替テキスト", "announcement.announcement": "お知らせ", + "annual_report.summary.archetype.booster": "トレンドハンター", + "annual_report.summary.archetype.lurker": "ROM専", + "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": "バー二ーには秘密にしておくよ。", + "annual_report.summary.thanks": "Mastodonの一員になってくれてありがとう!", "attachments_list.unprocessed": "(未処理)", "audio.hide": "音声を閉じる", "block_modal.remote_users_caveat": "このサーバーはあなたのブロックの意思を尊重するように {domain} へ通知します。しかしながら、ブロックの扱い方はサーバーによってさまざまで、相手のサーバーは必ずしもこのブロックを適切に取り扱うものではないことに留意が必要です。また、あなたの公開投稿はサーバーからログアウトすれば誰からも見ることができます。", @@ -273,7 +291,6 @@ "empty_column.hashtag": "このハッシュタグはまだ使われていません。", "empty_column.home": "ホームタイムラインはまだ空っぽです。だれかをフォローして埋めてみましょう。", "empty_column.list": "このリストにはまだなにもありません。このリストのメンバーが新しい投稿をするとここに表示されます。", - "empty_column.lists": "まだリストがありません。リストを作るとここに表示されます。", "empty_column.mutes": "まだ誰もミュートしていません。", "empty_column.notification_requests": "ここに表示するものはありません。新しい通知を受け取ったとき、フィルタリング設定で通知がブロックされたアカウントがある場合はここに表示されます。", "empty_column.notifications": "まだ通知がありません。他の人とふれ合って会話を始めましょう。", @@ -446,20 +463,11 @@ "link_preview.author": "{name}", "link_preview.more_from_author": "{name}さんの投稿をもっと読む", "link_preview.shares": "{count, plural, other {{counter}件の投稿}}", - "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.followed": "フォロー中のユーザー全員", "lists.replies_policy.list": "リストのメンバー", "lists.replies_policy.none": "表示しない", - "lists.replies_policy.title": "リプライを表示:", - "lists.search": "フォローしている人の中から検索", - "lists.subheading": "あなたのリスト", "load_pending": "{count}件の新着", "loading_indicator.label": "読み込み中…", "media_gallery.hide": "隠す", @@ -508,6 +516,8 @@ "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}さんにフォローされました", diff --git a/app/javascript/mastodon/locales/ka.json b/app/javascript/mastodon/locales/ka.json index fc0ed0730d..b38cc0e44a 100644 --- a/app/javascript/mastodon/locales/ka.json +++ b/app/javascript/mastodon/locales/ka.json @@ -145,14 +145,8 @@ "lightbox.close": "დახურვა", "lightbox.next": "შემდეგი", "lightbox.previous": "წინა", - "lists.account.add": "სიაში დამატება", - "lists.account.remove": "სიიდან ამოშლა", "lists.delete": "სიის წაშლა", "lists.edit": "სიის შეცვლა", - "lists.new.create": "სიის დამატება", - "lists.new.title_placeholder": "ახალი სიის სათაური", - "lists.search": "ძებნა ადამიანებს შორის რომელთაც მიჰყვებით", - "lists.subheading": "თქვენი სიები", "navigation_bar.blocks": "დაბლოკილი მომხმარებლები", "navigation_bar.community_timeline": "ლოკალური თაიმლაინი", "navigation_bar.compose": "Compose new toot", diff --git a/app/javascript/mastodon/locales/kab.json b/app/javascript/mastodon/locales/kab.json index 9cf94f2606..74d8e5a194 100644 --- a/app/javascript/mastodon/locales/kab.json +++ b/app/javascript/mastodon/locales/kab.json @@ -219,7 +219,6 @@ "empty_column.hashtag": "Ar tura ulac kra n ugbur yesɛan assaɣ ɣer uhacṭag-agi.", "empty_column.home": "Tasuddemt tagejdant n yisallen d tilemt! Ẓer {public} neɣ nadi ad tafeḍ imseqdacen-nniḍen ad ten-ḍefṛeḍ.", "empty_column.list": "Ar tura ur yelli kra deg umuɣ-a. Ad d-yettwasken da ticki iɛeggalen n wumuɣ-a suffɣen-d kra.", - "empty_column.lists": "Ulac ɣur-k·m kra n wumuɣ yakan. Ad d-tettwasken da ticki tesluleḍ-d yiwet.", "empty_column.mutes": "Ulac ɣur-k·m imseqdacen i yettwasgugmen.", "empty_column.notifications": "Ulac ɣur-k·m alɣuten. Sedmer akked yemdanen-nniḍen akken ad tebduḍ adiwenni.", "empty_column.public": "Ulac kra da! Aru kra, neɣ ḍfeṛ imdanen i yellan deg yiqeddacen-nniḍen akken ad d-teččar tsuddemt tazayezt", @@ -341,20 +340,11 @@ "link_preview.author": "S-ɣur {name}", "link_preview.more_from_author": "Ugar sɣur {name}", "link_preview.shares": "{count, plural, one {{counter} n tsuffeɣt} other {{counter} n tsuffaɣ}}", - "lists.account.add": "Rnu ɣer tebdart", - "lists.account.remove": "Kkes seg tebdart", "lists.delete": "Kkes tabdart", "lists.edit": "Ẓreg tabdart", - "lists.edit.submit": "Beddel azwel", - "lists.exclusive": "Ffer tisuffaɣ-a seg ugejdan", - "lists.new.create": "Rnu tabdart", - "lists.new.title_placeholder": "Azwel amaynut n tebdart", "lists.replies_policy.followed": "Kra n useqdac i yettwaḍefren", "lists.replies_policy.list": "Iɛeggalen n tebdart", "lists.replies_policy.none": "Ula yiwen·t", - "lists.replies_policy.title": "Ssken-d tiririyin i:", - "lists.search": "Nadi gar yemdanen i teṭṭafaṛeḍ", - "lists.subheading": "Tibdarin-ik·im", "load_pending": "{count, plural, one {# n uferdis amaynut} other {# n yiferdisen imaynuten}}", "loading_indicator.label": "Yessalay-d …", "media_gallery.hide": "Seggelmes", diff --git a/app/javascript/mastodon/locales/kk.json b/app/javascript/mastodon/locales/kk.json index f146fc652d..fad2807ffa 100644 --- a/app/javascript/mastodon/locales/kk.json +++ b/app/javascript/mastodon/locales/kk.json @@ -149,7 +149,6 @@ "empty_column.hashtag": "Бұндай хэштегпен әлі ешкім жазбапты.", "empty_column.home": "Әлі ешкімге жазылмапсыз. Бәлкім {public} жазбаларын қарап немесе іздеуді қолданып көрерсіз.", "empty_column.list": "Бұл тізімде ештеңе жоқ.", - "empty_column.lists": "Әзірше ешқандай тізіміңіз жоқ. Біреуін құрғаннан кейін осы жерде көрінетін болады.", "empty_column.mutes": "Әзірше ешқандай үнсізге қойылған қолданушы жоқ.", "empty_column.notifications": "Әзірше ешқандай ескертпе жоқ. Басқалармен араласуды бастаңыз және пікірталастарға қатысыңыз.", "empty_column.public": "Ештеңе жоқ бұл жерде! Өзіңіз бастап жазып көріңіз немесе басқаларға жазылыңыз", @@ -212,15 +211,8 @@ "lightbox.close": "Жабу", "lightbox.next": "Келесі", "lightbox.previous": "Алдыңғы", - "lists.account.add": "Тізімге қосу", - "lists.account.remove": "Тізімнен шығару", "lists.delete": "Тізімді өшіру", "lists.edit": "Тізімді өңдеу", - "lists.edit.submit": "Тақырыбын өзгерту", - "lists.new.create": "Тізім құру", - "lists.new.title_placeholder": "Жаңа тізім аты", - "lists.search": "Сіз іздеген адамдар арасында іздеу", - "lists.subheading": "Тізімдеріңіз", "load_pending": "{count, plural, one {# жаңа нәрсе} other {# жаңа нәрсе}}", "navigation_bar.blocks": "Бұғатталғандар", "navigation_bar.bookmarks": "Бетбелгілер", diff --git a/app/javascript/mastodon/locales/ko.json b/app/javascript/mastodon/locales/ko.json index 3462675e3e..ac19040d3a 100644 --- a/app/javascript/mastodon/locales/ko.json +++ b/app/javascript/mastodon/locales/ko.json @@ -87,6 +87,25 @@ "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.most_used_hashtag.none": "없음", + "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 +132,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": "마스토돈에서 가입", @@ -273,7 +292,6 @@ "empty_column.hashtag": "이 해시태그는 아직 사용되지 않았습니다.", "empty_column.home": "당신의 홈 타임라인은 비어있습니다! 더 많은 사람을 팔로우하여 채워보세요.", "empty_column.list": "리스트에 아직 아무것도 없습니다. 리스트의 누군가가 게시물을 올리면 여기에 나타납니다.", - "empty_column.lists": "아직 리스트가 없습니다. 리스트를 만들면 여기에 나타납니다.", "empty_column.mutes": "아직 아무도 뮤트하지 않았습니다.", "empty_column.notification_requests": "깔끔합니다! 여기엔 아무 것도 없습니다. 알림을 받게 되면 설정에 따라 여기에 나타나게 됩니다.", "empty_column.notifications": "아직 알림이 없습니다. 다른 사람들이 당신에게 반응했을 때, 여기에서 볼 수 있습니다.", @@ -386,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 계정이 없나요?", @@ -397,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} 분", @@ -444,20 +464,11 @@ "link_preview.author": "{name}", "link_preview.more_from_author": "{name} 프로필 보기", "link_preview.shares": "{count, plural, other {{counter} 개의 게시물}}", - "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.followed": "팔로우 한 사용자 누구나", "lists.replies_policy.list": "리스트의 구성원", "lists.replies_policy.none": "모두 제외", - "lists.replies_policy.title": "답글 표시:", - "lists.search": "팔로우 중인 사람들 중에서 찾기", - "lists.subheading": "리스트", "load_pending": "{count, plural, other {#}} 개의 새 항목", "loading_indicator.label": "불러오는 중...", "media_gallery.hide": "숨기기", @@ -506,6 +517,8 @@ "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} 님이 나를 팔로우했습니다", diff --git a/app/javascript/mastodon/locales/ku.json b/app/javascript/mastodon/locales/ku.json index 86ecf98446..d15fbb6762 100644 --- a/app/javascript/mastodon/locales/ku.json +++ b/app/javascript/mastodon/locales/ku.json @@ -190,7 +190,6 @@ "empty_column.hashtag": "Di vê hashtagê de hêj tiştekî tune.", "empty_column.home": "Rojeva demnameya te vala ye! Ji bona tijîkirinê bêtir mirovan bişopîne. {suggestions}", "empty_column.list": "Di vê rêzokê de hîn tiştek tune ye. Gava ku endamên vê rêzokê peyamên nû biweşînin, ew ê li vir xuya bibin.", - "empty_column.lists": "Hîn tu rêzokên te tune ne. Dema yekî çê bikî, ew ê li vir xuya bibe.", "empty_column.mutes": "Te tu bikarhêner bêdeng nekiriye.", "empty_column.notifications": "Hêj hişyariyên te tunene. Dema ku mirovên din bi we re têkilî danîn, hûn ê wê li vir bibînin.", "empty_column.public": "Li vir tiştekî tuneye! Ji raya giştî re tiştekî binivîsîne, an ji bo tijîkirinê ji rajekerên din bikarhêneran bi destan bişopînin", @@ -297,19 +296,11 @@ "lightbox.previous": "Paş", "limited_account_hint.action": "Bi heman awayî profîlê nîşan bide", "limited_account_hint.title": "Profîl ji aliyê rêveberên {domain}ê ve hatiye veşartin.", - "lists.account.add": "Li lîsteyê zêde bike", - "lists.account.remove": "Ji lîsteyê rake", "lists.delete": "Lîsteyê jê bibe", "lists.edit": "Lîsteyê serrast bike", - "lists.edit.submit": "Sernavê biguherîne", - "lists.new.create": "Li lîsteyê zêde bike", - "lists.new.title_placeholder": "Sernavê lîsteya nû", "lists.replies_policy.followed": "Bikarhênereke şopandî", "lists.replies_policy.list": "Endamên lîsteyê", "lists.replies_policy.none": "Ne yek", - "lists.replies_policy.title": "Bersivan nîşan bide:", - "lists.search": "Di navbera kesên ku te dişopînin bigere", - "lists.subheading": "Lîsteyên te", "load_pending": "{count, plural, one {# hêmaneke nû} other {#hêmaneke nû}}", "moved_to_account_banner.text": "Ajimêrê te {disabledAccount} niha neçalak e ji ber ku te bar kir bo {movedToAccount}.", "navigation_bar.about": "Derbar", diff --git a/app/javascript/mastodon/locales/kw.json b/app/javascript/mastodon/locales/kw.json index cef24aa3b7..49f8149f65 100644 --- a/app/javascript/mastodon/locales/kw.json +++ b/app/javascript/mastodon/locales/kw.json @@ -131,7 +131,6 @@ "empty_column.hashtag": "Nyns eus travyth y'n bòlnos ma hwath.", "empty_column.home": "Agas amserlin dre yw gwag! Holyewgh moy a dus dh'y lenwel. {suggestions}", "empty_column.list": "Nyns eus travyth y'n rol ma hwath. Pan wra eseli an rol ma dyllo postow nowydh, i a wra omdhiskwedhes omma.", - "empty_column.lists": "Nyns eus dhywgh rolyow hwath. Pan wrewgh onan, hi a wra omdhiskwedhes omma.", "empty_column.mutes": "Ny wrussowgh tawhe devnydhyoryon vyth hwath.", "empty_column.notifications": "Nyns eus dhywgh gwarnyansow hwath. Pan wra tus erel ynterweythresa genowgh, hwi a'n gwel omma.", "empty_column.public": "Nyns eus travyth omma! Skrifewgh neppyth yn poblek, po holyewgh tus a leurennow erel dre leuv dh'y lenwel", @@ -197,19 +196,11 @@ "lightbox.close": "Degea", "lightbox.next": "Nessa", "lightbox.previous": "Kynsa", - "lists.account.add": "Keworra dhe rol", - "lists.account.remove": "Removya a rol", "lists.delete": "Dilea rol", "lists.edit": "Golegi rol", - "lists.edit.submit": "Chanjya titel", - "lists.new.create": "Keworra rol", - "lists.new.title_placeholder": "Titel rol nowydh", "lists.replies_policy.followed": "Py devnydhyer holys pynag", "lists.replies_policy.list": "Eseli an rol", "lists.replies_policy.none": "Nagonan", - "lists.replies_policy.title": "Diskwedhes gorthebow orth:", - "lists.search": "Hwilas yn-mysk tus a holyewgh", - "lists.subheading": "Agas rolyow", "load_pending": "{count, plural, one {# daklennowydh} other {# a daklennow nowydh}}", "navigation_bar.blocks": "Devnydhyoryon lettys", "navigation_bar.bookmarks": "Folennosow", diff --git a/app/javascript/mastodon/locales/la.json b/app/javascript/mastodon/locales/la.json index 55678dbdf8..fc36d89272 100644 --- a/app/javascript/mastodon/locales/la.json +++ b/app/javascript/mastodon/locales/la.json @@ -81,7 +81,6 @@ "empty_column.followed_tags": "Nōn adhūc aliquem hastāginem secūtus es. Cum id fēceris, hic ostendētur.", "empty_column.home": "Tua linea temporum domesticus vacua est! Sequere plures personas ut eam compleas.", "empty_column.list": "There is nothing in this list yet. When members of this list post new statuses, they will appear here.", - "empty_column.lists": "Nōn adhūc habēs ullo tabellās. Cum creās, hīc apparēbunt.", "empty_column.mutes": "Nondum quemquam usorem tacuisti.", "empty_column.notification_requests": "Omnia clara sunt! Nihil hic est. Cum novās notificātiōnēs accipīs, hic secundum tua praecepta apparebunt.", "empty_column.notifications": "Nōn adhūc habēs ullo notificātiōnēs. Cum aliī tē interagunt, hīc videbis.", @@ -138,9 +137,6 @@ "keyboard_shortcuts.up": "to move up in the list", "lightbox.close": "Claudere", "lightbox.next": "Secundum", - "lists.account.add": "Adde ad tabellās", - "lists.new.create": "Addere tabella", - "lists.subheading": "Tuae tabulae", "load_pending": "{count, plural, one {# novum item} other {# nova itema}}", "moved_to_account_banner.text": "Tua ratione {disabledAccount} interdum reposita est, quod ad {movedToAccount} migrāvisti.", "mute_modal.you_wont_see_mentions": "Non videbis nuntios quī eōs commemorant.", diff --git a/app/javascript/mastodon/locales/lad.json b/app/javascript/mastodon/locales/lad.json index 563eb3b190..9f4f6e6cb9 100644 --- a/app/javascript/mastodon/locales/lad.json +++ b/app/javascript/mastodon/locales/lad.json @@ -87,6 +87,17 @@ "alert.unexpected.title": "Atyo!", "alt_text_badge.title": "Teksto alternativo", "announcement.announcement": "Pregon", + "annual_report.summary.archetype.pollster": "El anketero", + "annual_report.summary.followers.followers": "suivantes", + "annual_report.summary.highlighted_post.by_favourites": "la puvlikasyon mas favoritada", + "annual_report.summary.highlighted_post.by_reblogs": "la puvlikasyon mas repartajada", + "annual_report.summary.highlighted_post.by_replies": "la puvlikasyon kon mas repuestas", + "annual_report.summary.highlighted_post.possessive": "de {name}", + "annual_report.summary.most_used_app.most_used_app": "la aplikasyon mas uzada", + "annual_report.summary.most_used_hashtag.most_used_hashtag": "la etiketa mas uzada", + "annual_report.summary.most_used_hashtag.none": "Dinguno", + "annual_report.summary.new_posts.new_posts": "puvlikasyones muevas", + "annual_report.summary.thanks": "Mersi por ser parte de Mastodon!", "attachments_list.unprocessed": "(no prosesado)", "audio.hide": "Eskonde audio", "block_modal.show_less": "Amostra manko", @@ -97,6 +108,7 @@ "block_modal.you_wont_see_mentions": "No veras publikasyones ke lo enmentan.", "boost_modal.combo": "Puedes klikar {combo} para ometer esto la proksima vez", "boost_modal.reblog": "Repartajar puvlikasyon?", + "boost_modal.undo_reblog": "Departajar puvlikasyon?", "bundle_column_error.copy_stacktrace": "Kopia el raporto de yerro", "bundle_column_error.error.body": "La pajina solisitada no pudo ser renderada. Podria ser por un yerro en muestro kodiche o un problem de kompatibilita kon el navigador.", "bundle_column_error.error.title": "Atyo, no!", @@ -155,6 +167,7 @@ "compose_form.poll.duration": "Durasion de anketa", "compose_form.poll.multiple": "Multiples opsyones", "compose_form.poll.option_placeholder": "Opsyon {number}", + "compose_form.poll.single": "Opsyon unika", "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", @@ -213,6 +226,7 @@ "dismissable_banner.public_timeline": "Estas son las publikasyones publikas mas resientes de personas en la red sosyala a las kualas la djente de {domain} sige.", "domain_block_modal.block": "Bloka sirvidor", "domain_block_modal.block_account_instead": "Bloka @{name} en su lugar", + "domain_block_modal.they_can_interact_with_old_posts": "Las personas de este sirvidor pueden enteraktuar kon tus puvlikasyones viejas.", "domain_block_modal.they_cant_follow": "Dingun de este sirvidor puede segirte.", "domain_block_modal.they_wont_know": "No savra ke tiene sido blokado.", "domain_block_modal.title": "Bloka el domeno?", @@ -256,7 +270,6 @@ "empty_column.hashtag": "Ainda no ay niente en esta etiketa.", "empty_column.home": "Tu linya de tiempo esta vaziya! Sige a mas personas para inchirla.", "empty_column.list": "Ainda no ay niente en esta lista. Kuando miembros de esta lista publiken muevas publikasyones, se amostraran aki.", - "empty_column.lists": "Ainda no tienes dinguna lista. Kuando kriyes una, aperesera aki.", "empty_column.mutes": "Ainda no tienes silensiado a dingun utilizador.", "empty_column.notifications": "Ainda no tienes dingun avizo. Kuando otras personas enteraktuen kontigo, se amostraran aki.", "empty_column.public": "No ay niente aki! Eskrive algo publikamente o manualmente sige utilizadores de otros sirvidores para inchirlo", @@ -307,6 +320,7 @@ "follow_suggestions.personalized_suggestion": "Sujestion personalizada", "follow_suggestions.popular_suggestion": "Sujestion populara", "follow_suggestions.popular_suggestion_longer": "Popular en {domain}", + "follow_suggestions.similar_to_recently_followed_longer": "Similares a los profils ke tienes segido resyentemente", "follow_suggestions.view_all": "Ve todos", "follow_suggestions.who_to_follow": "A ken segir", "followed_tags": "Etiketas segidas", @@ -335,6 +349,9 @@ "hashtag.follow": "Sige etiketa", "hashtag.unfollow": "Desige etiketa", "hashtags.and_other": "…i {count, plural, one {}other {# mas}}", + "hints.profiles.followers_may_be_missing": "Puede ser ke algunos suivantes de este profil no se amostren.", + "hints.profiles.follows_may_be_missing": "Puede ser ke algunos kuentos segidos por este profil no se amostren.", + "hints.profiles.posts_may_be_missing": "Puede ser ke algunas puvlikasyones de este profil no se amostren.", "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}", @@ -352,10 +369,12 @@ "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?", + "ignore_notifications_modal.private_mentions_title": "Ignorar avizos de mensyones privadas no solisitadas?", "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.", "interaction_modal.description.reply": "Kon un kuento en Mastodon, puedes arispondir a esta publikasyon.", + "interaction_modal.description.vote": "Kon un kuento en Mastodon, puedes votar en esta anketa.", "interaction_modal.login.action": "Va a tu sirvidor", "interaction_modal.login.prompt": "Domeno del sirvidor de tu kuento, por enshemplo mastodon.social", "interaction_modal.no_account_yet": "No tyenes kuento de Mastodon?", @@ -367,6 +386,7 @@ "interaction_modal.title.follow": "Sige a {name}", "interaction_modal.title.reblog": "Repartaja publikasyon de {name}", "interaction_modal.title.reply": "Arisponde a publikasyon de {name}", + "interaction_modal.title.vote": "Vota en la anketa de {name}", "intervals.full.days": "{number, plural, one {# diya} other {# diyas}}", "intervals.full.hours": "{number, plural, one {# ora} other {# oras}}", "intervals.full.minutes": "{number, plural, one {# minuto} other {# minutos}}", @@ -412,20 +432,11 @@ "link_preview.author": "Publikasyon de {name}", "link_preview.more_from_author": "Mas de {name}", "link_preview.shares": "{count, plural, one {{counter} publikasyon} other {{counter} publikasyones}}", - "lists.account.add": "Adjusta a lista", - "lists.account.remove": "Kita de lista", "lists.delete": "Efasa lista", "lists.edit": "Edita lista", - "lists.edit.submit": "Troka titolo", - "lists.exclusive": "Eskonder estas publikasyones de linya prinsipala", - "lists.new.create": "Adjusta lista", - "lists.new.title_placeholder": "Titolo de mueva lista", "lists.replies_policy.followed": "Kualseker utilizador segido", "lists.replies_policy.list": "Miembros de la lista", "lists.replies_policy.none": "Dinguno", - "lists.replies_policy.title": "Amostra repuestas a:", - "lists.search": "Bushka entre personas a las kualas siges", - "lists.subheading": "Tus listas", "load_pending": "{count, plural, one {# muevo elemento} other {# muevos elementos}}", "loading_indicator.label": "Eskargando…", "media_gallery.hide": "Eskonde", @@ -466,13 +477,16 @@ "navigation_bar.security": "Segurita", "not_signed_in_indicator.not_signed_in": "Nesesitas konektarse kon tu kuento para akseder este rekurso.", "notification.admin.report": "{name} raporto {target}", + "notification.admin.report_statuses": "{name} raporto {target} por {category}", "notification.admin.report_statuses_other": "{name} raporto {target}", "notification.admin.sign_up": "{name} kriyo un konto", + "notification.annual_report.view": "Ve #Wrapstodon", "notification.favourite": "A {name} le plaze tu publikasyon", "notification.follow": "{name} te ampeso a segir", "notification.follow_request": "{name} tiene solisitado segirte", "notification.label.mention": "Enmenta", "notification.label.private_mention": "Enmentadura privada", + "notification.label.private_reply": "Repuesta privada", "notification.label.reply": "Arisponde", "notification.mention": "Enmenta", "notification.mentioned_you": "{name} te enmento", @@ -536,6 +550,7 @@ "notifications.policy.accept_hint": "Amostra en avizos", "notifications.policy.drop": "Inyora", "notifications.policy.filter": "Filtra", + "notifications.policy.filter_limited_accounts_hint": "Limitadas por moderadores del sirvidor", "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", diff --git a/app/javascript/mastodon/locales/lt.json b/app/javascript/mastodon/locales/lt.json index 7d53c2702f..f9080f96e5 100644 --- a/app/javascript/mastodon/locales/lt.json +++ b/app/javascript/mastodon/locales/lt.json @@ -69,7 +69,7 @@ "account.unendorse": "Nerodyti profilyje", "account.unfollow": "Nebesekti", "account.unmute": "Atšaukti nutildymą @{name}", - "account.unmute_notifications_short": "Atšaukti nutildymą pranešimams", + "account.unmute_notifications_short": "Atšaukti pranešimų nutildymą", "account.unmute_short": "Atšaukti nutildymą", "account_note.placeholder": "Spustelėk, kad pridėtum pastabą.", "admin.dashboard.daily_retention": "Naudotojų pasilikimo rodiklis pagal dieną po registracijos", @@ -87,6 +87,25 @@ "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.most_used_hashtag.none": "Nieko", + "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.", @@ -121,13 +140,16 @@ "column.blocks": "Užblokuoti naudotojai", "column.bookmarks": "Žymės", "column.community": "Vietinė laiko skalė", + "column.create_list": "Kurti sąrašą", "column.direct": "Privatūs paminėjimai", "column.directory": "Naršyti profilius", "column.domain_blocks": "Užblokuoti serveriai", + "column.edit_list": "Redaguoti sąrašą", "column.favourites": "Mėgstami", "column.firehose": "Tiesioginiai srautai", "column.follow_requests": "Sekimo prašymai", "column.home": "Pagrindinis", + "column.list_members": "Tvarkyti sąrašo narius", "column.lists": "Sąrašai", "column.mutes": "Nutildyti naudotojai", "column.notifications": "Pranešimai", @@ -273,7 +295,6 @@ "empty_column.hashtag": "Nėra nieko šiame saitažodyje kol kas.", "empty_column.home": "Tavo pagrindinio laiko skalė tuščia. Sek daugiau žmonių, kad ją užpildytum.", "empty_column.list": "Nėra nieko šiame sąraše kol kas. Kai šio sąrašo nariai paskelbs naujų įrašų, jie bus rodomi čia.", - "empty_column.lists": "Dar neturi jokių sąrašų. Kai jį sukursi, jis bus rodomas čia.", "empty_column.mutes": "Dar nesi nutildęs (-usi) nė vieno naudotojo.", "empty_column.notification_requests": "Viskas švaru! Čia nieko nėra. Kai gausi naujų pranešimų, jie bus rodomi čia pagal tavo nustatymus.", "empty_column.notifications": "Dar neturi jokių pranešimų. Kai kiti žmonės su tavimi sąveikaus, matysi tai čia.", @@ -446,20 +467,32 @@ "link_preview.author": "Sukūrė {name}", "link_preview.more_from_author": "Daugiau iš {name}", "link_preview.shares": "{count, plural, one {{counter} įrašas} few {{counter} įrašai} many {{counter} įrašo} other {{counter} įrašų}}", - "lists.account.add": "Pridėti į sąrašą", - "lists.account.remove": "Pašalinti iš sąrašo", + "lists.add_member": "Pridėti", + "lists.add_to_list": "Pridėti į sąrašą", + "lists.add_to_lists": "Pridėti {name} į sąrašą", + "lists.create": "Kurti", + "lists.create_a_list_to_organize": "Sukurkite naują sąrašą, kad sutvarkytumėte pagrindinį srautą", + "lists.create_list": "Kurti sąrašą", "lists.delete": "Ištrinti sąrašą", + "lists.done": "Atlikta", "lists.edit": "Redaguoti sąrašą", - "lists.edit.submit": "Keisti pavadinimą", - "lists.exclusive": "Slėpti šiuos įrašus iš pagrindinio", - "lists.new.create": "Pridėti sąrašą", - "lists.new.title_placeholder": "Naujas sąrašo pavadinimas", + "lists.exclusive": "Slėpti narius pagrindiniame", + "lists.exclusive_hint": "Jei kas nors yra šiame sąraše, paslėpkite juos pagrindinio srauto laiko skalėje, kad nematytumėte jų įrašus dukart.", + "lists.find_users_to_add": "Raskite naudotojų, kurių pridėti", + "lists.list_members": "Sąrašo nariai", + "lists.list_members_count": "{count, plural, one {# narys} few {# nariai} many {# nario} other {# narių}}", + "lists.list_name": "Sąrašo pavadinimas", + "lists.new_list_name": "Naujas sąrašo pavadinimas", + "lists.no_lists_yet": "Kol kas nėra sąrašų.", + "lists.no_members_yet": "Kol kas nėra narių.", + "lists.no_results_found": "Rezultatų nerasta.", + "lists.remove_member": "Šalinti", "lists.replies_policy.followed": "Bet kuriam sekamam naudotojui", "lists.replies_policy.list": "Sąrašo nariams", "lists.replies_policy.none": "Nei vienam", - "lists.replies_policy.title": "Rodyti atsakymus:", - "lists.search": "Ieškoti tarp sekamų žmonių", - "lists.subheading": "Tavo sąrašai", + "lists.save": "Išsaugoti", + "lists.search_placeholder": "Ieškokite asmenų, kuriuos sekate", + "lists.show_replies_to": "Įtraukti atsakymus iš sąrašo narių į", "load_pending": "{count, plural, one {# naujas elementas} few {# nauji elementai} many {# naujo elemento} other {# naujų elementų}}", "loading_indicator.label": "Kraunama…", "media_gallery.hide": "Slėpti", @@ -507,6 +540,9 @@ "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.admin.sign_up.name_and_others": "{name} ir {count, plural, one {# kitas} few {# kiti} many {# kito} other {# kitų}} 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", @@ -516,6 +552,7 @@ "notification.label.private_reply": "Privatus atsakymas", "notification.label.reply": "Atsakymas", "notification.mention": "Paminėjimas", + "notification.mentioned_you": "{name} paminėjo jus", "notification.moderation-warning.learn_more": "Sužinoti daugiau", "notification.moderation_warning": "Gavai prižiūrėjimo įspėjimą", "notification.moderation_warning.action_delete_statuses": "Kai kurie tavo įrašai buvo pašalintos.", diff --git a/app/javascript/mastodon/locales/lv.json b/app/javascript/mastodon/locales/lv.json index d7507ee884..542231f05f 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", @@ -84,6 +86,14 @@ "alert.unexpected.message": "Radās negaidīta kļūda.", "alert.unexpected.title": "Ups!", "announcement.announcement": "Paziņojums", + "annual_report.summary.followers.followers": "sekotāji", + "annual_report.summary.followers.total": "pavisam {count}", + "annual_report.summary.here_it_is": "Šeit ir {year}. gada pārskats:", + "annual_report.summary.highlighted_post.possessive": "{name}", + "annual_report.summary.most_used_app.most_used_app": "visizmantotākā lietotne", + "annual_report.summary.most_used_hashtag.most_used_hashtag": "visizmantotākais tēmturis", + "annual_report.summary.most_used_hashtag.none": "Nav", + "annual_report.summary.new_posts.new_posts": "jauni ieraksti", "attachments_list.unprocessed": "(neapstrādāti)", "audio.hide": "Slēpt audio", "block_modal.remote_users_caveat": "Mēs vaicāsim serverim {domain} ņemt vērā Tavu lēmumu. Tomēr atbilstība nav nodrošināta, jo atsevišķi serveri var apstrādāt bloķēšanu citādi. Publiski ieraksti joprojām var būt redzami lietotājiem, kuri nav pieteikušies.", @@ -191,6 +201,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", @@ -211,6 +222,7 @@ "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?", @@ -250,7 +262,6 @@ "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.", - "empty_column.lists": "Pašlaik Tev nav neviena saraksta. Kad tādu izveidosi, tas parādīsies šeit.", "empty_column.mutes": "Neviens lietotājs vēl nav apklusināts.", "empty_column.notifications": "Tev vēl nav paziņojumu. Kad citi cilvēki ar Tevi mijiedarbosies, Tu to redzēsi šeit.", "empty_column.public": "Šeit nekā nav. Ieraksti kaut ko publiski vai seko lietotājiem no citiem serveriem, lai iegūtu saturu", @@ -321,7 +332,11 @@ "hashtag.follow": "Sekot tēmturim", "hashtag.unfollow": "Pārstāt sekot tēmturim", "hashtags.and_other": "… un {count, plural, other {vēl #}}", + "hints.profiles.see_more_followers": "Skatīt vairāk sekotāju {domain}", + "hints.profiles.see_more_follows": "Skatīt vairāk sekojumu {domain}", + "hints.profiles.see_more_posts": "Skatīt vairāk ierakstu {domain}", "hints.threads.replies_may_be_missing": "Var trūkt atbildes no citiem serveriem.", + "hints.threads.see_more": "Skatīt vairāk atbilžu {domain}", "home.column_settings.show_reblogs": "Rādīt pastiprinātos ierakstus", "home.column_settings.show_replies": "Rādīt atbildes", "home.hide_announcements": "Slēpt paziņojumus", @@ -329,6 +344,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.", @@ -388,20 +404,11 @@ "limited_account_hint.title": "{domain} moderatori ir paslēpuši šo profilu.", "link_preview.author": "Pēc {name}", "link_preview.more_from_author": "Vairāk no {name}", - "lists.account.add": "Pievienot sarakstam", - "lists.account.remove": "Noņemt no saraksta", "lists.delete": "Izdzēst sarakstu", "lists.edit": "Labot sarakstu", - "lists.edit.submit": "Mainīt virsrakstu", - "lists.exclusive": "Nerādīt šos ierakstus sākumā", - "lists.new.create": "Pievienot sarakstu", - "lists.new.title_placeholder": "Jaunā saraksta nosaukums", "lists.replies_policy.followed": "Jebkuram sekotajam lietotājam", "lists.replies_policy.list": "Saraksta dalībniekiem", "lists.replies_policy.none": "Nevienam", - "lists.replies_policy.title": "Rādīt atbildes:", - "lists.search": "Meklēt starp cilvēkiem, kuriem tu seko", - "lists.subheading": "Tavi saraksti", "load_pending": "{count, plural, one {# jauna lieta} other {# jaunas lietas}}", "loading_indicator.label": "Ielādē…", "media_gallery.hide": "Paslēpt", @@ -505,10 +512,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", @@ -526,7 +533,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", diff --git a/app/javascript/mastodon/locales/ml.json b/app/javascript/mastodon/locales/ml.json index b7a2ad2a3f..de4f565a5f 100644 --- a/app/javascript/mastodon/locales/ml.json +++ b/app/javascript/mastodon/locales/ml.json @@ -275,17 +275,9 @@ "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": "ബുക്ക്മാർക്കുകൾ", diff --git a/app/javascript/mastodon/locales/mr.json b/app/javascript/mastodon/locales/mr.json index aa8169616e..363269541b 100644 --- a/app/javascript/mastodon/locales/mr.json +++ b/app/javascript/mastodon/locales/mr.json @@ -173,19 +173,11 @@ "lightbox.previous": "मागील", "limited_account_hint.action": "तरीही प्रोफाइल दाखवा", "limited_account_hint.title": "हे प्रोफाइल {domain} च्या नियंत्रकांनी लपवले आहे.", - "lists.account.add": "यादीमध्ये जोडा", - "lists.account.remove": "यादीमधून काढा", "lists.delete": "सूची हटवा", "lists.edit": "सूची संपादित करा", - "lists.edit.submit": "शीर्षक बदला", - "lists.new.create": "यादी जोडा", - "lists.new.title_placeholder": "नवीन सूची शीर्षक", "lists.replies_policy.followed": "कोणताही फॉलो केलेला वापरकर्ता", "lists.replies_policy.list": "यादीतील सदस्य", "lists.replies_policy.none": "कोणीच नाही", - "lists.replies_policy.title": "यांना उत्तरे दाखवा:", - "lists.search": "तुम्ही फॉलो करत असलेल्या लोकांमध्ये शोधा", - "lists.subheading": "तुमच्या याद्या", "load_pending": "{count, plural, one {# new item} other {# new items}}", "navigation_bar.compose": "Compose new toot", "navigation_bar.domain_blocks": "Hidden domains", diff --git a/app/javascript/mastodon/locales/ms.json b/app/javascript/mastodon/locales/ms.json index 9dea731397..f2af798d4e 100644 --- a/app/javascript/mastodon/locales/ms.json +++ b/app/javascript/mastodon/locales/ms.json @@ -229,7 +229,6 @@ "empty_column.hashtag": "Belum ada apa-apa dengan tanda pagar ini.", "empty_column.home": "Garis masa laman utama anda kosong! Ikuti lebih ramai orang untuk mengisinya. {suggestions}", "empty_column.list": "Tiada apa-apa di senarai ini lagi. Apabila ahli senarai ini menerbitkan hantaran baharu, ia akan dipaparkan di sini.", - "empty_column.lists": "Anda belum ada sebarang senarai. Apabila anda menciptanya, ia akan muncul di sini.", "empty_column.mutes": "Anda belum membisukan sesiapa.", "empty_column.notifications": "Anda belum ada sebarang pemberitahuan. Apabila orang lain berinteraksi dengan anda, ia akan muncul di sini.", "empty_column.public": "Tiada apa-apa di sini! Tulis sesuatu secara awam, atau ikuti pengguna daripada pelayan lain secara manual untuk mengisinya", @@ -366,20 +365,11 @@ "limited_account_hint.action": "Paparkan profil", "limited_account_hint.title": "Profil ini telah disembunyikan oleh moderator {domain}.", "link_preview.author": "Dengan {name}", - "lists.account.add": "Tambah ke senarai", - "lists.account.remove": "Buang daripada senarai", "lists.delete": "Padam senarai", "lists.edit": "Sunting senarai", - "lists.edit.submit": "Ubah tajuk", - "lists.exclusive": "Sembunyikan pos ini dari rumah", - "lists.new.create": "Tambah senarai", - "lists.new.title_placeholder": "Tajuk senarai baharu", "lists.replies_policy.followed": "Sesiapa yang diikuti", "lists.replies_policy.list": "Ahli-ahli dalam senarai", "lists.replies_policy.none": "Tiada sesiapa", - "lists.replies_policy.title": "Tunjukkan balasan kepada:", - "lists.search": "Cari dalam kalangan orang yang anda ikuti", - "lists.subheading": "Senarai anda", "load_pending": "{count, plural, one {# item baharu} other {# item baharu}}", "loading_indicator.label": "Memuatkan…", "moved_to_account_banner.text": "Akaun anda {disabledAccount} kini dinyahdayakan kerana anda berpindah ke {movedToAccount}.", diff --git a/app/javascript/mastodon/locales/my.json b/app/javascript/mastodon/locales/my.json index c97de73335..a82e56e6f2 100644 --- a/app/javascript/mastodon/locales/my.json +++ b/app/javascript/mastodon/locales/my.json @@ -215,7 +215,6 @@ "empty_column.hashtag": "ဤ hashtag တွင် မည်သည့်အရာမျှ မရှိသေးပါ။", "empty_column.home": "သင့်ပင်မစာမျက်နှာမှာ အလွတ်ဖြစ်နေပါသည်။ ဖြည့်ရန်အတွက် လူများကို စောင့်ကြည့်ပါ {suggestions}", "empty_column.list": "There is nothing in this list yet. When members of this list post new statuses, they will appear here.", - "empty_column.lists": "သင့်တွင် List မရှိသေးပါ။ List အသစ်ဖွင့်လျှင် ဤနေရာတွင်ကြည့်ရှုနိုင်မည်", "empty_column.mutes": "ပိတ်ထားသောအကောင့်များမရှိသေးပါ", "empty_column.notifications": "သတိပေးချက်မရှိသေးပါ။ သတိပေးချက်အသစ်ရှိလျှင် ဤနေရာတွင်ကြည့်ရှုနိုင်သည်", "empty_column.public": "ဤနေရာတွင် မည်သည့်အရာမျှမရှိပါ။ တစ်ခုခုရေးပါ သို့မဟုတ် ဖြည့်စွက်ရန်အတွက် အခြားဆာဗာ အသုံးပြုသူများကို စောင့်ကြည့်ပါ။", @@ -344,20 +343,11 @@ "limited_account_hint.action": "ဘာပဲဖြစ်ဖြစ် ပရိုဖိုင်ကို ပြပါ", "limited_account_hint.title": "ဤပရိုဖိုင်ကို {domain} ၏ စိစစ်သူများမှ ဖျောက်ထားသည်။", "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.followed": "မည်သည့်စောင့်ကြည့်သူမဆို", "lists.replies_policy.list": "စာရင်းထဲမှ အဖွဲ့ဝင်များ", "lists.replies_policy.none": "တစ်ယောက်မှမရှိပါ", - "lists.replies_policy.title": "ပြန်စာများကို ပြရန် -", - "lists.search": "မိမိဖောလိုးထားသူများမှရှာဖွေမည်", - "lists.subheading": "သင့်၏စာရင်းများ", "load_pending": "{count, plural, one {# new item} other {# new items}}", "loading_indicator.label": "လုပ်ဆောင်နေသည်…", "moved_to_account_banner.text": "{movedToAccount} အကောင့်သို့ပြောင်းလဲထားသဖြင့် {disabledAccount} အကောင့်မှာပိတ်ထားသည်", diff --git a/app/javascript/mastodon/locales/nl.json b/app/javascript/mastodon/locales/nl.json index 9f265782e1..1828fc8f02 100644 --- a/app/javascript/mastodon/locales/nl.json +++ b/app/javascript/mastodon/locales/nl.json @@ -87,6 +87,25 @@ "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.most_used_hashtag.none": "Geen", + "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.", @@ -121,13 +140,16 @@ "column.blocks": "Geblokkeerde gebruikers", "column.bookmarks": "Bladwijzers", "column.community": "Lokale tijdlijn", + "column.create_list": "Lijst aanmaken", "column.direct": "Privéberichten", "column.directory": "Gebruikersgids", "column.domain_blocks": "Geblokkeerde servers", + "column.edit_list": "Lijst bewerken", "column.favourites": "Favorieten", "column.firehose": "Openbare tijdlijnen", "column.follow_requests": "Volgverzoeken", "column.home": "Start", + "column.list_members": "Lijstleden beheren", "column.lists": "Lijsten", "column.mutes": "Genegeerde gebruikers", "column.notifications": "Meldingen", @@ -273,7 +295,6 @@ "empty_column.hashtag": "Er is nog niks te vinden onder deze hashtag.", "empty_column.home": "Deze tijdlijn is leeg! Volg meer mensen om het te vullen.", "empty_column.list": "Er is nog niks te zien in deze lijst. Wanneer lijstleden nieuwe berichten plaatsen, zijn deze hier te zien.", - "empty_column.lists": "Je hebt nog geen lijsten. Wanneer je er een aanmaakt, valt dat hier te zien.", "empty_column.mutes": "Jij hebt nog geen gebruikers genegeerd.", "empty_column.notification_requests": "Helemaal leeg! Er is hier niets. Wanneer je nieuwe meldingen ontvangt, verschijnen deze hier volgens jouw instellingen.", "empty_column.notifications": "Je hebt nog geen meldingen. Begin met iemand een gesprek.", @@ -446,20 +467,32 @@ "link_preview.author": "Door {name}", "link_preview.more_from_author": "Meer van {name}", "link_preview.shares": "{count, plural, one {{counter} bericht} other {{counter} berichten}}", - "lists.account.add": "Aan lijst toevoegen", - "lists.account.remove": "Uit lijst verwijderen", + "lists.add_member": "Toevoegen", + "lists.add_to_list": "Aan lijst toevoegen", + "lists.add_to_lists": "{name} aan lijsten toevoegen", + "lists.create": "Aanmaken", + "lists.create_a_list_to_organize": "Maak een nieuwe lijst aan om je Startpagina te organiseren", + "lists.create_list": "Lijst aanmaken", "lists.delete": "Lijst verwijderen", + "lists.done": "Klaar", "lists.edit": "Lijst bewerken", - "lists.edit.submit": "Titel veranderen", - "lists.exclusive": "Verberg lijstleden op je starttijdlijn", - "lists.new.create": "Lijst toevoegen", - "lists.new.title_placeholder": "Naam nieuwe lijst", + "lists.exclusive": "Leden op je Startpagina verbergen", + "lists.exclusive_hint": "Als iemand op deze lijst staat, verberg hem dan op je Startpagina om te voorkomen dat zijn berichten twee keer worden getoond.", + "lists.find_users_to_add": "Vind gebruikers om toe te voegen", + "lists.list_members": "Lijstleden", + "lists.list_members_count": "{count, plural, one{# lid} other{# leden}}", + "lists.list_name": "Lijstnaam", + "lists.new_list_name": "Nieuwe lijstnaam", + "lists.no_lists_yet": "Nog geen lijsten.", + "lists.no_members_yet": "Nog geen leden.", + "lists.no_results_found": "Geen resultaten gevonden.", + "lists.remove_member": "Verwijderen", "lists.replies_policy.followed": "Elke gevolgde gebruiker", "lists.replies_policy.list": "Leden van de lijst", "lists.replies_policy.none": "Niemand", - "lists.replies_policy.title": "Toon reacties aan:", - "lists.search": "Zoek naar mensen die je volgt", - "lists.subheading": "Jouw lijsten", + "lists.save": "Opslaan", + "lists.search_placeholder": "Zoek mensen die je volgt", + "lists.show_replies_to": "Voeg antwoorden van lijstleden toe aan", "load_pending": "{count, plural, one {# nieuw item} other {# nieuwe items}}", "loading_indicator.label": "Laden…", "media_gallery.hide": "Verberg", @@ -508,6 +541,8 @@ "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", diff --git a/app/javascript/mastodon/locales/nn.json b/app/javascript/mastodon/locales/nn.json index cc56754193..440387e1a9 100644 --- a/app/javascript/mastodon/locales/nn.json +++ b/app/javascript/mastodon/locales/nn.json @@ -87,6 +87,25 @@ "alert.unexpected.title": "Oi sann!", "alt_text_badge.title": "Alternativ tekst", "announcement.announcement": "Kunngjering", + "annual_report.summary.archetype.booster": "Den som jaktar på noko kult", + "annual_report.summary.archetype.lurker": "Den som heng på hjørnet", + "annual_report.summary.archetype.oracle": "Orakelet", + "annual_report.summary.archetype.pollster": "Meiningsmålaren", + "annual_report.summary.archetype.replier": "Den sosiale sumarfuglen", + "annual_report.summary.followers.followers": "fylgjarar", + "annual_report.summary.followers.total": "{count} i alt", + "annual_report.summary.here_it_is": "Her er eit gjensyn med {year}:", + "annual_report.summary.highlighted_post.by_favourites": "det mest omtykte innlegget", + "annual_report.summary.highlighted_post.by_reblogs": "det mest framheva innlegget", + "annual_report.summary.highlighted_post.by_replies": "innlegget med flest svar", + "annual_report.summary.highlighted_post.possessive": "som {name} laga", + "annual_report.summary.most_used_app.most_used_app": "mest brukte app", + "annual_report.summary.most_used_hashtag.most_used_hashtag": "mest brukte emneknagg", + "annual_report.summary.most_used_hashtag.none": "Ingen", + "annual_report.summary.new_posts.new_posts": "nye innlegg", + "annual_report.summary.percentile.text": "Du er av deiivrigaste Mastodon-brukarane.", + "annual_report.summary.percentile.we_wont_tell_bernie": "Ikkje eit ord til pressa.", + "annual_report.summary.thanks": "Takk for at du er med i Mastodon!", "attachments_list.unprocessed": "(ubehandla)", "audio.hide": "Gøym lyd", "block_modal.remote_users_caveat": "Me vil be tenaren {domain} om å respektere di avgjerd. Me kan ikkje garantera at det vert gjort, sidan nokre tenarar kan handtera blokkering ulikt. Offentlege innlegg kan framleis vera synlege for ikkje-innlogga brukarar.", @@ -197,6 +216,7 @@ "confirmations.unfollow.title": "Slutt å fylgja brukaren?", "content_warning.hide": "Gøym innlegg", "content_warning.show": "Vis likevel", + "content_warning.show_more": "Vis meir", "conversation.delete": "Slett samtale", "conversation.mark_as_read": "Marker som lesen", "conversation.open": "Sjå samtale", @@ -272,7 +292,6 @@ "empty_column.hashtag": "Det er ingenting i denne emneknaggen enno.", "empty_column.home": "Heime-tidslina di er tom! Fylg fleire folk for å fylla ho med innhald. {suggestions}.", "empty_column.list": "Det er ingenting i denne lista enno. Når medlemer av denne lista legg ut nye statusar, så dukkar dei opp her.", - "empty_column.lists": "Du har ingen lister enno. Når du lagar ei, så dukkar ho opp her.", "empty_column.mutes": "Du har ikkje målbunde nokon enno.", "empty_column.notification_requests": "Ferdig! Her er det ingenting. Når du får nye varsel, kjem dei opp her slik du har valt.", "empty_column.notifications": "Du har ingen varsel enno. Kommuniser med andre for å starte samtalen.", @@ -305,6 +324,7 @@ "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", @@ -444,20 +464,11 @@ "link_preview.author": "Av {name}", "link_preview.more_from_author": "Meir frå {name}", "link_preview.shares": "{count, plural,one {{counter} innlegg} other {{counter} innlegg}}", - "lists.account.add": "Legg til i liste", - "lists.account.remove": "Fjern frå liste", "lists.delete": "Slett liste", "lists.edit": "Rediger liste", - "lists.edit.submit": "Endre tittel", - "lists.exclusive": "Skjul desse innlegga frå heimestraumen din", - "lists.new.create": "Legg til liste", - "lists.new.title_placeholder": "Ny listetittel", "lists.replies_policy.followed": "Alle fylgde brukarar", "lists.replies_policy.list": "Medlemar i lista", "lists.replies_policy.none": "Ingen", - "lists.replies_policy.title": "Vis svar på:", - "lists.search": "Søk blant folk du fylgjer", - "lists.subheading": "Listene dine", "load_pending": "{count, plural, one {# nytt element} other {# nye element}}", "loading_indicator.label": "Lastar…", "media_gallery.hide": "Gøym", @@ -506,6 +517,8 @@ "notification.admin.report_statuses_other": "{name} rapporterte {target}", "notification.admin.sign_up": "{name} er registrert", "notification.admin.sign_up.name_and_others": "{name} og {count, plural, one {# annan} other {# andre}} vart med", + "notification.annual_report.message": "#Året ditt for {year} ventar! Sjå kva som skjedde i løpet av Mastodon-året ditt!", + "notification.annual_report.view": "Sjå #Året ditt", "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", diff --git a/app/javascript/mastodon/locales/no.json b/app/javascript/mastodon/locales/no.json index 9a5f379797..b461d3049f 100644 --- a/app/javascript/mastodon/locales/no.json +++ b/app/javascript/mastodon/locales/no.json @@ -268,7 +268,6 @@ "empty_column.hashtag": "Det er ingenting i denne emneknaggen ennå.", "empty_column.home": "Hjem-tidslinjen din er tom! Følg flere folk for å fylle den. {suggestions}", "empty_column.list": "Det er ingenting i denne listen ennå. Når medlemmene av denne listen legger ut nye statuser vil de dukke opp her.", - "empty_column.lists": "Du har ingen lister enda. Når du lager en, vil den dukke opp her.", "empty_column.mutes": "Du har ikke dempet noen brukere enda.", "empty_column.notification_requests": "Alt klart! Det er ingenting her. Når du mottar nye varsler, vises de her i henhold til dine innstillinger.", "empty_column.notifications": "Du har ingen varsler ennå. Kommuniser med andre for å begynne samtalen.", @@ -436,20 +435,11 @@ "link_preview.author": "Av {name}", "link_preview.more_from_author": "Mer fra {name}", "link_preview.shares": "{count, plural, one {{counter} innlegg} other {{counter} innlegg}}", - "lists.account.add": "Legg til i listen", - "lists.account.remove": "Fjern fra listen", "lists.delete": "Slett listen", "lists.edit": "Rediger listen", - "lists.edit.submit": "Endre tittel", - "lists.exclusive": "Skjul disse innleggene i tidslinjen", - "lists.new.create": "Legg til liste", - "lists.new.title_placeholder": "Ny listetittel", "lists.replies_policy.followed": "Enhver fulgt bruker", "lists.replies_policy.list": "Medlemmer i listen", "lists.replies_policy.none": "Ingen", - "lists.replies_policy.title": "Vis svar på:", - "lists.search": "Søk blant personer du følger", - "lists.subheading": "Dine lister", "load_pending": "{count, plural,one {# ny gjenstand} other {# nye gjenstander}}", "loading_indicator.label": "Laster…", "moved_to_account_banner.text": "Din konto {disabledAccount} er for øyeblikket deaktivert fordi du flyttet til {movedToAccount}.", diff --git a/app/javascript/mastodon/locales/oc.json b/app/javascript/mastodon/locales/oc.json index 37687bc844..ddaf949873 100644 --- a/app/javascript/mastodon/locales/oc.json +++ b/app/javascript/mastodon/locales/oc.json @@ -202,7 +202,6 @@ "empty_column.hashtag": "I a pas encara de contengut ligat a aquesta etiqueta.", "empty_column.home": "Vòstre flux d’acuèlh es void. Visitatz {public} o utilizatz la recèrca per vos connectar a d’autras personas.", "empty_column.list": "I a pas res dins la lista pel moment. Quand de membres d’aquesta lista publiquen de novèls estatuts los veiretz aquí.", - "empty_column.lists": "Encara avètz pas cap de lista. Quand ne creetz una, apareisserà aquí.", "empty_column.mutes": "Encara avètz pas mes en silenci degun.", "empty_column.notifications": "Avètz pas encara de notificacions. Respondètz a qualqu’un per començar una conversacion.", "empty_column.public": "I a pas res aquí ! Escrivètz quicòm de public, o seguètz de personas d’autres servidors per garnir lo flux public", @@ -311,19 +310,11 @@ "limited_account_hint.action": "Afichar lo perfil de tota manièra", "limited_account_hint.title": "Aqueste perfil foguèt rescondut per la moderacion de {domain}.", "link_preview.author": "Per {name}", - "lists.account.add": "Ajustar a la lista", - "lists.account.remove": "Levar de la lista", "lists.delete": "Suprimir la lista", "lists.edit": "Modificar la lista", - "lists.edit.submit": "Cambiar lo títol", - "lists.new.create": "Ajustar una lista", - "lists.new.title_placeholder": "Títol de la nòva lista", "lists.replies_policy.followed": "Quin seguidor que siá", "lists.replies_policy.list": "Membres de la lista", "lists.replies_policy.none": "Degun", - "lists.replies_policy.title": "Mostrar las responsas a :", - "lists.search": "Cercar demest lo mond que seguètz", - "lists.subheading": "Vòstras listas", "load_pending": "{count, plural, one {# nòu element} other {# nòu elements}}", "loading_indicator.label": "Cargament…", "navigation_bar.about": "A prepaus", diff --git a/app/javascript/mastodon/locales/pa.json b/app/javascript/mastodon/locales/pa.json index 5da88ff08f..86226f4cde 100644 --- a/app/javascript/mastodon/locales/pa.json +++ b/app/javascript/mastodon/locales/pa.json @@ -201,8 +201,6 @@ "lightbox.next": "ਅਗਲੀ", "lightbox.previous": "ਪਿਛਲੀ", "link_preview.author": "{name} ਵਲੋਂ", - "lists.account.add": "ਸੂਚੀ ਵਿੱਚ ਜੋੜੋ", - "lists.account.remove": "ਸੂਚੀ ਵਿਚੋਂ ਹਟਾਓ", "lists.delete": "ਸੂਚੀ ਹਟਾਓ", "lists.replies_policy.followed": "ਕੋਈ ਵੀ ਫ਼ਾਲੋ ਕੀਤਾ ਵਰਤੋਂਕਾਰ", "lists.replies_policy.none": "ਕੋਈ ਨਹੀਂ", diff --git a/app/javascript/mastodon/locales/pl.json b/app/javascript/mastodon/locales/pl.json index c521fabf39..86c02a6a87 100644 --- a/app/javascript/mastodon/locales/pl.json +++ b/app/javascript/mastodon/locales/pl.json @@ -87,6 +87,24 @@ "alert.unexpected.title": "Ups!", "alt_text_badge.title": "Tekst alternatywny", "announcement.announcement": "Ogłoszenie", + "annual_report.summary.archetype.booster": "Łowca treści", + "annual_report.summary.archetype.lurker": "Czyhający", + "annual_report.summary.archetype.oracle": "Wyrocznia", + "annual_report.summary.archetype.pollster": "Ankieter", + "annual_report.summary.archetype.replier": "Motyl społeczny", + "annual_report.summary.followers.followers": "obserwujących", + "annual_report.summary.followers.total": "łącznie {count}", + "annual_report.summary.here_it_is": "Oto przegląd Twojego {year} roku:", + "annual_report.summary.highlighted_post.by_favourites": "najbardziej ulubiony wpis", + "annual_report.summary.highlighted_post.by_reblogs": "najbardziej promowany wpis", + "annual_report.summary.highlighted_post.by_replies": "wpis z największą liczbą odpowiedzi", + "annual_report.summary.highlighted_post.possessive": "{name}", + "annual_report.summary.most_used_app.most_used_app": "najczęściej używana aplikacja", + "annual_report.summary.most_used_hashtag.most_used_hashtag": "najczęściej używany hashtag", + "annual_report.summary.most_used_hashtag.none": "Brak", + "annual_report.summary.new_posts.new_posts": "nowe wpisy", + "annual_report.summary.percentile.we_wont_tell_bernie": "Nie powiemy Berniemu.", + "annual_report.summary.thanks": "Dziękujemy, że jesteś częścią Mastodona!", "attachments_list.unprocessed": "(nieprzetworzone)", "audio.hide": "Ukryj dźwięk", "block_modal.remote_users_caveat": "Poprosimy serwer {domain} o uszanowanie twojej decyzji. Zgodność nie jest jednak gwarantowana, bo niektóre serwery mogą inaczej obsługiwać blokowanie. Wpisy publiczne mogą być widoczne dla niezalogowanych użytkowników.", @@ -273,7 +291,6 @@ "empty_column.hashtag": "Nie ma wpisów oznaczonych tym hasztagiem. Możesz napisać pierwszy(-a).", "empty_column.home": "Nie obserwujesz nikogo. Odwiedź globalną oś czasu lub użyj wyszukiwarki, aby znaleźć interesujące Cię profile.", "empty_column.list": "Nie ma nic na tej liście. Kiedy członkowie listy dodadzą nowe wpisy, pojawia się one tutaj.", - "empty_column.lists": "Nie masz żadnych list. Kiedy utworzysz jedną, pojawi się tutaj.", "empty_column.mutes": "Nie wyciszyłeś(-aś) jeszcze żadnego użytkownika.", "empty_column.notification_requests": "To wszystko – kiedy otrzymasz nowe powiadomienia, pokażą się tutaj zgodnie z twoimi ustawieniami.", "empty_column.notifications": "Nie masz żadnych powiadomień. Rozpocznij interakcje z innymi użytkownikami.", @@ -446,20 +463,11 @@ "link_preview.author": "{name}", "link_preview.more_from_author": "Więcej od {name}", "link_preview.shares": "{count, plural, one {{counter} wpis} few {{counter} wpisy} many {{counter} wpisów} other {{counter} wpisów}}", - "lists.account.add": "Dodaj do listy", - "lists.account.remove": "Usunąć z listy", "lists.delete": "Usuń listę", "lists.edit": "Edytuj listę", - "lists.edit.submit": "Zmień tytuł", - "lists.exclusive": "Ukryj te posty w lokalnej osi czasu", - "lists.new.create": "Utwórz listę", - "lists.new.title_placeholder": "Wprowadź tytuł listy", "lists.replies_policy.followed": "Dowolny obserwowany użytkownik", "lists.replies_policy.list": "Członkowie listy", "lists.replies_policy.none": "Nikt", - "lists.replies_policy.title": "Pokazuj odpowiedzi dla:", - "lists.search": "Szukaj wśród osób które obserwujesz", - "lists.subheading": "Twoje listy", "load_pending": "{count, plural, one {# nowa pozycja} other {nowe pozycje}}", "loading_indicator.label": "Ładowanie…", "media_gallery.hide": "Ukryj", @@ -508,6 +516,7 @@ "notification.admin.report_statuses_other": "{name} zgłosił(a) {target}", "notification.admin.sign_up": "Użytkownik {name} zarejestrował się", "notification.admin.sign_up.name_and_others": "zarejestrował(-a) się {name} i {count, plural, one {# inna osoba} few {# inne osoby} other {# innych osób}}", + "notification.annual_report.view": "Zobacz #Wrapstodon", "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ę", diff --git a/app/javascript/mastodon/locales/pt-BR.json b/app/javascript/mastodon/locales/pt-BR.json index c620933abe..8740cd13de 100644 --- a/app/javascript/mastodon/locales/pt-BR.json +++ b/app/javascript/mastodon/locales/pt-BR.json @@ -87,6 +87,25 @@ "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.most_used_hashtag.none": "Nenhuma", + "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.", @@ -121,13 +140,16 @@ "column.blocks": "Usuários bloqueados", "column.bookmarks": "Salvos", "column.community": "Linha local", + "column.create_list": "Criar lista", "column.direct": "Menções privadas", "column.directory": "Explorar perfis", "column.domain_blocks": "Domínios bloqueados", + "column.edit_list": "Editar lista", "column.favourites": "Favoritos", "column.firehose": "Feeds ao vivo", "column.follow_requests": "Seguidores pendentes", "column.home": "Página inicial", + "column.list_members": "Gerenciar membros da lista", "column.lists": "Listas", "column.mutes": "Usuários silenciados", "column.notifications": "Notificações", @@ -273,7 +295,6 @@ "empty_column.hashtag": "Nada aqui.", "empty_column.home": "Sua página inicial está vazia! Siga mais pessoas para começar: {suggestions}", "empty_column.list": "Nada aqui. Quando membros da lista tootarem, eles aparecerão aqui.", - "empty_column.lists": "Nada aqui. Quando você criar listas, elas aparecerão aqui.", "empty_column.mutes": "Nada aqui.", "empty_column.notification_requests": "Tudo limpo! Não há nada aqui. Quando você receber novas notificações, elas aparecerão aqui de acordo com suas configurações.", "empty_column.notifications": "Interaja com outros usuários para começar a conversar.", @@ -446,20 +467,32 @@ "link_preview.author": "Por {name}", "link_preview.more_from_author": "Mais de {name}", "link_preview.shares": "{count, plural, one {{counter} publicação} other {{counter} publicações}}", - "lists.account.add": "Adicionar à lista", - "lists.account.remove": "Remover da lista", + "lists.add_member": "Adicionar", + "lists.add_to_list": "Adicionar à lista", + "lists.add_to_lists": "Adicionar {name} à lista", + "lists.create": "Criar", + "lists.create_a_list_to_organize": "Crie uma lista para organizar seu feed inicial", + "lists.create_list": "Criar lista", "lists.delete": "Excluir lista", + "lists.done": "Concluído", "lists.edit": "Editar lista", - "lists.edit.submit": "Renomear lista", - "lists.exclusive": "Ocultar estes posts da página inicial", - "lists.new.create": "Criar lista", - "lists.new.title_placeholder": "Nome da lista", + "lists.exclusive": "Ocultar membros no início", + "lists.exclusive_hint": "Se existe alguém nesta lista, oculte-os no seu feed inicial para evitar ver suas publicações duas vezes.", + "lists.find_users_to_add": "Encontrar usuários para adicionar", + "lists.list_members": "Membros da lista", + "lists.list_members_count": "{count, plural, one {# membro} other {# membros}}", + "lists.list_name": "Nome da lista", + "lists.new_list_name": "Nome novo da lista", + "lists.no_lists_yet": "Sem listas ainda.", + "lists.no_members_yet": "Nenhum membro ainda.", + "lists.no_results_found": "Nenhum resultado encontrado.", + "lists.remove_member": "Remover", "lists.replies_policy.followed": "Qualquer usuário seguido", "lists.replies_policy.list": "Membros da lista", "lists.replies_policy.none": "Ninguém", - "lists.replies_policy.title": "Mostrar respostas para:", - "lists.search": "Procurar entre as pessoas que segue", - "lists.subheading": "Suas listas", + "lists.save": "Salvar", + "lists.search_placeholder": "Buscar pessoas que você segue", + "lists.show_replies_to": "Incluir respostas de membros da lista para", "load_pending": "{count, plural, one {# novo item} other {# novos items}}", "loading_indicator.label": "Carregando…", "media_gallery.hide": "Ocultar", @@ -508,6 +541,8 @@ "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", diff --git a/app/javascript/mastodon/locales/pt-PT.json b/app/javascript/mastodon/locales/pt-PT.json index a4f2e27401..6a6b5549ed 100644 --- a/app/javascript/mastodon/locales/pt-PT.json +++ b/app/javascript/mastodon/locales/pt-PT.json @@ -85,7 +85,11 @@ "alert.rate_limited.title": "Limite de tentativas", "alert.unexpected.message": "Ocorreu um erro inesperado.", "alert.unexpected.title": "Bolas!", + "alt_text_badge.title": "Texto alternativo", "announcement.announcement": "Anúncio", + "annual_report.summary.followers.total": "{count} total", + "annual_report.summary.here_it_is": "Aqui está o seu {year} em revisão:", + "annual_report.summary.new_posts.new_posts": "novas publicações", "attachments_list.unprocessed": "(não processado)", "audio.hide": "Ocultar áudio", "block_modal.remote_users_caveat": "Vamos pedir ao servidor {domain} para respeitar a sua decisão. No entanto, não é garantido o seu cumprimento, uma vez que alguns servidores podem tratar os bloqueios de forma diferente. As mensagens públicas podem continuar a ser visíveis para utilizadores não autenticados.", @@ -268,7 +272,6 @@ "empty_column.hashtag": "Não foram encontradas publicações com essa #etiqueta.", "empty_column.home": "A sua linha cronológica inicial está vazia! Siga mais pessoas para a preencher.", "empty_column.list": "Ainda não existem publicações nesta lista. Quando membros desta lista fizerem novas publicações, elas aparecerão aqui.", - "empty_column.lists": "Ainda não tem qualquer lista. Quando criar uma, ela irá aparecer aqui.", "empty_column.mutes": "Ainda não silenciaste qualquer utilizador.", "empty_column.notification_requests": "Tudo limpo! Não há nada aqui. Quando você receber novas notificações, elas aparecerão aqui conforme as suas configurações.", "empty_column.notifications": "Não tens notificações. Interage com outros utilizadores para iniciar uma conversa.", @@ -436,20 +439,11 @@ "link_preview.author": "Por {name}", "link_preview.more_from_author": "Mais de {name}", "link_preview.shares": "{count, plural, one {{counter} publicação} other {{counter} publicações}}", - "lists.account.add": "Adicionar à lista", - "lists.account.remove": "Remover da lista", "lists.delete": "Eliminar lista", "lists.edit": "Editar lista", - "lists.edit.submit": "Mudar o título", - "lists.exclusive": "Ocultar essas publicações da página inicial", - "lists.new.create": "Adicionar lista", - "lists.new.title_placeholder": "Título da nova lista", "lists.replies_policy.followed": "Qualquer utilizador seguido", "lists.replies_policy.list": "Membros da lista", "lists.replies_policy.none": "Ninguém", - "lists.replies_policy.title": "Mostrar respostas para:", - "lists.search": "Pesquisa entre as pessoas que segues", - "lists.subheading": "As tuas listas", "load_pending": "{count, plural, one {# novo item} other {# novos itens}}", "loading_indicator.label": "A carregar…", "media_gallery.hide": "Esconder", diff --git a/app/javascript/mastodon/locales/ro.json b/app/javascript/mastodon/locales/ro.json index 96f9eac2b3..f21ce027f4 100644 --- a/app/javascript/mastodon/locales/ro.json +++ b/app/javascript/mastodon/locales/ro.json @@ -213,7 +213,6 @@ "empty_column.hashtag": "Acest hashtag încă nu a fost folosit.", "empty_column.home": "Nu există nimic în cronologia ta! Abonează-te la mai multe persoane pentru a o umple. {suggestions}", "empty_column.list": "Momentan nu există nimic în această listă. Când membrii ei vor posta ceva nou, vor apărea aici.", - "empty_column.lists": "Momentan nu ai nicio listă. Când vei crea una, va apărea aici.", "empty_column.mutes": "Momentan nu ai ignorat niciun utilizator.", "empty_column.notifications": "Momentan nu ai nicio notificare. Când alte persoane vor interacționa cu tine, îl vei vedea aici.", "empty_column.public": "Nu există nimic aici! Postează ceva public, sau abonează-te manual la utilizatori din alte servere pentru a umple cronologia", @@ -338,19 +337,11 @@ "limited_account_hint.action": "Afișează profilul oricum", "limited_account_hint.title": "Acest profil a fost ascuns de moderatorii domeniului {domain}.", "link_preview.author": "De {name}", - "lists.account.add": "Adaugă în listă", - "lists.account.remove": "Elimină din listă", "lists.delete": "Șterge lista", "lists.edit": "Modifică lista", - "lists.edit.submit": "Schimbă titlul", - "lists.new.create": "Adaugă o listă", - "lists.new.title_placeholder": "Titlu pentru noua listă", "lists.replies_policy.followed": "Tuturor persoanelor la care te-ai abonat", "lists.replies_policy.list": "Membrilor din listă", "lists.replies_policy.none": "Nu afișa nimănui", - "lists.replies_policy.title": "Afișează răspunsurile:", - "lists.search": "Caută printre persoanele la care ești abonat", - "lists.subheading": "Listele tale", "load_pending": "{count, plural, one {# element nou} other {# elemente noi}}", "moved_to_account_banner.text": "Contul tău {disabledAccount} este în acest moment dezactivat deoarece te-ai mutat la {movedToAccount}.", "navigation_bar.about": "Despre", diff --git a/app/javascript/mastodon/locales/ru.json b/app/javascript/mastodon/locales/ru.json index 2a985a1f84..90af458cdc 100644 --- a/app/javascript/mastodon/locales/ru.json +++ b/app/javascript/mastodon/locales/ru.json @@ -40,7 +40,7 @@ "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,13 +62,13 @@ "account.requested_follow": "{name} отправил(а) вам запрос на подписку", "account.share": "Поделиться профилем @{name}", "account.show_reblogs": "Показывать продвижения от @{name}", - "account.statuses_counter": "{count, plural, one {# пост} few {# поста} many {# постов} other {# постов}}", + "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": "Текст заметки", @@ -84,9 +84,27 @@ "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.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.most_used_hashtag.none": "Нет", + "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} уважать ваше решение. Однако, соблюдение требований не гарантировано, поскольку некоторые серверы могут работать с блокировками по-разному. Публичные записи по-прежнему могут быть видны неавторизованным пользователям.", @@ -95,11 +113,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": "О нет!", @@ -144,12 +162,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}. Любой пользователь сможет подписаться на вас и просматривать посты для подписчиков.", @@ -158,16 +176,17 @@ "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.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": "Удалить", @@ -177,17 +196,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": "Перепишем пост?", @@ -196,6 +215,7 @@ "confirmations.unfollow.title": "Отписаться?", "content_warning.hide": "Скрыть пост", "content_warning.show": "Всё равно показать", + "content_warning.show_more": "Покажи ещё", "conversation.delete": "Удалить беседу", "conversation.mark_as_read": "Отметить как прочитанное", "conversation.open": "Просмотр беседы", @@ -221,6 +241,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, 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, но и в различных социальных приложениях.", @@ -240,7 +261,7 @@ "embed.preview": "Так это будет выглядеть:", "emoji_button.activity": "Занятия", "emoji_button.clear": "Очистить", - "emoji_button.custom": "С этого узла", + "emoji_button.custom": "С этого сервера", "emoji_button.flags": "Флаги", "emoji_button.food": "Еда и напитки", "emoji_button.label": "Вставить эмодзи", @@ -270,7 +291,6 @@ "empty_column.hashtag": "С этим хэштегом пока ещё ничего не постили.", "empty_column.home": "Ваша лента совсем пуста! Подписывайтесь на других, чтобы заполнить её.", "empty_column.list": "В этом списке пока ничего нет.", - "empty_column.lists": "У вас ещё нет списков. Созданные вами списки будут показаны здесь.", "empty_column.mutes": "Вы ещё никого не добавляли в список игнорируемых.", "empty_column.notification_requests": "Здесь ничего нет! Когда вы получите новые уведомления, они здесь появятся согласно вашим настройкам.", "empty_column.notifications": "У вас пока нет уведомлений. Взаимодействуйте с другими, чтобы завести разговор.", @@ -303,6 +323,7 @@ "filter_modal.select_filter.subtitle": "Используйте существующую категорию или создайте новую", "filter_modal.select_filter.title": "Фильтровать этот пост", "filter_modal.title.status": "Фильтровать пост", + "filter_warning.matches_filter": "Соответствует фильтру \"{title}\"", "filtered_notifications_banner.pending_requests": "Вы можете знать {count, plural, =0 {ни одного человека} one {одного человека} other {# человек}}", "filtered_notifications_banner.title": "Отфильтрованные уведомления", "firehose.all": "Все", @@ -346,12 +367,12 @@ "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 {# ещё}}", + "hashtags.and_other": "…и {count, plural, other {ещё #}}", "hints.profiles.followers_may_be_missing": "Подписчики у этого профиля могут отсутствовать.", "hints.profiles.follows_may_be_missing": "Фолловеры для этого профиля могут отсутствовать.", "hints.profiles.posts_may_be_missing": "Некоторые сообщения из этого профиля могут отсутствовать.", @@ -382,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?", @@ -393,6 +415,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 {# минут}}", @@ -405,8 +428,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": "перейти к домашней ленте", @@ -414,7 +437,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": "открыть вложение", @@ -426,7 +449,7 @@ "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": "вверх по списку", @@ -440,20 +463,11 @@ "link_preview.author": "Автор: {name}", "link_preview.more_from_author": "Больше от {name}", "link_preview.shares": "{count, plural, one {{counter} пост} other {{counter} посты}}", - "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.followed": "Любой подписанный пользователь", "lists.replies_policy.list": "Пользователи в списке", "lists.replies_policy.none": "Никого", - "lists.replies_policy.title": "Показать ответы только:", - "lists.search": "Искать среди подписок", - "lists.subheading": "Ваши списки", "load_pending": "{count, plural, one {# новый элемент} few {# новых элемента} other {# новых элементов}}", "loading_indicator.label": "Загрузка…", "media_gallery.hide": "Скрыть", @@ -468,8 +482,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": "Локальная лента", @@ -495,26 +509,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.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": "Некоторые из ваших сообщений были отмечены как деликатные.", @@ -525,7 +542,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 {# аккаунтов}}, на которые вы подписаны.", @@ -534,10 +551,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": "Уведомления от этой учетной записи были отфильтрованы, поскольку учетная запись была ограничена модератором.", @@ -549,15 +571,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": "Пуш-уведомления", @@ -577,31 +600,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!", @@ -619,7 +643,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": "Поделиться вашим профилем", @@ -634,7 +658,7 @@ "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.verification": "Знали ли вы? Вы можете подтвердить свою учетную запись, разместив ссылку на свой профиль Mastodon на собственном сайте и добавив сайт в свой профиль. Никаких сборов или документов не требуется!", @@ -678,15 +702,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": "этим профилем", @@ -757,31 +781,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.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}", @@ -800,6 +825,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": "Убрать из закладок", @@ -813,13 +839,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": "Главная", @@ -829,7 +855,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} млрд", @@ -856,11 +882,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/sa.json b/app/javascript/mastodon/locales/sa.json index 2d48f688d5..a12bb6bde7 100644 --- a/app/javascript/mastodon/locales/sa.json +++ b/app/javascript/mastodon/locales/sa.json @@ -194,7 +194,6 @@ "empty_column.hashtag": "नाऽस्मिन् प्रचलितवस्तुचिह्ने किमपि ।", "empty_column.home": "गृहसमयतालिका रिक्ताऽस्ति । गम्यतां {public} वाऽन्वेषणैः प्रारभ्यतां मेलनं क्रियताञ्च ।", "empty_column.list": "न किमपि वर्तते सूच्यामस्याम् । यदा सूच्याः सदस्या नवपत्राणि प्रकटीकुर्वन्ति तदाऽत्राऽऽयान्ति ।", - "empty_column.lists": "तव पार्श्वे न कापि सूचिर्वर्तते। यदैकां सृजसि तदा अत्र दृश्यते।", "empty_column.mutes": "त्वया अद्यापि नैकोऽप्युपभोक्ता मूकीकृतो वर्तते।", "empty_column.notifications": "तव पार्श्वे न अधुना पर्यन्तं किमपि विज्ञापनं वर्तते। यदा अन्या जना त्वया संयोजयन्ति तदा इह पश्यसि।", "empty_column.public": "न इह किमपि वर्तते! किञ्चिल्लिख सार्वजनिकरूपेण, उत स्वयमन्यसर्वर्तः उपभोक्तॄननुसर एतत्पूरयितुम्", @@ -303,19 +302,11 @@ "lightbox.previous": "पूर्वः", "limited_account_hint.action": "प्रोफैलं दर्शय कथञ्चित्", "limited_account_hint.title": "{domain} इत्यस्य प्रशासकैरयं प्रोफैल्प्रच्छन्नः।", - "lists.account.add": "सूचेर्मध्ये योजय", - "lists.account.remove": "सूचेर्मार्जय", "lists.delete": "सूचिं मार्जय", "lists.edit": "सूचिं सम्पादय", - "lists.edit.submit": "उपाधिं परिवर्तय", - "lists.new.create": "सूचिं योजय", - "lists.new.title_placeholder": "नूतनसूच्युपाधिः", "lists.replies_policy.followed": "कोऽप्यनुसारितोपभोक्ता", "lists.replies_policy.list": "सूचेस्सदस्याः", "lists.replies_policy.none": "न कोऽपि", - "lists.replies_policy.title": "एतमुत्तराणि दर्शय :", - "lists.search": "त्वया अनुसारितजनेषु अन्विष्य", - "lists.subheading": "तव सूचयः", "load_pending": "{count, plural, one {# नूतनवस्तु} other {# नूतनवस्तूनि}}", "moved_to_account_banner.text": "तव एकौण्ट् {disabledAccount} अधुना निष्कृतो यतोहि {movedToAccount} अस्मिन्त्वमसार्षीः।", "navigation_bar.about": "विषये", diff --git a/app/javascript/mastodon/locales/sc.json b/app/javascript/mastodon/locales/sc.json index 71bcaef7ab..19bdba818c 100644 --- a/app/javascript/mastodon/locales/sc.json +++ b/app/javascript/mastodon/locales/sc.json @@ -257,7 +257,6 @@ "empty_column.hashtag": "Ancora nudda in custa eticheta.", "empty_column.home": "Sa lìnia de tempus printzipale tua est bòida. Visita {public} o imprea sa chirca pro cumintzare e agatare àteras persones.", "empty_column.list": "Nudda ancora in custa lista. Cando is persones de custa lista ant a publicare, is publicatziones ant a aparèssere inoghe.", - "empty_column.lists": "Non tenes ancora peruna lista. Cando nd'as a creare una, at a èssere ammustrada inoghe.", "empty_column.mutes": "No as postu ancora nemos a sa muda.", "empty_column.notifications": "Non tenes ancora peruna notìfica. Chistiona cun una persone pro cumintzare un'arresonada.", "empty_column.public": "Nudda inoghe. Iscrie calicuna cosa pùblica, o sighi àteras persones de àteros serbidores pro prenare custu ispàtziu", @@ -392,20 +391,11 @@ "lightbox.previous": "Pretzedente", "limited_account_hint.title": "Custu profilu est istadu cuadu dae sa moderatzione de {domain}.", "link_preview.shares": "{count, plural, one {{counter} publicatzione} other {{counter} publicatziones}}", - "lists.account.add": "Agiunghe a sa lista", - "lists.account.remove": "Boga dae sa lista", "lists.delete": "Cantzella sa lista", "lists.edit": "Modìfica sa lista", - "lists.edit.submit": "Muda su tìtulu", - "lists.exclusive": "Cua custas publicatziones dae sa pàgina printzipale", - "lists.new.create": "Agiunghe lista", - "lists.new.title_placeholder": "Tìtulu de sa lista noa", "lists.replies_policy.followed": "Cale si siat persone chi sighis", "lists.replies_policy.list": "Persones de sa lista", "lists.replies_policy.none": "Nemos", - "lists.replies_policy.title": "Ammustra is rispostas a:", - "lists.search": "Chirca intre sa gente chi ses sighende", - "lists.subheading": "Is listas tuas", "load_pending": "{count, plural, one {# elementu nou} other {# elementos noos}}", "loading_indicator.label": "Carrighende…", "media_gallery.hide": "Cua", diff --git a/app/javascript/mastodon/locales/sco.json b/app/javascript/mastodon/locales/sco.json index c14f1cc51a..196b4cdb08 100644 --- a/app/javascript/mastodon/locales/sco.json +++ b/app/javascript/mastodon/locales/sco.json @@ -185,7 +185,6 @@ "empty_column.hashtag": "There naethin in this hashtag yit.", "empty_column.home": "Yer hame timeline is toum! Follae mair fowk fir tae full it up. {suggestions}", "empty_column.list": "There naethin in this list yit. Whan memmers o this list publish new posts, ye'll see them here.", - "empty_column.lists": "Ye dinnae hae onie lists yit. Ance ye mak ane, it'll shaw up here.", "empty_column.mutes": "Ye'v no wheesht onie uisers yit.", "empty_column.notifications": "Ye dinnae hae onie notes yit. Whan ither fowk interacks wi ye, ye'll see it here.", "empty_column.public": "There naethin here! Scrieve socht public, or follae uisers fae ither servers fir tae full it up", @@ -288,19 +287,11 @@ "lightbox.previous": "Last ane", "limited_account_hint.action": "Shaw profile onieweys", "limited_account_hint.title": "This profile haes been planked bi the moderators o {domain}.", - "lists.account.add": "Add tae list", - "lists.account.remove": "Tak aff o the list", "lists.delete": "Delete list", "lists.edit": "Edit list", - "lists.edit.submit": "Chynge title", - "lists.new.create": "Add list", - "lists.new.title_placeholder": "New list title", "lists.replies_policy.followed": "Onie follaed uiser", "lists.replies_policy.list": "Memmers o the list", "lists.replies_policy.none": "Naebody", - "lists.replies_policy.title": "Shaw replies tae:", - "lists.search": "Seirch amang the fowk ye ken", - "lists.subheading": "Yer lists", "load_pending": "{count, plural, one {# new item} other {# new items}}", "moved_to_account_banner.text": "Yer accoont {disabledAccount} is disabilt the noo acause ye flittit tae {movedToAccount}.", "navigation_bar.about": "Aboot", diff --git a/app/javascript/mastodon/locales/si.json b/app/javascript/mastodon/locales/si.json index 93ce9dd7e2..dbf6a41f6f 100644 --- a/app/javascript/mastodon/locales/si.json +++ b/app/javascript/mastodon/locales/si.json @@ -166,7 +166,6 @@ "empty_column.favourited_statuses": "ඔබ සතුව ප්‍රියතම ලිපි කිසිවක් නැත. ඔබ යමකට ප්‍රිය කළ විට එය මෙහි පෙන්වනු ඇත.", "empty_column.follow_requests": "ඔබට තවමත් අනුගමන ඉල්ලීම් ලැබී නැත. ඉල්ලීමක් ලැබුණු විට, එය මෙහි පෙන්වනු ඇත.", "empty_column.home": "මුල් පිටුව හිස් ය! මෙය පිරවීමට බොහෝ පුද්ගලයින් අනුගමනය කරන්න.", - "empty_column.lists": "ඔබට තවමත් ලැයිස්තු කිසිවක් නැත. ඔබ එකක් සාදන විට, එය මෙහි පෙන්වනු ඇත.", "empty_column.mutes": "ඔබ තවමත් කිසිදු පරිශීලකයෙකු නිහඬ කර නැත.", "empty_column.notifications": "ඔබට දැනුම්දීම් ලැබී නැත. අන් අය සහ ඔබ අතර අන්‍යෝන්‍ය බලපවත්වන දෑ මෙහි දිස්වනු ඇත.", "error.unexpected_crash.explanation": "අපගේ කේතයේ දෝෂයක් හෝ බ්‍රවුසර ගැළපුම් ගැටලුවක් හේතුවෙන්, මෙම පිටුව නිවැරදිව ප්‍රදර්ශනය කළ නොහැක.", @@ -250,17 +249,10 @@ "lightbox.next": "ඊළඟ", "lightbox.previous": "පෙර", "limited_account_hint.action": "කෙසේ හෝ පැතිකඩ පෙන්වන්න", - "lists.account.add": "ලැයිස්තුවට දමන්න", - "lists.account.remove": "ලැයිස්තුවෙන් ඉවතලන්න", "lists.delete": "ලැයිස්තුව මකන්න", "lists.edit": "ලැයිස්තුව සංස්කරණය", - "lists.edit.submit": "සිරැසිය සංශෝධනය", - "lists.new.create": "එකතු", - "lists.new.title_placeholder": "නව ලැයිස්තුවේ සිරැසිය", "lists.replies_policy.list": "ලැයිස්තුවේ සාමාජිකයින්", "lists.replies_policy.none": "කිසිවෙක් නැත", - "lists.replies_policy.title": "පිළිතුරු පෙන්වන්න:", - "lists.subheading": "ඔබගේ ලැයිස්තු", "navigation_bar.about": "පිළිබඳව", "navigation_bar.blocks": "අවහිර කළ අය", "navigation_bar.bookmarks": "පොත්යොමු", diff --git a/app/javascript/mastodon/locales/sk.json b/app/javascript/mastodon/locales/sk.json index a1bcdb9ff9..d7e396c69b 100644 --- a/app/javascript/mastodon/locales/sk.json +++ b/app/javascript/mastodon/locales/sk.json @@ -87,11 +87,21 @@ "alert.unexpected.title": "Ups!", "alt_text_badge.title": "Alternatívny popis", "announcement.announcement": "Oznámenie", + "annual_report.summary.followers.followers": "sledovatelia", + "annual_report.summary.followers.total": "{count} celkovo", + "annual_report.summary.highlighted_post.by_favourites": "najviac obľúbený príspevok", + "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", "block_modal.show_more": "Zobraziť viac", "block_modal.they_cant_mention": "Nemôžu ťa spomenúť, alebo nasledovať.", + "block_modal.they_cant_see_posts": "On/a nemôže vidieť tvoje príspevky a ty neuvidíš jej/ho.", "block_modal.they_will_know": "Môžu vidieť, že sú zablokovaní/ý.", "block_modal.title": "Blokovať užívateľa?", "block_modal.you_wont_see_mentions": "Neuvidíš príspevky, ktoré ich spomínajú.", @@ -194,6 +204,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", @@ -258,7 +269,6 @@ "empty_column.hashtag": "Pod týmto hashtagom sa ešte nič nenachádza.", "empty_column.home": "Vaša domáca časová os je zatiaľ prázdna. Začnite sledovať ostatných a naplňte si ju.", "empty_column.list": "Tento zoznam je zatiaľ prázdny. Keď ale členovia tohoto zoznamu uverejnia nové príspevky, objavia sa tu.", - "empty_column.lists": "Zatiaľ nemáte žiadne zoznamy. Keď nejaký vytvoríte, zobrazí sa tu.", "empty_column.mutes": "Zatiaľ ste si nikoho nestíšili.", "empty_column.notification_requests": "Všetko čisté! Nič tu nieje. Keď dostaneš nové oboznámenia, zobrazia sa tu podľa tvojich nastavení.", "empty_column.notifications": "Zatiaľ nemáte žiadne upozornenia. Začnú vám pribúdať, keď s vami začnú interagovať ostatní.", @@ -337,6 +347,9 @@ "hashtag.follow": "Sledovať hashtag", "hashtag.unfollow": "Prestať sledovať hashtag", "hashtags.and_other": "…a {count, plural, other {# ďalších}}", + "hints.profiles.see_more_posts": "Pozri viac príspevkov na {domain}", + "hints.threads.replies_may_be_missing": "Odpovede z ostatných serverov môžu chýbať.", + "hints.threads.see_more": "Pozri viac odpovedí na {domain}", "home.column_settings.show_reblogs": "Zobraziť zdieľania", "home.column_settings.show_replies": "Zobraziť odpovede", "home.hide_announcements": "Skryť oznámenia", @@ -344,7 +357,14 @@ "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", + "ignore_notifications_modal.new_accounts_title": "Nevšímať si oznámenia z nových účtov?", + "ignore_notifications_modal.not_followers_title": "Nevšímať si oznámenia od ľudí, ktorí ťa nenasledujú?", + "ignore_notifications_modal.not_following_title": "Nevšímať si oznámenia od ľudí, ktorých nenasleduješ?", + "ignore_notifications_modal.private_mentions_title": "Nevšímať si oznámenia o nevyžiadaných súkromných spomínaniach?", "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.", "interaction_modal.description.reblog": "S účtom na Mastodone môžete tento príspevok zdeľať so svojimi sledovateľmi.", @@ -360,6 +380,7 @@ "interaction_modal.title.follow": "Sledovať {name}", "interaction_modal.title.reblog": "Zdieľať príspevok od {name}", "interaction_modal.title.reply": "Odpovedať na príspevok od {name}", + "interaction_modal.title.vote": "Hlasuj v ankete od {name}", "intervals.full.days": "{number, plural, one {# deň} few {# dni} many {# dní} other {# dní}}", "intervals.full.hours": "{number, plural, one {# hodina} few {# hodiny} many {# hodín} other {# hodín}}", "intervals.full.minutes": "{number, plural, one {# minúta} few {# minúty} many {# minút} other {# minút}}", @@ -400,25 +421,17 @@ "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", "lists.edit": "Upraviť zoznam", - "lists.edit.submit": "Zmeniť názov", - "lists.exclusive": "Skryť tieto príspevky z domovskej stránky", - "lists.new.create": "Pridať zoznam", - "lists.new.title_placeholder": "Názov nového zoznamu", "lists.replies_policy.followed": "Akémukoľvek sledovanému účtu", "lists.replies_policy.list": "Členom zoznamu", "lists.replies_policy.none": "Nikomu", - "lists.replies_policy.title": "Zobraziť odpovede:", - "lists.search": "Vyhľadávať medzi účtami, ktoré sledujete", - "lists.subheading": "Vaše zoznamy", "load_pending": "{count, plural, one {# nová položka} few {# nové položky} many {# nových položiek} other {# nových položiek}}", "loading_indicator.label": "Načítavanie…", "media_gallery.hide": "Skryť", @@ -427,7 +440,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 +484,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 +504,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 +539,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 +548,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 +719,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 32626b80f9..84141a779d 100644 --- a/app/javascript/mastodon/locales/sl.json +++ b/app/javascript/mastodon/locales/sl.json @@ -85,7 +85,14 @@ "alert.rate_limited.title": "Hitrost omejena", "alert.unexpected.message": "Zgodila se je nepričakovana napaka.", "alert.unexpected.title": "Ojoj!", + "alt_text_badge.title": "Nadomestno besedilo", "announcement.announcement": "Obvestilo", + "annual_report.summary.followers.followers": "sledilcev", + "annual_report.summary.followers.total": "", + "annual_report.summary.highlighted_post.by_favourites": "- najpriljubljenejša objava", + "annual_report.summary.most_used_hashtag.none": "Brez", + "annual_report.summary.new_posts.new_posts": "nove objave", + "annual_report.summary.thanks": "Hvala, ker ste del Mastodona!", "attachments_list.unprocessed": "(neobdelano)", "audio.hide": "Skrij zvok", "block_modal.remote_users_caveat": "Od strežnika {domain} bomo zahtevali, da spoštuje vašo odločitev. Izpolnjevanje zahteve ni zagotovljeno, ker nekateri strežniki blokiranja obravnavajo drugače. Javne objave bodo morda še vedno vidne neprijavljenim uporabnikom.", @@ -97,6 +104,8 @@ "block_modal.title": "Blokiraj uporabnika?", "block_modal.you_wont_see_mentions": "Objav, ki jih omenjajo, ne boste videli.", "boost_modal.combo": "Če želite preskočiti to, lahko pritisnete {combo}", + "boost_modal.reblog": "Izpostavi objavo?", + "boost_modal.undo_reblog": "Ali želite preklicati izpostavitev objave?", "bundle_column_error.copy_stacktrace": "Kopiraj poročilo o napaki", "bundle_column_error.error.body": "Zahtevane strani ni mogoče upodobiti. Vzrok težave je morda hrošč v naši kodi ali pa nezdružljivost z brskalnikom.", "bundle_column_error.error.title": "Oh, ne!", @@ -118,13 +127,16 @@ "column.blocks": "Blokirani uporabniki", "column.bookmarks": "Zaznamki", "column.community": "Krajevna časovnica", + "column.create_list": "Ustvari seznam", "column.direct": "Zasebne omembe", "column.directory": "Prebrskaj profile", "column.domain_blocks": "Blokirane domene", + "column.edit_list": "Uredi seznam", "column.favourites": "Priljubljeni", "column.firehose": "Viri v živo", "column.follow_requests": "Sledi prošnjam", "column.home": "Domov", + "column.list_members": "Upravljaj člane seznama", "column.lists": "Seznami", "column.mutes": "Utišani uporabniki", "column.notifications": "Obvestila", @@ -155,6 +167,7 @@ "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": "Ena izbira", "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", @@ -191,6 +204,9 @@ "confirmations.unfollow.confirm": "Ne sledi več", "confirmations.unfollow.message": "Ali ste prepričani, da ne želite več slediti {name}?", "confirmations.unfollow.title": "Želite nehati spremljati uporabnika?", + "content_warning.hide": "Skrij objavo", + "content_warning.show": "Vseeno pokaži", + "content_warning.show_more": "Pokaži več", "conversation.delete": "Izbriši pogovor", "conversation.mark_as_read": "Označi kot prebrano", "conversation.open": "Pokaži pogovor", @@ -264,7 +280,6 @@ "empty_column.hashtag": "V tem ključniku še ni nič.", "empty_column.home": "Vaša domača časovnica je prazna! Sledite več osebam, da jo zapolnite. {suggestions}", "empty_column.list": "Na tem seznamu ni ničesar. Ko bodo člani tega seznama objavili nove statuse, se bodo pojavili tukaj.", - "empty_column.lists": "Nimate seznamov. Ko ga boste ustvarili, se bo prikazal tukaj.", "empty_column.mutes": "Niste utišali še nobenega uporabnika.", "empty_column.notification_requests": "Vse prebrano! Tu ni ničesar več. Ko prejmete nova obvestila, se bodo pojavila tu glede na vaše nastavitve.", "empty_column.notifications": "Nimate še nobenih obvestil. Povežite se z drugimi, da začnete pogovor.", @@ -346,7 +361,10 @@ "hashtag.unfollow": "Nehaj slediti ključniku", "hashtags.and_other": "…in še {count, plural, other {#}}", "hints.profiles.posts_may_be_missing": "Nekatere objave s tega profila morda manjkajo.", + "hints.profiles.see_more_followers": "Pokaži več sledilcev na {domain}", + "hints.profiles.see_more_posts": "Pokaži več objav na {domain}", "hints.threads.replies_may_be_missing": "Odgovori z drugih strežnikov morda manjkajo.", + "hints.threads.see_more": "Pokaži več odgovorov na {domain}", "home.column_settings.show_reblogs": "Pokaži izpostavitve", "home.column_settings.show_replies": "Pokaži odgovore", "home.hide_announcements": "Skrij obvestila", @@ -417,22 +435,28 @@ "link_preview.author": "Avtor_ica {name}", "link_preview.more_from_author": "Več od {name}", "link_preview.shares": "{count, plural, one {{counter} objava} two {{counter} objavi} few {{counter} objave} other {{counter} objav}}", - "lists.account.add": "Dodaj na seznam", - "lists.account.remove": "Odstrani s seznama", + "lists.add_member": "Dodaj", + "lists.add_to_list": "Dodaj na seznam", + "lists.create": "Ustvari", + "lists.create_list": "Ustvari seznam", "lists.delete": "Izbriši seznam", + "lists.done": "Opravljeno", "lists.edit": "Uredi seznam", - "lists.edit.submit": "Spremeni naslov", - "lists.exclusive": "Skrij te objave od doma", - "lists.new.create": "Dodaj seznam", - "lists.new.title_placeholder": "Nov naslov seznama", + "lists.find_users_to_add": "Poišči člane za dodajanje", + "lists.list_name": "Ime seznama", + "lists.new_list_name": "Novo ime seznama", + "lists.no_lists_yet": "Ni seznamov.", + "lists.no_members_yet": "Ni še nobenega člana.", + "lists.no_results_found": "Ni rezultatov.", + "lists.remove_member": "Odstrani", "lists.replies_policy.followed": "Vsem sledenim uporabnikom", "lists.replies_policy.list": "Članom seznama", "lists.replies_policy.none": "Nikomur", - "lists.replies_policy.title": "Pokaži odgovore:", - "lists.search": "Iščite med ljudmi, katerim sledite", - "lists.subheading": "Vaši seznami", + "lists.save": "Shrani", + "lists.search_placeholder": "Iščite ljudi, katerim sledite", "load_pending": "{count, plural, one {# nov element} two {# nova elementa} few {# novi elementi} other {# novih elementov}}", "loading_indicator.label": "Nalaganje …", + "media_gallery.hide": "Skrij", "moved_to_account_banner.text": "Vaš račun {disabledAccount} je trenutno onemogočen, ker ste se prestavili na {movedToAccount}.", "mute_modal.hide_from_notifications": "Skrijte se pred obvestili", "mute_modal.hide_options": "Skrij možnosti", @@ -444,6 +468,7 @@ "mute_modal.you_wont_see_mentions": "Objav, ki jih omenjajo, ne boste videli.", "mute_modal.you_wont_see_posts": "Še vedno vidijo vaše objave, vi pa ne njihovih.", "navigation_bar.about": "O Mastodonu", + "navigation_bar.administration": "Upravljanje", "navigation_bar.advanced_interface": "Odpri v naprednem spletnem vmesniku", "navigation_bar.blocks": "Blokirani uporabniki", "navigation_bar.bookmarks": "Zaznamki", @@ -460,6 +485,7 @@ "navigation_bar.follows_and_followers": "Sledenja in sledilci", "navigation_bar.lists": "Seznami", "navigation_bar.logout": "Odjava", + "navigation_bar.moderation": "Moderiranje", "navigation_bar.mutes": "Utišani uporabniki", "navigation_bar.opened_in_classic_interface": "Objave, računi in druge specifične strani se privzeto odprejo v klasičnem spletnem vmesniku.", "navigation_bar.personal": "Osebno", @@ -478,10 +504,12 @@ "notification.favourite": "{name} je vzljubil/a vašo objavo", "notification.follow": "{name} vam sledi", "notification.follow_request": "{name} vam želi slediti", + "notification.label.mention": "Omemba", "notification.label.private_mention": "Zasebna omemba", "notification.label.private_reply": "Zasebni odgovor", "notification.label.reply": "Odgovori", "notification.mention": "Omemba", + "notification.mentioned_you": "{name} vas je omenil/a", "notification.moderation-warning.learn_more": "Več o tem", "notification.moderation_warning": "Prejeli ste opozorilo moderatorjev", "notification.moderation_warning.action_delete_statuses": "Nekatere vaše objave so odstranjene.", @@ -502,6 +530,7 @@ "notification.status": "{name} je pravkar objavil/a", "notification.update": "{name} je uredil(a) objavo", "notification_requests.accept": "Sprejmi", + "notification_requests.confirm_accept_multiple.title": "Ali želite sprejeti zahteve za obvestila?", "notification_requests.confirm_dismiss_multiple.title": "Želite opustiti zahteve za obvestila?", "notification_requests.dismiss": "Zavrni", "notification_requests.edit_selection": "Uredi", @@ -740,6 +769,7 @@ "status.edit": "Uredi", "status.edited": "Zadnje urejanje {date}", "status.edited_x_times": "Urejeno {count, plural, one {#-krat} two {#-krat} few {#-krat} other {#-krat}}", + "status.embed": "Pridobite kodo za vgradnjo", "status.favourite": "Priljubljen_a", "status.favourites": "{count, plural, one {priljubitev} two {priljubitvi} few {priljubitve} other {priljubitev}}", "status.filter": "Filtriraj to objavo", diff --git a/app/javascript/mastodon/locales/sq.json b/app/javascript/mastodon/locales/sq.json index 410d7c2ef3..c2781a2b6a 100644 --- a/app/javascript/mastodon/locales/sq.json +++ b/app/javascript/mastodon/locales/sq.json @@ -87,6 +87,20 @@ "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.most_used_hashtag.none": "Asnjë", + "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.", @@ -121,13 +135,16 @@ "column.blocks": "Përdorues të bllokuar", "column.bookmarks": "Faqerojtës", "column.community": "Rrjedhë kohore vendore", + "column.create_list": "Krijo listë", "column.direct": "Përmendje private", "column.directory": "Shfletoni profile", "column.domain_blocks": "Përkatësi të bllokuara", + "column.edit_list": "Përpunoni listën", "column.favourites": "Të parapëlqyer", "column.firehose": "Prurje “live”", "column.follow_requests": "Kërkesa për ndjekje", "column.home": "Kreu", + "column.list_members": "Administroni anëtarë liste", "column.lists": "Lista", "column.mutes": "Përdorues të heshtuar", "column.notifications": "Njoftime", @@ -273,7 +290,6 @@ "empty_column.hashtag": "Ende s’ka gjë nën këtë hashtag.", "empty_column.home": "Rrjedha juaj kohore është e zbrazët! Vizitoni {public} ose përdorni kërkimin që t’ia filloni dhe të takoni përdorues të tjerë.", "empty_column.list": "Në këtë listë ende s’ka gjë. Kur anëtarë të kësaj liste postojnë gjendje të reja, ato do të shfaqen këtu.", - "empty_column.lists": "Ende s’keni ndonjë listë. Kur të krijoni një të tillë, do të duket këtu.", "empty_column.mutes": "S’keni heshtuar ende ndonjë përdorues.", "empty_column.notification_requests": "Gjithçka si duhet! S’ka ç’bëhet këtu. Kur merrni njoftime të reja, do të shfaqen këtu, në përputhje me rregullimet tuaja.", "empty_column.notifications": "Ende s’keni ndonjë njoftim. Ndërveproni me të tjerët që të nisë biseda.", @@ -446,20 +462,32 @@ "link_preview.author": "Nga {name}", "link_preview.more_from_author": "Më tepër nga {name}", "link_preview.shares": "{count, plural, one {{counter} post} other {{counter} postime}}", - "lists.account.add": "Shto në listë", - "lists.account.remove": "Hiqe nga lista", + "lists.add_member": "Shtoje", + "lists.add_to_list": "Shto në listë", + "lists.add_to_lists": "Shtoje {name} në lista", + "lists.create": "Krijoje", + "lists.create_a_list_to_organize": "Krijoni një listë të re të sistemoni prurjen tuaj Kreu", + "lists.create_list": "Krijo listë", "lists.delete": "Fshije listën", + "lists.done": "U bë", "lists.edit": "Përpunoni listën", - "lists.edit.submit": "Ndryshoni titullin", - "lists.exclusive": "Fshihi këto postime prej kreut", - "lists.new.create": "Shtoni listë", - "lists.new.title_placeholder": "Titull liste të re", + "lists.exclusive": "Fshihni anëtarët në Krye", + "lists.exclusive_hint": "Nëse dikush gjendje në këtë listë, fshihini ata te prurja juaj e Kreut, që të shmangni parjen dy herë të postimeve të tyre.", + "lists.find_users_to_add": "Gjeni përdorues për t’i shtuar", + "lists.list_members": "Shfaq anëtarë", + "lists.list_members_count": "{count, plural, one {# anëtar} other {# anëtarë}}", + "lists.list_name": "Emër liste", + "lists.new_list_name": "Emër liste të re", + "lists.no_lists_yet": "Ende pa lista.", + "lists.no_members_yet": "Ende pa anëtarë.", + "lists.no_results_found": "S’u gjetën përfundime.", + "lists.remove_member": "Hiqe", "lists.replies_policy.followed": "Cilido përdorues i ndjekur", "lists.replies_policy.list": "Anëtarë të listës", "lists.replies_policy.none": "Askush", - "lists.replies_policy.title": "Shfaq përgjigje për:", - "lists.search": "Kërkoni mes personash që ndiqni", - "lists.subheading": "Listat tuaja", + "lists.save": "Ruaje", + "lists.search_placeholder": "Kërkoni persona që ndiqni", + "lists.show_replies_to": "Përfshi përgjigje nga anëtarë liste te", "load_pending": "{count, plural,one {# objekt i ri }other {# objekte të rinj }}", "loading_indicator.label": "Po ngarkohet…", "media_gallery.hide": "Fshihe", @@ -508,9 +536,12 @@ "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", @@ -569,6 +600,7 @@ "notifications.column_settings.filter_bar.category": "Shtyllë filtrimesh të shpejta", "notifications.column_settings.follow": "Ndjekës të rinj:", "notifications.column_settings.follow_request": "Kërkesa të reja për ndjekje:", + "notifications.column_settings.group": "Grupoji", "notifications.column_settings.mention": "Përmendje:", "notifications.column_settings.poll": "Përfundime pyetësori:", "notifications.column_settings.push": "Njoftime Push", diff --git a/app/javascript/mastodon/locales/sr-Latn.json b/app/javascript/mastodon/locales/sr-Latn.json index 4a33c2f5ca..5a587f2666 100644 --- a/app/javascript/mastodon/locales/sr-Latn.json +++ b/app/javascript/mastodon/locales/sr-Latn.json @@ -256,7 +256,6 @@ "empty_column.hashtag": "Još uvek nema ničega u ovoj heš oznaci.", "empty_column.home": "Vaša početna vremenska linija je prazna! Pratite više ljudi da biste je popunili.", "empty_column.list": "U ovoj listi još nema ničega. Kada članovi ove liste objave nešto novo, pojaviće se ovde.", - "empty_column.lists": "Još uvek nemate nijednu listu. Kada napravite jednu, ona će se pojaviti ovde.", "empty_column.mutes": "Još uvek ne ignorišete nijednog korisnika.", "empty_column.notification_requests": "Sve je čisto! Ovde nema ničega. Kada dobijete nova obaveštenja, ona će se pojaviti ovde u skladu sa vašim podešavanjima.", "empty_column.notifications": "Još uvek nemate nikakva obaveštenja. Kada drugi ljudi budu u interakciji sa vama, videćete to ovde.", @@ -404,20 +403,11 @@ "link_preview.author": "Po {name}", "link_preview.more_from_author": "Više od {name}", "link_preview.shares": "{count, plural, one {{counter} objava} few {{counter} objave} other {{counter} objava}}", - "lists.account.add": "Dodaj na listu", - "lists.account.remove": "Ukloni sa liste", "lists.delete": "Izbriši listu", "lists.edit": "Uredi listu", - "lists.edit.submit": "Promeni naslov", - "lists.exclusive": "Sakrijte ove objave sa početne stranice", - "lists.new.create": "Dodaj listu", - "lists.new.title_placeholder": "Naslov nove liste", "lists.replies_policy.followed": "Svakom praćenom korisniku", "lists.replies_policy.list": "Članovima liste", "lists.replies_policy.none": "Nikome", - "lists.replies_policy.title": "Prikaži odgovore:", - "lists.search": "Pretraži među ljudima koje pratite", - "lists.subheading": "Vaše liste", "load_pending": "{count, plural, one {# nova stavka} few {# nove stavke} other {# novih stavki}}", "loading_indicator.label": "Učitavanje…", "moved_to_account_banner.text": "Vaš nalog {disabledAccount} je trenutno onemogućen jer ste prešli na {movedToAccount}.", diff --git a/app/javascript/mastodon/locales/sr.json b/app/javascript/mastodon/locales/sr.json index d80411859e..ea92a3bf10 100644 --- a/app/javascript/mastodon/locales/sr.json +++ b/app/javascript/mastodon/locales/sr.json @@ -256,7 +256,6 @@ "empty_column.hashtag": "Још увек нема ничега у овој хеш ознаци.", "empty_column.home": "Ваша почетна временска линија је празна! Пратите више људи да бисте је попунили.", "empty_column.list": "У овој листи још нема ничега. Када чланови ове листе објаве нешто ново, појавиће се овде.", - "empty_column.lists": "Још увек немате ниједну листу. Када направите једну, она ће се појавити овде.", "empty_column.mutes": "Још увек не игноришете ниједног корисника.", "empty_column.notification_requests": "Све је чисто! Овде нема ничега. Када добијете нова обавештења, она ће се појавити овде у складу са вашим подешавањима.", "empty_column.notifications": "Још увек немате никаква обавештења. Када други људи буду у интеракцији са вама, видећете то овде.", @@ -404,20 +403,11 @@ "link_preview.author": "По {name}", "link_preview.more_from_author": "Више од {name}", "link_preview.shares": "{count, plural, one {{counter} објава} few {{counter} објаве} other {{counter} објава}}", - "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.followed": "Сваком праћеном кориснику", "lists.replies_policy.list": "Члановима листе", "lists.replies_policy.none": "Никоме", - "lists.replies_policy.title": "Прикажи одговоре:", - "lists.search": "Претражи међу људима које пратите", - "lists.subheading": "Ваше листе", "load_pending": "{count, plural, one {# нова ставка} few {# нове ставке} other {# нових ставки}}", "loading_indicator.label": "Учитавање…", "moved_to_account_banner.text": "Ваш налог {disabledAccount} је тренутно онемогућен јер сте прешли на {movedToAccount}.", diff --git a/app/javascript/mastodon/locales/sv.json b/app/javascript/mastodon/locales/sv.json index 7824d07629..0fb714d9a7 100644 --- a/app/javascript/mastodon/locales/sv.json +++ b/app/javascript/mastodon/locales/sv.json @@ -82,11 +82,30 @@ "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.most_used_hashtag.none": "Inga", + "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.", @@ -271,9 +290,8 @@ "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.", "empty_column.notification_requests": "Allt klart! Det finns inget mer här. När du får nya meddelanden visas de här enligt dina inställningar.", "empty_column.notifications": "Du har inga meddelanden än. Interagera med andra för att starta konversationen.", @@ -383,7 +401,7 @@ "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.", @@ -405,37 +423,37 @@ "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.compose": "för att fokusera skrivfältet", + "keyboard_shortcuts.column": "Fokusera kolumn", + "keyboard_shortcuts.compose": "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", "keyboard_shortcuts.federated": "Öppna federerad tidslinje", "keyboard_shortcuts.heading": "Tangentbordsgenvägar", - "keyboard_shortcuts.home": "för att öppna Hem-tidslinjen", + "keyboard_shortcuts.home": "Öppna Hemtidslinjen", "keyboard_shortcuts.hotkey": "Kommando", - "keyboard_shortcuts.legend": "för att visa denna översikt", - "keyboard_shortcuts.local": "för att öppna Lokal tidslinje", - "keyboard_shortcuts.mention": "för att nämna skaparen", + "keyboard_shortcuts.legend": "Visa denna översikt", + "keyboard_shortcuts.local": "Öppna lokal tidslinje", + "keyboard_shortcuts.mention": "Nämna skaparen", "keyboard_shortcuts.muted": "Öppna listan över tystade användare", - "keyboard_shortcuts.my_profile": "för att öppna din profil", - "keyboard_shortcuts.notifications": "för att öppna Meddelanden", - "keyboard_shortcuts.open_media": "öppna media", + "keyboard_shortcuts.my_profile": "Öppna din profil", + "keyboard_shortcuts.notifications": "Öppna meddelanden", + "keyboard_shortcuts.open_media": "Öppna media", "keyboard_shortcuts.pinned": "Öppna listan över fästa inlägg", - "keyboard_shortcuts.profile": "för att öppna skaparens profil", + "keyboard_shortcuts.profile": "Öppna författarens profil", "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.requests": "Öppna följförfrågningar", + "keyboard_shortcuts.search": "Fokusera sökfältet", + "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", @@ -446,20 +464,11 @@ "link_preview.author": "Av {name}", "link_preview.more_from_author": "Mer från {name}", "link_preview.shares": "{count, plural, one {{counter} inlägg} other {{counter} inlägg}}", - "lists.account.add": "Lägg till i lista", - "lists.account.remove": "Ta bort från lista", "lists.delete": "Radera lista", "lists.edit": "Redigera lista", - "lists.edit.submit": "Ändra titel", - "lists.exclusive": "Dölj dessa inlägg från hemflödet", - "lists.new.create": "Lägg till lista", - "lists.new.title_placeholder": "Ny listrubrik", "lists.replies_policy.followed": "Alla användare som följs", "lists.replies_policy.list": "Medlemmar i listan", "lists.replies_policy.none": "Ingen", - "lists.replies_policy.title": "Visa svar till:", - "lists.search": "Sök bland personer du följer", - "lists.subheading": "Dina listor", "load_pending": "{count, plural, one {# nytt objekt} other {# nya objekt}}", "loading_indicator.label": "Laddar…", "media_gallery.hide": "Dölj", @@ -508,6 +517,8 @@ "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", @@ -617,11 +628,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", @@ -642,7 +653,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", @@ -733,8 +744,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", @@ -829,7 +840,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", diff --git a/app/javascript/mastodon/locales/ta.json b/app/javascript/mastodon/locales/ta.json index 87d6660f05..1465fcb51f 100644 --- a/app/javascript/mastodon/locales/ta.json +++ b/app/javascript/mastodon/locales/ta.json @@ -174,7 +174,6 @@ "empty_column.hashtag": "இந்த சிட்டையில் இதுவரை ஏதும் இல்லை.", "empty_column.home": "உங்கள் மாஸ்டடான் வீட்டில் யாரும் இல்லை. {public} -இல் சென்று பார்க்கவும், அல்லது தேடல் கருவியைப் பயன்படுத்திப் பிற பயனர்களைக் கண்டடையவும்.", "empty_column.list": "இந்தப் பட்டியலில் இதுவரை ஏதும் இல்லை. இப்பட்டியலின் உறுப்பினர்கள் புதிய டூட்டுகளை இட்டால். அவை இங்கே காண்பிக்கப்படும்.", - "empty_column.lists": "இதுவரை நீங்கள் எந்தப் பட்டியலையும் உருவாக்கவில்லை. உருவாக்கினால், அது இங்கே காண்பிக்கப்படும்.", "empty_column.mutes": "நீங்கள் இதுவரை எந்தப் பயனர்களையும் முடக்கியிருக்கவில்லை.", "empty_column.notifications": "உங்களுக்காக எந்த அறிவிப்புகளும் இல்லை. உரையாடலைத் துவங்க பிறரைத் தொடர்புகொள்ளவும்.", "empty_column.public": "இங்கு எதுவும் இல்லை! இவ்விடத்தை நிரப்ப எதையேனும் எழுதவும், அல்லது வேறு சர்வர்களில் உள்ள பயனர்களைப் பின்தொடரவும்", @@ -242,15 +241,8 @@ "lightbox.close": "நெருக்கமாக", "lightbox.next": "அடுத்த", "lightbox.previous": "சென்ற", - "lists.account.add": "பட்டியலில் சேர்", - "lists.account.remove": "பட்டியலில் இருந்து அகற்று", "lists.delete": "பட்டியலை நீக்கு", "lists.edit": "பட்டியலை திருத்து", - "lists.edit.submit": "தலைப்பு மாற்றவும்", - "lists.new.create": "பட்டியலில் சேர்", - "lists.new.title_placeholder": "புதிய பட்டியல் தலைப்பு", - "lists.search": "நீங்கள் பின்தொடரும் நபர்கள் மத்தியில் தேடுதல்", - "lists.subheading": "உங்கள் பட்டியல்கள்", "load_pending": "{count, plural,one {# புதியது}other {# புதியவை}}", "navigation_bar.blocks": "தடுக்கப்பட்ட பயனர்கள்", "navigation_bar.bookmarks": "அடையாளக்குறிகள்", diff --git a/app/javascript/mastodon/locales/te.json b/app/javascript/mastodon/locales/te.json index 40fbd7f7bd..d58a691635 100644 --- a/app/javascript/mastodon/locales/te.json +++ b/app/javascript/mastodon/locales/te.json @@ -106,7 +106,6 @@ "empty_column.hashtag": "ఇంకా హాష్ ట్యాగ్లో ఏమీ లేదు.", "empty_column.home": "మీ హోమ్ కాలక్రమం ఖాళీగా ఉంది! {Public} ను సందర్శించండి లేదా ఇతర వినియోగదారులను కలుసుకోవడానికి మరియు అన్వేషణ కోసం శోధనను ఉపయోగించండి.", "empty_column.list": "ఇంకా ఈ జాబితాలో ఏదీ లేదు. ఈ జాబితాలోని సభ్యులు కొత్త స్టేటస్ లను పోస్ట్ చేసినప్పుడు, అవి ఇక్కడ కనిపిస్తాయి.", - "empty_column.lists": "మీకు ఇంకా జాబితాలు ఏమీ లేవు. మీరు ఒకటి సృష్టించగానే, అది ఇక్కడ కనబడుతుంది.", "empty_column.mutes": "మీరు ఇంకా ఏ వినియోగదారులనూ మ్యూట్ చేయలేదు.", "empty_column.notifications": "మీకు ఇంకా ఏ నోటిఫికేషన్లు లేవు. సంభాషణను ప్రారంభించడానికి ఇతరులతో ప్రతిస్పందించండి.", "empty_column.public": "ఇక్కడ ఏమీ లేదు! దీన్ని నింపడానికి బహిరంగంగా ఏదైనా వ్రాయండి, లేదా ఇతర సేవికల నుండి వినియోగదారులను అనుసరించండి", @@ -158,15 +157,8 @@ "lightbox.close": "మూసివేయు", "lightbox.next": "తరువాత", "lightbox.previous": "మునుపటి", - "lists.account.add": "జాబితాకు జోడించు", - "lists.account.remove": "జాబితా నుండి తొలగించు", "lists.delete": "జాబితాను తొలగించు", "lists.edit": "జాబితాను సవరించు", - "lists.edit.submit": "శీర్షిక మార్చు", - "lists.new.create": "జాబితాను జోడించు", - "lists.new.title_placeholder": "కొత్త జాబితా శీర్షిక", - "lists.search": "మీరు అనుసరించే వ్యక్తులలో శోధించండి", - "lists.subheading": "మీ జాబితాలు", "navigation_bar.blocks": "బ్లాక్ చేయబడిన వినియోగదారులు", "navigation_bar.community_timeline": "స్థానిక కాలక్రమం", "navigation_bar.compose": "కొత్త టూట్ను రాయండి", diff --git a/app/javascript/mastodon/locales/th.json b/app/javascript/mastodon/locales/th.json index b0ad6e1c66..b9fe9cf33b 100644 --- a/app/javascript/mastodon/locales/th.json +++ b/app/javascript/mastodon/locales/th.json @@ -44,7 +44,7 @@ "account.joined_short": "เข้าร่วมเมื่อ", "account.languages": "เปลี่ยนภาษาที่บอกรับ", "account.link_verified_on": "ตรวจสอบความเป็นเจ้าของของลิงก์นี้เมื่อ {date}", - "account.locked_info": "สถานะความเป็นส่วนตัวของบัญชีนี้ถูกตั้งค่าเป็นล็อค เจ้าของตรวจสอบด้วยตนเองว่าใครสามารถติดตามพวกเขาได้", + "account.locked_info": "มีการตั้งสถานะความเป็นส่วนตัวของบัญชีนี้เป็นล็อคอยู่ เจ้าของตรวจทานผู้ที่สามารถติดตามเขาด้วยตนเอง", "account.media": "สื่อ", "account.mention": "กล่าวถึง @{name}", "account.moved_to": "{name} ได้ระบุว่าบัญชีใหม่ของเขาในตอนนี้คือ:", @@ -87,6 +87,13 @@ "alert.unexpected.title": "อุปส์!", "alt_text_badge.title": "ข้อความแสดงแทน", "announcement.announcement": "ประกาศ", + "annual_report.summary.followers.followers": "ผู้ติดตาม", + "annual_report.summary.highlighted_post.by_favourites": "โพสต์ที่ได้รับการชื่นชอบมากที่สุด", + "annual_report.summary.highlighted_post.by_reblogs": "โพสต์ที่ได้รับการดันมากที่สุด", + "annual_report.summary.highlighted_post.by_replies": "โพสต์ที่มีการตอบกลับมากที่สุด", + "annual_report.summary.new_posts.new_posts": "โพสต์ใหม่", + "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} เคารพการตัดสินใจของคุณ อย่างไรก็ตาม ไม่รับประกันการปฏิบัติตามข้อกำหนดเนื่องจากเซิร์ฟเวอร์บางแห่งอาจจัดการการปิดกั้นแตกต่างกัน โพสต์สาธารณะอาจยังคงปรากฏแก่ผู้ใช้ที่ไม่ได้เข้าสู่ระบบ", @@ -97,7 +104,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": "คัดลอกรายงานข้อผิดพลาด", @@ -273,7 +280,6 @@ "empty_column.hashtag": "ยังไม่มีสิ่งใดในแฮชแท็กนี้", "empty_column.home": "เส้นเวลาหน้าแรกของคุณว่างเปล่า! ติดตามผู้คนเพิ่มเติมเพื่อเติมเส้นเวลาให้เต็ม", "empty_column.list": "ยังไม่มีสิ่งใดในรายการนี้ เมื่อสมาชิกของรายการนี้โพสต์โพสต์ใหม่ โพสต์จะปรากฏที่นี่", - "empty_column.lists": "คุณยังไม่มีรายการใด ๆ เมื่อคุณสร้างรายการ รายการจะปรากฏที่นี่", "empty_column.mutes": "คุณยังไม่ได้ซ่อนผู้ใช้ใด ๆ", "empty_column.notification_requests": "โล่งทั้งหมด! ไม่มีสิ่งใดที่นี่ เมื่อคุณได้รับการแจ้งเตือนใหม่ การแจ้งเตือนจะปรากฏที่นี่ตามการตั้งค่าของคุณ", "empty_column.notifications": "คุณยังไม่มีการแจ้งเตือนใด ๆ เมื่อผู้คนอื่น ๆ โต้ตอบกับคุณ คุณจะเห็นการแจ้งเตือนที่นี่", @@ -386,6 +392,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?", @@ -397,6 +404,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 {# นาที}}", @@ -444,20 +452,11 @@ "link_preview.author": "โดย {name}", "link_preview.more_from_author": "เพิ่มเติมจาก {name}", "link_preview.shares": "{count, plural, other {{counter} โพสต์}}", - "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.followed": "ผู้ใช้ใด ๆ ที่ติดตาม", "lists.replies_policy.list": "สมาชิกของรายการ", "lists.replies_policy.none": "ไม่มีใคร", - "lists.replies_policy.title": "แสดงการตอบกลับแก่:", - "lists.search": "ค้นหาในหมู่ผู้คนที่คุณติดตาม", - "lists.subheading": "รายการของคุณ", "load_pending": "{count, plural, other {# รายการใหม่}}", "loading_indicator.label": "กำลังโหลด…", "media_gallery.hide": "ซ่อน", @@ -506,6 +505,7 @@ "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.view": "ดู #Wrapstodon", "notification.favourite": "{name} ได้ชื่นชอบโพสต์ของคุณ", "notification.favourite.name_and_others_with_link": "{name} และ {count, plural, other {# อื่น ๆ}} ได้ชื่นชอบโพสต์ของคุณ", "notification.follow": "{name} ได้ติดตามคุณ", @@ -855,11 +855,11 @@ "upload_error.poll": "ไม่อนุญาตการอัปโหลดไฟล์โดยมีการสำรวจความคิดเห็น", "upload_form.audio_description": "อธิบายสำหรับผู้ที่สูญเสียการได้ยิน", "upload_form.description": "อธิบายสำหรับผู้คนที่พิการทางการมองเห็นหรือมีสายตาเลือนราง", - "upload_form.drag_and_drop.instructions": "หากต้องการเลือกไฟล์สื่อ ให้กดปุ่มที Space หรือ Enter บนแป้นพิมพ์ เมื่อเลือกไฟล์ได้แล้ว ก็สามารถใช้ปุ่มลูกศรเพื่อเลื่อนไฟล์ไปในทิศทางที่ต้องการได้ เมื่อต้องการวางไฟล์ในตำแหน่งใหม่ ให้กดปุ่ม Space หรือ Enter ดูอีกครั้ง หรือหากต้องการยกเลิกการเลือก ให้กดปุ่ม Esc ได้", - "upload_form.drag_and_drop.on_drag_cancel": "การลากไฟล์นั้นหยุดชะงัก ไฟล์ที่กำลังแนบมาถูกยกเลิก {item} ได้ถูกลบทิ้งแล้ว", - "upload_form.drag_and_drop.on_drag_end": "ไฟล์แนบ {item} ได้ถูกยกเลิกแล้ว", - "upload_form.drag_and_drop.on_drag_over": "ไฟล์แนบ {item} ได้ถูกย้ายไปแล้ว", - "upload_form.drag_and_drop.on_drag_start": "ได้รับไฟล์แนบเรียบร้อยแล้ว {item}.", + "upload_form.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 2cf7f1929a..d526c271c6 100644 --- a/app/javascript/mastodon/locales/tok.json +++ b/app/javascript/mastodon/locales/tok.json @@ -191,7 +191,6 @@ "empty_column.hashtag": "ala li lon toki ni", "empty_column.home": "ala a li lon lipu open sina! sina wile lon e ijo lon ni la o kute e jan pi toki suli.", "empty_column.list": "ala li lon kulupu lipu ni. jan pi kulupu lipu ni li toki sin la toki ni li lon ni.", - "empty_column.lists": "sina jo ala e kulupu lipu. sina pali sin e kulupu lipu la ona li lon ni.", "empty_column.mutes": "jan ala li len tawa sina.", "error.unexpected_crash.explanation": "ilo li ken ala pana e lipu ni. ni li ken tan pakala mi tan pakala pi ilo sina.", "errors.unexpected_crash.report_issue": "o toki e pakala tawa lawa", @@ -253,17 +252,11 @@ "lightbox.next": "sinpin", "lightbox.previous": "monsi", "link_preview.author": "tan {name}", - "lists.account.add": "o pana tawa kulupu lipu", - "lists.account.remove": "o weka tan kulupu lipu", "lists.delete": "o weka e kulupu lipu", "lists.edit": "o ante e kulupu lipu", - "lists.edit.submit": "o ante e nimi", - "lists.exclusive": "o len e toki lon lipu open", - "lists.new.create": "o sin e kulupu lipu", "lists.replies_policy.followed": "jan kute ale", "lists.replies_policy.list": "jan pi kulupu ni taso", "lists.replies_policy.none": "jan ala", - "lists.subheading": "kulupu lipu sina", "load_pending": "{count, plural, other {ijo sin #}}", "loading_indicator.label": "ni li kama…", "mute_modal.title": "sina wile ala wile kute e jan ni?", diff --git a/app/javascript/mastodon/locales/tr.json b/app/javascript/mastodon/locales/tr.json index 5ac5a3368b..7851da5ecb 100644 --- a/app/javascript/mastodon/locales/tr.json +++ b/app/javascript/mastodon/locales/tr.json @@ -81,12 +81,31 @@ "admin.impact_report.instance_followers": "Kullanıcılarımızın kaybedeceği takipçiler", "admin.impact_report.instance_follows": "Kullanıcılarının kaybedeceği takipçiler", "admin.impact_report.title": "Etki özeti", - "alert.rate_limited.message": "Lütfen {retry_time, time, medium} saatinden sonra tekrar deneyin.", + "alert.rate_limited.message": "Lütfen sonra tekrar deneyin {retry_time, time, medium}.", "alert.rate_limited.title": "Aşırı istek gönderildi", "alert.unexpected.message": "Beklenmedik bir hata oluştu.", "alert.unexpected.title": "Hay aksi!", "alt_text_badge.title": "Alternatif metin", "announcement.announcement": "Duyuru", + "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.most_used_hashtag.none": "Yok", + "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.", @@ -121,13 +140,16 @@ "column.blocks": "Engellenen kullanıcılar", "column.bookmarks": "Yer İşaretleri", "column.community": "Yerel ağ akışı", + "column.create_list": "Liste oluştur", "column.direct": "Özel değinmeler", "column.directory": "Profillere göz at", "column.domain_blocks": "Engellenen alan adları", + "column.edit_list": "Listeyi düzenle", "column.favourites": "Gözdelerin", "column.firehose": "Anlık Akışlar", "column.follow_requests": "Takip istekleri", "column.home": "Anasayfa", + "column.list_members": "Liste üyelerini yönet", "column.lists": "Listeler", "column.mutes": "Sessize alınmış kullanıcılar", "column.notifications": "Bildirimler", @@ -273,7 +295,6 @@ "empty_column.hashtag": "Henüz bu etikete sahip hiçbir gönderi yok.", "empty_column.home": "Ana zaman tünelin boş! Akışını doldurmak için daha fazla kişiyi takip ediniz.", "empty_column.list": "Henüz bu listede bir şey yok. Bu listenin üyeleri bir şey paylaşığında burada gözükecek.", - "empty_column.lists": "Henüz listen yok. Liste oluşturduğunda burada görünür.", "empty_column.mutes": "Henüz bir kullanıcıyı sessize almadınız.", "empty_column.notification_requests": "Hepsi tamam! Burada yeni bir şey yok. Yeni bildirim aldığınızda, ayarlarınıza göre burada görüntülenecekler.", "empty_column.notifications": "Henüz bildiriminiz yok. Sohbete başlamak için başkalarıyla etkileşim kurun.", @@ -339,7 +360,7 @@ "footer.privacy_policy": "Gizlilik politikası", "footer.source_code": "Kaynak kodu görüntüle", "footer.status": "Durum", - "generic.saved": "Kaydedildi", + "generic.saved": "Kaydet", "getting_started.heading": "Başlarken", "hashtag.column_header.tag_mode.all": "ve {additional}", "hashtag.column_header.tag_mode.any": "ya da {additional}", @@ -446,20 +467,31 @@ "link_preview.author": "Yazar: {name}", "link_preview.more_from_author": "{name} kişisinden daha fazlası", "link_preview.shares": "{count, plural, one {{counter} gönderi} other {{counter} gönderi}}", - "lists.account.add": "Listeye ekle", - "lists.account.remove": "Listeden kaldır", + "lists.add_member": "Ekle", + "lists.add_to_list": "Listeye ekle", + "lists.add_to_lists": "{name} kişisini listelere ekle", + "lists.create": "Oluştur", + "lists.create_a_list_to_organize": "Anasayfa akışınızı düzenlemek için yeni bir liste oluşturun", + "lists.create_list": "Liste oluştur", "lists.delete": "Listeyi sil", + "lists.done": "Tamamlandı", "lists.edit": "Listeleri düzenle", - "lists.edit.submit": "Başlığı değiştir", - "lists.exclusive": "Bu gönderileri Anasayfadan gizle", - "lists.new.create": "Liste ekle", - "lists.new.title_placeholder": "Yeni liste başlığı", + "lists.exclusive": "Anasayfada üyeleri gizle", + "lists.exclusive_hint": "Birisi bu listede yer alıyorsa, gönderilerini iki kez görmekten kaçınmak için onu anasayfa akışınızda gizleyin.", + "lists.find_users_to_add": "Eklenecek kullanıcıları bul", + "lists.list_members": "Liste üyeleri", + "lists.list_members_count": "{count, plural, one {# üye} other {# üye}}", + "lists.list_name": "Liste adı", + "lists.new_list_name": "Yeni liste adı", + "lists.no_lists_yet": "Henüz liste yok.", + "lists.no_members_yet": "Henüz üye yok.", + "lists.no_results_found": "Sonuç bulunamadı.", + "lists.remove_member": "Kaldır", "lists.replies_policy.followed": "Takip edilen herhangi bir kullanıcı", "lists.replies_policy.list": "Listenin üyeleri", "lists.replies_policy.none": "Hiç kimse", - "lists.replies_policy.title": "Yanıtları göster:", - "lists.search": "Takip ettiğiniz kişiler arasından arayın", - "lists.subheading": "Listeleriniz", + "lists.save": "Kaydet", + "lists.search_placeholder": "Takip ettiğiniz kişilerde arama yapın", "load_pending": "{count, plural, one {# yeni öğe} other {# yeni öğe}}", "loading_indicator.label": "Yükleniyor…", "media_gallery.hide": "Gizle", @@ -508,6 +540,8 @@ "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", diff --git a/app/javascript/mastodon/locales/tt.json b/app/javascript/mastodon/locales/tt.json index 08bb7979a1..07b9decc10 100644 --- a/app/javascript/mastodon/locales/tt.json +++ b/app/javascript/mastodon/locales/tt.json @@ -275,16 +275,10 @@ "lightbox.previous": "Алдагы", "limited_account_hint.action": "Барыбер профильне күрсәтергә", "limited_account_hint.title": "Бу профильне модераторлар яшергән {domain}.", - "lists.account.add": "Исемлеккә өстәргә", - "lists.account.remove": "Исемлектән бетерергә", "lists.delete": "Исемлекне бетерегез", "lists.edit": "Исемлекне үзгәртү", - "lists.edit.submit": "Исемен үзгәртү", - "lists.new.create": "Исемлек өстәгез", - "lists.new.title_placeholder": "Яңа исемлек башламы", "lists.replies_policy.list": "Исемлек әгъзалары", "lists.replies_policy.none": "Һичкем", - "lists.subheading": "Исемлегегегезләр", "load_pending": "{count, plural, one {# яңа элемент} other {# яңа элемент}}", "navigation_bar.about": "Проект турында", "navigation_bar.blocks": "Блокланган кулланучылар", diff --git a/app/javascript/mastodon/locales/uk.json b/app/javascript/mastodon/locales/uk.json index fc396aa933..a88c588350 100644 --- a/app/javascript/mastodon/locales/uk.json +++ b/app/javascript/mastodon/locales/uk.json @@ -87,6 +87,25 @@ "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.most_used_hashtag.none": "Немає", + "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} поважати ваше рішення. Однак дотримання вимог не гарантується, оскільки деякі сервери можуть обробляти блоки по-різному. Загальнодоступні дописи все ще можуть бути видимими для користувачів, які не увійшли в систему.", @@ -121,9 +140,11 @@ "column.blocks": "Заблоковані користувачі", "column.bookmarks": "Закладки", "column.community": "Локальна стрічка", + "column.create_list": "Створити список", "column.direct": "Особисті згадки", "column.directory": "Переглянути профілі", "column.domain_blocks": "Заблоковані домени", + "column.edit_list": "Редагувати список", "column.favourites": "Уподобане", "column.firehose": "Стрічка новин", "column.follow_requests": "Запити на підписку", @@ -273,7 +294,6 @@ "empty_column.hashtag": "Дописів з цим гештеґом поки не існує.", "empty_column.home": "Ваша стрічка порожня! Підпишіться на інших, щоб її заповнити.", "empty_column.list": "Цей список порожній. Коли його учасники додадуть нові дописи, вони з'являться тут.", - "empty_column.lists": "У вас ще немає списків. Коли ви їх створите, вони з'являться тут.", "empty_column.mutes": "Ви ще не приховали жодного користувача.", "empty_column.notification_requests": "Усе чисто! Тут нічого немає. Коли ви отримаєте нові сповіщення, вони з'являться тут відповідно до ваших налаштувань.", "empty_column.notifications": "У вас ще немає сповіщень. Коли інші люди почнуть взаємодіяти з вами, ви побачите їх тут.", @@ -446,20 +466,11 @@ "link_preview.author": "Від {name}", "link_preview.more_from_author": "Більше від {name}", "link_preview.shares": "{count, plural, one {{counter} допис} few {{counter} дописи} many {{counter} дописів} other {{counter} допис}}", - "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.followed": "Будь-який відстежуваний користувач", "lists.replies_policy.list": "Учасники списку", "lists.replies_policy.none": "Ніхто", - "lists.replies_policy.title": "Показати відповіді для:", - "lists.search": "Шукати серед людей, на яких ви підписані", - "lists.subheading": "Ваші списки", "load_pending": "{count, plural, one {# новий елемент} other {# нових елементів}}", "loading_indicator.label": "Завантаження…", "media_gallery.hide": "Сховати", @@ -508,6 +519,8 @@ "notification.admin.report_statuses_other": "{name} повідомляє про {target}", "notification.admin.sign_up": "{name} приєдналися", "notification.admin.sign_up.name_and_others": "{name} та {count, plural, one {# інший} few {# інших} many {# інших} 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 {# інший} few {# інших} many {# інших} other {# інший}} вподобали ваш допис", "notification.follow": "{name} підписалися на вас", diff --git a/app/javascript/mastodon/locales/ur.json b/app/javascript/mastodon/locales/ur.json index cb5dfa63cd..476b8c2afb 100644 --- a/app/javascript/mastodon/locales/ur.json +++ b/app/javascript/mastodon/locales/ur.json @@ -162,7 +162,6 @@ "empty_column.hashtag": "ابھی یہ ہیش ٹیگ خالی ہے.", "empty_column.home": "آپ کا خانگی جدول خالی ہے! {public} دیکھیں یا شروعات کیلئے تلاش کریں اور دیگر صارفین سے ملیں.", "empty_column.list": "یہ فہرست ابھی خالی ہے. جب اس فہرست کے ارکان کچھ تحریر کریں گے، یہاں نظر آئے گا.", - "empty_column.lists": "ابھی آپ کی کوئی فہرست نہیں ہے. جب آپ بنائیں گے، وہ یہاں نظر آئے گی.", "empty_column.mutes": "آپ نے ابھی کسی صارف کو خاموش نہیں کیا ہے.", "empty_column.notifications": "ابھی آپ کیلئے کوئی اطلاعات نہیں ہیں. گفتگو شروع کرنے کے لئے دیگر صارفین سے متعامل ہوں.", "empty_column.public": "یہاں کچھ بھی نہیں ہے! کچھ عمومی تحریر کریں یا اس جگہ کو پُر کرنے کے لئے از خود دیگر سرورس کے صارفین کی پیروی کریں", diff --git a/app/javascript/mastodon/locales/uz.json b/app/javascript/mastodon/locales/uz.json index 6dae368ffc..dd67fc6c81 100644 --- a/app/javascript/mastodon/locales/uz.json +++ b/app/javascript/mastodon/locales/uz.json @@ -187,7 +187,6 @@ "empty_column.hashtag": "Ushbu hashtagda hali hech narsa yo'q.", "empty_column.home": "Bosh sahifa yilnomangiz boʻsh! Uni to'ldirish uchun ko'proq odamlarni kuzatib boring. {suggestions}", "empty_column.list": "Bu ro'yxatda hali hech narsa yo'q. Ushbu roʻyxat aʼzolari yangi xabarlarni nashr qilganda, ular shu yerda paydo boʻladi.", - "empty_column.lists": "Sizda hali hech qanday roʻyxat yoʻq. Uni yaratganingizda, u shu yerda paydo bo'ladi.", "empty_column.mutes": "Siz hali hech bir foydalanuvchining ovozini o‘chirmagansiz.", "empty_column.notifications": "Sizda hali hech qanday bildirishnoma yo‘q. Boshqa odamlar siz bilan muloqot qilganda, buni shu yerda ko'rasiz.", "empty_column.public": "Bu erda hech narsa yo'q! Biror narsani ochiq yozing yoki uni toʻldirish uchun boshqa serverlardagi foydalanuvchilarni qoʻlda kuzatib boring", @@ -288,16 +287,10 @@ "keyboard_shortcuts.up": "Roʻyxatda yuqoriga koʻtarish", "lightbox.close": "Yopish", "limited_account_hint.action": "Baribir profilni ko'rsatish", - "lists.account.add": "Ro‘yxatga qo‘shish", - "lists.account.remove": "Roʻyxatdan o'chirish", "lists.delete": "Roʻyxatni o'chirish", "lists.edit": "Roʻyxatni tahrirlash", - "lists.new.create": "Ro‘yxatga qo‘shish", "lists.replies_policy.list": "Ro'yxat a'zolari", "lists.replies_policy.none": "Hech kim", - "lists.replies_policy.title": "Javoblarni ko'rsatish:", - "lists.search": "Siz kuzatadigan odamlar orasidan qidiring", - "lists.subheading": "Sizning ro'yxatlaringiz", "load_pending": "{count, plural, one {# yangi element} other {# yangi elementlar}}", "moved_to_account_banner.text": "{movedToAccount} hisobiga koʻchganingiz uchun {disabledAccount} hisobingiz hozirda oʻchirib qoʻyilgan.", "navigation_bar.about": "Haqida", diff --git a/app/javascript/mastodon/locales/vi.json b/app/javascript/mastodon/locales/vi.json index 7ae955c1b0..4ba36e0545 100644 --- a/app/javascript/mastodon/locales/vi.json +++ b/app/javascript/mastodon/locales/vi.json @@ -87,6 +87,25 @@ "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.most_used_hashtag.none": "Không có", + "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.", @@ -121,13 +140,16 @@ "column.blocks": "Người đã chặn", "column.bookmarks": "Những tút đã lưu", "column.community": "Máy chủ này", + "column.create_list": "Tạo danh sách", "column.direct": "Nhắn riêng", "column.directory": "Tìm người cùng sở thích", "column.domain_blocks": "Máy chủ đã chặn", + "column.edit_list": "Sửa danh sách", "column.favourites": "Những tút đã thích", "column.firehose": "Bảng tin", "column.follow_requests": "Yêu cầu theo dõi", "column.home": "Trang chủ", + "column.list_members": "Quản lý danh sách", "column.lists": "Danh sách", "column.mutes": "Người đã ẩn", "column.notifications": "Thông báo", @@ -273,7 +295,6 @@ "empty_column.hashtag": "Chưa có tút nào dùng hashtag này.", "empty_column.home": "Trang chủ của bạn đang trống! Hãy theo dõi nhiều người hơn để lấp đầy.", "empty_column.list": "Chưa có tút. Khi những người trong danh sách này đăng tút mới, chúng sẽ xuất hiện ở đây.", - "empty_column.lists": "Bạn chưa tạo danh sách nào.", "empty_column.mutes": "Bạn chưa ẩn bất kỳ ai.", "empty_column.notification_requests": "Sạch sẽ! Không còn gì ở đây. Khi bạn nhận được thông báo mới, chúng sẽ xuất hiện ở đây theo cài đặt của bạn.", "empty_column.notifications": "Bạn chưa có thông báo nào. Hãy thử theo dõi hoặc nhắn riêng cho ai đó.", @@ -446,20 +467,32 @@ "link_preview.author": "Bởi {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", + "lists.add_member": "Thêm", + "lists.add_to_list": "Thêm vào danh sách", + "lists.add_to_lists": "Thêm {name} vào danh sách", + "lists.create": "Tạo", + "lists.create_a_list_to_organize": "Tạo một danh sách để sắp xếp Bảng tin", + "lists.create_list": "Tạo danh sách", "lists.delete": "Xóa danh sách", + "lists.done": "Xong", "lists.edit": "Sửa danh sách", - "lists.edit.submit": "Thay đổi tiêu đề", - "lists.exclusive": "Ẩn những tút này khỏi bảng tin", - "lists.new.create": "Tạo mới", - "lists.new.title_placeholder": "Tên danh sách", + "lists.exclusive": "Ẩn thành viên trong Trang chủ", + "lists.exclusive_hint": "Nếu ai đó có trong danh sách này, ẩn họ trong Trang chủ để tránh thấy tút của họ hiện trùng lặp.", + "lists.find_users_to_add": "Tìm người để thêm vào", + "lists.list_members": "Liệt kê các thành viên", + "lists.list_members_count": "{count, plural, other {# thành viên}}", + "lists.list_name": "Tên danh sách", + "lists.new_list_name": "Tên danh sách mới", + "lists.no_lists_yet": "Chưa có danh sách nào.", + "lists.no_members_yet": "Chưa có thành viên nào.", + "lists.no_results_found": "Không tìm thấy kết quả nào.", + "lists.remove_member": "Xóa", "lists.replies_policy.followed": "Người theo dõi", "lists.replies_policy.list": "Người trong danh sách", "lists.replies_policy.none": "Không ai", - "lists.replies_policy.title": "Cho phép trả lời với:", - "lists.search": "Tìm kiếm những người mà bạn quan tâm", - "lists.subheading": "Danh sách của bạn", + "lists.save": "Lưu", + "lists.search_placeholder": "Tìm những người mà bạn quan tâm", + "lists.show_replies_to": "Bao gồm lượt trả lời từ thành viên danh sách", "load_pending": "{count, plural, one {# tút mới} other {# tút mới}}", "loading_indicator.label": "Đang tải…", "media_gallery.hide": "Ẩn", @@ -508,6 +541,8 @@ "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", diff --git a/app/javascript/mastodon/locales/zgh.json b/app/javascript/mastodon/locales/zgh.json index 2fe63fe83c..73a626d59f 100644 --- a/app/javascript/mastodon/locales/zgh.json +++ b/app/javascript/mastodon/locales/zgh.json @@ -107,16 +107,9 @@ "keyboard_shortcuts.unfocus": "to un-focus compose textarea/search", "keyboard_shortcuts.up": "to move up in the list", "lightbox.close": "ⵔⴳⵍ", - "lists.account.add": "ⵔⵏⵓ ⵖⵔ ⵜⵍⴳⴰⵎⵜ", - "lists.account.remove": "ⴽⴽⵙ ⵙⴳ ⵜⵍⴳⴰⵎⵜ", "lists.delete": "ⴽⴽⵙ ⵜⴰⵍⴳⴰⵎⵜ", "lists.edit": "ⵙⵏⴼⵍ ⵜⴰⵍⴳⴰⵎⵜ", - "lists.edit.submit": "ⵙⵏⴼⵍ ⴰⵣⵡⵍ", - "lists.new.create": "ⵙⴽⵔ ⵜⴰⵍⴳⴰⵎⵜ", - "lists.new.title_placeholder": "ⴰⵣⵡⵍ ⵏ ⵜⵍⴳⴰⵎⵜ ⵜⴰⵎⴰⵢⵏⵓⵜ", "lists.replies_policy.none": "ⴰⵡⴷ ⵢⴰⵏ", - "lists.replies_policy.title": "ⵙⴽⵏ ⵜⵉⵔⴰⵔⵉⵏ ⵉ:", - "lists.subheading": "ⵜⵉⵍⴳⴰⵎⵉⵏ ⵏⵏⴽ", "load_pending": "{count, plural, one {# ⵓⴼⵔⴷⵉⵙ ⴰⵎⴰⵢⵏⵓ} other {# ⵉⴼⵔⴷⴰⵙ ⵉⵎⴰⵢⵏⵓⵜⵏ}}", "navigation_bar.compose": "Compose new toot", "navigation_bar.domain_blocks": "Hidden domains", diff --git a/app/javascript/mastodon/locales/zh-CN.json b/app/javascript/mastodon/locales/zh-CN.json index 603ec5d791..16d32417c6 100644 --- a/app/javascript/mastodon/locales/zh-CN.json +++ b/app/javascript/mastodon/locales/zh-CN.json @@ -11,7 +11,7 @@ "about.not_available": "此信息在当前服务器尚不可用。", "about.powered_by": "由 {mastodon} 驱动的去中心化社交媒体", "about.rules": "站点规则", - "account.account_note_header": "个人备注", + "account.account_note_header": "备注", "account.add_or_remove_from_list": "从列表中添加或移除", "account.badges.bot": "机器人", "account.badges.group": "群组", @@ -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} 的转嘟", @@ -87,9 +87,28 @@ "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.most_used_hashtag.none": "无", + "annual_report.summary.new_posts.new_posts": "新嘟嘟", + "annual_report.summary.percentile.text": "这使你跻身 Mastodon 用户的前", + "annual_report.summary.percentile.we_wont_tell_bernie": "我们打死也不会告诉扣税国王的(他知道的话要来收你发嘟税了)。", + "annual_report.summary.thanks": "感谢你这一年与 Mastodon 一路同行!", "attachments_list.unprocessed": "(未处理)", "audio.hide": "隐藏音频", - "block_modal.remote_users_caveat": "我们将要求服务器 {domain} 尊重您的决定。然而,我们无法保证对方一定遵从,因为某些服务器可能会以不同的方案处理屏蔽操作。公开嘟文仍然可能对未登录的用户可见。", + "block_modal.remote_users_caveat": "我们将要求服务器 {domain} 尊重你的决定。然而,我们无法保证对方一定遵从,因为某些服务器可能会以不同的方案处理屏蔽操作。公开嘟文仍然可能对未登录的用户可见。", "block_modal.show_less": "隐藏", "block_modal.show_more": "显示更多", "block_modal.they_cant_mention": "他们不能提及或关注你。", @@ -113,26 +132,29 @@ "bundle_modal_error.message": "载入这个组件时发生了错误。", "bundle_modal_error.retry": "重试", "closed_registrations.other_server_instructions": "基于 Mastodon 去中心化的特性,你可以在其它服务器上创建账号并继续与此服务器互动。", - "closed_registrations_modal.description": "您目前无法在 {domain} 上创建账户,但请注意,使用 Mastodon 并非需要专门在 {domain} 上注册账户。", + "closed_registrations_modal.description": "你目前无法在 {domain} 上创建账户,但请注意,使用 Mastodon 并非需要专门在 {domain} 上注册账户。", "closed_registrations_modal.find_another_server": "查找其他服务器", "closed_registrations_modal.preamble": "Mastodon 是去中心化的,所以无论在哪个实例创建账号,都可以关注本服务器上的账号并与之交流。 或者你还可以自己搭建实例!", "closed_registrations_modal.title": "注册 Mastodon 账号", "column.about": "关于", "column.blocks": "屏蔽的用户", "column.bookmarks": "书签", - "column.community": "本站时间轴", + "column.community": "本站时间线", + "column.create_list": "创建列表", "column.direct": "私下提及", "column.directory": "浏览用户资料", "column.domain_blocks": "已屏蔽的域名", + "column.edit_list": "编辑列表", "column.favourites": "喜欢", "column.firehose": "实时动态", "column.follow_requests": "关注请求", "column.home": "主页", + "column.list_members": "管理列表成员", "column.lists": "列表", "column.mutes": "已隐藏的用户", "column.notifications": "通知", "column.pins": "置顶嘟文", - "column.public": "跨站公共时间轴", + "column.public": "跨站公共时间线", "column_back_button.label": "返回", "column_header.hide_settings": "隐藏设置", "column_header.moveLeft_settings": "将此栏左移", @@ -142,8 +164,8 @@ "column_header.unpin": "取消置顶", "column_subheading.settings": "设置", "community.column_settings.local_only": "仅限本站", - "community.column_settings.media_only": "仅限媒体", - "community.column_settings.remote_only": "仅限外部", + "community.column_settings.media_only": "仅媒体", + "community.column_settings.remote_only": "仅外站", "compose.language.change": "更改语言", "compose.language.search": "搜索语言...", "compose.published.body": "嘟文已发布。", @@ -161,11 +183,11 @@ "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.publish_form": "新嘟文", "compose_form.reply": "回复", - "compose_form.save_changes": "更新", + "compose_form.save_changes": "更改", "compose_form.spoiler.marked": "移除内容警告", "compose_form.spoiler.unmarked": "添加内容警告", "compose_form.spoiler_placeholder": "内容警告 (可选)", @@ -173,15 +195,15 @@ "confirmations.block.confirm": "屏蔽", "confirmations.delete.confirm": "删除", "confirmations.delete.message": "你确定要删除这条嘟文吗?", - "confirmations.delete.title": "确认删除嘟文?", + "confirmations.delete.title": "是否删除嘟文?", "confirmations.delete_list.confirm": "删除", - "confirmations.delete_list.message": "确定永久删除这个列表吗?", - "confirmations.delete_list.title": "确认删除列表?", + "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.title": "确认覆盖嘟文?", + "confirmations.edit.title": "是否重写嘟文?", "confirmations.logout.confirm": "退出登录", "confirmations.logout.message": "确定要退出登录吗?", "confirmations.logout.title": "是否退出登录?", @@ -191,13 +213,13 @@ "confirmations.redraft.title": "是否删除并重新编辑嘟文?", "confirmations.reply.confirm": "回复", "confirmations.reply.message": "回复此消息将会覆盖当前正在编辑的信息。确定继续吗?", - "confirmations.reply.title": "确认覆盖嘟文?", + "confirmations.reply.title": "是否重写嘟文?", "confirmations.unfollow.confirm": "取消关注", "confirmations.unfollow.message": "你确定要取消关注 {name} 吗?", "confirmations.unfollow.title": "是否取消关注用户?", - "content_warning.hide": "隐藏嘟文", - "content_warning.show": "仍然显示", - "content_warning.show_more": "显示更多", + "content_warning.hide": "隐藏", + "content_warning.show": "展开", + "content_warning.show_more": "展开", "conversation.delete": "删除对话", "conversation.mark_as_read": "标记为已读", "conversation.open": "查看对话", @@ -210,19 +232,19 @@ "directory.new_arrivals": "新来者", "directory.recently_active": "最近活跃", "disabled_account_banner.account_settings": "账号设置", - "disabled_account_banner.text": "您的账号 {disabledAccount} 目前已被禁用。", + "disabled_account_banner.text": "你的账号 {disabledAccount} 目前已被禁用。", "dismissable_banner.community_timeline": "这些是来自 {domain} 用户的最新公开嘟文。", "dismissable_banner.dismiss": "忽略", "dismissable_banner.explore_links": "这些新闻故事正被本站和分布式网络上其他站点的用户谈论。", "dismissable_banner.explore_statuses": "这些是目前在社交网络上引起关注的嘟文。嘟文的喜欢和转嘟次数越多,排名越高。", "dismissable_banner.explore_tags": "这些标签正在本站和分布式网络上其他站点的用户中引起关注。", - "dismissable_banner.public_timeline": "这些是在 {domain} 上关注的人们最新发布的公开嘟文。", + "dismissable_banner.public_timeline": "这些是 {domain} 上的用户关注的人的最新公开嘟文。", "domain_block_modal.block": "屏蔽服务器", "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.title": "屏蔽该域名?", + "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": "你将不会看到此服务器上用户的嘟文或通知。", @@ -240,12 +262,12 @@ "domain_pill.your_server": "你的数字家园,你的所有嘟文都存放在这里。不喜欢这个服务器吗?随时带上你的关注者一起迁移到其它服务器。", "domain_pill.your_username": "你在这个服务器上的唯一标识符。不同服务器上可能会存在相同用户名的用户。", "embed.instructions": "复制下列代码以在你的网站中嵌入此嘟文。", - "embed.preview": "它会像这样显示出来:", + "embed.preview": "这是它的预览效果:", "emoji_button.activity": "活动", "emoji_button.clear": "清除", "emoji_button.custom": "自定义", "emoji_button.flags": "旗帜", - "emoji_button.food": "食物和饮料", + "emoji_button.food": "食物与饮料", "emoji_button.label": "插入表情符号", "emoji_button.nature": "自然", "emoji_button.not_found": "未找到匹配的表情符号", @@ -255,27 +277,26 @@ "emoji_button.search": "搜索…", "emoji_button.search_results": "搜索结果", "emoji_button.symbols": "符号", - "emoji_button.travel": "旅行和地点", - "empty_column.account_hides_collections": "该用户选择不提供此信息", + "emoji_button.travel": "旅行与地点", + "empty_column.account_hides_collections": "该用户选择不公开此信息", "empty_column.account_suspended": "账户已被停用", "empty_column.account_timeline": "这里没有嘟文!", "empty_column.account_unavailable": "个人资料不可用", "empty_column.blocks": "你还未屏蔽任何用户。", - "empty_column.bookmarked_statuses": "你还没有给任何嘟文添加过书签。在你添加书签后,嘟文就会显示在这里。", - "empty_column.community": "本站时间轴暂时没有内容,快写点什么让它动起来吧!", + "empty_column.bookmarked_statuses": "你还没有收藏任何嘟文。收藏后嘟文就会显示在这里。", + "empty_column.community": "本站时间线还没有内容,写点什么并公开发布,让它活跃起来吧!", "empty_column.direct": "你还未使用过私下提及。当你发出或者收到私下提及时,它将显示在此。", "empty_column.domain_blocks": "暂且没有被屏蔽的站点。", "empty_column.explore_statuses": "目前没有热门内容,稍后再来看看吧!", "empty_column.favourited_statuses": "你没有喜欢过任何嘟文。喜欢过的嘟文会显示在这里。", "empty_column.favourites": "没有人喜欢过这条嘟文。如果有人喜欢了,就会显示在这里。", "empty_column.follow_requests": "你还没有收到任何关注请求。当你收到一个关注请求时,它会出现在这里。", - "empty_column.followed_tags": "您还没有关注任何话题标签。 当您关注后,它们会出现在这里。", + "empty_column.followed_tags": "你还没有关注任何话题标签。 当你关注后,它们会出现在这里。", "empty_column.hashtag": "这个话题标签下暂时没有内容。", - "empty_column.home": "你的主页时间线是空的!快去关注更多人吧。 {suggestions}", + "empty_column.home": "你的主页时间线还没有内容!快去关注更多人吧。", "empty_column.list": "列表中还没有任何内容。当列表成员发布新嘟文时,它们将出现在这里。", - "empty_column.lists": "你还没有创建过列表。你创建的列表会在这里显示。", "empty_column.mutes": "你没有隐藏任何用户。", - "empty_column.notification_requests": "都看完了!这里没有任何未读通知。当收到新的通知时,它们将根据您的设置显示在这里。", + "empty_column.notification_requests": "都看完了!这里没有任何未读通知。当收到新的通知时,它们将根据你的设置显示在这里。", "empty_column.notifications": "你还没有收到过任何通知,快和其他用户互动吧。", "empty_column.public": "这里什么都没有!写一些公开的嘟文,或者关注其他服务器的用户后,这里就会有嘟文出现了", "error.unexpected_crash.explanation": "此页面无法正确显示,这可能是因为我们的代码中有错误,也可能是因为浏览器兼容问题。", @@ -314,7 +335,7 @@ "firehose.remote": "其他服务器", "follow_request.authorize": "同意", "follow_request.reject": "拒绝", - "follow_requests.unlocked_explanation": "尽管你没有锁嘟,但是 {domain} 的工作人员认为你也许会想手动审核审核这些账号的关注请求。", + "follow_requests.unlocked_explanation": "尽管你没有锁嘟,但是 {domain} 的站务人员认为你也许会想手动审核审核这些账号的关注请求。", "follow_suggestions.curated_suggestion": "站务人员精选", "follow_suggestions.dismiss": "不再显示", "follow_suggestions.featured_longer": "由 {domain} 管理团队精选", @@ -330,12 +351,12 @@ "follow_suggestions.similar_to_recently_followed_longer": "与你近期关注的用户相似", "follow_suggestions.view_all": "查看全部", "follow_suggestions.who_to_follow": "推荐关注", - "followed_tags": "关注的话题标签", + "followed_tags": "已关注话题标签", "footer.about": "关于", "footer.directory": "用户目录", "footer.get_app": "获取应用", "footer.invite": "邀请", - "footer.keyboard_shortcuts": "快捷键列表", + "footer.keyboard_shortcuts": "快捷键", "footer.privacy_policy": "隐私政策", "footer.source_code": "查看源代码", "footer.status": "状态", @@ -382,18 +403,18 @@ "ignore_notifications_modal.not_followers_title": "是否忽略未关注你的人的通知?", "ignore_notifications_modal.not_following_title": "是否忽略你未关注的人的通知?", "ignore_notifications_modal.private_mentions_title": "是否忽略不请自来的私下提及?", - "interaction_modal.description.favourite": "只需一个 Mastodon 账号,即可喜欢这条嘟文,对嘟文的作者展示您欣赏的态度,并保存嘟文以供日后使用。", + "interaction_modal.description.favourite": "只需一个 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.login.prompt": "你所入驻的服务器域名,如:mastodon.social", "interaction_modal.no_account_yet": "不在 Mastodon 上?", "interaction_modal.on_another_server": "在另一服务器", "interaction_modal.on_this_server": "在此服务器", - "interaction_modal.sign_in": "您尚未登录此服务器,您的账号托管在哪?", - "interaction_modal.sign_in_hint": "提示:这是您注册的网站,如果您不记得了,请在邮箱的收件箱中查找欢迎邮件。您还可以输入完整的用户名!(例如 @Mastodon@mastodon.social)", + "interaction_modal.sign_in": "你尚未登录此服务器,你的账号托管在哪?", + "interaction_modal.sign_in_hint": "提示:这是你注册的网站,如果你不记得了,请在邮箱的收件箱中查找欢迎邮件。你还可以输入完整的用户名!(例如 @Mastodon@mastodon.social)", "interaction_modal.title.favourite": "喜欢 {name} 的嘟文", "interaction_modal.title.follow": "关注 {name}", "interaction_modal.title.reblog": "转发 {name} 的嘟文", @@ -405,20 +426,20 @@ "keyboard_shortcuts.back": "返回上一页", "keyboard_shortcuts.blocked": "打开被屏蔽用户列表", "keyboard_shortcuts.boost": "转嘟", - "keyboard_shortcuts.column": "选择某栏", - "keyboard_shortcuts.compose": "选择输入框", + "keyboard_shortcuts.column": "选中某栏", + "keyboard_shortcuts.compose": "选中输入框", "keyboard_shortcuts.description": "说明", "keyboard_shortcuts.direct": "打开私下提及栏", "keyboard_shortcuts.down": "在列表中让光标下移", "keyboard_shortcuts.enter": "展开嘟文", "keyboard_shortcuts.favourite": "喜欢嘟文", "keyboard_shortcuts.favourites": "打开喜欢列表", - "keyboard_shortcuts.federated": "打开跨站时间轴", + "keyboard_shortcuts.federated": "打开跨站时间线", "keyboard_shortcuts.heading": "快捷键列表", - "keyboard_shortcuts.home": "打开主页时间轴", + "keyboard_shortcuts.home": "打开主页时间线", "keyboard_shortcuts.hotkey": "快捷键", "keyboard_shortcuts.legend": "显示此列表", - "keyboard_shortcuts.local": "打开本站时间轴", + "keyboard_shortcuts.local": "打开本站时间线", "keyboard_shortcuts.mention": "提及嘟文作者", "keyboard_shortcuts.muted": "打开隐藏用户列表", "keyboard_shortcuts.my_profile": "打开你的个人资料", @@ -428,7 +449,7 @@ "keyboard_shortcuts.profile": "打开作者的个人资料", "keyboard_shortcuts.reply": "回复嘟文", "keyboard_shortcuts.requests": "打开关注请求列表", - "keyboard_shortcuts.search": "选择搜索框", + "keyboard_shortcuts.search": "选中搜索框", "keyboard_shortcuts.spoilers": "显示或隐藏被折叠的正文", "keyboard_shortcuts.start": "打开“开始使用”栏", "keyboard_shortcuts.toggle_hidden": "显示或隐藏被折叠的正文", @@ -446,24 +467,36 @@ "link_preview.author": "由 {name}", "link_preview.more_from_author": "查看 {name} 的更多内容", "link_preview.shares": "{count, plural, other {{counter} 条嘟文}}", - "lists.account.add": "添加到列表", - "lists.account.remove": "从列表中移除", + "lists.add_member": "添加", + "lists.add_to_list": "添加到列表", + "lists.add_to_lists": "把 {name} 添加到列表", + "lists.create": "创建", + "lists.create_a_list_to_organize": "新建一个列表,整理你的主页动态", + "lists.create_list": "创建列表", "lists.delete": "删除列表", + "lists.done": "完成", "lists.edit": "编辑列表", - "lists.edit.submit": "更改标题", - "lists.exclusive": "在主页中隐藏这些嘟文", - "lists.new.create": "新建列表", - "lists.new.title_placeholder": "新列表的标题", - "lists.replies_policy.followed": "任何被关注的用户", + "lists.exclusive": "在主页动态中隐藏列表成员", + "lists.exclusive_hint": "列表成员的嘟文将不会在你的主页动态中显示,以免重复阅读。", + "lists.find_users_to_add": "查找要添加的用户", + "lists.list_members": "列表成员", + "lists.list_members_count": "{count, plural, other {# 人}}", + "lists.list_name": "列表名称", + "lists.new_list_name": "新列表名称", + "lists.no_lists_yet": "尚无列表。", + "lists.no_members_yet": "尚无成员。", + "lists.no_results_found": "未找到结果。", + "lists.remove_member": "移除", + "lists.replies_policy.followed": "所有我关注的用户", "lists.replies_policy.list": "列表成员", - "lists.replies_policy.none": "无人", - "lists.replies_policy.title": "显示回复:", - "lists.search": "搜索你关注的人", - "lists.subheading": "你的列表", + "lists.replies_policy.none": "不显示", + "lists.save": "保存", + "lists.search_placeholder": "搜索你关注的人", + "lists.show_replies_to": "列表成员回复的显示范围", "load_pending": "{count} 项", "loading_indicator.label": "加载中…", "media_gallery.hide": "隐藏", - "moved_to_account_banner.text": "您的账号 {disabledAccount} 已禁用,因为您已迁移到 {movedToAccount}。", + "moved_to_account_banner.text": "你的账号 {disabledAccount} 已禁用,因为你已迁移到 {movedToAccount}。", "mute_modal.hide_from_notifications": "从通知中隐藏", "mute_modal.hide_options": "隐藏选项", "mute_modal.indefinite": "直到我取消隐藏他们", @@ -478,7 +511,7 @@ "navigation_bar.advanced_interface": "在高级网页界面中打开", "navigation_bar.blocks": "已屏蔽的用户", "navigation_bar.bookmarks": "书签", - "navigation_bar.community_timeline": "本站时间轴", + "navigation_bar.community_timeline": "本站时间线", "navigation_bar.compose": "撰写新嘟文", "navigation_bar.direct": "私下提及", "navigation_bar.discover": "发现", @@ -488,19 +521,19 @@ "navigation_bar.filters": "忽略的关键词", "navigation_bar.follow_requests": "关注请求", "navigation_bar.followed_tags": "关注的话题标签", - "navigation_bar.follows_and_followers": "关注和粉丝", + "navigation_bar.follows_and_followers": "关注与关注者", "navigation_bar.lists": "列表", "navigation_bar.logout": "退出登录", - "navigation_bar.moderation": "运营", + "navigation_bar.moderation": "审核", "navigation_bar.mutes": "已隐藏的用户", "navigation_bar.opened_in_classic_interface": "嘟文、账户和其他特定页面默认在经典网页界面中打开。", "navigation_bar.personal": "个人", "navigation_bar.pins": "置顶嘟文", - "navigation_bar.preferences": "首选项", - "navigation_bar.public_timeline": "跨站公共时间轴", + "navigation_bar.preferences": "偏好设置", + "navigation_bar.public_timeline": "跨站公共时间线", "navigation_bar.search": "搜索", "navigation_bar.security": "安全", - "not_signed_in_indicator.not_signed_in": "您需要登录才能访问此资源。", + "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_other": "{name} 举报了来自 {target} 的 {count, plural, other {# 条嘟文}}", @@ -508,9 +541,11 @@ "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} 关注了你", "notification.follow.name_and_others": "{name} 和 {count, plural, other {另外 # 人}} 关注了你", "notification.follow_request": "{name} 向你发送了关注请求", "notification.follow_request.name_and_others": "{name} 和 {count, plural, other {另外 # 人}} 向你发送了关注请求", @@ -548,7 +583,7 @@ "notification_requests.confirm_dismiss_multiple.button": "{count, plural, other {拒绝请求}}", "notification_requests.confirm_dismiss_multiple.message": "你将要拒绝 {count, plural, other {# 个通知请求}}。你将无法再轻易访问{count, plural, other {它们}}。是否继续?", "notification_requests.confirm_dismiss_multiple.title": "是否拒绝通知请求?", - "notification_requests.dismiss": "拒绝", + "notification_requests.dismiss": "忽略", "notification_requests.dismiss_multiple": "{count, plural, other {拒绝 # 个请求…}}", "notification_requests.edit_selection": "编辑", "notification_requests.exit_selection": "完成", @@ -576,7 +611,7 @@ "notifications.column_settings.push": "推送通知", "notifications.column_settings.reblog": "转嘟:", "notifications.column_settings.show": "在通知栏显示", - "notifications.column_settings.sound": "播放音效", + "notifications.column_settings.sound": "播放提示音", "notifications.column_settings.status": "新嘟文:", "notifications.column_settings.unread_notifications.category": "未读通知", "notifications.column_settings.unread_notifications.highlight": "高亮显示未读通知", @@ -609,7 +644,7 @@ "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.filter_private_mentions_title": "不请自来的私下提及", "notifications.policy.title": "管理来自 … 的通知", "notifications_permission_banner.enable": "启用桌面通知", "notifications_permission_banner.how_to_control": "启用桌面通知以在 Mastodon 未打开时接收通知。你可以通过交互通过上面的 {icon} 按钮来精细控制可以发送桌面通知的交互类型。", @@ -619,9 +654,9 @@ "onboarding.actions.go_to_explore": "看看有什么新鲜事", "onboarding.actions.go_to_home": "转到主页动态", "onboarding.compose.template": "你好 #Mastodon!", - "onboarding.follows.empty": "很抱歉,现在无法显示任何结果。您可以尝试使用搜索或浏览探索页面来查找要关注的人,或稍后再试。", + "onboarding.follows.empty": "很抱歉,现在无法显示任何结果。你可以尝试使用搜索或浏览探索页面来查找要关注的人,或稍后再试。", "onboarding.follows.lead": "你管理你自己的家庭饲料。你关注的人越多,它将越活跃和有趣。 这些配置文件可能是一个很好的起点——你可以随时取消关注它们!", - "onboarding.follows.title": "定制您的主页动态", + "onboarding.follows.title": "定制你的主页动态", "onboarding.profile.discoverable": "让我的资料卡可被他人发现", "onboarding.profile.discoverable_hint": "当你选择在 Mastodon 上启用发现功能时,你的嘟文可能会出现在搜索结果和热门中,你的账户可能会被推荐给与你兴趣相似的人。", "onboarding.profile.display_name": "昵称", @@ -632,28 +667,28 @@ "onboarding.profile.save_and_continue": "保存并继续", "onboarding.profile.title": "设置个人资料", "onboarding.profile.upload_avatar": "上传头像", - "onboarding.profile.upload_header": "上传资料卡头图", + "onboarding.profile.upload_header": "上传个人资料背景横幅", "onboarding.share.lead": "让人们知道他们如何在Mastodon找到你!", "onboarding.share.message": "我是来自 #Mastodon 的 {username}!请在 {url} 关注我。", "onboarding.share.next_steps": "可能的下一步:", "onboarding.share.title": "分享你的个人资料", - "onboarding.start.lead": "你的新 Mastodon 帐户已准备好。下面是如何最大限度地利用它:", + "onboarding.start.lead": "你的新 Mastodon 账户已准备好。下面是如何最大限度地利用它:", "onboarding.start.skip": "想要在前面跳过吗?", "onboarding.start.title": "你已经成功了!", "onboarding.steps.follow_people.body": "You curate your own feed. Lets fill it with interesting people.", - "onboarding.steps.follow_people.title": "定制您的主页动态", + "onboarding.steps.follow_people.title": "定制你的主页动态", "onboarding.steps.publish_status.body": "向世界问声好吧。", "onboarding.steps.publish_status.title": "发布你的第一篇嘟文", "onboarding.steps.setup_profile.body": "Others are more likely to interact with you with a filled out profile.", "onboarding.steps.setup_profile.title": "自定义你的个人资料", - "onboarding.steps.share_profile.body": "Let your friends know how to find you on Mastodon!", + "onboarding.steps.share_profile.body": "让你的朋友知道怎样在 Mastodon 找到你", "onboarding.steps.share_profile.title": "分享你的个人资料", "onboarding.tips.2fa": "你知道吗?你可以在账户设置中配置双因素认证来保护账户安全。可以使用你选择的任何 TOTP 应用,无需电话号码!", "onboarding.tips.accounts_from_other_servers": "你知道吗? 既然Mastodon是去中心化的,你所看到的一些账户将被托管在你以外的服务器上。 但你可以无缝地与他们交互!他们的服务器在他们的用户名的后半部分!", - "onboarding.tips.migration": "您知道吗? 如果你觉得你喜欢 {domain} 不是您未来的一个伟大的服务器选择。 您可以移动到另一个 Mastodon 服务器而不失去您的关注者。 您甚至可以主持您自己的服务器!", - "onboarding.tips.verification": "您知道吗? 您可以通过在自己的网站上放置一个链接到您的 Mastodon 个人资料并将网站添加到您的个人资料来验证您的帐户。 无需收费或文书工作!", + "onboarding.tips.migration": "你知道吗?如果你将来觉得 {domain} 不再符合您的需求,你可以在保留现有关注者的情况下迁移至其他 Mastodon 服务器。你甚至可以部署自己的服务器!", + "onboarding.tips.verification": "你知道吗? 你可以通过在自己的网站上放置一个链接到你的 Mastodon 个人资料并将网站添加到你的个人资料来验证你的账户。 无需收费或文书工作!", "password_confirmation.exceeds_maxlength": "密码确认超过最大密码长度", - "password_confirmation.mismatching": "密码确认不匹配", + "password_confirmation.mismatching": "确认密码与密码不一致。", "picture_in_picture.restore": "恢复", "poll.closed": "已关闭", "poll.refresh": "刷新", @@ -666,13 +701,13 @@ "poll_button.add_poll": "发起投票", "poll_button.remove_poll": "移除投票", "privacy.change": "设置嘟文的可见范围", - "privacy.direct.long": "帖子中提到的每个人", + "privacy.direct.long": "嘟文中提到的每个人", "privacy.direct.short": "特定的人", - "privacy.private.long": "仅限您的关注者", + "privacy.private.long": "仅限你的关注者", "privacy.private.short": "关注者", - "privacy.public.long": "所有 Mastodon 内外的人", + "privacy.public.long": "", "privacy.public.short": "公开", - "privacy.unlisted.additional": "该模式的行为与“公开”完全相同,只是帖子不会出现在实时动态、话题标签、探索或 Mastodon 搜索中,即使你已在账户级设置中选择加入。", + "privacy.unlisted.additional": "该模式的行为与“公开”完全相同,只是嘟文不会出现在实时动态、话题标签、探索或 Mastodon 搜索中,即使你已在账户级设置中选择加入。", "privacy.unlisted.long": "减少算法影响", "privacy.unlisted.short": "悄悄公开", "privacy_policy.last_updated": "最近更新于 {date}", @@ -724,12 +759,12 @@ "report.reasons.violation": "违反服务器规则", "report.reasons.violation_description": "你清楚它违反了特定的规则", "report.rules.subtitle": "选择所有适用选项", - "report.rules.title": "哪些规则被违反了?", + "report.rules.title": "违反了哪些规则?", "report.statuses.subtitle": "选择所有适用选项", - "report.statuses.title": "是否有任何嘟文可以支持这一报告?", + "report.statuses.title": "是否有可以证实此举报的嘟文?", "report.submit": "提交", "report.target": "举报 {target}", - "report.thanks.take_action": "以下是您控制您在 Mastodon 上能看到哪些内容的选项:", + "report.thanks.take_action": "以下是你控制你在 Mastodon 上能看到哪些内容的选项:", "report.thanks.take_action_actionable": "在我们审阅这个问题时,你可以对 @{name} 采取行动", "report.thanks.title": "不想看到这个内容?", "report.thanks.title_actionable": "感谢提交举报,我们将会进行处理。", @@ -759,7 +794,7 @@ "search_popout.options": "搜索选项", "search_popout.quick_actions": "快捷操作", "search_popout.recent": "最近搜索", - "search_popout.specific_date": "指定日期", + "search_popout.specific_date": "具体日期", "search_popout.user": "用户", "search_results.accounts": "用户", "search_results.all": "全部", @@ -768,7 +803,7 @@ "search_results.see_all": "查看全部", "search_results.statuses": "嘟文", "search_results.title": "搜索 {q}", - "server_banner.about_active_users": "过去 30 天内使用此服务器的人(每月活跃用户)", + "server_banner.about_active_users": "过去 30 天内使用此服务器的人(月活跃用户)", "server_banner.active_users": "活跃用户", "server_banner.administered_by": "本站管理员:", "server_banner.is_one_of_many": "{domain} 是可用于参与联邦宇宙的众多独立 Mastodon 服务器之一。", @@ -793,7 +828,7 @@ "status.direct_indicator": "私下提及", "status.edit": "编辑", "status.edited": "最后编辑于 {date}", - "status.edited_x_times": "共编辑 {count, plural, one {{count} 次} other {{count} 次}}", + "status.edited_x_times": "共编辑 {count, plural, other {{count} 次}}", "status.embed": "获取嵌入代码", "status.favourite": "喜欢", "status.favourites": "{count, plural, other {次喜欢}}", @@ -813,7 +848,7 @@ "status.pinned": "置顶嘟文", "status.read_more": "查看更多", "status.reblog": "转嘟", - "status.reblog_private": "转嘟(可见者不变)", + "status.reblog_private": "以相同可见性转嘟", "status.reblogged_by": "{name} 转嘟了", "status.reblogs": "{count, plural, other {次转嘟}}", "status.reblogs.empty": "没有人转嘟过此条嘟文。如果有人转嘟了,就会显示在这里。", @@ -835,7 +870,7 @@ "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": "主页", @@ -865,7 +900,7 @@ "upload_form.edit": "编辑", "upload_form.thumbnail": "更改缩略图", "upload_form.video_description": "为听障人士和视障人士添加文字描述", - "upload_modal.analyzing_picture": "分析图片…", + "upload_modal.analyzing_picture": "正在分析图片…", "upload_modal.apply": "应用", "upload_modal.applying": "正在应用…", "upload_modal.choose_image": "选择图像", @@ -887,5 +922,5 @@ "video.mute": "静音", "video.pause": "暂停", "video.play": "播放", - "video.unmute": "解除禁音" + "video.unmute": "取消静音" } diff --git a/app/javascript/mastodon/locales/zh-HK.json b/app/javascript/mastodon/locales/zh-HK.json index 8acd6df078..ff0a124fcf 100644 --- a/app/javascript/mastodon/locales/zh-HK.json +++ b/app/javascript/mastodon/locales/zh-HK.json @@ -263,7 +263,6 @@ "empty_column.hashtag": "這個標籤暫時未有內容。", "empty_column.home": "你還沒有關注任何使用者。快看看{public},向其他使用者搭訕吧。", "empty_column.list": "這個列表暫時未有內容。", - "empty_column.lists": "你還沒有建立任何名單。這裡將會顯示你所建立的名單。", "empty_column.mutes": "你尚未靜音任何使用者。", "empty_column.notification_requests": "沒有新通知了!當有新通知時,會根據設定顯示在這裏。", "empty_column.notifications": "你沒有任何通知紀錄,快向其他用戶搭訕吧。", @@ -410,20 +409,11 @@ "limited_account_hint.action": "一律顯示個人檔案", "limited_account_hint.title": "此個人檔案已被 {domain} 的管理員隱藏。", "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.followed": "任何已關注的用戶", "lists.replies_policy.list": "列表中的用戶", "lists.replies_policy.none": "無人", - "lists.replies_policy.title": "顯示回應文章︰", - "lists.search": "從你關注的人搜索", - "lists.subheading": "列表", "load_pending": "{count, plural, other {# 個新項目}}", "loading_indicator.label": "載入中…", "media_gallery.hide": "隱藏", diff --git a/app/javascript/mastodon/locales/zh-TW.json b/app/javascript/mastodon/locales/zh-TW.json index a3de26ffc4..355fecac4c 100644 --- a/app/javascript/mastodon/locales/zh-TW.json +++ b/app/javascript/mastodon/locales/zh-TW.json @@ -87,6 +87,25 @@ "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.most_used_hashtag.none": "無最常用之主題標籤", + "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} 伺服器尊重您的決定。然而,我們無法保證所有伺服器皆會遵守,某些伺服器可能以不同方式處理封鎖。未登入之使用者仍可能看見您的公開嘟文。", @@ -121,13 +140,16 @@ "column.blocks": "已封鎖的使用者", "column.bookmarks": "書籤", "column.community": "本站時間軸", + "column.create_list": "建立列表", "column.direct": "私訊", "column.directory": "瀏覽個人檔案", "column.domain_blocks": "已封鎖網域", + "column.edit_list": "編輯列表", "column.favourites": "最愛", "column.firehose": "即時內容", "column.follow_requests": "跟隨請求", "column.home": "首頁", + "column.list_members": "管理列表成員", "column.lists": "列表", "column.mutes": "已靜音的使用者", "column.notifications": "推播通知", @@ -273,7 +295,6 @@ "empty_column.hashtag": "這個主題標籤下什麼也沒有。", "empty_column.home": "您的首頁時間軸是空的!跟隨更多人來將它填滿吧!", "empty_column.list": "這份列表下什麼也沒有。當此列表的成員嘟出新的嘟文時,它們將顯示於此。", - "empty_column.lists": "您還沒有新增任何列表。當您新增列表時,它將於此顯示。", "empty_column.mutes": "您尚未靜音任何使用者。", "empty_column.notification_requests": "清空啦!已經沒有任何推播通知。當您收到新推播通知時,它們將依照您的設定於此顯示。", "empty_column.notifications": "您還沒有收到任何推播通知,當您與別人開始互動時,它將於此顯示。", @@ -446,20 +467,32 @@ "link_preview.author": "來自 {name}", "link_preview.more_from_author": "來自 {name} 之更多內容", "link_preview.shares": "{count, plural, other {{count} 則嘟文}}", - "lists.account.add": "新增至列表", - "lists.account.remove": "自列表中移除", + "lists.add_member": "新增", + "lists.add_to_list": "新增至列表", + "lists.add_to_lists": "新增 {name} 至列表", + "lists.create": "建立", + "lists.create_a_list_to_organize": "建立新列表以整理您的首頁動態", + "lists.create_list": "建立列表", "lists.delete": "刪除列表", + "lists.done": "完成", "lists.edit": "編輯列表", - "lists.edit.submit": "變更標題", - "lists.exclusive": "於首頁時間軸隱藏這些嘟文", - "lists.new.create": "新增列表", - "lists.new.title_placeholder": "新列表標題", + "lists.exclusive": "在首頁隱藏成員", + "lists.exclusive_hint": "如果某個帳號於此列表中,將自您的首頁動態中隱藏此帳號,以防重複見到他們的嘟文。", + "lists.find_users_to_add": "尋找欲新增之使用者", + "lists.list_members": "列表成員", + "lists.list_members_count": "{count, plural, other {# 個成員}}", + "lists.list_name": "列表名稱", + "lists.new_list_name": "新列表名稱", + "lists.no_lists_yet": "尚無列表。", + "lists.no_members_yet": "尚無成員。", + "lists.no_results_found": "找不到結果。", + "lists.remove_member": "移除", "lists.replies_policy.followed": "任何跟隨的使用者", "lists.replies_policy.list": "列表成員", "lists.replies_policy.none": "沒有人", - "lists.replies_policy.title": "顯示回覆:", - "lists.search": "搜尋您跟隨之使用者", - "lists.subheading": "您的列表", + "lists.save": "儲存", + "lists.search_placeholder": "搜尋您跟隨的人", + "lists.show_replies_to": "包含來自列表成員的回覆到", "load_pending": "{count, plural, other {# 個新項目}}", "loading_indicator.label": "正在載入...", "media_gallery.hide": "隱藏", @@ -508,6 +541,8 @@ "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} 已跟隨您", 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/list.ts b/app/javascript/mastodon/models/list.ts new file mode 100644 index 0000000000..50b9896775 --- /dev/null +++ b/app/javascript/mastodon/models/list.ts @@ -0,0 +1,18 @@ +import type { RecordOf } from 'immutable'; +import { Record } from 'immutable'; + +import type { ApiListJSON } from 'mastodon/api_types/lists'; + +type ListShape = Required; // no changes from server shape +export type List = RecordOf; + +const ListFactory = Record({ + id: '', + title: '', + exclusive: false, + replies_policy: 'list', +}); + +export function createList(attributes: Partial) { + return ListFactory(attributes); +} diff --git a/app/javascript/mastodon/models/notification_group.ts b/app/javascript/mastodon/models/notification_group.ts index 09d407d449..d98e755aa2 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, @@ -16,6 +17,7 @@ export const NOTIFICATIONS_GROUP_MAX_AVATARS = 8; interface BaseNotificationGroup extends Omit { sampleAccountIds: string[]; + partial: boolean; } interface BaseNotificationWithStatus @@ -65,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; } @@ -86,7 +94,8 @@ export type NotificationGroup = | NotificationGroupModerationWarning | NotificationGroupSeveredRelationships | NotificationGroupAdminSignUp - | NotificationGroupAdminReport; + | NotificationGroupAdminReport + | NotificationGroupAnnualReport; function createReportFromJSON(reportJSON: ApiReportJSON): Report { const { target_account, ...report } = reportJSON; @@ -112,6 +121,12 @@ function createAccountRelationshipSeveranceEventFromJSON( return eventJson; } +function createAnnualReportEventFromJSON( + eventJson: ApiAnnualReportEventJSON, +): AnnualReportEvent { + return eventJson; +} + export function createNotificationGroupFromJSON( groupJson: ApiNotificationGroupJSON, ): NotificationGroup { @@ -128,6 +143,7 @@ export function createNotificationGroupFromJSON( return { statusId: statusId ?? undefined, sampleAccountIds, + partial: false, ...groupWithoutStatus, }; } @@ -136,27 +152,39 @@ export function createNotificationGroupFromJSON( return { report: createReportFromJSON(report), sampleAccountIds, + partial: false, ...groupWithoutTargetAccount, }; } case 'severed_relationships': return { ...group, + partial: false, event: createAccountRelationshipSeveranceEventFromJSON(group.event), sampleAccountIds, }; - case 'moderation_warning': { const { moderation_warning, ...groupWithoutModerationWarning } = group; return { ...groupWithoutModerationWarning, + partial: false, moderationWarning: createAccountWarningFromJSON(moderation_warning), sampleAccountIds, }; } + case 'annual_report': { + const { annual_report, ...groupWithoutAnnualReport } = group; + return { + ...groupWithoutAnnualReport, + partial: false, + annualReport: createAnnualReportEventFromJSON(annual_report), + sampleAccountIds, + }; + } default: return { sampleAccountIds, + partial: false, ...group, }; } @@ -164,17 +192,17 @@ export function createNotificationGroupFromJSON( export function createNotificationGroupFromNotificationJSON( notification: ApiNotificationJSON, -) { +): NotificationGroup { const group = { sampleAccountIds: [notification.account.id], group_key: notification.group_key, notifications_count: 1, - type: notification.type, most_recent_notification_id: notification.id, page_min_id: notification.id, page_max_id: notification.id, latest_page_notification_at: notification.created_at, - } as NotificationGroup; + partial: true, + }; switch (notification.type) { case 'favourite': @@ -183,12 +211,21 @@ export function createNotificationGroupFromNotificationJSON( case 'mention': case 'poll': case 'update': - return { ...group, statusId: notification.status?.id }; + return { + ...group, + type: notification.type, + statusId: notification.status?.id, + }; case 'admin.report': - return { ...group, report: createReportFromJSON(notification.report) }; + return { + ...group, + type: notification.type, + report: createReportFromJSON(notification.report), + }; case 'severed_relationships': return { ...group, + type: notification.type, event: createAccountRelationshipSeveranceEventFromJSON( notification.event, ), @@ -196,11 +233,15 @@ export function createNotificationGroupFromNotificationJSON( case 'moderation_warning': return { ...group, + type: notification.type, moderationWarning: createAccountWarningFromJSON( notification.moderation_warning, ), }; default: - return group; + return { + ...group, + type: notification.type, + }; } } diff --git a/app/javascript/mastodon/reducers/index.ts b/app/javascript/mastodon/reducers/index.ts index b92de0dbcd..aafee19c09 100644 --- a/app/javascript/mastodon/reducers/index.ts +++ b/app/javascript/mastodon/reducers/index.ts @@ -17,9 +17,7 @@ import filters from './filters'; import followed_tags from './followed_tags'; import height_cache from './height_cache'; import history from './history'; -import listAdder from './list_adder'; -import listEditor from './list_editor'; -import lists from './lists'; +import { listsReducer } from './lists'; import { markersReducer } from './markers'; import media_attachments from './media_attachments'; import meta from './meta'; @@ -69,9 +67,7 @@ const reducers = { notificationGroups: notificationGroupsReducer, height_cache, custom_emojis, - lists, - listEditor, - listAdder, + lists: listsReducer, filters, conversations, suggestions, diff --git a/app/javascript/mastodon/reducers/list_adder.js b/app/javascript/mastodon/reducers/list_adder.js deleted file mode 100644 index 0f61273aa6..0000000000 --- a/app/javascript/mastodon/reducers/list_adder.js +++ /dev/null @@ -1,48 +0,0 @@ -import { Map as ImmutableMap, List as ImmutableList } from 'immutable'; - -import { - LIST_ADDER_RESET, - LIST_ADDER_SETUP, - LIST_ADDER_LISTS_FETCH_REQUEST, - LIST_ADDER_LISTS_FETCH_SUCCESS, - LIST_ADDER_LISTS_FETCH_FAIL, - LIST_EDITOR_ADD_SUCCESS, - LIST_EDITOR_REMOVE_SUCCESS, -} from '../actions/lists'; - -const initialState = ImmutableMap({ - accountId: null, - - lists: ImmutableMap({ - items: ImmutableList(), - loaded: false, - isLoading: false, - }), -}); - -export default function listAdderReducer(state = initialState, action) { - switch(action.type) { - case LIST_ADDER_RESET: - return initialState; - case LIST_ADDER_SETUP: - return state.withMutations(map => { - map.set('accountId', action.account.get('id')); - }); - case LIST_ADDER_LISTS_FETCH_REQUEST: - return state.setIn(['lists', 'isLoading'], true); - case LIST_ADDER_LISTS_FETCH_FAIL: - return state.setIn(['lists', 'isLoading'], false); - case LIST_ADDER_LISTS_FETCH_SUCCESS: - return state.update('lists', lists => lists.withMutations(map => { - map.set('isLoading', false); - map.set('loaded', true); - map.set('items', ImmutableList(action.lists.map(item => item.id))); - })); - case LIST_EDITOR_ADD_SUCCESS: - return state.updateIn(['lists', 'items'], list => list.unshift(action.listId)); - case LIST_EDITOR_REMOVE_SUCCESS: - return state.updateIn(['lists', 'items'], list => list.filterNot(item => item === action.listId)); - default: - return state; - } -} diff --git a/app/javascript/mastodon/reducers/list_editor.js b/app/javascript/mastodon/reducers/list_editor.js deleted file mode 100644 index d3fd62adec..0000000000 --- a/app/javascript/mastodon/reducers/list_editor.js +++ /dev/null @@ -1,99 +0,0 @@ -import { Map as ImmutableMap, List as ImmutableList } from 'immutable'; - -import { - LIST_CREATE_REQUEST, - LIST_CREATE_FAIL, - LIST_CREATE_SUCCESS, - LIST_UPDATE_REQUEST, - LIST_UPDATE_FAIL, - LIST_UPDATE_SUCCESS, - LIST_EDITOR_RESET, - LIST_EDITOR_SETUP, - LIST_EDITOR_TITLE_CHANGE, - LIST_ACCOUNTS_FETCH_REQUEST, - LIST_ACCOUNTS_FETCH_SUCCESS, - LIST_ACCOUNTS_FETCH_FAIL, - LIST_EDITOR_SUGGESTIONS_READY, - LIST_EDITOR_SUGGESTIONS_CLEAR, - LIST_EDITOR_SUGGESTIONS_CHANGE, - LIST_EDITOR_ADD_SUCCESS, - LIST_EDITOR_REMOVE_SUCCESS, -} from '../actions/lists'; - -const initialState = ImmutableMap({ - listId: null, - isSubmitting: false, - isChanged: false, - title: '', - isExclusive: false, - - accounts: ImmutableMap({ - items: ImmutableList(), - loaded: false, - isLoading: false, - }), - - suggestions: ImmutableMap({ - value: '', - items: ImmutableList(), - }), -}); - -export default function listEditorReducer(state = initialState, action) { - switch(action.type) { - case LIST_EDITOR_RESET: - return initialState; - case LIST_EDITOR_SETUP: - return state.withMutations(map => { - map.set('listId', action.list.get('id')); - map.set('title', action.list.get('title')); - map.set('isExclusive', action.list.get('is_exclusive')); - map.set('isSubmitting', false); - }); - case LIST_EDITOR_TITLE_CHANGE: - return state.withMutations(map => { - map.set('title', action.value); - map.set('isChanged', true); - }); - case LIST_CREATE_REQUEST: - case LIST_UPDATE_REQUEST: - return state.withMutations(map => { - map.set('isSubmitting', true); - map.set('isChanged', false); - }); - case LIST_CREATE_FAIL: - case LIST_UPDATE_FAIL: - return state.set('isSubmitting', false); - case LIST_CREATE_SUCCESS: - case LIST_UPDATE_SUCCESS: - return state.withMutations(map => { - map.set('isSubmitting', false); - map.set('listId', action.list.id); - }); - case LIST_ACCOUNTS_FETCH_REQUEST: - return state.setIn(['accounts', 'isLoading'], true); - case LIST_ACCOUNTS_FETCH_FAIL: - return state.setIn(['accounts', 'isLoading'], false); - case LIST_ACCOUNTS_FETCH_SUCCESS: - return state.update('accounts', accounts => accounts.withMutations(map => { - map.set('isLoading', false); - map.set('loaded', true); - map.set('items', ImmutableList(action.accounts.map(item => item.id))); - })); - case LIST_EDITOR_SUGGESTIONS_CHANGE: - return state.setIn(['suggestions', 'value'], action.value); - case LIST_EDITOR_SUGGESTIONS_READY: - return state.setIn(['suggestions', 'items'], ImmutableList(action.accounts.map(item => item.id))); - case LIST_EDITOR_SUGGESTIONS_CLEAR: - return state.update('suggestions', suggestions => suggestions.withMutations(map => { - map.set('items', ImmutableList()); - map.set('value', ''); - })); - case LIST_EDITOR_ADD_SUCCESS: - return state.updateIn(['accounts', 'items'], list => list.unshift(action.accountId)); - case LIST_EDITOR_REMOVE_SUCCESS: - return state.updateIn(['accounts', 'items'], list => list.filterNot(item => item === action.accountId)); - default: - return state; - } -} diff --git a/app/javascript/mastodon/reducers/lists.js b/app/javascript/mastodon/reducers/lists.js deleted file mode 100644 index 2a797772b3..0000000000 --- a/app/javascript/mastodon/reducers/lists.js +++ /dev/null @@ -1,38 +0,0 @@ -import { Map as ImmutableMap, fromJS } from 'immutable'; - -import { - LIST_FETCH_SUCCESS, - LIST_FETCH_FAIL, - LISTS_FETCH_SUCCESS, - LIST_CREATE_SUCCESS, - LIST_UPDATE_SUCCESS, - LIST_DELETE_SUCCESS, -} from '../actions/lists'; - -const initialState = ImmutableMap(); - -const normalizeList = (state, list) => state.set(list.id, fromJS(list)); - -const normalizeLists = (state, lists) => { - lists.forEach(list => { - state = normalizeList(state, list); - }); - - return state; -}; - -export default function lists(state = initialState, action) { - switch(action.type) { - case LIST_FETCH_SUCCESS: - case LIST_CREATE_SUCCESS: - case LIST_UPDATE_SUCCESS: - return normalizeList(state, action.list); - case LISTS_FETCH_SUCCESS: - return normalizeLists(state, action.lists); - case LIST_DELETE_SUCCESS: - case LIST_FETCH_FAIL: - return state.set(action.id, false); - default: - return state; - } -} diff --git a/app/javascript/mastodon/reducers/lists.ts b/app/javascript/mastodon/reducers/lists.ts new file mode 100644 index 0000000000..593e717949 --- /dev/null +++ b/app/javascript/mastodon/reducers/lists.ts @@ -0,0 +1,49 @@ +import type { Reducer } from '@reduxjs/toolkit'; +import { Map as ImmutableMap } from 'immutable'; + +import { createList, updateList } from 'mastodon/actions/lists_typed'; +import type { ApiListJSON } from 'mastodon/api_types/lists'; +import { createList as createListFromJSON } from 'mastodon/models/list'; +import type { List } from 'mastodon/models/list'; + +import { + LIST_FETCH_SUCCESS, + LIST_FETCH_FAIL, + LISTS_FETCH_SUCCESS, + LIST_DELETE_SUCCESS, +} from '../actions/lists'; + +const initialState = ImmutableMap(); +type State = typeof initialState; + +const normalizeList = (state: State, list: ApiListJSON) => + state.set(list.id, createListFromJSON(list)); + +const normalizeLists = (state: State, lists: ApiListJSON[]) => { + lists.forEach((list) => { + state = normalizeList(state, list); + }); + + return state; +}; + +export const listsReducer: Reducer = (state = initialState, action) => { + if ( + createList.fulfilled.match(action) || + updateList.fulfilled.match(action) + ) { + return normalizeList(state, action.payload); + } else { + switch (action.type) { + case LIST_FETCH_SUCCESS: + return normalizeList(state, action.list as ApiListJSON); + case LISTS_FETCH_SUCCESS: + return normalizeLists(state, action.lists as ApiListJSON[]); + case LIST_DELETE_SUCCESS: + case LIST_FETCH_FAIL: + return state.set(action.id as string, null); + default: + return state; + } + } +}; diff --git a/app/javascript/mastodon/reducers/notification_groups.ts b/app/javascript/mastodon/reducers/notification_groups.ts index 7a165f5fec..d43714beb7 100644 --- a/app/javascript/mastodon/reducers/notification_groups.ts +++ b/app/javascript/mastodon/reducers/notification_groups.ts @@ -534,10 +534,13 @@ export const notificationGroupsReducer = createReducer( if (existingGroupIndex > -1) { const existingGroup = state.groups[existingGroupIndex]; if (existingGroup && existingGroup.type !== 'gap') { - group.notifications_count += existingGroup.notifications_count; - group.sampleAccountIds = group.sampleAccountIds - .concat(existingGroup.sampleAccountIds) - .slice(0, NOTIFICATIONS_GROUP_MAX_AVATARS); + if (group.partial) { + group.notifications_count += + existingGroup.notifications_count; + group.sampleAccountIds = group.sampleAccountIds + .concat(existingGroup.sampleAccountIds) + .slice(0, NOTIFICATIONS_GROUP_MAX_AVATARS); + } state.groups.splice(existingGroupIndex, 1); } } diff --git a/app/javascript/mastodon/selectors/lists.ts b/app/javascript/mastodon/selectors/lists.ts new file mode 100644 index 0000000000..f93e90ce68 --- /dev/null +++ b/app/javascript/mastodon/selectors/lists.ts @@ -0,0 +1,15 @@ +import { createSelector } from '@reduxjs/toolkit'; +import type { Map as ImmutableMap } from 'immutable'; + +import type { List } from 'mastodon/models/list'; +import type { RootState } from 'mastodon/store'; + +export const getOrderedLists = createSelector( + [(state: RootState) => state.lists], + (lists: ImmutableMap) => + lists + .toList() + .filter((item: List | null) => !!item) + .sort((a: List, b: List) => a.title.localeCompare(b.title)) + .toArray(), +); 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/diff.scss b/app/javascript/styles/mastodon-light/diff.scss index 45da56994c..3d4539bb9d 100644 --- a/app/javascript/styles/mastodon-light/diff.scss +++ b/app/javascript/styles/mastodon-light/diff.scss @@ -535,3 +535,10 @@ a.sparkline { ::-webkit-scrollbar-thumb { opacity: 0.25; } + +.notification-group--annual-report { + .notification-group__icon, + .notification-group__main .link-button { + color: var(--indigo-3); + } +} diff --git a/app/javascript/styles/mastodon-light/variables.scss b/app/javascript/styles/mastodon-light/variables.scss index 777c622ace..2d5e1b1094 100644 --- a/app/javascript/styles/mastodon-light/variables.scss +++ b/app/javascript/styles/mastodon-light/variables.scss @@ -79,4 +79,5 @@ body { --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%); + --input-placeholder-color: #{transparentize($dark-text-color, 0.5)}; } diff --git a/app/javascript/styles/mastodon/admin.scss b/app/javascript/styles/mastodon/admin.scss index c7b32a9c9e..b5f8570ae2 100644 --- a/app/javascript/styles/mastodon/admin.scss +++ b/app/javascript/styles/mastodon/admin.scss @@ -611,16 +611,6 @@ body, max-width: 100%; } -.simple_form { - .actions { - margin-top: 15px; - } - - .button { - font-size: 15px; - } -} - .batch-form-box { display: flex; flex-wrap: wrap; @@ -1922,3 +1912,31 @@ a.sparkline { } } } + +.status__card { + padding: 15px; + border-radius: 4px; + background: $ui-base-color; + font-size: 15px; + line-height: 20px; + word-wrap: break-word; + font-weight: 400; + border: 1px solid lighten($ui-base-color, 4%); + color: $primary-text-color; + box-sizing: border-box; + min-height: 100%; + + .status__prepend { + padding: 0 0 15px; + gap: 4px; + align-items: center; + } + + .status__content { + padding-top: 0; + + summary { + display: list-item; + } + } +} diff --git a/app/javascript/styles/mastodon/annual_reports.scss b/app/javascript/styles/mastodon/annual_reports.scss new file mode 100644 index 0000000000..dff1c76eca --- /dev/null +++ b/app/javascript/styles/mastodon/annual_reports.scss @@ -0,0 +1,340 @@ +: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); + } + } + + .status-card, + .hashtag-bar { + display: none; + } + } + + &__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: 54px; + 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: 600px; + 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 f688b9b4ba..2c6efb71b4 100644 --- a/app/javascript/styles/mastodon/components.scss +++ b/app/javascript/styles/mastodon/components.scss @@ -1686,7 +1686,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 { @@ -4649,6 +4650,7 @@ a.status-card { border: 0; background: transparent; cursor: pointer; + text-decoration: none; .icon { width: 13px; @@ -5062,7 +5064,8 @@ a.status-card { color: $dark-text-color; text-align: center; padding: 20px; - font-size: 15px; + font-size: 14px; + line-height: 20px; font-weight: 400; cursor: default; display: flex; @@ -5084,6 +5087,17 @@ a.status-card { } } +.empty-column-indicator { + &__arrow { + position: absolute; + top: 50%; + inset-inline-start: 50%; + pointer-events: none; + transform: translate(100%, -100%) rotate(12deg); + transform-origin: center; + } +} + .follow_requests-unlocked_explanation { background: var(--surface-background-color); border-bottom: 1px solid var(--background-border-color); @@ -5775,7 +5789,7 @@ a.status-card { .modal-root { position: relative; - z-index: 9999; + z-index: 9998; } .modal-root__overlay { @@ -5784,7 +5798,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; } @@ -6139,13 +6154,6 @@ a.status-card { } } -.onboard-sliders { - display: inline-block; - max-width: 30px; - max-height: auto; - margin-inline-start: 10px; -} - .safety-action-modal { width: 600px; flex-direction: column; @@ -6379,12 +6387,14 @@ a.status-card { border-radius: 16px; &__header { + box-sizing: border-box; border-bottom: 1px solid var(--modal-border-color); display: flex; align-items: center; justify-content: space-between; flex-direction: row-reverse; padding: 12px 24px; + min-height: 61px; &__title { font-size: 16px; @@ -7991,92 +8001,6 @@ noscript { background: rgba($base-overlay-background, 0.5); } -.list-adder, -.list-editor { - backdrop-filter: var(--background-filter); - background: var(--modal-background-color); - border: 1px solid var(--modal-border-color); - flex-direction: column; - border-radius: 8px; - width: 380px; - overflow: hidden; - - @media screen and (width <= 420px) { - width: 90%; - } -} - -.list-adder { - &__lists { - height: 50vh; - border-radius: 0 0 8px 8px; - overflow-y: auto; - } - - .list { - padding: 10px; - border-bottom: 1px solid var(--background-border-color); - } - - .list__wrapper { - display: flex; - } - - .list__display-name { - flex: 1 1 auto; - overflow: hidden; - text-decoration: none; - font-size: 16px; - padding: 10px; - display: flex; - align-items: center; - gap: 4px; - } -} - -.list-editor { - h4 { - padding: 15px 0; - background: lighten($ui-base-color, 13%); - font-weight: 500; - font-size: 16px; - text-align: center; - border-radius: 8px 8px 0 0; - } - - .drawer__pager { - height: 50vh; - border: 0; - } - - .drawer__inner { - &.backdrop { - width: calc(100% - 60px); - box-shadow: 2px 4px 15px rgba($base-shadow-color, 0.4); - border-radius: 0 0 0 8px; - } - } - - &__accounts { - background: unset; - overflow-y: auto; - } - - .account__display-name { - &:hover strong { - text-decoration: none; - } - } - - .account__avatar { - cursor: default; - } - - .search { - margin-bottom: 0; - } -} - .focal-point { position: relative; cursor: move; @@ -8808,6 +8732,7 @@ noscript { &__item { flex-shrink: 0; background: lighten($ui-base-color, 12%); + color: $darker-text-color; border: 0; border-radius: 3px; margin: 2px; @@ -8844,7 +8769,6 @@ noscript { font-weight: 500; text-align: center; margin-inline-start: 6px; - color: $darker-text-color; } &:hover, @@ -8853,10 +8777,7 @@ noscript { background: lighten($ui-base-color, 16%); transition: all 200ms ease-out; transition-property: background-color, color; - - &__count { - color: lighten($darker-text-color, 4%); - } + color: lighten($darker-text-color, 4%); } &.active { @@ -8867,10 +8788,7 @@ noscript { $ui-highlight-color, 80% ); - - .reactions-bar__item__count { - color: lighten($highlight-text-color, 8%); - } + color: lighten($highlight-text-color, 8%); } } @@ -10140,7 +10058,7 @@ noscript { position: fixed; bottom: 2rem; inset-inline-start: 0; - z-index: 999; + z-index: 9999; display: flex; flex-direction: column; gap: 4px; @@ -10485,7 +10403,7 @@ noscript { &__text { flex: 1 1 auto; - font-style: 14px; + font-size: 14px; line-height: 20px; strong { @@ -10543,7 +10461,7 @@ noscript { &__name { flex: 1 1 auto; color: $darker-text-color; - font-style: 14px; + font-size: 14px; line-height: 20px; overflow: hidden; text-overflow: ellipsis; @@ -11148,3 +11066,87 @@ noscript { } } } + +.lists__item { + display: flex; + align-items: center; + gap: 16px; + padding-inline-end: 13px; + border-bottom: 1px solid var(--background-border-color); + + &__title { + display: flex; + align-items: center; + gap: 5px; + padding: 16px 13px; + flex: 1 1 auto; + font-size: 16px; + line-height: 24px; + color: $secondary-text-color; + text-decoration: none; + + &:is(a):hover, + &:is(a):focus, + &:is(a):active { + color: $primary-text-color; + } + + input { + display: block; + width: 100%; + background: transparent; + border: 0; + padding: 0; + font-family: inherit; + font-size: inherit; + line-height: inherit; + color: inherit; + + &::placeholder { + color: var(--input-placeholder-color); + opacity: 1; + } + + &:focus { + outline: 0; + } + } + } +} + +.column-search-header { + display: flex; + border-radius: 4px 4px 0 0; + border: 1px solid var(--background-border-color); + + .column-header__back-button.compact { + flex: 0 0 auto; + color: $primary-text-color; + } + + input { + background: transparent; + border: 0; + color: $primary-text-color; + font-size: 16px; + display: block; + flex: 1 1 auto; + + &::placeholder { + color: var(--input-placeholder-color); + opacity: 1; + } + + &:focus { + outline: 0; + } + } +} + +.column-footer { + padding: 16px; +} + +.lists-scrollable { + min-height: 50vh; +} diff --git a/app/javascript/styles/mastodon/forms.scss b/app/javascript/styles/mastodon/forms.scss index 641fb19a57..69bd1ca9dd 100644 --- a/app/javascript/styles/mastodon/forms.scss +++ b/app/javascript/styles/mastodon/forms.scss @@ -1255,6 +1255,8 @@ code { } .app-form { + padding: 20px; + &__avatar-input, &__header-input { display: block; @@ -1370,4 +1372,55 @@ code { padding-inline-start: 16px; } } + + &__link { + display: flex; + gap: 16px; + padding: 8px 0; + align-items: center; + text-decoration: none; + color: $primary-text-color; + margin-bottom: 16px; + + &__text { + flex: 1 1 auto; + font-size: 14px; + line-height: 20px; + color: $darker-text-color; + + strong { + font-weight: 600; + display: block; + color: $primary-text-color; + } + } + } +} + +.avatar-pile { + display: flex; + align-items: center; + + img { + display: block; + border-radius: 8px; + width: 32px; + height: 32px; + border: 2px solid var(--background-color); + background: var(--surface-background-color); + margin-inline-end: -16px; + transform: rotate(0); + + &:first-child { + transform: rotate(-4deg); + } + + &:nth-child(2) { + transform: rotate(-2deg); + } + + &:last-child { + margin-inline-end: 0; + } + } } diff --git a/app/javascript/styles/mastodon/polls.scss b/app/javascript/styles/mastodon/polls.scss index 939fca3364..ced4c60c44 100644 --- a/app/javascript/styles/mastodon/polls.scss +++ b/app/javascript/styles/mastodon/polls.scss @@ -38,11 +38,6 @@ background: darken($ui-primary-color, 5%); } - &::-ms-fill { - border-radius: 4px; - background: darken($ui-primary-color, 5%); - } - &::-webkit-progress-value { border-radius: 4px; background: darken($ui-primary-color, 5%); diff --git a/app/javascript/styles/mastodon/tables.scss b/app/javascript/styles/mastodon/tables.scss index 0cbf5c1d55..07d1ce12fd 100644 --- a/app/javascript/styles/mastodon/tables.scss +++ b/app/javascript/styles/mastodon/tables.scss @@ -339,16 +339,12 @@ a.table-action-link { } } - .status__content { - padding-top: 0; - - summary { - display: list-item; - } - - strong { - font-weight: 700; - } + // Reset the status card to not have borders, background or padding when + // inline in the table of statuses + .status__card { + border: none; + background: none; + padding: 0; } .nothing-here { diff --git a/app/javascript/styles/mastodon/variables.scss b/app/javascript/styles/mastodon/variables.scss index fe36e16631..2036f01aff 100644 --- a/app/javascript/styles/mastodon/variables.scss +++ b/app/javascript/styles/mastodon/variables.scss @@ -119,4 +119,5 @@ $font-monospace: 'mastodon-font-monospace' !default; --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%); + --input-placeholder-color: #{$dark-text-color}; } diff --git a/app/javascript/styles/mastodon/widgets.scss b/app/javascript/styles/mastodon/widgets.scss index d810ee4bfc..e1e8797460 100644 --- a/app/javascript/styles/mastodon/widgets.scss +++ b/app/javascript/styles/mastodon/widgets.scss @@ -82,6 +82,7 @@ .accounts-table { width: 100%; + table-layout: fixed; .account { padding: 0; diff --git a/app/javascript/svg-icons/squiggly_arrow.svg b/app/javascript/svg-icons/squiggly_arrow.svg new file mode 100644 index 0000000000..ae636d7dfd --- /dev/null +++ b/app/javascript/svg-icons/squiggly_arrow.svg @@ -0,0 +1,3 @@ + + + diff --git a/app/lib/account_reach_finder.rb b/app/lib/account_reach_finder.rb index 481e254396..19464024a6 100644 --- a/app/lib/account_reach_finder.rb +++ b/app/lib/account_reach_finder.rb @@ -1,6 +1,10 @@ # frozen_string_literal: true class AccountReachFinder + RECENT_LIMIT = 2_000 + STATUS_LIMIT = 200 + STATUS_SINCE = 2.days + def initialize(account) @account = account end @@ -20,13 +24,27 @@ class AccountReachFinder end def recently_mentioned_inboxes - cutoff_id = Mastodon::Snowflake.id_at(2.days.ago, with_random: false) - recent_statuses = @account.statuses.recent.where(id: cutoff_id...).limit(200) - - Account.joins(:mentions).where(mentions: { status: recent_statuses }).inboxes.take(2000) + Account + .joins(:mentions) + .where(mentions: { status: recent_statuses }) + .inboxes + .take(RECENT_LIMIT) end def relay_inboxes Relay.enabled.pluck(:inbox_url) end + + def oldest_status_id + Mastodon::Snowflake + .id_at(STATUS_SINCE.ago, with_random: false) + end + + def recent_statuses + @account + .statuses + .recent + .where(id: oldest_status_id...) + .limit(STATUS_LIMIT) + end end 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 30ab671d8a..2316789f2a 100644 --- a/app/lib/annual_report/commonly_interacted_with_accounts.rb +++ b/app/lib/annual_report/commonly_interacted_with_accounts.rb @@ -17,6 +17,6 @@ class AnnualReport::CommonlyInteractedWithAccounts < AnnualReport::Source private def commonly_interacted_with_accounts - report_statuses.where.not(in_reply_to_account_id: @account.id).group(:in_reply_to_account_id).having('count(*) > 1').order(total: :desc).limit(SET_SIZE).pluck(Arel.sql('in_reply_to_account_id, count(*) AS total')) + report_statuses.where.not(in_reply_to_account_id: @account.id).group(:in_reply_to_account_id).having('count(*) > 1').order(count_all: :desc).limit(SET_SIZE).count end end diff --git a/app/lib/annual_report/most_reblogged_accounts.rb b/app/lib/annual_report/most_reblogged_accounts.rb index cfc4022ca7..69e247f2a6 100644 --- a/app/lib/annual_report/most_reblogged_accounts.rb +++ b/app/lib/annual_report/most_reblogged_accounts.rb @@ -17,6 +17,6 @@ class AnnualReport::MostRebloggedAccounts < AnnualReport::Source private def most_reblogged_accounts - report_statuses.where.not(reblog_of_id: nil).joins(reblog: :account).group('accounts.id').having('count(*) > 1').order(total: :desc).limit(SET_SIZE).pluck(Arel.sql('accounts.id, count(*) as total')) + report_statuses.where.not(reblog_of_id: nil).joins(reblog: :account).group(accounts: [:id]).having('count(*) > 1').order(count_all: :desc).limit(SET_SIZE).count end end diff --git a/app/lib/annual_report/most_used_apps.rb b/app/lib/annual_report/most_used_apps.rb index fb1ca1d167..a2e1aca452 100644 --- a/app/lib/annual_report/most_used_apps.rb +++ b/app/lib/annual_report/most_used_apps.rb @@ -17,6 +17,6 @@ class AnnualReport::MostUsedApps < AnnualReport::Source private def most_used_apps - report_statuses.joins(:application).group('oauth_applications.name').order(total: :desc).limit(SET_SIZE).pluck(Arel.sql('oauth_applications.name, count(*) as total')) + report_statuses.joins(:application).group(oauth_applications: [:name]).order(count_all: :desc).limit(SET_SIZE).count end 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_hashtags.rb b/app/lib/annual_report/top_hashtags.rb index 32bd10d698..ae000a8beb 100644 --- a/app/lib/annual_report/top_hashtags.rb +++ b/app/lib/annual_report/top_hashtags.rb @@ -17,6 +17,12 @@ class AnnualReport::TopHashtags < AnnualReport::Source private def top_hashtags - Tag.joins(:statuses).where(statuses: { id: report_statuses.select(:id) }).group(:id).having('count(*) > 1').order(total: :desc).limit(SET_SIZE).pluck(Arel.sql('COALESCE(tags.display_name, tags.name), count(*) AS total')) + Tag.joins(:statuses).where(statuses: { id: report_statuses.select(:id) }).group(coalesced_tag_names).having('count(*) > 1').order(count_all: :desc).limit(SET_SIZE).count + end + + def coalesced_tag_names + Arel.sql(<<~SQL.squish) + COALESCE(tags.display_name, tags.name) + SQL end end diff --git a/app/lib/antispam.rb b/app/lib/antispam.rb new file mode 100644 index 0000000000..4ebf192485 --- /dev/null +++ b/app/lib/antispam.rb @@ -0,0 +1,64 @@ +# frozen_string_literal: true + +class Antispam + include Redisable + + ACCOUNT_AGE_EXEMPTION = 1.week.freeze + + class DummyStatus < SimpleDelegator + def self.model_name + Mention.model_name + end + + def active_mentions + # Don't use the scope but the in-memory array + mentions.filter { |mention| !mention.silent? } + end + end + + class SilentlyDrop < StandardError + attr_reader :status + + def initialize(status) + super() + + status.created_at = Time.now.utc + status.id = Mastodon::Snowflake.id_at(status.created_at) + status.in_reply_to_account_id = status.thread&.account_id + + status.delete # Make sure this is not persisted + + @status = DummyStatus.new(status) + end + end + + def local_preflight_check!(status) + return unless spammy_texts.any? { |spammy_text| status.text.include?(spammy_text) } + return unless suspicious_reply_or_mention?(status) + return unless status.account.created_at >= ACCOUNT_AGE_EXEMPTION.ago + + report_if_needed!(status.account) + + raise SilentlyDrop, status + end + + private + + def spammy_texts + redis.smembers('antispam:spammy_texts') + end + + def suspicious_reply_or_mention?(status) + parent = status.thread + return true if parent.present? && !Follow.exists?(account_id: parent.account_id, target_account: status.account_id) + + account_ids = status.mentions.map(&:account_id).uniq + !Follow.exists?(account_id: account_ids, target_account_id: status.account.id) + end + + def report_if_needed!(account) + return if Report.unresolved.exists?(account: Account.representative, target_account: account) + + Report.create!(account: Account.representative, target_account: account, category: :spam, comment: 'Account automatically reported for posting a banned URL') + end +end diff --git a/app/lib/domain_resource.rb b/app/lib/domain_resource.rb new file mode 100644 index 0000000000..59a29d8797 --- /dev/null +++ b/app/lib/domain_resource.rb @@ -0,0 +1,22 @@ +# frozen_string_literal: true + +class DomainResource + attr_reader :domain + + RESOLVE_TIMEOUT = 5 + + def initialize(domain) + @domain = domain + end + + def mx + Resolv::DNS.open do |dns| + dns.timeouts = RESOLVE_TIMEOUT + dns + .getresources(domain, Resolv::DNS::Resource::IN::MX) + .to_a + .map { |mx| mx.exchange.to_s } + .compact_blank + end + end +end diff --git a/app/lib/feed_manager.rb b/app/lib/feed_manager.rb index 97cb25d58f..edd1162f4f 100644 --- a/app/lib/feed_manager.rb +++ b/app/lib/feed_manager.rb @@ -162,7 +162,7 @@ class FeedManager timeline_key = key(:home, into_account.id) timeline_status_ids = redis.zrange(timeline_key, 0, -1) - from_account.statuses.select('id, reblog_of_id').where(id: timeline_status_ids).reorder(nil).find_each do |status| + from_account.statuses.select(:id, :reblog_of_id).where(id: timeline_status_ids).reorder(nil).find_each do |status| remove_from_feed(:home, into_account.id, status, aggregate_reblogs: into_account.user&.aggregates_reblogs?) end end @@ -175,7 +175,7 @@ class FeedManager timeline_key = key(:list, list.id) timeline_status_ids = redis.zrange(timeline_key, 0, -1) - from_account.statuses.select('id, reblog_of_id').where(id: timeline_status_ids).reorder(nil).find_each do |status| + from_account.statuses.select(:id, :reblog_of_id).where(id: timeline_status_ids).reorder(nil).find_each do |status| remove_from_feed(:list, list.id, status, aggregate_reblogs: list.account.user&.aggregates_reblogs?) end end @@ -196,7 +196,7 @@ class FeedManager .where.not(account: into_account.following) .tagged_with_none(TagFollow.where(account: into_account).pluck(:tag_id)) - scope.select('id, reblog_of_id').reorder(nil).find_each do |status| + scope.select(:id, :reblog_of_id).reorder(nil).find_each do |status| remove_from_feed(:home, into_account.id, status, aggregate_reblogs: into_account.user&.aggregates_reblogs?) end end diff --git a/app/lib/importer/statuses_index_importer.rb b/app/lib/importer/statuses_index_importer.rb index 1922f65f6d..5c8a9f28c8 100644 --- a/app/lib/importer/statuses_index_importer.rb +++ b/app/lib/importer/statuses_index_importer.rb @@ -71,7 +71,7 @@ class Importer::StatusesIndexImporter < Importer::BaseImporter end def local_votes_scope - Poll.joins(:votes).where(votes: { account: Account.local }).select('polls.id, polls.status_id') + Poll.joins(:votes).where(votes: { account: Account.local }).select(polls: [:id, :status_id]) end def local_statuses_scope diff --git a/app/lib/link_details_extractor.rb b/app/lib/link_details_extractor.rb index e4e815c38d..fe7f23f481 100644 --- a/app/lib/link_details_extractor.rb +++ b/app/lib/link_details_extractor.rb @@ -157,7 +157,7 @@ class LinkDetailsExtractor end def title - html_entities.decode(structured_data&.headline || opengraph_tag('og:title') || document.xpath('//title').map(&:content).first)&.strip + html_entities.decode(structured_data&.headline || opengraph_tag('og:title') || head.at_xpath('title')&.content)&.strip end def description @@ -205,11 +205,11 @@ class LinkDetailsExtractor end def language - valid_locale_or_nil(structured_data&.language || opengraph_tag('og:locale') || document.xpath('//html').pick('lang')) + valid_locale_or_nil(structured_data&.language || opengraph_tag('og:locale') || document.root.attr('lang')) end def icon - valid_url_or_nil(structured_data&.publisher_icon || link_tag('apple-touch-icon') || link_tag('shortcut icon')) + valid_url_or_nil(structured_data&.publisher_icon || link_tag('apple-touch-icon') || link_tag('icon')) end private @@ -237,18 +237,20 @@ class LinkDetailsExtractor end def link_tag(name) - document.xpath("//link[@rel=\"#{name}\"]").pick('href') + head.at_xpath("//link[nokogiri:link_rel_include(@rel, '#{name}')]", NokogiriHandler)&.attr('href') end def opengraph_tag(name) - document.xpath("//meta[@property=\"#{name}\" or @name=\"#{name}\"]").pick('content') + head.at_xpath("//meta[nokogiri:casecmp(@property, '#{name}') or nokogiri:casecmp(@name, '#{name}')]", NokogiriHandler)&.attr('content') end def meta_tag(name) - document.xpath("//meta[@name=\"#{name}\"]").pick('content') + head.at_xpath("//meta[nokogiri:casecmp(@name, '#{name}')]", NokogiriHandler)&.attr('content') end def structured_data + return @structured_data if defined?(@structured_data) + # Some publications have more than one JSON-LD definition on the page, # and some of those definitions aren't valid JSON either, so we have # to loop through here until we find something that is the right type @@ -273,6 +275,10 @@ class LinkDetailsExtractor @document ||= detect_encoding_and_parse_document end + def head + @head ||= document.at_xpath('/html/head') + end + def detect_encoding_and_parse_document html = nil encoding = nil diff --git a/app/lib/nokogiri_handler.rb b/app/lib/nokogiri_handler.rb new file mode 100644 index 0000000000..26cf457955 --- /dev/null +++ b/app/lib/nokogiri_handler.rb @@ -0,0 +1,16 @@ +# frozen_string_literal: true + +class NokogiriHandler + class << self + # See "set of space-separated tokens" in the HTML5 spec. + WHITE_SPACE = /[ \x09\x0A\x0C\x0D]+/ + + def link_rel_include(token_list, token) + token_list.to_s.downcase.split(WHITE_SPACE).include?(token.downcase) + end + + def casecmp(str1, str2) + str1.to_s.casecmp?(str2.to_s) + end + end +end diff --git a/app/lib/oauth_pre_authorization_extension.rb b/app/lib/oauth_pre_authorization_extension.rb deleted file mode 100644 index 1885e0823d..0000000000 --- a/app/lib/oauth_pre_authorization_extension.rb +++ /dev/null @@ -1,13 +0,0 @@ -# frozen_string_literal: true - -module OauthPreAuthorizationExtension - extend ActiveSupport::Concern - - included do - validate :code_challenge_method_s256, error: Doorkeeper::Errors::InvalidCodeChallengeMethod - end - - def validate_code_challenge_method_s256 - code_challenge.blank? || code_challenge_method == 'S256' - end -end diff --git a/app/lib/request.rb b/app/lib/request.rb index d7da9fe63c..a12e6e3747 100644 --- a/app/lib/request.rb +++ b/app/lib/request.rb @@ -334,14 +334,10 @@ class Request def check_private_address(address, host) addr = IPAddr.new(address.to_s) - return if Rails.env.development? || private_address_exceptions.any? { |range| range.include?(addr) } + return if Rails.env.development? || Rails.configuration.x.private_address_exceptions.any? { |range| range.include?(addr) } raise Mastodon::PrivateNetworkAddressError, host if PrivateAddressCheck.private_address?(addr) end - - def private_address_exceptions - @private_address_exceptions = (ENV['ALLOWED_PRIVATE_ADDRESSES'] || '').split(/(?:\s*,\s*|\s+)/).map { |addr| IPAddr.new(addr) } - end end end diff --git a/app/lib/search_query_transformer.rb b/app/lib/search_query_transformer.rb index 1306ed12ed..59352c6e6e 100644 --- a/app/lib/search_query_transformer.rb +++ b/app/lib/search_query_transformer.rb @@ -144,6 +144,8 @@ class SearchQueryTransformer < Parslet::Transform end class PrefixClause + EPOCH_RE = /\A\d+\z/ + attr_reader :operator, :prefix, :term def initialize(prefix, operator, term, options = {}) @@ -168,15 +170,15 @@ class SearchQueryTransformer < Parslet::Transform when 'before' @filter = :created_at @type = :range - @term = { lt: TermValidator.validate_date!(term), time_zone: @options[:current_account]&.user_time_zone.presence || 'UTC' } + @term = { lt: date_from_term(term), time_zone: @options[:current_account]&.user_time_zone.presence || 'UTC' } when 'after' @filter = :created_at @type = :range - @term = { gt: TermValidator.validate_date!(term), time_zone: @options[:current_account]&.user_time_zone.presence || 'UTC' } + @term = { gt: date_from_term(term), time_zone: @options[:current_account]&.user_time_zone.presence || 'UTC' } when 'during' @filter = :created_at @type = :range - @term = { gte: TermValidator.validate_date!(term), lte: TermValidator.validate_date!(term), time_zone: @options[:current_account]&.user_time_zone.presence || 'UTC' } + @term = { gte: date_from_term(term), lte: date_from_term(term), time_zone: @options[:current_account]&.user_time_zone.presence || 'UTC' } when 'in' @operator = :flag @term = term @@ -222,16 +224,10 @@ class SearchQueryTransformer < Parslet::Transform term end - end - class TermValidator - STRICT_DATE_REGEX = /\A\d{4}-\d{2}-\d{2}\z/ # yyyy-MM-dd - EPOCH_MILLIS_REGEX = /\A\d{1,19}\z/ - - def self.validate_date!(value) - return value if value.match?(STRICT_DATE_REGEX) || value.match?(EPOCH_MILLIS_REGEX) - - raise Mastodon::FilterValidationError, "Invalid date #{value}" + def date_from_term(term) + DateTime.iso8601(term) unless term.match?(EPOCH_RE) # This will raise Date::Error if the date is invalid + term end end diff --git a/app/lib/status_reach_finder.rb b/app/lib/status_reach_finder.rb index 17e42e3ec3..d08c077c74 100644 --- a/app/lib/status_reach_finder.rb +++ b/app/lib/status_reach_finder.rb @@ -16,7 +16,9 @@ class StatusReachFinder private def reached_account_inboxes - Account.where(id: reached_account_ids).inboxes + scope = Account.where(id: reached_account_ids) + scope.merge!(Account.without_suspended) unless unsafe? + scope.inboxes end def reached_account_ids 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/vacuum/imports_vacuum.rb b/app/lib/vacuum/imports_vacuum.rb index b67865194f..7f101c4506 100644 --- a/app/lib/vacuum/imports_vacuum.rb +++ b/app/lib/vacuum/imports_vacuum.rb @@ -9,10 +9,16 @@ class Vacuum::ImportsVacuum private def clean_unconfirmed_imports! - BulkImport.state_unconfirmed.where(created_at: ..10.minutes.ago).in_batches.delete_all + BulkImport + .confirmation_missed + .in_batches + .delete_all end def clean_old_imports! - BulkImport.where(created_at: ..1.week.ago).in_batches.delete_all + BulkImport + .archival_completed + .in_batches + .delete_all end end diff --git a/app/lib/video_metadata_extractor.rb b/app/lib/video_metadata_extractor.rb index 2155766251..fda6405121 100644 --- a/app/lib/video_metadata_extractor.rb +++ b/app/lib/video_metadata_extractor.rb @@ -46,6 +46,9 @@ class VideoMetadataExtractor # For some video streams the frame_rate reported by `ffprobe` will be 0/0, but for these streams we # should use `r_frame_rate` instead. Video screencast generated by Gnome Screencast have this issue. @frame_rate ||= @r_frame_rate + # If the video has not been re-encoded by ffmpeg, it may contain rotation information, + # and we need to simulate applying it to the dimensions + @width, @height = @height, @width if video_stream[:side_data_list]&.any? { |x| x[:rotation].abs == 90 } end if (audio_stream = audio_streams.first) diff --git a/app/models/account.rb b/app/models/account.rb index 957ccc73c4..206529301e 100644 --- a/app/models/account.rb +++ b/app/models/account.rb @@ -90,6 +90,8 @@ class Account < ApplicationRecord include Account::Interactions include Account::Merging include Account::Search + include Account::Sensitizes + include Account::Silences include Account::StatusesSearch include Account::Suspensions include Account::AttributionDomains @@ -129,9 +131,6 @@ class Account < ApplicationRecord scope :remote, -> { where.not(domain: nil) } scope :local, -> { where(domain: nil) } scope :partitioned, -> { order(Arel.sql('row_number() over (partition by domain)')) } - scope :silenced, -> { where.not(silenced_at: nil) } - scope :sensitized, -> { where.not(sensitized_at: nil) } - scope :without_silenced, -> { where(silenced_at: nil) } scope :without_instance_actor, -> { where.not(id: INSTANCE_ACTOR_ID) } scope :recent, -> { reorder(id: :desc) } scope :bots, -> { where(actor_type: AUTOMATED_ACTOR_TYPES) } @@ -244,30 +243,6 @@ class Account < ApplicationRecord ResolveAccountService.new.call(acct) unless local? end - def silenced? - silenced_at.present? - end - - def silence!(date = Time.now.utc) - update!(silenced_at: date) - end - - def unsilence! - update!(silenced_at: nil) - end - - def sensitized? - sensitized_at.present? - end - - def sensitize!(date = Time.now.utc) - update!(sensitized_at: date) - end - - def unsensitize! - update!(sensitized_at: nil) - end - def memorialize! update!(memorial: true) end diff --git a/app/models/account_filter.rb b/app/models/account_filter.rb index e2f359a8c3..f5e9fc7db9 100644 --- a/app/models/account_filter.rb +++ b/app/models/account_filter.rb @@ -61,7 +61,7 @@ class AccountFilter when 'email' accounts_with_users.merge(User.matches_email(value.to_s.strip)) when 'ip' - valid_ip?(value) ? accounts_with_users.merge(User.matches_ip(value).group('users.id, accounts.id')) : Account.none + valid_ip?(value) ? accounts_with_users.merge(User.matches_ip(value).group(users: [:id], accounts: [:id])) : Account.none when 'invited_by' invited_by_scope(value) when 'order' 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/action_log_filter.rb b/app/models/admin/action_log_filter.rb index 1f48e0a497..dfb7fd00ed 100644 --- a/app/models/admin/action_log_filter.rb +++ b/app/models/admin/action_log_filter.rb @@ -31,6 +31,7 @@ class Admin::ActionLogFilter create_domain_block: { target_type: 'DomainBlock', action: 'create' }.freeze, create_email_domain_block: { target_type: 'EmailDomainBlock', action: 'create' }.freeze, create_ip_block: { target_type: 'IpBlock', action: 'create' }.freeze, + create_relay: { target_type: 'Relay', action: 'create' }.freeze, create_unavailable_domain: { target_type: 'UnavailableDomain', action: 'create' }.freeze, create_user_role: { target_type: 'UserRole', action: 'create' }.freeze, create_canonical_email_block: { target_type: 'CanonicalEmailBlock', action: 'create' }.freeze, @@ -40,6 +41,7 @@ class Admin::ActionLogFilter destroy_domain_allow: { target_type: 'DomainAllow', action: 'destroy' }.freeze, destroy_domain_block: { target_type: 'DomainBlock', action: 'destroy' }.freeze, destroy_ip_block: { target_type: 'IpBlock', action: 'destroy' }.freeze, + destroy_relay: { target_type: 'Relay', action: 'destroy' }.freeze, destroy_email_domain_block: { target_type: 'EmailDomainBlock', action: 'destroy' }.freeze, destroy_instance: { target_type: 'Instance', action: 'destroy' }.freeze, destroy_unavailable_domain: { target_type: 'UnavailableDomain', action: 'destroy' }.freeze, @@ -49,8 +51,10 @@ class Admin::ActionLogFilter disable_2fa_user: { target_type: 'User', action: 'disable_2fa' }.freeze, disable_custom_emoji: { target_type: 'CustomEmoji', action: 'disable' }.freeze, disable_user: { target_type: 'User', action: 'disable' }.freeze, + disable_relay: { target_type: 'Relay', action: 'disable' }.freeze, enable_custom_emoji: { target_type: 'CustomEmoji', action: 'enable' }.freeze, enable_user: { target_type: 'User', action: 'enable' }.freeze, + enable_relay: { target_type: 'Relay', action: 'enable' }.freeze, memorialize_account: { target_type: 'Account', action: 'memorialize' }.freeze, promote_user: { target_type: 'User', action: 'promote' }.freeze, remove_avatar_user: { target_type: 'User', action: 'remove_avatar' }.freeze, 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/application_record.rb b/app/models/application_record.rb index 299aad6340..24e9d6aeba 100644 --- a/app/models/application_record.rb +++ b/app/models/application_record.rb @@ -1,7 +1,7 @@ # frozen_string_literal: true class ApplicationRecord < ActiveRecord::Base - self.abstract_class = true + primary_abstract_class include Remotable diff --git a/app/models/bulk_import.rb b/app/models/bulk_import.rb index 9b3f4c8a3a..e3e46d7b1c 100644 --- a/app/models/bulk_import.rb +++ b/app/models/bulk_import.rb @@ -21,6 +21,9 @@ class BulkImport < ApplicationRecord self.inheritance_column = false + ARCHIVE_PERIOD = 1.week + CONFIRM_PERIOD = 10.minutes + belongs_to :account has_many :rows, class_name: 'BulkImportRow', inverse_of: :bulk_import, dependent: :delete_all @@ -42,6 +45,9 @@ class BulkImport < ApplicationRecord validates :type, presence: true + scope :archival_completed, -> { where(created_at: ..ARCHIVE_PERIOD.ago) } + scope :confirmation_missed, -> { state_unconfirmed.where(created_at: ..CONFIRM_PERIOD.ago) } + def self.progress!(bulk_import_id, imported: false) # Use `increment_counter` so that the incrementation is done atomically in the database BulkImport.increment_counter(:processed_items, bulk_import_id) diff --git a/app/models/concerns/account/associations.rb b/app/models/concerns/account/associations.rb index 637e785953..cafb2d151c 100644 --- a/app/models/concerns/account/associations.rb +++ b/app/models/concerns/account/associations.rb @@ -4,75 +4,68 @@ module Account::Associations extend ActiveSupport::Concern included do - # Local users - has_one :user, inverse_of: :account, dependent: :destroy + # Core associations + with_options dependent: :destroy do + # Association where account owns record + with_options inverse_of: :account do + has_many :account_moderation_notes + has_many :account_pins + has_many :account_warnings + has_many :aliases, class_name: 'AccountAlias' + has_many :bookmarks + has_many :conversations, class_name: 'AccountConversation' + has_many :custom_filters + has_many :favourites + has_many :featured_tags, -> { includes(:tag) } + has_many :list_accounts + has_many :media_attachments + has_many :mentions + has_many :migrations, class_name: 'AccountMigration' + has_many :notification_permissions + has_many :notification_requests + has_many :notifications + has_many :owned_lists, class_name: 'List' + has_many :polls + has_many :report_notes + has_many :reports + has_many :scheduled_statuses + has_many :status_pins + has_many :statuses - # Timelines - has_many :statuses, inverse_of: :account, dependent: :destroy - has_many :favourites, inverse_of: :account, dependent: :destroy - has_many :bookmarks, inverse_of: :account, dependent: :destroy - has_many :mentions, inverse_of: :account, dependent: :destroy - has_many :conversations, class_name: 'AccountConversation', dependent: :destroy, inverse_of: :account - has_many :scheduled_statuses, inverse_of: :account, dependent: :destroy + has_one :deletion_request, class_name: 'AccountDeletionRequest' + has_one :follow_recommendation_suppression + has_one :notification_policy + has_one :statuses_cleanup_policy, class_name: 'AccountStatusesCleanupPolicy' + has_one :user + end - # Notifications - has_many :notifications, inverse_of: :account, dependent: :destroy - has_one :notification_policy, inverse_of: :account, dependent: :destroy - has_many :notification_permissions, inverse_of: :account, dependent: :destroy - has_many :notification_requests, inverse_of: :account, dependent: :destroy + # Association where account is targeted by record + with_options foreign_key: :target_account_id, inverse_of: :target_account do + has_many :strikes, class_name: 'AccountWarning' + has_many :targeted_moderation_notes, class_name: 'AccountModerationNote' + has_many :targeted_reports, class_name: 'Report' + end + end - # Pinned statuses - has_many :status_pins, inverse_of: :account, dependent: :destroy - has_many :pinned_statuses, -> { reorder('status_pins.created_at DESC') }, through: :status_pins, class_name: 'Status', source: :status + # Status records pinned by the account + has_many :pinned_statuses, -> { reorder(status_pins: { created_at: :desc }) }, through: :status_pins, class_name: 'Status', source: :status - # Endorsements - has_many :account_pins, inverse_of: :account, dependent: :destroy + # Account records endorsed (pinned) by the account has_many :endorsed_accounts, through: :account_pins, class_name: 'Account', source: :target_account - # Media - has_many :media_attachments, dependent: :destroy - has_many :polls, dependent: :destroy - - # Report relationships - has_many :reports, dependent: :destroy, inverse_of: :account - has_many :targeted_reports, class_name: 'Report', foreign_key: :target_account_id, dependent: :destroy, inverse_of: :target_account - - has_many :report_notes, dependent: :destroy - has_many :custom_filters, inverse_of: :account, dependent: :destroy - - # Moderation notes - has_many :account_moderation_notes, dependent: :destroy, inverse_of: :account - has_many :targeted_moderation_notes, class_name: 'AccountModerationNote', foreign_key: :target_account_id, dependent: :destroy, inverse_of: :target_account - has_many :account_warnings, dependent: :destroy, inverse_of: :account - has_many :strikes, class_name: 'AccountWarning', foreign_key: :target_account_id, dependent: :destroy, inverse_of: :target_account - - # Lists (that the account is on, not owned by the account) - has_many :list_accounts, inverse_of: :account, dependent: :destroy + # List records the account has been added to (not owned by the account) has_many :lists, through: :list_accounts - # Lists (owned by the account) - has_many :owned_lists, class_name: 'List', dependent: :destroy, inverse_of: :account - - # Account migrations + # Account record where account has been migrated belongs_to :moved_to_account, class_name: 'Account', optional: true - has_many :migrations, class_name: 'AccountMigration', dependent: :destroy, inverse_of: :account - has_many :aliases, class_name: 'AccountAlias', dependent: :destroy, inverse_of: :account - # Hashtags + # Tag records applied to account has_and_belongs_to_many :tags # rubocop:disable Rails/HasAndBelongsToMany - has_many :featured_tags, -> { includes(:tag) }, dependent: :destroy, inverse_of: :account - # Account deletion requests - has_one :deletion_request, class_name: 'AccountDeletionRequest', inverse_of: :account, dependent: :destroy - - # Follow recommendations + # FollowRecommendation for account (surfaced via view) has_one :follow_recommendation, inverse_of: :account, dependent: nil - has_one :follow_recommendation_suppression, inverse_of: :account, dependent: :destroy - # Account statuses cleanup policy - has_one :statuses_cleanup_policy, class_name: 'AccountStatusesCleanupPolicy', inverse_of: :account, dependent: :destroy - - # Imports + # BulkImport records owned by account has_many :bulk_imports, inverse_of: :account, dependent: :delete_all end end diff --git a/app/models/concerns/account/interactions.rb b/app/models/concerns/account/interactions.rb index 536afba17f..6f6b8c16d0 100644 --- a/app/models/concerns/account/interactions.rb +++ b/app/models/concerns/account/interactions.rb @@ -80,8 +80,8 @@ module Account::Interactions has_many :passive_relationships, foreign_key: 'target_account_id', inverse_of: :target_account end - has_many :following, -> { order('follows.id desc') }, through: :active_relationships, source: :target_account - has_many :followers, -> { order('follows.id desc') }, through: :passive_relationships, source: :account + has_many :following, -> { order(follows: { id: :desc }) }, through: :active_relationships, source: :target_account + has_many :followers, -> { order(follows: { id: :desc }) }, through: :passive_relationships, source: :account with_options class_name: 'SeveredRelationship', dependent: :destroy do has_many :severed_relationships, foreign_key: 'local_account_id', inverse_of: :local_account @@ -96,16 +96,16 @@ module Account::Interactions has_many :block_relationships, foreign_key: 'account_id', inverse_of: :account has_many :blocked_by_relationships, foreign_key: :target_account_id, inverse_of: :target_account end - has_many :blocking, -> { order('blocks.id desc') }, through: :block_relationships, source: :target_account - has_many :blocked_by, -> { order('blocks.id desc') }, through: :blocked_by_relationships, source: :account + has_many :blocking, -> { order(blocks: { id: :desc }) }, through: :block_relationships, source: :target_account + has_many :blocked_by, -> { order(blocks: { id: :desc }) }, through: :blocked_by_relationships, source: :account # Mute relationships with_options class_name: 'Mute', dependent: :destroy do has_many :mute_relationships, foreign_key: 'account_id', inverse_of: :account has_many :muted_by_relationships, foreign_key: :target_account_id, inverse_of: :target_account end - has_many :muting, -> { order('mutes.id desc') }, through: :mute_relationships, source: :target_account - has_many :muted_by, -> { order('mutes.id desc') }, through: :muted_by_relationships, source: :account + has_many :muting, -> { order(mutes: { id: :desc }) }, through: :mute_relationships, source: :target_account + has_many :muted_by, -> { order(mutes: { id: :desc }) }, through: :muted_by_relationships, source: :account has_many :conversation_mutes, dependent: :destroy has_many :domain_blocks, class_name: 'AccountDomainBlock', dependent: :destroy has_many :announcement_mutes, dependent: :destroy diff --git a/app/models/concerns/account/sensitizes.rb b/app/models/concerns/account/sensitizes.rb new file mode 100644 index 0000000000..3bb74324a8 --- /dev/null +++ b/app/models/concerns/account/sensitizes.rb @@ -0,0 +1,21 @@ +# frozen_string_literal: true + +module Account::Sensitizes + extend ActiveSupport::Concern + + included do + scope :sensitized, -> { where.not(sensitized_at: nil) } + end + + def sensitized? + sensitized_at.present? + end + + def sensitize!(date = Time.now.utc) + update!(sensitized_at: date) + end + + def unsensitize! + update!(sensitized_at: nil) + end +end diff --git a/app/models/concerns/account/silences.rb b/app/models/concerns/account/silences.rb new file mode 100644 index 0000000000..bd785df311 --- /dev/null +++ b/app/models/concerns/account/silences.rb @@ -0,0 +1,22 @@ +# frozen_string_literal: true + +module Account::Silences + extend ActiveSupport::Concern + + included do + scope :silenced, -> { where.not(silenced_at: nil) } + scope :without_silenced, -> { where(silenced_at: nil) } + end + + def silenced? + silenced_at.present? + end + + def silence!(date = Time.now.utc) + update!(silenced_at: date) + end + + def unsilence! + update!(silenced_at: nil) + end +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/notification/groups.rb b/app/models/concerns/notification/groups.rb new file mode 100644 index 0000000000..2f29bd9cea --- /dev/null +++ b/app/models/concerns/notification/groups.rb @@ -0,0 +1,123 @@ +# frozen_string_literal: true + +module Notification::Groups + extend ActiveSupport::Concern + + # `set_group_key!` needs to be updated if this list changes + GROUPABLE_NOTIFICATION_TYPES = %i(favourite reblog follow).freeze + MAXIMUM_GROUP_SPAN_HOURS = 12 + + def set_group_key! + return if filtered? || GROUPABLE_NOTIFICATION_TYPES.exclude?(type) + + type_prefix = case type + when :favourite, :reblog + [type, target_status&.id].join('-') + when :follow + type + else + raise NotImplementedError + end + redis_key = "notif-group/#{account.id}/#{type_prefix}" + hour_bucket = activity.created_at.utc.to_i / 1.hour.to_i + + # Reuse previous group if it does not span too large an amount of time + previous_bucket = redis.get(redis_key).to_i + hour_bucket = previous_bucket if hour_bucket < previous_bucket + MAXIMUM_GROUP_SPAN_HOURS + + # We do not concern ourselves with race conditions since we use hour buckets + redis.set(redis_key, hour_bucket, ex: MAXIMUM_GROUP_SPAN_HOURS.hours.to_i) + + self.group_key = "#{type_prefix}-#{hour_bucket}" + end + + class_methods do + def paginate_groups(limit, pagination_order, grouped_types: nil) + raise ArgumentError unless %i(asc desc).include?(pagination_order) + + query = reorder(id: pagination_order) + + # Ideally `:types` would be a bind rather than part of the SQL itself, but that does not + # seem to be possible to do with Rails, considering that the expression would occur in + # multiple places, including in a `select` + group_key_sql = begin + if grouped_types.present? + # Normalize `grouped_types` so the number of different SQL query shapes remains small, and + # the queries can be analyzed in monitoring/telemetry tools + grouped_types = (grouped_types.map(&:to_sym) & GROUPABLE_NOTIFICATION_TYPES).sort + + sanitize_sql_array([<<~SQL.squish, { types: grouped_types }]) + COALESCE( + CASE + WHEN notifications.type IN (:types) THEN notifications.group_key + ELSE NULL + END, + 'ungrouped-' || notifications.id + ) + SQL + else + "COALESCE(notifications.group_key, 'ungrouped-' || notifications.id)" + end + end + + unscoped + .with_recursive( + grouped_notifications: [ + # Base case: fetching one notification and annotating it with visited groups + query + .select('notifications.*', "ARRAY[#{group_key_sql}] AS groups") + .limit(1), + # Recursive case, always yielding at most one annotated notification + unscoped + .from( + [ + # Expose the working table as `wt`, but quit early if we've reached the limit + unscoped + .select('id', 'groups') + .from('grouped_notifications') + .where('array_length(grouped_notifications.groups, 1) < :limit', limit: limit) + .arel.as('wt'), + # Recursive query, using `LATERAL` so we can refer to `wt` + query + .where(pagination_order == :desc ? 'notifications.id < wt.id' : 'notifications.id > wt.id') + .where.not("#{group_key_sql} = ANY(wt.groups)") + .limit(1) + .arel.lateral('notifications'), + ] + ) + .select('notifications.*', "array_append(wt.groups, #{group_key_sql}) AS groups"), + ] + ) + .from('grouped_notifications AS notifications') + .order(id: pagination_order) + .limit(limit) + end + + # This returns notifications from the request page, but with at most one notification per group. + # Notifications that have no `group_key` each count as a separate group. + def paginate_groups_by_max_id(limit, max_id: nil, since_id: nil, grouped_types: nil) + query = reorder(id: :desc) + query = query.where(id: ...(max_id.to_i)) if max_id.present? + query = query.where(id: (since_id.to_i + 1)...) if since_id.present? + query.paginate_groups(limit, :desc, grouped_types: grouped_types) + end + + # Differs from :paginate_groups_by_max_id in that it gives the results immediately following min_id, + # whereas since_id gives the items with largest id, but with since_id as a cutoff. + # Results will be in ascending order by id. + def paginate_groups_by_min_id(limit, max_id: nil, min_id: nil, grouped_types: nil) + query = reorder(id: :asc) + query = query.where(id: (min_id.to_i + 1)...) if min_id.present? + query = query.where(id: ...(max_id.to_i)) if max_id.present? + query.paginate_groups(limit, :asc, grouped_types: grouped_types) + end + + def to_a_grouped_paginated_by_id(limit, options = {}) + if options[:min_id].present? + paginate_groups_by_min_id(limit, min_id: options[:min_id], max_id: options[:max_id], grouped_types: options[:grouped_types]).reverse + else + paginate_groups_by_max_id(limit, max_id: options[:max_id], since_id: options[:since_id], grouped_types: options[:grouped_types]).to_a + end + end + end +end 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/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_request.rb b/app/models/follow_request.rb index c13cc718d8..964d4e279a 100644 --- a/app/models/follow_request.rb +++ b/app/models/follow_request.rb @@ -33,8 +33,15 @@ class FollowRequest < ApplicationRecord def authorize! follow = account.follow!(target_account, reblogs: show_reblogs, notify: notify, languages: languages, uri: uri, bypass_limit: true) - ListAccount.where(follow_request: self).update_all(follow_request_id: nil, follow_id: follow.id) - MergeWorker.perform_async(target_account.id, account.id) if account.local? + + if account.local? + ListAccount.where(follow_request: self).update_all(follow_request_id: nil, follow_id: follow.id) + MergeWorker.perform_async(target_account.id, account.id, 'home') + MergeWorker.push_bulk(List.where(account: account).joins(:list_accounts).where(list_accounts: { account_id: target_account.id }).pluck(:id)) do |list_id| + [target_account.id, list_id, 'list'] + end + end + destroy! end diff --git a/app/models/instance_filter.rb b/app/models/instance_filter.rb index 1d94c919f9..7e71640e52 100644 --- a/app/models/instance_filter.rb +++ b/app/models/instance_filter.rb @@ -28,9 +28,9 @@ class InstanceFilter def scope_for(key, value) case key.to_s when 'limited' - Instance.joins(:domain_block).reorder(Arel.sql('domain_blocks.id desc')) + Instance.joins(:domain_block).reorder(domain_blocks: { id: :desc }) when 'allowed' - Instance.joins(:domain_allow).reorder(Arel.sql('domain_allows.id desc')) + Instance.joins(:domain_allow).reorder(domain_allows: { id: :desc }) when 'by_domain' Instance.matches_domain(value) when 'availability' diff --git a/app/models/ip_block.rb b/app/models/ip_block.rb index 5ed4d2a846..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, { diff --git a/app/models/list.rb b/app/models/list.rb index d4915f56fa..bb7dd4cfc0 100644 --- a/app/models/list.rb +++ b/app/models/list.rb @@ -34,7 +34,7 @@ class List < ApplicationRecord private def validate_account_lists_limit - errors.add(:base, I18n.t('lists.errors.limit')) if account.lists.count >= PER_ACCOUNT_LIMIT + errors.add(:base, I18n.t('lists.errors.limit')) if account.owned_lists.count >= PER_ACCOUNT_LIMIT end def clean_feed_manager diff --git a/app/models/notification.rb b/app/models/notification.rb index 695f39a316..e7ada3399a 100644 --- a/app/models/notification.rb +++ b/app/models/notification.rb @@ -19,6 +19,7 @@ class Notification < ApplicationRecord self.inheritance_column = nil + include Notification::Groups include Paginable include Redisable @@ -31,10 +32,6 @@ class Notification < ApplicationRecord 'Poll' => :poll, }.freeze - # `set_group_key!` needs to be updated if this list changes - GROUPABLE_NOTIFICATION_TYPES = %i(favourite reblog follow).freeze - MAXIMUM_GROUP_SPAN_HOURS = 12 - # Please update app/javascript/api_types/notification.ts if you change this PROPERTIES = { mention: { @@ -67,6 +64,9 @@ class Notification < ApplicationRecord moderation_warning: { filterable: false, }.freeze, + annual_report: { + filterable: false, + }.freeze, 'admin.sign_up': { filterable: false, }.freeze, @@ -101,6 +101,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 } @@ -126,30 +127,6 @@ class Notification < ApplicationRecord end end - def set_group_key! - return if filtered? || Notification::GROUPABLE_NOTIFICATION_TYPES.exclude?(type) - - type_prefix = case type - when :favourite, :reblog - [type, target_status&.id].join('-') - when :follow - type - else - raise NotImplementedError - end - redis_key = "notif-group/#{account.id}/#{type_prefix}" - hour_bucket = activity.created_at.utc.to_i / 1.hour.to_i - - # Reuse previous group if it does not span too large an amount of time - previous_bucket = redis.get(redis_key).to_i - hour_bucket = previous_bucket if hour_bucket < previous_bucket + MAXIMUM_GROUP_SPAN_HOURS - - # We do not concern ourselves with race conditions since we use hour buckets - redis.set(redis_key, hour_bucket, ex: MAXIMUM_GROUP_SPAN_HOURS.hours.to_i) - - self.group_key = "#{type_prefix}-#{hour_bucket}" - end - class << self def browserable(types: [], exclude_types: [], from_account_id: nil, include_filtered: false) requested_types = if types.empty? @@ -167,94 +144,6 @@ class Notification < ApplicationRecord end end - def paginate_groups(limit, pagination_order, grouped_types: nil) - raise ArgumentError unless %i(asc desc).include?(pagination_order) - - query = reorder(id: pagination_order) - - # Ideally `:types` would be a bind rather than part of the SQL itself, but that does not - # seem to be possible to do with Rails, considering that the expression would occur in - # multiple places, including in a `select` - group_key_sql = begin - if grouped_types.present? - # Normalize `grouped_types` so the number of different SQL query shapes remains small, and - # the queries can be analyzed in monitoring/telemetry tools - grouped_types = (grouped_types.map(&:to_sym) & GROUPABLE_NOTIFICATION_TYPES).sort - - sanitize_sql_array([<<~SQL.squish, { types: grouped_types }]) - COALESCE( - CASE - WHEN notifications.type IN (:types) THEN notifications.group_key - ELSE NULL - END, - 'ungrouped-' || notifications.id - ) - SQL - else - "COALESCE(notifications.group_key, 'ungrouped-' || notifications.id)" - end - end - - unscoped - .with_recursive( - grouped_notifications: [ - # Base case: fetching one notification and annotating it with visited groups - query - .select('notifications.*', "ARRAY[#{group_key_sql}] AS groups") - .limit(1), - # Recursive case, always yielding at most one annotated notification - unscoped - .from( - [ - # Expose the working table as `wt`, but quit early if we've reached the limit - unscoped - .select('id', 'groups') - .from('grouped_notifications') - .where('array_length(grouped_notifications.groups, 1) < :limit', limit: limit) - .arel.as('wt'), - # Recursive query, using `LATERAL` so we can refer to `wt` - query - .where(pagination_order == :desc ? 'notifications.id < wt.id' : 'notifications.id > wt.id') - .where.not("#{group_key_sql} = ANY(wt.groups)") - .limit(1) - .arel.lateral('notifications'), - ] - ) - .select('notifications.*', "array_append(wt.groups, #{group_key_sql}) AS groups"), - ] - ) - .from('grouped_notifications AS notifications') - .order(id: pagination_order) - .limit(limit) - end - - # This returns notifications from the request page, but with at most one notification per group. - # Notifications that have no `group_key` each count as a separate group. - def paginate_groups_by_max_id(limit, max_id: nil, since_id: nil, grouped_types: nil) - query = reorder(id: :desc) - query = query.where(id: ...(max_id.to_i)) if max_id.present? - query = query.where(id: (since_id.to_i + 1)...) if since_id.present? - query.paginate_groups(limit, :desc, grouped_types: grouped_types) - end - - # Differs from :paginate_groups_by_max_id in that it gives the results immediately following min_id, - # whereas since_id gives the items with largest id, but with since_id as a cutoff. - # Results will be in ascending order by id. - def paginate_groups_by_min_id(limit, max_id: nil, min_id: nil, grouped_types: nil) - query = reorder(id: :asc) - query = query.where(id: (min_id.to_i + 1)...) if min_id.present? - query = query.where(id: ...(max_id.to_i)) if max_id.present? - query.paginate_groups(limit, :asc, grouped_types: grouped_types) - end - - def to_a_grouped_paginated_by_id(limit, options = {}) - if options[:min_id].present? - paginate_groups_by_min_id(limit, min_id: options[:min_id], max_id: options[:max_id], grouped_types: options[:grouped_types]).reverse - else - paginate_groups_by_max_id(limit, max_id: options[:max_id], since_id: options[:since_id], grouped_types: options[:grouped_types]).to_a - end - end - def preload_cache_collection_target_statuses(notifications, &_block) notifications.group_by(&:type).each do |type, grouped_notifications| associations = TARGET_STATUS_INCLUDES_BY_TYPE[type] @@ -309,7 +198,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/poll.rb b/app/models/poll.rb index cc4184f80a..ebd4644094 100644 --- a/app/models/poll.rb +++ b/app/models/poll.rb @@ -29,8 +29,8 @@ class Poll < ApplicationRecord has_many :votes, class_name: 'PollVote', inverse_of: :poll, dependent: :delete_all with_options class_name: 'Account', source: :account, through: :votes do - has_many :voters, -> { group('accounts.id') } - has_many :local_voters, -> { group('accounts.id').merge(Account.local) } + has_many :voters, -> { group(accounts: [:id]) } + has_many :local_voters, -> { group(accounts: [:id]).merge(Account.local) } end has_many :notifications, as: :activity, dependent: :destroy diff --git a/app/models/relay.rb b/app/models/relay.rb index f652b4864b..1a8fdebc7f 100644 --- a/app/models/relay.rb +++ b/app/models/relay.rb @@ -25,6 +25,10 @@ class Relay < ApplicationRecord alias enabled? accepted? + def to_log_human_identifier + inbox_url + end + def enable! activity_id = ActivityPub::TagManager.instance.generate_uri_for(nil) payload = Oj.dump(follow_activity(activity_id)) 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 31f18fd7ef..d99ecf8adb 100644 --- a/app/models/session_activation.rb +++ b/app/models/session_activation.rb @@ -30,6 +30,8 @@ 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) @@ -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/software_update.rb b/app/models/software_update.rb index 51a73c2731..7e2b15656e 100644 --- a/app/models/software_update.rb +++ b/app/models/software_update.rb @@ -22,19 +22,33 @@ class SoftwareUpdate < ApplicationRecord Gem::Version.new(version) end + def outdated? + runtime_version >= gem_version + end + + def pending? + gem_version > runtime_version + end + class << self def check_enabled? - ENV['UPDATE_CHECK_URL'] != '' + Rails.configuration.x.mastodon.software_update_url.present? end def pending_to_a return [] unless check_enabled? - all.to_a.filter { |update| update.gem_version > Mastodon::Version.gem_version } + all.to_a.filter(&:pending?) end def urgent_pending? pending_to_a.any?(&:urgent?) end end + + private + + def runtime_version + Mastodon::Version.gem_version + end end diff --git a/app/models/status.rb b/app/models/status.rb index f0a4f50ff6..5a81b00773 100644 --- a/app/models/status.rb +++ b/app/models/status.rb @@ -127,6 +127,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) } after_create_commit :trigger_create_webhooks after_update_commit :trigger_update_webhooks @@ -355,23 +356,23 @@ class Status < ApplicationRecord end def favourites_map(status_ids, account_id) - Favourite.select('status_id').where(status_id: status_ids).where(account_id: account_id).each_with_object({}) { |f, h| h[f.status_id] = true } + Favourite.select(:status_id).where(status_id: status_ids).where(account_id: account_id).each_with_object({}) { |f, h| h[f.status_id] = true } end def bookmarks_map(status_ids, account_id) - Bookmark.select('status_id').where(status_id: status_ids).where(account_id: account_id).map { |f| [f.status_id, true] }.to_h + Bookmark.select(:status_id).where(status_id: status_ids).where(account_id: account_id).map { |f| [f.status_id, true] }.to_h end def reblogs_map(status_ids, account_id) - unscoped.select('reblog_of_id').where(reblog_of_id: status_ids).where(account_id: account_id).each_with_object({}) { |s, h| h[s.reblog_of_id] = true } + unscoped.select(:reblog_of_id).where(reblog_of_id: status_ids).where(account_id: account_id).each_with_object({}) { |s, h| h[s.reblog_of_id] = true } end def mutes_map(conversation_ids, account_id) - ConversationMute.select('conversation_id').where(conversation_id: conversation_ids).where(account_id: account_id).each_with_object({}) { |m, h| h[m.conversation_id] = true } + ConversationMute.select(:conversation_id).where(conversation_id: conversation_ids).where(account_id: account_id).each_with_object({}) { |m, h| h[m.conversation_id] = true } end def pins_map(status_ids, account_id) - StatusPin.select('status_id').where(status_id: status_ids).where(account_id: account_id).each_with_object({}) { |p, h| h[p.status_id] = true } + StatusPin.select(:status_id).where(status_id: status_ids).where(account_id: account_id).each_with_object({}) { |p, h| h[p.status_id] = true } end def from_text(text) diff --git a/app/models/tag.rb b/app/models/tag.rb index 93210eb307..67fa9e5d3a 100644 --- a/app/models/tag.rb +++ b/app/models/tag.rb @@ -61,7 +61,7 @@ class Tag < ApplicationRecord scope :recently_used, lambda { |account| joins(:statuses) .where(statuses: { id: account.statuses.select(:id).limit(RECENT_STATUS_LIMIT) }) - .group(:id).order(Arel.sql('count(*) desc')) + .group(:id).order(Arel.star.count.desc) } scope :matches_name, ->(term) { where(arel_table[:name].lower.matches(arel_table.lower("#{sanitize_sql_like(Tag.normalize(term))}%"), nil, true)) } # Search with case-sensitive to use B-tree index @@ -127,7 +127,7 @@ class Tag < ApplicationRecord query = query.merge(Tag.listable) if options[:exclude_unlistable] query = query.merge(matching_name(stripped_term).or(reviewed)) if options[:exclude_unreviewed] - query.order(Arel.sql('length(name) ASC, name ASC')) + query.order(Arel.sql('LENGTH(name)').asc, name: :asc) .limit(limit) .offset(offset) end diff --git a/app/models/tag_follow.rb b/app/models/tag_follow.rb index abe36cd171..528616c450 100644 --- a/app/models/tag_follow.rb +++ b/app/models/tag_follow.rb @@ -21,4 +21,6 @@ class TagFollow < ApplicationRecord accepts_nested_attributes_for :tag rate_limit by: :account, family: :follows + + scope :for_local_distribution, -> { joins(account: :user).merge(User.signed_in_recently) } end diff --git a/app/models/trends/statuses.rb b/app/models/trends/statuses.rb index 8757e5aa9c..cdf5929069 100644 --- a/app/models/trends/statuses.rb +++ b/app/models/trends/statuses.rb @@ -106,7 +106,7 @@ class Trends::Statuses < Trends::Base private def eligible?(status) - status.public_visibility? && status.account.discoverable? && !status.account.silenced? && !status.account.sensitized? && status.spoiler_text.blank? && !status.sensitive? && !status.reply? && valid_locale?(status.language) + status.created_at.past? && status.public_visibility? && status.account.discoverable? && !status.account.silenced? && !status.account.sensitized? && status.spoiler_text.blank? && !status.sensitive? && !status.reply? && valid_locale?(status.language) end def calculate_scores(statuses, at_time) diff --git a/app/models/user.rb b/app/models/user.rb index 69c5a01569..c90a78f0cc 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 @@ -280,6 +280,15 @@ class User < ApplicationRecord save! end + def applications_last_used + Doorkeeper::AccessToken + .where(resource_owner_id: id) + .where.not(last_used_at: nil) + .group(:application_id) + .maximum(:last_used_at) + .to_h + end + def token_for_app(app) return nil if app.nil? || app.owner != self @@ -340,7 +349,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`` @@ -444,7 +453,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? @@ -457,13 +466,7 @@ class User < ApplicationRecord # Doing this conditionally is not very satisfying, but this is consistent # with the MX records validations we do and keeps the specs tractable. - unless self.class.skip_mx_check? - Resolv::DNS.open do |dns| - dns.timeouts = 5 - - records = dns.getresources(domain, Resolv::DNS::Resource::IN::MX).to_a.map { |e| e.exchange.to_s }.compact_blank - end - end + records = DomainResource.new(domain).mx unless self.class.skip_mx_check? EmailDomainBlock.requires_approval?(records + [domain], attempt_ip: sign_up_ip) end 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/presenters/oauth_metadata_presenter.rb b/app/presenters/oauth_metadata_presenter.rb index 7d75e8498a..f488a62925 100644 --- a/app/presenters/oauth_metadata_presenter.rb +++ b/app/presenters/oauth_metadata_presenter.rb @@ -65,7 +65,7 @@ class OauthMetadataPresenter < ActiveModelSerializers::Model end def code_challenge_methods_supported - %w(S256) + doorkeeper.pkce_code_challenge_methods_supported end private 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/credential_application_serializer.rb b/app/serializers/rest/credential_application_serializer.rb index bfec7d03e8..0532390c9a 100644 --- a/app/serializers/rest/credential_application_serializer.rb +++ b/app/serializers/rest/credential_application_serializer.rb @@ -1,7 +1,7 @@ # frozen_string_literal: true class REST::CredentialApplicationSerializer < REST::ApplicationSerializer - attributes :client_id, :client_secret + attributes :client_id, :client_secret, :client_secret_expires_at def client_id object.uid @@ -10,4 +10,10 @@ class REST::CredentialApplicationSerializer < REST::ApplicationSerializer def client_secret object.secret end + + # Added for future forwards compatibility when we may decide to expire OAuth + # Applications. Set to zero means that the client_secret never expires. + def client_secret_expires_at + 0 + end end diff --git a/app/serializers/rest/notification_group_serializer.rb b/app/serializers/rest/notification_group_serializer.rb index 7e8f00df3c..f4af842e38 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/v1/instance_serializer.rb b/app/serializers/rest/v1/instance_serializer.rb index 7f9f21c5af..db83af4907 100644 --- a/app/serializers/rest/v1/instance_serializer.rb +++ b/app/serializers/rest/v1/instance_serializer.rb @@ -48,14 +48,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/add_accounts_to_list_service.rb b/app/services/add_accounts_to_list_service.rb new file mode 100644 index 0000000000..df4e4c8314 --- /dev/null +++ b/app/services/add_accounts_to_list_service.rb @@ -0,0 +1,33 @@ +# frozen_string_literal: true + +class AddAccountsToListService < BaseService + def call(list, accounts) + @list = list + @accounts = accounts + + return if @accounts.empty? + + update_list! + merge_into_list! + end + + private + + def update_list! + ApplicationRecord.transaction do + @accounts.each do |account| + @list.accounts << account + end + end + end + + def merge_into_list! + MergeWorker.push_bulk(merge_account_ids) do |account_id| + [account_id, @list.id, 'list'] + end + end + + def merge_account_ids + ListAccount.where(list: @list, account: @accounts).where.not(follow_id: nil).pluck(:account_id) + end +end diff --git a/app/services/fan_out_on_write_service.rb b/app/services/fan_out_on_write_service.rb index 50b414bc52..3c084bc857 100644 --- a/app/services/fan_out_on_write_service.rb +++ b/app/services/fan_out_on_write_service.rb @@ -103,7 +103,7 @@ class FanOutOnWriteService < BaseService end def deliver_to_hashtag_followers! - TagFollow.where(tag_id: @status.tags.map(&:id)).select(:id, :account_id).reorder(nil).find_in_batches do |follows| + TagFollow.for_local_distribution.where(tag_id: @status.tags.map(&:id)).select(:id, :account_id).reorder(nil).find_in_batches do |follows| FeedInsertWorker.push_bulk(follows) do |follow| [@status.id, follow.account_id, 'tags', { 'update' => update? }] end diff --git a/app/services/fetch_resource_service.rb b/app/services/fetch_resource_service.rb index 911950ccca..3fde78455c 100644 --- a/app/services/fetch_resource_service.rb +++ b/app/services/fetch_resource_service.rb @@ -74,7 +74,7 @@ class FetchResourceService < BaseService def process_html(response) page = Nokogiri::HTML5(response.body_with_limit) - json_link = page.xpath('//link[@rel="alternate"]').find { |link| ACTIVITY_STREAM_LINK_TYPES.include?(link['type']) } + json_link = page.xpath('//link[nokogiri:link_rel_include(@rel, "alternate")]', NokogiriHandler).find { |link| ACTIVITY_STREAM_LINK_TYPES.include?(link['type']) } process(json_link['href'], terminal: true) unless json_link.nil? end diff --git a/app/services/follow_service.rb b/app/services/follow_service.rb index af5f996077..cff38b8e6e 100644 --- a/app/services/follow_service.rb +++ b/app/services/follow_service.rb @@ -81,7 +81,10 @@ class FollowService < BaseService follow = @source_account.follow!(@target_account, **follow_options.merge(rate_limit: @options[:with_rate_limit], bypass_limit: @options[:bypass_limit])) LocalNotificationWorker.perform_async(@target_account.id, follow.id, follow.class.name, 'follow') - MergeWorker.perform_async(@target_account.id, @source_account.id) + MergeWorker.perform_async(@target_account.id, @source_account.id, 'home') + MergeWorker.push_bulk(List.where(account: @source_account).joins(:list_accounts).where(list_accounts: { account_id: @target_account.id }).pluck(:id)) do |list_id| + [@target_account.id, list_id, 'list'] + end follow 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 98fd95f025..765c80723e 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 @@ -38,6 +36,8 @@ class PostStatusService < BaseService @text = @options[:text] || '' @in_reply_to = @options[:thread] + @antispam = Antispam.new + return idempotency_duplicate if idempotency_given? && idempotency_duplicate? validate_media! @@ -57,6 +57,8 @@ class PostStatusService < BaseService end @status + rescue Antispam::SilentlyDrop => e + e.status end private @@ -76,6 +78,7 @@ class PostStatusService < BaseService @status = @account.statuses.new(status_attributes) process_mentions_service.call(@status, save_records: false) safeguard_mentions!(@status) + @antispam.local_preflight_check!(@status) # The following transaction block is needed to wrap the UPDATEs to # the media attachments when the status is created @@ -97,6 +100,7 @@ class PostStatusService < BaseService def schedule_status! status_for_validation = @account.statuses.build(status_attributes) + @antispam.local_preflight_check!(status_for_validation) if status_for_validation.valid? # Marking the status as destroyed is necessary to prevent the status from being @@ -113,6 +117,8 @@ class PostStatusService < BaseService else raise ActiveRecord::RecordInvalid end + rescue Antispam::SilentlyDrop + @status = @account.scheduled_status.new(scheduled_status_attributes).tap(&:delete) end def postprocess_status! 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_accounts_from_list_service.rb b/app/services/remove_accounts_from_list_service.rb new file mode 100644 index 0000000000..bd5b7c439e --- /dev/null +++ b/app/services/remove_accounts_from_list_service.rb @@ -0,0 +1,29 @@ +# frozen_string_literal: true + +class RemoveAccountsFromListService < BaseService + def call(list, accounts) + @list = list + @accounts = accounts + + return if @accounts.empty? + + unmerge_from_list! + update_list! + end + + private + + def update_list! + ListAccount.where(list: @list, account: @accounts).destroy_all + end + + def unmerge_from_list! + UnmergeWorker.push_bulk(unmerge_account_ids) do |account_id| + [account_id, @list.id, 'list'] + end + end + + def unmerge_account_ids + ListAccount.where(list: @list, account: @accounts).where.not(follow_id: nil).pluck(:account_id) + end +end diff --git a/app/services/remove_status_service.rb b/app/services/remove_status_service.rb index 221791ad32..dc9fb6cab6 100644 --- a/app/services/remove_status_service.rb +++ b/app/services/remove_status_service.rb @@ -115,7 +115,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/software_update_check_service.rb b/app/services/software_update_check_service.rb index 24a6955b88..45ec1f50db 100644 --- a/app/services/software_update_check_service.rb +++ b/app/services/software_update_check_service.rb @@ -12,7 +12,7 @@ class SoftwareUpdateCheckService < BaseService def clean_outdated_updates! SoftwareUpdate.find_each do |software_update| - software_update.delete if Mastodon::Version.gem_version >= software_update.gem_version + software_update.delete if software_update.outdated? rescue ArgumentError software_update.delete end @@ -27,7 +27,7 @@ class SoftwareUpdateCheckService < BaseService end def api_url - ENV.fetch('UPDATE_CHECK_URL', 'https://api.joinmastodon.org/update-check') + Rails.configuration.x.mastodon.software_update_url end def version 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/services/unfollow_service.rb b/app/services/unfollow_service.rb index fe9a7f0d87..b3f2cd66f6 100644 --- a/app/services/unfollow_service.rb +++ b/app/services/unfollow_service.rb @@ -31,7 +31,13 @@ class UnfollowService < BaseService create_notification(follow) if !@target_account.local? && @target_account.activitypub? create_reject_notification(follow) if @target_account.local? && !@source_account.local? && @source_account.activitypub? - UnmergeWorker.perform_async(@target_account.id, @source_account.id) unless @options[:skip_unmerge] + + unless @options[:skip_unmerge] + UnmergeWorker.perform_async(@target_account.id, @source_account.id, 'home') + UnmergeWorker.push_bulk(List.where(account: @source_account).joins(:list_accounts).where(list_accounts: { account_id: @target_account.id }).pluck(:list_id)) do |list_id| + [@target_account.id, list_id, 'list'] + end + end follow end diff --git a/app/services/unmute_service.rb b/app/services/unmute_service.rb index 6aeea358f7..9262961f7d 100644 --- a/app/services/unmute_service.rb +++ b/app/services/unmute_service.rb @@ -6,6 +6,12 @@ class UnmuteService < BaseService account.unmute!(target_account) - MergeWorker.perform_async(target_account.id, account.id) if account.following?(target_account) + if account.following?(target_account) + MergeWorker.perform_async(target_account.id, account.id, 'home') + + MergeWorker.push_bulk(List.where(account: account).joins(:list_accounts).where(list_accounts: { account_id: target_account.id }).pluck(:id)) do |list_id| + [target_account.id, list_id, 'list'] + end + end end end diff --git a/app/services/verify_link_service.rb b/app/services/verify_link_service.rb index 17c86426be..fc3c4cbc28 100644 --- a/app/services/verify_link_service.rb +++ b/app/services/verify_link_service.rb @@ -26,7 +26,7 @@ class VerifyLinkService < BaseService def link_back_present? return false if @body.blank? - links = Nokogiri::HTML5(@body).css("a[rel~='me'],link[rel~='me']") + links = Nokogiri::HTML5(@body).xpath('(//a|//link)[@rel][nokogiri:link_rel_include(@rel, "me")]', NokogiriHandler) if links.any? { |link| link['href']&.downcase == @link_back.downcase } true diff --git a/app/views/about/show.html.haml b/app/views/about/show.html.haml index 05d8989add..e8f7b43eaa 100644 --- a/app/views/about/show.html.haml +++ b/app/views/about/show.html.haml @@ -1,5 +1,4 @@ -- content_for :page_title do - = t('about.title') +- content_for :page_title, t('about.title') - content_for :header_tags do = render partial: 'shared/og' diff --git a/app/views/accounts/show.html.haml b/app/views/accounts/show.html.haml index dde9c50847..1f5f81348e 100644 --- a/app/views/accounts/show.html.haml +++ b/app/views/accounts/show.html.haml @@ -1,5 +1,4 @@ -- content_for :page_title do - #{display_name(@account)} (#{acct(@account)}) +- content_for :page_title, "#{display_name(@account)} (#{acct(@account)})" - content_for :header_tags do - if @account.user_prefers_noindex? diff --git a/app/views/admin/dashboard/index.html.haml b/app/views/admin/dashboard/index.html.haml index 2b4d02fa67..c3b7933293 100644 --- a/app/views/admin/dashboard/index.html.haml +++ b/app/views/admin/dashboard/index.html.haml @@ -16,7 +16,7 @@ .dashboard__item = react_admin_component :counter, end_at: @time_period.last, - href: admin_accounts_path(origin: 'local'), + href: current_user.can?(:manage_users) ? admin_accounts_path(origin: 'local') : nil, label: t('admin.dashboard.new_users'), measure: 'new_users', start_at: @time_period.first @@ -24,7 +24,7 @@ .dashboard__item = react_admin_component :counter, end_at: @time_period.last, - href: admin_accounts_path(origin: 'local'), + href: current_user.can?(:manage_users) ? admin_accounts_path(origin: 'local') : nil, label: t('admin.dashboard.active_users'), measure: 'active_users', start_at: @time_period.first @@ -39,7 +39,7 @@ .dashboard__item = react_admin_component :counter, end_at: @time_period.last, - href: admin_reports_path, + href: current_user.can?(:manage_reports) ? admin_reports_path : nil, label: t('admin.dashboard.opened_reports'), measure: 'opened_reports', start_at: @time_period.first @@ -47,7 +47,7 @@ .dashboard__item = react_admin_component :counter, end_at: @time_period.last, - href: admin_reports_path(resolved: '1'), + href: current_user.can?(:manage_reports) ? admin_reports_path(resolved: '1') : nil, label: t('admin.dashboard.resolved_reports'), measure: 'resolved_reports', start_at: @time_period.first diff --git a/app/views/admin/email_domain_blocks/new.html.haml b/app/views/admin/email_domain_blocks/new.html.haml index 2dfdca9376..4db8fbe5e5 100644 --- a/app/views/admin/email_domain_blocks/new.html.haml +++ b/app/views/admin/email_domain_blocks/new.html.haml @@ -30,12 +30,12 @@ %label.batch-table__row__select.batch-table__row__select--aligned.batch-checkbox = f.input_field :other_domains, as: :boolean, - checked_value: record.exchange.to_s, + checked_value: record, include_hidden: false, multiple: true .batch-table__row__content.pending-account .pending-account__header - %samp= record.exchange.to_s + %samp= record %br = t('admin.email_domain_blocks.dns.types.mx') diff --git a/app/views/admin/instances/_dashboard.html.haml b/app/views/admin/instances/_dashboard.html.haml index ef8500103b..16dcb051a2 100644 --- a/app/views/admin/instances/_dashboard.html.haml +++ b/app/views/admin/instances/_dashboard.html.haml @@ -7,7 +7,7 @@ .dashboard__item = react_admin_component :counter, end_at: period_end_at, - href: admin_accounts_path(origin: 'remote', by_domain: instance_domain), + href: current_user.can?(:manage_users) ? admin_accounts_path(origin: 'remote', by_domain: instance_domain) : nil, label: t('admin.instances.dashboard.instance_accounts_measure'), measure: 'instance_accounts', params: { domain: instance_domain }, @@ -43,7 +43,7 @@ .dashboard__item = react_admin_component :counter, end_at: period_end_at, - href: admin_reports_path(by_target_domain: instance_domain), + href: current_user.can?(:manage_reports) ? admin_reports_path(by_target_domain: instance_domain) : nil, label: t('admin.instances.dashboard.instance_reports_measure'), measure: 'instance_reports', params: { domain: instance_domain }, diff --git a/app/views/admin/reports/_status.html.haml b/app/views/admin/reports/_status.html.haml index f4630ed25a..d20266aa2c 100644 --- a/app/views/admin/reports/_status.html.haml +++ b/app/views/admin/reports/_status.html.haml @@ -2,40 +2,52 @@ %label.batch-table__row__select.batch-checkbox = f.check_box :status_ids, { multiple: true, include_hidden: false }, status.id .batch-table__row__content - .status__content>< - - if status.proper.spoiler_text.blank? - = prerender_custom_emojis(status_content_format(status.proper), status.proper.emojis) - - else - %details< - %summary>< - %strong> Content warning: #{prerender_custom_emojis(h(status.proper.spoiler_text), status.proper.emojis)} - = prerender_custom_emojis(status_content_format(status.proper), status.proper.emojis) - - - unless status.proper.ordered_media_attachments.empty? - = render partial: 'admin/reports/media_attachments', locals: { status: status.proper } - - .detailed-status__meta - - if status.application - = status.application.name - · - = link_to ActivityPub::TagManager.instance.url_for(status.proper), class: 'detailed-status__datetime', target: stream_link_target, rel: 'noopener noreferrer' do - %time.formatted{ datetime: status.created_at.iso8601, title: l(status.created_at) }= l(status.created_at) - - if status.edited? - · - = link_to t('statuses.edited_at_html', date: content_tag(:time, l(status.edited_at), datetime: status.edited_at.iso8601, title: l(status.edited_at), class: 'formatted')), - admin_account_status_path(status.account_id, status), - class: 'detailed-status__datetime' - - if status.discarded? - · - %span.negative-hint= t('admin.statuses.deleted') - · + .status__card - if status.reblog? - = material_symbol('repeat_active') - = t('statuses.boosted_from_html', acct_link: admin_account_inline_link_to(status.proper.account)) - - else + .status__prepend + = material_symbol('repeat') + = t('statuses.boosted_from_html', acct_link: admin_account_inline_link_to(status.proper.account, path: admin_account_status_path(status.proper.account.id, status.proper.id))) + - elsif status.reply? && status.in_reply_to_id.present? + .status__prepend + = material_symbol('reply') + = t('admin.statuses.replied_to_html', acct_link: admin_account_inline_link_to(status.in_reply_to_account, path: status.thread.present? ? admin_account_status_path(status.thread.account_id, status.in_reply_to_id) : nil)) + .status__content>< + - if status.proper.spoiler_text.blank? + = prerender_custom_emojis(status_content_format(status.proper), status.proper.emojis) + - else + %details< + %summary>< + %strong> Content warning: #{prerender_custom_emojis(h(status.proper.spoiler_text), status.proper.emojis)} + = prerender_custom_emojis(status_content_format(status.proper), status.proper.emojis) + + - unless status.proper.ordered_media_attachments.empty? + = render partial: 'admin/reports/media_attachments', locals: { status: status.proper } + + .detailed-status__meta + - if status.application + = status.application.name + · + + = link_to admin_account_status_path(status.account.id, status), class: 'detailed-status__datetime' do + %time.formatted{ datetime: status.created_at.iso8601, title: l(status.created_at) }= l(status.created_at) + - if status.edited? + · + = link_to t('statuses.edited_at_html', date: content_tag(:time, l(status.edited_at), datetime: status.edited_at.iso8601, title: l(status.edited_at), class: 'formatted')), + admin_account_status_path(status.account_id, status), + class: 'detailed-status__datetime' + - if status.discarded? + · + %span.negative-hint= t('admin.statuses.deleted') + · + = material_symbol visibility_icon(status) = t("statuses.visibilities.#{status.visibility}") - - if status.proper.sensitive? · - = material_symbol('visibility_off') - = t('stream_entries.sensitive_content') + + = link_to ActivityPub::TagManager.instance.url_for(status.proper), class: 'detailed-status__link', rel: 'noopener noreferrer' do + = t('admin.statuses.view_publicly') + + - if status.proper.sensitive? + · + = material_symbol('visibility_off') + = t('stream_entries.sensitive_content') diff --git a/app/views/admin/statuses/index.html.haml b/app/views/admin/statuses/index.html.haml index 4d5d037060..57b9fe0e15 100644 --- a/app/views/admin/statuses/index.html.haml +++ b/app/views/admin/statuses/index.html.haml @@ -1,7 +1,5 @@ - content_for :page_title do - = t('admin.statuses.title') - \- - @#{@account.pretty_acct} + = t('admin.statuses.title', name: @account.pretty_acct) .filters .filter-subset @@ -33,11 +31,18 @@ = check_box_tag :batch_checkbox_all, nil, false .batch-table__toolbar__actions - unless @statuses.empty? - = f.button safe_join([material_symbol('flag'), t('admin.statuses.batch.report')]), - class: 'table-action-link', - data: { confirm: t('admin.reports.are_you_sure') }, - name: :report, - type: :submit + - if params[:report_id] + = f.button safe_join([material_symbol('add'), t('admin.statuses.batch.add_to_report', id: params[:report_id])]), + class: 'table-action-link', + data: { confirm: t('admin.reports.are_you_sure') }, + name: :report, + type: :submit + - else + = f.button safe_join([material_symbol('flag'), t('admin.statuses.batch.report')]), + class: 'table-action-link', + data: { confirm: t('admin.reports.are_you_sure') }, + name: :report, + type: :submit .batch-table__body - if @statuses.empty? = nothing_here 'nothing-here--under-tabs' diff --git a/app/views/admin/statuses/show.html.haml b/app/views/admin/statuses/show.html.haml index 9cadde2870..1ff4763158 100644 --- a/app/views/admin/statuses/show.html.haml +++ b/app/views/admin/statuses/show.html.haml @@ -1,7 +1,14 @@ - content_for :page_title do - = t('statuses.title', name: display_name(@account), quote: truncate(@status.spoiler_text.presence || @status.text, length: 50, omission: '…', escape: false)) + = t('admin.statuses.status_title', name: @account.pretty_acct) - content_for :heading_actions do + = form_with model: @status_batch_action, url: batch_admin_account_statuses_path(@account.id) do |f| + = f.hidden_field :status_ids, { multiple: true, value: @status.id } + = f.button safe_join([material_symbol('flag'), t('admin.statuses.batch.report')]), + class: 'button', + data: { confirm: t('admin.reports.are_you_sure') }, + name: :report, + type: :submit = link_to t('admin.statuses.open'), ActivityPub::TagManager.instance.url_for(@status), class: 'button', target: '_blank', rel: 'noopener noreferrer' %h3= t('admin.statuses.metadata') @@ -15,7 +22,7 @@ - if @status.reply? %tr %th= t('admin.statuses.in_reply_to') - %td= admin_account_link_to @status.in_reply_to_account, path: admin_account_status_path(@status.thread.account_id, @status.in_reply_to_id) + %td= admin_account_link_to @status.in_reply_to_account, path: @status.thread.present? ? admin_account_status_path(@status.thread.account_id, @status.in_reply_to_id) : nil %tr %th= t('admin.statuses.application') %td= @status.application&.name @@ -44,7 +51,56 @@ %hr.spacer/ -%h3= t('admin.statuses.history') +%h3= t('admin.statuses.contents') -%ol.history - = render partial: 'admin/status_edits/status_edit', collection: batched_ordered_status_edits +.status__card + - if @status.reblog? + .status__prepend + = material_symbol('repeat') + = t('statuses.boosted_from_html', acct_link: admin_account_inline_link_to(@status.proper.account, path: admin_account_status_path(@status.proper.account.id, @status.proper.id))) + - elsif @status.reply? && @status.in_reply_to_id.present? + .status__prepend + = material_symbol('reply') + = t('admin.statuses.replied_to_html', acct_link: admin_account_inline_link_to(@status.in_reply_to_account, path: @status.thread.present? ? admin_account_status_path(@status.thread.account_id, @status.in_reply_to_id) : nil)) + .status__content>< + - if @status.proper.spoiler_text.blank? + = prerender_custom_emojis(status_content_format(@status.proper), @status.proper.emojis) + - else + %details< + %summary>< + %strong> Content warning: #{prerender_custom_emojis(h(@status.proper.spoiler_text), @status.proper.emojis)} + = prerender_custom_emojis(status_content_format(@status.proper), @status.proper.emojis) + + - unless @status.proper.ordered_media_attachments.empty? + = render partial: 'admin/reports/media_attachments', locals: { status: @status.proper } + + .detailed-status__meta + - if @status.application + = @status.application.name + · + %span.detailed-status__datetime + %time.formatted{ datetime: @status.created_at.iso8601, title: l(@status.created_at) }= l(@status.created_at) + - if @status.edited? + · + %span.detailed-status__datetime + = t('statuses.edited_at_html', date: content_tag(:time, l(@status.edited_at), datetime: @status.edited_at.iso8601, title: l(@status.edited_at), class: 'formatted')) + - if @status.discarded? + · + %span.negative-hint= t('admin.statuses.deleted') + - unless @status.reblog? + · + = material_symbol(visibility_icon(@status)) + = t("statuses.visibilities.#{@status.visibility}") + - if @status.proper.sensitive? + · + = material_symbol('visibility_off') + = t('stream_entries.sensitive_content') + +%hr.spacer/ + +%h3= t('admin.statuses.history') +- if @status.edits.empty? + %p= t('admin.statuses.no_history') +- else + %ol.history + = render partial: 'admin/status_edits/status_edit', collection: batched_ordered_status_edits diff --git a/app/views/filters/statuses/_status_filter.html.haml b/app/views/filters/statuses/_status_filter.html.haml index d0d04638d2..3476869e60 100644 --- a/app/views/filters/statuses/_status_filter.html.haml +++ b/app/views/filters/statuses/_status_filter.html.haml @@ -23,7 +23,7 @@ = image_tag(status.account.avatar.url, width: 15, height: 15, alt: '', class: 'avatar') .username= status.account.acct · - = link_to ActivityPub::TagManager.instance.url_for(status), class: 'detailed-status__datetime', target: stream_link_target, rel: 'noopener noreferrer' do + = link_to ActivityPub::TagManager.instance.url_for(status), class: 'detailed-status__datetime', rel: 'noopener noreferrer' do %time.formatted{ datetime: status.created_at.iso8601, title: l(status.created_at) }= l(status.created_at) - if status.edited? · diff --git a/app/views/privacy/show.html.haml b/app/views/privacy/show.html.haml index 95e506641b..9eb4f7a570 100644 --- a/app/views/privacy/show.html.haml +++ b/app/views/privacy/show.html.haml @@ -1,5 +1,4 @@ -- content_for :page_title do - = t('privacy_policy.title') +- content_for :page_title, t('privacy_policy.title') - content_for :header_tags do = render partial: 'shared/og' diff --git a/app/views/relationships/show.html.haml b/app/views/relationships/show.html.haml index 7478b8c5ce..b062a4f53d 100644 --- a/app/views/relationships/show.html.haml +++ b/app/views/relationships/show.html.haml @@ -42,13 +42,33 @@ %label.batch-table__toolbar__select.batch-checkbox-all = check_box_tag :batch_checkbox_all, nil, false .batch-table__toolbar__actions - = f.button safe_join([material_symbol('person_add'), t('relationships.follow_selected_followers')]), name: :follow, class: 'table-action-link', type: :submit, data: { confirm: t('relationships.confirm_follow_selected_followers') } if followed_by_relationship? && !mutual_relationship? + - if followed_by_relationship? && !mutual_relationship? + = f.button safe_join([material_symbol('person_add'), t('relationships.follow_selected_followers')]), + class: 'table-action-link', + data: { confirm: t('relationships.confirm_follow_selected_followers') }, + name: :follow, + type: :submit - = f.button safe_join([material_symbol('person_remove'), t('relationships.remove_selected_follows')]), name: :unfollow, class: 'table-action-link', type: :submit, data: { confirm: t('relationships.confirm_remove_selected_follows') } unless followed_by_relationship? + - unless followed_by_relationship? + = f.button safe_join([material_symbol('person_remove'), t('relationships.remove_selected_follows')]), + class: 'table-action-link', + data: { confirm: t('relationships.confirm_remove_selected_follows') }, + name: :unfollow, + type: :submit - = f.button safe_join([material_symbol('delete'), t('relationships.remove_selected_followers')]), name: :remove_from_followers, class: 'table-action-link', type: :submit, data: { confirm: t('relationships.confirm_remove_selected_followers') } unless following_relationship? + - unless following_relationship? + = f.button safe_join([material_symbol('delete'), t('relationships.remove_selected_followers')]), + class: 'table-action-link', + data: { confirm: t('relationships.confirm_remove_selected_followers') }, + name: :remove_from_followers, + type: :submit - = f.button safe_join([material_symbol('delete'), t('relationships.remove_selected_domains')]), name: :remove_domains_from_followers, class: 'table-action-link', type: :submit, data: { confirm: t('admin.reports.are_you_sure') } if followed_by_relationship? + - if followed_by_relationship? + = f.button safe_join([material_symbol('delete'), t('relationships.remove_selected_domains')]), + class: 'table-action-link', + data: { confirm: t('admin.reports.are_you_sure') }, + name: :remove_domains_from_followers, + type: :submit .batch-table__body - if @accounts.empty? = nothing_here 'nothing-here--under-tabs' diff --git a/app/views/settings/verifications/show.html.haml b/app/views/settings/verifications/show.html.haml index 4def10e595..a93ffcebed 100644 --- a/app/views/settings/verifications/show.html.haml +++ b/app/views/settings/verifications/show.html.haml @@ -65,7 +65,7 @@ %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 } + = f.input :attribution_domains_as_text, as: :text, wrapper: :with_block_label, input_html: { placeholder: "example1.com\nexample2.com\nexample3.com", rows: 4, autocapitalize: 'none', autocorrect: 'off' } .actions = f.button :button, t('generic.save_changes'), type: :submit diff --git a/app/views/shared/_web_app.html.haml b/app/views/shared/_web_app.html.haml index 89d6ee567d..4f9a20a9f4 100644 --- a/app/views/shared/_web_app.html.haml +++ b/app/views/shared/_web_app.html.haml @@ -1,3 +1,4 @@ +- content_for :body_classes, 'app-body' - content_for :header_tags do - if user_signed_in? = preload_pack_asset 'features/compose.js' diff --git a/app/views/statuses/show.html.haml b/app/views/statuses/show.html.haml index 08bab63073..f669885de0 100644 --- a/app/views/statuses/show.html.haml +++ b/app/views/statuses/show.html.haml @@ -1,5 +1,4 @@ -- content_for :page_title do - = t('statuses.title', name: display_name(@account), quote: truncate(@status.spoiler_text.presence || @status.text, length: 50, omission: '…', escape: false)) +- content_for :page_title, t('statuses.title', name: display_name(@account), quote: truncate(@status.spoiler_text.presence || @status.text, length: 50, omission: '…', escape: false)) - content_for :header_tags do - if @account.user_prefers_noindex? diff --git a/app/workers/merge_worker.rb b/app/workers/merge_worker.rb index 8e1614ad21..d4dcb326bc 100644 --- a/app/workers/merge_worker.rb +++ b/app/workers/merge_worker.rb @@ -5,18 +5,42 @@ class MergeWorker include Redisable include DatabaseHelper - def perform(from_account_id, into_account_id) + def perform(from_account_id, into_id, type = 'home') with_primary do @from_account = Account.find(from_account_id) + end + + case type + when 'home' + merge_into_home!(into_id) + when 'list' + merge_into_list!(into_id) + end + rescue ActiveRecord::RecordNotFound + true + end + + private + + def merge_into_home!(into_account_id) + with_primary do @into_account = Account.find(into_account_id) end with_read_replica do FeedManager.instance.merge_into_home(@from_account, @into_account) end - rescue ActiveRecord::RecordNotFound - true ensure redis.del("account:#{into_account_id}:regeneration") end + + def merge_into_list!(into_list_id) + with_primary do + @into_list = List.find(into_list_id) + end + + with_read_replica do + FeedManager.instance.merge_into_list(@from_account, @into_list) + end + end end diff --git a/app/workers/mute_worker.rb b/app/workers/mute_worker.rb index c74f657cba..ebd401dc20 100644 --- a/app/workers/mute_worker.rb +++ b/app/workers/mute_worker.rb @@ -2,9 +2,18 @@ class MuteWorker include Sidekiq::Worker + include DatabaseHelper def perform(account_id, target_account_id) - FeedManager.instance.clear_from_home(Account.find(account_id), Account.find(target_account_id)) + with_primary do + @account = Account.find(account_id) + @target_account = Account.find(target_account_id) + end + + with_read_replica do + FeedManager.instance.clear_from_home(@account, @target_account) + FeedManager.instance.clear_from_lists(@account, @target_account) + end rescue ActiveRecord::RecordNotFound true end diff --git a/app/workers/publish_scheduled_status_worker.rb b/app/workers/publish_scheduled_status_worker.rb index aa5c4a834a..0ec081de91 100644 --- a/app/workers/publish_scheduled_status_worker.rb +++ b/app/workers/publish_scheduled_status_worker.rb @@ -9,6 +9,8 @@ class PublishScheduledStatusWorker scheduled_status = ScheduledStatus.find(scheduled_status_id) scheduled_status.destroy! + return true if scheduled_status.account.user.disabled? + PostStatusService.new.call( scheduled_status.account, options_with_objects(scheduled_status.params.with_indifferent_access) 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/unmerge_worker.rb b/app/workers/unmerge_worker.rb index e8ac535dfe..e8a3bf9b78 100644 --- a/app/workers/unmerge_worker.rb +++ b/app/workers/unmerge_worker.rb @@ -6,16 +6,40 @@ class UnmergeWorker sidekiq_options queue: 'pull' - def perform(from_account_id, into_account_id) + def perform(from_account_id, into_id, type = 'home') with_primary do @from_account = Account.find(from_account_id) + end + + case type + when 'home' + unmerge_from_home!(into_id) + when 'list' + unmerge_from_list!(into_id) + end + rescue ActiveRecord::RecordNotFound + true + end + + private + + def unmerge_from_home!(into_account_id) + with_primary do @into_account = Account.find(into_account_id) end with_read_replica do FeedManager.instance.unmerge_from_home(@from_account, @into_account) end - rescue ActiveRecord::RecordNotFound - true + end + + def unmerge_from_list!(into_list_id) + with_primary do + @into_list = List.find(into_list_id) + end + + with_read_replica do + FeedManager.instance.unmerge_from_list(@from_account, @into_list) + end end end diff --git a/app/workers/web/push_notification_worker.rb b/app/workers/web/push_notification_worker.rb index 824e7b5940..3629904fa7 100644 --- a/app/workers/web/push_notification_worker.rb +++ b/app/workers/web/push_notification_worker.rb @@ -13,6 +13,8 @@ class Web::PushNotificationWorker @subscription = Web::PushSubscription.find(subscription_id) @notification = Notification.find(notification_id) + return if @notification.updated_at < TTL.ago + # Polymorphically associated activity could have been deleted # in the meantime, so we have to double-check before proceeding return unless @notification.activity.present? && @subscription.pushable?(@notification) 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 f94366d36f..e4e9680e66 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. @@ -110,6 +105,7 @@ module Mastodon end config.x.captcha = config_for(:captcha) + config.x.mastodon = config_for(:mastodon) config.x.translation = config_for(:translation) config.to_prepare do @@ -118,7 +114,6 @@ module Mastodon Doorkeeper::Application.include ApplicationExtension Doorkeeper::AccessGrant.include AccessGrantExtension Doorkeeper::AccessToken.include AccessTokenExtension - Doorkeeper::OAuth::PreAuthorization.include OauthPreAuthorizationExtension Devise::FailureApp.include AbstractController::Callbacks Devise::FailureApp.include Localized end diff --git a/config/database.yml b/config/database.yml index 2898415d80..eba20e849f 100644 --- a/config/database.yml +++ b/config/database.yml @@ -55,10 +55,11 @@ production: prepared_statements: <%= ENV['PREPARED_STATEMENTS'] || 'true' %> replica: <<: *default - database: <%= ENV['REPLICA_DB_NAME'] ||ENV['DB_NAME'] || 'mastodon_production' %> - username: <%= ENV['REPLICA_DB_USER'] ||ENV['DB_USER'] || 'mastodon' %> + database: <%= ENV['REPLICA_DB_NAME'] || ENV['DB_NAME'] || 'mastodon_production' %> + username: <%= ENV['REPLICA_DB_USER'] || ENV['DB_USER'] || 'mastodon' %> password: <%= (ENV['REPLICA_DB_PASS'] || ENV['DB_PASS'] || '').to_json %> - host: <%= ENV['REPLICA_DB_HOST'] ||ENV['DB_HOST'] || 'localhost' %> - port: <%= ENV['REPLICA_DB_PORT'] ||ENV['DB_PORT'] || 5432 %> - prepared_statements: <%= ENV['PREPARED_STATEMENTS'] || 'true' %> + host: <%= ENV['REPLICA_DB_HOST'] || ENV['DB_HOST'] || 'localhost' %> + port: <%= ENV['REPLICA_DB_PORT'] || ENV['DB_PORT'] || 5432 %> + prepared_statements: <%= ENV['REPLICA_PREPARED_STATEMENTS'] || ENV['PREPARED_STATEMENTS'] || 'true' %> replica: true + database_tasks: <%= ENV['REPLICA_DB_TASKS'] || 'true' %> diff --git a/config/environments/development.rb b/config/environments/development.rb index f5f22a3c1f..8533935a88 100644 --- a/config/environments/development.rb +++ b/config/environments/development.rb @@ -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. @@ -89,6 +86,9 @@ Rails.application.configure do # 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 1cf752f3b2..6d4c30cd20 100644 --- a/config/environments/production.rb +++ b/config/environments/production.rb @@ -17,7 +17,6 @@ Rails.application.configure do # Full error reports are disabled and caching is turned on. 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). @@ -26,8 +25,11 @@ Rails.application.configure do # 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? @@ -37,6 +39,10 @@ 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. @@ -46,14 +52,19 @@ Rails.application.configure do }, } - # 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 @@ -61,6 +72,8 @@ Rails.application.configure do # 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. @@ -87,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 eb29ab1e17..5406eac9ec 100644 --- a/config/environments/test.rb +++ b/config/environments/test.rb @@ -19,8 +19,6 @@ 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.action_controller.perform_caching = false @@ -32,6 +30,8 @@ Rails.application.configure do # 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. diff --git a/config/initializers/allowed_private_addresses.rb b/config/initializers/allowed_private_addresses.rb new file mode 100644 index 0000000000..65c7af03b4 --- /dev/null +++ b/config/initializers/allowed_private_addresses.rb @@ -0,0 +1,5 @@ +# frozen_string_literal: true + +Rails.application.configure do + config.x.private_address_exceptions = (ENV['ALLOWED_PRIVATE_ADDRESSES'] || '').split(/(?:\s*,\s*|\s+)/).map { |addr| IPAddr.new(addr) } +end 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/doorkeeper.rb b/config/initializers/doorkeeper.rb index de1c75f576..516db258df 100644 --- a/config/initializers/doorkeeper.rb +++ b/config/initializers/doorkeeper.rb @@ -52,6 +52,9 @@ Doorkeeper.configure do # Issue access tokens with refresh token (disabled by default) # use_refresh_token + # Proof of Key Code Exchange + pkce_code_challenge_methods ['S256'] + # Forbids creating/updating applications with arbitrary scopes that are # not in configuration, i.e. `default_scopes` or `optional_scopes`. # (Disabled by default) diff --git a/config/initializers/enable_yjit.rb b/config/initializers/enable_yjit.rb deleted file mode 100644 index 7b1053ec11..0000000000 --- a/config/initializers/enable_yjit.rb +++ /dev/null @@ -1,13 +0,0 @@ -# frozen_string_literal: true - -# Automatically enable YJIT as of Ruby 3.3, as it brings very -# sizeable performance improvements. - -# If you are deploying to a memory constrained environment -# you may want to delete this file, but otherwise it's free -# performance. -if defined?(RubyVM::YJIT.enable) - Rails.application.config.after_initialize do - RubyVM::YJIT.enable - 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/initializers/opentelemetry.rb b/config/initializers/opentelemetry.rb index 8edce03b90..a40cd4e4c5 100644 --- a/config/initializers/opentelemetry.rb +++ b/config/initializers/opentelemetry.rb @@ -65,6 +65,13 @@ if ENV.keys.any? { |name| name.match?(/OTEL_.*_ENDPOINT/) } "#{prefix}#{separator}#{$PROGRAM_NAME.split('/').last}" end c.service_version = Mastodon::Version.to_s + + if Mastodon::Version.source_commit.present? + c.resource = OpenTelemetry::SDK::Resources::Resource.create( + 'vcs.repository.ref.revision' => Mastodon::Version.source_commit, + 'vcs.repository.url.full' => Mastodon::Version.source_base_url + ) + end end end diff --git a/config/locales/activerecord.zh-CN.yml b/config/locales/activerecord.zh-CN.yml index a4edf294a3..f620158361 100644 --- a/config/locales/activerecord.zh-CN.yml +++ b/config/locales/activerecord.zh-CN.yml @@ -49,16 +49,16 @@ zh-CN: blocked: 使用了被封禁的电子邮件提供商 unreachable: 似乎不存在 role_id: - elevated: 不能高于您当前的身份 + elevated: 不能高于你现在的身份 user_role: attributes: permissions_as_keys: dangerous: 包含对基本角色不安全的权限 - elevated: 不能包含您当前身份未有的权限 - own_role: 无法以您当前的身份更改 + elevated: 不能包含你当前身份未有的权限 + own_role: 无权以你当前的身份更改 position: - elevated: 不能高于您当前的角色 - own_role: 无法以您当前的身份更改 + elevated: 不能高于你当前的角色 + own_role: 无权以你当前的身份更改 webhook: attributes: events: diff --git a/config/locales/an.yml b/config/locales/an.yml index 2db042f1b1..f941651438 100644 --- a/config/locales/an.yml +++ b/config/locales/an.yml @@ -723,7 +723,6 @@ an: original_status: Publicación orichinal reblogs: Impulsos status_changed: Publicación cambiada - title: Estau d'as cuentas trending: En tendencia visibility: Visibilidat with_media: Con multimedia diff --git a/config/locales/ar.yml b/config/locales/ar.yml index 1a6f0da8c6..832f60795f 100644 --- a/config/locales/ar.yml +++ b/config/locales/ar.yml @@ -847,7 +847,6 @@ ar: original_status: المنشور الأصلي reblogs: المعاد تدوينها status_changed: عُدّل المنشور - title: منشورات الحساب trending: المتداولة visibility: مدى الظهور with_media: تحتوي على وسائط diff --git a/config/locales/be.yml b/config/locales/be.yml index b627672b2d..c97547b8b9 100644 --- a/config/locales/be.yml +++ b/config/locales/be.yml @@ -856,7 +856,6 @@ be: original_status: Зыходны допіс reblogs: Рэпосты status_changed: Допіс зменены - title: Допісы уліковага запісу trending: Папулярныя visibility: Бачнасць with_media: З медыя diff --git a/config/locales/bg.yml b/config/locales/bg.yml index 1fdd0e3533..20ee1f6c68 100644 --- a/config/locales/bg.yml +++ b/config/locales/bg.yml @@ -21,9 +21,12 @@ bg: one: Публикация other: Публикации posts_tab_heading: Публикации + self_follow_error: Не е позволено да следвате собствения си акаунт admin: account_actions: action: Изпълняване на действие + already_silenced: Този акаунт вече е ограничен. + already_suspended: Този акаунт вече е спрян. title: Извършване на модериращо действие за %{acct} account_moderation_notes: create: Оставяне на бележка @@ -45,6 +48,7 @@ bg: title: Промяна на имейл за %{username} change_role: changed_msg: Успешно променена роля! + edit_roles: Управление на потребителските роли label: Промяна на ролята no_role: Без роля title: Промяна на ролята за %{username} @@ -412,6 +416,7 @@ bg: attempts_over_week: one: "%{count} опит за изминалата седмица" other: "%{count} опита за регистрация през изминалата седмица" + created_msg: Успешно блокиран домейн на е-поща delete: Изтриване dns: types: @@ -420,8 +425,11 @@ bg: new: create: Добавяне на домейн resolve: Преобразуване на домейна + title: Блокиране на нов домейн на имейл + no_email_domain_block_selected: Няма промяна, тъй като няма избрани блокирания на домейн на имейл not_permitted: Няма позволение resolved_through_html: Преобразувано чрез %{domain} + title: Блокирани домейни на имейл export_domain_allows: new: title: Внасяне на позволенията на домейни @@ -799,7 +807,7 @@ bg: original_status: Първообразна публикация reblogs: Блогване пак status_changed: Публикацията променена - title: Публикации на акаунта + title: Публикации на акаунт - @%{name} trending: Изгряващи visibility: Видимост with_media: С мултимедия @@ -842,6 +850,9 @@ bg: message_html: Не сте определили никакви правила на сървъра. sidekiq_process_check: message_html: Не работи процес Sidekiq за %{value} опашка/и. Прегледайте настройките си за Sidekiq + software_version_check: + action: Преглед на наличните обновявания + message_html: Налично е обновяване на Mastodon. software_version_critical_check: action: Преглед на наличните обновявания message_html: Налично e критично обновяване на Mastodon. Обновете възможно най-бързо. @@ -868,6 +879,7 @@ bg: name: Име newest: Най-нови oldest: Най-стари + open: Преглед публично reset: Нулиране review: Преглед на състояние search: Търсене @@ -881,6 +893,7 @@ bg: links: allow: Позволяване на връзка allow_provider: Позволяване на публикуващия + confirm_allow: Наистина ли искате да позволите избраните връзки? confirm_allow_provider: Наистина ли искате да позволите избраните доставчици? description_html: Това са връзки, които в момента са много пъти споделяни от акаунти, чиито публикации сървърът ви вижда. Може да помогне на потребителите ви да разберат какво се случва по света. Никоя връзка няма да се показва публично, докато не одобрите публикуващия. Може още и да одобрявате или отхвърляте отделни връзки. disallow: Забранявам връзката @@ -905,6 +918,8 @@ bg: statuses: allow: Позволяване на публикацията allow_account: Позволяване на автора + confirm_allow: Наистина ли искате да позволите избраните статуси? + confirm_allow_account: Наистина ли искате да позволите избраните акаунти? description_html: Това са публикации, за които сървърът ви знае, че са често споделяни или харесвани в момента. Това може да помогне на вашите нови и завръщащи се потребители да открият повече хора за следване. Никоя от публикациите няма да бъде показана публично, докато не одобрите автора и докато авторът не позволи акаунтът му да бъде предлган на другите. Също така можете да позволявате или отхвърляте отделни публикации. disallow: Забраняване на публикацията disallow_account: Забрана на автора @@ -1021,6 +1036,7 @@ bg: guide_link_text: Всеки може да участва. sensitive_content: Деликатно съдържание application_mailer: + notification_preferences: Промяна на предпочитанията за е-поща salutation: "%{name}," unsubscribe: Стоп на абонамента view: 'Преглед:' @@ -1089,8 +1105,10 @@ bg: security: Сигурност set_new_password: Задаване на нова парола setup: + email_below_hint_html: Проверете папката си за спам или поискайте друго е-писмо. Може да поправите адреса на имейла си, ако е грешен. email_settings_hint_html: Щракнете на връзката за потвърждаване, която ви изпратихме до %{email}. Ще ви почакаме тук. link_not_received: Не получихте ли връзка? + new_confirmation_instructions_sent: До няколко минути ще получите друго е-писмо с връзка за потвърждаване! title: Проверете входящата си поща sign_in: preamble_html: Влезте с идентификационните данни за %{domain}. Ако вашият акаунт е хостван на различен сървър, няма да можете да влезете в този. @@ -1101,12 +1119,22 @@ bg: title: Първоначални настройки за %{domain}. status: account_status: Състояние на акаунта + confirming: Чака се потвърждението на имейла да завърши. functional: Вашият акаунт е в изправност. + pending: Вашето приложение чака преглед от персонала ни. Това може да отнеме време. Ще получите е-писмо, ако приложението ви се одобри. redirecting_to: Вашият акаунт е бездеен, защото сега се пренасочва към %{acct}. self_destruct: Затваряйки %{domain}, ще получите само ограничен достъп до акаунта си. view_strikes: Преглед на предишните предупреждения против акаунта ви too_fast: Образецът подаден пребързо, опитайте пак. 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: "Съвет: няма да ви питаме пак за паролата през следващия час." @@ -1143,6 +1171,9 @@ bg: before: 'Прочетете внимателно тези бележки преди да продължите:' caches: Съдържание, което може да е кеширано от други сървъри, може да се задържи data_removal: Ваши публикации и други данни ще бъдат завинаги премахнати + email_change_html: Може да промените адреса на имейла си, без да изтривате акаунта си + email_contact_html: Ако още не сте го получили, то обърнете се за помощ към %{email} + email_reconfirmation_html: Ако не сте получили е-писмо за потвърждение, може да го заявите отново irreversible: Няма да може да възстановите или да задействате пак акаунта си more_details_html: За повече детайли прегледайте декларацията за поверителност. username_available: Вашето потребителско име ще стане налично отново @@ -1370,6 +1401,7 @@ bg: unsubscribe: action: Да, да се спре абонамента complete: Спрян абонамент + confirmation_html: Наистина ли искате да спрете абонамента от получаването на %{type} за Mastodon в %{domain} към имейла си при %{email}? Може винаги пак да се абонирате от своите настройки за известяване по е-поща. title: Спиране на абонамента media_attachments: validations: @@ -1450,6 +1482,7 @@ bg: update: subject: "%{name} промени публикация" notifications: + administration_emails: Известия за администратори по е-поща email_events_hint: 'Изберете събития, за които искате да получавате известия:' number: human: @@ -1607,6 +1640,7 @@ bg: import: Импортиране import_and_export: Импортиране и експортиране migrate: Миграция на акаунта + notifications: Известия по е-поща preferences: Предпочитания profile: Профил relationships: Последвания и последователи @@ -1842,6 +1876,7 @@ bg: invalid_otp_token: Невалиден код otp_lost_help_html: Ако загубите достъп до двете, то може да се свържете с %{email} rate_limited: Премного опити за удостоверяване. Опитайте пак по-късно. + seamless_external_login: Влезли сте чрез външна услуга, така че настройките за парола и имейл не са налични. signed_in_as: 'Влезли като:' verification: extra_instructions_html: Съвет:Връзката в уебсайта ви може да е невидима. Важна част е rel="me", която предотврятява имитирането на уебсайтове с породено от потребителите съдържание. Може дори да употребите етикет за връзката в заглавката на странице вместо а, но HTML трябва да достъпен без изпълнение на JavaScript. @@ -1850,6 +1885,7 @@ bg: instructions_html: Копипейстнете кода долу в HTML на уебсайта си. Тогава добавете адреса на уебсайта си в едно от допълнителните полета на профила ви от раздела "Редактиране на профила" и запазане на промените. verification: Проверка verified_links: Вашите потвърдени връзки + website_verification: Потвърждаване на уебсайта webauthn_credentials: add: Добавяне на нов ключ за сигурност create: diff --git a/config/locales/br.yml b/config/locales/br.yml index f9fbd34adb..fbe91fcbd7 100644 --- a/config/locales/br.yml +++ b/config/locales/br.yml @@ -263,7 +263,7 @@ br: original_status: Toud orin reblogs: Skignadennoù status_changed: Toud kemmet - title: Toudoù ar gont + status_title: Embannadenn gant @%{name} visibility: Gwelusted with_media: Gant mediaoù strikes: diff --git a/config/locales/ca.yml b/config/locales/ca.yml index 9d861fa30c..b1af2d95d4 100644 --- a/config/locales/ca.yml +++ b/config/locales/ca.yml @@ -187,6 +187,7 @@ ca: create_domain_block: Crea un bloqueig de domini create_email_domain_block: Crea un blocatge del domini del correu electrònic create_ip_block: Crear regla IP + create_relay: Crea un repetidor create_unavailable_domain: Crea un domini no disponible create_user_role: Crea Rol demote_user: Degrada l'usuari @@ -198,14 +199,17 @@ ca: destroy_email_domain_block: Elimina el blocatge del domini del correu electrònic destroy_instance: Purga Domini destroy_ip_block: Eliminar regla IP + destroy_relay: Esborra el repetidor destroy_status: Elimina la publicació destroy_unavailable_domain: Esborra domini no disponible destroy_user_role: Destrueix Rol disable_2fa_user: Desactiva 2FA disable_custom_emoji: Desactiva l'emoji personalitzat + disable_relay: Desactiva el repetidor disable_sign_in_token_auth_user: Desactivar l'autenticació de token per correu-e per a l'usuari disable_user: Deshabilita l'usuari enable_custom_emoji: Activa l'emoji personalitzat + enable_relay: Activa el repetidor enable_sign_in_token_auth_user: Activar l'autenticació de token per correu-e per a l'usuari enable_user: Activa l'usuari memorialize_account: Memoritza el compte @@ -247,6 +251,7 @@ ca: create_domain_block_html: "%{name} ha bloquejat el domini %{target}" create_email_domain_block_html: "%{name} ha blocat el domini de correu electrònic %{target}" create_ip_block_html: "%{name} ha creat una regla per a l'IP %{target}" + create_relay_html: "%{name} ha creat un repetidor %{target}" create_unavailable_domain_html: "%{name} ha aturat el lliurament al domini %{target}" create_user_role_html: "%{name} ha creat el rol %{target}" demote_user_html: "%{name} ha degradat l'usuari %{target}" @@ -258,14 +263,17 @@ ca: destroy_email_domain_block_html: "%{name} ha desblocat el domini de correu electrònic %{target}" destroy_instance_html: "%{name} ha purgat el domini %{target}" destroy_ip_block_html: "%{name} ha esborrat la regla per a l'IP %{target}" + destroy_relay_html: "%{name} ha esborrat el repetidor %{target}" destroy_status_html: "%{name} ha eliminat el tut de %{target}" destroy_unavailable_domain_html: "%{name} ha représ el lliurament delivery al domini %{target}" destroy_user_role_html: "%{name} ha esborrat el rol %{target}" disable_2fa_user_html: "%{name} ha desactivat el requisit de dos factors per a l'usuari %{target}" disable_custom_emoji_html: "%{name} ha desactivat l'emoji %{target}" + disable_relay_html: "%{name} ha desactivat el repetidor %{target}" disable_sign_in_token_auth_user_html: "%{name} ha desactivat l'autenticació de token per correu-e per a %{target}" disable_user_html: "%{name} ha desactivat l'accés del usuari %{target}" enable_custom_emoji_html: "%{name} ha activat l'emoji %{target}" + enable_relay_html: "%{name} ha activat el repetidor %{target}" enable_sign_in_token_auth_user_html: "%{name} ha activat l'autenticació de token per correu-e per a %{target}" enable_user_html: "%{name} ha activat l'accés del usuari %{target}" memorialize_account_html: "%{name} ha convertit el compte %{target} en una pàgina de memorial" @@ -833,7 +841,6 @@ ca: original_status: Publicació original reblogs: Impulsos status_changed: Publicació canviada - title: Estats del compte trending: Tendència visibility: Visibilitat with_media: Amb contingut multimèdia diff --git a/config/locales/ckb.yml b/config/locales/ckb.yml index 88dadff014..cfee624e36 100644 --- a/config/locales/ckb.yml +++ b/config/locales/ckb.yml @@ -520,7 +520,6 @@ ckb: media: title: میدیا no_status_selected: هیچ دۆخیک نەگۆڕاوە وەک ئەوەی هیچ بارێک دەستنیشان نەکراوە - title: دۆخی ئەژمێر with_media: بە میدیا tags: review: پێداچوونەوەی دۆخ diff --git a/config/locales/co.yml b/config/locales/co.yml index dad3e08ffd..39d9e9157e 100644 --- a/config/locales/co.yml +++ b/config/locales/co.yml @@ -459,7 +459,6 @@ co: media: title: Media no_status_selected: I statuti ùn sò micca stati mudificati perchè manc'unu era selezziunatu - title: Statuti di u contu with_media: Cù media system_checks: rules_check: diff --git a/config/locales/cs.yml b/config/locales/cs.yml index 15211b928a..19a6372224 100644 --- a/config/locales/cs.yml +++ b/config/locales/cs.yml @@ -826,7 +826,6 @@ cs: original_status: Původní příspěvek reblogs: Boosty status_changed: Příspěvek změněn - title: Příspěvky účtu trending: Populární visibility: Viditelnost with_media: S médii diff --git a/config/locales/cy.yml b/config/locales/cy.yml index 2d6a0eb38d..0daa793f97 100644 --- a/config/locales/cy.yml +++ b/config/locales/cy.yml @@ -199,6 +199,7 @@ cy: create_domain_block: Creu Gwaharddiad Parth create_email_domain_block: Creu Rhwystr Parth E-bost create_ip_block: Creu rheol IP + create_relay: Creu Cyfnewidiad create_unavailable_domain: Creu Parth Ddim ar Gael create_user_role: Creu Rôl demote_user: Diraddio Defnyddiwr @@ -210,14 +211,17 @@ cy: destroy_email_domain_block: Dileu Rhwystr Parth E-bost destroy_instance: Clirio Parth destroy_ip_block: Dileu rheol IP + destroy_relay: Dileu Cyfnewidiad destroy_status: Dileu Postiad destroy_unavailable_domain: Dileu Parth Ddim ar Gael destroy_user_role: Dileu Rôl disable_2fa_user: Diffodd 2FA disable_custom_emoji: Analluogi Emoji Addasedig + disable_relay: Analluogi Cyfnewidiad disable_sign_in_token_auth_user: Analluogi Dilysu Tocyn E-bost Defnyddiwr disable_user: Analluogi Defnyddiwr enable_custom_emoji: Galluogi Emoji Addasedig + enable_relay: Galluogi Cyfnewidiad enable_sign_in_token_auth_user: Galluogi Dilysu Tocyn E-bost Defnyddiwr enable_user: Galluogi Defnyddiwr memorialize_account: Cofadeilio Cyfrif @@ -259,6 +263,7 @@ cy: create_domain_block_html: Mae %{name} wedi rhwystro parth %{target} create_email_domain_block_html: Mae %{name} wedi rhwystro parth e-bost %{target} create_ip_block_html: Mae %{name} wedi creu rheol ar gyfer IP %{target} + create_relay_html: Creodd %{name} gyfnewidiad %{target} create_unavailable_domain_html: Mae %{name} wedi stopio danfon i barth %{target} create_user_role_html: Mae %{name} wedi creu rôl %{target} demote_user_html: Mae %{name} wedi israddio defnyddiwr %{target} @@ -270,14 +275,17 @@ cy: destroy_email_domain_block_html: Mae %{name} wedi dad-rwystro parth e-bost %{target} destroy_instance_html: Mae %{name} wedi dileu parth %{target} destroy_ip_block_html: Mae %{name} dileu rheol ar gyfer IP %{target} + destroy_relay_html: Dileodd %{name} y cyfnewidiad %{target} destroy_status_html: Mae %{name} wedi tynnu postiad gan %{target} destroy_unavailable_domain_html: Mae %{name} wedi ailddechrau anfon i barth %{target} destroy_user_role_html: Mae %{name} wedi dileu rôl %{target} disable_2fa_user_html: Mae %{name} wedi analluogi gofyniad dau ffactor ar gyfer defnyddiwr %{target} disable_custom_emoji_html: Mae %{name} wedi analluogi emoji %{target} + disable_relay_html: Analluogodd %{name} y cyfnewidiad %{target} disable_sign_in_token_auth_user_html: Mae %{name} wedi analluogi dilysiad tocyn e-bost %{target} disable_user_html: Mae %{name} wedi analluogi mewngofnodi defnyddiwr %{target} enable_custom_emoji_html: Mae %{name} wedi analluogi emoji %{target} + enable_relay_html: Galluogodd %{name} y cyfnewidiad %{target} enable_sign_in_token_auth_user_html: Mae %{name} wedi galluogi dilysiad tocyn e-bost %{target} enable_user_html: Mae %{name} wedi galluogi mewngofnodi defnyddiwr %{target} memorialize_account_html: Newidiodd %{name} gyfrif %{target} i dudalen memoriam @@ -889,7 +897,6 @@ cy: original_status: Postiad gwreiddiol reblogs: Ailflogiadau status_changed: Postiad wedi'i newid - title: Postiadau cyfrif trending: Yn trendio visibility: Gwelededd with_media: Gyda chyfryngau diff --git a/config/locales/da.yml b/config/locales/da.yml index 6447afb493..3a82278b93 100644 --- a/config/locales/da.yml +++ b/config/locales/da.yml @@ -187,6 +187,7 @@ da: create_domain_block: Opret domæneblokering create_email_domain_block: Opret e-maildomæneblokering create_ip_block: Opret IP-regel + create_relay: Opret Videresendelse create_unavailable_domain: Opret Utilgængeligt Domæne create_user_role: Opret rolle demote_user: Degradér bruger @@ -198,14 +199,17 @@ da: destroy_email_domain_block: Slet e-maildomæneblokering destroy_instance: Udrens domæne destroy_ip_block: Slet IP-regel + destroy_relay: Slet Videresendelse destroy_status: Slet indlæg destroy_unavailable_domain: Slet Utilgængeligt Domæne destroy_user_role: Ødelæg rolle disable_2fa_user: Deaktivér 2FA disable_custom_emoji: Deaktivér tilpasset emoji + disable_relay: Deaktivér Videresendelse disable_sign_in_token_auth_user: Deaktivér e-mailtoken godkendelse for bruger disable_user: Deaktivér bruger enable_custom_emoji: Aktivér tilpasset emoji + enable_relay: Aktivér Relay enable_sign_in_token_auth_user: Aktivér e-mailtoken godkendelse for bruger enable_user: Aktivér bruger memorialize_account: Memoralisér konto @@ -247,6 +251,7 @@ da: create_domain_block_html: "%{name} blokerede domænet %{target}" create_email_domain_block_html: "%{name} blokerede e-maildomænet %{target}" create_ip_block_html: "%{name} oprettede en regel for IP %{target}" + create_relay_html: "%{name} oprettede videresendelsen %{target}" create_unavailable_domain_html: "%{name} stoppede levering til domænet %{target}" create_user_role_html: "%{name} oprettede %{target}-rolle" demote_user_html: "%{name} degraderede brugeren %{target}" @@ -258,14 +263,17 @@ da: destroy_email_domain_block_html: "%{name} afblokerede e-maildomænet %{target}" destroy_instance_html: "%{name} udrensede domænet %{target}" destroy_ip_block_html: "%{name} slettede en regel for IP %{target}" + destroy_relay_html: "%{name} oprettede videresendelsen %{target}" destroy_status_html: "%{name} fjernede indlægget fra %{target}" destroy_unavailable_domain_html: "%{name} genoptog levering til domænet %{target}" destroy_user_role_html: "%{name} slettede %{target}-rolle" disable_2fa_user_html: "%{name} deaktiverede tofaktorkravet for brugeren %{target}" disable_custom_emoji_html: "%{name} deaktiverede emojien %{target}" + disable_relay_html: "%{name} deaktiverede videresendelsen %{target}" disable_sign_in_token_auth_user_html: "%{name} deaktiverede e-mailtoken godkendelsen for %{target}" disable_user_html: "%{name} deaktiverede indlogning for brugeren %{target}" enable_custom_emoji_html: "%{name} aktiverede emojien %{target}" + enable_relay_html: "%{name} aktiverede videresendelsen %{target}" enable_sign_in_token_auth_user_html: "%{name} aktiverede e-mailtoken godkendelse for %{target}" enable_user_html: "%{name} aktiverede indlogning for brugeren %{target}" memorialize_account_html: "%{name} gjorde %{target}s konto til en mindeside" @@ -818,8 +826,10 @@ da: back_to_account: Retur til kontoside back_to_report: Retur til anmeldelsesside batch: + add_to_report: 'Føj til rapporten #%{id}' remove_from_report: Fjern fra anmeldelse report: Anmeldelse + contents: Indhold deleted: Slettet favourites: Favoritter history: Versionshistorik @@ -828,13 +838,17 @@ da: media: title: Medier metadata: Metadata + no_history: Dette indlæg er ikke blevet redigeret no_status_selected: Ingen indlæg ændret (ingen valgt) open: Åbn indlæg original_status: Oprindeligt indlæg reblogs: Genblogninger + replied_to_html: Besvarede %{acct_link} status_changed: Indlæg ændret - title: Kontoindlæg + status_title: Indlæg fra @%{name} + title: Kontoindlæg - @%{name} trending: Populære + view_publicly: Vis offentligt visibility: Synlighed with_media: Med medier strikes: diff --git a/config/locales/de.yml b/config/locales/de.yml index 323579f25f..26ccc8f3ee 100644 --- a/config/locales/de.yml +++ b/config/locales/de.yml @@ -187,6 +187,7 @@ de: create_domain_block: Domain sperren create_email_domain_block: E-Mail-Domain-Sperre erstellen create_ip_block: IP-Regel erstellen + create_relay: Relay erstellen create_unavailable_domain: Nicht verfügbare Domain erstellen create_user_role: Rolle erstellen demote_user: Benutzer*in herabstufen @@ -198,14 +199,17 @@ de: destroy_email_domain_block: E-Mail-Domain-Sperre entfernen destroy_instance: Domain-Daten entfernen destroy_ip_block: IP-Regel löschen + destroy_relay: Relay löschen destroy_status: Beitrag entfernen destroy_unavailable_domain: Nicht-verfügbare Domain entfernen destroy_user_role: Rolle entfernen disable_2fa_user: 2FA deaktivieren disable_custom_emoji: Eigenes Emoji deaktivieren + disable_relay: Relay deaktivieren disable_sign_in_token_auth_user: E-Mail-Token-Authentisierung für dieses Konto deaktivieren disable_user: Benutzer*in deaktivieren enable_custom_emoji: Eigenes Emoji aktivieren + enable_relay: Relay aktivieren enable_sign_in_token_auth_user: E-Mail-Token-Authentisierung für dieses Konto aktivieren enable_user: Benutzer*in aktivieren memorialize_account: Gedenkkonto @@ -247,6 +251,7 @@ de: create_domain_block_html: "%{name} sperrte die Domain %{target}" create_email_domain_block_html: "%{name} sperrte die E-Mail-Domain %{target}" create_ip_block_html: "%{name} erstellte eine IP-Regel für %{target}" + create_relay_html: "%{name} erstellte ein Relay %{target}" create_unavailable_domain_html: "%{name} beendete die Zustellung an die Domain %{target}" create_user_role_html: "%{name} erstellte die Rolle %{target}" demote_user_html: "%{name} stufte %{target} herunter" @@ -258,14 +263,17 @@ de: destroy_email_domain_block_html: "%{name} entsperrte die E-Mail-Domain %{target}" destroy_instance_html: "%{name} entfernte die Daten der Domain %{target} von diesem Server" destroy_ip_block_html: "%{name} entfernte eine IP-Regel für %{target}" + destroy_relay_html: "%{name} löschte das Relay %{target}" destroy_status_html: "%{name} entfernte einen Beitrag von %{target}" destroy_unavailable_domain_html: "%{name} nahm die Zustellung an die Domain %{target} wieder auf" destroy_user_role_html: "%{name} löschte die Rolle %{target}" disable_2fa_user_html: "%{name} deaktivierte die Zwei-Faktor-Authentisierung für %{target}" disable_custom_emoji_html: "%{name} deaktivierte das Emoji %{target}" + disable_relay_html: "%{name} deaktivierte das Relay %{target}" disable_sign_in_token_auth_user_html: "%{name} deaktivierte die E-Mail-Token-Authentisierung für %{target}" disable_user_html: "%{name} deaktivierte den Zugang für %{target}" enable_custom_emoji_html: "%{name} aktivierte das Emoji %{target}" + enable_relay_html: "%{name} aktivierte das Relay %{target}" enable_sign_in_token_auth_user_html: "%{name} aktivierte die E-Mail-Token-Authentisierung für %{target}" enable_user_html: "%{name} aktivierte den Zugang für %{target}" memorialize_account_html: "%{name} wandelte das Konto von %{target} in eine Gedenkseite um" @@ -419,9 +427,9 @@ de: not_permitted: Du bist nicht berechtigt, diese Aktion durchzuführen obfuscate: Domain-Name verschleiern obfuscate_hint: Den Domain-Namen öffentlich nur teilweise bekannt geben, sofern die Liste der Domain-Beschränkungen aktiviert ist - private_comment: Interne bzw. nicht-öffentliche Notiz + private_comment: Nicht-öffentliche Notiz private_comment_hint: Kommentar zu dieser Domain-Beschränkung für die interne Nutzung durch die Moderator*innen. - public_comment: Öffentliche Notiz + public_comment: Öffentliche Begründung public_comment_hint: Öffentlicher Hinweis zu dieser Domain-Beschränkung, sofern das Veröffentlichen von Sperrlisten grundsätzlich aktiviert ist. reject_media: Mediendateien ablehnen reject_media_hint: Entfernt lokal gespeicherte Mediendateien und verhindert deren künftiges Herunterladen. Für Sperren irrelevant @@ -494,7 +502,7 @@ de: by_domain: Domain confirm_purge: Möchtest du die Daten von dieser Domain wirklich für immer löschen? content_policies: - comment: Interne Notiz + comment: Nicht-öffentliche Notiz description_html: Du kannst Inhaltsrichtlinien definieren, die auf alle Konten dieser Domain und einer ihrer Subdomains angewendet werden. limited_federation_mode_description_html: Du kannst auswählen, ob du eine Föderation mit dieser Domain erlaubst. policies: @@ -818,8 +826,10 @@ de: back_to_account: Zurück zum Konto back_to_report: Zurück zur Seite mit den Meldungen batch: + add_to_report: Der Meldung Nr. %{id} hinzufügen remove_from_report: Von der Meldung entfernen report: Meldung + contents: Inhalte deleted: Gelöscht favourites: Favoriten history: Versionsverlauf @@ -828,13 +838,17 @@ de: media: title: Medien metadata: Metadaten + no_history: Der Beitrag wurde nicht bearbeitet no_status_selected: Keine Beiträge wurden geändert, weil keine ausgewählt wurden open: Beitrag öffnen original_status: Ursprünglicher Beitrag reblogs: Geteilte Beiträge + replied_to_html: Antwortete %{acct_link} status_changed: Beitrag bearbeitet - title: Beiträge des Kontos + status_title: Beitrag von @%{name} + title: Beiträge des Kontos – @%{name} trending: Trends + view_publicly: Öffentlich anzeigen visibility: Sichtbarkeit with_media: Mit Medien strikes: diff --git a/config/locales/devise.lv.yml b/config/locales/devise.lv.yml index 4470c8109e..5aaa23a731 100644 --- a/config/locales/devise.lv.yml +++ b/config/locales/devise.lv.yml @@ -14,7 +14,7 @@ lv: not_found_in_database: Nederīga %{authentication_keys} vai parole. omniauth_user_creation_failure: Kļūda šīs identitātes konta izveidošanā. pending: Tavs konts joprojām tiek pārskatīts. - timeout: Sesijair beigusies. Lūgums vēlreiz pieteikties, lai turpinātu. + timeout: Sesija ir beigusies. Lūgums vēlreiz pieteikties, lai turpinātu. unauthenticated: Lai turpinātu, jāpiesakās vai jāreģistrējas. unconfirmed: Lai turpinātu, jāapliecina sava e-pasta adrese. mailer: @@ -90,13 +90,13 @@ lv: no_token: Tu nevari piekļūt šai lapai, ja neesi saņēmis paroles atiestatīšanas e-pasta ziņojumu. Ja ienāci no paroles atiestatīšanas e-pasta, lūdzu, pārliecinies, vai izmanto visu norādīto URL. send_instructions: Ja tava e-pasta adrese ir mūsu datu bāzē, pēc dažām minūtēm uz savu e-pasta adresi saņemsi paroles atkopšanas saiti. Lūdzu, pārbaudi spama mapi, ja neesi saņēmis šo e-pastu. send_paranoid_instructions: Ja tava e-pasta adrese ir mūsu datu bāzē, pēc dažām minūtēm uz savu e-pasta adresi saņemsi paroles atkopšanas saiti. Lūdzu, pārbaudi spama mapi, ja neesi saņēmis šo e-pastu. - updated: Tava parole tika veiksmīgi nomainīta. Tu tagad esi pieteicies. + updated: Tava parole tika veiksmīgi nomainīta. Tagad esi pieteicies. updated_not_active: Tava parole ir veiksmīgi nomainīta. registrations: destroyed: Visu labu! Tavs konts ir veiksmīgi atcelts. Mēs ceram tevi drīz atkal redzēt. signed_up: Laipni lūdzam! Tu esi veiksmīgi reģistrējies. - signed_up_but_inactive: Tava reģistrācija bija veiksmīga. Tomēr mēs nevarējām tevi pierakstīt, jo tavs konts vēl nav aktivizēts. - signed_up_but_locked: Tava reģistrācija bija veiksmīga. Tomēr mēs nevarējām tevi pierakstīt, jo tavs konts ir bloķēts. + signed_up_but_inactive: Tava reģistrācija bija veiksmīga. Tomēr mēs nevarējām Tevi pieteikt, jo Tavs konts vēl nav aktivizēts. + signed_up_but_locked: Tava reģistrācija bija veiksmīga. Tomēr mēs nevarējām Tevi pieteikt, jo Tavs konts ir slēgts. signed_up_but_pending: Uz tavu e-pasta adresi ir nosūtīts ziņojums ar apstiprinājuma saiti. Pēc noklikšķināšanas uz saites mēs izskatīsim tavu pieteikumu. Tu tiksi informēts, ja tas tiks apstiprināts. signed_up_but_unconfirmed: Uz tavu e-pasta adresi ir nosūtīts ziņojums ar apstiprinājuma saiti. Lūdzu, seko saitei, lai aktivizētu savu kontu. Lūdzu, pārbaudi spama mapi, ja neesi saņēmis šo e-pastu. update_needs_confirmation: Tu veiksmīgi atjaunināji savu kontu, taču mums ir jāverificē teva jaunā e-pasta adrese. Lūdzu, pārbaudi savu e-pastu un seko apstiprinājuma saitei, lai apstiprinātu savu jauno e-pasta adresi. Lūdzu, pārbaudi spama mapi, ja neesi saņēmis šo e-pastu. @@ -111,7 +111,7 @@ lv: unlocked: Konts tika veiksmīgi atbloķēts. Lūgums pieteikties, lai turpinātu. errors: messages: - already_confirmed: jau tika apstiprināts, lūdzu, mēģini pierakstīties + already_confirmed: jau tika apstiprināts, lūgums mēģināt pieteikties confirmation_period_expired: jāapstiprina %{period} laikā, lūdzu, pieprasi jaunu expired: ir beidzies derīguma termiņš, lūdzu, pieprasi jaunu not_found: nav atrasts diff --git a/config/locales/devise.zh-CN.yml b/config/locales/devise.zh-CN.yml index 86e78c1b18..1b5f364d08 100644 --- a/config/locales/devise.zh-CN.yml +++ b/config/locales/devise.zh-CN.yml @@ -9,7 +9,7 @@ zh-CN: already_authenticated: 你已登录。 inactive: 你还没有激活账户。 invalid: "%{authentication_keys} 无效或密码错误。" - last_attempt: 你只有最后一次尝试机会,若未通过,帐号将被锁定。 + last_attempt: 你只有最后一次尝试机会,若未通过,账号将被锁定。 locked: 你的账户已被锁定。 not_found_in_database: "%{authentication_keys}或密码错误。" omniauth_user_creation_failure: 为此身份创建账户时出错。 @@ -33,7 +33,7 @@ zh-CN: title: 新邮箱地址 password_change: explanation: 你的账户密码已更改。 - extra: 如果你并没有申请更改密码,那似乎有人已经入侵你的帐户。请立即更改你的密码;如果你已经无法访问你的帐户,请联系服务器的管理员获取帮助。 + extra: 如果你并没有申请更改密码,那似乎有人已经入侵你的账户。请立即更改你的密码;如果你已经无法访问你的账户,请联系服务器的管理员获取帮助。 subject: Mastodon:密码已被更改 title: 密码已被重置 reconfirmation_instructions: @@ -66,7 +66,7 @@ zh-CN: subject: Mastodon:账户解锁信息 webauthn_credential: added: - explanation: 以下安全密钥已添加到你的帐户 + explanation: 以下安全密钥已添加到你的账户 subject: Mastodon:新的安全密钥 title: 已添加一个新的安全密钥 deleted: diff --git a/config/locales/doorkeeper.ia.yml b/config/locales/doorkeeper.ia.yml index 6bf5e38506..efde9be9c0 100644 --- a/config/locales/doorkeeper.ia.yml +++ b/config/locales/doorkeeper.ia.yml @@ -60,6 +60,7 @@ ia: error: title: Un error ha occurrite new: + prompt_html: "%{client_name} vole haber le permission de acceder a tu conto. Solmente approba iste requesta si tu recognosce e confide in iste fonte." review_permissions: Revider permissiones title: Autorisation necessari show: @@ -82,6 +83,7 @@ ia: access_denied: Le proprietario del ressource o servitor de autorisation ha refusate le requesta. credential_flow_not_configured: Le processo de credentiales de contrasigno del proprietario del ressource ha fallite perque Doorkeeper.configure.resource_owner_from_credentials non es configurate. invalid_client: Le authentication del cliente ha fallite perque le cliente es incognite, necun authentication de cliente es includite, o le methodo de authentication non es supportate. + invalid_code_challenge_method: Le methodo de defia de codice debe esser S256. Le methodo simple (plain) non es supportate. invalid_grant: Le concession de autorisation fornite es invalide, expirate, revocate, non corresponde al URI de redirection usate in le requesta de autorisation, o ha essite emittite a un altere cliente. invalid_redirect_uri: Le URI de redirection includite non es valide. invalid_request: diff --git a/config/locales/doorkeeper.ig.yml b/config/locales/doorkeeper.ig.yml index 7c264f0d73..ef11972aed 100644 --- a/config/locales/doorkeeper.ig.yml +++ b/config/locales/doorkeeper.ig.yml @@ -1 +1,11 @@ +--- ig: + doorkeeper: + grouped_scopes: + title: + filters: Myọ + profile: Profaịlụ Mastọdọnụ gị + scopes: + read:filters: lelee myọ gị + write:accounts: dezie profaịlụ gị + write:filters: mepụta myọ diff --git a/config/locales/doorkeeper.ro.yml b/config/locales/doorkeeper.ro.yml index 9c02501eff..08b7c3fa8d 100644 --- a/config/locales/doorkeeper.ro.yml +++ b/config/locales/doorkeeper.ro.yml @@ -60,6 +60,7 @@ ro: error: title: A apărut o eroare new: + prompt_html: "%{client_name} ar dori să vă acceseze contul. Aprobați această solicitare numai dacă recunoașteți și aveți încredere în această sursă." review_permissions: Revizuiți permisiunile title: Autorizare necesară show: @@ -82,6 +83,7 @@ ro: access_denied: Proprietarul de resurse sau serverul de autorizare a refuzat cererea. credential_flow_not_configured: Fluxul Resurselor de Acreditări Parole a eșuat din cauza faptului că Doorkeeper.configure.resource_owner_from_credentials nu este configurat. invalid_client: Autentificarea clientului a eșuat din cauza unui client necunoscut, nici o autentificare client inclusă, sau metodă de autentificare nesuportată. + invalid_code_challenge_method: Metoda de provocare a codului trebuie să fie S256, simplu nu este acceptată. invalid_grant: Acordarea autorizației furnizată este invalidă, expirată, revocată, nu corespunde URI-ului de redirecționare folosit în cererea de autorizare, sau a fost eliberat altui client. invalid_redirect_uri: Uri-ul de redirecționare inclus nu este valid. invalid_request: @@ -134,6 +136,7 @@ ro: media: Atașamente media mutes: Pus pe silențios notifications: Notificări + profile: Profilul tău Mastodon push: Notificări push reports: Rapoarte search: Căutare @@ -148,12 +151,23 @@ ro: scopes: admin:read: citește toate datele de pe server admin:read:accounts: citește informații sensibile ale tuturor conturilor + admin:read:canonical_email_blocks: citește informații sensibile ale tuturor blocurilor de e-mail canonice + admin:read:domain_allows: citește informații sensibile ale tuturor domeniilor permise + admin:read:domain_blocks: citește informații sensibile ale tuturor blocurilor de domeniu + admin:read:email_domain_blocks: citește informații sensibile ale tuturor blocurilor de domeniu de e-mail + admin:read:ip_blocks: citește informații sensibile ale tuturor blocurilor IP admin:read:reports: citește informații sensibile din toate rapoartele și conturile raportate admin:write: modifică toate datele de pe server admin:write:accounts: efectuează acțiuni de moderare pe conturi + admin:write:canonical_email_blocks: efectuează acțiuni de moderare pe blocurile de e-mail canonice + admin:write:domain_allows: efectuează acțiuni de moderare pe domeniile permise + admin:write:domain_blocks: efectuează acțiuni de moderare pe blocurile de domeniu + admin:write:email_domain_blocks: efectuează acțiuni de moderare pe blocurile de domeniu de e-mail + admin:write:ip_blocks: efectuează acțiuni de moderare pe blocurile IP admin:write:reports: efectuează acțiuni de moderare pe rapoarte crypto: utilizează criptare la ambele capete follow: modifică relațiile contului + profile: citește doar informațiile de profil ale contului tău push: primește notificările tale push read: citește toate datele contului tău read:accounts: vede informațiile privind conturile 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 ca8271ebf1..3c8b08ff26 100644 --- a/config/locales/doorkeeper.sv.yml +++ b/config/locales/doorkeeper.sv.yml @@ -72,7 +72,7 @@ sv: revoke: Är du säker? index: authorized_at: Godkändes den %{date} - description_html: Dessa applikationer har åtkomst till ditt konto genom API:et. Om det finns applikationer du inte känner igen här, eller om en applikation inte fungerar, kan du återkalla dess åtkomst. + description_html: Detta är program som kan komma åt ditt konto med hjälp av API. Om det finns program som du inte känner igen här, eller om ett program är inte fungerar kan du återkalla dess åtkomst. last_used_at: Användes senast %{date} never_used: Aldrig använd scopes: Behörigheter diff --git a/config/locales/doorkeeper.th.yml b/config/locales/doorkeeper.th.yml index 2dfc72cd6c..3b52e170ea 100644 --- a/config/locales/doorkeeper.th.yml +++ b/config/locales/doorkeeper.th.yml @@ -60,7 +60,7 @@ th: error: title: เกิดข้อผิดพลาด new: - prompt_html: "%{client_name} ร้องขอสิทธิ์ในการเข้าถึงข้อมูลในบัญชีของคุณ อนุมัติคำขอนี้ได้ก็ต่อเมื่อคุณมั่นใจและเชื่อถือในแหล่งที่มาของข้อมูลนี้" + prompt_html: "%{client_name} ต้องการสิทธิอนุญาตเพื่อเข้าถึงบัญชีของคุณ อนุมัติคำขอนี้เฉพาะหากคุณรู้จักและเชื่อถือแหล่งที่มานี้เท่านั้น" review_permissions: ตรวจทานสิทธิอนุญาต title: ต้องการการอนุญาต show: diff --git a/config/locales/doorkeeper.zh-CN.yml b/config/locales/doorkeeper.zh-CN.yml index 08f9885894..848b0d6b6c 100644 --- a/config/locales/doorkeeper.zh-CN.yml +++ b/config/locales/doorkeeper.zh-CN.yml @@ -60,7 +60,7 @@ zh-CN: error: title: 发生错误 new: - prompt_html: "%{client_name} 请求获得访问您账户的权限。 请在确保自己了解并信任此来源后再批准该请求。" + prompt_html: "%{client_name} 请求获得访问你账户的权限。 请在确保自己了解并信任此来源后再批准该请求。" review_permissions: 检查权限 title: 需要授权 show: @@ -85,7 +85,7 @@ zh-CN: invalid_client: 由于应用信息未知、未提交认证信息或使用了不支持的认证方式,认证失败 invalid_code_challenge_method: 代码验证方法必须是 S256,不支持明文。 invalid_grant: 授权方式无效、过期或已被撤销、与授权请求中的回调地址不一致,或使用了其他应用的回调地址 - invalid_redirect_uri: 无效的登录回调地址 + invalid_redirect_uri: 登录回调地址无效。 invalid_request: missing_param: 缺少必需的参数:%{value} request_not_authorized: 请求需要被授权。授权请求所需的参数缺失或无效。 @@ -123,14 +123,14 @@ zh-CN: admin/accounts: 账号管理 admin/all: 所有管理功能 admin/reports: 举报管理 - all: 完全访问您的Mastodon账户 + all: 完全访问你的Mastodon账户 blocks: 屏蔽 bookmarks: 书签 conversations: 会话 crypto: 端到端加密 favourites: 喜欢 filters: 过滤器 - follow: 关注者,隐藏与屏蔽 + follow: 关注,隐藏与屏蔽 follows: 关注 lists: 列表 media: 媒体文件 @@ -163,7 +163,7 @@ zh-CN: admin:write:domain_allows: 在域上执行管理操作 admin:write:domain_blocks: 在域块上执行管理操作 admin:write:email_domain_blocks: 对已屏蔽邮箱域名执行管理操作 - admin:write:ip_blocks: 在 IP 块上执行管理操作 + admin:write:ip_blocks: 针对 IP 段执行管理操作 admin:write:reports: 对举报执行管理操作 crypto: 使用端到端加密 follow: 关注或屏蔽用户 diff --git a/config/locales/el.yml b/config/locales/el.yml index 0df31b246f..98ef5f18b7 100644 --- a/config/locales/el.yml +++ b/config/locales/el.yml @@ -21,6 +21,7 @@ el: one: Ανάρτηση other: Αναρτήσεις posts_tab_heading: Αναρτήσεις + self_follow_error: Δεν επιτρέπεται να ακολουθήσεις τον δικό σου λογαριασμό admin: account_actions: action: Εκτέλεση ενέργειας @@ -816,7 +817,6 @@ el: original_status: Αρχική ανάρτηση reblogs: Αναδημοσιεύσεις status_changed: Η ανάρτηση άλλαξε - title: Καταστάσεις λογαριασμού trending: Τάσεις visibility: Ορατότητα with_media: Με πολυμέσα diff --git a/config/locales/en-GB.yml b/config/locales/en-GB.yml index fb284479f2..76a16aa9db 100644 --- a/config/locales/en-GB.yml +++ b/config/locales/en-GB.yml @@ -832,7 +832,6 @@ en-GB: original_status: Original post reblogs: Reblogs status_changed: Post changed - title: Account posts trending: Trending visibility: Visibility with_media: With media diff --git a/config/locales/en.yml b/config/locales/en.yml index e9c8822d5a..2971fe1f25 100644 --- a/config/locales/en.yml +++ b/config/locales/en.yml @@ -187,6 +187,7 @@ en: create_domain_block: Create Domain Block create_email_domain_block: Create Email Domain Block create_ip_block: Create IP rule + create_relay: Create Relay create_unavailable_domain: Create Unavailable Domain create_user_role: Create Role demote_user: Demote User @@ -198,14 +199,17 @@ en: destroy_email_domain_block: Delete Email Domain Block destroy_instance: Purge Domain destroy_ip_block: Delete IP rule + destroy_relay: Delete Relay destroy_status: Delete Post destroy_unavailable_domain: Delete Unavailable Domain destroy_user_role: Destroy Role disable_2fa_user: Disable 2FA disable_custom_emoji: Disable Custom Emoji + disable_relay: Disable Relay disable_sign_in_token_auth_user: Disable Email Token Authentication for User disable_user: Disable User enable_custom_emoji: Enable Custom Emoji + enable_relay: Enable Relay enable_sign_in_token_auth_user: Enable Email Token Authentication for User enable_user: Enable User memorialize_account: Memorialize Account @@ -247,6 +251,7 @@ en: create_domain_block_html: "%{name} blocked domain %{target}" create_email_domain_block_html: "%{name} blocked email domain %{target}" create_ip_block_html: "%{name} created rule for IP %{target}" + create_relay_html: "%{name} created a relay %{target}" create_unavailable_domain_html: "%{name} stopped delivery to domain %{target}" create_user_role_html: "%{name} created %{target} role" demote_user_html: "%{name} demoted user %{target}" @@ -258,14 +263,17 @@ en: destroy_email_domain_block_html: "%{name} unblocked email domain %{target}" destroy_instance_html: "%{name} purged domain %{target}" destroy_ip_block_html: "%{name} deleted rule for IP %{target}" + destroy_relay_html: "%{name} deleted the relay %{target}" destroy_status_html: "%{name} removed post by %{target}" destroy_unavailable_domain_html: "%{name} resumed delivery to domain %{target}" destroy_user_role_html: "%{name} deleted %{target} role" disable_2fa_user_html: "%{name} disabled two factor requirement for user %{target}" disable_custom_emoji_html: "%{name} disabled emoji %{target}" + disable_relay_html: "%{name} disabled the relay %{target}" disable_sign_in_token_auth_user_html: "%{name} disabled email token authentication for %{target}" disable_user_html: "%{name} disabled login for user %{target}" enable_custom_emoji_html: "%{name} enabled emoji %{target}" + enable_relay_html: "%{name} enabled the relay %{target}" enable_sign_in_token_auth_user_html: "%{name} enabled email token authentication for %{target}" enable_user_html: "%{name} enabled login for user %{target}" memorialize_account_html: "%{name} turned %{target}'s account into a memoriam page" @@ -818,8 +826,10 @@ en: back_to_account: Back to account page back_to_report: Back to report page batch: + add_to_report: 'Add to report #%{id}' remove_from_report: Remove from report report: Report + contents: Contents deleted: Deleted favourites: Favorites history: Version history @@ -828,13 +838,17 @@ en: media: title: Media metadata: Metadata + no_history: This post hasn't been edited no_status_selected: No posts were changed as none were selected open: Open post original_status: Original post reblogs: Reblogs + replied_to_html: Replied to %{acct_link} status_changed: Post changed - title: Account posts + status_title: Post by @%{name} + title: Account posts - @%{name} trending: Trending + view_publicly: View publicly visibility: Visibility with_media: With media strikes: diff --git a/config/locales/eo.yml b/config/locales/eo.yml index 12cae075f0..120df142b7 100644 --- a/config/locales/eo.yml +++ b/config/locales/eo.yml @@ -73,7 +73,7 @@ eo: enable_sign_in_token_auth: Ebligu retpoŝtan ĵeton-aŭtentikigon enabled: Ebligita enabled_msg: Sukcese malfrostigis konton de %{username} - followers: Sekvantoj + followers: Sekvoj follows: Sekvatoj header: Kapa bildo inbox_url: Enira URL @@ -187,6 +187,7 @@ eo: create_domain_block: Krei Blokadon De Domajno create_email_domain_block: Krei retpoŝtan domajnan blokon create_ip_block: Krei IP-regulon + create_relay: Krei Relajson create_unavailable_domain: Krei Nehaveblan Domajnon create_user_role: Krei Rolon demote_user: Malpromocii Uzanton @@ -198,13 +199,18 @@ eo: destroy_email_domain_block: Forigi retpoŝtan domajnan blokon destroy_instance: Forigi Domajnon destroy_ip_block: Forigi IP-regulon + destroy_relay: Forigi Relajson destroy_status: Forigi Afiŝon destroy_unavailable_domain: Forigi Nehaveblan Domajnon destroy_user_role: Detrui Rolon disable_2fa_user: Malebligi 2FA disable_custom_emoji: Malebligi proprajn emoĝiojn + disable_relay: Malebligi Relajson + disable_sign_in_token_auth_user: Malebligi aŭtentigon per retpoŝta ĵetono por la uzanto disable_user: Neebligi la uzanton enable_custom_emoji: Ebligi Propran Emoĝion + enable_relay: Ebligi Relajson + enable_sign_in_token_auth_user: Ebligi aŭtentigon per retpoŝta ĵetono por la uzanto enable_user: Ebligi uzanton memorialize_account: Memorigu Konton promote_user: Promocii Uzanton @@ -245,6 +251,7 @@ eo: create_domain_block_html: "%{name} blokis domajnon %{target}" create_email_domain_block_html: "%{name} blokis retpoŝtan domajnon %{target}" create_ip_block_html: "%{name} kreis regulon por IP %{target}" + create_relay_html: "%{name} kreis relajson %{target}" create_unavailable_domain_html: "%{name} ĉesis sendon al domajno %{target}" create_user_role_html: "%{name} kreis rolon de %{target}" demote_user_html: "%{name} degradis uzanton %{target}" @@ -256,13 +263,18 @@ eo: destroy_email_domain_block_html: "%{name} malblokis retpoŝtan domajnon %{target}" destroy_instance_html: "%{name} forigis domajnon %{target}" destroy_ip_block_html: "%{name} forigis regulon por IP %{target}" + destroy_relay_html: "%{name} forigis la relajson %{target}" destroy_status_html: "%{name} forigis mesaĝojn de %{target}" destroy_unavailable_domain_html: "%{name} restartigis sendon al domajno %{target}" destroy_user_role_html: "%{name} forigis rolon de %{target}" disable_2fa_user_html: "%{name} malebligis dufaktoran aŭtentigon por uzanto %{target}" disable_custom_emoji_html: "%{name} malebligis la emoĝion %{target}" + disable_relay_html: "%{name} malebligis la relajson %{target}" + disable_sign_in_token_auth_user_html: "%{name} malebligis la aŭtentigon de retpoŝta ĵetono por %{target}" disable_user_html: "%{name} malebligis ensaluton por uzanto %{target}" enable_custom_emoji_html: "%{name} ebligis la emoĝion %{target}" + enable_relay_html: "%{name} ebligis la relajson %{target}" + enable_sign_in_token_auth_user_html: "%{name} ebligis la aŭtentigon de retpoŝta ĵetono por %{target}" enable_user_html: "%{name} ebligis ensaluton por uzanto %{target}" memorialize_account_html: "%{name} ŝanĝis la konton de %{target} al memora paĝo" promote_user_html: "%{name} plirangigis uzanton %{target}" @@ -270,6 +282,7 @@ eo: reject_user_html: "%{name} malakceptis registriĝon de %{target}" remove_avatar_user_html: "%{name} forigis la profilbildon de %{target}" reopen_report_html: "%{name} remalfermis signalon %{target}" + resend_user_html: "%{name} resendis konfirman retmesaĝon por %{target}" reset_password_user_html: "%{name} restarigis la pasvorton de la uzanto %{target}" resolve_report_html: "%{name} solvis raporton %{target}" sensitive_account_html: "%{name} markis audovidaĵon de %{target} kiel tiklan" @@ -440,6 +453,7 @@ eo: create: Aldoni domajnon resolve: Solvi domajnon title: Bloki novan retpoŝtan domajnon + no_email_domain_block_selected: Neniuj domajn blokoj ŝanĝiĝis ĉar nenio estis elektita not_permitted: Ne permesita resolved_through_html: Solvis tra %{domain} title: Blokis retpoŝtajn domajnojn @@ -467,6 +481,8 @@ eo: title: Rekomendoj de sekvado unsuppress: Regajni sekvorekomendon instances: + audit_log: + title: Novaj Protokoloj Pri Ekzamenoj availability: description_html: one: Se sendo la domajno malsukcesis por %{count} dio, ne estas sendprovo plu escepte de la dojmano. @@ -814,7 +830,6 @@ eo: original_status: Originala afiŝo reblogs: Reblogaĵoj status_changed: Afiŝo ŝanĝiĝis - title: Afiŝoj de la konto trending: Popularaĵoj visibility: Videbleco with_media: Kun aŭdovidaĵoj @@ -1054,6 +1069,7 @@ eo: awaiting_review_title: Via registriĝo estas reviziita clicking_this_link: alklakante ĉi tiun ligilon login_link: ensaluti + proceed_to_login_html: Vi nun povas iri al %{login_link}. registration_complete: Via registriĝo sur %{domain} nun finiĝis! welcome_title: Bonvenon, %{name}! wrong_email_hint: Se tiu retadreso ne estas ĝusta, vi povas ŝanĝi ĝin en kontagordoj. @@ -1329,6 +1345,7 @@ eo: unconfirmed: Nekonfirmita status: Stato success: Viaj datumoj estis sukcese alŝutitaj kaj estos traktitaj kiel planite + time_started: Komencis je titles: following: Importado de sekvaj kontoj lists: Importi listojn @@ -1375,6 +1392,7 @@ eo: authentication_methods: otp: 2-faktora autentigprogramaro password: pasvorto + sign_in_token: retpoŝta sekureca kodo webauthn: sekurecaj ŝlosiloj description_html: Se vi vidas nerekonitan agon, eble ŝanĝu vian pasvorton. empty: Neniu autentighistorio disponebla @@ -1385,6 +1403,9 @@ eo: unsubscribe: action: Jes, malabonu complete: Malabonita + emails: + notification_emails: + follow_request: retpoŝtajn petoj de sekvado title: Malaboni media_attachments: validations: @@ -1725,6 +1746,7 @@ eo: default: "%Y.%b.%d, %H:%M" month: "%b %Y" time: "%H:%M" + with_time_zone: "%b %d, %Y, %H:%M %Z" translation: errors: quota_exceeded: La tutservila uzkvoto por la tradukservo estas superita. @@ -1805,6 +1827,7 @@ eo: apps_ios_action: Elŝutu ĉe la App Store apps_step: Elŝutu niajn oficialajn aplikaĵojn. apps_title: Aplikaĵoj de Mastodon + checklist_title: Bonvenan Markolisto edit_profile_action: Agordi edit_profile_title: Agordi vian profilon explanation: Jen kelkaj konsiloj por helpi vin komenci diff --git a/config/locales/es-AR.yml b/config/locales/es-AR.yml index 79bfdfbdbf..09163c2e4a 100644 --- a/config/locales/es-AR.yml +++ b/config/locales/es-AR.yml @@ -187,6 +187,7 @@ es-AR: create_domain_block: Crear bloqueo de dominio create_email_domain_block: Crear bloqueo de dominio de correo electrónico create_ip_block: Crear regla de dirección IP + create_relay: Crear Relé create_unavailable_domain: Crear dominio no disponible create_user_role: Crear rol demote_user: Descender usuario @@ -198,14 +199,17 @@ es-AR: destroy_email_domain_block: Eliminar bloqueo de dominio de correo electrónico destroy_instance: Purgar dominio destroy_ip_block: Eliminar regla de dirección IP + destroy_relay: Eliminar Relé destroy_status: Eliminar mensaje destroy_unavailable_domain: Eliminar dominio no disponible destroy_user_role: Destruir rol disable_2fa_user: Deshabilitar 2FA disable_custom_emoji: Deshabilitar emoji personalizado + disable_relay: Desactivar Relé disable_sign_in_token_auth_user: Deshabilitar autenticación de token por correo electrónico para el usuario disable_user: Deshabilitar usuario enable_custom_emoji: Habilitar emoji personalizado + enable_relay: Activar Relé enable_sign_in_token_auth_user: Habilitar autenticación de token por correo electrónico para el usuario enable_user: Habilitar usuario memorialize_account: Convertir en cuenta conmemorativa @@ -247,6 +251,7 @@ es-AR: create_domain_block_html: "%{name} bloqueó el dominio %{target}" create_email_domain_block_html: "%{name} bloqueó el dominio de correo electrónico %{target}" create_ip_block_html: "%{name} creó la regla para la dirección IP %{target}" + create_relay_html: "%{name} creó un relé %{target}" create_unavailable_domain_html: "%{name} detuvo la entrega al dominio %{target}" create_user_role_html: "%{name} creó el rol %{target}" demote_user_html: "%{name} bajó de nivel al usuario %{target}" @@ -258,14 +263,17 @@ es-AR: destroy_email_domain_block_html: "%{name} desbloqueó el dominio de correo electrónico %{target}" destroy_instance_html: "%{name} purgó el dominio %{target}" destroy_ip_block_html: "%{name} eliminó la regla para la dirección IP %{target}" + destroy_relay_html: "%{name} eliminó el relé %{target}" destroy_status_html: "%{name} eliminó el mensaje de %{target}" destroy_unavailable_domain_html: "%{name} reanudó la entrega al dominio %{target}" destroy_user_role_html: "%{name} eliminó el rol %{target}" disable_2fa_user_html: "%{name} deshabilitó el requerimiento de dos factores para el usuario %{target}" disable_custom_emoji_html: "%{name} deshabilitó el emoji %{target}" + disable_relay_html: "%{name} desactivó el relé %{target}" disable_sign_in_token_auth_user_html: "%{name} deshabilitó la autenticación de token por correo electrónico para %{target}" disable_user_html: "%{name} deshabilitó el inicio de sesión para el usuario %{target}" enable_custom_emoji_html: "%{name} habilitó el emoji %{target}" + enable_relay_html: "%{name} activó el relé %{target}" enable_sign_in_token_auth_user_html: "%{name} habilitó la autenticación de token por 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 cuenta conmemorativa" @@ -818,8 +826,10 @@ es-AR: back_to_account: Volver a la página de la cuenta back_to_report: Volver a la página de la denuncia batch: + add_to_report: 'Añadir al informe #%{id}' remove_from_report: Quitar de la denuncia report: Denunciar + contents: Contenidos deleted: Eliminado favourites: Favoritos history: Historial de versiones @@ -828,13 +838,17 @@ es-AR: media: title: Medios metadata: Metadatos + no_history: Esta publicación no ha sido editada no_status_selected: No se cambió ningún mensaje, ya que ninguno fue seleccionado open: Abrir mensaje original_status: Mensaje original reblogs: Adhesiones + replied_to_html: Respondió a %{acct_link} status_changed: Mensaje cambiado - title: Mensajes de la cuenta + status_title: Publicación de @%{name} + title: Publicaciones de la cuenta - @%{name} trending: En tendencia + view_publicly: Ver públicamente visibility: Visibilidad with_media: Con medios strikes: diff --git a/config/locales/es-MX.yml b/config/locales/es-MX.yml index fef805680a..53557c091a 100644 --- a/config/locales/es-MX.yml +++ b/config/locales/es-MX.yml @@ -187,6 +187,7 @@ es-MX: create_domain_block: Crear Bloqueo de Dominio create_email_domain_block: Crear bloqueo de dominio de correo electrónico create_ip_block: Crear regla IP + create_relay: Crear Relé create_unavailable_domain: Crear Dominio No Disponible create_user_role: Crear rol demote_user: Degradar Usuario @@ -198,14 +199,17 @@ es-MX: destroy_email_domain_block: Eliminar bloqueo de dominio de correo electrónico destroy_instance: Purgar dominio destroy_ip_block: Eliminar regla IP + destroy_relay: Eliminar Relé destroy_status: Eliminar Estado destroy_unavailable_domain: Eliminar Dominio No Disponible destroy_user_role: Destruir Rol disable_2fa_user: Deshabilitar 2FA disable_custom_emoji: Deshabilitar Emoji Personalizado + disable_relay: Desactivar Relé disable_sign_in_token_auth_user: Deshabilitar la autenticación por token de correo electrónico para el usuario disable_user: Deshabilitar Usuario enable_custom_emoji: Habilitar Emoji Personalizado + enable_relay: Activar Relé enable_sign_in_token_auth_user: Habilitar la autenticación por token de correo electrónico para el usuario enable_user: Habilitar Usuario memorialize_account: Transformar en Cuenta Conmemorativa @@ -247,6 +251,7 @@ es-MX: create_domain_block_html: "%{name} bloqueó el dominio %{target}" create_email_domain_block_html: "%{name} bloqueó el dominio de correo electrónico %{target}" create_ip_block_html: "%{name} creó una regla para la IP %{target}" + create_relay_html: "%{name} creó un relé %{target}" create_unavailable_domain_html: "%{name} detuvo las entregas al dominio %{target}" create_user_role_html: "%{name} creó el rol %{target}" demote_user_html: "%{name} degradó al usuario %{target}" @@ -258,14 +263,17 @@ es-MX: destroy_email_domain_block_html: "%{name} desbloqueó el dominio de correo electrónico %{target}" destroy_instance_html: "%{name} purgó el dominio %{target}" destroy_ip_block_html: "%{name} eliminó una regla para la IP %{target}" + destroy_relay_html: "%{name} eliminó el relé %{target}" destroy_status_html: "%{name} eliminó el estado por %{target}" destroy_unavailable_domain_html: "%{name} reanudó las entregas al dominio %{target}" 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_relay_html: "%{name} desactivó el relé %{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_relay_html: "%{name} activó el relé %{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" @@ -818,8 +826,10 @@ es-MX: back_to_account: Volver a la cuenta back_to_report: Volver a la página de reporte batch: + add_to_report: 'Añadir al informe #%{id}' remove_from_report: Eliminar del reporte report: Reportar + contents: Contenidos deleted: Eliminado favourites: Favoritos history: Historial de versiones @@ -828,13 +838,17 @@ es-MX: media: title: Multimedia metadata: Metadatos + no_history: Esta publicación no ha sido editada no_status_selected: No se cambió ningún estado al no seleccionar ninguno open: Abrir publicación original_status: Publicación original reblogs: Impulsos + replied_to_html: Respondió a %{acct_link} status_changed: Publicación cambiada - title: Estado de las cuentas + status_title: Publicación de @%{name} + title: Publicaciones de la cuenta - @%{name} trending: En tendencia + view_publicly: Ver públicamente visibility: Visibilidad with_media: Con multimedia strikes: diff --git a/config/locales/es.yml b/config/locales/es.yml index 8690c1cdfb..22123e4309 100644 --- a/config/locales/es.yml +++ b/config/locales/es.yml @@ -57,7 +57,7 @@ es: confirming: Confirmando custom: Personalizado delete: Eliminar datos - deleted: Borrado + deleted: Eliminado demote: Degradar destroyed_msg: Los datos de %{username} están ahora en cola para ser eliminados inminentemente disable: Deshabilitar @@ -67,8 +67,8 @@ es: display_name: Nombre domain: Dominio edit: Editar - email: E-mail - email_status: E-mail Status + email: Correo electrónico + email_status: Estado del correo electrónico enable: Habilitar enable_sign_in_token_auth: Habilitar la autenticación por token de correo electrónico enabled: Habilitada @@ -86,7 +86,7 @@ es: local: Local remote: Remoto title: Localización - login_status: Estado del login + login_status: Estado de inicio de sesión media_attachments: Multimedia memorialize: Convertir en memorial memorialized: Cuenta conmemorativa @@ -102,7 +102,7 @@ es: moderation_notes: Notas de moderación most_recent_activity: Actividad más reciente most_recent_ip: IP más reciente - no_account_selected: Ninguna cuenta se cambió como ninguna fue seleccionada + no_account_selected: Ninguna cuenta se cambió, ya que ninguna fue seleccionada no_limits_imposed: Sin límites impuestos no_role_assigned: Ningún rol asignado not_subscribed: No se está suscrito @@ -116,7 +116,7 @@ es: protocol: Protocolo public: Público push_subscription_expires: Expiración de la suscripción PuSH - redownload: Refrescar avatar + redownload: Refrescar perfil redownloaded_msg: Se actualizó correctamente el perfil de %{username} desde el origen reject: Rechazar rejected_msg: La solicitud de registro de %{username} ha sido rechazada con éxito @@ -132,17 +132,17 @@ es: success: "¡Enlace de confirmación enviado con éxito!" reset: Reiniciar reset_password: Reiniciar contraseña - resubscribe: Re-suscribir + resubscribe: Volver a suscribirse role: Rol search: Buscar search_same_email_domain: Otros usuarios con el mismo dominio de correo search_same_ip: Otros usuarios con la misma IP security: Seguridad security_measures: - only_password: Sólo contraseña + only_password: Solo contraseña password_and_2fa: Contraseña y 2FA sensitive: Sensible - sensitized: marcado como sensible + sensitized: Marcada como sensible shared_inbox_url: URL de bandeja compartida show: created_reports: Reportes hechos por esta cuenta @@ -161,10 +161,10 @@ es: unblocked_email_msg: Se ha desbloqueado correctamente la dirección de correo de %{username} unconfirmed_email: Correo electrónico sin confirmar undo_sensitized: Desmarcar como sensible - undo_silenced: Des-silenciar - undo_suspension: Des-suspender + undo_silenced: Dejar de silenciar + undo_suspension: Deshacer suspensión unsilenced_msg: Se quitó con éxito el límite de la cuenta %{username} - unsubscribe: Desuscribir + unsubscribe: Cancelar suscripción unsuspended_msg: Se quitó con éxito la suspensión de la cuenta de %{username} username: Nombre de usuario view_domain: Ver resumen del dominio @@ -187,6 +187,7 @@ es: create_domain_block: Crear Bloqueo de Dominio create_email_domain_block: Crear Bloqueo de Dominio de Correo Electrónico create_ip_block: Crear regla IP + create_relay: Crear Relé create_unavailable_domain: Crear Dominio No Disponible create_user_role: Crear Rol demote_user: Degradar Usuario @@ -198,14 +199,17 @@ es: destroy_email_domain_block: Eliminar Bloqueo de Dominio de Correo Electrónico destroy_instance: Purgar Dominio destroy_ip_block: Eliminar regla IP + destroy_relay: Eliminar Relé destroy_status: Eliminar Publicación destroy_unavailable_domain: Eliminar Dominio No Disponible destroy_user_role: Destruir Rol disable_2fa_user: Deshabilitar 2FA disable_custom_emoji: Deshabilitar Emoji Personalizado + disable_relay: Desactivar Relé disable_sign_in_token_auth_user: Deshabilitar la Autenticación por Token de Correo Electrónico para el Usuario disable_user: Deshabilitar Usuario enable_custom_emoji: Habilitar Emoji Personalizado + enable_relay: Activar Relé enable_sign_in_token_auth_user: Habilitar la Autenticación por Token de Correo Electrónico para el Usuario enable_user: Habilitar Usuario memorialize_account: Transformar en Cuenta Conmemorativa @@ -247,6 +251,7 @@ es: create_domain_block_html: "%{name} bloqueó el dominio %{target}" create_email_domain_block_html: "%{name} bloqueó el dominio de correo electrónico %{target}" create_ip_block_html: "%{name} creó una regla para la IP %{target}" + create_relay_html: "%{name} creó un relé %{target}" create_unavailable_domain_html: "%{name} detuvo las entregas al dominio %{target}" create_user_role_html: "%{name} creó el rol %{target}" demote_user_html: "%{name} degradó al usuario %{target}" @@ -258,14 +263,17 @@ es: destroy_email_domain_block_html: "%{name} desbloqueó el dominio de correo electrónico %{target}" destroy_instance_html: "%{name} purgó el dominio %{target}" destroy_ip_block_html: "%{name} eliminó una regla para la IP %{target}" + destroy_relay_html: "%{name} eliminó el relé %{target}" destroy_status_html: "%{name} eliminó la publicación de %{target}" destroy_unavailable_domain_html: "%{name} reanudó las entregas al dominio %{target}" 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_relay_html: "%{name} desactivó el relé %{target}" disable_sign_in_token_auth_user_html: "%{name} ha deshabilitado 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_relay_html: "%{name} activó el relé %{target}" enable_sign_in_token_auth_user_html: "%{name} ha habilitado la 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" @@ -296,7 +304,7 @@ es: empty: No se encontraron registros. filter_by_action: Filtrar por acción filter_by_user: Filtrar por usuario - title: Log de auditoría + title: Registro de auditoría unavailable_instance: "(nombre de dominio no disponible)" announcements: destroyed_msg: "¡Anuncio eliminado con éxito!" @@ -338,7 +346,7 @@ es: listed: Listados new: title: Añadir nuevo emoji personalizado - no_emoji_selected: No se cambió ningún emoji ya que no se seleccionó ninguno + no_emoji_selected: No se cambió ningún emoji, ya que no se seleccionó ninguno not_permitted: No tienes permiso para realizar esta acción overwrite: Sobrescribir shortcode: Código de atajo @@ -566,7 +574,7 @@ es: '94670856': 3 años new: title: Crear nueva regla IP - no_ip_block_selected: No se han cambiado reglas IP ya que no se ha seleccionado ninguna + no_ip_block_selected: No se han cambiado reglas IP, ya que no se ha seleccionado ninguna title: Reglas IP relationships: title: Relaciones de %{acct} @@ -818,8 +826,10 @@ es: back_to_account: Volver a la cuenta back_to_report: Volver a la página del reporte batch: + add_to_report: 'Añadir al informe #%{id}' remove_from_report: Eliminar del reporte report: Reporte + contents: Contenidos deleted: Eliminado favourites: Favoritos history: Historial de versiones @@ -828,13 +838,17 @@ es: media: title: Multimedia metadata: Metadatos + no_history: Esta publicación no ha sido editada no_status_selected: No se cambió ninguna publicación al no seleccionar ninguna open: Abrir publicación original_status: Publicación original reblogs: Impulsos + replied_to_html: Respondió a %{acct_link} status_changed: Publicación cambiada - title: Publicaciones de la cuenta + status_title: Publicación de @%{name} + title: Publicaciones de la cuenta - @%{name} trending: En tendencia + view_publicly: Ver públicamente visibility: Visibilidad with_media: Con multimedia strikes: @@ -910,7 +924,7 @@ es: review: Estado de revisión search: Buscar title: Etiquetas - updated_msg: Hashtags actualizados exitosamente + updated_msg: La configuración de etiquetas se actualizó correctamente title: Administración trends: allow: Permitir @@ -1109,7 +1123,7 @@ es: didnt_get_confirmation: "¿No recibiste un enlace de confirmación?" dont_have_your_security_key: "¿No tienes tu clave de seguridad?" forgot_password: "¿Olvidaste tu contraseña?" - invalid_reset_password_token: El token de reinicio de contraseña es inválido o expiró. Por favor pide uno nuevo. + invalid_reset_password_token: El token de restablecimiento de contraseña no es válido o ha expirado. Por favor solicita uno nuevo. link_to_otp: Introduce un código de dos factores desde tu teléfono o un código de recuperación link_to_webauth: Utilice su dispositivo de clave de seguridad log_in_with: Iniciar sesión con @@ -1258,7 +1272,7 @@ es: '422': content: Verificación de seguridad fallida. ¿Estás bloqueando algunas cookies? title: Verificación de seguridad fallida - '429': Asfixiado + '429': Demasiadas solicitudes '500': content: Lo sentimos, algo ha funcionado mal por nuestra parte. title: Esta página no es correcta @@ -1446,7 +1460,7 @@ es: '604800': 1 semana '86400': 1 día expires_in_prompt: Nunca - generate: Generar + generate: Generar enlace de invitación invalid: Esta invitación no es válida invited_by: 'Fuiste invitado por:' max_uses: @@ -1489,12 +1503,12 @@ es: title: Cancelar suscripición media_attachments: validations: - images_and_video: No se puede adjuntar un video a unapublicación que ya contenga imágenes + images_and_video: No se puede adjuntar un video a una publicación que ya contenga imágenes not_found: Archivos multimedia %{ids} no encontrados, o ya se encuentran adjuntos a otra publicación not_ready: No se pueden adjuntar archivos que no se han terminado de procesar. ¡Inténtalo de nuevo en un momento! too_many: No se pueden adjuntar más de 4 archivos migrations: - acct: username@domain de la nueva cuenta + acct: Movido a cancel: Cancelar redireccionamiento cancel_explanation: Al cancelar el redireccionamiento se reactivará tu cuenta actual, pero no recuperarás los seguidores que hayan sido trasladados a la otra cuenta. cancelled_msg: El redireccionamiento se ha cancelado correctamente. @@ -1729,7 +1743,7 @@ es: migrate: Migración de cuenta notifications: Notificaciones por correo electrónico preferences: Preferencias - profile: Perfil + profile: Perfil público relationships: Siguiendo y seguidores severed_relationships: Relaciones cortadas statuses_cleanup: Eliminación automática de publicaciones @@ -1773,11 +1787,11 @@ es: 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: La publicación de otra persona no puede fijarse - reblog: Un boost no puede fijarse + reblog: Una publicación impulsada no puede fijarse title: "%{name}: «%{quote}»" visibilities: direct: Directa - private: Sólo mostrar a seguidores + private: Solo seguidores private_long: Solo mostrar a tus seguidores public: Pública public_long: Todos pueden ver @@ -1826,8 +1840,8 @@ es: tags: does_not_match_previous_name: no coincide con el nombre anterior themes: - contrast: Alto contraste - default: Mastodon + contrast: Mastodon (alto contraste) + default: Mastodon (oscuro) mastodon-light: Mastodon (claro) system: Automático (usar tema del sistema) time: @@ -1847,7 +1861,7 @@ es: edit: Editar enabled: La autenticación de dos factores está activada enabled_success: Verificación de dos factores activada exitosamente - generate_recovery_codes: generar códigos de recuperación + generate_recovery_codes: Generar códigos de recuperación lost_recovery_codes: Los códigos de recuperación te permiten obtener acceso a tu cuenta si pierdes tu teléfono. Si has perdido tus códigos de recuperación, puedes regenerarlos aquí. Tus viejos códigos de recuperación se harán inválidos. methods: Métodos de autenticación de doble factor otp: Aplicación de autenticación diff --git a/config/locales/et.yml b/config/locales/et.yml index 3be9add91c..40db2eede0 100644 --- a/config/locales/et.yml +++ b/config/locales/et.yml @@ -833,7 +833,6 @@ et: original_status: Algne postitus reblogs: Jagamised status_changed: Muudetud postitus - title: Konto postitused trending: Populaarne visibility: Nähtavus with_media: Meediaga diff --git a/config/locales/eu.yml b/config/locales/eu.yml index e9c3be2d24..dc064ebc7b 100644 --- a/config/locales/eu.yml +++ b/config/locales/eu.yml @@ -793,7 +793,6 @@ eu: original_status: Jatorrizko bidalketa reblogs: Bultzadak status_changed: Bidalketa aldatuta - title: Kontuaren bidalketak trending: Joera visibility: Ikusgaitasuna with_media: Multimediarekin diff --git a/config/locales/fa.yml b/config/locales/fa.yml index 603cfe8de1..7cb0714c28 100644 --- a/config/locales/fa.yml +++ b/config/locales/fa.yml @@ -741,7 +741,6 @@ fa: original_status: فرستهٔ اصلی reblogs: تقویت‌ها status_changed: فرسته تغییر کرد - title: نوشته‌های حساب trending: پرطرفدار visibility: نمایانی with_media: دارای عکس یا ویدیو diff --git a/config/locales/fi.yml b/config/locales/fi.yml index 2f9a76c80d..d7755d23b8 100644 --- a/config/locales/fi.yml +++ b/config/locales/fi.yml @@ -187,6 +187,7 @@ fi: create_domain_block: Luo verkkotunnuksen esto create_email_domain_block: Luo sähköpostiverkkotunnuksen esto create_ip_block: Luo IP-sääntö + create_relay: Luo välittäjä create_unavailable_domain: Luo ei-saatavilla oleva verkkotunnus create_user_role: Luo rooli demote_user: Alenna käyttäjä @@ -198,14 +199,17 @@ fi: destroy_email_domain_block: Poista sähköpostiverkkotunnuksen esto destroy_instance: Tyhjennä verkkotunnus destroy_ip_block: Poista IP-sääntö + destroy_relay: Poista välittäjä destroy_status: Poista julkaisu destroy_unavailable_domain: Poista ei-saatavilla oleva verkkotunnus destroy_user_role: Hävitä rooli disable_2fa_user: Poista kaksivaiheinen todennus käytöstä disable_custom_emoji: Poista mukautettu emoji käytöstä + disable_relay: Poista välittäjä käytöstä disable_sign_in_token_auth_user: Poista sähköpostitunnuksella todennus käytöstä käyttäjältä disable_user: Poista tili käytöstä enable_custom_emoji: Ota mukautettu emoji käyttöön + enable_relay: Ota välittäjä käyttöön enable_sign_in_token_auth_user: Ota sähköpostitunnuksella todennus käyttöön käyttäjälle enable_user: Ota tili käyttöön memorialize_account: Muuta muistotiliksi @@ -216,7 +220,7 @@ fi: reopen_report: Avaa raportti uudelleen resend_user: Lähetä vahvistusviesti uudelleen reset_password_user: Palauta salasana - resolve_report: Selvitä raportti + resolve_report: Ratkaise raportti sensitive_account: Pakota arkaluonteiseksi tiliksi silence_account: Rajoita tiliä suspend_account: Jäädytä tili @@ -247,6 +251,7 @@ fi: create_domain_block_html: "%{name} esti verkkotunnuksen %{target}" create_email_domain_block_html: "%{name} esti sähköpostiverkkotunnuksen %{target}" create_ip_block_html: "%{name} loi säännön IP-osoitteelle %{target}" + create_relay_html: "%{name} loi välittäjän %{target}" create_unavailable_domain_html: "%{name} pysäytti toimituksen verkkotunnukseen %{target}" create_user_role_html: "%{name} loi roolin %{target}" demote_user_html: "%{name} alensi käyttäjän %{target}" @@ -258,14 +263,17 @@ fi: destroy_email_domain_block_html: "%{name} kumosi sähköpostiverkkotunnuksen %{target} eston" destroy_instance_html: "%{name} tyhjensi verkkotunnuksen %{target}" destroy_ip_block_html: "%{name} poisti säännön IP-osoitteelta %{target}" + destroy_relay_html: "%{name} poisti välittäjän %{target}" destroy_status_html: "%{name} poisti käyttäjän %{target} julkaisun" destroy_unavailable_domain_html: "%{name} jatkoi toimitusta verkkotunnukseen %{target}" destroy_user_role_html: "%{name} poisti roolin %{target}" disable_2fa_user_html: "%{name} poisti käyttäjältä %{target} vaatimuksen kaksivaiheiseen todentamiseen" disable_custom_emoji_html: "%{name} poisti emojin %{target} käytöstä" + disable_relay_html: "%{name} poisti välittäjän %{target} käytöstä" disable_sign_in_token_auth_user_html: "%{name} poisti sähköpostitunnuksella todennuksen käytöstä käyttäjältä %{target}" disable_user_html: "%{name} poisti kirjautumisen käytöstä käyttäjältä %{target}" enable_custom_emoji_html: "%{name} otti emojin %{target} käyttöön" + enable_relay_html: "%{name} otti välittäjän %{target} käyttöön" enable_sign_in_token_auth_user_html: "%{name} otti sähköpostitunnuksella todennuksen käyttöön käyttäjälle %{target}" enable_user_html: "%{name} otti kirjautumisen käyttöön käyttäjälle %{target}" memorialize_account_html: "%{name} muutti käyttäjän %{target} tilin muistosivuksi" @@ -818,8 +826,10 @@ fi: back_to_account: Takaisin tilin sivulle back_to_report: Takaisin raporttisivulle batch: + add_to_report: Lisää raporttiin nro %{id} remove_from_report: Poista raportista report: Raportti + contents: Sisältö deleted: Poistettu favourites: Suosikit history: Versiohistoria @@ -828,13 +838,17 @@ fi: media: title: Media metadata: Metadata + no_history: Tätä julkaisua ei ole muokattu no_status_selected: Julkaisuja ei muutettu, koska yhtään ei ollut valittuna open: Avaa julkaisu original_status: Alkuperäinen julkaisu reblogs: Edelleen jako + replied_to_html: Vastaus käyttäjälle %{acct_link} status_changed: Julkaisua muutettu - title: Tilin tilat + status_title: Julkaisu käyttäjältä @%{name} + title: Tilin julkaisut - @%{name} trending: Suosituttua + view_publicly: Näytä julkisesti visibility: Näkyvyys with_media: Sisältää mediaa strikes: diff --git a/config/locales/fo.yml b/config/locales/fo.yml index 3ade3007f4..502c027b5d 100644 --- a/config/locales/fo.yml +++ b/config/locales/fo.yml @@ -187,6 +187,7 @@ fo: create_domain_block: Stovna navnaøkjablokering create_email_domain_block: Stovna t-post-økisnavnablokk create_ip_block: Stovna IP reglu + create_relay: Stovna reiðlag create_unavailable_domain: Stovna navnaøki, sum ikki er tøkt create_user_role: Stovna leiklut demote_user: Lækka brúkara í tign @@ -198,14 +199,17 @@ fo: destroy_email_domain_block: Strika t-posta-økisnavnablokk destroy_instance: Reinsa navnaøki destroy_ip_block: Strika IP reglu + destroy_relay: Strika reiðlag destroy_status: Strika post destroy_unavailable_domain: Strika navnaøki, sum ikki er tøkt destroy_user_role: Bein burtur leiklut disable_2fa_user: Ger 2FA óvirkið disable_custom_emoji: Ger serligt kenslutekn óvirkið + disable_relay: Ger reiðlag óvirkið disable_sign_in_token_auth_user: Ger váttan við teldupostateknum óvirkna fyri brúkara disable_user: Ger brúkara óvirknan enable_custom_emoji: Ger serligt kenslutekn virkið + enable_relay: Ger reiðlag virkið enable_sign_in_token_auth_user: Ger váttan við teldupostateknum virkna fyri brúkara enable_user: Ger brúkara virknan memorialize_account: Minnst til Konto @@ -247,6 +251,7 @@ fo: create_domain_block_html: "%{name} blokeraði navnaøkið %{target}" create_email_domain_block_html: "%{name} blokeraði teldupostanavnaøkið %{target}" create_ip_block_html: "%{name} gjørdi reglu fyri IP %{target}" + create_relay_html: "%{name} gjørdi eitt reiðlag %{target}" create_unavailable_domain_html: "%{name} steðgaði veiting til navnaøkið %{target}" create_user_role_html: "%{name} stovnaði %{target} leiklutin" demote_user_html: "%{name} lækkaði tignina hjá brúkaranum %{target}" @@ -258,14 +263,17 @@ fo: destroy_email_domain_block_html: "%{name} leysgav teldupostanavnaøkið %{target}" destroy_instance_html: "%{name} reinsaði navnaøkið %{target}" destroy_ip_block_html: "%{name} slettaðar reglur fyri IP %{target}" + destroy_relay_html: "%{name} strikaði reiðlagið %{target}" destroy_status_html: "%{name} slettaði upplegg hjá %{target}" destroy_unavailable_domain_html: "%{name} tók upp aftir veiting til navnaøkið %{target}" destroy_user_role_html: "%{name} slettaði leiklutin hjá %{target}" disable_2fa_user_html: "%{name} slepti kravið um váttan í tveimum stigum fyri brúkaran %{target}" disable_custom_emoji_html: "%{name} gjørdi kensluteknið %{target} óvirkið" + disable_relay_html: "%{name} gjørdi reiðlagið %{target} óvirkið" disable_sign_in_token_auth_user_html: "%{name} gjørdi váttan við teldupostteknum óvirkna fyri %{target}" disable_user_html: "%{name} gjørdi innritan hjá brúkaranum %{target} óvirkna" enable_custom_emoji_html: "%{name} gjørdi kensluteknið %{target} virkið" + enable_relay_html: "%{name} gjørdi reiðlagið %{target} virkið" enable_sign_in_token_auth_user_html: "%{name} gjørdi váttan við teldupostteknum virkna fyri %{target}" enable_user_html: "%{name} gjørdi innritan virkna fyri brúkaran %{target}" memorialize_account_html: "%{name} broytti kontuna hjá %{target} til eina minnissíðu" @@ -818,8 +826,10 @@ fo: back_to_account: Aftur til kontusíðu back_to_report: Aftur til meldingarsíðu batch: + add_to_report: 'Legg afturat melding #%{id}' remove_from_report: Strika frá melding report: Melding + contents: Innihald deleted: Strikað favourites: Dámdir postar history: Útgávusøga @@ -828,13 +838,17 @@ fo: media: title: Miðlar metadata: Metadátur + no_history: Hesin posturin er ikki broyttur no_status_selected: Eingir postar vóru broyttir, tí eingir vóru valdir open: Lat post upp original_status: Upprunapostur reblogs: Endurbloggar + replied_to_html: Svaraði %{acct_link} status_changed: Postur broyttur - title: Postar hjá kontu + status_title: Postar hjá @%{name} + title: Kontupostar - @%{name} trending: Vælumtókt + view_publicly: Vís fyri øllum visibility: Sýni with_media: Við miðli strikes: @@ -1368,6 +1382,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 3c771d4c64..9c2bf3398e 100644 --- a/config/locales/fr-CA.yml +++ b/config/locales/fr-CA.yml @@ -836,7 +836,6 @@ fr-CA: original_status: Message original reblogs: Partages status_changed: Publication modifiée - title: Messages du compte trending: Tendances visibility: Visibilité with_media: Avec médias diff --git a/config/locales/fr.yml b/config/locales/fr.yml index 58fc63fc1b..650147eb5d 100644 --- a/config/locales/fr.yml +++ b/config/locales/fr.yml @@ -836,7 +836,6 @@ fr: original_status: Message original reblogs: Partages status_changed: Publication modifiée - title: Messages du compte trending: Tendances visibility: Visibilité with_media: Avec médias diff --git a/config/locales/fy.yml b/config/locales/fy.yml index 8ccedd2be1..24be51d9d7 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 @@ -832,7 +833,6 @@ fy: original_status: Oarspronklik berjocht reblogs: Boosts status_changed: Berjocht wizige - title: Accountberjochten trending: Trending visibility: Sichtberheid with_media: Mei media @@ -1165,8 +1165,11 @@ fy: use_security_key: Befeiligingskaai brûke author_attribution: example_title: Faorbyldtekst + 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 5e5ecb238e..deb9986691 100644 --- a/config/locales/ga.yml +++ b/config/locales/ga.yml @@ -196,6 +196,7 @@ ga: create_domain_block: Cruthaigh Bloc Fearainn create_email_domain_block: Cruthaigh Bloc Fearainn Ríomhphoist create_ip_block: Cruthaigh riail IP + create_relay: Cruthaigh Leaschraolacháin create_unavailable_domain: Cruthaigh Fearann ​​Gan Fáil create_user_role: Cruthaigh Ról demote_user: Ísligh úsáideoir @@ -207,14 +208,17 @@ ga: destroy_email_domain_block: Scrios Bloc Fearainn Ríomhphoist destroy_instance: Fearann ​​Purge destroy_ip_block: Scrios riail IP + destroy_relay: Scrios Leaschraolacháin destroy_status: Scrios Postáil destroy_unavailable_domain: Scrios Fearann ​​Gan Fáil destroy_user_role: Scrios ról disable_2fa_user: Díchumasaigh 2FA disable_custom_emoji: Díchumasaigh Emoji Saincheaptha + disable_relay: Díchumasaigh Leaschraolacháin disable_sign_in_token_auth_user: Díchumasaigh Fíordheimhniú Comhartha Ríomhphoist don Úsáideoir disable_user: Díchumasaigh Úsáideoir enable_custom_emoji: Cumasaigh Emoji Saincheaptha + enable_relay: Cumasaigh Leaschraolacháin enable_sign_in_token_auth_user: Cumasaigh Fíordheimhniú Comhartha Ríomhphoist don Úsáideoir enable_user: Cumasaigh Úsáideoir memorialize_account: Cuntas Cuimhneacháin @@ -256,6 +260,7 @@ ga: create_domain_block_html: "%{name} fearann ​​bactha %{target}" create_email_domain_block_html: Chuir %{name} fearann ​​ríomhphoist bactha %{target} create_ip_block_html: Chruthaigh %{name} riail don IP %{target} + create_relay_html: Chruthaigh %{name} athsheoladh %{target} create_unavailable_domain_html: Chuir %{name} deireadh leis an seachadadh chuig fearann ​​%{target} create_user_role_html: Chruthaigh %{name} %{target} ról demote_user_html: "%{name} úsáideoir scriosta %{target}" @@ -267,14 +272,17 @@ ga: destroy_email_domain_block_html: "%{name} fearann ​​ríomhphoist díchoiscthe %{target}" destroy_instance_html: Glanadh %{name} fearann ​​%{target} destroy_ip_block_html: "%{name} scriosta riail le haghaidh IP %{target}" + destroy_relay_html: Scrios %{name} an athsheoladh %{target} destroy_status_html: Bhain %{name} postáil le %{target} destroy_unavailable_domain_html: D'athchrom %{name} ar an seachadadh chuig fearann ​​%{target} destroy_user_role_html: Scrios %{name} ról %{target} disable_2fa_user_html: Dhíchumasaigh %{name} riachtanas dhá fhachtóir don úsáideoir %{target} disable_custom_emoji_html: Dhíchumasaigh %{name} emoji %{target} + disable_relay_html: Dhíchumasaigh %{name} an athsheoladh %{target} disable_sign_in_token_auth_user_html: Dhíchumasaigh %{name} fíordheimhniú comhartha ríomhphoist le haghaidh %{target} disable_user_html: "%{name} logáil isteach díchumasaithe d'úsáideoir %{target}" enable_custom_emoji_html: "%{name} emoji cumasaithe %{target}" + enable_relay_html: Chuir %{name} an sealaíocht %{target} ar chumas enable_sign_in_token_auth_user_html: Chuir %{name} fíordheimhniú comhartha ríomhphoist ar chumas %{target} enable_user_html: "%{name} logáil isteach cumasaithe don úsáideoir %{target}" memorialize_account_html: Rinne %{name} cuntas %{target} a iompú ina leathanach cuimhneacháin @@ -860,8 +868,10 @@ ga: back_to_account: Ar ais go leathanach cuntais back_to_report: Ar ais go leathanach tuairisce batch: + add_to_report: 'Cuir leis an tuairisc # %{id}' remove_from_report: Bain den tuairisc report: Tuairisc + contents: Ábhar deleted: Scriosta favourites: Toghanna history: Stair leagan @@ -870,13 +880,17 @@ ga: media: title: Meáin metadata: Meiteashonraí + no_history: Níl an postáil seo curtha in eagar no_status_selected: Níor athraíodh aon phostáil mar níor roghnaíodh ceann ar bith open: Oscail postáil original_status: Bunphostáil reblogs: Athbhlaganna + replied_to_html: D'fhreagair %{acct_link} status_changed: Athraíodh postáil - title: Poist chuntais + status_title: Postáil le @ %{name} + title: Postálacha cuntais - @%{name} trending: Ag treochtáil + view_publicly: Féach go poiblí visibility: Infheictheacht with_media: Le meáin strikes: diff --git a/config/locales/gd.yml b/config/locales/gd.yml index a05ce6ed3c..7581f6c856 100644 --- a/config/locales/gd.yml +++ b/config/locales/gd.yml @@ -193,6 +193,7 @@ gd: create_domain_block: Cruthaich bacadh àrainne create_email_domain_block: Cruthaich bacadh àrainne puist-d create_ip_block: Cruthaich riaghailt IP + create_relay: Cruthaich ath-sheachadan create_unavailable_domain: Cruthaich àrainn nach eil ri fhaighinn create_user_role: Cruthaich dreuchd demote_user: Ìslich an cleachdaiche @@ -204,14 +205,17 @@ gd: destroy_email_domain_block: Sguab às bacadh na h-àrainne puist-d destroy_instance: Purgaidich an àrainn destroy_ip_block: Sguab às an riaghailt IP + destroy_relay: Sguab às an t-ath-sheachadan destroy_status: Sguab às am post destroy_unavailable_domain: Sguab às àrainn nach eil ri fhaighinn destroy_user_role: Mill an dreuchd disable_2fa_user: Cuir an dearbhadh dà-cheumnach à comas disable_custom_emoji: Cuir an t-Emoji gnàthaichte à comas + disable_relay: Cuir an t-ath-sheachadan à comas disable_sign_in_token_auth_user: Cuir à comas dearbhadh le tòcan puist-d dhan chleachdaiche disable_user: Cuir an cleachdaiche à comas enable_custom_emoji: Cuir an t-Emoji gnàthaichte an comas + enable_relay: Cuir an ath-sheachadan an comas enable_sign_in_token_auth_user: Cuir an comas dearbhadh le tòcan puist-d dhan chleachdaiche enable_user: Cuir an cleachdaiche an comas memorialize_account: Dèan cuimhneachan dhen chunntas @@ -253,6 +257,7 @@ gd: create_domain_block_html: Bhac %{name} an àrainn %{target} create_email_domain_block_html: Bhac %{name} an àrainn puist-d %{target} create_ip_block_html: Chruthaich %{name} riaghailt dhan IP %{target} + create_relay_html: Chruthaich %{name} an t-ath-sheachadan %{target} create_unavailable_domain_html: Sguir %{name} ris an lìbhrigeadh dhan àrainn %{target} create_user_role_html: Chruthaich %{name} an dreuchd %{target} demote_user_html: Dh’ìslich %{name} an cleachdaiche %{target} @@ -262,16 +267,19 @@ 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_relay_html: Sguab %{name} às an t-ath-sheachadan %{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} destroy_user_role_html: Sguab %{name} às an dreuchd %{target} disable_2fa_user_html: Chuir %{name} riatanas an dearbhaidh dà-cheumnaich à comas dhan chleachdaiche %{target} disable_custom_emoji_html: Chuir %{name} an Emoji %{target} à comas + disable_relay_html: Chuir %{name} an t-ath-sheachadan %{target} à comas disable_sign_in_token_auth_user_html: Chuir %{name} à comas dearbhadh le tòcan puist-d dha %{target} disable_user_html: Chuir %{name} an clàradh a-steach à comas dhan chleachdaiche %{target} enable_custom_emoji_html: Chuir %{name} an Emoji %{target} an comas + enable_relay_html: Chuir %{name} an t-ath-sheachadan %{target} an comas enable_sign_in_token_auth_user_html: Chuir %{name} an comas dearbhadh le tòcan puist-d dha %{target} enable_user_html: Chuir %{name} an clàradh a-steach an comas dhan chleachdaiche %{target} memorialize_account_html: Rinn %{name} duilleag cuimhneachain dhen chunntas aig %{target} @@ -846,8 +854,10 @@ gd: back_to_account: Till gu duilleag a’ chunntais back_to_report: Till gu duilleag a’ ghearain batch: + add_to_report: 'Cuir ris a’ ghearan #%{id}' remove_from_report: Thoir air falbh on ghearan report: Gearan + contents: Susbaint deleted: Chaidh a sguabadh às favourites: Annsachdan history: Eachdraidh nan tionndadh @@ -856,13 +866,17 @@ gd: media: title: Meadhanan metadata: Meata-dàta + no_history: Cha deach am post seo a dheasachadh no_status_selected: Cha deach post sam bith atharrachadh o nach deach gin dhiubh a thaghadh open: Fosgail am post original_status: Am post tùsail reblogs: Brosnachaidhean + replied_to_html: Freagairt do %{acct_link} status_changed: Post air atharrachadh - title: Postaichean a’ chunntais + status_title: Post le @%{name} + title: Postaichean a’ chunntais – @%{name} trending: A’ treandadh + view_publicly: Seall gu poblach visibility: Faicsinneachd with_media: Le meadhanan riutha strikes: diff --git a/config/locales/gl.yml b/config/locales/gl.yml index a4f63a50e0..feda673621 100644 --- a/config/locales/gl.yml +++ b/config/locales/gl.yml @@ -187,6 +187,7 @@ gl: create_domain_block: Crear bloquedo do Dominio create_email_domain_block: Crear Bloqueo de Dominio do correo create_ip_block: Crear regra IP + create_relay: Crear Repetidor create_unavailable_domain: Crear dominio Non dispoñible create_user_role: Crear Rol demote_user: Degradar usuaria @@ -198,14 +199,17 @@ gl: destroy_email_domain_block: Eliminar bloqueo do dominio do correo destroy_instance: Purgar Dominio destroy_ip_block: Eliminar regra IP + destroy_relay: Eliminar Repetidor destroy_status: Eliminar publicación destroy_unavailable_domain: Eliminar dominio Non dispoñible destroy_user_role: Eliminar Rol disable_2fa_user: Desactivar 2FA disable_custom_emoji: Desactivar emoticona personalizada + disable_relay: Desactivar Repetidor disable_sign_in_token_auth_user: Desactivar Autenticación por Token no Correo para a Usuaria disable_user: Desactivar usuaria enable_custom_emoji: Activar emoticona personalizada + enable_relay: Activar Repetidor enable_sign_in_token_auth_user: Activar Autenticación con Token no Correo para a Usuaria enable_user: Activar usuaria memorialize_account: Transformar en conta conmemorativa @@ -247,6 +251,7 @@ gl: create_domain_block_html: "%{name} bloqueou o dominio %{target}" create_email_domain_block_html: "%{name} bloqueou o dominio de correo %{target}" create_ip_block_html: "%{name} creou regra para o IP %{target}" + create_relay_html: "%{name} creou un repetidor en %{target}" create_unavailable_domain_html: "%{name} deixou de interactuar co dominio %{target}" create_user_role_html: "%{name} creou o rol %{target}" demote_user_html: "%{name} degradou a usuaria %{target}" @@ -258,14 +263,17 @@ gl: destroy_email_domain_block_html: "%{name} desbloqueou o dominio de correo %{target}" destroy_instance_html: "%{name} purgou o dominio %{target}" destroy_ip_block_html: "%{name} eliminou a regra para o IP %{target}" + destroy_relay_html: "%{name} eliminou o repetidor %{target}" destroy_status_html: "%{name} eliminou a publicación de %{target}" destroy_unavailable_domain_html: "%{name} retomou a interacción co dominio %{target}" destroy_user_role_html: "%{name} eliminou o rol %{target}" disable_2fa_user_html: "%{name} desactivou o requerimento do segundo factor para a usuaria %{target}" disable_custom_emoji_html: "%{name} desactivou o emoji %{target}" + disable_relay_html: "%{name} desactivou o repetidor %{target}" disable_sign_in_token_auth_user_html: "%{name} desactivou a autenticación por token no email para %{target}" disable_user_html: "%{name} desactivou as credenciais para a usuaria %{target}" enable_custom_emoji_html: "%{name} activou o emoji %{target}" + enable_relay_html: "%{name} activou o repetidor %{target}" enable_sign_in_token_auth_user_html: "%{name} activou a autenticación con token no email para %{target}" enable_user_html: "%{name} activou as credenciais para a usuaria %{target}" memorialize_account_html: "%{name} convertiu a conta de %{target} nunha páxina para o recordo" @@ -818,8 +826,10 @@ gl: back_to_account: Volver a páxina da conta back_to_report: Volver a denuncias batch: + add_to_report: 'Engadir á denuncia #%{id}' remove_from_report: Eliminar da denuncia report: Denuncia + contents: Contidos deleted: Eliminado favourites: Favoritas history: Historial de versións @@ -828,13 +838,17 @@ gl: media: title: Medios metadata: Metadatos + no_history: Esta publicación foi editada no_status_selected: Non se cambiou ningunha publicación xa que ningunha foi seleccionada open: Abrir publicación original_status: Publicación orixinal reblogs: Promocións + replied_to_html: Respondeu a %{acct_link} status_changed: Publicación editada - title: Publicacións da conta + status_title: Publicación de @%{name} + title: Publicacións da conta - @%{name} trending: Popular + view_publicly: Ver publicamente visibility: Visibilidade with_media: con medios strikes: diff --git a/config/locales/he.yml b/config/locales/he.yml index 10b4611b9a..5243cf4768 100644 --- a/config/locales/he.yml +++ b/config/locales/he.yml @@ -193,6 +193,7 @@ he: create_domain_block: יצירת דומיין חסום create_email_domain_block: יצירת חסימת דומיין דוא"ל create_ip_block: יצירת כלל IP + create_relay: יצירת ממסר create_unavailable_domain: יצירת דומיין בלתי זמין create_user_role: יצירת תפקיד demote_user: הורדת משתמש בדרגה @@ -204,14 +205,17 @@ he: destroy_email_domain_block: מחיקת חסימת דומיין דוא"ל destroy_instance: טיהור דומיין destroy_ip_block: מחיקת כלל IP + destroy_relay: מחיקת ממסר destroy_status: מחיקת הודעה destroy_unavailable_domain: מחיקת דומיין בלתי זמין destroy_user_role: מחיקת תפקיד disable_2fa_user: השעיית זיהוי דו-גורמי disable_custom_emoji: השעיית אמוג'י מיוחד + disable_relay: השבתת ממסר disable_sign_in_token_auth_user: השעיית אסימון הזדהות בדוא"ל של משתמש disable_user: השעיית משתמש enable_custom_emoji: הפעלת אמוג'י מיוחד + enable_relay: החייאת ממסר enable_sign_in_token_auth_user: הפעלת אסימון הזדהות בדוא"ל של משתמש enable_user: אפשור משתמש memorialize_account: הנצחת חשבון @@ -253,6 +257,7 @@ he: create_domain_block_html: "%{name} חסם/ה את הדומיין %{target}" create_email_domain_block_html: '%{name} חסם/ה את דומיין הדוא"ל %{target}' create_ip_block_html: "%{name} יצר/ה כלל עבור IP %{target}" + create_relay_html: "%{name} יצרו את הממסר %{target}" create_unavailable_domain_html: "%{name} הפסיק/ה משלוח לדומיין %{target}" create_user_role_html: "%{name} יצר את התפקיד של %{target}" demote_user_html: "%{name} הוריד/ה בדרגה את המשתמש %{target}" @@ -264,14 +269,17 @@ he: destroy_email_domain_block_html: '%{name} הסיר/ה חסימה מדומיין הדוא"ל %{target}' destroy_instance_html: "%{name} טיהר/ה את הדומיין %{target}" destroy_ip_block_html: "%{name} מחק/ה את הכלל עבור IP %{target}" + destroy_relay_html: "%{name} מחקו את הממסר %{target}" destroy_status_html: ההודעה של %{target} הוסרה ע"י %{name} destroy_unavailable_domain_html: "%{name} התחיל/ה מחדש משלוח לדומיין %{target}" destroy_user_role_html: "%{name} ביטל את התפקיד של %{target}" disable_2fa_user_html: "%{name} ביטל/ה את הדרישה לאימות דו-גורמי למשתמש %{target}" disable_custom_emoji_html: "%{name} השבית/ה את האמוג'י %{target}" + disable_relay_html: "%{name} השביתו את הממסר %{target}" disable_sign_in_token_auth_user_html: '%{name} השבית/ה את האימות בעזרת אסימון דוא"ל עבור %{target}' disable_user_html: "%{name} חסם/ה כניסה מהמשתמש/ת %{target}" enable_custom_emoji_html: "%{name} אפשר/ה את האמוג'י %{target}" + enable_relay_html: "%{name} החיו את הממסר %{target}" enable_sign_in_token_auth_user_html: '%{name} אפשר/ה אימות בעזרת אסימון דוא"ל עבור %{target}' enable_user_html: "%{name} אפשר/ה כניסה עבור המשתמש %{target}" memorialize_account_html: "%{name} הפך/ה את חשבונו של %{target} לדף הנצחה" @@ -846,8 +854,10 @@ he: back_to_account: חזרה לדף החשבון back_to_report: חזרה לעמוד הדיווח batch: + add_to_report: להוסיף לדו"ח מספר %{id} remove_from_report: הסרה מהדיווח report: דווח + contents: תוכן deleted: מחוקים favourites: חיבובים history: היסטורית גרסאות @@ -856,13 +866,17 @@ he: media: title: מדיה metadata: נתוני-מטא + no_history: הודעה זו לא נערכה no_status_selected: לא בוצעו שינויים בהודעות שכן לא נבחרו כאלו open: פתח הודעה original_status: הודעה מקורית reblogs: שיתופים + replied_to_html: בתגובה לחשבון %{acct_link} status_changed: הודעה שונתה - title: הודעות החשבון + status_title: פרסום מאת @%{name} + title: פרסומי החשבון - @%{name} trending: נושאים חמים + view_publicly: צפיה בפומבי visibility: נראות with_media: עם מדיה strikes: diff --git a/config/locales/hu.yml b/config/locales/hu.yml index 47bd24fccf..f23711d403 100644 --- a/config/locales/hu.yml +++ b/config/locales/hu.yml @@ -187,6 +187,7 @@ hu: create_domain_block: Domain tiltás létrehozása create_email_domain_block: E-mail-domain-tiltás létrehozása create_ip_block: IP szabály létrehozása + create_relay: Továbbító létrehozása create_unavailable_domain: Elérhetetlen domain létrehozása create_user_role: Szerepkör létrehozása demote_user: Felhasználó lefokozása @@ -198,14 +199,17 @@ hu: destroy_email_domain_block: E-mail-domain-tiltás törlése destroy_instance: Domain végleges törlése destroy_ip_block: IP szabály törlése + destroy_relay: Továbbító törlése destroy_status: Bejegyzés törlése destroy_unavailable_domain: Elérhetetlen domain törlése destroy_user_role: Szerepkör eltávolítása disable_2fa_user: Kétlépcsős hitelesítés letiltása disable_custom_emoji: Egyéni emodzsi letiltása + disable_relay: Továbbító letiltása disable_sign_in_token_auth_user: A felhasználó tokenes e-mail-hitelesítésének letiltása disable_user: Felhasználói letiltása enable_custom_emoji: Egyéni emodzsi engedélyezése + enable_relay: Továbbító engedélyezése enable_sign_in_token_auth_user: A felhasználó tokenes e-mail-hitelesítésének engedélyezése enable_user: Felhasználó engedélyezése memorialize_account: Fiók emlékké nyilvánítása @@ -247,6 +251,7 @@ hu: create_domain_block_html: "%{name} letiltotta a %{target} domaint" create_email_domain_block_html: "%{name} letiltotta a(z) %{target} e-mail-domaint" create_ip_block_html: "%{name} létrehozta a(z) %{target} IP-címre vonatkozó szabályt" + create_relay_html: "%{name} létrehozta az átirányítót: %{target}" create_unavailable_domain_html: "%{name} leállította a kézbesítést a %{target} domainbe" create_user_role_html: "%{name} létrehozta a(z) %{target} szerepkört" demote_user_html: "%{name} lefokozta %{target} felhasználót" @@ -258,14 +263,17 @@ hu: destroy_email_domain_block_html: "%{name} engedélyezte a(z) %{target} e-mail-domaint" destroy_instance_html: "%{name} véglegesen törölte a(z) %{target} domaint" destroy_ip_block_html: "%{name} törölte a(z) %{target} IP-címre vonatkozó szabályt" + destroy_relay_html: "%{name} törölte az átirányítót: %{target}" destroy_status_html: "%{name} eltávolította %{target} felhasználó bejegyzését" destroy_unavailable_domain_html: "%{name} újraindította a kézbesítést a %{target} domainbe" destroy_user_role_html: "%{name} törölte a(z) %{target} szerepkört" disable_2fa_user_html: "%{name} kikapcsolta a kétlépcsős hitelesítést %{target} felhasználó fiókján" disable_custom_emoji_html: "%{name} letiltotta az emodzsit: %{target}" + disable_relay_html: "%{name} letiltotta az átirányítót: %{target}" disable_sign_in_token_auth_user_html: "%{name} letiltotta a tokenes e-mail-hitelesítést %{target} felhasználóra" disable_user_html: "%{name} letiltotta %{target} felhasználó bejelentkezését" enable_custom_emoji_html: "%{name} engedélyezte az emodzsit: %{target}" + enable_relay_html: "%{name} engedélyezte az átirányítót: %{target}" enable_sign_in_token_auth_user_html: "%{name} engedélyezte a tokenes e-mail-hitelesítést %{target} felhasználóra" enable_user_html: "%{name} engedélyezte %{target} felhasználó bejelentkezését" memorialize_account_html: "%{name} emléket állított %{target} felhasználónak" @@ -571,21 +579,21 @@ hu: relationships: title: "%{acct} kapcsolatai" relays: - add_new: Új relé hozzáadása + add_new: Új továbbító hozzáadása delete: Törlés - description_html: A föderációs relé egy olyan köztes szerver, mely nagy mennyiségű nyilvános bejegyzést cserél az erre feliratkozó vagy erre publikáló szerverek között. Ezzel segíthetsz kis és közepes szervereknek tartalmat megtalálni a föderációban, mely egyébként csak akkor válna lehetővé, ha a saját felhasználóik más szervereken lévő fiókokat követnének. + description_html: A föderációs továbbító egy olyan köztes kiszolgáló, mely nagy mennyiségű nyilvános bejegyzést cserél az erre feliratkozó vagy erre publikáló kiszolgálók között. Ezzel segíthetsz kis és közepes kiszolgálóknak megtalálni a tartalmakat a föderációban, melyek egyébként csak akkor válnának lehetővé, ha a saját felhasználóik más kiszolgálókon lévő fiókokat követnének. disable: Kikapcsolás disabled: Kikapcsolva enable: Bekapcsolás - enable_hint: Ha bekapcsolod, a szerver minden nyilvános bejegyzésre feliratkozik ezen a relén, valamint az összes nyilvános bejegyzést elküldi ennek. + enable_hint: Ha bekapcsolod, a kiszolgáló minden nyilvános bejegyzésre feliratkozik ezen a továbbítón, valamint az összes nyilvános bejegyzést elküldi ennek. enabled: Bekapcsolva - inbox_url: Relé URL - pending: Várakozás a relé jóváhagyására + inbox_url: Továbbító URL + pending: Várakozás a továbbító jóváhagyására save_and_enable: Mentés és engedélyezés - setup: Relé kapcsolat felállítása - signatures_not_enabled: A relék nem fognak megfelelően működni, amíg a biztonságos mód vagy a korlátozott föderációs mód engedélyezett + setup: Továbbító kapcsolat felállítása + signatures_not_enabled: A továbbítók nem fognak megfelelően működni, amíg a biztonságos mód vagy a korlátozott föderációs mód engedélyezett status: Állapot - title: Relék + title: Továbbítók report_notes: created_msg: Bejelentési feljegyzés létrehozva! destroyed_msg: Bejelentési feljegyzés törölve! @@ -833,7 +841,6 @@ hu: original_status: Eredeti bejegyzés reblogs: Megosztások status_changed: A bejegyzés megváltozott - title: Fiók bejegyzései trending: Felkapott visibility: Láthatóság with_media: Médiával diff --git a/config/locales/hy.yml b/config/locales/hy.yml index 201922d102..3b4aaf3629 100644 --- a/config/locales/hy.yml +++ b/config/locales/hy.yml @@ -402,7 +402,6 @@ hy: deleted: Ջնջված է media: title: Մեդիա - title: Օգտատիրոջ գրառումները with_media: Մեդիայի հետ tags: review: Վերանայել գրառումը diff --git a/config/locales/ia.yml b/config/locales/ia.yml index 843e8724b9..54401b1c5a 100644 --- a/config/locales/ia.yml +++ b/config/locales/ia.yml @@ -187,6 +187,7 @@ ia: create_domain_block: Crear blocada de dominio create_email_domain_block: Crear blocada de dominio de e-mail create_ip_block: Crear un regula IP + create_relay: Crear repetitor create_unavailable_domain: Crear dominio indisponibile create_user_role: Crear un rolo demote_user: Degradar usator @@ -198,14 +199,17 @@ ia: destroy_email_domain_block: Deler blocada de dominio de e-mail destroy_instance: Purgar dominio destroy_ip_block: Deler le regula IP + destroy_relay: Deler repetitor destroy_status: Deler message destroy_unavailable_domain: Deler dominio indisponibile destroy_user_role: Destruer rolo disable_2fa_user: Disactivar A2F disable_custom_emoji: Disactivar emoji personalisate + disable_relay: Disactivar repetitor disable_sign_in_token_auth_user: Disactivar le authentication per token de e-mail pro le usator disable_user: Disactivar le usator enable_custom_emoji: Activar emoji personalisate + enable_relay: Activar repetitor enable_sign_in_token_auth_user: Activar le authentication per token de e-mail pro le usator enable_user: Activar le usator memorialize_account: Converter conto in memorial @@ -247,6 +251,7 @@ ia: create_domain_block_html: "%{name} blocava dominio %{target}" create_email_domain_block_html: "%{name} blocava le dominio de e-mail %{target}" create_ip_block_html: "%{name} creava regula pro IP %{target}" + create_relay_html: "%{name} ha create un repetitor %{target}" create_unavailable_domain_html: "%{name} stoppava livration al dominio %{target}" create_user_role_html: "%{name} creava rolo de %{target}" demote_user_html: "%{name} degradava usator %{target}" @@ -258,14 +263,17 @@ ia: destroy_email_domain_block_html: "%{name} disblocava le dominio de e-mail %{target}" destroy_instance_html: "%{name} purgava le dominio %{target}" destroy_ip_block_html: "%{name} deleva le regula pro IP %{target}" + destroy_relay_html: "%{name} ha delite le repetitor %{target}" destroy_status_html: "%{name} removeva un message de %{target}" destroy_unavailable_domain_html: "%{name} reprendeva le livration al dominio %{target}" destroy_user_role_html: "%{name} deleva le rolo %{target}" disable_2fa_user_html: "%{name} disactivava le authentication a duo factores pro le usator %{target}" disable_custom_emoji_html: "%{name} disactivava le emoji %{target}" + disable_relay_html: "%{name} ha disactivate le repetitor %{target}" disable_sign_in_token_auth_user_html: "%{name} disactivava le authentication per token de e-mail pro %{target}" disable_user_html: "%{name} disactivava le apertura de session pro le usator %{target}" enable_custom_emoji_html: "%{name} activava le emoji %{target}" + enable_relay_html: "%{name} ha activate le repetitor %{target}" enable_sign_in_token_auth_user_html: "%{name} activava le authentication per token de e-mail pro %{target}" enable_user_html: "%{name} activava le apertura de session pro le usator %{target}" memorialize_account_html: "%{name} converteva le conto de %{target} in un pagina commemorative" @@ -818,8 +826,10 @@ ia: back_to_account: Retornar al pagina del conto back_to_report: Retro al pagina de reporto batch: + add_to_report: 'Adder al reporto #%{id}' remove_from_report: Remover del reporto report: Reporto + contents: Contento deleted: Delite favourites: Favorites history: Historia de versiones @@ -828,13 +838,17 @@ ia: media: title: Multimedia metadata: Metadatos + no_history: Iste message non ha essite modificate no_status_selected: Necun message ha essite cambiate perque necun ha essite seligite open: Aperir message original_status: Message original reblogs: Republicationes + replied_to_html: Respondite a %{acct_link} status_changed: Message cambiate - title: Messages del conto + status_title: Message de @%{name} + title: Messages del conto – @%{name} trending: Tendentias + view_publicly: Vider publicamente visibility: Visibilitate with_media: Con multimedia strikes: @@ -1118,7 +1132,7 @@ ia: migrate_account: Migrar a un altere conto migrate_account_html: Si tu vole rediriger iste conto a un altere, tu pote configurar lo hic. or_log_in_with: O aperi session con - privacy_policy_agreement_html: Io ha legite e accepta le politica de confidentialitate + privacy_policy_agreement_html: Io ha legite e accepta le politica de confidentialitate progress: confirm: Confirmar e-mail details: Tu detalios @@ -1166,8 +1180,11 @@ ia: use_security_key: Usar clave de securitate author_attribution: example_title: Texto de exemplo + hint_html: Scribe tu articulos de novas o de blog foras de Mastodon? Controla le maniera in que tu recipe attribution quando on los condivide sur Mastodon. + instructions: 'Assecura te que iste codice appare in le HTML de tu articulo:' more_from_html: Plus de %{name} s_blog: Blog de %{name} + then_instructions: Postea, adde le nomine de dominio del publication in le campo sequente. title: Attribution de autor challenge: confirm: Continuar diff --git a/config/locales/id.yml b/config/locales/id.yml index 6a005fddaa..34b690828d 100644 --- a/config/locales/id.yml +++ b/config/locales/id.yml @@ -711,7 +711,6 @@ id: original_status: Kiriman asli reblogs: Reblog status_changed: Kiriman diubah - title: Status akun trending: Sedang tren visibility: Visibilitas with_media: Dengan media diff --git a/config/locales/ie.yml b/config/locales/ie.yml index 94c4b7f4f0..f006f2c8ad 100644 --- a/config/locales/ie.yml +++ b/config/locales/ie.yml @@ -791,7 +791,6 @@ ie: original_status: Original posta reblogs: Boosts status_changed: Posta modificat - title: Postas del conto trending: Populari visibility: Visibilitá with_media: Con medie diff --git a/config/locales/ig.yml b/config/locales/ig.yml index 9db771fdcf..81d425916c 100644 --- a/config/locales/ig.yml +++ b/config/locales/ig.yml @@ -1,5 +1,28 @@ --- ig: + admin: + settings: + discovery: + profile_directory: Ndekọ profaịlụ + admin_mailer: + new_trends: + new_trending_statuses: + title: Edemede na-ewu ewu + application_mailer: + view_profile: Lelee profaịlụ filters: contexts: + account: Profaịlụ home: Ụlọ na ndepụta + edit: + title: Dezie myọ + index: + delete: Hichapụ + empty: Ị nweghi myọ ọbụla. + title: Myọ + settings: + edit_profile: Dezie profaịlụ gị + profile: Profaịlụ ọha + user_mailer: + welcome: + share_title: Kekọrịta profaịlụ Mastọdọnụ gị diff --git a/config/locales/io.yml b/config/locales/io.yml index 8ce5f3403b..83c92484ff 100644 --- a/config/locales/io.yml +++ b/config/locales/io.yml @@ -779,7 +779,6 @@ io: original_status: Originala posto reblogs: Dissemi status_changed: Posto chanjita - title: Kontoposti trending: Populara visibility: Videbleso with_media: Kun medii diff --git a/config/locales/is.yml b/config/locales/is.yml index c50b3dd20d..cad01257fd 100644 --- a/config/locales/is.yml +++ b/config/locales/is.yml @@ -187,6 +187,7 @@ is: create_domain_block: Búa til útilokun léns create_email_domain_block: Búa til útilokun tölvupóstléns create_ip_block: Búa til IP-reglu + create_relay: Búa til endurvarpa create_unavailable_domain: Útbúa lén sem ekki er tiltækt create_user_role: Útbúa hlutverk demote_user: Lækka notanda í tign @@ -198,14 +199,17 @@ is: destroy_email_domain_block: Eyða útilokun tölvupóstléns destroy_instance: Henda léni destroy_ip_block: Eyða IP-reglu + destroy_relay: Eyða endurvarpa destroy_status: Eyða færslu destroy_unavailable_domain: Eyða léni sem ekki er tiltækt destroy_user_role: Eyða hlutverki disable_2fa_user: Gera tveggja-þátta auðkenningu óvirka disable_custom_emoji: Gera sérsniðið tjáningartákn óvirkt + disable_relay: Gera endurvarpa óvirkan disable_sign_in_token_auth_user: Gera óvirka auðkenningu með teikni í tölvupósti fyrir notandann disable_user: Gera notanda óvirkan enable_custom_emoji: Virkja sérsniðið tjáningartákn + enable_relay: Virkja endurvarpa enable_sign_in_token_auth_user: Gera virka auðkenningu með teikni í tölvupósti fyrir notandann enable_user: Virkja notanda memorialize_account: Gera aðgang að minningargrein @@ -247,6 +251,7 @@ is: create_domain_block_html: "%{name} útilokaði lénið %{target}" create_email_domain_block_html: "%{name} útilokaði póstlénið %{target}" create_ip_block_html: "%{name} útbjó reglu fyrir IP-vistfangið %{target}" + create_relay_html: "%{name} bjó til endurvarpa %{target}" create_unavailable_domain_html: "%{name} stöðvaði afhendingu til lénsins %{target}" create_user_role_html: "%{name} útbjó %{target} hlutverk" demote_user_html: "%{name} lækkaði notandann %{target} í tign" @@ -258,14 +263,17 @@ is: destroy_email_domain_block_html: "%{name} aflétti útilokun af póstléninu %{target}" destroy_instance_html: "%{name} henti léninu %{target}" destroy_ip_block_html: "%{name} eyddi reglu fyrir IP-vistfangið %{target}" + destroy_relay_html: "%{name} eyddi endurvarpanum %{target}" destroy_status_html: "%{name} fjarlægði færslu frá %{target}" destroy_unavailable_domain_html: "%{name} hóf aftur afhendingu til lénsins %{target}" destroy_user_role_html: "%{name} eyddi hlutverki %{target}" disable_2fa_user_html: "%{name} gerði kröfu um tveggja-þátta innskráningu óvirka fyrir notandann %{target}" disable_custom_emoji_html: "%{name} gerði tjáningartáknið %{target} óvirkt" + disable_relay_html: "%{name} gerði endurvarpann %{target} óvirkan" disable_sign_in_token_auth_user_html: "%{name} gerði óvirka auðkenningu með teikni í tölvupósti fyrir %{target}" disable_user_html: "%{name} gerði innskráningu óvirka fyrir notandann %{target}" enable_custom_emoji_html: "%{name} gerði tjáningartáknið %{target} virkt" + enable_relay_html: "%{name} virkjaði endurvarpann %{target}" enable_sign_in_token_auth_user_html: "%{name} gerði virka auðkenningu með teikni í tölvupósti fyrir %{target}" enable_user_html: "%{name} gerði innskráningu virka fyrir notandann %{target}" memorialize_account_html: "%{name} breytti notandaaðgangnum %{target} í minningargreinarsíðu" @@ -820,8 +828,10 @@ is: back_to_account: Fara aftur á síðu notandaaðgangsins back_to_report: Til baka á kærusíðu batch: + add_to_report: 'Bæta við skýrslu #%{id}' remove_from_report: Fjarlægja úr kæru report: Kæra + contents: Efni deleted: Eytt favourites: Eftirlæti history: Útgáfuferill @@ -830,13 +840,17 @@ is: media: title: Myndefni metadata: Lýsigögn + no_history: Færslunni hefur ekki verið breytt no_status_selected: Engum færslum var breytt þar sem engar voru valdar open: Opna færslu original_status: Upprunaleg færsla reblogs: Endurbirtingar + replied_to_html: Svaraði til %{acct_link} status_changed: Færslu breytt - title: Færslur notandaaðgangs + status_title: Færsla frá @%{name} + title: Færslur notanda - @%{name} trending: Vinsælt + view_publicly: Skoða opinberlega visibility: Sýnileiki with_media: Með myndefni strikes: diff --git a/config/locales/it.yml b/config/locales/it.yml index e18cb0e8f6..3b36bd3f7a 100644 --- a/config/locales/it.yml +++ b/config/locales/it.yml @@ -187,6 +187,7 @@ it: create_domain_block: Crea Blocco del Dominio create_email_domain_block: Crea blocco del dominio e-mail create_ip_block: Crea regola IP + create_relay: Crea Relay create_unavailable_domain: Crea Dominio Non Disponibile create_user_role: Crea Ruolo demote_user: Retrocedi Utente @@ -198,14 +199,17 @@ it: destroy_email_domain_block: Elimina il blocco del dominio e-mail destroy_instance: Elimina Dominio destroy_ip_block: Elimina regola IP + destroy_relay: Elimina Relay destroy_status: Elimina Toot destroy_unavailable_domain: Elimina Dominio Non Disponibile destroy_user_role: Distruggi Ruolo disable_2fa_user: Disabilita A2F disable_custom_emoji: Disabilita Emoji Personalizzata + disable_relay: Disabilita Relay disable_sign_in_token_auth_user: Disabilita l'autenticazione del token e-mail per l'utente disable_user: Disabilita l'Utente enable_custom_emoji: Abilita Emoji Personalizzata + enable_relay: Abilita Relay enable_sign_in_token_auth_user: Abilita l'autenticazione del token e-mail per l'utente enable_user: Abilita l'Utente memorialize_account: Commemora Profilo @@ -247,6 +251,7 @@ it: create_domain_block_html: "%{name} ha bloccato il dominio %{target}" create_email_domain_block_html: "%{name} ha bloccato il dominio e-mail %{target}" create_ip_block_html: "%{name} ha creato una regola per l'IP %{target}" + create_relay_html: "%{name} ha creato un relay %{target}" create_unavailable_domain_html: "%{name} ha interrotto la consegna al dominio %{target}" create_user_role_html: "%{name} ha creato il ruolo %{target}" demote_user_html: "%{name} ha retrocesso l'utente %{target}" @@ -258,14 +263,17 @@ it: destroy_email_domain_block_html: "%{name} ha sbloccato il dominio e-mail %{target}" destroy_instance_html: "%{name} ha eliminato il dominio %{target}" destroy_ip_block_html: "%{name} ha eliminato la regola per l'IP %{target}" + destroy_relay_html: "%{name} ha eliminato il relay %{target}" destroy_status_html: "%{name} ha rimosso il toot di %{target}" destroy_unavailable_domain_html: "%{name} ha ripreso la consegna al dominio %{target}" destroy_user_role_html: "%{name} ha eliminato il ruolo %{target}" disable_2fa_user_html: "%{name} ha disabilitato l'autenticazione a due fattori per l'utente %{target}" disable_custom_emoji_html: "%{name} ha disabilitato emoji %{target}" + disable_relay_html: "%{name} ha disabilitato il relay %{target}" disable_sign_in_token_auth_user_html: "%{name} ha disabilitato l'autenticazione del token e-mail per %{target}" disable_user_html: "%{name} ha disabilitato l'accesso per l'utente %{target}" enable_custom_emoji_html: "%{name} ha abilitato l'emoji %{target}" + enable_relay_html: "%{name} ha abilitato il relay %{target}" enable_sign_in_token_auth_user_html: "%{name} ha abilitato l'autenticazione del token e-mail per %{target}" enable_user_html: "%{name} ha abilitato l'accesso per l'utente %{target}" memorialize_account_html: "%{name} ha trasformato il profilo di %{target} in una pagina commemorativa" @@ -818,8 +826,10 @@ it: back_to_account: Torna alla pagina dell'account back_to_report: Torna alla pagina del report batch: + add_to_report: 'Aggiungi alla segnalazione #%{id}' remove_from_report: Rimuovi dal report report: Rapporto + contents: Contenuti deleted: Cancellato favourites: Preferiti history: Cronologia delle versioni @@ -828,13 +838,17 @@ it: media: title: Media metadata: Metadati + no_history: Questo post non è stato modificato no_status_selected: Nessun status è stato modificato perché nessuno era stato selezionato open: Apri il post original_status: Post originale reblogs: Condivisioni + replied_to_html: Risposta a %{acct_link} status_changed: Post modificato - title: Gli status dell'account + status_title: Post di @%{name} + title: Post dell'account - @%{name} trending: Di tendenza + view_publicly: Visualizza pubblicamente visibility: Visibilità with_media: con media strikes: diff --git a/config/locales/ja.yml b/config/locales/ja.yml index a70ae680e4..810de2b227 100644 --- a/config/locales/ja.yml +++ b/config/locales/ja.yml @@ -184,6 +184,7 @@ ja: create_domain_block: ドメインブロックを作成 create_email_domain_block: メールドメインブロックを作成 create_ip_block: IPルールを作成 + create_relay: リレーの追加 create_unavailable_domain: 配送できないドメインを作成 create_user_role: ロールを作成 demote_user: ユーザーを降格 @@ -195,14 +196,17 @@ ja: destroy_email_domain_block: メールドメインブロックを削除 destroy_instance: ドメインをブロックする destroy_ip_block: IPルールを削除 + destroy_relay: リレーの削除 destroy_status: 投稿を削除 destroy_unavailable_domain: 配送できないドメインを削除 destroy_user_role: ロールを削除 disable_2fa_user: 二要素認証を無効化 disable_custom_emoji: カスタム絵文字を無効化 + disable_relay: リレーの無効化 disable_sign_in_token_auth_user: ユーザのメールトークン認証を無効化 disable_user: ユーザーを無効化 enable_custom_emoji: カスタム絵文字を有効化 + enable_relay: リレーの有効化 enable_sign_in_token_auth_user: ユーザのメールトークン認証を有効化 enable_user: ユーザーを有効化 memorialize_account: 追悼アカウント化 @@ -244,6 +248,7 @@ ja: create_domain_block_html: "%{name}さんがドメイン %{target}をブロックしました" create_email_domain_block_html: "%{name} さんがメールドメイン %{target} をブロックしました" create_ip_block_html: "%{name}さんがIP %{target}のルールを作成しました" + create_relay_html: "%{name} さんがリレー %{target} を追加しました" create_unavailable_domain_html: "%{name}がドメイン %{target}への配送を停止しました" create_user_role_html: "%{name}さんがロール『%{target}』を作成しました" demote_user_html: "%{name}さんが%{target}さんを降格しました" @@ -252,17 +257,20 @@ ja: 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_email_domain_block_html: "%{name} さんがメールドメイン %{target} のブロックを外しました" destroy_instance_html: "%{name}さんがドメイン %{target}をブロックしました" destroy_ip_block_html: "%{name}さんが IP %{target}のルールを削除しました" + destroy_relay_html: "%{name} さんがリレー %{target} を削除しました" destroy_status_html: "%{name}さんが%{target}さんの投稿を削除しました" destroy_unavailable_domain_html: "%{name}がドメイン %{target}への配送を再開しました" destroy_user_role_html: "%{name}さんがロール『%{target}』を削除しました" disable_2fa_user_html: "%{name}さんが%{target}さんの二要素認証を無効化しました" disable_custom_emoji_html: "%{name}さんがカスタム絵文字 %{target}を無効化しました" + disable_relay_html: "%{name} さんがリレー %{target} を無効にしました" disable_sign_in_token_auth_user_html: "%{name} が %{target} のメールトークン認証を無効化しました" disable_user_html: "%{name}さんが%{target}さんのログインを無効化しました" enable_custom_emoji_html: "%{name}さんがカスタム絵文字 %{target}を有効化しました" + enable_relay_html: "%{name} さんがリレー %{target} を有効にしました" enable_sign_in_token_auth_user_html: "%{name} が %{target} のメールトークン認証を有効化しました" enable_user_html: "%{name}さんが%{target}さんのログインを有効化しました" memorialize_account_html: "%{name}さんが%{target}さんを追悼アカウントページに登録しました" @@ -804,8 +812,10 @@ ja: back_to_account: アカウントページに戻る back_to_report: 通報ページに戻る batch: + add_to_report: 'レポート #%{id} に追加' remove_from_report: 通報から削除 report: 通報 + contents: 投稿内容 deleted: 削除済み favourites: お気に入り history: 更新履歴 @@ -814,13 +824,17 @@ ja: media: title: メディア metadata: メタデータ + no_history: この投稿は編集されていません no_status_selected: 何も選択されていないため、変更されていません open: 投稿を開く original_status: オリジナルの投稿 reblogs: ブースト + replied_to_html: "%{acct_link}さんへの返信" status_changed: 投稿を変更しました - title: 投稿一覧 + status_title: "@%{name} の投稿" + title: 投稿一覧 - @%{name} trending: トレンド + view_publicly: 元の投稿を開く visibility: 公開範囲 with_media: メディアあり strikes: diff --git a/config/locales/ka.yml b/config/locales/ka.yml index 2a0365fbf5..f3178be8d3 100644 --- a/config/locales/ka.yml +++ b/config/locales/ka.yml @@ -190,7 +190,6 @@ ka: media: title: მედია no_status_selected: სატუსები არ შეცვლილა, რადგან არცერთი არ მონიშნულა - title: ანგარიშის სტატუსები with_media: მედიით title: ადმინისტრაცია admin_mailer: diff --git a/config/locales/kab.yml b/config/locales/kab.yml index 993488f1fc..1f5c5ded79 100644 --- a/config/locales/kab.yml +++ b/config/locales/kab.yml @@ -419,7 +419,6 @@ kab: media: title: Amidya open: Ldi tasuffeɣt - title: Tisuffaɣ n umiḍan trending: Ayen mucaɛen visibility: Abani with_media: S umidya diff --git a/config/locales/kk.yml b/config/locales/kk.yml index 537104ba51..7ab33b3134 100644 --- a/config/locales/kk.yml +++ b/config/locales/kk.yml @@ -285,7 +285,6 @@ kk: media: title: Медиa no_status_selected: Бірде-бір статус өзгерген жоқ, себебі ештеңе таңдалмады - title: Аккаунт статустары with_media: Медиамен tags: review: Статусты көрсету diff --git a/config/locales/ko.yml b/config/locales/ko.yml index 6bff1703e6..3394433758 100644 --- a/config/locales/ko.yml +++ b/config/locales/ko.yml @@ -184,6 +184,7 @@ ko: create_domain_block: 도메인 차단 추가 create_email_domain_block: 이메일 도메인 차단 생성 create_ip_block: IP 규칙 만들기 + create_relay: 릴레이 생성 create_unavailable_domain: 사용 불가능한 도메인 생성 create_user_role: 역할 생성 demote_user: 사용자 강등 @@ -195,14 +196,17 @@ ko: destroy_email_domain_block: 이메일 도메인 차단 삭제 destroy_instance: 도메인 퍼지하기 destroy_ip_block: IP 규칙 삭제 + destroy_relay: 릴레이 삭제 destroy_status: 게시물 삭제 destroy_unavailable_domain: 사용 불가능한 도메인 제거 destroy_user_role: 역할 삭제 disable_2fa_user: 2단계 인증 비활성화 disable_custom_emoji: 커스텀 에모지 비활성화 + disable_relay: 릴레이 비활성화 disable_sign_in_token_auth_user: 사용자의 이메일 토큰 인증 비활성화 disable_user: 사용자 비활성화 enable_custom_emoji: 커스텀 에모지 활성화 + enable_relay: 릴레이 활성화 enable_sign_in_token_auth_user: 사용자의 이메일 토큰 인증 활성화 enable_user: 사용자 활성화 memorialize_account: 고인의 계정으로 전환 @@ -244,6 +248,7 @@ ko: create_domain_block_html: "%{name} 님이 도메인 %{target}를 차단했습니다" create_email_domain_block_html: "%{name} 님이 이메일 도메인 %{target}를 차단했습니다" create_ip_block_html: "%{name} 님이 IP 규칙 %{target}을 만들었습니다" + create_relay_html: "%{name} 님이 릴레이 %{target}를 생성했습니다" create_unavailable_domain_html: "%{name} 님이 도메인 %{target}에 대한 전달을 중지했습니다" create_user_role_html: "%{name} 님이 %{target} 역할을 생성했습니다" demote_user_html: "%{name} 님이 사용자 %{target} 님을 강등했습니다" @@ -255,14 +260,17 @@ ko: destroy_email_domain_block_html: "%{name} 님이 이메일 도메인 %{target}을 차단 해제하였습니다" destroy_instance_html: "%{name} 님이 도메인 %{target}를 제거했습니다" destroy_ip_block_html: "%{name} 님이 IP 규칙 %{target}을 삭제하였습니다" + destroy_relay_html: "%{name} 님이 릴레이 %{target}를 삭제했습니다" destroy_status_html: "%{name} 님이 %{target} 님의 게시물을 삭제했습니다" destroy_unavailable_domain_html: "%{name} 님이 도메인 %{target}에 대한 전달을 재개" destroy_user_role_html: "%{name} 님이 %{target} 역할을 삭제했습니다" disable_2fa_user_html: "%{name} 님이 사용자 %{target} 님의 2단계 인증을 비활성화 했습니다" disable_custom_emoji_html: "%{name} 님이 에모지 %{target}를 비활성화했습니다" + disable_relay_html: "%{name} 님이 릴레이 %{target}를 비활성화했습니다" disable_sign_in_token_auth_user_html: "%{name} 님이 %{target} 님의 이메일 토큰 인증을 비활성화했습니다" disable_user_html: "%{name} 님이 사용자 %{target}의 로그인을 비활성화했습니다" enable_custom_emoji_html: "%{name} 님이 에모지 %{target}를 활성화했습니다" + enable_relay_html: "%{name} 님이 릴레이 %{target}를 활성화했습니다" enable_sign_in_token_auth_user_html: "%{name} 님이 %{target} 님의 이메일 토큰 인증을 활성화했습니다" enable_user_html: "%{name} 님이 사용자 %{target}의 로그인을 활성화했습니다" memorialize_account_html: "%{name} 님이 %{target}의 계정을 고인의 계정 페이지로 전환했습니다" @@ -806,8 +814,10 @@ ko: back_to_account: 계정으로 돌아가기 back_to_report: 신고 페이지로 돌아가기 batch: + add_to_report: '신고 #%{id}에 추가' remove_from_report: 신고에서 제거 report: 신고 + contents: 내용 deleted: 삭제됨 favourites: 좋아요 history: 버전 이력 @@ -816,13 +826,17 @@ ko: media: title: 미디어 metadata: 메타데이터 + no_history: 이 게시물은 수정되지 않았습니다 no_status_selected: 아무 것도 선택 되지 않아 어떤 게시물도 바뀌지 않았습니다 open: 게시물 열기 original_status: 원본 게시물 reblogs: 리블로그 + replied_to_html: "%{acct_link} 님에게 답장" status_changed: 게시물 변경됨 - title: 계정 게시물 + status_title: "@%{name} 님의 게시물" + title: 계정 게시물 - @%{name} trending: 유행 중 + view_publicly: 공개시점으로 보기 visibility: 공개 설정 with_media: 미디어 있음 strikes: diff --git a/config/locales/ku.yml b/config/locales/ku.yml index ddd214441c..5337610992 100644 --- a/config/locales/ku.yml +++ b/config/locales/ku.yml @@ -720,7 +720,6 @@ ku: original_status: Şandiyê resen reblogs: Ji nû ve nivîsandin status_changed: Şandî hate guhertin - title: Şandiyên ajimêr trending: Rojev visibility: Xuyabarî with_media: Bi medya yê re diff --git a/config/locales/lad.yml b/config/locales/lad.yml index ad241856a4..2612ae2131 100644 --- a/config/locales/lad.yml +++ b/config/locales/lad.yml @@ -24,6 +24,7 @@ lad: admin: account_actions: action: Realiza aksion + already_silenced: Este kuento ya tiene sido limitado. already_suspended: Este kuento ya tiene sido suspendido. title: Modera %{acct} account_moderation_notes: @@ -638,6 +639,7 @@ lad: report: 'Raporta #%{id}' reported_account: Kuento raportado reported_by: Raportado por + reported_with_application: Raportado kon aplikasyon resolved: Rezolvido resolved_msg: Tienes rezolvido la denunsia djustamente! skip_to_actions: Va direktamente a las aksyones @@ -752,6 +754,7 @@ lad: desc_html: Esto se baza en eskriptos eksternos de hCaptcha, ke pueden ser una influensya negra a la sigurita i privasita. Ademas, esto puede rezultar en un proseso de enrejistrasyon signifikativamente manko aksesivle para algunas personas (espesyalmente diskapasitadas). Por estas razones, por favor, konsidera otras alternativas komo rejistrasyon por aprovasyon manuala o kon envitasyon. title: Solisita ke los muevos utilizadores rezolven un CAPTCHA para konfirmar su konto content_retention: + danger_zone: Zona de perikolo preamble: Kontrola komo el kontenido jenerado por el utilizador se magazina en Mastodon. title: Retensyon de kontenido default_noindex: @@ -822,7 +825,6 @@ lad: original_status: Publikasyon orijinala reblogs: Repartajasyones status_changed: Publikasyon trokada - title: Publikasyones del kuento trending: Trendes visibility: Vizivilita with_media: Kon multimedia @@ -882,9 +884,12 @@ lad: message_html: "Tu magazinaje de objektos es mal konfigurado. La privasita de tus utilizadores esta en riziko." tags: moderation: + not_trendable: No trendavle + not_usable: No uzavle pending_review: Revizion esta asperando reviewed: Revizado title: Estado + trendable: Trendavle unreviewed: No revizado usable: Uzavle name: Nombre @@ -959,6 +964,7 @@ lad: used_by_over_week: one: Uzada por una persona durante la ultima semana other: Uzada por %{count} personas durante la ultima semana + title: Rekomendasyones i trendes trending: En trend warning_presets: add_new: Adjusta muevo @@ -1138,7 +1144,9 @@ lad: too_fast: Formulario enviado demaziado rapido, aprovalo de muevo. use_security_key: Uza la yave de sigurita author_attribution: + example_title: Teksto de enshemplo more_from_html: Mas de %{name} + s_blog: Blog de %{name} challenge: confirm: Kontinua hint_html: "Konsejo: No retornaremos a demandarte por el kod durante la sigiente ora." diff --git a/config/locales/lt.yml b/config/locales/lt.yml index 8ba3bad070..65bd4456ae 100644 --- a/config/locales/lt.yml +++ b/config/locales/lt.yml @@ -185,6 +185,7 @@ lt: create_domain_allow: Kurti domeno leidimą create_domain_block: Kurti domeno bloką create_ip_block: Kurti IP taisyklę + create_relay: Kurti perdavimą create_unavailable_domain: Kurti nepasiekiamą domeną create_user_role: Kurti vaidmenį demote_user: Pažeminti naudotoją @@ -194,13 +195,16 @@ lt: destroy_domain_block: Ištrinti domeno bloką destroy_instance: Išvalyti domeną destroy_ip_block: Ištrinti IP taisyklę + destroy_relay: Ištrinti perdavimą destroy_status: Ištrinti įrašą destroy_unavailable_domain: Ištrinti nepasiekiamą domeną destroy_user_role: Sunaikinti vaidmenį disable_2fa_user: Išjungti 2FA disable_custom_emoji: Išjungti pasirinktinį jaustuką + disable_relay: Išjungti perdavimą disable_user: Išjungti naudotoją enable_custom_emoji: Įjungti pasirinktinį jaustuką + enable_relay: Įjungti perdavimą enable_user: Įjungti naudotoją memorialize_account: Memorializuoti paskyrą promote_user: Paaukštinti naudotoją @@ -237,6 +241,7 @@ lt: create_domain_allow_html: "%{name} leido federaciją su domenu %{target}" create_domain_block_html: "%{name} užblokavo domeną %{target}" create_ip_block_html: "%{name} sukūrė taisyklę IP %{target}" + create_relay_html: "%{name} sukūrė perdavimą %{target}" create_unavailable_domain_html: "%{name} sustabdė tiekimą į domeną %{target}" create_user_role_html: "%{name} sukūrė %{target} vaidmenį" demote_user_html: "%{name} pažemino naudotoją %{target}" @@ -246,13 +251,16 @@ lt: destroy_domain_block_html: "%{name} atblokavo domeną %{target}" destroy_instance_html: "%{name} išvalė domeną %{target}" destroy_ip_block_html: "%{name} ištrynė taisyklę IP %{target}" + destroy_relay_html: "%{name} ištrynė perdavimą %{target}" destroy_status_html: "%{name} pašalino įrašą %{target}" destroy_unavailable_domain_html: "%{name} pratęsė tiekimą į domeną %{target}" destroy_user_role_html: "%{name} ištrynė %{target} vaidmenį" disable_2fa_user_html: "%{name} išjungė dviejų veiksnių reikalavimą naudotojui %{target}" disable_custom_emoji_html: "%{name} išjungė jaustuką %{target}" + disable_relay_html: "%{name} išjungė perdavimą %{target}" disable_user_html: "%{name} išjungė prisijungimą naudotojui %{target}" enable_custom_emoji_html: "%{name} įjungė jaustuką %{target}" + enable_relay_html: "%{name} įjungė perdavimą %{target}" enable_user_html: "%{name} įjungė prisijungimą naudotojui %{target}" memorialize_account_html: "%{name} pavertė %{target} paskyrą į atminimo puslapį" promote_user_html: "%{name} paaukštino naudotoją %{target}" @@ -581,7 +589,9 @@ lt: back_to_account: Grįžti į paskyros puslapį back_to_report: Grįžti į ataskaitos puslapį batch: + add_to_report: 'Pridėti į ataskaitą #%{id}' remove_from_report: Pašalinti iš ataskaitos + contents: Turinys deleted: Ištrinta favourites: Mėgstami history: Versijų istorija @@ -590,11 +600,15 @@ lt: media: title: Medija metadata: Metaduomenys + no_history: Šis įrašas nebuvo redaguotas no_status_selected: Jokie įrašai nebuvo pakeisti, nes nė vienas buvo pasirinktas open: Atidaryti įrašą original_status: Originalus įrašas - title: Paskyros statusai + replied_to_html: Atsakyta į %{acct_link} + status_title: Paskelbė @%{name} + title: Paskyros įrašai – @%{name} trending: Tendencinga + view_publicly: Peržiūrėti viešai with_media: Su medija system_checks: database_schema_check: diff --git a/config/locales/lv.yml b/config/locales/lv.yml index 9e95155110..3e44adbf46 100644 --- a/config/locales/lv.yml +++ b/config/locales/lv.yml @@ -293,7 +293,7 @@ lv: empty: Žurnāli nav atrasti. filter_by_action: Filtrēt pēc darbības filter_by_user: Filtrēt pēc lietotāja - title: Auditācijas pieraksti + title: Audita žurnāls unavailable_instance: "(domēna vārds nav pieejams)" announcements: destroyed_msg: Paziņojums ir veiksmīgi izdzēsts! @@ -447,6 +447,7 @@ lv: resolve: Atrisināt domēnu not_permitted: Nav atļauta resolved_through_html: Atrisināts, izmantojot %{domain} + title: Bloķētie e-pasta domēni export_domain_allows: new: title: Importēt domēnu atļaujas @@ -595,7 +596,7 @@ lv: one: "%{count} piezīme" other: "%{count} piezīmes" zero: "%{count} piezīmju" - action_log: Auditācijas pieraksti + action_log: Audita žurnāls action_taken_by: Veiktā darbība actions: delete_description_html: Raksti, par kurām ziņots, tiks dzēsti, un tiks reģistrēts brīdinājums, lai palīdzētu tev izvērst turpmākos pārkāpumus saistībā ar to pašu kontu. @@ -829,7 +830,7 @@ lv: original_status: Oriģinālā ziņa reblogs: Reblogi status_changed: Ziņa mainīta - title: Konta ziņas + status_title: Publicēja @%{name} trending: Aktuāli visibility: Redzamība with_media: Ar multividi @@ -872,6 +873,9 @@ lv: message_html: Tu neesi definējis nevienu servera nosacījumu. sidekiq_process_check: message_html: Rindā(s) %{value} nedarbojas neviens Sidekiq process. Lūdzu, pārskati savu Sidekiq konfigurāciju + software_version_check: + action: Skatīt pieejamos atjauninājumus + message_html: Pieejams Mastodon atjauninājums. software_version_critical_check: action: Skatīt pieejamos atjauninājumus message_html: Ir pieejams kritisks Mastodon atjauninājums. Lūdzu, atjaunini to pēc iespējas ātrāk. @@ -967,6 +971,7 @@ lv: one: Pēdējās nedēļas laikā izmantoja viens cilvēks other: Pēdējās nedēļas laikā izmantoja %{count} cilvēki zero: Pēdējās nedēļas laikā izmantoja %{count} cilvēku + title: Ieteikumi un pašlaik populāri trending: Populārākie warning_presets: add_new: Pievienot jaunu @@ -1129,7 +1134,7 @@ lv: title: Pārbaudi savu iesūtni sign_in: preamble_html: Jāpiesakās ar saviem %{domain} piekļuves datiem. Ja konts tiek mitināts citā serverī, šeit nevarēs pieteikties. - title: Pierakstīties %{domain} + title: Pieteikties %{domain} sign_up: manual_review: Reģistrācijas domēnā %{domain} manuāli pārbauda mūsu moderatori. Lai palīdzētu mums apstrādāt tavu reģistrāciju, uzraksti mazliet par sevi un to, kāpēc vēlies kontu %{domain}. preamble: Ar kontu šajā Mastodon serverī varēsi sekot jebkuram citam tīklā esošam cilvēkam neatkarīgi no tā, kur tiek mitināts viņa konts. @@ -1415,13 +1420,20 @@ lv: webauthn: drošības atslēgas description_html: Ja pamani darbības, kuras neatpazīsti, jāapsver iespēja nomainīt savu paroli un iespējot divpakāpju autentifikāciju. empty: Nav pieejama autentifikācijas vēsture - failed_sign_in_html: Neizdevies pierakstīšanās mēģinājums ar %{method} no %{ip} (%{browser}) - successful_sign_in_html: Veiksmīga pierakstīšanās ar %{method} no %{ip} (%{browser}) + failed_sign_in_html: Neizdevies pieteikšanās mēģinājums ar %{method} no %{ip} (%{browser}) + successful_sign_in_html: Veiksmīga pieteikšanās ar %{method} no %{ip} (%{browser}) title: Autentifikācijas vēsture mail_subscriptions: unsubscribe: action: Jā, atcelt abonēšanu complete: Anulēts + emails: + notification_emails: + favourite: izlases paziņojumu e-pasta ziņojumi + follow: sekošanas paziņojumu e-pasta ziņojumi + follow_request: sekošanas pieprasījumu e-pasta ziņojumi + mention: pieminēšanas paziņojumu e-pasta ziņojumi + reblog: pastiprinājumu paziņojumu e-pasta ziņojumi title: Atcelt abonēšanu media_attachments: validations: @@ -1653,6 +1665,7 @@ lv: delete: Konta dzēšana development: Izstrāde edit_profile: Labot profilu + export: Izgūt featured_tags: Piedāvātie tēmturi import: Imports import_and_export: Imports un eksports @@ -1668,6 +1681,8 @@ lv: webauthn_authentication: Drošības atslēgas severed_relationships: download: Lejupielādēt (%{count}) + event_type: + user_domain_block: Jūs bloķējāt %{target_name} lost_followers: Zaudētie sekotāji lost_follows: Zaudētie sekojumi type: Notikums @@ -1797,11 +1812,11 @@ lv: title: Arhīva līdzņemšana suspicious_sign_in: change_password: mainīt paroli - details: 'Šeit ir detalizēta informācija par pierakstīšanos:' - explanation: Esam konstatējuši pierakstīšanos tavā kontā no jaunas IP adreses. + details: 'Šeit ir pieteikšanās izvērsums:' + explanation: Esam noteikuši pieteikšanos Tavā kontā no jaunas IP adreses. further_actions_html: Ja tas nebiji tu, iesakām nekavējoties %{action} un iespējot divu faktoru autentifikāciju, lai tavs konts būtu drošībā. subject: Tavam kontam ir piekļūts no jaunas IP adreses - title: Jauna pierakstīšanās + title: Jauna pieteikšanās warning: appeal: Iesniegt apelāciju appeal_description: Ja uzskatāt, ka tā ir kļūda, varat iesniegt apelāciju %{instance} darbiniekiem. diff --git a/config/locales/ms.yml b/config/locales/ms.yml index 90493a30b6..948ad56a54 100644 --- a/config/locales/ms.yml +++ b/config/locales/ms.yml @@ -768,7 +768,6 @@ ms: original_status: Hantaran asal reblogs: Ulang siar status_changed: Hantaran diubah - title: Hantaran akaun trending: Sohor kini visibility: Visibiliti with_media: Dengan media diff --git a/config/locales/my.yml b/config/locales/my.yml index 6a330a16c7..4428843855 100644 --- a/config/locales/my.yml +++ b/config/locales/my.yml @@ -764,7 +764,6 @@ my: original_status: မူရင်းပို့စ် reblogs: Reblog များ status_changed: ပို့စ်ပြောင်းပြီးပါပြီ - title: အကောင့်ပို့စ်များ trending: လက်ရှိခေတ်စားနေခြင်း visibility: မြင်နိုင်မှု with_media: မီဒီယာနှင့်အတူ diff --git a/config/locales/nl.yml b/config/locales/nl.yml index 1af30bca98..048214eca3 100644 --- a/config/locales/nl.yml +++ b/config/locales/nl.yml @@ -818,8 +818,10 @@ nl: back_to_account: Terug naar accountpagina back_to_report: Terug naar de rapportage batch: + add_to_report: 'Toevoegen aan rapport #%{id}' remove_from_report: Uit de rapportage verwijderen report: Rapportage + contents: Inhoud deleted: Verwijderd favourites: Favorieten history: Versiegeschiedenis @@ -828,12 +830,14 @@ nl: media: title: Media metadata: Metagegevens + no_history: Dit bericht is niet bewerkt no_status_selected: Er werden geen berichten gewijzigd, omdat er geen enkele werd geselecteerd open: Bericht tonen original_status: Oorspronkelijk bericht reblogs: Boosts status_changed: Bericht veranderd - title: Berichten van account + status_title: Bericht van @%{name} + title: Accountberichten - @%{name} trending: Trending visibility: Zichtbaarheid with_media: Met media diff --git a/config/locales/nn.yml b/config/locales/nn.yml index 9ec4f29f42..dbb8b6c693 100644 --- a/config/locales/nn.yml +++ b/config/locales/nn.yml @@ -187,6 +187,7 @@ nn: create_domain_block: Opprett domene-blokk create_email_domain_block: Opprett blokkering av e-postdomene create_ip_block: Opprett IP-regel + create_relay: Opprett eit relé create_unavailable_domain: Opprett utilgjengeleg domene create_user_role: Opprett rolle demote_user: Degrader brukar @@ -198,14 +199,17 @@ nn: destroy_email_domain_block: Fjern blokkering av e-postdomene destroy_instance: Slett domene destroy_ip_block: Slett IP-regel + destroy_relay: Slett relé destroy_status: Slett status destroy_unavailable_domain: Slett utilgjengeleg domene destroy_user_role: Øydelegg rolle disable_2fa_user: Skruv av 2FA disable_custom_emoji: Skruv av tilpassa emoji + disable_relay: Skru av reléet disable_sign_in_token_auth_user: Slå av e-post-token-autentisering for brukar disable_user: Skruv av brukar enable_custom_emoji: Skruv på tilpassa emoji + enable_relay: Skru på reléet enable_sign_in_token_auth_user: Slå på e-post-token-autentisering for brukar enable_user: Skruv på brukar memorialize_account: Opprett minnekonto @@ -247,6 +251,7 @@ nn: create_domain_block_html: "%{name} blokkerte domenet %{target}" create_email_domain_block_html: "%{name} blokkerte e-postdomenet %{target}" create_ip_block_html: "%{name} oppretta ein regel for IP-en %{target}" + create_relay_html: "%{name} laga reléet %{target}" create_unavailable_domain_html: "%{name} stogga levering til domenet %{target}" create_user_role_html: "%{name} oppretta rolla %{target}" demote_user_html: "%{name} degraderte brukaren %{target}" @@ -258,14 +263,17 @@ nn: destroy_email_domain_block_html: "%{name} avblokkerte e-postdomenet %{target}" destroy_instance_html: "%{name} tømde domenet %{target}" destroy_ip_block_html: "%{name} sletta ein regel for IP-en %{target}" + destroy_relay_html: "%{name} sletta reléet %{target}" destroy_status_html: "%{name} fjerna innlegget frå %{target}" destroy_unavailable_domain_html: "%{name} tok opp att levering til domenet %{target}" destroy_user_role_html: "%{name} sletta rolla %{target}" disable_2fa_user_html: "%{name} tok vekk krav om tofaktorautentisering for brukaren %{target}" disable_custom_emoji_html: "%{name} deaktiverte emojien %{target}" + disable_relay_html: "%{name} skrudde av reléet %{target}" disable_sign_in_token_auth_user_html: "%{name} deaktiverte e-post-token-autentisering for %{target}" disable_user_html: "%{name} slo av innlogging for brukaren %{target}" enable_custom_emoji_html: "%{name} aktiverte emojien %{target}" + enable_relay_html: "%{name} skrudde på reléet %{target}" enable_sign_in_token_auth_user_html: "%{name} aktiverte e-post-token-autentisering for %{target}" enable_user_html: "%{name} aktiverte innlogging for brukaren %{target}" memorialize_account_html: "%{name} endret %{target}s konto til en minneside" @@ -818,8 +826,10 @@ nn: back_to_account: Tilbake til kontosida back_to_report: Attende til rapporteringssida batch: + add_to_report: 'Legg til rapport #%{id}' remove_from_report: Fjern fra rapport report: Rapport + contents: Innhald deleted: Sletta favourites: Favorittar history: Versjonshistorikk @@ -828,13 +838,17 @@ nn: media: title: Media metadata: Metadata + no_history: Dette innlegget har ikkje blitt redigert no_status_selected: Ingen statusar vart endra sidan ingen vart valde open: Opne innlegg original_status: Opprinnelig innlegg reblogs: Framhevingar + replied_to_html: Svarte %{acct_link} status_changed: Innlegg endret - title: Kontostatusar + status_title: Innlegg av @%{name} + title: Kontoinnlegg - @%{name} trending: Populært + view_publicly: Vis offentleg visibility: Synlighet with_media: Med media strikes: @@ -1381,6 +1395,9 @@ nn: 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. + lists_html: + one: Du er i ferd med å erstatta listene dine med innhaldet i %{filename}. Opptil %{count} konto vil bli lagt til i dei nye listene. + other: Du er i ferd med å erstatta listene dine med innhaldet i %{filename}. Opptil %{count} kontoar vil bli lagt til i dei nye listene. 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}. diff --git a/config/locales/no.yml b/config/locales/no.yml index 94986f4cae..8bf5daad0e 100644 --- a/config/locales/no.yml +++ b/config/locales/no.yml @@ -786,7 +786,6 @@ original_status: Opprinnelig innlegg reblogs: Fremheve status_changed: Innlegg endret - title: Kontostatuser trending: Populært visibility: Synlighet with_media: Med media diff --git a/config/locales/oc.yml b/config/locales/oc.yml index a30126c44b..5dec5ebb77 100644 --- a/config/locales/oc.yml +++ b/config/locales/oc.yml @@ -401,7 +401,6 @@ oc: media: title: Mèdia no_status_selected: Cap d’estatut pas cambiat estant que cap èra pas seleccionat - title: Estatuts del compte visibility: Visibilitat with_media: Amb mèdia system_checks: diff --git a/config/locales/pl.yml b/config/locales/pl.yml index d50a042a22..3592ea53f6 100644 --- a/config/locales/pl.yml +++ b/config/locales/pl.yml @@ -193,6 +193,7 @@ pl: create_domain_block: Utwórz blokadę domeny create_email_domain_block: Utwórz blokadę domeny e-mail create_ip_block: Utwórz regułę IP + create_relay: Utwórz przekaźnik create_unavailable_domain: Utwórz niedostępną domenę create_user_role: Utwórz rolę demote_user: Zdegraduj użytkownika @@ -204,14 +205,17 @@ pl: destroy_email_domain_block: Usuń blokadę domeny e-mail destroy_instance: Wyczyść domenę destroy_ip_block: Usuń regułę IP + destroy_relay: Usuń przekaźnik destroy_status: Usuń wpis destroy_unavailable_domain: Usuń niedostępną domenę destroy_user_role: Zlikwiduj rolę disable_2fa_user: Wyłącz 2FA disable_custom_emoji: Wyłącz niestandardowe emoji + disable_relay: Wyłącz przekaźnik disable_sign_in_token_auth_user: Wyłącz uwierzytelnianie tokenem przez e-mail dla użytkownika disable_user: Wyłącz użytkownika enable_custom_emoji: Włącz niestandardowe emoji + enable_relay: Włącz przekaźnik enable_sign_in_token_auth_user: Włącz uwierzytelnianie tokenem przez e-mail dla użytkownika enable_user: Włącz użytkownika memorialize_account: Upamiętnij konto @@ -253,6 +257,7 @@ pl: create_domain_block_html: "%{name} zablokował(a) domenę %{target}" create_email_domain_block_html: "%{name} dodał(a) domenę e-mail %{target} na czarną listę" create_ip_block_html: "%{name} stworzył(a) regułę dla IP %{target}" + create_relay_html: "%{name} utworzył przekaźnik %{target}" create_unavailable_domain_html: "%{name} przestał(a) doręczać na domenę %{target}" create_user_role_html: "%{name} utworzył rolę %{target}" demote_user_html: "%{name} zdegradował(a) użytkownika %{target}" @@ -264,14 +269,17 @@ pl: destroy_email_domain_block_html: "%{name} usunął(-ęła) domenę e-mail %{target} z czarnej listy" destroy_instance_html: "%{name} usunął domenę %{target}" destroy_ip_block_html: "%{name} usunął(-ęła) regułę dla IP %{target}" + destroy_relay_html: "%{name} usunął przekaźnik %{target}" destroy_status_html: "%{name} usunął(-ęła) wpis użytkownika %{target}" destroy_unavailable_domain_html: "%{name} wznowił(a) doręczanie do domeny %{target}" destroy_user_role_html: "%{name} usunął rolę %{target}" disable_2fa_user_html: "%{name} wyłączył(a) uwierzytelnianie dwuskładnikowe użytkownikowi %{target}" disable_custom_emoji_html: "%{name} wyłączył(a) emoji %{target}" + disable_relay_html: "%{name} wyłączył przekaźnik %{target}" disable_sign_in_token_auth_user_html: "%{name} wyłączył/a uwierzytelnianie tokenem przez e-mail dla %{target}" disable_user_html: "%{name} zablokował(a) możliwość logowania użytkownikowi %{target}" enable_custom_emoji_html: "%{name} włączył(a) emoji %{target}" + enable_relay_html: "%{name} włączył przekaźnik %{target}" enable_sign_in_token_auth_user_html: "%{name} włączył/a uwierzytelnianie tokenem przez e-mail dla %{target}" enable_user_html: "%{name} przywrócił(a) możliwość logowania użytkownikowi %{target}" memorialize_account_html: "%{name} nadał(a) kontu %{target} status in memoriam" @@ -846,8 +854,10 @@ pl: back_to_account: Wróć na konto back_to_report: Wróć do strony zgłoszenia batch: + add_to_report: 'Dodaj do raportu #%{id}' remove_from_report: Usuń ze zgłoszenia report: Zgłoszenie + contents: Zawartość deleted: Usunięto favourites: Ulubione history: Historia wersji @@ -856,13 +866,17 @@ pl: media: title: Multimedia metadata: Metadane + no_history: Ten wpis nie był edytowany no_status_selected: Żaden wpis nie został zmieniony, bo żaden nie został wybrany open: Otwarty post original_status: Oryginalny post reblogs: Podbicia + replied_to_html: Odpowiedziano na %{acct_link} status_changed: Post zmieniony - title: Wpisy konta + status_title: Wpis @%{name} + title: Wpisy konta - @%{name} trending: Popularne + view_publicly: Wyświetl publicznie visibility: Widoczność with_media: Z zawartością multimedialną strikes: diff --git a/config/locales/pt-BR.yml b/config/locales/pt-BR.yml index 8b2feb5193..537dee5f74 100644 --- a/config/locales/pt-BR.yml +++ b/config/locales/pt-BR.yml @@ -35,12 +35,12 @@ pt-BR: accounts: add_email_domain_block: Bloquear domínio de email approve: Aprovar - approved_msg: O registro de %{username} foi aprovado + approved_msg: Aprovado com sucesso o pedido de registro de %{username} are_you_sure: Você tem certeza? avatar: Imagem de perfil by_domain: Domínio change_email: - changed_msg: E-mail alterado! + changed_msg: E-mail alterado com sucesso! current_email: E-mail atual label: Alterar e-mail new_email: Novo e-mail @@ -187,6 +187,7 @@ pt-BR: create_domain_block: Bloquear domínio create_email_domain_block: Criar Bloqueio de Domínio de Email create_ip_block: Criar regra de IP + create_relay: Criar Retransmissão create_unavailable_domain: Criar domínio indisponível create_user_role: Criar cargo demote_user: Rebaixar usuário @@ -198,14 +199,17 @@ pt-BR: destroy_email_domain_block: Deletar bloqueio de domínio Email destroy_instance: Limpar domínio destroy_ip_block: Excluir regra de IP + destroy_relay: Excluir Retransmissão destroy_status: Excluir publicação destroy_unavailable_domain: Excluir domínio indisponível destroy_user_role: Destruir cargo disable_2fa_user: Desativar autenticação de dois fatores disable_custom_emoji: Desativar emoji personalizado + disable_relay: Desativar Retransmissão disable_sign_in_token_auth_user: Desativar autenticação via Token de Email para Usuário disable_user: Desativar usuário enable_custom_emoji: Ativar emoji personalizado + enable_relay: Ativar Retransmissão enable_sign_in_token_auth_user: Ativar autenticação via Token de Email para Usuário enable_user: Ativar usuário memorialize_account: Converter conta em memorial @@ -247,6 +251,7 @@ pt-BR: create_domain_block_html: "%{name} bloqueou o domínio %{target}" create_email_domain_block_html: "%{name} bloqueou o domínio de e-mail %{target}" create_ip_block_html: "%{name} criou a regra para o IP %{target}" + create_relay_html: "%{name} criou uma retransmissão %{target}" create_unavailable_domain_html: "%{name} parou a entrega ao domínio %{target}" create_user_role_html: "%{name} criou o cargo %{target}" demote_user_html: "%{name} rebaixou o usuário %{target}" @@ -258,14 +263,17 @@ pt-BR: destroy_email_domain_block_html: "%{name} desbloqueou o domínio de e-mail %{target}" destroy_instance_html: "%{name} limpou o domínio %{target}" destroy_ip_block_html: "%{name} excluiu a regra para o IP %{target}" + destroy_relay_html: "%{name} excluiu uma retransmissão %{target}" destroy_status_html: "%{name} removeu a publicação de %{target}" destroy_unavailable_domain_html: "%{name} retomou a entrega ao domínio %{target}" destroy_user_role_html: "%{name} excluiu o cargo %{target}" disable_2fa_user_html: "%{name} desativou a exigência da autenticação de dois fatores para o usuário %{target}" disable_custom_emoji_html: "%{name} desativou o emoji %{target}" + disable_relay_html: "%{name} desativou uma retransmissão %{target}" disable_sign_in_token_auth_user_html: "%{name} desativou a autenticação via token por e-mail para %{target}" disable_user_html: "%{name} desativou o login para %{target}" enable_custom_emoji_html: "%{name} ativou o emoji %{target}" + enable_relay_html: "%{name} ativou uma retransmissão %{target}" enable_sign_in_token_auth_user_html: "%{name} ativou a autenticação via token por e-mail para %{target}" enable_user_html: "%{name} ativou o login para %{target}" memorialize_account_html: "%{name} transformou a conta de %{target} em um memorial" @@ -818,8 +826,10 @@ pt-BR: back_to_account: Voltar para página da conta back_to_report: Voltar às denúncias batch: + add_to_report: 'Adicionar à denúncia #%{id}' remove_from_report: Remover da denúncia report: Denunciar + contents: Conteúdos deleted: Excluídos favourites: Favoritos history: Histórico de versões @@ -828,13 +838,17 @@ pt-BR: media: title: Mídia metadata: Metadados + no_history: Esta publicação não foi editada no_status_selected: Nenhuma publicação foi modificada porque nenhuma estava selecionada open: Publicação aberta original_status: Publicação original reblogs: Reblogs + replied_to_html: Respondeu à %{acct_link} status_changed: Publicação alterada - title: Publicações da conta + status_title: Publicação de @%{name} + title: Publicações da conta - @%{name} trending: Em alta + view_publicly: Ver publicamente visibility: Visibilidade with_media: Com mídia strikes: @@ -1368,6 +1382,17 @@ pt-BR: merge_long: Manter os registros existentes e adicionar novos overwrite: Sobrescrever overwrite_long: Substituir os registros atuais com os novos + overwrite_preambles: + blocking_html: + one: Você está prestes a trocar seu bloco de listas com mais de %{count} conta de %{filename}. + other: Você está prestes a substituir sua lista de blocos com mais de %{count} contas de %{filename}. + bookmarks_html: + one: Você está prestes a substituir seus salvos por até %{count} publicação de %{filename}. + other: Você está prestes a substituir seus salvos por até %{count} publicações de %{filename}. + preambles: + muting_html: + one: Você está prestes a silenciar %{count} conta de %{filename}. + other: Você está prestes a silenciar mais de %{count} contas de %{filename}. preface: Você pode importar dados que você exportou de outro servidor, como a lista de pessoas que você segue ou bloqueou. recent_imports: Importações recentes states: diff --git a/config/locales/pt-PT.yml b/config/locales/pt-PT.yml index 1761ec3f0c..cceceb0534 100644 --- a/config/locales/pt-PT.yml +++ b/config/locales/pt-PT.yml @@ -832,7 +832,6 @@ pt-PT: original_status: Publicação original reblogs: Re-publicacões status_changed: Publicação alterada - title: Estado das contas trending: Em tendência visibility: Visibilidade with_media: Com media diff --git a/config/locales/ru.yml b/config/locales/ru.yml index b7a10269fa..d9bf96c625 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} сняты успешно @@ -178,104 +179,112 @@ ru: whitelisted: В белом списке action_logs: action_types: - approve_appeal: Одобрить обжалование - approve_user: Утвердить + approve_appeal: Одобрение обжалований + approve_user: Утверждение регистраций assigned_to_self_report: Присвоение жалоб - change_email_user: Сменить e-mail для пользователя - change_role_user: Изменить роль пользователя + change_email_user: Смена e-mail пользователей + change_role_user: Смена ролей пользователей confirm_user: Подтверждение пользователей create_account_warning: Выдача предупреждения create_announcement: Создание объявлений - create_canonical_email_block: Создать блок электронной почты + create_canonical_email_block: Создание блокировок e-mail create_custom_emoji: Добавление эмодзи create_domain_allow: Разрешение доменов create_domain_block: Блокировка доменов - create_email_domain_block: Создать блок домена электронной почты + create_email_domain_block: Создание доменных блокировок e-mail create_ip_block: Создание правил для IP-адресов + create_relay: Создание ретранслятора create_unavailable_domain: Добавление домена в список недоступных - create_user_role: Создать роль + create_user_role: Создание ролей demote_user: Разжалование пользователей destroy_announcement: Удаление объявлений - destroy_canonical_email_block: Удалить блок электронной почты + destroy_canonical_email_block: Удаление блокировок e-mail destroy_custom_emoji: Удаление эмодзи destroy_domain_allow: Отзыв разрешений для доменов destroy_domain_block: Разблокировка доменов - destroy_email_domain_block: Удалить блок домена электронной почты + destroy_email_domain_block: Удаление доменных блокировок e-mail destroy_instance: Очистить домен destroy_ip_block: Удаление правил для IP-адресов + destroy_relay: Удаление ретранслятора destroy_status: Удаление постов destroy_unavailable_domain: Исключение доменов из списка недоступных - destroy_user_role: Удалить роль + destroy_user_role: Удаление ролей disable_2fa_user: Отключение 2FA disable_custom_emoji: Отключение эмодзи - disable_sign_in_token_auth_user: Отключить аутентификацию пользователя с помощью токена электронной почты + disable_relay: Отключение ретранслятора + disable_sign_in_token_auth_user: Отключение аутентификации по e-mail кодам disable_user: Заморозка пользователей enable_custom_emoji: Включение эмодзи - enable_sign_in_token_auth_user: Включить аутентификацию пользователя с помощью токена электронной почты + enable_relay: Включение ретранслятора + enable_sign_in_token_auth_user: Включение аутентификации по e-mail кодам enable_user: Разморозка пользователей memorialize_account: Присвоение пользователям статуса «мемориала» promote_user: Повышение пользователей - reject_appeal: Отклонить обжалование - reject_user: Отклонить + reject_appeal: Отклонение обжалований + reject_user: Отклонение регистраций remove_avatar_user: Удаление аватаров reopen_report: Возобновление жалоб - resend_user: Повторно отправить письмо с подтверждением + resend_user: Повторная отправка писем с подтверждением reset_password_user: Сброс пароля пользователей resolve_report: Отметка жалоб «решёнными» sensitive_account: Присвоение пользователям отметки «деликатного содержания» silence_account: Скрытие пользователей suspend_account: Блокировка пользователей unassigned_report: Снятие жалоб - unblock_email_account: Разблокировать e-mail адрес + unblock_email_account: Разблокировка e-mail адресов unsensitive_account: Снятие с пользователей отметки «деликатного содержания» unsilence_account: Отмена скрытия пользователей unsuspend_account: Разблокировка пользователей update_announcement: Обновление объявлений update_custom_emoji: Обновление эмодзи update_domain_block: Изменение блокировки домена - update_ip_block: Обновить правило для IP-адреса - update_report: Обновить рапорт + update_ip_block: Обновление правил для IP-адресов + update_report: Изменение жалоб update_status: Изменение постов - update_user_role: Обновить роль + update_user_role: Изменение ролей actions: - approve_appeal_html: "%{name} одобрил апелляцию на умеренное решение от %{target}" + 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} cменил(а) e-mail адрес пользователя %{target}" change_role_user_html: "%{name} изменил(а) роль %{target}" - confirm_user_html: "%{name} подтвержденный адрес электронной почты пользователя %{target}" + confirm_user_html: "%{name} подтвердил(а) e-mail адрес пользователя %{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} заблокировал(а) e-mail с хешем %{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} заблокировал(а) e-mail домен %{target}" create_ip_block_html: "%{name} создал(а) правило для IP %{target}" + create_relay_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_canonical_email_block_html: "%{name} снял(а) блокировку e-mail с хэшем %{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_email_domain_block_html: "%{name} снял(а) блокировку с e-mail домена %{target}" destroy_instance_html: "%{name} очистил(а) данные для домена %{target}" destroy_ip_block_html: "%{name} удалил(а) правило для IP %{target}" + destroy_relay_html: "%{name} удалил(а) ретранслятор %{target}" destroy_status_html: "%{name} удалил(а) пост пользователя %{target}" destroy_unavailable_domain_html: "%{name} возобновил доставку на узел %{target}" 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_relay_html: "%{name} отключил(а) ретранслятор %{target}" + disable_sign_in_token_auth_user_html: "%{name} отключил(а) аутентификацию по e-mail кодам для %{target}" disable_user_html: "%{name} заморозил(а) пользователя %{target}" enable_custom_emoji_html: "%{name} включил(а) эмодзи %{target}" - enable_sign_in_token_auth_user_html: "%{name} включил аутентификацию с помощью маркера электронной почты для %{target}" + enable_relay_html: "%{name} включил(а) ретранслятор %{target}" + enable_sign_in_token_auth_user_html: "%{name} включил(а) аутентификацию по e-mail кодам для %{target}" enable_user_html: "%{name} разморозил(а) пользователя %{target}" memorialize_account_html: "%{name} перевел(а) учётную запись пользователя %{target} в статус памятника" promote_user_html: "%{name} повысил(а) пользователя %{target}" - reject_appeal_html: "%{name} отклонил апелляцию на модерацию от %{target}" + reject_appeal_html: "%{name} отклонил(а) обжалование действий модерации от %{target}" reject_user_html: "%{name} отклонил(а) регистрацию %{target}" remove_avatar_user_html: "%{name} убрал(а) аватарку пользователя %{target}" reopen_report_html: "%{name} повторно открыл(а) жалобу %{target}" @@ -294,7 +303,7 @@ ru: 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: удалённая учётная запись @@ -462,6 +471,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 +635,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: Прикрепить ещё @@ -858,7 +869,6 @@ ru: original_status: Оригинальный пост reblogs: Продвинули status_changed: Пост изменен - title: Посты пользователя trending: Популярное visibility: Видимость with_media: С файлами @@ -902,6 +912,7 @@ ru: sidekiq_process_check: message_html: Ни один Sidekiq не запущен для %{value} очереди(-ей). Пожалуйста, просмотрите настройки Sidekiq software_version_check: + action: Посмотреть доступные обновления message_html: Доступно обновление для Mastodon. software_version_critical_check: action: Посмотреть доступные обновления @@ -1198,8 +1209,11 @@ ru: use_security_key: Использовать ключ безопасности author_attribution: example_title: Образец текста + hint_html: Публикуете ли вы свои статьи где-либо ещё кроме Mastodon? Если да, то ваше авторство может быть упомянуто, когда ими делятся в Mastodon. + instructions: 'Добавьте код ниже в HTML ваших статей:' more_from_html: Больше от %{name} s_blog: "%{name}'S Блог" + then_instructions: Затем добавьте доменное имя сайта, где вы публикуетесь, в поле ниже. title: Авторская атрибуция challenge: confirm: Продолжить @@ -1309,7 +1323,7 @@ ru: csv: CSV domain_blocks: Доменные блокировки lists: Списки - mutes: Ваши игнорируете + mutes: Ваши игнорируемые storage: Ваши файлы featured_tags: add_new: Добавить @@ -1411,6 +1425,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: @@ -1483,6 +1559,7 @@ ru: unsubscribe: action: Да, отписаться complete: Подписка отменена + confirmation_html: Вы точно желаете отписаться от всех уведомления типа «%{type}», доставляемых из сервера Mastodon %{domain} на ваш адрес электронной почты %{email}? Вы всегда сможете подписаться снова в настройках e-mail уведомлений. emails: notification_emails: favourite: любимые электронные письма с уведомлениями @@ -1728,6 +1805,7 @@ ru: delete: Удаление учётной записи development: Разработчикам edit_profile: Изменить профиль + export: Экспорт featured_tags: Избранные хэштеги import: Импорт import_and_export: Импорт и экспорт diff --git a/config/locales/sc.yml b/config/locales/sc.yml index 9ab62cea71..38ede0a72c 100644 --- a/config/locales/sc.yml +++ b/config/locales/sc.yml @@ -582,7 +582,6 @@ sc: open: Aberi sa publicatzione original_status: Publicatzione originale status_changed: Publicatzione modificada - title: Istados de su contu trending: Populares visibility: Visibilidade with_media: Cun elementos multimediales diff --git a/config/locales/sco.yml b/config/locales/sco.yml index 8cc733a4ac..ff3a730b17 100644 --- a/config/locales/sco.yml +++ b/config/locales/sco.yml @@ -713,7 +713,6 @@ sco: original_status: Original post reblogs: Reblogs status_changed: Post chynged - title: Accoont posts trending: Trendin visibility: Visibility with_media: Wi media diff --git a/config/locales/si.yml b/config/locales/si.yml index 270e0ae3fc..cd4abf6451 100644 --- a/config/locales/si.yml +++ b/config/locales/si.yml @@ -607,7 +607,6 @@ si: open: ලිපිය අරින්න original_status: මුල් ලිපිය status_changed: ලිපිය සංශෝධිතයි - title: ගිණුමේ ලිපි trending: නැගී එන with_media: මාධ්‍ය සමඟ strikes: diff --git a/config/locales/simple_form.ar.yml b/config/locales/simple_form.ar.yml index 0a665fb784..f5be51f9c3 100644 --- a/config/locales/simple_form.ar.yml +++ b/config/locales/simple_form.ar.yml @@ -9,7 +9,6 @@ ar: indexable: قد تظهر منشوراتك الموجهة للعامة في نتائج البحث على ماستدون. فالأشخاص الذين تفاعلوا مع منشوراتك قد يكون بمقدورهم البحث عنها بغظ النظر عن ذلك. note: 'يمكنك @ذكر أشخاص آخرين أو استعمال #الوسوم.' show_collections: سيستطيع الناس من تصفح متابعيك و متابعاتك. سيرى الأشخاص الذين تتبعهم أنك تتبعهم دون أي شك. - unlocked: سيتمكن الآخرون من متابعتك دون طلب الموافقة. قم بتعطيله إن كنت ترغب في مراجعة تلك الطلبات يدويا باختيار قبول أو رفض المتابعين الجدد. account_alias: acct: ادخِل عنون الحساب username@domain الذي تودّ مغادرته account_migration: diff --git a/config/locales/simple_form.ast.yml b/config/locales/simple_form.ast.yml index 00617c4e3c..997423449d 100644 --- a/config/locales/simple_form.ast.yml +++ b/config/locales/simple_form.ast.yml @@ -4,7 +4,6 @@ ast: hints: account: note: 'Pues @mentar a otros perfiles o poner #etiquetes.' - unlocked: Los perfiles van ser a siguite ensin solicitar la to aprobación. Desmarca esta opción si quies revisar les solicitúes de siguimientu y escoyer si aceptales o refugales. admin_account_action: text_html: Opcional. Pues usar la sintaxis de los artículos y amestar alvertencies preconfiguraes p'aforrar tiempu type_html: Escueyi qué facer con %{acct} diff --git a/config/locales/simple_form.be.yml b/config/locales/simple_form.be.yml index db6a94f8eb..d7be72b876 100644 --- a/config/locales/simple_form.be.yml +++ b/config/locales/simple_form.be.yml @@ -9,7 +9,6 @@ be: indexable: Вашыя публічныя допісы могуць з'яўляцца ў рэзультатах пошуку Mastodon. Людзі, якія ўзаемадзейнічалі з вашымі допісамі, усё роўна маюць магчымасць іх знаходзіць. note: 'Вы можаце @згадаць іншых людзей або выкарыстоўваць #хэштэгі.' show_collections: Людзі змогуць праглядаць спіс вашых падпісак і падпісчыкаў. Людзі, на якіх вы падпісаны ў любым выпадку будуць бачыць, што вы іх чытаеце. - unlocked: Людзі змогуць сачыць за вамі, не запытваючы пацвярджэння. Зніміце сцяжок, калі вы хочаце праглядаць запыты на падпіску і выбіраць, прымаць ці адхіляць новых падпісчыкаў. account_alias: acct: Прызначце карыстальнік@дамен уліковага запісу з якога вы хочаце пераехаць account_migration: diff --git a/config/locales/simple_form.bg.yml b/config/locales/simple_form.bg.yml index 2690f07141..17b7bd6239 100644 --- a/config/locales/simple_form.bg.yml +++ b/config/locales/simple_form.bg.yml @@ -3,13 +3,14 @@ bg: simple_form: hints: account: + attribution_domains_as_text: Едно на ред. Защитава от фалшиви атрибути. discoverable: Вашите публични публикации и профил може да се представят или препоръчват в различни области на Mastodon и вашия профил може да се предлага на други потребители. display_name: Вашето пълно име или псевдоним. fields: Вашата начална страница, местоимения, години, всичко що искате. indexable: Вашите обществени публикации може да се появят в резултатите от търсене в Mastodon. Взаимодействалите с публикациите ви може да ги търсят независимо. note: 'Може да @споменавате други хора или #хаштагове.' show_collections: Хората ще може да разглеждат през вашите последвания и последователи. Хората, които сте следвали, ще видят, че ги следвате независимо от това. - unlocked: Хората ще могат да ви последват без изискване на одобрение. Размаркирайте, ако искате да преглеждате заявките за последване и изберете дали да приемете или отхвърлите новите последователи. + unlocked: Хората ще могат да ви последват без изискване на одобрение. Размаркирайте, ако искате да преглеждате заявките за последване и избирате дали да приемете или отхвърлите новите последователи. account_alias: acct: Посочете потребителско_име@домейн на акаунта си, от който искате да се преместите account_migration: @@ -143,6 +144,7 @@ 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 c628bebaad..defb13325b 100644 --- a/config/locales/simple_form.ca.yml +++ b/config/locales/simple_form.ca.yml @@ -9,7 +9,7 @@ ca: indexable: Els teus tuts públics poden aparèixer en els resultats de cerca de Mastodon. Les persones que han interaccionat amb el teus tuts seran sempre capaços de cercar-los. note: 'Pots @mencionar altra gent o #etiquetes.' show_collections: La gent podrà navegar pels teus seguits i seguidors. Qui segueixis sí que veurà que els segueixes. - unlocked: La gent serà capaç de seguir-te sense sol·licitar-ho. Desmarca si vols revisar les sol·licituds i triar si acceptes o no els nous seguidors. + unlocked: Us podran seguir sense la vostra aprovació. Desmarqueu si voleu moderar les peticions de seguiment i decidir quines autoritzeu o denegueu. account_alias: acct: Especifica l'usuari@domini del compte des d'on et vols traslladar account_migration: diff --git a/config/locales/simple_form.cs.yml b/config/locales/simple_form.cs.yml index 6242b1ca6e..ef82b3232a 100644 --- a/config/locales/simple_form.cs.yml +++ b/config/locales/simple_form.cs.yml @@ -9,7 +9,6 @@ cs: indexable: Vaše veřejné příspěvky se mohou objevit ve výsledcích vyhledávání na Mastodonu. Lidé, kteří s vašimi příspěvky interagovaly, je mohou stále vyhledávat. note: 'Můžete @zmínit jiné osoby nebo #hashtagy.' show_collections: Lidé budou moci procházet skrz sledující. Lidé, které sledujete, uvidí, že je sledujete bezohledně. - unlocked: Lidé vás budou moci sledovat, aniž by vás žádali o schválení. Zrušte zaškrtnutí, pokud chcete zkontrolovat požadavky a zvolte, zda přijmete nebo odmítněte nové následovníky. account_alias: acct: Zadejte svůj účet, ze kterého se chcete přesunout jinam, ve formátu přezdívka@doména account_migration: diff --git a/config/locales/simple_form.cy.yml b/config/locales/simple_form.cy.yml index dedd50504b..6c21683b07 100644 --- a/config/locales/simple_form.cy.yml +++ b/config/locales/simple_form.cy.yml @@ -3,14 +3,14 @@ cy: simple_form: hints: account: - attribution_domains_as_text: Un i bob llinell. Yn amddiffyn rhag cydnabyddiaethau ffug. + attribution_domains_as_text: Un i bob llinell. Yn amddiffyn rhag priodoli 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. indexable: Mae'n bosib y bydd eich postiadau cyhoeddus yn ymddangos yng nghanlyniadau chwilio ar Mastodon. Mae'n bosibl y bydd pobl sydd wedi rhyngweithio â'ch postiadau yn dal i allu eu chwilio. note: 'Gallwch @grybwyll pobl eraill neu #hashnodau.' show_collections: Bydd pobl yn gallu pori trwy'r rhai rydych yn eu dilyn a'ch dilynwyr. Bydd y bobl rydych chi'n eu dilyn yn gweld eich bod chi'n eu dilyn beth bynnag. - unlocked: Bydd pobl yn gallu eich dilyn heb ofyn am ganiatâd. Dad-diciwch os ydych am adolygu ceisiadau dilyn a dewis a ydych am dderbyn neu wrthod dilynwyr newydd. + unlocked: Bydd pobl yn gallu eich dilyn heb ofyn am gymeradwyaeth. Dad-diciwch os ydych am adolygu ceisiadau i'ch dilyn a dewis a ydych am dderbyn neu wrthod dilynwyr newydd. account_alias: acct: Rhowch enwdefnyddiwr@parth y cyfrif y hoffech chi symud ohono account_migration: diff --git a/config/locales/simple_form.da.yml b/config/locales/simple_form.da.yml index 25cf670ea9..32e8e90b85 100644 --- a/config/locales/simple_form.da.yml +++ b/config/locales/simple_form.da.yml @@ -10,7 +10,7 @@ da: indexable: Dine offentlige indlæg vil kunne vises i Mastodon-søgeresultater. Folk, som har interageret med dem, vil kunne finde dem uanset. note: 'Du kan @omtale andre personer eller #hashtags.' show_collections: Folk vil ikke kunne tjekke dine Følger og Følgere. Folk, du selv følger, vil stadig kunne se dette. - unlocked: Folk vil kunne følge dig uden krav om godkendelse. Fjern markeringen, såfremt du ønsker at tjekke Følg-anmodninger og individuelt acceptere eller afvise nye Følgere. + unlocked: Man vil kunne følges af folk uden først at godkende dem. Ønsker man at gennemgå Følg-anmodninger og individuelt acceptere/afvise nye følgere, så fjern markeringen. account_alias: acct: Angiv brugernavn@domain for den konto, hvorfra du vil flytte account_migration: diff --git a/config/locales/simple_form.el.yml b/config/locales/simple_form.el.yml index 9dcac5c160..a04db4b228 100644 --- a/config/locales/simple_form.el.yml +++ b/config/locales/simple_form.el.yml @@ -9,7 +9,6 @@ el: indexable: Οι δημόσιες δημοσιεύσεις σου μπορεί να εμφανιστούν στα αποτελέσματα αναζήτησης στο Mastodon. Άτομα που έχουν αλληλεπιδράσει με τις δημοσιεύσεις σου μπορεί να είναι σε θέση να τις αναζητήσουν όπως και να 'χει. note: 'Μπορείς να @επισημάνεις άλλα άτομα ή #ετικέτες.' show_collections: Οι χρήστες θα είναι σε θέση να περιηγηθούν στα άτομα που ακολουθείς και στους ακόλουθούς σου. Άτομα που ακολουθείς θα βλέπουν ότι τους ακολουθείς όπως και να 'χει. - unlocked: Οι χρήστες θα είναι σε θέση να σε ακολουθήσουν χωρίς να ζητούν έγκριση. Κατάργησε την επιλογή αν θες να αξιολογείς τα αιτήματα ακολούθησης και να επιλέξεις αν θα αποδεχθείς ή απορρίψεις νέους ακόλουθους. account_alias: acct: Όρισε το username@domain του λογαριασμού από τον οποίο θέλεις να μετακινηθείς account_migration: diff --git a/config/locales/simple_form.en-GB.yml b/config/locales/simple_form.en-GB.yml index e20249e6bc..ef252d8aeb 100644 --- a/config/locales/simple_form.en-GB.yml +++ b/config/locales/simple_form.en-GB.yml @@ -9,7 +9,6 @@ en-GB: indexable: Your public posts may appear in search results on Mastodon. People who have interacted with your posts may be able to search them regardless. note: 'You can @mention other people or #hashtags.' show_collections: People will be able to browse through your follows and followers. People that you follow will see that you follow them regardless. - unlocked: People will be able to follow you without requesting approval. Uncheck if you want to review follow requests and chose whether to accept or reject new followers. account_alias: acct: Specify the username@domain of the account you want to move from account_migration: diff --git a/config/locales/simple_form.en.yml b/config/locales/simple_form.en.yml index 25de9f5910..f451c780b0 100644 --- a/config/locales/simple_form.en.yml +++ b/config/locales/simple_form.en.yml @@ -10,7 +10,7 @@ en: indexable: Your public posts may appear in search results on Mastodon. People who have interacted with your posts may be able to search them regardless. note: 'You can @mention other people or #hashtags.' show_collections: People will be able to browse through your follows and followers. People that you follow will see that you follow them regardless. - unlocked: People will be able to follow you without requesting approval. Uncheck if you want to review follow requests and chose whether to accept or reject new followers. + unlocked: People will be able to follow you without requesting approval. Uncheck if you want to review follow requests and choose whether to accept or reject new followers. account_alias: acct: Specify the username@domain of the account you want to move from account_migration: diff --git a/config/locales/simple_form.eo.yml b/config/locales/simple_form.eo.yml index f8a5776835..f39eb18f61 100644 --- a/config/locales/simple_form.eo.yml +++ b/config/locales/simple_form.eo.yml @@ -10,7 +10,7 @@ eo: indexable: Viaj publikaj afiŝoj povas aperi en serĉrezultoj ĉe Mastodon. Homoj, kiuj interagis kun viaj afiŝoj, eble povos serĉi ilin sendepende. note: 'Vi povas @mencii aliajn homojn aŭ #haŝetikedoj.' show_collections: Homoj povos foliumi viajn sekvatojn kaj sekvantojn. Homoj, kiujn vi sekvas, vidos, ke vi sekvas ilin ĉiaokaze. - unlocked: Homoj povos sekvi vin sen peto de aprobo. Malelektu se vi volas kontroli petojn de sekvado kaj elekti, ĉu akcepti aŭ malakcepti novajn sekvantojn. + unlocked: Homoj povos sekvi vin sen peti aprobon. Malmarku ĉu vi volas revizii sekvajn petojn kaj elektu ĉu akcepti aŭ malakcepti novajn sekvantojn. account_alias: acct: Specifu la uzantnomon@domajnon de la konto el kiu vi volas translokiĝi account_migration: diff --git a/config/locales/simple_form.es-AR.yml b/config/locales/simple_form.es-AR.yml index 98254c5e99..c3a65c0cc2 100644 --- a/config/locales/simple_form.es-AR.yml +++ b/config/locales/simple_form.es-AR.yml @@ -10,7 +10,7 @@ es-AR: indexable: Tus mensajes públicos pueden aparecer en los resultados de la búsqueda en Mastodon. La gente que interactuó con tus mensajes puede ser capaz de buscarlos sin importar el momento. note: 'Podés @mencionar otras cuentas o usar #etiquetas.' show_collections: La gente podrá navegar a través de tus seguidos y seguidores. Sin embargo, la gente que sigás, sabrá que lo estás haciendo. - unlocked: La gente podrá seguirte sin solicitar aprobación. Desmarcá si querés revisar las solicitudes de seguimiento y elegir si aceptar o rechazar nuevos seguidores. + unlocked: Las personas podrán seguirte sin solicitar aprobación. Desmarcá si querés revisar las solicitudes de seguimiento y elegir si querés aceptar o rechazar nuevos seguidores. account_alias: acct: Especificá el nombredeusuario@dominio de la cuenta desde la que querés mudarte account_migration: diff --git a/config/locales/simple_form.es-MX.yml b/config/locales/simple_form.es-MX.yml index 2b5d22aee8..3c340b3005 100644 --- a/config/locales/simple_form.es-MX.yml +++ b/config/locales/simple_form.es-MX.yml @@ -10,7 +10,7 @@ es-MX: indexable: Tus publicaciones públicas pueden aparecer en los resultados de búsqueda en Mastodon. Las personas que han interactuado con tus publicaciones pueden buscarlas en cualquier momento. note: 'Puedes @mencionar a otra gente o #hashtags.' show_collections: Las personas pueden navegar a través de tus seguidos y seguidores. Las personas que te siguen pueden ver que las sigues. - unlocked: Las personas pueden seguirte sin solicitar la aprobación. No lo selecciones si quieres revisar las solicitudes de seguimiento y elegir si aceptas o rechazas a nuevos seguidores. + unlocked: Las personas podrán seguirte sin solicitar aprobación. Desmarca si quieres revisar las solicitudes de seguimiento y elige si quieres aceptar o rechazar nuevos seguidores. account_alias: acct: Especifique el nombre de usuario@dominio de la cuenta desde la cual se desea migrar account_migration: diff --git a/config/locales/simple_form.es.yml b/config/locales/simple_form.es.yml index 8bc2c5f65c..a0338a3029 100644 --- a/config/locales/simple_form.es.yml +++ b/config/locales/simple_form.es.yml @@ -10,7 +10,7 @@ es: indexable: Tus publicaciones públicas pueden aparecer en los resultados de búsqueda en Mastodon. Las personas que han interactuado con tus publicaciones pueden ser capaces de buscarlas sin importar su visibilidad. note: Puedes mencionar a otras personas o etiquetas. show_collections: Las personas podrán navegar a través de tus seguidos y seguidores. Esto no impide que las personas que sigues sepan que las estás siguiendo. - unlocked: Las personas podrán seguirte sin pedir aprobación. Desmarca si deseas revisar las solicitudes de seguimiento y aceptar o rechazar nuevos seguidores. + unlocked: Las personas podrán seguirte sin solicitar aprobación. Desmarca si quieres revisar las solicitudes de seguimiento y elige si quieres aceptar o rechazar nuevos seguidores. account_alias: acct: Especifica el nombre_de_usuario@dominio de la cuenta desde donde deseas migrar account_migration: diff --git a/config/locales/simple_form.et.yml b/config/locales/simple_form.et.yml index a2ebf63b11..690661cd49 100644 --- a/config/locales/simple_form.et.yml +++ b/config/locales/simple_form.et.yml @@ -10,7 +10,6 @@ et: indexable: Sinu avalikud postitused võivad ilmuda Mastodoni otsingutulemustes. Inimesed, kes on sinu postitustele reageerinud, saavad neid otsida nii või naa. note: 'Saad @mainida teisi inimesi või #silte.' show_collections: Inimesed saavad sirvida su jälgijaid ja jälgitavaid. Inimesed, keda sa jälgid, näevad seda sõltumata häälestuse valikust. - unlocked: Inimesed saavad sind jälgima hakata kinnitamist taotlemata. Eemalda märge, kui soovid jälgimistaotlusi üle vaadata ja valida, kas nõustuda või keelduda uute jälgijatega. account_alias: acct: Sisesta konto kasutajanimi@domeen, mille soovid siia ümber kolida account_migration: diff --git a/config/locales/simple_form.eu.yml b/config/locales/simple_form.eu.yml index 7647e187ec..f6c4f14915 100644 --- a/config/locales/simple_form.eu.yml +++ b/config/locales/simple_form.eu.yml @@ -9,7 +9,6 @@ eu: indexable: Zure argitalpen publikoak bilaketa-emaitzetan ager daitezke Mastodonen. Zure argitalpenekin elkarregin duten jendeak ikusi ahal izango dituzte, hala ere. note: 'Beste pertsona edo #traola batzuk @aipatu ditzakezu.' show_collections: Pertsonek zuk jarraitzen dituzunak eta zure jarraitzaileak arakatu ahal izango dute. Jarraitzen dituzun pertsonak jarraitzen dituzula ikusi ahal izando dute, hala ere. - unlocked: Pertsonek zuri jarraitu ahal izango dizute onarpen-eskaerarik gabe. Desgaitu jarraipen-eskaerak berrikusi nahi badituzu eta hauek onartu edo ez erabaki nahi baduzu. account_alias: acct: Zehaztu migrazioaren jatorri den kontuaren erabiltzailea@domeinua account_migration: diff --git a/config/locales/simple_form.fa.yml b/config/locales/simple_form.fa.yml index f51a4ce8bf..9872de222f 100644 --- a/config/locales/simple_form.fa.yml +++ b/config/locales/simple_form.fa.yml @@ -10,7 +10,6 @@ fa: indexable: ممکن است فرسته‌های عمومیتان در نتیجه‌های جست‌وجوی ماستودون ظاهر شود. افرادی که با فرسته‌هایتان تعامل داشتند در هر صورت می‌توانند جست‌وجویشان کنند. note: 'می‌توانید افراد دیگر را @نام برده یا #برچسب بزنید.' show_collections: افراد خواهند توانست پی‌گیران و پی‌گرفته شده‌هایتان را مرور کنند. افرادی که پی‌می‌گیریدشان در هر صورت خواهند دید که پی‌می‌گیریدشان. - unlocked: افراد خواهند توانست بدون درخواست تأیید پی‌بگیرندتان. اگر می‌خواهید درخواست‌های پی‌گیری را بازبینی کرده و بگزینید که پی‌گیران جدید را بپذیرید یا رد کنید، علامت را بردارید. account_alias: acct: مشخّص کردن username@domain حسابی که می‌خواهید از آن منتقل شوید account_migration: diff --git a/config/locales/simple_form.fr-CA.yml b/config/locales/simple_form.fr-CA.yml index d2ce30ec8e..d38aeaa414 100644 --- a/config/locales/simple_form.fr-CA.yml +++ b/config/locales/simple_form.fr-CA.yml @@ -9,7 +9,6 @@ fr-CA: indexable: Vos messages publics peuvent apparaître dans les résultats de recherche sur Mastodon. Les personnes qui ont interagi avec vos messages peuvent les trouver dans une recherche quoi qu’il arrive. note: 'Vous pouvez @mentionner d’autres personnes ou des #hashtags.' show_collections: Les gens pourront voir les personnes que vous suivez ou qui vous suivent. Ceux que vous suivez verront que vous les suivez dans tous les cas. - unlocked: Les gens pourront vous suivre sans demander d'approbation. Décochez cette option si vous voulez valider les demandes d'abonnement et choisir d'accepter ou de rejeter les nouveaux abonnés. account_alias: acct: Spécifiez l’identifiant@domaine du compte que vous souhaitez faire migrer account_migration: diff --git a/config/locales/simple_form.fr.yml b/config/locales/simple_form.fr.yml index 626032600a..b601bf0b66 100644 --- a/config/locales/simple_form.fr.yml +++ b/config/locales/simple_form.fr.yml @@ -9,7 +9,6 @@ fr: indexable: Vos messages publics peuvent apparaître dans les résultats de recherche sur Mastodon. Les personnes qui ont interagi avec vos messages peuvent les trouver dans une recherche quoi qu’il arrive. note: 'Vous pouvez @mentionner d’autres personnes ou des #hashtags.' show_collections: Les gens pourront voir les personnes que vous suivez ou qui vous suivent. Ceux que vous suivez verront que vous les suivez dans tous les cas. - unlocked: Les gens pourront vous suivre sans demander d'approbation. Décochez cette option si vous voulez valider les demandes d'abonnement et choisir d'accepter ou de rejeter les nouveaux abonnés. account_alias: acct: Spécifiez l’identifiant@domaine du compte à partir duquel vous souhaitez migrer account_migration: diff --git a/config/locales/simple_form.fy.yml b/config/locales/simple_form.fy.yml index 8a753dcc89..6a37a09201 100644 --- a/config/locales/simple_form.fy.yml +++ b/config/locales/simple_form.fy.yml @@ -3,13 +3,13 @@ fy: simple_form: hints: account: + 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. indexable: Jo iepenbiere berjochten kinne ferskine yn de sykresultaten op Mastodon. Minsken dy’t reagearre hawwe op jo berjochten kinne se hoe dan ek trochsykje. note: 'Jo kinne oare minsken @fermelde of #hashtags brûke.' show_collections: Minsken kinne sjen wa’t jo folgje en wa’t jo folget. - unlocked: Minsken kinne jo folgje sûnder dêrfoar tastimming freegje te hoegen. Wannear’t jo nije folgers hânmjittich goedkarre wolle, moatte jo dizze opsje deselektearje. account_alias: acct: Fermeld de brûkersnamme@domein fan de account fan wêr’t jo ferhúzje wolle account_migration: @@ -143,6 +143,7 @@ fy: url: Wêr’t eveneminten nei ta stjoerd wurde labels: account: + 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.gd.yml b/config/locales/simple_form.gd.yml index af1f06a316..4c3a297738 100644 --- a/config/locales/simple_form.gd.yml +++ b/config/locales/simple_form.gd.yml @@ -10,7 +10,7 @@ gd: indexable: Faodaidh na postaichean poblach agad a nochdadh am measg toraidhean luirg air Mastodon. ’S urrainn dhan fheadhainn a rinn eadar-ghabhail leis na postaichean agad lorg annta air a h-uile dòigh. note: "’S urrainn dhut @iomradh a thoirt air càch no air #tagaicheanHais." show_collections: "’S urrainn do chàch na dàimhean leantainn agad a rùrachadh. Chì daoine a leanas tu gu bheil thu ’gan leantainn air a h-uile dòigh." - unlocked: "’S urrainnear do leantainn gun aontachadh iarraidh. Thoir a’ chromag far a’ bhogsa nam bu mhiann leat lèirmheas a dhèanamh air na h-iarrtasan leantainn agus taghadh an aontaich thu ri neach-leantainn ùr no an dhiùlt thu iad." + unlocked: "’S urrainnear do leantainn gun aonta iarraidh. Thoir a’ chromag air falbh ma tha thu airson lèirmheas a dhèanamh air iarrtasan leantainn agus cur romhad an gabh thu ri luchd-leantainn ùr no an diùilt thu iad." account_alias: acct: Sònraich ainm-cleachdaiche@àrainn dhen chunntas a tha thu airson imrich uaithe account_migration: diff --git a/config/locales/simple_form.hu.yml b/config/locales/simple_form.hu.yml index 230965fe87..60922b06b5 100644 --- a/config/locales/simple_form.hu.yml +++ b/config/locales/simple_form.hu.yml @@ -48,7 +48,7 @@ hu: digest: Csak hosszú távollét esetén küldődik és csak ha személyes üzenetet kaptál távollétedben email: Kapsz egy megerősítő e-mailt header: WEBP, PNG, GIF vagy JPG. Legfeljebb %{size}. Át lesz méretezve %{dimensions} képpontosra. - inbox_url: Másold ki a használandó relé szerver kezdőoldalának URL-jét + inbox_url: Másold ki a használandó továbbító kiszolgáló kezdőoldalának URL-jét irreversible: A kiszűrt bejegyzések visszafordíthatatlanul eltűnnek, a szűrő későbbi törlése esetén is locale: A felhasználói felület, e-mailek, push üzenetek nyelve password: Legalább 8 karakter @@ -195,7 +195,7 @@ hu: fields: Profil metaadatai header: Fejléc honeypot: "%{label} (ne töltsd ki)" - inbox_url: Relé inbox-hoz tartozó URL + inbox_url: Továbbító inbox-hoz tartozó URL irreversible: Eldobás elrejtés helyett locale: Felhasználói felület nyelve max_uses: Hányszor használható diff --git a/config/locales/simple_form.ia.yml b/config/locales/simple_form.ia.yml index 85fa74f1ed..1a405980c0 100644 --- a/config/locales/simple_form.ia.yml +++ b/config/locales/simple_form.ia.yml @@ -3,6 +3,7 @@ ia: simple_form: hints: account: + attribution_domains_as_text: Un per linea. Protege contra false attributiones. discoverable: Tu messages public e tu profilo pote esser mittite in evidentia o recommendate in varie areas de Mastodon e tu profilo pote esser suggerite a altere usatores. display_name: Tu prenomine e nomine de familia o tu pseudonymo. fields: Tu pagina principal, pronomines, etate, tote lo que tu vole. @@ -130,6 +131,7 @@ ia: name: Tu pote solmente cambiar le litteras inter majusculas e minusculas, per exemplo, pro render lo plus legibile user: chosen_languages: Si marcate, solo le messages in le linguas seligite sera monstrate in chronologias public + role: Le rolo controla qual permissos le usator ha. user_role: color: Color a esser usate pro le rolo in omne parte del UI, como RGB in formato hexadecimal highlighted: Iste rende le rolo publicamente visibile @@ -142,6 +144,7 @@ ia: url: Ubi le eventos essera inviate labels: account: + attribution_domains_as_text: Sitos web autorisate a accreditar te discoverable: Evidentiar le profilo e messages in le algorithmos de discoperta fields: name: Etiquetta @@ -210,6 +213,7 @@ ia: setting_default_privacy: Confidentialitate del messages setting_default_sensitive: Sempre marcar le medios cmo sensbile setting_delete_modal: Monstrar le dialogo de confirmation ante deler un message + setting_disable_hover_cards: Disactivar le previsualisation de profilos al passar del mus setting_disable_swiping: Disactivar le movimentos per glissamento setting_display_media: Visualisation de medios setting_display_media_default: Predefinite diff --git a/config/locales/simple_form.ie.yml b/config/locales/simple_form.ie.yml index 771e341616..56e737172d 100644 --- a/config/locales/simple_form.ie.yml +++ b/config/locales/simple_form.ie.yml @@ -9,7 +9,6 @@ ie: indexable: Tui public postas posse aparir in sercha-resultates sur Mastodon. E in omni casu, tis qui ha interactet con tui postas va posser serchar e trovar les. note: 'Tu posse @mentionar altri persones o #hashtags.' show_collections: Gente va posser navigar tra tui sequentes e sequitores. Gente quem tu seque va vider que tu seque les sin egarda. - unlocked: Persones va posser sequer te sin petir aprobation. Desselecte si tu vole manualmen tractar petitiones de sequer e decider ca acceptar o rejecter nov sequitores. account_alias: acct: Specificar li usatornomine@dominia del conto ex quel tu vole translocar account_migration: diff --git a/config/locales/simple_form.ig.yml b/config/locales/simple_form.ig.yml index 7c264f0d73..e88d195b8a 100644 --- a/config/locales/simple_form.ig.yml +++ b/config/locales/simple_form.ig.yml @@ -1 +1,8 @@ +--- ig: + simple_form: + labels: + defaults: + avatar: Foto profaịlụ + chosen_languages: Myọcha asụsụ + context: Myọcha ọnọdụ diff --git a/config/locales/simple_form.io.yml b/config/locales/simple_form.io.yml index 1df5008195..631e7182fd 100644 --- a/config/locales/simple_form.io.yml +++ b/config/locales/simple_form.io.yml @@ -9,7 +9,6 @@ io: indexable: Vua posta publika povos aparar en rezultaji di serchi che Mastodon. Personi qui interagis kun vua posti povos serchar oli irgakaze. note: 'Vu povas @mencionar altra personi o #hashtagi.' show_collections: Personi povos navigar tra vua sequati e sequanti. Personi quin vu sequas, vidos ke vu sequas li irgakaze. - unlocked: Personi povos sequar vu sen demandar aprobo. Deselektez se vu volas revuar sequadodemandi e selektez aceptar o refuzar nova sequati. account_alias: acct: Partikulare pozez uzantonomo@domeno di konto quon vua volas ektransferesar account_migration: diff --git a/config/locales/simple_form.it.yml b/config/locales/simple_form.it.yml index c36fce36f7..b1fb6c3fc1 100644 --- a/config/locales/simple_form.it.yml +++ b/config/locales/simple_form.it.yml @@ -10,7 +10,7 @@ it: indexable: I tuoi post pubblici potrebbero apparire nei risultati di ricerca su Mastodon. Le persone che hanno interagito con i tuoi post potrebbero essere in grado di cercarli anche se non hai attivato questa impostazione. note: 'Puoi @menzionare altre persone o usare gli #hashtags.' show_collections: Le persone saranno in grado di navigare attraverso i tuoi seguaci e seguaci. Le persone che segui vedranno che li seguirai indipendentemente dalle tue impostazioni. - unlocked: Le persone saranno in grado di seguirti senza richiedere l'approvazione. Deseleziona se vuoi controllare le richieste di seguirti e scegli se accettare o rifiutare nuovi follower. + unlocked: Le persone potranno seguirti senza richiedere l'approvazione. Deseleziona questa opzione, se vuoi rivedere le richieste per poterti seguire e scegliere se accettare o rifiutare i nuovi seguaci. account_alias: acct: Indica il nomeutente@dominio dell'account dal quale vuoi trasferirti account_migration: diff --git a/config/locales/simple_form.ko.yml b/config/locales/simple_form.ko.yml index c40814d61b..962f062534 100644 --- a/config/locales/simple_form.ko.yml +++ b/config/locales/simple_form.ko.yml @@ -32,9 +32,9 @@ ko: warning_preset_id: 선택사항. 틀의 마지막에 임의의 텍스트를 추가 할 수 있습니다 announcement: all_day: 체크 되었을 경우, 그 시간에 속한 날짜들에만 표시됩니다 - ends_at: 옵션입니다. 공지사항이 이 시간에 자동으로 발행 중지 됩니다 + ends_at: 선택사항. 공지사항이 이 시간에 자동으로 발행 중지 됩니다 scheduled_at: 공백으로 두면 공지사항이 곧바로 발행 됩니다 - starts_at: 공지사항이 특정한 시간에 종속 될 때를 위한 옵션입니다 + starts_at: 선택사항. 공지사항이 특정한 시간에 종속 될 때를 위한 옵션입니다 text: 게시물 문법을 사용할 수 있습니다. 공지사항은 사용자의 화면 상단 공간을 차지한다는 것을 명심하세요 appeal: text: 처벌에 대해 단 한 번만 이의제기를 할 수 있습니다 @@ -46,7 +46,7 @@ ko: current_password: 보안을 위해 현재 계정의 암호를 입력해주세요 current_username: 확인을 위해, 현재 계정의 사용자명을 입력해주세요 digest: 오랫동안 활동하지 않았을 때 받은 멘션들에 대한 요약 받기 - email: 확인용 이메일을 보냈습니다. + email: 확인용 이메일을 보내게 됩니다 header: WEBP, PNG, GIF 혹은 JPG. 최대 %{size}. %{dimensions}px로 축소됨 inbox_url: 사용 할 릴레이 서버의 프론트페이지에서 URL을 복사합니다 irreversible: 필터링 된 게시물은 나중에 필터가 사라지더라도 돌아오지 않게 됩니다 @@ -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: '휴대전화에서 생성된 이중 인증 코드를 입력하거나, 복구 코드 중 하나를 사용하세요:' diff --git a/config/locales/simple_form.lt.yml b/config/locales/simple_form.lt.yml index de3dd2f31c..77482d8012 100644 --- a/config/locales/simple_form.lt.yml +++ b/config/locales/simple_form.lt.yml @@ -10,7 +10,7 @@ lt: indexable: Tavo vieši įrašai gali būti rodomi Mastodon paieškos rezultatuose. Žmonės, kurie bendravo su tavo įrašais, gali jų ieškoti nepriklausomai nuo to. note: 'Gali @paminėti kitus žmones arba #saitažodžius.' show_collections: Žmonės galės peržiūrėti tavo sekimus ir sekėjus. Žmonės, kuriuos seki, matys, kad juos seki, nepaisant to. - unlocked: Žmonės galės tave sekti nepaprašę patvirtinimo. Panaikink žymėjimą, jei nori peržiūrėti sekimo prašymus ir pasirinkti, ar priimti, ar atmesti naujus sekėjus. + unlocked: Žmonės galės jus sekti nepaprašę patvirtinimo. Panaikinkite žymėjimą, jei norite peržiūrėti sekimo prašymus ir pasirinkti, ar priimti, ar atmesti naujus sekėjus. account_alias: acct: Nurodyk paskyros, iš kurios nori perkelti, naudotojo vardą@domeną account_migration: diff --git a/config/locales/simple_form.lv.yml b/config/locales/simple_form.lv.yml index 974008b5eb..2f4a05dca4 100644 --- a/config/locales/simple_form.lv.yml +++ b/config/locales/simple_form.lv.yml @@ -10,7 +10,7 @@ lv: indexable: Tavi publiskie ieraksti var tikt parādīti Mastodon meklēšanas iznākumā. Cilvēki, kuri ir mijiedarbojušies ar Taviem ierakstiem, var tos meklēt neatkarīgi no tā. note: 'Tu vari @minēt citus cilvēkus vai #mirkļbirkas.' show_collections: Cilvēki varēs pārlūkot Tavus sekotājus un sekojamos. Cilvēki, kuriem Tu seko, redzēs, ka Tu seko viņiem neatkarīgi no tā. - unlocked: Cilvēki varēs tev sekot, neprasot apstiprinājumu. Noņem atzīmi, ja vēlies pārskatīt sekošanas pieprasījumus un izvēlēties, pieņemt vai noraidīt jaunus sekotājus. + unlocked: Cilvēki varēs Tev sekot bez apstiprinājuma pieprasīšanas. Jānoņem atzīme, ja vēlies pārskatīt sekošanas pieprasījumus un izvēlēties, vai apstiprināt vai noraidīt jaunus sekotājus. account_alias: acct: Norādi konta lietotājvārdu@domēnu, no kura vēlies pārvākties account_migration: @@ -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: @@ -89,7 +89,7 @@ lv: media_cache_retention_period: Informācijas nesēju datnes no ierakstiem, kurus ir veikuši attālie lietotāji, tiek kešoti šajā serverī. Kad ir iestatīta apstiprinoša vērtība, informācijas nesēji tiks izdzēsti pēc norādītā dienu skaita. Ja informācijas nesēju dati tiks pieprasīti pēc tam, kad tie tika izdzēsti, tie tiks atkārtoti lejupielādēti, ja avota saturs joprojām būs pieejams. Saišu priekšskatījuma karšu vaicājumu biežuma ierobežojumu dēļ ir ieteicams iestatīt šo vērtību vismaz 14 dienas vai saišu priekšskatījuma kartes netiks atjauninātas pēc pieprasījuma pirms tā laika. peers_api_enabled: Domēna vārdu saraksts, ar kuriem šis serveris ir saskāries fediversā. Šeit nav iekļauti dati par to, vai tu veic federāciju ar noteiktu serveri, tikai tavs serveris par to zina. To izmanto dienesti, kas apkopo statistiku par federāciju vispārīgā nozīmē. profile_directory: Profilu direktorijā ir uzskaitīti visi lietotāji, kuri ir izvēlējušies būt atklājami. - require_invite_text: 'Ja pierakstīšanai nepieciešama manuāla apstiprināšana, izdari tā, lai teksta: “Kāpēc vēlaties pievienoties?” ievade ir obligāta, nevis opcionāla' + require_invite_text: Ja nepieciešama pašrocīga apstiprināšana, lai pierakstītos, teksta “Kāpēc vēlies pievienoties?” ievade jāpadara par nepieciešamu, nevis izvēles site_contact_email: Kā cilvēki var sazināties ar tevi par juridiskiem vai atbalsta jautājumiem. site_contact_username: Tagad cilvēki var tevi sasniegt Mastodon. site_extended_description: Jebkura papildu informācija, kas var būt noderīga apmeklētājiem un lietotājiem. Var strukturēt ar Markdown sintaksi. @@ -183,7 +183,7 @@ lv: autofollow: Uzaicini sekot tavam kontam avatar: Profila attēls bot: Šis ir automatizēts konts - chosen_languages: Filtrēt valodas + chosen_languages: Atlasīt valodas confirm_new_password: Apstiprināt jauno paroli confirm_password: Apstiprināt paroli context: Filtrēt kontekstus @@ -339,5 +339,5 @@ lv: text: nepieciešams title: sessions: - webauthn: Lai pierakstītos, izmanto vienu no savām drošības atslēgām + webauthn: Lai pieteiktos, jāizmanto viena no savām drošības atslēgām 'yes': Jā diff --git a/config/locales/simple_form.ms.yml b/config/locales/simple_form.ms.yml index ecc3588d67..96c6002aa4 100644 --- a/config/locales/simple_form.ms.yml +++ b/config/locales/simple_form.ms.yml @@ -9,7 +9,6 @@ ms: indexable: Kiriman awam anda mungkin muncul dalam hasil carian di Mastodon. Orang yang telah berinteraksi dengan kiriman anda mungkin boleh mencarinya. note: 'Anda boleh @menyebut orang lain atau #hashtags.' show_collections: Orang akan dapat menyemak imbas ikutan dan pengikut anda. Orang yang anda ikuti akan melihat bahawa anda tetap mengikuti mereka. - unlocked: Orang akan dapat mengikuti anda tanpa meminta kelulusan. Nyahtanda jika anda ingin menyemak permintaan ikutan dan pilih sama ada untuk menerima atau menolak pengikut baharu. account_alias: acct: Tentukan namapengguna@domain akaun yang ingin anda alihkan daripada account_migration: diff --git a/config/locales/simple_form.my.yml b/config/locales/simple_form.my.yml index abcb11bdaa..474b0f6cb4 100644 --- a/config/locales/simple_form.my.yml +++ b/config/locales/simple_form.my.yml @@ -9,7 +9,6 @@ my: indexable: သင်၏ အများမြင်ပို့စ်များသည် Mastodon ရှိ ရှာဖွေမှုရလဒ်များတွင် ပေါ်လာနိုင်သည်။ သင့်ပို့စ်များမှတစ်ဆင့် အပြန်အလှန်တုံ့ပြန်ပြီး ရှာဖွေနိုင်ပါမည်။ note: 'သင်သည် အခြားသူများ သို့မဟုတ် #hashtag များကို @mention ဖြင့် ဖော်ပြနိုင်သည်။' show_collections: သင်စောင့်ကြည့်သူများနှင့် သင့်ကိုစောင့်ကြည့်သူများမှတစ်ဆင့် ရှာဖွေနိုင်မည်ဖြစ်သည်။ သင်စောင့်ကြည့်သူများသည် သင်သူတို့ကို မည်သို့စောင့်ကြည့်သည်ကို တွေ့ရလိမ့်မည်။ - unlocked: ခွင့်ပြုချက်မတောင်းဘဲ လူများက သင့်ကိုစောင့်ကြည့်နိုင်ပါမည်။ စောင့်ကြည့်ရန်အတွက် တောင်းဆိုချက်များထားရှိလိုပါက အမှန်ခြစ်ဖြုတ်ပြီး စောင့်ကြည့်သူသစ်များကို လက်ခံခြင်း သို့မဟုတ် ငြင်းပယ်ခြင်းလည်း အမှန်ခြစ်ဖြုတ်နိုင်ပါသည်။ account_alias: acct: ပြောင်းရွှေ့မည့်အကောင့်မှ username@domain ကို သတ်မှတ်ပါ account_migration: diff --git a/config/locales/simple_form.nl.yml b/config/locales/simple_form.nl.yml index 7280ba6d80..2bb31aa0f9 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: Eén per regel. Beschermt tegen valse attribueringen. + attribution_domains_as_text: Eén per regel. Beschermt tegen ongeldige attributies. 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. diff --git a/config/locales/simple_form.no.yml b/config/locales/simple_form.no.yml index 73ba17cd4c..fb7a808876 100644 --- a/config/locales/simple_form.no.yml +++ b/config/locales/simple_form.no.yml @@ -9,7 +9,6 @@ indexable: Dine offentlige innlegg kan vises i søkeresultat på Mastodon. Personer som har samhandlet med innleggene dine kan finne de uansett. note: 'Du kan @nevne andre eller #emneknagger.' show_collections: Folk vil kunne bla gjennom de du følger og dine følgere. Folk du følger vil uansett se at du følger dem. - unlocked: Folk vil kunne følge deg uten å be om godkjenning. Fjern markeringen om du vil gjennomgå følge-forespørsler og velge om du vil akseptere eller avvise nye følgere. account_alias: acct: Spesifiser brukernavn@domene til kontoen du vil flytte fra account_migration: diff --git a/config/locales/simple_form.pt-BR.yml b/config/locales/simple_form.pt-BR.yml index 16d7cfe445..fca59515f0 100644 --- a/config/locales/simple_form.pt-BR.yml +++ b/config/locales/simple_form.pt-BR.yml @@ -10,7 +10,7 @@ pt-BR: indexable: Suas publicações públicas podem aparecer nos resultados da pesquisa em Mastodon. As pessoas que interagiram com suas publicações podem conseguir pesquisá-las independentemente disso. note: 'Você pode @mencionar outras pessoas ou #hashtags.' show_collections: As pessoas poderão navegar entre os seus seguidores e seguidores. As pessoas que você segue verão que você as segue independentemente disso. - unlocked: As pessoas poderão te seguir sem pedir aprovação. Desmarque se você deseja revisar pedidos e escolher se aceita ou rejeita novos seguidores. + unlocked: As pessoas poderão seguir você sem solicitar aprovação. Desmarque caso você queira revisar as solicitações de seguidor e escolha se queira aceitar ou rejeitar novos seguidores. account_alias: acct: Especifique o usuário@domínio de onde veio account_migration: diff --git a/config/locales/simple_form.pt-PT.yml b/config/locales/simple_form.pt-PT.yml index 3b606df032..a172ed2752 100644 --- a/config/locales/simple_form.pt-PT.yml +++ b/config/locales/simple_form.pt-PT.yml @@ -9,7 +9,6 @@ pt-PT: indexable: As suas mensagens públicas podem aparecer nos resultados da pesquisa no Mastodon. Independentemente disso, as pessoas que interagiram com as suas publicações podem ser capazes de as pesquisar. note: 'Pode @mencionar outras pessoas ou #hashtags.' show_collections: As pessoas podem navegar pelas listas das pessoas que segue e dos seus seguidores. Independentemente disso, as pessoas que segue verão que você as segue. - unlocked: As pessoas podem segui-lo/a sem pedir a sua aprovação. Desmarque se quiser rever os pedidos para seguir e escolher se aceita ou rejeita os novos seguidores. account_alias: acct: Especifique o utilizador@domínio da conta de onde você deseja migrar account_migration: diff --git a/config/locales/simple_form.ro.yml b/config/locales/simple_form.ro.yml index 458638ddec..63dcf91343 100644 --- a/config/locales/simple_form.ro.yml +++ b/config/locales/simple_form.ro.yml @@ -3,11 +3,14 @@ ro: simple_form: hints: account: + attribution_domains_as_text: Una pe linie. Protejează împotriva atribuirilor false. discoverable: Este posibil ca postările și profilul tău să fie recomandate în diferite zone ale Mastodon, iar profilul tău ar poate fi sugerat altor utilizatori. + display_name: Numele dvs. complet sau numele dvs. amuzant. fields: Pagina ta principală, pronumele tale, vârsta, sau orice îți dorești. indexable: Postările tale publice pot apărea în rezultatele căutărilor pe Mastodon. Persoanele care au interacționat cu postările tale vor putea să le caute oricând. note: 'Poți @menționa alte persoane sau #hashtag-uri.' - unlocked: Alte persoane vă vor putea urmări fără a solicita aprobare. Debifați dacă doriți să revizuiți cererile și să alegeți dacă doriți să acceptați sau să respingeți noii urmăritori. + show_collections: Oamenii vor putea să răsfoiască urmăriți și urmăritorii dvs. Oamenii pe care îi urmăriți vor vedea că îi urmăriți indiferent. + unlocked: Alte persoane vă vor putea urmări fără a solicita aprobare. Debifați dacă doriți să revizuiți cererile de urmărire și să alegeți dacă doriți să acceptați sau să respingeți noii urmăritori. account_alias: acct: Specificați numele de utilizator@domeniu al contului de la care doriți să treceți account_migration: @@ -20,6 +23,12 @@ ro: send_email_notification: Utilizatorul va primi o explicație cu privire la ceea ce sa întâmplat cu contul lui text_html: Opțional. Poți utiliza sintaxe. Poți adăuga avertismente predefinite pentru a salva timp type_html: Alege ce se întâmplă cu %{acct} + types: + disable: Împiedicați utilizatorul să-și folosească contul, dar nu ștergeți sau ascundeți conținutul acestuia. + none: Utilizați acest lucru pentru a trimite o avertizare utilizatorului, fără a declanșa nicio altă acțiune. + sensitive: Forțează toate atașamentele media ale acestui utilizator să fie marcate ca sensibile. + silence: Împiedicați utilizatorul să poată posta cu vizibilitate publică, ascundeți postările și notificările de la persoanele care nu le urmăresc. Închide toate rapoartele pentru acest cont. + suspend: Preveniți orice interacțiune din sau către acest cont și ștergeți conținutul acestuia. Reversibil în 30 de zile. Închide toate rapoartele pentru acest cont. warning_preset_id: Opțional. Poți adăuga text personalizat la sfârșitul presetului announcement: all_day: Când este bifat, numai datele intervalului de timp vor fi afișate @@ -27,6 +36,8 @@ ro: scheduled_at: Lăsați necompletat pentru a publica anunțul imediat starts_at: Opțional. În cazul în care anunțul tău este legat de un anumit interval de timp text: Poți folosi sintaxa de postare. Te rugăm să fii atent la spațiul pe care anunțul îl va ocupa pe ecranul utilizatorului + appeal: + text: Puteți contesta un avertisment o singură dată defaults: autofollow: Persoanele care se înregistrează datorită invitației tale te vor urmări automat avatar: WEBP, PNG, GIF sau JPG. Cel mult %{size}. Va fi redimensionată la %{dimensions}px @@ -65,18 +76,64 @@ ro: actions: hide: Ascunde complet conținutul filtrat, ca și cum nu ar exista warn: Ascunde conținutul filtrat în spatele unui avertisment care menționează titlul filtrului + form_admin_settings: + activity_api_enabled: Numărul de postări publicate local, utilizatori activi și înregistrări noi în grupe săptămânale + app_icon: WEBP, PNG, GIF sau JPG. Înlocuiește pictograma implicită a aplicației pe dispozitivele mobile cu o pictogramă personalizată. + backups_retention_period: Utilizatorii au posibilitatea de a genera arhive ale postărilor lor pentru a le descărca mai târziu. Când este setat la o valoare pozitivă, aceste arhive vor fi șterse automat din spațiul dvs. de stocare după numărul de zile specificat. + bootstrap_timeline_accounts: Aceste conturi vor fi fixate în partea de sus a recomandărilor de urmărire ale noilor utilizatori. + closed_registrations_message: Afișat când înscrierile sunt închise + content_cache_retention_period: Toate postările de pe alte servere (inclusiv amplificarea și răspunsurile) vor fi șterse după numărul specificat de zile, fără a ține cont de interacțiunea utilizatorului local cu acele postări. Aceasta include postările în care un utilizator local le-a marcat ca marcaje sau favorite. Mențiunile private între utilizatorii din diferite instanțe se vor pierde și vor fi imposibil de restaurat. Utilizarea acestei setări este destinată cazurilor cu scop special și încalcă multe așteptări ale utilizatorilor atunci când este implementată pentru uz general. + custom_css: Puteți aplica stiluri personalizate pe versiunea web a Mastodon. + favicon: WEBP, PNG, GIF sau JPG. Suprascrie favicon-ul implicit Mastodon cu o pictogramă personalizată. + mascot: Suprascrie ilustrația din interfața web avansată. + media_cache_retention_period: Fișierele media din postările făcute de utilizatorii la distanță sunt stocate în cache pe serverul dvs. Când este setată la o valoare pozitivă, fișierele media vor fi ștearse după numărul specificat de zile. Dacă datele media sunt solicitate după ce sunt șterse, acestea vor fi re-descărcate, dacă conținutul sursă este încă disponibil. Din cauza restricțiilor cu privire la frecvența cu care cardurile de previzualizare a linkurilor interogează site-urile terțelor părți, se recomandă să setați această valoare la cel puțin 14 zile, sau cardurile de previzualizare a linkurilor nu vor fi actualizate la cerere înainte de această oră. + peers_api_enabled: O listă de nume de domenii pe care acest server le-a întâlnit în fediverse. Nu sunt incluse aici date despre dacă vă federați cu un anumit server, doar că serverul dvs. știe despre asta. Acesta este folosit de serviciile care colectează statistici despre federație în sens general. + profile_directory: Directorul de profil listează toți utilizatorii care au optat pentru a fi descoperibili. + require_invite_text: Când înscrierile necesită aprobare manuală, faceți introducerea textului „De ce doriți să vă alăturați?” obligatorie și nu opțională + site_contact_email: Cum vă pot contacta oamenii pentru întrebări juridice sau de asistență. + site_contact_username: Cum vă pot contacta oamenii pe Mastodon. + site_extended_description: Orice informație suplimentară care poate fi utilă vizitatorilor și utilizatorilor dvs. Poate fi structurată cu sintaxa Markdown. + site_short_description: O descriere scurtă pentru a ajuta la identificarea unică a serverului dvs. Cine-l conduce, pentru cine este? + site_terms: Utilizați propria politică de confidențialitate sau lăsați necompletat pentru a o utiliza pe cea implicit. Poate fi structurată cu sintaxa Markdown. + site_title: Cum se pot referi oamenii la serverul dvs. în afară de numele său de domeniu. + status_page_url: URL-ul unei pagini unde oamenii pot vedea starea acestui server în timpul unei întreruperi + theme: Tema pe care vizitatorii deconectați și utilizatorii noi o văd. + thumbnail: O imagine de aproximativ 2:1 afișată alături de informațiile serverului dvs. + timeline_preview: Vizitatorii deconectați vor putea să răsfoiască cele mai recente postări publice disponibile pe server. + trendable_by_default: Omiteți revizuirea manuală a conținutului în tendințe. Elementele individuale pot fi în continuare eliminate din tendințe după fapt. + trends: Tendințele arată ce postări, hashtag-uri și știri câștigă teren pe serverul dvs. + trends_as_landing_page: Afișați conținut în tendințe utilizatorilor deconectați și vizitatorilor în loc de o descriere a acestui server. Necesită ca tendințele să fie activate. form_challenge: current_password: Ați intrat într-o zonă securizată imports: data: Fișierul CSV exportat de la o altă instanță invite_request: text: Acest lucru ne va ajuta să revizuim cererea dvs + ip_block: + comment: Opțional. Amintiți-vă de ce ați adăugat această regulă. + expires_in: Adresele IP sunt o resursă finită, uneori sunt partajate și adesea se schimbă. Din acest motiv, blocurile IP nedefinite nu sunt recomandate. + ip: Introduceți o adresă IPv4 sau IPv6. Puteți bloca întregul spectru folosind sintaxa CIDR. Aveți grijă să nu vă blocați! + severities: + no_access: Blocați accesul la toate resursele + sign_up_block: Nu vor fi posibile înscrieri noi + sign_up_requires_approval: Înscrierile noi vor necesita aprobarea dvs. + severity: Alegeți ce se va întâmpla cu cererile de la acestă adresă IP + rule: + hint: Opțional. Oferiți mai multe detalii despre regulă + text: Descrieți o regulă sau o cerință pentru utilizatorii de pe acest server. Încercați să o faceți scurtă și simplă sessions: otp: 'Introdu codul pentru dubla protecție generat de telefonul mobil sau unul din codurile de rezervă:' + webauthn: Dacă este o cheie USB, asigurați-vă că o introduceți și, dacă este necesar, atingeți-o. + settings: + indexable: Pagina dvs. de profil poate apărea în rezultatele căutării pe Google, Bing și altele. + show_application: Veți putea întotdeauna să vedeți ce aplicație v-a publicat postarea. tag: name: Poți doar să schimbi caseta literelor, de exemplu, pentru a o face mai lizibilă user: chosen_languages: Doar postările în limbile selectate vor fi afișate în fluxurile publice + role: Rolul controlează ce permisiuni are utilizatorul. + user_role: + color: Culoare care va fi folosită pentru rol în întreaga interfață, ca RGB în format hexazecimal labels: account: fields: diff --git a/config/locales/simple_form.ru.yml b/config/locales/simple_form.ru.yml index 1bdffc6f1d..37626ff9fd 100644 --- a/config/locales/simple_form.ru.yml +++ b/config/locales/simple_form.ru.yml @@ -3,6 +3,7 @@ ru: simple_form: hints: account: + attribution_domains_as_text: По одному на строку. Защищает от ложных атрибуций. discoverable: Ваши публичные сообщения и профиль могут быть показаны или рекомендованы в различных разделах Mastodon, и ваш профиль может быть предложен другим пользователям. display_name: Ваше полное имя или псевдоним. fields: Ваша домашняя страница, местоимения, возраст - все, что угодно. @@ -143,6 +144,7 @@ ru: url: Куда события будут отправляться labels: account: + attribution_domains_as_text: Веб-сайты, которым разрешено ссылаться на вас discoverable: Профиль и сообщения в алгоритмах обнаружения fields: name: Пункт diff --git a/config/locales/simple_form.sl.yml b/config/locales/simple_form.sl.yml index d1ae553c8c..1f1867854e 100644 --- a/config/locales/simple_form.sl.yml +++ b/config/locales/simple_form.sl.yml @@ -9,7 +9,6 @@ sl: indexable: Vaše javne objave se lahko pojavijo v rezultatih iskanja na Mastodonu. Ljudje, ki so bili v interakciji z vašimi objavami, jih bodo lahko iskali ne glede na to. note: 'Druge osebe lahko @omenite ali #ključnite.' show_collections: Ljudje bodo lahko brskali po vaših sledilcih in sledenih. Ljudje, ki jim sledite, bodo videli, da jim sledite ne glede na to. - unlocked: Ljudje vam bodo lahko sledili, ne da bi zahtevali odobritev. Ne potrdite, če želite pregledati prošnje za sledenje, in izbirajte, ali želite nove sledilce sprejeti ali zavrniti. account_alias: acct: Določite uporabniškoime@domena računa, od katerega se želite preseliti account_migration: diff --git a/config/locales/simple_form.sr-Latn.yml b/config/locales/simple_form.sr-Latn.yml index 1dec901340..fee7600074 100644 --- a/config/locales/simple_form.sr-Latn.yml +++ b/config/locales/simple_form.sr-Latn.yml @@ -9,7 +9,6 @@ sr-Latn: indexable: Vaše javne objave se mogu pojaviti u rezultatima pretrage na Mastodon-u. Ljudi koji su stupili u interakciju sa vašim objavama će možda moći da ih pretražuju. note: 'Možete da @pomenete druge ljude ili #heš oznake.' show_collections: Ljudi će moći da pregledaju vaše pratioce i pratioce. Ljudi koje pratite videće da ih pratite. - unlocked: Ljudi će moći da vas prate bez zahtevanja odobrenja. Opozovite izbor ako želite da pregledate zahteve za praćenje i izaberite da li da prihvatite ili odbijete nove pratioce. account_alias: acct: Navedite korisničko_ime@domen naloga sa kojeg želite da se preselite account_migration: diff --git a/config/locales/simple_form.sr.yml b/config/locales/simple_form.sr.yml index 9566e09475..7161627e28 100644 --- a/config/locales/simple_form.sr.yml +++ b/config/locales/simple_form.sr.yml @@ -9,7 +9,6 @@ sr: indexable: Ваше јавне објаве се могу појавити у резултатима претраге на Mastodon-у. Људи који су ступили у интеракцију са вашим објавама ће можда моћи да их претражују. note: 'Можете да @поменете друге људе или #хеш ознаке.' show_collections: Људи ће моћи да прегледају ваше пратиоце и пратиоце. Људи које пратите видеће да их пратите. - unlocked: Људи ће моћи да вас прате без захтевања одобрења. Опозовите избор ако желите да прегледате захтеве за праћење и изаберите да ли да прихватите или одбијете нове пратиоце. account_alias: acct: Наведите корисничко_име@домен налога са којег желите да се преселите account_migration: diff --git a/config/locales/simple_form.sv.yml b/config/locales/simple_form.sv.yml index 36d1def012..72c3f000f6 100644 --- a/config/locales/simple_form.sv.yml +++ b/config/locales/simple_form.sv.yml @@ -74,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 diff --git a/config/locales/simple_form.th.yml b/config/locales/simple_form.th.yml index f8f4d3f119..0ba54e26ce 100644 --- a/config/locales/simple_form.th.yml +++ b/config/locales/simple_form.th.yml @@ -10,7 +10,6 @@ th: indexable: โพสต์สาธารณะของคุณอาจปรากฏในผลลัพธ์การค้นหาใน Mastodon ผู้คนที่ได้โต้ตอบกับโพสต์ของคุณอาจสามารถค้นหาโพสต์เหล่านั้นได้ไม่ว่าอย่างไรก็ตาม note: 'คุณสามารถ @กล่าวถึง ผู้คนอื่น ๆ หรือ #แฮชแท็ก' show_collections: ผู้คนจะสามารถเรียกดูการติดตามและผู้ติดตามของคุณ ผู้คนที่คุณติดตามจะเห็นว่าคุณติดตามเขาไม่ว่าอย่างไรก็ตาม - unlocked: ผู้คนจะสามารถติดตามคุณได้โดยไม่ต้องขอการอนุมัติ เลิกกาเครื่องหมายหากคุณต้องการตรวจทานคำขอติดตามและเลือกว่าจะยอมรับหรือปฏิเสธผู้ติดตามใหม่ account_alias: acct: ระบุ username@domain ของบัญชีที่คุณต้องการย้ายจาก account_migration: diff --git a/config/locales/simple_form.zh-CN.yml b/config/locales/simple_form.zh-CN.yml index 6586c372ef..04c23f1706 100644 --- a/config/locales/simple_form.zh-CN.yml +++ b/config/locales/simple_form.zh-CN.yml @@ -4,13 +4,13 @@ zh-CN: hints: account: attribution_domains_as_text: 每行一个域名。这样就可以保护作品免受虚假署名。 - discoverable: 您的公开嘟文和个人资料可能会在 Mastodon 的多个位置展示,您的个人资料可能会被推荐给其他用户。 + discoverable: 你的公开嘟文和个人资料可能会在 Mastodon 的多个位置展示,你的个人资料可能会被推荐给其他用户。 display_name: 你的全名或昵称。 fields: 你的主页、人称代词、年龄,以及任何你想要添加的内容。 - indexable: 您的公开嘟文会出现在 Mastodon 的搜索结果中。无论是否勾选,与您的嘟文有过交互的人都可能通过搜索找到它们。 - note: '你可以提及 @其他人 或 #标签 。' - show_collections: 人们将能够浏览您的关注和追随者。您关注的人会看到您关注他们。 - unlocked: 人们将能够在不请求批准的情况下关注你。如果你希望审核关注请求并选择接受或拒绝新的粉丝,请取消勾选此项。 + indexable: 你的公开嘟文会出现在 Mastodon 的搜索结果中。无论是否勾选,与你的嘟文有过交互的人都可能通过搜索找到它们。 + note: '你可以提及 @其他人 或 #话题标签 。' + show_collections: 人们将能够浏览你的关注和追随者。你关注的人会看到你关注他们。 + unlocked: 人们将能够在不请求批准的情况下关注你。如果你希望审核关注请求并选择接受或拒绝新的关注者,请取消勾选此项。 account_alias: acct: 指定你想要迁移过来的原账号:用户名@站点域名 account_migration: @@ -61,8 +61,8 @@ zh-CN: setting_display_media_hide_all: 始终隐藏媒体 setting_display_media_show_all: 始终显示媒体 setting_use_blurhash: 渐变是基于模糊后的隐藏内容生成的 - setting_use_pending_items: 关闭自动滚动更新,时间轴会在点击后更新 - username: 您只能使用字母、数字和下划线 + setting_use_pending_items: 点击查看时间线更新,而非自动滚动更新动态。 + username: 你只能使用字母、数字和下划线 whole_word: 如果关键词只包含字母和数字,将只在词语完全匹配时才会应用 domain_allow: domain: 该站点将能够从该服务器上拉取数据,并处理和存储收到的数据。 @@ -80,14 +80,14 @@ zh-CN: activity_api_enabled: 本站每周的嘟文数、活跃用户数和新注册用户数 app_icon: WEBP、PNG、GIF 或 JPG。使用自定义图标覆盖移动设备上的默认应用图标。 backups_retention_period: 用户可以生成其嘟文存档以供之后下载。当该值被设为正值时,这些存档将在指定的天数后自动从你的存储中删除。 - bootstrap_timeline_accounts: 这些账号将在新用户关注推荐中置顶。 + bootstrap_timeline_accounts: 这些账号将在新用户关注推荐中置顶显示。 closed_registrations_message: 在关闭注册时显示 content_cache_retention_period: 来自其它实例的所有嘟文(包括转嘟与回复)都将在指定天数后被删除,不论本实例用户是否与这些嘟文产生过交互。这包括被本实例用户喜欢和收藏的嘟文。实例间用户的私下提及也将丢失并无法恢复。此设置针对的是特殊用途的实例,用于一般用途时会打破许多用户的期望。 custom_css: 你可以为网页版 Mastodon 应用自定义样式。 favicon: WEBP、PNG、GIF 或 JPG。使用自定义图标覆盖 Mastodon 的默认图标。 mascot: 覆盖高级网页界面中的绘图形象。 media_cache_retention_period: 来自外站用户嘟文的媒体文件将被缓存到你的实例上。当该值被设为正值时,缓存的媒体文件将在指定天数后被清除。如果媒体文件在被清除后重新被请求,且源站内容仍然可用,它将被重新下载。由于链接预览卡拉取第三方站点的频率受到限制,建议将此值设置为至少 14 天,如果小于该值,链接预览卡将不会按需更新。 - peers_api_enabled: 此服务器在联邦宇宙中遇到的域名列表。 这里不包含关于您是否与给定服务器联合的数据,只是您的服务器知道它。 这由收集一般意义上的联邦统计信息的服务使用。 + peers_api_enabled: 此服务器在联邦宇宙中遇到的实例列表。 此处不包含关于您是否与给定服务器联合的数据,只是您的服务器知道它。 这由收集一般意义上的联邦统计信息的服务使用。 profile_directory: 个人资料目录会列出所有选择可被发现的用户。 require_invite_text: 当注册需要手动批准时,将“你为什么想要加入?”设为必填项 site_contact_email: 他人需要询恰法务或支持信息时的联络方式 @@ -99,7 +99,7 @@ zh-CN: status_page_url: 配置一个网址,当服务中断时,人们可以通过该网址查看服务器的状态。 theme: 给未登录访客和新用户使用的主题。 thumbnail: 与服务器信息一并展示的约 2:1 比例的图像。 - timeline_preview: 未登录访客将能够浏览服务器上最新的公共嘟文。 + timeline_preview: 未登录访客将能够浏览服务器上的最新公开嘟文。 trendable_by_default: 跳过对热门内容的手工审核。个别项目仍可在之后从趋势中删除。 trends: 热门页中会显示正在你服务器上受到关注的嘟文、标签和新闻故事。 trends_as_landing_page: 向注销的用户和访问者显示热门内容,而不是对该服务器的描述,需要启用热门。 @@ -125,12 +125,12 @@ zh-CN: otp: 输入你手机应用上生成的双因素认证代码,或者任意一个恢复代码: webauthn: 如果是 USB 密钥,请确保将其插入,如有必要,请点击它。 settings: - indexable: 您的个人资料页面可能会出现在Google、Bing等搜索结果中。 + indexable: 你的个人资料页面可能会出现在Google、Bing等搜索结果中。 show_application: 无论如何,你始终可以看到是哪个应用发布了你的嘟文。 tag: name: 你只能改变字母的大小写,让它更易读 user: - chosen_languages: 仅选中语言的嘟文会出现在公共时间轴上(全不选则显示所有语言的嘟文) + chosen_languages: 仅选中语言的嘟文会出现在公共时间线上(全不选则显示所有语言的嘟文) role: 角色用于控制用户拥有的权限。 user_role: color: 在界面各处用于标记该角色的颜色,以十六进制 RGB 格式表示 @@ -205,7 +205,7 @@ zh-CN: password: 密码 phrase: 关键词 setting_advanced_layout: 启用高级 Web 界面 - setting_aggregate_reblogs: 在时间轴中合并转嘟 + setting_aggregate_reblogs: 在时间线中合并转嘟 setting_always_send_emails: 总是发送电子邮件通知 setting_auto_play_gif: 自动播放 GIF 动画 setting_boost_modal: 在转嘟前询问我 @@ -247,7 +247,7 @@ zh-CN: activity_api_enabled: 在 API 中发布有关用户活动的汇总统计数据 app_icon: 应用图标 backups_retention_period: 用户存档保留期 - bootstrap_timeline_accounts: 推荐新用户关注以下账号 + bootstrap_timeline_accounts: 向新用户推荐以下账号 closed_registrations_message: 在关闭注册时显示的自定义消息 content_cache_retention_period: 外站内容保留期 custom_css: 自定义 CSS @@ -257,7 +257,7 @@ zh-CN: peers_api_enabled: 在API中公开的已知实例的服务器的列表 profile_directory: 启用用户目录 registrations_mode: 谁可以注册 - require_invite_text: 注册前需要提供理由 + require_invite_text: 注册时需要提供理由 show_domain_blocks: 显示域名屏蔽列表 show_domain_blocks_rationale: 显示域名屏蔽原因 site_contact_email: 联系邮箱 @@ -269,7 +269,7 @@ zh-CN: status_page_url: 状态页网址 theme: 默认主题 thumbnail: 本站缩略图 - timeline_preview: 时间轴预览 + timeline_preview: 允许未登录用户访问公共时间线 trendable_by_default: 允许在未审核的情况下将话题置为热门 trends: 启用热门 trends_as_landing_page: 使用热门页作为登陆页面 @@ -292,13 +292,13 @@ zh-CN: notification_emails: appeal: 有人对审核结果提出申诉 digest: 发送摘要邮件 - favourite: 当有用户喜欢了我的嘟文时,发送电子邮件提醒我 - follow: 有用户关注我时 - follow_request: 有用户向我发送关注请求时 - mention: 有用户提及我时 - pending_account: 有账号需要审核时 - reblog: 有用户转嘟我的嘟文时 - report: 新举报已提交 + favourite: 有用户喜欢了我的嘟文 + follow: 有人关注了我 + follow_request: 有人向我发送了关注请求 + mention: 有人提到了我 + pending_account: 有账号需要审核 + reblog: 有人转嘟了我的嘟文 + report: 有人提交了新举报 software_updates: all: 通知所有更新 critical: 仅在有关键更新时通知 @@ -311,7 +311,7 @@ zh-CN: text: 规则 settings: indexable: 允许搜索引擎索引个人资料页面 - show_application: 显示你发嘟所用的应用 + show_application: 显示 tag: listable: 允许这个话题标签在用户目录中显示 name: 话题标签 @@ -328,8 +328,8 @@ zh-CN: position: 优先级 webhook: events: 已启用事件 - template: 载荷模板 - url: 对端 URL + template: Payload 模板 + url: 端点 URL 'no': 否 not_recommended: 不推荐 overridden: 已覆盖 diff --git a/config/locales/simple_form.zh-HK.yml b/config/locales/simple_form.zh-HK.yml index dd134a58fb..c77de84e4a 100644 --- a/config/locales/simple_form.zh-HK.yml +++ b/config/locales/simple_form.zh-HK.yml @@ -9,7 +9,6 @@ zh-HK: indexable: 你的公開帖文可能會出現在 Mastodon 的搜尋結果中。無論如何,與你帖文互動過的人都能搜尋到它。 note: '你可以 @提及他人 或使用 #主題標籤。' show_collections: 大家可瀏覽你追蹤的人和你的追蹤者。你追蹤的人無論如何都會看到你追蹤了他們。 - unlocked: 大家毋須獲得批准即可追蹤你。如果你想審核追蹤請求,來接受或拒絕新追蹤者,請取消勾選。 account_alias: acct: 指定欲移動之帳戶的「使用者名稱@域名」 account_migration: diff --git a/config/locales/sk.yml b/config/locales/sk.yml index 6ef78a8f21..c946b8abf1 100644 --- a/config/locales/sk.yml +++ b/config/locales/sk.yml @@ -684,7 +684,6 @@ sk: open: Otvor príspevok original_status: Pôvodný príspevok status_changed: Príspevok bol zmenený - title: Príspevky na účte trending: Populárne visibility: Viditeľnosť with_media: S médiami diff --git a/config/locales/sl.yml b/config/locales/sl.yml index e9c06bcaa6..909b89e5a9 100644 --- a/config/locales/sl.yml +++ b/config/locales/sl.yml @@ -853,7 +853,6 @@ sl: original_status: Izvorna objava reblogs: Ponovljeni blogi status_changed: Objava spremenjena - title: Objave računa trending: V trendu visibility: Vidnost with_media: Z mediji diff --git a/config/locales/sq.yml b/config/locales/sq.yml index 980eff1aa5..e9247ef365 100644 --- a/config/locales/sq.yml +++ b/config/locales/sq.yml @@ -187,6 +187,7 @@ sq: create_domain_block: Krijo Bllokim Përkatësie create_email_domain_block: Krijoni Bllokim Përkatësie Email-esh create_ip_block: Krijoni Rregull IP + create_relay: Krijoni Rele create_unavailable_domain: Krijo Përkatësi të Papërdorshme create_user_role: Krijoni Rol demote_user: Zhgradoje Përdoruesin @@ -198,14 +199,17 @@ sq: destroy_email_domain_block: Fshini Bllokim Përkatësie Email-esh destroy_instance: Spastroje Përkatësinë destroy_ip_block: Fshini Rregull IP + destroy_relay: Fshije Relenë destroy_status: Fshi Gjendje destroy_unavailable_domain: Fshi Përkatësi të Papërdorshme destroy_user_role: Asgjësoje Rolin disable_2fa_user: Çaktivizo 2FA-në disable_custom_emoji: Çaktivizo Emotikon Vetjak + disable_relay: Çaktivizoje Relenë disable_sign_in_token_auth_user: Çaktivizoni për Përdoruesin Mirëfilltësim Me Token Email-i disable_user: Çaktivizo Përdorues enable_custom_emoji: Aktivizo Emotikon Vetjak + enable_relay: Aktivizoje Relenë enable_sign_in_token_auth_user: Aktivizoni për Përdoruesin Mirëfilltësim Me Token Email-i enable_user: Aktivizo Përdorues memorialize_account: Bëje Llogari Përkujtimore @@ -247,6 +251,7 @@ sq: create_domain_block_html: "%{name} bllokoi përkatësinë %{target}" create_email_domain_block_html: "%{name} bllokoi përkatësinë email %{target}" create_ip_block_html: "%{name} krijoi rregull për IP-në %{target}" + create_relay_html: "%{name} krijoi një rele %{target}" create_unavailable_domain_html: "%{name} ndali dërgimin drejt përkatësisë %{target}" create_user_role_html: "%{name} krijoi rolin %{target}" demote_user_html: "%{name} zhgradoi përdoruesin %{target}" @@ -258,14 +263,17 @@ sq: destroy_email_domain_block_html: "%{name} zhbllokoi përkatësi email %{target}" destroy_instance_html: "%{name} spastroi përkatësinë %{target}" destroy_ip_block_html: "%{name} fshiu rregull për IP-në %{target}" + destroy_relay_html: "%{name} fshiu relenë %{target}" destroy_status_html: "%{name} hoqi gjendje nga %{target}" destroy_unavailable_domain_html: "%{name} rinisi dërgimin drejt përkatësisë %{target}" destroy_user_role_html: "%{name} fshiu rolin %{target}" disable_2fa_user_html: "%{name} çaktivizoi domosdoshmërinë për dyfaktorësh për përdoruesin %{target}" disable_custom_emoji_html: "%{name} çaktivizoi emoxhin %{target}" + disable_relay_html: "%{name} çaktivizoi relenë %{target}" disable_sign_in_token_auth_user_html: "%{name} çaktivizoi mirëfilltësim me token email për %{target}" disable_user_html: "%{name} çaktivizoi hyrje për përdoruesin %{target}" enable_custom_emoji_html: "%{name} aktivizoi emoxhin %{target}" + enable_relay_html: "%{name} aktivizoi relenë %{target}" enable_sign_in_token_auth_user_html: "%{name} aktivizoi mirëfilltësim me token email për %{target}" enable_user_html: "%{name} aktivizoi hyrje për përdoruesin %{target}" memorialize_account_html: "%{name} e shndërroi llogarinë e %{target} në një faqe përkujtimore" @@ -645,6 +653,7 @@ sq: report: 'Raportim #%{id}' reported_account: Llogari e raportuar reported_by: Raportuar nga + reported_with_application: Raportuar me aplikacion resolved: I zgjidhur resolved_msg: Raportimi u zgjidh me sukses! skip_to_actions: Kaloni te veprimet @@ -814,8 +823,10 @@ sq: back_to_account: Mbrapsht te faqja e llogarisë back_to_report: Mbrapsht te faqja e raportimit batch: + add_to_report: 'Shtoje te raportimi #%{id}' remove_from_report: Hiqe prej raportimit report: Raportojeni + contents: Lëndë deleted: E fshirë favourites: Të parapëlqyer history: Historik versioni @@ -824,13 +835,17 @@ sq: media: title: Media metadata: Tejtëdhëna + no_history: Ky postim s’është përpunuar no_status_selected: S’u ndryshua ndonjë gjendje, ngaqë s’u përzgjodh ndonjë e tillë open: Hape postimin original_status: Postim origjinal reblogs: Riblogime + replied_to_html: Iu përgjigj %{acct_link} status_changed: Postimi ndryshoi - title: Gjendje llogarish + status_title: Postim nga @%{name} + title: Postime llogarie - @%{name} trending: Në modë + view_publicly: Shiheni publikisht visibility: Dukshmëri with_media: Me media strikes: diff --git a/config/locales/sr-Latn.yml b/config/locales/sr-Latn.yml index f56cdb9cb5..0b3043c47b 100644 --- a/config/locales/sr-Latn.yml +++ b/config/locales/sr-Latn.yml @@ -807,7 +807,6 @@ sr-Latn: original_status: Originalna objava reblogs: Deljenja status_changed: Objava promenjena - title: Statusi naloga trending: U trendu visibility: Vidljivost with_media: Sa multimedijom diff --git a/config/locales/sr.yml b/config/locales/sr.yml index 45feb0b5fc..e077a40eee 100644 --- a/config/locales/sr.yml +++ b/config/locales/sr.yml @@ -837,7 +837,6 @@ sr: original_status: Оригинална објава reblogs: Дељења status_changed: Објава промењена - title: Статуси налога trending: У тренду visibility: Видљивост with_media: Са мултимедијом diff --git a/config/locales/sv.yml b/config/locales/sv.yml index f3ce6443f6..173dd24c88 100644 --- a/config/locales/sv.yml +++ b/config/locales/sv.yml @@ -59,11 +59,11 @@ sv: delete: Radera data deleted: Raderad demote: Degradera - destroyed_msg: "%{username}'s data har nu lagts till kön för att raderas omedelbart" - disable: inaktivera + 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 - disabled: inaktiverad + disabled: Inaktiverad display_name: Visningsnamn domain: Domän edit: Redigera @@ -72,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 @@ -142,7 +142,7 @@ sv: only_password: Endast lösenord password_and_2fa: Lösenord och 2FA sensitive: Känsligt - sensitized: markerad som känsligt + sensitized: Markerad som känsligt shared_inbox_url: Delad inkorg URL show: created_reports: Anmälningar som skapats av det här kontot @@ -187,6 +187,7 @@ sv: create_domain_block: Skapa blockerad domän create_email_domain_block: Skapa E-post domän block create_ip_block: Skapa IP-regel + create_relay: Skapa ombud create_unavailable_domain: Skapa otillgänglig domän create_user_role: Skapa roll demote_user: Degradera användare @@ -198,14 +199,17 @@ sv: destroy_email_domain_block: Ta bort E-post domän block destroy_instance: Rensa domänen destroy_ip_block: Radera IP-regel + destroy_relay: Radera ombud destroy_status: Radera inlägg destroy_unavailable_domain: Ta bort otillgänglig domän destroy_user_role: Förstör roll disable_2fa_user: Inaktivera 2FA disable_custom_emoji: Inaktivera egna emojis + disable_relay: Inaktivera ombud disable_sign_in_token_auth_user: Inaktivera autentisering med pollett via e-post för användare disable_user: Inaktivera användare enable_custom_emoji: Aktivera egna emojis + enable_relay: Aktivera ombud enable_sign_in_token_auth_user: Aktivera autentisering med pollett via e-post för användare enable_user: Aktivera användare memorialize_account: Minnesmärk konto @@ -247,6 +251,7 @@ sv: create_domain_block_html: "%{name} blockerade domänen %{target}" create_email_domain_block_html: "%{name} blockerade e-post domänet%{target}" create_ip_block_html: "%{name} skapade regel för IP %{target}" + create_relay_html: "%{name} skapade ombudet %{target}" create_unavailable_domain_html: "%{name} stoppade leverans till domänen %{target}" create_user_role_html: "%{name} skapade rollen %{target}" demote_user_html: "%{name} nedgraderade användare %{target}" @@ -258,31 +263,34 @@ sv: destroy_email_domain_block_html: "%{name} avblockerade e-post domänet %{target}" destroy_instance_html: "%{name} rensade domän %{target}" destroy_ip_block_html: "%{name} tog bort regel för IP %{target}" + destroy_relay_html: "%{name} tog bort ombudet %{target}" destroy_status_html: "%{name} tog bort inlägget av %{target}" destroy_unavailable_domain_html: "%{name} återupptog leverans till domänen %{target}" 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_relay_html: "%{name} inaktiverade ombudet %{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_relay_html: "%{name} aktiverat ombudet %{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}" @@ -569,9 +577,9 @@ 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ä + add_new: Lägg till nytt ombud delete: Radera description_html: Ett federeringsombud är en mellanliggande server som utbyter höga antal offentliga inlägg mellan servrar som prenumererar på och publicerar till det. Det kan hjälpa små och medelstora servrar upptäcka innehåll från fediversumet, vilket annars skulle kräva att lokala användare manuellt följer personer på fjärrservrar. disable: Inaktivera @@ -582,10 +590,10 @@ sv: inbox_url: Ombuds-URL pending: Väntar på ombudets godkännande save_and_enable: Spara och aktivera - setup: Konfigurera en relä-anslutning - signatures_not_enabled: Ombud fungerar inte korrekt medan säkert läge eller begränsat federeringsläge är aktiverade + setup: Konfigurera ett ombud + signatures_not_enabled: Ombud fungerar inte korrekt om säkert läge eller begränsat federeringsläge är aktiverade status: Status - title: Relä + title: Ombud report_notes: created_msg: Anmälningsanteckning har skapats! destroyed_msg: Anmälningsanteckning har raderats! @@ -818,8 +826,10 @@ sv: back_to_account: Tillbaka till kontosidan back_to_report: Tillbaka till rapportsidan batch: + add_to_report: 'Lägg till i rapport #%{id}' remove_from_report: Ta bort från rapport report: Rapportera + contents: Innehåll deleted: Raderad favourites: Favoriter history: Versionshistorik @@ -828,15 +838,19 @@ sv: media: title: Media metadata: Metadata + no_history: Detta inlägg har inte redigerats no_status_selected: Inga inlägg ändrades eftersom inga valdes open: Öppna inlägg original_status: Ursprungligt inlägg reblogs: Ombloggningar + replied_to_html: Svarade på %{acct_link} status_changed: Inlägg ändrat - title: Kontoinlägg + status_title: Inlägg av @%{name} + title: Kontoinlägg - @%{name} trending: Trendande + view_publicly: Visa offentligt visibility: Synlighet - with_media: med media + with_media: Med media strikes: actions: delete_statuses: "%{name} raderade %{target}s inlägg" @@ -899,7 +913,7 @@ sv: review_requested: Granskning begärd reviewed: Granskat title: Status - trendable: + trendable: Kan trenda unreviewed: Ogranskad usable: Användbar name: Namn @@ -1494,7 +1508,7 @@ sv: 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: - acct: användarnamn@domän av det nya kontot + acct: Flyttad till cancel: Avbryt omdirigering cancel_explanation: Avstängning av omdirigeringen kommer att återaktivera ditt nuvarande konto, men kommer inte att återskapa följare som har flyttats till det kontot. cancelled_msg: Avbröt omdirigeringen. @@ -1703,7 +1717,7 @@ sv: ios: iOS kai_os: KaiOS linux: Linux - mac: Mac + mac: macOS unknown_platform: Okänd plattform windows: Windows windows_mobile: Windows Mobile @@ -1826,8 +1840,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: @@ -1879,7 +1893,7 @@ sv: subject: Andra faktorns autentiseringsfel title: Misslyckad tvåfaktorsautentisering suspicious_sign_in: - change_password: Ändra ditt lösenord + change_password: ändra ditt lösenord details: 'Här är inloggningsdetaljerna:' explanation: Vi har upptäckt en inloggning till ditt konto från en ny IP-adress. further_actions_html: Om detta inte var du, rekommenderar vi att du snarast %{action} och aktiverar tvåfaktorsautentisering för att hålla ditt konto säkert. diff --git a/config/locales/th.yml b/config/locales/th.yml index cdc56d98ce..5178506bab 100644 --- a/config/locales/th.yml +++ b/config/locales/th.yml @@ -819,7 +819,6 @@ th: original_status: โพสต์ดั้งเดิม reblogs: การดัน status_changed: เปลี่ยนโพสต์แล้ว - title: โพสต์ของบัญชี trending: กำลังนิยม visibility: การมองเห็น with_media: มีสื่อ @@ -1148,11 +1147,11 @@ th: use_security_key: ใช้กุญแจความปลอดภัย author_attribution: example_title: ข้อความตัวอย่าง - hint_html: คุณเขียนข่าวหรือลงบทความที่อื่นๆที่นอกจาก Mastodon บ้างไหม? ถ้าหากคุณเขียนอยู่ล่ะก็ คุณสามารถบอกได้นะว่าอยากให้คนอื่นให้เครดิตคุณยังไงเวลาแชร์ไปที่ Mastodon นะ - instructions: 'โปรดตรวจสอบให้แน่ใจว่าโค้ดนี้ได้มีอยู่ในบทความของคุณแล้ว HTML:' + hint_html: คุณกำลังเขียนข่าวหรือบทความบล็อกภายนอก Mastodon หรือไม่? ควบคุมวิธีที่คุณได้รับเครดิตเมื่อมีการแบ่งปันข่าวหรือบทความบล็อกใน Mastodon + instructions: 'ตรวจสอบให้แน่ใจว่าโค้ดนี้อยู่ใน HTML ของบทความของคุณ:' more_from_html: เพิ่มเติมจาก %{name} s_blog: บล็อกของ %{name} - then_instructions: จากนั้น ให้เพิ่มใส่ชื่อเว็บไซต์ของสิ่งพิมพ์ลงไปในช่องว่างข้างล่าง + then_instructions: จากนั้น เพิ่มชื่อโดเมนของการเผยแพร่ในช่องด้านล่าง title: การระบุแหล่งที่มาผู้สร้าง challenge: confirm: ดำเนินการต่อ diff --git a/config/locales/tr.yml b/config/locales/tr.yml index 942ee2fbf2..48f6c5e240 100644 --- a/config/locales/tr.yml +++ b/config/locales/tr.yml @@ -187,6 +187,7 @@ tr: create_domain_block: Engellenen Alan Adı Oluştur create_email_domain_block: E-Posta Alan Adı Engeli Oluştur create_ip_block: IP kuralı oluştur + create_relay: Aktarıcı Oluştur create_unavailable_domain: Mevcut Olmayan Alan Adı Oluştur create_user_role: Rol Oluştur demote_user: Kullanıcıyı Düşür @@ -198,14 +199,17 @@ tr: destroy_email_domain_block: E-posta Alan Adı Engelini Sil destroy_instance: Alan adını temizle destroy_ip_block: IP kuralını sil + destroy_relay: Aktarıcı Sil destroy_status: Durumu Sil destroy_unavailable_domain: Mevcut Olmayan Alan Adı Sil destroy_user_role: Rolü Kaldır disable_2fa_user: 2AD Kapat disable_custom_emoji: Özel İfadeyi Devre Dışı Bırak + disable_relay: Aktarıcıyı Devre Dışı Bırak disable_sign_in_token_auth_user: Kullanıcı için E-posta Token Doğrulamayı Devre Dışı Bırak disable_user: Kullanıcıyı Devre Dışı Bırak enable_custom_emoji: Özel İfadeyi Etkinleştir + enable_relay: Aktarıcıyı Etkinleştir enable_sign_in_token_auth_user: Kullanıcı için E-posta Token Doğrulamayı Etkinleştir enable_user: Kullanıcıyı Etkinleştir memorialize_account: Hesabı Anıtlaştır @@ -247,6 +251,7 @@ tr: create_domain_block_html: "%{name}, %{target} alan adını engelledi" create_email_domain_block_html: "%{name}, %{target} e-posta alan adını engelledi" create_ip_block_html: "%{name}, %{target} IP adresi için kural oluşturdu" + create_relay_html: "%{name}, %{target} aktarıcısını oluşturdu" create_unavailable_domain_html: "%{name}, %{target} alan adına teslimatı durdurdu" create_user_role_html: "%{name}, %{target} rolünü oluşturdu" demote_user_html: "%{name}, %{target} kullanıcısını düşürdü" @@ -258,14 +263,17 @@ tr: destroy_email_domain_block_html: "%{name}, %{target} e-posta alan adı engelini kaldırdı" destroy_instance_html: "%{name}, %{target} alan adını temizledi" destroy_ip_block_html: "%{name}, %{target} IP adresi kuralını sildi" + destroy_relay_html: "%{name}, %{target} aktarıcısını sildi" destroy_status_html: "%{name}, %{target} kullanıcısının gönderisini kaldırdı" destroy_unavailable_domain_html: "%{name}, %{target} alan adına teslimatı sürdürdü" destroy_user_role_html: "%{name}, %{target} rolünü sildi" disable_2fa_user_html: "%{name}, %{target} kullanıcısının iki aşamalı doğrulama gereksinimini kapattı" disable_custom_emoji_html: "%{name}, %{target} emojisini devre dışı bıraktı" + disable_relay_html: "%{name}, %{target} aktarıcısını devre dışı bıraktı" disable_sign_in_token_auth_user_html: "%{name}, %{target} için e-posta token doğrulamayı devre dışı bıraktı" disable_user_html: "%{name}, %{target} kullanıcısı için oturum açmayı devre dışı bıraktı" enable_custom_emoji_html: "%{name}, %{target} emojisini etkinleştirdi" + enable_relay_html: "%{name}, %{target} aktarıcısını etkinleştirdi" enable_sign_in_token_auth_user_html: "%{name}, %{target} için e-posta token doğrulamayı etkinleştirdi" enable_user_html: "%{name}, %{target} kullanıcısı için oturum açmayı etkinleştirdi" memorialize_account_html: "%{name}, %{target} kullanıcısının hesabını bir anıt sayfaya dönüştürdü" @@ -818,8 +826,10 @@ tr: back_to_account: Hesap sayfasına geri dön back_to_report: Bildirim sayfasına geri dön batch: + add_to_report: "#%{id} raporuna ekle" remove_from_report: Bildirimden kaldır report: Bildirim + contents: İçerikler deleted: Silindi favourites: Favoriler history: Sürüm geçmişi @@ -828,13 +838,17 @@ tr: media: title: Medya metadata: Üstveri + no_history: Bu gönderi düzenlenmemiş no_status_selected: Hiçbiri seçilmediğinden hiçbir durum değiştirilmedi open: Gönderiyi aç original_status: Özgün gönderi reblogs: Yeniden Paylaşımlar + replied_to_html: Yanıtladı %{acct_link} status_changed: Gönderi değişti - title: Hesap durumları + status_title: "@%{name} gönderisi" + title: Hesap gönderileri - @%{name} trending: Öne çıkanlar + view_publicly: Herkese açık görüntüle visibility: Görünürlük with_media: Medya ile strikes: diff --git a/config/locales/uk.yml b/config/locales/uk.yml index e6a765267f..68ca10c0cc 100644 --- a/config/locales/uk.yml +++ b/config/locales/uk.yml @@ -861,7 +861,6 @@ uk: original_status: Оригінальний допис reblogs: Поширення status_changed: Допис змінено - title: Дописи облікових записів trending: Популярне visibility: Видимість with_media: З медіа diff --git a/config/locales/vi.yml b/config/locales/vi.yml index 172ce55a3d..acc69f96cd 100644 --- a/config/locales/vi.yml +++ b/config/locales/vi.yml @@ -184,6 +184,7 @@ vi: create_domain_block: Chặn máy chủ create_email_domain_block: Chặn tên miền email create_ip_block: Chặn IP + create_relay: Tạo relay create_unavailable_domain: Bỏ liên hợp create_user_role: Tạo vai trò demote_user: Hạ vai trò @@ -195,14 +196,17 @@ vi: 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_relay: Xóa relay destroy_status: Xóa tút 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_relay: Tắt relay disable_sign_in_token_auth_user: Tắt xác minh bằng email cho người dùng disable_user: Vô hiệu hóa đăng nhập enable_custom_emoji: Cho phép emoji + enable_relay: Bật relay 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: Gán tưởng niệm @@ -244,6 +248,7 @@ vi: 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_relay_html: "%{name} đã tạo relay %{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}" @@ -255,14 +260,17 @@ vi: 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_relay_html: "%{name} đã xóa relay %{target}" destroy_status_html: "%{name} đã xóa tút của %{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_relay_html: "%{name} đã tắt relay %{target}" disable_sign_in_token_auth_user_html: "%{name} đã tắt xác minh email của %{target}" disable_user_html: "%{name} đã vô hiệu hóa đăng nhập %{target}" enable_custom_emoji_html: "%{name} đã cho phép emoji %{target}" + enable_relay_html: "%{name} đã bật relay %{target}" enable_sign_in_token_auth_user_html: "%{name} đã bật xác minh email của %{target}" enable_user_html: "%{name} đã bỏ vô hiệu hóa đăng nhập %{target}" memorialize_account_html: "%{name} đã biến tài khoản %{target} thành một trang tưởng niệm" @@ -804,8 +812,10 @@ vi: back_to_account: Quay lại trang tài khoản back_to_report: Quay lại trang báo cáo batch: + add_to_report: 'Thêm vào báo cáo #%{id}' remove_from_report: Xóa khỏi báo cáo report: Báo cáo + contents: Nội dung deleted: Đã xóa favourites: Lượt thích history: Lịch sử phiên bản @@ -814,13 +824,17 @@ vi: media: title: Media metadata: Metadata + no_history: Tút này chưa được chỉnh sửa no_status_selected: Bạn chưa chọn bất kỳ tút nào open: Mở tút original_status: Tút gốc reblogs: Lượt đăng lại + replied_to_html: Trả lời đến %{acct_link} status_changed: Tút đã sửa - title: Tất cả tút + status_title: Đăng bởi @%{name} + title: Tút từ tài khoản - @%{name} trending: Xu hướng + view_publicly: Xem công khai visibility: Hiển thị with_media: Có media strikes: diff --git a/config/locales/zh-CN.yml b/config/locales/zh-CN.yml index 209683e21c..1623f39ad6 100644 --- a/config/locales/zh-CN.yml +++ b/config/locales/zh-CN.yml @@ -10,7 +10,7 @@ zh-CN: followers: other: 关注者 following: 正在关注 - instance_actor_flash: 该账号用来代表虚拟角色,并不代表个人用户,仅代表服务器本身。该账号用于达成互联之目的,不应该被停用。 + instance_actor_flash: 该账号用来代表虚拟角色,并不代表个人用户,仅代表服务器本身。该账号用于联合目的,不应该被停用。 last_active: 最近活动 link_verified_on: 此链接的所有权已在 %{date} 检查 nothing_here: 空空如也! @@ -24,7 +24,7 @@ zh-CN: account_actions: action: 执行操作 already_silenced: 此账户已受限。 - already_suspended: 此帐户已被封禁。 + already_suspended: 此账户已被封禁。 title: 在 %{acct} 上执行管理操作 account_moderation_notes: create: 新建记录 @@ -86,9 +86,9 @@ zh-CN: title: 位置 login_status: 登录状态 media_attachments: 媒体文件 - memorialize: 设置为追悼账户 - memorialized: 被悼念 - memorialized_msg: 成功将 %{username} 转换为悼念账号 + memorialize: 设为追悼账户 + memorialized: 已设为追悼账户 + memorialized_msg: 成功将 %{username} 转换为追悼账户 moderation: active: 活跃 all: 全部 @@ -98,8 +98,8 @@ zh-CN: suspended: 已封禁 title: 管理 moderation_notes: 管理记录 - most_recent_activity: 最后一次活跃的时间 - most_recent_ip: 最后一次活跃的 IP 地址 + most_recent_activity: 最后活跃时间 + most_recent_ip: 最后活跃IP no_account_selected: 因为没有选中任何账号,所以没有更改 no_limits_imposed: 无限制 no_role_assigned: 未定角色 @@ -167,7 +167,7 @@ zh-CN: view_domain: 查看域名摘要 warn: 警告 web: 站内页面 - whitelisted: 允许跨站交互 + whitelisted: 允许联合 action_logs: action_types: approve_appeal: 批准申诉 @@ -184,6 +184,7 @@ zh-CN: create_domain_block: 封禁新域名 create_email_domain_block: 封禁新的邮箱域名 create_ip_block: 新建 IP 规则 + create_relay: 创建中继站 create_unavailable_domain: 创建不可用域名 create_user_role: 创建角色 demote_user: 给用户降职 @@ -195,17 +196,20 @@ zh-CN: destroy_email_domain_block: 解除邮箱域名封禁 destroy_instance: 删除实例 destroy_ip_block: 删除 IP 规则 + destroy_relay: 删除中继站 destroy_status: 删除嘟文 destroy_unavailable_domain: 删除不可用域名 destroy_user_role: 销毁角色 disable_2fa_user: 停用双因素认证 disable_custom_emoji: 禁用自定义表情符号 + disable_relay: 禁用中继站 disable_sign_in_token_auth_user: 为用户禁用邮件令牌身份验证 disable_user: 禁用用户 enable_custom_emoji: 启用自定义表情符号 + enable_relay: 启用中继站 enable_sign_in_token_auth_user: 为用户启用邮件令牌身份验证 enable_user: 启用用户 - memorialize_account: 将账户设为追悼模式 + memorialize_account: 设为追悼账户 promote_user: 给用户升任 reject_appeal: 驳回申诉 reject_user: 拒绝用户 @@ -240,29 +244,33 @@ zh-CN: create_announcement_html: "%{name} 创建了新公告 %{target}" create_canonical_email_block_html: "%{name} 封禁了 hash 为 %{target} 的邮箱地址" create_custom_emoji_html: "%{name} 添加了新的自定义表情 %{target}" - create_domain_allow_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} 为 IP %{target} 创建了规则" + create_relay_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} 解封了 hash 为 %{target} 的邮箱地址" destroy_custom_emoji_html: "%{name} 删除了自定义表情 %{target}" - destroy_domain_allow_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} 删除了 IP %{target} 的规则" + destroy_relay_html: "%{name} 删除了中继站 %{target}" destroy_status_html: "%{name} 删除了 %{target} 的嘟文" destroy_unavailable_domain_html: "%{name} 恢复了向域名 %{target} 的投递" destroy_user_role_html: "%{name} 删除了 %{target} 角色" disable_2fa_user_html: "%{name} 停用了用户 %{target} 的双因素认证" disable_custom_emoji_html: "%{name} 停用了自定义表情 %{target}" + disable_relay_html: "%{name} 停用了中继站 %{target}" disable_sign_in_token_auth_user_html: "%{name} 为 %{target} 禁用了邮件令牌身份验证" disable_user_html: "%{name} 将用户 %{target} 设置为禁止登录" enable_custom_emoji_html: "%{name} 启用了自定义表情 %{target}" + enable_relay_html: "%{name} 启用了中继站 %{target}" enable_sign_in_token_auth_user_html: "%{name} 为 %{target} 启用了邮件令牌身份验证" enable_user_html: "%{name} 将用户 %{target} 设置为允许登录" memorialize_account_html: "%{name} 将 %{target} 设置为追悼账户" @@ -293,7 +301,7 @@ zh-CN: empty: 没有找到日志 filter_by_action: 根据行为过滤 filter_by_user: 根据用户过滤 - title: 运营日志 + title: 审核日志 unavailable_instance: "(域名不可用)" announcements: destroyed_msg: 公告已删除! @@ -329,7 +337,7 @@ zh-CN: emoji: 表情 enable: 启用 enabled: 已启用 - enabled_msg: 表情启用成功 + enabled_msg: 已成功启用此表情 image_hint: 最大 %{size} 的 PNG 或 GIF list: 列表 listed: 已显示 @@ -342,7 +350,7 @@ zh-CN: shortcode_hint: 至少 2 个字符,只能使用字母、数字和下划线 title: 自定义表情 uncategorized: 未分类 - unlist: 不公开 + unlist: 隐藏 unlisted: 已隐藏 update_failed_msg: 表情更新失败 updated_msg: 表情更新成功! @@ -362,24 +370,24 @@ zh-CN: pending_users_html: other: "%{count} 个待处理用户" resolved_reports: 已处理的举报 - software: 软件 + software: 软件信息 sources: 注册来源 space: 存储使用情况 title: 信息面板 top_languages: 最活跃的语言 top_servers: 最活跃的服务器 - website: 网页端 + website: 网站 disputes: appeals: - empty: 没有发现申诉。 + empty: 未找到申诉。 title: 申诉 domain_allows: - add_new: 允许和域名跨站交互 - created_msg: 域名已被允许跨站交互 - destroyed_msg: 域名已被禁止跨站交互 + add_new: 允许与此实例联合 + created_msg: 实例已被允许联合 + destroyed_msg: 实例已被禁止联合 export: 导出 import: 导入 - undo: 不允许和该域名跨站交互 + undo: 禁止与此实例联合 domain_blocks: add_new: 添加新屏蔽域名 confirm_suspension: @@ -395,15 +403,15 @@ zh-CN: destroyed_msg: 域名屏蔽已撤销 domain: 域名 edit: 编辑域名屏蔽 - existing_domain_block: 您已经对 %{name} 设置了更严格的限制。 + existing_domain_block: 你已经对 %{name} 设置了更严格的限制。 existing_domain_block_html: 你已经对 %{name} 施加了更严格的限制,你需要先 解封。 export: 导出 import: 导入 new: create: 添加屏蔽 - hint: 域名屏蔽不会阻止该域名下的帐户进入本站的数据库,但是会对来自这个域名的帐户自动进行预先设置的管理操作。 + hint: 域名屏蔽不会阻止该域名下的账户进入本站的数据库,但是会对来自这个域名的账户自动进行预先设置的管理操作。 severity: - desc_html: 选择隐藏会将该域名下帐户发送的嘟文设置为仅关注者可见;选择封禁会将该域名下帐户发送的嘟文、媒体文件以及个人资料数据从本实例上删除;如果你只是想拒绝接收来自该域名的任何媒体文件,请选择。 + desc_html: 选择隐藏会将该域名下账户发送的嘟文设置为仅关注者可见;选择封禁会将该域名下账户发送的嘟文、媒体文件以及个人资料数据从本实例上删除;如果你只是想拒绝接收来自该域名的任何媒体文件,请选择。 noop: 无 silence: 隐藏 suspend: 封禁 @@ -448,9 +456,9 @@ zh-CN: no_file: 没有选择文件 export_domain_blocks: import: - description_html: 您即将导入域名列表,如果您不是此域名列表的作者,请仔细检查核对。 + description_html: 你即将导入域名列表,如果你不是此域名列表的作者,请仔细检查核对。 existing_relationships_warning: 现有的关注关系 - private_comment_description_html: 为了帮助您追踪域名列表来源,导入的域名列表将被添加如下的私人注释:%{comment} + private_comment_description_html: 为了帮助你追踪域名列表来源,导入的域名列表将被添加如下的私人注释:%{comment} private_comment_template: 从 %{source} 导入 %{date} title: 导入域名列表 invalid_domain_block: 由于以下错误,一个或多个域名屏蔽被跳过: %{error} @@ -486,7 +494,7 @@ zh-CN: content_policies: comment: 内部备注 description_html: 你可以设置应用于此域名所有账号和其所有子域名的内容策略。 - limited_federation_mode_description_html: 您可以选择是否允许与该联邦联合。 + limited_federation_mode_description_html: 你可以选择是否允许与此实例联合。 policies: reject_media: 拒收媒体 reject_reports: 拒收举报 @@ -521,7 +529,7 @@ zh-CN: moderation: all: 全部 limited: 受限的 - title: 运营 + title: 审核 private_comment: 私密评论 public_comment: 公开评论 purge: 删除 @@ -535,7 +543,7 @@ zh-CN: totals_time_period_hint_html: 下方显示的总数来自全部历史数据。 unknown_instance: 此服务器上目前没有此域名的记录。 invites: - deactivate_all: 撤销所有邀请链接 + deactivate_all: 全部停用 filter: all: 全部 available: 可用 @@ -555,7 +563,7 @@ zh-CN: '94670856': 3年 new: title: 创建新 IP 规则 - no_ip_block_selected: 因为没有 IP 规则被选中,所以没有更改 + no_ip_block_selected: 未选中任何 IP 规则,所以没有更改 title: IP 规则 relationships: title: "%{acct} 的关系" @@ -572,7 +580,7 @@ zh-CN: pending: 等待中继站的确认 save_and_enable: 保存并启用 setup: 设置中继连接 - signatures_not_enabled: 安全模式或限联模式启用时,中继将不会正常工作 + signatures_not_enabled: 安全模式或白名单模式启用时,中继站可能将不会正常工作 status: 状态 title: 中继站 report_notes: @@ -589,12 +597,12 @@ zh-CN: mark_as_sensitive_description_html: 被举报的嘟文将被标记为敏感,同时该账号将被标记一次处罚,以供未来同一账号再次违规时参考。 other_description_html: 查看更多控制该账号行为的选项,并自定义编写与被举报账号的通信。 resolve_description_html: 不会对被举报账号采取任何动作,举报将被关闭,也不会留下处罚记录。 - silence_description_html: 只有关注或手工搜索此账号才能查看其资料,将严重限制其触达范围。可随时撤销。关闭针对此帐户的所有举报。 - suspend_description_html: 该帐户及其所有内容将无法访问并最终被删除,且无法与该帐户进行互动。 在 30 天内可随时撤销。关闭针对此帐户的所有举报。 + silence_description_html: 只有关注或手工搜索此账号才能查看其资料,将严重限制其触达范围。可随时撤销。关闭针对此账户的所有举报。 + suspend_description_html: 该账户及其所有内容将无法访问并最终被删除,且无法与该账户进行互动。 在 30 天内可随时撤销。关闭针对此账户的所有举报。 actions_description_html: 决定采取何种措施处理此举报。如果对被举报账号采取惩罚性措施,将向其发送一封电子邮件通知。但若选中垃圾信息类别则不会发送通知。 - actions_description_remote_html: 决定采取何种行动来解决此举报。 这只会影响您的服务器如何与该远程帐户的通信并处理其内容。 + actions_description_remote_html: 决定采取何种行动来解决此举报。 这只会影响你的服务器如何与该远程账户的通信并处理其内容。 actions_no_posts: 该举报没有相关嘟文可供删除 - add_to_report: 增加更多举报内容 + add_to_report: 添加更多内容到举报 already_suspended_badges: local: 已在此服务器上被封禁 remote: 已在其所属服务器被封禁 @@ -614,7 +622,7 @@ zh-CN: delete_and_resolve: 删除嘟文 forwarded: 已转发 forwarded_replies_explanation: 该举报来自外站用户,涉及外站内容。之所以转发给你,是因为被举报的内容是对你站点一位用户的回复。 - forwarded_to: 转发举报至 %{domain} + forwarded_to: 转发举报到 %{domain} mark_as_resolved: 标记为已处理 mark_as_sensitive: 标记为敏感内容 mark_as_unresolved: 标记为未处理 @@ -622,7 +630,7 @@ zh-CN: notes: create: 添加记录 create_and_resolve: 添加记录并标记为“已处理” - create_and_unresolve: 添加记录并重开 + create_and_unresolve: 添加备注并重新打开 delete: 删除 placeholder: 描述已经执行的操作,或其他任何相关的跟进情况… title: 备注 @@ -643,20 +651,20 @@ zh-CN: statuses_description_html: 在与该账号的通信中将引用违规内容 summary: action_preambles: - delete_html: 您即将删除 @%{acct} 的一些嘟文。 这将: - mark_as_sensitive_html: 您即将 标记 @%{acct} 的帖一些子为 敏感。这将: - silence_html: 您即将限制 @%{acct} 的帐户。 这将: - suspend_html: 您即将暂停 @%{acct} 的帐户。 这将: + delete_html: 你即将删除 @%{acct} 的一些嘟文。 这将: + mark_as_sensitive_html: 你即将 标记 @%{acct} 的帖一些子为 敏感。这将: + silence_html: 你即将限制 @%{acct} 的账户。 这将: + suspend_html: 你即将暂停 @%{acct} 的账户。 这将: actions: delete_html: 删除违规嘟文 mark_as_sensitive_html: 将违规嘟文的媒体标记为敏感 silence_html: 严格限制 @%{acct} 的影响力,方法是让他们的个人资料和内容仅对已经关注他们的人可见,或手动查找其个人资料时 suspend_html: 暂停 @%{acct},使他们的个人资料和内容无法访问,也无法与之互动 - close_report: '将报告 #%{id} 标记为已解决' - close_reports_html: 将针对 @%{acct}所有 报告标记为已解决 + close_report: '将举报 #%{id} 标记为已解决' + close_reports_html: 将针对 @%{acct}所有举报标记为已解决 delete_data_html: 从现在起 30 天后删除 @%{acct} 的个人资料和内容,除非他们同时解除暂停。 preview_preamble_html: "@%{acct} 将收到包含以下内容的警告:" - record_strike_html: 记录一次针对 @%{acct} 的警示,以帮助您在这个帐户上的未来违规事件中得到重视。 + record_strike_html: 记录一次针对 @%{acct} 的警示,以帮助你在这个账户上的未来违规事件中得到重视。 send_email_html: 向 @%{acct} 发送警告邮件 warning_placeholder: 可选的补充理由,以说明调整的情况。 target_origin: 被举报账号的来源 @@ -677,7 +685,7 @@ zh-CN: moderation: 监察 special: 特殊 delete: 刪除 - description_html: 使用 用户角色,您可以自定义您的用户可以访问的功能和区域。 + description_html: 使用 用户角色,你可以自定义你的用户可以访问的功能和区域。 edit: 编辑 '%{name}' 角色 everyone: 默认权限 everyone_full_description_html: 这是影响到 所有用户基础角色,包括未指定角色的用户。 其他所有的角色都继承着它的权限。 @@ -698,7 +706,7 @@ zh-CN: manage_blocks_description: 允许用户屏蔽邮箱提供商和IP地址 manage_custom_emojis: 管理自定义表情 manage_custom_emojis_description: 允许用户管理服务器上的自定义表情 - manage_federation: 管理邦联 + manage_federation: 管理联合 manage_federation_description: 允许用户屏蔽或允许同其他域名的邦联,并控制消息投递能力 manage_invites: 管理邀请 manage_invites_description: 允许用户浏览和停用邀请链接 @@ -735,7 +743,7 @@ zh-CN: settings: about: manage_rules: 管理服务器规则 - preamble: 提供此服务器如何运营、资金状况等的深入信息。 + preamble: 提供此服务器如何运营、审核及资金状况等详细信息。 rules_hint: 有一个专门区域用于显示用户需要遵守的规则。 title: 关于本站 appearance: @@ -758,7 +766,7 @@ zh-CN: follow_recommendations: 关注推荐 preamble: 露出有趣的内容有助于新加入 Mastodon 的用户融入。可在这里控制多种发现功能如何在你的服务器上工作。 profile_directory: 个人资料目录 - public_timelines: 公共时间轴 + public_timelines: 公共时间线 publish_discovered_servers: 已公开实例的服务器 publish_statistics: 发布统计数据 title: 发现 @@ -766,7 +774,7 @@ zh-CN: domain_blocks: all: 对所有人 disabled: 不对任何人 - users: 对本地已登录用户 + users: 对已登录的本站用户 registrations: moderation_recommandation: 在向所有人开放注册之前,请确保你拥有一个人手足够且反应迅速的管理团队! preamble: 控制谁可以在你的服务器上创建账号。 @@ -781,7 +789,7 @@ zh-CN: authorized_fetch: 需要跨站认证 authorized_fetch_hint: 要求外站请求通过验证能够使用户级别与服务器级别的封锁更为严格。然而,这将带来额外的性能负担、减少回复触达范围、并可能导致与一些联邦宇宙服务的兼容性问题。此外,这并不能阻止他人针对性地获取公开嘟文与账户。 authorized_fetch_overridden_hint: 由于此设置被环境变量覆盖,目前无法更改。 - federation_authentication: 强制跨站认证 + federation_authentication: 联合时强制要求身份验证 title: 服务器设置 site_uploads: delete: 删除已上传的文件 @@ -801,11 +809,13 @@ zh-CN: statuses: account: 作者 application: 应用 - back_to_account: 返回帐户信息页 + back_to_account: 返回账户信息页 back_to_report: 返回举报页 batch: - remove_from_report: 从报告中移除 + add_to_report: '添加到举报 #%{id}' + remove_from_report: 从举报中移除 report: 举报 + contents: 内容 deleted: 已删除 favourites: 喜欢 history: 版本历史记录 @@ -814,13 +824,17 @@ zh-CN: media: title: 媒体文件 metadata: 元数据 + no_history: 此嘟文没有编辑历史 no_status_selected: 因为没有嘟文被选中,所以没有更改 open: 展开嘟文 original_status: 原始嘟文 reblogs: 转发 + replied_to_html: 回复给 %{acct_link} status_changed: 嘟文已编辑 - title: 帐户嘟文 + status_title: "@%{name} 的嘟文" + title: 该账号的嘟文 - @%{name} trending: 当前热门 + view_publicly: 以公开身份查看 visibility: 可见性 with_media: 含有媒体文件 strikes: @@ -952,7 +966,7 @@ zh-CN: tag_languages_dimension: 语言排行 tag_servers_dimension: 服务器排行 tag_servers_measure: 不同服务器 - tag_uses_measure: 总使用 + tag_uses_measure: 总使用次数 description_html: 这些是当前此服务器可见嘟文中大量出现的标签。它可以帮助用户发现其他人正关注的话题。在获得批准前不会公开显示任何标签。 listable: 可被推荐 no_tag_selected: 因为没有选中任何标签,所以没有更改 @@ -972,17 +986,17 @@ zh-CN: warning_presets: add_new: 添加新条目 delete: 删除 - edit_preset: 编辑预置警告 + edit_preset: 编辑预设警告 empty: 你尚未定义任何警告预设。 title: 预设警告 webhooks: - add_new: 新增对端 + add_new: 新增端点 delete: 删除 description_html: "Webhook 使 Mastodon 能够推送 关于所选事件的实时通知 到你自己的应用程序,进而由你的应用程序自动触发反应。" disable: 禁用 disabled: 已禁用 edit: 编辑对端 - empty: 你尚未配置任何 Webhook 对端。 + empty: 你尚未配置任何 Webhook 端点。 enable: 启用 enabled: 活跃 enabled_events: @@ -1035,14 +1049,14 @@ zh-CN: aliases: add_new: 创建别名 created_msg: 成功创建了一个新别名。你现在可以从旧账户开始迁移了。 - deleted_msg: 成功移除别名。已经无法从该帐户移动到此帐户了。 - empty: 你没有设置别名 + deleted_msg: 成功移除别名。已经无法从该账户移动到此账户了。 + empty: 你没有设置别名。 hint_html: 如果你想从另一个账号迁移到这里,可以先在这里创建一个别名。要把旧账号的关注者迁移过来,这一步是必须的。设置别名的操作是无害且可撤销的账号迁移的操作会从旧账号发起。 remove: 取消关联别名 appearance: advanced_web_interface: 高级 Web 界面 - advanced_web_interface_hint: 如果你想使用整个屏幕宽度,高级 web 界面允许您配置多个不同的栏目,可以同时看到更多的信息:主页、通知、跨站时间轴、任意数量的列表和话题标签。 - animations_and_accessibility: 动画和访问选项 + advanced_web_interface_hint: 如果你想使用整个屏幕宽度,高级 web 界面允许你配置多个不同的栏目,可以同时看到更多的信息:主页、通知、跨站时间线、任意数量的列表和话题标签。 + animations_and_accessibility: 动画与可访问性 confirmation_dialogs: 确认对话框 discovery: 发现 localization: @@ -1082,8 +1096,8 @@ zh-CN: registration_complete: 你在 %{domain} 上的注册现已完成! welcome_title: 欢迎你,%{name}! wrong_email_hint: 如果该邮箱地址不正确,你可以在账户设置中进行更改。 - delete_account: 删除帐户 - delete_account_html: 如果你想删除你的帐户,请点击这里继续。你需要确认你的操作。 + delete_account: 删除账户 + delete_account_html: 如果你想删除你的账户,请点击这里继续。你需要确认你的操作。 description: prefix_invited_by_user: "@%{name} 邀请你加入这个Mastodon服务器!" prefix_sign_up: 现在就注册 Mastodon! @@ -1103,8 +1117,8 @@ zh-CN: privacy_policy_agreement_html: 我已阅读并同意 隐私政策 progress: confirm: 确认邮箱 - details: 您的详情 - review: 我们的复审 + details: 你的详情 + review: 我们的审核 rules: 接受规则 providers: cas: CAS @@ -1120,21 +1134,21 @@ zh-CN: preamble: 这些由 %{domain} 监察员设置和执行。 preamble_invited: 在你继续之前,请考虑 %{domain} 的管理员设定的基本规则。 title: 一些基本规则。 - title_invited: 您已经被邀请。 + title_invited: 你已经被邀请。 security: 账户安全 set_new_password: 设置新密码 setup: email_below_hint_html: 请检查你的垃圾邮件文件夹,或请求再发送一次。如果你的邮箱地址不正确,你可以更正它。 - email_settings_hint_html: 请点击我们发送给 %{email} 地址中的确认链接。我在这儿等着您。 + email_settings_hint_html: 请点击我们发送给 %{email} 地址中的确认链接。我在这儿等着你。 link_not_received: 没有收到链接? new_confirmation_instructions_sent: 你将在几分钟内收到一封带有确认链接的新邮件! title: 请检查你的收件箱 sign_in: - preamble_html: 使用您在 %{domain} 的账户和密码登录。如果您的账户托管在其他的服务器上,您将无法在此登录。 + preamble_html: 使用你在 %{domain} 的账户和密码登录。如果你的账户托管在其他的服务器上,你将无法在此登录。 title: 登录到 %{domain} sign_up: - manual_review: 您在 %{domain} 上的注册需要经由管理人员手动审核。 为了帮助我们处理您的注册,请稍微介绍一下您为什么想在 %{domain} 上注册。 - preamble: 有了这个Mastodon服务器上的账户,您就可以关注Mastodon网络上的任何其他人,无论他们的账户在哪里。 + manual_review: 你在 %{domain} 上的注册需要经由管理人员手动审核。 为了帮助我们处理你的注册,请稍微介绍一下你为什么想在 %{domain} 上注册。 + preamble: 有了这个Mastodon服务器上的账户,你就可以关注Mastodon网络上的任何其他人,无论他们的账户在哪里。 title: 让我们在 %{domain} 上开始。 status: account_status: 账户状态 @@ -1149,7 +1163,7 @@ zh-CN: author_attribution: example_title: 示例文本 hint_html: 你是否在 Mastodon 之外撰写新闻或博客文章?控制它们被分享到 Mastodon 时的署名方式。 - instructions: 请确保将这段代码放在您文章的 HTML 中: + instructions: 请确保将这段代码放在你文章的 HTML 中: more_from_html: 来自 %{name} 的更多内容 s_blog: "%{name} 的博客" then_instructions: 然后,在下面的文本框中添加你用于发布文章的域名。 @@ -1210,7 +1224,7 @@ zh-CN: approve_appeal: 批准申诉 associated_report: 相关举报 created_at: 日期 - description_html: 这些是针对您的账户采取的行动和警告,已经由 %{instance} 的工作人员发送给您。 + description_html: 这些是针对你的账户采取的行动和警告,已经由 %{instance} 的工作人员发送给你。 recipient: 发送至 reject_appeal: 驳回申诉 status: '嘟文 #%{id}' @@ -1229,7 +1243,7 @@ zh-CN: your_appeal_rejected: 你的申诉已被驳回 edit_profile: basic_information: 基本信息 - hint_html: "自定义公开资料和嘟文旁边显示的内容。当您填写完整的个人资料并设置了头像时,其他人更有可能关注您并与您互动。" + hint_html: "自定义公开资料和嘟文旁边显示的内容。当你填写完整的个人资料并设置了头像时,其他人更有可能关注你并与你互动。" other: 其他 errors: '400': 你提交的请求无效或格式不正确。 @@ -1267,14 +1281,14 @@ zh-CN: featured_tags: add_new: 添加新条目 errors: - limit: 您所推荐的话题标签数已达上限 + limit: 你所推荐的话题标签数已达上限 hint_html: "什么是精选话题标签? 它们被显示在你的公开个人资料中的突出位置,人们可以在这些标签下浏览你的公共嘟文。 它们是跟踪创作或长期项目的进度的重要工具。" filters: contexts: account: 个人资料 - home: 主页时间轴 + home: 主页时间线 notifications: 通知 - public: 公共时间轴 + public: 公共时间线 thread: 对话 edit: add_keyword: 添加关键词 @@ -1313,7 +1327,7 @@ zh-CN: all_items_on_page_selected_html: other: 此页面上的所有 %{count} 项目已被选中。 all_matching_items_selected_html: - other: 所有 %{count} 匹配您搜索的项目都已被选中。 + other: 所有 %{count} 匹配你搜索的项目都已被选中。 cancel: 取消 changes_saved_msg: 更改保存成功! confirm: 确认 @@ -1324,7 +1338,7 @@ zh-CN: order_by: 排序方式 save_changes: 保存更改 select_all_matching_items: - other: 选择匹配您搜索的所有 %{count} 个项目。 + other: 选择匹配你搜索的所有 %{count} 个项目。 today: 今天 validation_errors: other: 出错啦!检查一下下面 %{count} 处出错的地方吧 @@ -1345,7 +1359,7 @@ zh-CN: overwrite_long: 将当前记录替换为新记录 overwrite_preambles: blocking_html: - other: 你即将使用来自 %{filename} 的最多 %{count} 个帐户替换你的屏蔽列表。 + other: 你即将使用来自 %{filename} 的最多 %{count} 个账户替换你的屏蔽列表。 bookmarks_html: other: 你即将使用来自 %{filename} 的最多 %{count} 条嘟文替换你的书签。 domain_blocking_html: @@ -1355,7 +1369,7 @@ zh-CN: lists_html: other: 你即将使用来自 %{filename} 的内容替换你的列表。最多将会有 %{count} 个账户 被添加到新列表。 muting_html: - other: 你即将使用来自 %{filename} 的最多 %{count} 个帐户替换你的已隐藏账户列表。 + other: 你即将使用来自 %{filename} 的最多 %{count} 个账户替换你的已隐藏账户列表。 preambles: blocking_html: other: 你即将屏蔽来自 %{filename} 的最多 %{count} 个账号。 @@ -1389,7 +1403,7 @@ zh-CN: type: 导入类型 type_groups: constructive: 关注和书签 - destructive: 屏蔽和隐藏 + destructive: 屏蔽与隐藏 types: blocking: 屏蔽列表 bookmarks: 书签 @@ -1422,14 +1436,14 @@ zh-CN: title: 邀请用户 lists: errors: - limit: 您已达到列表数量的上限 + limit: 你已达到列表数量的上限 login_activities: authentication_methods: otp: 双因素认证应用 password: 密码 sign_in_token: 邮件安全码 webauthn: 安全密钥 - description_html: 如有您无法识别的活动,请考虑更改密码并启用双因素认证。 + description_html: 如有你无法识别的活动,请考虑更改密码并启用双因素认证。 empty: 没有可用的认证记录 failed_sign_in_html: 失败的 %{method} 登录尝试,来自 %{ip} (%{browser}) successful_sign_in_html: 通过 %{method} 成功登录,来自 %{ip} (%{browser}) @@ -1487,7 +1501,7 @@ zh-CN: other_data: 不会自动移动其它数据 redirect: 在收到一个跳转通知后,你当前的账号资料将会更新,并被排除在搜索范围外 moderation: - title: 运营 + title: 审核 move_handler: carry_blocks_over_text: 这个用户迁移自你屏蔽过的 %{acct} carry_mutes_over_text: 这个用户由你隐藏过的 %{acct} 迁移而来 @@ -1515,7 +1529,7 @@ zh-CN: title: 新的关注请求 mention: action: 回复 - body: "%{name} 在嘟文中提到了你:" + body: "%{name} 提到了你:" subject: "%{name} 提到了你" title: 新的提及 poll: @@ -1571,13 +1585,13 @@ zh-CN: preferences: other: 其他 posting_defaults: 发布默认值 - public_timelines: 公共时间轴 + public_timelines: 公共时间线 privacy: hint_html: "自定义你希望如何找到你的个人资料和嘟文。启用Mastodon中的各种功能可以帮助你扩大受众范围。请花点时间查看这些设置,确保它们适合你的使用情况。" privacy: 隐私 privacy_hint_html: 控制你愿意向他人透露多少信息。通过浏览他人的关注列表和查看他们发嘟所用的应用,人们可以发现有趣的用户和酷炫的应用,但你可能更喜欢将其隐藏起来。 reach: 范围 - reach_hint_html: 控制您是否希望被新人发现和关注。您是否希望您的嘟文出现在“探索”页面上?您是否希望其他人在关注推荐中看到您?您是想自动接受所有新粉丝,还是对每个粉丝都进行仔细的筛选? + reach_hint_html: 控制你是否希望被新人发现和关注。你是否希望你的嘟文出现在“探索”页面上?你是否希望其他人在关注推荐中看到你?你是想自动接受所有新粉丝,还是对每个粉丝都进行仔细的筛选? search: 搜索 search_hint_html: 控制你希望被找到的方式。你想让人们通过你公开发布的内容来找到你吗?当在网络上搜索时,你是否希望Mastodon之外的人能够找到你的个人资料?请注意,我们无法保证完全排除所有搜索引擎对公开信息的索引。 title: 隐私与可达性 @@ -1585,16 +1599,16 @@ zh-CN: title: 隐私政策 reactions: errors: - limit_reached: 互动种类的限制 - unrecognized_emoji: 不是一个可识别的表情 + limit_reached: 回应种类个数超过限制 + unrecognized_emoji: 不是一个可被识别的表情 redirects: prompt: 如果你信任此链接,请单击以继续跳转。 title: 你正在离开 %{instance} 。 relationships: activity: 账号活动 - confirm_follow_selected_followers: 您确定想要关注所选的关注者吗? - confirm_remove_selected_followers: 您确定想要取关所选的关注者吗? - confirm_remove_selected_follows: 您确定要删除选定的关注着吗? + confirm_follow_selected_followers: 你确定想要关注所选的关注者吗? + confirm_remove_selected_followers: 你确定想要取关所选的关注者吗? + confirm_remove_selected_follows: 您确定要删除选定的关注者吗? dormant: 休眠 follow_failure: 无法关注选中的部分账户。 follow_selected_followers: 关注选中的关注者 @@ -1641,12 +1655,12 @@ zh-CN: generic: 未知浏览器 huawei_browser: 华为浏览器 ie: IE 浏览器 - micro_messenger: 微信 + micro_messenger: MicroMessenger nokia: Nokia S40 Ovi 浏览器 opera: 欧朋浏览器 otter: Otter phantom_js: PhantomJS - qq: QQ浏览器 + qq: QQ 浏览器 safari: Safari uc_browser: UC 浏览器 unknown_browser: 未知浏览器 @@ -1665,7 +1679,7 @@ zh-CN: ios: iOS kai_os: KaiOS linux: Linux - mac: Mac + mac: macOS unknown_platform: 未知平台 windows: Windows windows_mobile: Windows Mobile @@ -1685,17 +1699,17 @@ zh-CN: development: 开发 edit_profile: 更改个人资料 export: 导出 - featured_tags: 精选的话题标签 + featured_tags: 精选话题标签 import: 导入 - import_and_export: 导入和导出 + import_and_export: 导入与导出 migrate: 账户迁移 notifications: 邮件通知 - preferences: 首选项 + preferences: 偏好设置 profile: 个人资料 relationships: 关注管理 severed_relationships: 已断开的关系 statuses_cleanup: 自动删除嘟文 - strikes: 操作记录 + strikes: 管理处罚记录 two_factor_authentication: 双因素认证 webauthn_authentication: 安全密钥 severed_relationships: @@ -1729,7 +1743,7 @@ zh-CN: over_character_limit: 超过了 %{max} 字的限制 pin_errors: direct: 仅对被提及的用户可见的帖子不能被置顶 - limit: 你所固定的嘟文数量已达到上限 + limit: 你置顶的嘟文数量已达上限 ownership: 不能置顶别人的嘟文 reblog: 不能置顶转嘟 title: "%{name}:“%{quote}”" @@ -1738,14 +1752,14 @@ zh-CN: private: 仅关注者 private_long: 只有关注你的用户能看到 public: 公开 - public_long: 所有人可见,并会出现在公共时间轴上 - unlisted: 不公开 - unlisted_long: 所有人可见,但不会出现在公共时间轴上 + public_long: 所有人可见,并会出现在公共时间线上 + unlisted: 悄悄公开 + unlisted_long: 对所有人可见,但不出现在公共时间线上 statuses_cleanup: enabled: 自动删除旧嘟文 - enabled_hint: 达到指定过期时间后自动删除您的嘟文,除非满足下列条件之一 + enabled_hint: 达到指定过期时间后自动删除你的嘟文,除非满足下列条件之一 exceptions: 例外 - explanation: 删除嘟文是一个消耗系统资源的耗时操作,所以这个操作会在服务器空闲时完成。因此,您的嘟文可能会在达到过期阈值之后一段时间才会被删除。 + explanation: 删除嘟文是一个消耗系统资源的耗时操作,所以这个操作会在服务器空闲时完成。因此,你的嘟文可能会在达到过期阈值之后一段时间才会被删除。 ignore_favs: 取消喜欢 ignore_reblogs: 忽略转嘟 interaction_exceptions: 基于互动的例外 @@ -1784,10 +1798,10 @@ zh-CN: tags: does_not_match_previous_name: 和之前的名称不匹配 themes: - contrast: Mastodon(高对比度) - default: Mastodon(暗色主题) - mastodon-light: Mastodon(亮色主题) - system: 自动切换(使用系统主题) + contrast: Mastodon (高对比度) + default: Mastodon (暗色) + mastodon-light: Mastodon (亮色) + system: 自动切换 (使用系统主题) time: formats: default: "%Y年%m月%d日 %H:%M" @@ -1839,10 +1853,10 @@ zh-CN: suspicious_sign_in: change_password: 更改密码 details: 以下是该次登录的详细信息: - explanation: 我们检测到有新 IP 地址登录了您的账号。 - further_actions_html: 如果不是您本人操作,我们建议您立即 %{action} 并启用双因素认证,以确保账号安全。 - subject: 已有新 IP 地址访问了您的账号 - title: 新登录 + explanation: 我们检测到有新 IP 地址登录了你的账号。 + further_actions_html: 如果不是你本人操作,我们建议你立即 %{action} 并启用双因素认证,以确保账号安全。 + subject: 已有新 IP 地址访问了你的账号 + title: 一次新登录 warning: appeal: 提交申诉 appeal_description: 如果你认为此结果有误,可以向 %{instance} 的工作人员提交申诉。 @@ -1887,7 +1901,7 @@ zh-CN: explanation: 下面是几个小贴士,希望它们能帮到你 feature_action: 了解更多 feature_audience: Mastodon 为你提供了无需中间商即可管理受众的独特可能。Mastodon 可被部署在你自己的基础设施上,允许你关注其它任何 Mastodon 在线服务器的用户,或被任何其他在线 Mastodon 服务器的用户关注,并且不受你之外的任何人控制。 - feature_audience_title: 放手去建立起你的受众 + feature_audience_title: 自由吸引你的受众 feature_control: 你最清楚你想在你自己的主页中看到什么动态。没有算法或广告浪费你的时间。你可以用一个账号关注任何 Mastodon 服务器上的任何人,并按时间顺序获得他们发布的嘟文,让你的互联网的角落更合自己的心意。 feature_control_title: 掌控自己的时间线 feature_creativity: Mastodon 支持音频、视频和图片、无障碍描述、投票、内容警告, 动画头像、自定义表情包、缩略图裁剪控制等功能,帮助你在网上尽情表达自己。无论你是要发布你的艺术作品、音乐还是播客,Mastodon 都能为你服务。 diff --git a/config/locales/zh-HK.yml b/config/locales/zh-HK.yml index e33ebeadb4..752c9b5cbf 100644 --- a/config/locales/zh-HK.yml +++ b/config/locales/zh-HK.yml @@ -777,7 +777,6 @@ zh-HK: original_status: 原始帖文 reblogs: 轉發 status_changed: 帖文已變更 - title: 帳戶文章 trending: 熱門 visibility: 可見性 with_media: 含有媒體檔案 diff --git a/config/locales/zh-TW.yml b/config/locales/zh-TW.yml index d8fef10816..701ea0ea53 100644 --- a/config/locales/zh-TW.yml +++ b/config/locales/zh-TW.yml @@ -184,6 +184,7 @@ zh-TW: create_domain_block: 新增網域封鎖 create_email_domain_block: 新增電子郵件網域封鎖 create_ip_block: 新增IP規則 + create_relay: 新增中繼 create_unavailable_domain: 新增無法存取的網域 create_user_role: 新增角色 demote_user: 將用戶降級 @@ -195,14 +196,17 @@ zh-TW: destroy_email_domain_block: 刪除電子郵件網域封鎖 destroy_instance: 清除網域 destroy_ip_block: 刪除 IP 規則 + destroy_relay: 刪除中繼 destroy_status: 刪除狀態 destroy_unavailable_domain: 刪除無法存取的網域 destroy_user_role: 移除角色 disable_2fa_user: 停用兩階段驗證 disable_custom_emoji: 停用自訂 emoji 表情符號 + disable_relay: 停用中繼 disable_sign_in_token_auth_user: 停用使用者電子郵件 token 驗證 disable_user: 停用帳號 enable_custom_emoji: 啟用自訂 emoji 表情符號 + enable_relay: 啟用中繼 enable_sign_in_token_auth_user: 啟用使用者電子郵件 token 驗證 enable_user: 啓用帳號 memorialize_account: 設定成追悼帳號 @@ -244,6 +248,7 @@ zh-TW: create_domain_block_html: "%{name} 已封鎖網域 %{target}" create_email_domain_block_html: "%{name} 已封鎖電子郵件網域 %{target}" create_ip_block_html: "%{name} 已設定 IP %{target} 的規則" + create_relay_html: "%{name} 已新增中繼 %{target}" create_unavailable_domain_html: "%{name} 停止發送至網域 %{target}" create_user_role_html: "%{name} 已新增 %{target} 角色" demote_user_html: "%{name} 將使用者 %{target} 降級" @@ -255,14 +260,17 @@ zh-TW: destroy_email_domain_block_html: "%{name} 已解除封鎖電子郵件網域 %{target}" destroy_instance_html: "%{name} 已清除網域 %{target}" destroy_ip_block_html: "%{name} 已刪除 IP %{target} 的規則" + destroy_relay_html: "%{name} 已刪除中繼 %{target}" destroy_status_html: "%{name} 已刪除 %{target} 的嘟文" destroy_unavailable_domain_html: "%{name} 已恢復對網域 %{target} 的發送" destroy_user_role_html: "%{name} 已刪除 %{target} 角色" disable_2fa_user_html: "%{name} 已停用使用者 %{target} 的兩階段驗證 (2FA) " disable_custom_emoji_html: "%{name} 已停用自訂 emoji 表情符號 %{target}" + disable_relay_html: "%{name} 已停用中繼 %{target}" disable_sign_in_token_auth_user_html: "%{name} 已停用 %{target} 之使用者電子郵件 token 驗證" disable_user_html: "%{name} 將使用者 %{target} 設定為禁止登入" enable_custom_emoji_html: "%{name} 已啟用自訂 emoji 表情符號 %{target}" + enable_relay_html: "%{name} 已啟用中繼 %{target}" enable_sign_in_token_auth_user_html: "%{name} 已啟用 %{target} 之使用者電子郵件 token 驗證" enable_user_html: "%{name} 將使用者 %{target} 設定為允許登入" memorialize_account_html: "%{name} 將 %{target} 設定為追悼帳號" @@ -560,7 +568,7 @@ zh-TW: relationships: title: "%{acct} 的關係" relays: - add_new: 新增中繼站 + add_new: 新增中繼 delete: 刪除 description_html: "聯邦中繼站 是種中繼伺服器,會於訂閱並推送至此中繼站的伺服器之間交換大量的公開嘟文。中繼站也能協助小型或中型伺服器自聯邦宇宙中探索內容,而無須本地使用者手動跟隨遠端伺服器的其他使用者。" disable: 停用 @@ -806,8 +814,10 @@ zh-TW: back_to_account: 返回帳號資訊頁面 back_to_report: 回到檢舉報告頁面 batch: + add_to_report: '新增至報告 #%{id}' remove_from_report: 自檢舉報告中移除 report: 檢舉報告 + contents: 內容 deleted: 已刪除 favourites: 最愛 history: 版本紀錄 @@ -816,13 +826,17 @@ zh-TW: media: title: 媒體檔案 metadata: 詮釋資料 + no_history: 此嘟文未曾被編輯 no_status_selected: 因未選取嘟文,所以什麼事都沒發生。 open: 公開嘟文 original_status: 原始嘟文 reblogs: 轉嘟 + replied_to_html: 回覆給 %{acct_link} status_changed: 嘟文已編輯 - title: 帳號嘟文 + status_title: 由 @%{name} 發嘟 + title: 嘟文帳號 - @%{name} trending: 熱門 + view_publicly: 公開檢視 visibility: 可見性 with_media: 含有媒體檔案 strikes: diff --git a/config/mastodon.yml b/config/mastodon.yml new file mode 100644 index 0000000000..2c09c59e0a --- /dev/null +++ b/config/mastodon.yml @@ -0,0 +1,4 @@ +--- +shared: + self_destruct_value: <%= ENV.fetch('SELF_DESTRUCT', nil) %> + software_update_url: <%= ENV.fetch('UPDATE_CHECK_URL', 'https://api.joinmastodon.org/update-check') %> diff --git a/config/navigation.rb b/config/navigation.rb index 7ec7ecb7e7..bdda569092 100644 --- a/config/navigation.rb +++ b/config/navigation.rb @@ -6,7 +6,11 @@ SimpleNavigation::Configuration.run do |navigation| navigation.items do |n| n.item :web, safe_join([material_symbol('chevron_left'), t('settings.back')]), root_path - n.item :software_updates, safe_join([material_symbol('report'), t('admin.critical_update_pending')]), admin_software_updates_path, if: -> { ENV['UPDATE_CHECK_URL'] != '' && current_user.can?(:view_devops) && SoftwareUpdate.urgent_pending? }, html: { class: 'warning' } + n.item :software_updates, + safe_join([material_symbol('report'), t('admin.critical_update_pending')]), + admin_software_updates_path, + if: -> { Rails.configuration.x.mastodon.software_update_url.present? && current_user.can?(:view_devops) && SoftwareUpdate.urgent_pending? }, + html: { class: 'warning' } n.item :profile, safe_join([material_symbol('person'), t('settings.profile')]), settings_profile_path, if: -> { current_user.functional? && !self_destruct }, highlights_on: %r{/settings/profile|/settings/featured_tags|/settings/verification|/settings/privacy} diff --git a/config/routes/admin.rb b/config/routes/admin.rb index 3dba6fa5b8..2afe570236 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 57ce3ba9fd..86e41a2abe 100644 --- a/config/routes/api.rb +++ b/config/routes/api.rb @@ -44,15 +44,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 @@ -223,7 +225,7 @@ namespace :api, format: false do resources :featured_tags, only: [:index, :create, :destroy] - resources :polls, only: [:create, :show] do + resources :polls, only: [:show] do resources :votes, only: :create, module: :polls end diff --git a/config/settings.yml b/config/settings.yml index 297bf0281d..673a4c1be2 100644 --- a/config/settings.yml +++ b/config/settings.yml @@ -21,14 +21,27 @@ defaults: &defaults trends_as_landing_page: true trendable_by_default: false reserved_usernames: + - abuse + - account + - accounts - admin - - support - - help - - root - - webmaster + - administration - administrator + - admins + - help + - helpdesk + - instance - mod - moderator + - moderators + - mods + - owner + - root + - security + - server + - staff + - support + - webmaster disallowed_hashtags: # space separated string or list of hashtags without the hash bootstrap_timeline_accounts: '' activity_api_enabled: true 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 bea9ad46be..30b16a8a82 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_22_214312) do +ActiveRecord::Schema[7.2].define(version: 2024_11_04_082851) do # These are extensions that must be enabled in order to support this database enable_extension "plpgsql" @@ -260,6 +260,13 @@ ActiveRecord::Schema[7.1].define(version: 2024_10_22_214312) 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 diff --git a/dist/nginx.conf b/dist/nginx.conf index 5bb9903864..3ab9bb66a2 100644 --- a/dist/nginx.conf +++ b/dist/nginx.conf @@ -63,6 +63,7 @@ server { gzip_buffers 16 8k; gzip_http_version 1.1; gzip_types text/plain text/css application/json application/javascript text/xml application/xml application/xml+rss text/javascript image/svg+xml image/x-icon; + gzip_static on; location / { try_files $uri @proxy; diff --git a/docker-compose.yml b/docker-compose.yml index eab6a87cc3..42288207b3 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -59,7 +59,7 @@ services: web: # You can uncomment the following line if you want to not use the prebuilt image, for example if you have local code changes # build: . - image: ghcr.io/mastodon/mastodon:v4.3.0 + image: ghcr.io/mastodon/mastodon:v4.3.1 restart: always env_file: .env.production command: bundle exec puma -C config/puma.rb @@ -83,7 +83,7 @@ services: # build: # dockerfile: ./streaming/Dockerfile # context: . - image: ghcr.io/mastodon/mastodon-streaming:v4.3.0 + image: ghcr.io/mastodon/mastodon-streaming:v4.3.1 restart: always env_file: .env.production command: node ./streaming/index.js @@ -101,7 +101,7 @@ services: sidekiq: build: . - image: ghcr.io/mastodon/mastodon:v4.3.0 + image: ghcr.io/mastodon/mastodon:v4.3.1 restart: always env_file: .env.production command: bundle exec sidekiq 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/exceptions.rb b/lib/exceptions.rb index 1910d37a13..135f8126a4 100644 --- a/lib/exceptions.rb +++ b/lib/exceptions.rb @@ -8,7 +8,6 @@ module Mastodon class LengthValidationError < ValidationError; end class DimensionsValidationError < ValidationError; end class StreamValidationError < ValidationError; end - class FilterValidationError < ValidationError; end class RaceConditionError < Error; end class RateLimitExceededError < Error; end class SyntaxError < Error; end diff --git a/lib/mastodon/cli/accounts.rb b/lib/mastodon/cli/accounts.rb index 23c907543f..41127741ef 100644 --- a/lib/mastodon/cli/accounts.rb +++ b/lib/mastodon/cli/accounts.rb @@ -164,7 +164,7 @@ module Mastodon::CLI user.disabled = false if options[:enable] user.disabled = true if options[:disable] user.approved = true if options[:approve] - user.otp_required_for_login = false if options[:disable_2fa] + user.disable_two_factor! if options[:disable_2fa] if user.save user.confirm if options[:confirm] @@ -321,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..0cc9ccb705 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 @@ -43,12 +45,7 @@ module Mastodon::CLI end other_domains = [] - if options[:with_dns_records] - Resolv::DNS.open do |dns| - dns.timeouts = 5 - other_domains = dns.getresources(@email_domain_block.domain, Resolv::DNS::Resource::IN::MX).to_a - end - end + other_domains = DomainResource.new(domain).mx if options[:with_dns_records] email_domain_block = EmailDomainBlock.new(domain: domain, other_domains: other_domains) email_domain_block.save! 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/federation.rb b/lib/mastodon/cli/federation.rb index c738796557..f512bca358 100644 --- a/lib/mastodon/cli/federation.rb +++ b/lib/mastodon/cli/federation.rb @@ -76,7 +76,7 @@ module Mastodon::CLI def self_destruct_value Rails .application - .message_verifier('self-destruct') + .message_verifier(SelfDestructHelper::VERIFY_PURPOSE) .generate(Rails.configuration.x.local_domain) 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/mastodon/cli/statuses.rb b/lib/mastodon/cli/statuses.rb index f441dbcd84..7104181e97 100644 --- a/lib/mastodon/cli/statuses.rb +++ b/lib/mastodon/cli/statuses.rb @@ -40,17 +40,11 @@ module Mastodon::CLI def remove_statuses return if options[:skip_status_remove] - say('Creating temporary database indices...') - - ActiveRecord::Base.connection.add_index(:media_attachments, :remote_url, name: :index_media_attachments_remote_url, where: 'remote_url is not null', algorithm: :concurrently, if_not_exists: true) - - max_id = Mastodon::Snowflake.id_at(options[:days].days.ago, with_random: false) start_at = Time.now.to_f - unless options[:continue] && ActiveRecord::Base.connection.table_exists?('statuses_to_be_deleted') - ActiveRecord::Base.connection.add_index(:accounts, :id, name: :index_accounts_local, where: 'domain is null', algorithm: :concurrently, if_not_exists: true) - ActiveRecord::Base.connection.add_index(:status_pins, :status_id, name: :index_status_pins_status_id, algorithm: :concurrently, if_not_exists: true) + max_id = Mastodon::Snowflake.id_at(options[:days].days.ago, with_random: false) + unless options[:continue] && ActiveRecord::Base.connection.table_exists?('statuses_to_be_deleted') say('Extract the deletion target from statuses... This might take a while...') ActiveRecord::Base.connection.create_table('statuses_to_be_deleted', force: true) @@ -72,9 +66,6 @@ module Mastodon::CLI SQL say('Removing temporary database indices to restore write performance...') - - ActiveRecord::Base.connection.remove_index(:accounts, name: :index_accounts_local, if_exists: true) - ActiveRecord::Base.connection.remove_index(:status_pins, name: :index_status_pins_status_id, if_exists: true) end say('Beginning statuses removal... This might take a while...') @@ -102,12 +93,6 @@ module Mastodon::CLI ActiveRecord::Base.connection.drop_table('statuses_to_be_deleted') say("Done after #{Time.now.to_f - start_at}s, removed #{removed} out of #{processed} statuses.", :green) - ensure - say('Removing temporary database indices to restore write performance...') - - ActiveRecord::Base.connection.remove_index(:accounts, name: :index_accounts_local, if_exists: true) - ActiveRecord::Base.connection.remove_index(:status_pins, name: :index_status_pins_status_id, if_exists: true) - ActiveRecord::Base.connection.remove_index(:media_attachments, name: :index_media_attachments_remote_url, if_exists: true) end def remove_orphans_media_attachments diff --git a/lib/mastodon/version.rb b/lib/mastodon/version.rb index 88aa515296..f132c3a548 100644 --- a/lib/mastodon/version.rb +++ b/lib/mastodon/version.rb @@ -70,6 +70,10 @@ module Mastodon end end + def source_commit + ENV.fetch('SOURCE_COMMIT', nil) + end + def user_agent @user_agent ||= "Mastodon/#{Version} (#{HTTP::Request::USER_AGENT}; +http#{Rails.configuration.x.use_https ? 's' : ''}://#{Rails.configuration.x.web_domain}/)" end diff --git a/lib/paperclip/vips_lazy_thumbnail.rb b/lib/paperclip/vips_lazy_thumbnail.rb index 4764b04af8..fea4b86064 100644 --- a/lib/paperclip/vips_lazy_thumbnail.rb +++ b/lib/paperclip/vips_lazy_thumbnail.rb @@ -52,6 +52,7 @@ module Paperclip # implement. If cropping ever becomes necessary for other situations, this will # need to be expanded. crop_width = crop_height = [target_width, target_height].min if @target_geometry&.square? + crop_width = crop_height = "'min(iw,ih)'" if crop_width == 'ih' filter = begin if @crop diff --git a/lib/tasks/annotate_rb.rake b/lib/tasks/annotate_rb.rake new file mode 100644 index 0000000000..e8368b2e94 --- /dev/null +++ b/lib/tasks/annotate_rb.rake @@ -0,0 +1,10 @@ +# frozen_string_literal: true + +# This rake task was added by annotate_rb gem. + +# Can set `ANNOTATERB_SKIP_ON_DB_TASKS` to be anything to skip this +if Rails.env.development? && ENV['ANNOTATERB_SKIP_ON_DB_TASKS'].nil? + require 'annotate_rb' + + AnnotateRb::Core.load_rake_tasks +end diff --git a/lib/tasks/auto_annotate_models.rake b/lib/tasks/auto_annotate_models.rake deleted file mode 100644 index 4b5997920a..0000000000 --- a/lib/tasks/auto_annotate_models.rake +++ /dev/null @@ -1,46 +0,0 @@ -# frozen_string_literal: true - -if Rails.env.development? - task :set_annotation_options do - Annotate.set_defaults( - 'routes' => 'false', - 'models' => 'true', - 'position_in_routes' => 'before', - 'position_in_class' => 'before', - 'position_in_test' => 'before', - 'position_in_fixture' => 'before', - 'position_in_factory' => 'before', - 'position_in_serializer' => 'before', - 'show_foreign_keys' => 'false', - 'show_indexes' => 'false', - 'simple_indexes' => 'false', - 'model_dir' => 'app/models', - 'root_dir' => '', - 'include_version' => 'false', - 'require' => '', - 'exclude_tests' => 'true', - 'exclude_fixtures' => 'true', - 'exclude_factories' => 'true', - 'exclude_serializers' => 'true', - 'exclude_scaffolds' => 'true', - 'exclude_controllers' => 'true', - 'exclude_helpers' => 'true', - 'ignore_model_sub_dir' => 'false', - 'ignore_columns' => nil, - 'ignore_routes' => nil, - 'ignore_unknown_models' => 'false', - 'hide_limit_column_types' => 'integer,boolean', - 'skip_on_db_migrate' => 'false', - 'format_bare' => 'true', - 'format_rdoc' => 'false', - 'format_markdown' => 'false', - 'sort' => 'false', - 'force' => 'false', - 'trace' => 'false', - 'wrapper_open' => nil, - 'wrapper_close' => nil - ) - end - - Annotate.load_tasks -end 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 f907dc4f6c..4eb95d4389 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "@mastodon/mastodon", "license": "AGPL-3.0-or-later", - "packageManager": "yarn@4.5.1", + "packageManager": "yarn@4.5.2", "engines": { "node": ">=18" }, diff --git a/spec/controllers/api/base_controller_spec.rb b/spec/controllers/api/base_controller_spec.rb index 1e0e7c8f4d..bd4073dfaf 100644 --- a/spec/controllers/api/base_controller_spec.rb +++ b/spec/controllers/api/base_controller_spec.rb @@ -7,10 +7,6 @@ RSpec.describe Api::BaseController do def success head 200 end - - def failure - FakeService.new - end end it 'returns private cache control headers by default' do diff --git a/spec/controllers/auth/challenges_controller_spec.rb b/spec/controllers/auth/challenges_controller_spec.rb index 56fdfa61b5..3c9d2a5964 100644 --- a/spec/controllers/auth/challenges_controller_spec.rb +++ b/spec/controllers/auth/challenges_controller_spec.rb @@ -8,9 +8,7 @@ RSpec.describe Auth::ChallengesController do let(:password) { 'foobar12345' } let(:user) { Fabricate(:user, password: password) } - before do - sign_in user - end + before { sign_in user } describe 'POST #create' do let(:return_to) { edit_user_registration_path } @@ -18,28 +16,24 @@ RSpec.describe Auth::ChallengesController do context 'with correct password' do before { post :create, params: { form_challenge: { return_to: return_to, current_password: password } } } - it 'redirects back' do - expect(response).to redirect_to(return_to) - end - - it 'sets session' do - expect(session[:challenge_passed_at]).to_not be_nil + it 'redirects back and sets challenge passed at in session' do + expect(response) + .to redirect_to(return_to) + expect(session[:challenge_passed_at]) + .to_not be_nil end end context 'with incorrect password' do before { post :create, params: { form_challenge: { return_to: return_to, current_password: 'hhfggjjd562' } } } - it 'renders challenge' do - expect(response).to render_template('auth/challenges/new') - end - - it 'displays error' do - expect(response.body).to include 'Invalid password' - end - - it 'does not set session' do - expect(session[:challenge_passed_at]).to be_nil + it 'renders challenge, displays error, does not set session' do + expect(response) + .to render_template('auth/challenges/new') + expect(response.body) + .to include 'Invalid password' + expect(session[:challenge_passed_at]) + .to be_nil end end end diff --git a/spec/controllers/auth/confirmations_controller_spec.rb b/spec/controllers/auth/confirmations_controller_spec.rb index a5b212e660..09a178f0e8 100644 --- a/spec/controllers/auth/confirmations_controller_spec.rb +++ b/spec/controllers/auth/confirmations_controller_spec.rb @@ -23,12 +23,11 @@ RSpec.describe Auth::ConfirmationsController do get :show, params: { confirmation_token: 'foobar' } end - it 'redirects to login' do - expect(response).to redirect_to(new_user_session_path) - end - - it 'queues up bootstrapping of home timeline' do - expect(BootstrapTimelineWorker).to have_received(:perform_async).with(user.account_id) + it 'redirects to login and queues worker' do + expect(response) + .to redirect_to(new_user_session_path) + expect(BootstrapTimelineWorker) + .to have_received(:perform_async).with(user.account_id) end end @@ -88,13 +87,13 @@ RSpec.describe Auth::ConfirmationsController do get :show, params: { confirmation_token: 'foobar' } end - it 'redirects to login and confirms email' do - expect(response).to redirect_to(new_user_session_path) - expect(user.reload.unconfirmed_email).to be_nil - end - - it 'does not queue up bootstrapping of home timeline' do - expect(BootstrapTimelineWorker).to_not have_received(:perform_async) + it 'redirects to login, confirms email, does not queue worker' do + expect(response) + .to redirect_to(new_user_session_path) + expect(user.reload.unconfirmed_email) + .to be_nil + expect(BootstrapTimelineWorker) + .to_not have_received(:perform_async) end end end diff --git a/spec/controllers/auth/passwords_controller_spec.rb b/spec/controllers/auth/passwords_controller_spec.rb index 9ccbb9e494..90095ac4b8 100644 --- a/spec/controllers/auth/passwords_controller_spec.rb +++ b/spec/controllers/auth/passwords_controller_spec.rb @@ -57,29 +57,30 @@ RSpec.describe Auth::PasswordsController do post :update, params: { user: { password: password, password_confirmation: password, reset_password_token: token } } end - it 'redirect to sign in' do - expect(response).to redirect_to '/auth/sign_in' - end + it 'resets the password' do + expect(response) + .to redirect_to '/auth/sign_in' - it 'changes password' do - this_user = User.find(user.id) + # Change password + expect(User.find(user.id)) + .to be_present + .and be_valid_password(password) - expect(this_user).to_not be_nil - expect(this_user.valid_password?(password)).to be true - end + # Deactivate session + expect(user.session_activations.count) + .to eq 0 + expect { session_activation.reload } + .to raise_error(ActiveRecord::RecordNotFound) - it 'deactivates all sessions' do - expect(user.session_activations.count).to eq 0 - expect { session_activation.reload }.to raise_error(ActiveRecord::RecordNotFound) - end + # Revoke tokens + expect(Doorkeeper::AccessToken.active_for(user).count) + .to eq 0 - it 'revokes all access tokens' do - expect(Doorkeeper::AccessToken.active_for(user).count).to eq 0 - end - - it 'removes push subscriptions' do - expect(Web::PushSubscription.where(user: user).or(Web::PushSubscription.where(access_token: access_token)).count).to eq 0 - expect { web_push_subscription.reload }.to raise_error(ActiveRecord::RecordNotFound) + # Remove push subs + expect(Web::PushSubscription.where(user: user).or(Web::PushSubscription.where(access_token: access_token)).count) + .to eq 0 + expect { web_push_subscription.reload } + .to raise_error(ActiveRecord::RecordNotFound) end end @@ -88,15 +89,13 @@ RSpec.describe Auth::PasswordsController do post :update, params: { user: { password: password, password_confirmation: password, reset_password_token: 'some_invalid_value' } } end - it 'renders reset password' do - expect(response).to render_template(:new) - end + it 'renders reset password and retains password' do + expect(response) + .to render_template(:new) - it 'retains password' do - this_user = User.find(user.id) - - expect(this_user).to_not be_nil - expect(this_user.external_or_valid_password?(user.password)).to be true + expect(User.find(user.id)) + .to be_present + .and be_external_or_valid_password(user.password) end end end diff --git a/spec/controllers/auth/registrations_controller_spec.rb b/spec/controllers/auth/registrations_controller_spec.rb index d1542128e7..739cb455e8 100644 --- a/spec/controllers/auth/registrations_controller_spec.rb +++ b/spec/controllers/auth/registrations_controller_spec.rb @@ -6,25 +6,33 @@ RSpec.describe Auth::RegistrationsController do render_views shared_examples 'checks for enabled registrations' do |path| - it 'redirects if it is in single user mode while it is open for registration' do - Fabricate(:account) - Setting.registrations_mode = 'open' - allow(Rails.configuration.x).to receive(:single_user_mode).and_return(true) + context 'when in single user mode and open for registration' do + before do + Setting.registrations_mode = 'open' + allow(Rails.configuration.x).to receive(:single_user_mode).and_return(true) + end - get path + it 'redirects to root' do + Fabricate(:account) + get path - expect(response).to redirect_to '/' - expect(Rails.configuration.x).to have_received(:single_user_mode) + expect(response).to redirect_to '/' + expect(Rails.configuration.x).to have_received(:single_user_mode) + end end - it 'redirects if it is not open for registration while it is not in single user mode' do - Setting.registrations_mode = 'none' - allow(Rails.configuration.x).to receive(:single_user_mode).and_return(false) + context 'when registrations closed and not in single user mode' do + before do + Setting.registrations_mode = 'none' + allow(Rails.configuration.x).to receive(:single_user_mode).and_return(false) + end - get path + it 'redirects to root' do + get path - expect(response).to redirect_to '/' - expect(Rails.configuration.x).to have_received(:single_user_mode) + expect(response).to redirect_to '/' + expect(Rails.configuration.x).to have_received(:single_user_mode) + end end end @@ -35,12 +43,12 @@ RSpec.describe Auth::RegistrationsController do get :edit end - it 'returns http success' do - expect(response).to have_http_status(200) - end + it 'returns http success and cache headers' do + expect(response) + .to have_http_status(200) - it 'returns private cache control header' do - expect(response.headers['Cache-Control']).to include('private, no-store') + expect(response.headers['Cache-Control']) + .to include('private, no-store') end end @@ -53,14 +61,13 @@ RSpec.describe Auth::RegistrationsController do sign_in(user, scope: :user) end - it 'returns http success' do + it 'returns http success and cache headers' do put :update - expect(response).to have_http_status(200) - end - it 'returns private cache control headers' do - put :update - expect(response.headers['Cache-Control']).to include('private, no-store') + expect(response) + .to have_http_status(200) + expect(response.headers['Cache-Control']) + .to include('private, no-store') end it 'can update the user email' do @@ -174,16 +181,14 @@ RSpec.describe Auth::RegistrationsController do post :create, params: { user: { account_attributes: { username: 'test' }, email: 'test@example.com', password: '12345678', password_confirmation: '12345678', agreement: 'true' } } end - it 'redirects to setup' do + it 'redirects to setup and creates user' do subject - expect(response).to redirect_to auth_setup_path - end - it 'creates user' do - subject - user = User.find_by(email: 'test@example.com') - expect(user).to_not be_nil - expect(user.locale).to eq(accept_language) + expect(response) + .to redirect_to auth_setup_path + expect(User.find_by(email: 'test@example.com')) + .to be_present + .and have_attributes(locale: eq(accept_language)) end end @@ -254,17 +259,18 @@ RSpec.describe Auth::RegistrationsController do post :create, params: { user: { account_attributes: { username: 'test' }, email: 'test@example.com', password: '12345678', password_confirmation: '12345678', agreement: 'true' } } end - it 'redirects to setup' do + it 'redirects to setup and creates user' do subject - expect(response).to redirect_to auth_setup_path - end - it 'creates user' do - subject - user = User.find_by(email: 'test@example.com') - expect(user).to_not be_nil - expect(user.locale).to eq(accept_language) - expect(user.approved).to be(false) + expect(response) + .to redirect_to auth_setup_path + + expect(User.find_by(email: 'test@example.com')) + .to be_present + .and have_attributes( + locale: eq(accept_language), + approved: be(false) + ) end end @@ -276,17 +282,17 @@ RSpec.describe Auth::RegistrationsController do post :create, params: { user: { account_attributes: { username: 'test' }, email: 'test@example.com', password: '12345678', password_confirmation: '12345678', invite_code: invite.code, agreement: 'true' } } end - it 'redirects to setup' do + it 'redirects to setup and creates user' do subject - expect(response).to redirect_to auth_setup_path - end - it 'creates user' do - subject - user = User.find_by(email: 'test@example.com') - expect(user).to_not be_nil - expect(user.locale).to eq(accept_language) - expect(user.approved).to be(false) + expect(response).to redirect_to auth_setup_path + + expect(User.find_by(email: 'test@example.com')) + .to be_present + .and have_attributes( + locale: eq(accept_language), + approved: be(false) + ) end end @@ -300,17 +306,17 @@ RSpec.describe Auth::RegistrationsController do post :create, params: { user: { account_attributes: { username: 'test' }, email: 'test@example.com', password: '12345678', password_confirmation: '12345678', invite_code: invite.code, agreement: 'true' } } end - it 'redirects to setup' do + it 'redirects to setup and creates user' do subject - expect(response).to redirect_to auth_setup_path - end - it 'creates user' do - subject - user = User.find_by(email: 'test@example.com') - expect(user).to_not be_nil - expect(user.locale).to eq(accept_language) - expect(user.approved).to be(true) + expect(response).to redirect_to auth_setup_path + + expect(User.find_by(email: 'test@example.com')) + .to be_present + .and have_attributes( + locale: eq(accept_language), + approved: be(true) + ) end end @@ -348,12 +354,11 @@ RSpec.describe Auth::RegistrationsController do delete :destroy end - it 'returns http not found' do - expect(response).to have_http_status(404) - end - - it 'does not delete user' do - expect(User.find(user.id)).to_not be_nil + it 'returns http not found and keeps user' do + expect(response) + .to have_http_status(404) + expect(User.find(user.id)) + .to_not be_nil end end end diff --git a/spec/fixtures/files/avatar-high.gif b/spec/fixtures/files/avatar-high.gif new file mode 100644 index 0000000000..7639f2c507 Binary files /dev/null and b/spec/fixtures/files/avatar-high.gif differ diff --git a/spec/helpers/accounts_helper_spec.rb b/spec/helpers/accounts_helper_spec.rb index 2c949cde69..8526482362 100644 --- a/spec/helpers/accounts_helper_spec.rb +++ b/spec/helpers/accounts_helper_spec.rb @@ -3,16 +3,6 @@ require 'rails_helper' RSpec.describe AccountsHelper do - def set_not_embedded_view - params[:controller] = "not_#{StatusesHelper::EMBEDDED_CONTROLLER}" - params[:action] = "not_#{StatusesHelper::EMBEDDED_ACTION}" - end - - def set_embedded_view - params[:controller] = StatusesHelper::EMBEDDED_CONTROLLER - params[:action] = StatusesHelper::EMBEDDED_ACTION - end - describe '#display_name' do it 'uses the display name when it exists' do account = Account.new(display_name: 'Display', username: 'Username') @@ -28,9 +18,8 @@ RSpec.describe AccountsHelper do end describe '#acct' do - it 'is fully qualified for embedded local accounts' do + it 'is fully qualified for local accounts' do allow(Rails.configuration.x).to receive(:local_domain).and_return('local_domain') - set_embedded_view account = Account.new(domain: nil, username: 'user') acct = helper.acct(account) @@ -38,32 +27,12 @@ RSpec.describe AccountsHelper do expect(acct).to eq '@user@local_domain' end - it 'is fully qualified for embedded foreign accounts' do - set_embedded_view + it 'is fully qualified for remote accounts' do account = Account.new(domain: 'foreign_server.com', username: 'user') acct = helper.acct(account) expect(acct).to eq '@user@foreign_server.com' end - - it 'is fully qualified for non embedded foreign accounts' do - set_not_embedded_view - account = Account.new(domain: 'foreign_server.com', username: 'user') - - acct = helper.acct(account) - - expect(acct).to eq '@user@foreign_server.com' - end - - it 'is fully qualified for non embedded local accounts' do - allow(Rails.configuration.x).to receive(:local_domain).and_return('local_domain') - set_not_embedded_view - account = Account.new(domain: nil, username: 'user') - - acct = helper.acct(account) - - expect(acct).to eq '@user@local_domain' - end end end diff --git a/spec/helpers/application_helper_spec.rb b/spec/helpers/application_helper_spec.rb index ffcc5b81b6..557d08e851 100644 --- a/spec/helpers/application_helper_spec.rb +++ b/spec/helpers/application_helper_spec.rb @@ -257,11 +257,11 @@ RSpec.describe ApplicationHelper do expect(helper.html_title).to be_html_safe end - it 'removes extra new lines' do + it 'does not escape twice' do Setting.site_title = 'Site Title' - helper.content_for(:page_title, "Test Value\n") + helper.content_for(:page_title, '"Test Value"'.html_safe) - expect(helper.html_title).to eq 'Test Value - Site Title' + expect(helper.html_title).to eq '"Test Value" - Site Title' expect(helper.html_title).to be_html_safe end end diff --git a/spec/helpers/self_destruct_helper_spec.rb b/spec/helpers/self_destruct_helper_spec.rb index 09d7347eee..dca1590764 100644 --- a/spec/helpers/self_destruct_helper_spec.rb +++ b/spec/helpers/self_destruct_helper_spec.rb @@ -3,19 +3,20 @@ require 'rails_helper' RSpec.describe SelfDestructHelper do - describe 'self_destruct?' do + describe '#self_destruct?' do + before { Rails.configuration.x.mastodon.self_destruct_value = destruct_value } + after { Rails.configuration.x.mastodon.self_destruct_value = nil } + context 'when SELF_DESTRUCT is unset' do + let(:destruct_value) { nil } + it 'returns false' do expect(helper.self_destruct?).to be false end end context 'when SELF_DESTRUCT is set to an invalid value' do - around do |example| - ClimateControl.modify SELF_DESTRUCT: 'true' do - example.run - end - end + let(:destruct_value) { 'true' } it 'returns false' do expect(helper.self_destruct?).to be false @@ -23,9 +24,10 @@ RSpec.describe SelfDestructHelper do end context 'when SELF_DESTRUCT is set to value signed for the wrong purpose' do + let(:destruct_value) { Rails.configuration.x.mastodon.self_destruct_value = Rails.application.message_verifier('foo').generate('example.com') } + around do |example| ClimateControl.modify( - SELF_DESTRUCT: Rails.application.message_verifier('foo').generate('example.com'), LOCAL_DOMAIN: 'example.com' ) do example.run @@ -38,9 +40,10 @@ RSpec.describe SelfDestructHelper do end context 'when SELF_DESTRUCT is set to value signed for the wrong domain' do + let(:destruct_value) { Rails.configuration.x.mastodon.self_destruct_value = Rails.application.message_verifier(described_class::VERIFY_PURPOSE).generate('foo.com') } + around do |example| ClimateControl.modify( - SELF_DESTRUCT: Rails.application.message_verifier('self-destruct').generate('foo.com'), LOCAL_DOMAIN: 'example.com' ) do example.run @@ -53,9 +56,10 @@ RSpec.describe SelfDestructHelper do end context 'when SELF_DESTRUCT is set to a correctly-signed value' do + let(:destruct_value) { Rails.configuration.x.mastodon.self_destruct_value = Rails.application.message_verifier(described_class::VERIFY_PURPOSE).generate('example.com') } + around do |example| ClimateControl.modify( - SELF_DESTRUCT: Rails.application.message_verifier('self-destruct').generate('example.com'), LOCAL_DOMAIN: 'example.com' ) do example.run diff --git a/spec/helpers/statuses_helper_spec.rb b/spec/helpers/statuses_helper_spec.rb index edd3e8f2f7..07ad72eda9 100644 --- a/spec/helpers/statuses_helper_spec.rb +++ b/spec/helpers/statuses_helper_spec.rb @@ -77,28 +77,4 @@ RSpec.describe StatusesHelper do end end end - - describe '#stream_link_target' do - it 'returns nil if it is not an embedded view' do - set_not_embedded_view - - expect(helper.stream_link_target).to be_nil - end - - it 'returns _blank if it is an embedded view' do - set_embedded_view - - expect(helper.stream_link_target).to eq '_blank' - end - end - - def set_not_embedded_view - params[:controller] = "not_#{StatusesHelper::EMBEDDED_CONTROLLER}" - params[:action] = "not_#{StatusesHelper::EMBEDDED_ACTION}" - end - - def set_embedded_view - params[:controller] = StatusesHelper::EMBEDDED_CONTROLLER - params[:action] = StatusesHelper::EMBEDDED_ACTION - 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/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/admin/system_check/software_version_check_spec.rb b/spec/lib/admin/system_check/software_version_check_spec.rb index 8460d90668..75dc1a4732 100644 --- a/spec/lib/admin/system_check/software_version_check_spec.rb +++ b/spec/lib/admin/system_check/software_version_check_spec.rb @@ -27,9 +27,10 @@ RSpec.describe Admin::SystemCheck::SoftwareVersionCheck do context 'when checks are disabled' do around do |example| - ClimateControl.modify UPDATE_CHECK_URL: '' do - example.run - end + original = Rails.configuration.x.mastodon.software_update_url + Rails.configuration.x.mastodon.software_update_url = '' + example.run + Rails.configuration.x.mastodon.software_update_url = original 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 0e31827912..12bf3810db 100644 --- a/spec/lib/annual_report/commonly_interacted_with_accounts_spec.rb +++ b/spec/lib/annual_report/commonly_interacted_with_accounts_spec.rb @@ -21,18 +21,27 @@ RSpec.describe AnnualReport::CommonlyInteractedWithAccounts do let(:account) { Fabricate :account } let(:other_account) { Fabricate :account } + let(:most_other_account) { Fabricate :account } before do _other = Fabricate :status + Fabricate :status, account: account, reply: true, in_reply_to_id: Fabricate(:status, account: other_account).id Fabricate :status, account: account, reply: true, in_reply_to_id: Fabricate(:status, account: other_account).id + + Fabricate :status, account: account, reply: true, in_reply_to_id: Fabricate(:status, account: most_other_account).id + Fabricate :status, account: account, reply: true, in_reply_to_id: Fabricate(:status, account: most_other_account).id + Fabricate :status, account: account, reply: true, in_reply_to_id: Fabricate(:status, account: most_other_account).id end it 'builds a report for an account' do expect(subject.generate) .to include( - commonly_interacted_with_accounts: contain_exactly( - include(account_id: other_account.id.to_s, count: 2) + commonly_interacted_with_accounts: eq( + [ + { account_id: most_other_account.id.to_s, count: 3 }, + { 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 2f04934e47..956549c325 100644 --- a/spec/lib/annual_report/most_reblogged_accounts_spec.rb +++ b/spec/lib/annual_report/most_reblogged_accounts_spec.rb @@ -21,18 +21,26 @@ RSpec.describe AnnualReport::MostRebloggedAccounts do let(:account) { Fabricate :account } let(:other_account) { Fabricate :account } + let(:most_other_account) { Fabricate :account } before do _other = Fabricate :status Fabricate :status, account: account, reblog: Fabricate(:status, account: other_account) Fabricate :status, account: account, reblog: Fabricate(:status, account: other_account) + + Fabricate :status, account: account, reblog: Fabricate(:status, account: most_other_account) + Fabricate :status, account: account, reblog: Fabricate(:status, account: most_other_account) + Fabricate :status, account: account, reblog: Fabricate(:status, account: most_other_account) end it 'builds a report for an account' do expect(subject.generate) .to include( - most_reblogged_accounts: contain_exactly( - include(account_id: other_account.id.to_s, count: 2) + most_reblogged_accounts: eq( + [ + { account_id: most_other_account.id.to_s, count: 3 }, + { account_id: other_account.id.to_s, count: 2 }, + ] ) ) end diff --git a/spec/lib/annual_report/most_used_apps_spec.rb b/spec/lib/annual_report/most_used_apps_spec.rb index d2fcecc4d8..ab7022ef20 100644 --- a/spec/lib/annual_report/most_used_apps_spec.rb +++ b/spec/lib/annual_report/most_used_apps_spec.rb @@ -20,18 +20,23 @@ RSpec.describe AnnualReport::MostUsedApps do context 'with an active account' do let(:account) { Fabricate :account } - let(:application) { Fabricate :application } + let(:application) { Fabricate :application, name: 'App' } + let(:most_application) { Fabricate :application, name: 'Most App' } before do _other = Fabricate :status Fabricate.times 2, :status, account: account, application: application + Fabricate.times 3, :status, account: account, application: most_application end it 'builds a report for an account' do expect(subject.generate) .to include( - most_used_apps: contain_exactly( - include(name: application.name, count: 2) + most_used_apps: eq( + [ + { name: most_application.name, count: 3 }, + { name: application.name, 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_hashtags_spec.rb b/spec/lib/annual_report/top_hashtags_spec.rb index 58a9152184..b9cc9392ed 100644 --- a/spec/lib/annual_report/top_hashtags_spec.rb +++ b/spec/lib/annual_report/top_hashtags_spec.rb @@ -21,20 +21,31 @@ RSpec.describe AnnualReport::TopHashtags do let(:account) { Fabricate :account } let(:tag) { Fabricate :tag } + let(:most_tag) { Fabricate :tag } before do _other = Fabricate :status + first = Fabricate :status, account: account first.tags << tag + first.tags << most_tag + last = Fabricate :status, account: account last.tags << tag + last.tags << most_tag + + middle = Fabricate :status, account: account + middle.tags << most_tag end it 'builds a report for an account' do expect(subject.generate) .to include( - top_hashtags: contain_exactly( - include(name: tag.name, count: 2) + top_hashtags: eq( + [ + { name: most_tag.name, count: 3 }, + { name: tag.name, count: 2 }, + ] ) ) end diff --git a/spec/lib/domain_resource_spec.rb b/spec/lib/domain_resource_spec.rb new file mode 100644 index 0000000000..0d239fd9de --- /dev/null +++ b/spec/lib/domain_resource_spec.rb @@ -0,0 +1,19 @@ +# frozen_string_literal: true + +require 'rails_helper' + +RSpec.describe DomainResource do + describe '#mx' do + subject { described_class.new(domain) } + + let(:domain) { 'example.host' } + let(:exchange) { 'mx.host' } + + before { configure_mx(domain: domain, exchange: exchange) } + + it 'returns array of hostnames' do + expect(subject.mx) + .to eq([exchange]) + end + end +end diff --git a/spec/lib/feed_manager_spec.rb b/spec/lib/feed_manager_spec.rb index 1d70499674..afb007af42 100644 --- a/spec/lib/feed_manager_spec.rb +++ b/spec/lib/feed_manager_spec.rb @@ -343,16 +343,16 @@ RSpec.describe FeedManager do end describe '#push_to_list' do - let(:owner) { Fabricate(:account, username: 'owner') } + let(:list_owner) { Fabricate(:account, username: 'list_owner') } let(:alice) { Fabricate(:account, username: 'alice') } let(:bob) { Fabricate(:account, username: 'bob') } let(:eve) { Fabricate(:account, username: 'eve') } - let(:list) { Fabricate(:list, account: owner) } + let(:list) { Fabricate(:list, account: list_owner) } before do - owner.follow!(alice) - owner.follow!(bob) - owner.follow!(eve) + list_owner.follow!(alice) + list_owner.follow!(bob) + list_owner.follow!(eve) list.accounts << alice list.accounts << bob @@ -377,7 +377,7 @@ RSpec.describe FeedManager do end it 'pushes statuses that are replies to list owner' do - status = Fabricate(:status, text: 'Hello world', account: owner) + status = Fabricate(:status, text: 'Hello world', account: list_owner) reply = Fabricate(:status, text: 'Nay', thread: status, account: bob) expect(subject.push_to_list(list, reply)).to be true end @@ -400,7 +400,7 @@ RSpec.describe FeedManager do end it 'pushes statuses that are replies to list owner' do - status = Fabricate(:status, text: 'Hello world', account: owner) + status = Fabricate(:status, text: 'Hello world', account: list_owner) reply = Fabricate(:status, text: 'Nay', thread: status, account: bob) expect(subject.push_to_list(list, reply)).to be true end @@ -429,7 +429,7 @@ RSpec.describe FeedManager do end it 'pushes statuses that are replies to list owner' do - status = Fabricate(:status, text: 'Hello world', account: owner) + status = Fabricate(:status, text: 'Hello world', account: list_owner) reply = Fabricate(:status, text: 'Nay', thread: status, account: bob) expect(subject.push_to_list(list, reply)).to be true end diff --git a/spec/lib/link_details_extractor_spec.rb b/spec/lib/link_details_extractor_spec.rb index d8d9db0ad1..36d6f22b00 100644 --- a/spec/lib/link_details_extractor_spec.rb +++ b/spec/lib/link_details_extractor_spec.rb @@ -49,7 +49,8 @@ RSpec.describe LinkDetailsExtractor do Man bites dog - + + HTML @@ -59,7 +60,8 @@ RSpec.describe LinkDetailsExtractor do .to have_attributes( title: eq('Man bites dog'), description: eq("A dog's tale"), - language: eq('en') + language: eq('en'), + icon: eq('https://example.com/favicon.ico') ) end end @@ -256,7 +258,7 @@ RSpec.describe LinkDetailsExtractor do - + diff --git a/spec/lib/mastodon/cli/email_domain_blocks_spec.rb b/spec/lib/mastodon/cli/email_domain_blocks_spec.rb index a5fbd23e65..6ce1a7c5f3 100644 --- a/spec/lib/mastodon/cli/email_domain_blocks_spec.rb +++ b/spec/lib/mastodon/cli/email_domain_blocks_spec.rb @@ -63,6 +63,22 @@ RSpec.describe Mastodon::CLI::EmailDomainBlocks do .and(change(EmailDomainBlock, :count).by(1)) end end + + context 'with --with-dns-records true' do + let(:domain) { 'host.example' } + let(:arguments) { [domain] } + let(:options) { { with_dns_records: true } } + + before do + configure_mx(domain: domain, exchange: 'other.host') + end + + it 'adds a new block for parent and children' do + expect { subject } + .to output_results('Added 2') + .and(change(EmailDomainBlock, :count).by(2)) + end + end end describe '#remove' do diff --git a/spec/lib/search_query_transformer_spec.rb b/spec/lib/search_query_transformer_spec.rb index 9399f3503d..b69e3afc9d 100644 --- a/spec/lib/search_query_transformer_spec.rb +++ b/spec/lib/search_query_transformer_spec.rb @@ -16,6 +16,7 @@ RSpec.describe SearchQueryTransformer do ['"2022-01-01"', '2022-01-01'], ['12345678', '12345678'], ['"12345678"', '12345678'], + ['"2024-10-31T23:47:20Z"', '2024-10-31T23:47:20Z'], ].each do |value, parsed| context "with #{operator}:#{value}" do let(:query) { "#{operator}:#{value}" } @@ -34,7 +35,7 @@ RSpec.describe SearchQueryTransformer do let(:query) { "#{operator}:\"abc\"" } it 'raises an exception' do - expect { subject }.to raise_error(Mastodon::FilterValidationError, 'Invalid date abc') + expect { subject }.to raise_error(Date::Error) end end end diff --git a/spec/models/account_spec.rb b/spec/models/account_spec.rb index 7a5deed599..77341b7786 100644 --- a/spec/models/account_spec.rb +++ b/spec/models/account_spec.rb @@ -983,14 +983,6 @@ RSpec.describe Account do end end - describe 'silenced' do - it 'returns an array of accounts who are silenced' do - silenced_account = Fabricate(:account, silenced: true) - _account = Fabricate(:account, silenced: false) - expect(described_class.silenced).to contain_exactly(silenced_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/bulk_import_spec.rb b/spec/models/bulk_import_spec.rb new file mode 100644 index 0000000000..a3bd01d2a8 --- /dev/null +++ b/spec/models/bulk_import_spec.rb @@ -0,0 +1,42 @@ +# frozen_string_literal: true + +require 'rails_helper' + +RSpec.describe BulkImport do + describe 'Associations' do + it { is_expected.to belong_to(:account).required } + it { is_expected.to have_many(:rows).class_name('BulkImportRow').inverse_of(:bulk_import).dependent(:delete_all) } + end + + describe 'Validations' do + subject { Fabricate.build :bulk_import } + + it { is_expected.to validate_presence_of(:type) } + end + + describe 'Scopes' do + describe '.archival_completed' do + let!(:old_import) { Fabricate :bulk_import, created_at: 1.month.ago } + let!(:new_import) { Fabricate :bulk_import, created_at: 1.day.ago } + + it 'returns imports which have passed the archive window period' do + expect(described_class.archival_completed) + .to include(old_import) + .and not_include(new_import) + end + end + + describe '.confirmation_missed' do + let!(:old_unconfirmed_import) { Fabricate :bulk_import, created_at: 1.week.ago, state: :unconfirmed } + let!(:old_scheduled_import) { Fabricate :bulk_import, created_at: 1.week.ago, state: :scheduled } + let!(:new_unconfirmed_import) { Fabricate :bulk_import, created_at: 1.minute.ago, state: :unconfirmed } + + it 'returns imports which have passed the confirmation window without confirming' do + expect(described_class.confirmation_missed) + .to include(old_unconfirmed_import) + .and not_include(old_scheduled_import) + .and not_include(new_unconfirmed_import) + end + end + end +end diff --git a/spec/models/concerns/account/interactions_spec.rb b/spec/models/concerns/account/interactions_spec.rb index 4868054df7..f7ec3a3912 100644 --- a/spec/models/concerns/account/interactions_spec.rb +++ b/spec/models/concerns/account/interactions_spec.rb @@ -3,10 +3,10 @@ require 'rails_helper' RSpec.describe Account::Interactions do - let(:account) { Fabricate(:account, username: 'account') } + let(:account) { Fabricate(:account) } let(:account_id) { account.id } let(:account_ids) { [account_id] } - let(:target_account) { Fabricate(:account, username: 'target') } + let(:target_account) { Fabricate(:account) } let(:target_account_id) { target_account.id } let(:target_account_ids) { [target_account_id] } diff --git a/spec/models/concerns/account/sensitizes_spec.rb b/spec/models/concerns/account/sensitizes_spec.rb new file mode 100644 index 0000000000..5416d40570 --- /dev/null +++ b/spec/models/concerns/account/sensitizes_spec.rb @@ -0,0 +1,18 @@ +# frozen_string_literal: true + +require 'rails_helper' + +RSpec.describe Account::Sensitizes do + describe 'Scopes' do + describe '.sensitized' do + let(:sensitized_account) { Fabricate :account, sensitized_at: 2.days.ago } + + before { Fabricate :account, sensitized_at: nil } + + it 'returns an array of accounts who are sensitized' do + expect(Account.sensitized) + .to contain_exactly(sensitized_account) + end + end + end +end diff --git a/spec/models/concerns/account/silences_spec.rb b/spec/models/concerns/account/silences_spec.rb new file mode 100644 index 0000000000..0d8337ce1d --- /dev/null +++ b/spec/models/concerns/account/silences_spec.rb @@ -0,0 +1,18 @@ +# frozen_string_literal: true + +require 'rails_helper' + +RSpec.describe Account::Silences do + describe 'Scopes' do + describe '.silenced' do + let(:silenced_account) { Fabricate :account, silenced: true } + + before { Fabricate :account, silenced: false } + + it 'returns an array of accounts who are silenced' do + expect(Account.silenced) + .to contain_exactly(silenced_account) + end + 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_request_spec.rb b/spec/models/follow_request_spec.rb index 9cccb82903..237875deab 100644 --- a/spec/models/follow_request_spec.rb +++ b/spec/models/follow_request_spec.rb @@ -30,7 +30,7 @@ RSpec.describe FollowRequest do follow_request.authorize! expect(account).to have_received(:follow!).with(target_account, reblogs: true, notify: false, uri: follow_request.uri, languages: nil, bypass_limit: true) - expect(MergeWorker).to have_received(:perform_async).with(target_account.id, account.id) + expect(MergeWorker).to have_received(:perform_async).with(target_account.id, account.id, 'home') expect(follow_request).to have_received(:destroy!) end diff --git a/spec/models/form/import_spec.rb b/spec/models/form/import_spec.rb index 22ffdfd877..e14ad6eca0 100644 --- a/spec/models/form/import_spec.rb +++ b/spec/models/form/import_spec.rb @@ -237,51 +237,26 @@ RSpec.describe Form::Import do let(:import_file) { file } let(:import_mode) { mode } - before do - subject.save - end - - it 'creates the expected rows' do - expect(account.bulk_imports.first.rows.pluck(:data)).to match_array(expected_rows) - end + before { subject.save } context 'with a BulkImport' do let(:bulk_import) { account.bulk_imports.first } - it 'creates a non-nil bulk import' do - expect(bulk_import).to_not be_nil - end - - it 'matches the subjects type' do - expect(bulk_import.type.to_sym).to eq subject.type.to_sym - end - - it 'matches the subjects original filename' do - expect(bulk_import.original_filename).to eq subject.data.original_filename - end - - it 'matches the subjects likely_mismatched? value' do - expect(bulk_import.likely_mismatched?).to eq subject.likely_mismatched? - end - - it 'matches the subject overwrite value' do - expect(bulk_import.overwrite?).to eq !!subject.overwrite # rubocop:disable Style/DoubleNegation - end - - it 'has zero processed items' do - expect(bulk_import.processed_items).to eq 0 - end - - it 'has zero imported items' do - expect(bulk_import.imported_items).to eq 0 - end - - it 'has a correct total_items value' do - expect(bulk_import.total_items).to eq bulk_import.rows.count - end - - it 'defaults to unconfirmed true' do - expect(bulk_import.state_unconfirmed?).to be true + it 'creates a bulk import with correct values' do + expect(bulk_import) + .to be_present + .and have_attributes( + type: eq(subject.type), + original_filename: eq(subject.data.original_filename), + likely_mismatched?: eq(subject.likely_mismatched?), + overwrite?: eq(!!subject.overwrite), # rubocop:disable Style/DoubleNegation + processed_items: eq(0), + imported_items: eq(0), + total_items: eq(bulk_import.rows.count), + state_unconfirmed?: be(true) + ) + expect(bulk_import.rows.pluck(:data)) + .to match_array(expected_rows) end end end diff --git a/spec/models/list_spec.rb b/spec/models/list_spec.rb index 62a84dfebf..48c273d3ec 100644 --- a/spec/models/list_spec.rb +++ b/spec/models/list_spec.rb @@ -11,7 +11,11 @@ RSpec.describe List do context 'when account has hit max list limit' do let(:account) { Fabricate :account } - before { stub_const 'List::PER_ACCOUNT_LIMIT', 0 } + before do + stub_const 'List::PER_ACCOUNT_LIMIT', 1 + + Fabricate(:list, account: account) + end context 'when creating a new list' do it { is_expected.to_not allow_value(account).for(:account).against(:base).with_message(I18n.t('lists.errors.limit')) } diff --git a/spec/models/login_activity_spec.rb b/spec/models/login_activity_spec.rb new file mode 100644 index 0000000000..5b7935e8ba --- /dev/null +++ b/spec/models/login_activity_spec.rb @@ -0,0 +1,17 @@ +# frozen_string_literal: true + +require 'rails_helper' + +RSpec.describe LoginActivity do + include_examples 'BrowserDetection' + + describe 'Associations' do + it { is_expected.to belong_to(:user).required } + end + + describe 'Validations' do + subject { Fabricate.build :login_activity } + + it { is_expected.to define_enum_for(:authentication_method).backed_by_column_of_type(:string) } + end +end diff --git a/spec/models/report_spec.rb b/spec/models/report_spec.rb index a0e4f6fafd..b4fbea437f 100644 --- a/spec/models/report_spec.rb +++ b/spec/models/report_spec.rb @@ -108,15 +108,22 @@ RSpec.describe Report do let(:report) { Fabricate(:report, target_account_id: target_account.id, status_ids: [status.id], created_at: 3.days.ago, updated_at: 1.day.ago) } let(:target_account) { Fabricate(:account) } let(:status) { Fabricate(:status) } + let(:account_warning) { Fabricate(:account_warning, report_id: report.id) } before do Fabricate(:action_log, target_type: 'Report', account_id: target_account.id, target_id: report.id, created_at: 2.days.ago) Fabricate(:action_log, target_type: 'Account', account_id: target_account.id, target_id: report.target_account_id, created_at: 2.days.ago) Fabricate(:action_log, target_type: 'Status', account_id: target_account.id, target_id: status.id, created_at: 2.days.ago) + Fabricate(:action_log, target_type: 'AccountWarning', account_id: target_account.id, target_id: account_warning.id, created_at: 2.days.ago) end - it 'returns right logs' do - expect(action_logs.count).to eq 3 + it 'returns expected logs' do + expect(action_logs) + .to have_attributes(count: 4) + .and include(have_attributes(target_type: 'Account')) + .and include(have_attributes(target_type: 'AccountWarning')) + .and include(have_attributes(target_type: 'Report')) + .and include(have_attributes(target_type: 'Status')) end end diff --git a/spec/models/session_activation_spec.rb b/spec/models/session_activation_spec.rb index bed411c369..bb9b3c785f 100644 --- a/spec/models/session_activation_spec.rb +++ b/spec/models/session_activation_spec.rb @@ -3,39 +3,7 @@ require 'rails_helper' RSpec.describe SessionActivation do - describe '#detection' do - let(:session_activation) { Fabricate(:session_activation, user_agent: 'Chrome/62.0.3202.89') } - - it 'sets a Browser instance as detection' do - expect(session_activation.detection).to be_a Browser::Chrome - end - end - - describe '#browser' do - before do - allow(session_activation).to receive(:detection).and_return(detection) - end - - let(:detection) { instance_double(Browser::Chrome, id: 1) } - let(:session_activation) { Fabricate(:session_activation) } - - it 'returns detection.id' do - expect(session_activation.browser).to be 1 - end - end - - describe '#platform' do - before do - allow(session_activation).to receive(:detection).and_return(detection) - end - - let(:session_activation) { Fabricate(:session_activation) } - let(:detection) { instance_double(Browser::Chrome, platform: instance_double(Browser::Platform, id: 1)) } - - it 'returns detection.platform.id' do - expect(session_activation.platform).to be 1 - end - end + include_examples 'BrowserDetection' describe '.active?' do subject { described_class.active?(id) } diff --git a/spec/models/software_update_spec.rb b/spec/models/software_update_spec.rb index 0a494b0c4c..43e9cd058f 100644 --- a/spec/models/software_update_spec.rb +++ b/spec/models/software_update_spec.rb @@ -3,6 +3,60 @@ require 'rails_helper' RSpec.describe SoftwareUpdate do + describe '#pending?' do + subject { described_class.new(version: update_version) } + + before { allow(Mastodon::Version).to receive(:gem_version).and_return(Gem::Version.new(mastodon_version)) } + + context 'when the runtime version is older than the update' do + let(:mastodon_version) { '4.0.0' } + let(:update_version) { '5.0.0' } + + it { is_expected.to be_pending } + end + + context 'when the runtime version is newer than the update' do + let(:mastodon_version) { '6.0.0' } + let(:update_version) { '5.0.0' } + + it { is_expected.to_not be_pending } + end + + context 'when the runtime version is same as the update' do + let(:mastodon_version) { '4.0.0' } + let(:update_version) { '4.0.0' } + + it { is_expected.to_not be_pending } + end + end + + describe '#outdated?' do + subject { described_class.new(version: update_version) } + + before { allow(Mastodon::Version).to receive(:gem_version).and_return(Gem::Version.new(mastodon_version)) } + + context 'when the runtime version is older than the update' do + let(:mastodon_version) { '4.0.0' } + let(:update_version) { '5.0.0' } + + it { is_expected.to_not be_outdated } + end + + context 'when the runtime version is newer than the update' do + let(:mastodon_version) { '6.0.0' } + let(:update_version) { '5.0.0' } + + it { is_expected.to be_outdated } + end + + context 'when the runtime version is same as the update' do + let(:mastodon_version) { '4.0.0' } + let(:update_version) { '4.0.0' } + + it { is_expected.to be_outdated } + end + end + describe '.pending_to_a' do before do allow(Mastodon::Version).to receive(:gem_version).and_return(Gem::Version.new(mastodon_version)) diff --git a/spec/models/user_spec.rb b/spec/models/user_spec.rb index 4393be5a4e..9a5a070d25 100644 --- a/spec/models/user_spec.rb +++ b/spec/models/user_spec.rb @@ -598,4 +598,27 @@ RSpec.describe User do end end end + + describe '#applications_last_used' do + let!(:user) { Fabricate(:user) } + + let!(:never_used_application) { Fabricate :application, owner: user } + let!(:application_one) { Fabricate :application, owner: user } + let!(:application_two) { Fabricate :application, owner: user } + + before do + _other_user_token = Fabricate :access_token, last_used_at: 3.days.ago + _never_used_token = Fabricate :access_token, application: never_used_application, resource_owner_id: user.id, last_used_at: nil + _app_one_old_token = Fabricate :access_token, application: application_one, resource_owner_id: user.id, last_used_at: 5.days.ago + _app_one_new_token = Fabricate :access_token, application: application_one, resource_owner_id: user.id, last_used_at: 1.day.ago + _never_used_token = Fabricate :access_token, application: application_two, resource_owner_id: user.id, last_used_at: 5.days.ago + end + + it 'returns a hash of unique applications with last used values' do + expect(user.applications_last_used) + .to include(application_one.id => be_within(1.0).of(1.day.ago)) + .and include(application_two.id => be_within(1.0).of(5.days.ago)) + .and not_include(never_used_application.id) + end + end end diff --git a/spec/rails_helper.rb b/spec/rails_helper.rb index d2ad40be73..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? diff --git a/spec/requests/api/v1/apps/credentials_spec.rb b/spec/requests/api/v1/apps/credentials_spec.rb index 8e5fa14b7e..3aca53ed0a 100644 --- a/spec/requests/api/v1/apps/credentials_spec.rb +++ b/spec/requests/api/v1/apps/credentials_spec.rb @@ -44,6 +44,7 @@ RSpec.describe 'Credentials' do expect(response.parsed_body) .to not_include(client_id: be_present) .and not_include(client_secret: be_present) + .and not_include(client_secret_expires_at: be_present) end end diff --git a/spec/requests/api/v1/apps_spec.rb b/spec/requests/api/v1/apps_spec.rb index cf43e14d62..4e9147ba32 100644 --- a/spec/requests/api/v1/apps_spec.rb +++ b/spec/requests/api/v1/apps_spec.rb @@ -42,6 +42,7 @@ RSpec.describe 'Apps' do id: app.id.to_s, client_id: app.uid, client_secret: app.secret, + client_secret_expires_at: 0, name: client_name, website: website, scopes: ['read', 'write'], diff --git a/spec/requests/well_known/oauth_metadata_spec.rb b/spec/requests/well_known/oauth_metadata_spec.rb index 01e9146fde..42a6c1b328 100644 --- a/spec/requests/well_known/oauth_metadata_spec.rb +++ b/spec/requests/well_known/oauth_metadata_spec.rb @@ -27,7 +27,7 @@ RSpec.describe 'The /.well-known/oauth-authorization-server request' do response_modes_supported: Doorkeeper.configuration.authorization_response_flows.flat_map(&:response_mode_matches).uniq, token_endpoint_auth_methods_supported: %w(client_secret_basic client_secret_post), grant_types_supported: grant_types_supported, - code_challenge_methods_supported: ['S256'], + code_challenge_methods_supported: Doorkeeper.configuration.pkce_code_challenge_methods_supported, # non-standard extension: app_registration_endpoint: api_v1_apps_url ) 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/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/services/software_update_check_service_spec.rb b/spec/services/software_update_check_service_spec.rb index a1eb9d86e9..637e1e26c5 100644 --- a/spec/services/software_update_check_service_spec.rb +++ b/spec/services/software_update_check_service_spec.rb @@ -27,6 +27,7 @@ RSpec.describe SoftwareUpdateCheckService do before do Fabricate(:software_update, version: '3.5.0', type: 'major', urgent: false) Fabricate(:software_update, version: '42.13.12', type: 'major', urgent: false) + Fabricate(:software_update, version: 'Malformed', type: 'major', urgent: false) owner_user.settings.update('notification_emails.software_updates': 'all') owner_user.save! @@ -50,7 +51,7 @@ RSpec.describe SoftwareUpdateCheckService do end it 'deletes outdated update records but keeps valid update records' do - expect { subject.call }.to change { SoftwareUpdate.pluck(:version).sort }.from(['3.5.0', '42.13.12']).to(['42.13.12']) + expect { subject.call }.to change { SoftwareUpdate.pluck(:version).sort }.from(['3.5.0', '42.13.12', 'Malformed']).to(['42.13.12']) end end @@ -85,7 +86,7 @@ RSpec.describe SoftwareUpdateCheckService do end it 'updates the list of known updates' do - expect { subject.call }.to change { SoftwareUpdate.pluck(:version).sort }.from(['3.5.0', '42.13.12']).to(['4.2.1', '4.3.0', '5.0.0']) + expect { subject.call }.to change { SoftwareUpdate.pluck(:version).sort }.from(['3.5.0', '42.13.12', 'Malformed']).to(['4.2.1', '4.3.0', '5.0.0']) end context 'when no update is urgent' do @@ -124,9 +125,10 @@ RSpec.describe SoftwareUpdateCheckService do context 'when update checking is disabled' do around do |example| - ClimateControl.modify UPDATE_CHECK_URL: '' do - example.run - end + original = Rails.configuration.x.mastodon.software_update_url + Rails.configuration.x.mastodon.software_update_url = '' + example.run + Rails.configuration.x.mastodon.software_update_url = original end before do @@ -148,9 +150,10 @@ RSpec.describe SoftwareUpdateCheckService do let(:update_check_url) { 'https://api.example.com/update_check' } around do |example| - ClimateControl.modify UPDATE_CHECK_URL: 'https://api.example.com/update_check' do - example.run - end + original = Rails.configuration.x.mastodon.software_update_url + Rails.configuration.x.mastodon.software_update_url = 'https://api.example.com/update_check' + example.run + Rails.configuration.x.mastodon.software_update_url = original end it_behaves_like 'when the feature is enabled' diff --git a/spec/services/unmute_service_spec.rb b/spec/services/unmute_service_spec.rb index 92c7a70d65..a052e0dd0a 100644 --- a/spec/services/unmute_service_spec.rb +++ b/spec/services/unmute_service_spec.rb @@ -16,7 +16,7 @@ RSpec.describe UnmuteService do it 'removes the account mute and sets up a merge' do expect { subject.call(account, target_account) } .to remove_account_mute - expect(MergeWorker).to have_enqueued_sidekiq_job(target_account.id, account.id) + expect(MergeWorker).to have_enqueued_sidekiq_job(target_account.id, account.id, 'home') end end diff --git a/spec/services/verify_link_service_spec.rb b/spec/services/verify_link_service_spec.rb index a4fd19751b..7e2f9607cf 100644 --- a/spec/services/verify_link_service_spec.rb +++ b/spec/services/verify_link_service_spec.rb @@ -46,6 +46,21 @@ RSpec.describe VerifyLinkService do end end + context 'when a link contains an back' do + let(:html) do + <<~HTML + + + Follow me on Mastodon + + HTML + end + + it 'marks the field as verified' do + expect(field.verified?).to be true + end + end + context 'when a link contains a back' do let(:html) do <<~HTML diff --git a/spec/support/examples/models/concerns/account_avatar.rb b/spec/support/examples/models/concerns/account_avatar.rb index 232f51fa3c..c6cc4e75a5 100644 --- a/spec/support/examples/models/concerns/account_avatar.rb +++ b/spec/support/examples/models/concerns/account_avatar.rb @@ -2,13 +2,20 @@ RSpec.shared_examples 'AccountAvatar' do |fabricator| describe 'static avatars', :attachment_processing do - describe 'when GIF' do + describe 'with a square GIF' do it 'creates a png static style' do account = Fabricate(fabricator, avatar: attachment_fixture('avatar.gif')) expect(account.avatar_static_url).to_not eq account.avatar_original_url end end + describe 'with a higher-than-wide GIF' do + it 'creates a png static style' do + account = Fabricate(fabricator, avatar: attachment_fixture('avatar-high.gif')) + expect(account.avatar_static_url).to_not eq account.avatar_original_url + end + end + describe 'when non-GIF' do it 'does not create extra static style' do account = Fabricate(fabricator, avatar: attachment_fixture('attachment.jpg')) diff --git a/spec/support/examples/models/concerns/browser_detection.rb b/spec/support/examples/models/concerns/browser_detection.rb new file mode 100644 index 0000000000..e80fa4595c --- /dev/null +++ b/spec/support/examples/models/concerns/browser_detection.rb @@ -0,0 +1,37 @@ +# frozen_string_literal: true + +RSpec.shared_examples 'BrowserDetection' do + subject { described_class.new(user_agent: 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.1 Safari/605.1.15') } + + describe '#detection' do + it 'sets a Browser instance as detection' do + expect(subject.detection) + .to be_a(Browser::Safari) + end + end + + describe '#browser' do + it 'returns browser name from id' do + expect(subject.browser) + .to eq(:safari) + end + end + + describe '#platform' do + it 'returns detected platform' do + expect(subject.platform) + .to eq(:mac) + end + end + + describe 'Callbacks' do + describe 'populating the user_agent value' do + subject { Fabricate.build described_class.name.underscore.to_sym, user_agent: nil } + + it 'changes nil to empty string' do + expect { subject.save } + .to change(subject, :user_agent).from(nil).to('') + end + end + end +end diff --git a/spec/system/about_spec.rb b/spec/system/about_spec.rb index f832802f91..d7fd7f51a1 100644 --- a/spec/system/about_spec.rb +++ b/spec/system/about_spec.rb @@ -8,5 +8,6 @@ RSpec.describe 'About page' do expect(page) .to have_css('noscript', text: /Mastodon/) + .and have_css('body', class: 'app-body') end end diff --git a/spec/system/home_spec.rb b/spec/system/home_spec.rb index c1ce4e1726..0838b3d8e7 100644 --- a/spec/system/home_spec.rb +++ b/spec/system/home_spec.rb @@ -11,6 +11,7 @@ RSpec.describe 'Home page' do expect(page) .to have_css('noscript', text: /Mastodon/) + .and have_css('body', class: 'app-body') end end @@ -20,6 +21,7 @@ RSpec.describe 'Home page' do expect(page) .to have_css('noscript', text: /Mastodon/) + .and have_css('body', class: 'app-body') end end end diff --git a/spec/system/oauth_spec.rb b/spec/system/oauth_spec.rb index 14ffc163f0..caed5ea9af 100644 --- a/spec/system/oauth_spec.rb +++ b/spec/system/oauth_spec.rb @@ -115,6 +115,8 @@ RSpec.describe 'Using OAuth from an external app' do subject within '.form-container .flash-message' do + # FIXME: Replace with doorkeeper.errors.messages.invalid_code_challenge_method.one for Doorkeeper > 5.8.0 + # see: https://github.com/doorkeeper-gem/doorkeeper/pull/1747 expect(page).to have_content(I18n.t('doorkeeper.errors.messages.invalid_code_challenge_method')) end end diff --git a/spec/system/privacy_spec.rb b/spec/system/privacy_spec.rb index 631440ebb2..f2e4d5a993 100644 --- a/spec/system/privacy_spec.rb +++ b/spec/system/privacy_spec.rb @@ -8,5 +8,6 @@ RSpec.describe 'Privacy policy page' do expect(page) .to have_css('noscript', text: /Mastodon/) + .and have_css('body', class: 'app-body') end end diff --git a/spec/system/tags_spec.rb b/spec/system/tags_spec.rb index f39c6bf0d8..9da5768c7f 100644 --- a/spec/system/tags_spec.rb +++ b/spec/system/tags_spec.rb @@ -13,6 +13,7 @@ RSpec.describe 'Tags' do expect(page) .to have_css('noscript', text: /Mastodon/) + .and have_css('body', class: 'app-body') .and have_private_cache_control end end diff --git a/spec/views/statuses/show.html.haml_spec.rb b/spec/views/statuses/show.html.haml_spec.rb index 1afcb046d4..02b1fe7384 100644 --- a/spec/views/statuses/show.html.haml_spec.rb +++ b/spec/views/statuses/show.html.haml_spec.rb @@ -18,7 +18,7 @@ RSpec.describe 'statuses/show.html.haml' do assign(:descendant_threads, []) end - it 'has valid opengraph tags' do + it 'has valid opengraph tags and twitter player tags' do render expect(header_tags) @@ -26,10 +26,6 @@ RSpec.describe 'statuses/show.html.haml' do .and match(//) .and match(//) .and match(%r{}) - end - - it 'has twitter player tag' do - render expect(header_tags) .to match(%r{}) diff --git a/spec/workers/activitypub/delivery_worker_spec.rb b/spec/workers/activitypub/delivery_worker_spec.rb index 3dfbef31a4..9e6805c68b 100644 --- a/spec/workers/activitypub/delivery_worker_spec.rb +++ b/spec/workers/activitypub/delivery_worker_spec.rb @@ -5,26 +5,45 @@ require 'rails_helper' RSpec.describe ActivityPub::DeliveryWorker do include RoutingHelper - subject { described_class.new } - - let(:sender) { Fabricate(:account) } + let(:sender) { Fabricate(:account) } let(:payload) { 'test' } + let(:url) { 'https://example.com/api' } before do - allow(sender).to receive(:remote_followers_hash).with('https://example.com/api').and_return('somehash') + allow(sender).to receive(:remote_followers_hash).with(url).and_return('somehash') allow(Account).to receive(:find).with(sender.id).and_return(sender) end describe 'perform' do - it 'performs a request' do - stub_request(:post, 'https://example.com/api').to_return(status: 200) - subject.perform(payload, sender.id, 'https://example.com/api', { synchronize_followers: true }) - expect(a_request(:post, 'https://example.com/api').with(headers: { 'Collection-Synchronization' => "collectionId=\"#{account_followers_url(sender)}\", digest=\"somehash\", url=\"#{account_followers_synchronization_url(sender)}\"" })).to have_been_made.once + context 'with successful request' do + before { stub_request(:post, url).to_return(status: 200) } + + it 'performs a request to synchronize collection' do + subject.perform(payload, sender.id, url, { synchronize_followers: true }) + + expect(request_to_url) + .to have_been_made.once + end + + def request_to_url + a_request(:post, url) + .with( + headers: { + 'Collection-Synchronization' => <<~VALUES.squish, + collectionId="#{account_followers_url(sender)}", digest="somehash", url="#{account_followers_synchronization_url(sender)}" + VALUES + } + ) + end end - it 'raises when request fails' do - stub_request(:post, 'https://example.com/api').to_return(status: 500) - expect { subject.perform(payload, sender.id, 'https://example.com/api') }.to raise_error Mastodon::UnexpectedResponseError + context 'with failing request' do + before { stub_request(:post, url).to_return(status: 500) } + + it 'raises error' do + expect { subject.perform(payload, sender.id, url) } + .to raise_error Mastodon::UnexpectedResponseError + end end end end diff --git a/spec/workers/publish_scheduled_status_worker_spec.rb b/spec/workers/publish_scheduled_status_worker_spec.rb index 35e510d253..9365e8a4bc 100644 --- a/spec/workers/publish_scheduled_status_worker_spec.rb +++ b/spec/workers/publish_scheduled_status_worker_spec.rb @@ -12,12 +12,26 @@ RSpec.describe PublishScheduledStatusWorker do subject.perform(scheduled_status.id) end - it 'creates a status' do - expect(scheduled_status.account.statuses.first.text).to eq 'Hello world, future!' + context 'when the account is not disabled' do + it 'creates a status' do + expect(scheduled_status.account.statuses.first.text).to eq 'Hello world, future!' + end + + it 'removes the scheduled status' do + expect(ScheduledStatus.find_by(id: scheduled_status.id)).to be_nil + end end - it 'removes the scheduled status' do - expect(ScheduledStatus.find_by(id: scheduled_status.id)).to be_nil + context 'when the account is disabled' do + let(:scheduled_status) { Fabricate(:scheduled_status, account: Fabricate(:account, user: Fabricate(:user, disabled: true))) } + + it 'does not create a status' do + expect(Status.count).to eq 0 + end + + it 'removes the scheduled status' do + expect(ScheduledStatus.find_by(id: scheduled_status.id)).to be_nil + end end end end diff --git a/streaming/database.js b/streaming/database.js index 9f1d742143..60a3b34ef0 100644 --- a/streaming/database.js +++ b/streaming/database.js @@ -116,13 +116,44 @@ let pool; /** * * @param {pg.PoolConfig} config + * @param {string} environment + * @param {import('pino').Logger} logger * @returns {pg.Pool} */ -export function getPool(config) { +export function getPool(config, environment, logger) { if (pool) { return pool; } pool = new pg.Pool(config); + + // Setup logging on pool.query and client.query for checked out clients: + // This is taken from: https://node-postgres.com/guides/project-structure + if (environment === 'development') { + const logQuery = (originalQuery) => { + return async (queryTextOrConfig, values, ...rest) => { + const start = process.hrtime(); + + const result = await originalQuery.apply(pool, [queryTextOrConfig, values, ...rest]); + + const duration = process.hrtime(start); + const durationInMs = (duration[0] * 1000000000 + duration[1]) / 1000000; + + logger.debug({ + query: queryTextOrConfig, + values, + duration: durationInMs + }, 'Executed database query'); + + return result; + }; + }; + + pool.on('connect', (client) => { + const originalQuery = client.query.bind(client); + client.query = logQuery(originalQuery); + }); + } + return pool; } diff --git a/streaming/index.js b/streaming/index.js index 3e362f1860..e00da1bb83 100644 --- a/streaming/index.js +++ b/streaming/index.js @@ -101,7 +101,8 @@ const CHANNEL_NAMES = [ ]; const startServer = async () => { - const pgPool = Database.getPool(Database.configFromEnv(process.env, environment)); + const pgConfig = Database.configFromEnv(process.env, environment); + const pgPool = Database.getPool(pgConfig, environment, logger); const metrics = setupMetrics(CHANNEL_NAMES, pgPool); diff --git a/streaming/package.json b/streaming/package.json index 585c4be4e1..521544f42b 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.1", + "packageManager": "yarn@4.5.2", "engines": { "node": ">=18" }, @@ -27,7 +27,7 @@ "pino": "^9.0.0", "pino-http": "^10.0.0", "prom-client": "^15.0.0", - "uuid": "^10.0.0", + "uuid": "^11.0.0", "ws": "^8.12.1" }, "devDependencies": { diff --git a/yarn.lock b/yarn.lock index 0b24803e6c..20d00347b8 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1463,13 +1463,13 @@ __metadata: languageName: node linkType: hard -"@csstools/cascade-layer-name-parser@npm:^2.0.3": - version: 2.0.3 - resolution: "@csstools/cascade-layer-name-parser@npm:2.0.3" +"@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.3 - "@csstools/css-tokenizer": ^3.0.2 - checksum: 10c0/a0f0d6c94122d0a82b0da94ee2619915a9e6e98211de6e1f28afebe34332a29cab1b7905a34b6e5c1df30a125df9f9860ce5fa960c676484417d4ef2c4db4757 + "@csstools/css-parser-algorithms": ^3.0.4 + "@csstools/css-tokenizer": ^3.0.3 + checksum: 10c0/774f2bcc96a576183853191bdfd31df15e22c51901ee01678ee47f1d1afcb4ab0e6d9a78e08f7383ac089c7e0b390013633f45ff1f1d577c9aefd252589bcced languageName: node linkType: hard @@ -1480,42 +1480,42 @@ __metadata: languageName: node linkType: hard -"@csstools/css-calc@npm:^2.0.3": - version: 2.0.3 - resolution: "@csstools/css-calc@npm:2.0.3" +"@csstools/css-calc@npm:^2.1.0": + version: 2.1.0 + resolution: "@csstools/css-calc@npm:2.1.0" peerDependencies: - "@csstools/css-parser-algorithms": ^3.0.3 - "@csstools/css-tokenizer": ^3.0.2 - checksum: 10c0/a3dacda66bde67edab0f2384e85462dcd46b5bb62bc2a6396f0577a006d9ad59eae270353cbd6fe1a5f7081d0546fe4b1fd9b2df242758da54ec8b7022296570 + "@csstools/css-parser-algorithms": ^3.0.4 + "@csstools/css-tokenizer": ^3.0.3 + checksum: 10c0/c707bb533a6ea63ed5bb4b8f1ffcbf3cd2daf970a6d76d42b684243426f5aa7513179a8f34d2e3c5a85df3870f44d3bc2850ca40b085c5fe00b41a291a2ecae2 languageName: node linkType: hard -"@csstools/css-color-parser@npm:^3.0.4": - version: 3.0.4 - resolution: "@csstools/css-color-parser@npm:3.0.4" +"@csstools/css-color-parser@npm:^3.0.6": + version: 3.0.6 + resolution: "@csstools/css-color-parser@npm:3.0.6" dependencies: "@csstools/color-helpers": "npm:^5.0.1" - "@csstools/css-calc": "npm:^2.0.3" + "@csstools/css-calc": "npm:^2.1.0" peerDependencies: - "@csstools/css-parser-algorithms": ^3.0.3 - "@csstools/css-tokenizer": ^3.0.2 - checksum: 10c0/8f05264254d3768e45e46ce10e9355fe8ca0f6e4d2f648a22572f46c6d05b2378c37c2e5d970ed3b7bdfa0b152ea2af0c56a0556249bd85973aee9db7b091aa7 + "@csstools/css-parser-algorithms": ^3.0.4 + "@csstools/css-tokenizer": ^3.0.3 + checksum: 10c0/7c4f42a704c8c44cece75f5dcd647a83634dec0f44d398ae1fbdc6e8527d4fbdc3a809eaaba3b739edf8e3c09d62c28234636f250f9b0b0d52a599e824c22047 languageName: node linkType: hard -"@csstools/css-parser-algorithms@npm:^3.0.1, @csstools/css-parser-algorithms@npm:^3.0.3": +"@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.3 + checksum: 10c0/d411f07765e14eede17bccc6bd4f90ff303694df09aabfede3fd104b2dfacfd4fe3697cd25ddad14684c850328f3f9420ebfa9f78380892492974db24ae47dbd + languageName: node + linkType: hard + +"@csstools/css-tokenizer@npm:^3.0.1, @csstools/css-tokenizer@npm:^3.0.3": version: 3.0.3 - resolution: "@csstools/css-parser-algorithms@npm:3.0.3" - peerDependencies: - "@csstools/css-tokenizer": ^3.0.2 - checksum: 10c0/c1e634384affb10c3726a36f090867247005a2a470cb223de88debeab07921b78c0e7875e7847d90949c2b0ba88a290c71565f1839f7739c21a5bf1c870e137d - 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 + resolution: "@csstools/css-tokenizer@npm:3.0.3" + checksum: 10c0/c31bf410e1244b942e71798e37c54639d040cb59e0121b21712b40015fced2b0fb1ffe588434c5f8923c9cd0017cfc1c1c8f3921abc94c96edf471aac2eba5e5 languageName: node linkType: hard @@ -1529,13 +1529,13 @@ __metadata: languageName: node linkType: hard -"@csstools/media-query-list-parser@npm:^4.0.1": - version: 4.0.1 - resolution: "@csstools/media-query-list-parser@npm:4.0.1" +"@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.3 - "@csstools/css-tokenizer": ^3.0.2 - checksum: 10c0/037f57520b6ca7d58ba1d71a477bd99bdbe3a6d8e7b972ed0f436d649e574f5b429e54fc47d0272daa2ac24ffb819bd9d260a90e154c4a265b8ee4d1cfb1d279 + "@csstools/css-parser-algorithms": ^3.0.4 + "@csstools/css-tokenizer": ^3.0.3 + checksum: 10c0/5d008a70f5d4fd96224066a433f5cdefa76cfd78a74416a20d6d5b2bb1bc8282b140e8373015d807d4dadb91daf3deb73eb13f853ec4e0479d0cb92e80c6f20d languageName: node linkType: hard @@ -1551,60 +1551,60 @@ __metadata: languageName: node linkType: hard -"@csstools/postcss-color-function@npm:^4.0.4": - version: 4.0.4 - resolution: "@csstools/postcss-color-function@npm:4.0.4" +"@csstools/postcss-color-function@npm:^4.0.6": + version: 4.0.6 + resolution: "@csstools/postcss-color-function@npm:4.0.6" dependencies: - "@csstools/css-color-parser": "npm:^3.0.4" - "@csstools/css-parser-algorithms": "npm:^3.0.3" - "@csstools/css-tokenizer": "npm:^3.0.2" + "@csstools/css-color-parser": "npm:^3.0.6" + "@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/e7735c6d7c84f039c84dc1b180410aa4db7c404d55477c2e7872bc8306a3150bf37883583ec080ebd8b40b765f700cc78892d61dc167578f76e324543d551c04 + checksum: 10c0/facbae01fd58898a176219cfcffee9ffb06fb466a2c439fd28403819e48778b682621b86a69682c0f758c659f8ec5f14eca1a9612b12b8777a2198173f386b49 languageName: node linkType: hard -"@csstools/postcss-color-mix-function@npm:^3.0.4": - version: 3.0.4 - resolution: "@csstools/postcss-color-mix-function@npm:3.0.4" +"@csstools/postcss-color-mix-function@npm:^3.0.6": + version: 3.0.6 + resolution: "@csstools/postcss-color-mix-function@npm:3.0.6" dependencies: - "@csstools/css-color-parser": "npm:^3.0.4" - "@csstools/css-parser-algorithms": "npm:^3.0.3" - "@csstools/css-tokenizer": "npm:^3.0.2" + "@csstools/css-color-parser": "npm:^3.0.6" + "@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/3e01f04853e49c9f69ee0538b817209b630649844039ee5b195cfbae94d41cf6e0d8a50a3d02dbe066f84855eefa1b7047f6750e4744858519978468577e567f + checksum: 10c0/66b906b2425ed137b1c2ef3d166036719ae69039668385dccce4e02bd91e41733b37dd3c884b74a2999067bfe8a8d8d1afa4082ef21a0bf044ba7e7fffb77e01 languageName: node linkType: hard -"@csstools/postcss-content-alt-text@npm:^2.0.3": - version: 2.0.3 - resolution: "@csstools/postcss-content-alt-text@npm:2.0.3" +"@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.3" - "@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/0389292a1ba11483f58db1bdd38cc774b0ec18c73f03d1db5f4a1f38edc861bb8b8d750b5c5b3615a98aaf995c0464dcfd6db5421888be0f868548c69455b5b3 + checksum: 10c0/84caccedd8a519df434babd58b14104c5a92cd326057ce509bdbaa2a4bb3130afb1c1456caf30235ba14da52d1628a5411ea4f5d2fb558d603d234f795538017 languageName: node linkType: hard -"@csstools/postcss-exponential-functions@npm:^2.0.3": - version: 2.0.3 - resolution: "@csstools/postcss-exponential-functions@npm:2.0.3" +"@csstools/postcss-exponential-functions@npm:^2.0.5": + version: 2.0.5 + resolution: "@csstools/postcss-exponential-functions@npm:2.0.5" dependencies: - "@csstools/css-calc": "npm:^2.0.3" - "@csstools/css-parser-algorithms": "npm:^3.0.3" - "@csstools/css-tokenizer": "npm:^3.0.2" + "@csstools/css-calc": "npm:^2.1.0" + "@csstools/css-parser-algorithms": "npm:^3.0.4" + "@csstools/css-tokenizer": "npm:^3.0.3" peerDependencies: postcss: ^8.4 - checksum: 10c0/690ac6c5ec72e085160401100cc8465a040fd70d59efadf61ef767094edac28bbb2653f53ea7cfa47d8220d0be0b9e23c3e3c2b80d9e93ad07b1db8031163d70 + checksum: 10c0/8935cb69f70d7448aa5a3dcdfd188bdcfbc34e9a99131306947df8847126272773212011dcff85e10bcee4c9d01f94f7f8557ef93933122a0b82743185684ab1 languageName: node linkType: hard @@ -1620,46 +1620,46 @@ __metadata: languageName: node linkType: hard -"@csstools/postcss-gamut-mapping@npm:^2.0.4": - version: 2.0.4 - resolution: "@csstools/postcss-gamut-mapping@npm:2.0.4" +"@csstools/postcss-gamut-mapping@npm:^2.0.6": + version: 2.0.6 + resolution: "@csstools/postcss-gamut-mapping@npm:2.0.6" dependencies: - "@csstools/css-color-parser": "npm:^3.0.4" - "@csstools/css-parser-algorithms": "npm:^3.0.3" - "@csstools/css-tokenizer": "npm:^3.0.2" + "@csstools/css-color-parser": "npm:^3.0.6" + "@csstools/css-parser-algorithms": "npm:^3.0.4" + "@csstools/css-tokenizer": "npm:^3.0.3" peerDependencies: postcss: ^8.4 - checksum: 10c0/60c6ff13cc71a0cda7ce184fa8b42924975f2bd05e3bc096059de853ae01d48e36f27d02d7e6286d9e8c4eb4dfd526f7c302ff51be19c5f7949dd6079915a3a9 + checksum: 10c0/8a3f012774ab261924cc9f3519caa87a25a6abcd70d78f622144d8e7126a687bddbdaa92995fc30f53355759cd5971e71ac099b6b8cb85c89d8ca86455588e3b languageName: node linkType: hard -"@csstools/postcss-gradients-interpolation-method@npm:^5.0.4": - version: 5.0.4 - resolution: "@csstools/postcss-gradients-interpolation-method@npm:5.0.4" +"@csstools/postcss-gradients-interpolation-method@npm:^5.0.6": + version: 5.0.6 + resolution: "@csstools/postcss-gradients-interpolation-method@npm:5.0.6" dependencies: - "@csstools/css-color-parser": "npm:^3.0.4" - "@csstools/css-parser-algorithms": "npm:^3.0.3" - "@csstools/css-tokenizer": "npm:^3.0.2" + "@csstools/css-color-parser": "npm:^3.0.6" + "@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/3b6aa4404851be09a083f35b596acc7e3f74f525386dcd2887720438638ca1893f79e699e5dad0e3a35487cb9527e08d0dcd29f1331f87800f53c13423321d6e + checksum: 10c0/0d97be76837f972ea323b58189ded2310b618ad94b40777464d0d8ac050b557ca9fd1f20af5ada105d61574cc9d8c119ae0daf294a3aacaaa89926f864d9d674 languageName: node linkType: hard -"@csstools/postcss-hwb-function@npm:^4.0.4": - version: 4.0.4 - resolution: "@csstools/postcss-hwb-function@npm:4.0.4" +"@csstools/postcss-hwb-function@npm:^4.0.6": + version: 4.0.6 + resolution: "@csstools/postcss-hwb-function@npm:4.0.6" dependencies: - "@csstools/css-color-parser": "npm:^3.0.4" - "@csstools/css-parser-algorithms": "npm:^3.0.3" - "@csstools/css-tokenizer": "npm:^3.0.2" + "@csstools/css-color-parser": "npm:^3.0.6" + "@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/2460cc7e6324f0793d12976de175ff33344c3410ff7a04ca8a5ce0560ee3354d1d8034f9f07c0759c2b7e222a4681d02298f6a29c2a326c76b33060830da83b4 + checksum: 10c0/e7bcc98095ef2873a7b1a7326f1618bbeecc1c78660b23805bbefd8ec067bf2f35f2a2d4675be51a02d2280046f36f74d55f6af78e3ce107b82624d1a421ffcf languageName: node linkType: hard @@ -1697,17 +1697,17 @@ __metadata: languageName: node linkType: hard -"@csstools/postcss-light-dark-function@npm:^2.0.6": - version: 2.0.6 - resolution: "@csstools/postcss-light-dark-function@npm:2.0.6" +"@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.3" - "@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/f3e93b58a23f0f01c9d032a892070a18e3393e60997e1d2b57c5bddb2cb36f7ee6cbaeaeb3d531b065a545a03e54d86567d34b45eddf85ed48ac360eb4ab66cd + checksum: 10c0/c116bfd2d3f4d0caabdedf8954c2a25908ffb29f9bbe2c57d44a2974277c7e46ee79862eea848385dc040275d343f2330350394a2095ec30f0aa17f72e2f4e39 languageName: node linkType: hard @@ -1749,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.3": - version: 2.0.3 - resolution: "@csstools/postcss-media-minmax@npm:2.0.3" +"@csstools/postcss-media-minmax@npm:^2.0.5": + version: 2.0.5 + resolution: "@csstools/postcss-media-minmax@npm:2.0.5" dependencies: - "@csstools/css-calc": "npm:^2.0.3" - "@csstools/css-parser-algorithms": "npm:^3.0.3" - "@csstools/css-tokenizer": "npm:^3.0.2" - "@csstools/media-query-list-parser": "npm:^4.0.1" + "@csstools/css-calc": "npm:^2.1.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/87c1ed6fe6ed487125e383ae7bc356ba0f68885c41cd129b85c323af69255031a8ac7b2e994d4f9b6b65d6a9f6833aeb1301ca230b592547825aedb3e3acab4b + checksum: 10c0/0d17782076fcaba2c3c85bd769fc102d95809e9ee6141ad9de706ee116466cada62424fd68623c58cc2456771725291c356e550377ba73a102ab6fe628931e30 languageName: node linkType: hard -"@csstools/postcss-media-queries-aspect-ratio-number-values@npm:^3.0.3": - version: 3.0.3 - resolution: "@csstools/postcss-media-queries-aspect-ratio-number-values@npm:3.0.3" +"@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.3" - "@csstools/css-tokenizer": "npm:^3.0.2" - "@csstools/media-query-list-parser": "npm:^4.0.1" + "@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/3bbadd5c79ff2102b4a2e0f107d7f3cbb89d2840b935915531d0a1bfc711d58386e6e234fccb9b4abb37e48f07cdfaa4dd66b5c795dfac9e317fa8b5cfd38e06 + checksum: 10c0/27dc9419b0f4315774647588f599348e7cc593984f59b414c51c910066501fd087cbe232deb762907c18bd21dd4184e7b6e0e0b730e5c72341ab9cc696c75739 languageName: node linkType: hard @@ -1811,18 +1811,18 @@ __metadata: languageName: node linkType: hard -"@csstools/postcss-oklab-function@npm:^4.0.4": - version: 4.0.4 - resolution: "@csstools/postcss-oklab-function@npm:4.0.4" +"@csstools/postcss-oklab-function@npm:^4.0.6": + version: 4.0.6 + resolution: "@csstools/postcss-oklab-function@npm:4.0.6" dependencies: - "@csstools/css-color-parser": "npm:^3.0.4" - "@csstools/css-parser-algorithms": "npm:^3.0.3" - "@csstools/css-tokenizer": "npm:^3.0.2" + "@csstools/css-color-parser": "npm:^3.0.6" + "@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/4fd2a5c22ebaf69053e005d9d009ccb41b6879f0246677159bfb6a28208e90af857446c443d34fe3efdaf50bccdd67b16fcd0c1e7c52961396a48bd84e45311f + checksum: 10c0/74ec74eb7171881deeff7a79e0dc696097fb53dcdcd9627d9559cd7be63f41adecec06c1e88ddd5d8a37f4705715d1c0c135ca2b001fb70fdc0b76ab1e491b66 languageName: node linkType: hard @@ -1837,18 +1837,31 @@ __metadata: languageName: node linkType: hard -"@csstools/postcss-relative-color-syntax@npm:^3.0.4": - version: 3.0.4 - resolution: "@csstools/postcss-relative-color-syntax@npm:3.0.4" +"@csstools/postcss-random-function@npm:^1.0.0": + version: 1.0.1 + resolution: "@csstools/postcss-random-function@npm:1.0.1" dependencies: - "@csstools/css-color-parser": "npm:^3.0.4" - "@csstools/css-parser-algorithms": "npm:^3.0.3" - "@csstools/css-tokenizer": "npm:^3.0.2" + "@csstools/css-calc": "npm:^2.1.0" + "@csstools/css-parser-algorithms": "npm:^3.0.4" + "@csstools/css-tokenizer": "npm:^3.0.3" + peerDependencies: + postcss: ^8.4 + checksum: 10c0/5e8f29c024aa6ed1f89ee8b9c8ece39c8e72602d63faa82d9684e3183828f01971cf2f760b7d5b773605d44a4ea661d6d4389ec03f7e21002f9aa9e8db613a61 + languageName: node + linkType: hard + +"@csstools/postcss-relative-color-syntax@npm:^3.0.6": + version: 3.0.6 + resolution: "@csstools/postcss-relative-color-syntax@npm:3.0.6" + dependencies: + "@csstools/css-color-parser": "npm:^3.0.6" + "@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/f2ae6f9053e976e2431d08bdc5aa40ca5242754e23370abdfd7b6087d7ed56037e46911d1be801cf7e760aa8aee94bcab6a46f4f68696cf6befacf707c1534b7 + checksum: 10c0/207ae711831f8ae9170093dbea3727cd6f32ca31d22c1231b5b678592679eb49e329e87ea403714b8e10feb5b9137780364cc7e1e7d8cc4c90d47483a42132dc languageName: node linkType: hard @@ -1863,16 +1876,29 @@ __metadata: languageName: node linkType: hard -"@csstools/postcss-stepped-value-functions@npm:^4.0.3": - version: 4.0.3 - resolution: "@csstools/postcss-stepped-value-functions@npm:4.0.3" +"@csstools/postcss-sign-functions@npm:^1.0.0": + version: 1.0.0 + resolution: "@csstools/postcss-sign-functions@npm:1.0.0" dependencies: - "@csstools/css-calc": "npm:^2.0.3" - "@csstools/css-parser-algorithms": "npm:^3.0.3" - "@csstools/css-tokenizer": "npm:^3.0.2" + "@csstools/css-calc": "npm:^2.1.0" + "@csstools/css-parser-algorithms": "npm:^3.0.4" + "@csstools/css-tokenizer": "npm:^3.0.3" peerDependencies: postcss: ^8.4 - checksum: 10c0/31af5a650d4b2de97d3a3ef77e7ad0777b3f013f7463e23455ac31ffc946d2f79f365a1fdead52c7c535176232ab57f6f086ecdbeca1bb0b250161b1302e8c8c + checksum: 10c0/ec745b2f1e714ffead43ade5964234dfc1750c3a71d2e29df862ab3f79ba4a1275187b270b4c226bbb1155bee8e9e63c35597b4f4cb3effaa632e5e07e422344 + languageName: node + linkType: hard + +"@csstools/postcss-stepped-value-functions@npm:^4.0.5": + version: 4.0.5 + resolution: "@csstools/postcss-stepped-value-functions@npm:4.0.5" + dependencies: + "@csstools/css-calc": "npm:^2.1.0" + "@csstools/css-parser-algorithms": "npm:^3.0.4" + "@csstools/css-tokenizer": "npm:^3.0.3" + peerDependencies: + postcss: ^8.4 + checksum: 10c0/76f1f60c24b9e6a80b044eb19f37c1816788a2335fbf7c25f3fbea1cd7104857f424a451dcff60e4f8841618c6b6ffa6091f8b840d6d5930c1c7100c2f8ae74b languageName: node linkType: hard @@ -1888,16 +1914,16 @@ __metadata: languageName: node linkType: hard -"@csstools/postcss-trigonometric-functions@npm:^4.0.3": - version: 4.0.3 - resolution: "@csstools/postcss-trigonometric-functions@npm:4.0.3" +"@csstools/postcss-trigonometric-functions@npm:^4.0.5": + version: 4.0.5 + resolution: "@csstools/postcss-trigonometric-functions@npm:4.0.5" dependencies: - "@csstools/css-calc": "npm:^2.0.3" - "@csstools/css-parser-algorithms": "npm:^3.0.3" - "@csstools/css-tokenizer": "npm:^3.0.2" + "@csstools/css-calc": "npm:^2.1.0" + "@csstools/css-parser-algorithms": "npm:^3.0.4" + "@csstools/css-tokenizer": "npm:^3.0.3" peerDependencies: postcss: ^8.4 - checksum: 10c0/a13dd72c00e45e6db16c03e135f1cd1b2b412e83b7681696b49feef3a4c36ab80f5f806f3589d33405e2d14dd0dfb13572ec12007ebe3d294077b0bd3d645b2b + checksum: 10c0/b8518c8b81da047448dcee12a5f3716dbc19671333387a4a673991a16f1a120441d2768de8a30ce1e2ef8d0d76509b9509f506ef1e8630da84834451414b23a3 languageName: node linkType: hard @@ -2206,8 +2232,8 @@ __metadata: linkType: hard "@formatjs/cli@npm:^6.1.1": - version: 6.3.5 - resolution: "@formatjs/cli@npm:6.3.5" + version: 6.3.11 + resolution: "@formatjs/cli@npm:6.3.11" peerDependencies: "@glimmer/env": ^0.1.7 "@glimmer/reference": ^0.91.1 || ^0.92.0 @@ -2236,7 +2262,7 @@ __metadata: optional: true bin: formatjs: bin/formatjs - checksum: 10c0/f3fd57de6df3ef0cfa668813c49acd7dcbecbf52444f30e8edec4ee7bc2d8c47c2e6fb4b7ce3c9c5b4595bdf8416c37953ebb05b400f99874a7f810943f6265b + checksum: 10c0/31d5fac85314e97591c4c6a4793abf1d9c6fbf790fbbea779b2a4c0f742f1859804f290e77be06d128274468e44bc27992196aacb4cb6f2fbd141755ca79a98d languageName: node linkType: hard @@ -2251,14 +2277,14 @@ __metadata: languageName: node linkType: hard -"@formatjs/ecma402-abstract@npm:2.2.1": - version: 2.2.1 - resolution: "@formatjs/ecma402-abstract@npm:2.2.1" +"@formatjs/ecma402-abstract@npm:2.2.3": + version: 2.2.3 + resolution: "@formatjs/ecma402-abstract@npm:2.2.3" dependencies: - "@formatjs/fast-memoize": "npm:2.2.2" - "@formatjs/intl-localematcher": "npm:0.5.6" + "@formatjs/fast-memoize": "npm:2.2.3" + "@formatjs/intl-localematcher": "npm:0.5.7" tslib: "npm:2" - checksum: 10c0/bb0b01282368d201d9bcfb3232963af90069f6048da5824d38a674118fd49a0cb92b05d19d2526fe6d035428b2e47e1abd671bb59a673317f1418e67974253fa + checksum: 10c0/611d12bf320fc5c5b85cb2b57e3dcebe8490a51c6a0459c857c7a3560656cd2bdba5b117e9dd7cf174f5aa120c11eaad7a65a6783637b816caa59a1bc5c727f6 languageName: node linkType: hard @@ -2271,12 +2297,12 @@ __metadata: languageName: node linkType: hard -"@formatjs/fast-memoize@npm:2.2.2": - version: 2.2.2 - resolution: "@formatjs/fast-memoize@npm:2.2.2" +"@formatjs/fast-memoize@npm:2.2.3": + version: 2.2.3 + resolution: "@formatjs/fast-memoize@npm:2.2.3" dependencies: tslib: "npm:2" - checksum: 10c0/cebbf632a6ed8798ed67dba59d05be8bbe81c9ada7bcbc8ce69798fbaa5e0117c35792f212097d28b8b06fb99cf73bdbc7754702c06cda34f847e5082814643b + checksum: 10c0/f1004c3b280de7e362bd37c5f48ff34c2ba1d6271d4a7b695fed561d1201a3379397824d8bffbf15fecee344d1e70398393bbb04297f242692310a305f12e75b languageName: node linkType: hard @@ -2291,14 +2317,14 @@ __metadata: languageName: node linkType: hard -"@formatjs/icu-messageformat-parser@npm:2.9.1": - version: 2.9.1 - resolution: "@formatjs/icu-messageformat-parser@npm:2.9.1" +"@formatjs/icu-messageformat-parser@npm:2.9.3": + version: 2.9.3 + resolution: "@formatjs/icu-messageformat-parser@npm:2.9.3" dependencies: - "@formatjs/ecma402-abstract": "npm:2.2.1" - "@formatjs/icu-skeleton-parser": "npm:1.8.5" + "@formatjs/ecma402-abstract": "npm:2.2.3" + "@formatjs/icu-skeleton-parser": "npm:1.8.7" tslib: "npm:2" - checksum: 10c0/53554edc7d41f6bd737dc3bb3e03dcd4b4081b4fc9a70383612b87993c1639747d1d3827d8ebb13f8bf3566c60442549a0a42df4959699eef76633d4c7b49b25 + checksum: 10c0/519b59f7b4cf90681315c5382f7fcd105eb1974486f0d62d9227b6d0498895114ccc818792c208baae1ef79571d93b0edb9914c676e5ab76924dddb7fd6c28a0 languageName: node linkType: hard @@ -2312,35 +2338,35 @@ __metadata: languageName: node linkType: hard -"@formatjs/icu-skeleton-parser@npm:1.8.5": - version: 1.8.5 - resolution: "@formatjs/icu-skeleton-parser@npm:1.8.5" +"@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.1" + "@formatjs/ecma402-abstract": "npm:2.2.3" tslib: "npm:2" - checksum: 10c0/3e5ddd26e5dc983547320ca09b4a5daa692a00c15382e85474a9a539c223b581dba2290708d71aae12589c3ddd053b3bfd0dab0a07a11c44033fb313605566bc + checksum: 10c0/e29eb4151580f2d324e6591509dc4543e2326266fc209a08580c94d502acab14acc3560d98b3aaf9ffbd5ff8e2683601ff08c65b32886f22da015c31ca35c5d0 languageName: node linkType: hard -"@formatjs/intl-displaynames@npm:6.8.1": - version: 6.8.1 - resolution: "@formatjs/intl-displaynames@npm:6.8.1" +"@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.1" - "@formatjs/intl-localematcher": "npm:0.5.6" + "@formatjs/ecma402-abstract": "npm:2.2.3" + "@formatjs/intl-localematcher": "npm:0.5.7" tslib: "npm:2" - checksum: 10c0/6d39c7bbc3cf0b1398463d662662e5c7c8b873fe977e93b7d702a337f1ed639246492b71b7138c1f193df9e1045add5609edb3fd3efc76c6174ce134c02a186f + checksum: 10c0/54d3ecaabc45dc8494be4cd9633bbf5eb0bc40c5f62ed5e5073aa5b214c4a9a9620d61d1c8a6f0074618474fd9c2ccc42904605078d2f6341c242bf43627bb3a languageName: node linkType: hard -"@formatjs/intl-listformat@npm:7.7.1": - version: 7.7.1 - resolution: "@formatjs/intl-listformat@npm:7.7.1" +"@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.1" - "@formatjs/intl-localematcher": "npm:0.5.6" + "@formatjs/ecma402-abstract": "npm:2.2.3" + "@formatjs/intl-localematcher": "npm:0.5.7" tslib: "npm:2" - checksum: 10c0/9ac38d34956ee8018c000bbd594c84f1de283d18441f1376b072658844735a4ebee61ac4711f824dd0a89f4a855acfc7a24159e4cd8a4747609b1d2153316a61 + checksum: 10c0/2683513e86cc7885528f23237079e3ab9e3a8bc7111aa10d4c685dcbe368ef07039573115df240112fb20f2ec0b70c8ea189ea3b79cbfed7e3dc46024a4667ff languageName: node linkType: hard @@ -2353,43 +2379,43 @@ __metadata: languageName: node linkType: hard -"@formatjs/intl-localematcher@npm:0.5.6": - version: 0.5.6 - resolution: "@formatjs/intl-localematcher@npm:0.5.6" +"@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/39fc454641b7871f4b37416a01c7851624db6f1bf6cdcd5c854dfe06b95c0ca7540ec7c803a654140fc3f1c758596a684de8054bc95c4d6c7962091c251f5671 + checksum: 10c0/1ae374ca146a0d7457794926eed808c99971628e594f704a42ae2540b1f38928b26cbf942a7bbcc2796cc9fe8d9d7a603ac422bd9b89b714d2f91b506da40792 languageName: node linkType: hard "@formatjs/intl-pluralrules@npm:^5.2.2": - version: 5.3.1 - resolution: "@formatjs/intl-pluralrules@npm:5.3.1" + version: 5.3.3 + resolution: "@formatjs/intl-pluralrules@npm:5.3.3" dependencies: - "@formatjs/ecma402-abstract": "npm:2.2.1" - "@formatjs/intl-localematcher": "npm:0.5.6" + "@formatjs/ecma402-abstract": "npm:2.2.3" + "@formatjs/intl-localematcher": "npm:0.5.7" tslib: "npm:2" - checksum: 10c0/71a87aa81d5d69d56dca0636144f8f9714176b95fe3bc92ae1e455322c09b5b09ba0018315d81def00e89fc95e4fbffe41110104c86eb189ba6d58ac09efa48c + checksum: 10c0/003d33af6f5d902517f230b7038e39b8336da3a84500fe5f4278fa5cac0c9a1b746de484f1c2bb2315026fd771491eafdc0aa59a809bb25189b63093efb8400d languageName: node linkType: hard -"@formatjs/intl@npm:2.10.11": - version: 2.10.11 - resolution: "@formatjs/intl@npm:2.10.11" +"@formatjs/intl@npm:2.10.13": + version: 2.10.13 + resolution: "@formatjs/intl@npm:2.10.13" dependencies: - "@formatjs/ecma402-abstract": "npm:2.2.1" - "@formatjs/fast-memoize": "npm:2.2.2" - "@formatjs/icu-messageformat-parser": "npm:2.9.1" - "@formatjs/intl-displaynames": "npm:6.8.1" - "@formatjs/intl-listformat": "npm:7.7.1" - intl-messageformat: "npm:10.7.3" + "@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/83baa76d1194dbaae38c21d28cdc4e1ce024f8c49a37e2c02629a9f6afe18912f640435e346fae11af7d8128dac6355b36b93cff37685542ab3095edf3ec6d19 + checksum: 10c0/14edcc45addc181c7a45845bc34cec5c73bb5544dcf8ed455eca916bbd3a5023c7204a8e8e289060545b85006933c6f297c33c4f04a8a4cb3890aa7baae5bfbf languageName: node linkType: hard @@ -2413,13 +2439,13 @@ __metadata: languageName: node linkType: hard -"@formatjs/ts-transformer@npm:3.13.20": - version: 3.13.20 - resolution: "@formatjs/ts-transformer@npm:3.13.20" +"@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.1" + "@formatjs/icu-messageformat-parser": "npm:2.9.3" "@types/json-stable-stringify": "npm:1" - "@types/node": "npm:14 || 16 || 17 || 18 || 20" + "@types/node": "npm:14 || 16 || 17 || 18 || 20 || 22" chalk: "npm:4" json-stable-stringify: "npm:1" tslib: "npm:2" @@ -2429,7 +2455,7 @@ __metadata: peerDependenciesMeta: ts-jest: optional: true - checksum: 10c0/0c1a203ce2e0efc24b9c1fc087771330f9630ebb4220e34dd2fffe64d5ee94816554df8ed8402a54dd588c186617765efb6c200a3373cf1d5dfb093ba8d70416 + checksum: 10c0/42503292248bcae728181fdf68e79eac4169c18064953beb9245097d2c58e5434ae7a7978e6ce2829dfd6eb4b4155f78fecef70ac6820626a338f231c66f60cb languageName: node linkType: hard @@ -3001,7 +3027,7 @@ __metadata: prom-client: "npm:^15.0.0" typescript: "npm:^5.0.4" utf-8-validate: "npm:^6.0.3" - uuid: "npm:^10.0.0" + uuid: "npm:^11.0.0" ws: "npm:^8.12.1" dependenciesMeta: bufferutil: @@ -3445,8 +3471,8 @@ __metadata: linkType: hard "@testing-library/jest-dom@npm:^6.0.0": - version: 6.6.2 - resolution: "@testing-library/jest-dom@npm:6.6.2" + 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" @@ -3455,7 +3481,7 @@ __metadata: dom-accessibility-api: "npm:^0.6.3" lodash: "npm:^4.17.21" redent: "npm:^3.0.0" - checksum: 10c0/1c51390f97063ce8b06a7267534aac0d6ac9b1f27042a0ae43ca52d886b32c9d2b0ff85e62e7cfeb7e1f089ef03c4d75fda4f2b7b1f08afb4bdb09a5d56566d9 + checksum: 10c0/5566b6c0b7b0709bc244aec3aa3dc9e5f4663e8fb2b99d8cd456fc07279e59db6076cbf798f9d3099a98fca7ef4cd50e4e1f4c4dec5a60a8fad8d24a638a5bf6 languageName: node linkType: hard @@ -3776,9 +3802,9 @@ __metadata: linkType: hard "@types/lodash@npm:^4.14.195": - version: 4.17.12 - resolution: "@types/lodash@npm:4.17.12" - checksum: 10c0/106008f628ea3c74ed7ee7842dee79e230c84e3721ac38c293700031adb5bd130113048c22f476dbde0d0c119506b0fc447d4bd62eca922682d11e00e1377967 + version: 4.17.13 + resolution: "@types/lodash@npm:4.17.13" + checksum: 10c0/c3d0b7efe7933ac0369b99f2f7bff9240d960680fdb74b41ed4bd1b3ca60cca1e31fe4046d9abbde778f941a41bc2a75eb629abf8659fa6c27b66efbbb0802a9 languageName: node linkType: hard @@ -3803,12 +3829,12 @@ __metadata: languageName: node linkType: hard -"@types/node@npm:*, @types/node@npm:14 || 16 || 17 || 18 || 20": - version: 20.16.13 - resolution: "@types/node@npm:20.16.13" +"@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:~6.19.2" - checksum: 10c0/7f4fd7176db0802c62e11ebbf7a66d0248e2dc8ec9153d9fc8bcb164d9aed581d91c407046c823c522e60d0babfdc24a1618dba7f2c6920ef1a24e1d416c9550 + undici-types: "npm:~6.19.8" + checksum: 10c0/d3a11f2549234a91a4c5d0ff35ab4bdcb7ba34db4d3f1d189be39b8bd41c19aac98d117150a95a9c5a9d45b1014135477ea240b2b8317c86ae3d3cf1c3b3f8f4 languageName: node linkType: hard @@ -3998,7 +4024,7 @@ __metadata: languageName: node linkType: hard -"@types/react@npm:*, @types/react@npm:>=16.9.11, @types/react@npm:^18.2.7, @types/react@npm:^18.3.11": +"@types/react@npm:*, @types/react@npm:16 || 17 || 18, @types/react@npm:>=16.9.11, @types/react@npm:^18.2.7": version: 18.3.12 resolution: "@types/react@npm:18.3.12" dependencies: @@ -4151,11 +4177,11 @@ __metadata: 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 @@ -5180,21 +5206,21 @@ __metadata: linkType: hard "babel-plugin-formatjs@npm:^10.5.1": - version: 10.5.22 - resolution: "babel-plugin-formatjs@npm:10.5.22" + version: 10.5.24 + resolution: "babel-plugin-formatjs@npm:10.5.24" dependencies: "@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.1" - "@formatjs/ts-transformer": "npm:3.13.20" + "@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/c35ec81d89eb228d23d3d62e7e4d0e5d7216f0d09f91b1dc3c46e049c5515a201fcfe77c1079924c6bfb9883b2941af91431f479a0f5a24a0574b695f18b64bc + checksum: 10c0/a99c92e62edb30e0b6a5bf1115811eb18336b851109f8c096b5a9aa2be3eb72299eea3a8cb706e03705eb79edfa5a62d69bb52d80a375c1d5a1c963e3d00c40e languageName: node linkType: hard @@ -6714,10 +6740,10 @@ __metadata: languageName: node linkType: hard -"cssdb@npm:^8.1.2": - version: 8.1.2 - resolution: "cssdb@npm:8.1.2" - checksum: 10c0/056149e713a78921f56d9ef0cd734577cedb93c27966c3d0eab01956a2aa8d3c260a911766064b57ded8b4d9c55dd5275626cbb022ccd8d2d0b93b53fefd1603 +"cssdb@npm:^8.2.1": + version: 8.2.1 + resolution: "cssdb@npm:8.2.1" + checksum: 10c0/d27d7db0a39e1105181aac119a98d6c92cd5ceba2e8bd349cdf2ba4a8d9ead149b685a1dba9542ca24f094cc70eca4a3e02973fe1f74c11a373b508606e5e1c0 languageName: node linkType: hard @@ -9741,15 +9767,15 @@ __metadata: languageName: node linkType: hard -"intl-messageformat@npm:10.7.3, intl-messageformat@npm:^10.3.5": - version: 10.7.3 - resolution: "intl-messageformat@npm:10.7.3" +"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.2.1" - "@formatjs/fast-memoize": "npm:2.2.2" - "@formatjs/icu-messageformat-parser": "npm:2.9.1" + "@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/7ddd118c04023c9ecdf9a2270753abd876e90a428d5106ce8373622ddefe72ff1daa33993b12065a3339b7f838e9266c3db9048aa7dd20012c8703c6ebe26fd4 + checksum: 10c0/1aa173a8c16ace50520af3de7d3f0ce9bafda90d47b6d674eb88cc47c12c3460d4d53c97ca412fae1141b00abb8ff2ba313250997a040837f01a25379165c949 languageName: node linkType: hard @@ -13053,10 +13079,10 @@ __metadata: languageName: node linkType: hard -"picocolors@npm:^1.0.0, picocolors@npm:^1.0.1, picocolors@npm:^1.1.0": - version: 1.1.0 - resolution: "picocolors@npm:1.1.0" - checksum: 10c0/86946f6032148801ef09c051c6fb13b5cf942eaf147e30ea79edb91dd32d700934edebe782a1078ff859fb2b816792e97ef4dab03d7f0b804f6b01a0df35e023 +"picocolors@npm:^1.0.0, picocolors@npm:^1.0.1, picocolors@npm:^1.1.1": + version: 1.1.1 + resolution: "picocolors@npm:1.1.1" + checksum: 10c0/e2e3e8170ab9d7c7421969adaa7e1b31434f789afb9b3f115f6b96d91945041ac3ceb02e9ec6fe6510ff036bcc0bf91e69a1772edc0b707e12b19c0f2d6bcf58 languageName: node linkType: hard @@ -13270,18 +13296,18 @@ __metadata: languageName: node linkType: hard -"postcss-color-functional-notation@npm:^7.0.4": - version: 7.0.4 - resolution: "postcss-color-functional-notation@npm:7.0.4" +"postcss-color-functional-notation@npm:^7.0.6": + version: 7.0.6 + resolution: "postcss-color-functional-notation@npm:7.0.6" dependencies: - "@csstools/css-color-parser": "npm:^3.0.4" - "@csstools/css-parser-algorithms": "npm:^3.0.3" - "@csstools/css-tokenizer": "npm:^3.0.2" + "@csstools/css-color-parser": "npm:^3.0.6" + "@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/1e39c47f27610ebf6a6308cfea2904fbe1f157b13654325ada23153a944666722c6132b53dfc7660632406a636479dda68eeb97a246c2e593ad6eed1e9bf838d + checksum: 10c0/15f6dfc9a24d6f5186fb054623a92bcf9e804f4eaa35b339551a8048cdb0c7bd2e4655fdbb09a0c9a89f854e9fb1d71e298e8749597660ac034e79bd0d38d7dd languageName: node linkType: hard @@ -13335,46 +13361,46 @@ __metadata: languageName: node linkType: hard -"postcss-custom-media@npm:^11.0.4": - version: 11.0.4 - resolution: "postcss-custom-media@npm:11.0.4" +"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.3" - "@csstools/css-parser-algorithms": "npm:^3.0.3" - "@csstools/css-tokenizer": "npm:^3.0.2" - "@csstools/media-query-list-parser": "npm:^4.0.1" + "@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/31e82e5802f6933a15f5fcf64ff41c8107af9c1d5dcba3c4422a6de3fac77bce9e3dc4ed2b79ae7f6ae460549c5da5a013669af05c1ae21549dbb09b66a9492d + checksum: 10c0/5ba1ca0383818e83d5f6f398a2b0c12cfda066b5d552adfc0e030a2c5f8690c2cc6224f9a1832a9c780dae3fd8d00d78c4a5c88eb36b731da1752f0c3917d488 languageName: node linkType: hard -"postcss-custom-properties@npm:^14.0.3": - version: 14.0.3 - resolution: "postcss-custom-properties@npm:14.0.3" +"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.3" - "@csstools/css-parser-algorithms": "npm:^3.0.3" - "@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/878ffd171ab9bbbba711930cf1b5bd48a12779e3b45d69f41366c2f65d84518f9338a92a277c0e390518c9e12272e06892cdc6575783bcdecfa6d26ebde3d043 + checksum: 10c0/5b101ee71289657cc2e5a16f4912009c10441052e2c54bd9e4f3d4d72b652bab56adb662ddaa96881413e375cf9852e2159b3c778d953442ce86efb781c3b2bf languageName: node linkType: hard -"postcss-custom-selectors@npm:^8.0.3": - version: 8.0.3 - resolution: "postcss-custom-selectors@npm:8.0.3" +"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.3" - "@csstools/css-parser-algorithms": "npm:^3.0.3" - "@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" postcss-selector-parser: "npm:^7.0.0" peerDependencies: postcss: ^8.4 - checksum: 10c0/3acdada43e385c23130f1dde41b189acc7739e5bbd14751ae28b2bd97b0d97f30c2a53da4f9558d108a893cc48717f76b28395a9ff38dcbbe3c3a1721ee4a68a + checksum: 10c0/09d494d2580d0a99f57684f79793d03358286c32460b61a84063c33bdde24865771cb1205efe9a8e26a508be24eba4fb93fc7f1e96ba21ca96a5d17fadb24863 languageName: node linkType: hard @@ -13492,18 +13518,18 @@ __metadata: languageName: node linkType: hard -"postcss-lab-function@npm:^7.0.4": - version: 7.0.4 - resolution: "postcss-lab-function@npm:7.0.4" +"postcss-lab-function@npm:^7.0.6": + version: 7.0.6 + resolution: "postcss-lab-function@npm:7.0.6" dependencies: - "@csstools/css-color-parser": "npm:^3.0.4" - "@csstools/css-parser-algorithms": "npm:^3.0.3" - "@csstools/css-tokenizer": "npm:^3.0.2" + "@csstools/css-color-parser": "npm:^3.0.6" + "@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/79ce3cc20484aef0e0bbc2d18c8f91d7362226a3db52f06a931ac8e1c58ffbc60876c6439f364093e5f16ef92260a420230cfb2a9e7b95c6c11e6f7d57626260 + checksum: 10c0/8b8d498dbc939ee79737b29232b39d09cbda26cc92e8926fb74fe56a1bb05af1198e85a67a822f39cc69109ac6757a6ff7b20842ba5ffafce891abc9bc1c3c68 languageName: node linkType: hard @@ -13824,53 +13850,55 @@ __metadata: linkType: hard "postcss-preset-env@npm:^10.0.0": - version: 10.0.8 - resolution: "postcss-preset-env@npm:10.0.8" + version: 10.1.0 + resolution: "postcss-preset-env@npm:10.1.0" dependencies: "@csstools/postcss-cascade-layers": "npm:^5.0.1" - "@csstools/postcss-color-function": "npm:^4.0.4" - "@csstools/postcss-color-mix-function": "npm:^3.0.4" - "@csstools/postcss-content-alt-text": "npm:^2.0.3" - "@csstools/postcss-exponential-functions": "npm:^2.0.3" + "@csstools/postcss-color-function": "npm:^4.0.6" + "@csstools/postcss-color-mix-function": "npm:^3.0.6" + "@csstools/postcss-content-alt-text": "npm:^2.0.4" + "@csstools/postcss-exponential-functions": "npm:^2.0.5" "@csstools/postcss-font-format-keywords": "npm:^4.0.0" - "@csstools/postcss-gamut-mapping": "npm:^2.0.4" - "@csstools/postcss-gradients-interpolation-method": "npm:^5.0.4" - "@csstools/postcss-hwb-function": "npm:^4.0.4" + "@csstools/postcss-gamut-mapping": "npm:^2.0.6" + "@csstools/postcss-gradients-interpolation-method": "npm:^5.0.6" + "@csstools/postcss-hwb-function": "npm:^4.0.6" "@csstools/postcss-ic-unit": "npm:^4.0.0" "@csstools/postcss-initial": "npm:^2.0.0" "@csstools/postcss-is-pseudo-class": "npm:^5.0.1" - "@csstools/postcss-light-dark-function": "npm:^2.0.6" + "@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.3" - "@csstools/postcss-media-queries-aspect-ratio-number-values": "npm:^3.0.3" + "@csstools/postcss-logical-viewport-units": "npm:^3.0.3" + "@csstools/postcss-media-minmax": "npm:^2.0.5" + "@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.4" + "@csstools/postcss-oklab-function": "npm:^4.0.6" "@csstools/postcss-progressive-custom-properties": "npm:^4.0.0" - "@csstools/postcss-relative-color-syntax": "npm:^3.0.4" + "@csstools/postcss-random-function": "npm:^1.0.0" + "@csstools/postcss-relative-color-syntax": "npm:^3.0.6" "@csstools/postcss-scope-pseudo-class": "npm:^4.0.1" - "@csstools/postcss-stepped-value-functions": "npm:^4.0.3" + "@csstools/postcss-sign-functions": "npm:^1.0.0" + "@csstools/postcss-stepped-value-functions": "npm:^4.0.5" "@csstools/postcss-text-decoration-shorthand": "npm:^4.0.1" - "@csstools/postcss-trigonometric-functions": "npm:^4.0.3" + "@csstools/postcss-trigonometric-functions": "npm:^4.0.5" "@csstools/postcss-unset-value": "npm:^4.0.0" autoprefixer: "npm:^10.4.19" browserslist: "npm:^4.23.1" 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.2" + cssdb: "npm:^8.2.1" postcss-attribute-case-insensitive: "npm:^7.0.1" postcss-clamp: "npm:^4.1.0" - postcss-color-functional-notation: "npm:^7.0.4" + postcss-color-functional-notation: "npm:^7.0.6" postcss-color-hex-alpha: "npm:^10.0.0" postcss-color-rebeccapurple: "npm:^10.0.0" - postcss-custom-media: "npm:^11.0.4" - postcss-custom-properties: "npm:^14.0.3" - postcss-custom-selectors: "npm:^8.0.3" + 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.1" @@ -13878,7 +13906,7 @@ __metadata: postcss-font-variant: "npm:^5.0.0" postcss-gap-properties: "npm:^6.0.0" postcss-image-set-function: "npm:^7.0.0" - postcss-lab-function: "npm:^7.0.4" + postcss-lab-function: "npm:^7.0.6" postcss-logical: "npm:^8.0.0" postcss-nesting: "npm:^13.0.1" postcss-opacity-percentage: "npm:^3.0.0" @@ -13890,7 +13918,7 @@ __metadata: postcss-selector-not: "npm:^8.0.1" peerDependencies: postcss: ^8.4 - checksum: 10c0/3f7dc8eb2e7f4e7a5eee0a9456972a5b18bd40109d1aa3328f60cd645d352f3a70c83c507ea58f83b820153b0f5c3f14af3f376573c56599c36d5739c943b6f1 + checksum: 10c0/bd157dbed38c3c125b3bf86f5437a8094539ec5bf24428487c7bbf29da393731e48053afc695494cc9dbe4d182cfe405c398fcf0b22eb326b6db395e7315f892 languageName: node linkType: hard @@ -14024,13 +14052,13 @@ __metadata: linkType: hard "postcss@npm:^8.2.15, postcss@npm:^8.4.24, postcss@npm:^8.4.47": - version: 8.4.47 - resolution: "postcss@npm:8.4.47" + version: 8.4.49 + resolution: "postcss@npm:8.4.49" dependencies: nanoid: "npm:^3.3.7" - picocolors: "npm:^1.1.0" + picocolors: "npm:^1.1.1" source-map-js: "npm:^1.2.1" - checksum: 10c0/929f68b5081b7202709456532cee2a145c1843d391508c5a09de2517e8c4791638f71dd63b1898dba6712f8839d7a6da046c72a5e44c162e908f5911f57b5f44 + checksum: 10c0/f1b3f17aaf36d136f59ec373459f18129908235e65dbdc3aee5eef8eba0756106f52de5ec4682e29a2eab53eb25170e7e871b3e4b52a8f1de3d344a514306be3 languageName: node linkType: hard @@ -14474,18 +14502,18 @@ __metadata: linkType: hard "react-intl@npm:^6.4.2": - version: 6.8.4 - resolution: "react-intl@npm:6.8.4" + version: 6.8.6 + resolution: "react-intl@npm:6.8.6" dependencies: - "@formatjs/ecma402-abstract": "npm:2.2.1" - "@formatjs/icu-messageformat-parser": "npm:2.9.1" - "@formatjs/intl": "npm:2.10.11" - "@formatjs/intl-displaynames": "npm:6.8.1" - "@formatjs/intl-listformat": "npm:7.7.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:^18.3.11" + "@types/react": "npm:16 || 17 || 18" hoist-non-react-statics: "npm:3" - intl-messageformat: "npm:10.7.3" + intl-messageformat: "npm:10.7.5" tslib: "npm:2" peerDependencies: react: ^16.6.0 || 17 || 18 @@ -14493,7 +14521,7 @@ __metadata: peerDependenciesMeta: typescript: optional: true - checksum: 10c0/a6b417c1cfb36ffe38645fe9daaaf3e1a25660468b8dbd4ccf386be063cc7c0fdeecc3c0490c671721408696b6578262b8db5882d00b76d4ec48d94601b14eab + checksum: 10c0/ec88cc2b1d0edf089f04c8061ffda730840fb3317177d0dc1a6df208245ec278f52b4ca8546ff9511b0b28ff2d89863c5837a274d33731d4c8f75a3b3baafbe2 languageName: node linkType: hard @@ -14654,8 +14682,8 @@ __metadata: linkType: hard "react-select@npm:^5.7.3": - version: 5.8.2 - resolution: "react-select@npm:5.8.2" + version: 5.8.3 + resolution: "react-select@npm:5.8.3" dependencies: "@babel/runtime": "npm:^7.12.0" "@emotion/cache": "npm:^11.4.0" @@ -14669,7 +14697,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/3089b8bfb23f556a7b1de07ea654fc5f5976f531a731a0231bbcbc195afb9294c36f49d712712f2deefc13eb6d7ede4aa1d80cb45b80afd3e26fde2f09db35eb + checksum: 10c0/25aaf0ad964a31dcf991be8b9eb478f94b2ff5dfd2e74a894f692c6dec9247f6ded6258fbf875984d2ada5aeb0ee742b85c6a94f58fae89112e913526cfd0577 languageName: node linkType: hard @@ -14759,15 +14787,15 @@ __metadata: linkType: hard "react-textarea-autosize@npm:^8.4.1": - version: 8.5.4 - resolution: "react-textarea-autosize@npm:8.5.4" + version: 8.5.5 + resolution: "react-textarea-autosize@npm:8.5.5" 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/ea92fda2128983c1a8e84c74706ffb4b8bfa1a19c803d210868ec031c1ac3b8ceee8028766ef5d91017265da2bdccf6a85e5b6e5d553005e839f0c47e5758b43 + checksum: 10c0/d708a31b39a409d0246cd8afbd956ce51db58ce0b6411b9d4e1dc876ce93c329d20875933ce5d337662fdcd3699596966dc630149236fee2835d74e302404c98 languageName: node linkType: hard @@ -17339,7 +17367,7 @@ __metadata: languageName: node linkType: hard -"undici-types@npm:~6.19.2": +"undici-types@npm:~6.19.8": version: 6.19.8 resolution: "undici-types@npm:6.19.8" checksum: 10c0/078afa5990fba110f6824823ace86073b4638f1d5112ee26e790155f481f2a868cc3e0615505b6f4282bdf74a3d8caad715fd809e870c2bb0704e3ea6082f344 @@ -17599,12 +17627,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 @@ -17652,12 +17680,12 @@ __metadata: languageName: node linkType: hard -"uuid@npm:^10.0.0": - version: 10.0.0 - resolution: "uuid@npm:10.0.0" +"uuid@npm:^11.0.0": + version: 11.0.3 + resolution: "uuid@npm:11.0.3" bin: - uuid: dist/bin/uuid - checksum: 10c0/eab18c27fe4ab9fb9709a5d5f40119b45f2ec8314f8d4cf12ce27e4c6f4ffa4a6321dc7db6c515068fa373c075b49691ba969f0010bf37f44c37ca40cd6bf7fe + uuid: dist/esm/bin/uuid + checksum: 10c0/cee762fc76d949a2ff9205770334699e0043d52bb766472593a25f150077c9deed821230251ea3d6ab3943a5ea137d2826678797f1d5f6754c7ce5ce27e9f7a6 languageName: node linkType: hard