diff --git a/.annotaterb.yml b/.annotaterb.yml
new file mode 100644
index 00000000000000..df8e92b24776a0
--- /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 5c7263c87467d9..705d26e0ab28a0 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 03a0f5bf37b81b..6204319a6379fa 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/Dockerfile b/Dockerfile
index a6c7d46b579ad8..c91f10de0f6614 100644
--- a/Dockerfile
+++ b/Dockerfile
@@ -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 47506929b064ed..6abb075c1ce613 100644
--- a/Gemfile
+++ b/Gemfile
@@ -114,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
@@ -172,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'
diff --git a/Gemfile.lock b/Gemfile.lock
index 106fb0d0fde5e4..bb503e157e076f 100644
--- a/Gemfile.lock
+++ b/Gemfile.lock
@@ -90,23 +90,21 @@ GEM
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.1004.0)
- aws-sdk-core (3.212.0)
+ aws-partitions (1.1009.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.170.1)
+ aws-sdk-s3 (1.172.0)
aws-sdk-core (~> 3, >= 3.210.0)
aws-sdk-kms (~> 1)
aws-sigv4 (~> 1.5)
@@ -348,7 +346,7 @@ GEM
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)
@@ -480,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)
@@ -529,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)
@@ -884,7 +882,7 @@ 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)
@@ -968,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)
diff --git a/app/controllers/admin/instances_controller.rb b/app/controllers/admin/instances_controller.rb
index d7f88a71f3698f..a48c4773ed5dd4 100644
--- a/app/controllers/admin/instances_controller.rb
+++ b/app/controllers/admin/instances_controller.rb
@@ -5,6 +5,8 @@ class InstancesController < BaseController
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 @@ def index
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/api/v1/accounts/familiar_followers_controller.rb b/app/controllers/api/v1/accounts/familiar_followers_controller.rb
index a49eb2eb274672..81f0a9ed0f9df9 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 @@ def index
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/featured_tags/suggestions_controller.rb b/app/controllers/api/v1/featured_tags/suggestions_controller.rb
index 9c72e4380d887f..d533b1af7b0846 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 @@ def index
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 b1c0e609d04baf..616159f05f7b7f 100644
--- a/app/controllers/api/v1/lists/accounts_controller.rb
+++ b/app/controllers/api/v1/lists/accounts_controller.rb
@@ -15,17 +15,12 @@ def show
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 @@ def load_accounts
end
end
- def list_accounts
- Account.find(account_ids)
- end
-
def account_ids
Array(resource_params[:account_ids])
end
diff --git a/app/controllers/settings/featured_tags_controller.rb b/app/controllers/settings/featured_tags_controller.rb
index 90c112e21960e7..7e29dd1d2987e2 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 @@ def set_featured_tags
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 569aa07c533ece..5346a448a3912f 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 @@ def set_bulk_import
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/self_destruct_helper.rb b/app/helpers/self_destruct_helper.rb
index 78557c25e522f2..f1927b1e043d40 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 9bbb03fd820230..16b9d3fb531b21 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 @@ def status_description(status)
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/mastodon/actions/notification_groups.ts b/app/javascript/mastodon/actions/notification_groups.ts
index a3c8095ac44fe4..aa7f50da4ec81e 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/features/ui/components/boost_modal.tsx b/app/javascript/mastodon/features/ui/components/boost_modal.tsx
index cdf7138d496d51..72a28a01f998fc 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/locales/ar.json b/app/javascript/mastodon/locales/ar.json
index 5c7dfeb128fb19..7892766d87d0ea 100644
--- a/app/javascript/mastodon/locales/ar.json
+++ b/app/javascript/mastodon/locales/ar.json
@@ -490,6 +490,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/bg.json b/app/javascript/mastodon/locales/bg.json
index 44482f6c960488..456247cedfaed8 100644
--- a/app/javascript/mastodon/locales/bg.json
+++ b/app/javascript/mastodon/locales/bg.json
@@ -87,16 +87,23 @@
"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": "Скриване на звука",
@@ -634,7 +641,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": "Споделяне на профила ви",
diff --git a/app/javascript/mastodon/locales/de.json b/app/javascript/mastodon/locales/de.json
index bd24ccd48fc692..510cc821f3022f 100644
--- a/app/javascript/mastodon/locales/de.json
+++ b/app/javascript/mastodon/locales/de.json
@@ -101,7 +101,7 @@
"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": "Kein",
+ "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.",
@@ -688,7 +688,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/fi.json b/app/javascript/mastodon/locales/fi.json
index 2763c39168def9..2c0aacc53559a7 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",
@@ -101,6 +101,7 @@
"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!",
diff --git a/app/javascript/mastodon/locales/ga.json b/app/javascript/mastodon/locales/ga.json
index 3181d7978e1e6e..137a7c591fde95 100644
--- a/app/javascript/mastodon/locales/ga.json
+++ b/app/javascript/mastodon/locales/ga.json
@@ -101,6 +101,7 @@
"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.",
diff --git a/app/javascript/mastodon/locales/he.json b/app/javascript/mastodon/locales/he.json
index 48ea869dd2f11c..52d61b737b431b 100644
--- a/app/javascript/mastodon/locales/he.json
+++ b/app/javascript/mastodon/locales/he.json
@@ -101,6 +101,7 @@
"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": "לא נגלה לברני.",
diff --git a/app/javascript/mastodon/locales/ia.json b/app/javascript/mastodon/locales/ia.json
index e41d390a3f123d..402829817f860a 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",
@@ -304,6 +325,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 +405,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 +417,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}}",
@@ -503,9 +527,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 +591,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/it.json b/app/javascript/mastodon/locales/it.json
index 06779d337c495a..c4fcbdc3a4b2b8 100644
--- a/app/javascript/mastodon/locales/it.json
+++ b/app/javascript/mastodon/locales/it.json
@@ -88,6 +88,7 @@
"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:",
diff --git a/app/javascript/mastodon/locales/lt.json b/app/javascript/mastodon/locales/lt.json
index 378f642cfe816d..6d4f46f1d445e3 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",
@@ -526,6 +526,7 @@
"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šą",
@@ -537,6 +538,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 f6053b2e0922a4..d6fcb348281740 100644
--- a/app/javascript/mastodon/locales/lv.json
+++ b/app/javascript/mastodon/locales/lv.json
@@ -89,6 +89,10 @@
"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",
@@ -329,7 +333,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",
diff --git a/app/javascript/mastodon/locales/nn.json b/app/javascript/mastodon/locales/nn.json
index b45ff9058582fb..85d19c4f934ce5 100644
--- a/app/javascript/mastodon/locales/nn.json
+++ b/app/javascript/mastodon/locales/nn.json
@@ -101,6 +101,7 @@
"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.",
diff --git a/app/javascript/mastodon/locales/pl.json b/app/javascript/mastodon/locales/pl.json
index c521fabf390515..4558e29cb8ef99 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.",
@@ -508,6 +526,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/sk.json b/app/javascript/mastodon/locales/sk.json
index 8a01263eb222ce..1ecbaaffddb3ce 100644
--- a/app/javascript/mastodon/locales/sk.json
+++ b/app/javascript/mastodon/locales/sk.json
@@ -348,6 +348,8 @@
"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",
@@ -360,6 +362,10 @@
"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.",
diff --git a/app/javascript/mastodon/locales/sl.json b/app/javascript/mastodon/locales/sl.json
index 32626b80f9d19d..3690c612b7d163 100644
--- a/app/javascript/mastodon/locales/sl.json
+++ b/app/javascript/mastodon/locales/sl.json
@@ -86,6 +86,8 @@
"alert.unexpected.message": "Zgodila se je nepričakovana napaka.",
"alert.unexpected.title": "Ojoj!",
"announcement.announcement": "Obvestilo",
+ "annual_report.summary.most_used_hashtag.none": "Brez",
+ "annual_report.summary.new_posts.new_posts": "nove objave",
"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.",
@@ -433,6 +435,7 @@
"lists.subheading": "Vaši seznami",
"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 +447,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",
@@ -478,10 +482,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 +508,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 +747,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/tr.json b/app/javascript/mastodon/locales/tr.json
index ece97614ad7a58..061f9c6c281a00 100644
--- a/app/javascript/mastodon/locales/tr.json
+++ b/app/javascript/mastodon/locales/tr.json
@@ -81,7 +81,7 @@
"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!",
@@ -358,7 +358,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}",
diff --git a/app/javascript/mastodon/locales/zh-CN.json b/app/javascript/mastodon/locales/zh-CN.json
index 887410dd51d4f0..cc0f0b9341a94d 100644
--- a/app/javascript/mastodon/locales/zh-CN.json
+++ b/app/javascript/mastodon/locales/zh-CN.json
@@ -89,7 +89,7 @@
"announcement.announcement": "公告",
"annual_report.summary.archetype.booster": "潮流捕手",
"annual_report.summary.archetype.lurker": "吃瓜群众",
- "annual_report.summary.archetype.oracle": "预言家",
+ "annual_report.summary.archetype.oracle": "无所不在",
"annual_report.summary.archetype.pollster": "投票狂魔",
"annual_report.summary.archetype.replier": "评论区原住民",
"annual_report.summary.followers.followers": "关注者",
@@ -102,13 +102,13 @@
"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.new_posts.new_posts": "新嘟嘟",
"annual_report.summary.percentile.text": "这使你跻身 Mastodon 用户的前",
- "annual_report.summary.percentile.we_wont_tell_bernie": "我们打死也不会告诉Bernie。",
+ "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": "他们不能提及或关注你。",
@@ -132,7 +132,7 @@
"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 账号",
@@ -161,8 +161,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": "嘟文已发布。",
@@ -180,11 +180,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": "内容警告 (可选)",
@@ -197,7 +197,7 @@
"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": "确认覆盖嘟文?",
@@ -229,7 +229,7 @@
"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": "这些新闻故事正被本站和分布式网络上其他站点的用户谈论。",
@@ -264,7 +264,7 @@
"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": "未找到匹配的表情符号",
@@ -288,13 +288,13 @@
"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.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": "此页面无法正确显示,这可能是因为我们的代码中有错误,也可能是因为浏览器兼容问题。",
@@ -333,7 +333,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} 管理团队精选",
@@ -354,7 +354,7 @@
"footer.directory": "用户目录",
"footer.get_app": "获取应用",
"footer.invite": "邀请",
- "footer.keyboard_shortcuts": "快捷键列表",
+ "footer.keyboard_shortcuts": "快捷键",
"footer.privacy_policy": "隐私政策",
"footer.source_code": "查看源代码",
"footer.status": "状态",
@@ -401,18 +401,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} 的嘟文",
@@ -424,8 +424,8 @@
"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": "在列表中让光标下移",
@@ -447,7 +447,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": "显示或隐藏被折叠的正文",
@@ -473,16 +473,16 @@
"lists.exclusive": "在主页中隐藏这些嘟文",
"lists.new.create": "新建列表",
"lists.new.title_placeholder": "新列表的标题",
- "lists.replies_policy.followed": "任何被关注的用户",
+ "lists.replies_policy.followed": "所有我关注的用户",
"lists.replies_policy.list": "列表成员",
- "lists.replies_policy.none": "无人",
+ "lists.replies_policy.none": "不显示",
"lists.replies_policy.title": "显示回复:",
"lists.search": "搜索你关注的人",
"lists.subheading": "你的列表",
"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": "直到我取消隐藏他们",
@@ -507,19 +507,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.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 {# 条嘟文}}",
@@ -528,10 +528,10 @@
"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.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 {另外 # 人}} 向你发送了关注请求",
@@ -569,7 +569,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": "完成",
@@ -597,7 +597,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": "高亮显示未读通知",
@@ -630,7 +630,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} 按钮来精细控制可以发送桌面通知的交互类型。",
@@ -640,9 +640,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": "昵称",
@@ -653,28 +653,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": "刷新",
@@ -687,9 +687,9 @@
"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.short": "公开",
@@ -745,12 +745,12 @@
"report.reasons.violation": "违反服务器规则",
"report.reasons.violation_description": "你清楚它违反了特定的规则",
"report.rules.subtitle": "选择所有适用选项",
- "report.rules.title": "哪些规则被违反了?",
+ "report.rules.title": "违反了哪些规则?",
"report.statuses.subtitle": "选择所有适用选项",
"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": "感谢提交举报,我们将会进行处理。",
@@ -780,7 +780,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": "全部",
@@ -789,7 +789,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 服务器之一。",
@@ -814,7 +814,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 {次喜欢}}",
@@ -834,7 +834,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": "没有人转嘟过此条嘟文。如果有人转嘟了,就会显示在这里。",
@@ -856,7 +856,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": "主页",
@@ -886,7 +886,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": "选择图像",
@@ -908,5 +908,5 @@
"video.mute": "静音",
"video.pause": "暂停",
"video.play": "播放",
- "video.unmute": "解除禁音"
+ "video.unmute": "取消静音"
}
diff --git a/app/lib/annual_report/commonly_interacted_with_accounts.rb b/app/lib/annual_report/commonly_interacted_with_accounts.rb
index 30ab671d8a821c..2316789f2adfd7 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 @@ def generate
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 cfc4022ca79019..69e247f2a6b01b 100644
--- a/app/lib/annual_report/most_reblogged_accounts.rb
+++ b/app/lib/annual_report/most_reblogged_accounts.rb
@@ -17,6 +17,6 @@ def generate
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 fb1ca1d16705c6..a2e1aca452ccee 100644
--- a/app/lib/annual_report/most_used_apps.rb
+++ b/app/lib/annual_report/most_used_apps.rb
@@ -17,6 +17,6 @@ def generate
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/top_hashtags.rb b/app/lib/annual_report/top_hashtags.rb
index 32bd10d6989b48..ae000a8beba5a7 100644
--- a/app/lib/annual_report/top_hashtags.rb
+++ b/app/lib/annual_report/top_hashtags.rb
@@ -17,6 +17,12 @@ def generate
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/feed_manager.rb b/app/lib/feed_manager.rb
index 3c278b37d83eaa..0ebd5a92146cbf 100644
--- a/app/lib/feed_manager.rb
+++ b/app/lib/feed_manager.rb
@@ -187,7 +187,7 @@ def unmerge_from_home(from_account, into_account)
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
@@ -200,7 +200,7 @@ def unmerge_from_list(from_account, list)
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
@@ -221,7 +221,7 @@ def unmerge_tag_from_home(from_tag, into_account)
.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 1922f65f6dc45a..5c8a9f28c8e6a2 100644
--- a/app/lib/importer/statuses_index_importer.rb
+++ b/app/lib/importer/statuses_index_importer.rb
@@ -71,7 +71,7 @@ def local_bookmarks_scope
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/search_query_transformer.rb b/app/lib/search_query_transformer.rb
index 1306ed12edaeed..59352c6e6e34b8 100644
--- a/app/lib/search_query_transformer.rb
+++ b/app/lib/search_query_transformer.rb
@@ -144,6 +144,8 @@ def to_query
end
class PrefixClause
+ EPOCH_RE = /\A\d+\z/
+
attr_reader :operator, :prefix, :term
def initialize(prefix, operator, term, options = {})
@@ -168,15 +170,15 @@ def initialize(prefix, operator, term, options = {})
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 @@ def language_code_from_term(term)
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/models/account_filter.rb b/app/models/account_filter.rb
index e2f359a8c32ef6..f5e9fc7db9496a 100644
--- a/app/models/account_filter.rb
+++ b/app/models/account_filter.rb
@@ -61,7 +61,7 @@ def scope_for(key, value)
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/concerns/account/associations.rb b/app/models/concerns/account/associations.rb
index 637e785953d06e..cafb2d151c1064 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
-
- # 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
-
- # 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
-
- # 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
-
- # Endorsements
- has_many :account_pins, 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
+
+ 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
+
+ # 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
+
+ # Status records pinned by the account
+ has_many :pinned_statuses, -> { reorder(status_pins: { created_at: :desc }) }, through: :status_pins, class_name: 'Status', source: :status
+
+ # 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 536afba17faf3b..6f6b8c16d016a5 100644
--- a/app/models/concerns/account/interactions.rb
+++ b/app/models/concerns/account/interactions.rb
@@ -80,8 +80,8 @@ def follow_mapping(query, field)
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 @@ def follow_mapping(query, field)
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/notification/groups.rb b/app/models/concerns/notification/groups.rb
new file mode 100644
index 00000000000000..2f29bd9ceaedcb
--- /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/follow_request.rb b/app/models/follow_request.rb
index c13cc718d8f0ce..964d4e279a1797 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 1d94c919f9680b..7e71640e52ce56 100644
--- a/app/models/instance_filter.rb
+++ b/app/models/instance_filter.rb
@@ -28,9 +28,9 @@ def results
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/notification.rb b/app/models/notification.rb
index 7b90fd92f96ce3..e7ada3399aa495 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: {
@@ -130,30 +127,6 @@ def target_status
end
end
- def set_group_key!
- return if filtered? || Notification::GROUPABLE_NOTIFICATION_TYPES.exclude?(type)
-
- type_prefix = case type
- when :favourite, :reblog
- [type, target_status&.id].join('-')
- when :follow
- type
- else
- raise NotImplementedError
- end
- redis_key = "notif-group/#{account.id}/#{type_prefix}"
- hour_bucket = activity.created_at.utc.to_i / 1.hour.to_i
-
- # Reuse previous group if it does not span too large an amount of time
- previous_bucket = redis.get(redis_key).to_i
- hour_bucket = previous_bucket if hour_bucket < previous_bucket + MAXIMUM_GROUP_SPAN_HOURS
-
- # We do not concern ourselves with race conditions since we use hour buckets
- redis.set(redis_key, hour_bucket, ex: MAXIMUM_GROUP_SPAN_HOURS.hours.to_i)
-
- self.group_key = "#{type_prefix}-#{hour_bucket}"
- end
-
class << self
def browserable(types: [], exclude_types: [], from_account_id: nil, include_filtered: false)
requested_types = if types.empty?
@@ -171,94 +144,6 @@ def browserable(types: [], exclude_types: [], from_account_id: nil, include_filt
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]
diff --git a/app/models/poll.rb b/app/models/poll.rb
index cc4184f80a4c0f..ebd46440946bd9 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/status.rb b/app/models/status.rb
index 573e27d1a706d9..2825ade5247786 100644
--- a/app/models/status.rb
+++ b/app/models/status.rb
@@ -399,23 +399,23 @@ def as_direct_timeline(account, limit = 20, max_id = nil, since_id = nil)
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 93210eb307e936..67fa9e5d3a0e0e 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 @@ def search_for(term, limit = 5, offset = 0, options = {})
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/trends/statuses.rb b/app/models/trends/statuses.rb
index 0c1135ceb50d4f..cf982dd0cd9710 100644
--- a/app/models/trends/statuses.rb
+++ b/app/models/trends/statuses.rb
@@ -106,7 +106,7 @@ def klass
private
def eligible?(status)
- status.public_visibility? && status.account.discoverable? && !status.account.silenced? && !status.account.sensitized? && (status.spoiler_text.blank? || Setting.trending_status_cw) && !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? || Setting.trending_status_cw) && !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 2024cabf365109..8b2a053ba81c55 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).merge(IpBlock.contained_by(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
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 00000000000000..df4e4c83140738
--- /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/follow_service.rb b/app/services/follow_service.rb
index af5f996077e4a1..cff38b8e6e9d01 100644
--- a/app/services/follow_service.rb
+++ b/app/services/follow_service.rb
@@ -81,7 +81,10 @@ def direct_follow!
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/remove_accounts_from_list_service.rb b/app/services/remove_accounts_from_list_service.rb
new file mode 100644
index 00000000000000..bd5b7c439e9fb8
--- /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/unfollow_service.rb b/app/services/unfollow_service.rb
index fe9a7f0d87ccd3..b3f2cd66f67c7e 100644
--- a/app/services/unfollow_service.rb
+++ b/app/services/unfollow_service.rb
@@ -31,7 +31,13 @@ def unfollow!
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 6aeea358f758b0..9262961f7d74ab 100644
--- a/app/services/unmute_service.rb
+++ b/app/services/unmute_service.rb
@@ -6,6 +6,12 @@ def call(account, target_account)
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/views/admin/reports/_status.html.haml b/app/views/admin/reports/_status.html.haml
index 3a35fdd2725efb..d20266aa2ca425 100644
--- a/app/views/admin/reports/_status.html.haml
+++ b/app/views/admin/reports/_status.html.haml
@@ -10,7 +10,7 @@
- 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: admin_account_status_path(status.thread.account_id, status.in_reply_to_id)))
+ = 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)
@@ -44,7 +44,7 @@
= t("statuses.visibilities.#{status.visibility}")
·
- = link_to ActivityPub::TagManager.instance.url_for(status.proper), class: 'detailed-status__link', target: stream_link_target, rel: 'noopener noreferrer' do
+ = 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?
diff --git a/app/views/admin/statuses/show.html.haml b/app/views/admin/statuses/show.html.haml
index 49c23e921c2b71..1ff47631588f2e 100644
--- a/app/views/admin/statuses/show.html.haml
+++ b/app/views/admin/statuses/show.html.haml
@@ -22,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
@@ -61,7 +61,7 @@
- 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: admin_account_status_path(@status.thread.account_id, @status.in_reply_to_id)))
+ = 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)
diff --git a/app/views/filters/statuses/_status_filter.html.haml b/app/views/filters/statuses/_status_filter.html.haml
index d0d04638d2aad8..3476869e6028fc 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/relationships/show.html.haml b/app/views/relationships/show.html.haml
index 1ce685d1c0ebc5..c1dccf51250194 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/workers/merge_worker.rb b/app/workers/merge_worker.rb
index 8e1614ad21b36f..d4dcb326bc2a22 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 c74f657cbacad8..ebd401dc20cc25 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/unmerge_worker.rb b/app/workers/unmerge_worker.rb
index e8ac535dfe6be3..e8a3bf9b78024f 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/config/database.yml b/config/database.yml
index 2898415d800877..eba20e849fe854 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/initializers/opentelemetry.rb b/config/initializers/opentelemetry.rb
index 8edce03b909914..a40cd4e4c544c5 100644
--- a/config/initializers/opentelemetry.rb
+++ b/config/initializers/opentelemetry.rb
@@ -65,6 +65,13 @@
"#{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 a4edf294a37627..f620158361d5a2 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 43f8d358cc2af2..f941651438dc59 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 - @%{name}
trending: En tendencia
visibility: Visibilidat
with_media: Con multimedia
diff --git a/config/locales/ar.yml b/config/locales/ar.yml
index bbc481a1377cce..832f60795f7be9 100644
--- a/config/locales/ar.yml
+++ b/config/locales/ar.yml
@@ -847,7 +847,6 @@ ar:
original_status: المنشور الأصلي
reblogs: المعاد تدوينها
status_changed: عُدّل المنشور
- title: منشورات الحساب - @%{name}
trending: المتداولة
visibility: مدى الظهور
with_media: تحتوي على وسائط
diff --git a/config/locales/be.yml b/config/locales/be.yml
index c59233eb8b8ad3..c97547b8b9664d 100644
--- a/config/locales/be.yml
+++ b/config/locales/be.yml
@@ -856,7 +856,6 @@ be:
original_status: Зыходны допіс
reblogs: Рэпосты
status_changed: Допіс зменены
- title: Допісы уліковага запісу - @%{name}
trending: Папулярныя
visibility: Бачнасць
with_media: З медыя
diff --git a/config/locales/bg.yml b/config/locales/bg.yml
index 2c5edf0b13af7c..20ee1f6c681848 100644
--- a/config/locales/bg.yml
+++ b/config/locales/bg.yml
@@ -807,7 +807,7 @@ bg:
original_status: Първообразна публикация
reblogs: Блогване пак
status_changed: Публикацията променена
- title: Публикации на акаунта - @%{name}
+ title: Публикации на акаунт - @%{name}
trending: Изгряващи
visibility: Видимост
with_media: С мултимедия
@@ -1105,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}. Ако вашият акаунт е хостван на различен сървър, няма да можете да влезете в този.
@@ -1117,6 +1119,7 @@ bg:
title: Първоначални настройки за %{domain}.
status:
account_status: Състояние на акаунта
+ confirming: Чака се потвърждението на имейла да завърши.
functional: Вашият акаунт е в изправност.
pending: Вашето приложение чака преглед от персонала ни. Това може да отнеме време. Ще получите е-писмо, ако приложението ви се одобри.
redirecting_to: Вашият акаунт е бездеен, защото сега се пренасочва към %{acct}.
@@ -1126,6 +1129,8 @@ bg:
use_security_key: Употреба на ключ за сигурност
author_attribution:
example_title: Примерен текст
+ hint_html: Пишете ли новинарски статии или блогове извън Mastodon? Управлявайте как ви приписват авторството, когато са споделени в Mastodon.
+ instructions: 'Уверете се, че този код е в HTML на статията ви:'
more_from_html: Още от %{name}
s_blog: Блогът на %{name}
then_instructions: Тогава добавете име на домейна на публикацията в долното поле.
@@ -1166,6 +1171,9 @@ bg:
before: 'Прочетете внимателно тези бележки преди да продължите:'
caches: Съдържание, което може да е кеширано от други сървъри, може да се задържи
data_removal: Ваши публикации и други данни ще бъдат завинаги премахнати
+ email_change_html: Може да промените адреса на имейла си, без да изтривате акаунта си
+ email_contact_html: Ако още не сте го получили, то обърнете се за помощ към %{email}
+ email_reconfirmation_html: Ако не сте получили е-писмо за потвърждение, може да го заявите отново
irreversible: Няма да може да възстановите или да задействате пак акаунта си
more_details_html: За повече детайли прегледайте декларацията за поверителност.
username_available: Вашето потребителско име ще стане налично отново
@@ -1393,6 +1401,7 @@ bg:
unsubscribe:
action: Да, да се спре абонамента
complete: Спрян абонамент
+ confirmation_html: Наистина ли искате да спрете абонамента от получаването на %{type} за Mastodon в %{domain} към имейла си при %{email}? Може винаги пак да се абонирате от своите настройки за известяване по е-поща.
title: Спиране на абонамента
media_attachments:
validations:
diff --git a/config/locales/br.yml b/config/locales/br.yml
index 098b20934fc23e..fbe91fcbd7e237 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 - @%{name}
+ 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 970fd99fff0111..b1af2d95d48a20 100644
--- a/config/locales/ca.yml
+++ b/config/locales/ca.yml
@@ -841,7 +841,6 @@ ca:
original_status: Publicació original
reblogs: Impulsos
status_changed: Publicació canviada
- title: Estats del compte - @%{name}
trending: Tendència
visibility: Visibilitat
with_media: Amb contingut multimèdia
diff --git a/config/locales/ckb.yml b/config/locales/ckb.yml
index 6e1b11379cb123..cfee624e368471 100644
--- a/config/locales/ckb.yml
+++ b/config/locales/ckb.yml
@@ -520,7 +520,6 @@ ckb:
media:
title: میدیا
no_status_selected: هیچ دۆخیک نەگۆڕاوە وەک ئەوەی هیچ بارێک دەستنیشان نەکراوە
- title: دۆخی ئەژمێر - @%{name}
with_media: بە میدیا
tags:
review: پێداچوونەوەی دۆخ
diff --git a/config/locales/co.yml b/config/locales/co.yml
index b81427e83399a2..39d9e9157e6951 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 - @%{name}
with_media: Cù media
system_checks:
rules_check:
diff --git a/config/locales/cs.yml b/config/locales/cs.yml
index f5f7f4d7310977..19a63722247d29 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 - @%{name}
trending: Populární
visibility: Viditelnost
with_media: S médii
diff --git a/config/locales/cy.yml b/config/locales/cy.yml
index f479f0f0a00629..0daa793f9744d1 100644
--- a/config/locales/cy.yml
+++ b/config/locales/cy.yml
@@ -897,7 +897,6 @@ cy:
original_status: Postiad gwreiddiol
reblogs: Ailflogiadau
status_changed: Postiad wedi'i newid
- title: Postiadau cyfrif - @%{name}
trending: Yn trendio
visibility: Gwelededd
with_media: Gyda chyfryngau
diff --git a/config/locales/da.yml b/config/locales/da.yml
index e157af9cc2d66e..3a82278b933de9 100644
--- a/config/locales/da.yml
+++ b/config/locales/da.yml
@@ -826,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
@@ -836,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
+ 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 e3ee03264e77ff..26ccc8f3ee411c 100644
--- a/config/locales/de.yml
+++ b/config/locales/de.yml
@@ -427,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
@@ -502,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:
@@ -826,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
@@ -836,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 - @%{name}
+ 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.zh-CN.yml b/config/locales/devise.zh-CN.yml
index 86e78c1b18ddf1..1b5f364d081a37 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 6bf5e3850670e4..efde9be9c05669 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.zh-CN.yml b/config/locales/doorkeeper.zh-CN.yml
index 08f9885894d0d3..848b0d6b6c063a 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 26b0ec00a261b8..98ef5f18b70710 100644
--- a/config/locales/el.yml
+++ b/config/locales/el.yml
@@ -817,7 +817,6 @@ el:
original_status: Αρχική ανάρτηση
reblogs: Αναδημοσιεύσεις
status_changed: Η ανάρτηση άλλαξε
- title: Καταστάσεις λογαριασμού - @%{name}
trending: Τάσεις
visibility: Ορατότητα
with_media: Με πολυμέσα
diff --git a/config/locales/en-GB.yml b/config/locales/en-GB.yml
index e22ed62051c3eb..76a16aa9dbf61f 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 - @%{name}
trending: Trending
visibility: Visibility
with_media: With media
diff --git a/config/locales/eo.yml b/config/locales/eo.yml
index 194b2c17b81279..120df142b7e4e3 100644
--- a/config/locales/eo.yml
+++ b/config/locales/eo.yml
@@ -830,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 - @%{name}
trending: Popularaĵoj
visibility: Videbleco
with_media: Kun aŭdovidaĵoj
diff --git a/config/locales/es-AR.yml b/config/locales/es-AR.yml
index 6dc9d99f377c97..09163c2e4a0c97 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 - @%{name}
+ 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 7e6570f068d4a7..53557c091a210e 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 - @%{name}
+ 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 32abd9420db4d6..22123e4309a322 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
@@ -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
@@ -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"
@@ -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
+ 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 f8a4f7f69ec7bc..40db2eede0b3a6 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 - @%{name}
trending: Populaarne
visibility: Nähtavus
with_media: Meediaga
diff --git a/config/locales/eu.yml b/config/locales/eu.yml
index a764e88baccc54..dc064ebc7ba82c 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 - @%{name}
trending: Joera
visibility: Ikusgaitasuna
with_media: Multimediarekin
diff --git a/config/locales/fa.yml b/config/locales/fa.yml
index 38daf70d298e05..7cb0714c28e86f 100644
--- a/config/locales/fa.yml
+++ b/config/locales/fa.yml
@@ -741,7 +741,6 @@ fa:
original_status: فرستهٔ اصلی
reblogs: تقویتها
status_changed: فرسته تغییر کرد
- title: "@%{name} - نوشتههای حساب"
trending: پرطرفدار
visibility: نمایانی
with_media: دارای عکس یا ویدیو
diff --git a/config/locales/fi.yml b/config/locales/fi.yml
index efdfdfed04bf7b..d7755d23b81ae6 100644
--- a/config/locales/fi.yml
+++ b/config/locales/fi.yml
@@ -826,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
@@ -836,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 - @%{name}
+ 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 8dab61c267ad4e..502c027b5db268 100644
--- a/config/locales/fo.yml
+++ b/config/locales/fo.yml
@@ -826,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
@@ -836,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 - @%{name}
+ 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:
diff --git a/config/locales/fr-CA.yml b/config/locales/fr-CA.yml
index bb0501d0e38d0c..9c2bf3398ef84f 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 - @%{name}
trending: Tendances
visibility: Visibilité
with_media: Avec médias
diff --git a/config/locales/fr.yml b/config/locales/fr.yml
index 0c35dea62ab605..650147eb5d33fa 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 - @%{name}
trending: Tendances
visibility: Visibilité
with_media: Avec médias
diff --git a/config/locales/fy.yml b/config/locales/fy.yml
index 8a4f519e0cb976..24be51d9d737b7 100644
--- a/config/locales/fy.yml
+++ b/config/locales/fy.yml
@@ -833,7 +833,6 @@ fy:
original_status: Oarspronklik berjocht
reblogs: Boosts
status_changed: Berjocht wizige
- title: Accountberjochten - @%{name}
trending: Trending
visibility: Sichtberheid
with_media: Mei media
diff --git a/config/locales/ga.yml b/config/locales/ga.yml
index 67461f3c2a268d..deb99866918b65 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 - @%{name}
+ 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 89198bd5143585..78f4516cfc7594 100644
--- a/config/locales/gd.yml
+++ b/config/locales/gd.yml
@@ -861,7 +861,6 @@ gd:
original_status: Am post tùsail
reblogs: Brosnachaidhean
status_changed: Post air atharrachadh
- title: Postaichean a’ chunntais - @%{name}
trending: A’ treandadh
visibility: Faicsinneachd
with_media: Le meadhanan riutha
diff --git a/config/locales/gl.yml b/config/locales/gl.yml
index 0f3420a7f3513d..feda673621e80d 100644
--- a/config/locales/gl.yml
+++ b/config/locales/gl.yml
@@ -826,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
@@ -836,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
+ 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 59dc09799d05e1..5243cf4768b84f 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: הודעות החשבון - @%{name}
+ 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 56d41daf864bef..f23711d4032064 100644
--- a/config/locales/hu.yml
+++ b/config/locales/hu.yml
@@ -841,7 +841,6 @@ hu:
original_status: Eredeti bejegyzés
reblogs: Megosztások
status_changed: A bejegyzés megváltozott
- title: Fiók bejegyzései - @%{name}
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 d8cf2a97ba9472..3b4aaf3629fa9e 100644
--- a/config/locales/hy.yml
+++ b/config/locales/hy.yml
@@ -402,7 +402,6 @@ hy:
deleted: Ջնջված է
media:
title: Մեդիա
- title: Օգտատիրոջ գրառումները - @%{name}
with_media: Մեդիայի հետ
tags:
review: Վերանայել գրառումը
diff --git a/config/locales/ia.yml b/config/locales/ia.yml
index 1398ae51d4526e..54401b1c5adf59 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 - @%{name}
+ 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 9c31daf420705e..34b690828d6625 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 - @%{name}
trending: Sedang tren
visibility: Visibilitas
with_media: Dengan media
diff --git a/config/locales/ie.yml b/config/locales/ie.yml
index d7df83ef6956f0..f006f2c8adc9a4 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 - @%{name}
trending: Populari
visibility: Visibilitá
with_media: Con medie
diff --git a/config/locales/io.yml b/config/locales/io.yml
index 1ff5d98bf2daf3..83c92484ff4fc5 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 - @%{name}
trending: Populara
visibility: Videbleso
with_media: Kun medii
diff --git a/config/locales/is.yml b/config/locales/is.yml
index 9ba29f2af0ab88..cad01257fd3845 100644
--- a/config/locales/is.yml
+++ b/config/locales/is.yml
@@ -828,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
@@ -838,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 - @%{name}
+ 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 08e224ad94adc7..3b36bd3f7a1ca2 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 - @%{name}
+ 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 76152c374401fa..810de2b22785a4 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: 投稿を変更しました
+ 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 93f7a39dc38ffd..f3178be8d386a8 100644
--- a/config/locales/ka.yml
+++ b/config/locales/ka.yml
@@ -190,7 +190,6 @@ ka:
media:
title: მედია
no_status_selected: სატუსები არ შეცვლილა, რადგან არცერთი არ მონიშნულა
- title: ანგარიშის სტატუსები - @%{name}
with_media: მედიით
title: ადმინისტრაცია
admin_mailer:
diff --git a/config/locales/kab.yml b/config/locales/kab.yml
index c74540cfbfacd1..1f5c5ded79cdfe 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 - @%{name}
trending: Ayen mucaɛen
visibility: Abani
with_media: S umidya
diff --git a/config/locales/kk.yml b/config/locales/kk.yml
index 4b9cef245e1dc2..7ab33b31344016 100644
--- a/config/locales/kk.yml
+++ b/config/locales/kk.yml
@@ -285,7 +285,6 @@ kk:
media:
title: Медиa
no_status_selected: Бірде-бір статус өзгерген жоқ, себебі ештеңе таңдалмады
- title: Аккаунт статустары - @%{name}
with_media: Медиамен
tags:
review: Статусты көрсету
diff --git a/config/locales/ko.yml b/config/locales/ko.yml
index 36a13397d0fa98..3394433758ece2 100644
--- a/config/locales/ko.yml
+++ b/config/locales/ko.yml
@@ -814,8 +814,10 @@ ko:
back_to_account: 계정으로 돌아가기
back_to_report: 신고 페이지로 돌아가기
batch:
+ add_to_report: '신고 #%{id}에 추가'
remove_from_report: 신고에서 제거
report: 신고
+ contents: 내용
deleted: 삭제됨
favourites: 좋아요
history: 버전 이력
@@ -824,13 +826,17 @@ ko:
media:
title: 미디어
metadata: 메타데이터
+ no_history: 이 게시물은 수정되지 않았습니다
no_status_selected: 아무 것도 선택 되지 않아 어떤 게시물도 바뀌지 않았습니다
open: 게시물 열기
original_status: 원본 게시물
reblogs: 리블로그
+ replied_to_html: "%{acct_link} 님에게 답장"
status_changed: 게시물 변경됨
+ 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 54188d25146365..5337610992c5a1 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 - @%{name}
trending: Rojev
visibility: Xuyabarî
with_media: Bi medya yê re
diff --git a/config/locales/lad.yml b/config/locales/lad.yml
index 3b33888c71e006..2612ae21317962 100644
--- a/config/locales/lad.yml
+++ b/config/locales/lad.yml
@@ -825,7 +825,6 @@ lad:
original_status: Publikasyon orijinala
reblogs: Repartajasyones
status_changed: Publikasyon trokada
- title: Publikasyones del kuento - @%{name}
trending: Trendes
visibility: Vizivilita
with_media: Kon multimedia
diff --git a/config/locales/lt.yml b/config/locales/lt.yml
index 3519cb5b32616c..65bd4456aeb24a 100644
--- a/config/locales/lt.yml
+++ b/config/locales/lt.yml
@@ -589,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
@@ -598,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 - @%{name}
+ 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 33b357b837f2f9..3e44adbf46f278 100644
--- a/config/locales/lv.yml
+++ b/config/locales/lv.yml
@@ -830,7 +830,7 @@ lv:
original_status: Oriģinālā ziņa
reblogs: Reblogi
status_changed: Ziņa mainīta
- title: Konta ziņas - @%{name}
+ status_title: Publicēja @%{name}
trending: Aktuāli
visibility: Redzamība
with_media: Ar multividi
@@ -971,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
diff --git a/config/locales/ms.yml b/config/locales/ms.yml
index 76f914dd168f18..948ad56a54c3ff 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 - @%{name}
trending: Sohor kini
visibility: Visibiliti
with_media: Dengan media
diff --git a/config/locales/my.yml b/config/locales/my.yml
index b238abb051278c..44288438556c55 100644
--- a/config/locales/my.yml
+++ b/config/locales/my.yml
@@ -764,7 +764,6 @@ my:
original_status: မူရင်းပို့စ်
reblogs: Reblog များ
status_changed: ပို့စ်ပြောင်းပြီးပါပြီ
- title: "@%{name} - အကောင့်ပို့စ်များ"
trending: လက်ရှိခေတ်စားနေခြင်း
visibility: မြင်နိုင်မှု
with_media: မီဒီယာနှင့်အတူ
diff --git a/config/locales/nl.yml b/config/locales/nl.yml
index d4a88b3bea7bdb..048214eca3e210 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 - @%{name}
+ 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 e04c0168f20037..dbb8b6c693ef89 100644
--- a/config/locales/nn.yml
+++ b/config/locales/nn.yml
@@ -826,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
@@ -836,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 - @%{name}
+ status_title: Innlegg av @%{name}
+ title: Kontoinnlegg - @%{name}
trending: Populært
+ view_publicly: Vis offentleg
visibility: Synlighet
with_media: Med media
strikes:
diff --git a/config/locales/no.yml b/config/locales/no.yml
index 408fdd5ae1c7d9..8bf5daad0e57f8 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 - @%{name}
trending: Populært
visibility: Synlighet
with_media: Med media
diff --git a/config/locales/oc.yml b/config/locales/oc.yml
index 5130977cb32e6f..5dec5ebb77366d 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 - @%{name}
visibility: Visibilitat
with_media: Amb mèdia
system_checks:
diff --git a/config/locales/pl.yml b/config/locales/pl.yml
index c5d63e1d73e6d0..3592ea53f68086 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
+ 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 c5a0f3764a9722..537dee5f74041c 100644
--- a/config/locales/pt-BR.yml
+++ b/config/locales/pt-BR.yml
@@ -826,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
@@ -836,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
+ 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:
@@ -1377,9 +1383,16 @@ pt-BR:
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 ff80948848af25..cceceb0534f8dc 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 - @%{name}
trending: Em tendência
visibility: Visibilidade
with_media: Com media
diff --git a/config/locales/ru.yml b/config/locales/ru.yml
index 09d89cef9d7d8b..d9bf96c625489d 100644
--- a/config/locales/ru.yml
+++ b/config/locales/ru.yml
@@ -869,7 +869,6 @@ ru:
original_status: Оригинальный пост
reblogs: Продвинули
status_changed: Пост изменен
- title: Посты пользователя - @%{name}
trending: Популярное
visibility: Видимость
with_media: С файлами
diff --git a/config/locales/sc.yml b/config/locales/sc.yml
index 09f8ba0e0e7838..38ede0a72c19c3 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 - @%{name}
trending: Populares
visibility: Visibilidade
with_media: Cun elementos multimediales
diff --git a/config/locales/sco.yml b/config/locales/sco.yml
index 55e0603d458bd1..ff3a730b17f686 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 - @%{name}
trending: Trendin
visibility: Visibility
with_media: Wi media
diff --git a/config/locales/si.yml b/config/locales/si.yml
index b0eb1d3b0cabf2..cd4abf6451dd59 100644
--- a/config/locales/si.yml
+++ b/config/locales/si.yml
@@ -607,7 +607,6 @@ si:
open: ලිපිය අරින්න
original_status: මුල් ලිපිය
status_changed: ලිපිය සංශෝධිතයි
- title: ගිණුමේ ලිපි - @%{name}
trending: නැගී එන
with_media: මාධ්ය සමඟ
strikes:
diff --git a/config/locales/simple_form.es-AR.yml b/config/locales/simple_form.es-AR.yml
index dada648d5a188b..c3a65c0cc2701b 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: 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.
+ 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.ga.yml b/config/locales/simple_form.ga.yml
index 62d59235bf2aa5..f8257a9da9dd10 100644
--- a/config/locales/simple_form.ga.yml
+++ b/config/locales/simple_form.ga.yml
@@ -10,6 +10,7 @@ ga:
indexable: Seans go mbeidh do phostálacha poiblí le feiceáil sna torthaí cuardaigh ar Mastodon. Seans go mbeidh daoine a d’idirghníomhaigh le do phostálacha in ann iad a chuardach beag beann ar.
note: 'Is féidir leat @trá a dhéanamh ar dhaoine eile nó #hashtags.'
show_collections: Beidh daoine in ann brabhsáil trí do seo a leanas agus do leanúna. Feicfidh na daoine a leanann tú go leanann tú iad beag beann ar.
+ unlocked: Beidh daoine in ann tú a leanúint gan cead a iarraidh. Díthiceáil an dteastaíonn uait athbhreithniú a dhéanamh ar iarratais leantacha agus roghnaigh cé acu an nglacfaidh nó an diúltóidh tú do leantóirí nua.
account_alias:
acct: Sonraigh ainm@fearann don chuntas ar mhaith leat aistriú uaidh
account_migration:
diff --git a/config/locales/simple_form.ia.yml b/config/locales/simple_form.ia.yml
index 5ac75aafb1a14c..1a405980c027a2 100644
--- a/config/locales/simple_form.ia.yml
+++ b/config/locales/simple_form.ia.yml
@@ -3,12 +3,14 @@ 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.
indexable: Tu messages public pote apparer in le resultatos de recerca sur Mastodon. Le personas qui ha interagite con tu messages pote cercar los in omne caso.
note: 'Tu pote @mentionar altere personas o #hashtags.'
show_collections: Le gente potera percurrer le listas de personas que tu seque e qui te seque. Le personas que tu seque videra que tu les seque in omne caso.
+ unlocked: Le personas potera sequer te sin requestar approbation. Dismarca si tu vole revider le requestas de sequimento e seliger si acceptar o rejectar nove sequitores.
account_alias:
acct: Specifica le nomine_de_usator@dominio del conto desde le qual tu vole migrar
account_migration:
@@ -129,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
@@ -141,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
@@ -209,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.pt-BR.yml b/config/locales/simple_form.pt-BR.yml
index 0c6be63aaae1e1..fca59515f0f22d 100644
--- a/config/locales/simple_form.pt-BR.yml
+++ b/config/locales/simple_form.pt-BR.yml
@@ -10,6 +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 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.zh-CN.yml b/config/locales/simple_form.zh-CN.yml
index 5f98d73be67115..0b7edae913ca86 100644
--- a/config/locales/simple_form.zh-CN.yml
+++ b/config/locales/simple_form.zh-CN.yml
@@ -4,12 +4,12 @@ zh-CN:
hints:
account:
attribution_domains_as_text: 每行一个域名。这样就可以保护作品免受虚假署名。
- discoverable: 您的公开嘟文和个人资料可能会在 Mastodon 的多个位置展示,您的个人资料可能会被推荐给其他用户。
+ discoverable: 你的公开嘟文和个人资料可能会在 Mastodon 的多个位置展示,你的个人资料可能会被推荐给其他用户。
display_name: 你的全名或昵称。
fields: 你的主页、人称代词、年龄,以及任何你想要添加的内容。
- indexable: 您的公开嘟文会出现在 Mastodon 的搜索结果中。无论是否勾选,与您的嘟文有过交互的人都可能通过搜索找到它们。
- note: '你可以提及 @其他人 或 #标签 。'
- show_collections: 人们将能够浏览您的关注和追随者。您关注的人会看到您关注他们。
+ indexable: 你的公开嘟文会出现在 Mastodon 的搜索结果中。无论是否勾选,与你的嘟文有过交互的人都可能通过搜索找到它们。
+ note: '你可以提及 @其他人 或 #话题标签 。'
+ show_collections: 人们将能够浏览你的关注和追随者。你关注的人会看到你关注他们。
unlocked: 人们将能够在不请求批准的情况下关注你。如果你希望审核关注请求并选择接受或拒绝新的关注者,请取消勾选此项。
account_alias:
acct: 指定你想要迁移过来的原账号:用户名@站点域名
@@ -62,7 +62,7 @@ zh-CN:
setting_display_media_show_all: 始终显示媒体
setting_use_blurhash: 渐变是基于模糊后的隐藏内容生成的
setting_use_pending_items: 关闭自动滚动更新,时间轴会在点击后更新
- username: 您只能使用字母、数字和下划线
+ username: 你只能使用字母、数字和下划线
whole_word: 如果关键词只包含字母和数字,将只在词语完全匹配时才会应用
domain_allow:
domain: 该站点将能够从该服务器上拉取数据,并处理和存储收到的数据。
@@ -87,7 +87,7 @@ zh-CN:
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: 他人需要询恰法务或支持信息时的联络方式
@@ -125,7 +125,7 @@ zh-CN:
otp: 输入你手机应用上生成的双因素认证代码,或者任意一个恢复代码:
webauthn: 如果是 USB 密钥,请确保将其插入,如有必要,请点击它。
settings:
- indexable: 您的个人资料页面可能会出现在Google、Bing等搜索结果中。
+ indexable: 你的个人资料页面可能会出现在Google、Bing等搜索结果中。
show_application: 无论如何,你始终可以看到是哪个应用发布了你的嘟文。
tag:
name: 你只能改变字母的大小写,让它更易读
@@ -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: 联系邮箱
@@ -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: 仅在有关键更新时通知
@@ -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/sk.yml b/config/locales/sk.yml
index d576bf0382d625..c946b8abf1a7e9 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 - @%{name}
trending: Populárne
visibility: Viditeľnosť
with_media: S médiami
diff --git a/config/locales/sl.yml b/config/locales/sl.yml
index 6ae239d69f67be..909b89e5a9e77e 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 - @%{name}
trending: V trendu
visibility: Vidnost
with_media: Z mediji
diff --git a/config/locales/sq.yml b/config/locales/sq.yml
index b1e2a4f61e9f50..e9247ef365960a 100644
--- a/config/locales/sq.yml
+++ b/config/locales/sq.yml
@@ -823,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
@@ -833,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 - @%{name}
+ 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 76a0f8afe976af..0b3043c47b950d 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 - @%{name}
trending: U trendu
visibility: Vidljivost
with_media: Sa multimedijom
diff --git a/config/locales/sr.yml b/config/locales/sr.yml
index 6a75316c23e87b..e077a40eeef511 100644
--- a/config/locales/sr.yml
+++ b/config/locales/sr.yml
@@ -837,7 +837,6 @@ sr:
original_status: Оригинална објава
reblogs: Дељења
status_changed: Објава промењена
- title: Статуси налога - @%{name}
trending: У тренду
visibility: Видљивост
with_media: Са мултимедијом
diff --git a/config/locales/sv.yml b/config/locales/sv.yml
index 11b37f8bfc7c89..173dd24c88cd01 100644
--- a/config/locales/sv.yml
+++ b/config/locales/sv.yml
@@ -826,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
@@ -836,13 +838,17 @@ 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
+ status_title: Inlägg av @%{name}
title: Kontoinlägg - @%{name}
trending: Trendande
+ view_publicly: Visa offentligt
visibility: Synlighet
with_media: Med media
strikes:
diff --git a/config/locales/th.yml b/config/locales/th.yml
index 32f2b30292c7c0..5178506bab6db1 100644
--- a/config/locales/th.yml
+++ b/config/locales/th.yml
@@ -819,7 +819,6 @@ th:
original_status: โพสต์ดั้งเดิม
reblogs: การดัน
status_changed: เปลี่ยนโพสต์แล้ว
- title: โพสต์ของบัญชี - @%{name}
trending: กำลังนิยม
visibility: การมองเห็น
with_media: มีสื่อ
diff --git a/config/locales/tr.yml b/config/locales/tr.yml
index 2eafed1b4788b8..48f6c5e240aab5 100644
--- a/config/locales/tr.yml
+++ b/config/locales/tr.yml
@@ -826,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
@@ -836,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ı - @%{name}
+ 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 7ea76b2a75d1e3..68ca10c0ccbdbf 100644
--- a/config/locales/uk.yml
+++ b/config/locales/uk.yml
@@ -861,7 +861,6 @@ uk:
original_status: Оригінальний допис
reblogs: Поширення
status_changed: Допис змінено
- title: Дописи облікових записів - @%{name}
trending: Популярне
visibility: Видимість
with_media: З медіа
diff --git a/config/locales/vi.yml b/config/locales/vi.yml
index 71c4357f2f2ce7..acc69f96cd9267 100644
--- a/config/locales/vi.yml
+++ b/config/locales/vi.yml
@@ -812,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
@@ -822,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 - @%{name}
+ 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 cae0efee57ea8a..7dc0f3d9494f0c 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: 批准申诉
@@ -209,7 +209,7 @@ zh-CN:
enable_relay: 启用中继站
enable_sign_in_token_auth_user: 为用户启用邮件令牌身份验证
enable_user: 启用用户
- memorialize_account: 将账户设为追悼模式
+ memorialize_account: 设为追悼账户
promote_user: 给用户升任
reject_appeal: 驳回申诉
reject_user: 拒绝用户
@@ -244,7 +244,7 @@ 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} 创建了规则"
@@ -255,7 +255,7 @@ zh-CN:
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}"
@@ -301,7 +301,7 @@ zh-CN:
empty: 没有找到日志
filter_by_action: 根据行为过滤
filter_by_user: 根据用户过滤
- title: 运营日志
+ title: 审核日志
unavailable_instance: "(域名不可用)"
announcements:
destroyed_msg: 公告已删除!
@@ -337,7 +337,7 @@ zh-CN:
emoji: 表情
enable: 启用
enabled: 已启用
- enabled_msg: 表情启用成功
+ enabled_msg: 已成功启用此表情
image_hint: 最大 %{size} 的 PNG 或 GIF
list: 列表
listed: 已显示
@@ -350,7 +350,7 @@ zh-CN:
shortcode_hint: 至少 2 个字符,只能使用字母、数字和下划线
title: 自定义表情
uncategorized: 未分类
- unlist: 不公开
+ unlist: 隐藏
unlisted: 已隐藏
update_failed_msg: 表情更新失败
updated_msg: 表情更新成功!
@@ -370,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:
@@ -403,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: 封禁
@@ -456,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}
@@ -494,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: 拒收举报
@@ -529,7 +529,7 @@ zh-CN:
moderation:
all: 全部
limited: 受限的
- title: 运营
+ title: 审核
private_comment: 私密评论
public_comment: 公开评论
purge: 删除
@@ -543,7 +543,7 @@ zh-CN:
totals_time_period_hint_html: 下方显示的总数来自全部历史数据。
unknown_instance: 此服务器上目前没有此域名的记录。
invites:
- deactivate_all: 撤销所有邀请链接
+ deactivate_all: 全部停用
filter:
all: 全部
available: 可用
@@ -563,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} 的关系"
@@ -580,7 +580,7 @@ zh-CN:
pending: 等待中继站的确认
save_and_enable: 保存并启用
setup: 设置中继连接
- signatures_not_enabled: 安全模式或限联模式启用时,中继将不会正常工作
+ signatures_not_enabled: 安全模式或白名单模式启用时,中继站可能将不会正常工作
status: 状态
title: 中继站
report_notes:
@@ -597,10 +597,10 @@ 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: 增加更多举报内容
already_suspended_badges:
@@ -622,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: 标记为未处理
@@ -630,7 +630,7 @@ zh-CN:
notes:
create: 添加记录
create_and_resolve: 添加记录并标记为“已处理”
- create_and_unresolve: 添加记录并重开
+ create_and_unresolve: 添加备注并重新打开
delete: 删除
placeholder: 描述已经执行的操作,或其他任何相关的跟进情况…
title: 备注
@@ -651,10 +651,10 @@ 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: 将违规嘟文的媒体标记为敏感
@@ -664,7 +664,7 @@ zh-CN:
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: 被举报账号的来源
@@ -685,7 +685,7 @@ zh-CN:
moderation: 监察
special: 特殊
delete: 刪除
- description_html: 使用 用户角色,您可以自定义您的用户可以访问的功能和区域。
+ description_html: 使用 用户角色,你可以自定义你的用户可以访问的功能和区域。
edit: 编辑 '%{name}' 角色
everyone: 默认权限
everyone_full_description_html: 这是影响到 所有用户的基础角色,包括未指定角色的用户。 其他所有的角色都继承着它的权限。
@@ -706,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: 允许用户浏览和停用邀请链接
@@ -743,7 +743,7 @@ zh-CN:
settings:
about:
manage_rules: 管理服务器规则
- preamble: 提供此服务器如何运营、资金状况等的深入信息。
+ preamble: 提供此服务器如何运营、审核及资金状况等详细信息。
rules_hint: 有一个专门区域用于显示用户需要遵守的规则。
title: 关于本站
appearance:
@@ -774,7 +774,7 @@ zh-CN:
domain_blocks:
all: 对所有人
disabled: 不对任何人
- users: 对本地已登录用户
+ users: 对已登录的本站用户
registrations:
moderation_recommandation: 在向所有人开放注册之前,请确保你拥有一个人手足够且反应迅速的管理团队!
preamble: 控制谁可以在你的服务器上创建账号。
@@ -789,7 +789,7 @@ zh-CN:
authorized_fetch: 需要跨站认证
authorized_fetch_hint: 要求外站请求通过验证能够使用户级别与服务器级别的封锁更为严格。然而,这将带来额外的性能负担、减少回复触达范围、并可能导致与一些联邦宇宙服务的兼容性问题。此外,这并不能阻止他人针对性地获取公开嘟文与账户。
authorized_fetch_overridden_hint: 由于此设置被环境变量覆盖,目前无法更改。
- federation_authentication: 强制跨站认证
+ federation_authentication: 联合时强制要求身份验证
title: 服务器设置
site_uploads:
delete: 删除已上传的文件
@@ -809,11 +809,13 @@ zh-CN:
statuses:
account: 作者
application: 应用
- back_to_account: 返回帐户信息页
+ back_to_account: 返回账户信息页
back_to_report: 返回举报页
batch:
+ add_to_report: '添加到举报 #%{id}'
remove_from_report: 从报告中移除
report: 举报
+ contents: 内容
deleted: 已删除
favourites: 喜欢
history: 版本历史记录
@@ -822,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: 帐户嘟文 - @%{name}
+ status_title: "@%{name} 的嘟文"
+ title: 该账号的嘟文 - @%{name}
trending: 当前热门
+ view_publicly: 以公开身份查看
visibility: 可见性
with_media: 含有媒体文件
strikes:
@@ -960,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: 因为没有选中任何标签,所以没有更改
@@ -980,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:
@@ -1043,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:
@@ -1090,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!
@@ -1111,8 +1117,8 @@ zh-CN:
privacy_policy_agreement_html: 我已阅读并同意 隐私政策
progress:
confirm: 确认邮箱
- details: 您的详情
- review: 我们的复审
+ details: 你的详情
+ review: 我们的审核
rules: 接受规则
providers:
cas: CAS
@@ -1128,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: 账户状态
@@ -1157,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: 然后,在下面的文本框中添加你用于发布文章的域名。
@@ -1218,7 +1224,7 @@ zh-CN:
approve_appeal: 批准申诉
associated_report: 相关举报
created_at: 日期
- description_html: 这些是针对您的账户采取的行动和警告,已经由 %{instance} 的工作人员发送给您。
+ description_html: 这些是针对你的账户采取的行动和警告,已经由 %{instance} 的工作人员发送给你。
recipient: 发送至
reject_appeal: 驳回申诉
status: '嘟文 #%{id}'
@@ -1237,7 +1243,7 @@ zh-CN:
your_appeal_rejected: 你的申诉已被驳回
edit_profile:
basic_information: 基本信息
- hint_html: "自定义公开资料和嘟文旁边显示的内容。当您填写完整的个人资料并设置了头像时,其他人更有可能关注您并与您互动。"
+ hint_html: "自定义公开资料和嘟文旁边显示的内容。当你填写完整的个人资料并设置了头像时,其他人更有可能关注你并与你互动。"
other: 其他
errors:
'400': 你提交的请求无效或格式不正确。
@@ -1275,7 +1281,7 @@ zh-CN:
featured_tags:
add_new: 添加新条目
errors:
- limit: 您所推荐的话题标签数已达上限
+ limit: 你所推荐的话题标签数已达上限
hint_html: "什么是精选话题标签? 它们被显示在你的公开个人资料中的突出位置,人们可以在这些标签下浏览你的公共嘟文。 它们是跟踪创作或长期项目的进度的重要工具。"
filters:
contexts:
@@ -1321,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: 确认
@@ -1332,7 +1338,7 @@ zh-CN:
order_by: 排序方式
save_changes: 保存更改
select_all_matching_items:
- other: 选择匹配您搜索的所有 %{count} 个项目。
+ other: 选择匹配你搜索的所有 %{count} 个项目。
today: 今天
validation_errors:
other: 出错啦!检查一下下面 %{count} 处出错的地方吧
@@ -1353,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:
@@ -1363,7 +1369,7 @@ zh-CN:
lists_html:
other: 你即将使用来自 %{filename} 的内容替换你的列表。最多将会有 %{count} 个账户 被添加到新列表。
muting_html:
- other: 你即将使用来自 %{filename} 的最多 %{count} 个帐户替换你的已隐藏账户列表。
+ other: 你即将使用来自 %{filename} 的最多 %{count} 个账户替换你的已隐藏账户列表。
preambles:
blocking_html:
other: 你即将屏蔽来自 %{filename} 的最多 %{count} 个账号。
@@ -1397,7 +1403,7 @@ zh-CN:
type: 导入类型
type_groups:
constructive: 关注和书签
- destructive: 屏蔽和隐藏
+ destructive: 屏蔽与隐藏
types:
blocking: 屏蔽列表
bookmarks: 书签
@@ -1430,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})
@@ -1495,7 +1501,7 @@ zh-CN:
other_data: 不会自动移动其它数据
redirect: 在收到一个跳转通知后,你当前的账号资料将会更新,并被排除在搜索范围外
moderation:
- title: 运营
+ title: 审核
move_handler:
carry_blocks_over_text: 这个用户迁移自你屏蔽过的 %{acct}
carry_mutes_over_text: 这个用户由你隐藏过的 %{acct} 迁移而来
@@ -1523,7 +1529,7 @@ zh-CN:
title: 新的关注请求
mention:
action: 回复
- body: "%{name} 在嘟文中提到了你:"
+ body: "%{name} 提到了你:"
subject: "%{name} 提到了你"
title: 新的提及
poll:
@@ -1585,7 +1591,7 @@ zh-CN:
privacy: 隐私
privacy_hint_html: 控制你愿意向他人透露多少信息。通过浏览他人的关注列表和查看他们发嘟所用的应用,人们可以发现有趣的用户和酷炫的应用,但你可能更喜欢将其隐藏起来。
reach: 范围
- reach_hint_html: 控制您是否希望被新人发现和关注。您是否希望您的嘟文出现在“探索”页面上?您是否希望其他人在关注推荐中看到您?您是想自动接受所有新粉丝,还是对每个粉丝都进行仔细的筛选?
+ reach_hint_html: 控制你是否希望被新人发现和关注。你是否希望你的嘟文出现在“探索”页面上?你是否希望其他人在关注推荐中看到你?你是想自动接受所有新粉丝,还是对每个粉丝都进行仔细的筛选?
search: 搜索
search_hint_html: 控制你希望被找到的方式。你想让人们通过你公开发布的内容来找到你吗?当在网络上搜索时,你是否希望Mastodon之外的人能够找到你的个人资料?请注意,我们无法保证完全排除所有搜索引擎对公开信息的索引。
title: 隐私与可达性
@@ -1593,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: 关注选中的关注者
@@ -1649,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: 未知浏览器
@@ -1673,7 +1679,7 @@ zh-CN:
ios: iOS
kai_os: KaiOS
linux: Linux
- mac: Mac
+ mac: macOS
unknown_platform: 未知平台
windows: Windows
windows_mobile: Windows Mobile
@@ -1695,15 +1701,15 @@ zh-CN:
export: 导出
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:
@@ -1737,7 +1743,7 @@ zh-CN:
over_character_limit: 超过了 %{max} 字的限制
pin_errors:
direct: 仅对被提及的用户可见的帖子不能被置顶
- limit: 你所固定的嘟文数量已达到上限
+ limit: 你置顶的嘟文数量已达上限
ownership: 不能置顶别人的嘟文
reblog: 不能置顶转嘟
title: "%{name}:“%{quote}”"
@@ -1747,13 +1753,13 @@ zh-CN:
private_long: 只有关注你的用户能看到
public: 公开
public_long: 所有人可见,并会出现在公共时间轴上
- unlisted: 不公开
+ unlisted: 悄悄公开
unlisted_long: 所有人可见,但不会出现在公共时间轴上
statuses_cleanup:
enabled: 自动删除旧嘟文
- enabled_hint: 达到指定过期时间后自动删除您的嘟文,除非满足下列条件之一
+ enabled_hint: 达到指定过期时间后自动删除你的嘟文,除非满足下列条件之一
exceptions: 例外
- explanation: 删除嘟文是一个消耗系统资源的耗时操作,所以这个操作会在服务器空闲时完成。因此,您的嘟文可能会在达到过期阈值之后一段时间才会被删除。
+ explanation: 删除嘟文是一个消耗系统资源的耗时操作,所以这个操作会在服务器空闲时完成。因此,你的嘟文可能会在达到过期阈值之后一段时间才会被删除。
ignore_favs: 取消喜欢
ignore_reblogs: 忽略转嘟
interaction_exceptions: 基于互动的例外
@@ -1792,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"
@@ -1847,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} 的工作人员提交申诉。
@@ -1895,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 6f0a99a5b35567..752c9b5cbf0ebf 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: 帳戶文章 - @%{name}
trending: 熱門
visibility: 可見性
with_media: 含有媒體檔案
diff --git a/config/locales/zh-TW.yml b/config/locales/zh-TW.yml
index ce6bd3e8f5c4bc..701ea0ea537b41 100644
--- a/config/locales/zh-TW.yml
+++ b/config/locales/zh-TW.yml
@@ -814,8 +814,10 @@ zh-TW:
back_to_account: 返回帳號資訊頁面
back_to_report: 回到檢舉報告頁面
batch:
+ add_to_report: '新增至報告 #%{id}'
remove_from_report: 自檢舉報告中移除
report: 檢舉報告
+ contents: 內容
deleted: 已刪除
favourites: 最愛
history: 版本紀錄
@@ -824,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: 帳號嘟文 - @%{name}
+ status_title: 由 @%{name} 發嘟
+ title: 嘟文帳號 - @%{name}
trending: 熱門
+ view_publicly: 公開檢視
visibility: 可見性
with_media: 含有媒體檔案
strikes:
diff --git a/config/mastodon.yml b/config/mastodon.yml
index 255213b4b7a698..2c09c59e0a8bc6 100644
--- a/config/mastodon.yml
+++ b/config/mastodon.yml
@@ -1,3 +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/lib/exceptions.rb b/lib/exceptions.rb
index 1910d37a13ceee..135f8126a41f80 100644
--- a/lib/exceptions.rb
+++ b/lib/exceptions.rb
@@ -8,7 +8,6 @@ class HostValidationError < ValidationError; end
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/federation.rb b/lib/mastodon/cli/federation.rb
index c7387965573d3c..f512bca358ac76 100644
--- a/lib/mastodon/cli/federation.rb
+++ b/lib/mastodon/cli/federation.rb
@@ -76,7 +76,7 @@ def proceed_prompt_negative?
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/version.rb b/lib/mastodon/version.rb
index 5bc32b1eaf605d..a16b3d550f953c 100644
--- a/lib/mastodon/version.rb
+++ b/lib/mastodon/version.rb
@@ -70,6 +70,10 @@ def source_url
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/tasks/annotate_rb.rake b/lib/tasks/annotate_rb.rake
new file mode 100644
index 00000000000000..e8368b2e940c1c
--- /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 4b5997920a3533..00000000000000
--- 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/spec/helpers/accounts_helper_spec.rb b/spec/helpers/accounts_helper_spec.rb
index 2c949cde696912..85264823624618 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 @@ def set_embedded_view
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 @@ def set_embedded_view
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/self_destruct_helper_spec.rb b/spec/helpers/self_destruct_helper_spec.rb
index 09d7347eee7ab7..dca1590764522c 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 @@
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 @@
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 @@
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 edd3e8f2f7ff5a..07ad72eda956f9 100644
--- a/spec/helpers/statuses_helper_spec.rb
+++ b/spec/helpers/statuses_helper_spec.rb
@@ -77,28 +77,4 @@
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/annual_report/commonly_interacted_with_accounts_spec.rb b/spec/lib/annual_report/commonly_interacted_with_accounts_spec.rb
index 0e31827912b58d..12bf3810db6d60 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 @@
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 2f04934e47799e..956549c32527f1 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 @@
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 d2fcecc4d8130c..ab7022ef2037a2 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 @@
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/top_hashtags_spec.rb b/spec/lib/annual_report/top_hashtags_spec.rb
index 58a915218467de..b9cc9392ed224a 100644
--- a/spec/lib/annual_report/top_hashtags_spec.rb
+++ b/spec/lib/annual_report/top_hashtags_spec.rb
@@ -21,20 +21,31 @@
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/search_query_transformer_spec.rb b/spec/lib/search_query_transformer_spec.rb
index 9399f3503d0702..b69e3afc9d5313 100644
--- a/spec/lib/search_query_transformer_spec.rb
+++ b/spec/lib/search_query_transformer_spec.rb
@@ -16,6 +16,7 @@
['"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 @@
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/concerns/account/sensitizes_spec.rb b/spec/models/concerns/account/sensitizes_spec.rb
index 3596c9a1261050..5416d40570ad91 100644
--- a/spec/models/concerns/account/sensitizes_spec.rb
+++ b/spec/models/concerns/account/sensitizes_spec.rb
@@ -7,7 +7,7 @@
describe '.sensitized' do
let(:sensitized_account) { Fabricate :account, sensitized_at: 2.days.ago }
- before { Fabricate :account, sensitized_at: false }
+ before { Fabricate :account, sensitized_at: nil }
it 'returns an array of accounts who are sensitized' do
expect(Account.sensitized)
diff --git a/spec/models/follow_request_spec.rb b/spec/models/follow_request_spec.rb
index f30e27e701c46e..4db129dc51d2b0 100644
--- a/spec/models/follow_request_spec.rb
+++ b/spec/models/follow_request_spec.rb
@@ -30,7 +30,7 @@
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 22ffdfd877c0d1..e14ad6eca03523 100644
--- a/spec/models/form/import_spec.rb
+++ b/spec/models/form/import_spec.rb
@@ -237,51 +237,26 @@
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/login_activity_spec.rb b/spec/models/login_activity_spec.rb
new file mode 100644
index 00000000000000..5b7935e8ba4179
--- /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 a0e4f6fafd5e71..b4fbea437ffe08 100644
--- a/spec/models/report_spec.rb
+++ b/spec/models/report_spec.rb
@@ -108,15 +108,22 @@
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 bed411c3698d26..bb9b3c785f13ed 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/services/unmute_service_spec.rb b/spec/services/unmute_service_spec.rb
index 92c7a70d65d105..a052e0dd0a78b6 100644
--- a/spec/services/unmute_service_spec.rb
+++ b/spec/services/unmute_service_spec.rb
@@ -16,7 +16,7 @@
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/support/examples/models/concerns/browser_detection.rb b/spec/support/examples/models/concerns/browser_detection.rb
new file mode 100644
index 00000000000000..e80fa4595cd651
--- /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/workers/activitypub/delivery_worker_spec.rb b/spec/workers/activitypub/delivery_worker_spec.rb
index 3dfbef31a43594..9e6805c68b4f06 100644
--- a/spec/workers/activitypub/delivery_worker_spec.rb
+++ b/spec/workers/activitypub/delivery_worker_spec.rb
@@ -5,26 +5,45 @@
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/streaming/database.js b/streaming/database.js
index 9f1d742143a158..60a3b34ef0fcbe 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 7bbcc1497f9e50..9c2b671c65e103 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/yarn.lock b/yarn.lock
index 1e9250ee913762..0eb01d5a670c96 100644
--- a/yarn.lock
+++ b/yarn.lock
@@ -2232,8 +2232,8 @@ __metadata:
linkType: hard
"@formatjs/cli@npm:^6.1.1":
- version: 6.3.8
- resolution: "@formatjs/cli@npm:6.3.8"
+ 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
@@ -2262,7 +2262,7 @@ __metadata:
optional: true
bin:
formatjs: bin/formatjs
- checksum: 10c0/61fb0e56a2da26befad5ca6ff5a8bcf9c383d22634cf288f3cab5661bece7686e6f064adaa500954b37726a7745c73134b459d115d52c931b76d68d998c7b22d
+ checksum: 10c0/31d5fac85314e97591c4c6a4793abf1d9c6fbf790fbbea779b2a4c0f742f1859804f290e77be06d128274468e44bc27992196aacb4cb6f2fbd141755ca79a98d
languageName: node
linkType: hard