diff --git a/.env.production.sample b/.env.production.sample index 15004b9d0d9..8ea569fb016 100644 --- a/.env.production.sample +++ b/.env.production.sample @@ -91,9 +91,6 @@ SESSION_RETENTION_PERIOD=31556952 # Fetch All Replies Behavior # -------------------------- -# When a user expands a post (DetailedStatus view), fetch all of its replies -# (default: false) -FETCH_REPLIES_ENABLED=false # Period to wait between fetching replies (in minutes) FETCH_REPLIES_COOLDOWN_MINUTES=15 diff --git a/.ruby-version b/.ruby-version index 1cf8253024c..2aa51319921 100644 --- a/.ruby-version +++ b/.ruby-version @@ -1 +1 @@ -3.4.6 +3.4.7 diff --git a/.storybook/preview.tsx b/.storybook/preview.tsx index fcba9230308..d66f0fb11a8 100644 --- a/.storybook/preview.tsx +++ b/.storybook/preview.tsx @@ -50,9 +50,13 @@ const preview: Preview = { locale: 'en', }, decorators: [ - (Story, { parameters, globals }) => { + (Story, { parameters, globals, args }) => { + // Get the locale from the global toolbar + // and merge it with any parameters or args state. const { locale } = globals as { locale: string }; const { state = {} } = parameters; + const { state: argsState = {} } = args; + const reducer = reducerWithInitialState( { meta: { @@ -60,7 +64,9 @@ const preview: Preview = { }, }, state as Record, + argsState as Record, ); + const store = configureStore({ reducer, middleware(getDefaultMiddleware) { diff --git a/CHANGELOG.md b/CHANGELOG.md index 3ad88c51070..bebb2a3b158 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,130 @@ All notable changes to this project will be documented in this file. +## [4.5.0] - UNRELEASED + +### Added + +- **Add support for allowing and authoring quotes** (#35355, #35578, #35614, #35618, #35624, #35626, #35652, #35629, #35665, #35653, #35670, #35677, #35690, #35697, #35689, #35699, #35700, #35701, #35709, #35714, #35713, #35715, #35725, #35749, #35769, #35780, #35762, #35804, #35808, #35805, #35819, #35824, #35828, #35822, #35835, #35865, #35860, #35832, #35891, #35894, #35895, #35820, #35917, #35924, #35925, #35914, #35930, #35941, #35939, #35948, #35955, #35967, #35990, #35991, #35975, #35971, #36002, #35986, #36031, #36034, #36038, #36054, #36052, #36055, #36065, #36068, #36083, #36087, #36080, #36091, #36090, #36118, #36119, #36128, #36094, #36129, #36138, #36132, #36151, #36158, #36171, #36194, #36220, #36169, #36130, #36249, #36153, #36299, #36291, #36301, #36315, #36317, #36364, #36383, #36381, #36459, #36464, and #36461 by @ChaosExAnima, @ClearlyClaire, @Lycolia, @diondiondion, and @tribela)\ + This includes a revamp of the composer interface.\ + See https://blog.joinmastodon.org/2025/09/introducing-quote-posts/ for a user-centric overview of the feature, and https://docs.joinmastodon.org/client/quotes/ for API documentation. +- **Add support for fetching and refreshing replies to the web UI** (#35210, #35496, #35575, #35500, #35577, #35602, #35603, #35654, #36141, #36237, #36172, #36256, #36271, #36334, #36382, and #36239 by @ClearlyClaire, @Gargron, and @diondiondion) +- **Add ability to block words in usernames** (#35407, #35655, and #35806 by @ClearlyClaire and @Gargron) +- Add support for displaying link previews for Admin UI (#35958 by @ThisIsMissEm) +- Add support for dynamic viewport height (#36272 by @e1berd) +- Add support for numeric-based URIs for new local accounts (#32724, #36304, #36316, and #36365 by @ClearlyClaire) +- Add Traditional Mongolian to posting languages (#36196 by @shimon1024) +- Add example post with manual quote approval policy to `dev:populate_sample_data` (#36099 by @ClearlyClaire) +- Add server-side support for handling posts with a quote policy allowing followers to quote (#36093 and #36127 by @ClearlyClaire) +- Add schema.org markup to SEO-enabled posts (#36075 by @Gargron) +- Add migration to fill unset default quote policy based on default post privacy (#36041 by @ClearlyClaire) +- Add support for exposing conversation context for new public conversations according to FEP-7888 (#35959 and #36064 by @ClearlyClaire and @jesseplusplus) +- Add digest re-check before removing followers in synchronization mechanism (#34273 by @ClearlyClaire) +- Add “Posting defaults” setting page, moving existing settings from “Other” (#35896, #36033, #35966, #35969, and #36084 by @ClearlyClaire and @diondiondion) +- Add support for displaying Valkey version on admin dashboard (#35785 by @ykzts) +- Add delivery failure tracking and handling to FASP jobs (#35625, #35628, and #35723 by @oneiros) +- Add example of quote post with a preview card to development sample data (#35616 by @ClearlyClaire) +- Add second set of blocked text that applies to accounts regardless of account age for spam-blocking (#35563 by @ClearlyClaire) +- Add experimental feature to select custom emoji rendering (#35229, #35282, #35253, #35424, #35473, #35483, #35505, #35568, #35605, #35659, #35664, #35739, #35985, #36051, #36071, #36137, #36165, #36248, #36262, #36275, #36293, #36341, #36342, #36366, #36377, #36378, #36385, #36393, #36397, #36403, #36413, #36410, #36454, and #36402 by @ChaosExAnima and @braddunbar)\ + This also completely reworks the processing and rendering of emojis and server-rendered HTML in statuses and other places. + +### Changed + +- Change confirmation dialogs for follow button actions “unfollow”, “unblock”, and “withdraw request” (#36289 by @diondiondion) +- Change “Follow” button labels (#36264 by @diondiondion) +- Change display of content warnings in Admin UI (#35935 by @ThisIsMissEm) +- Change index on `follows` table to improve performance of some queries (#36374 by @ClearlyClaire) +- Change links to accounts in settings and moderation views to link to local view unless account is suspended (#36340 by @diondiondion) +- Change redirection for denied registration from web app to sign-in page with error message (#36384 by @ClearlyClaire) +- Change `timeline_preview` setting into four more granular settings (#36338 and #36467 by @ClearlyClaire) +- Change wording and design of interaction dialog to simplify it (#36124 by @diondiondion) +- Change dropdown menus to allow disabled items to be focused (#36078 by @diondiondion) +- Change modal background colours in light mode (#36069 by @diondiondion) +- Change “Posting defaults” settings page to enforce `nobody` quote policy for `private` default visibility (#36040 by @ClearlyClaire) +- Change description of “Quiet public” (#36032 by @ClearlyClaire) +- Change “Boost with original visibility” to “Share again with your followers” (#36035 by @ClearlyClaire) +- Change handling of push subscriptions to automatically delete invalid ones on delivery (#35987 by @ThisIsMissEm) +- Change design of quote posts in web UI (#35584 and #35834 by @ClearlyClaire and @Gargron) +- Change auditable accounts to be sorted by username in admin action logs interface (#35272 by @breadtk) +- Change order of translation restoration and service credit on post card (#33619 by @colindean) +- Change position of ‘add more’ to be inside table toolbar on reports (#35963 by @ThisIsMissEm) + +### Fixed + +- Fix rendering of poll options in status history modal (#35633 by @ThisIsMissEm) +- Fix “mute” button being displayed to unauthenticated visitors in hashtag dropdown (#36353 by @mkljczk) +- Fix overflow handling of `.more-from-author` (#36310 by @edent) +- Fix unfortunate action button wrapping in admin area (#36247 by @diondiondion) +- Fix translate button width in Safari (#36164 and #36216 by @diondiondion) +- Fix login page linking to other pages within OAuth authorization flow (#36115 by @Gargron) +- Fix stale search results being displayed in Web UI while new query is in progress (#36053 by @ChaosExAnima) +- Fix YouTube iframe not being able to start at a defined time (#26584 by @BrunoViveiros) +- Fix banned text being able to be circumvented via unicode (#35978 by @Gargron) +- Fix batch table toolbar displaying under status media (#35962 by @ThisIsMissEm) +- Fix incorrect RSS feed MIME type in gzip_types directive (#35562 by @iioflow) +- Fix 404 error after deleting status from detail view (#35800) (#35881 by @crafkaz) +- Fix feeds keyboard navigation issues (#35853, #35864, and #36267 by @braddunbar and @diondiondion) +- Fix layout shift caused by “Who to follow” widget (#35861 by @diondiondion) +- Fix Vagrantfile (#35765 by @ClearlyClaire) +- Fix reply indicator displaying wrong avatar in rare cases (#35756 by @ClearlyClaire) +- Fix `Chewy::UndefinedUpdateStrategy` in `dev:populate_sample_data` task when Elasticsearch is enabled (#35615 by @ClearlyClaire) +- Fix unnecessary account note addition for already-muted moved-to users (#35566 by @mjankowski) +- Fix seeded admin user creation failing on specific configurations (#35565 by @oneiros) +- Fix media modal images in Web UI having redundant `title` attribute (#35468 by @mayank99) +- Fix inconsistent default privacy post setting when unset in settings (#35422 by @oneiros) +- Fix glitchy status keyboard navigation (#35455 and #35504 by @diondiondion) +- Fix post being submitted when pressing “Enter” in the CW field (#35445 by @diondiondion) + +## [4.4.7] - 2025-10-15 + +### Fixed + +- Fix forwarder being called with `nil` status when quote post is soft-deleted (#36463 by @ClearlyClaire) +- Fix moderation warning e-mails that include posts (#36462 by @ClearlyClaire) +- Fix allow_referrer_origin typo (#36460 by @ShadowJonathan) + +## [4.4.6] - 2025-10-13 + +### Security + +- Update dependencies `rack` and `uri` +- Fix streaming server connection not being closed on user suspension (by @ThisIsMissEm, [GHSA-r2fh-jr9c-9pxh](https://github.com/mastodon/mastodon/security/advisories/GHSA-r2fh-jr9c-9pxh)) +- Fix password change through admin CLI not invalidating existing sessions and access tokens (by @ThisIsMissEm, [GHSA-f3q3-rmf7-9655](https://github.com/mastodon/mastodon/security/advisories/GHSA-f3q3-rmf7-9655)) +- Fix streaming server allowing access to public timelines even without the `read` or `read:statuses` OAuth scopes (by @ThisIsMissEm, [GHSA-7gwh-mw97-qjgp](https://github.com/mastodon/mastodon/security/advisories/GHSA-7gwh-mw97-qjgp)) + +### Added + +- Add support for processing quotes of deleted posts signaled through a `Tombstone` (#36381 by @ClearlyClaire) + +### Fixed + +- Fix quote post state sometimes not being updated through streaming server (#36408 by @ClearlyClaire) +- Fix inconsistent “pending tags” count on admin dashboard (#36404 by @mjankowski) +- Fix JSON payload being potentially mutated when processing interaction policies (#36392 by @ClearlyClaire) +- Fix quotes not being displayed in email notifications (#36379 by @diondiondion) +- Fix redirect to external object when URL is missing or malformed (#36347 by @ClearlyClaire) +- Fix quotes not being displayed in the featured carousel (#36335 by @diondiondion) + +## [4.4.5] - 2025-09-23 + +### Security + +- Update dependencies + +### Added + +- Add support for `has:quote` in search (#36217 by @ClearlyClaire) + +### Changed + +- Change quoted posts from silenced accounts to use a click-through rather than being hidden (#36166 and #36167 by @ClearlyClaire) + +### Fixed + +- Fix processing of out-of-order `Update` as implicit updates (#36190 by @ClearlyClaire) +- Fix getting `Create` and `Update` out of order (#36176 by @ClearlyClaire) +- Fix quotes with Content Warnings but no text being shown without Content Warnings (#36150 by @ClearlyClaire) + ## [4.4.4] - 2025-09-16 ### Security diff --git a/Dockerfile b/Dockerfile index f2164ffd941..e457ae3623b 100644 --- a/Dockerfile +++ b/Dockerfile @@ -13,7 +13,7 @@ ARG BASE_REGISTRY="docker.io" # Ruby image to use for base image, change with [--build-arg RUBY_VERSION="3.4.x"] # renovate: datasource=docker depName=docker.io/ruby -ARG RUBY_VERSION="3.4.6" +ARG RUBY_VERSION="3.4.7" # # Node.js version to use in base image, change with [--build-arg NODE_MAJOR_VERSION="20"] # renovate: datasource=node-version depName=node ARG NODE_MAJOR_VERSION="22" @@ -208,12 +208,12 @@ FROM build AS ffmpeg # renovate: datasource=repology depName=ffmpeg packageName=openpkg_current/ffmpeg ARG FFMPEG_VERSION=8.0 # ffmpeg download URL, change with [--build-arg FFMPEG_URL="https://ffmpeg.org/releases"] -ARG FFMPEG_URL=https://ffmpeg.org/releases +ARG FFMPEG_URL=https://github.com/FFmpeg/FFmpeg/archive/refs/tags WORKDIR /usr/local/ffmpeg/src # Download and extract ffmpeg source code -ADD ${FFMPEG_URL}/ffmpeg-${FFMPEG_VERSION}.tar.xz /usr/local/ffmpeg/src/ -RUN tar xf ffmpeg-${FFMPEG_VERSION}.tar.xz; +ADD ${FFMPEG_URL}/n${FFMPEG_VERSION}.tar.gz /usr/local/ffmpeg/src/ +RUN tar xf n${FFMPEG_VERSION}.tar.gz && mv FFmpeg-n${FFMPEG_VERSION} ffmpeg-${FFMPEG_VERSION}; WORKDIR /usr/local/ffmpeg/src/ffmpeg-${FFMPEG_VERSION} diff --git a/Gemfile b/Gemfile index 0d9ab342715..a12e7169200 100644 --- a/Gemfile +++ b/Gemfile @@ -105,20 +105,20 @@ gem 'prometheus_exporter', '~> 2.2', require: false gem 'opentelemetry-api', '~> 1.7.0' group :opentelemetry do - gem 'opentelemetry-exporter-otlp', '~> 0.30.0', require: false - gem 'opentelemetry-instrumentation-active_job', '~> 0.8.0', require: false - gem 'opentelemetry-instrumentation-active_model_serializers', '~> 0.22.0', require: false - gem 'opentelemetry-instrumentation-concurrent_ruby', '~> 0.22.0', require: false - gem 'opentelemetry-instrumentation-excon', '~> 0.24.0', require: false - gem 'opentelemetry-instrumentation-faraday', '~> 0.28.0', require: false - gem 'opentelemetry-instrumentation-http', '~> 0.25.0', require: false - gem 'opentelemetry-instrumentation-http_client', '~> 0.24.0', require: false - gem 'opentelemetry-instrumentation-net_http', '~> 0.24.0', require: false - gem 'opentelemetry-instrumentation-pg', '~> 0.30.0', require: false - gem 'opentelemetry-instrumentation-rack', '~> 0.27.0', require: false - gem 'opentelemetry-instrumentation-rails', '~> 0.37.0', require: false - gem 'opentelemetry-instrumentation-redis', '~> 0.26.0', require: false - gem 'opentelemetry-instrumentation-sidekiq', '~> 0.26.0', require: false + gem 'opentelemetry-exporter-otlp', '~> 0.31.0', require: false + gem 'opentelemetry-instrumentation-active_job', '~> 0.9.0', require: false + gem 'opentelemetry-instrumentation-active_model_serializers', '~> 0.23.0', require: false + gem 'opentelemetry-instrumentation-concurrent_ruby', '~> 0.23.0', require: false + gem 'opentelemetry-instrumentation-excon', '~> 0.25.0', require: false + gem 'opentelemetry-instrumentation-faraday', '~> 0.29.0', require: false + gem 'opentelemetry-instrumentation-http', '~> 0.26.0', require: false + gem 'opentelemetry-instrumentation-http_client', '~> 0.25.0', require: false + gem 'opentelemetry-instrumentation-net_http', '~> 0.25.0', require: false + gem 'opentelemetry-instrumentation-pg', '~> 0.31.0', require: false + gem 'opentelemetry-instrumentation-rack', '~> 0.28.0', require: false + gem 'opentelemetry-instrumentation-rails', '~> 0.38.0', require: false + gem 'opentelemetry-instrumentation-redis', '~> 0.27.0', require: false + gem 'opentelemetry-instrumentation-sidekiq', '~> 0.27.0', require: false gem 'opentelemetry-sdk', '~> 1.4', require: false end diff --git a/Gemfile.lock b/Gemfile.lock index cd96d60e1d5..991cdf1549a 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -96,7 +96,7 @@ GEM ast (2.4.3) attr_required (1.0.2) aws-eventstream (1.4.0) - aws-partitions (1.1135.0) + aws-partitions (1.1168.0) aws-sdk-core (3.215.1) aws-eventstream (~> 1, >= 1.3.0) aws-partitions (~> 1, >= 1.992.0) @@ -121,7 +121,7 @@ GEM erubi (>= 1.0.0) rack (>= 0.9.0) rouge (>= 1.0.0) - bigdecimal (3.2.3) + bigdecimal (3.3.1) bindata (2.5.1) binding_of_caller (1.0.1) debug_inspector (>= 1.2.0) @@ -207,7 +207,7 @@ GEM railties (>= 5) dotenv (3.1.8) drb (2.2.3) - dry-cli (1.2.0) + dry-cli (1.3.0) elasticsearch (7.17.11) elasticsearch-api (= 7.17.11) elasticsearch-transport (= 7.17.11) @@ -226,18 +226,18 @@ GEM activemodel erb (5.0.2) erubi (1.13.1) - et-orbi (1.2.11) + et-orbi (1.4.0) tzinfo - excon (1.2.8) + excon (1.3.0) logger fabrication (3.0.0) faker (3.5.2) i18n (>= 1.8.11, < 2) - faraday (2.13.4) + faraday (2.14.0) faraday-net_http (>= 2.0, < 3.5) json logger - faraday-follow_redirects (0.3.0) + faraday-follow_redirects (0.4.0) faraday (>= 1, < 3) faraday-httpclient (2.0.2) httpclient (>= 2.2) @@ -266,18 +266,19 @@ GEM fog-openstack (1.1.5) fog-core (~> 2.1) fog-json (>= 1.0) - formatador (1.1.1) + formatador (1.2.1) + reline forwardable (1.3.3) - fugit (1.11.1) - et-orbi (~> 1, >= 1.2.11) + fugit (1.12.0) + et-orbi (~> 1.4) raabro (~> 1.4) - globalid (1.2.1) + globalid (1.3.0) activesupport (>= 6.1) - google-protobuf (4.31.1) + google-protobuf (4.32.1) bigdecimal rake (>= 13) - googleapis-common-protos-types (1.20.0) - google-protobuf (>= 3.18, < 5.a) + googleapis-common-protos-types (1.22.0) + google-protobuf (~> 4.26) haml (6.3.0) temple (>= 0.8.2) thor @@ -293,7 +294,7 @@ GEM rainbow rubocop (>= 1.0) sysexits (~> 1.1) - hashdiff (1.2.0) + hashdiff (1.2.1) hashie (5.0.0) hcaptcha (7.1.0) json @@ -309,7 +310,7 @@ GEM http-cookie (~> 1.0) http-form_data (~> 2.2) llhttp-ffi (~> 0.5.0) - http-cookie (1.0.8) + http-cookie (1.1.0) domain_name (~> 0.5) http-form_data (2.3.0) http_accept_language (2.1.1) @@ -345,9 +346,9 @@ GEM azure-blob (~> 0.5.2) hashie (~> 5.0) jmespath (1.6.2) - json (2.15.0) + json (2.15.1) json-canonicalization (1.0.0) - json-jwt (1.16.7) + json-jwt (1.17.0) activesupport (>= 4.2) aes_key_wrap base64 @@ -438,7 +439,7 @@ GEM mime-types (3.7.0) logger mime-types-data (~> 3.2025, >= 3.2025.0507) - mime-types-data (3.2025.0916) + mime-types-data (3.2025.0924) mini_mime (1.1.5) mini_portile2 (2.8.9) minitest (5.25.5) @@ -447,7 +448,7 @@ GEM mutex_m (0.3.0) net-http (0.6.0) uri - net-imap (0.5.10) + net-imap (0.5.12) date net-protocol net-ldap (0.20.0) @@ -466,8 +467,9 @@ GEM oj (3.16.11) bigdecimal (>= 3.0) ostruct (>= 0.2) - omniauth (2.1.3) + omniauth (2.1.4) hashie (>= 3.4.6) + logger rack (>= 2.2.3) rack-protection omniauth-cas (3.0.2) @@ -496,102 +498,77 @@ GEM tzinfo validate_url webfinger (~> 2.0) - openssl (3.3.0) + openssl (3.3.1) openssl-signature_algorithm (1.3.0) openssl (> 2.0) opentelemetry-api (1.7.0) - opentelemetry-common (0.22.0) + opentelemetry-common (0.23.0) opentelemetry-api (~> 1.0) - opentelemetry-exporter-otlp (0.30.0) + opentelemetry-exporter-otlp (0.31.0) google-protobuf (>= 3.18) googleapis-common-protos-types (~> 1.3) opentelemetry-api (~> 1.1) opentelemetry-common (~> 0.20) opentelemetry-sdk (~> 1.2) opentelemetry-semantic_conventions - opentelemetry-helpers-sql (0.1.1) - opentelemetry-api (~> 1.0) + opentelemetry-helpers-sql (0.2.0) + opentelemetry-api (~> 1.7) opentelemetry-helpers-sql-obfuscation (0.3.0) opentelemetry-common (~> 0.21) - opentelemetry-instrumentation-action_mailer (0.4.0) - opentelemetry-api (~> 1.0) + opentelemetry-instrumentation-action_mailer (0.5.0) opentelemetry-instrumentation-active_support (~> 0.7) - opentelemetry-instrumentation-base (~> 0.23.0) - opentelemetry-instrumentation-action_pack (0.13.0) - opentelemetry-api (~> 1.0) - opentelemetry-instrumentation-base (~> 0.23.0) + opentelemetry-instrumentation-action_pack (0.14.1) opentelemetry-instrumentation-rack (~> 0.21) - opentelemetry-instrumentation-action_view (0.9.0) - opentelemetry-api (~> 1.0) + opentelemetry-instrumentation-action_view (0.10.0) opentelemetry-instrumentation-active_support (~> 0.7) - opentelemetry-instrumentation-base (~> 0.23.0) - opentelemetry-instrumentation-active_job (0.8.0) - opentelemetry-api (~> 1.0) - opentelemetry-instrumentation-base (~> 0.23.0) - opentelemetry-instrumentation-active_model_serializers (0.22.0) - opentelemetry-api (~> 1.0) + opentelemetry-instrumentation-active_job (0.9.2) + opentelemetry-instrumentation-base (~> 0.24) + opentelemetry-instrumentation-active_model_serializers (0.23.0) opentelemetry-instrumentation-active_support (>= 0.7.0) - opentelemetry-instrumentation-base (~> 0.23.0) - opentelemetry-instrumentation-active_record (0.9.0) - opentelemetry-api (~> 1.0) - opentelemetry-instrumentation-base (~> 0.23.0) - opentelemetry-instrumentation-active_storage (0.1.1) - opentelemetry-api (~> 1.0) + opentelemetry-instrumentation-active_record (0.10.1) + opentelemetry-instrumentation-base (~> 0.24) + opentelemetry-instrumentation-active_storage (0.2.0) opentelemetry-instrumentation-active_support (~> 0.7) - opentelemetry-instrumentation-base (~> 0.23.0) - opentelemetry-instrumentation-active_support (0.8.0) - opentelemetry-api (~> 1.0) - opentelemetry-instrumentation-base (~> 0.23.0) - opentelemetry-instrumentation-base (0.23.0) - opentelemetry-api (~> 1.0) + opentelemetry-instrumentation-active_support (0.9.1) + opentelemetry-instrumentation-base (~> 0.24) + opentelemetry-instrumentation-base (0.24.0) + opentelemetry-api (~> 1.7) opentelemetry-common (~> 0.21) opentelemetry-registry (~> 0.1) - opentelemetry-instrumentation-concurrent_ruby (0.22.0) - opentelemetry-api (~> 1.0) - opentelemetry-instrumentation-base (~> 0.23.0) - opentelemetry-instrumentation-excon (0.24.0) - opentelemetry-api (~> 1.0) - opentelemetry-instrumentation-base (~> 0.23.0) - opentelemetry-instrumentation-faraday (0.28.0) - opentelemetry-api (~> 1.0) - opentelemetry-instrumentation-base (~> 0.23.0) - opentelemetry-instrumentation-http (0.25.1) - opentelemetry-api (~> 1.0) - opentelemetry-instrumentation-base (~> 0.23.0) - opentelemetry-instrumentation-http_client (0.24.0) - opentelemetry-api (~> 1.0) - opentelemetry-instrumentation-base (~> 0.23.0) - opentelemetry-instrumentation-net_http (0.24.0) - opentelemetry-api (~> 1.0) - opentelemetry-instrumentation-base (~> 0.23.0) - opentelemetry-instrumentation-pg (0.30.1) - opentelemetry-api (~> 1.0) + opentelemetry-instrumentation-concurrent_ruby (0.23.1) + opentelemetry-instrumentation-base (~> 0.24) + opentelemetry-instrumentation-excon (0.25.2) + opentelemetry-instrumentation-base (~> 0.24) + opentelemetry-instrumentation-faraday (0.29.1) + opentelemetry-instrumentation-base (~> 0.24) + opentelemetry-instrumentation-http (0.26.1) + opentelemetry-instrumentation-base (~> 0.24) + opentelemetry-instrumentation-http_client (0.25.1) + opentelemetry-instrumentation-base (~> 0.24) + opentelemetry-instrumentation-net_http (0.25.1) + opentelemetry-instrumentation-base (~> 0.24) + opentelemetry-instrumentation-pg (0.31.1) opentelemetry-helpers-sql opentelemetry-helpers-sql-obfuscation - opentelemetry-instrumentation-base (~> 0.23.0) - opentelemetry-instrumentation-rack (0.27.1) - opentelemetry-api (~> 1.0) - opentelemetry-instrumentation-base (~> 0.23.0) - opentelemetry-instrumentation-rails (0.37.0) - opentelemetry-api (~> 1.0) - opentelemetry-instrumentation-action_mailer (~> 0.4.0) - opentelemetry-instrumentation-action_pack (~> 0.13.0) - opentelemetry-instrumentation-action_view (~> 0.9.0) - opentelemetry-instrumentation-active_job (~> 0.8.0) - opentelemetry-instrumentation-active_record (~> 0.9.0) - opentelemetry-instrumentation-active_storage (~> 0.1.0) - opentelemetry-instrumentation-active_support (~> 0.8.0) - opentelemetry-instrumentation-base (~> 0.23.0) - opentelemetry-instrumentation-concurrent_ruby (~> 0.22.0) - opentelemetry-instrumentation-redis (0.26.1) - opentelemetry-api (~> 1.0) - opentelemetry-instrumentation-base (~> 0.23.0) - opentelemetry-instrumentation-sidekiq (0.26.1) - opentelemetry-api (~> 1.0) - opentelemetry-instrumentation-base (~> 0.23.0) + opentelemetry-instrumentation-base (~> 0.24) + opentelemetry-instrumentation-rack (0.28.2) + opentelemetry-instrumentation-base (~> 0.24) + opentelemetry-instrumentation-rails (0.38.0) + opentelemetry-instrumentation-action_mailer (~> 0.4) + opentelemetry-instrumentation-action_pack (~> 0.13) + opentelemetry-instrumentation-action_view (~> 0.9) + opentelemetry-instrumentation-active_job (~> 0.8) + opentelemetry-instrumentation-active_record (~> 0.9) + opentelemetry-instrumentation-active_storage (~> 0.1) + opentelemetry-instrumentation-active_support (~> 0.8) + opentelemetry-instrumentation-concurrent_ruby (~> 0.22) + opentelemetry-instrumentation-redis (0.27.1) + opentelemetry-instrumentation-base (~> 0.24) + opentelemetry-instrumentation-sidekiq (0.27.1) + opentelemetry-instrumentation-base (~> 0.24) opentelemetry-registry (0.4.0) opentelemetry-api (~> 1.1) - opentelemetry-sdk (1.9.0) + opentelemetry-sdk (1.10.0) opentelemetry-api (~> 1.1) opentelemetry-common (~> 0.20) opentelemetry-registry (~> 0.2) @@ -615,7 +592,7 @@ GEM playwright-ruby-client (1.55.0) concurrent-ruby (>= 1.1.6) mime-types (>= 3.0) - pp (0.6.2) + pp (0.6.3) prettyprint premailer (1.27.0) addressable @@ -643,7 +620,7 @@ GEM activesupport (>= 3.0.0) raabro (1.4.0) racc (1.8.1) - rack (3.2.1) + rack (3.2.3) rack-attack (6.7.0) rack (>= 1.0, < 4) rack-cors (3.0.0) @@ -713,9 +690,10 @@ GEM readline (~> 0.0) rdf-normalize (0.7.0) rdf (~> 3.3) - rdoc (6.14.2) + rdoc (6.15.0) erb psych (>= 4.0.0) + tsort readline (0.0.4) reline redcarpet (3.6.1) @@ -732,7 +710,7 @@ GEM railties (>= 5.2) rexml (3.4.4) rotp (6.3.0) - rouge (4.6.0) + rouge (4.6.1) rpam2 (4.0.2) rqrcode (3.1.0) chunky_png (~> 1.0) @@ -765,7 +743,7 @@ GEM rspec-expectations (~> 3.0) rspec-mocks (~> 3.0) sidekiq (>= 5, < 9) - rspec-support (3.13.4) + rspec-support (3.13.6) rubocop (1.81.1) json (~> 2.3) language_server-protocol (~> 3.17.0.2) @@ -826,7 +804,7 @@ GEM securerandom (0.4.1) shoulda-matchers (6.5.0) activesupport (>= 5.2.0) - sidekiq (8.0.7) + sidekiq (8.0.8) connection_pool (>= 2.5.0) json (>= 2.9.0) logger (>= 1.6.2) @@ -859,7 +837,7 @@ GEM stoplight (5.3.8) zeitwerk stringio (3.1.7) - strong_migrations (2.5.0) + strong_migrations (2.5.1) activerecord (>= 7.1) swd (2.0.3) activesupport (>= 3) @@ -904,7 +882,7 @@ GEM unicode-display_width (3.2.0) unicode-emoji (~> 4.1) unicode-emoji (4.1.0) - uri (1.0.3) + uri (1.0.4) useragent (0.16.11) validate_url (1.0.15) activemodel (>= 3.0.0) @@ -1030,20 +1008,20 @@ DEPENDENCIES omniauth-saml (~> 2.0) omniauth_openid_connect (~> 0.8.0) opentelemetry-api (~> 1.7.0) - opentelemetry-exporter-otlp (~> 0.30.0) - opentelemetry-instrumentation-active_job (~> 0.8.0) - opentelemetry-instrumentation-active_model_serializers (~> 0.22.0) - opentelemetry-instrumentation-concurrent_ruby (~> 0.22.0) - opentelemetry-instrumentation-excon (~> 0.24.0) - opentelemetry-instrumentation-faraday (~> 0.28.0) - opentelemetry-instrumentation-http (~> 0.25.0) - opentelemetry-instrumentation-http_client (~> 0.24.0) - opentelemetry-instrumentation-net_http (~> 0.24.0) - opentelemetry-instrumentation-pg (~> 0.30.0) - opentelemetry-instrumentation-rack (~> 0.27.0) - opentelemetry-instrumentation-rails (~> 0.37.0) - opentelemetry-instrumentation-redis (~> 0.26.0) - opentelemetry-instrumentation-sidekiq (~> 0.26.0) + opentelemetry-exporter-otlp (~> 0.31.0) + opentelemetry-instrumentation-active_job (~> 0.9.0) + opentelemetry-instrumentation-active_model_serializers (~> 0.23.0) + opentelemetry-instrumentation-concurrent_ruby (~> 0.23.0) + opentelemetry-instrumentation-excon (~> 0.25.0) + opentelemetry-instrumentation-faraday (~> 0.29.0) + opentelemetry-instrumentation-http (~> 0.26.0) + opentelemetry-instrumentation-http_client (~> 0.25.0) + opentelemetry-instrumentation-net_http (~> 0.25.0) + opentelemetry-instrumentation-pg (~> 0.31.0) + opentelemetry-instrumentation-rack (~> 0.28.0) + opentelemetry-instrumentation-rails (~> 0.38.0) + opentelemetry-instrumentation-redis (~> 0.27.0) + opentelemetry-instrumentation-sidekiq (~> 0.27.0) opentelemetry-sdk (~> 1.4) ox (~> 2.14) parslet @@ -1109,4 +1087,4 @@ RUBY VERSION ruby 3.4.1p0 BUNDLED WITH - 2.7.1 + 2.7.2 diff --git a/app/controllers/admin/dashboard_controller.rb b/app/controllers/admin/dashboard_controller.rb index 5b0867dcfba..fe314daeca6 100644 --- a/app/controllers/admin/dashboard_controller.rb +++ b/app/controllers/admin/dashboard_controller.rb @@ -9,10 +9,16 @@ module Admin @pending_appeals_count = Appeal.pending.async_count @pending_reports_count = Report.unresolved.async_count - @pending_tags_count = Tag.pending_review.async_count + @pending_tags_count = pending_tags.async_count @pending_users_count = User.pending.async_count @system_checks = Admin::SystemCheck.perform(current_user) @time_period = (29.days.ago.to_date...Time.now.utc.to_date) end + + private + + def pending_tags + ::Trends::TagFilter.new(status: :pending_review).results + end end end diff --git a/app/controllers/api/v1/timelines/base_controller.rb b/app/controllers/api/v1/timelines/base_controller.rb index 1dba4a5bb21..e79eba79ee5 100644 --- a/app/controllers/api/v1/timelines/base_controller.rb +++ b/app/controllers/api/v1/timelines/base_controller.rb @@ -3,14 +3,8 @@ class Api::V1::Timelines::BaseController < Api::BaseController after_action :insert_pagination_headers, unless: -> { @statuses.empty? } - before_action :require_user!, if: :require_auth? - private - def require_auth? - !Setting.timeline_preview - end - def pagination_collection @statuses end diff --git a/app/controllers/api/v1/timelines/home_controller.rb b/app/controllers/api/v1/timelines/home_controller.rb index b8384a13687..a07faae7208 100644 --- a/app/controllers/api/v1/timelines/home_controller.rb +++ b/app/controllers/api/v1/timelines/home_controller.rb @@ -3,8 +3,8 @@ class Api::V1::Timelines::HomeController < Api::V1::Timelines::BaseController include AsyncRefreshesConcern - before_action -> { doorkeeper_authorize! :read, :'read:statuses' }, only: [:show] - before_action :require_user!, only: [:show] + before_action -> { doorkeeper_authorize! :read, :'read:statuses' } + before_action :require_user! PERMITTED_PARAMS = %i(local limit).freeze diff --git a/app/controllers/api/v1/timelines/link_controller.rb b/app/controllers/api/v1/timelines/link_controller.rb index 37ed084f062..9e6ddd69243 100644 --- a/app/controllers/api/v1/timelines/link_controller.rb +++ b/app/controllers/api/v1/timelines/link_controller.rb @@ -1,6 +1,6 @@ # frozen_string_literal: true -class Api::V1::Timelines::LinkController < Api::V1::Timelines::BaseController +class Api::V1::Timelines::LinkController < Api::V1::Timelines::TopicController before_action -> { authorize_if_got_token! :read, :'read:statuses' } before_action :set_preview_card before_action :set_statuses diff --git a/app/controllers/api/v1/timelines/public_controller.rb b/app/controllers/api/v1/timelines/public_controller.rb index 029e8fc2c13..670c3b02b6b 100644 --- a/app/controllers/api/v1/timelines/public_controller.rb +++ b/app/controllers/api/v1/timelines/public_controller.rb @@ -2,6 +2,7 @@ class Api::V1::Timelines::PublicController < Api::V1::Timelines::BaseController before_action -> { authorize_if_got_token! :read, :'read:statuses' } + before_action :require_user!, if: :require_auth? PERMITTED_PARAMS = %i(local remote limit only_media).freeze @@ -13,6 +14,16 @@ class Api::V1::Timelines::PublicController < Api::V1::Timelines::BaseController private + def require_auth? + if truthy_param?(:local) + Setting.local_live_feed_access != 'public' + elsif truthy_param?(:remote) + Setting.remote_live_feed_access != 'public' + else + Setting.local_live_feed_access != 'public' || Setting.remote_live_feed_access != 'public' + end + end + def load_statuses preloaded_public_statuses_page end diff --git a/app/controllers/api/v1/timelines/tag_controller.rb b/app/controllers/api/v1/timelines/tag_controller.rb index 2b097aab0f8..dc3c6a72157 100644 --- a/app/controllers/api/v1/timelines/tag_controller.rb +++ b/app/controllers/api/v1/timelines/tag_controller.rb @@ -1,6 +1,6 @@ # frozen_string_literal: true -class Api::V1::Timelines::TagController < Api::V1::Timelines::BaseController +class Api::V1::Timelines::TagController < Api::V1::Timelines::TopicController before_action -> { authorize_if_got_token! :read, :'read:statuses' } before_action :load_tag @@ -14,10 +14,6 @@ class Api::V1::Timelines::TagController < Api::V1::Timelines::BaseController private - def require_auth? - !Setting.timeline_preview - end - def load_tag @tag = Tag.find_normalized(params[:id]) end diff --git a/app/controllers/api/v1/timelines/topic_controller.rb b/app/controllers/api/v1/timelines/topic_controller.rb new file mode 100644 index 00000000000..6faf54f7083 --- /dev/null +++ b/app/controllers/api/v1/timelines/topic_controller.rb @@ -0,0 +1,17 @@ +# frozen_string_literal: true + +class Api::V1::Timelines::TopicController < Api::V1::Timelines::BaseController + before_action :require_user!, if: :require_auth? + + private + + def require_auth? + if truthy_param?(:local) + Setting.local_topic_feed_access != 'public' + elsif truthy_param?(:remote) + Setting.remote_topic_feed_access != 'public' + else + Setting.local_topic_feed_access != 'public' || Setting.remote_topic_feed_access != 'public' + end + end +end diff --git a/app/controllers/auth/registrations_controller.rb b/app/controllers/auth/registrations_controller.rb index fc430544fbe..780c0be3191 100644 --- a/app/controllers/auth/registrations_controller.rb +++ b/app/controllers/auth/registrations_controller.rb @@ -89,7 +89,7 @@ class Auth::RegistrationsController < Devise::RegistrationsController end def check_enabled_registrations - redirect_to root_path unless allowed_registration?(request.remote_ip, @invite) + redirect_to new_user_session_path, alert: I18n.t('devise.failure.closed_registrations', email: Setting.site_contact_email) unless allowed_registration?(request.remote_ip, @invite) end def invite_code diff --git a/app/controllers/concerns/async_refreshes_concern.rb b/app/controllers/concerns/async_refreshes_concern.rb index 29122e16b5e..2d0e9ff4ff4 100644 --- a/app/controllers/concerns/async_refreshes_concern.rb +++ b/app/controllers/concerns/async_refreshes_concern.rb @@ -6,6 +6,9 @@ module AsyncRefreshesConcern def add_async_refresh_header(async_refresh, retry_seconds: 3) return unless async_refresh.running? - response.headers['Mastodon-Async-Refresh'] = "id=\"#{async_refresh.id}\", retry=#{retry_seconds}" + value = "id=\"#{async_refresh.id}\", retry=#{retry_seconds}" + value += ", result_count=#{async_refresh.result_count}" unless async_refresh.result_count.nil? + + response.headers['Mastodon-Async-Refresh'] = value end end diff --git a/app/helpers/home_helper.rb b/app/helpers/home_helper.rb index 79e28c983af..59bc06031ee 100644 --- a/app/helpers/home_helper.rb +++ b/app/helpers/home_helper.rb @@ -21,7 +21,13 @@ module HomeHelper end end else - link_to(path || ActivityPub::TagManager.instance.url_for(account), class: 'account__display-name') do + account_url = if account.suspended? + ActivityPub::TagManager.instance.url_for(account) + else + web_url("@#{account.pretty_acct}") + end + + link_to(path || account_url, class: 'account__display-name') do content_tag(:div, class: 'account__avatar-wrapper') do image_tag(full_asset_url(current_account&.user&.setting_auto_play_gif ? account.avatar_original_url : account.avatar_static_url), class: 'account__avatar', width: 46, height: 46) end + diff --git a/app/helpers/statuses_helper.rb b/app/helpers/statuses_helper.rb index 9cf64d09b4d..68e9b130478 100644 --- a/app/helpers/statuses_helper.rb +++ b/app/helpers/statuses_helper.rb @@ -57,6 +57,20 @@ module StatusesHelper components.compact_blank.join("\n\n") end + # This logic should be kept in sync with https://github.com/mastodon/mastodon/blob/425311e1d95c8a64ddac6c724fca247b8b893a82/app/javascript/mastodon/features/status/components/card.jsx#L160 + def preview_card_aspect_ratio_classname(preview_card) + interactive = preview_card.type == 'video' + large_image = (preview_card.image.present? && preview_card.width > preview_card.height) || interactive + + if large_image && interactive + 'status-card__image--video' + elsif large_image + 'status-card__image--large' + else + 'status-card__image--normal' + end + end + def visibility_icon(status) VISIBLITY_ICONS[status.visibility.to_sym] end diff --git a/app/javascript/entrypoints/admin.tsx b/app/javascript/entrypoints/admin.tsx index a60778f0c04..af9309d342c 100644 --- a/app/javascript/entrypoints/admin.tsx +++ b/app/javascript/entrypoints/admin.tsx @@ -1,6 +1,7 @@ import { createRoot } from 'react-dom/client'; import Rails from '@rails/ujs'; +import { decode, ValidationError } from 'blurhash'; import ready from '../mastodon/ready'; @@ -362,6 +363,46 @@ ready(() => { document.querySelectorAll('[data-admin-component]').forEach((element) => { void mountReactComponent(element); }); + + document + .querySelectorAll('canvas[data-blurhash]') + .forEach((canvas) => { + const blurhash = canvas.dataset.blurhash; + if (blurhash) { + try { + // decode returns a Uint8ClampedArray not Uint8ClampedArray + const pixels = decode( + blurhash, + 32, + 32, + ) as Uint8ClampedArray; + const ctx = canvas.getContext('2d'); + const imageData = new ImageData(pixels, 32, 32); + + ctx?.putImageData(imageData, 0, 0); + } catch (err) { + if (err instanceof ValidationError) { + // ignore blurhash validation errors + return; + } + + throw err; + } + } + }); + + document + .querySelectorAll('.preview-card') + .forEach((previewCard) => { + const spoilerButton = previewCard.querySelector('.spoiler-button'); + if (!spoilerButton) { + return; + } + + spoilerButton.addEventListener('click', () => { + previewCard.classList.toggle('preview-card--image-visible'); + }); + }); }).catch((reason: unknown) => { throw reason; }); diff --git a/app/javascript/entrypoints/public.tsx b/app/javascript/entrypoints/public.tsx index dd1956446da..fea3eb0d792 100644 --- a/app/javascript/entrypoints/public.tsx +++ b/app/javascript/entrypoints/public.tsx @@ -70,7 +70,7 @@ function loaded() { }; document.querySelectorAll('.emojify').forEach((content) => { - content.innerHTML = emojify(content.innerHTML); + content.innerHTML = emojify(content.innerHTML, {}, true); // Force emojify as public doesn't load the new emoji system. }); document diff --git a/app/javascript/mastodon/actions/compose_typed.ts b/app/javascript/mastodon/actions/compose_typed.ts index 7f70a1bd481..0f9bf5cfb3c 100644 --- a/app/javascript/mastodon/actions/compose_typed.ts +++ b/app/javascript/mastodon/actions/compose_typed.ts @@ -4,6 +4,7 @@ import { createAction } from '@reduxjs/toolkit'; import type { List as ImmutableList, Map as ImmutableMap } from 'immutable'; import { apiUpdateMedia } from 'mastodon/api/compose'; +import { apiGetSearch } from 'mastodon/api/search'; import type { ApiMediaAttachmentJSON } from 'mastodon/api_types/media_attachments'; import type { MediaAttachment } from 'mastodon/models/media_attachment'; import { @@ -16,9 +17,14 @@ import type { Status } from '../models/status'; import { showAlert } from './alerts'; import { focusCompose } from './compose'; +import { importFetchedStatuses } from './importer'; import { openModal } from './modal'; const messages = defineMessages({ + quoteErrorEdit: { + id: 'quote_error.edit', + defaultMessage: 'Quotes cannot be added when editing a post.', + }, quoteErrorUpload: { id: 'quote_error.upload', defaultMessage: 'Quoting is not allowed with media attachments.', @@ -122,7 +128,9 @@ export const quoteComposeByStatus = createAppThunk( false, ); - if (composeState.get('poll')) { + if (composeState.get('id')) { + dispatch(showAlert({ message: messages.quoteErrorEdit })); + } else if (composeState.get('poll')) { dispatch(showAlert({ message: messages.quoteErrorPoll })); } else if ( composeState.get('is_uploading') || @@ -165,6 +173,42 @@ export const quoteComposeById = createAppThunk( }, ); +export const pasteLinkCompose = createDataLoadingThunk( + 'compose/pasteLink', + async ({ url }: { url: string }) => { + return await apiGetSearch({ + q: url, + type: 'statuses', + resolve: true, + limit: 2, + }); + }, + (data, { dispatch, getState }) => { + const composeState = getState().compose; + + if ( + composeState.get('quoted_status_id') || + composeState.get('is_submitting') || + composeState.get('poll') || + composeState.get('is_uploading') || + composeState.get('id') + ) + return; + + dispatch(importFetchedStatuses(data.statuses)); + + if ( + data.statuses.length === 1 && + data.statuses[0] && + ['automatic', 'manual'].includes( + data.statuses[0].quote_approval?.current_user ?? 'denied', + ) + ) { + dispatch(quoteComposeById(data.statuses[0].id)); + } + }, +); + export const quoteComposeCancel = createAction('compose/quoteComposeCancel'); export const setComposeQuotePolicy = createAction( diff --git a/app/javascript/mastodon/actions/statuses_typed.ts b/app/javascript/mastodon/actions/statuses_typed.ts index f34d9f2bc37..be9bec71bb3 100644 --- a/app/javascript/mastodon/actions/statuses_typed.ts +++ b/app/javascript/mastodon/actions/statuses_typed.ts @@ -9,8 +9,9 @@ import { importFetchedStatuses } from './importer'; export const fetchContext = createDataLoadingThunk( 'status/context', - ({ statusId }: { statusId: string }) => apiGetContext(statusId), - ({ context, refresh }, { dispatch }) => { + ({ statusId }: { statusId: string; prefetchOnly?: boolean }) => + apiGetContext(statusId), + ({ context, refresh }, { dispatch, actionArg: { prefetchOnly = false } }) => { const statuses = context.ancestors.concat(context.descendants); dispatch(importFetchedStatuses(statuses)); @@ -18,6 +19,7 @@ export const fetchContext = createDataLoadingThunk( return { context, refresh, + prefetchOnly, }; }, ); @@ -26,6 +28,14 @@ export const completeContextRefresh = createAction<{ statusId: string }>( 'status/context/complete', ); +export const showPendingReplies = createAction<{ statusId: string }>( + 'status/context/showPendingReplies', +); + +export const clearPendingReplies = createAction<{ statusId: string }>( + 'status/context/clearPendingReplies', +); + export const setStatusQuotePolicy = createDataLoadingThunk( 'status/setQuotePolicy', ({ statusId, policy }: { statusId: string; policy: ApiQuotePolicy }) => { diff --git a/app/javascript/mastodon/api_types/announcements.ts b/app/javascript/mastodon/api_types/announcements.ts new file mode 100644 index 00000000000..03e8922d8f1 --- /dev/null +++ b/app/javascript/mastodon/api_types/announcements.ts @@ -0,0 +1,28 @@ +// See app/serializers/rest/announcement_serializer.rb + +import type { ApiCustomEmojiJSON } from './custom_emoji'; +import type { ApiMentionJSON, ApiStatusJSON, ApiTagJSON } from './statuses'; + +export interface ApiAnnouncementJSON { + id: string; + content: string; + starts_at: null | string; + ends_at: null | string; + all_day: boolean; + published_at: string; + updated_at: null | string; + read: boolean; + mentions: ApiMentionJSON[]; + statuses: ApiStatusJSON[]; + tags: ApiTagJSON[]; + emojis: ApiCustomEmojiJSON[]; + reactions: ApiAnnouncementReactionJSON[]; +} + +export interface ApiAnnouncementReactionJSON { + name: string; + count: number; + me: boolean; + url?: string; + static_url?: string; +} diff --git a/app/javascript/mastodon/components/account/index.tsx b/app/javascript/mastodon/components/account/index.tsx index 8397695a443..3aebedc9497 100644 --- a/app/javascript/mastodon/components/account/index.tsx +++ b/app/javascript/mastodon/components/account/index.tsx @@ -5,6 +5,7 @@ import { defineMessages, useIntl, FormattedMessage } from 'react-intl'; import classNames from 'classnames'; import { Link } from 'react-router-dom'; +import { EmojiHTML } from '@/mastodon/components/emoji/html'; import MoreHorizIcon from '@/material-icons/400-24px/more_horiz.svg?react'; import { blockAccount, @@ -331,9 +332,10 @@ export const Account: React.FC = ({ {account && withBio && (account.note.length > 0 ? ( -
) : (
diff --git a/app/javascript/mastodon/components/account_bio.tsx b/app/javascript/mastodon/components/account_bio.tsx index b5ff686f864..e87ae654fdf 100644 --- a/app/javascript/mastodon/components/account_bio.tsx +++ b/app/javascript/mastodon/components/account_bio.tsx @@ -7,8 +7,8 @@ import { useLinks } from 'mastodon/hooks/useLinks'; import { useAppSelector } from '../store'; import { isModernEmojiEnabled } from '../utils/environment'; -import { AnimateEmojiProvider } from './emoji/context'; import { EmojiHTML } from './emoji/html'; +import { useElementHandledLink } from './status/handled_link'; interface AccountBioProps { className: string; @@ -24,19 +24,29 @@ export const AccountBio: React.FC = ({ const handleClick = useLinks(showDropdown); const handleNodeChange = useCallback( (node: HTMLDivElement | null) => { - if (!showDropdown || !node || node.childNodes.length === 0) { + if ( + !showDropdown || + !node || + node.childNodes.length === 0 || + isModernEmojiEnabled() + ) { return; } addDropdownToHashtags(node, accountId); }, [showDropdown, accountId], ); + + const htmlHandlers = useElementHandledLink({ + hashtagAccountId: showDropdown ? accountId : undefined, + }); + const note = useAppSelector((state) => { const account = state.accounts.get(accountId); if (!account) { return ''; } - return isModernEmojiEnabled() ? account.note : account.note_emojified; + return account.note_emojified; }); const extraEmojis = useAppSelector((state) => { const account = state.accounts.get(accountId); @@ -48,13 +58,14 @@ export const AccountBio: React.FC = ({ } return ( - - - + {...htmlHandlers} + /> ); }; diff --git a/app/javascript/mastodon/components/account_fields.tsx b/app/javascript/mastodon/components/account_fields.tsx index 4ce55f7896a..dd17b89d865 100644 --- a/app/javascript/mastodon/components/account_fields.tsx +++ b/app/javascript/mastodon/components/account_fields.tsx @@ -1,42 +1,70 @@ +import { useIntl } from 'react-intl'; + import classNames from 'classnames'; import CheckIcon from '@/material-icons/400-24px/check.svg?react'; import { Icon } from 'mastodon/components/icon'; -import { useLinks } from 'mastodon/hooks/useLinks'; import type { Account } from 'mastodon/models/account'; -export const AccountFields: React.FC<{ - fields: Account['fields']; - limit: number; -}> = ({ fields, limit = -1 }) => { - const handleClick = useLinks(); +import { CustomEmojiProvider } from './emoji/context'; +import { EmojiHTML } from './emoji/html'; +import { useElementHandledLink } from './status/handled_link'; + +export const AccountFields: React.FC> = ({ + fields, + emojis, +}) => { + const intl = useIntl(); + const htmlHandlers = useElementHandledLink(); if (fields.size === 0) { return null; } return ( -
- {fields.take(limit).map((pair, i) => ( -
-
+ {fields.map((pair, i) => ( +
+ -
- {pair.get('verified_at') && ( - - )} - + {pair.verified_at && ( + + + + )}{' '} +
))} -
+ ); }; + +const dateFormatOptions: Intl.DateTimeFormatOptions = { + month: 'short', + day: 'numeric', + year: 'numeric', + hour: '2-digit', + minute: '2-digit', +}; diff --git a/app/javascript/mastodon/components/autosuggest_textarea.jsx b/app/javascript/mastodon/components/autosuggest_textarea.jsx index de5accc4b28..68cf9e17fc9 100644 --- a/app/javascript/mastodon/components/autosuggest_textarea.jsx +++ b/app/javascript/mastodon/components/autosuggest_textarea.jsx @@ -150,10 +150,7 @@ const AutosuggestTextarea = forwardRef(({ }, [suggestions, onSuggestionSelected, textareaRef]); const handlePaste = useCallback((e) => { - if (e.clipboardData && e.clipboardData.files.length === 1) { - onPaste(e.clipboardData.files); - e.preventDefault(); - } + onPaste(e); }, [onPaste]); // Show the suggestions again whenever they change and the textarea is focused diff --git a/app/javascript/mastodon/components/content_warning.tsx b/app/javascript/mastodon/components/content_warning.tsx index 6bcae1d6f73..a407ec146e3 100644 --- a/app/javascript/mastodon/components/content_warning.tsx +++ b/app/javascript/mastodon/components/content_warning.tsx @@ -1,15 +1,38 @@ +import type { List } from 'immutable'; + +import type { CustomEmoji } from '../models/custom_emoji'; +import type { Status } from '../models/status'; + +import { EmojiHTML } from './emoji/html'; import { StatusBanner, BannerVariant } from './status_banner'; export const ContentWarning: React.FC<{ - text: string; + status: Status; expanded?: boolean; onClick?: () => void; -}> = ({ text, expanded, onClick }) => ( - - - -); +}> = ({ status, expanded, onClick }) => { + const hasSpoiler = !!status.get('spoiler_text'); + if (!hasSpoiler) { + return null; + } + + const text = + status.getIn(['translation', 'spoilerHtml']) || status.get('spoilerHtml'); + if (typeof text !== 'string' || text.length === 0) { + return null; + } + + return ( + + } + /> + + ); +}; diff --git a/app/javascript/mastodon/components/display_name/no-domain.tsx b/app/javascript/mastodon/components/display_name/no-domain.tsx index bb5a0936593..ee6e84050c3 100644 --- a/app/javascript/mastodon/components/display_name/no-domain.tsx +++ b/app/javascript/mastodon/components/display_name/no-domain.tsx @@ -2,8 +2,6 @@ import type { ComponentPropsWithoutRef, FC } from 'react'; import classNames from 'classnames'; -import { isModernEmojiEnabled } from '@/mastodon/utils/environment'; - import { AnimateEmojiProvider } from '../emoji/context'; import { EmojiHTML } from '../emoji/html'; import { Skeleton } from '../skeleton'; @@ -24,11 +22,7 @@ export const DisplayNameWithoutDomain: FC< {account ? ( diff --git a/app/javascript/mastodon/components/display_name/simple.tsx b/app/javascript/mastodon/components/display_name/simple.tsx index 375f4932b2e..29d9ee217b1 100644 --- a/app/javascript/mastodon/components/display_name/simple.tsx +++ b/app/javascript/mastodon/components/display_name/simple.tsx @@ -1,7 +1,5 @@ import type { ComponentPropsWithoutRef, FC } from 'react'; -import { isModernEmojiEnabled } from '@/mastodon/utils/environment'; - import { EmojiHTML } from '../emoji/html'; import type { DisplayNameProps } from './index'; @@ -19,11 +17,7 @@ export const DisplayNameSimple: FC< diff --git a/app/javascript/mastodon/components/emoji/emoji.stories.tsx b/app/javascript/mastodon/components/emoji/emoji.stories.tsx new file mode 100644 index 00000000000..a5e283158d6 --- /dev/null +++ b/app/javascript/mastodon/components/emoji/emoji.stories.tsx @@ -0,0 +1,56 @@ +import type { ComponentProps } from 'react'; + +import type { Meta, StoryObj } from '@storybook/react-vite'; + +import { importCustomEmojiData } from '@/mastodon/features/emoji/loader'; + +import { Emoji } from './index'; + +type EmojiProps = ComponentProps & { state: string }; + +const meta = { + title: 'Components/Emoji', + component: Emoji, + args: { + code: '🖤', + state: 'auto', + }, + argTypes: { + code: { + name: 'Emoji', + }, + state: { + control: { + type: 'select', + labels: { + auto: 'Auto', + native: 'Native', + twemoji: 'Twemoji', + }, + }, + options: ['auto', 'native', 'twemoji'], + name: 'Emoji Style', + mapping: { + auto: { meta: { emoji_style: 'auto' } }, + native: { meta: { emoji_style: 'native' } }, + twemoji: { meta: { emoji_style: 'twemoji' } }, + }, + }, + }, + render(args) { + void importCustomEmojiData(); + return ; + }, +} satisfies Meta; + +export default meta; + +type Story = StoryObj; + +export const Default: Story = {}; + +export const CustomEmoji: Story = { + args: { + code: ':custom:', + }, +}; diff --git a/app/javascript/mastodon/components/emoji/html.tsx b/app/javascript/mastodon/components/emoji/html.tsx index a6ecc869c1d..628385f6493 100644 --- a/app/javascript/mastodon/components/emoji/html.tsx +++ b/app/javascript/mastodon/components/emoji/html.tsx @@ -1,60 +1,89 @@ import { useMemo } from 'react'; -import type { ComponentPropsWithoutRef, ElementType } from 'react'; import classNames from 'classnames'; import type { CustomEmojiMapArg } from '@/mastodon/features/emoji/types'; import { isModernEmojiEnabled } from '@/mastodon/utils/environment'; +import type { + OnAttributeHandler, + OnElementHandler, +} from '@/mastodon/utils/html'; import { htmlStringToComponents } from '@/mastodon/utils/html'; +import { polymorphicForwardRef } from '@/types/polymorphic'; import { AnimateEmojiProvider, CustomEmojiProvider } from './context'; import { textToEmojis } from './index'; -type EmojiHTMLProps = Omit< - ComponentPropsWithoutRef, - 'dangerouslySetInnerHTML' | 'className' -> & { +export interface EmojiHTMLProps { htmlString: string; extraEmojis?: CustomEmojiMapArg; - as?: Element; className?: string; -}; + onElement?: OnElementHandler; + onAttribute?: OnAttributeHandler; +} -export const ModernEmojiHTML = ({ - extraEmojis, - htmlString, - as: asProp = 'div', // Rename for syntax highlighting - shallow, - className = '', - ...props -}: EmojiHTMLProps) => { - const contents = useMemo( - () => htmlStringToComponents(htmlString, { onText: textToEmojis }), - [htmlString], - ); +export const ModernEmojiHTML = polymorphicForwardRef<'div', EmojiHTMLProps>( + ( + { + extraEmojis, + htmlString, + as: asProp = 'div', // Rename for syntax highlighting + className = '', + onElement, + onAttribute, + ...props + }, + ref, + ) => { + const contents = useMemo( + () => + htmlStringToComponents(htmlString, { + onText: textToEmojis, + onElement, + onAttribute, + }), + [htmlString, onAttribute, onElement], + ); - return ( - - - {contents} - - - ); -}; + return ( + + + {contents} + + + ); + }, +); +ModernEmojiHTML.displayName = 'ModernEmojiHTML'; -export const LegacyEmojiHTML = ( - props: EmojiHTMLProps, -) => { - const { as: asElement, htmlString, extraEmojis, className, ...rest } = props; - const Wrapper = asElement ?? 'div'; - return ( - - ); -}; +export const LegacyEmojiHTML = polymorphicForwardRef<'div', EmojiHTMLProps>( + (props, ref) => { + const { + as: asElement, + htmlString, + extraEmojis, + className, + onElement, + onAttribute, + ...rest + } = props; + const Wrapper = asElement ?? 'div'; + return ( + + ); + }, +); +LegacyEmojiHTML.displayName = 'LegacyEmojiHTML'; export const EmojiHTML = isModernEmojiEnabled() ? ModernEmojiHTML diff --git a/app/javascript/mastodon/components/emoji/index.tsx b/app/javascript/mastodon/components/emoji/index.tsx index e070eb30dd8..0dff8314ffc 100644 --- a/app/javascript/mastodon/components/emoji/index.tsx +++ b/app/javascript/mastodon/components/emoji/index.tsx @@ -2,7 +2,7 @@ import type { FC } from 'react'; import { useContext, useEffect, useState } from 'react'; import { EMOJI_TYPE_CUSTOM } from '@/mastodon/features/emoji/constants'; -import { useEmojiAppState } from '@/mastodon/features/emoji/hooks'; +import { useEmojiAppState } from '@/mastodon/features/emoji/mode'; import { unicodeHexToUrl } from '@/mastodon/features/emoji/normalize'; import { isStateLoaded, diff --git a/app/javascript/mastodon/components/featured_carousel.tsx b/app/javascript/mastodon/components/featured_carousel.tsx index 195331ef9f5..df64c43b421 100644 --- a/app/javascript/mastodon/components/featured_carousel.tsx +++ b/app/javascript/mastodon/components/featured_carousel.tsx @@ -20,7 +20,7 @@ import { useDrag } from '@use-gesture/react'; import { expandAccountFeaturedTimeline } from '@/mastodon/actions/timelines'; import { Icon } from '@/mastodon/components/icon'; import { IconButton } from '@/mastodon/components/icon_button'; -import StatusContainer from '@/mastodon/containers/status_container'; +import { StatusQuoteManager } from '@/mastodon/components/status_quoted'; import { usePrevious } from '@/mastodon/hooks/usePrevious'; import { useAppDispatch, useAppSelector } from '@/mastodon/store'; import ChevronLeftIcon from '@/material-icons/400-24px/chevron_left.svg?react'; @@ -218,12 +218,7 @@ const FeaturedCarouselItem: React.FC< ref={handleRef} {...props} > - + ); }; diff --git a/app/javascript/mastodon/components/hover_card_account.tsx b/app/javascript/mastodon/components/hover_card_account.tsx index a5a5e4c9575..471d4884157 100644 --- a/app/javascript/mastodon/components/hover_card_account.tsx +++ b/app/javascript/mastodon/components/hover_card_account.tsx @@ -23,6 +23,8 @@ import { domain } from 'mastodon/initial_state'; import { getAccountHidden } from 'mastodon/selectors/accounts'; import { useAppSelector, useAppDispatch } from 'mastodon/store'; +import { useLinks } from '../hooks/useLinks'; + export const HoverCardAccount = forwardRef< HTMLDivElement, { accountId?: string } @@ -64,6 +66,8 @@ export const HoverCardAccount = forwardRef< !isMutual && !isFollower; + const handleClick = useLinks(); + return (
- + +
+ +
+ {note && note.length > 0 && (
diff --git a/app/javascript/mastodon/components/html_block/html_block.stories.tsx b/app/javascript/mastodon/components/html_block/html_block.stories.tsx index 9c104ba45cb..6fb3206df0e 100644 --- a/app/javascript/mastodon/components/html_block/html_block.stories.tsx +++ b/app/javascript/mastodon/components/html_block/html_block.stories.tsx @@ -7,23 +7,49 @@ const meta = { title: 'Components/HTMLBlock', component: HTMLBlock, args: { - contents: - '

Hello, world!

\n

A link

\n

This should be filtered out:

', + htmlString: `

Hello, world!

+

A link

+

This should be filtered out:

+

This also has emoji: 🖤

`, + }, + argTypes: { + extraEmojis: { + table: { + disable: true, + }, + }, + onElement: { + table: { + disable: true, + }, + }, + onAttribute: { + table: { + disable: true, + }, + }, }, render(args) { return ( // Just for visual clarity in Storybook. -
- -
+ /> ); }, + // Force Twemoji to demonstrate emoji rendering. + parameters: { + state: { + meta: { + emoji_style: 'twemoji', + }, + }, + }, } satisfies Meta; export default meta; diff --git a/app/javascript/mastodon/components/html_block/index.tsx b/app/javascript/mastodon/components/html_block/index.tsx index 51baea614d7..69fa1d9bf55 100644 --- a/app/javascript/mastodon/components/html_block/index.tsx +++ b/app/javascript/mastodon/components/html_block/index.tsx @@ -1,50 +1,30 @@ -import type { FC, ReactNode } from 'react'; -import { useMemo } from 'react'; +import { useCallback } from 'react'; -import { cleanExtraEmojis } from '@/mastodon/features/emoji/normalize'; -import type { CustomEmojiMapArg } from '@/mastodon/features/emoji/types'; -import { createLimitedCache } from '@/mastodon/utils/cache'; +import type { OnElementHandler } from '@/mastodon/utils/html'; +import { polymorphicForwardRef } from '@/types/polymorphic'; -import { htmlStringToComponents } from '../../utils/html'; +import type { EmojiHTMLProps } from '../emoji/html'; +import { ModernEmojiHTML } from '../emoji/html'; +import { useElementHandledLink } from '../status/handled_link'; -// Use a module-level cache to avoid re-rendering the same HTML multiple times. -const cache = createLimitedCache({ maxSize: 1000 }); - -interface HTMLBlockProps { - contents: string; - extraEmojis?: CustomEmojiMapArg; -} - -export const HTMLBlock: FC = ({ - contents: raw, - extraEmojis, -}) => { - const customEmojis = useMemo( - () => cleanExtraEmojis(extraEmojis), - [extraEmojis], - ); - const contents = useMemo(() => { - const key = JSON.stringify({ raw, customEmojis }); - if (cache.has(key)) { - return cache.get(key); - } - - const rendered = htmlStringToComponents(raw, { - onText, - extraArgs: { customEmojis }, +export const HTMLBlock = polymorphicForwardRef< + 'div', + EmojiHTMLProps & Parameters[0] +>( + ({ + onElement: onParentElement, + hrefToMention, + hashtagAccountId, + ...props + }) => { + const { onElement: onLinkElement } = useElementHandledLink({ + hrefToMention, + hashtagAccountId, }); - - cache.set(key, rendered); - return rendered; - }, [raw, customEmojis]); - - return contents; -}; - -function onText( - text: string, - // eslint-disable-next-line @typescript-eslint/no-unused-vars -- Doesn't do anything, just showing how typing would work. - { customEmojis }: { customEmojis: CustomEmojiMapArg | null }, -) { - return text; -} + const onElement: OnElementHandler = useCallback( + (...args) => onParentElement?.(...args) ?? onLinkElement(...args), + [onLinkElement, onParentElement], + ); + return ; + }, +); diff --git a/app/javascript/mastodon/components/poll.tsx b/app/javascript/mastodon/components/poll.tsx index 80444f6406f..a9229e6ee49 100644 --- a/app/javascript/mastodon/components/poll.tsx +++ b/app/javascript/mastodon/components/poll.tsx @@ -8,6 +8,7 @@ import classNames from 'classnames'; import { animated, useSpring } from '@react-spring/web'; import escapeTextContentForBrowser from 'escape-html'; +import { EmojiHTML } from '@/mastodon/components/emoji/html'; import CheckIcon from '@/material-icons/400-24px/check.svg?react'; import { openModal } from 'mastodon/actions/modal'; import { fetchPoll, vote } from 'mastodon/actions/polls'; @@ -305,10 +306,11 @@ const PollOption: React.FC = (props) => { )} - {!!voted && ( diff --git a/app/javascript/mastodon/components/status.jsx b/app/javascript/mastodon/components/status.jsx index 196da7c99a8..2a8c9bfb2d8 100644 --- a/app/javascript/mastodon/components/status.jsx +++ b/app/javascript/mastodon/components/status.jsx @@ -118,7 +118,7 @@ class Status extends ImmutablePureComponent { unread: PropTypes.bool, showThread: PropTypes.bool, isQuotedPost: PropTypes.bool, - shouldHighlightOnMount: PropTypes.bool, + shouldHighlightOnMount: PropTypes.bool, getScrollPosition: PropTypes.func, updateScrollBottom: PropTypes.func, cacheMediaWidth: PropTypes.func, @@ -600,7 +600,7 @@ class Status extends ImmutablePureComponent { {matchedFilters && } - {(status.get('spoiler_text').length > 0 && (!matchedFilters || this.state.showDespiteFilter)) && } + {(!matchedFilters || this.state.showDespiteFilter) && } {expanded && ( <> diff --git a/app/javascript/mastodon/components/status/handled_link.stories.tsx b/app/javascript/mastodon/components/status/handled_link.stories.tsx new file mode 100644 index 00000000000..e3438337048 --- /dev/null +++ b/app/javascript/mastodon/components/status/handled_link.stories.tsx @@ -0,0 +1,102 @@ +import type { Meta, StoryObj } from '@storybook/react-vite'; + +import { HashtagMenuController } from '@/mastodon/features/ui/components/hashtag_menu_controller'; +import { accountFactoryState } from '@/testing/factories'; + +import { HoverCardController } from '../hover_card_controller'; + +import type { HandledLinkProps } from './handled_link'; +import { HandledLink } from './handled_link'; + +type HandledLinkStoryProps = Pick< + HandledLinkProps, + 'href' | 'text' | 'prevText' +> & { + mentionAccount: 'local' | 'remote' | 'none'; + hashtagAccount: boolean; +}; + +const meta = { + title: 'Components/Status/HandledLink', + render({ mentionAccount, hashtagAccount, ...args }) { + let mention: HandledLinkProps['mention'] | undefined; + if (mentionAccount === 'local') { + mention = { id: '1', acct: 'testuser' }; + } else if (mentionAccount === 'remote') { + mention = { id: '2', acct: 'remoteuser@mastodon.social' }; + } + return ( + <> + + {args.text} + + + + + ); + }, + args: { + href: 'https://example.com/path/subpath?query=1#hash', + text: 'https://example.com', + mentionAccount: 'none', + hashtagAccount: false, + }, + argTypes: { + mentionAccount: { + control: { type: 'select' }, + options: ['local', 'remote', 'none'], + defaultValue: 'none', + }, + }, + parameters: { + state: { + accounts: { + '1': accountFactoryState({ id: '1', acct: 'hashtaguser' }), + }, + }, + }, +} satisfies Meta; + +export default meta; + +type Story = StoryObj; + +export const Default: Story = {}; + +export const Simple: Story = { + args: { + href: 'https://example.com/test', + }, +}; + +export const Hashtag: Story = { + args: { + text: '#example', + hashtagAccount: true, + }, +}; + +export const Mention: Story = { + args: { + text: '@user', + mentionAccount: 'local', + }, +}; + +export const InternalLink: Story = { + args: { + href: '/about', + text: 'About', + }, +}; + +export const InvalidURL: Story = { + args: { + href: 'ht!tp://invalid-url', + text: 'ht!tp://invalid-url -- invalid!', + }, +}; diff --git a/app/javascript/mastodon/components/status/handled_link.tsx b/app/javascript/mastodon/components/status/handled_link.tsx new file mode 100644 index 00000000000..3c8973992bd --- /dev/null +++ b/app/javascript/mastodon/components/status/handled_link.tsx @@ -0,0 +1,109 @@ +import { useCallback } from 'react'; +import type { ComponentProps, FC } from 'react'; + +import classNames from 'classnames'; +import { Link } from 'react-router-dom'; + +import type { ApiMentionJSON } from '@/mastodon/api_types/statuses'; +import type { OnElementHandler } from '@/mastodon/utils/html'; + +export interface HandledLinkProps { + href: string; + text: string; + prevText?: string; + hashtagAccountId?: string; + mention?: Pick; +} + +export const HandledLink: FC> = ({ + href, + text, + prevText, + hashtagAccountId, + mention, + className, + children, + ...props +}) => { + // Handle hashtags + if (text.startsWith('#') || prevText?.endsWith('#')) { + const hashtag = text.slice(1).trim(); + return ( + + {children} + + ); + } else if ((text.startsWith('@') || prevText?.endsWith('@')) && mention) { + // Handle mentions + return ( + + {children} + + ); + } + + // Non-absolute paths treated as internal links. This shouldn't happen, but just in case. + if (href.startsWith('/')) { + return ( + + {children} + + ); + } + + return ( + + {children} + + ); +}; + +export const useElementHandledLink = ({ + hashtagAccountId, + hrefToMention, +}: { + hashtagAccountId?: string; + hrefToMention?: (href: string) => ApiMentionJSON | undefined; +} = {}) => { + const onElement = useCallback( + (element, { key, ...props }, children) => { + if (element instanceof HTMLAnchorElement) { + const mention = hrefToMention?.(element.href); + return ( + + {children} + + ); + } + return undefined; + }, + [hashtagAccountId, hrefToMention], + ); + return { onElement }; +}; diff --git a/app/javascript/mastodon/components/status_banner.tsx b/app/javascript/mastodon/components/status_banner.tsx index e11b2c9279b..a1d200133f8 100644 --- a/app/javascript/mastodon/components/status_banner.tsx +++ b/app/javascript/mastodon/components/status_banner.tsx @@ -3,6 +3,8 @@ import { useCallback, useRef, useId } from 'react'; import { FormattedMessage } from 'react-intl'; +import { AnimateEmojiProvider } from './emoji/context'; + export enum BannerVariant { Warning = 'warning', Filter = 'filter', @@ -34,8 +36,7 @@ export const StatusBanner: React.FC<{ return ( // Element clicks are passed on to button - // eslint-disable-next-line jsx-a11y/click-events-have-key-events, jsx-a11y/no-static-element-interactions -
)} -
+ ); }; diff --git a/app/javascript/mastodon/components/status_content.jsx b/app/javascript/mastodon/components/status_content.jsx index d766793d87c..14779ce3a43 100644 --- a/app/javascript/mastodon/components/status_content.jsx +++ b/app/javascript/mastodon/components/status_content.jsx @@ -18,6 +18,7 @@ import { languages as preloadedLanguages } from 'mastodon/initial_state'; import { isModernEmojiEnabled } from '../utils/environment'; import { EmojiHTML } from './emoji/html'; +import { HandledLink } from './status/handled_link'; const MAX_HEIGHT = 706; // 22px * 32 (+ 2px padding at the top) @@ -27,9 +28,6 @@ const MAX_HEIGHT = 706; // 22px * 32 (+ 2px padding at the top) * @returns {string} */ export function getStatusContent(status) { - if (isModernEmojiEnabled()) { - return status.getIn(['translation', 'content']) || status.get('content'); - } return status.getIn(['translation', 'contentHtml']) || status.get('contentHtml'); } @@ -99,6 +97,23 @@ class StatusContent extends PureComponent { } const { status, onCollapsedToggle } = this.props; + if (status.get('collapsed', null) === null && onCollapsedToggle) { + const { collapsible, onClick } = this.props; + + const collapsed = + collapsible + && onClick + && node.clientHeight > MAX_HEIGHT + && status.get('spoiler_text').length === 0; + + onCollapsedToggle(collapsed); + } + + // Exit if modern emoji is enabled, as it handles links using the HandledLink component. + if (isModernEmojiEnabled()) { + return; + } + const links = node.querySelectorAll('a'); let link, mention; @@ -128,18 +143,6 @@ class StatusContent extends PureComponent { link.classList.add('unhandled-link'); } } - - if (status.get('collapsed', null) === null && onCollapsedToggle) { - const { collapsible, onClick } = this.props; - - const collapsed = - collapsible - && onClick - && node.clientHeight > MAX_HEIGHT - && status.get('spoiler_text').length === 0; - - onCollapsedToggle(collapsed); - } } componentDidMount () { @@ -201,6 +204,27 @@ class StatusContent extends PureComponent { this.node = c; }; + handleElement = (element, { key, ...props }, children) => { + if (element instanceof HTMLAnchorElement) { + const mention = this.props.status.get('mentions').find(item => element.href === item.get('url')); + return ( + + {children} + + ); + } else if (element instanceof HTMLParagraphElement && element.classList.contains('quote-inline')) { + return null; + } + return undefined; + } + render () { const { status, intl, statusContent } = this.props; @@ -245,6 +269,7 @@ class StatusContent extends PureComponent { lang={language} htmlString={content} extraEmojis={status.get('emojis')} + onElement={this.handleElement.bind(this)} /> {poll} @@ -262,6 +287,7 @@ class StatusContent extends PureComponent { lang={language} htmlString={content} extraEmojis={status.get('emojis')} + onElement={this.handleElement.bind(this)} /> {poll} diff --git a/app/javascript/mastodon/components/verified_badge.tsx b/app/javascript/mastodon/components/verified_badge.tsx index 626cc500d6a..43edbc79518 100644 --- a/app/javascript/mastodon/components/verified_badge.tsx +++ b/app/javascript/mastodon/components/verified_badge.tsx @@ -1,10 +1,17 @@ +import { EmojiHTML } from '@/mastodon/components/emoji/html'; import CheckIcon from '@/material-icons/400-24px/check.svg?react'; +import { isModernEmojiEnabled } from '../utils/environment'; +import type { OnAttributeHandler } from '../utils/html'; + import { Icon } from './icon'; const domParser = new DOMParser(); const stripRelMe = (html: string) => { + if (isModernEmojiEnabled()) { + return html; + } const document = domParser.parseFromString(html, 'text/html').documentElement; document.querySelectorAll('a[rel]').forEach((link) => { @@ -15,7 +22,23 @@ const stripRelMe = (html: string) => { }); const body = document.querySelector('body'); - return body ? { __html: body.innerHTML } : undefined; + return body?.innerHTML ?? ''; +}; + +const onAttribute: OnAttributeHandler = (name, value, tagName) => { + if (name === 'rel' && tagName === 'a') { + if (value === 'me') { + return null; + } + return [ + name, + value + .split(' ') + .filter((x) => x !== 'me') + .join(' '), + ]; + } + return undefined; }; interface Props { @@ -24,6 +47,10 @@ interface Props { export const VerifiedBadge: React.FC = ({ link }) => ( - + ); diff --git a/app/javascript/mastodon/features/account_timeline/components/account_header.tsx b/app/javascript/mastodon/features/account_timeline/components/account_header.tsx index 776157ccf51..2bf636d060d 100644 --- a/app/javascript/mastodon/features/account_timeline/components/account_header.tsx +++ b/app/javascript/mastodon/features/account_timeline/components/account_header.tsx @@ -7,9 +7,9 @@ import { Helmet } from 'react-helmet'; import { NavLink } from 'react-router-dom'; import { AccountBio } from '@/mastodon/components/account_bio'; +import { AccountFields } from '@/mastodon/components/account_fields'; import { DisplayName } from '@/mastodon/components/display_name'; import { AnimateEmojiProvider } from '@/mastodon/components/emoji/context'; -import CheckIcon from '@/material-icons/400-24px/check.svg?react'; import LockIcon from '@/material-icons/400-24px/lock.svg?react'; import MoreHorizIcon from '@/material-icons/400-24px/more_horiz.svg?react'; import NotificationsIcon from '@/material-icons/400-24px/notifications.svg?react'; @@ -186,14 +186,6 @@ const titleFromAccount = (account: Account) => { return `${prefix} (@${acct})`; }; -const dateFormatOptions: Intl.DateTimeFormatOptions = { - month: 'short', - day: 'numeric', - year: 'numeric', - hour: '2-digit', - minute: '2-digit', -}; - export const AccountHeader: React.FC<{ accountId: string; hideTabs?: boolean; @@ -891,46 +883,7 @@ export const AccountHeader: React.FC<{
- {fields.map((pair, i) => ( -
-
- -
- {pair.verified_at && ( - - - - )}{' '} - -
-
- ))} +
diff --git a/app/javascript/mastodon/features/compose/components/edit_indicator.jsx b/app/javascript/mastodon/features/compose/components/edit_indicator.jsx index 106ff7bdaa4..3fa37bb8c8b 100644 --- a/app/javascript/mastodon/features/compose/components/edit_indicator.jsx +++ b/app/javascript/mastodon/features/compose/components/edit_indicator.jsx @@ -50,9 +50,7 @@ export const EditIndicator = () => { {(status.get('poll') || status.get('media_attachments').size > 0) && ( diff --git a/app/javascript/mastodon/features/compose/components/reply_indicator.jsx b/app/javascript/mastodon/features/compose/components/reply_indicator.jsx index 35733ac23b6..e746fe6a6d2 100644 --- a/app/javascript/mastodon/features/compose/components/reply_indicator.jsx +++ b/app/javascript/mastodon/features/compose/components/reply_indicator.jsx @@ -35,9 +35,7 @@ export const ReplyIndicator = () => { {(status.get('poll') || status.get('media_attachments').size > 0) && ( diff --git a/app/javascript/mastodon/features/compose/containers/compose_form_container.js b/app/javascript/mastodon/features/compose/containers/compose_form_container.js index 5f86426c4d4..3dad46bc520 100644 --- a/app/javascript/mastodon/features/compose/containers/compose_form_container.js +++ b/app/javascript/mastodon/features/compose/containers/compose_form_container.js @@ -10,10 +10,13 @@ import { insertEmojiCompose, uploadCompose, } from 'mastodon/actions/compose'; +import { pasteLinkCompose } from 'mastodon/actions/compose_typed'; import { openModal } from 'mastodon/actions/modal'; import ComposeForm from '../components/compose_form'; +const urlLikeRegex = /^https?:\/\/[^\s]+\/[^\s]+$/i; + const mapStateToProps = state => ({ text: state.getIn(['compose', 'text']), suggestions: state.getIn(['compose', 'suggestions']), @@ -71,8 +74,21 @@ const mapDispatchToProps = (dispatch, props) => ({ dispatch(changeComposeSpoilerText(checked)); }, - onPaste (files) { - dispatch(uploadCompose(files)); + onPaste (e) { + if (e.clipboardData && e.clipboardData.files.length === 1) { + dispatch(uploadCompose(e.clipboardData.files)); + e.preventDefault(); + } else if (e.clipboardData && e.clipboardData.files.length === 0) { + const data = e.clipboardData.getData('text/plain'); + if (!data.match(urlLikeRegex)) return; + + try { + const url = new URL(data); + dispatch(pasteLinkCompose({ url })); + } catch { + return; + } + } }, onPickEmoji (position, data, needsSpace) { diff --git a/app/javascript/mastodon/features/directory/components/account_card.tsx b/app/javascript/mastodon/features/directory/components/account_card.tsx index 6dc70532ab0..562a72b4e8b 100644 --- a/app/javascript/mastodon/features/directory/components/account_card.tsx +++ b/app/javascript/mastodon/features/directory/components/account_card.tsx @@ -2,6 +2,7 @@ import { FormattedMessage } from 'react-intl'; import { Link } from 'react-router-dom'; +import { EmojiHTML } from '@/mastodon/components/emoji/html'; import { Avatar } from 'mastodon/components/avatar'; import { DisplayName } from 'mastodon/components/display_name'; import { FollowButton } from 'mastodon/components/follow_button'; @@ -39,9 +40,10 @@ export const AccountCard: React.FC<{ accountId: string }> = ({ accountId }) => { {account.get('note').length > 0 && ( -
)} diff --git a/app/javascript/mastodon/features/emoji/emoji.js b/app/javascript/mastodon/features/emoji/emoji.js index d1843c33bda..cc0d6fe195f 100644 --- a/app/javascript/mastodon/features/emoji/emoji.js +++ b/app/javascript/mastodon/features/emoji/emoji.js @@ -1,5 +1,6 @@ import Trie from 'substring-trie'; +import { isModernEmojiEnabled } from '@/mastodon/utils/environment'; import { assetHost } from 'mastodon/utils/config'; import { autoPlayGif } from '../../initial_state'; @@ -148,7 +149,17 @@ const emojifyNode = (node, customEmojis) => { } }; -const emojify = (str, customEmojis = {}) => { +/** + * Legacy emoji processing function. + * @param {string} str + * @param {object} customEmojis + * @param {boolean} force If true, always emojify even if modern emoji is enabled + * @returns {string} + */ +const emojify = (str, customEmojis = {}, force = false) => { + if (isModernEmojiEnabled() && !force) { + return str; + } const wrapper = document.createElement('div'); wrapper.innerHTML = str; diff --git a/app/javascript/mastodon/features/emoji/emoji_picker.tsx b/app/javascript/mastodon/features/emoji/emoji_picker.tsx index f5300c9fece..f9367c775cc 100644 --- a/app/javascript/mastodon/features/emoji/emoji_picker.tsx +++ b/app/javascript/mastodon/features/emoji/emoji_picker.tsx @@ -2,9 +2,12 @@ import type { EmojiProps, PickerProps } from 'emoji-mart'; import EmojiRaw from 'emoji-mart/dist-es/components/emoji/nimble-emoji'; import PickerRaw from 'emoji-mart/dist-es/components/picker/nimble-picker'; +import { isModernEmojiEnabled } from '@/mastodon/utils/environment'; import { assetHost } from 'mastodon/utils/config'; +import { EMOJI_MODE_NATIVE } from './constants'; import EmojiData from './emoji_data.json'; +import { useEmojiAppState } from './mode'; const backgroundImageFnDefault = () => `${assetHost}/emoji/sheet_15_1.png`; @@ -16,6 +19,7 @@ const Emoji = ({ backgroundImageFn = backgroundImageFnDefault, ...props }: EmojiProps) => { + const { mode } = useEmojiAppState(); return ( @@ -37,6 +42,7 @@ const Picker = ({ backgroundImageFn = backgroundImageFnDefault, ...props }: PickerProps) => { + const { mode } = useEmojiAppState(); return ( ); diff --git a/app/javascript/mastodon/features/emoji/hooks.ts b/app/javascript/mastodon/features/emoji/hooks.ts deleted file mode 100644 index b3b27d274a6..00000000000 --- a/app/javascript/mastodon/features/emoji/hooks.ts +++ /dev/null @@ -1,75 +0,0 @@ -import { useCallback, useLayoutEffect, useMemo, useState } from 'react'; - -import { useAppSelector } from '@/mastodon/store'; -import { isModernEmojiEnabled } from '@/mastodon/utils/environment'; - -import { toSupportedLocale } from './locale'; -import { determineEmojiMode } from './mode'; -import { cleanExtraEmojis } from './normalize'; -import { emojifyElement, emojifyText } from './render'; -import type { CustomEmojiMapArg, EmojiAppState } from './types'; -import { stringHasAnyEmoji } from './utils'; - -interface UseEmojifyOptions { - text: string; - extraEmojis?: CustomEmojiMapArg; - deep?: boolean; -} - -export function useEmojify({ - text, - extraEmojis, - deep = true, -}: UseEmojifyOptions) { - const [emojifiedText, setEmojifiedText] = useState(null); - - const appState = useEmojiAppState(); - const extra = useMemo(() => cleanExtraEmojis(extraEmojis), [extraEmojis]); - - const emojify = useCallback( - async (input: string) => { - let result: string | null = null; - if (deep) { - const wrapper = document.createElement('div'); - wrapper.innerHTML = input; - if (await emojifyElement(wrapper, appState, extra ?? {})) { - result = wrapper.innerHTML; - } - } else { - result = await emojifyText(text, appState, extra ?? {}); - } - if (result) { - setEmojifiedText(result); - } else { - setEmojifiedText(input); - } - }, - [appState, deep, extra, text], - ); - useLayoutEffect(() => { - if (isModernEmojiEnabled() && !!text.trim() && stringHasAnyEmoji(text)) { - void emojify(text); - } else { - // If no emoji or we don't want to render, fall back. - setEmojifiedText(text); - } - }, [emojify, text]); - - return emojifiedText; -} - -export function useEmojiAppState(): EmojiAppState { - const locale = useAppSelector((state) => - toSupportedLocale(state.meta.get('locale') as string), - ); - const mode = useAppSelector((state) => - determineEmojiMode(state.meta.get('emoji_style') as string), - ); - - return { - currentLocale: locale, - locales: [locale], - mode, - darkTheme: document.body.classList.contains('theme-default'), - }; -} diff --git a/app/javascript/mastodon/features/emoji/index.ts b/app/javascript/mastodon/features/emoji/index.ts index d128da6b536..3701ad67679 100644 --- a/app/javascript/mastodon/features/emoji/index.ts +++ b/app/javascript/mastodon/features/emoji/index.ts @@ -10,6 +10,8 @@ let worker: Worker | null = null; const log = emojiLogger('index'); +const WORKER_TIMEOUT = 1_000; // 1 second + export function initializeEmoji() { log('initializing emojis'); if (!worker && 'Worker' in window) { @@ -29,7 +31,7 @@ export function initializeEmoji() { log('worker is not ready after timeout'); worker = null; void fallbackLoad(); - }, 500); + }, WORKER_TIMEOUT); thisWorker.addEventListener('message', (event: MessageEvent) => { const { data: message } = event; if (message === 'ready') { diff --git a/app/javascript/mastodon/features/emoji/mode.ts b/app/javascript/mastodon/features/emoji/mode.ts index 0f581d8b504..afb8a78ebcc 100644 --- a/app/javascript/mastodon/features/emoji/mode.ts +++ b/app/javascript/mastodon/features/emoji/mode.ts @@ -1,6 +1,7 @@ // Credit to Nolan Lawson for the original implementation. // See: https://github.com/nolanlawson/emoji-picker-element/blob/master/src/picker/utils/testColorEmojiSupported.js +import { createAppSelector, useAppSelector } from '@/mastodon/store'; import { isDevelopment } from '@/mastodon/utils/environment'; import { @@ -8,7 +9,27 @@ import { EMOJI_MODE_NATIVE_WITH_FLAGS, EMOJI_MODE_TWEMOJI, } from './constants'; -import type { EmojiMode } from './types'; +import { toSupportedLocale } from './locale'; +import type { EmojiAppState, EmojiMode } from './types'; + +const modeSelector = createAppSelector( + [(state) => state.meta.get('emoji_style') as string], + (emoji_style) => determineEmojiMode(emoji_style), +); + +export function useEmojiAppState(): EmojiAppState { + const locale = useAppSelector((state) => + toSupportedLocale(state.meta.get('locale') as string), + ); + const mode = useAppSelector(modeSelector); + + return { + currentLocale: locale, + locales: [locale], + mode, + darkTheme: document.body.classList.contains('theme-default'), + }; +} type Feature = Uint8ClampedArray; diff --git a/app/javascript/mastodon/features/emoji/normalize.ts b/app/javascript/mastodon/features/emoji/normalize.ts index 65667dfe6dd..a09505e97fc 100644 --- a/app/javascript/mastodon/features/emoji/normalize.ts +++ b/app/javascript/mastodon/features/emoji/normalize.ts @@ -154,15 +154,21 @@ export function cleanExtraEmojis(extraEmojis?: CustomEmojiMapArg) { if (!extraEmojis) { return null; } - if (!isList(extraEmojis)) { - return extraEmojis; - } - return extraEmojis - .toJSON() - .reduce( + if (Array.isArray(extraEmojis)) { + return extraEmojis.reduce( (acc, emoji) => ({ ...acc, [emoji.shortcode]: emoji }), {}, ); + } + if (isList(extraEmojis)) { + return extraEmojis + .toJS() + .reduce( + (acc, emoji) => ({ ...acc, [emoji.shortcode]: emoji }), + {}, + ); + } + return extraEmojis; } function hexStringToNumbers(hexString: string): number[] { diff --git a/app/javascript/mastodon/features/emoji/render.test.ts b/app/javascript/mastodon/features/emoji/render.test.ts index 108cf747504..05dbc388c45 100644 --- a/app/javascript/mastodon/features/emoji/render.test.ts +++ b/app/javascript/mastodon/features/emoji/render.test.ts @@ -1,101 +1,12 @@ import { customEmojiFactory, unicodeEmojiFactory } from '@/testing/factories'; -import { EMOJI_MODE_TWEMOJI } from './constants'; import * as db from './database'; +import * as loader from './loader'; import { - emojifyElement, - emojifyText, - testCacheClear, + loadEmojiDataToState, + stringToEmojiState, tokenizeText, } from './render'; -import type { EmojiAppState } from './types'; - -function mockDatabase() { - return { - searchCustomEmojisByShortcodes: vi - .spyOn(db, 'searchCustomEmojisByShortcodes') - .mockResolvedValue([customEmojiFactory()]), - searchEmojisByHexcodes: vi - .spyOn(db, 'searchEmojisByHexcodes') - .mockResolvedValue([ - unicodeEmojiFactory({ - hexcode: '1F60A', - label: 'smiling face with smiling eyes', - unicode: '😊', - }), - unicodeEmojiFactory({ - hexcode: '1F1EA-1F1FA', - label: 'flag-eu', - unicode: '🇪🇺', - }), - ]), - }; -} - -const expectedSmileImage = - '😊'; -const expectedFlagImage = - '🇪🇺'; - -function testAppState(state: Partial = {}) { - return { - locales: ['en'], - mode: EMOJI_MODE_TWEMOJI, - currentLocale: 'en', - darkTheme: false, - ...state, - } satisfies EmojiAppState; -} - -describe('emojifyElement', () => { - function testElement(text = '

Hello 😊🇪🇺!

:custom:

') { - const testElement = document.createElement('div'); - testElement.innerHTML = text; - return testElement; - } - - afterEach(() => { - testCacheClear(); - vi.restoreAllMocks(); - }); - - test('caches element rendering results', async () => { - const { searchCustomEmojisByShortcodes, searchEmojisByHexcodes } = - mockDatabase(); - await emojifyElement(testElement(), testAppState()); - await emojifyElement(testElement(), testAppState()); - await emojifyElement(testElement(), testAppState()); - expect(searchEmojisByHexcodes).toHaveBeenCalledExactlyOnceWith( - ['1F1EA-1F1FA', '1F60A'], - 'en', - ); - expect(searchCustomEmojisByShortcodes).toHaveBeenCalledExactlyOnceWith([ - ':custom:', - ]); - }); - - test('returns null when no emoji are found', async () => { - mockDatabase(); - const actual = await emojifyElement( - testElement('

here is just text :)

'), - testAppState(), - ); - expect(actual).toBeNull(); - }); -}); - -describe('emojifyText', () => { - test('returns original input when no emoji are in string', async () => { - const actual = await emojifyText('nothing here', testAppState()); - expect(actual).toBe('nothing here'); - }); - - test('renders Unicode emojis to twemojis', async () => { - mockDatabase(); - const actual = await emojifyText('Hello 😊🇪🇺!', testAppState()); - expect(actual).toBe(`Hello ${expectedSmileImage}${expectedFlagImage}!`); - }); -}); describe('tokenizeText', () => { test('returns an array of text to be a single token', () => { @@ -162,3 +73,106 @@ describe('tokenizeText', () => { ]); }); }); + +describe('stringToEmojiState', () => { + test('returns unicode emoji state for valid unicode emoji', () => { + expect(stringToEmojiState('😊')).toEqual({ + type: 'unicode', + code: '1F60A', + }); + }); + + test('returns custom emoji state for valid custom emoji', () => { + expect(stringToEmojiState(':smile:')).toEqual({ + type: 'custom', + code: 'smile', + data: undefined, + }); + }); + + test('returns custom emoji state with data when provided', () => { + const customEmoji = { + smile: customEmojiFactory({ + shortcode: 'smile', + url: 'https://example.com/smile.png', + static_url: 'https://example.com/smile_static.png', + }), + }; + expect(stringToEmojiState(':smile:', customEmoji)).toEqual({ + type: 'custom', + code: 'smile', + data: customEmoji.smile, + }); + }); + + test('returns null for invalid emoji strings', () => { + expect(stringToEmojiState('notanemoji')).toBeNull(); + expect(stringToEmojiState(':invalid-emoji:')).toBeNull(); + }); +}); + +describe('loadEmojiDataToState', () => { + beforeEach(() => { + vi.clearAllMocks(); + }); + + test('loads unicode data into state', async () => { + const dbCall = vi + .spyOn(db, 'loadEmojiByHexcode') + .mockResolvedValue(unicodeEmojiFactory()); + const unicodeState = { type: 'unicode', code: '1F60A' } as const; + const result = await loadEmojiDataToState(unicodeState, 'en'); + expect(dbCall).toHaveBeenCalledWith('1F60A', 'en'); + expect(result).toEqual({ + type: 'unicode', + code: '1F60A', + data: unicodeEmojiFactory(), + }); + }); + + test('loads custom emoji data into state', async () => { + const dbCall = vi + .spyOn(db, 'loadCustomEmojiByShortcode') + .mockResolvedValueOnce(customEmojiFactory()); + const customState = { type: 'custom', code: 'smile' } as const; + const result = await loadEmojiDataToState(customState, 'en'); + expect(dbCall).toHaveBeenCalledWith('smile'); + expect(result).toEqual({ + type: 'custom', + code: 'smile', + data: customEmojiFactory(), + }); + }); + + test('returns null if unicode emoji not found in database', async () => { + vi.spyOn(db, 'loadEmojiByHexcode').mockResolvedValueOnce(undefined); + const unicodeState = { type: 'unicode', code: '1F60A' } as const; + const result = await loadEmojiDataToState(unicodeState, 'en'); + expect(result).toBeNull(); + }); + + test('returns null if custom emoji not found in database', async () => { + vi.spyOn(db, 'loadCustomEmojiByShortcode').mockResolvedValueOnce(undefined); + const customState = { type: 'custom', code: 'smile' } as const; + const result = await loadEmojiDataToState(customState, 'en'); + expect(result).toBeNull(); + }); + + test('retries loading emoji data once if initial load fails', async () => { + const dbCall = vi + .spyOn(db, 'loadEmojiByHexcode') + .mockRejectedValue(new db.LocaleNotLoadedError('en')); + vi.spyOn(loader, 'importEmojiData').mockResolvedValueOnce(); + const consoleCall = vi + .spyOn(console, 'warn') + .mockImplementationOnce(() => null); + + const unicodeState = { type: 'unicode', code: '1F60A' } as const; + const result = await loadEmojiDataToState(unicodeState, 'en'); + + expect(dbCall).toHaveBeenCalledTimes(2); + expect(loader.importEmojiData).toHaveBeenCalledWith('en'); + expect(consoleCall).toHaveBeenCalled(); + expect(result).toBeNull(); + }); +}); diff --git a/app/javascript/mastodon/features/emoji/render.ts b/app/javascript/mastodon/features/emoji/render.ts index e0c8fd8dce5..574d5ef59b2 100644 --- a/app/javascript/mastodon/features/emoji/render.ts +++ b/app/javascript/mastodon/features/emoji/render.ts @@ -1,7 +1,3 @@ -import { autoPlayGif } from '@/mastodon/initial_state'; -import { createLimitedCache } from '@/mastodon/utils/cache'; -import * as perf from '@/mastodon/utils/performance'; - import { EMOJI_MODE_NATIVE, EMOJI_MODE_NATIVE_WITH_FLAGS, @@ -12,33 +8,69 @@ import { loadCustomEmojiByShortcode, loadEmojiByHexcode, LocaleNotLoadedError, - searchCustomEmojisByShortcodes, - searchEmojisByHexcodes, } from './database'; import { importEmojiData } from './loader'; -import { emojiToUnicodeHex, unicodeHexToUrl } from './normalize'; +import { emojiToUnicodeHex } from './normalize'; import type { - EmojiAppState, EmojiLoadedState, EmojiMode, EmojiState, EmojiStateCustom, - EmojiStateMap, EmojiStateUnicode, ExtraCustomEmojiMap, - LocaleOrCustom, } from './types'; import { anyEmojiRegex, emojiLogger, isCustomEmoji, isUnicodeEmoji, - stringHasAnyEmoji, stringHasUnicodeFlags, } from './utils'; const log = emojiLogger('render'); +type TokenizedText = (string | EmojiState)[]; + +/** + * Tokenizes text into strings and emoji states. + * @param text Text to tokenize. + * @returns Array of strings and emoji states. + */ +export function tokenizeText(text: string): TokenizedText { + if (!text.trim()) { + return [text]; + } + + const tokens = []; + let lastIndex = 0; + for (const match of text.matchAll(anyEmojiRegex())) { + if (match.index > lastIndex) { + tokens.push(text.slice(lastIndex, match.index)); + } + + const code = match[0]; + + if (code.startsWith(':') && code.endsWith(':')) { + // Custom emoji + tokens.push({ + type: EMOJI_TYPE_CUSTOM, + code, + } satisfies EmojiStateCustom); + } else { + // Unicode emoji + tokens.push({ + type: EMOJI_TYPE_UNICODE, + code: code, + } satisfies EmojiStateUnicode); + } + lastIndex = match.index + code.length; + } + if (lastIndex < text.length) { + tokens.push(text.slice(lastIndex)); + } + return tokens; +} + /** * Parses emoji string to extract emoji state. * @param code Hex code or custom shortcode. @@ -132,305 +164,19 @@ export function isStateLoaded(state: EmojiState): state is EmojiLoadedState { } /** - * Emojifies an element. This modifies the element in place, replacing text nodes with emojified versions. + * Determines if the given token should be rendered as an image based on the emoji mode. + * @param state Emoji state to parse. + * @param mode Rendering mode. + * @returns Whether to render as an image. */ -export async function emojifyElement( - element: Element, - appState: EmojiAppState, - extraEmojis: ExtraCustomEmojiMap = {}, -): Promise { - const cacheKey = createCacheKey(element, appState, extraEmojis); - const cached = getCached(cacheKey); - if (cached !== undefined) { - log('Cache hit on %s', element.outerHTML); - if (cached === null) { - return null; - } - element.innerHTML = cached; - return element; - } - if (!stringHasAnyEmoji(element.innerHTML)) { - updateCache(cacheKey, null); - return null; - } - perf.start('emojifyElement()'); - const queue: (HTMLElement | Text)[] = [element]; - while (queue.length > 0) { - const current = queue.shift(); - if ( - !current || - current instanceof HTMLScriptElement || - current instanceof HTMLStyleElement - ) { - continue; - } - - if ( - current.textContent && - (current instanceof Text || !current.hasChildNodes()) - ) { - const renderedContent = await textToElementArray( - current.textContent, - appState, - extraEmojis, - ); - if (renderedContent) { - if (!(current instanceof Text)) { - current.textContent = null; // Clear the text content if it's not a Text node. - } - current.replaceWith(renderedToHTML(renderedContent)); - } - continue; - } - - for (const child of current.childNodes) { - if (child instanceof HTMLElement || child instanceof Text) { - queue.push(child); - } - } - } - updateCache(cacheKey, element.innerHTML); - perf.stop('emojifyElement()'); - return element; -} - -export async function emojifyText( - text: string, - appState: EmojiAppState, - extraEmojis: ExtraCustomEmojiMap = {}, -): Promise { - const cacheKey = createCacheKey(text, appState, extraEmojis); - const cached = getCached(cacheKey); - if (cached !== undefined) { - log('Cache hit on %s', text); - return cached ?? text; - } - if (!stringHasAnyEmoji(text)) { - updateCache(cacheKey, null); - return text; - } - const eleArray = await textToElementArray(text, appState, extraEmojis); - if (!eleArray) { - updateCache(cacheKey, null); - return text; - } - const rendered = renderedToHTML(eleArray, document.createElement('div')); - updateCache(cacheKey, rendered.innerHTML); - return rendered.innerHTML; -} - -// Private functions - -const { - set: updateCache, - get: getCached, - clear: cacheClear, -} = createLimitedCache({ log: log.extend('cache') }); - -function createCacheKey( - input: HTMLElement | string, - appState: EmojiAppState, - extraEmojis: ExtraCustomEmojiMap, -) { - return JSON.stringify([ - input instanceof HTMLElement ? input.outerHTML : input, - appState, - extraEmojis, - ]); -} - -type EmojifiedTextArray = (string | HTMLImageElement)[]; - -async function textToElementArray( - text: string, - appState: EmojiAppState, - extraEmojis: ExtraCustomEmojiMap = {}, -): Promise { - // Exit if no text to convert. - if (!text.trim()) { - return null; - } - - const tokens = tokenizeText(text); - - // If only one token and it's a string, exit early. - if (tokens.length === 1 && typeof tokens[0] === 'string') { - return null; - } - - // Get all emoji from the state map, loading any missing ones. - await loadMissingEmojiIntoCache(tokens, appState, extraEmojis); - - const renderedFragments: EmojifiedTextArray = []; - for (const token of tokens) { - if (typeof token !== 'string' && shouldRenderImage(token, appState.mode)) { - let state: EmojiState | undefined; - if (token.type === EMOJI_TYPE_CUSTOM) { - const extraEmojiData = extraEmojis[token.code]; - if (extraEmojiData) { - state = { - type: EMOJI_TYPE_CUSTOM, - data: extraEmojiData, - code: token.code, - }; - } else { - state = emojiForLocale(token.code, EMOJI_TYPE_CUSTOM); - } - } else { - state = emojiForLocale( - emojiToUnicodeHex(token.code), - appState.currentLocale, - ); - } - - // If the state is valid, create an image element. Otherwise, just append as text. - if (state && typeof state !== 'string' && isStateLoaded(state)) { - const image = stateToImage(state, appState); - renderedFragments.push(image); - continue; - } - } - const text = typeof token === 'string' ? token : token.code; - renderedFragments.push(text); - } - - return renderedFragments; -} - -type TokenizedText = (string | EmojiState)[]; - -export function tokenizeText(text: string): TokenizedText { - if (!text.trim()) { - return [text]; - } - - const tokens = []; - let lastIndex = 0; - for (const match of text.matchAll(anyEmojiRegex())) { - if (match.index > lastIndex) { - tokens.push(text.slice(lastIndex, match.index)); - } - - const code = match[0]; - - if (code.startsWith(':') && code.endsWith(':')) { - // Custom emoji - tokens.push({ - type: EMOJI_TYPE_CUSTOM, - code, - } satisfies EmojiStateCustom); - } else { - // Unicode emoji - tokens.push({ - type: EMOJI_TYPE_UNICODE, - code: code, - } satisfies EmojiStateUnicode); - } - lastIndex = match.index + code.length; - } - if (lastIndex < text.length) { - tokens.push(text.slice(lastIndex)); - } - return tokens; -} - -const localeCacheMap = new Map([ - [ - EMOJI_TYPE_CUSTOM, - createLimitedCache({ log: log.extend('custom') }), - ], -]); - -function cacheForLocale(locale: LocaleOrCustom): EmojiStateMap { - return ( - localeCacheMap.get(locale) ?? - createLimitedCache({ log: log.extend(locale) }) - ); -} - -function emojiForLocale( - code: string, - locale: LocaleOrCustom, -): EmojiState | undefined { - const cache = cacheForLocale(locale); - return cache.get(code); -} - -async function loadMissingEmojiIntoCache( - tokens: TokenizedText, - { mode, currentLocale }: EmojiAppState, - extraEmojis: ExtraCustomEmojiMap, -) { - const missingUnicodeEmoji = new Set(); - const missingCustomEmoji = new Set(); - - // Iterate over tokens and check if they are in the cache already. - for (const token of tokens) { - if (typeof token === 'string') { - continue; // Skip plain strings. - } - - // If this is a custom emoji, check it separately. - if (token.type === EMOJI_TYPE_CUSTOM) { - const code = token.code; - if (code in extraEmojis) { - continue; // We don't care about extra emoji. - } - const emojiState = emojiForLocale(code, EMOJI_TYPE_CUSTOM); - if (!emojiState) { - missingCustomEmoji.add(code); - } - // Otherwise this is a unicode emoji, so check it against all locales. - } else if (shouldRenderImage(token, mode)) { - const code = emojiToUnicodeHex(token.code); - if (missingUnicodeEmoji.has(code)) { - continue; // Already marked as missing. - } - const emojiState = emojiForLocale(code, currentLocale); - if (!emojiState) { - // If it's missing in one locale, we consider it missing for all. - missingUnicodeEmoji.add(code); - } - } - } - - if (missingUnicodeEmoji.size > 0) { - const missingEmojis = Array.from(missingUnicodeEmoji).toSorted(); - const emojis = await searchEmojisByHexcodes(missingEmojis, currentLocale); - const cache = cacheForLocale(currentLocale); - for (const emoji of emojis) { - cache.set(emoji.hexcode, { - type: EMOJI_TYPE_UNICODE, - data: emoji, - code: emoji.hexcode, - }); - } - localeCacheMap.set(currentLocale, cache); - } - - if (missingCustomEmoji.size > 0) { - const missingEmojis = Array.from(missingCustomEmoji).toSorted(); - const emojis = await searchCustomEmojisByShortcodes(missingEmojis); - const cache = cacheForLocale(EMOJI_TYPE_CUSTOM); - for (const emoji of emojis) { - cache.set(emoji.shortcode, { - type: EMOJI_TYPE_CUSTOM, - data: emoji, - code: emoji.shortcode, - }); - } - localeCacheMap.set(EMOJI_TYPE_CUSTOM, cache); - } -} - -export function shouldRenderImage(token: EmojiState, mode: EmojiMode): boolean { - if (token.type === EMOJI_TYPE_UNICODE) { +export function shouldRenderImage(state: EmojiState, mode: EmojiMode): boolean { + if (state.type === EMOJI_TYPE_UNICODE) { // If the mode is native or native with flags for non-flag emoji // we can just append the text node directly. if ( mode === EMOJI_MODE_NATIVE || (mode === EMOJI_MODE_NATIVE_WITH_FLAGS && - !stringHasUnicodeFlags(token.code)) + !stringHasUnicodeFlags(state.code)) ) { return false; } @@ -438,52 +184,3 @@ export function shouldRenderImage(token: EmojiState, mode: EmojiMode): boolean { return true; } - -function stateToImage(state: EmojiLoadedState, appState: EmojiAppState) { - const image = document.createElement('img'); - image.draggable = false; - image.classList.add('emojione'); - - if (state.type === EMOJI_TYPE_UNICODE) { - image.alt = state.data.unicode; - image.title = state.data.label; - image.src = unicodeHexToUrl(state.data.hexcode, appState.darkTheme); - } else { - // Custom emoji - const shortCode = `:${state.data.shortcode}:`; - image.classList.add('custom-emoji'); - image.alt = shortCode; - image.title = shortCode; - image.src = autoPlayGif ? state.data.url : state.data.static_url; - image.dataset.original = state.data.url; - image.dataset.static = state.data.static_url; - } - - return image; -} - -function renderedToHTML(renderedArray: EmojifiedTextArray): DocumentFragment; -function renderedToHTML( - renderedArray: EmojifiedTextArray, - parent: ParentType, -): ParentType; -function renderedToHTML( - renderedArray: EmojifiedTextArray, - parent: ParentNode | null = null, -) { - const fragment = parent ?? document.createDocumentFragment(); - for (const fragmentItem of renderedArray) { - if (typeof fragmentItem === 'string') { - fragment.appendChild(document.createTextNode(fragmentItem)); - } else if (fragmentItem instanceof HTMLImageElement) { - fragment.appendChild(fragmentItem); - } - } - return fragment; -} - -// Testing helpers -export const testCacheClear = () => { - cacheClear(); - localeCacheMap.clear(); -}; diff --git a/app/javascript/mastodon/features/emoji/types.ts b/app/javascript/mastodon/features/emoji/types.ts index 043b21361bb..8cd0902aa4a 100644 --- a/app/javascript/mastodon/features/emoji/types.ts +++ b/app/javascript/mastodon/features/emoji/types.ts @@ -4,7 +4,6 @@ import type { FlatCompactEmoji, Locale } from 'emojibase'; import type { ApiCustomEmojiJSON } from '@/mastodon/api_types/custom_emoji'; import type { CustomEmoji } from '@/mastodon/models/custom_emoji'; -import type { LimitedCache } from '@/mastodon/utils/cache'; import type { EMOJI_MODE_NATIVE, @@ -48,23 +47,18 @@ export interface EmojiStateCustom { data?: CustomEmojiRenderFields; } export type EmojiState = EmojiStateUnicode | EmojiStateCustom; + export type EmojiLoadedState = | Required | Required; -export type EmojiStateMap = LimitedCache; - export type CustomEmojiMapArg = | ExtraCustomEmojiMap - | ImmutableList; + | ImmutableList + | CustomEmoji[] + | ApiCustomEmojiJSON[]; export type ExtraCustomEmojiMap = Record< string, Pick >; - -export interface TwemojiBorderInfo { - hexCode: string; - hasLightBorder: boolean; - hasDarkBorder: boolean; -} diff --git a/app/javascript/mastodon/features/emoji/utils.test.ts b/app/javascript/mastodon/features/emoji/utils.test.ts index b9062294c47..3844c814a10 100644 --- a/app/javascript/mastodon/features/emoji/utils.test.ts +++ b/app/javascript/mastodon/features/emoji/utils.test.ts @@ -1,35 +1,31 @@ -import { - stringHasAnyEmoji, - stringHasCustomEmoji, - stringHasUnicodeEmoji, - stringHasUnicodeFlags, -} from './utils'; +import { isCustomEmoji, isUnicodeEmoji, stringHasUnicodeFlags } from './utils'; -describe('stringHasUnicodeEmoji', () => { +describe('isUnicodeEmoji', () => { test.concurrent.for([ - ['only text', false], - ['text with non-emoji symbols ™©', false], - ['text with emoji 😀', true], - ['multiple emojis 😀😃😄', true], - ['emoji with skin tone 👍🏽', true], - ['emoji with ZWJ 👩‍❤️‍👨', true], - ['emoji with variation selector ✊️', true], - ['emoji with keycap 1️⃣', true], - ['emoji with flags 🇺🇸', true], - ['emoji with regional indicators 🇦🇺', true], - ['emoji with gender 👩‍⚕️', true], - ['emoji with family 👨‍👩‍👧‍👦', true], - ['emoji with zero width joiner 👩‍🔬', true], - ['emoji with non-BMP codepoint 🧑‍🚀', true], - ['emoji with combining marks 👨‍👩‍👧‍👦', true], - ['emoji with enclosing keycap #️⃣', true], - ['emoji with no visible glyph \u200D', false], - ] as const)( - 'stringHasUnicodeEmoji has emojis in "%s": %o', - ([text, expected], { expect }) => { - expect(stringHasUnicodeEmoji(text)).toBe(expected); - }, - ); + ['😊', true], + ['🇿🇼', true], + ['🏴‍☠️', true], + ['🏳️‍🌈', true], + ['foo', false], + [':smile:', false], + ['😊foo', false], + ] as const)('isUnicodeEmoji("%s") is %o', ([input, expected], { expect }) => { + expect(isUnicodeEmoji(input)).toBe(expected); + }); +}); + +describe('isCustomEmoji', () => { + test.concurrent.for([ + [':smile:', true], + [':smile_123:', true], + [':SMILE:', true], + ['😊', false], + ['foo', false], + [':smile', false], + ['smile:', false], + ] as const)('isCustomEmoji("%s") is %o', ([input, expected], { expect }) => { + expect(isCustomEmoji(input)).toBe(expected); + }); }); describe('stringHasUnicodeFlags', () => { @@ -51,27 +47,3 @@ describe('stringHasUnicodeFlags', () => { }, ); }); - -describe('stringHasCustomEmoji', () => { - test('string with custom emoji returns true', () => { - expect(stringHasCustomEmoji(':custom: :test:')).toBeTruthy(); - }); - test('string without custom emoji returns false', () => { - expect(stringHasCustomEmoji('🏳️‍🌈 :🏳️‍🌈: text ™')).toBeFalsy(); - }); -}); - -describe('stringHasAnyEmoji', () => { - test('string without any emoji or characters', () => { - expect(stringHasAnyEmoji('normal text. 12356?!')).toBeFalsy(); - }); - test('string with non-emoji characters', () => { - expect(stringHasAnyEmoji('™©')).toBeFalsy(); - }); - test('has unicode emoji', () => { - expect(stringHasAnyEmoji('🏳️‍🌈🔥🇸🇹 👩‍🔬')).toBeTruthy(); - }); - test('has custom emoji', () => { - expect(stringHasAnyEmoji(':test: :custom:')).toBeTruthy(); - }); -}); diff --git a/app/javascript/mastodon/features/emoji/utils.ts b/app/javascript/mastodon/features/emoji/utils.ts index e811565c271..c567afc2ccc 100644 --- a/app/javascript/mastodon/features/emoji/utils.ts +++ b/app/javascript/mastodon/features/emoji/utils.ts @@ -6,10 +6,6 @@ export function emojiLogger(segment: string) { return debug(`emojis:${segment}`); } -export function stringHasUnicodeEmoji(input: string): boolean { - return new RegExp(EMOJI_REGEX, supportedFlags()).test(input); -} - export function isUnicodeEmoji(input: string): boolean { return ( input.length > 0 && @@ -34,19 +30,13 @@ export function stringHasUnicodeFlags(input: string): boolean { // Constant as this is supported by all browsers. const CUSTOM_EMOJI_REGEX = /:([a-z0-9_]+):/i; +// Use the polyfill regex or the Unicode property escapes if supported. +const EMOJI_REGEX = emojiRegexPolyfill?.source ?? '\\p{RGI_Emoji}'; export function isCustomEmoji(input: string): boolean { return new RegExp(`^${CUSTOM_EMOJI_REGEX.source}$`, 'i').test(input); } -export function stringHasCustomEmoji(input: string) { - return CUSTOM_EMOJI_REGEX.test(input); -} - -export function stringHasAnyEmoji(input: string) { - return stringHasUnicodeEmoji(input) || stringHasCustomEmoji(input); -} - export function anyEmojiRegex() { return new RegExp( `${EMOJI_REGEX}|${CUSTOM_EMOJI_REGEX.source}`, @@ -64,5 +54,3 @@ function supportedFlags(flags = '') { } return flags; } - -const EMOJI_REGEX = emojiRegexPolyfill?.source ?? '\\p{RGI_Emoji}'; diff --git a/app/javascript/mastodon/features/explore/components/author_link.jsx b/app/javascript/mastodon/features/explore/components/author_link.jsx deleted file mode 100644 index cf92ebc78b3..00000000000 --- a/app/javascript/mastodon/features/explore/components/author_link.jsx +++ /dev/null @@ -1,23 +0,0 @@ -import PropTypes from 'prop-types'; - -import { Avatar } from 'mastodon/components/avatar'; -import { useAppSelector } from 'mastodon/store'; -import { LinkedDisplayName } from '@/mastodon/components/display_name'; - -export const AuthorLink = ({ accountId }) => { - const account = useAppSelector(state => state.getIn(['accounts', accountId])); - - if (!account) { - return null; - } - - return ( - - - - ); -}; - -AuthorLink.propTypes = { - accountId: PropTypes.string.isRequired, -}; diff --git a/app/javascript/mastodon/features/explore/components/author_link.tsx b/app/javascript/mastodon/features/explore/components/author_link.tsx new file mode 100644 index 00000000000..a4667693a59 --- /dev/null +++ b/app/javascript/mastodon/features/explore/components/author_link.tsx @@ -0,0 +1,22 @@ +import type { FC } from 'react'; + +import { LinkedDisplayName } from '@/mastodon/components/display_name'; +import { Avatar } from 'mastodon/components/avatar'; +import { useAppSelector } from 'mastodon/store'; + +export const AuthorLink: FC<{ accountId: string }> = ({ accountId }) => { + const account = useAppSelector((state) => state.accounts.get(accountId)); + + if (!account) { + return null; + } + + return ( + + + + ); +}; diff --git a/app/javascript/mastodon/features/firehose/index.jsx b/app/javascript/mastodon/features/firehose/index.jsx index ff80aac2200..69db171cddc 100644 --- a/app/javascript/mastodon/features/firehose/index.jsx +++ b/app/javascript/mastodon/features/firehose/index.jsx @@ -13,7 +13,7 @@ import { changeSetting } from 'mastodon/actions/settings'; import { connectPublicStream, connectCommunityStream } from 'mastodon/actions/streaming'; import { expandPublicTimeline, expandCommunityTimeline } from 'mastodon/actions/timelines'; import { DismissableBanner } from 'mastodon/components/dismissable_banner'; -import { domain } from 'mastodon/initial_state'; +import { localLiveFeedAccess, remoteLiveFeedAccess, me, domain } from 'mastodon/initial_state'; import { useAppDispatch, useAppSelector } from 'mastodon/store'; import Column from '../../components/column'; @@ -165,19 +165,21 @@ const Firehose = ({ feedType, multiColumn }) => { -
- - - + {(signedIn || (localLiveFeedAccess === 'public' && remoteLiveFeedAccess === 'public')) && ( +
+ + + - - - + + + - - - -
+ + + +
+ )} @@ -40,7 +40,11 @@ class AccountAuthorize extends ImmutablePureComponent { -
+
diff --git a/app/javascript/mastodon/features/hashtag_timeline/index.jsx b/app/javascript/mastodon/features/hashtag_timeline/index.jsx index ab3c32e6a7b..791f494d3d8 100644 --- a/app/javascript/mastodon/features/hashtag_timeline/index.jsx +++ b/app/javascript/mastodon/features/hashtag_timeline/index.jsx @@ -16,15 +16,21 @@ import { expandHashtagTimeline, clearTimeline } from 'mastodon/actions/timelines import Column from 'mastodon/components/column'; import ColumnHeader from 'mastodon/components/column_header'; import { identityContextPropShape, withIdentity } from 'mastodon/identity_context'; +import { remoteTopicFeedAccess, me } from 'mastodon/initial_state'; import StatusListContainer from '../ui/containers/status_list_container'; import { HashtagHeader } from './components/hashtag_header'; import ColumnSettingsContainer from './containers/column_settings_container'; -const mapStateToProps = (state, props) => ({ - hasUnread: state.getIn(['timelines', `hashtag:${props.params.id}${props.params.local ? ':local' : ''}`, 'unread']) > 0, -}); +const mapStateToProps = (state, props) => { + const local = props.params.local || (!me && remoteTopicFeedAccess !== 'public'); + + return ({ + local, + hasUnread: state.getIn(['timelines', `hashtag:${props.params.id}${local ? ':local' : ''}`, 'unread']) > 0, + }); +}; class HashtagTimeline extends PureComponent { disconnects = []; @@ -113,16 +119,16 @@ class HashtagTimeline extends PureComponent { } _unload () { - const { dispatch } = this.props; - const { id, local } = this.props.params; + const { dispatch, local } = this.props; + const { id } = this.props.params; this._unsubscribe(); dispatch(clearTimeline(`hashtag:${id}${local ? ':local' : ''}`)); } _load() { - const { dispatch } = this.props; - const { id, tags, local } = this.props.params; + const { dispatch, local } = this.props; + const { id, tags } = this.props.params; this._subscribe(dispatch, id, tags, local); dispatch(expandHashtagTimeline(id, { tags, local })); @@ -133,10 +139,10 @@ class HashtagTimeline extends PureComponent { } componentDidUpdate (prevProps) { - const { params } = this.props; - const { id, tags, local } = prevProps.params; + const { params, local } = this.props; + const { id, tags } = prevProps.params; - if (id !== params.id || !isEqual(tags, params.tags) || !isEqual(local, params.local)) { + if (id !== params.id || !isEqual(tags, params.tags) || !isEqual(local, prevProps.local)) { this._unload(); this._load(); } @@ -151,15 +157,15 @@ class HashtagTimeline extends PureComponent { }; handleLoadMore = maxId => { - const { dispatch, params } = this.props; - const { id, tags, local } = params; + const { dispatch, params, local } = this.props; + const { id, tags } = params; dispatch(expandHashtagTimeline(id, { maxId, tags, local })); }; render () { - const { hasUnread, columnId, multiColumn } = this.props; - const { id, local } = this.props.params; + const { hasUnread, columnId, multiColumn, local } = this.props; + const { id } = this.props.params; const pinned = !!columnId; return ( diff --git a/app/javascript/mastodon/features/home_timeline/components/announcements/announcement.tsx b/app/javascript/mastodon/features/home_timeline/components/announcements/announcement.tsx new file mode 100644 index 00000000000..8513e6169bd --- /dev/null +++ b/app/javascript/mastodon/features/home_timeline/components/announcements/announcement.tsx @@ -0,0 +1,119 @@ +import { useEffect, useState } from 'react'; +import type { FC } from 'react'; + +import { FormattedDate, FormattedMessage } from 'react-intl'; + +import type { ApiAnnouncementJSON } from '@/mastodon/api_types/announcements'; +import { AnimateEmojiProvider } from '@/mastodon/components/emoji/context'; +import { EmojiHTML } from '@/mastodon/components/emoji/html'; + +import { ReactionsBar } from './reactions'; + +export interface IAnnouncement extends ApiAnnouncementJSON { + contentHtml: string; +} + +interface AnnouncementProps { + announcement: IAnnouncement; + selected: boolean; +} + +export const Announcement: FC = ({ + announcement, + selected, +}) => { + const [unread, setUnread] = useState(!announcement.read); + useEffect(() => { + // Only update `unread` marker once the announcement is out of view + if (!selected && unread !== !announcement.read) { + setUnread(!announcement.read); + } + }, [announcement.read, selected, unread]); + + return ( + + + + + {' · '} + + + + + + + + + {unread && } + + ); +}; + +const Timestamp: FC> = ({ + announcement, +}) => { + const startsAt = announcement.starts_at && new Date(announcement.starts_at); + const endsAt = announcement.ends_at && new Date(announcement.ends_at); + const now = new Date(); + const hasTimeRange = startsAt && endsAt; + const skipTime = announcement.all_day; + + if (hasTimeRange) { + const skipYear = + startsAt.getFullYear() === endsAt.getFullYear() && + endsAt.getFullYear() === now.getFullYear(); + const skipEndDate = + startsAt.getDate() === endsAt.getDate() && + startsAt.getMonth() === endsAt.getMonth() && + startsAt.getFullYear() === endsAt.getFullYear(); + return ( + <> + {' '} + -{' '} + + + ); + } + const publishedAt = new Date(announcement.published_at); + return ( + + ); +}; diff --git a/app/javascript/mastodon/features/home_timeline/components/announcements/index.tsx b/app/javascript/mastodon/features/home_timeline/components/announcements/index.tsx new file mode 100644 index 00000000000..8c7c704849d --- /dev/null +++ b/app/javascript/mastodon/features/home_timeline/components/announcements/index.tsx @@ -0,0 +1,118 @@ +import { useCallback, useState } from 'react'; +import type { FC } from 'react'; + +import { defineMessages, useIntl } from 'react-intl'; + +import type { Map, List } from 'immutable'; + +import ReactSwipeableViews from 'react-swipeable-views'; + +import elephantUIPlane from '@/images/elephant_ui_plane.svg'; +import { CustomEmojiProvider } from '@/mastodon/components/emoji/context'; +import { IconButton } from '@/mastodon/components/icon_button'; +import LegacyAnnouncements from '@/mastodon/features/getting_started/containers/announcements_container'; +import { mascot, reduceMotion } from '@/mastodon/initial_state'; +import { createAppSelector, useAppSelector } from '@/mastodon/store'; +import { isModernEmojiEnabled } from '@/mastodon/utils/environment'; +import ChevronLeftIcon from '@/material-icons/400-24px/chevron_left.svg?react'; +import ChevronRightIcon from '@/material-icons/400-24px/chevron_right.svg?react'; + +import type { IAnnouncement } from './announcement'; +import { Announcement } from './announcement'; + +const messages = defineMessages({ + close: { id: 'lightbox.close', defaultMessage: 'Close' }, + previous: { id: 'lightbox.previous', defaultMessage: 'Previous' }, + next: { id: 'lightbox.next', defaultMessage: 'Next' }, +}); + +const announcementSelector = createAppSelector( + [(state) => state.announcements as Map>>], + (announcements) => + (announcements.get('items')?.toJS() as IAnnouncement[] | undefined) ?? [], +); + +export const ModernAnnouncements: FC = () => { + const intl = useIntl(); + + const announcements = useAppSelector(announcementSelector); + const emojis = useAppSelector((state) => state.custom_emojis); + + const [index, setIndex] = useState(0); + const handleChangeIndex = useCallback( + (idx: number) => { + setIndex(idx % announcements.length); + }, + [announcements.length], + ); + const handleNextIndex = useCallback(() => { + setIndex((prevIndex) => (prevIndex + 1) % announcements.length); + }, [announcements.length]); + const handlePrevIndex = useCallback(() => { + setIndex((prevIndex) => + prevIndex === 0 ? announcements.length - 1 : prevIndex - 1, + ); + }, [announcements.length]); + + if (announcements.length === 0) { + return null; + } + + return ( +
+ + +
+ + + {announcements + .map((announcement, idx) => ( + + )) + .reverse()} + + + + {announcements.length > 1 && ( +
+ + + {index + 1} / {announcements.length} + + +
+ )} +
+
+ ); +}; + +export const Announcements = isModernEmojiEnabled() + ? ModernAnnouncements + : LegacyAnnouncements; diff --git a/app/javascript/mastodon/features/home_timeline/components/announcements/reactions.tsx b/app/javascript/mastodon/features/home_timeline/components/announcements/reactions.tsx new file mode 100644 index 00000000000..481e87f190b --- /dev/null +++ b/app/javascript/mastodon/features/home_timeline/components/announcements/reactions.tsx @@ -0,0 +1,108 @@ +import { useCallback, useMemo } from 'react'; +import type { FC, HTMLAttributes } from 'react'; + +import classNames from 'classnames'; + +import type { AnimatedProps } from '@react-spring/web'; +import { animated, useTransition } from '@react-spring/web'; + +import { addReaction, removeReaction } from '@/mastodon/actions/announcements'; +import type { ApiAnnouncementReactionJSON } from '@/mastodon/api_types/announcements'; +import { AnimatedNumber } from '@/mastodon/components/animated_number'; +import { Emoji } from '@/mastodon/components/emoji'; +import { Icon } from '@/mastodon/components/icon'; +import EmojiPickerDropdown from '@/mastodon/features/compose/containers/emoji_picker_dropdown_container'; +import { isUnicodeEmoji } from '@/mastodon/features/emoji/utils'; +import { useAppDispatch } from '@/mastodon/store'; +import AddIcon from '@/material-icons/400-24px/add.svg?react'; + +export const ReactionsBar: FC<{ + reactions: ApiAnnouncementReactionJSON[]; + id: string; +}> = ({ reactions, id }) => { + const visibleReactions = useMemo( + () => reactions.filter((x) => x.count > 0), + [reactions], + ); + + const dispatch = useAppDispatch(); + const handleEmojiPick = useCallback( + (emoji: { native: string }) => { + dispatch(addReaction(id, emoji.native.replaceAll(/:/g, ''))); + }, + [dispatch, id], + ); + + const transitions = useTransition(visibleReactions, { + from: { + scale: 0, + }, + enter: { + scale: 1, + }, + leave: { + scale: 0, + }, + keys: visibleReactions.map((x) => x.name), + }); + + return ( +
+ {transitions(({ scale }, reaction) => ( + `scale(${s})`) }} + id={id} + /> + ))} + + {visibleReactions.length < 8 && ( + } + /> + )} +
+ ); +}; + +const Reaction: FC<{ + reaction: ApiAnnouncementReactionJSON; + id: string; + style: AnimatedProps>['style']; +}> = ({ id, reaction, style }) => { + const dispatch = useAppDispatch(); + const handleClick = useCallback(() => { + if (reaction.me) { + dispatch(removeReaction(id, reaction.name)); + } else { + dispatch(addReaction(id, reaction.name)); + } + }, [dispatch, id, reaction.me, reaction.name]); + + const code = isUnicodeEmoji(reaction.name) + ? reaction.name + : `:${reaction.name}:`; + + return ( + + + + + + + + + ); +}; diff --git a/app/javascript/mastodon/features/home_timeline/index.jsx b/app/javascript/mastodon/features/home_timeline/index.jsx index 39a8355b899..8c5555fd49e 100644 --- a/app/javascript/mastodon/features/home_timeline/index.jsx +++ b/app/javascript/mastodon/features/home_timeline/index.jsx @@ -14,7 +14,6 @@ import { SymbolLogo } from 'mastodon/components/logo'; import { fetchAnnouncements, toggleShowAnnouncements } from 'mastodon/actions/announcements'; import { IconWithBadge } from 'mastodon/components/icon_with_badge'; import { NotSignedInIndicator } from 'mastodon/components/not_signed_in_indicator'; -import AnnouncementsContainer from 'mastodon/features/getting_started/containers/announcements_container'; import { identityContextPropShape, withIdentity } from 'mastodon/identity_context'; import { criticalUpdatesPending } from 'mastodon/initial_state'; import { withBreakpoint } from 'mastodon/features/ui/hooks/useBreakpoint'; @@ -27,6 +26,7 @@ import StatusListContainer from '../ui/containers/status_list_container'; import { ColumnSettings } from './components/column_settings'; import { CriticalUpdateBanner } from './components/critical_update_banner'; +import { Announcements } from './components/announcements'; const messages = defineMessages({ title: { id: 'column.home', defaultMessage: 'Home' }, @@ -162,7 +162,7 @@ class HomeTimeline extends PureComponent { pinned={pinned} multiColumn={multiColumn} extraButton={announcementsButton} - appendContent={hasAnnouncements && showAnnouncements && } + appendContent={hasAnnouncements && showAnnouncements && } > diff --git a/app/javascript/mastodon/features/navigation_panel/index.tsx b/app/javascript/mastodon/features/navigation_panel/index.tsx index 66f8a657edf..d509bfb6c1d 100644 --- a/app/javascript/mastodon/features/navigation_panel/index.tsx +++ b/app/javascript/mastodon/features/navigation_panel/index.tsx @@ -35,7 +35,12 @@ import { Search } from 'mastodon/features/compose/components/search'; import { ColumnLink } from 'mastodon/features/ui/components/column_link'; import { useBreakpoint } from 'mastodon/features/ui/hooks/useBreakpoint'; import { useIdentity } from 'mastodon/identity_context'; -import { timelinePreview, trendsEnabled, me } from 'mastodon/initial_state'; +import { + localLiveFeedAccess, + remoteLiveFeedAccess, + trendsEnabled, + me, +} from 'mastodon/initial_state'; import { transientSingleColumn } from 'mastodon/is_mobile'; import { selectUnreadNotificationGroupsCount } from 'mastodon/selectors/notifications'; import { useAppSelector, useAppDispatch } from 'mastodon/store'; @@ -257,10 +262,16 @@ export const NavigationPanel: React.FC<{ multiColumn?: boolean }> = ({ /> )} - {(signedIn || timelinePreview) && ( + {(signedIn || + localLiveFeedAccess === 'public' || + remoteLiveFeedAccess === 'public') && ( ; +export type Mention = RecordOf; export const EmbeddedStatus: React.FC<{ statusId: string }> = ({ statusId, @@ -86,12 +87,9 @@ export const EmbeddedStatus: React.FC<{ statusId: string }> = ({ } // Assign status attributes to variables with a forced type, as status is not yet properly typed - const contentHtml = status.get('contentHtml') as string; - const contentWarning = status.get('spoilerHtml') as string; + const hasContentWarning = !!status.get('spoiler_text'); const poll = status.get('poll'); - const language = status.get('language') as string; - const mentions = status.get('mentions') as ImmutableList; - const expanded = !status.get('hidden') || !contentWarning; + const expanded = !status.get('hidden') || !hasContentWarning; const mediaAttachmentsSize = ( status.get('media_attachments') as ImmutableList ).size; @@ -109,20 +107,16 @@ export const EmbeddedStatus: React.FC<{ statusId: string }> = ({
- {contentWarning && ( - - )} + - {(!contentWarning || expanded) && ( + {(!hasContentWarning || expanded) && ( )} diff --git a/app/javascript/mastodon/features/notifications_v2/components/embedded_status_content.tsx b/app/javascript/mastodon/features/notifications_v2/components/embedded_status_content.tsx index 855e160fac6..b7dc998a479 100644 --- a/app/javascript/mastodon/features/notifications_v2/components/embedded_status_content.tsx +++ b/app/javascript/mastodon/features/notifications_v2/components/embedded_status_content.tsx @@ -1,4 +1,4 @@ -import { useCallback } from 'react'; +import { useCallback, useMemo } from 'react'; import { useHistory } from 'react-router-dom'; @@ -6,16 +6,22 @@ import type { List } from 'immutable'; import type { History } from 'history'; +import type { ApiMentionJSON } from '@/mastodon/api_types/statuses'; +import { EmojiHTML } from '@/mastodon/components/emoji/html'; +import { useElementHandledLink } from '@/mastodon/components/status/handled_link'; +import type { Status } from '@/mastodon/models/status'; +import { isModernEmojiEnabled } from '@/mastodon/utils/environment'; + import type { Mention } from './embedded_status'; const handleMentionClick = ( history: History, - mention: Mention, + mention: ApiMentionJSON, e: MouseEvent, ) => { if (e.button === 0 && !(e.ctrlKey || e.metaKey)) { e.preventDefault(); - history.push(`/@${mention.get('acct')}`); + history.push(`/@${mention.acct}`); } }; @@ -31,16 +37,25 @@ const handleHashtagClick = ( }; export const EmbeddedStatusContent: React.FC<{ - content: string; - mentions: List; - language: string; + status: Status; className?: string; -}> = ({ content, mentions, language, className }) => { +}> = ({ status, className }) => { const history = useHistory(); + const mentions = useMemo( + () => (status.get('mentions') as List).toJS(), + [status], + ); + const htmlHandlers = useElementHandledLink({ + hashtagAccountId: status.get('account') as string | undefined, + hrefToMention(href) { + return mentions.find((item) => item.url === href); + }, + }); + const handleContentRef = useCallback( (node: HTMLDivElement | null) => { - if (!node) { + if (!node || isModernEmojiEnabled()) { return; } @@ -53,7 +68,7 @@ export const EmbeddedStatusContent: React.FC<{ link.classList.add('status-link'); - const mention = mentions.find((item) => link.href === item.get('url')); + const mention = mentions.find((item) => link.href === item.url); if (mention) { link.addEventListener( @@ -61,8 +76,8 @@ export const EmbeddedStatusContent: React.FC<{ handleMentionClick.bind(null, history, mention), false, ); - link.setAttribute('title', `@${mention.get('acct')}`); - link.setAttribute('href', `/@${mention.get('acct')}`); + link.setAttribute('title', `@${mention.acct}`); + link.setAttribute('href', `/@${mention.acct}`); } else if ( link.textContent.startsWith('#') || link.previousSibling?.textContent?.endsWith('#') @@ -83,11 +98,12 @@ export const EmbeddedStatusContent: React.FC<{ ); return ( -
); }; diff --git a/app/javascript/mastodon/features/status/components/detailed_status.tsx b/app/javascript/mastodon/features/status/components/detailed_status.tsx index b09e109afb2..9b525b616c7 100644 --- a/app/javascript/mastodon/features/status/components/detailed_status.tsx +++ b/app/javascript/mastodon/features/status/components/detailed_status.tsx @@ -394,17 +394,13 @@ export const DetailedStatus: React.FC<{ /> )} - {status.get('spoiler_text').length > 0 && - (!matchedFilters || showDespiteFilter) && ( - - )} + {(!matchedFilters || showDespiteFilter) && ( + + )} {expanded && ( <> diff --git a/app/javascript/mastodon/features/status/components/refresh_controller.tsx b/app/javascript/mastodon/features/status/components/refresh_controller.tsx index 34faaf1d5d2..253cce46919 100644 --- a/app/javascript/mastodon/features/status/components/refresh_controller.tsx +++ b/app/javascript/mastodon/features/status/components/refresh_controller.tsx @@ -5,6 +5,8 @@ import { useIntl, defineMessages } from 'react-intl'; import { fetchContext, completeContextRefresh, + showPendingReplies, + clearPendingReplies, } from 'mastodon/actions/statuses'; import type { AsyncRefreshHeader } from 'mastodon/api'; import { apiGetAsyncRefresh } from 'mastodon/api/async_refreshes'; @@ -34,13 +36,9 @@ const messages = defineMessages({ id: 'status.context.loading', defaultMessage: 'Loading', }, - loadingMore: { - id: 'status.context.loading_more', - defaultMessage: 'Loading more replies', - }, success: { id: 'status.context.loading_success', - defaultMessage: 'All replies loaded', + defaultMessage: 'New replies loaded', }, error: { id: 'status.context.loading_error', @@ -52,80 +50,113 @@ const messages = defineMessages({ }, }); -type LoadingState = - | 'idle' - | 'more-available' - | 'loading-initial' - | 'loading-more' - | 'success' - | 'error'; +type LoadingState = 'idle' | 'more-available' | 'loading' | 'success' | 'error'; export const RefreshController: React.FC<{ statusId: string; }> = ({ statusId }) => { - const refresh = useAppSelector( - (state) => state.contexts.refreshing[statusId], - ); - const currentReplyCount = useAppSelector( - (state) => state.contexts.replies[statusId]?.length ?? 0, - ); - const autoRefresh = !currentReplyCount; const dispatch = useAppDispatch(); const intl = useIntl(); - const [loadingState, setLoadingState] = useState( - refresh && autoRefresh ? 'loading-initial' : 'idle', + const refreshHeader = useAppSelector( + (state) => state.contexts.refreshing[statusId], ); + const hasPendingReplies = useAppSelector( + (state) => !!state.contexts.pendingReplies[statusId]?.length, + ); + const [partialLoadingState, setLoadingState] = useState( + refreshHeader ? 'loading' : 'idle', + ); + const loadingState = hasPendingReplies + ? 'more-available' + : partialLoadingState; const [wasDismissed, setWasDismissed] = useState(false); const dismissPrompt = useCallback(() => { setWasDismissed(true); setLoadingState('idle'); - }, []); + dispatch(clearPendingReplies({ statusId })); + }, [dispatch, statusId]); useEffect(() => { let timeoutId: ReturnType; - const scheduleRefresh = (refresh: AsyncRefreshHeader) => { + const scheduleRefresh = ( + refresh: AsyncRefreshHeader, + iteration: number, + ) => { timeoutId = setTimeout(() => { void apiGetAsyncRefresh(refresh.id).then((result) => { - if (result.async_refresh.status === 'finished') { - dispatch(completeContextRefresh({ statusId })); + // At three scheduled refreshes, we consider the job + // long-running and attempt to fetch any new replies so far + const isLongRunning = iteration === 3; - if (result.async_refresh.result_count > 0) { - if (autoRefresh) { - void dispatch(fetchContext({ statusId })).then(() => { - setLoadingState('idle'); - }); - } else { - setLoadingState('more-available'); - } - } else { - setLoadingState('idle'); - } - } else { - scheduleRefresh(refresh); + const { status, result_count } = result.async_refresh; + + // If the refresh status is not finished and not long-running, + // we just schedule another refresh and exit + if (status === 'running' && !isLongRunning) { + scheduleRefresh(refresh, iteration + 1); + return; } + + // If refresh status is finished, clear `refreshHeader` + // (we don't want to do this if it's just a long-running job) + if (status === 'finished') { + dispatch(completeContextRefresh({ statusId })); + } + + // Exit if there's nothing to fetch + if (result_count === 0) { + if (status === 'finished') { + setLoadingState('idle'); + } else { + scheduleRefresh(refresh, iteration + 1); + } + return; + } + + // A positive result count means there _might_ be new replies, + // so we fetch the context in the background to check if there + // are any new replies. + // If so, they will populate `contexts.pendingReplies[statusId]` + void dispatch(fetchContext({ statusId, prefetchOnly: true })) + .then(() => { + // Reset loading state to `idle`. If the fetch has + // resulted in new pending replies, the `hasPendingReplies` + // flag will switch the loading state to 'more-available' + if (status === 'finished') { + setLoadingState('idle'); + } else { + // Keep background fetch going if `isLongRunning` is true + scheduleRefresh(refresh, iteration + 1); + } + }) + .catch(() => { + // Show an error if the fetch failed + setLoadingState('error'); + }); }); }, refresh.retry * 1000); }; - if (refresh && !wasDismissed) { - scheduleRefresh(refresh); - setLoadingState('loading-initial'); + // Initialise a refresh + if (refreshHeader && !wasDismissed) { + scheduleRefresh(refreshHeader, 1); + setLoadingState('loading'); } return () => { clearTimeout(timeoutId); }; - }, [dispatch, statusId, refresh, autoRefresh, wasDismissed]); + }, [dispatch, statusId, refreshHeader, wasDismissed]); useEffect(() => { // Hide success message after a short delay if (loadingState === 'success') { const timeoutId = setTimeout(() => { setLoadingState('idle'); - }, 3000); + }, 2500); return () => { clearTimeout(timeoutId); @@ -134,20 +165,19 @@ export const RefreshController: React.FC<{ return () => ''; }, [loadingState]); - const handleClick = useCallback(() => { - setLoadingState('loading-more'); - - dispatch(fetchContext({ statusId })) - .then(() => { - setLoadingState('success'); - return ''; - }) - .catch(() => { - setLoadingState('error'); - }); + useEffect(() => { + // Clear pending replies on unmount + return () => { + dispatch(clearPendingReplies({ statusId })); + }; }, [dispatch, statusId]); - if (loadingState === 'loading-initial') { + const handleClick = useCallback(() => { + dispatch(showPendingReplies({ statusId })); + setLoadingState('success'); + }, [dispatch, statusId]); + + if (loadingState === 'loading') { return (
- -
+
{ancestors} diff --git a/app/javascript/mastodon/features/ui/components/compare_history_modal.jsx b/app/javascript/mastodon/features/ui/components/compare_history_modal.jsx index 4227c741317..f260444265d 100644 --- a/app/javascript/mastodon/features/ui/components/compare_history_modal.jsx +++ b/app/javascript/mastodon/features/ui/components/compare_history_modal.jsx @@ -15,6 +15,8 @@ import InlineAccount from 'mastodon/components/inline_account'; import MediaAttachments from 'mastodon/components/media_attachments'; import { RelativeTimestamp } from 'mastodon/components/relative_timestamp'; import emojify from 'mastodon/features/emoji/emoji'; +import { EmojiHTML } from '@/mastodon/components/emoji/html'; +import { CustomEmojiProvider } from '@/mastodon/components/emoji/context'; const mapStateToProps = (state, { statusId }) => ({ language: state.getIn(['statuses', statusId, 'language']), @@ -51,8 +53,8 @@ class CompareHistoryModal extends PureComponent { return obj; }, {}); - const content = { __html: emojify(currentVersion.get('content'), emojiMap) }; - const spoilerContent = { __html: emojify(escapeTextContentForBrowser(currentVersion.get('spoiler_text')), emojiMap) }; + const content = emojify(currentVersion.get('content'), emojiMap); + const spoilerContent = emojify(escapeTextContentForBrowser(currentVersion.get('spoiler_text')), emojiMap); const formattedDate = ; const formattedName = ; @@ -65,43 +67,52 @@ class CompareHistoryModal extends PureComponent { return (
-
- - {label} -
- -
-
- {currentVersion.get('spoiler_text').length > 0 && ( - <> -
-
- - )} - -
- - {!!currentVersion.get('poll') && ( -
-
    - {currentVersion.getIn(['poll', 'options']).map(option => ( -
  • - - - -
  • - ))} -
-
- )} - - + +
+ + {label}
-
+ +
+
+ {currentVersion.get('spoiler_text').length > 0 && ( + <> + +
+ + )} + + + + {!!currentVersion.get('poll') && ( +
+
    + {currentVersion.getIn(['poll', 'options']).map(option => ( +
  • + +
  • + ))} +
+
+ )} + + +
+
+
); } diff --git a/app/javascript/mastodon/features/ui/components/hashtag_menu_controller.tsx b/app/javascript/mastodon/features/ui/components/hashtag_menu_controller.tsx index 6707b246728..6833073813d 100644 --- a/app/javascript/mastodon/features/ui/components/hashtag_menu_controller.tsx +++ b/app/javascript/mastodon/features/ui/components/hashtag_menu_controller.tsx @@ -11,6 +11,8 @@ import type { } from 'react-overlays/esm/usePopper'; import { DropdownMenu } from 'mastodon/components/dropdown_menu'; +import { useIdentity } from 'mastodon/identity_context'; +import type { MenuItem } from 'mastodon/models/dropdown_menu'; import { useAppSelector } from 'mastodon/store'; const messages = defineMessages({ @@ -45,6 +47,7 @@ interface TargetParams { export const HashtagMenuController: React.FC = () => { const intl = useIntl(); + const { signedIn } = useIdentity(); const [open, setOpen] = useState(false); const [{ accountId, hashtag }, setTargetParams] = useState({}); const targetRef = useRef(null); @@ -96,8 +99,8 @@ export const HashtagMenuController: React.FC = () => { targetRef.current = null; }, [setOpen]); - const menu = useMemo( - () => [ + const menu = useMemo(() => { + const arr: MenuItem[] = [ { text: intl.formatMessage(messages.browseHashtag, { hashtag, @@ -111,17 +114,20 @@ export const HashtagMenuController: React.FC = () => { }), to: `/@${account?.acct}/tagged/${hashtag}`, }, - null, - { + ]; + + if (signedIn) { + arr.push(null, { text: intl.formatMessage(messages.muteHashtag, { hashtag, }), href: '/filters', dangerous: true, - }, - ], - [intl, hashtag, account], - ); + }); + } + + return arr; + }, [intl, hashtag, account, signedIn]); if (!open) { return null; diff --git a/app/javascript/mastodon/hooks/useLinks.ts b/app/javascript/mastodon/hooks/useLinks.ts index 00e1dd9bb44..77609181be9 100644 --- a/app/javascript/mastodon/hooks/useLinks.ts +++ b/app/javascript/mastodon/hooks/useLinks.ts @@ -7,6 +7,8 @@ import { isFulfilled, isRejected } from '@reduxjs/toolkit'; import { openURL } from 'mastodon/actions/search'; import { useAppDispatch } from 'mastodon/store'; +import { isModernEmojiEnabled } from '../utils/environment'; + const isMentionClick = (element: HTMLAnchorElement) => element.classList.contains('mention') && !element.classList.contains('hashtag'); @@ -53,6 +55,11 @@ export const useLinks = (skipHashtags?: boolean) => { const handleClick = useCallback( (e: React.MouseEvent) => { + // Exit early if modern emoji is enabled, as this is handled by HandledLink. + if (isModernEmojiEnabled()) { + return; + } + const target = (e.target as HTMLElement).closest('a'); if (!target || e.button !== 0 || e.ctrlKey || e.metaKey) { diff --git a/app/javascript/mastodon/initial_state.ts b/app/javascript/mastodon/initial_state.ts index b6d7d55483f..f28d81a10ce 100644 --- a/app/javascript/mastodon/initial_state.ts +++ b/app/javascript/mastodon/initial_state.ts @@ -32,7 +32,10 @@ interface InitialStateMeta { single_user_mode: boolean; source_url: string; streaming_api_base_url: string; - timeline_preview: boolean; + local_live_feed_access: 'public' | 'authenticated'; + remote_live_feed_access: 'public' | 'authenticated'; + local_topic_feed_access: 'public' | 'authenticated'; + remote_topic_feed_access: 'public' | 'authenticated'; title: string; show_trends: boolean; trends_as_landing_page: boolean; @@ -110,7 +113,10 @@ export const trendsEnabled = getMeta('trends_enabled'); export const showTrends = getMeta('show_trends'); export const singleUserMode = getMeta('single_user_mode'); export const source_url = getMeta('source_url'); -export const timelinePreview = getMeta('timeline_preview'); +export const localLiveFeedAccess = getMeta('local_live_feed_access'); +export const remoteLiveFeedAccess = getMeta('remote_live_feed_access'); +export const localTopicFeedAccess = getMeta('local_topic_feed_access'); +export const remoteTopicFeedAccess = getMeta('remote_topic_feed_access'); export const title = getMeta('title'); export const trendsAsLanding = getMeta('trends_as_landing_page'); export const useBlurhash = getMeta('use_blurhash'); diff --git a/app/javascript/mastodon/locales/be.json b/app/javascript/mastodon/locales/be.json index e51b5a56b1d..0a7b3c805e6 100644 --- a/app/javascript/mastodon/locales/be.json +++ b/app/javascript/mastodon/locales/be.json @@ -257,7 +257,12 @@ "confirmations.revoke_quote.confirm": "Выдаліць допіс", "confirmations.revoke_quote.message": "Гэтае дзеянне немагчыма адмяніць.", "confirmations.revoke_quote.title": "Выдаліць допіс?", + "confirmations.unblock.confirm": "Разблакіраваць", + "confirmations.unblock.title": "Разблакіраваць {name}?", "confirmations.unfollow.confirm": "Адпісацца", + "confirmations.unfollow.title": "Адпісацца ад {name}?", + "confirmations.withdraw_request.confirm": "Адклікаць запыт", + "confirmations.withdraw_request.title": "Адклікаць запыт на падпіску на {name}?", "content_warning.hide": "Схаваць допіс", "content_warning.show": "Усё адно паказаць", "content_warning.show_more": "Паказаць усё роўна", @@ -748,6 +753,7 @@ "privacy.unlisted.short": "Ціхі публічны", "privacy_policy.last_updated": "Адноўлена {date}", "privacy_policy.title": "Палітыка канфідэнцыйнасці", + "quote_error.edit": "Нельга дадаваць цытаты пры рэдагаванні допісаў.", "quote_error.poll": "Нельга цытаваць з апытаннямі.", "quote_error.quote": "За раз дазволена рабіць толькі адну цытату.", "quote_error.unauthorized": "Вы не ўвайшлі, каб цытаваць гэты допіс.", @@ -870,7 +876,6 @@ "status.contains_quote": "Утрымлівае цытату", "status.context.loading": "Загружаюцца іншыя адказы", "status.context.loading_error": "Немагчыма загрузіць новыя адказы", - "status.context.loading_more": "Загружаюцца іншыя адказы", "status.context.loading_success": "Усе адказы загружаныя", "status.context.more_replies_found": "Знойдзеныя іншыя адказы", "status.context.retry": "Паспрабаваць зноў", @@ -918,6 +923,8 @@ "status.quote_private": "Прыватныя допісы нельга цытаваць", "status.quotes": "{count, plural,one {цытата} few {цытаты} other {цытат}}", "status.quotes.empty": "Яшчэ ніхто не цытаваў гэты допіс. Калі гэта адбудзецца, то Вы пабачыце гэта тут.", + "status.quotes.local_other_disclaimer": "Цытаты, у якіх адмовіў аўтар, паказаныя не будуць.", + "status.quotes.remote_other_disclaimer": "Толькі цытаты з {domain} тут будуць гарантавана паказаныя. Цытаты, у якіх адмовіў аўтар, паказаныя не будуць.", "status.read_more": "Чытаць болей", "status.reblog": "Пашырыць", "status.reblog_or_quote": "Пашырыць ці цытаваць", diff --git a/app/javascript/mastodon/locales/br.json b/app/javascript/mastodon/locales/br.json index c33d64a54e5..3d87c0fd93d 100644 --- a/app/javascript/mastodon/locales/br.json +++ b/app/javascript/mastodon/locales/br.json @@ -28,6 +28,7 @@ "account.disable_notifications": "Paouez d'am c'hemenn pa vez embannet traoù gant @{name}", "account.domain_blocking": "Domani stanket", "account.edit_profile": "Kemmañ ar profil", + "account.edit_profile_short": "Kemmañ", "account.enable_notifications": "Ma c'hemenn pa vez embannet traoù gant @{name}", "account.endorse": "Lakaat en a-raok war ar profil", "account.familiar_followers_one": "Heuliet gant {name1}", @@ -39,6 +40,10 @@ "account.featured_tags.last_status_never": "Embann ebet", "account.follow": "Heuliañ", "account.follow_back": "Heuliañ d'ho tro", + "account.follow_back_short": "Heuliañ d'ho tro", + "account.follow_request": "Reked d'ho heuliañ", + "account.follow_request_cancel": "Nullañ ar reked", + "account.follow_request_cancel_short": "Nullañ", "account.followers": "Tud koumanantet", "account.followers.empty": "Den na heul an implijer·ez-mañ c'hoazh.", "account.followers_counter": "{count, plural, one {{counter} heulier} two {{counter} heulier} few {{counter} heulier} many {{counter} heulier} other {{counter} heulier}}", @@ -210,13 +215,19 @@ "confirmations.missing_alt_text.secondary": "Embann memes tra", "confirmations.missing_alt_text.title": "Ouzhpennañ an eiltestenn?", "confirmations.mute.confirm": "Kuzhat", + "confirmations.quiet_post_quote_info.got_it": "Mat eo", "confirmations.redraft.confirm": "Diverkañ ha skrivañ en-dro", "confirmations.redraft.title": "Diverkañ ha skrivañ an embann en-dro?", "confirmations.remove_from_followers.confirm": "Dilemel an heulier·ez", "confirmations.remove_from_followers.title": "Dilemel an heulier·ez?", "confirmations.revoke_quote.confirm": "Dilemel an embannadur", "confirmations.revoke_quote.title": "Dilemel an embannadur?", + "confirmations.unblock.confirm": "Distankañ", + "confirmations.unblock.title": "Distankañ {name}?", "confirmations.unfollow.confirm": "Diheuliañ", + "confirmations.unfollow.title": "Diheuliañ {name}?", + "confirmations.withdraw_request.confirm": "Nullañ ar reked", + "confirmations.withdraw_request.title": "Nullañ ho reked da heuliañ {name}?", "content_warning.hide": "Kuzhat an embannadur", "content_warning.show": "Diskwel memes tra", "content_warning.show_more": "Diskouez muioc'h", @@ -239,6 +250,7 @@ "domain_block_modal.block_account_instead": "Stankañ @{name} kentoc'h", "domain_block_modal.title": "Stankañ an domani?", "domain_pill.server": "Dafariad", + "domain_pill.their_handle": "H·ec'h anaouder:", "domain_pill.username": "Anv-implijer", "domain_pill.whats_in_a_handle": "Petra eo an anaouder?", "domain_pill.your_handle": "Hoc'h anaouder:", @@ -260,6 +272,7 @@ "emoji_button.search_results": "Disoc'hoù an enklask", "emoji_button.symbols": "Arouezioù", "emoji_button.travel": "Beajiñ & Lec'hioù", + "empty_column.account_featured_other.unknown": "N'eo ket bet lakaet netra en a-raok gant ar gont-mañ.", "empty_column.account_suspended": "Kont astalet", "empty_column.account_timeline": "Embannadur ebet amañ!", "empty_column.account_unavailable": "Profil dihegerz", @@ -486,6 +499,7 @@ "notifications.column_settings.admin.sign_up": "Enskrivadurioù nevez :", "notifications.column_settings.alert": "Kemennoù war ar burev", "notifications.column_settings.favourite": "Muiañ-karet:", + "notifications.column_settings.filter_bar.advanced": "Diskouez an holl rummadoù", "notifications.column_settings.follow": "Heulierien nevez:", "notifications.column_settings.follow_request": "Rekedoù heuliañ nevez:", "notifications.column_settings.group": "Strollañ", @@ -511,7 +525,7 @@ "notifications.group": "{count} a gemennoù", "notifications.mark_as_read": "Merkañ an holl kemennoù evel bezañ lennet", "notifications.permission_denied": "Kemennoù war ar burev n'int ket hegerz rak pedadenn aotren ar merdeer a zo bet nullet araok", - "notifications.permission_denied_alert": "Kemennoù wa ar burev na c'hellont ket bezañ lezelet, rak aotre ar merdeer a zo bet nac'het a-raok", + "notifications.permission_denied_alert": "Kemennoù war ar burev na c'hellont ket bezañ lezelet, rak aotre ar merdeer a zo bet nac'het a-raok", "notifications.permission_required": "Kemennoù war ar burev n'int ket hegerz abalamour d'an aotre rekis n'eo ket bet roet.", "notifications.policy.accept": "Asantiñ", "notifications.policy.accept_hint": "Diskouez er c’hemennoù", diff --git a/app/javascript/mastodon/locales/ca.json b/app/javascript/mastodon/locales/ca.json index 1d33a2fec5f..956420026ac 100644 --- a/app/javascript/mastodon/locales/ca.json +++ b/app/javascript/mastodon/locales/ca.json @@ -28,6 +28,7 @@ "account.disable_notifications": "Deixa de notificar-me els tuts de @{name}", "account.domain_blocking": "Bloquem el domini", "account.edit_profile": "Edita el perfil", + "account.edit_profile_short": "Edita", "account.enable_notifications": "Notifica'm els tuts de @{name}", "account.endorse": "Recomana en el perfil", "account.familiar_followers_many": "Seguit per {name1}, {name2} i {othersCount, plural, one {# altre compte} other {# altres comptes}} que coneixeu", @@ -40,6 +41,11 @@ "account.featured_tags.last_status_never": "No hi ha tuts", "account.follow": "Segueix", "account.follow_back": "Segueix tu també", + "account.follow_back_short": "Segueix tu també", + "account.follow_request": "Sol·licita seguir", + "account.follow_request_cancel": "Cancel·la la petició", + "account.follow_request_cancel_short": "Cancel·la", + "account.follow_request_short": "Petició", "account.followers": "Seguidors", "account.followers.empty": "A aquest usuari encara no el segueix ningú.", "account.followers_counter": "{count, plural, one {{counter} seguidor} other {{counter} seguidors}}", @@ -238,6 +244,8 @@ "confirmations.missing_alt_text.secondary": "Publica-la igualment", "confirmations.missing_alt_text.title": "Hi voleu afegir text alternatiu?", "confirmations.mute.confirm": "Silencia", + "confirmations.quiet_post_quote_info.dismiss": "No m'ho tornis a recordar", + "confirmations.quiet_post_quote_info.got_it": "Entesos", "confirmations.redraft.confirm": "Esborra i reescriu", "confirmations.redraft.message": "Segur que vols eliminar aquest tut i tornar a escriure'l? Es perdran tots els impulsos i els favorits, i les respostes al tut original quedaran aïllades.", "confirmations.redraft.title": "Esborrar i reescriure la publicació?", @@ -247,7 +255,12 @@ "confirmations.revoke_quote.confirm": "Eliminar la publicació", "confirmations.revoke_quote.message": "Aquesta acció no es pot desfer.", "confirmations.revoke_quote.title": "Eliminar la publicació?", + "confirmations.unblock.confirm": "Desbloca", + "confirmations.unblock.title": "Desblocar {name}?", "confirmations.unfollow.confirm": "Deixa de seguir", + "confirmations.unfollow.title": "Deixar de seguir {name}?", + "confirmations.withdraw_request.confirm": "Retirar la sol·licitud", + "confirmations.withdraw_request.title": "Retirar la sol·licitud de seguir {name}?", "content_warning.hide": "Amaga la publicació", "content_warning.show": "Mostra-la igualment", "content_warning.show_more": "Mostra'n més", @@ -445,10 +458,12 @@ "ignore_notifications_modal.not_following_title": "Voleu ignorar les notificacions de qui no seguiu?", "ignore_notifications_modal.private_mentions_title": "Voleu ignorar les notificacions de mencions privades no sol·licitades?", "info_button.label": "Ajuda", + "interaction_modal.action": "Per a interactuar amb la publicació de {name} cal que inicieu la sessió en el servidor que feu servir.", "interaction_modal.go": "Endavant", "interaction_modal.no_account_yet": "Encara no teniu cap compte?", "interaction_modal.on_another_server": "A un altre servidor", "interaction_modal.on_this_server": "En aquest servidor", + "interaction_modal.title": "Inicieu la sessió per a continuar", "interaction_modal.username_prompt": "P. ex. {example}", "intervals.full.days": "{number, plural, one {# dia} other {# dies}}", "intervals.full.hours": "{number, plural, one {# hora} other {# hores}}", @@ -726,10 +741,18 @@ "privacy.private.short": "Seguidors", "privacy.public.long": "Tothom dins o fora Mastodon", "privacy.public.short": "Públic", + "privacy.quote.anyone": "{visibility}, qualsevol pot citar", + "privacy.quote.disabled": "{visibility}, cites desactivades", + "privacy.quote.limited": "{visibility}, cites limitades", "privacy.unlisted.additional": "Es comporta igual que públic, excepte que la publicació no apareixerà als canals en directe o etiquetes, l'explora o a la cerca de Mastodon, fins i tot si ho heu activat a nivell de compte.", + "privacy.unlisted.long": "Amagat dels resultats de cerca de Mastodon, de les tendències i de les línies temporals", "privacy.unlisted.short": "Públic silenciós", "privacy_policy.last_updated": "Darrera actualització {date}", "privacy_policy.title": "Política de Privacitat", + "quote_error.poll": "Amb les enquestes no es permeten cites.", + "quote_error.quote": "Només es permet una cita alhora.", + "quote_error.unauthorized": "No se us permet de citar aquesta publicació.", + "quote_error.upload": "Amb media adjunts no es permeten cites.", "recommended": "Recomanat", "refresh": "Actualitza", "regeneration_indicator.please_stand_by": "Espereu.", @@ -745,6 +768,9 @@ "relative_time.minutes": "{number}min", "relative_time.seconds": "{number}s", "relative_time.today": "avui", + "remove_quote_hint.button_label": "Entesos", + "remove_quote_hint.message": "Ho podeu fer des de {icon} al menú d'opcions.", + "remove_quote_hint.title": "Voleu eliminar la vostra publicació citada?", "reply_indicator.attachments": "{count, plural, one {# adjunt} other {# adjunts}}", "reply_indicator.cancel": "Cancel·la", "reply_indicator.poll": "Enquesta", @@ -840,7 +866,15 @@ "status.block": "Bloca @{name}", "status.bookmark": "Marca", "status.cancel_reblog_private": "Desfés l'impuls", + "status.cannot_quote": "No se't permet de citar aquesta publicació", "status.cannot_reblog": "No es pot impulsar aquest tut", + "status.contains_quote": "Conté una cita", + "status.context.loading": "Es carreguen més respostes", + "status.context.loading_error": "No s'han pogut carregar respostes noves", + "status.context.loading_success": "S'han carregat totes les respostes", + "status.context.more_replies_found": "S'han trobat més respostes", + "status.context.retry": "Torna-ho a provar", + "status.context.show": "Mostra", "status.continued_thread": "Continuació del fil", "status.copy": "Copia l'enllaç al tut", "status.delete": "Elimina", @@ -870,24 +904,33 @@ "status.quote": "Cita", "status.quote.cancel": "Canceŀlar la citació", "status.quote_error.filtered": "No es mostra a causa d'un dels vostres filtres", + "status.quote_error.limited_account_hint.action": "Mostra-la igualment", + "status.quote_error.limited_account_hint.title": "Aquest perfil l'han amagat els moderadors de {domain}.", "status.quote_error.not_available": "Publicació no disponible", "status.quote_error.pending_approval": "Publicació pendent", + "status.quote_error.pending_approval_popout.body": "A Mastodon pots controlar si algú et pot citar. Aquesta publicació està pendent mentre esperem l'aprovació de l'autor original.", + "status.quote_error.revoked": "Publicació eliminada per l'autor", "status.quote_followers_only": "Només els seguidors poden citar aquesta publicació", "status.quote_manual_review": "L'autor ho revisarà manualment", + "status.quote_noun": "Cita", "status.quote_policy_change": "Canvieu qui us pot citar", "status.quote_post_author": "S'ha citat una publicació de @{name}", "status.quote_private": "No es poden citar les publicacions privades", "status.quotes": "{count, plural, one {cita} other {cites}}", "status.quotes.empty": "Encara no ha citat aquesta publicació ningú. Quan ho faci algú apareixerà aquí.", + "status.quotes.local_other_disclaimer": "No es mostraran les cites rebutjades per l'autor.", + "status.quotes.remote_other_disclaimer": "Només es garanteix que es mostraran aquí les cites de {domain}. No es mostraran les rebutjades per l'autor.", "status.read_more": "Més informació", "status.reblog": "Impulsa", "status.reblog_or_quote": "Impuls or cita", + "status.reblog_private": "Compartiu de nou amb els vostres seguidors", "status.reblogged_by": "impulsat per {name}", "status.reblogs": "{count, plural, one {impuls} other {impulsos}}", "status.reblogs.empty": "Encara no ha impulsat ningú aquest tut. Quan algú ho faci, apareixerà aquí.", "status.redraft": "Esborra i reescriu", "status.remove_bookmark": "Elimina el marcador", "status.remove_favourite": "Elimina dels preferits", + "status.remove_quote": "Elimina", "status.replied_in_thread": "Respost al fil", "status.replied_to": "En resposta a {name}", "status.reply": "Respon", @@ -932,6 +975,7 @@ "upload_button.label": "Afegeix imatges, un vídeo o un fitxer d'àudio", "upload_error.limit": "S'ha superat el límit de càrrega d'arxius.", "upload_error.poll": "No es permet carregar fitxers a les enquestes.", + "upload_error.quote": "No es permet de carregat fitxer amb cites.", "upload_form.drag_and_drop.instructions": "Per a agafar un fitxer multimèdia adjunt, premeu l'espai o la tecla Enter. Mentre l'arrossegueu, utilitzeu les fletxes per a moure l'adjunt en qualsevol direcció. Premeu espai o Enter un altre cop per a deixar-lo anar a la seva nova posició, o premeu la tecla d'escapament per cancel·lar.", "upload_form.drag_and_drop.on_drag_cancel": "S'ha cancel·lat l'arrossegament. S'ha deixat anar l'adjunt multimèdia {item}.", "upload_form.drag_and_drop.on_drag_end": "S'ha deixat anar l'adjunt multimèdia {item}.", @@ -960,7 +1004,9 @@ "visibility_modal.helper.direct_quoting": "No es poden citar mencions privades fetes a Mastondon.", "visibility_modal.helper.private_quoting": "No es poden citar publicacions fetes a Mastodon només per a seguidors.", "visibility_modal.helper.unlisted_quoting": "Quan la gent et citi les seves publicacions estaran amagades de les línies de temps de tendències.", + "visibility_modal.privacy_label": "Visibilitat", "visibility_modal.quote_followers": "Només seguidors", + "visibility_modal.quote_label": "Qui pot citar", "visibility_modal.quote_nobody": "Només jo", "visibility_modal.quote_public": "Qualsevol", "visibility_modal.save": "Desa" diff --git a/app/javascript/mastodon/locales/cs.json b/app/javascript/mastodon/locales/cs.json index 7b69cdc6542..b9f7d0bdfb5 100644 --- a/app/javascript/mastodon/locales/cs.json +++ b/app/javascript/mastodon/locales/cs.json @@ -257,7 +257,12 @@ "confirmations.revoke_quote.confirm": "Odstranit příspěvek", "confirmations.revoke_quote.message": "Tuto akci nelze vrátit zpět.", "confirmations.revoke_quote.title": "Odstranit příspěvek?", + "confirmations.unblock.confirm": "Odblokovat", + "confirmations.unblock.title": "Odblokovat {name}?", "confirmations.unfollow.confirm": "Přestat sledovat", + "confirmations.unfollow.title": "Přestat sledovat {name}?", + "confirmations.withdraw_request.confirm": "Zrušit žádost", + "confirmations.withdraw_request.title": "Zrušit žádost na sledování {name}?", "content_warning.hide": "Skrýt příspěvek", "content_warning.show": "Přesto zobrazit", "content_warning.show_more": "Zobrazit více", @@ -748,6 +753,7 @@ "privacy.unlisted.short": "Ztišené veřejné", "privacy_policy.last_updated": "Naposledy aktualizováno {date}", "privacy_policy.title": "Zásady ochrany osobních údajů", + "quote_error.edit": "Citáty nemohou být přidány při úpravě příspěvku.", "quote_error.poll": "Citování není u dotazníků povoleno.", "quote_error.quote": "Je povoleno citovat pouze jednou.", "quote_error.unauthorized": "Nemáte oprávnění citovat tento příspěvek.", @@ -870,7 +876,6 @@ "status.contains_quote": "Obsahuje citaci", "status.context.loading": "Načítání dalších odpovědí", "status.context.loading_error": "Nelze načíst nové odpovědi", - "status.context.loading_more": "Načítání dalších odpovědí", "status.context.loading_success": "Všechny odpovědi načteny", "status.context.more_replies_found": "Nalezeny další odpovědi", "status.context.retry": "Zkusit znovu", @@ -918,6 +923,8 @@ "status.quote_private": "Soukromé příspěvky nelze citovat", "status.quotes": "{count, plural, one {citace} few {citace} other {citací}}", "status.quotes.empty": "Tento příspěvek zatím nikdo necitoval. Pokud tak někdo učiní, uvidíte to zde.", + "status.quotes.local_other_disclaimer": "Citace zamítnuté autorem nebudou zobrazeny.", + "status.quotes.remote_other_disclaimer": "Pouze citace z {domain} zde budou zaručeně ukázány. Citace zamítnuté autorem nebudou zobrazeny.", "status.read_more": "Číst více", "status.reblog": "Boostnout", "status.reblog_or_quote": "Boostnout nebo citovat", diff --git a/app/javascript/mastodon/locales/cy.json b/app/javascript/mastodon/locales/cy.json index 843e2ae1879..7bd83922d92 100644 --- a/app/javascript/mastodon/locales/cy.json +++ b/app/javascript/mastodon/locales/cy.json @@ -257,7 +257,12 @@ "confirmations.revoke_quote.confirm": "Dileu'r postiad", "confirmations.revoke_quote.message": "Does dim modd dadwneud y weithred hon.", "confirmations.revoke_quote.title": "Dileu'r postiad?", + "confirmations.unblock.confirm": "Dadrwystro", + "confirmations.unblock.title": "Dadrwystro {name}?", "confirmations.unfollow.confirm": "Dad-ddilyn", + "confirmations.unfollow.title": "Dad-ddilyn {name}", + "confirmations.withdraw_request.confirm": "Tynnu'r cais yn ôl", + "confirmations.withdraw_request.title": "Tynnu nôl y cais i ddilyn {name}?", "content_warning.hide": "Cuddio'r postiad", "content_warning.show": "Dangos beth bynnag", "content_warning.show_more": "Dangos rhagor", @@ -870,7 +875,6 @@ "status.contains_quote": "Yn cynnwys dyfyniad", "status.context.loading": "Yn llwytho mwy o atebion", "status.context.loading_error": "Wedi methu llwytho atebion newydd", - "status.context.loading_more": "Yn llwytho mwy o atebion", "status.context.loading_success": "Wedi llwytho'r holl atebion", "status.context.more_replies_found": "Mwy o atebion wedi'u canfod", "status.context.retry": "Ceisio eto", @@ -916,8 +920,10 @@ "status.quote_policy_change": "Newid pwy all ddyfynnu", "status.quote_post_author": "Wedi dyfynnu postiad gan @{name}", "status.quote_private": "Does dim modd dyfynnu postiadau preifat", - "status.quotes": "{count, plural, zero {}one {dyfyniad} two {ddyfyniad} few {dyfyniad} many {dyfyniad} other {dyfyniad}}", + "status.quotes": "{count, plural, zero {dyfyniadau} one {dyfyniad} two {ddyfyniad} few {dyfyniad} many {dyfyniad} other {dyfyniad}}", "status.quotes.empty": "Does neb wedi dyfynnu'r postiad hwn eto. Pan fydd rhywun yn gwneud hynny, bydd yn ymddangos yma.", + "status.quotes.local_other_disclaimer": "Bydd dyfyniadau wedi'u gwrthod gan yr awdur ddim yn cael eu dangos.", + "status.quotes.remote_other_disclaimer": "Dim ond dyfyniadau o {domain} sy'n siŵr o gael eu dangos yma. Bydd dyfyniadau wedi'u gwrthod gan yr awdur ddim yn cael eu dangos.", "status.read_more": "Darllen rhagor", "status.reblog": "Hybu", "status.reblog_or_quote": "Hybu neu ddyfynnu", diff --git a/app/javascript/mastodon/locales/da.json b/app/javascript/mastodon/locales/da.json index 5c4dc9ff1d4..c36da1a614e 100644 --- a/app/javascript/mastodon/locales/da.json +++ b/app/javascript/mastodon/locales/da.json @@ -753,6 +753,7 @@ "privacy.unlisted.short": "Offentlig (stille)", "privacy_policy.last_updated": "Senest opdateret {date}", "privacy_policy.title": "Privatlivspolitik", + "quote_error.edit": "Citater kan ikke tilføjes ved redigering af et indlæg.", "quote_error.poll": "Citering ikke tilladt i afstemninger.", "quote_error.quote": "Kun ét citat ad gangen er tilladt.", "quote_error.unauthorized": "Du har ikke tilladelse til at citere dette indlæg.", @@ -875,7 +876,6 @@ "status.contains_quote": "Indeholder citat", "status.context.loading": "Indlæser flere svar", "status.context.loading_error": "Kunne ikke indlæse nye svar", - "status.context.loading_more": "Indlæser flere svar", "status.context.loading_success": "Alle svar indlæst", "status.context.more_replies_found": "Flere svar fundet", "status.context.retry": "Prøv igen", diff --git a/app/javascript/mastodon/locales/de.json b/app/javascript/mastodon/locales/de.json index 2ee15010ccf..b7d52e4e501 100644 --- a/app/javascript/mastodon/locales/de.json +++ b/app/javascript/mastodon/locales/de.json @@ -257,8 +257,8 @@ "confirmations.revoke_quote.confirm": "Beitrag entfernen", "confirmations.revoke_quote.message": "Diese Aktion kann nicht rückgängig gemacht werden.", "confirmations.revoke_quote.title": "Beitrag entfernen?", - "confirmations.unblock.confirm": "Nicht mehr blockieren", - "confirmations.unblock.title": "{name} nicht mehr blockieren?", + "confirmations.unblock.confirm": "Entsperren", + "confirmations.unblock.title": "{name} entsperren?", "confirmations.unfollow.confirm": "Entfolgen", "confirmations.unfollow.title": "{name} entfolgen?", "confirmations.withdraw_request.confirm": "Anfrage zurückziehen", @@ -753,6 +753,7 @@ "privacy.unlisted.short": "Öffentlich (still)", "privacy_policy.last_updated": "Stand: {date}", "privacy_policy.title": "Datenschutzerklärung", + "quote_error.edit": "Beim Bearbeiten eines Beitrags können keine Zitate hinzugefügt werden.", "quote_error.poll": "Zitieren ist bei Umfragen nicht gestattet.", "quote_error.quote": "Es ist jeweils nur ein Zitat zulässig.", "quote_error.unauthorized": "Du bist nicht berechtigt, diesen Beitrag zu zitieren.", @@ -875,7 +876,6 @@ "status.contains_quote": "Enthält Zitat", "status.context.loading": "Weitere Antworten laden", "status.context.loading_error": "Weitere Antworten konnten nicht geladen werden", - "status.context.loading_more": "Weitere Antworten laden", "status.context.loading_success": "Alle weiteren Antworten geladen", "status.context.more_replies_found": "Weitere Antworten verfügbar", "status.context.retry": "Erneut versuchen", diff --git a/app/javascript/mastodon/locales/el.json b/app/javascript/mastodon/locales/el.json index 6df9c3c1e2e..400171aeb0a 100644 --- a/app/javascript/mastodon/locales/el.json +++ b/app/javascript/mastodon/locales/el.json @@ -739,7 +739,7 @@ "poll_button.add_poll": "Προσθήκη δημοσκόπησης", "poll_button.remove_poll": "Αφαίρεση δημοσκόπησης", "privacy.change": "Προσαρμογή ιδιωτικότητας ανάρτησης", - "privacy.direct.long": "Όλοι όσοι αναφέρθηκαν στην ανάρτηση", + "privacy.direct.long": "Όλοι όσοι επισημάνθηκαν στην ανάρτηση", "privacy.direct.short": "Ιδιωτική επισήμανση", "privacy.private.long": "Μόνο οι ακόλουθοί σας", "privacy.private.short": "Ακόλουθοι", @@ -753,6 +753,7 @@ "privacy.unlisted.short": "Ήσυχα δημόσια", "privacy_policy.last_updated": "Τελευταία ενημέρωση {date}", "privacy_policy.title": "Πολιτική Απορρήτου", + "quote_error.edit": "Δεν μπορούν να προστεθούν παραθέσεις κατά την επεξεργασία μιας ανάρτησης.", "quote_error.poll": "Η παράθεση δεν επιτρέπεται με δημοσκοπήσεις.", "quote_error.quote": "Επιτρέπεται μόνο μία παράθεση τη φορά.", "quote_error.unauthorized": "Δεν είστε εξουσιοδοτημένοι να παραθέσετε αυτή την ανάρτηση.", @@ -875,7 +876,6 @@ "status.contains_quote": "Περιέχει παράθεση", "status.context.loading": "Φόρτωση περισσότερων απαντήσεων", "status.context.loading_error": "Αδυναμία φόρτωσης νέων απαντήσεων", - "status.context.loading_more": "Φόρτωση περισσότερων απαντήσεων", "status.context.loading_success": "Όλες οι απαντήσεις φορτώθηκαν", "status.context.more_replies_found": "Βρέθηκαν περισσότερες απαντήσεις", "status.context.retry": "Επανάληψη", diff --git a/app/javascript/mastodon/locales/en.json b/app/javascript/mastodon/locales/en.json index a88a2f1801b..6917bfef36c 100644 --- a/app/javascript/mastodon/locales/en.json +++ b/app/javascript/mastodon/locales/en.json @@ -753,6 +753,7 @@ "privacy.unlisted.short": "Quiet public", "privacy_policy.last_updated": "Last updated {date}", "privacy_policy.title": "Privacy Policy", + "quote_error.edit": "Quotes cannot be added when editing a post.", "quote_error.poll": "Quoting is not allowed with polls.", "quote_error.quote": "Only one quote at a time is allowed.", "quote_error.unauthorized": "You are not authorized to quote this post.", @@ -875,8 +876,7 @@ "status.contains_quote": "Contains quote", "status.context.loading": "Loading more replies", "status.context.loading_error": "Couldn't load new replies", - "status.context.loading_more": "Loading more replies", - "status.context.loading_success": "All replies loaded", + "status.context.loading_success": "New replies loaded", "status.context.more_replies_found": "More replies found", "status.context.retry": "Retry", "status.context.show": "Show", diff --git a/app/javascript/mastodon/locales/es-AR.json b/app/javascript/mastodon/locales/es-AR.json index 485ac9036ad..d9b5bdaec58 100644 --- a/app/javascript/mastodon/locales/es-AR.json +++ b/app/javascript/mastodon/locales/es-AR.json @@ -753,6 +753,7 @@ "privacy.unlisted.short": "Público silencioso", "privacy_policy.last_updated": "Última actualización: {date}", "privacy_policy.title": "Política de privacidad", + "quote_error.edit": "Las citas no se pueden agregar al editar un mensaje.", "quote_error.poll": "No se permite citar encuestas.", "quote_error.quote": "Solo se permite una cita a la vez.", "quote_error.unauthorized": "No tenés autorización para citar este mensaje.", @@ -875,7 +876,6 @@ "status.contains_quote": "Contiene cita", "status.context.loading": "Cargando más respuestas", "status.context.loading_error": "No se pudieron cargar nuevas respuestas", - "status.context.loading_more": "Cargando más respuestas", "status.context.loading_success": "Se cargaron todas las respuestas", "status.context.more_replies_found": "Se encontraron más respuestas", "status.context.retry": "Reintentar", @@ -923,8 +923,8 @@ "status.quote_private": "No se pueden citar los mensajes privados", "status.quotes": "{count, plural, one {# voto} other {# votos}}", "status.quotes.empty": "Todavía nadie citó este mensaje. Cuando alguien lo haga, se mostrará acá.", - "status.quotes.local_other_disclaimer": "Las citas rechazadas por el autor no se mostrarán.", - "status.quotes.remote_other_disclaimer": "Solo se muestran las citas de {domain}. Las citas rechazadas por el autor no se mostrarán.", + "status.quotes.local_other_disclaimer": "Las citas rechazadas por el autor no serán mostradas.", + "status.quotes.remote_other_disclaimer": "Solo las citas de {domain} están garantizadas de ser mostradas acá. Las citas rechazadas por el autor no serán mostradas.", "status.read_more": "Leé más", "status.reblog": "Adherir", "status.reblog_or_quote": "Adherir o citar", diff --git a/app/javascript/mastodon/locales/es-MX.json b/app/javascript/mastodon/locales/es-MX.json index 3875b0187d0..a523b32867b 100644 --- a/app/javascript/mastodon/locales/es-MX.json +++ b/app/javascript/mastodon/locales/es-MX.json @@ -753,6 +753,7 @@ "privacy.unlisted.short": "Pública, pero discreta", "privacy_policy.last_updated": "Actualizado por última vez {date}", "privacy_policy.title": "Política de Privacidad", + "quote_error.edit": "No se pueden añadir citas mientras se edita una publicación.", "quote_error.poll": "No se permite citar encuestas.", "quote_error.quote": "Solo se permite una cita a la vez.", "quote_error.unauthorized": "No estás autorizado a citar esta publicación.", @@ -875,7 +876,6 @@ "status.contains_quote": "Contiene cita", "status.context.loading": "Cargando más respuestas", "status.context.loading_error": "No se pudieron cargar nuevas respuestas", - "status.context.loading_more": "Cargando más respuestas", "status.context.loading_success": "Todas las respuestas cargadas", "status.context.more_replies_found": "Se han encontrado más respuestas", "status.context.retry": "Reintentar", @@ -924,7 +924,7 @@ "status.quotes": "{count, plural,one {cita} other {citas}}", "status.quotes.empty": "Nadie ha citado esta publicación todavía. Cuando alguien lo haga, aparecerá aquí.", "status.quotes.local_other_disclaimer": "Las citas rechazadas por el autor no se mostrarán.", - "status.quotes.remote_other_disclaimer": "Solo se muestran las citas de {domain}. Las citas rechazadas por el autor no se mostrarán.", + "status.quotes.remote_other_disclaimer": "Solo se garantiza que se muestren las citas de {domain}. Las citas rechazadas por el autor no se mostrarán.", "status.read_more": "Leer más", "status.reblog": "Impulsar", "status.reblog_or_quote": "Impulsar o citar", diff --git a/app/javascript/mastodon/locales/es.json b/app/javascript/mastodon/locales/es.json index 3123f55b85f..96ae7857430 100644 --- a/app/javascript/mastodon/locales/es.json +++ b/app/javascript/mastodon/locales/es.json @@ -753,6 +753,7 @@ "privacy.unlisted.short": "Pública silenciosa", "privacy_policy.last_updated": "Actualizado por última vez {date}", "privacy_policy.title": "Política de Privacidad", + "quote_error.edit": "No se pueden añadir citas mientras se edita una publicación.", "quote_error.poll": "No es posible citar encuestas.", "quote_error.quote": "Solo se permite una cita a la vez.", "quote_error.unauthorized": "No tienes permiso para citar esta publicación.", @@ -875,7 +876,6 @@ "status.contains_quote": "Contiene cita", "status.context.loading": "Cargando más respuestas", "status.context.loading_error": "No se pudieron cargar nuevas respuestas", - "status.context.loading_more": "Cargando más respuestas", "status.context.loading_success": "Se cargaron todas las respuestas", "status.context.more_replies_found": "Se encontraron más respuestas", "status.context.retry": "Reintentar", @@ -924,7 +924,7 @@ "status.quotes": "{count, plural,one {cita} other {citas}}", "status.quotes.empty": "Nadie ha citado esta publicación todavía. Cuando alguien lo haga, aparecerá aquí.", "status.quotes.local_other_disclaimer": "Las citas rechazadas por el autor no se mostrarán.", - "status.quotes.remote_other_disclaimer": "Solo se muestran las citas de {domain}. Las citas rechazadas por el autor no se mostrarán.", + "status.quotes.remote_other_disclaimer": "Solo se garantiza que se muestren las citas de {domain}. Las citas rechazadas por el autor no se mostrarán.", "status.read_more": "Leer más", "status.reblog": "Impulsar", "status.reblog_or_quote": "Impulsar o citar", diff --git a/app/javascript/mastodon/locales/et.json b/app/javascript/mastodon/locales/et.json index 9175a6cc29e..4848c4f7e15 100644 --- a/app/javascript/mastodon/locales/et.json +++ b/app/javascript/mastodon/locales/et.json @@ -257,7 +257,12 @@ "confirmations.revoke_quote.confirm": "Eemalda postitus", "confirmations.revoke_quote.message": "Seda tegevust ei saa tagasi pöörata.", "confirmations.revoke_quote.title": "Kas eemaldame postituse?", + "confirmations.unblock.confirm": "Lõpeta blokeerimine", + "confirmations.unblock.title": "Kas lõpetad {name} kasutaja blokeerimise?", "confirmations.unfollow.confirm": "Ära jälgi", + "confirmations.unfollow.title": "Kas lõpetad {name} kasutaja jälgimise?", + "confirmations.withdraw_request.confirm": "Tühista päring", + "confirmations.withdraw_request.title": "Tühistad päringu {name} kasutaja jälgimiseks?", "content_warning.hide": "Peida postitus", "content_warning.show": "Näita ikkagi", "content_warning.show_more": "Näita rohkem", @@ -870,7 +875,6 @@ "status.contains_quote": "Sisaldab tsitaati", "status.context.loading": "Laadin veel vastuseid", "status.context.loading_error": "Uute vastuste laadimine ei õnnestunud", - "status.context.loading_more": "Laadin veel vastuseid", "status.context.loading_success": "Kõik vastused on laaditud", "status.context.more_replies_found": "Leidub veel vastuseid", "status.context.retry": "Proovi uuesti", @@ -918,6 +922,8 @@ "status.quote_private": "Otsepostituste tsiteerimine pole võimalik", "status.quotes": "{count, plural, one {# tsiteerimine} other {# tsiteerimist}}", "status.quotes.empty": "Keegi pole seda postitust veel tsiteerinud. Kui keegi seda teeb, siis on ta nähtav siin.", + "status.quotes.local_other_disclaimer": "Autori poolt tagasilükatud tsitaate ei kuvata.", + "status.quotes.remote_other_disclaimer": "Kui kasutaja on {domain} domeenist, siis siin on tagatud vaid tema tsitaatide näitamine. Autori poolt tagasilükatud tsitaate ei kuvata.", "status.read_more": "Loe veel", "status.reblog": "Jaga", "status.reblog_or_quote": "Anna hoogu või tsiteeri", diff --git a/app/javascript/mastodon/locales/fi.json b/app/javascript/mastodon/locales/fi.json index 27b5c209e6d..ca38be95131 100644 --- a/app/javascript/mastodon/locales/fi.json +++ b/app/javascript/mastodon/locales/fi.json @@ -753,6 +753,7 @@ "privacy.unlisted.short": "Vaivihkaa julkinen", "privacy_policy.last_updated": "Päivitetty viimeksi {date}", "privacy_policy.title": "Tietosuojakäytäntö", + "quote_error.edit": "Lainauksia ei voi lisätä julkaisua muokattaessa.", "quote_error.poll": "Äänestysten lainaaminen ei ole sallittua.", "quote_error.quote": "Vain yksi lainaus kerrallaan on sallittu.", "quote_error.unauthorized": "Sinulla ei ole valtuuksia lainata tätä julkaisua.", @@ -875,7 +876,6 @@ "status.contains_quote": "Sisältää lainauksen", "status.context.loading": "Ladataan lisää vastauksia", "status.context.loading_error": "Ei voitu ladata lisää vastauksia", - "status.context.loading_more": "Ladataan lisää vastauksia", "status.context.loading_success": "Kaikki vastaukset ladattu", "status.context.more_replies_found": "Löytyi lisää vastauksia", "status.context.retry": "Yritä uudelleen", diff --git a/app/javascript/mastodon/locales/fo.json b/app/javascript/mastodon/locales/fo.json index 52a385e9528..55a3d2455b8 100644 --- a/app/javascript/mastodon/locales/fo.json +++ b/app/javascript/mastodon/locales/fo.json @@ -19,7 +19,7 @@ "account.badges.group": "Bólkur", "account.block": "Banna @{name}", "account.block_domain": "Banna økisnavnið {domain}", - "account.block_short": "Blokera", + "account.block_short": "Banna", "account.blocked": "Bannað/ur", "account.blocking": "Banni", "account.cancel_follow_request": "Strika fylgjaraumbøn", @@ -257,7 +257,12 @@ "confirmations.revoke_quote.confirm": "Strika post", "confirmations.revoke_quote.message": "Hendan atgerðin kann ikki angrast.", "confirmations.revoke_quote.title": "Strika post?", + "confirmations.unblock.confirm": "Banna ikki", + "confirmations.unblock.title": "Banna ikki {name}?", "confirmations.unfollow.confirm": "Fylg ikki", + "confirmations.unfollow.title": "Gevst at fylgja {name}?", + "confirmations.withdraw_request.confirm": "Tak umbønina aftur", + "confirmations.withdraw_request.title": "Tak umbønina um at fylgja {name} aftur?", "content_warning.hide": "Fjal post", "content_warning.show": "Vís kortini", "content_warning.show_more": "Vís meiri", @@ -748,6 +753,7 @@ "privacy.unlisted.short": "Stillur almenningur", "privacy_policy.last_updated": "Seinast dagført {date}", "privacy_policy.title": "Privatlívspolitikkur", + "quote_error.edit": "Sitatir kunnu ikki leggjast afturat tá tú rættar ein post.", "quote_error.poll": "Tað er ikki loyvt at sitera spurnarkanningar.", "quote_error.quote": "Bara ein sitering er loyvd í senn.", "quote_error.unauthorized": "Tú hevur ikki rættindi at sitera hendan postin.", @@ -870,7 +876,6 @@ "status.contains_quote": "Inniheldur sitat", "status.context.loading": "Tekur fleiri svar niður", "status.context.loading_error": "Fekk ikki tikið nýggj svar niður", - "status.context.loading_more": "Tekur fleiri svar niður", "status.context.loading_success": "Øll svar tikin niður", "status.context.more_replies_found": "Fleiri svar funnin", "status.context.retry": "Royn aftur", @@ -918,6 +923,8 @@ "status.quote_private": "Privatir postar kunnu ikki siterast", "status.quotes": "{count, plural, one {sitat} other {sitat}}", "status.quotes.empty": "Eingin hevur siterað hendan postin enn. Tá onkur siterar postin, verður hann sjónligur her.", + "status.quotes.local_other_disclaimer": "Sitatir, sum eru avvíst av høvundanum, verða ikki víst.", + "status.quotes.remote_other_disclaimer": "Einans sitatir frá {domain} vera garanterað víst her. Sitatir, sum eru avvíst av høvundanum, verða ikki víst.", "status.read_more": "Les meira", "status.reblog": "Stimbra", "status.reblog_or_quote": "Stimbra ella sitera", diff --git a/app/javascript/mastodon/locales/fr-CA.json b/app/javascript/mastodon/locales/fr-CA.json index 63e8fdf2ab7..d5c282d2f89 100644 --- a/app/javascript/mastodon/locales/fr-CA.json +++ b/app/javascript/mastodon/locales/fr-CA.json @@ -251,7 +251,12 @@ "confirmations.revoke_quote.confirm": "Retirer la publication", "confirmations.revoke_quote.message": "Cette action ne peut pas être annulée.", "confirmations.revoke_quote.title": "Retirer la publication ?", + "confirmations.unblock.confirm": "Débloquer", + "confirmations.unblock.title": "Débloquer {name} ?", "confirmations.unfollow.confirm": "Ne plus suivre", + "confirmations.unfollow.title": "Ne plus suivre {name} ?", + "confirmations.withdraw_request.confirm": "Rejeter la demande", + "confirmations.withdraw_request.title": "Rejeter la demande de suivre {name} ?", "content_warning.hide": "Masquer le message", "content_warning.show": "Montrer quand même", "content_warning.show_more": "Montrer plus", @@ -861,6 +866,13 @@ "status.cancel_reblog_private": "Débooster", "status.cannot_quote": "Vous n'êtes pas autorisé à citer ce message", "status.cannot_reblog": "Cette publication ne peut pas être boostée", + "status.contains_quote": "Contient la citation", + "status.context.loading": "Chargement de réponses supplémentaires", + "status.context.loading_error": "Impossible de charger les nouvelles réponses", + "status.context.loading_success": "Toutes les réponses sont chargées", + "status.context.more_replies_found": "Plus de réponses trouvées", + "status.context.retry": "Réessayer", + "status.context.show": "Montrer", "status.continued_thread": "Suite du fil", "status.copy": "Copier un lien vers cette publication", "status.delete": "Supprimer", @@ -890,17 +902,22 @@ "status.quote": "Citer", "status.quote.cancel": "Annuler la citation", "status.quote_error.filtered": "Caché en raison de l'un de vos filtres", + "status.quote_error.limited_account_hint.action": "Afficher quand même", + "status.quote_error.limited_account_hint.title": "Ce profil a été masqué par la modération de {domain}.", "status.quote_error.not_available": "Publication non disponible", "status.quote_error.pending_approval": "Publication en attente", "status.quote_error.pending_approval_popout.body": "Sur Mastodon, vous pouvez contrôler si quelqu'un peut vous citer. Ce message est en attente pendant que nous recevons l'approbation de l'auteur original.", "status.quote_error.revoked": "Post supprimé par l'auteur", "status.quote_followers_only": "Seul·e·s les abonné·e·s peuvent citer cette publication", "status.quote_manual_review": "L'auteur va vérifier manuellement", + "status.quote_noun": "Citation", "status.quote_policy_change": "Changer qui peut vous citer", "status.quote_post_author": "A cité un message par @{name}", "status.quote_private": "Les publications privées ne peuvent pas être citées", "status.quotes": " {count, plural, one {quote} other {quotes}}", "status.quotes.empty": "Personne n'a encore cité ce message. Quand quelqu'un le fera, il apparaîtra ici.", + "status.quotes.local_other_disclaimer": "Les citations rejetées par l'auteur ne seront pas affichées.", + "status.quotes.remote_other_disclaimer": "Seules les citations de {domain} sont garanties d'être affichées ici. Les citations rejetées par l'auteur ne seront pas affichées.", "status.read_more": "En savoir plus", "status.reblog": "Booster", "status.reblog_or_quote": "Boost ou citation", diff --git a/app/javascript/mastodon/locales/fr.json b/app/javascript/mastodon/locales/fr.json index e16e177ca49..cc70dbc68f2 100644 --- a/app/javascript/mastodon/locales/fr.json +++ b/app/javascript/mastodon/locales/fr.json @@ -251,7 +251,12 @@ "confirmations.revoke_quote.confirm": "Retirer la publication", "confirmations.revoke_quote.message": "Cette action ne peut pas être annulée.", "confirmations.revoke_quote.title": "Retirer la publication ?", + "confirmations.unblock.confirm": "Débloquer", + "confirmations.unblock.title": "Débloquer {name} ?", "confirmations.unfollow.confirm": "Ne plus suivre", + "confirmations.unfollow.title": "Ne plus suivre {name} ?", + "confirmations.withdraw_request.confirm": "Rejeter la demande", + "confirmations.withdraw_request.title": "Rejeter la demande de suivre {name} ?", "content_warning.hide": "Masquer le message", "content_warning.show": "Montrer quand même", "content_warning.show_more": "Montrer plus", @@ -861,6 +866,13 @@ "status.cancel_reblog_private": "Annuler le partage", "status.cannot_quote": "Vous n'êtes pas autorisé à citer ce message", "status.cannot_reblog": "Ce message ne peut pas être partagé", + "status.contains_quote": "Contient la citation", + "status.context.loading": "Chargement de réponses supplémentaires", + "status.context.loading_error": "Impossible de charger les nouvelles réponses", + "status.context.loading_success": "Toutes les réponses sont chargées", + "status.context.more_replies_found": "Plus de réponses trouvées", + "status.context.retry": "Réessayer", + "status.context.show": "Montrer", "status.continued_thread": "Suite du fil", "status.copy": "Copier le lien vers le message", "status.delete": "Supprimer", @@ -890,18 +902,23 @@ "status.quote": "Citer", "status.quote.cancel": "Annuler la citation", "status.quote_error.filtered": "Caché en raison de l'un de vos filtres", + "status.quote_error.limited_account_hint.action": "Afficher quand même", + "status.quote_error.limited_account_hint.title": "Ce profil a été masqué par la modération de {domain}.", "status.quote_error.not_available": "Publication non disponible", "status.quote_error.pending_approval": "Publication en attente", "status.quote_error.pending_approval_popout.body": "Sur Mastodon, vous pouvez contrôler si quelqu'un peut vous citer. Ce message est en attente pendant que nous recevons l'approbation de l'auteur original.", "status.quote_error.revoked": "Post supprimé par l'auteur", "status.quote_followers_only": "Seul·e·s les abonné·e·s peuvent citer cette publication", "status.quote_manual_review": "L'auteur va vérifier manuellement", + "status.quote_noun": "Citation", "status.quote_policy_change": "Changer qui peut vous citer", "status.quote_post_author": "A cité un message par @{name}", "status.quote_private": "Les publications privées ne peuvent pas être citées", "status.quotes": " {count, plural, one {quote} other {quotes}}", "status.quotes.empty": "Personne n'a encore cité ce message. Quand quelqu'un le fera, il apparaîtra ici.", - "status.read_more": "En savoir plus", + "status.quotes.local_other_disclaimer": "Les citations rejetées par l'auteur ne seront pas affichées.", + "status.quotes.remote_other_disclaimer": "Seules les citations de {domain} sont garanties d'être affichées ici. Les citations rejetées par l'auteur ne seront pas affichées.", + "status.read_more": "Lire la suite", "status.reblog": "Partager", "status.reblog_or_quote": "Boost ou citation", "status.reblog_private": "Partagez à nouveau avec vos abonnés", diff --git a/app/javascript/mastodon/locales/ga.json b/app/javascript/mastodon/locales/ga.json index cec7a6e8f3d..5b0d00d04c6 100644 --- a/app/javascript/mastodon/locales/ga.json +++ b/app/javascript/mastodon/locales/ga.json @@ -257,7 +257,12 @@ "confirmations.revoke_quote.confirm": "Bain postáil", "confirmations.revoke_quote.message": "Ní féidir an gníomh seo a chealú.", "confirmations.revoke_quote.title": "Bain postáil?", + "confirmations.unblock.confirm": "Díbhlocáil", + "confirmations.unblock.title": "Díbhlocáil {name}?", "confirmations.unfollow.confirm": "Ná lean", + "confirmations.unfollow.title": "Díleanúint {name}?", + "confirmations.withdraw_request.confirm": "Iarratas ar tharraingt siar", + "confirmations.withdraw_request.title": "Iarratas chun {name} a leanúint a tharraingt siar?", "content_warning.hide": "Folaigh postáil", "content_warning.show": "Taispeáin ar aon nós", "content_warning.show_more": "Taispeáin níos mó", @@ -870,7 +875,6 @@ "status.contains_quote": "Tá luachan ann", "status.context.loading": "Ag lódáil tuilleadh freagraí", "status.context.loading_error": "Níorbh fhéidir freagraí nua a lódáil", - "status.context.loading_more": "Ag lódáil tuilleadh freagraí", "status.context.loading_success": "Luchtaithe na freagraí uile", "status.context.more_replies_found": "Tuilleadh freagraí aimsithe", "status.context.retry": "Déan iarracht arís", @@ -918,6 +922,8 @@ "status.quote_private": "Ní féidir poist phríobháideacha a lua", "status.quotes": "{count, plural, one {sliocht} few {sliocht} other {sliocht}}", "status.quotes.empty": "Níl an post seo luaite ag aon duine go fóill. Nuair a dhéanann duine é, taispeánfar anseo é.", + "status.quotes.local_other_disclaimer": "Ní thaispeánfar sleachta ar dhiúltaigh an t-údar dóibh.", + "status.quotes.remote_other_disclaimer": "Níl ráthaíocht ann go dtaispeánfar anseo ach sleachta ó {domain}. Ní thaispeánfar sleachta ar dhiúltaigh an t-údar dóibh.", "status.read_more": "Léan a thuilleadh", "status.reblog": "Treisiú", "status.reblog_or_quote": "Borradh nó luachan", diff --git a/app/javascript/mastodon/locales/gl.json b/app/javascript/mastodon/locales/gl.json index a7e1cfd8c30..0cec616ff04 100644 --- a/app/javascript/mastodon/locales/gl.json +++ b/app/javascript/mastodon/locales/gl.json @@ -753,6 +753,7 @@ "privacy.unlisted.short": "Pública limitada", "privacy_policy.last_updated": "Actualizado por última vez no {date}", "privacy_policy.title": "Política de Privacidade", + "quote_error.edit": "Non se poden engadir citas ao editar unha publicación.", "quote_error.poll": "Non se permite citar as enquisas.", "quote_error.quote": "Só se permite citar unha vez.", "quote_error.unauthorized": "Non tes permiso para citar esta publicación.", @@ -875,7 +876,6 @@ "status.contains_quote": "Contén unha cita", "status.context.loading": "Cargando máis respostas", "status.context.loading_error": "Non se puideron mostrar novas respostas", - "status.context.loading_more": "Cargando máis respostas", "status.context.loading_success": "Móstranse todas as respostas", "status.context.more_replies_found": "Existen máis respostas", "status.context.retry": "Volver tentar", diff --git a/app/javascript/mastodon/locales/he.json b/app/javascript/mastodon/locales/he.json index f67ee0fd693..9e7a90cab1f 100644 --- a/app/javascript/mastodon/locales/he.json +++ b/app/javascript/mastodon/locales/he.json @@ -753,6 +753,7 @@ "privacy.unlisted.short": "ציבורי שקט", "privacy_policy.last_updated": "עודכן לאחרונה {date}", "privacy_policy.title": "מדיניות פרטיות", + "quote_error.edit": "לא ניתן להוסיף ציטוטים בשלב עריכת ההודעה.", "quote_error.poll": "לא ניתן לכלול משאל כאשר מחברים הודעת ציטוט.", "quote_error.quote": "רק ציטוט אחד מותר בכל הודעה.", "quote_error.unauthorized": "אין לך הרשאה לצטט את ההודעה הזו.", @@ -875,7 +876,6 @@ "status.contains_quote": "הודעה מכילה ציטוט", "status.context.loading": "נטענות תשובות נוספות", "status.context.loading_error": "טעינת תשובות נוספות נכשלה", - "status.context.loading_more": "נטענות תשובות נוספות", "status.context.loading_success": "כל התשובות נטענו", "status.context.more_replies_found": "תשובות נוספות נמצאו", "status.context.retry": "נסה שוב", diff --git a/app/javascript/mastodon/locales/hu.json b/app/javascript/mastodon/locales/hu.json index 1aba0615b41..5cc41a13404 100644 --- a/app/javascript/mastodon/locales/hu.json +++ b/app/javascript/mastodon/locales/hu.json @@ -28,6 +28,7 @@ "account.disable_notifications": "Ne figyelmeztessen, ha @{name} bejegyzést tesz közzé", "account.domain_blocking": "Domain tiltás", "account.edit_profile": "Profil szerkesztése", + "account.edit_profile_short": "Szerkesztés", "account.enable_notifications": "Figyelmeztessen, ha @{name} bejegyzést tesz közzé", "account.endorse": "Kiemelés a profilodon", "account.familiar_followers_many": "{name1}, {name2} és még {othersCount, plural, one {egy valaki} other {# valaki}}, akit ismersz", @@ -40,6 +41,11 @@ "account.featured_tags.last_status_never": "Nincs bejegyzés", "account.follow": "Követés", "account.follow_back": "Viszontkövetés", + "account.follow_back_short": "Visszakövetés", + "account.follow_request": "Követési kérés", + "account.follow_request_cancel": "Kérés törlése", + "account.follow_request_cancel_short": "Mégse", + "account.follow_request_short": "Kérés", "account.followers": "Követő", "account.followers.empty": "Ezt a felhasználót még senki sem követi.", "account.followers_counter": "{count, plural, one {{counter} követő} other {{counter} követő}}", @@ -251,7 +257,12 @@ "confirmations.revoke_quote.confirm": "Bejegyzés eltávolítása", "confirmations.revoke_quote.message": "Ez a művelet nem vonható vissza.", "confirmations.revoke_quote.title": "Bejegyzés eltávolítása?", + "confirmations.unblock.confirm": "Tiltás feloldása", + "confirmations.unblock.title": "{name} tiltásának feloldása?", "confirmations.unfollow.confirm": "Követés visszavonása", + "confirmations.unfollow.title": "{name} követésének megszüntetése?", + "confirmations.withdraw_request.confirm": "Kérés visszavonása", + "confirmations.withdraw_request.title": "{name} követése kérésének visszavonása?", "content_warning.hide": "Bejegyzés elrejtése", "content_warning.show": "Megjelenítés mindenképp", "content_warning.show_more": "Több megjelenítése", @@ -742,6 +753,7 @@ "privacy.unlisted.short": "Csendes nyilvános", "privacy_policy.last_updated": "Utoljára frissítve: {date}", "privacy_policy.title": "Adatvédelmi szabályzat", + "quote_error.edit": "Idézés nem adható hozzá bejegyzés szerkesztésekor.", "quote_error.poll": "Az idézés szavazások esetén nincs engedélyezve.", "quote_error.quote": "Egyszerre csak egy idézet van engedélyezve.", "quote_error.unauthorized": "Nem idézheted ezt a bejegyzést.", @@ -862,6 +874,12 @@ "status.cannot_quote": "Nem idézheted ezt a bejegyzést", "status.cannot_reblog": "Ezt a bejegyzést nem lehet megtolni", "status.contains_quote": "Idézést tartalmaz", + "status.context.loading": "Több válasz betöltése", + "status.context.loading_error": "Az új válaszok nem tölthetőek be", + "status.context.loading_success": "Összes válasz betöltve", + "status.context.more_replies_found": "Több válasz található", + "status.context.retry": "Újra", + "status.context.show": "Megjelenítés", "status.continued_thread": "Folytatott szál", "status.copy": "Link másolása bejegyzésbe", "status.delete": "Törlés", @@ -905,6 +923,8 @@ "status.quote_private": "A privát bejegyzések nem idézhetőek", "status.quotes": "{count, plural, one {idézés} other {idézés}}", "status.quotes.empty": "Senki sem idézte még ezt a bejegyzést. Ha valaki megteszi, itt fog megjelenni.", + "status.quotes.local_other_disclaimer": "A szerző által elutasított idézések nem fognak megjelenni.", + "status.quotes.remote_other_disclaimer": "Csak a(z) {domain} idézései jelennek meg itt garantáltan. A szerző által elutasított idézések nem fognak megjelenni.", "status.read_more": "Bővebben", "status.reblog": "Megtolás", "status.reblog_or_quote": "Megtolás vagy idézés", diff --git a/app/javascript/mastodon/locales/ia.json b/app/javascript/mastodon/locales/ia.json index 50b836ad629..4a9929ddc05 100644 --- a/app/javascript/mastodon/locales/ia.json +++ b/app/javascript/mastodon/locales/ia.json @@ -870,7 +870,6 @@ "status.contains_quote": "Contine un citation", "status.context.loading": "Cargante plus responsas", "status.context.loading_error": "Non poteva cargar nove responsas", - "status.context.loading_more": "Cargante plus responsas", "status.context.loading_success": "Tote le responsas cargate", "status.context.more_replies_found": "Plus responsas trovate", "status.context.retry": "Tentar de novo", diff --git a/app/javascript/mastodon/locales/is.json b/app/javascript/mastodon/locales/is.json index 4dbdee7c8c3..7934d15692c 100644 --- a/app/javascript/mastodon/locales/is.json +++ b/app/javascript/mastodon/locales/is.json @@ -875,7 +875,6 @@ "status.contains_quote": "Inniheldur tilvitnun", "status.context.loading": "Hleð inn fleiri svörum", "status.context.loading_error": "Gat ekki hlaðið inn nýjum svörum", - "status.context.loading_more": "Hleð inn fleiri svörum", "status.context.loading_success": "Öllum svörum hlaðið inn", "status.context.more_replies_found": "Fleiri svör fundust", "status.context.retry": "Reyna aftur", diff --git a/app/javascript/mastodon/locales/it.json b/app/javascript/mastodon/locales/it.json index af4b5d4866f..bd84dfcadee 100644 --- a/app/javascript/mastodon/locales/it.json +++ b/app/javascript/mastodon/locales/it.json @@ -28,6 +28,7 @@ "account.disable_notifications": "Smetti di avvisarmi quando @{name} pubblica un post", "account.domain_blocking": "Account di un dominio bloccato", "account.edit_profile": "Modifica profilo", + "account.edit_profile_short": "Modifica", "account.enable_notifications": "Avvisami quando @{name} pubblica un post", "account.endorse": "In evidenza sul profilo", "account.familiar_followers_many": "Seguito da {name1}, {name2}, e {othersCount, plural, one {un altro che conosci} other {# altri che conosci}}", @@ -40,6 +41,11 @@ "account.featured_tags.last_status_never": "Nessun post", "account.follow": "Segui", "account.follow_back": "Segui a tua volta", + "account.follow_back_short": "Segui a tua volta", + "account.follow_request": "Richiesta di seguire", + "account.follow_request_cancel": "Annulla la richiesta", + "account.follow_request_cancel_short": "Annulla", + "account.follow_request_short": "Richiesta", "account.followers": "Follower", "account.followers.empty": "Ancora nessuno segue questo utente.", "account.followers_counter": "{count, plural, one {{counter} seguace} other {{counter} seguaci}}", @@ -251,7 +257,12 @@ "confirmations.revoke_quote.confirm": "Elimina il post", "confirmations.revoke_quote.message": "Questa azione non può essere annullata.", "confirmations.revoke_quote.title": "Rimuovere il post?", + "confirmations.unblock.confirm": "Sblocca", + "confirmations.unblock.title": "Sbloccare {name}?", "confirmations.unfollow.confirm": "Smetti di seguire", + "confirmations.unfollow.title": "Smettere di seguire {name}?", + "confirmations.withdraw_request.confirm": "Annulla la richiesta", + "confirmations.withdraw_request.title": "Annullare la richiesta di seguire {name}?", "content_warning.hide": "Nascondi post", "content_warning.show": "Mostra comunque", "content_warning.show_more": "Mostra di più", @@ -864,7 +875,6 @@ "status.contains_quote": "Contiene una citazione", "status.context.loading": "Caricamento di altre risposte", "status.context.loading_error": "Impossibile caricare nuove risposte", - "status.context.loading_more": "Caricamento di altre risposte", "status.context.loading_success": "Tutte le risposte caricate", "status.context.more_replies_found": "Sono state trovate altre risposte", "status.context.retry": "Riprova", @@ -912,6 +922,8 @@ "status.quote_private": "I post privati non possono essere citati", "status.quotes": "{count, plural, one {citazione} other {citazioni}}", "status.quotes.empty": "Nessuno ha ancora citato questo post. Quando qualcuno lo farà, verrà visualizzato qui.", + "status.quotes.local_other_disclaimer": "Le citazioni rifiutate dall'autore non verranno mostrate.", + "status.quotes.remote_other_disclaimer": "Solo le citazioni provenienti da {domain} saranno mostrate qui. Le citazioni rifiutate dall'autore non saranno mostrate.", "status.read_more": "Leggi di più", "status.reblog": "Reblog", "status.reblog_or_quote": "Condividi o cita", diff --git a/app/javascript/mastodon/locales/ku.json b/app/javascript/mastodon/locales/ku.json index d641c896237..cf8d3e2bece 100644 --- a/app/javascript/mastodon/locales/ku.json +++ b/app/javascript/mastodon/locales/ku.json @@ -1,6 +1,7 @@ { "about.blocks": "Rajekarên çavdêrkirî", "about.contact": "Têkilî:", + "about.default_locale": "Berdest", "about.disclaimer": "Mastodon belaş e, nermalaveke çavkaniya vekirî ye û markeyeke Mastodon gGmbHê ye.", "about.domain_blocks.no_reason_available": "Sedem ne berdest e", "about.domain_blocks.preamble": "Mastodon bi gelemperî dihêle ku tu naverokê bibînî û bi bikarhênerên ji rajekareke din a li fendiverse re têkilî dayne. Ev awaretyên ku li ser vê rajekara taybetî hatine çêkirin ev in.", @@ -8,6 +9,7 @@ "about.domain_blocks.silenced.title": "Sînorkirî", "about.domain_blocks.suspended.explanation": "Dê tu daneya ji van rajekaran neyê berhev kirin, tomarkirin an jî guhertin, ku têkilî an danûstendinek bi bikarhênerên van rajekaran re tune dike.", "about.domain_blocks.suspended.title": "Hatiye rawestandin", + "about.language_label": "Ziman", "about.not_available": "Ev zanyarî li ser vê rajekarê nehatine peydakirin.", "about.powered_by": "Medyaya civakî ya nenavendî bi hêzdariya {mastodon}", "about.rules": "Rêbazên rajekar", @@ -19,17 +21,25 @@ "account.block_domain": "Navpera {domain} asteng bike", "account.block_short": "Asteng bike", "account.blocked": "Astengkirî", + "account.blocking": "Astengkirin", "account.cancel_follow_request": "Daxwaza şopandinê vekişîne", "account.copy": "Girêdanê bo profîlê jê bigire", "account.direct": "Bi taybetî qale @{name} bike", "account.disable_notifications": "Êdî min agahdar neke gava @{name} diweşîne", "account.edit_profile": "Profîlê serrast bike", + "account.edit_profile_short": "Serrast bike", "account.enable_notifications": "Min agahdar bike gava @{name} diweşîne", "account.endorse": "Taybetiyên li ser profîl", + "account.featured.accounts": "Profîl", + "account.featured.hashtags": "Hashtag", "account.featured_tags.last_status_at": "Şandiya dawî di {date} de", "account.featured_tags.last_status_never": "Şandî tune ne", "account.follow": "Bişopîne", "account.follow_back": "Bişopîne", + "account.follow_request": "Bo şopandinê daxwaz bike", + "account.follow_request_cancel": "Daxwazê têk bibe", + "account.follow_request_cancel_short": "Têk bibe", + "account.follow_request_short": "Daxwaz bike", "account.followers": "Şopîner", "account.followers.empty": "Kesekî hin ev bikarhêner neşopandiye.", "account.followers_counter": "{count, plural, one {{counter} şopîner} other {{counter} şopîner}}", diff --git a/app/javascript/mastodon/locales/lv.json b/app/javascript/mastodon/locales/lv.json index 9d289c5c53c..6f2fcb03729 100644 --- a/app/javascript/mastodon/locales/lv.json +++ b/app/javascript/mastodon/locales/lv.json @@ -322,6 +322,7 @@ "errors.unexpected_crash.copy_stacktrace": "Kopēt stacktrace uz starpliktuvi", "errors.unexpected_crash.report_issue": "Ziņot par problēmu", "explore.suggested_follows": "Cilvēki", + "explore.title": "Populārākie", "explore.trending_links": "Jaunumi", "explore.trending_statuses": "Ieraksti", "explore.trending_tags": "Tēmturi", @@ -487,8 +488,10 @@ "mute_modal.show_options": "Parādīt iespējas", "mute_modal.title": "Apklusināt lietotāju?", "navigation_bar.about": "Par", + "navigation_bar.account_settings": "Parole un drošība", "navigation_bar.administration": "Pārvaldība", "navigation_bar.advanced_interface": "Atvērt paplašinātā tīmekļa saskarnē", + "navigation_bar.automated_deletion": "Automātiska ziņu dzēšana", "navigation_bar.blocks": "Bloķētie lietotāji", "navigation_bar.bookmarks": "Grāmatzīmes", "navigation_bar.direct": "Privātas pieminēšanas", @@ -498,6 +501,7 @@ "navigation_bar.follow_requests": "Sekošanas pieprasījumi", "navigation_bar.followed_tags": "Sekojamie tēmturi", "navigation_bar.follows_and_followers": "Seko un sekotāji", + "navigation_bar.import_export": "Imports un eksports", "navigation_bar.lists": "Saraksti", "navigation_bar.logout": "Iziet", "navigation_bar.moderation": "Satura pārraudzība", @@ -505,6 +509,7 @@ "navigation_bar.mutes": "Apklusinātie lietotāji", "navigation_bar.opened_in_classic_interface": "Ieraksti, konti un citas noteiktas lapas pēc noklusējuma tiek atvērtas klasiskajā tīmekļa saskarnē.", "navigation_bar.preferences": "Iestatījumi", + "navigation_bar.privacy_and_reach": "Privātums un sasniedzamība", "navigation_bar.search": "Meklēt", "not_signed_in_indicator.not_signed_in": "Ir jāpiesakās, lai piekļūtu šim resursam.", "notification.admin.report": "{name} ziņoja par {target}", diff --git a/app/javascript/mastodon/locales/nan.json b/app/javascript/mastodon/locales/nan.json index a4ffafbe5cc..5d864eeddf1 100644 --- a/app/javascript/mastodon/locales/nan.json +++ b/app/javascript/mastodon/locales/nan.json @@ -257,7 +257,12 @@ "confirmations.revoke_quote.confirm": "Thâi掉PO文", "confirmations.revoke_quote.message": "Tsit ê動作bē當復原。", "confirmations.revoke_quote.title": "Kám beh thâi掉PO文?", + "confirmations.unblock.confirm": "取消封鎖", + "confirmations.unblock.title": "取消封鎖 {name}?", "confirmations.unfollow.confirm": "取消跟tuè", + "confirmations.unfollow.title": "取消跟tuè {name}?", + "confirmations.withdraw_request.confirm": "Kā跟tuè請求收tńg去", + "confirmations.withdraw_request.title": "Kám beh收tńg去跟tuè {name} ê請求?", "content_warning.hide": "Am-khàm PO文", "content_warning.show": "Mā tio̍h顯示", "content_warning.show_more": "其他內容", @@ -870,7 +875,6 @@ "status.contains_quote": "包含引用", "status.context.loading": "載入其他回應", "status.context.loading_error": "Bē當載入新回應", - "status.context.loading_more": "載入其他回應", "status.context.loading_success": "回應lóng載入ah", "status.context.more_replies_found": "Tshuē-tio̍h其他回應", "status.context.retry": "Koh試", @@ -917,6 +921,8 @@ "status.quote_private": "私人PO文bē當引用", "status.quotes": "{count, plural, other {# 篇引用ê PO文}}", "status.quotes.empty": "Iáu無lâng引用tsit篇PO文。Nā是有lâng引用,ē佇tsia顯示。.", + "status.quotes.local_other_disclaimer": "Hōo作者拒絕引用ê引文bē當顯示。", + "status.quotes.remote_other_disclaimer": "Kan-ta tuì {domain} 來ê引文tsiah保證佇tsia顯示。Hōo作者拒絕ê引文buē顯示。", "status.read_more": "讀詳細", "status.reblog": "轉送", "status.reblog_or_quote": "轉送á是引用", diff --git a/app/javascript/mastodon/locales/nl.json b/app/javascript/mastodon/locales/nl.json index 54f14fde278..12ffbec03df 100644 --- a/app/javascript/mastodon/locales/nl.json +++ b/app/javascript/mastodon/locales/nl.json @@ -247,7 +247,7 @@ "confirmations.quiet_post_quote_info.dismiss": "Herinner me er niet nogmaals aan", "confirmations.quiet_post_quote_info.got_it": "Begrepen", "confirmations.quiet_post_quote_info.message": "Wanneer je een minder openbaar bericht citeert, verschijnt jouw bericht niet onder trends.", - "confirmations.quiet_post_quote_info.title": "Minder openbare berichten citeren", + "confirmations.quiet_post_quote_info.title": "Berichten die minder openbaar zijn citeren", "confirmations.redraft.confirm": "Verwijderen en herschrijven", "confirmations.redraft.message": "Weet je zeker dat je dit bericht wilt verwijderen en herschrijven? Je verliest wel de boosts en favorieten, en de reacties op het originele bericht raak je kwijt.", "confirmations.redraft.title": "Bericht verwijderen en herschrijven?", @@ -753,6 +753,7 @@ "privacy.unlisted.short": "Minder openbaar", "privacy_policy.last_updated": "Laatst bijgewerkt op {date}", "privacy_policy.title": "Privacybeleid", + "quote_error.edit": "Citaten kunnen niet tijdens het bewerken van een bericht worden toegevoegd.", "quote_error.poll": "Het is niet mogelijk om polls te citeren.", "quote_error.quote": "Je kunt maar één bericht per keer citeren.", "quote_error.unauthorized": "Je bent niet gemachtigd om dit bericht te citeren.", @@ -875,7 +876,6 @@ "status.contains_quote": "Bevat citaat", "status.context.loading": "Meer reacties laden", "status.context.loading_error": "Kon geen nieuwe reacties laden", - "status.context.loading_more": "Meer reacties laden", "status.context.loading_success": "Alle reacties zijn geladen", "status.context.more_replies_found": "Meer reacties gevonden", "status.context.retry": "Opnieuw proberen", diff --git a/app/javascript/mastodon/locales/nn.json b/app/javascript/mastodon/locales/nn.json index f13b1297a71..faa4efe61fb 100644 --- a/app/javascript/mastodon/locales/nn.json +++ b/app/javascript/mastodon/locales/nn.json @@ -28,6 +28,7 @@ "account.disable_notifications": "Slutt å varsle meg når @{name} skriv innlegg", "account.domain_blocking": "Blokkerer domenet", "account.edit_profile": "Rediger profil", + "account.edit_profile_short": "Rediger", "account.enable_notifications": "Varsle meg når @{name} skriv innlegg", "account.endorse": "Vis på profilen", "account.familiar_followers_many": "Fylgt av {name1}, {name2}, og {othersCount, plural, one {ein annan du kjenner} other {# andre du kjenner}}", @@ -40,6 +41,11 @@ "account.featured_tags.last_status_never": "Ingen innlegg", "account.follow": "Fylg", "account.follow_back": "Fylg tilbake", + "account.follow_back_short": "Fylg tilbake", + "account.follow_request": "Folk som vil fylgja deg", + "account.follow_request_cancel": "Avbrit førespurnaden", + "account.follow_request_cancel_short": "Avbryt", + "account.follow_request_short": "Førespurnad", "account.followers": "Fylgjarar", "account.followers.empty": "Ingen fylgjer denne brukaren enno.", "account.followers_counter": "{count, plural, one {{counter} fylgjar} other {{counter} fylgjarar}}", @@ -251,7 +257,12 @@ "confirmations.revoke_quote.confirm": "Fjern innlegget", "confirmations.revoke_quote.message": "Du kan ikkje angra denne handlinga.", "confirmations.revoke_quote.title": "Fjern innlegget?", + "confirmations.unblock.confirm": "Opphev blokkeringa", + "confirmations.unblock.title": "Opphev blokkeringa av {name}?", "confirmations.unfollow.confirm": "Slutt å fylgja", + "confirmations.unfollow.title": "Slutt å fylgja {name}?", + "confirmations.withdraw_request.confirm": "Trekk attende førespurnad", + "confirmations.withdraw_request.title": "Trekkja tilbake førespurnaden om å fylgja {name}?", "content_warning.hide": "Gøym innlegg", "content_warning.show": "Vis likevel", "content_warning.show_more": "Vis meir", @@ -861,6 +872,13 @@ "status.cancel_reblog_private": "Opphev framheving", "status.cannot_quote": "Du har ikkje løyve til å sitera dette innlegget", "status.cannot_reblog": "Du kan ikkje framheva dette innlegget", + "status.contains_quote": "Inneheld eit sitat", + "status.context.loading": "Lastar fleire svar", + "status.context.loading_error": "Kunne ikkje lasta nye svar", + "status.context.loading_success": "Alle svara er lasta", + "status.context.more_replies_found": "Fann fleire svar", + "status.context.retry": "Prøv om att", + "status.context.show": "Vis", "status.continued_thread": "Framhald til tråden", "status.copy": "Kopier lenke til status", "status.delete": "Slett", @@ -890,17 +908,22 @@ "status.quote": "Siter", "status.quote.cancel": "Avbryt siteringa", "status.quote_error.filtered": "Gøymt på grunn av eitt av filtra dine", + "status.quote_error.limited_account_hint.action": "Vis likevel", + "status.quote_error.limited_account_hint.title": "Denne kontoen har vorte skjult av moderatorane på {domain}.", "status.quote_error.not_available": "Innlegget er ikkje tilgjengeleg", "status.quote_error.pending_approval": "Innlegget ventar", "status.quote_error.pending_approval_popout.body": "På Mastodon kan du kontrollera om folk får sitera deg. Innlegget ditt ventar medan me ventar på at opphavspersonen godkjenner det.", "status.quote_error.revoked": "Innlegget er sletta av skribenten", "status.quote_followers_only": "Berre fylgjarar kan sitera dette innlegget", "status.quote_manual_review": "Skribenten ser gjennom manuelt", + "status.quote_noun": "Sitat", "status.quote_policy_change": "Byt kven som kan sitera", "status.quote_post_author": "Siterte eit innlegg av @{name}", "status.quote_private": "Du kan ikkje sitera private innlegg", "status.quotes": "{count, plural, one {sitat} other {sitat}}", "status.quotes.empty": "Ingen har sitert dette innlegget enno. Når nokon gje det, vil det dukka opp her.", + "status.quotes.local_other_disclaimer": "Sitat som skribenten avviser, vil ikkje syna.", + "status.quotes.remote_other_disclaimer": "Berre sitat frå {domain} er garanterte å syna her. Sitat som skribenten har avvist, vil ikkje syna.", "status.read_more": "Les meir", "status.reblog": "Framhev", "status.reblog_or_quote": "Framhev eller siter", diff --git a/app/javascript/mastodon/locales/pt-PT.json b/app/javascript/mastodon/locales/pt-PT.json index 751db6fdd4d..82fa079e9b2 100644 --- a/app/javascript/mastodon/locales/pt-PT.json +++ b/app/javascript/mastodon/locales/pt-PT.json @@ -870,7 +870,6 @@ "status.contains_quote": "Contém citação", "status.context.loading": "A carregar mais respostas", "status.context.loading_error": "Não foi possível carregar novas respostas", - "status.context.loading_more": "A carregar mais respostas", "status.context.loading_success": "Todas as respostas carregadas", "status.context.more_replies_found": "Foram encontradas mais respostas", "status.context.retry": "Repetir", diff --git a/app/javascript/mastodon/locales/sk.json b/app/javascript/mastodon/locales/sk.json index ffc36973931..c11df5d0d2e 100644 --- a/app/javascript/mastodon/locales/sk.json +++ b/app/javascript/mastodon/locales/sk.json @@ -1,6 +1,7 @@ { "about.blocks": "Moderované servery", "about.contact": "Kontakt:", + "about.default_locale": "Predvolený", "about.disclaimer": "Mastodon je bezplatný open-source softvér s otvoreným zdrojovým kódom a ochranná známka spoločnosti Mastodon gGmbH.", "about.domain_blocks.no_reason_available": "Dôvod nebol uvedený", "about.domain_blocks.preamble": "Mastodon vo všeobecnosti umožňuje prezerať obsah a komunikovať s používateľmi z akéhokoľvek iného servera vo fediverze. Tu sú uvedené výnimky, ktoré boli urobené na tomto konkrétnom serveri.", @@ -20,13 +21,17 @@ "account.block_domain": "Blokovať doménu {domain}", "account.block_short": "Blokovať", "account.blocked": "Účet blokovaný", + "account.blocking": "Blokované", "account.cancel_follow_request": "Zrušiť žiadosť o sledovanie", "account.copy": "Skopírovať odkaz na profil", "account.direct": "Súkromne označiť @{name}", "account.disable_notifications": "Zrušiť upozornenia na príspevky od @{name}", + "account.domain_blocking": "Blokované domény", "account.edit_profile": "Upraviť profil", + "account.edit_profile_short": "Upraviť", "account.enable_notifications": "Zapnúť upozornenia na príspevky od @{name}", "account.endorse": "Zobraziť na vlastnom profile", + "account.familiar_followers_many": "Sleduje {name1}, {name2} a {othersCount, plural, one {ďalší účet, ktorý poznáte} few {# ďalšie účty, ktoré poznáte} many {#} other {# ďalších účtov, ktoré poznáte}}", "account.familiar_followers_one": "Nasledovanie od {name1}", "account.familiar_followers_two": "Nasledovanie od {name1} a {name2}", "account.featured": "Zviditeľnené", @@ -36,13 +41,19 @@ "account.featured_tags.last_status_never": "Žiadne príspevky", "account.follow": "Sledovať", "account.follow_back": "Sledovať späť", - "account.followers": "Sledovatelia", + "account.follow_back_short": "Sledovať späť", + "account.follow_request": "Požiadať o sledovanie", + "account.follow_request_cancel": "Zrušiť žiadosť", + "account.follow_request_cancel_short": "Zrušiť", + "account.follow_request_short": "Požiadať", + "account.followers": "Sledujúce účty", "account.followers.empty": "Ešte nikto nesleduje tohto užívateľa.", - "account.followers_counter": "{count, plural, one {{counter} sledujúci} other {{counter} sledujúci}}", - "account.following": "Sledovaný účet", + "account.followers_counter": "{count, plural, one {{counter} sledujúci účet} few {{counter} sledujúce účty} many {{counter} followers} other {{counter} sledujúcich účtov}}", + "account.followers_you_know_counter": "{count, one {{counter}, ktorý poznáte}, few {{counter}, ktoré poznáte}, many {{counter}, kterých znáte} other {{counter}, ktoré poznáte}}", + "account.following": "Sledovaných účtov", "account.following_counter": "{count, plural, one {{counter} sledovaných} other {{counter} sledovaných}}", "account.follows.empty": "Tento účet ešte nikoho nesleduje.", - "account.follows_you": "Nasleduje ťa", + "account.follows_you": "Sleduje vás", "account.go_to_profile": "Prejsť na profil", "account.hide_reblogs": "Skryť zdieľania od @{name}", "account.in_memoriam": "In memoriam.", @@ -58,13 +69,15 @@ "account.mute_short": "Stíšiť", "account.muted": "Účet stíšený", "account.muting": "Stíšenie", - "account.mutual": "Nasledujete sa navzájom", + "account.mutual": "Sledujete sa navzájom", "account.no_bio": "Nie je uvedený žiadny popis.", "account.open_original_page": "Otvoriť pôvodnú stránku", "account.posts": "Príspevky", "account.posts_with_replies": "Príspevky a odpovede", + "account.remove_from_followers": "Zrušiť sledovanie od {name}", "account.report": "Nahlásiť @{name}", "account.requested_follow": "{name} vás chce sledovať", + "account.requests_to_follow_you": "Žiadosti o sledovanie", "account.share": "Zdieľaj profil @{name}", "account.show_reblogs": "Zobrazovať zdieľania od @{name}", "account.statuses_counter": "{count, plural, one {{counter} príspevok} other {{counter} príspevkov}}", @@ -91,26 +104,37 @@ "alert.rate_limited.title": "Priveľa žiadostí", "alert.unexpected.message": "Vyskytla sa nečakaná chyba.", "alert.unexpected.title": "Ups!", - "alt_text_badge.title": "Alternatívny popis", - "alt_text_modal.add_text_from_image": "Pridaj text z obrázka", + "alt_text_badge.title": "Opis", + "alt_text_modal.add_alt_text": "Pridať opis", + "alt_text_modal.add_text_from_image": "Pridať text z obrázka", "alt_text_modal.cancel": "Zrušiť", + "alt_text_modal.change_thumbnail": "Zmeniť náhľad", + "alt_text_modal.describe_for_people_with_hearing_impairments": "Opíšte obsah pre ľudí so sluchovým postihnutím…", + "alt_text_modal.describe_for_people_with_visual_impairments": "Opíšte obsah pre ľudí so zrakovým postihnutím…", "alt_text_modal.done": "Hotovo", "announcement.announcement": "Oznámenie", - "annual_report.summary.archetype.oracle": "Veštec", + "annual_report.summary.archetype.booster": "Zdieľač*ka", + "annual_report.summary.archetype.lurker": "Sliedič*ka", + "annual_report.summary.archetype.oracle": "Divoká karta", + "annual_report.summary.archetype.pollster": "Anketár*ka", + "annual_report.summary.archetype.replier": "Hlasná trúba", "annual_report.summary.followers.followers": "sledovatelia", "annual_report.summary.followers.total": "{count} celkovo", "annual_report.summary.here_it_is": "Tu je tvoja {year} v zhrnutí:", "annual_report.summary.highlighted_post.by_favourites": "najviac obľúbený príspevok", - "annual_report.summary.highlighted_post.by_reblogs": "najviac vyzdvihovaný príspevok", + "annual_report.summary.highlighted_post.by_reblogs": "najviac zdieľaný príspevok", "annual_report.summary.highlighted_post.by_replies": "príspevok s najviac odpoveďami", + "annual_report.summary.highlighted_post.possessive": "{name}", "annual_report.summary.most_used_app.most_used_app": "najviac používaná aplikácia", "annual_report.summary.most_used_hashtag.most_used_hashtag": "najviac užívaný hashtag", "annual_report.summary.most_used_hashtag.none": "Žiaden", "annual_report.summary.new_posts.new_posts": "nové príspevky", + "annual_report.summary.percentile.text": "Takže patríte do topúčtov na {domain}", "annual_report.summary.percentile.we_wont_tell_bernie": "Nepovieme Berniemu.", "annual_report.summary.thanks": "Vďaka, že si súčasťou Mastodonu!", "attachments_list.unprocessed": "(nespracované)", "audio.hide": "Skryť zvuk", + "block_modal.remote_users_caveat": "Požiadame server {domain} o rešpektovanie vášho rozhodnutia. Nevieme to však zaručiť, keďže niektoré servery pristupujú k blokovaniu inak. Verejné príspevky sa stále môžu zobrazovať neprihláseným ľuďom.", "block_modal.show_less": "Zobraziť menej", "block_modal.show_more": "Zobraziť viac", "block_modal.they_cant_mention": "Nemôžu ťa spomenúť, alebo nasledovať.", @@ -119,7 +143,8 @@ "block_modal.title": "Blokovať užívateľa?", "block_modal.you_wont_see_mentions": "Neuvidíš príspevky, ktoré ich spomínajú.", "boost_modal.combo": "Nabudúce môžete preskočiť stlačením {combo}", - "boost_modal.reblog": "Vyzdvihnúť príspevok?", + "boost_modal.reblog": "Zdieľať príspevok?", + "boost_modal.undo_reblog": "Zrušiť zdieľanie?", "bundle_column_error.copy_stacktrace": "Kopírovať chybovú hlášku", "bundle_column_error.error.body": "Požadovanú stránku nebolo možné vykresliť. Môže to byť spôsobené chybou v našom kóde alebo problémom s kompatibilitou prehliadača.", "bundle_column_error.error.title": "Ale nie!", @@ -130,6 +155,7 @@ "bundle_column_error.routing.body": "Žiadaná stránka nebola nájdená. Ste si istí, že zadaná adresa URL je správna?", "bundle_column_error.routing.title": "404", "bundle_modal_error.close": "Zatvoriť", + "bundle_modal_error.message": "Pri načítavaní tejto obrazovky nastala chyba.", "bundle_modal_error.retry": "Skúsiť znova", "closed_registrations.other_server_instructions": "Keďže Mastodon je decentralizovaný, môžete si vytvoriť účet na inom serveri a stále komunikovať s týmto serverom.", "closed_registrations_modal.description": "Vytvorenie účtu na {domain} nie je v súčasnosti možné, ale myslite na to, že na používanie Mastodonu nepotrebujete účet práve na {domain}.", @@ -145,7 +171,7 @@ "column.directory": "Prehľadávať profily", "column.domain_blocks": "Blokované domény", "column.edit_list": "Uprav zoznam", - "column.favourites": "Obľúbené", + "column.favourites": "Ohviezdičkované", "column.firehose": "Živé kanály", "column.follow_requests": "Žiadosti o sledovanie", "column.home": "Domov", @@ -174,7 +200,7 @@ "compose_form.direct_message_warning_learn_more": "Viac informácií", "compose_form.encryption_warning": "Príspevky na Mastodone nie sú šifrované end-to-end. Nezdieľajte cez Mastodon žiadne citlivé informácie.", "compose_form.hashtag_warning": "Tento príspevok nebude zobrazený pod žiadným hashtagom, lebo nie je verejný. Iba verejné príspevky môžu byť nájdené podľa hashtagu.", - "compose_form.lock_disclaimer": "Váš účet nie je {locked}. Ktokoľvek vás môže sledovať a vidieť vaše príspevky pre sledujúcich.", + "compose_form.lock_disclaimer": "Váš účet nie je {locked}. Ktokoľvek vás môže sledovať a vidieť vaše príspevky pre sledujúce účty.", "compose_form.lock_disclaimer.lock": "zamknutý", "compose_form.placeholder": "Na čo práve myslíte?", "compose_form.poll.duration": "Trvanie ankety", @@ -198,6 +224,8 @@ "confirmations.delete_list.confirm": "Vymazať", "confirmations.delete_list.message": "Určite chcete tento zoznam trvalo vymazať?", "confirmations.delete_list.title": "Vymazať zoznam?", + "confirmations.discard_draft.confirm": "Zahodiť a pokračovať", + "confirmations.discard_draft.edit.cancel": "Pokračovať v úpravách", "confirmations.discard_edit_media.confirm": "Zahodiť", "confirmations.discard_edit_media.message": "Máte neuložené zmeny v popise alebo náhľade média, zahodiť ich aj tak?", "confirmations.follow_to_list.confirm": "Nasleduj a pridaj do zoznamu", @@ -206,13 +234,19 @@ "confirmations.logout.confirm": "Odhlásiť sa", "confirmations.logout.message": "Určite sa chcete odhlásiť?", "confirmations.logout.title": "Odhlásiť sa?", - "confirmations.missing_alt_text.secondary": "Odošli aj tak", + "confirmations.missing_alt_text.confirm": "Pridať opis", + "confirmations.missing_alt_text.message": "Váš príspevok obsahuje médiá bez opisu. Pridanie opisu sprístupňuje váš obsah viac ľuďom.", + "confirmations.missing_alt_text.secondary": "Aj tak uverejniť", + "confirmations.missing_alt_text.title": "Pridať opis?", "confirmations.mute.confirm": "Stíšiť", "confirmations.redraft.confirm": "Vymazať a prepísať", "confirmations.redraft.message": "Určite chcete tento príspevok vymazať a prepísať? Prídete o jeho zdieľania a ohviezdičkovania a odpovede na pôvodný príspevok budú odlúčené.", "confirmations.redraft.title": "Vymazať a prepísať príspevok?", "confirmations.remove_from_followers.confirm": "Odstrániť nasledovateľa", - "confirmations.unfollow.confirm": "Prestať sledovať", + "confirmations.revoke_quote.title": "Vymazať príspevok?", + "confirmations.unblock.confirm": "Odblokovať", + "confirmations.unblock.title": "Odblokovať {name}?", + "confirmations.unfollow.confirm": "Zrušiť sledovanie", "content_warning.hide": "Skryť príspevok", "content_warning.show": "Aj tak zobraziť", "content_warning.show_more": "Ukázať viac", @@ -265,7 +299,7 @@ "empty_column.account_timeline": "Nie sú tu žiadne príspevky.", "empty_column.account_unavailable": "Profil nedostupný", "empty_column.blocks": "Nemáte blokované žiadne účty.", - "empty_column.bookmarked_statuses": "Ešte nemáte záložku v žiadnom príspevku. Keď si ju do nejakého príspevkuk pridáte, zobrazí sa tu.", + "empty_column.bookmarked_statuses": "Ešte nemáte záložku v žiadnom príspevku. Keď si ju do nejakého príspevku pridáte, zobrazí sa tu.", "empty_column.community": "Miesta časová os je prázdna. Napíšte niečo, aby to tu ožilo!", "empty_column.direct": "Ešte nemáte žiadne súkromné označenia. Keď nejaké pošlete alebo dostanete, zobrazí sa tu.", "empty_column.domain_blocks": "Žiadne domény ešte nie sú blokované.", @@ -291,6 +325,7 @@ "explore.trending_links": "Správy", "explore.trending_statuses": "Príspevky", "explore.trending_tags": "Hashtagy", + "featured_carousel.header": "{count, plural, one {Pripnutý príspevok} few {Pripnuté príspevky} many {} other {Pripnutých príspevkov}}", "filter_modal.added.context_mismatch_explanation": "Táto kategória filtrov sa nevzťahuje na kontext, v ktorom ste získali prístup k tomuto príspevku. Ak chcete, aby sa príspevok filtroval aj v tomto kontexte, budete musieť filter upraviť.", "filter_modal.added.context_mismatch_title": "Nesúlad kontextu!", "filter_modal.added.expired_explanation": "Platnosť tejto kategórie filtra vypršala, aby sa použila, je potrebné zmeniť dátum vypršania platnosti.", @@ -351,12 +386,12 @@ "hashtag.column_settings.tag_mode.any": "Ľubovoľné z týchto", "hashtag.column_settings.tag_mode.none": "Žiaden z týchto", "hashtag.column_settings.tag_toggle": "Vložte dodatočné hashtagy pre tento stĺpec", - "hashtag.counter_by_accounts": "{count, plural, one {{counter} prispievateľ} few {{counter} prispievatelia} many {{counter} prispievateľov} other {{counter} prispievateľov}}", + "hashtag.counter_by_accounts": "{count, plural, one {{counter} prispievajúci účet} few {{counter} prispievajúce účty} many {{counter} participants} other {{counter} prispievajúcich účtov}}", "hashtag.counter_by_uses": "{count, plural, one {{counter} príspevok} few {{counter} príspevky} many {{counter} príspevkov} other {{counter} príspevkov}}", "hashtag.counter_by_uses_today": "{count, plural, one {{counter} príspevok} few {{counter} príspevky} many {{counter} príspevkov} other {{counter} príspevkov}} dnes", "hashtag.follow": "Sledovať hashtag", "hashtag.mute": "Utlmiť #{hashtag}", - "hashtag.unfollow": "Prestať sledovať hashtag", + "hashtag.unfollow": "Zrušiť sledovanie hashtagu", "hashtags.and_other": "…a {count, plural, other {# ďalších}}", "hints.profiles.followers_may_be_missing": "Nasledovatelia tohto profilu môžu chýbať.", "hints.profiles.follows_may_be_missing": "Nasledovatelia tohto profilu môžu chýbať.", @@ -373,7 +408,7 @@ "home.show_announcements": "Zobraziť oznámenia", "ignore_notifications_modal.filter_instead": "Radšej triediť", "ignore_notifications_modal.filter_to_act_users": "Stále budeš môcť akceptovať, odmietnuť, alebo nahlásiť užívateľov", - "ignore_notifications_modal.filter_to_avoid_confusion": "Triedenie pomáha vyvarovať sa možnému zmäteniu", + "ignore_notifications_modal.filter_to_avoid_confusion": "Filtrovanie pomáha vyvarovať sa možnému zmäteniu", "ignore_notifications_modal.ignore": "Ignoruj upozornenia", "ignore_notifications_modal.limited_accounts_title": "Ignorovať oboznámenia z obmedzených účtov?", "ignore_notifications_modal.new_accounts_title": "Nevšímať si oznámenia z nových účtov?", @@ -381,6 +416,7 @@ "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?", "info_button.label": "Pomoc", + "info_button.what_is_alt_text": "

Čo je to opis?

Opis médií umožňuje ľuďom so zdravotným postihnutím alebo slabým pripojením porozumieť obsahu príspevku.

Zrozumiteľné, stručné a objektívne opisy sprístupňujú a vysvetľujú váš obsah väčšiemu počtu ľudí.

  • Spomeňte dôležité prvky
  • Zhrňte text na obrázkoch a fotkách
  • Píšte bežné vety
  • Vynechajte zbytočné informácie
  • Pri zložitých vizuáloch (napr. nákresoch či mapách) sa sústreďte na kľúčové vzorce a závery
", "interaction_modal.go": "Prejdi", "interaction_modal.no_account_yet": "Ešte nemáš účet?", "interaction_modal.on_another_server": "Na inom serveri", @@ -421,7 +457,7 @@ "keyboard_shortcuts.toggle_hidden": "Zobraziť/skryť text za varovaním o obsahu", "keyboard_shortcuts.toggle_sensitivity": "Zobraziť/skryť médiá", "keyboard_shortcuts.toot": "Vytvoriť nový príspevok", - "keyboard_shortcuts.translate": "preložiť príspevok", + "keyboard_shortcuts.translate": "Preložiť príspevok", "keyboard_shortcuts.unfocus": "Odísť z textového poľa", "keyboard_shortcuts.up": "Posunúť sa vyššie v zozname", "lightbox.close": "Zatvoriť", @@ -437,7 +473,7 @@ "lists.add_to_list": "Pridaj do zoznamu", "lists.add_to_lists": "Pridaj {name} do zoznamov", "lists.create": "Vytvor", - "lists.create_a_list_to_organize": "Vytvor nový zoznam pre spravovanie tvojej domovskej osi", + "lists.create_a_list_to_organize": "Vytvorte si nový zoznam na organizáciu svojho domovského kanála", "lists.create_list": "Vytvor zoznam", "lists.delete": "Vymazať zoznam", "lists.done": "Hotovo", @@ -447,7 +483,7 @@ "lists.find_users_to_add": "Nájdi užívateľov na pridanie", "lists.list_name": "Názov zoznamu", "lists.new_list_name": "Názov nového zoznamu", - "lists.no_lists_yet": "Ešte žiadne zoznamy.", + "lists.no_lists_yet": "Zatiaľ nemáte žiadne zoznamy.", "lists.no_members_yet": "Zatiaľ bez členov.", "lists.no_results_found": "Žiadne výsledky nenájdené.", "lists.remove_member": "Odstráň", @@ -471,8 +507,10 @@ "mute_modal.you_wont_see_mentions": "Neuvidíš príspevky, ktoré ho/ju spomínajú.", "mute_modal.you_wont_see_posts": "Stále uvidí tvoje príspevky, ale ty neuvidíš jeho/jej.", "navigation_bar.about": "O tomto serveri", + "navigation_bar.account_settings": "Heslo a zabezpečenie", "navigation_bar.administration": "Spravovanie", "navigation_bar.advanced_interface": "Otvoriť v pokročilom webovom rozhraní", + "navigation_bar.automated_deletion": "Automatické mazanie príspevkov", "navigation_bar.blocks": "Blokované účty", "navigation_bar.bookmarks": "Záložky", "navigation_bar.direct": "Súkromné označenia", @@ -481,13 +519,16 @@ "navigation_bar.filters": "Filtrované slová", "navigation_bar.follow_requests": "Žiadosti o sledovanie", "navigation_bar.followed_tags": "Sledované hashtagy", - "navigation_bar.follows_and_followers": "Sledovania a sledovatelia", + "navigation_bar.follows_and_followers": "Sledované a sledujúce účty", + "navigation_bar.import_export": "Import a export", "navigation_bar.lists": "Zoznamy", "navigation_bar.logout": "Odhlásiť sa", "navigation_bar.moderation": "Moderovanie", + "navigation_bar.more": "Viac", "navigation_bar.mutes": "Stíšené účty", "navigation_bar.opened_in_classic_interface": "Príspevky, účty a iné špeciálne stránky sú predvolene otvárané v klasickom webovom rozhraní.", "navigation_bar.preferences": "Nastavenia", + "navigation_bar.privacy_and_reach": "Súkromie a dosah", "navigation_bar.search": "Hľadať", "not_signed_in_indicator.not_signed_in": "Ak chcete získať prístup k tomuto zdroju, prihláste sa.", "notification.admin.report": "Účet {name} nahlásil {target}", @@ -498,24 +539,25 @@ "notification.favourite_pm": "{name} obľúbil/a tvoje súkromné spomenutie", "notification.follow": "{name} vás sleduje", "notification.follow_request": "{name} vás žiada sledovať", - "notification.label.mention": "Zmienka", - "notification.label.private_mention": "Súkromná zmienka", + "notification.label.mention": "Označenie", + "notification.label.private_mention": "Súkromné označenie", "notification.label.private_reply": "Súkromná odpoveď", "notification.label.reply": "Odpoveď", - "notification.mention": "Zmienka", + "notification.mention": "Označenie", "notification.mentioned_you": "{name} ťa spomenul/a", "notification.moderation-warning.learn_more": "Zisti viac", "notification.moderation_warning": "Dostal/a si varovanie od moderátora", "notification.moderation_warning.action_delete_statuses": "Niektoré z tvojich príspevkov boli odstránené.", "notification.moderation_warning.action_disable": "Tvoj účet bol vypnutý.", - "notification.moderation_warning.action_mark_statuses_as_sensitive": "Niektoré tvoje príspevky boli označené za chúlostivé.", + "notification.moderation_warning.action_mark_statuses_as_sensitive": "Niektoré vaše príspevky boli označené ako citlivé.", "notification.moderation_warning.action_none": "Tvoj účet dostal upozornenie od moderátora.", - "notification.moderation_warning.action_sensitive": "Tvoje príspevky budú odteraz označované ako chúlostivé.", + "notification.moderation_warning.action_sensitive": "Vaše príspevky budú odteraz označované ako citlivé.", "notification.moderation_warning.action_silence": "Tvoj účet bol obmedzený.", "notification.moderation_warning.action_suspend": "Tvoj účet bol pozastavený.", "notification.own_poll": "Vaša anketa sa skončila", "notification.poll": "Anketa, v ktorej si hlasoval/a, skončila", "notification.reblog": "{name} zdieľa váš príspevok", + "notification.reblog.name_and_others_with_link": "{name} a {count, plural, one {# ďalší človek} few {# ďalší ľudia} many {#} other {# ďalších ľudí}} zdieľa váš príspevok", "notification.relationships_severance_event": "Stratené prepojenia s {name}", "notification.relationships_severance_event.account_suspension": "Správca z {from} pozastavil/a {target}, čo znamená, že od nich viac nemôžeš dostávať aktualizácie, alebo s nimi interaktovať.", "notification.relationships_severance_event.learn_more": "Zisti viac", @@ -592,7 +634,7 @@ "onboarding.profile.save_and_continue": "Uložiť a pokračovať", "onboarding.profile.title": "Nastavenie profilu", "onboarding.profile.upload_avatar": "Nahrať profilový obrázok", - "onboarding.profile.upload_header": "Nahrať obrázok záhlavia profilu", + "onboarding.profile.upload_header": "Nahrať obrázok v záhlaví profilu", "password_confirmation.exceeds_maxlength": "Potvrdené heslo presahuje maximálnu dĺžku hesla", "password_confirmation.mismatching": "Zadané heslá sa nezhodujú", "picture_in_picture.restore": "Vrátiť späť", @@ -720,6 +762,7 @@ "status.admin_account": "Moderovať @{name}", "status.admin_domain": "Moderovať {domain}", "status.admin_status": "Moderovať príspevok", + "status.all_disabled": "Zdieľania a citácie sú vypnuté", "status.block": "Blokovať @{name}", "status.bookmark": "Pridať záložku", "status.cancel_reblog_private": "Zrušiť zdieľanie", @@ -733,7 +776,7 @@ "status.edit": "Upraviť", "status.edited": "Naposledy upravený {date}", "status.edited_x_times": "Upravený {count, plural, other {{count}×}}", - "status.favourite": "Ohviezdičkované", + "status.favourite": "Ohviezdičkovať", "status.filter": "Filtrovanie tohto príspevku", "status.history.created": "Vytvorené účtom {name} {date}", "status.history.edited": "Upravené účtom {name} {date}", @@ -747,13 +790,16 @@ "status.mute_conversation": "Stíšiť konverzáciu", "status.open": "Rozbaliť príspevok", "status.pin": "Pripnúť na profil", + "status.quote_policy_change": "Zmeňte, kto vás môže citovať", "status.read_more": "Čítaj ďalej", "status.reblog": "Zdieľať", + "status.reblog_or_quote": "Zdieľať alebo citovať", "status.reblogged_by": "{name} zdieľa", + "status.reblogs": "{count, plural, one {zdieľanie} few {zdieľania} many {} other {zdieľaní}}", "status.reblogs.empty": "Nikto ešte tento príspevok nezdieľal. Keď tak niekto urobí, zobrazí sa to tu.", "status.redraft": "Vymazať a prepísať", "status.remove_bookmark": "Odstrániť záložku", - "status.remove_favourite": "Odstráň z obľúbených", + "status.remove_favourite": "Zrušiť ohviezdičkovanie", "status.replied_in_thread": "Odpovedal/a vo vlákne", "status.replied_to": "Odpoveď na {name}", "status.reply": "Odpovedať", @@ -805,5 +851,10 @@ "video.pause": "Pozastaviť", "video.play": "Prehrať", "video.volume_down": "Hlasitosť nadol", - "video.volume_up": "Hlasitosť nahor" + "video.volume_up": "Hlasitosť nahor", + "visibility_modal.header": "Viditeľnosť a interakcia", + "visibility_modal.quote_followers": "Iba sledujúce účty", + "visibility_modal.quote_label": "Kto vás môže citovať", + "visibility_modal.quote_nobody": "Iba ja", + "visibility_modal.quote_public": "Ktokoľvek" } diff --git a/app/javascript/mastodon/locales/sq.json b/app/javascript/mastodon/locales/sq.json index 3f61ff0a29c..6f6d96509df 100644 --- a/app/javascript/mastodon/locales/sq.json +++ b/app/javascript/mastodon/locales/sq.json @@ -28,6 +28,7 @@ "account.disable_notifications": "Resht së njoftuari mua, kur poston @{name}", "account.domain_blocking": "Bllokim përkatësie", "account.edit_profile": "Përpunoni profilin", + "account.edit_profile_short": "Përpunojeni", "account.enable_notifications": "Njoftomë, kur poston @{name}", "account.endorse": "Pasqyrojeni në profil", "account.familiar_followers_many": "Ndjekur nga {name1}, {name2} dhe {othersCount, plural, one {një tjetër që njihni} other {# të tjerë që njihni}}", @@ -40,6 +41,11 @@ "account.featured_tags.last_status_never": "Pa postime", "account.follow": "Ndiqeni", "account.follow_back": "Ndiqe gjithashtu", + "account.follow_back_short": "Ndiqe gjithashtu", + "account.follow_request": "Kërkoni ta ndiqni", + "account.follow_request_cancel": "Anuloje kërkesën", + "account.follow_request_cancel_short": "Anuloje", + "account.follow_request_short": "Kërkoje", "account.followers": "Ndjekës", "account.followers.empty": "Këtë përdorues ende s’e ndjek kush.", "account.followers_counter": "{count, plural, one {{counter} ndjekës} other {{counter} ndjekës}}", @@ -107,6 +113,7 @@ "alt_text_modal.describe_for_people_with_visual_impairments": "Përshkruajeni këtë për persona me mangësi shikimi…", "alt_text_modal.done": "U bë", "announcement.announcement": "Lajmërim", + "annual_report.summary.archetype.oracle": "Orakulli", "annual_report.summary.followers.followers": "ndjekës", "annual_report.summary.followers.total": "{count} gjithsej", "annual_report.summary.here_it_is": "Ja {year} juaj e shqyrtuar:", @@ -233,13 +240,25 @@ "confirmations.missing_alt_text.secondary": "Postoje, sido qoftë", "confirmations.missing_alt_text.title": "Të shtohet tekst alternativ?", "confirmations.mute.confirm": "Heshtoje", + "confirmations.quiet_post_quote_info.dismiss": "Mos ma kujto më", + "confirmations.quiet_post_quote_info.got_it": "E mora vesh", + "confirmations.quiet_post_quote_info.message": "Kur citoni një postim publik të heshtuar, postimi juaj do të kalohet i fshehur te rrjedha kohore e gjërave në modë.", + "confirmations.quiet_post_quote_info.title": "Citim postimesh publikë të heshtuar", "confirmations.redraft.confirm": "Fshijeni & rihartojeni", "confirmations.redraft.message": "Jeni i sigurt se doni të fshihet kjo gjendje dhe të rihartohet? Të parapëlqyerit dhe përforcimet do të humbin, ndërsa përgjigjet te postimi origjinal do të bëhen jetime.", "confirmations.redraft.title": "Të fshihet & riharothet postimi?", "confirmations.remove_from_followers.confirm": "Hiqe ndjekësin", "confirmations.remove_from_followers.message": "{name} do të reshtë së ndjekuri ju. Jeni i sigurt se doni të vazhdohet?", "confirmations.remove_from_followers.title": "Të hiqet ndjekësi?", + "confirmations.revoke_quote.confirm": "Hiqe postimin", + "confirmations.revoke_quote.message": "Ky veprim s’mund të zhbëhet.", + "confirmations.revoke_quote.title": "Të hiqet postimi?", + "confirmations.unblock.confirm": "Zhbllokoje", + "confirmations.unblock.title": "Të zhbllojohet {name}?", "confirmations.unfollow.confirm": "Resht së ndjekuri", + "confirmations.unfollow.title": "Të ndalet ndjekja për {name}?", + "confirmations.withdraw_request.confirm": "Tërhiqeni mbrapsht kërkesën", + "confirmations.withdraw_request.title": "Të tërhiqet mbrapsht kërkesa për ndjeken e {name}?", "content_warning.hide": "Fshihe postimin", "content_warning.show": "Shfaqe, sido qoftë", "content_warning.show_more": "Shfaq më tepër", @@ -281,6 +300,7 @@ "domain_pill.your_handle": "Targa juaj:", "domain_pill.your_server": "Shtëpia juaj dixhitale, kur gjenden krejt postimet tuaja. S’ju pëlqen kjo këtu? Shpërngulni shërbyes kur të doni dhe sillni edhe ndjekësit tuaj.", "domain_pill.your_username": "Identifikuesi juja unik në këtë shërbyes. Është e mundur të gjenden përdorues me të njëjtin emër përdoruesi në shërbyes të ndryshëm.", + "dropdown.empty": "Përzgjidhni një mundësi", "embed.instructions": "Trupëzojeni këtë gjendje në sajtin tuaj duke kopjuar kodin më poshtë.", "embed.preview": "Ja si do të duket:", "emoji_button.activity": "Veprimtari", @@ -437,10 +457,12 @@ "ignore_notifications_modal.private_mentions_title": "Të shpërfillen njoftime nga Përmendje Private të pakërkuara?", "info_button.label": "Ndihmë", "info_button.what_is_alt_text": "

Ç’është teksti alternativ?

Teksti alternativ jep përshkrime figurash për persona me mangësi në të parët, lidhje me gjerësi bande të ulët, ose për ata që duan kontekst shtesë.

Mund të përmirësoni përdorimin nga persona me aftësi të kufizuara dhe kuptimin për këto, duke shkruar tekst alternativ të qartë, konciz dhe objektiv.

  • Rrokni elementët e rëndësishëm
  • Përmblidhni tekst në figura
  • Përdorni strukturë të rregullt fjalish
  • Shmangni përsëritje informacioni
  • Në aspekte pamore të ndërlikuara (fjala vjen, diagrame ose harta) përqendrohuni te prirje dhe gjetje gjërash kyçe
", + "interaction_modal.action": "Që të ndërveproni me postimin nga {name}, lypset të bëni hyrjen në llogarinë tuaj, ose në çfarëdo shërbyesi Mastodon që përdorni.", "interaction_modal.go": "Shko", "interaction_modal.no_account_yet": "S’keni ende një llogari?", "interaction_modal.on_another_server": "Në një tjetër shërbyes", "interaction_modal.on_this_server": "Në këtë shërbyes", + "interaction_modal.title": "Që të vazhdohet, bëni hyrjen", "interaction_modal.username_prompt": "P.sh., {example}", "intervals.full.days": "{number, plural, one {# ditë} other {# ditë}}", "intervals.full.hours": "{number, plural, one {# orë} other {# orë}}", @@ -461,6 +483,7 @@ "keyboard_shortcuts.home": "Për hapje rrjedhe kohore vetjake", "keyboard_shortcuts.hotkey": "Tast përkatës", "keyboard_shortcuts.legend": "Për shfaqje të kësaj legjende", + "keyboard_shortcuts.load_more": "Kaloje fokusin te butoni “Ngarko më tepër”", "keyboard_shortcuts.local": "Për hapje rrjedhe kohore vendore", "keyboard_shortcuts.mention": "Për përmendje të autorit", "keyboard_shortcuts.muted": "Për hapje liste përdoruesish të heshtuar", @@ -469,6 +492,7 @@ "keyboard_shortcuts.open_media": "Për hapje mediash", "keyboard_shortcuts.pinned": "Për hapje liste mesazhesh të fiksuar", "keyboard_shortcuts.profile": "Për hapje të profilit të autorit", + "keyboard_shortcuts.quote": "Citoni postim", "keyboard_shortcuts.reply": "Për t’iu përgjigjur një postimi", "keyboard_shortcuts.requests": "Për hapje liste kërkesash për ndjekje", "keyboard_shortcuts.search": "Për kalim fokusi te kërkimi", @@ -480,6 +504,8 @@ "keyboard_shortcuts.translate": "për të përkthyer një postim", "keyboard_shortcuts.unfocus": "Për heqjen e fokusit nga fusha e hartimit të mesazheve apo kërkimeve", "keyboard_shortcuts.up": "Për ngjitje sipër nëpër listë", + "learn_more_link.got_it": "E mora vesh", + "learn_more_link.learn_more": "Mësoni më tepër", "lightbox.close": "Mbylle", "lightbox.next": "Pasuesja", "lightbox.previous": "E mëparshmja", @@ -544,6 +570,8 @@ "navigation_bar.follows_and_followers": "Ndjekje dhe ndjekës", "navigation_bar.import_export": "Importim dhe eksportim", "navigation_bar.lists": "Lista", + "navigation_bar.live_feed_local": "Pryrje e atypëratyshme (vendore)", + "navigation_bar.live_feed_public": "Prurje e atypëratyshme (publike)", "navigation_bar.logout": "Dalje", "navigation_bar.moderation": "Moderim", "navigation_bar.more": "Më tepër", @@ -578,6 +606,7 @@ "notification.label.mention": "Përmendje", "notification.label.private_mention": "Përmendje private", "notification.label.private_reply": "Përgjigje private", + "notification.label.quote": "{name} citoi postimin tuaj", "notification.label.reply": "Përgjigje", "notification.mention": "Përmendje", "notification.mentioned_you": "{name} ju ka përmendur", @@ -592,6 +621,7 @@ "notification.moderation_warning.action_suspend": "Llogaria juaj është pezulluar.", "notification.own_poll": "Pyetësori juaj ka përfunduar", "notification.poll": "Ka përfunduar një pyetësor në të cilin keni marrë pjesë", + "notification.quoted_update": "{name} përpunoi një postim që keni cituar", "notification.reblog": "{name} përforcoi mesazhin tuaj", "notification.reblog.name_and_others_with_link": "Ju ka përforcuar {name} dhe {count, plural, one {# tjetër} other {# të tjerë}}", "notification.relationships_severance_event": "Lidhje të humbura me {name}", @@ -635,6 +665,7 @@ "notifications.column_settings.mention": "Përmendje:", "notifications.column_settings.poll": "Përfundime pyetësori:", "notifications.column_settings.push": "Njoftime Push", + "notifications.column_settings.quote": "Ctime:", "notifications.column_settings.reblog": "Përforcime:", "notifications.column_settings.show": "Shfaqi në shtylla", "notifications.column_settings.sound": "Luaj një tingull", @@ -710,10 +741,19 @@ "privacy.private.short": "Ndjekës", "privacy.public.long": "Cilido që hyn e del në Mastodon", "privacy.public.short": "Publik", + "privacy.quote.anyone": "{visibility}, mund të citojë cilido", + "privacy.quote.disabled": "{visibility}, citimet janë çaktivizuar", + "privacy.quote.limited": "{visibility}, citime të kufizuara", "privacy.unlisted.additional": "Ky sillet saktësisht si publik, vetëm se postimi s’do të shfaqet në prurje të drejtpërdrejta, ose në hashtag-ë, te eksploroni, apo kërkim në Mastodon, edhe kur keni zgjedhur të jetë për tërë llogarinë.", + "privacy.unlisted.long": "Fshehur nga përfundime kërkimi në Mastodon, rrjedha kohore gjërash në modë dhe publike", "privacy.unlisted.short": "Publik i qetë", "privacy_policy.last_updated": "Përditësuar së fundi më {date}", "privacy_policy.title": "Rregulla Privatësie", + "quote_error.edit": "Kur përpunohet një postim, s’mund të shtohen citime.", + "quote_error.poll": "Me pyetësorët nuk lejohet citim.", + "quote_error.quote": "Lejohet vetëm një citim në herë.", + "quote_error.unauthorized": "S’jen i autorizuar ta citoni këtë postim.", + "quote_error.upload": "Me bashkëngjitjet media nuk lejohet citim.", "recommended": "E rekomanduar", "refresh": "Rifreskoje", "regeneration_indicator.please_stand_by": "Ju lutemi, mos u largoni.", @@ -729,6 +769,9 @@ "relative_time.minutes": "{number}m", "relative_time.seconds": "{number}s", "relative_time.today": "sot", + "remove_quote_hint.button_label": "E mora vesh", + "remove_quote_hint.message": "Këtë mund ta bëni një menuja e mundësive {icon}.", + "remove_quote_hint.title": "Doni të hiqet postimi juaj i cituar?", "reply_indicator.attachments": "{count, plural, one {# bashkëngjitje} other {# bashkëngjitje}}", "reply_indicator.cancel": "Anuloje", "reply_indicator.poll": "Pyetësor", @@ -820,13 +863,23 @@ "status.admin_account": "Hap ndërfaqe moderimi për @{name}", "status.admin_domain": "Hap ndërfaqe moderimi për {domain}", "status.admin_status": "Hape këtë mesazh te ndërfaqja e moderimit", + "status.all_disabled": "Përforcimet dhe citime janë të çaktivizuara", "status.block": "Blloko @{name}", "status.bookmark": "Faqeruaje", "status.cancel_reblog_private": "Shpërforcojeni", + "status.cannot_quote": "S’keni leje të citoni këtë postim", "status.cannot_reblog": "Ky postim s’mund të përforcohet", + "status.contains_quote": "Përmban citim", + "status.context.loading": "Po ngarkohen më tepër përgjigje", + "status.context.loading_error": "S’u ngarkuan dot përgjigje të reja", + "status.context.loading_success": "Janë ngarkuar krejt përgjigjet", + "status.context.more_replies_found": "U gjetën më tepër përgjigje", + "status.context.retry": "Riprovoni", + "status.context.show": "Shfaqe", "status.continued_thread": "Vazhdoi rrjedhën", "status.copy": "Kopjoje lidhjen për te mesazhi", "status.delete": "Fshije", + "status.delete.success": "Postimi u fshi", "status.detailed_status": "Pamje e hollësishme bisede", "status.direct": "Përmendje private për @{name}", "status.direct_indicator": "Përmendje private", @@ -849,20 +902,43 @@ "status.mute_conversation": "Heshtoje bisedën", "status.open": "Zgjeroje këtë mesazh", "status.pin": "Fiksoje në profil", + "status.quote": "Citojeni", + "status.quote.cancel": "Anuloje citimin", "status.quote_error.filtered": "Fshehur për shkak të njërit nga filtrat tuaj", + "status.quote_error.limited_account_hint.action": "Shfaqe, sido qoftë", + "status.quote_error.limited_account_hint.title": "Kjo llogari është fshehur nga moderatorët e {domain}.", + "status.quote_error.not_available": "Postim që s’mund të kihet", + "status.quote_error.pending_approval": "Postim pezull", + "status.quote_error.pending_approval_popout.body": "Në Mastodon mundeni të kontrolloni nëse dikush ju citon a jo. Ky postim është pezull, teksa po marrim miratimin e autorit origjinal.", + "status.quote_error.revoked": "Postim i hequr nga autori", + "status.quote_followers_only": "Këtë postim mund ta citojnë vetëm ndjekës", + "status.quote_manual_review": "Autori do ta shqyrtojë dorazi", + "status.quote_noun": "Citim", + "status.quote_policy_change": "Ndryshoni cilët mund të citojnë", + "status.quote_post_author": "U citua një postim nga @{name}", + "status.quote_private": "Postimet private s’mund të citohen", + "status.quotes": "{count, plural, one {citim} other {citime}}", + "status.quotes.empty": "Këtë postim ende s’e ka cituar kush. Kur dikush ta bëjë, do të shfaqet këtu.", + "status.quotes.local_other_disclaimer": "Citimet e hedhura poshtë nga autori s’do të shfaqen.", + "status.quotes.remote_other_disclaimer": "Këtu garantohet të shfaqen vetëm citime nga {domain}. Citime të hedhura poshtë nga autori s’do të shfaqen.", "status.read_more": "Lexoni më tepër", "status.reblog": "Përforcojeni", + "status.reblog_or_quote": "Përforconi ose citoni", + "status.reblog_private": "Rindajeni me ndjekësit tuaj", "status.reblogged_by": "{name} përforcoi", "status.reblogs": "{count, plural, one {përforcim} other {përforcime}}", "status.reblogs.empty": "Këtë mesazh s’e ka përforcuar njeri deri tani. Kur ta bëjë dikush, kjo do të duket këtu.", "status.redraft": "Fshijeni & rihartojeni", "status.remove_bookmark": "Hiqe faqerojtësin", "status.remove_favourite": "Hiqe nga të parapëlqyerat", + "status.remove_quote": "Hiqe", "status.replied_in_thread": "U përgjigj te rrjedha", "status.replied_to": "Iu përgjigj {name}", "status.reply": "Përgjigjuni", "status.replyAll": "Përgjigjuni rrjedhës", "status.report": "Raportojeni @{name}", + "status.request_quote": "Kërkoni të citohet", + "status.revoke_quote": "Hiqe postimin tim nga postimi i @{name}", "status.sensitive_warning": "Lëndë rezervat", "status.share": "Ndajeni me të tjerë", "status.show_less_all": "Shfaq më pak për të tërë", @@ -900,6 +976,7 @@ "upload_button.label": "Shtoni figura, një video ose një kartelë audio", "upload_error.limit": "U tejkalua kufi ngarkimi kartelash.", "upload_error.poll": "Me pyetësorët s’lejohet ngarkim kartelash.", + "upload_error.quote": "Nuk lejohet ngarkim kartelash me citime.", "upload_form.drag_and_drop.instructions": "Që të merrni një bashkëngjitje media, shtypni tastin Space ose Enter. Teksa bëhet tërheqje, përdorni tastet shigjetë për ta shpënë bashkëngjitjen media në cilëndo drejtori që doni. Shtypni sërish Space ose Enter që të lihet bashkëngjitja media në pozicionin e vet të ri, ose shtypni Esc, që të anulohet veprimi.", "upload_form.drag_and_drop.on_drag_cancel": "Tërheqja u anulua. Bashkëngjitja media {item} u la.", "upload_form.drag_and_drop.on_drag_end": "Bashkëngjitja media {item} u la.", @@ -922,5 +999,19 @@ "video.skip_forward": "Anashkalo pasardhësen", "video.unmute": "Hiqi heshtimin", "video.volume_down": "Ulje volumi", - "video.volume_up": "Ngritje volumi" + "video.volume_up": "Ngritje volumi", + "visibility_modal.button_title": "Caktoni dukshmëri", + "visibility_modal.header": "Dukshmëri dhe ndërveprim", + "visibility_modal.helper.direct_quoting": "Përmendje private të krijuara në Mastodon s’mund të citohen nga të tjerë.", + "visibility_modal.helper.privacy_editing": "Dukshmëria s’mund të ndryshohet pasi postimi botohet.", + "visibility_modal.helper.privacy_private_self_quote": "Citimet nga ju vetë të postime private s’mund të bëhen publike.", + "visibility_modal.helper.private_quoting": "Postime vetëm për ndjekësit, të krijuara në Mastodon s’mund të citohen nga të tjerë.", + "visibility_modal.helper.unlisted_quoting": "Kur njerëzit ju citojnë, nga rrjedha kohore e gjërave në modë do të kalohen si të fshehura edhe postimet e tyre.", + "visibility_modal.instructions": "Kontrolloni cilët mund të ndërveprojnë me këtë postim. Rregullime mund të aplikooni edhe mbi krejt postimet e ardshme, që nga Parapëlqime > Parazgjedhje postimi.", + "visibility_modal.privacy_label": "Dukshmëri", + "visibility_modal.quote_followers": "Vetëm ndjekës", + "visibility_modal.quote_label": "Cilët mund të citojnë", + "visibility_modal.quote_nobody": "Thjesht unë", + "visibility_modal.quote_public": "Cilido", + "visibility_modal.save": "Ruaje" } diff --git a/app/javascript/mastodon/locales/th.json b/app/javascript/mastodon/locales/th.json index 1fcaad9b64d..63df997694b 100644 --- a/app/javascript/mastodon/locales/th.json +++ b/app/javascript/mastodon/locales/th.json @@ -417,6 +417,7 @@ "interaction_modal.no_account_yet": "ยังไม่มีบัญชี?", "interaction_modal.on_another_server": "ในเซิร์ฟเวอร์อื่น", "interaction_modal.on_this_server": "ในเซิร์ฟเวอร์นี้", + "interaction_modal.title": "ลงชื่อเข้า", "interaction_modal.username_prompt": "เช่น {example}", "intervals.full.days": "{number, plural, other {# วัน}}", "intervals.full.hours": "{number, plural, other {# ชั่วโมง}}", diff --git a/app/javascript/mastodon/locales/tr.json b/app/javascript/mastodon/locales/tr.json index d8f07d12c9e..19b37b569b7 100644 --- a/app/javascript/mastodon/locales/tr.json +++ b/app/javascript/mastodon/locales/tr.json @@ -257,7 +257,12 @@ "confirmations.revoke_quote.confirm": "Gönderiyi kaldır", "confirmations.revoke_quote.message": "Bu işlem geri alınamaz.", "confirmations.revoke_quote.title": "Gönderiyi silmek ister misiniz?", + "confirmations.unblock.confirm": "Engeli kaldır", + "confirmations.unblock.title": "{name} için engel kaldırılsın mı?", "confirmations.unfollow.confirm": "Takibi bırak", + "confirmations.unfollow.title": "{name} takipten çıkılsın mı?", + "confirmations.withdraw_request.confirm": "İsteği geri çek", + "confirmations.withdraw_request.title": "{name} takip isteği geri çekilsin mi?", "content_warning.hide": "Gönderiyi gizle", "content_warning.show": "Yine de göster", "content_warning.show_more": "Daha fazla göster", @@ -748,6 +753,7 @@ "privacy.unlisted.short": "Sessizce herkese açık", "privacy_policy.last_updated": "Son güncelleme {date}", "privacy_policy.title": "Gizlilik Politikası", + "quote_error.edit": "Gönderi düzenlenirken alıntılar eklenemez.", "quote_error.poll": "Anketlerde alıntıya izin verilmez.", "quote_error.quote": "Bir seferde tek bir alıntıya izin var.", "quote_error.unauthorized": "Bu gönderiyi alıntılamaya yetkiniz yok.", @@ -870,7 +876,6 @@ "status.contains_quote": "Alıntı içeriyor", "status.context.loading": "Daha fazla yanıt yükleniyor", "status.context.loading_error": "Yeni yanıtlar yüklenemiyor", - "status.context.loading_more": "Daha fazla yanıt yükleniyor", "status.context.loading_success": "Tüm yanıtlar yüklendi", "status.context.more_replies_found": "Daha fazla yanıt bulundu", "status.context.retry": "Yeniden dene", @@ -918,6 +923,8 @@ "status.quote_private": "Özel gönderiler alıntılanamaz", "status.quotes": "{count, plural, one {# alıntı} other {# alıntı}}", "status.quotes.empty": "Henüz hiç kimse bu gönderiyi alıntılamadı. Herhangi bir kullanıcı alıntıladığında burada görüntülenecek.", + "status.quotes.local_other_disclaimer": "Yazar tarafından reddedilen alıntılar gösterilmez.", + "status.quotes.remote_other_disclaimer": "Yalnızca {domain} adresinden gelen alıntılar burada gösterilir. Yazar tarafından reddedilen alıntılar gösterilmez.", "status.read_more": "Devamını okuyun", "status.reblog": "Yeniden paylaş", "status.reblog_or_quote": "Yükselt veya alıntıla", diff --git a/app/javascript/mastodon/locales/vi.json b/app/javascript/mastodon/locales/vi.json index 08b224e3d64..61de7d3e563 100644 --- a/app/javascript/mastodon/locales/vi.json +++ b/app/javascript/mastodon/locales/vi.json @@ -875,7 +875,6 @@ "status.contains_quote": "Chứa trích dẫn", "status.context.loading": "Tải thêm các trả lời", "status.context.loading_error": "Không thể tải những trả lời mới", - "status.context.loading_more": "Tải thêm các trả lời", "status.context.loading_success": "Đã tải toàn bộ trả lời", "status.context.more_replies_found": "Có trả lời mới", "status.context.retry": "Thử lại", diff --git a/app/javascript/mastodon/locales/zh-CN.json b/app/javascript/mastodon/locales/zh-CN.json index 1397f28f930..052dfdcfd07 100644 --- a/app/javascript/mastodon/locales/zh-CN.json +++ b/app/javascript/mastodon/locales/zh-CN.json @@ -753,6 +753,7 @@ "privacy.unlisted.short": "悄悄公开", "privacy_policy.last_updated": "最近更新于 {date}", "privacy_policy.title": "隐私政策", + "quote_error.edit": "编辑嘟文时无法添加引用。", "quote_error.poll": "不允许引用投票嘟文。", "quote_error.quote": "一次只能引用一条嘟文。", "quote_error.unauthorized": "你没有权限引用此嘟文。", @@ -875,7 +876,6 @@ "status.contains_quote": "包含引用", "status.context.loading": "正在加载更多回复", "status.context.loading_error": "无法加载新回复", - "status.context.loading_more": "正在加载更多回复", "status.context.loading_success": "已加载所有回复", "status.context.more_replies_found": "已找到更多回复", "status.context.retry": "重试", diff --git a/app/javascript/mastodon/locales/zh-TW.json b/app/javascript/mastodon/locales/zh-TW.json index 5e340810941..81cb45fd3bf 100644 --- a/app/javascript/mastodon/locales/zh-TW.json +++ b/app/javascript/mastodon/locales/zh-TW.json @@ -42,7 +42,7 @@ "account.follow": "跟隨", "account.follow_back": "跟隨回去", "account.follow_back_short": "跟隨回去", - "account.follow_request": "要求跟隨您", + "account.follow_request": "跟隨", "account.follow_request_cancel": "取消跟隨請求", "account.follow_request_cancel_short": "取消", "account.follow_request_short": "跟隨請求", @@ -753,6 +753,7 @@ "privacy.unlisted.short": "不公開", "privacy_policy.last_updated": "最後更新:{date}", "privacy_policy.title": "隱私權政策", + "quote_error.edit": "編輯嘟文時無法新增引用嘟文。", "quote_error.poll": "無法引用投票嘟文。", "quote_error.quote": "一次僅能引用一則嘟文。", "quote_error.unauthorized": "您不被授權允許引用此嘟文。", @@ -875,7 +876,6 @@ "status.contains_quote": "包含引用嘟文", "status.context.loading": "讀取更多回嘟", "status.context.loading_error": "無法讀取新回嘟", - "status.context.loading_more": "讀取更多回嘟", "status.context.loading_success": "已讀取所有回嘟", "status.context.more_replies_found": "已有更多回嘟", "status.context.retry": "再試一次", diff --git a/app/javascript/mastodon/polyfills/index.ts b/app/javascript/mastodon/polyfills/index.ts index 0ff0dd72690..1abfe0a935e 100644 --- a/app/javascript/mastodon/polyfills/index.ts +++ b/app/javascript/mastodon/polyfills/index.ts @@ -19,7 +19,7 @@ export function loadPolyfills() { return Promise.all([ loadIntlPolyfills(), // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition -- those properties might not exist in old browsers, even if they are always here in types - needsExtraPolyfills && importExtraPolyfills(), + needsExtraPolyfills ? importExtraPolyfills() : Promise.resolve(), loadEmojiPolyfills(), ]); } diff --git a/app/javascript/mastodon/reducers/contexts.ts b/app/javascript/mastodon/reducers/contexts.ts index cf378b4c048..0331c8083a4 100644 --- a/app/javascript/mastodon/reducers/contexts.ts +++ b/app/javascript/mastodon/reducers/contexts.ts @@ -13,7 +13,12 @@ import type { import type { Status } from 'mastodon/models/status'; import { blockAccountSuccess, muteAccountSuccess } from '../actions/accounts'; -import { fetchContext, completeContextRefresh } from '../actions/statuses'; +import { + fetchContext, + completeContextRefresh, + showPendingReplies, + clearPendingReplies, +} from '../actions/statuses'; import { TIMELINE_UPDATE } from '../actions/timelines'; import { compareId } from '../compare_id'; @@ -26,52 +31,84 @@ interface TimelineUpdateAction extends UnknownAction { interface State { inReplyTos: Record; replies: Record; + pendingReplies: Record< + string, + Pick[] + >; refreshing: Record; } const initialState: State = { inReplyTos: {}, replies: {}, + pendingReplies: {}, refreshing: {}, }; +const addReply = ( + state: Draft, + { id, in_reply_to_id }: Pick, +) => { + if (!in_reply_to_id) { + return; + } + + if (!state.inReplyTos[id]) { + const siblings = (state.replies[in_reply_to_id] ??= []); + const index = siblings.findIndex((sibling) => compareId(sibling, id) < 0); + siblings.splice(index + 1, 0, id); + state.inReplyTos[id] = in_reply_to_id; + } +}; + const normalizeContext = ( state: Draft, id: string, { ancestors, descendants }: ApiContextJSON, ): void => { - const addReply = ({ - id, - in_reply_to_id, - }: { - id: string; - in_reply_to_id?: string; - }) => { - if (!in_reply_to_id) { - return; - } - - if (!state.inReplyTos[id]) { - const siblings = (state.replies[in_reply_to_id] ??= []); - const index = siblings.findIndex((sibling) => compareId(sibling, id) < 0); - siblings.splice(index + 1, 0, id); - state.inReplyTos[id] = in_reply_to_id; - } - }; + ancestors.forEach((item) => { + addReply(state, item); + }); // We know in_reply_to_id of statuses but `id` itself. // So we assume that the status of the id replies to last ancestors. - - ancestors.forEach(addReply); - if (ancestors[0]) { - addReply({ + addReply(state, { id, in_reply_to_id: ancestors[ancestors.length - 1]?.id, }); } - descendants.forEach(addReply); + descendants.forEach((item) => { + addReply(state, item); + }); +}; + +const applyPrefetchedReplies = (state: Draft, statusId: string) => { + const pendingReplies = state.pendingReplies[statusId]; + if (pendingReplies?.length) { + pendingReplies.forEach((item) => { + addReply(state, item); + }); + delete state.pendingReplies[statusId]; + } +}; + +const storePrefetchedReplies = ( + state: Draft, + statusId: string, + { descendants }: ApiContextJSON, +): void => { + descendants.forEach(({ id, in_reply_to_id }) => { + if (!in_reply_to_id) { + return; + } + const isNewReply = !state.replies[in_reply_to_id]?.includes(id); + if (isNewReply) { + const pendingReplies = (state.pendingReplies[statusId] ??= []); + pendingReplies.push({ id, in_reply_to_id }); + } + }); }; const deleteFromContexts = (state: Draft, ids: string[]): void => { @@ -129,12 +166,33 @@ const updateContext = (state: Draft, status: ApiStatusJSON): void => { export const contextsReducer = createReducer(initialState, (builder) => { builder .addCase(fetchContext.fulfilled, (state, action) => { - normalizeContext(state, action.meta.arg.statusId, action.payload.context); + const currentReplies = state.replies[action.meta.arg.statusId] ?? []; + const hasReplies = currentReplies.length > 0; + // Ignore prefetchOnly if there are no replies - then we can load them immediately + if (action.payload.prefetchOnly && hasReplies) { + storePrefetchedReplies( + state, + action.meta.arg.statusId, + action.payload.context, + ); + } else { + normalizeContext( + state, + action.meta.arg.statusId, + action.payload.context, + ); - if (action.payload.refresh) { - state.refreshing[action.meta.arg.statusId] = action.payload.refresh; + if (action.payload.refresh && !action.payload.prefetchOnly) { + state.refreshing[action.meta.arg.statusId] = action.payload.refresh; + } } }) + .addCase(showPendingReplies, (state, action) => { + applyPrefetchedReplies(state, action.payload.statusId); + }) + .addCase(clearPendingReplies, (state, action) => { + delete state.pendingReplies[action.payload.statusId]; + }) .addCase(completeContextRefresh, (state, action) => { delete state.refreshing[action.payload.statusId]; }) diff --git a/app/javascript/mastodon/reducers/modal.ts b/app/javascript/mastodon/reducers/modal.ts index e287626ff2f..dfdff7cf037 100644 --- a/app/javascript/mastodon/reducers/modal.ts +++ b/app/javascript/mastodon/reducers/modal.ts @@ -41,7 +41,7 @@ const popModal = ( modalType === state.get('stack').get(0)?.get('modalType') ) { return state - .set('ignoreFocus', !!ignoreFocus) + .set('ignoreFocus', ignoreFocus) .update('stack', (stack) => stack.shift()); } else { return state; diff --git a/app/javascript/mastodon/utils/__tests__/html-test.ts b/app/javascript/mastodon/utils/__tests__/html-test.ts index 6aacc396dc8..a48a8b572b3 100644 --- a/app/javascript/mastodon/utils/__tests__/html-test.ts +++ b/app/javascript/mastodon/utils/__tests__/html-test.ts @@ -53,13 +53,19 @@ describe('html', () => { it('calls onElement callback', () => { const input = '

lorem ipsum

'; - const onElement = vi.fn( - (element: HTMLElement, children: React.ReactNode[]) => - React.createElement(element.tagName.toLowerCase(), {}, ...children), + const onElement = vi.fn( + (element, props, children) => + React.createElement( + element.tagName.toLowerCase(), + props, + ...children, + ), ); html.htmlStringToComponents(input, { onElement }); expect(onElement).toHaveBeenCalledExactlyOnceWith( expect.objectContaining({ tagName: 'P' }), + // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment + expect.objectContaining({ key: expect.any(String) }), expect.arrayContaining(['lorem ipsum']), {}, ); @@ -71,6 +77,8 @@ describe('html', () => { const output = html.htmlStringToComponents(input, { onElement }); expect(onElement).toHaveBeenCalledExactlyOnceWith( expect.objectContaining({ tagName: 'P' }), + // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment + expect.objectContaining({ key: expect.any(String) }), expect.arrayContaining(['lorem ipsum']), {}, ); diff --git a/app/javascript/mastodon/utils/environment.ts b/app/javascript/mastodon/utils/environment.ts index c666e2c94d7..c2b6b1cf86a 100644 --- a/app/javascript/mastodon/utils/environment.ts +++ b/app/javascript/mastodon/utils/environment.ts @@ -20,10 +20,7 @@ export function isFeatureEnabled(feature: Features) { export function isModernEmojiEnabled() { try { - return ( - isFeatureEnabled('modern_emojis') && - localStorage.getItem('experiments')?.split(',').includes('modern_emojis') - ); + return isFeatureEnabled('modern_emojis'); } catch { return false; } diff --git a/app/javascript/mastodon/utils/html.ts b/app/javascript/mastodon/utils/html.ts index 971aefa6d16..c87b5a34cfc 100644 --- a/app/javascript/mastodon/utils/html.ts +++ b/app/javascript/mastodon/utils/html.ts @@ -32,20 +32,31 @@ interface QueueItem { depth: number; } -export interface HTMLToStringOptions> { +export type OnElementHandler< + Arg extends Record = Record, +> = ( + element: HTMLElement, + props: Record, + children: React.ReactNode[], + extra: Arg, +) => React.ReactNode; + +export type OnAttributeHandler< + Arg extends Record = Record, +> = ( + name: string, + value: string, + tagName: string, + extra: Arg, +) => [string, unknown] | undefined | null; + +export interface HTMLToStringOptions< + Arg extends Record = Record, +> { maxDepth?: number; onText?: (text: string, extra: Arg) => React.ReactNode; - onElement?: ( - element: HTMLElement, - children: React.ReactNode[], - extra: Arg, - ) => React.ReactNode; - onAttribute?: ( - name: string, - value: string, - tagName: string, - extra: Arg, - ) => [string, unknown] | null; + onElement?: OnElementHandler; + onAttribute?: OnAttributeHandler; allowedTags?: AllowedTagsType; extraArgs?: Arg; } @@ -125,9 +136,57 @@ export function htmlStringToComponents>( const children: React.ReactNode[] = []; let element: React.ReactNode = undefined; + // Generate props from attributes. + const key = `html-${uniqueIdCounter++}`; // Get the current key and then increment it. + const props: Record = { key }; + for (const attr of node.attributes) { + let name = attr.name.toLowerCase(); + + // Custom attribute handler. + if (onAttribute) { + const result = onAttribute(name, attr.value, tagName, extraArgs); + // Rewrite this attribute. + if (result) { + const [cbName, value] = result; + props[cbName] = value; + continue; + } else if (result === null) { + // Explicitly remove this attribute. + continue; + } + } + + // Check global attributes first, then tag-specific ones. + const globalAttr = globalAttributes[name]; + const tagAttr = tagInfo.attributes?.[name]; + + // Exit if neither global nor tag-specific attribute is allowed. + if (!globalAttr && !tagAttr) { + continue; + } + + // Rename if needed. + if (typeof tagAttr === 'string') { + name = tagAttr; + } else if (typeof globalAttr === 'string') { + name = globalAttr; + } + + let value: string | boolean | number = attr.value; + + // Handle boolean attributes. + if (value === 'true') { + value = true; + } else if (value === 'false') { + value = false; + } + + props[name] = value; + } + // If onElement is provided, use it to create the element. if (onElement) { - const component = onElement(node, children, extraArgs); + const component = onElement(node, props, children, extraArgs); // Check for undefined to allow returning null. if (component !== undefined) { @@ -137,53 +196,6 @@ export function htmlStringToComponents>( // If the element wasn't created, use the default conversion. if (element === undefined) { - const props: Record = {}; - props.key = `html-${uniqueIdCounter++}`; // Get the current key and then increment it. - for (const attr of node.attributes) { - let name = attr.name.toLowerCase(); - - // Custom attribute handler. - if (onAttribute) { - const result = onAttribute( - name, - attr.value, - node.tagName.toLowerCase(), - extraArgs, - ); - if (result) { - const [cbName, value] = result; - props[cbName] = value; - } - } else { - // Check global attributes first, then tag-specific ones. - const globalAttr = globalAttributes[name]; - const tagAttr = tagInfo.attributes?.[name]; - - // Exit if neither global nor tag-specific attribute is allowed. - if (!globalAttr && !tagAttr) { - continue; - } - - // Rename if needed. - if (typeof tagAttr === 'string') { - name = tagAttr; - } else if (typeof globalAttr === 'string') { - name = globalAttr; - } - - let value: string | boolean | number = attr.value; - - // Handle boolean attributes. - if (value === 'true') { - value = true; - } else if (value === 'false') { - value = false; - } - - props[name] = value; - } - } - element = React.createElement( tagName, props, diff --git a/app/javascript/styles/entrypoints/mailer.scss b/app/javascript/styles/entrypoints/mailer.scss index 7d2a54afae0..fcbbd66f4c7 100644 --- a/app/javascript/styles/entrypoints/mailer.scss +++ b/app/javascript/styles/entrypoints/mailer.scss @@ -88,6 +88,14 @@ table + p { padding: 24px; } +.email-inner-nested-card-td { + border-radius: 12px; + padding: 18px; + overflow: hidden; + background-color: #fff; + border: 1px solid #dfdee3; +} + // Account .email-account-banner-table { background-color: #f3f2f5; @@ -559,12 +567,29 @@ table + p { } } +.email-quote-header-img { + width: 34px; + + img { + width: 34px; + height: 34px; + border-radius: 8px; + overflow: hidden; + } +} + .email-status-header-text { padding-left: 16px; padding-right: 16px; vertical-align: middle; } +.email-quote-header-text { + padding-left: 14px; + padding-right: 14px; + vertical-align: middle; +} + .email-status-header-name { font-size: 16px; font-weight: 600; @@ -578,6 +603,19 @@ table + p { color: #746a89; } +.email-quote-header-name { + font-size: 14px; + font-weight: 600; + line-height: 18px; + color: #17063b; +} + +.email-quote-header-handle { + font-size: 13px; + line-height: 18px; + color: #746a89; +} + .email-status-content { padding-top: 24px; } @@ -589,6 +627,10 @@ table + p { } .email-status-prose { + .quote-inline { + display: none; + } + p { font-size: 14px; line-height: 20px; diff --git a/app/javascript/styles/mastodon/admin.scss b/app/javascript/styles/mastodon/admin.scss index e2a3f0c0afe..b76d7ef843d 100644 --- a/app/javascript/styles/mastodon/admin.scss +++ b/app/javascript/styles/mastodon/admin.scss @@ -300,9 +300,9 @@ $content-width: 840px; font-size: 13px; font-weight: 700; color: $darker-text-color; - padding-bottom: 8px; + padding-top: 24px; margin-bottom: 8px; - border-bottom: 1px solid var(--background-border-color); + border-top: 1px solid var(--background-border-color); } h6 { @@ -696,7 +696,7 @@ body, } &__title { - word-wrap: break-word; + overflow-wrap: break-word; } &__timestamp { @@ -747,7 +747,7 @@ body, } &__title { - word-wrap: break-word; + overflow-wrap: break-word; } &__timestamp { @@ -1397,7 +1397,7 @@ a.sparkline { .report-header { display: grid; - grid-gap: 15px; + gap: 15px; grid-template-columns: minmax(0, 1fr) 300px; &__details { @@ -1507,7 +1507,7 @@ a.sparkline { margin: 8px 0; overflow: hidden; text-overflow: ellipsis; - word-wrap: break-word; + overflow-wrap: break-word; max-height: 21px * 2; position: relative; font-size: 15px; @@ -1664,7 +1664,7 @@ a.sparkline { &__content { font-size: 15px; line-height: 20px; - word-wrap: break-word; + overflow-wrap: break-word; font-weight: 400; color: $primary-text-color; @@ -1766,7 +1766,7 @@ a.sparkline { padding: 15px; font-size: 15px; line-height: 20px; - word-wrap: break-word; + overflow-wrap: break-word; font-weight: 400; color: $primary-text-color; box-sizing: border-box; @@ -1946,10 +1946,9 @@ a.sparkline { .status__card { padding: 15px; border-radius: 4px; - background: $ui-base-color; font-size: 15px; line-height: 20px; - word-wrap: break-word; + overflow-wrap: break-word; font-weight: 400; border: 1px solid lighten($ui-base-color, 4%); color: $primary-text-color; @@ -1965,8 +1964,105 @@ a.sparkline { .status__content { padding-top: 0; - summary { - display: list-item; + > details { + summary { + display: block; + box-sizing: border-box; + background: var(--nested-card-background); + color: var(--nested-card-text); + border: var(--nested-card-border); + border-radius: 8px; + padding: 8px 13px; + position: relative; + font-size: 15px; + line-height: 22px; + cursor: pointer; + + &::after { + content: attr(data-show, 'Show more'); + margin-top: 8px; + display: block; + font-size: 15px; + line-height: 20px; + color: $highlight-text-color; + cursor: pointer; + border: 0; + background: transparent; + padding: 0; + text-decoration: none; + font-weight: 500; + } + + &:hover, + &:focus-visible { + &::after { + text-decoration: underline !important; + } + } + } + + &[open] summary { + margin-bottom: 16px; + + &::after { + content: attr(data-hide, 'Hide post'); + } + } + } + } + + .preview-card { + position: relative; + max-width: 566px; + + .status-card__image { + &--video { + aspect-ratio: 16 / 9; + } + + &--large { + aspect-ratio: 1.91 / 1; + } + + aspect-ratio: 1; + } + + .spoiler-button__overlay__label { + outline: 1px solid var(--media-outline-color); + } + + .hide-button { + // Toggled to appear when the preview-card is unblurred: + display: none; + position: absolute; + top: 5px; + right: 5px; + color: $white; + border: 0; + outline: 1px solid var(--media-outline-color); + background-color: color.change($black, $alpha: 0.45); + backdrop-filter: $backdrop-blur-filter; + padding: 3px 12px; + border-radius: 99px; + font-size: 14px; + font-weight: 700; + line-height: 20px; + + &:hover, + &:focus { + background-color: color.change($black, $alpha: 0.9); + } + } + + &.preview-card--image-visible { + .hide-button { + display: block; + } + + .spoiler-button__overlay, + .status-card__image-preview { + display: none; + } } } } diff --git a/app/javascript/styles/mastodon/components.scss b/app/javascript/styles/mastodon/components.scss index bf518d72fcf..78c711c5528 100644 --- a/app/javascript/styles/mastodon/components.scss +++ b/app/javascript/styles/mastodon/components.scss @@ -1122,7 +1122,7 @@ .edit-indicator__content, .reply-indicator__content { position: relative; - word-wrap: break-word; + overflow-wrap: break-word; font-weight: 400; overflow: hidden; text-overflow: ellipsis; @@ -1363,7 +1363,7 @@ } .announcements__item__content { - word-wrap: break-word; + overflow-wrap: break-word; overflow-y: auto; .emojione { @@ -1528,7 +1528,7 @@ & > .status__content, & > .status__action-bar, & > .media-gallery, - & > .video-player, + & > div > .video-player, & > .audio-player, & > .attachment-list, & > .picture-in-picture-placeholder, @@ -3153,18 +3153,23 @@ a.account__display-name { .column__alert { position: sticky; - bottom: 1rem; + bottom: 0; z-index: 10; box-sizing: border-box; display: grid; width: 100%; max-width: 360px; - padding-inline: 10px; - margin-top: 1rem; - margin-inline: auto; + padding: 1rem; + margin: auto auto 0; + overflow: clip; + + &:empty { + padding: 0; + } @media (max-width: #{$mobile-menu-breakpoint - 1}) { - bottom: 4rem; + // Compensate for mobile menubar + bottom: var(--mobile-bottom-nav-height); } & > * { @@ -3963,7 +3968,7 @@ a.account__display-name { .react-toggle-screenreader-only, .sr-only { border: 0; - clip: rect(0 0 0 0); + clip-path: inset(50%); height: 1px; margin: -1px; overflow: hidden; @@ -5172,10 +5177,8 @@ a.status-card { &__menu { @include search-popout; - & { - padding: 0; - background: $ui-secondary-color; - } + padding: 0; + background: $ui-secondary-color; } &__menu-list { @@ -8317,7 +8320,7 @@ noscript { font-weight: 400; overflow: hidden; word-break: normal; - word-wrap: break-word; + overflow-wrap: break-word; p { margin-bottom: 20px; @@ -8961,7 +8964,7 @@ noscript { position: relative; font-size: 15px; line-height: 20px; - word-wrap: break-word; + overflow-wrap: break-word; font-weight: 400; max-height: 50vh; overflow: hidden; @@ -10436,7 +10439,7 @@ noscript { &:hover, &:focus, &:active { - background: color.change($ui-base-color, $alpha: 0.85); + background: color.change($white, $alpha: 0.15); } } diff --git a/app/javascript/styles/mastodon/dashboard.scss b/app/javascript/styles/mastodon/dashboard.scss index c99cdc357af..8326022f71a 100644 --- a/app/javascript/styles/mastodon/dashboard.scss +++ b/app/javascript/styles/mastodon/dashboard.scss @@ -61,7 +61,7 @@ .dashboard { display: grid; grid-template-columns: minmax(0, 1fr) minmax(0, 1fr) minmax(0, 1fr); - grid-gap: 10px; + gap: 10px; @media screen and (width <= 1350px) { grid-template-columns: minmax(0, 1fr) minmax(0, 1fr); diff --git a/app/javascript/styles/mastodon/emoji_picker.scss b/app/javascript/styles/mastodon/emoji_picker.scss index 1fde5de1dc2..d443b74fe3a 100644 --- a/app/javascript/styles/mastodon/emoji_picker.scss +++ b/app/javascript/styles/mastodon/emoji_picker.scss @@ -190,7 +190,7 @@ padding: 0; margin: -1px; overflow: hidden; - clip: rect(0, 0, 0, 0); + clip-path: inset(50%); border: 0; } diff --git a/app/javascript/styles/mastodon/forms.scss b/app/javascript/styles/mastodon/forms.scss index b3708b722e3..650081d1ebb 100644 --- a/app/javascript/styles/mastodon/forms.scss +++ b/app/javascript/styles/mastodon/forms.scss @@ -299,7 +299,7 @@ code { color: $primary-text-color; display: block; margin-bottom: 8px; - word-wrap: break-word; + overflow-wrap: break-word; font-weight: 500; } diff --git a/app/javascript/styles/mastodon/polls.scss b/app/javascript/styles/mastodon/polls.scss index b13c9d61329..e8f2f5c3940 100644 --- a/app/javascript/styles/mastodon/polls.scss +++ b/app/javascript/styles/mastodon/polls.scss @@ -60,7 +60,6 @@ &__text { display: inline-block; - word-wrap: break-word; overflow-wrap: break-word; max-width: calc(100% - 45px - 25px); } diff --git a/app/javascript/testing/api.ts b/app/javascript/testing/api.ts index 4948d719974..dd45b7e7b6b 100644 --- a/app/javascript/testing/api.ts +++ b/app/javascript/testing/api.ts @@ -1,7 +1,10 @@ +import type { CompactEmoji } from 'emojibase'; import { http, HttpResponse } from 'msw'; import { action } from 'storybook/actions'; -import { relationshipsFactory } from './factories'; +import { toSupportedLocale } from '@/mastodon/features/emoji/locale'; + +import { customEmojiFactory, relationshipsFactory } from './factories'; export const mockHandlers = { mute: http.post<{ id: string }>('/api/v1/accounts/:id/mute', ({ params }) => { @@ -40,6 +43,24 @@ export const mockHandlers = { ); }, ), + emojiCustomData: http.get('/api/v1/custom_emojis', () => { + action('fetching custom emoji data')(); + return HttpResponse.json([customEmojiFactory()]); + }), + emojiData: http.get<{ locale: string }>( + '/packs-dev/emoji/:locale.json', + async ({ params }) => { + const locale = toSupportedLocale(params.locale); + action('fetching emoji data')(locale); + const { default: data } = (await import( + `emojibase-data/${locale}/compact.json` + )) as { + default: CompactEmoji[]; + }; + + return HttpResponse.json([data]); + }, + ), }; export const unhandledRequestHandler = ({ url }: Request) => { diff --git a/app/lib/activitypub/activity/create.rb b/app/lib/activitypub/activity/create.rb index 607e9be8cc7..3d52c9a56ca 100644 --- a/app/lib/activitypub/activity/create.rb +++ b/app/lib/activitypub/activity/create.rb @@ -218,11 +218,11 @@ class ActivityPub::Activity::Create < ActivityPub::Activity def process_quote @quote_uri = @status_parser.quote_uri - return if @quote_uri.blank? + return unless @status_parser.quote? approval_uri = @status_parser.quote_approval_uri approval_uri = nil if unsupported_uri_scheme?(approval_uri) || TagManager.instance.local_url?(approval_uri) - @quote = Quote.new(account: @account, approval_uri: approval_uri, legacy: @status_parser.legacy_quote?) + @quote = Quote.new(account: @account, approval_uri: approval_uri, legacy: @status_parser.legacy_quote?, state: @status_parser.deleted_quote? ? :deleted : :pending) end def process_hashtag(tag) diff --git a/app/lib/activitypub/activity/delete.rb b/app/lib/activitypub/activity/delete.rb index ce36cfe763f..3e77f9b9556 100644 --- a/app/lib/activitypub/activity/delete.rb +++ b/app/lib/activitypub/activity/delete.rb @@ -59,9 +59,11 @@ class ActivityPub::Activity::Delete < ActivityPub::Activity @quote = Quote.find_by(approval_uri: object_uri, quoted_account: @account) return if @quote.nil? - ActivityPub::Forwarder.new(@account, @json, @quote.status).forward! + ActivityPub::Forwarder.new(@account, @json, @quote.status).forward! if @quote.status.present? + @quote.reject! - DistributionWorker.perform_async(@quote.status_id, { 'update' => true }) + + DistributionWorker.perform_async(@quote.status_id, { 'update' => true }) if @quote.status.present? end def forwarder diff --git a/app/lib/activitypub/forwarder.rb b/app/lib/activitypub/forwarder.rb index 3a94f9669ab..c5ff59fa5ae 100644 --- a/app/lib/activitypub/forwarder.rb +++ b/app/lib/activitypub/forwarder.rb @@ -27,17 +27,25 @@ class ActivityPub::Forwarder @reblogged_by_account_ids ||= @status.reblogs.includes(:account).references(:account).merge(Account.local).pluck(:account_id) end + def quoted_by_account_ids + @quoted_by_account_ids ||= @status.quotes.includes(:account).references(:account).merge(Account.local).pluck(:account_id) + end + + def shared_by_account_ids + reblogged_by_account_ids.concat(quoted_by_account_ids) + end + def signature_account_id @signature_account_id ||= if in_reply_to_local? in_reply_to.account_id else - reblogged_by_account_ids.first + shared_by_account_ids.first end end def inboxes @inboxes ||= begin - arr = inboxes_for_followers_of_reblogged_by_accounts + arr = inboxes_for_followers_of_shared_by_accounts arr += inboxes_for_followers_of_replied_to_account if in_reply_to_local? arr -= [@account.preferred_inbox_url] arr.uniq! @@ -45,8 +53,8 @@ class ActivityPub::Forwarder end end - def inboxes_for_followers_of_reblogged_by_accounts - Account.where(id: ::Follow.where(target_account_id: reblogged_by_account_ids).select(:account_id)).inboxes + def inboxes_for_followers_of_shared_by_accounts + Account.where(id: ::Follow.where(target_account_id: shared_by_account_ids).select(:account_id)).inboxes end def inboxes_for_followers_of_replied_to_account diff --git a/app/lib/activitypub/parser/status_parser.rb b/app/lib/activitypub/parser/status_parser.rb index ad4ecebbbf5..57e6cb926c4 100644 --- a/app/lib/activitypub/parser/status_parser.rb +++ b/app/lib/activitypub/parser/status_parser.rb @@ -118,6 +118,14 @@ class ActivityPub::Parser::StatusParser flags end + def quote? + %w(quote _misskey_quote quoteUrl quoteUri).any? { |key| @object[key].present? } + end + + def deleted_quote? + @object['quote'].is_a?(Hash) && @object['quote']['type'] == 'Tombstone' + end + def quote_uri %w(quote _misskey_quote quoteUrl quoteUri).filter_map do |key| value_or_id(as_array(@object[key]).first) @@ -142,7 +150,7 @@ class ActivityPub::Parser::StatusParser def quote_subpolicy(subpolicy) flags = 0 - allowed_actors = as_array(subpolicy) + allowed_actors = as_array(subpolicy).dup allowed_actors.uniq! flags |= Status::QUOTE_APPROVAL_POLICY_FLAGS[:public] if allowed_actors.delete('as:Public') || allowed_actors.delete('Public') || allowed_actors.delete('https://www.w3.org/ns/activitystreams#Public') diff --git a/app/lib/permalink_redirector.rb b/app/lib/permalink_redirector.rb index 142a05d10d3..19fb3f401c9 100644 --- a/app/lib/permalink_redirector.rb +++ b/app/lib/permalink_redirector.rb @@ -12,21 +12,21 @@ class PermalinkRedirector @object ||= begin if at_username_status_request? || statuses_status_request? status = Status.find_by(id: second_segment) - status if status&.distributable? && !status&.local? + status if status&.distributable? && !status&.local? && !status&.account&.suspended? elsif at_username_request? username, domain = first_segment.delete_prefix('@').split('@') domain = nil if TagManager.instance.local_domain?(domain) account = Account.find_remote(username, domain) - account unless account&.local? + account if !account&.local? && !account&.suspended? elsif accounts_request? && record_integer_id_request? account = Account.find_by(id: second_segment) - account unless account&.local? + account if !account&.local? && !account&.suspended? end end end def redirect_path - return ActivityPub::TagManager.instance.url_for(object) if object.present? + return ActivityPub::TagManager.instance.url_for(object) || ActivityPub::TagManager.instance.uri_for(object) if object.present? @path.delete_prefix('/deck') if @path.start_with?('/deck') end diff --git a/app/models/account.rb b/app/models/account.rb index a837cc6a6ff..5f4caf9eaa7 100644 --- a/app/models/account.rb +++ b/app/models/account.rb @@ -52,7 +52,7 @@ # requested_review_at :datetime # indexable :boolean default(FALSE), not null # attribution_domains :string default([]), is an Array -# id_scheme :integer default("username_ap_id") +# id_scheme :integer default("numeric_ap_id") # class Account < ApplicationRecord @@ -446,7 +446,6 @@ class Account < ApplicationRecord before_validation :prepare_contents, if: :local? before_create :generate_keys - before_create :set_id_scheme before_destroy :clean_feed_manager def ensure_keys! @@ -471,12 +470,6 @@ class Account < ApplicationRecord self.public_key = keypair.public_key.to_pem end - def set_id_scheme - return unless local? && Mastodon::Feature.numeric_ap_ids_enabled? - - self.id_scheme = :numeric_ap_id - end - def normalize_domain return if local? diff --git a/app/models/concerns/account/suspensions.rb b/app/models/concerns/account/suspensions.rb index c981fb5a295..4c9ca593ad0 100644 --- a/app/models/concerns/account/suspensions.rb +++ b/app/models/concerns/account/suspensions.rb @@ -32,6 +32,10 @@ module Account::Suspensions update!(suspended_at: date, suspension_origin: origin) create_canonical_email_block! if block_email end + + # This terminates all connections for the given account with the streaming + # server: + redis.publish("timeline:system:#{id}", Oj.dump(event: :kill)) if local? end def unsuspend! diff --git a/app/models/form/admin_settings.rb b/app/models/form/admin_settings.rb index a19a6308fac..a0decbea860 100644 --- a/app/models/form/admin_settings.rb +++ b/app/models/form/admin_settings.rb @@ -14,7 +14,6 @@ class Form::AdminSettings site_terms registrations_mode closed_registrations_message - timeline_preview bootstrap_timeline_accounts theme activity_api_enabled @@ -41,6 +40,10 @@ class Form::AdminSettings app_icon favicon min_age + local_live_feed_access + remote_live_feed_access + local_topic_feed_access + remote_topic_feed_access ).freeze INTEGER_KEYS = %i( @@ -84,6 +87,7 @@ class Form::AdminSettings DESCRIPTION_LIMIT = 200 DOMAIN_BLOCK_AUDIENCES = %w(disabled users all).freeze REGISTRATION_MODES = %w(open approved none).freeze + FEED_ACCESS_MODES = %w(public authenticated).freeze attr_accessor(*KEYS) @@ -93,6 +97,10 @@ class Form::AdminSettings validates :bootstrap_timeline_accounts, existing_username: { multiple: true }, if: -> { defined?(@bootstrap_timeline_accounts) } validates :show_domain_blocks, inclusion: { in: DOMAIN_BLOCK_AUDIENCES }, if: -> { defined?(@show_domain_blocks) } validates :show_domain_blocks_rationale, inclusion: { in: DOMAIN_BLOCK_AUDIENCES }, if: -> { defined?(@show_domain_blocks_rationale) } + validates :local_live_feed_access, inclusion: { in: FEED_ACCESS_MODES }, if: -> { defined?(@local_live_feed_access) } + validates :remote_live_feed_access, inclusion: { in: FEED_ACCESS_MODES }, if: -> { defined?(@remote_live_feed_access) } + validates :local_topic_feed_access, inclusion: { in: FEED_ACCESS_MODES }, if: -> { defined?(@local_topic_feed_access) } + validates :remote_topic_feed_access, inclusion: { in: FEED_ACCESS_MODES }, if: -> { defined?(@remote_topic_feed_access) } validates :media_cache_retention_period, :content_cache_retention_period, :backups_retention_period, numericality: { only_integer: true }, allow_blank: true, if: -> { defined?(@media_cache_retention_period) || defined?(@content_cache_retention_period) || defined?(@backups_retention_period) } validates :min_age, numericality: { only_integer: true }, allow_blank: true, if: -> { defined?(@min_age) } validates :site_short_description, length: { maximum: DESCRIPTION_LIMIT }, if: -> { defined?(@site_short_description) } diff --git a/app/models/quote.rb b/app/models/quote.rb index dcfcd3b353c..0d24cb239a8 100644 --- a/app/models/quote.rb +++ b/app/models/quote.rb @@ -25,7 +25,7 @@ class Quote < ApplicationRecord REFRESH_DEADLINE = 6.hours enum :state, - { pending: 0, accepted: 1, rejected: 2, revoked: 3 }, + { pending: 0, accepted: 1, rejected: 2, revoked: 3, deleted: 4 }, validate: true belongs_to :status diff --git a/app/models/status_edit.rb b/app/models/status_edit.rb index d99591d7992..060866e50c3 100644 --- a/app/models/status_edit.rb +++ b/app/models/status_edit.rb @@ -52,6 +52,10 @@ class StatusEdit < ApplicationRecord underlying_quote end + def with_preview_card? + false + end + def with_media? ordered_media_attachments.any? end diff --git a/app/models/user.rb b/app/models/user.rb index 8e0785e7fdd..ccd96bdc92a 100644 --- a/app/models/user.rb +++ b/app/models/user.rb @@ -180,6 +180,10 @@ class User < ApplicationRecord def disable! update!(disabled: true) + + # This terminates all connections for the given account with the streaming + # server: + redis.publish("timeline:system:#{account.id}", Oj.dump(event: :kill)) end def enable! @@ -357,17 +361,22 @@ class User < ApplicationRecord end def reset_password! + # First, change password to something random, this revokes sessions and on-going access: + change_password!(SecureRandom.hex) + + # Finally, send a reset password prompt to the user + send_reset_password_instructions + end + + def change_password!(new_password) # First, change password to something random and deactivate all sessions transaction do - update(password: SecureRandom.hex) + update(password: new_password) session_activations.destroy_all end # Then, remove all authorized applications and connected push subscriptions revoke_access! - - # Finally, send a reset password prompt to the user - send_reset_password_instructions end protected diff --git a/app/serializers/activitypub/note_serializer.rb b/app/serializers/activitypub/note_serializer.rb index 4c5d3f4cf8f..f162f4ee243 100644 --- a/app/serializers/activitypub/note_serializer.rb +++ b/app/serializers/activitypub/note_serializer.rb @@ -32,8 +32,8 @@ class ActivityPub::NoteSerializer < ActivityPub::Serializer attribute :voters_count, if: :poll_and_voters_count? attribute :quote, if: :quote? - attribute :quote, key: :_misskey_quote, if: :quote? - attribute :quote, key: :quote_uri, if: :quote? + attribute :quote, key: :_misskey_quote, if: :serializable_quote? + attribute :quote, key: :quote_uri, if: :serializable_quote? attribute :quote_authorization, if: :quote_authorization? attribute :interaction_policy @@ -214,13 +214,17 @@ class ActivityPub::NoteSerializer < ActivityPub::Serializer object.quote&.present? end + def serializable_quote? + object.quote&.quoted_status&.present? + end + def quote_authorization? object.quote.present? && ActivityPub::TagManager.instance.approval_uri_for(object.quote).present? end def quote # TODO: handle inlining self-quotes - ActivityPub::TagManager.instance.uri_for(object.quote.quoted_status) + object.quote.quoted_status.present? ? ActivityPub::TagManager.instance.uri_for(object.quote.quoted_status) : { type: 'Tombstone' } end def quote_authorization diff --git a/app/serializers/initial_state_serializer.rb b/app/serializers/initial_state_serializer.rb index 495b543e3d4..93c06b7676a 100644 --- a/app/serializers/initial_state_serializer.rb +++ b/app/serializers/initial_state_serializer.rb @@ -111,12 +111,15 @@ class InitialStateSerializer < ActiveModel::Serializer sso_redirect: sso_redirect, status_page_url: Setting.status_page_url, streaming_api_base_url: Rails.configuration.x.streaming_api_base_url, - timeline_preview: Setting.timeline_preview, title: instance_presenter.title, trends_as_landing_page: Setting.trends_as_landing_page, trends_enabled: Setting.trends, version: instance_presenter.version, terms_of_service_enabled: TermsOfService.current.present?, + local_live_feed_access: Setting.local_live_feed_access, + remote_live_feed_access: Setting.remote_live_feed_access, + local_topic_feed_access: Setting.local_topic_feed_access, + remote_topic_feed_access: Setting.remote_topic_feed_access, } end diff --git a/app/serializers/rest/instance_serializer.rb b/app/serializers/rest/instance_serializer.rb index 3008df5e81c..36ddfae3286 100644 --- a/app/serializers/rest/instance_serializer.rb +++ b/app/serializers/rest/instance_serializer.rb @@ -100,6 +100,21 @@ class REST::InstanceSerializer < ActiveModel::Serializer enabled: TranslationService.configured?, }, + timelines_access: { + live_feeds: { + local: Setting.local_live_feed_access, + remote: Setting.remote_live_feed_access, + }, + hashtag_feeds: { + local: Setting.local_topic_feed_access, + remote: Setting.remote_topic_feed_access, + }, + trending_link_feeds: { + local: Setting.local_topic_feed_access, + remote: Setting.remote_topic_feed_access, + }, + }, + limited_federation: limited_federation?, } end diff --git a/app/services/activitypub/process_status_update_service.rb b/app/services/activitypub/process_status_update_service.rb index 66c8da2b604..7e267342580 100644 --- a/app/services/activitypub/process_status_update_service.rb +++ b/app/services/activitypub/process_status_update_service.rb @@ -74,6 +74,8 @@ class ActivityPub::ProcessStatusUpdateService < BaseService update_quote_approval! update_counts! end + + broadcast_updates! if @status.quote&.state_previously_changed? end def update_interaction_policies! @@ -298,7 +300,7 @@ class ActivityPub::ProcessStatusUpdateService < BaseService def update_quote! quote_uri = @status_parser.quote_uri - if quote_uri.present? + if @status_parser.quote? approval_uri = @status_parser.quote_approval_uri approval_uri = nil if unsupported_uri_scheme?(approval_uri) || TagManager.instance.local_url?(approval_uri) @@ -308,7 +310,7 @@ class ActivityPub::ProcessStatusUpdateService < BaseService # Revoke the quote while we get a chance… maybe this should be a `before_destroy` hook? RevokeQuoteService.new.call(@status.quote) if @status.quote.quoted_account&.local? && @status.quote.accepted? @status.quote.destroy - quote = Quote.create(status: @status, approval_uri: approval_uri, legacy: @status_parser.legacy_quote?) + quote = Quote.create(status: @status, approval_uri: approval_uri, legacy: @status_parser.legacy_quote?, state: @status_parser.deleted_quote? ? :deleted : :pending) @quote_changed = true else quote = @status.quote diff --git a/app/services/revoke_quote_service.rb b/app/services/revoke_quote_service.rb index 1dd37d05550..346fba89709 100644 --- a/app/services/revoke_quote_service.rb +++ b/app/services/revoke_quote_service.rb @@ -21,6 +21,11 @@ class RevokeQuoteService < BaseService end def distribute_stamp_deletion! + # It is possible the quoted status has been soft-deleted. + # In this case, `signed_activity_json` would fail, but we can just ignore + # that, as we have already federated deletion. + return if @quote.quoted_status.nil? + ActivityPub::DeliveryWorker.push_bulk(inboxes, limit: 1_000) do |inbox_url| [signed_activity_json, @account.id, inbox_url] end diff --git a/app/views/admin/settings/discovery/show.html.haml b/app/views/admin/settings/discovery/show.html.haml index 51d482d70a5..2620dd94b1b 100644 --- a/app/views/admin/settings/discovery/show.html.haml +++ b/app/views/admin/settings/discovery/show.html.haml @@ -30,10 +30,35 @@ %h4= t('admin.settings.discovery.public_timelines') - .fields-group - = f.input :timeline_preview, - as: :boolean, - wrapper: :with_label + .fields-row + .fields-row__column.fields-row__column-6.fields-group + = f.input :local_live_feed_access, + collection: f.object.class::FEED_ACCESS_MODES, + include_blank: false, + label_method: ->(mode) { I18n.t("admin.settings.feed_access.modes.#{mode}") }, + wrapper: :with_label + + .fields-row__column.fields-row__column-6.fields-group + = f.input :remote_live_feed_access, + collection: f.object.class::FEED_ACCESS_MODES, + include_blank: false, + label_method: ->(mode) { I18n.t("admin.settings.feed_access.modes.#{mode}") }, + wrapper: :with_label + + .fields-row + .fields-row__column.fields-row__column-6.fields-group + = f.input :local_topic_feed_access, + collection: f.object.class::FEED_ACCESS_MODES, + include_blank: false, + label_method: ->(mode) { I18n.t("admin.settings.feed_access.modes.#{mode}") }, + wrapper: :with_label + + .fields-row__column.fields-row__column-6.fields-group + = f.input :remote_topic_feed_access, + collection: f.object.class::FEED_ACCESS_MODES, + include_blank: false, + label_method: ->(mode) { I18n.t("admin.settings.feed_access.modes.#{mode}") }, + wrapper: :with_label %h4= t('admin.settings.discovery.privacy') diff --git a/app/views/admin/shared/_preview_card.html.haml b/app/views/admin/shared/_preview_card.html.haml new file mode 100644 index 00000000000..c4796dc59cc --- /dev/null +++ b/app/views/admin/shared/_preview_card.html.haml @@ -0,0 +1,30 @@ +/# locals: (preview_card:) + +.preview-card + .status-card.expanded + .status-card__image{ class: preview_card_aspect_ratio_classname(preview_card) } + .spoiler-button + %button.hide-button{ type: 'button' }= t('link_preview.potentially_sensitive_content.hide_button') + %button.spoiler-button__overlay{ type: 'button' } + %span.spoiler-button__overlay__label + %span= t('link_preview.potentially_sensitive_content.label') + %span.spoiler-button__overlay__action + %span= t('link_preview.potentially_sensitive_content.action') + %canvas.status-card__image-preview{ 'data-blurhash': preview_card.blurhash, width: 32, height: 32 } + = image_tag preview_card.image.url, alt: '', class: 'status-card__image-image' + = link_to preview_card.url, target: '_blank', rel: 'noopener', data: { confirm: t('link_preview.potentially_sensitive_content.confirm_visit') } do + .status-card__content{ dir: 'auto' } + %span.status-card__host + %span{ lang: preview_card.language } + = preview_card.provider_name + - if preview_card.published_at + · + %time.relative-formatted{ datetime: preview_card.published_at.iso8601, title: l(preview_card.published_at) }= l(preview_card.published_at) + %strong.status-card__title{ title: preview_card.title, lang: preview_card.language } + = preview_card.title + - if preview_card.author_name.present? + %span.status-card__author + = t('link_preview.author_html', name: content_tag(:strong, preview_card.author_name)) + - else + %span.status-card__description{ lang: preview_card.language } + = preview_card.description diff --git a/app/views/admin/shared/_status_attachments.html.haml b/app/views/admin/shared/_status_attachments.html.haml index d34a4221db7..8fca4add52e 100644 --- a/app/views/admin/shared/_status_attachments.html.haml +++ b/app/views/admin/shared/_status_attachments.html.haml @@ -13,6 +13,9 @@ %button.button.button-secondary{ disabled: true } = t('polls.vote') +- if status.with_preview_card? + = render partial: 'admin/shared/preview_card', locals: { preview_card: status.preview_card } + - if status.with_media? - if status.ordered_media_attachments.first.video? = render_video_component(status, visible: false) diff --git a/app/views/admin/shared/_status_content.html.haml b/app/views/admin/shared/_status_content.html.haml index aedd84bdd67..465696fe5e9 100644 --- a/app/views/admin/shared/_status_content.html.haml +++ b/app/views/admin/shared/_status_content.html.haml @@ -1,8 +1,14 @@ .status__content>< - if status.spoiler_text.present? %details< - %summary>< - %strong> Content warning: #{prerender_custom_emojis(h(status.spoiler_text), status.emojis)} + %summary{ + data: { + show: t('statuses.content_warnings.show'), + hide: t('statuses.content_warnings.hide'), + } + }>< + %strong> + = prerender_custom_emojis(h(status.spoiler_text), status.emojis) = prerender_custom_emojis(status_content_format(status), status.emojis) = render partial: 'admin/shared/status_attachments', locals: { status: status.proper } - else diff --git a/app/views/notification_mailer/_nested_quote.html.haml b/app/views/notification_mailer/_nested_quote.html.haml new file mode 100644 index 00000000000..dc0921c2ed5 --- /dev/null +++ b/app/views/notification_mailer/_nested_quote.html.haml @@ -0,0 +1,17 @@ +%table.email-w-full{ cellspacing: 0, cellpadding: 0, border: 0, role: 'presentation' } + %tr + %td.email-quote-header-img + = image_tag full_asset_url(status.account.avatar.url), alt: '', width: 34, height: 34 + %td.email-quote-header-text + %h2.email-quote-header-name + = display_name(status.account) + %p.email-quote-header-handle + @#{status.account.pretty_acct} + +%table.email-w-full{ cellspacing: 0, cellpadding: 0, border: 0, role: 'presentation' } + %tr + %td.email-status-content + = render 'notification_mailer/status_content', status: status + + %p.email-status-footer + = link_to l(status.created_at.in_time_zone(time_zone.presence), format: :with_time_zone), web_url("@#{status.account.pretty_acct}/#{status.id}") diff --git a/app/views/notification_mailer/_status.html.haml b/app/views/notification_mailer/_status.html.haml index bf38dc9aa26..c56c7ec72ca 100644 --- a/app/views/notification_mailer/_status.html.haml +++ b/app/views/notification_mailer/_status.html.haml @@ -11,21 +11,12 @@ %table.email-w-full{ cellspacing: 0, cellpadding: 0, border: 0, role: 'presentation' } %tr %td.email-status-content - .auto-dir - - if status.spoiler_text? - %p.email-status-spoiler - = status.spoiler_text - - .email-status-prose - = status_content_format(status) - - - if status.ordered_media_attachments.size.positive? - %p.email-status-media - - status.ordered_media_attachments.each do |a| - - if status.local? - = link_to full_asset_url(a.file.url(:original)), full_asset_url(a.file.url(:original)) - - else - = link_to a.remote_url, a.remote_url + = render 'notification_mailer/status_content', status: status + - if status.local? && status.quote + %table.email-inner-card-table{ cellspacing: 0, cellpadding: 0, border: 0, role: 'presentation' } + %tr + %td.email-inner-nested-card-td + = render 'notification_mailer/nested_quote', status: status.quote.quoted_status, time_zone: time_zone %p.email-status-footer = link_to l(status.created_at.in_time_zone(time_zone.presence), format: :with_time_zone), web_url("@#{status.account.pretty_acct}/#{status.id}") diff --git a/app/views/notification_mailer/_status.text.erb b/app/views/notification_mailer/_status.text.erb index e03e8346c16..13711ee74d9 100644 --- a/app/views/notification_mailer/_status.text.erb +++ b/app/views/notification_mailer/_status.text.erb @@ -4,5 +4,9 @@ > <% end %> > <%= raw word_wrap(extract_status_plain_text(status), break_sequence: "\n> ") %> +<% if status.local? && status.quote %> +> +>> <%= raw word_wrap(extract_status_plain_text(status.quote.quoted_status), break_sequence: "\n>> ") %> +<% end %> <%= raw t('application_mailer.view')%> <%= web_url("@#{status.account.pretty_acct}/#{status.id}") %> diff --git a/app/views/notification_mailer/_status_content.html.haml b/app/views/notification_mailer/_status_content.html.haml new file mode 100644 index 00000000000..f95ba8ccba8 --- /dev/null +++ b/app/views/notification_mailer/_status_content.html.haml @@ -0,0 +1,15 @@ +.auto-dir + - if status.spoiler_text? + %p.email-status-spoiler + = status.spoiler_text + + .email-status-prose + = status_content_format(status) + + - if status.ordered_media_attachments.size.positive? + %p.email-status-media + - status.ordered_media_attachments.each do |a| + - if status.local? + = link_to full_asset_url(a.file.url(:original)), full_asset_url(a.file.url(:original)) + - else + = link_to a.remote_url, a.remote_url diff --git a/app/views/settings/preferences/appearance/show.html.haml b/app/views/settings/preferences/appearance/show.html.haml index 72e2575a8ea..3dc60697a44 100644 --- a/app/views/settings/preferences/appearance/show.html.haml +++ b/app/views/settings/preferences/appearance/show.html.haml @@ -47,15 +47,6 @@ #{t 'appearance.localization.body'} #{content_tag(:a, t('appearance.localization.guide_link_text'), href: t('appearance.localization.guide_link'), target: '_blank', rel: 'noopener')} = f.simple_fields_for :settings, current_user.settings do |ff| - %h4= t 'appearance.advanced_web_interface' - - %p.hint= t 'appearance.advanced_web_interface_hint' - - .fields-group - = ff.input :'web.advanced_layout', - hint: false, - label: I18n.t('simple_form.labels.defaults.setting_advanced_layout'), - wrapper: :with_label %h4= t 'appearance.animations_and_accessibility' .fields-group @@ -77,12 +68,10 @@ .fields-group = ff.input :'web.trends', wrapper: :with_label, label: I18n.t('simple_form.labels.defaults.setting_trends') - %h4= t 'appearance.confirmation_dialogs' + %h4= t 'appearance.boosting_preferences' .fields-group - = ff.input :'web.reblog_modal', wrapper: :with_label, label: I18n.t('simple_form.labels.defaults.setting_boost_modal') - = ff.input :'web.delete_modal', wrapper: :with_label, label: I18n.t('simple_form.labels.defaults.setting_delete_modal') - = ff.input :'web.missing_alt_text_modal', wrapper: :with_label, label: I18n.t('simple_form.labels.defaults.setting_missing_alt_text_modal') + = ff.input :'web.reblog_modal', wrapper: :with_label, hint: I18n.t('simple_form.hints.defaults.setting_boost_modal'), label: I18n.t('simple_form.labels.defaults.setting_boost_modal') %h4= t 'appearance.sensitive_content' @@ -106,5 +95,17 @@ .fields-group = ff.input :'web.expand_content_warnings', wrapper: :with_label, label: I18n.t('simple_form.labels.defaults.setting_expand_spoilers') + %h4= t 'appearance.advanced_settings' + + .fields-group + = ff.input :'web.advanced_layout', + hint: I18n.t('simple_form.hints.defaults.setting_advanced_layout'), + label: I18n.t('simple_form.labels.defaults.setting_advanced_layout'), + wrapper: :with_label + + .fields-group + = ff.input :'web.delete_modal', wrapper: :with_label, label: I18n.t('simple_form.labels.defaults.setting_delete_modal') + = ff.input :'web.missing_alt_text_modal', wrapper: :with_label, label: I18n.t('simple_form.labels.defaults.setting_missing_alt_text_modal') + .actions = f.button :button, t('generic.save_changes'), type: :submit diff --git a/app/workers/activitypub/refetch_and_verify_quote_worker.rb b/app/workers/activitypub/refetch_and_verify_quote_worker.rb index 0c7ecd9b2ac..e2df0231030 100644 --- a/app/workers/activitypub/refetch_and_verify_quote_worker.rb +++ b/app/workers/activitypub/refetch_and_verify_quote_worker.rb @@ -10,6 +10,7 @@ class ActivityPub::RefetchAndVerifyQuoteWorker def perform(quote_id, quoted_uri, options = {}) quote = Quote.find(quote_id) ActivityPub::VerifyQuoteService.new.call(quote, fetchable_quoted_uri: quoted_uri, request_id: options[:request_id]) + ::DistributionWorker.perform_async(quote.status_id, { 'update' => true }) if quote.state_previously_changed? rescue ActiveRecord::RecordNotFound # Do nothing true diff --git a/config/locales/activerecord.sk.yml b/config/locales/activerecord.sk.yml index 68a9e447b90..1513142bd2f 100644 --- a/config/locales/activerecord.sk.yml +++ b/config/locales/activerecord.sk.yml @@ -4,7 +4,7 @@ sk: attributes: poll: expires_at: Trvá do - options: Voľby + options: Možnosti user: agreement: Dohoda o poskytovaní služieb email: E-mailová adresa diff --git a/config/locales/af.yml b/config/locales/af.yml index 89ede096e28..4f6cacffea7 100644 --- a/config/locales/af.yml +++ b/config/locales/af.yml @@ -93,8 +93,6 @@ af: status: Status title: Webhoeke webhook: Web-hoek - appearance: - advanced_web_interface_hint: As jy die volle wydte van jou skerm gebruik, laat die gevorderde webkoppelvlak jou toe om kolomme met verskillende soorte inligting langs mekaar te rangskik. So kan jy, byvoorbeeld, tegelyk jou tuistoevoer, kennisgewings, gefedereerde tydlyn en nog ander lyste of hutsetikette dophou. auth: apply_for_account: Doen aansoek om ’n rekening logout: Teken uit diff --git a/config/locales/an.yml b/config/locales/an.yml index 4b9385d5f8f..64aa98ce5de 100644 --- a/config/locales/an.yml +++ b/config/locales/an.yml @@ -877,10 +877,7 @@ an: hint_html: Si quiers migrar d'unatra cuenta a esta, aquí puetz creyar un alias, que ye necesario antes de que puedas empecipiar a mover seguidors d'a cuenta anterior ta esta. Esta acción per ella mesma ye inofensiva y reversible. La migración d'a cuenta s'inicia dende la cuenta antiga. remove: Desvincular alias appearance: - advanced_web_interface: Interficie web abanzada - advanced_web_interface_hint: 'Si deseya utilizar tot l''amplo de pantalla, la interficie web abanzada le permite configurar quantas columnas diferents pa veyer tanta información a lo mesmo tiempo como quiera: Inicio, notificacions, linia de tiempo federada, qualsequier numero de listas y etiquetas.' animations_and_accessibility: Animacions y accesibilidat - confirmation_dialogs: Dialogos de confirmación discovery: Descubrir localization: body: Mastodon ye traduciu con la aduya de voluntarios. diff --git a/config/locales/ar.yml b/config/locales/ar.yml index f48e9fc9ef9..fb601718057 100644 --- a/config/locales/ar.yml +++ b/config/locales/ar.yml @@ -1253,10 +1253,7 @@ ar: hint_html: إذا كنت ترغب في الانتقال من حساب آخر إلى هذا الحساب الحالي، يمكنك إنشاء اسم مستعار هنا، والذي هو مطلوب قبل أن تتمكن من المضي قدما في نقل متابِعيك من الحساب القديم إلى هذا الحساب. هذا الإجراء بحد ذاته هو غير مؤذي و قابل للعكس. تتم بداية تهجير الحساب من الحساب القديم. remove: إلغاء ربط الكنية appearance: - advanced_web_interface: واجهة الويب المتقدمة - advanced_web_interface_hint: 'إذا كنت ترغب في استخدام عرض شاشتك بأكمله، فواجهة الويب المتقدمة تسمح لك بضبط العديد من الأعمدة المختلفة لرؤية أكبر قدر من المعلومات التي ترغب فيها في آن واحد: الخيط الرئيسي والإشعارات والخيط الزمني الفدرالي وأي عدد من القوائم والوسوم.' animations_and_accessibility: الإتاحة والحركة - confirmation_dialogs: نوافذ التأكيد discovery: الاستكشاف localization: body: ماستدون يُترجِمه متطوّعون. diff --git a/config/locales/ast.yml b/config/locales/ast.yml index 81806695b5e..b0e1052382a 100644 --- a/config/locales/ast.yml +++ b/config/locales/ast.yml @@ -326,6 +326,9 @@ ast: all: A tol mundu disabled: A naide users: A los perfiles llocales + feed_access: + modes: + public: Tol mundu registrations: preamble: Controla quién pue crear una cuenta nel sirvidor. title: Rexistros @@ -429,10 +432,7 @@ ast: aliases: empty: Nun tienes nengún nomatu. appearance: - advanced_web_interface: Interfaz web avanzada - advanced_web_interface_hint: 'Si quies asegúrate de que s''use tol llargor de la pantalla, la interfaz web avanzada permítete configurar columnes estremaes pa ver muncha más información al empar: Aniciu, avisos, llinia de tiempu federada y cualesquier cantidá de llistes y etiquetes.' animations_and_accessibility: Animaciones y accesibilidá - confirmation_dialogs: Diálogos de confirmación discovery: Descubrimientu localization: body: Mastodon tradúcenlu voluntarios, diff --git a/config/locales/az.yml b/config/locales/az.yml index 0fa11278cee..1f35a7ada1e 100644 --- a/config/locales/az.yml +++ b/config/locales/az.yml @@ -118,10 +118,7 @@ az: next_steps: Moderasiya qərarını geri almaq üçün etirazı təsdiqləyə, ya da etirazı yox saya bilərsiniz. subject: "%{username}, %{instance} üzərindəki bir moderasiya qərarına etiraz edir" appearance: - advanced_web_interface: Qabaqcıl veb interfeys - advanced_web_interface_hint: 'Tam ekran enini istifadə etmək istəyirsinizsə, qabaqcıl veb interfeys, istədiyiniz qədər məlumatı eyni anda görə bilməyiniz üçün bir çox fərqli sütunu konfiqurasiya etməyinizə imkan verir: Əsas ekran, bildirişlər, birləşmiş zaman xətti, istənilən sayda siyahı və mövzu etiketləri.' animations_and_accessibility: Animasiyalar və erişiləbilənlik - confirmation_dialogs: Təsdiq dialoq pəncərələri discovery: Kəşf et localization: guide_link_text: Hər kəs töhfə verə bilər. diff --git a/config/locales/be.yml b/config/locales/be.yml index cd7bf94e1a2..bbce0603271 100644 --- a/config/locales/be.yml +++ b/config/locales/be.yml @@ -707,7 +707,7 @@ be: created_at: Створана delete_and_resolve: Выдаліць допісы forwarded: Пераслана - forwarded_replies_explanation: Гэтае паведамленне паступіла ад выдаленага карыстальніка і дакранаецца выдаленага змесціва. Яно было накіраванае вам, бо змесціва паведамлення з'яўляецца адказам аднаму з вашых карыстальнікаў. + forwarded_replies_explanation: Гэтае паведамленне паступіла ад карыстальніка з іншага сервера і дакранаецца змесціва адтуль. Яно было накіраванае вам, бо змесціва паведамлення з'яўляецца адказам аднаму з вашых карыстальнікаў. forwarded_to: Пераслана на %{domain} mark_as_resolved: Пазначыць як вырашаную mark_as_sensitive: Пазначыць як далікатны @@ -876,6 +876,10 @@ be: all: Для ўсіх disabled: Нікому users: Лакальным карыстальнікам, якія ўвайшлі + feed_access: + modes: + authenticated: Толькі аўтэнтыфікаваныя карыстальнікі + public: Усе registrations: moderation_recommandation: Пераканайцеся, што ў вас ёсць адэкватная і аператыўная каманда мадэратараў, перш чым адчыняць рэгістрацыю для ўсіх жадаючых! preamble: Кантралюйце, хто можа ствараць уліковы запіс на вашым серверы. @@ -1220,10 +1224,7 @@ be: hint_html: Калі вы хочаце перайсці з іншага ўліковага запісу ў гэты, то тут вы можаце стварыць псеўданім, каб перамясціць падпісчыкаў са старога ўліковага запісу ў гэты. Гэта дзеянне з'яўляецца бясшкодным і зварачальным. Перанос уліковага запісу пачынаецца са старога ўліковага запісу. remove: Адмацаваць псеўданім appearance: - advanced_web_interface: Пашыраны вэб-інтэрфейс - advanced_web_interface_hint: 'Калі вы хочаце выкарыстоўваць усю шырыню экрана, пашыраны вэб-інтэрфейс дазваляе вам наладзіць мноства розных слупкоў, каб бачыць столькі інфармацыі, колькі вам трэба: галоўная, апавяшчэнні, глабальная стужка, любая колькасць спісаў і хэштэгаў.' animations_and_accessibility: Анімацыі і даступнасць - confirmation_dialogs: Дыялогавыя вокны пацвярджэння discovery: Адкрыцці localization: body: Mastodon перакладаецца добраахвотнікамі. @@ -1665,6 +1666,13 @@ be: expires_at: Дзее да uses: Выкарыстанні title: Запрасіць людзей + link_preview: + author_html: Ад %{name} + potentially_sensitive_content: + action: Націсніце, каб паказаць + confirm_visit: Вы ўпэўненыя, што хочаце адкрыць гэту спасылку? + hide_button: Схаваць + label: Патэнцыйна далікатны кантэнт lists: errors: limit: Вы дасягнулі макс. колькасці спісаў @@ -1981,6 +1989,9 @@ be: other: "%{count} відэафайла" boosted_from_html: Пашырыў уліковы запіс %{acct_link} content_warning: 'Папярэджанне аб змесціве: %{warning}' + content_warnings: + hide: Схаваць допіс + show: Паказаць усё роўна default_language: Такая, што і мова інтэрфэйсу disallowed_hashtags: few: 'змяшчае недазволеныя хэштэгі: %{tags}' diff --git a/config/locales/bg.yml b/config/locales/bg.yml index 309d634914e..1f22bf0047e 100644 --- a/config/locales/bg.yml +++ b/config/locales/bg.yml @@ -1166,10 +1166,7 @@ bg: hint_html: Ако желаете да се преместите от друг акаунт към този, тук можете да създадете псевдоним, което се изисква преди да можете да пристъпите към преместване на последователите си от стария акаунт към този. Това действие е безопасно и възстановимо. Миграцията към новия акаунт се инициира от стария акаунт. remove: Разкачвне на псевдонима appearance: - advanced_web_interface: Разширен уеб интерфейс - advanced_web_interface_hint: 'Ако искате да употребявате цялата ширина на екрана си, разширеният уеб интерфейс ви позволява да настроите най-различни колони, за да виждате едновременно множество сведения, колкото искате: Начало, известия, федеративен инфоканал, произволен брой списъци и хаштагове.' animations_and_accessibility: Анимация и достъпност - confirmation_dialogs: Диалогов прозорец за потвърждение discovery: Откриване localization: body: Mastodon е преведено от доброволци. diff --git a/config/locales/br.yml b/config/locales/br.yml index c6cb9152522..30f4a50fbce 100644 --- a/config/locales/br.yml +++ b/config/locales/br.yml @@ -145,6 +145,7 @@ br: destroy_custom_emoji_html: Dilamet eo bet ar fromlun %{target} gant %{name} destroy_email_domain_block_html: Distanket eo bet an domani postel %{target} gant %{name} destroy_status_html: Dilamet eo bet toud %{target} gant %{name} + destroy_user_role_html: Dilamet eo bet ar perzh %{target} gant %{name} disable_custom_emoji_html: Diweredekaet eo bet ar fromlun %{target} gant %{name} enable_custom_emoji_html: Gweredekaet eo bet ar fromlun %{target} gant %{name} resend_user_html: Adkaset eo bet ar postel kadarnaat evit %{target} gant %{name} @@ -372,6 +373,7 @@ br: manage_rules: Merañ reolennoù ar servijer title: Diwar-benn appearance: + preamble: Personelaat etrefas web Mastodon. title: Neuz content_retention: danger_zone: Takad dañjer @@ -776,12 +778,13 @@ br: account: Kont account_settings: Arventennoù ar gont aliases: Aliasoù ar gont + appearance: Neuz back: Distreiñ da vMastodon delete: Dilemel ar gont development: Diorren edit_profile: Kemmañ ar profil export: Ezporzhiañ - featured_tags: Gerioù-klik en a-raok + featured_tags: Penngerioù-klik import: Enporzhiañ import_and_export: Enporzhiañ hag ezporzhiañ notifications: Kemennoù dre bostel diff --git a/config/locales/ca.yml b/config/locales/ca.yml index eae71f330c8..c3be44daa8e 100644 --- a/config/locales/ca.yml +++ b/config/locales/ca.yml @@ -190,6 +190,7 @@ ca: create_relay: Crea un repetidor create_unavailable_domain: Crea un domini no disponible create_user_role: Crea Rol + create_username_block: Crear regla de nom d'usuari demote_user: Degrada l'usuari destroy_announcement: Esborra l'anunci destroy_canonical_email_block: Elimina el blocatge del correu electrònic @@ -203,6 +204,7 @@ ca: destroy_status: Elimina la publicació destroy_unavailable_domain: Esborra domini no disponible destroy_user_role: Destrueix Rol + destroy_username_block: Eliminar regla de nom d'usuari disable_2fa_user: Desactiva 2FA disable_custom_emoji: Desactiva l'emoji personalitzat disable_relay: Desactiva el repetidor @@ -237,6 +239,7 @@ ca: update_report: Actualitza l'informe update_status: Actualitza l'estat update_user_role: Actualitza Rol + update_username_block: Actualitzar regla de nom d'usuari actions: approve_appeal_html: "%{name} ha aprovat l'apel·lació a la decisió de moderació de %{target}" approve_user_html: "%{name} ha aprovat el registre de %{target}" @@ -1083,6 +1086,24 @@ ca: other: Emprat per %{count} persones en la darrera setmana title: Recomanacions i tendències trending: Tendència + username_blocks: + add_new: Afegeix-ne una de nova + comparison: + contains: Conté + equals: És igual a + contains_html: Conté %{string} + created_msg: Creada una regla de nom d'usuari + delete: Elimina + edit: + title: Editar regla de nom d'usuari + matches_exactly_html: És igual a %{string} + new: + create: Crea una regla + title: Crear nova regla de nom d'usuari + no_username_block_selected: No s'ha canviat cap regla de nom d'usuari perquè no se n'havia seleccionat cap + not_permitted: No permés + title: Regles de nom d'usuari + updated_msg: Actualitzada una regla de nom d'usuari warning_presets: add_new: Afegir-ne un de nou delete: Elimina @@ -1155,10 +1176,7 @@ ca: hint_html: Si et vols moure des d'un altre compte a aquest, aquí pots crear un àlies, el qual és requerit abans que puguis procedir a moure els seguidors del compte vell a aquest. Aquesta acció és per si mateixa inofensiva i reversible. La migració del compte és iniciada des de'l compte vell. remove: Desvincula l'àlies appearance: - advanced_web_interface: Interfície web avançada - advanced_web_interface_hint: 'Si vols fer ús de tota l''amplada de la teva pantalla, la interfície web avançada et permet configurar diverses columnes per a veure molta més informació al mateix temps: Inici, notificacions, línia de temps federada i qualsevol quantitat de llistes i etiquetes.' animations_and_accessibility: Animacions i accessibilitat - confirmation_dialogs: Diàlegs de confirmació discovery: Descobriment localization: body: Mastodon és traduït per voluntaris. @@ -1712,6 +1730,7 @@ ca: self_vote: No pots votar en les teves propies enquestes too_few_options: ha de tenir més d'una opció too_many_options: no pot contenir més de %{max} opcions + vote: Voteu preferences: other: Altres posting_defaults: Valors per defecte de publicació @@ -1888,6 +1907,7 @@ ca: title: '%{name}: "%{quote}"' visibilities: direct: Menció privada + private: Només seguidors public: Públic public_long: Tothom dins o fora Mastodon unlisted_long: Amagat dels resultats de cerca de Mastodon, de les tendències i de les línies temporals diff --git a/config/locales/ckb.yml b/config/locales/ckb.yml index 891453a7cef..8494e6e46ff 100644 --- a/config/locales/ckb.yml +++ b/config/locales/ckb.yml @@ -545,10 +545,7 @@ ckb: hint_html: ئەگەر دەتەوێت لە هەژمارەیەکی ترەوە بگوێزریتەوە بۆ ئەم هەژمارە، لێرەدا دەتوانیت نازناوێک دروست بکەیت، پێش ئەوەی ئەوە بەردەوام بیت لە گواستنەوەی لە هەژمارە کۆنەکە بۆ ئەم هەژمارە پێویستە. ئەم کردەوەیە خۆی لە خۆیدا بێ زەرە و ناگەڕێتەوەگواستنەوەی لە هەژمارەی کۆنە بۆ هەژمارەی نوێ دەستی پێکردووە. remove: سڕینەوەی پەیوەندی ناز ناو appearance: - advanced_web_interface: روخساری پێشکەوتوو - advanced_web_interface_hint: 'ئەگەر دەتەوێت پانی شاشەکە بەکاربێنیت، دەتوانی بە یارمەتی ڕووکاری پێشکەوتوو چەندین ستوونی جیاواز ڕێکبخەیت بۆ بینینی زانیاری زیاتر لە هەمان کات کە دەتەوێت بیبینیت: نووسراوەکانی نووسەرانی دیکە، ئاگانامەکان، پێرستی نووسراوەکانی هەموو شوێنێک، وە هەر ژمارەیەک لە لیستەکان و هاشتاگەکان.' animations_and_accessibility: ئەنیمەیشن و توانایی دەستپێگەیشتن - confirmation_dialogs: پەیامەکانی پەسەندکراو discovery: دۆزینەوە localization: body: ماستۆدۆن لەلایەن خۆبەخشەوە وەردەگێڕێت. diff --git a/config/locales/co.yml b/config/locales/co.yml index 01dcc19ba3a..268377d7dd3 100644 --- a/config/locales/co.yml +++ b/config/locales/co.yml @@ -508,10 +508,7 @@ co: hint_html: Per traslucà da un altru contu à questu, quì pudete creà un pseudonimu o "alias", riquisitu per trasferì l'abbunati da u vechju contu à u novu. St'azzione sola ùn face nunda è pò esse annullata senza prublemi. A migrazione hè principiata dapoi u vechju contu. remove: Sguassà u pseudonimu appearance: - advanced_web_interface: Interfaccia web avanzata - advanced_web_interface_hint: 'S''è voi vulete fà usu di a larghezza sana di u vostru screnu, l''interfaccia web avanzata vi permette di cunfigurà parechje culonne sfarente per vede tutta l''infurmazione chì vulete vede in listessu tempu: Accolta, nutificazione, linea pubblica, è tutti l''hashtag è liste chì vulete.' animations_and_accessibility: Animazione è accessibilità - confirmation_dialogs: Pop-up di cunfirmazione discovery: Scuperta localization: body: Mastodon hè tradottu da una squadra di vuluntari. diff --git a/config/locales/cs.yml b/config/locales/cs.yml index fd3b5797817..3919dbe98d0 100644 --- a/config/locales/cs.yml +++ b/config/locales/cs.yml @@ -876,6 +876,10 @@ cs: all: Všem disabled: Nikomu users: Přihlášeným místním uživatelům + feed_access: + modes: + authenticated: Pouze autentifikovaní uživatelé + public: Všichni registrations: moderation_recommandation: Před otevřením registrací všem se ujistěte, že máte vhodný a reaktivní moderační tým! preamble: Mějte pod kontrolou, kdo může vytvořit účet na vašem serveru. @@ -1220,10 +1224,7 @@ cs: hint_html: Chcete-li se přesunout z jiného účtu na tento, můžete si zde vytvořit alias, který je vyžadován předtím, než můžete pokračovat přesunem sledujících ze starého účtu na tento. Tato akce sama o sobě je neškodná a vratná. Přesun účtu se zahajuje ze starého účtu. remove: Odpojit alias appearance: - advanced_web_interface: Pokročilé webové rozhraní - advanced_web_interface_hint: 'Chcete-li využít celé šířky vaší obrazovky, dovolí vám pokročilé webové rozhraní nastavit si mnoho různých sloupců, takže ve stejnou chvíli uvidíte tolik informací, kolik chcete: domovskou časovou osu, oznámení, federovanou časovou osu a libovolný počet seznamů a hashtagů.' animations_and_accessibility: Animace a přístupnost - confirmation_dialogs: Potvrzovací dialogy discovery: Objevování localization: body: Mastodon je překládán dobrovolníky. @@ -1665,6 +1666,13 @@ cs: expires_at: Vyprší uses: Použití title: Pozvat lidi + link_preview: + author_html: Podle %{name} + potentially_sensitive_content: + action: Kliknutím zobrazíte + confirm_visit: Opravdu chcete otevřít tento odkaz? + hide_button: Skrýt + label: Potenciálně citlivý obsah lists: errors: limit: Dosáhl jste maximálního počtu seznamů @@ -1981,6 +1989,9 @@ cs: other: "%{count} videí" boosted_from_html: Boostnuto z %{acct_link} content_warning: 'Varování o obsahu: %{warning}' + content_warnings: + hide: Skrýt příspěvek + show: Zobrazit více default_language: Stejný jako jazyk rozhraní disallowed_hashtags: few: 'obsahoval zakázané hashtagy: %{tags}' diff --git a/config/locales/cy.yml b/config/locales/cy.yml index 7fe0e7dd85f..61d1d9d8afa 100644 --- a/config/locales/cy.yml +++ b/config/locales/cy.yml @@ -904,6 +904,10 @@ cy: all: I bawb disabled: I neb users: I ddefnyddwyr lleol wedi'u mewngofnodi + feed_access: + modes: + authenticated: Defnyddwyr dilys yn unig + public: Pawb registrations: moderation_recommandation: Gwnewch yn siŵr bod gennych chi dîm cymedroli digonol ac adweithiol cyn i chi agor cofrestriadau i bawb! preamble: Rheoli pwy all greu cyfrif ar eich gweinydd. @@ -1258,10 +1262,7 @@ cy: hint_html: Os ydych chi am symud o gyfrif arall i'r un hwn, gallwch greu enw arall yma, sy'n ofynnol cyn y gallwch symud ymlaen i symud dilynwyr o'r hen gyfrif i'r un hwn. Mae'r weithred hon ynddo'i hun yn ddiniwed ac yn wrthdroadwy. Mae'r mudo cyfrif yn cael ei wneud o'r hen gyfrif. remove: Dadgysylltu'r enw arall appearance: - advanced_web_interface: Rhyngwyneb gwe uwch - advanced_web_interface_hint: 'Os ydych chi am ddefnyddio lled eich sgrin gyfan, mae''r rhyngwyneb gwe datblygedig yn caniatáu i chi ffurfweddu llawer o wahanol golofnau i weld faint bynnag o wybodaeth ar yr un pryd ag y dymunwch: Cartref, hysbysiadau, ffrydiau ffederaleiddiwyd, faint bynnag o restrau a hashnodau.' animations_and_accessibility: Animeiddiadau a hygyrchedd - confirmation_dialogs: Deialogau cadarnhau discovery: Darganfod localization: body: Mae Mastodon yn cael ei gyfieithu gan wirfoddolwyr. @@ -1743,6 +1744,13 @@ cy: expires_at: Yn dod i ben ar uses: Defnyddiau title: Gwahodd pobl + link_preview: + author_html: Yn ôl %{name} + potentially_sensitive_content: + action: Cliciwch i ddangos + confirm_visit: Ydych chi'n siŵr eich bod chi eisiau agor y ddolen hon? + hide_button: Cuddio + label: Cynnwys a allai fod yn sensitif lists: errors: limit: Rydych chi wedi cyrraedd y nifer mwyaf o restrau @@ -2065,6 +2073,9 @@ cy: zero: "%{count} fideo" boosted_from_html: Wedi'i hybu o %{acct_link} content_warning: 'Rhybudd cynnwys: %{warning}' + content_warnings: + hide: Cuddio'r postiad + show: Dangos rhagor default_language: Yr un fath a'r iaith rhyngwyneb disallowed_hashtags: few: 'yn cynnwys yr hashnod gwaharddedig: %{tags}' diff --git a/config/locales/da.yml b/config/locales/da.yml index 8ad3ccb1389..e8eaae64bf9 100644 --- a/config/locales/da.yml +++ b/config/locales/da.yml @@ -848,6 +848,10 @@ da: all: Til alle disabled: Til ingen users: Til indloggede lokale brugere + feed_access: + modes: + authenticated: Kun godkendte brugere + public: Alle registrations: moderation_recommandation: Sørg for, at der er et tilstrækkeligt og reaktivt moderationsteam, før registrering åbnes for alle! preamble: Styr, hvem der kan oprette en konto på serveren. @@ -1182,10 +1186,7 @@ da: hint_html: Ønsker du at flytte fra en anden konto til denne, kan du hér oprette det alias, der kræves, for at du kan fortsætte med at flytte følgere fra den gamle konto til denne. Denne handling er i sig selv harmløs og reversibel. Kontomigreringen påbegyndes fra den gamle konto. remove: Fjern aliaslinkning appearance: - advanced_web_interface: Avanceret webgrænseflade - advanced_web_interface_hint: 'Ønsker du udnytte hele skærmbredden, lader den avancerede webgrænseflade dig opsætte mange forskellige kolonner for at se så meget information på samme tid som ønsket: Hjem, notifikationer, federeret tidslinje, et hvilket som helst antal lister og hashtags.' animations_and_accessibility: Animationer og tilgængelighed - confirmation_dialogs: Bekræftelsesdialoger discovery: Opdagelse localization: body: Mastodon oversættes af frivillige. @@ -1281,7 +1282,7 @@ da: account_status: Kontostatus confirming: Afventer færdiggørelse af e-mailbekræftelse. functional: Din konto er fuldt funktionel. - pending: Ansøgningen afventer gennemgang af vores personale. Dette kan tage noget tid. Man bør modtage en e-mail, såfremt ansøgningen godkendes. + pending: Ansøgningen afventer gennemgang af vores personale. Dette kan tage noget tid. Du modtager en e-mail, hvis din ansøgning bliver godkendt. redirecting_to: Din konto er inaktiv, da den pt. er omdirigerer til %{acct}. self_destruct: Da %{domain} er under nedlukning, vil kontoadgangen være begrænset. view_strikes: Se tidligere anmeldelser af din konto @@ -1587,6 +1588,13 @@ da: expires_at: Udløber uses: Benyttelser title: Invitér personer + link_preview: + author_html: Af %{name} + potentially_sensitive_content: + action: Klik for at vise + confirm_visit: Er du sikker på, at du vil åbne dette link? + hide_button: Skjul + label: Potentielt følsomt indhold lists: errors: limit: Maks. listeantal nået @@ -1897,6 +1905,9 @@ da: other: "%{count} videoer" boosted_from_html: Fremhævet fra %{acct_link} content_warning: 'Indholdsadvarsel: %{warning}' + content_warnings: + hide: Skjul indlæg + show: Vis mere default_language: Samme som UI-sproget disallowed_hashtags: one: 'indeholdte et ikke tilladt hashtag: %{tags}' diff --git a/config/locales/de.yml b/config/locales/de.yml index 0f694493fac..69c9e133223 100644 --- a/config/locales/de.yml +++ b/config/locales/de.yml @@ -848,6 +848,10 @@ de: all: Allen disabled: Niemandem users: Für angemeldete lokale Benutzer*innen + feed_access: + modes: + authenticated: Nur authentifizierte Nutzer*innen + public: Alle registrations: moderation_recommandation: Bitte vergewissere dich, dass du ein geeignetes und reaktionsschnelles Moderationsteam hast, bevor du die Registrierungen uneingeschränkt zulässt! preamble: Lege fest, wer auf deinem Server ein Konto erstellen darf. @@ -1182,10 +1186,7 @@ de: hint_html: Wenn du von einem anderen Konto auf dieses umziehen möchtest, dann kannst du hier einen Alias erstellen, der erforderlich ist, um deine Follower vom alten Konto auf dieses zu migrieren. Diese Aktion ist harmlos und wi­der­ruf­lich. Der Kontoumzug wird vom alten Konto aus eingeleitet. remove: Alle Aliasse aufheben appearance: - advanced_web_interface: Erweitertes Webinterface - advanced_web_interface_hint: Wenn du mehr aus deiner Bildschirmbreite herausholen möchtest, kannst du mit dem erweiterten Webinterface weitere Spalten hinzufügen und dadurch mehr Informationen auf einmal sehen, z. B. deine Startseite, die Benachrichtigungen, die föderierte Timeline sowie beliebig viele deiner Listen und Hashtags. animations_and_accessibility: Animationen und Barrierefreiheit - confirmation_dialogs: Bestätigungsdialoge discovery: Entdecken localization: body: Mastodon wird von Freiwilligen übersetzt. @@ -1587,6 +1588,13 @@ de: expires_at: Läuft ab uses: Verwendungen title: Einladungen + link_preview: + author_html: Von %{name} + potentially_sensitive_content: + action: Zum Anzeigen anklicken + confirm_visit: Möchtest du diesen Link wirklich öffnen? + hide_button: Ausblenden + label: Inhaltswarnung lists: errors: limit: Du hast die maximale Anzahl an Listen erreicht @@ -1897,6 +1905,9 @@ de: other: "%{count} Videos" boosted_from_html: Geteilt von %{acct_link} content_warning: 'Inhaltswarnung: %{warning}' + content_warnings: + hide: Beitrag ausblenden + show: Beitrag anzeigen default_language: Wie die Sprache des Webinterface disallowed_hashtags: one: 'enthält einen nicht-erlaubten Hashtag: %{tags}' diff --git a/config/locales/devise.en.yml b/config/locales/devise.en.yml index 65095cd788c..29cc473e019 100644 --- a/config/locales/devise.en.yml +++ b/config/locales/devise.en.yml @@ -7,6 +7,7 @@ en: send_paranoid_instructions: If your email address exists in our database, you will receive an email with instructions for how to confirm your email address in a few minutes. Please check your spam folder if you didn't receive this email. failure: already_authenticated: You are already signed in. + closed_registrations: Your registration attempt has been blocked due to a network policy. If you believe this is an error, contact %{email}. inactive: Your account is not activated yet. invalid: Invalid %{authentication_keys} or password. last_attempt: You have one more attempt before your account is locked. diff --git a/config/locales/devise.sk.yml b/config/locales/devise.sk.yml index 08e93456b03..9d852913d2d 100644 --- a/config/locales/devise.sk.yml +++ b/config/locales/devise.sk.yml @@ -4,7 +4,7 @@ sk: confirmations: confirmed: Vaša e-mailová adresa bola úspešne potvrdená. send_instructions: O niekoľko minút obdržíte e-mail s pokynmi na potvrdenie svojho účtu. Prosíme, skontrolujte si aj zložku spam, ak ste tento e-mail nedostali. - send_paranoid_instructions: Ak sa vaša e-mailová adresa nachádza v našej databáze, o niekoľko minút obdržíte e-mail s pokynmi na potvrdenie svojho účtu. Prosíme, skontrolujte aj zložku spam, ste tento e-mail nedostali. + send_paranoid_instructions: Ak sa vaša e-mailová adresa nachádza v našej databáze, o niekoľko minút obdržíte e-mail s pokynmi na potvrdenie svojho účtu. Prosíme, skontrolujte aj zložku spam, ak ste tento e-mail nedostali. failure: already_authenticated: Už ste sa prihlásili. inactive: Váš účet ešte nie je aktivovaný. @@ -88,8 +88,8 @@ sk: success: Úspešné overenie z účtu %{kind}. passwords: no_token: Túto stránku nemôžete navštíviť, ak vás sem nepresmeroval e-mail s pokynmi na obnovu hesla. Pokiaľ prichádzate z tohto e-mailu, uistite sa, že ste použili celú adresu URL z e-mailu. - send_instructions: Ak sa vaša emailová adresa nachádza v databáze, o niekoľko minút dostanete e-mail s pokynmi na nastavenie nového hesla. Ak ste ho nedostali, skontrolujte aj priečinok pre spam. - send_paranoid_instructions: Ak sa vaša emailová adresa nachádza v databáze, o niekoľko minút dostanete e-mail s pokynmi na nastavenie nového hesla. Ak ste ho nedostali, skontrolujte aj priečinok pre spam. + send_instructions: Ak sa vaša e-mailová adresa nachádza v databáze, o niekoľko minút dostanete e-mail s pokynmi na nastavenie nového hesla. Ak ste ho nedostali, skontrolujte aj priečinok pre spam. + send_paranoid_instructions: Ak sa vaša e-mailová adresa nachádza v databáze, o niekoľko minút dostanete e-mail s pokynmi na nastavenie nového hesla. Ak ste ho nedostali, skontrolujte aj priečinok pre spam. updated: Vaše heslo bolo úspešne zmenené. Teraz ste sa prihlásili. updated_not_active: Vaše heslo bolo úspešne zmenené. registrations: @@ -97,9 +97,9 @@ sk: update_needs_confirmation: Váš účet bol úspešne zmenený, ale ešte potrebujeme overiť vašu novú e-mailovú adresu. Overíte ju kliknutím na potvrdzovací odkaz zaslaný na váš e-mail. Ak ste e-mail nedostali, skontrolujte svoj priečinok pre spam. updated: Váš účet bol úspešne aktualizovaný. sessions: - already_signed_out: Úspešne ste sa odhlásili. + already_signed_out: Odhlásenie prebehlo úspešne. signed_in: Úspešne ste sa prihlásili. - signed_out: Úspešne ste sa odhlásili. + signed_out: Odhlásenie prebehlo úspešne. unlocks: send_instructions: O niekoľko minút obdržíte e-mail s pokynmi na odomknutie svojho účtu. Prosíme, skontrolujte si aj zložku spam, ak ste tento e-mail nedostali. send_paranoid_instructions: Ak váš účet existuje, o niekoľko minút obdržíte e-mail s pokynmi na jeho odomknutie. Prosíme, skontrolujte si aj zložku spam, ak ste tento e-mail nedostali. diff --git a/config/locales/el.yml b/config/locales/el.yml index a17e8700757..217c44e8ff3 100644 --- a/config/locales/el.yml +++ b/config/locales/el.yml @@ -848,6 +848,10 @@ el: all: Για όλους disabled: Για κανέναν users: Προς συνδεδεμένους τοπικούς χρήστες + feed_access: + modes: + authenticated: Πιστοποιημένοι χρήστες μόνο + public: Όλοι registrations: moderation_recommandation: Παρακαλώ βεβαιώσου ότι έχεις μια επαρκής και ενεργή ομάδα συντονισμού πριν ανοίξεις τις εγγραφές για όλους! preamble: Έλεγξε ποιος μπορεί να δημιουργήσει ένα λογαριασμό στον διακομιστή σας. @@ -1182,10 +1186,7 @@ el: hint_html: Αν θέλεις να μετακινηθείς από έναν άλλο λογαριασμό σε αυτόν εδώ, εδώ μπορείς να δημιουργήσεις ένα ψευδώνυμο, πράγμα που απαιτείται πριν προχωρήσεις για να μεταφέρεις τους ακολούθους σου από τον παλιό λογαριασμό σε αυτόν εδώ. Η ενέργεια αυτή είναι ακίνδυνη και αναστρέψιμη.Η μετακόμιση του λογαριασμού ξεκινάει από τον παλιό λογαριασμό. remove: Αποσύνδεση ψευδώνυμου appearance: - advanced_web_interface: Προηγμένη διεπαφή ιστού - advanced_web_interface_hint: 'Αν θέλεις να χρησιμοποιήσεις ολόκληρο το πλάτος της οθόνης σου, η προηγμένη λειτουργία χρήσης σου επιτρέπει να ορίσεις πολλαπλές στήλες ώστε να βλέπεις ταυτόχρονα όση πληροφορία θέλεις: Την αρχική ροή, τις ειδοποιήσεις, τις ομοσπονδιακές ροές και όσες λίστες και ετικέτες θέλεις.' animations_and_accessibility: Εφέ κινήσεων και προσβασιμότητα - confirmation_dialogs: Ερωτήσεις επιβεβαίωσης discovery: Ανακάλυψη localization: body: Το Mastodon μεταφράζεται από εθελοντές. @@ -1587,6 +1588,13 @@ el: expires_at: Λήγει uses: Χρήσεις title: Προσκάλεσε κόσμο + link_preview: + author_html: Από %{name} + potentially_sensitive_content: + action: Κάνε κλικ για εμφάνιση + confirm_visit: Σίγουρα θες να ανοίξεις αυτόν τον σύνδεσμο; + hide_button: Απόκρυψη + label: Δυνητικά ευαίσθητο περιεχόμενο lists: errors: limit: Έχεις φτάσει το μέγιστο αριθμό λιστών @@ -1897,6 +1905,9 @@ el: other: "%{count} βίντεο" boosted_from_html: Ενισχύθηκε από %{acct_link} content_warning: 'Προειδοποίηση περιεχομένου: %{warning}' + content_warnings: + hide: Απόκρυψη ανάρτησης + show: Εμφάνιση περισσότερων default_language: Ίδια με γλώσσα διεπαφής disallowed_hashtags: one: 'περιέχει μη επιτρεπτή ετικέτα: %{tags}' diff --git a/config/locales/en-GB.yml b/config/locales/en-GB.yml index 621a3a4e4fd..8cfd1b76217 100644 --- a/config/locales/en-GB.yml +++ b/config/locales/en-GB.yml @@ -1157,10 +1157,7 @@ en-GB: hint_html: If you want to move from another account to this one, here you can create an alias, which is required before you can proceed with moving followers from the old account to this one. This action by itself is harmless and reversible. The account migration is initiated from the old account. remove: Unlink alias appearance: - advanced_web_interface: Advanced web interface - advanced_web_interface_hint: 'If you want to make use of your entire screen width, the advanced web interface allows you to configure many different columns to see as much information at the same time as you want: Home, notifications, federated timeline, any number of lists and hashtags.' animations_and_accessibility: Animations and accessibility - confirmation_dialogs: Confirmation dialogues discovery: Discovery localization: body: Mastodon is translated by volunteers. diff --git a/config/locales/en.yml b/config/locales/en.yml index 11f8955f2f6..e21698b5892 100644 --- a/config/locales/en.yml +++ b/config/locales/en.yml @@ -848,6 +848,10 @@ en: all: To everyone disabled: To no one users: To logged-in local users + feed_access: + modes: + authenticated: Authenticated users only + public: Everyone registrations: moderation_recommandation: Please make sure you have an adequate and reactive moderation team before you open registrations to everyone! preamble: Control who can create an account on your server. @@ -1182,10 +1186,9 @@ en: hint_html: If you want to move from another account to this one, here you can create an alias, which is required before you can proceed with moving followers from the old account to this one. This action by itself is harmless and reversible. The account migration is initiated from the old account. remove: Unlink alias appearance: - advanced_web_interface: Advanced web interface - advanced_web_interface_hint: 'If you want to make use of your entire screen width, the advanced web interface allows you to configure many different columns to see as much information at the same time as you want: Home, notifications, federated timeline, any number of lists and hashtags.' + advanced_settings: Advanced settings animations_and_accessibility: Animations and accessibility - confirmation_dialogs: Confirmation dialogs + boosting_preferences: Boosting preferences discovery: Discovery localization: body: Mastodon is translated by volunteers. @@ -1587,6 +1590,13 @@ en: expires_at: Expires uses: Uses title: Invite people + link_preview: + author_html: By %{name} + potentially_sensitive_content: + action: Click to show + confirm_visit: Are you sure you wish to open this link? + hide_button: Hide + label: Potentially sensitive content lists: errors: limit: You have reached the maximum number of lists @@ -1898,6 +1908,9 @@ en: other: "%{count} videos" boosted_from_html: Boosted from %{acct_link} content_warning: 'Content warning: %{warning}' + content_warnings: + hide: Hide post + show: Show more default_language: Same as interface language disallowed_hashtags: one: 'contained a disallowed hashtag: %{tags}' diff --git a/config/locales/eo.yml b/config/locales/eo.yml index 812053fa390..2a8c98b1941 100644 --- a/config/locales/eo.yml +++ b/config/locales/eo.yml @@ -1175,10 +1175,7 @@ eo: hint_html: Se vi volas translokiĝi de alia konto al ĉi tie, kreu alinomon. Ĝi estas sekura kaj inversebla. Ĝi komencitas de malnova konto. remove: Malligili alinomon appearance: - advanced_web_interface: Altnivela retpaĝa interfaco - advanced_web_interface_hint: 'Se vi volas uzi la tutan larĝecon de via ekrano, la kompleksa reta interfaco permesas al vi agordi multajn malsamajn kolumnojn por vidi tiom da informoj kiom vi volas samtempe: Hejmo, sciigoj, fratara templinio, kaj ajna kvanto de listoj kaj kradvortoj.' animations_and_accessibility: Animacioj kaj alirebleco - confirmation_dialogs: Konfirmaj fenestroj discovery: Eltrovo localization: body: Mastodon estas tradukita de volontuloj. diff --git a/config/locales/es-AR.yml b/config/locales/es-AR.yml index 7e019daf464..758021015d2 100644 --- a/config/locales/es-AR.yml +++ b/config/locales/es-AR.yml @@ -848,6 +848,10 @@ es-AR: all: A todos disabled: A nadie users: A usuarios locales con sesiones abiertas + feed_access: + modes: + authenticated: Solo usuarios autenticados + public: Todos registrations: moderation_recommandation: Por favor, ¡asegurate de tener un equipo de moderación adecuado y reactivo antes de abrir los registros a todos! preamble: Controlá quién puede crear una cuenta en tu servidor. @@ -1182,10 +1186,7 @@ es-AR: hint_html: Si querés mudarte desde otra cuenta a esta, acá podés crear un alias, el cual es necesario antes de empezar a mudar seguidores de la cuenta vieja a ésta. Esta acción por sí misma es inofensiva y reversible. La migración de la cuenta se inicia desde la cuenta anterior. remove: Desvincular alias appearance: - advanced_web_interface: Interface web avanzada - advanced_web_interface_hint: 'Si querés hacer uso de todo el ancho de tu pantalla, la interface web avanzada te permite configurar varias columnas diferentes para ver tanta información al mismo tiempo como quieras: "Principal", "Notificaciones", "Línea temporal federada", y cualquier número de listas y etiquetas.' animations_and_accessibility: Animaciones y accesibilidad - confirmation_dialogs: Diálogos de confirmación discovery: Descubrí localization: body: Mastodon es localizado por voluntarios. @@ -1587,6 +1588,13 @@ es-AR: expires_at: Vence uses: Usos title: Invitar a gente + link_preview: + author_html: Por %{name} + potentially_sensitive_content: + action: Clic para mostrar + confirm_visit: "¿Está seguro de que querés abrir este enlace?" + hide_button: Ocultar + label: Contenido potencialmente sensible lists: errors: limit: Alcanzaste el número máximo de listas @@ -1897,6 +1905,9 @@ es-AR: other: "%{count} videos" boosted_from_html: Adherido desde %{acct_link} content_warning: 'Advertencia de contenido: %{warning}' + content_warnings: + hide: Ocultar mensaje + show: Mostrar más default_language: Igual que el idioma de la interface disallowed_hashtags: one: 'contenía una etiqueta no permitida: %{tags}' diff --git a/config/locales/es-MX.yml b/config/locales/es-MX.yml index 2f0a69891f1..d078abe8533 100644 --- a/config/locales/es-MX.yml +++ b/config/locales/es-MX.yml @@ -848,6 +848,10 @@ es-MX: all: A todos disabled: A nadie users: Para los usuarios locales que han iniciado sesión + feed_access: + modes: + authenticated: Solo usuarios autenticados + public: Todos registrations: moderation_recommandation: "¡Por favor, asegúrate de contar con un equipo de moderación adecuado y activo antes de abrir el registro al público!" preamble: Controla quién puede crear una cuenta en tu servidor. @@ -1182,10 +1186,7 @@ es-MX: hint_html: Si deseas migrar de otra cuenta a esta, aquí puedes crear un alias, que es necesario para poder mover seguidores de la cuenta anterior a esta. Esta acción por sí misma es inofensiva y reversible. La migración de la cuenta se inicia desde la cuenta anterior. remove: Desvincular alias appearance: - advanced_web_interface: Interfaz web avanzada - advanced_web_interface_hint: 'Si deseas aprovechar todo el ancho de tu pantalla, la interfaz web avanzada te permite configurar muchas columnas diferentes para ver toda la información que quieras al mismo tiempo: inicio, notificaciones, cronología federada, cualquier número de listas y etiquetas.' animations_and_accessibility: Animaciones y accesibilidad - confirmation_dialogs: Diálogos de confirmación discovery: Descubrir localization: body: Mastodon es traducido con la ayuda de voluntarios. @@ -1587,6 +1588,13 @@ es-MX: expires_at: Expira uses: Usos title: Invitar a gente + link_preview: + author_html: Por %{name} + potentially_sensitive_content: + action: Pulsa para mostrar + confirm_visit: "¿Seguro que quieres abrir este enlace?" + hide_button: Ocultar + label: Contenido potencialmente sensible lists: errors: limit: Has alcanzado la cantidad máxima de listas @@ -1897,6 +1905,9 @@ es-MX: other: "%{count} vídeos" boosted_from_html: Impulsado desde %{acct_link} content_warning: 'Alerta de contenido: %{warning}' + content_warnings: + hide: Ocultar publicación + show: Mostrar más default_language: Igual que el idioma de la interfaz disallowed_hashtags: one: 'contenía una etiqueta no permitida: %{tags}' diff --git a/config/locales/es.yml b/config/locales/es.yml index a14c924bd00..4a058efd5ec 100644 --- a/config/locales/es.yml +++ b/config/locales/es.yml @@ -848,6 +848,10 @@ es: all: A todos disabled: A nadie users: Para los usuarios locales que han iniciado sesión + feed_access: + modes: + authenticated: Solo usuarios autenticados + public: Todos registrations: moderation_recommandation: Por favor, ¡asegúrate de tener un equipo de moderación adecuado y reactivo antes de abrir los registros a todo el mundo! preamble: Controla quién puede crear una cuenta en tu servidor. @@ -1182,10 +1186,7 @@ es: hint_html: Si quieres migrar de otra cuenta a esta, aquí puedes crear un alias, es necesario proceder antes de empezar a mover seguidores de la cuenta anterior a esta. Esta acción por sí misma es inofensiva y reversible. La migración de la cuenta se inicia desde la cuenta antigua. remove: Desvincular alias appearance: - advanced_web_interface: Interfaz web avanzada - advanced_web_interface_hint: 'Si quieres aprovechar todo el ancho de tu pantalla, la interfaz web avanzada te permite configurar muchas columnas diferentes para ver toda la información que quieras al mismo tiempo: Inicio, notificaciones, cronología federada, cualquier número de listas y etiquetas.' animations_and_accessibility: Animaciones y accesibilidad - confirmation_dialogs: Diálogos de confirmación discovery: Descubrir localization: body: Mastodon es traducido con la ayuda de voluntarios. @@ -1587,6 +1588,13 @@ es: expires_at: Expira uses: Usos title: Invitar a gente + link_preview: + author_html: Por %{name} + potentially_sensitive_content: + action: Pulsa para mostrar + confirm_visit: "¿Seguro que quieres abrir este enlace?" + hide_button: Ocultar + label: Contenido potencialmente sensible lists: errors: limit: Has alcanzado la cantidad máxima de listas @@ -1897,6 +1905,9 @@ es: other: "%{count} vídeos" boosted_from_html: Impulsado desde %{acct_link} content_warning: 'Alerta de contenido: %{warning}' + content_warnings: + hide: Ocultar publicación + show: Mostrar más default_language: Igual que el idioma de la interfaz disallowed_hashtags: one: 'contenía una etiqueta no permitida: %{tags}' diff --git a/config/locales/et.yml b/config/locales/et.yml index 9607d7661d1..e7008164934 100644 --- a/config/locales/et.yml +++ b/config/locales/et.yml @@ -1182,10 +1182,7 @@ et: hint_html: Kui soovid konto siia üle kolida, pead esmalt siin määrama kolitava konto aadressi. Seejärel on konto valmis võtma vastu jälgijaid vanalt kontolt. Kolitava konto aadressi määramine on iseenesest kahjutu ja tagasipööratav. Jälgijate tegelik kolimine käivitatakse vanalt kontolt. remove: Loobu suunamise vastuvõtmisest appearance: - advanced_web_interface: Kohandatud veebiliides - advanced_web_interface_hint: 'Kui soovid kasutada kogu ekraani laiust, saab kohandatud veebiliideses seadistada mitut veergu, nii et samal ajal oleks näha nii palju infot kui soovid: Kodu, teavitused, föderatsiooni ajajoon ning kuitahes palju nimekirju ja silte.' animations_and_accessibility: Animatsioonid ja ligipääs - confirmation_dialogs: Kinnitusdialoogid discovery: Avastamine localization: body: Mastodoni tõlgivad vabatahtlikud. diff --git a/config/locales/eu.yml b/config/locales/eu.yml index fb11192599b..9e1fcc88a7a 100644 --- a/config/locales/eu.yml +++ b/config/locales/eu.yml @@ -1093,10 +1093,7 @@ eu: hint_html: Beste kontu batetik hona migratu nahi baduzu, hemen ezizen bat sortu dezakezu, hau beharrezkoa da kontu zaharreko jarraitzaileak hona ekartzeko. Ekintza hau berez kaltegabea eta desegingarria da. Kontuaren migrazioa kontu zaharretik abiatzen da. remove: Deslotu ezizena appearance: - advanced_web_interface: Web interfaze aurreratua - advanced_web_interface_hint: 'Pantaila bere zabalera osoan erabili nahi baduzu, web interfaze aurreratuak hainbat zutabe desberdin konfiguratzea ahalbidetzen dizu, aldi berean nahi beste informazio ikusteko: Hasiera, jakinarazpenak, federatutako denbora-lerroa, edo nahi beste zerrenda eta traola.' animations_and_accessibility: Animazioak eta irisgarritasuna - confirmation_dialogs: Berrespen dialogoak discovery: Aurkitzea localization: body: Mastodon boluntarioek itzultzen dute. diff --git a/config/locales/fa.yml b/config/locales/fa.yml index 9c24be80351..bfcb4815891 100644 --- a/config/locales/fa.yml +++ b/config/locales/fa.yml @@ -1182,10 +1182,7 @@ fa: hint_html: اگر می‌خواهید از حساب دیگری به این حساب منتقل شوید، این‌جا می‌توانید یک نام مستعار بسازید که برای انتقال از حساب قدیمی به این حساب لازم است. این کار به تنهایی بی‌ضرر و قابل بازگشت است. فرایند انتقال حساب از حساب قدیمی آغاز خواهد شد. remove: حذف ارتباط نام مستعار appearance: - advanced_web_interface: رابط کاربری پیشرفته - advanced_web_interface_hint: اگر می‌خواهید از تمامی پهنای صفحه‌تان استفاده کنید، رابط پیش‌رفتهٔ وب می‌گذارد هر چند ستون را که می‌خواهید، برای دیدن اطّلاعات بیش‌تر در یک زمان، پیکربندی کنید:‌خانه، آگاهی‌ها، خط زمانی عمومی،‌ هرتعدادی از سیاهه‌ها و برچسب‌ها. animations_and_accessibility: پویانمایی‌های و دسترسی‌پذیری - confirmation_dialogs: پیغام‌های تأیید discovery: کاوش localization: body: ماستودون توسط داوطلبان ترجمه شده است. diff --git a/config/locales/fi.yml b/config/locales/fi.yml index ec474090a62..08a9b1747af 100644 --- a/config/locales/fi.yml +++ b/config/locales/fi.yml @@ -848,6 +848,10 @@ fi: all: Kaikille disabled: Ei kenellekään users: Kirjautuneille paikallisille käyttäjille + feed_access: + modes: + authenticated: Vain todennetut käyttäjät + public: Kaikki registrations: moderation_recommandation: Varmista, että sinulla on riittävä ja toimintavalmis joukko moderaattoreita, ennen kuin avaat rekisteröitymisen kaikille! preamble: Määritä, kuka voi luoda tilin palvelimellesi. @@ -1182,10 +1186,7 @@ fi: hint_html: Jos haluat muuttaa toisesta tilistä tähän tiliin, voit luoda tässä aliaksen, mitä vaaditaan ennen kuin voit edetä siirtämään seuraajasi vanhalta tililtä tälle tilille. Tänä toiminto on itsessään vaaraton ja kumottavissa. Tilin muuttaminen aloitetaan vanhalta tililtä. remove: Poista aliaksen linkitys appearance: - advanced_web_interface: Edistynyt selainkäyttöliittymä - advanced_web_interface_hint: 'Jos haluat hyödyntää näytön koko leveyttä, edistyneen selainkäyttöliittymän avulla voit määrittää useita erilaisia sarakkeita, niin näet kerralla niin paljon tietoa kuin haluat: kotisyöte, ilmoitukset, yleinen aikajana, mikä tahansa määrä listoja ja aihetunnisteita.' animations_and_accessibility: Animaatiot ja saavutettavuus - confirmation_dialogs: Vahvistusikkunat discovery: Löytäminen localization: body: Mastodonin ovat kääntäneet vapaaehtoiset. @@ -1587,6 +1588,13 @@ fi: expires_at: Vanhenee uses: Käyttökertoja title: Kutsu käyttäjiä + link_preview: + author_html: Tehnyt %{name} + potentially_sensitive_content: + action: Näytä napsauttamalla + confirm_visit: Haluatko varmasti avata tämän linkin? + hide_button: Piilota + label: Mahdollisesti arkaluonteista sisältöä lists: errors: limit: Sinulla on enimmäismäärä listoja @@ -1897,6 +1905,9 @@ fi: other: "%{count} videota" boosted_from_html: Tehosti lähteestä %{acct_link} content_warning: 'Sisältövaroitus: %{warning}' + content_warnings: + hide: Piilota julkaisu + show: Näytä lisää default_language: Sama kuin käyttöliittymän kieli disallowed_hashtags: one: 'sisälsi kielletyn aihetunnisteen: %{tags}' diff --git a/config/locales/fo.yml b/config/locales/fo.yml index f6ba039efc7..de2cfc087f0 100644 --- a/config/locales/fo.yml +++ b/config/locales/fo.yml @@ -848,6 +848,10 @@ fo: all: Til øll disabled: Til ongan users: Fyri lokalum brúkarum, sum eru ritaðir inn + feed_access: + modes: + authenticated: Einans váttaðir brúkarar + public: Øll registrations: moderation_recommandation: Vinarliga tryggja tær, at tú hevur eitt nøktandi og klárt umsjónartoymi, áðreen tú letur upp fyri skrásetingum frá øllum! preamble: Stýr, hvør kann stovna eina kontu á tínum ambætara. @@ -1182,10 +1186,7 @@ fo: hint_html: Ynskir tú at flyta frá eini aðrari kontu til hesa, so kanst tú stovna eitt tøkuheiti her. Tað er kravt, áðrenn tú kanst fara í gongd við at flyta fylgjarar frá gomlu kontuni til hesa. Hendan atgerðin er í sær sjálvum meinaleys og kann angrast. Flytingin av kontuni verður sett í gongd frá gomlu kontuni. remove: Strika tilknýti til tøkuheiti appearance: - advanced_web_interface: Framkomið vevmarkamót - advanced_web_interface_hint: 'Ynskir tú at brúka alla skermbreiddina, so loyvir framkomna vevmarkamóti tær at uppseta fleiri ymiskar teigar, soleiðis at tú kanst síggja so nógvar upplýsingar, sum tú ynskir, samstundis: Heima, fráboðanir, sameind tíðarlinja og óavmarkað tal av listum og frámerkjum.' animations_and_accessibility: Teknimyndagerð og atkomuligheit - confirmation_dialogs: Váttanarskermmyndir discovery: Uppdaging localization: body: Mastodon er umsett av sjálvbodnum. @@ -1587,6 +1588,13 @@ fo: expires_at: Rennir út uses: Brúk title: Bjóða fólki + link_preview: + author_html: Av %{name} + potentially_sensitive_content: + action: Klikka fyri at vísa + confirm_visit: Er tú vís/ur í, at tú vil lata hetta leinkið upp? + hide_button: Fjal + label: Tilfar, sum møguliga er viðkvæmt lists: errors: limit: Tú hevur rokkið mesta talið av listum diff --git a/config/locales/fr-CA.yml b/config/locales/fr-CA.yml index 21bc5589837..0ae44cf373a 100644 --- a/config/locales/fr-CA.yml +++ b/config/locales/fr-CA.yml @@ -1135,10 +1135,7 @@ fr-CA: hint_html: Si vous voulez déménager d’un autre compte vers celui-ci, vous pouvez créer ici un alias, qui est nécessaire avant de pouvoir migrer les abonné·e·s de l’ancien compte vers celui-ci. Cette action en soi est inoffensive et réversible. La migration du compte est initiée à partir de l’ancien compte. remove: Détacher l'alias appearance: - advanced_web_interface: Interface web avancée - advanced_web_interface_hint: 'Si vous voulez utiliser toute la largeur de votre écran, l’interface web avancée vous permet de configurer plusieurs colonnes différentes pour voir autant d’informations que vous le souhaitez en même temps : Accueil, notifications, fil public fédéré, un nombre illimité de listes et hashtags.' animations_and_accessibility: Animations et accessibilité - confirmation_dialogs: Dialogues de confirmation discovery: Découverte localization: body: Mastodon est traduit par des volontaires. diff --git a/config/locales/fr.yml b/config/locales/fr.yml index 36244422330..42e0507fe40 100644 --- a/config/locales/fr.yml +++ b/config/locales/fr.yml @@ -1135,10 +1135,7 @@ fr: hint_html: Si vous voulez déménager d’un autre compte vers celui-ci, vous pouvez créer ici un alias, qui est nécessaire avant de pouvoir migrer les abonné·e·s de l’ancien compte vers celui-ci. Cette action en soi est inoffensive et réversible. La migration du compte est initiée à partir de l’ancien compte. remove: Détacher l'alias appearance: - advanced_web_interface: Interface web avancée - advanced_web_interface_hint: 'Si vous voulez utiliser toute la largeur de votre écran, l’interface web avancée vous permet de configurer plusieurs colonnes différentes pour voir autant d’informations que vous le souhaitez en même temps : Accueil, notifications, fil fédéré, un nombre illimité de listes et hashtags.' animations_and_accessibility: Animations et accessibilité - confirmation_dialogs: Dialogues de confirmation discovery: Découverte localization: body: Mastodon est traduit par des volontaires. diff --git a/config/locales/fy.yml b/config/locales/fy.yml index c631241a319..bad1e43f216 100644 --- a/config/locales/fy.yml +++ b/config/locales/fy.yml @@ -1182,10 +1182,7 @@ fy: hint_html: Wannear’t jo fan in oare account ôf nei dizze account ferhúzje wolle, kinne jo hjir in alias oanmeitsje. Dit is nedich eardat jo troch gean kinne mei it ferhúzjen fan folgers fan de âlde nei dizze nije account. Dizze aksje is op eins net gefaarlik en omkearber. De accountmigraasje wurdt start fan de âlde account ôf. remove: Alias ûntkeppelje appearance: - advanced_web_interface: Avansearre webomjouwing - advanced_web_interface_hint: 'Wannear’t jo fan de hiele skermbreedte gebrûk meitsje wolle, stelt de avansearre webomjouwing jo yn steat om meardere ferskate kolommen te konfigurearjen. Hjirmei kinne jo safolle mooglik ynformaasje op itselde momint besjen, lykas: Start, meldingen, de globale tiidline, meardere listen en hashtags.' animations_and_accessibility: Animaasjes en tagonklikheid - confirmation_dialogs: Befêstigingen discovery: Untdekke localization: body: Mastodon wurdt troch frijwilligers oerset. diff --git a/config/locales/ga.yml b/config/locales/ga.yml index adfdacb034b..36aa6a88c1f 100644 --- a/config/locales/ga.yml +++ b/config/locales/ga.yml @@ -890,6 +890,10 @@ ga: all: Do chách disabled: Do dhuine ar bith users: Chun úsáideoirí áitiúla logáilte isteach + feed_access: + modes: + authenticated: Úsáideoirí fíordheimhnithe amháin + public: Gach duine registrations: moderation_recommandation: Cinntigh le do thoil go bhfuil foireann mhodhnóireachta imoibríoch leordhóthanach agat sula n-osclaíonn tú clárúcháin do gach duine! preamble: Rialú cé atá in ann cuntas a chruthú ar do fhreastalaí. @@ -1239,10 +1243,7 @@ ga: hint_html: Más mian leat bogadh ó chuntas eile go dtí an ceann seo, anseo is féidir leat ailias a chruthú, a theastaíonn sular féidir leat leanúint ar aghaidh le leantóirí a bhogadh ón seanchuntas go dtí an ceann seo. Tá an gníomh seo ann féin neamhdhíobhálach agus inchúlaithe. Cuirtear tús leis an aistriú cuntais ón seanchuntas. remove: Dícheangail ailias appearance: - advanced_web_interface: Comhéadan gréasáin chun cinn - advanced_web_interface_hint: 'Más mian leat úsáid a bhaint as do leithead scáileáin ar fad, ceadaíonn an comhéadan gréasáin ardleibhéil duit go leor colúin éagsúla a chumrú chun an oiread faisnéise a fheiceáil ag an am céanna agus is mian leat: Baile, fógraí, amlíne chónaidhme, aon líon liostaí agus hashtags.' animations_and_accessibility: Beochan agus inrochtaineacht - confirmation_dialogs: Dialóga deimhnithe discovery: Fionnachtain localization: body: Oibrithe deonacha a dhéanann aistriúchán Mastodon. @@ -1704,6 +1705,13 @@ ga: expires_at: In éag uses: Úsáidí title: Tabhair cuireadh do dhaoine + link_preview: + author_html: Le %{name} + potentially_sensitive_content: + action: Cliceáil chun a thaispeáint + confirm_visit: An bhfuil tú cinnte gur mian leat an nasc seo a oscailt? + hide_button: Folaigh + label: Ábhar a d'fhéadfadh a bheith íogair lists: errors: limit: Tá uaslíon na liostaí sroichte agat @@ -2023,6 +2031,9 @@ ga: two: "%{count} físeáin" boosted_from_html: Molta ó %{acct_link} content_warning: 'Rabhadh ábhair: %{warning}' + content_warnings: + hide: Folaigh an post + show: Taispeáin níos mó default_language: Mar an gcéanna le teanga an chomhéadain disallowed_hashtags: few: 'bhí na Haischlib dícheadaithe: %{tags}' diff --git a/config/locales/gd.yml b/config/locales/gd.yml index 0720cf964a2..802b9254153 100644 --- a/config/locales/gd.yml +++ b/config/locales/gd.yml @@ -1220,10 +1220,7 @@ gd: hint_html: Nam bu mhiann leat imrich o chunntas eile dhan fhear seo, ’s urrainn dhut alias a chruthachadh an-seo agus feumaidh tu sin a dhèanamh mus urrainn dhut tòiseachadh air an luchd-leantainn agad imrich on seann-chunntas dhan fhear seo. Tha an gnìomh seo fhèin neo-chronail is chan eil e buan. Tòisichidh tu air imrich a’ chunntais on t-seann-chunntas. remove: Dì-cheangail an t-alias appearance: - advanced_web_interface: Eadar-aghaidh-lìn adhartach - advanced_web_interface_hint: 'Ma tha thu airson leud na sgrìn agad gu lèir a chleachdadh, leigidh an eadar-aghaidh-lìn adhartach leat mòran cholbhan eadar-dhealaichte a cho-rèiteachadh airson uiread de dh''fhiosrachadh ''s a thogras tu fhaicinn aig an aon àm: Dachaigh, brathan, loidhne-ama cho-naisgte, liostaichean is tagaichean hais a rèir do thoil.' animations_and_accessibility: Beòthachaidhean agus so-ruigsinneachd - confirmation_dialogs: Còmhraidhean dearbhaidh discovery: Rùrachadh localization: body: Tha Mastodon ’ga eadar-theangachadh le saor-thoilich. diff --git a/config/locales/gl.yml b/config/locales/gl.yml index 4eee0fe0f98..9f8a23832b0 100644 --- a/config/locales/gl.yml +++ b/config/locales/gl.yml @@ -848,6 +848,10 @@ gl: all: Para todos disabled: Para ninguén users: Para usuarias locais conectadas + feed_access: + modes: + authenticated: Só para usuarias con sesión iniciada + public: Para calquera registrations: moderation_recommandation: Por favor, pon interese en crear un equipo de moderación competente e reactivo antes de permitir que calquera poida crear unha conta! preamble: Xestiona quen pode crear unha conta no teu servidor. @@ -1182,10 +1186,7 @@ gl: hint_html: Se queres mudarte desde outra conta a esta nova, aquí podes crear un alcume, que é requerido antes de poder proceder a mover os seguidores da conta antiga a esta nova. Esta acción por si mesma é inocua e reversible. A migración da conta iníciase desde a conta antiga. remove: Desligar alcume appearance: - advanced_web_interface: Interface web avanzada - advanced_web_interface_hint: Se queres empregar todo o ancho da pantalla, a interface web avanzada permíteche configurar diferentes columnas para ver tanta información como queiras. Inicio, notificacións, cronoloxía federada, varias listaxes e cancelos. animations_and_accessibility: Animacións e accesibilidade - confirmation_dialogs: Diálogos de confirmación discovery: Descubrir localization: body: Mastodon tradúceno persoas voluntarias. diff --git a/config/locales/he.yml b/config/locales/he.yml index 9c8d91722ab..85b4ace518b 100644 --- a/config/locales/he.yml +++ b/config/locales/he.yml @@ -876,6 +876,10 @@ he: all: לכולם disabled: לאף אחד users: למשתמשים מקומיים מחוברים + feed_access: + modes: + authenticated: משתמשים מאומתים בלבד + public: כולם registrations: moderation_recommandation: יש לוודא שלאתר יש צוות מנחות ומנחי שיחה מספק ושירותי בטרם תבחרו לפתוח הרשמה לכולם! preamble: שליטה בהרשאות יצירת חשבון בשרת שלך. @@ -1220,10 +1224,7 @@ he: hint_html: אם ברצונך לעבור מחשבון אחר לחשבון הזה, כאן ניתן ליצור שם נרדף, הנדרש לפני שאפשר יהיה להמשיך עם העברת עוקבים מהחשבון הישן לזה. הפעולה עצמה הפיכה ובלתי מזיקה. הגירת החשבון מופעלת מהחשבון הישן. remove: הסרת שם נרדף appearance: - advanced_web_interface: ממשק ווב מתקדם - advanced_web_interface_hint: 'אם ברצונך לעשות שימוש במלוא רוחב המסך, ממשק הווב המתקדם מאפשר לך להגדיר עמודות רבות ושונות כדי לראות בו זמנית כמה מידע שתרצה/י: פיד הבית, התראות, פרהסיה ומספר כלשהו של רשימות ותגיות.' animations_and_accessibility: הנפשות ונגישות - confirmation_dialogs: חלונות אישור discovery: תגליות localization: body: מסטודון מתורגם על ידי מתנדבים. @@ -1665,6 +1666,13 @@ he: expires_at: פג תוקף ב- uses: שימושים title: הזמנת אנשים + link_preview: + author_html: מאת %{name} + potentially_sensitive_content: + action: לחץ להצגה + confirm_visit: האם להמשיך ליעד הקישור? + hide_button: להסתיר + label: תוכן שעלול להיות רגיש lists: errors: limit: הגעת למספר הרשימות המירבי @@ -1981,6 +1989,9 @@ he: two: "%{count} סרטונים" boosted_from_html: הודהד מ-%{acct_link} content_warning: 'אזהרת תוכן: %{warning}' + content_warnings: + hide: להסתיר הודעה + show: הצג עוד default_language: זהה לשפת ממשק disallowed_hashtags: many: 'מכיל את התגיות האסורות: %{tags}' diff --git a/config/locales/hr.yml b/config/locales/hr.yml index 7d04d7278c8..4439460df6c 100644 --- a/config/locales/hr.yml +++ b/config/locales/hr.yml @@ -79,7 +79,6 @@ hr: aliases: add_new: Stvori alias appearance: - advanced_web_interface: Napredno web sučelje localization: body: Mastodon prevode dobrovoljci. guide_link_text: Svi mogu doprinjeti. diff --git a/config/locales/hu.yml b/config/locales/hu.yml index 123e8a97c9f..86e2ed919b6 100644 --- a/config/locales/hu.yml +++ b/config/locales/hu.yml @@ -848,6 +848,10 @@ hu: all: Mindenkinek disabled: Senkinek users: Bejelentkezett helyi felhasználóknak + feed_access: + modes: + authenticated: Csak hitelesített felhasználók + public: Mindenki registrations: moderation_recommandation: Győződj meg arról, hogy megfelelő és gyors reagálású moderátor csapatod van, mielőtt mindenki számára megnyitod a regisztrációt! preamble: Szabályozd, hogy ki hozhat létre fiókot a kiszolgálón. @@ -1182,10 +1186,7 @@ hu: hint_html: Ha másik fiókról kívánsz átlépni erre a fiókra, itt létrehozhatsz egy aliast, amelyre szükség van, mielőtt folytathatod a követők áthelyezését a régi fiókból erre. Ez az áthelyezés önmagában ártalmatlan és visszafordítható folyamat. A fiók áttelepítése a régi fiókból indul el. remove: Alias szétkapcsolása appearance: - advanced_web_interface: Speciális webes felület - advanced_web_interface_hint: 'Ha szeretnéd, a képernyő teljes szélességét kihasználhatod. A speciális webes felülettel különböző oszlopokat állíthatsz be, hogy egyszerre annyi információt láthass, amennyit csak akarsz: Kezdőoldal, értesítések, föderációs idővonal, bármennyi lista vagy hashtag.' animations_and_accessibility: Animáció és akadálymentesítés - confirmation_dialogs: Megerősítő párbeszédablakok discovery: Felfedezés localization: body: A Mastodont önkéntesek fordítják. @@ -1587,6 +1588,13 @@ hu: expires_at: Lejárat uses: Használat title: Meghívások + link_preview: + author_html: 'Szerző: %{name}' + potentially_sensitive_content: + action: Kattints a megjelenítéshez + confirm_visit: Biztos, hogy megnyitod ezt a hivatkozást? + hide_button: Elrejtés + label: Lehet, hogy kényes tartalom lists: errors: limit: Elérted a listák maximális számát @@ -1897,6 +1905,9 @@ hu: other: "%{count} videó" boosted_from_html: Megtolva innen %{acct_link} content_warning: 'Tartalmi figyelmeztetés: %{warning}' + content_warnings: + hide: Bejegyzés elrejtése + show: Több megjelenítése default_language: Felhasználói felület nyelvével azonos disallowed_hashtags: one: 'tiltott hashtaget tartalmaz: %{tags}' diff --git a/config/locales/hy.yml b/config/locales/hy.yml index 933f8a4fa75..75220ecb13b 100644 --- a/config/locales/hy.yml +++ b/config/locales/hy.yml @@ -433,10 +433,7 @@ hy: new_trending_statuses: title: Թրենդային գրառումներ appearance: - advanced_web_interface: Սյունակավոր ինտերֆեյս - advanced_web_interface_hint: Եթէ ցանկանում ես օգտագործել էկրանիդ ամբողջ լայնքը, ապա ընդլայնուած վեբ ինտերֆեյսով հնարաւոր է էկրանը բաժանել սիւնակների՝ զուգահեռ տեսնելու տարբեր տիպի ինֆորմացիա՝ տեղական հոսքը, ծանուցումները, ֆեդերացված հոսքը, և ցանկացած թվի ցուցակ ու հեշթեգ։ animations_and_accessibility: Անիմացիաներ եւ հասանելիութիւն - confirmation_dialogs: Հաստատման պատուհաններ discovery: Բացայայտում localization: body: Մաստոդոնը թարգմանուում է կամաւորների կողմից։ diff --git a/config/locales/ia.yml b/config/locales/ia.yml index 019e3f8438d..5a4c0ba4237 100644 --- a/config/locales/ia.yml +++ b/config/locales/ia.yml @@ -1182,10 +1182,7 @@ ia: hint_html: Si tu vole migrar de un altere conto a iste, tu pote crear un alias ci, que es necessari pro poter transferer le sequitores del conto ancian a iste. Iste action per se es innocue e reversibile. Le migration del conto es initiate desde le conto ancian. remove: Disligar alias appearance: - advanced_web_interface: Interfacie web avantiate - advanced_web_interface_hint: 'Si tu vole utilisar tote le largessa de tu schermo, le interfacie web avantiate te permitte configurar multe columnas differente pro vider al mesme tempore tante informationes como tu vole: pagina principal, notificationes, chronologia federate, un numero illimitate de listas e hashtags.' animations_and_accessibility: Animationes e accessibilitate - confirmation_dialogs: Dialogos de confirmation discovery: Discoperta localization: body: Mastodon es traducite per voluntarios. diff --git a/config/locales/id.yml b/config/locales/id.yml index 3489519f847..81fc5903107 100644 --- a/config/locales/id.yml +++ b/config/locales/id.yml @@ -862,10 +862,7 @@ id: hint_html: Jika Anda ingin pindah dari akun lain ke sini, Anda dapat membuat alias, yang dilakukan sebelum Anda setuju dengan memindah pengikut dari akun lama ke akun sini. Aksi ini tidak berbahaya dan tidak bisa dikembalikan. Pemindahan akun dimulai dari akun lama. remove: Hapus tautan alias appearance: - advanced_web_interface: Antarmuka web tingkat lanjut - advanced_web_interface_hint: 'Jika Anda ingin memanfaatkan seluruh lebar layar Anda, antarmuka web tingkat lanjut memungkinkan Anda mengonfigurasi beragam kolom untuk menampilkan informasi sebanyak yang Anda inginkan: Beranda, notifikasi, linimasa gabungan, daftar, dan tagar.' animations_and_accessibility: Animasi dan aksesibilitas - confirmation_dialogs: Dialog konfirmasi discovery: Jelajah localization: body: Mastodon diterjemahkan oleh sukarelawan. diff --git a/config/locales/ie.yml b/config/locales/ie.yml index d202e96d491..ce219a9d682 100644 --- a/config/locales/ie.yml +++ b/config/locales/ie.yml @@ -982,10 +982,7 @@ ie: hint_html: Si tu vole mover de un altri conto a ti-ci, ci tu posse crear un alias, quel es besonat ante que tu posse proceder a mover sequitores del antiqui conto a ti-ci. Ti-ci action, sol, es ínnociv e reversibil. Li conto-migration es initiat del antiqui conto. remove: Desconexer alias appearance: - advanced_web_interface: Avansat web-interfacie - advanced_web_interface_hint: 'Si tu vole usar li tot largore de tui ecran, li avansat web-interfacie permisse que tu mey configurar mult columnes diferent por vider tam mult information simultanmen quam tu vole: Hem, federat témpor-linea, quelcunc númere de listes e hashtags.' animations_and_accessibility: Animationes e accessibilitá - confirmation_dialogs: Dialogs de confirmation discovery: Decovriment localization: body: Mastodon es traductet de voluntarios. diff --git a/config/locales/io.yml b/config/locales/io.yml index 36d4ce251fd..eaca822f1af 100644 --- a/config/locales/io.yml +++ b/config/locales/io.yml @@ -1097,10 +1097,7 @@ io: hint_html: Se vu volas transferesar de altra konto a co, hike vu povas krear alternativnomo, quo bezonesas ante vu povas durigar transferar sequanti de la olda konto a co. Ca ago esas nedanjeroza e inversigebla. Kontomigro komencesas de la olda konto. remove: Deligez alternative nomo appearance: - advanced_web_interface: Altnivela retintervizajo - advanced_web_interface_hint: 'Se vu volas uzar tota skrenlongeso, altnivela retintervizajo povigas vu modifikar multa dessama kolumni por vida multa informi en sama tempo quale vu volas: Hemo, savigi, fratara tempolineo, multa listi e gretvorti.' animations_and_accessibility: Animi e adirebleso - confirmation_dialogs: Konfirmdialogi discovery: Deskovro localization: body: Mastodon tradukesas da voluntarii. diff --git a/config/locales/is.yml b/config/locales/is.yml index 5f783331c06..acf5fa58735 100644 --- a/config/locales/is.yml +++ b/config/locales/is.yml @@ -850,6 +850,10 @@ is: all: Til allra disabled: Til engra users: Til innskráðra staðværra notenda + feed_access: + modes: + authenticated: Einungis auðkenndir notendur + public: Allir registrations: moderation_recommandation: Tryggðu að þú hafir hæft og aðgengilegt umsjónarteymi til taks áður en þú opnar á skráningar fyrir alla! preamble: Stýrðu því hverjir geta útbúið notandaaðgang á netþjóninum þínum. @@ -1184,10 +1188,7 @@ is: hint_html: Ef þú vilt flytjast af öðrum notandaaðgangi yfir á þennan, þá geturðu búið hér til samnefni, sem er nauðsynlegt áður en þú getur haldið áfram við að flytja fylgjendur af gamla notandaaðgangnum yfir á þennan aðgang. Þessi aðgerð er í sjálfu sér skaðlaus og afturkræf. Yfirfærsla notandaaðgangsins er síðan ræst á gamla notandaaðgangnum. remove: Aftengja samnefni appearance: - advanced_web_interface: Ítarlegt vefviðmót - advanced_web_interface_hint: 'Ef þú vilt geta notað alla skjábreiddina gefur ítarlegt vefviðmót þér færi á að stilla marga mismunandi dálka svo hægt sé að sjá eins miklar upplýsingar í einu eins og þér hentar: Heim, tilkynningar, sameiginleg tímalína, ótiltekinn fjöldi lista og myllumerkja.' animations_and_accessibility: Hreyfingar og algilt aðgengi - confirmation_dialogs: Staðfestingargluggar discovery: Uppgötvun localization: body: Mastodon er þýtt af sjálfboðaliðum. @@ -1591,6 +1592,13 @@ is: expires_at: Rennur út uses: Afnot title: Bjóða fólki + link_preview: + author_html: Frá %{name} + potentially_sensitive_content: + action: Smelltu til að birta + confirm_visit: Ertu viss um að þú viljir opna þennan tengil? + hide_button: Fela + label: Mögulega viðkvæmt efni lists: errors: limit: Þú hefur náð hámarksfjölda lista @@ -1901,6 +1909,9 @@ is: other: "%{count} myndskeið" boosted_from_html: Endurbirt frá %{acct_link} content_warning: 'Aðvörun vegna efnis (CW): %{warning}' + content_warnings: + hide: Fela færslu + show: Sýna meira default_language: Sama og tungumál viðmóts disallowed_hashtags: one: 'innihélt óleyfilegt myllumerki: %{tags}' diff --git a/config/locales/it.yml b/config/locales/it.yml index 264119d7e37..0735e4ed550 100644 --- a/config/locales/it.yml +++ b/config/locales/it.yml @@ -1182,12 +1182,7 @@ it: hint_html: Se vuoi trasferirti da un altro account a questo, qui puoi creare un alias, che è necessario prima di poter spostare i seguaci dal vecchio account a questo. Questa azione è innocua e reversibile. La migrazione dell'account è avviata dal vecchio account. remove: Scollega alias appearance: - advanced_web_interface: Interfaccia web avanzata - advanced_web_interface_hint: |- - Se vuoi utilizzare l'intera larghezza dello schermo, l'interfaccia web avanzata ti consente di configurare varie colonne per mostrare più informazioni allo stesso tempo, secondo le tue preferenze: - Home, notifiche, timeline federata, qualsiasi numero di liste e etichette. animations_and_accessibility: Animazioni e accessibilità - confirmation_dialogs: Dialoghi di conferma discovery: Scoperta localization: body: Mastodon è tradotto da volontari. diff --git a/config/locales/ja.yml b/config/locales/ja.yml index 184ab506d64..8feb830f0fd 100644 --- a/config/locales/ja.yml +++ b/config/locales/ja.yml @@ -1151,10 +1151,7 @@ ja: hint_html: 他のアカウントからこのアカウントにフォロワーを引き継いで引っ越したい場合、ここでエイリアスを作成しておく必要があります。エイリアス自体は無害で、取り消すことができます。引っ越しは以前のアカウント側から開始する必要があります。 remove: エイリアスを削除 appearance: - advanced_web_interface: 上級者向けUI - advanced_web_interface_hint: ディスプレイを幅いっぱいまで活用したい場合、上級者向け UI をおすすめします。ホーム、通知、連合タイムライン、更にはリストやハッシュタグなど、様々な異なるカラムから望む限りの情報を一度に受け取れるような設定が可能になります。 animations_and_accessibility: アニメーションとアクセシビリティー - confirmation_dialogs: 確認ダイアログ discovery: 見つける localization: body: Mastodonは有志によって翻訳されています。 diff --git a/config/locales/kab.yml b/config/locales/kab.yml index 61fb800301d..a8fd955ee48 100644 --- a/config/locales/kab.yml +++ b/config/locales/kab.yml @@ -538,7 +538,6 @@ kab: new_trending_tags: title: Ihacṭagen inezzaɣ appearance: - advanced_web_interface: Agrudem n web leqqayen discovery: Asnirem localization: body: Mastodon suqqlen-t-id yiwiziwen. diff --git a/config/locales/kk.yml b/config/locales/kk.yml index b877cb09c79..628dcbc3f82 100644 --- a/config/locales/kk.yml +++ b/config/locales/kk.yml @@ -308,10 +308,7 @@ kk: deleted_msg: Алиасты сәтті алып тастаңыз. Осы есептік жазбадан екіншіге ауысу мүмкін болмайды. remove: Алиас сілтемесін алып тастау appearance: - advanced_web_interface: Кеңейтілген веб-интерфейс - advanced_web_interface_hint: 'Егер сіз бүкіл экранның енін пайдаланғыңыз келсе, кеңейтілген веб-интерфейс сізге көптеген ақпаратты бір уақытта қалағанша көру үшін әр түрлі бағандарды конфигурациялауға мүмкіндік береді: негізгі бет, ескертпелер, жаһандық желі, тізім мен хэштегтерді.' animations_and_accessibility: Анимациялар және қолжетімділік - confirmation_dialogs: Пікірталас диалогтары discovery: Пікірталас sensitive_content: Нәзік контент application_mailer: diff --git a/config/locales/ko.yml b/config/locales/ko.yml index 5c158223c13..2503706bd0d 100644 --- a/config/locales/ko.yml +++ b/config/locales/ko.yml @@ -1165,10 +1165,7 @@ ko: hint_html: 다른 계정에서 이 계정으로 옮기길 원하는 경우, 여기에서 별칭을 만들 수 있습니다, 기존 계정의 팔로워를 이쪽으로 옮기고 싶은 경우 필요한 과정입니다. 이 행동 자체는 해롭지 않고 되돌리기가 가능합니다.계정 이주는 이전 계정에서 착수하게 됩니다 remove: 별칭 연결 끊기 appearance: - advanced_web_interface: 고급 웹 인터페이스 - advanced_web_interface_hint: '화면의 가로폭을 가득 채우고 싶다면, 고급 웹 인터페이스는 한 번에 여러 정보를 볼 수 있도록 여러 컬럼을 설정할 수 있도록 합니다: 홈, 알림, 연합타임라인, 리스트, 해시태그 등' animations_and_accessibility: 애니메이션과 접근성 - confirmation_dialogs: 확인 대화상자 discovery: 발견하기 localization: body: 마스토돈은 자원봉사자들에 의해 번역되었습니다. diff --git a/config/locales/ku.yml b/config/locales/ku.yml index b05f49cd471..31a0a1cf18b 100644 --- a/config/locales/ku.yml +++ b/config/locales/ku.yml @@ -875,10 +875,7 @@ ku: hint_html: Ku tu dixwazî ji ajimêreke din bar bike bo yekî din, li vir tu dikarî bernavekê biafirîne, ku pêdivî ye berî ku tu bi şopandina şopînerên xwe ji ajimêra kevn ber bi vê yekê biçe. Ev çalakî bi serê xwe bê ziyan û vegere.Koçberiya ajimêr ji ajimêreke kevin dest pê dike. remove: Girêdana nûçikê rake appearance: - advanced_web_interface: Navrûya tevnê yê pêşketî - advanced_web_interface_hint: 'Ku tu bixwazî tevahiya ferehiya dîmendera xwe bi kar bînî, navrûya pêşketî ya tevnê dihêle ku tu gelek stûnên cihêreng saz bikî da ku di heman demê de bi qasî ku tu dixwazî zanyariyan bibînî: Serrûpel, agahdarî, demnameya giştî, her hejmarek ji rêzik û hashtagan.' animations_and_accessibility: Anîmasyon û gihînî - confirmation_dialogs: Gotûbêjên piştrastkirî discovery: Vedîtin localization: body: Mastodon ji aliyê xêrxwazan tê wergerandin. diff --git a/config/locales/lad.yml b/config/locales/lad.yml index 06bc932ea4d..676de75e018 100644 --- a/config/locales/lad.yml +++ b/config/locales/lad.yml @@ -1085,10 +1085,7 @@ lad: hint_html: Si keres migrar de otro kuento a este, aki puedes kriyar un alias, kale proseder antes de ampesar a mover suivantes del kuento anterior a este. Esta aksion por si mezma es inofensiva i reversivle. La migrasyon del kuento se inisya dizde el kuento viejo. remove: Dezata alias appearance: - advanced_web_interface: Enterfaz web avanzada - advanced_web_interface_hint: 'Si keres utilizar todo el ancho de ekran, la enterfaz web avanzada te permete konfigurar varias kolumnas desferentes para ver tanta enformasyon al mezmo tiempo komo keras: Linya prinsipala, avizos, linya de tiempo federada, kualkier numero de listas i etiketas.' animations_and_accessibility: Animasyones i aksesivilita - confirmation_dialogs: Dialogos de konfirmasyon discovery: Diskuvrimiento localization: body: Mastodon es trezladado por volontarios. diff --git a/config/locales/lt.yml b/config/locales/lt.yml index eb69f2b06d5..d9eaf61e370 100644 --- a/config/locales/lt.yml +++ b/config/locales/lt.yml @@ -805,10 +805,7 @@ lt: title: Tendencingos saitažodžiai subject: Naujos tendencijos peržiūrimos %{instance} appearance: - advanced_web_interface: Išplėstinė žiniatinklio sąsaja - advanced_web_interface_hint: 'Jei nori išnaudoti visą ekrano plotį, išplėstinė žiniatinklio sąsaja leidžia sukonfigūruoti daug skirtingų stulpelių, kad vienu metu matytum tiek informacijos, kiek tik nori: Pagrindinis, pranešimai, federacinė laiko skalė, bet kokie sąrašai ir saitažodžiai.' animations_and_accessibility: Animacijos ir pritaikymas neįgaliesiems - confirmation_dialogs: Patvirtinimo dialogai discovery: Atradimas localization: body: Mastodon verčia savanoriai. diff --git a/config/locales/lv.yml b/config/locales/lv.yml index b57d2b3ef02..1a97adc6d0e 100644 --- a/config/locales/lv.yml +++ b/config/locales/lv.yml @@ -365,7 +365,7 @@ lv: dashboard: active_users: aktīvie lietotāji interactions: mijiedarbības - media_storage: Multividesu krātuve + media_storage: Multivides uzglabāšana new_users: jauni lietotāji opened_reports: atvērtie ziņojumi pending_appeals_html: @@ -1163,10 +1163,7 @@ lv: hint_html: Ja vēlies pāriet no cita konta uz šo, šeit vari izveidot aizstājvārdu, kas ir nepieciešams, lai varētu turpināt sekotāju pārvietošanu no vecā konta uz šo. Šī darbība pati par sevi ir nekaitīga un atgriezeniska. Konta migrācija tiek sākta no vecā konta. remove: Atsaistīt aizstājvārdu appearance: - advanced_web_interface: Paplašinātā tīmekļa saskarne - advanced_web_interface_hint: 'Ja vēlies izmantot visu ekrāna platumu, uzlabotā tīmekļa saskarne ļauj konfigurēt daudzas dažādas kolonnas, lai vienlaikus redzētu tik daudz informācijas, cik vēlies: Sākums, paziņojumi, apvienotā ziņu lenta, neierobežots skaits sarakstu un tēmturu.' animations_and_accessibility: Animācijas un pieejamība - confirmation_dialogs: Apstiprināšanas dialogi discovery: Atklāšana localization: body: Mastodon ir tulkojuši brīvprātīgie. @@ -1728,7 +1725,7 @@ lv: duration_too_short: ir par agru expired: Aptauja jau ir beigusies invalid_choice: Izvēlētā balsošanas iespēja nepastāv - over_character_limit: katrs nedrīkst būt garāks par %{max} rakstzīmēm + over_character_limit: nedrīkst būt garākas par %{max} rakstzīmēm self_vote: Tu nevari balsot pats savā aptaujā too_few_options: jābūt vairāk nekā vienam vienumam too_many_options: nevar saturēt vairāk par %{max} vienumiem @@ -1904,6 +1901,10 @@ lv: limit: Jau ir piesprausts lielākais iespējamais ierakstu skaits ownership: Kāda cita ierakstu nevar piespraust reblog: Pastiprinātu ierakstu nevar piespraust + quote_policies: + followers: Tikai sekotāji + nobody: Tikai es + public: Jebkurš title: "%{name}: “%{quote}”" visibilities: public: Publisks diff --git a/config/locales/ms.yml b/config/locales/ms.yml index 2df1e0c2b8f..dc3c9c36a9b 100644 --- a/config/locales/ms.yml +++ b/config/locales/ms.yml @@ -957,10 +957,7 @@ ms: hint_html: Jika anda ingin beralih dari akaun lain ke akaun ini, di sini anda boleh membuat alias, yang diperlukan sebelum anda boleh meneruskan dengan memindahkan pengikut dari akaun lama ke akaun ini. Tindakan ini dengan sendirinya tidak berbahaya dan boleh diterbalikkan. Penghijrahan akaun dimulakan daripada akaun lama. remove: Nyahpaut alias appearance: - advanced_web_interface: Antara muka web lanjutan - advanced_web_interface_hint: 'Jika anda ingin menggunakan keseluruhan lebar skrin anda, antara muka web lanjutan membolehkan anda mengkonfigurasi banyak lajur berbeza untuk melihat seberapa banyak maklumat pada masa yang sama seperti yang anda mahu: Laman Utama, pemberitahuan, garis masa bersekutu, sebarang bilangan senarai dan hashteg.' animations_and_accessibility: Animasi dan kebolehaksesan - confirmation_dialogs: Dialog pengesahan discovery: Penemuan localization: body: Mastodon diterjemahkan oleh sukarelawan. diff --git a/config/locales/my.yml b/config/locales/my.yml index 644e648ac54..bdf051ca6ee 100644 --- a/config/locales/my.yml +++ b/config/locales/my.yml @@ -938,10 +938,7 @@ my: hint_html: အခြားအကောင့်မှ ဤအကောင့်သို့ ပြောင်းရွှေ့လိုပါက ဤနေရာတွင် အကောင့်ဟောင်းမှ စောင့်ကြည့်သူများကို ဤအကောင့်သို့ မရွှေ့မီ လိုအပ်သော အမည်တစ်ခု ဖန်တီးနိုင်ပါသည်။ ဤလုပ်ဆောင်ချက်မှာ အန္တရာယ်ကင်းပြီး ပြန်ပြောင်းလုပ်ဆောင်နိုင်ပါသည်အကောင့်ပြောင်းရွှေ့ခြင်းကို အကောင့်ဟောင်းမှ စတင်လုပ်ဆောင်ပါသည်။ remove: နာမည်တူများကို လင့်ခ်ဖြုတ်ပါ appearance: - advanced_web_interface: အဆင့်မြင့်ဝဘ်ပုံစံ - advanced_web_interface_hint: အဆင့်မြင့်ဝဘ်အင်တာဖေ့စ်သည် မျက်နှာပြင်အကျယ်တစ်ခုလုံးကို သင် အသုံးပြုလိုပါက သင်အလိုရှိသည့်အတိုင်း အချက်အလက်များကို တစ်ပြိုင်နက်ကြည့်ရှုရန် ကော်လံများစွာဖြင့် ပြသနိုင်သည် - ပင်မစာမျက်နှာ၊ အကြောင်းကြားချက်များ၊ ဖက်ဒီစာမျက်နှာ၊ စာရင်းအရေအတွက်နှင့် hashtags မှန်သမျှကို ချိန်ညှိဖော်ပြနိုင်သည်။ animations_and_accessibility: လှုပ်ရှားမှုဆိုင်ရာများ - confirmation_dialogs: အတည်ပြုချက် ဒိုင်ယာလော့ခ်များ discovery: ရှာဖွေတွေ့ရှိမှု localization: body: Mastodon ကို စေတနာ့ဝန်ထမ်းများမှ ဘာသာပြန်ထားပါသည်။ diff --git a/config/locales/nan.yml b/config/locales/nan.yml index 20e53b4a865..74d4fd813fe 100644 --- a/config/locales/nan.yml +++ b/config/locales/nan.yml @@ -834,6 +834,10 @@ nan: all: Kàu ta̍k ê lâng disabled: 無kàu tó tsi̍t ê users: Kàu ta̍k位登入ê用者 + feed_access: + modes: + authenticated: Kan-ta hōo登入ê用者 + public: Ta̍k lâng registrations: moderation_recommandation: 佇開放hōo ta̍k ê lâng註冊進前,請確認lí有夠額koh主動反應ê管理團隊! preamble: 控制ē當佇lí ê服侍器註冊ê人。 @@ -991,8 +995,47 @@ nan: no_terms_of_service_html: Lí目前iáu無設定任何服務規定。服務規定是beh提供明確性,兼保護lí佇kap用者ê爭議中毋免承受可能ê責任。 notified_on_html: 佇 %{date} 通知ê用者 notify_users: 通知用者 + preview: + explanation_html: Tsit封email ē送hōo tī %{date} 進前註冊 ê %{display_count} ê用者。Email ē包括下跤ê文字: + send_preview: Kā tāi先看ê內容寄kàu %{email} + send_to_all: + other: 寄出 %{display_count} 張電子phue + title: 先kā服務規定ê通知看māi + publish: 公開 + published_on_html: 公開tī %{date} + save_draft: 儲存草稿 + title: 服務規定 + title: 管理 trends: + allow: 允准 + approved: 允准ah + confirm_allow: Lí kám確定beh允准所揀ê標簽? + confirm_disallow: Lí kám確定無愛允准所揀ê標簽? + disallow: 無愛允准 + links: + allow: 允准連結 + allow_provider: 允准提供者 + confirm_allow: Lí kám確定beh允准所揀ê連結? + confirm_allow_provider: Lí kám確定beh允准所揀ê提供者? + confirm_disallow: Lí kám確定無愛允准所揀ê連結? + confirm_disallow_provider: Lí kám確定無愛允准所揀ê提供者? + description_html: Tsia是連結,現tsú時lí ê服侍器hōo通見ê用者大量分享ê。tse通幫tsān lí ê用者tshuē著tsit-má世間有siánn tāi誌。直kàu lí允准公開者,連結bē公開展示。lí通允准á是拒絕單ê連結。 + disallow: 無愛允准連結 + disallow_provider: 無愛允准提供者 + no_link_selected: 因為無揀任何連結,所以lóng無改變 + publishers: + no_publisher_selected: 因為無揀任何提供者,所以lóng無改變 + shared_by_over_week: + other: 頂禮拜hōo %{count} 位用者分享 + title: 趨勢ê連結 + usage_comparison: Tī kin-á日hōo %{today} ê lâng分享,比較tsa-hng有 %{yesterday} ê + not_allowed_to_trend: 無允准刊tī趨勢 + only_allowed: Kan-ta允准 + pending_review: Teh等審核 preview_card_providers: + allowed: Tsit ê提供者ê連結通刊tī趨勢 + description_html: Tsiah ê域名來自定定受lí ê服侍器分享ê連結。連結bē變做公開趨勢,除非連結ê域名受允准。Lí ê允准(á是拒絕)擴展kàu kiánn域名。 + rejected: Tsit ê提供者ê連結bē刊tī趨勢 title: 發布者 rejected: 拒絕ê statuses: @@ -1002,9 +1045,55 @@ nan: confirm_allow_account: Lí kám確定beh允准所揀ê口座? confirm_disallow: Lí kám確定無愛允准所揀ê狀態? confirm_disallow_account: Lí kám確定無愛允准所揀ê口座? + description_html: Tsiah ê是lí ê服侍器所知ê,tsit-má teh受tsē-tsē分享kap收藏ê PO文。PO文bē公開顯示,除非lí允准作者,而且作者允准in ê口座hőng推薦hōo別lâng。Lí通允准á是拒絕個別PO文。 + disallow: 無允准PO文 + disallow_account: 無允准作者 + no_status_selected: 因為無揀任何趨勢PO文,所以lóng無改變 + not_discoverable: 作者iáu bē揀通hōo lâng發現 + shared_by: + other: Hōo lâng分享á是收藏 %{friendly_count} kái + title: 趨勢ê PO文 tags: + current_score: 目前ê分數:%{score} dashboard: + tag_accounts_measure: 無重複用 tag_languages_dimension: Tsia̍p用ê語言 + tag_servers_dimension: 人氣服侍器 + tag_servers_measure: 無kâng ê服侍器 + tag_uses_measure: Lóng總使用 + description_html: Tsiah ê是hashtag,tsit-má佇lí ê服侍器看見ê tsē-tsē PO文中出現。Tse通tsān lí ê用者tshuē著ta̍k家上tsē討論ê內容。除非lí核准,hashtag bē公開顯示。 + listable: 通受建議 + no_tag_selected: 因為無揀任何標簽,所以lóng無改變 + not_listable: Bē當受建議 + not_trendable: Bē刊tī趨勢 + not_usable: Bē當用 + peaked_on_and_decaying: 佇 %{date} 日上烘,tsit-má teh退火 + title: 趨勢ê hashtag + trendable: 通刊tī趨勢 + trending_rank: '趨勢 #%{rank}' + usable: Ē當用 + usage_comparison: Tī kin-á日hōo %{today} ê lâng用,比較tsa-hng有 %{yesterday} ê + used_by_over_week: + other: 頂禮拜hōo %{count} 位用者用 + title: 推薦kap趨勢 + trending: 趨勢 + username_blocks: + add_new: 加新ê + block_registrations: 封鎖註冊 + comparison: + contains: 包含 + equals: 等於 + contains_html: 包含 %{string} + created_msg: 成功加添用者名規則 + delete: Thâi掉 + edit: + title: 編輯使用者號名規則 + matches_exactly_html: 等於 %{string} + new: + create: 建立規則 + title: 創造使用者號名規則 + no_username_block_selected: 因為無揀任何使用者號名規則,所以lóng無改變 + not_permitted: 無允准 scheduled_statuses: too_soon: Tio̍h用未來ê日期。 statuses: diff --git a/config/locales/nl.yml b/config/locales/nl.yml index 0c557cd4421..e2d162115d6 100644 --- a/config/locales/nl.yml +++ b/config/locales/nl.yml @@ -848,6 +848,10 @@ nl: all: Aan iedereen disabled: Aan niemand users: Aan ingelogde lokale gebruikers + feed_access: + modes: + authenticated: Alleen ingelogde gebruikers + public: Iedereen registrations: moderation_recommandation: Zorg ervoor dat je een adequaat en responsief moderatieteam hebt voordat je registraties voor iedereen openstelt! preamble: Toezicht houden op wie een account op deze server kan registreren. @@ -907,7 +911,7 @@ nl: status_title: Bericht van @%{name} title: Accountberichten - @%{name} trending: Trending - view_publicly: In het openbaar bekijken + view_publicly: Openbaar bericht bekijken visibility: Zichtbaarheid with_media: Met media strikes: @@ -980,7 +984,7 @@ nl: name: Naam newest: Nieuwste oldest: Oudste - open: In het openbaar bekijken + open: Oorspronkelijk bericht bekijken reset: Opnieuw review: Status beoordelen search: Zoeken @@ -1182,10 +1186,7 @@ nl: hint_html: Wanneer je vanaf een ander account naar dit account wilt verhuizen, kun je hier een alias aanmaken. Dit is nodig voordat je verder kunt gaan met het verhuizen van volgers van het oude naar dit nieuwe account. Deze actie is op zich ongevaarlijk en omkeerbaar. De accountmigratie wordt gestart vanaf het oude account. remove: Alias ontkoppelen appearance: - advanced_web_interface: Geavanceerde webomgeving - advanced_web_interface_hint: 'Wanneer je van de hele schermbreedte gebruik wilt maken, stelt de geavanceerde webomgeving je in staat om meerdere verschillende kolommen te configureren. Hiermee kun je zoveel mogelijk informatie op hetzelfde moment bekijken, zoals: Start, meldingen, de globale tijdlijn, meerdere lijsten en hashtags.' animations_and_accessibility: Animaties en toegankelijkheid - confirmation_dialogs: Bevestigingen discovery: Ontdekken localization: body: Mastodon wordt door vrijwilligers vertaald. @@ -1587,6 +1588,13 @@ nl: expires_at: Verloopt op uses: Aantal keer te gebruiken title: Mensen uitnodigen + link_preview: + author_html: Door %{name} + potentially_sensitive_content: + action: Klik om te tonen + confirm_visit: Ben je zeker dat je deze link wilt openen? + hide_button: Verberg + label: Mogelijk gevoelige inhoud lists: errors: limit: Je hebt het maximum aantal lijsten bereikt @@ -1897,6 +1905,9 @@ nl: other: "%{count} video's" boosted_from_html: Geboost van %{acct_link} content_warning: 'Inhoudswaarschuwing: %{warning}' + content_warnings: + hide: Bericht verbergen + show: Meer tonen default_language: Hetzelfde als de taal van de gebruikersomgeving disallowed_hashtags: one: 'bevatte een niet toegestane hashtag: %{tags}' diff --git a/config/locales/nn.yml b/config/locales/nn.yml index bd59f5a1a67..6efd85d033e 100644 --- a/config/locales/nn.yml +++ b/config/locales/nn.yml @@ -1182,10 +1182,7 @@ nn: hint_html: Viss du vil flytta frå ein annan konto til denne, kan du laga eit alias her. Det treng du før du kan halda fram med å flytta fylgjarar frå den gamle kontoen til dnene. Denne handlinga er i seg sjølv harmlaus og kan angrast. Du har starta overføringa frå den gamle kontoen. remove: Fjern aliaslenking appearance: - advanced_web_interface: Avansert nettgrensesnitt - advanced_web_interface_hint: 'Om du vil bruke heile skjermbreidda di, let det avanserte nettgrensesnittet deg setje opp mange ulike kolonnar for å sjå så mykje informasjon du vil på ein gong: Heim, varsel, samla tidslinje, og kva som helst antall lister og emneknaggar.' animations_and_accessibility: Animasjonar og tilgjengelegheit - confirmation_dialogs: Bekreftelsesdialoger discovery: Oppdaging localization: body: Mastodon er omsett av friviljuge. diff --git a/config/locales/no.yml b/config/locales/no.yml index a10f4c6a6aa..72cbad788e3 100644 --- a/config/locales/no.yml +++ b/config/locales/no.yml @@ -997,10 +997,7 @@ hint_html: Dersom du vil flytte fra en annen konto til den, kan du lage et alias her, som er påkrevd før du kan gå videre med å flytte følgere fra den gamle kontoen til den nye. Handlingen i seg selv er harmløs og reversibel. Kontoflyttingen har blitt satt i gang fra den gamle kontoen. remove: Fjern aliaslenking appearance: - advanced_web_interface: Avansert nettgrensesnitt - advanced_web_interface_hint: 'Hvis du ønsker å bruke hele skjermbredden din, lar det avanserte nettgrensesnittet deg sette opp mange forskjellige kolonner for å se så mye informasjon på én gang som du vil: Hjem, varslinger, fellestidslinjen, og ethvert antall lister og emneknagger.' animations_and_accessibility: Animasjoner og tilgjengelighet - confirmation_dialogs: Bekreftelsesdialoger discovery: Oppdagelse localization: body: Mastodon er oversatt av frivillige. diff --git a/config/locales/oc.yml b/config/locales/oc.yml index 51f8d8c7b4d..1e34dcc6ea4 100644 --- a/config/locales/oc.yml +++ b/config/locales/oc.yml @@ -442,10 +442,7 @@ oc: add_new: Crear un alias remove: Desligar l’alias appearance: - advanced_web_interface: Interfàcia web avançada - advanced_web_interface_hint: 'Se volètz utilizar la nautor complèta de l’ecran, l’interfàcia web avançada vos permet de configurar diferentas colomnas per mostrar tan d’informacions que volètz : Acuèlh, notificacions, flux d’actualitat, e d’autras listas e etiquetas.' animations_and_accessibility: Animacion e accessibilitat - confirmation_dialogs: Fenèstras de confirmacion discovery: Descobèrta localization: body: Mastodon es traduch per de benevòls. diff --git a/config/locales/pl.yml b/config/locales/pl.yml index 20b391c8675..418d908f8c2 100644 --- a/config/locales/pl.yml +++ b/config/locales/pl.yml @@ -1199,10 +1199,7 @@ pl: hint_html: Jeżeli chcesz przenieść się z innego konta na to, możesz utworzyć alias, który jest wymagany zanim zaczniesz przenoszenie obserwacji z poprzedniego konta na to. To działanie nie wyrządzi szkód i jest odwracalne. Migracja konta jest inicjowana ze starego konta. remove: Odłącz alias appearance: - advanced_web_interface: Zaawansowany interfejs użytkownika - advanced_web_interface_hint: Jeśli chcesz użyć pełną szerokość swojego ekranu, zaawansowany interfejs użytkownika pozwala Ci skonfigurować wiele różnych kolumn, by zobaczyć jak najwięcej informacji kiedy tylko chcesz. Strona główna, Powiadomienia, Globalna oś czasu, dowolna ilość list i hasztagów. animations_and_accessibility: Animacje i dostępność - confirmation_dialogs: Dialogi potwierdzenia discovery: Odkrywanie localization: body: Mastodon jest tłumaczony przez wolontariuszy. diff --git a/config/locales/pt-BR.yml b/config/locales/pt-BR.yml index 4686305e647..5af82759510 100644 --- a/config/locales/pt-BR.yml +++ b/config/locales/pt-BR.yml @@ -1182,10 +1182,7 @@ pt-BR: hint_html: Se você quiser migrar de uma outra conta para esta, você pode criar um atalho aqui, o que é necessário antes que você possa migrar os seguidores da conta antiga para esta. Esta ação por si só é inofensiva e reversível. A migração da conta é iniciada pela conta antiga. remove: Desvincular alias appearance: - advanced_web_interface: Interface avançada de colunas - advanced_web_interface_hint: 'Se você deseja usar toda a sua largura de tela, a interface avançada permite que você configure muitas colunas diferentes para ver tantas informações ao mesmo tempo quanto você deseja: Página inicial, notificações, linha local, linha global, qualquer número de listas e hashtags.' animations_and_accessibility: Animações e acessibilidade - confirmation_dialogs: Diálogos de confirmação discovery: Descobrir localization: body: Mastodon é traduzido por voluntários. diff --git a/config/locales/pt-PT.yml b/config/locales/pt-PT.yml index 3ee79756485..208a91eb531 100644 --- a/config/locales/pt-PT.yml +++ b/config/locales/pt-PT.yml @@ -1182,10 +1182,7 @@ pt-PT: hint_html: Se quiseres mudar de outra conta para esta, podes criar aqui um pseudónimo, que é necessário antes de poderes prosseguir com a migração de seguidores da conta antiga para esta. Esta ação por si só é inofensiva e reversível. A migração da conta é iniciada a partir da conta antiga. remove: Desvincular pseudónimo appearance: - advanced_web_interface: Interface web avançada - advanced_web_interface_hint: 'Se quiseres utilizar toda a largura do teu ecrã, a interface web avançada permite configurar várias colunas diferentes para veres tanta informação ao mesmo tempo quanto quiseres: página inicial, notificações, cronologia federada, qualquer número de listas e etiquetas.' animations_and_accessibility: Animações e acessibilidade - confirmation_dialogs: Caixas de confirmação discovery: Descobrir localization: body: O Mastodon é traduzido por voluntários. diff --git a/config/locales/ru.yml b/config/locales/ru.yml index cdccbb65e11..12c73955791 100644 --- a/config/locales/ru.yml +++ b/config/locales/ru.yml @@ -1202,10 +1202,7 @@ ru: hint_html: Если вы собираетесь переехать с другой учётной записи на эту, то, прежде чем вы сможете перенести подписчиков со старой учётной записи, вы должны связать учётные записи здесь. Это действие само по себе безвредно и обратимо. Начать переезд можно только со старой учётной записи. remove: Отвязать учётную запись appearance: - advanced_web_interface: Многоколоночный интерфейс - advanced_web_interface_hint: 'Многоколоночный интерфейс даёт возможность использовать всю ширину экрана, позволяя вам обозревать столько информации, сколько вы захотите. Вы можете добавить множество различных столбцов: главную ленту, уведомления, глобальную ленту, неограниченное количество списков и хештегов.' animations_and_accessibility: Анимации и доступность - confirmation_dialogs: Диалоговые окна подтверждений discovery: Актуальное localization: body: Mastodon переводится добровольцами. diff --git a/config/locales/sc.yml b/config/locales/sc.yml index 606b47cc40d..5757e49077d 100644 --- a/config/locales/sc.yml +++ b/config/locales/sc.yml @@ -655,10 +655,7 @@ sc: hint_html: Si boles mudare dae un'àteru contu a custu, inoghe as a pòdere creare unu nomìngiu, chi est rechestu in antis de sighire cun sa tràmuda de is persones chi ti sighint dae su contu betzu a custu. Custa atzione est innòcua e reversìbile. Tràmuda de su contu betzu cumintzada. remove: Disconnete su nomìngiu appearance: - advanced_web_interface: Interfache web avantzada - advanced_web_interface_hint: 'Si boles impreare totu sa largària de s''ischermu, s''interfache web avantzada ti permitit de cunfigurare diversas colunnas pro bìdere meda prus informatzione in contemporànea: printzipale, notìficas, lìnia de tempus federada e cale si siat nùmeru de listas e etichetas.' animations_and_accessibility: Animatziones e atzessibilidade - confirmation_dialogs: Diàlogos de cunfirmatzione discovery: Iscoberta localization: body: Mastodon est bortadu in manera voluntària. diff --git a/config/locales/sco.yml b/config/locales/sco.yml index 5c1e451446b..f90c7e692c2 100644 --- a/config/locales/sco.yml +++ b/config/locales/sco.yml @@ -868,10 +868,7 @@ sco: hint_html: If ye'r wantin fir tae flit fae anither accoont tae this ane, ye kin mak a alias here, this is requirt afore ye kin gae forret flittin follaers fae the auld accoont tae this ane. This action bi an o itsel is hermless an reversible. The accoont migration is initiatie fae the auld accoont. remove: Unlink alias appearance: - advanced_web_interface: Advanced wab interface - advanced_web_interface_hint: 'Gin ye''r wantin fir tae mak uise o the ful width o yer screen, the advanced wab interface lets ye configure a wheen o different columns sae''s ye kin see as muckle information at the same time as ye want: Hame, notes, federatit timeline, onie nummer o lists an hashtags.' animations_and_accessibility: Animations an accessibility - confirmation_dialogs: Confirmation dialogs discovery: Discovery localization: body: Mastodon is translatit bi volunteers. diff --git a/config/locales/si.yml b/config/locales/si.yml index e6b561b2ba1..dee5e3bb959 100644 --- a/config/locales/si.yml +++ b/config/locales/si.yml @@ -754,10 +754,7 @@ si: hint_html: ඔබට වෙනත් ගිණුමකින් මෙය වෙත මාරු වීමට අවශ්‍ය නම්, මෙහිදී ඔබට අන්වර්ථ නාමයක් සෑදිය හැක, එය පැරණි ගිණුමෙන් අනුගාමිකයින් මෙම ගිණුමට ගෙන යාමට පෙර අවශ්‍ය වේ. මෙම ක්‍රියාවම හානිකර නොවන සහ ආපසු හැරවිය හැකිවේ. ගිණුම් සංක්‍රමණය පැරණි ගිණුමෙන් ආරම්භ වේ. remove: අන්වර්ථය විසන්ධි කරන්න appearance: - advanced_web_interface: සංකීර්ණ අතුරු මුහුණත - advanced_web_interface_hint: 'ඔබට ඔබේ සම්පූර්ණ තිරයේ පළල භාවිතා කිරීමට අවශ්‍ය නම්, උසස් වෙබ් අතුරු මුහුණත ඔබට අවශ්‍ය පරිදි එකම වේලාවක බොහෝ තොරතුරු බැලීමට විවිධ තීරු වින්‍යාස කිරීමට ඉඩ දෙයි: නිවස, දැනුම්දීම්, ෆෙඩරේටඩ් කාලරාමුව, ඕනෑම ලැයිස්තු සහ හැෂ් ටැග්.' animations_and_accessibility: සජීවිකරණ සහ ප්‍රවේශ්‍යතාව - confirmation_dialogs: තහවුරු කිරීමේ සංවාද discovery: සොයාගැනීම localization: body: මාස්ටඩන් ස්වේච්ඡාවෙන් පරිවර්තනය කර ඇත. diff --git a/config/locales/simple_form.an.yml b/config/locales/simple_form.an.yml index ad17b19ba05..d21689f6ed1 100644 --- a/config/locales/simple_form.an.yml +++ b/config/locales/simple_form.an.yml @@ -81,7 +81,6 @@ an: site_title: Cómo puede referir-se la chent a lo tuyo servidor amás de per lo nombre de dominio. theme: Lo tema que los visitantes no rechistraus y los nuevos usuarios veyen. thumbnail: Una imachen d'aproximadament 2:1 s'amuestra chunto a la información d'o tuyo servidor. - timeline_preview: Los visitantes no rechistraus podrán navegar per los mensaches publicos mas recients disponibles en o servidor. trendable_by_default: Omitir la revisión manual d'o conteniu en tendencia. Los elementos individuals encara podrán eliminar-se d'as tendencias. trends: Las tendencias amuestran qué mensaches, etiquetas y noticias son ganando tracción en o tuyo servidor. form_challenge: @@ -233,7 +232,6 @@ an: site_title: Nombre d'o servidor theme: Tema per defecto thumbnail: Miniatura d'o servidor - timeline_preview: Permitir l'acceso no autenticau a las linias de tiempo publicas trendable_by_default: Permitir tendencias sin revisión previa trends: Habilitar tendencias interactions: diff --git a/config/locales/simple_form.ar.yml b/config/locales/simple_form.ar.yml index 4e2c1cf67ee..767cd030bbd 100644 --- a/config/locales/simple_form.ar.yml +++ b/config/locales/simple_form.ar.yml @@ -102,7 +102,6 @@ ar: status_page_url: العنوان التشعبي حيث يمكن للناس رؤية صفحة حالة هذا الخادم عند حدوث عطب ما theme: الشكل الذي يشاهده الزوار الجدد و الغير مسجلين الدخول. thumbnail: عرض حوالي 2:1 صورة إلى جانب معلومات الخادم الخاص بك. - timeline_preview: الزوار الذين سجلوا خروجهم سيكونون قادرين على تصفح أحدث المشاركات العامة المتاحة على الخادم. trendable_by_default: تخطي مراجعة المحتوى التريند اليدوي. لا يزال من الممكن الإزالة اللاحقة للعناصر الفردية من التريندات. trends: تُظهِر المتداولة أي من المنشورات والوسوم وقصص الأخبار التي تجذب الانتباه على خادمك. trends_as_landing_page: إظهار المحتوى المتداوَل للمستخدمين والزوار غير المسجلين بدلاً من وصف هذا الخادم. يتطلب هذا تفعيل المتداولة. @@ -292,7 +291,6 @@ ar: status_page_url: الرابط التشعبي لصفحة حالة الخادم theme: الحُلَّة الإفتراضية thumbnail: الصورة المصغرة للخادم - timeline_preview: السماح بالوصول غير الموثق إلى الخيوط الزمنية العامة trendable_by_default: السماح للوسوم بالظهور على المتداوَلة دون مراجعة مسبقة trends: تمكين المتداوَلة trends_as_landing_page: استخدام المُتداوَلة كصفحة ترحيب diff --git a/config/locales/simple_form.ast.yml b/config/locales/simple_form.ast.yml index c042d3ced43..977f89027a8 100644 --- a/config/locales/simple_form.ast.yml +++ b/config/locales/simple_form.ast.yml @@ -142,7 +142,6 @@ ast: site_title: Nome del sirvidor theme: Estilu predetermináu thumbnail: Miniatura del sirvidor - timeline_preview: Permitir l'accesu ensin autenticar a les llinies de tiempu públiques trendable_by_default: Permitir tendencies ensin revisión previa trends: Activar les tendencies interactions: diff --git a/config/locales/simple_form.az.yml b/config/locales/simple_form.az.yml index fd290627cab..cb15c716222 100644 --- a/config/locales/simple_form.az.yml +++ b/config/locales/simple_form.az.yml @@ -66,7 +66,6 @@ az: setting_use_pending_items: Yavaş rejim form_admin_settings: show_domain_blocks: Əngəllənən domenləri göstər - timeline_preview: Ümumi zaman xətlərinə səlahiyyətsiz erişimə icazə ver ip_block: severities: no_access: Erişimi əngəllə diff --git a/config/locales/simple_form.be.yml b/config/locales/simple_form.be.yml index 811dd80dae1..eaa6d52708b 100644 --- a/config/locales/simple_form.be.yml +++ b/config/locales/simple_form.be.yml @@ -91,7 +91,7 @@ be: custom_css: Вы можаце прымяняць карыстальніцкія стылі ў вэб-версіі Mastodon. favicon: WEBP, PNG, GIF ці JPG. Замяняе прадвызначаны favicon Mastodon на ўласны значок. mascot: Замяняе ілюстрацыю ў пашыраным вэб-інтэрфейсе. - media_cache_retention_period: Медыяфайлы з допісаў, зробленых выдаленымі карыстальнікамі, кэшыруюцца на вашым серверы. Пры станоўчым значэнні медыяфайлы будуць выдалены праз пазначаную колькасць дзён. Калі медыяданыя будуць запытаны пасля выдалення, яны будуць спампаваны зноў, калі зыходнае змесціва усё яшчэ даступнае. У сувязі з абмежаваннямі на частату абнаўлення картак перадпрагляду іншых сайтаў, рэкамендуецца ўсталяваць значэнне не менш за 14 дзён, інакш гэтыя карткі не будуць абнаўляцца па запыце раней за гэты тэрмін. + media_cache_retention_period: Медыяфайлы з допісаў, зробленых карыстальнікамі з іншых сервераў, кэшыруюцца на вашым серверы. Пры станоўчым значэнні медыяфайлы будуць выдалены праз пазначаную колькасць дзён. Калі медыяданыя будуць запытаныя пасля выдалення, яны будуць спампаваныя зноў, калі зыходнае змесціва усё яшчэ даступнае. У сувязі з абмежаваннямі на частату абнаўлення картак перадпрагляду іншых сайтаў, рэкамендуецца ўсталяваць значэнне не менш за 14 дзён, інакш гэтыя карткі не будуць абнаўляцца па запыце раней за гэты тэрмін. min_age: Карыстальнікі будуць атрымліваць запыт на пацвярджэнне даты нараджэння падчас рэгістрацыі peers_api_enabled: Спіс даменных імён, з якімі сутыкнуўся гэты сервер у федэральным сусвеце. Даныя пра тое, ці знаходзіцеся вы з дадзеным серверам у федэрацыі, не ўключаны. Уключаны толькі даныя пра тое, што ваш сервер ведае пра іншыя серверы. Гэта выкарыстоўваецца сэрвісамі, якія збіраюць статыстыку па федэрацыі ў агульным сэнсе. profile_directory: Дырэкторыя профіляў змяшчае спіс усіх карыстальнікаў, якія вырашылі быць бачнымі. @@ -105,7 +105,6 @@ be: status_page_url: URL старонкі, дзе людзі могуць бачыць стан гэтага сервера падчас збою theme: Тэма, што бачаць новыя карыстальнікі ды наведвальнікі, якія выйшлі. thumbnail: Выява памерамі прыкладна 2:1, якая паказваецца побач з інфармацыяй пра ваш сервер. - timeline_preview: Наведвальнікі, якія выйшлі, змогуць праглядаць апошнія публічныя допісы на серверы. trendable_by_default: Прапусціць ручны агляд трэндавага змесціва. Асобныя элементы ўсё яшчэ можна будзе выдаліць з трэндаў пастфактум. trends: Трэнды паказваюць, якія допісы, хэштэгі і навіны набываюць папулярнасць на вашым серверы. trends_as_landing_page: Паказваць папулярнае змесціва карыстальнікам, якія выйшлі з сістэмы, і наведвальнікам, замест апісання гэтага сервера. Патрабуецца ўключэнне трэндаў. @@ -283,15 +282,19 @@ be: backups_retention_period: Працягласць захавання архіву карыстальніка bootstrap_timeline_accounts: Заўсёды раіць гэтыя ўліковыя запісы новым карыстальнікам closed_registrations_message: Уласнае паведамленне, калі рэгістрацыя немагчымая - content_cache_retention_period: Перыяд захоўвання выдаленага змесціва + content_cache_retention_period: Перыяд захоўвання змесціва з іншых сервераў custom_css: CSS карыстальніка favicon: Значок сайта + local_live_feed_access: Доступ да жывых стужак з лакальнымі допісамі + local_topic_feed_access: Доступ да хэштэгавых і спасылачных стужак з лакальнымі допісамі mascot: Уласны маскот(спадчына) media_cache_retention_period: Працягласць захавання кэшу для медыя min_age: Патрабаванне мінімальнага ўзросту peers_api_enabled: Апублікаваць спіс знойдзеных сервераў у API profile_directory: Уключыць каталог профіляў registrations_mode: Хто можа зарэгістравацца + remote_live_feed_access: Доступ да жывых стужак з допісамі з іншых сервераў + remote_topic_feed_access: Доступ да хэштэгавых і спасылачных стужак з допісамі з іншых сервераў require_invite_text: Каб далучыцца, патрэбна прычына show_domain_blocks: Паказаць заблакіраваныя дамены show_domain_blocks_rationale: Паказваць прычыну блакавання даменаў @@ -304,7 +307,6 @@ be: status_page_url: URL старонкі статусу theme: Тэма па змаўчанні thumbnail: Мініяцюра сервера - timeline_preview: Дазволіць неаўтэнтыфікаваны доступ да публічных стужак trendable_by_default: Дазваляць трэнды без папярэдняй праверкі trends: Уключыць трэнды trends_as_landing_page: Выкарыстоўваць трэнды ў якасці лэндзінга diff --git a/config/locales/simple_form.bg.yml b/config/locales/simple_form.bg.yml index d1673b9e1fc..38e3c2a538f 100644 --- a/config/locales/simple_form.bg.yml +++ b/config/locales/simple_form.bg.yml @@ -103,7 +103,6 @@ bg: status_page_url: Адресът на страницата, където хората могат да видят състоянието на този сървър по време на прекъсване theme: Темата, която излизащи от системата посетители и нови потребители виждат. thumbnail: Образ в съотношение около 2:1, показвано до информацията за сървъра ви. - timeline_preview: Излизащите от системата посетители ще може да разглеждат най-новите публични публикации, налични на сървъра. trendable_by_default: Прескачане на ръчния преглед на изгряващо съдържание. Отделни елементи още могат да се премахват от изгряващи постфактум. trends: В раздел „Налагащо се“ се показват публикации, хаштагове и новини, набрали популярност на сървъра ви. trends_as_landing_page: Показване на налагащото се съдържание за излизащите потребители и посетители вместо на описа на този сървър. Изисква налагащото се да бъде включено. @@ -298,7 +297,6 @@ bg: status_page_url: URL адрес на страница със състоянието theme: Стандартна тема thumbnail: Образче на сървъра - timeline_preview: Позволяване на неудостоверен достъп до публични инфопотоци trendable_by_default: Без преглед на налагащото се trends: Включване на налагащи се trends_as_landing_page: Употреба на налагащото се като целева страница diff --git a/config/locales/simple_form.ca.yml b/config/locales/simple_form.ca.yml index 0c12fbb476d..a8cbf6bb90b 100644 --- a/config/locales/simple_form.ca.yml +++ b/config/locales/simple_form.ca.yml @@ -56,6 +56,8 @@ ca: scopes: API permeses per a accedir a l'aplicació. Si selecciones un àmbit de nivell superior, no cal que en seleccionis un d'individual. setting_aggregate_reblogs: No mostra els nous impulsos dels tuts que ja s'han impulsat recentment (només afecta als impulsos nous rebuts) setting_always_send_emails: Normalment, no s'enviarà cap notificació per correu electrònic mentre facis servir Mastodon + setting_default_quote_policy_private: Altres no poden citar publicacions fetes a Mastodon només per a seguidors. + setting_default_quote_policy_unlisted: Quan la gent et citi la seva publicació estarà amagada de les línies de temps de tendències. setting_default_sensitive: El contingut sensible està ocult per defecte i es pot mostrar fent-hi clic setting_display_media_default: Amaga el contingut gràfic marcat com a sensible setting_display_media_hide_all: Oculta sempre tot el contingut multimèdia @@ -103,7 +105,6 @@ ca: status_page_url: Enllaç de la pàgina on els usuaris poden veure l'estat d'aquest servidor durant una interrupció del servei theme: El tema que els visitants i els nous usuaris veuen. thumbnail: Una imatge d'aproximadament 2:1 que es mostra al costat la informació del teu servidor. - timeline_preview: Els visitants amb sessió no iniciada seran capaços de navegar per els tuts més recents en el teu servidor. trendable_by_default: Omet la revisió manual del contingut en tendència. Els articles individuals poden encara ser eliminats després del fet. trends: Les tendències mostren quins tuts, etiquetes i notícies estan guanyant força en el teu servidor. trends_as_landing_page: Mostra el contingut en tendència als usuaris i visitants no autenticats enlloc de la descripció d'aquest servidor. Requereix que les tendències estiguin activades. @@ -295,7 +296,6 @@ ca: status_page_url: Enllaç de la pàgina d'estat theme: Tema per defecte thumbnail: Miniatura del servidor - timeline_preview: Permet l'accés no autenticat a les línies de temps públiques trendable_by_default: Permet tendències sense revisió prèvia trends: Activa les tendències trends_as_landing_page: Fer servir les tendències com a pàgina inicial @@ -370,6 +370,8 @@ ca: name: Nom permissions_as_keys: Permisos position: Prioritat + username_block: + comparison: Mètode de comparació webhook: events: Esdeveniments activats template: Plantilla de càrrega diff --git a/config/locales/simple_form.cs.yml b/config/locales/simple_form.cs.yml index f2ef4f672cc..93d6b202d8e 100644 --- a/config/locales/simple_form.cs.yml +++ b/config/locales/simple_form.cs.yml @@ -105,7 +105,6 @@ cs: status_page_url: URL stránky, kde mohou lidé vidět stav tohoto serveru během výpadku theme: Vzhled stránky, který vidí noví a odhlášení uživatelé. thumbnail: Přibližně 2:1 obrázek zobrazený vedle informací o vašem serveru. - timeline_preview: Odhlášení uživatelé budou moci procházet nejnovější veřejné příspěvky na serveru. trendable_by_default: Přeskočit manuální kontrolu populárního obsahu. Jednotlivé položky mohou být odstraněny z trendů později. trends: Trendy zobrazují, které příspěvky, hashtagy a zprávy získávají na serveru pozornost. trends_as_landing_page: Zobrazit populární obsah odhlášeným uživatelům a návštěvníkům místo popisu tohoto serveru. Vyžaduje povolení trendů. @@ -286,12 +285,16 @@ cs: content_cache_retention_period: Doba uchovávání vzdáleného obsahu custom_css: Vlastní CSS favicon: Favicon + local_live_feed_access: Přístup k live kanálům s lokálními příspěvky + local_topic_feed_access: Přístup ke kanálům s hashtagy a odkazy s lokálními příspěvky mascot: Vlastní maskot (zastaralé) media_cache_retention_period: Doba uchovávání mezipaměti médií min_age: Minimální věková hranice peers_api_enabled: Zveřejnit seznam nalezených serverů v API profile_directory: Povolit adresář profilů registrations_mode: Kdo se může přihlásit + remote_live_feed_access: Přístup k live kanálům s vzdálenými příspěvky + remote_topic_feed_access: Přístup ke kanálům s hashtagy a odkazy se vzdálenými příspěvky require_invite_text: Požadovat důvod pro připojení show_domain_blocks: Zobrazit blokace domén show_domain_blocks_rationale: Zobrazit proč byly blokovány domény @@ -304,7 +307,6 @@ cs: status_page_url: URL stránky se stavem theme: Výchozí motiv thumbnail: Miniatura serveru - timeline_preview: Povolit neověřený přístup k veřejným časovým osám trendable_by_default: Povolit trendy bez předchozí revize trends: Povolit trendy trends_as_landing_page: Použít trendy jako vstupní stránku diff --git a/config/locales/simple_form.cy.yml b/config/locales/simple_form.cy.yml index 0faa978c4d0..1c37bcbedbe 100644 --- a/config/locales/simple_form.cy.yml +++ b/config/locales/simple_form.cy.yml @@ -105,7 +105,6 @@ cy: status_page_url: URL tudalen lle gall pobl weld statws y gweinydd hwn yn ystod cyfnod o doriad gwasanaeth theme: Thema sy'n allgofnodi ymwelwyr a defnyddwyr newydd yn gweld. thumbnail: Delwedd tua 2:1 yn cael ei dangos ochr yn ochr â manylion eich gweinydd. - timeline_preview: Bydd ymwelwyr sydd wedi allgofnodi yn gallu pori drwy'r postiadau cyhoeddus diweddaraf sydd ar gael ar y gweinydd. trendable_by_default: Hepgor adolygiad llaw o gynnwys sy'n tueddu. Gall eitemau unigol gael eu tynnu o dueddiadau o hyd ar ôl y ffaith. trends: Mae pynciau llosg yn dangos y postiadau, hashnodau, a newyddion sy'n denu sylw ar eich gweinydd. trends_as_landing_page: Dangos cynnwys tueddiadol i ddefnyddwyr ac ymwelwyr sydd wedi allgofnodi yn lle disgrifiad o'r gweinydd hwn. Mae angen galluogi tueddiadau. @@ -283,17 +282,21 @@ cy: activity_api_enabled: Cyhoeddi ystadegau cyfanredol am weithgarwch defnyddwyr yn yr API app_icon: Eicon ap backups_retention_period: Cyfnod cadw archif defnyddwyr - bootstrap_timeline_accounts: Argymhellwch y cyfrifon hyn i ddefnyddwyr newydd bob amser + bootstrap_timeline_accounts: Argymhellwch y cyfrifon hyn i ddefnyddwyr newydd bob tro closed_registrations_message: Neges bersonol pan nad yw cofrestriadau ar gael content_cache_retention_period: Cyfnod cadw cynnwys o bell custom_css: CSS cyfaddas favicon: Favicon + local_live_feed_access: Mynediad i ffrydiau byw sy'n cynnwys postiadau lleol + local_topic_feed_access: Mynediad i ffrydiau hashnod a dolenni sy'n cynnwys postiadau lleol mascot: Mascot cyfaddas (hen) media_cache_retention_period: Cyfnod cadw storfa cyfryngau min_age: Gofyniad oed ieuengaf peers_api_enabled: Cyhoeddi rhestr o weinyddion a ddarganfuwyd yn yr API profile_directory: Galluogi cyfeiriadur proffil registrations_mode: Pwy all gofrestru + remote_live_feed_access: Mynediad i ffrydiau byw sy'n cynnwys postiadau pell + remote_topic_feed_access: Mynediad i ffrydiau hashnod a dolenni sy'n cynnwys postiadau o bell require_invite_text: Gofyn am reswm i ymuno show_domain_blocks: Dangos blociau parth show_domain_blocks_rationale: Dangos pam y cafodd parthau eu rhwystro @@ -306,7 +309,6 @@ cy: status_page_url: URL tudalen statws theme: Thema ragosodedig thumbnail: Bawdlun y gweinydd - timeline_preview: Caniatáu mynediad heb ei ddilysu i linellau amser cyhoeddus trendable_by_default: Caniatáu pynciau llosg heb adolygiad trends: Galluogi pynciau llosg trends_as_landing_page: Defnyddio tueddiadau fel y dudalen gartref diff --git a/config/locales/simple_form.da.yml b/config/locales/simple_form.da.yml index 05fa2acc9c0..7b15510e03c 100644 --- a/config/locales/simple_form.da.yml +++ b/config/locales/simple_form.da.yml @@ -105,7 +105,6 @@ da: status_page_url: URL'en til en side, hvor status for denne server kan ses under en afbrydelse theme: Tema, som udloggede besøgende og nye brugere ser. thumbnail: Et ca. 2:1 billede vist sammen med serveroplysningerne. - timeline_preview: Udloggede besøgende kan gennemse serverens seneste offentlige indlæg. trendable_by_default: Spring manuel gennemgang af trendindhold over. Individuelle elementer kan stadig fjernes fra trends efter kendsgerningen. trends: Tendenser viser, hvilke indlæg, hashtags og nyheder opnår momentum på serveren. trends_as_landing_page: Vis tendensindhold til udloggede brugere og besøgende i stedet for en beskrivelse af denne server. Kræver, at tendenser er aktiveret. @@ -284,12 +283,16 @@ da: content_cache_retention_period: Opbevaringsperiode for eksternt indhold custom_css: Tilpasset CSS favicon: Favikon + local_live_feed_access: Adgang til live feeds med lokale indlæg + local_topic_feed_access: Adgang til hashtag- og link-feeds med lokale indlæg mascot: Tilpasset maskot (ældre funktion) media_cache_retention_period: Media-cache opbevaringsperiode min_age: Minimums alderskrav peers_api_enabled: Udgiv liste over fundne server i API'en profile_directory: Aktivér profiloversigt registrations_mode: Hvem, der kan tilmelde sig + remote_live_feed_access: Adgang til live feeds med eksterne indlæg + remote_topic_feed_access: Adgang til hashtag- og link-feeds med eksterne indlæg require_invite_text: Kræv tilmeldingsbegrundelse show_domain_blocks: Vis domæneblokeringer show_domain_blocks_rationale: Vis, hvorfor domæner blev blokeret @@ -302,7 +305,6 @@ da: status_page_url: Statusside-URL theme: Standardtema thumbnail: Serverminiaturebillede - timeline_preview: Tillad ikke-godkendt adgang til offentlige tidslinjer trendable_by_default: Tillad ikke-reviderede trends trends: Aktivér trends trends_as_landing_page: Brug tendenser som destinationssiden diff --git a/config/locales/simple_form.de.yml b/config/locales/simple_form.de.yml index 0eed719cf71..fac3892a902 100644 --- a/config/locales/simple_form.de.yml +++ b/config/locales/simple_form.de.yml @@ -105,7 +105,6 @@ de: status_page_url: Link zu einer Internetseite, auf der der Serverstatus während eines Ausfalls angezeigt wird theme: Das Design, das abgemeldete Besucher und neue Benutzer sehen. thumbnail: Ein Bild ungefähr im 2:1-Format, das neben den Server-Informationen angezeigt wird. - timeline_preview: Nicht angemeldete Personen können die neuesten öffentlichen Beiträge dieses Servers aufrufen. trendable_by_default: Manuelles Überprüfen angesagter Inhalte überspringen. Einzelne Elemente können später noch aus den Trends entfernt werden. trends: Trends zeigen, welche Beiträge, Hashtags und Nachrichten auf deinem Server immer beliebter werden. trends_as_landing_page: Dies zeigt nicht angemeldeten Personen Trendinhalte anstelle einer Beschreibung des Servers an. Erfordert, dass Trends aktiviert sind. @@ -284,12 +283,16 @@ de: content_cache_retention_period: Aufbewahrungsfrist für externe Inhalte custom_css: Eigenes CSS favicon: Favicon + local_live_feed_access: Zugriff auf Live-Feeds, die lokale Beiträge beinhalten + local_topic_feed_access: Zugriff auf Hashtags und Links, die lokale Beiträge beinhalten mascot: Benutzerdefiniertes Maskottchen (Legacy) media_cache_retention_period: Aufbewahrungsfrist für Medien im Cache min_age: Erforderliches Mindestalter peers_api_enabled: Die entdeckten Server im Fediverse über die API veröffentlichen profile_directory: Profilverzeichnis aktivieren registrations_mode: Wer darf ein neues Konto registrieren? + remote_live_feed_access: Zugriff auf Live-Feeds, die Beiträge externer Server beinhalten + remote_topic_feed_access: Zugriff auf Hashtags und Links, die Beiträge externer Server beinhalten require_invite_text: Begründung für Beitritt verlangen show_domain_blocks: Anzeigen, welche Domains gesperrt wurden show_domain_blocks_rationale: Anzeigen, weshalb Domains gesperrt wurden @@ -302,7 +305,6 @@ de: status_page_url: Statusseite (URL) theme: Standard-Design thumbnail: Vorschaubild des Servers - timeline_preview: Nicht-authentisierten Zugriff auf öffentliche Timelines gestatten trendable_by_default: Trends ohne vorherige Überprüfung erlauben trends: Trends aktivieren trends_as_landing_page: Trends als Landingpage verwenden diff --git a/config/locales/simple_form.el.yml b/config/locales/simple_form.el.yml index f43399b5e69..f65ad49793b 100644 --- a/config/locales/simple_form.el.yml +++ b/config/locales/simple_form.el.yml @@ -105,7 +105,6 @@ el: status_page_url: Το URL μιας σελίδας όπου κάποιος μπορεί να δει την κατάσταση αυτού του διακομιστή κατά τη διάρκεια μιας διακοπής λειτουργίας theme: Θέμα που βλέπουν αποσυνδεδεμένοι επισκέπτες ή νέοι χρήστες. thumbnail: Μια εικόνα περίπου 2:1 που εμφανίζεται παράλληλα με τις πληροφορίες του διακομιστή σου. - timeline_preview: Αποσυνδεδεμένοι επισκέπτες θα μπορούν να περιηγηθούν στις πιο πρόσφατες δημόσιες δημοσιεύσεις που είναι διαθέσιμες στο διακομιστή. trendable_by_default: Παράλειψη χειροκίνητης αξιολόγησης του περιεχομένου σε τάση. Μεμονωμένα στοιχεία μπορούν ακόμα να αφαιρεθούν από τις τάσεις μετέπειτα. trends: Τάσεις δείχνουν ποιες δημοσιεύσεις, ετικέτες και ειδήσεις προκαλούν έλξη στο διακομιστή σας. trends_as_landing_page: Εμφάνιση περιεχομένου σε τάση σε αποσυνδεδεμένους χρήστες και επισκέπτες αντί για μια περιγραφή αυτού του διακομιστή. Απαιτεί οι τάσεις να έχουν ενεργοποιηθεί. @@ -284,12 +283,16 @@ el: content_cache_retention_period: Περίοδος διατήρησης απομακρυσμένου περιεχομένου custom_css: Προσαρμοσμένο CSS favicon: Favicon + local_live_feed_access: Πρόσβαση σε ζωντανές ροές με τοπικές αναρτήσεις + local_topic_feed_access: Πρόσβαση σε ροές ετικετών και συνδέσμων με τοπικές αναρτήσεις mascot: Προσαρμοσμένη μασκότ (απαρχαιωμένο) media_cache_retention_period: Περίοδος διατήρησης προσωρινής μνήμης πολυμέσων min_age: Ελάχιστη απαιτούμενη ηλικία peers_api_enabled: Δημοσίευση λίστας των εντοπισμένων διακομιστών στο API profile_directory: Ενεργοποίηση καταλόγου προφίλ registrations_mode: Ποιος μπορεί να εγγραφεί + remote_live_feed_access: Πρόσβαση σε ζωντανές ροές με απομακρυσμένες αναρτήσεις + remote_topic_feed_access: Πρόσβαση σε ροές ετικετών και συνδέσμων με απομακρυσμένες αναρτήσεις require_invite_text: Απαίτησε έναν λόγο για να γίνει κάποιος μέλος show_domain_blocks: Εμφάνιση αποκλεισμένων τομέων show_domain_blocks_rationale: Εμφάνιση γιατί αποκλείστηκαν οι τομείς @@ -302,7 +305,6 @@ el: status_page_url: URL σελίδας κατάστασης theme: Προεπιλεγμένο θέμα thumbnail: Μικρογραφία διακομιστή - timeline_preview: Να επιτρέπεται μη πιστοποιημένη πρόσβαση σε δημόσιες ροές trendable_by_default: Επίτρεψε τις τάσεις χωρίς προηγούμενη αξιολόγηση trends: Ενεργοποίηση τάσεων trends_as_landing_page: Χρήση των τάσεων ως σελίδα προορισμού diff --git a/config/locales/simple_form.en-GB.yml b/config/locales/simple_form.en-GB.yml index e813ecc0c34..1e534d1d216 100644 --- a/config/locales/simple_form.en-GB.yml +++ b/config/locales/simple_form.en-GB.yml @@ -103,7 +103,6 @@ en-GB: status_page_url: URL of a page where people can see the status of this server during an outage theme: Theme that logged out visitors and new users see. thumbnail: A roughly 2:1 image displayed alongside your server information. - timeline_preview: Logged out visitors will be able to browse the most recent public posts available on the server. trendable_by_default: Skip manual review of trending content. Individual items can still be removed from trends after the fact. trends: Trends show which posts, hashtags and news stories are gaining traction on your server. trends_as_landing_page: Show trending content to logged-out users and visitors instead of a description of this server. Requires trends to be enabled. @@ -292,7 +291,6 @@ en-GB: status_page_url: Status page URL theme: Default theme thumbnail: Server thumbnail - timeline_preview: Allow unauthenticated access to public timelines trendable_by_default: Allow trends without prior review trends: Enable trends trends_as_landing_page: Use trends as the landing page diff --git a/config/locales/simple_form.en.yml b/config/locales/simple_form.en.yml index 0ab94b5a753..1bad98c0b6c 100644 --- a/config/locales/simple_form.en.yml +++ b/config/locales/simple_form.en.yml @@ -54,8 +54,10 @@ en: password: Use at least 8 characters phrase: Will be matched regardless of casing in text or content warning of a post scopes: Which APIs the application will be allowed to access. If you select a top-level scope, you don't need to select individual ones. + setting_advanced_layout: Display Mastodon as a multi-column layout, allowing you to view the timeline, notifications, and a third column of your choosing. Not recommended for smaller screens. setting_aggregate_reblogs: Do not show new boosts for posts that have been recently boosted (only affects newly-received boosts) setting_always_send_emails: Normally e-mail notifications won't be sent when you are actively using Mastodon + setting_boost_modal: When enabled, boosting will first open a confirmation dialog in which you can change the visibility of your boost. setting_default_quote_policy_private: Followers-only posts authored on Mastodon can't be quoted by others. setting_default_quote_policy_unlisted: When people quote you, their post will also be hidden from trending timelines. setting_default_sensitive: Sensitive media is hidden by default and can be revealed with a click @@ -105,7 +107,6 @@ en: status_page_url: URL of a page where people can see the status of this server during an outage theme: Theme that logged out visitors and new users see. thumbnail: A roughly 2:1 image displayed alongside your server information. - timeline_preview: Logged out visitors will be able to browse the most recent public posts available on the server. trendable_by_default: Skip manual review of trending content. Individual items can still be removed from trends after the fact. trends: Trends show which posts, hashtags and news stories are gaining traction on your server. trends_as_landing_page: Show trending content to logged-out users and visitors instead of a description of this server. Requires trends to be enabled. @@ -235,12 +236,12 @@ en: setting_aggregate_reblogs: Group boosts in timelines setting_always_send_emails: Always send e-mail notifications setting_auto_play_gif: Auto-play animated GIFs - setting_boost_modal: Show confirmation dialog before boosting + setting_boost_modal: Control boosting visibility setting_default_language: Posting language setting_default_privacy: Posting visibility setting_default_quote_policy: Who can quote setting_default_sensitive: Always mark media as sensitive - setting_delete_modal: Show confirmation dialog before deleting a post + setting_delete_modal: Warn me before deleting a post setting_disable_hover_cards: Disable profile preview on hover setting_disable_swiping: Disable swiping motions setting_display_media: Media display @@ -250,7 +251,7 @@ en: setting_emoji_style: Emoji style setting_expand_spoilers: Always expand posts marked with content warnings setting_hide_network: Hide your social graph - setting_missing_alt_text_modal: Show confirmation dialog before posting media without alt text + setting_missing_alt_text_modal: Warn me before posting media without alt text setting_reduce_motion: Reduce motion in animations setting_system_font_ui: Use system's default font setting_system_scrollbars_ui: Use system's default scrollbar @@ -284,12 +285,16 @@ en: content_cache_retention_period: Remote content retention period custom_css: Custom CSS favicon: Favicon + local_live_feed_access: Access to live feeds featuring local posts + local_topic_feed_access: Access to hashtag and link feeds featuring local posts mascot: Custom mascot (legacy) media_cache_retention_period: Media cache retention period min_age: Minimum age requirement peers_api_enabled: Publish list of discovered servers in the API profile_directory: Enable profile directory registrations_mode: Who can sign-up + remote_live_feed_access: Access to live feeds featuring remote posts + remote_topic_feed_access: Access to hashtag and link feeds featuring remote posts require_invite_text: Require a reason to join show_domain_blocks: Show domain blocks show_domain_blocks_rationale: Show why domains were blocked @@ -302,7 +307,6 @@ en: status_page_url: Status page URL theme: Default theme thumbnail: Server thumbnail - timeline_preview: Allow unauthenticated access to public timelines trendable_by_default: Allow trends without prior review trends: Enable trends trends_as_landing_page: Use trends as the landing page diff --git a/config/locales/simple_form.eo.yml b/config/locales/simple_form.eo.yml index 4e2ff0bf0af..c8bf3ec0bd7 100644 --- a/config/locales/simple_form.eo.yml +++ b/config/locales/simple_form.eo.yml @@ -105,7 +105,6 @@ eo: status_page_url: URL de paĝo kie homoj povas vidi la staton de ĉi tiu servilo dum malfunkcio theme: Etoso kiun elsalutitaj vizitantoj kaj novaj uzantoj vidas. thumbnail: Ĉirkaua 2:1 bildo montritas kun via servilinformo. - timeline_preview: Elsalutitaj vizitantoj povos vidi la plej lastajn publikajn mesaĝojn disponeblaj en la servilo. trendable_by_default: Ignori permanan kontrolon de tendenca enhavo. trends: Tendencoj montras kiu mesaĝoj, kradvortoj kaj novaĵoj populariĝas en via servilo. trends_as_landing_page: Montru tendencan enhavon al elsalutitaj uzantoj kaj vizitantoj anstataŭ priskribo de ĉi tiu servilo. Necesas ke tendencoj estu ebligitaj. @@ -298,7 +297,6 @@ eo: status_page_url: URL de la paĝo de stato theme: Implicita etoso thumbnail: Bildeto de servilo - timeline_preview: Permesi la neaŭtentigitan aliron al la publikaj templinioj trendable_by_default: Permesi tendencojn sen deviga kontrolo trends: Ŝalti furorojn trends_as_landing_page: Uzu tendencojn kiel la landpaĝon diff --git a/config/locales/simple_form.es-AR.yml b/config/locales/simple_form.es-AR.yml index cf697ea64c3..d65a3ef1fd7 100644 --- a/config/locales/simple_form.es-AR.yml +++ b/config/locales/simple_form.es-AR.yml @@ -105,7 +105,6 @@ es-AR: status_page_url: Dirección web de una página donde la gente puede ver el estado de este servidor durante un apagón theme: El tema que los visitantes no registrados y los nuevos usuarios ven. thumbnail: Una imagen de aproximadamente 2:1 se muestra junto a la información de tu servidor. - timeline_preview: Los visitantes no registrados podrán navegar por los mensajes públicos más recientes disponibles en el servidor. trendable_by_default: Omití la revisión manual del contenido en tendencia. Los elementos individuales aún podrán eliminarse de las tendencias. trends: Las tendencias muestran qué mensajes, etiquetas y noticias están ganando tracción en tu servidor. trends_as_landing_page: Mostrar contenido en tendencia para usuarios que no iniciaron sesión y visitantes, en lugar de una descripción de este servidor. Requiere que las tendencias estén habilitadas. @@ -284,12 +283,16 @@ es-AR: content_cache_retention_period: Período de retención de contenido remoto custom_css: CSS personalizado favicon: Favicón + local_live_feed_access: Acceso a líneas temporales en vivo, destacando mensajes locales + local_topic_feed_access: Acceso a líneas temporales de etiquetas y enlaces, destacando mensajes locales mascot: Mascota personalizada (legado) media_cache_retention_period: Período de retención de la caché de medios min_age: Edad mínima requerida peers_api_enabled: Publicar lista de servidores descubiertos en la API profile_directory: Habilitar directorio de perfiles registrations_mode: Quién puede registrarse + remote_live_feed_access: Acceso a líneas temporales en vivo, destacando mensajes remotos + remote_topic_feed_access: Acceso a líneas temporales de etiquetas y enlaces, destacando mensajes remotos require_invite_text: Requerir un motivo para unirse show_domain_blocks: Mostrar dominios bloqueados show_domain_blocks_rationale: Mostrar por qué se bloquearon los dominios @@ -302,7 +305,6 @@ es-AR: status_page_url: Dirección web de la página de estado theme: Tema predeterminado thumbnail: Miniatura del servidor - timeline_preview: Permitir el acceso no autenticado a las líneas temporales públicas trendable_by_default: Permitir tendencias sin revisión previa trends: Habilitar tendencias trends_as_landing_page: Usar las tendencias como la página de destino diff --git a/config/locales/simple_form.es-MX.yml b/config/locales/simple_form.es-MX.yml index ceaa3fcf9fe..088423f2759 100644 --- a/config/locales/simple_form.es-MX.yml +++ b/config/locales/simple_form.es-MX.yml @@ -105,7 +105,6 @@ es-MX: status_page_url: URL de una página donde las personas pueden ver el estado de este servidor durante una interrupción theme: El tema que los visitantes no registrados y los nuevos usuarios ven. thumbnail: Una imagen de aproximadamente 2:1 se muestra junto a la información de tu servidor. - timeline_preview: Los visitantes no registrados podrán navegar por los mensajes públicos más recientes disponibles en el servidor. trendable_by_default: Omitir la revisión manual del contenido en tendencia. Los elementos individuales aún podrán eliminarse de las tendencias. trends: Las tendencias muestran qué mensajes, etiquetas y noticias están ganando tracción en tu servidor. trends_as_landing_page: Mostrar contenido en tendencia para usuarios y visitantes desconectados en lugar de una descripción de este servidor. Requiere tendencias para ser habilitado. @@ -284,12 +283,16 @@ es-MX: content_cache_retention_period: Periodo de conservación de contenidos remotos custom_css: CSS personalizado favicon: Favicon + local_live_feed_access: Acceso a las cronologías que destacan publicaciones locales + local_topic_feed_access: Acceso a las etiquetas y enlaces en tendencia que destacan publicaciones locales mascot: Mascota personalizada (legado) media_cache_retention_period: Período de retención de caché multimedia min_age: Edad mínima requerida peers_api_enabled: Publicar lista de servidores descubiertos en la API profile_directory: Habilitar directorio de perfiles registrations_mode: Quién puede registrarse + remote_live_feed_access: Acceso a las cronologías que destacan publicaciones remotas + remote_topic_feed_access: Acceso a las etiquetas y enlaces en tendencia que destacan publicaciones remotas require_invite_text: Requerir una razón para unirse show_domain_blocks: Mostrar dominios bloqueados show_domain_blocks_rationale: Mostrar por qué se bloquearon los dominios @@ -302,7 +305,6 @@ es-MX: status_page_url: URL de página de estado theme: Tema por defecto thumbnail: Miniatura del servidor - timeline_preview: Permitir el acceso no autenticado a las líneas de tiempo públicas trendable_by_default: Permitir tendencias sin revisión previa trends: Habilitar tendencias trends_as_landing_page: Usar tendencias como página de destino diff --git a/config/locales/simple_form.es.yml b/config/locales/simple_form.es.yml index ec7ba3e30c3..d6f1c5d8657 100644 --- a/config/locales/simple_form.es.yml +++ b/config/locales/simple_form.es.yml @@ -105,7 +105,6 @@ es: status_page_url: URL de una página donde se pueda ver el estado de este servidor durante una incidencia theme: El tema que los visitantes no registrados y los nuevos usuarios ven. thumbnail: Una imagen de aproximadamente 2:1 se muestra junto a la información de tu servidor. - timeline_preview: Los visitantes no registrados podrán navegar por los mensajes públicos más recientes disponibles en el servidor. trendable_by_default: Omitir la revisión manual del contenido en tendencia. Los elementos individuales aún podrán eliminarse de las tendencias. trends: Las tendencias muestran qué publicaciones, etiquetas y noticias están ganando tracción en tu servidor. trends_as_landing_page: Mostrar contenido en tendencia para usuarios y visitantes en lugar de una descripción de este servidor. Requiere que las tendencias estén habilitadas. @@ -284,12 +283,16 @@ es: content_cache_retention_period: Período de retención de contenido remoto custom_css: CSS personalizado favicon: Favicon + local_live_feed_access: Acceso a las cronologías que destacan publicaciones locales + local_topic_feed_access: Acceso a las etiquetas y enlaces en tendencia que destacan publicaciones locales mascot: Mascota personalizada (legado) media_cache_retention_period: Período de retención de caché multimedia min_age: Edad mínima requerida peers_api_enabled: Publicar lista de servidores descubiertos en la API profile_directory: Habilitar directorio de perfiles registrations_mode: Quién puede registrarse + remote_live_feed_access: Acceso a las cronologías que destacan publicaciones remotas + remote_topic_feed_access: Acceso a las etiquetas y enlaces en tendencia que destacan publicaciones remotas require_invite_text: Requerir una razón para unirse show_domain_blocks: Mostrar dominios bloqueados show_domain_blocks_rationale: Mostrar por qué se bloquearon los dominios @@ -302,7 +305,6 @@ es: status_page_url: URL de página de estado theme: Tema por defecto thumbnail: Miniatura del servidor - timeline_preview: Permitir el acceso no autenticado a las líneas de tiempo públicas trendable_by_default: Permitir tendencias sin revisión previa trends: Habilitar tendencias trends_as_landing_page: Usar tendencias como la página de inicio diff --git a/config/locales/simple_form.et.yml b/config/locales/simple_form.et.yml index 1f9bf778fad..603d00f26d0 100644 --- a/config/locales/simple_form.et.yml +++ b/config/locales/simple_form.et.yml @@ -105,7 +105,6 @@ et: status_page_url: Lehe URL, kus saab serveri maas oleku ajal näha serveri olekut theme: Teema, mida näevad sisenemata ning uued kasutajad. thumbnail: Umbes 2:1 mõõdus pilt serveri informatsiooni kõrval. - timeline_preview: Sisenemata külastajatel on võimalik sirvida viimaseid avalikke postitusi serveril. trendable_by_default: Populaarse sisu ülevaatuse vahele jätmine. Pärast seda on siiski võimalik üksikuid üksusi trendidest eemaldada. trends: Trendid näitavad, millised postitused, sildid ja uudislood koguvad sinu serveris tähelepanu. trends_as_landing_page: Näitab välja logitud kasutajatele ja külalistele serveri kirjelduse asemel populaarset sisu. Populaarne sisu (trendid) peab selleks olema sisse lülitatud. @@ -302,7 +301,6 @@ et: status_page_url: Oleku lehe URL theme: Vaikmisi teema thumbnail: Serveri pisipilt - timeline_preview: Luba autentimata ligipääs avalikele ajajoontele trendable_by_default: Luba trendid eelneva ülevaatuseta trends: Luba trendid trends_as_landing_page: Kasuta maabumislehena lehte Populaarne diff --git a/config/locales/simple_form.eu.yml b/config/locales/simple_form.eu.yml index c1879e9f87c..ff4c4ed30a7 100644 --- a/config/locales/simple_form.eu.yml +++ b/config/locales/simple_form.eu.yml @@ -103,7 +103,6 @@ eu: status_page_url: Kanporatua dagoen jendeak zerbitzari honen egoera ikus dezaten gune baten URL theme: Saioa hasi gabeko erabiltzaileek eta berriek ikusiko duten gaia. thumbnail: Zerbitzariaren informazioaren ondoan erakusten den 2:1 inguruko irudia. - timeline_preview: Saioa hasi gabeko erabiltzaileek ezingo dituzte arakatu zerbitzariko bidalketa publiko berrienak. trendable_by_default: Saltatu joeretako edukiaren eskuzko berrikuspena. Ondoren elementuak banan-bana kendu daitezke joeretatik. trends: Joeretan zure zerbitzarian bogan dauden bidalketa, traola eta albisteak erakusten dira. trends_as_landing_page: Erakutsi pil-pilean dagoen edukia saioa hasita ez duten erabiltzaileei eta bisitariei, zerbitzari honen deskribapena erakutsi ordez. Joerak aktibatuak edukitzea beharrezkoa da. @@ -279,7 +278,6 @@ eu: status_page_url: Egoera-orriaren URLa theme: Lehenetsitako gaia thumbnail: Zerbitzariaren koadro txikia - timeline_preview: Onartu autentifikatu gabeko sarbidea denbora lerro publikoetara trendable_by_default: Onartu joerak aurrez berrikusi gabe trends: Gaitu joerak trends_as_landing_page: Erabili joerak hasierako orri gisa diff --git a/config/locales/simple_form.fa.yml b/config/locales/simple_form.fa.yml index 9d75b9e5db4..dac3c88bf9d 100644 --- a/config/locales/simple_form.fa.yml +++ b/config/locales/simple_form.fa.yml @@ -103,7 +103,6 @@ fa: status_page_url: نشانی وب صفحه‌ای که در آن افراد می‌توانند وضعیت این سرور را در هنگام قطع شدن ببینند theme: زمینه‌ای که بینندگان خارج شده و کاربران جدید می‌بینند. thumbnail: یک تصویر تقریباً 2:1 در کنار اطلاعات سرور شما نمایش داده می شود. - timeline_preview: بازدیدکنندگانی که از سیستم خارج شده اند می توانند جدیدترین پست های عمومی موجود در سرور را مرور کنند. trendable_by_default: از بررسی دستی محتوای پرطرفدار صرف نظر کنید. آیتم های فردی هنوز هم می توانند پس از واقعیت از روند حذف شوند. trends: روندها نشان می‌دهند که کدام پست‌ها، هشتگ‌ها و داستان‌های خبری در سرور شما مورد توجه قرار گرفته‌اند. trends_as_landing_page: به جای توضیح این سرور، محتوای پرطرفدار را به کاربران و بازدیدکنندگان از سیستم خارج شده نشان دهید. نیاز به فعال شدن روندها دارد. @@ -299,7 +298,6 @@ fa: status_page_url: نشانی صفحهٔ وضعیت theme: زمینهٔ پیش‌گزیده thumbnail: بندانگشتی کارساز - timeline_preview: اجازهٔ دسترسی بدون تأیید هویت به خط‌زمانی‌های عمومی trendable_by_default: اجازهٔ پرطرفدار شدن بدون بازبینی پیشین trends: به کار انداختن پرطرفدارها trends_as_landing_page: استفاده از داغ‌ها به عنوان صفحهٔ فرود diff --git a/config/locales/simple_form.fi.yml b/config/locales/simple_form.fi.yml index b31c8e1ef35..d99e86feeeb 100644 --- a/config/locales/simple_form.fi.yml +++ b/config/locales/simple_form.fi.yml @@ -105,7 +105,6 @@ fi: status_page_url: URL-osoite sivulle, josta tämän palvelimen tilan voi ongelmatilanteissa tarkistaa theme: Teema, jonka uloskirjautuneet vierailijat ja uudet käyttäjät näkevät. thumbnail: Noin 2:1 kuva näkyy palvelimen tietojen ohessa. - timeline_preview: Uloskirjautuneet vierailijat voivat selata uusimpia julkisia julkaisuja, jotka ovat saatavilla palvelimella. trendable_by_default: Ohita suositun sisällön manuaalinen tarkastus. Yksittäisiä kohteita voidaan edelleen poistaa jälkikäteen. trends: Trendit osoittavat, mitkä julkaisut, aihetunnisteet ja uutiset keräävät huomiota palvelimellasi. trends_as_landing_page: Näytä vierailijoille ja uloskirjautuneille käyttäjille suosittua sisältöä palvelimen kuvauksen sijaan. Edellyttää, että trendit on otettu käyttöön. @@ -283,12 +282,16 @@ fi: content_cache_retention_period: Etäsisällön säilytysaika custom_css: Mukautettu CSS favicon: Sivustokuvake + local_live_feed_access: Pääsy paikallisia julkaisuja esitteleviin livesyötteisiin + local_topic_feed_access: Pääsy paikallisia julkaisuja esitteleviin aihetunniste- ja linkkisyötteisiin mascot: Mukautettu maskotti (vanhentunut) media_cache_retention_period: Mediasisällön välimuistin säilytysaika min_age: Vähimmäisikävaatimus peers_api_enabled: Julkaise löydettyjen palvelinten luettelo ohjelmointirajapinnassa profile_directory: Ota profiilihakemisto käyttöön registrations_mode: Kuka voi rekisteröityä + remote_live_feed_access: Pääsy etäjulkaisuja esitteleviin livesyötteisiin + remote_topic_feed_access: Pääsy etäjulkaisuja esitteleviin aihetunniste- ja linkkisyötteisiin require_invite_text: Vaadi liittymissyy show_domain_blocks: Näytä verkkotunnusten estot show_domain_blocks_rationale: Näytä, miksi verkkotunnukset on estetty @@ -301,7 +304,6 @@ fi: status_page_url: Tilasivun URL-osoite theme: Oletusteema thumbnail: Palvelimen pienoiskuva - timeline_preview: Salli todentamaton pääsy julkisille aikajanoille trendable_by_default: Salli trendit ilman ennakkotarkastusta trends: Ota trendit käyttöön trends_as_landing_page: Käytä trendejä aloitussivuna diff --git a/config/locales/simple_form.fo.yml b/config/locales/simple_form.fo.yml index 95368bcf7ab..605b32fd80e 100644 --- a/config/locales/simple_form.fo.yml +++ b/config/locales/simple_form.fo.yml @@ -105,7 +105,6 @@ fo: status_page_url: Slóð til eina síðu, har ið fólk kunnu síggja støðuna á hesum ambætaranum í sambandi við streymslit theme: Uppsetingareyðkenni, sum vitjandi, ið ikki eru ritaði inn, og nýggir brúkarar síggja. thumbnail: Ein mynd í lutfallinum 2:1, sum verður víst saman við ambætaraupplýsingunum hjá tær. - timeline_preview: Vitjandi, sum eru ritaði út, fara at kunna blaða ígjøgnum nýggjastu almennu postarnar, sum eru tøkir á ambætaranum. trendable_by_default: Loyp uppum serskilda eftirkannan av tilfari, sum er vælumtókt. Einstakir lutir kunnu framvegis strikast frá listum við vælumtóktum tilfari seinni. trends: Listar við vælumtóktum tilfari vísa, hvørjir postar, frámerki og tíðindasøgur hava framburð á tínum ambætara. trends_as_landing_page: Vís vitjandi og brúkarum, sum ikki eru innritaðir, rák í staðin fyri eina lýsing av ambætaranum. Krevur at rák eru virkin. @@ -284,12 +283,16 @@ fo: content_cache_retention_period: Tíðarskeið fyri varðveiðslu av fjartilfari custom_css: Serskilt CSS favicon: Favikon + local_live_feed_access: Atgongd til beinleiðis rásir við lokalum postum + local_topic_feed_access: Atgongd til frámerki og rásir við leinkjum við lokalum postum mascot: Serskildur maskottur (arvur) media_cache_retention_period: Tíðarskeið, har miðlagoymslur verða varðveittar min_age: Aldursmark peers_api_enabled: Kunnger lista við uppdagaðum ambætarum í API'num profile_directory: Ger vangaskrá virkna registrations_mode: Hvør kann tilmelda seg + remote_live_feed_access: Atgongd til beinleiðis rásir við fjarum postum + remote_topic_feed_access: Atgongd til frámerki og rásir við leinkjum við fjarum postum require_invite_text: Krev eina orsøk at luttaka show_domain_blocks: Vís navnaøkisblokeringar show_domain_blocks_rationale: Vís hví navnaøki vóru blokeraði @@ -302,7 +305,6 @@ fo: status_page_url: Slóð til støðusíðu theme: Sjálvvalt uppsetingareyðkenni thumbnail: Ambætarasmámynd - timeline_preview: Loyv teimum, sum ikki eru ritaði inn, atgongd til almennar tíðarlinjur trendable_by_default: Loyv vælumtóktum tilfari uttan at viðgera tað fyrst trends: Loyv ráki trends_as_landing_page: Brúka rák sum lendingarsíðu diff --git a/config/locales/simple_form.fr-CA.yml b/config/locales/simple_form.fr-CA.yml index 4a38b571180..83c32efaff6 100644 --- a/config/locales/simple_form.fr-CA.yml +++ b/config/locales/simple_form.fr-CA.yml @@ -102,7 +102,6 @@ fr-CA: status_page_url: URL d'une page où les gens peuvent voir l'état de ce serveur en cas de panne theme: Thème que verront les utilisateur·rice·s déconnecté·e·s ainsi que les nouveaux·elles utilisateur·rice·s. thumbnail: Une image d'environ 2:1 affichée à côté des informations de votre serveur. - timeline_preview: Les visiteurs déconnectés pourront parcourir les derniers messages publics disponibles sur le serveur. trendable_by_default: Ignorer l'examen manuel du contenu tendance. Des éléments individuels peuvent toujours être supprimés des tendances après coup. trends: Les tendances montrent quelles publications, hashtags et actualités sont en train de gagner en traction sur votre serveur. trends_as_landing_page: Afficher le contenu tendance au lieu d'une description de ce serveur pour les comptes déconnectés et les non-inscrit⋅e⋅s. Nécessite que les tendances soient activées. @@ -290,7 +289,6 @@ fr-CA: status_page_url: URL de la page de l'état du serveur theme: Thème par défaut thumbnail: Miniature du serveur - timeline_preview: Autoriser l’accès non authentifié aux fils publics trendable_by_default: Autoriser les tendances sans révision préalable trends: Activer les tendances trends_as_landing_page: Utiliser les tendances comme page d'accueil diff --git a/config/locales/simple_form.fr.yml b/config/locales/simple_form.fr.yml index 83eef109363..249a08c3266 100644 --- a/config/locales/simple_form.fr.yml +++ b/config/locales/simple_form.fr.yml @@ -102,7 +102,6 @@ fr: status_page_url: URL d'une page où les gens peuvent voir l'état de ce serveur en cas de panne theme: Thème que verront les utilisateur·rice·s déconnecté·e·s ainsi que les nouveaux·elles utilisateur·rice·s. thumbnail: Une image d'environ 2:1 affichée à côté des informations de votre serveur. - timeline_preview: Les utilisateur⋅rice⋅s déconnecté⋅e⋅s pourront parcourir les derniers messages publics disponibles sur le serveur. trendable_by_default: Ignorer l'examen manuel du contenu tendance. Des éléments individuels peuvent toujours être supprimés des tendances après coup. trends: Les tendances montrent quels messages, hashtags et actualités gagnent en popularité sur votre serveur. trends_as_landing_page: Afficher le contenu tendance au lieu d'une description de ce serveur pour les comptes déconnectés et les non-inscrit⋅e⋅s. Nécessite que les tendances soient activées. @@ -290,7 +289,6 @@ fr: status_page_url: URL de la page de l'état du serveur theme: Thème par défaut thumbnail: Miniature du serveur - timeline_preview: Autoriser l’accès non authentifié aux fils publics trendable_by_default: Autoriser les tendances sans révision préalable trends: Activer les tendances trends_as_landing_page: Utiliser les tendances comme page d'accueil diff --git a/config/locales/simple_form.fy.yml b/config/locales/simple_form.fy.yml index 4345f2f6a70..31c6943c408 100644 --- a/config/locales/simple_form.fy.yml +++ b/config/locales/simple_form.fy.yml @@ -103,7 +103,6 @@ fy: status_page_url: URL fan in side dêr’t minsken de steat fan dizze server sjen kinne wylst in steuring theme: Tema dy’t ôfmelde besikers en nije brûkers sjen. thumbnail: In ôfbylding fan ûngefear in ferhâlding fan 2:1 dy’t njonken jo serverynformaasje toand wurdt. - timeline_preview: Net oanmelde besikers kinne de meast resinte, op de server oanwêzige iepenbiere berjochten besjen. trendable_by_default: Hânmjittige beoardieling fan trends oerslaan. Yndividuele items kinne letter dochs noch ôfkard wurde. trends: Trends toane hokker berjochten, hashtags en nijsberjochten op jo server oan populariteit winne. trends_as_landing_page: Toan trending ynhâld oan ôfmelde brûkers en besikers yn stee fan in beskriuwing fan dizze server. Fereasket dat trends ynskeakele binne. @@ -295,7 +294,6 @@ fy: status_page_url: URL fan steatside theme: Standerttema thumbnail: Serverthumbnail - timeline_preview: Tagong ta de iepenbiere tiidlinen sûnder oan te melden tastean trendable_by_default: Trends goedkarre sûnder yn it foar geande beoardieling trends: Trends ynskeakelje trends_as_landing_page: Lit trends op de startside sjen diff --git a/config/locales/simple_form.ga.yml b/config/locales/simple_form.ga.yml index c7e143743d9..f9c06764511 100644 --- a/config/locales/simple_form.ga.yml +++ b/config/locales/simple_form.ga.yml @@ -105,7 +105,6 @@ ga: status_page_url: URL leathanach inar féidir le daoine stádas an fhreastalaí seo a fheiceáil le linn briseadh amach theme: Téama a fheiceann cuairteoirí logáilte amach agus úsáideoirí nua. thumbnail: Íomhá thart ar 2:1 ar taispeáint taobh le faisnéis do fhreastalaí. - timeline_preview: Beidh cuairteoirí logáilte amach in ann na postálacha poiblí is déanaí atá ar fáil ar an bhfreastalaí a bhrabhsáil. trendable_by_default: Léim ar athbhreithniú láimhe ar ábhar treochta. Is féidir míreanna aonair a bhaint as treochtaí fós tar éis an fhíric. trends: Léiríonn treochtaí cé na postálacha, hashtags agus scéalta nuachta atá ag tarraingt ar do fhreastalaí. trends_as_landing_page: Taispeáin inneachar treochta d'úsáideoirí agus do chuairteoirí atá logáilte amach in ionad cur síos ar an bhfreastalaí seo. Éilíonn treochtaí a chumasú. @@ -287,12 +286,16 @@ ga: content_cache_retention_period: Tréimhse choinneála inneachair cianda custom_css: CSS saincheaptha favicon: Favicon + local_live_feed_access: Rochtain ar bheatha bheo ina bhfuil poist áitiúla + local_topic_feed_access: Rochtain ar fhothaí hashtag agus nasc ina bhfuil poist áitiúla mascot: Mascóg saincheaptha (oidhreacht) media_cache_retention_period: Tréimhse choinneála taisce meán min_age: Riachtanas aoise íosta peers_api_enabled: Foilsigh liosta de na freastalaithe aimsithe san API profile_directory: Cumasaigh eolaire próifíle registrations_mode: Cé atá in ann clárú + remote_live_feed_access: Rochtain ar bheatha bheo ina bhfuil poist iargúlta + remote_topic_feed_access: Rochtain ar fhothaí hashtag agus nasc ina bhfuil poist iargúlta require_invite_text: A cheangal ar chúis a bheith páirteach show_domain_blocks: Taispeáin bloic fearainn show_domain_blocks_rationale: Taispeáin cén fáth ar cuireadh bac ar fhearann @@ -305,7 +308,6 @@ ga: status_page_url: URL an leathanaigh stádais theme: Téama réamhshocraithe thumbnail: Mionsamhail freastalaí - timeline_preview: Ceadaigh rochtain neamhdheimhnithe ar amlínte poiblí trendable_by_default: Ceadaigh treochtaí gan athbhreithniú roimh ré trends: Cumasaigh treochtaí trends_as_landing_page: Úsáid treochtaí mar an leathanach tuirlingthe diff --git a/config/locales/simple_form.gd.yml b/config/locales/simple_form.gd.yml index 2464955a43e..19a0a2a5586 100644 --- a/config/locales/simple_form.gd.yml +++ b/config/locales/simple_form.gd.yml @@ -105,7 +105,6 @@ gd: status_page_url: URL duilleige far am faicear staid an fhrithealaiche seo nuair a bhios e sìos theme: An t-ùrlar a chì na h-aoighean gun chlàradh a-staigh agus an luchd-cleachdaidh ùr. thumbnail: Dealbh mu 2:1 a thèid a shealltainn ri taobh fiosrachadh an fhrithealaiche agad. - timeline_preview: "’S urrainn dha na h-aoighean gun chlàradh a-staigh na postaichean poblach as ùire a tha ri fhaighinn air an fhrithealaiche a bhrabhsadh." trendable_by_default: Geàrr leum thar lèirmheas a làimh na susbainte a’ treandadh. Gabhaidh nithean fa leth a thoirt far nan treandaichean fhathast an uairsin. trends: Seallaidh na treandaichean na postaichean, tagaichean hais is naidheachdan a tha fèill mhòr orra air an fhrithealaiche agad. trends_as_landing_page: Seall susbaint a’ treandadh dhan fheadhainn nach do chlàraich a-steach is do dh’aoighean seach tuairisgeul an fhrithealaiche seo. Feumaidh treandaichean a bhith an comas airson sin. @@ -303,7 +302,6 @@ gd: status_page_url: URL duilleag na staide theme: An t-ùrlar bunaiteach thumbnail: Dealbhag an fhrithealaiche - timeline_preview: Ceadaich inntrigeadh gun ùghdarrachadh air na loidhnichean-ama phoblach trendable_by_default: Ceadaich treandaichean gun lèirmheas ro làimh trends: Cuir na treandaichean an comas trends_as_landing_page: Cleachd na treandaichean ’nan duilleag-laighe diff --git a/config/locales/simple_form.gl.yml b/config/locales/simple_form.gl.yml index 3b4f72b1be4..7c77d4aec97 100644 --- a/config/locales/simple_form.gl.yml +++ b/config/locales/simple_form.gl.yml @@ -105,7 +105,6 @@ gl: status_page_url: URL dunha páxina onde se pode ver o estado deste servidor cando non está a funcionar theme: Decorado que verán visitantes e novas usuarias. thumbnail: Imaxe con proporcións 2:1 mostrada xunto á información sobre o servidor. - timeline_preview: Visitantes e usuarias non conectadas poderán ver as publicacións públicas máis recentes do servidor. trendable_by_default: Omitir a revisión manual dos contidos populares. Poderás igualmente eliminar manualmente os elementos que vaian aparecendo. trends: As tendencias mostran publicacións, cancelos e novas historias que teñen popularidade no teu servidor. trends_as_landing_page: Mostrar contidos en voga para as persoas sen sesión iniciada e visitantes no lugar dunha descrición deste servidor. Require ter activado Popularidade. @@ -284,12 +283,16 @@ gl: content_cache_retention_period: Período de retención de contido remoto custom_css: CSS personalizado favicon: Favicon + local_live_feed_access: Acceso a cronoloxías ao vivo que mostran publicacións locais + local_topic_feed_access: Acceso a cronoloxías de ligazóns e cancelos que mostran publicacións locais mascot: Mascota propia (herdado) media_cache_retention_period: Período de retención da caché multimedia min_age: Idade mínima requerida peers_api_enabled: Publicar na API unha lista dos servidores descubertos profile_directory: Activar o directorio de perfís registrations_mode: Quen se pode rexistrar + remote_live_feed_access: Acceso a cronoloxías ao vivo que mostran publicacións remotas + remote_topic_feed_access: Acceso a cronoloxías de ligazóns e cancelos que mostran publicacións remotas require_invite_text: Pedir unha razón para unirse show_domain_blocks: Amosar dominios bloqueados show_domain_blocks_rationale: Explicar porque están bloqueados os dominios @@ -302,7 +305,6 @@ gl: status_page_url: URL da páxina do estado theme: Decorado predeterminado thumbnail: Icona do servidor - timeline_preview: Permitir acceso á cronoloxía pública sen autenticación trendable_by_default: Permitir tendencias sen aprobación previa trends: Activar tendencias trends_as_landing_page: Usar as tendencias como páxina de benvida diff --git a/config/locales/simple_form.he.yml b/config/locales/simple_form.he.yml index b96d98f60d7..53ba7c1e5e9 100644 --- a/config/locales/simple_form.he.yml +++ b/config/locales/simple_form.he.yml @@ -105,7 +105,6 @@ he: status_page_url: כתובת לבדיקת מצב שרת זה בעת תקלה theme: ערכת המראה שיראו משתמשים חדשים ומשתמשים שאינם מחוברים. thumbnail: תמונה ביחס 2:1 בערך שתוצג ליד המידע על השרת שלך. - timeline_preview: משתמשים מנותקים יוכלו לדפדף בהודעות ציר הזמן הציבורי שעל השרת. trendable_by_default: לדלג על בדיקה ידנית של התכנים החמים. פריטים ספציפיים עדיין ניתנים להסרה לאחר מעשה. trends: נושאים חמים יציגו אילו הודעות, תגיות וידיעות חדשות צוברות חשיפה על השרת שלך. trends_as_landing_page: הצג למבקרים ולמשתמשים שאינם מחוברים את הנושאים החמים במקום את תיאור השרת. מחייב הפעלה של אפשרות הנושאים החמים. @@ -286,12 +285,16 @@ he: content_cache_retention_period: תקופת השמירה על תוכן חיצוני custom_css: CSS בהתאמה אישית favicon: סמל מועדפים (Favicon) + local_live_feed_access: גישה לפידים חיים המציגים הודעות מקומיות + local_topic_feed_access: גישה לפידים של תגיות וקישורים המציגים הודעות מקומיות mascot: סמל השרת (ישן) media_cache_retention_period: תקופת שמירת מטמון מדיה min_age: דרישת גיל מינימלי peers_api_enabled: פרסם רשימה של שרתים שנתגלו באמצעות ה-API profile_directory: הפעלת ספריית פרופילים registrations_mode: מי יכולים לפתוח חשבון + remote_live_feed_access: גישה לפידים חיים המציגים הודעות מהעולם + remote_topic_feed_access: גישה לפידים של תגיות וקישורים המציגים הודעות מהעולם require_invite_text: לדרוש סיבה להצטרפות show_domain_blocks: הצגת חסימת דומיינים show_domain_blocks_rationale: הצגת סיבות חסימה למתחמים @@ -304,7 +307,6 @@ he: status_page_url: URL של עמוד סטטוס חיצוני theme: ערכת נושא ברירת מחדל thumbnail: תמונה ממוזערת מהשרת - timeline_preview: הרשאת גישה בלתי מאומתת לפיד הפומבי trendable_by_default: הרשאה לפריטים להופיע בנושאים החמים ללא אישור מוקדם trends: אפשר פריטים חמים (טרנדים) trends_as_landing_page: דף הנחיתה יהיה "נושאים חמים" diff --git a/config/locales/simple_form.hu.yml b/config/locales/simple_form.hu.yml index c4f0e2b6f68..622fb0bbe9b 100644 --- a/config/locales/simple_form.hu.yml +++ b/config/locales/simple_form.hu.yml @@ -105,7 +105,6 @@ hu: status_page_url: Annak az oldalnak az URL-je, melyen ennek a kiszolgálónak az állapotát látják az emberek egy leállás során theme: A téma, melyet a kijelentkezett látogatók és az új felhasználók látnak. thumbnail: Egy durván 2:1 arányú kép, amely a kiszolgálóinformációk mellett jelenik meg. - timeline_preview: A kijelentkezett látogatók továbbra is böngészhetik a kiszolgáló legfrissebb nyilvános bejegyzéseit. trendable_by_default: Kézi felülvizsgálat kihagyása a felkapott tartalmaknál. Az egyes elemek utólag távolíthatók el a trendek közül. trends: A trendek azt mondják meg, hogy mely bejegyzések, hashtagek és hírbejegyzések felkapottak a kiszolgálódon. trends_as_landing_page: Felkapott tartalmak mutatása a kijelentkezett felhasználók és látogatók számára ennek a kiszolgálónak a leírása helyett. Szükséges hozzá a trendek engedélyezése. @@ -284,12 +283,16 @@ hu: content_cache_retention_period: Távoli tartalmak megtartási időszaka custom_css: Egyéni CSS favicon: Könyvjelzőikon + local_live_feed_access: Helyi bejegyzéseket bemutató élő hírfolyamok elérése + local_topic_feed_access: Helyi bejegyzéseket bemutató hashtagek és hivatkozásfolyamok elérése mascot: Egyéni kabala (örökölt) media_cache_retention_period: Média-gyorsítótár megtartási időszaka min_age: Minimális korhatár peers_api_enabled: Felfedezett kiszolgálók listájának közzététele az API-ban profile_directory: Profiladatbázis engedélyezése registrations_mode: Ki regisztrálhat + remote_live_feed_access: Távoli bejegyzéseket bemutató élő hírfolyamok elérése + remote_topic_feed_access: Távoli bejegyzéseket bemutató hashtagek és hivatkozásfolyamok elérése require_invite_text: Indok megkövetelése a csatlakozáshoz show_domain_blocks: Domain tiltások megjelenitése show_domain_blocks_rationale: A domainek letiltási okainak megjelenítése @@ -302,7 +305,6 @@ hu: status_page_url: Állapotoldal URL-je theme: Alapértelmezett téma thumbnail: Kiszolgáló bélyegképe - timeline_preview: A nyilvános idővonalak hitelesítés nélküli elérésének engedélyezése trendable_by_default: Trendek engedélyezése előzetes ellenőrzés nélkül trends: Trendek engedélyezése trends_as_landing_page: Trendek használata nyitóoldalként diff --git a/config/locales/simple_form.ia.yml b/config/locales/simple_form.ia.yml index 499d565f4f6..57b382fe065 100644 --- a/config/locales/simple_form.ia.yml +++ b/config/locales/simple_form.ia.yml @@ -105,7 +105,6 @@ ia: status_page_url: URL de un pagina ubi le personas pote vider le stato de iste servitor durante un interruption theme: Thema que le visitatores disconnexe e le nove usatores vide. thumbnail: Un imagine de circa 2:1 monstrate al latere del informationes de tu servitor. - timeline_preview: Le visitatores foras de session potera percurrer le messages public le plus recente disponibile sur le servitor. trendable_by_default: Saltar le revision manual del contento de tendentia. Elementos singule pote ancora esser removite de tendentias post le facto. trends: Tendentias monstra que messages, hashtags e novas gania traction sur tu servitor. trends_as_landing_page: Monstrar contento de tendentia a usatores disconnexe e visitatores in vice que un description de iste servitor. Require tendentias esser activate. @@ -302,7 +301,6 @@ ia: status_page_url: URL del pagina de stato theme: Thema predefinite thumbnail: Miniatura de servitor - timeline_preview: Permitter accesso non authenticate a chronologias public trendable_by_default: Permitter tendentias sin revision previe trends: Activar tendentias trends_as_landing_page: Usar tendentias como pagina de destination diff --git a/config/locales/simple_form.id.yml b/config/locales/simple_form.id.yml index 0413dafe36a..d89c610ddb5 100644 --- a/config/locales/simple_form.id.yml +++ b/config/locales/simple_form.id.yml @@ -80,7 +80,6 @@ id: site_title: Bagaimana orang dapat memberitahu tentang server selain nama domain. theme: Tema yang dilihat oleh pengunjung yang keluar dan pengguna baru. thumbnail: Gambar sekitar 2:1 yang ditampilkan di samping informasi server Anda. - timeline_preview: Pengunjung yang keluar akan dapat menjelajahi kiriman publik terkini yang tersedia di server. trendable_by_default: Lewati tinjauan manual dari konten tren. Item individu masih dapat dihapus dari tren setelah faktanya. trends: Tren yang menampilkan kiriman, tagar, dan cerita berita apa yang sedang tren di server Anda. form_challenge: @@ -230,7 +229,6 @@ id: site_title: Nama server theme: Tema bawaan thumbnail: Gambar kecil server - timeline_preview: Perbolehkan akses tidak terotentikasi ke linimasa publik trendable_by_default: Perbolehkan tren tanpa tinjauan trends: Aktifkan tren interactions: diff --git a/config/locales/simple_form.ie.yml b/config/locales/simple_form.ie.yml index 24635c7f832..ccb54501933 100644 --- a/config/locales/simple_form.ie.yml +++ b/config/locales/simple_form.ie.yml @@ -97,7 +97,6 @@ ie: status_page_url: URL de un págine monstrant li statu de ti-ci servitor durant un ruptura de servicie theme: Li dessine quel ínregistrat visitantes e nov usatores vide. thumbnail: Un image de dimensiones circa 2:1 monstrat along tui servitor-information. - timeline_preview: Ínregistrat visitantes va posser vider li max recent public postas disponibil che li servitor. trendable_by_default: Pretersaltar un manual revision de contenete in tendentie. Mem pos to on posse remover índividual pezzes de tendentie. trends: Tendenties monstra quel postas, hashtags e novas es ganiant atention sur tui servitor. trends_as_landing_page: Monstrar populari contenete a ínregistrat visitantes vice un description del servitor. Besona que tendenties es activisat. @@ -261,7 +260,6 @@ ie: status_page_url: URL de statu-págine theme: Predefenit tema thumbnail: Miniatura del servitor - timeline_preview: Permisser accesse ínautenticat al public témpor-lineas trendable_by_default: Possibilisar tendenties sin priori inspection trends: Possibilisar tendenties trends_as_landing_page: Usar tendenties quam frontispicie diff --git a/config/locales/simple_form.io.yml b/config/locales/simple_form.io.yml index b0904353c1a..c3d4d1a0f58 100644 --- a/config/locales/simple_form.io.yml +++ b/config/locales/simple_form.io.yml @@ -100,7 +100,6 @@ io: status_page_url: URL di pagino ube personi povas vidar la stando di ca servilo kande la servilo ne funcionas theme: Temo quo videsas da ekirita vizitanti e nova uzanti. thumbnail: Cirkum 2:1 imajo montresar kun informo di ca servilo. - timeline_preview: Ekirita vizitanti videsos maxim recenta publika posti quo esas displonebla en la servilo. trendable_by_default: Ignorez manuala kontrolar di populara enhavajo. trends: Populari montras quala afishi, gretvorti e novaji populareskas en vua servilo. trends_as_landing_page: Montrez populara posti a uzanti neeniriti e vizitanti vice deskriptajo pri ca servilo. Bezonas ke populari es aktivita. @@ -280,7 +279,6 @@ io: status_page_url: URL dil stando-pagino theme: Originala temo thumbnail: Servilimajeto - timeline_preview: Permisez neyurizita aceso a publika tempolineo trendable_by_default: Permisez populari sen kontrolo trends: Ebligar populari trends_as_landing_page: Uzar populari quale la iniciala pagino diff --git a/config/locales/simple_form.is.yml b/config/locales/simple_form.is.yml index bbbba8c8f7a..03d093fc6bf 100644 --- a/config/locales/simple_form.is.yml +++ b/config/locales/simple_form.is.yml @@ -105,7 +105,6 @@ is: status_page_url: Slóð á síðu þar sem fólk getur séð ástand netþjónsins þegar vandræði koma upp theme: Þema sem útskráðir gestir og nýjir notendur sjá. thumbnail: Mynd um það bil 2:1 sem birtist samhliða upplýsingum um netþjóninn þinn. - timeline_preview: Gestir sem ekki eru skráðir inn munu geta skoðað nýjustu opinberu færslurnar sem tiltækar eru á þjóninum. trendable_by_default: Sleppa handvirkri yfirferð á vinsælu efni. Áfram verður hægt að fjarlægja stök atriði úr vinsældarlistum. trends: Vinsældir sýna hvaða færslur, myllumerki og fréttasögur séu í umræðunni á netþjóninum þínum. trends_as_landing_page: Sýna vinsælt efni til ekki-innskráðra notenda í stað lýsingar á þessum netþjóni. Krefst þess að vinsældir efnis sé virkjað. @@ -284,12 +283,16 @@ is: content_cache_retention_period: Tímabil sem á að geyma fjartengt efni custom_css: Sérsniðið CSS favicon: Auðkennismynd + local_live_feed_access: Aðgangur að beinum streymum, þar með töldum staðværum færslum + local_topic_feed_access: Aðgangur að myllumerkjum og tengdum streymum, þar með töldum staðværum færslum mascot: Sérsniðið gæludýr (eldra) media_cache_retention_period: Tímalengd sem myndefni haldið min_age: Kröfur um lágmarksaldur peers_api_enabled: Birta lista yfir uppgötvaða netþjóna í API-kerfisviðmótinu profile_directory: Virkja notendamöppu registrations_mode: Hverjir geta nýskráð sig + remote_live_feed_access: Aðgangur að beinum streymum, þar með töldum fjartengdum færslum + remote_topic_feed_access: Aðgangur að myllumerkjum og tengdum streymum, þar með töldum fjartengdum færslum require_invite_text: Krefjast ástæðu fyrir þátttöku show_domain_blocks: Sýna útilokanir léna show_domain_blocks_rationale: Sýna af hverju lokað var á lén @@ -302,7 +305,6 @@ is: status_page_url: Slóð á ástandssíðu theme: Sjálfgefið þema thumbnail: Smámynd vefþjóns - timeline_preview: Leyfa óauðkenndan aðgang að opinberum tímalínum trendable_by_default: Leyfa vinsælt efni án undanfarandi yfirferðar trends: Virkja vinsælt trends_as_landing_page: Nota vinsælasta sem upphafssíðu diff --git a/config/locales/simple_form.it.yml b/config/locales/simple_form.it.yml index 39587cd5e50..59d7924820f 100644 --- a/config/locales/simple_form.it.yml +++ b/config/locales/simple_form.it.yml @@ -105,7 +105,6 @@ it: status_page_url: URL di una pagina in cui le persone possono visualizzare lo stato di questo server durante un disservizio theme: Tema visualizzato dai visitatori e dai nuovi utenti disconnessi. thumbnail: Un'immagine approssimativamente 2:1 visualizzata insieme alle informazioni del tuo server. - timeline_preview: I visitatori disconnessi potranno sfogliare i post pubblici più recenti disponibili sul server. trendable_by_default: Salta la revisione manuale dei contenuti di tendenza. I singoli elementi possono ancora essere rimossi dalle tendenze dopo il fatto. trends: Le tendenze mostrano quali post, hashtag e notizie stanno guadagnando popolarità sul tuo server. trends_as_landing_page: Mostra i contenuti di tendenza agli utenti disconnessi e ai visitatori, invece di una descrizione di questo server. Richiede l'abilitazione delle tendenze. @@ -302,7 +301,6 @@ it: status_page_url: URL della pagina di stato theme: Tema predefinito thumbnail: Miniatura del server - timeline_preview: Consenti l'accesso non autenticato alle timeline pubbliche trendable_by_default: Consenti le tendenze senza revisione preventiva trends: Abilita le tendenze trends_as_landing_page: Usa le tendenze come pagina di destinazione diff --git a/config/locales/simple_form.ja.yml b/config/locales/simple_form.ja.yml index 15e6439cb72..7ff3f36a657 100644 --- a/config/locales/simple_form.ja.yml +++ b/config/locales/simple_form.ja.yml @@ -102,7 +102,6 @@ ja: status_page_url: 障害発生時などにユーザーがサーバーの状態を確認できるページのURL theme: ログインしていない人と新規ユーザーに表示されるテーマ。 thumbnail: サーバー情報と共に表示される、アスペクト比が約 2:1 の画像。 - timeline_preview: ログインしていないユーザーがサーバー上の最新の公開投稿を閲覧できるようにします。 trendable_by_default: トレンドの審査を省略します。トレンドは掲載後でも個別に除外できます。 trends: トレンドは、サーバー上で人気を集めている投稿、ハッシュタグ、ニュース記事などが表示されます。 trends_as_landing_page: ログインしていないユーザーに対して、サーバーの説明の代わりにトレンドコンテンツを表示します。トレンドを有効にする必要があります。 @@ -292,7 +291,6 @@ ja: status_page_url: サーバーの状態ページのURL theme: デフォルトテーマ thumbnail: サーバーのサムネイル - timeline_preview: 公開タイムラインへの未認証のアクセスを許可する trendable_by_default: 審査前のトレンドの掲載を許可する trends: トレンドを有効にする trends_as_landing_page: 新規登録画面にトレンドを表示する diff --git a/config/locales/simple_form.ko.yml b/config/locales/simple_form.ko.yml index 4cca7676f7a..4b04631cb48 100644 --- a/config/locales/simple_form.ko.yml +++ b/config/locales/simple_form.ko.yml @@ -103,7 +103,6 @@ ko: status_page_url: 이 서버가 중단된 동안 사람들이 서버의 상태를 볼 수 있는 페이지 URL theme: 로그인 하지 않은 사용자나 새로운 사용자가 보게 될 테마. thumbnail: 대략 2:1 비율의 이미지가 서버 정보 옆에 표시됩니다. - timeline_preview: 로그아웃 한 사용자들이 이 서버에 있는 최신 공개글들을 볼 수 있게 합니다. trendable_by_default: 유행하는 콘텐츠에 대한 수동 승인을 건너뜁니다. 이 설정이 적용된 이후에도 각각의 항목들을 삭제할 수 있습니다. trends: 트렌드는 어떤 게시물, 해시태그 그리고 뉴스 기사가 이 서버에서 인기를 끌고 있는지 보여줍니다. trends_as_landing_page: 로그아웃한 사용자와 방문자에게 서버 설명 대신 유행하는 내용을 보여줍니다. 유행 기능을 활성화해야 합니다. @@ -298,7 +297,6 @@ ko: status_page_url: 상태 페이지 URL theme: 기본 테마 thumbnail: 서버 썸네일 - timeline_preview: 로그인 하지 않고 공개 타임라인에 접근하는 것을 허용 trendable_by_default: 사전 리뷰 없이 트렌드에 오르는 것을 허용 trends: 유행 활성화 trends_as_landing_page: 유행을 방문 페이지로 쓰기 diff --git a/config/locales/simple_form.ku.yml b/config/locales/simple_form.ku.yml index b9111e3f64d..1bd566d22dc 100644 --- a/config/locales/simple_form.ku.yml +++ b/config/locales/simple_form.ku.yml @@ -79,7 +79,6 @@ ku: site_title: Tu çawa dixwazî mirov qale rajekarê te bikin ji bilî navê navperê wî. theme: Rûkara ku mêvanên têneketî û bikarhênerên nû dibînin. thumbnail: Li kêleka zanyariyên rajekarê xwe wêneyeke 2:1 nîşan bide. - timeline_preview: Mêvanên têneketî wê karibin li şandiyên gelemperî yên herî dawî yên ku li ser rajekarê peyda dibin bigerin. trendable_by_default: Nirxandina destan a naveroka rojevê derbas bike. Tiştên kesane dîsa jî dikarin piştî rastiyê ji rojevê werin derxistin. trends: Rojev nîşan dide ka kîjan şandî, hashtag û çîrokê nûçeyan balê dikişîne li ser rajekarê te. form_challenge: @@ -229,7 +228,6 @@ ku: site_title: Navê rajekar theme: Rûkara berdest thumbnail: Wêneya piçûk a rajekar - timeline_preview: Mafê bide gihîştina ne naskirî bo demnameya gelemperî trendable_by_default: Mafê bide rojevê bêyî ku were nirxandin trends: Rojevê çalak bike interactions: diff --git a/config/locales/simple_form.lad.yml b/config/locales/simple_form.lad.yml index 08fefe240f0..f11eb946e52 100644 --- a/config/locales/simple_form.lad.yml +++ b/config/locales/simple_form.lad.yml @@ -93,7 +93,6 @@ lad: status_page_url: Adreso URL de la pajina ande la djente puede ver el estado de este sirvidor durante una insidensya theme: El tema ke los vizitantes no enrejistrados i los muevos utilizadores ven. thumbnail: Una imaje de aproksimadamente 2:1 se amostra djunto a la enformasyon de tu sirvidor. - timeline_preview: Los vizitantes no konektados podran navigar por los mesajes publikos mas resientes desponivles en el sirvidor. trendable_by_default: Omite la revizyon manuala del kontenido en trend. Los elementos individuales ainda podran supremirse de los trendes. trends: Los trendes amostran ke mesajes, etiketas i haberes estan ganando traksyon en tu sirvidor. trends_as_landing_page: Amostra kontenido en trend para utilizadores i vizitantes en lugar de una deskripsyon de este sirvidor. Rekiere ke los trendes esten kapasitados. @@ -259,7 +258,6 @@ lad: status_page_url: URL de pajina de estado theme: Tema predeterminado thumbnail: Minyatura del sirvidor - timeline_preview: Permite el akseso no autentifikado a las linyas de tiempo publikas trendable_by_default: Permite trendes sin revizyon previa trends: Kapasita trendes trends_as_landing_page: Kulanea trendes komo la pajina prinsipala diff --git a/config/locales/simple_form.lt.yml b/config/locales/simple_form.lt.yml index 2b2f2df1365..8eacc9685f2 100644 --- a/config/locales/simple_form.lt.yml +++ b/config/locales/simple_form.lt.yml @@ -91,7 +91,6 @@ lt: site_contact_username: Kaip žmonės gali tave pasiekti Mastodon. site_extended_description: Bet kokia papildoma informacija, kuri gali būti naudinga lankytojams ir naudotojams. Gali būti struktūrizuota naudojant Markdown sintaksę. thumbnail: Maždaug 2:1 dydžio vaizdas, rodomas šalia tavo serverio informacijos. - timeline_preview: Atsijungę lankytojai galės naršyti naujausius viešus įrašus, esančius serveryje. trends: Trendai rodo, kurios įrašai, saitažodžiai ir naujienų istorijos tavo serveryje sulaukia didžiausio susidomėjimo. trends_as_landing_page: Rodyti tendencingą turinį atsijungusiems naudotojams ir lankytojams vietoj šio serverio aprašymo. Reikia, kad tendencijos būtų įjungtos. imports: diff --git a/config/locales/simple_form.lv.yml b/config/locales/simple_form.lv.yml index 6e7e57ffabe..49ff578c31f 100644 --- a/config/locales/simple_form.lv.yml +++ b/config/locales/simple_form.lv.yml @@ -57,9 +57,9 @@ lv: setting_aggregate_reblogs: Nerādīt jaunus izcēlumus ziņām, kas nesen tika palielinātas (ietekmē tikai nesen saņemtos palielinājumus) setting_always_send_emails: Parasti e-pasta paziņojumi netiek sūtīti, kad aktīvi izmantojat Mastodon setting_default_sensitive: Pēc noklusējuma jūtīgi informācijas nesēji ir paslēpti, un tos var atklāt ar klikšķi - setting_display_media_default: Paslēpt informācijas nesējus, kas atzīmēti kā jūtīgi - setting_display_media_hide_all: Vienmēr slēpt multividi - setting_display_media_show_all: Vienmēr rādīt multividi + setting_display_media_default: Paslēpt attēlus un video, kas atzīmēti kā jūtīgi + setting_display_media_hide_all: Vienmēr slēpt attēlus un video + setting_display_media_show_all: Vienmēr rādīt attēlus un video setting_system_scrollbars_ui: Attiecas tikai uz darbvirsmas pārlūkiem, kuru pamatā ir Safari vai Chrome setting_use_blurhash: Pāreju pamatā ir paslēpto uzskatāmo līdzekļu krāsas, bet saturs tiek padarīts neskaidrs setting_use_pending_items: Paslēpt laika skalas atjauninājumus aiz klikšķa, nevis ar automātisku plūsmas ritināšanu @@ -102,7 +102,6 @@ lv: status_page_url: Tās lapas URL, kurā lietotāji var redzēt šī servera statusu pārtraukuma laikā theme: Tēma, kuru redz apmeklētāji, kuri ir atteikušies, un jaunie lietotāji. thumbnail: Aptuveni 2:1 attēls, kas tiek parādīts kopā ar tava servera informāciju. - timeline_preview: Atteikušies apmeklētāji varēs pārlūkot jaunākos serverī pieejamos publiskos ierakstus. trendable_by_default: Izlaist aktuālā satura manuālu pārskatīšanu. Atsevišķas preces joprojām var noņemt no tendencēm pēc fakta. trends: Tendences parāda, kuras ziņas, atsauces un ziņu stāsti gūst panākumus tavā serverī. trends_as_landing_page: Šī servera apraksta vietā rādīt aktuālo saturu lietotājiem un apmeklētājiem, kuri ir atteikušies. Nepieciešams iespējot tendences. @@ -223,7 +222,7 @@ lv: setting_default_language: Publicēšanas valoda setting_default_quote_policy: Kas var citēt setting_default_sensitive: Vienmēr atzīmēt informācijas nesējus kā jūtīgus - setting_delete_modal: Parādīt apstiprinājuma dialogu pirms ziņas dzēšanas + setting_delete_modal: Rādīt apstiprinājuma dialogu pirms ziņas dzēšanas setting_disable_hover_cards: Atspējot profila priekšskatījumu pēc kursora novietošanas setting_disable_swiping: Atspējot vilkšanas kustības setting_display_media: Multivides rādīšana @@ -232,13 +231,13 @@ lv: setting_display_media_show_all: Parādīt visu setting_expand_spoilers: Vienmēr izvērst ziņas, kas apzīmētas ar brīdinājumiem par saturu setting_hide_network: Slēpt savu sociālo grafu - setting_missing_alt_text_modal: Rādīt apstiprināšanas lodziņu pirms informācijas nesēju bez aprakstošā teksta iesūtīšanas + setting_missing_alt_text_modal: Rādīt apstiprināšanas lodziņu pirms iesūtīt attēlus vai video bez aprakstošā teksta setting_reduce_motion: Ierobežot kustību animācijās setting_system_font_ui: Lietot sistēmas noklusējuma fontu setting_system_scrollbars_ui: Lietot sistēmas noklusējuma ritjoslu setting_theme: Vietnes motīvs setting_trends: Parādīt šodienas tendences - setting_unfollow_modal: Parādīt apstiprinājuma dialogu pirms pārtraukt kādam sekot + setting_unfollow_modal: Rādīt apstiprinājuma dialogu pirms pārtraukt kādam sekot setting_use_blurhash: Rādīt krāsainas pārejas paslēptajiem informācijas nesējiem setting_use_pending_items: Lēnais režīms severity: Smagums @@ -254,7 +253,7 @@ lv: name: Tēmturis filters: actions: - blur: Paslēpt informācijas nesējus ar brīdinājumu + blur: Paslēpt attēlus un video ar brīdinājumu hide: Paslēpt pilnībā warn: Paslēpt ar brīdinājumu form_admin_settings: @@ -284,7 +283,6 @@ lv: status_page_url: Statusa lapas URL theme: Noklusētā tēma thumbnail: Servera sīkbilde - timeline_preview: Atļaut neautentificētu piekļuvi publiskajām ziņu lentām trendable_by_default: Atļaut tendences bez iepriekšējas pārskatīšanas trends: Iespējot tendences trends_as_landing_page: Izmantojiet tendences kā galveno lapu diff --git a/config/locales/simple_form.ms.yml b/config/locales/simple_form.ms.yml index 6c452407814..478d10a5b94 100644 --- a/config/locales/simple_form.ms.yml +++ b/config/locales/simple_form.ms.yml @@ -91,7 +91,6 @@ ms: status_page_url: URL halaman yang membolehkan orang ramai melihat status server ini semasa gangguan theme: Tema yang pelawat log keluar dan pengguna baharu lihat. thumbnail: Imej kira-kira 2:1 dipaparkan bersama maklumat server anda. - timeline_preview: Pelawat yang log keluar akan dapat menyemak imbas siaran awam terkini yang tersedia pada server. trendable_by_default: Langkau semakan manual kandungan sohor kini. Item individu masih boleh dialih keluar daripada trend selepas fakta itu. trends: Aliran menunjukkan pos, hashtag dan cerita berita yang mendapat tarikan pada server anda. trends_as_landing_page: Tunjukkan kandungan trend kepada pengguna dan pelawat yang log keluar dan bukannya penerangan tentang server ini. Memerlukan trend untuk didayakan. @@ -256,7 +255,6 @@ ms: status_page_url: URL halaman status theme: Tema asal thumbnail: Server thumbnail - timeline_preview: Benarkan akses tidak disahkan kepada garis masa awam trendable_by_default: Benarkan aliran tanpa semakan terlebih dahulu trends: Dayakan trend trends_as_landing_page: Gunakan trend sebagai halaman pendaratan diff --git a/config/locales/simple_form.my.yml b/config/locales/simple_form.my.yml index 283acbd76d6..fe8c476ea09 100644 --- a/config/locales/simple_form.my.yml +++ b/config/locales/simple_form.my.yml @@ -90,7 +90,6 @@ my: status_page_url: ပြတ်တောက်နေစဉ်အတွင်း လူများက ဤဆာဗာအခြေအနေကို မြင်နိုင်မည့် စာမျက်နှာ URL theme: အကောင့်မှထွက်ပြီး အသုံးပြုသူအသစ်များနှင့် ဝင်ကြည့်မည့်သူများအတွက် မြင်ရမည့်ပုံစံ။ thumbnail: သင့်ဆာဗာအချက်အလက်နှင့်အတူ အကြမ်းဖျင်းအားဖြင့် ၂:၁ ဖြင့် ပြသထားသောပုံတစ်ပုံ။ - timeline_preview: အကောင့်မှထွက်ထားသူများသည် ဆာဗာပေါ်ရှိ လတ်တလော အများမြင်ပို့စ်များကို ရှာဖွေကြည့်ရှုနိုင်မည်ဖြစ်သည်။ trendable_by_default: ခေတ်စားနေသော အကြောင်းအရာများ၏ ကိုယ်တိုင်သုံးသပ်ချက်ကို ကျော်ပါ။ နောက်ပိုင်းတွင် အချက်အလက်တစ်ခုချင်းစီကို ခေတ်စားနေသောအကြောင်းအရာများကဏ္ဍမှ ဖယ်ရှားနိုင်ပါသေးသည်။ trends: လက်ရှိခေတ်စားနေသာပို့စ်များ၊ hashtag များနှင့် သတင်းဇာတ်လမ်းများကို သင့်ဆာဗာပေါ်တွင် တွေ့မြင်နိုင်ပါမည်။ trends_as_landing_page: ဤဆာဗာဖော်ပြချက်အစား အကောင့်မှ ထွက်ထားသူများနှင့် ဝင်ရောက်ကြည့်ရှုသူများအတွက် ခေတ်စားနေသော အကြောင်းအရာများကို ပြသပါ။ ခေတ်စားနေသောပို့စ်များကို ဖွင့်ထားရန် လိုအပ်သည်။ @@ -252,7 +251,6 @@ my: status_page_url: အခြေအနေပြစာမျက်နှာ URL theme: မူလသတ်မှတ်ထားသည့် အပြင်အဆင် thumbnail: ဆာဗာ ပုံသေး - timeline_preview: အများမြင်စာမျက်နှာများသို့ အထောက်အထားမရှိဘဲ ဝင်ရောက်ခွင့်ပြုပါ trendable_by_default: ကြိုမသုံးသပ်ဘဲ ခေတ်စားနေသောအကြောင်းအရာများကို ခွင့်ပြုပါ trends: လက်ရှိခေတ်စားနေမှုများကိုပြပါ trends_as_landing_page: ခေတ်စားနေသောပို့စ်များကို landing စာမျက်နှာအဖြစ် အသုံးပြုပါ diff --git a/config/locales/simple_form.nl.yml b/config/locales/simple_form.nl.yml index 16fb62a11ea..22e0f3fa70f 100644 --- a/config/locales/simple_form.nl.yml +++ b/config/locales/simple_form.nl.yml @@ -105,7 +105,6 @@ nl: status_page_url: URL van een pagina waar mensen de status van deze server kunnen zien tijdens een storing theme: Thema die (niet ingelogde) bezoekers en nieuwe gebruikers zien. thumbnail: Een afbeelding van ongeveer een verhouding van 2:1 die naast jouw serverinformatie wordt getoond. - timeline_preview: Bezoekers (die niet zijn ingelogd) kunnen de meest recente, op de server aanwezige openbare berichten bekijken. trendable_by_default: Handmatige beoordeling van trends overslaan. Individuele items kunnen later alsnog worden afgekeurd. trends: Trends laten zien welke berichten, hashtags en nieuwsberichten op jouw server aan populariteit winnen. trends_as_landing_page: Toon trending inhoud aan uitgelogde gebruikers en bezoekers in plaats van een beschrijving van deze server. Vereist dat trends zijn ingeschakeld. @@ -284,12 +283,16 @@ nl: content_cache_retention_period: Bewaartermijn voor externe inhoud custom_css: Aangepaste CSS favicon: Favicon + local_live_feed_access: Toegang tot openbare lokale berichten + local_topic_feed_access: Toegang tot overzicht met lokale hashtags en links mascot: Aangepaste mascotte (legacy) media_cache_retention_period: Bewaartermijn mediacache min_age: Vereiste minimumleeftijd peers_api_enabled: Lijst van bekende servers via de API publiceren profile_directory: Gebruikersgids inschakelen registrations_mode: Wie kan zich registreren + remote_live_feed_access: Toegang tot openbare berichten van andere servers + remote_topic_feed_access: Toegang tot overzicht met hashtags en links van andere servers require_invite_text: Opgeven van een reden is verplicht show_domain_blocks: Domeinblokkades tonen show_domain_blocks_rationale: Redenen voor domeinblokkades tonen @@ -302,7 +305,6 @@ nl: status_page_url: URL van statuspagina theme: Standaardthema thumbnail: Server-miniatuur - timeline_preview: Toegang tot de openbare tijdlijnen zonder in te loggen toestaan trendable_by_default: Trends goedkeuren zonder voorafgaande beoordeling trends: Trends inschakelen trends_as_landing_page: Laat trends op de startpagina zien diff --git a/config/locales/simple_form.nn.yml b/config/locales/simple_form.nn.yml index 3e6982f1401..b80f90adb46 100644 --- a/config/locales/simple_form.nn.yml +++ b/config/locales/simple_form.nn.yml @@ -105,7 +105,6 @@ nn: status_page_url: Adressa til ei side der folk kan sjå statusen til denne tenaren ved feil og utkoplingar theme: Tema som er synleg for nye brukarar og besøkjande som ikkje er logga inn. thumbnail: Eit omlag 2:1 bilete vist saman med informasjon om tenaren. - timeline_preview: Besøkjande som ikkje er logga inn vil kunne bla gjennom dei siste offentlege innlegga på tenaren. trendable_by_default: Hopp over manuell gjennomgang av populært innhald. Enkeltståande innlegg kan fjernast frå trendar i etterkant. trends: Trendar viser kva for nokre innlegg, emneknaggar og nyheiter som er populære på tenaren. trends_as_landing_page: Vis populært innhald til utlogga brukarar og folk som kjem innom sida i staden for ei skildring av tenaren. Du må ha skrudd på trendar for å kunna bruka dette. @@ -302,7 +301,6 @@ nn: status_page_url: Adresse til statussida theme: Standardtema thumbnail: Miniatyrbilete for tenaren - timeline_preview: Tillat uautentisert tilgang til offentleg tidsline trendable_by_default: Tillat trendar utan gjennomgang på førehand trends: Aktiver trendar trends_as_landing_page: Bruk trendar som startside diff --git a/config/locales/simple_form.no.yml b/config/locales/simple_form.no.yml index cd92a269b1a..747cf2f3b85 100644 --- a/config/locales/simple_form.no.yml +++ b/config/locales/simple_form.no.yml @@ -92,7 +92,6 @@ status_page_url: URL-adressen til en side hvor folk kan se tilstanden til denne tjeneren under et avbrudd theme: Tema som vises for nye brukere og besøkende som ikke er logget inn. thumbnail: Et omtrent 2:1 bilde vist sammen med serverinformasjonen din. - timeline_preview: Logget ut besøkende vil kunne bla gjennom de siste offentlige innlegg tilgjengelig på serveren. trendable_by_default: Hopp over manuell gjennomgang av populære innhold. Individuelle elementer kan fjernes fra populært etter faktaen. trends: Trender viser hvilke innlegg, emneknagger og nyheter som får trekkraft på serveren din. trends_as_landing_page: Vis populære innhold til innloggede brukere og besøkende i stedet for en beskrivelse av tjeneren. Krever populært for å bli aktivert. @@ -255,7 +254,6 @@ status_page_url: Status side lenke theme: Standard tema thumbnail: Miniatyrbilde til server - timeline_preview: Tillat uautentisert tilgang til offentlige tidslinjer trendable_by_default: Tillat trender uten foregående vurdering trends: Aktiver trender trends_as_landing_page: Bruk trender som landingsside diff --git a/config/locales/simple_form.oc.yml b/config/locales/simple_form.oc.yml index 2eb7c58f544..26c310068e9 100644 --- a/config/locales/simple_form.oc.yml +++ b/config/locales/simple_form.oc.yml @@ -180,7 +180,6 @@ oc: site_title: Nom del servidor theme: Tèma per defaut thumbnail: Miniatura del servidor - timeline_preview: Permtre l’accès a l’apercebut del flux public sens autentificacion trendable_by_default: Activar las tendéncias sens revision prealabla trends: Activar las tendéncias interactions: diff --git a/config/locales/simple_form.pl.yml b/config/locales/simple_form.pl.yml index da7a8e25e54..07196019bd5 100644 --- a/config/locales/simple_form.pl.yml +++ b/config/locales/simple_form.pl.yml @@ -103,7 +103,6 @@ pl: status_page_url: Adres URL strony, na której odwiedzający mogą zobaczyć status tego serwera w trakcie awarii theme: Motyw, który widzą wylogowani i nowi użytkownicy. thumbnail: Obraz o proporcjach mniej więcej 2:1 wyświetlany obok informacji o serwerze. - timeline_preview: Wylogowani użytkownicy będą mogli przeglądać najnowsze publiczne wpisy dostępne na serwerze. trendable_by_default: Pomiń ręczny przegląd treści trendów. Pojedyncze elementy nadal mogą być usuwane z trendów po fakcie. trends: Tendencje pokazują, które posty, hasztagi i newsy zyskują popularność na Twoim serwerze. trends_as_landing_page: Pokaż najpopularniejsze treści niezalogowanym użytkownikom i odwiedzającym zamiast opisu tego serwera. Wymaga włączenia trendów. @@ -301,7 +300,6 @@ pl: status_page_url: Adres URL strony statusu theme: Domyślny motyw thumbnail: Miniaturka serwera - timeline_preview: Zezwalaj na nieuwierzytelniony dostęp do publicznych osi czasu trendable_by_default: Zezwalaj na trendy bez wcześniejszego przeglądu trends: Włącz trendy trends_as_landing_page: Użyj trendów jako strony początkowej diff --git a/config/locales/simple_form.pt-BR.yml b/config/locales/simple_form.pt-BR.yml index fc8d90a86a9..2aa15652d34 100644 --- a/config/locales/simple_form.pt-BR.yml +++ b/config/locales/simple_form.pt-BR.yml @@ -103,7 +103,6 @@ pt-BR: status_page_url: URL de uma página onde as pessoas podem ver o status deste servidor durante uma interrupção theme: Tema que visitantes e novos usuários veem. thumbnail: Uma imagem de aproximadamente 2:1 exibida ao lado da informação de sua instância. - timeline_preview: Visitantes conseguirão navegar pelas postagens públicas mais recentes disponíveis na instância. trendable_by_default: Pular a revisão manual do conteúdo em tendência. Itens individuais ainda poderão ser removidos das tendências após a sua exibição. trends: Tendências mostram quais publicações, hashtags e notícias estão ganhando destaque na sua instância. trends_as_landing_page: Mostrar conteúdo de tendências para usuários deslogados e visitantes em vez de uma descrição deste servidor. Requer que as tendências sejam ativadas. @@ -300,7 +299,6 @@ pt-BR: status_page_url: Endereço da página de status theme: Tema padrão thumbnail: Miniatura do servidor - timeline_preview: Permitir acesso não autenticado às linhas do tempo públicas trendable_by_default: Permitir tendências sem revisão prévia trends: Habilitar tendências trends_as_landing_page: Usar tendências como página inicial diff --git a/config/locales/simple_form.pt-PT.yml b/config/locales/simple_form.pt-PT.yml index 4e5fa12c041..3214690dcd6 100644 --- a/config/locales/simple_form.pt-PT.yml +++ b/config/locales/simple_form.pt-PT.yml @@ -105,7 +105,6 @@ pt-PT: status_page_url: URL de uma página onde as pessoas podem ver o estado deste servidor durante uma interrupção theme: Tema que os visitantes e os novos utilizadores veem. thumbnail: Uma imagem de cerca de 2:1, apresentada ao lado da informação do seu servidor. - timeline_preview: Os visitantes sem sessão iniciada poderão consultar as publicações públicas mais recentes disponíveis no servidor. trendable_by_default: Ignorar a revisão manual do conteúdo em destaque. Os itens individuais poderão ainda assim ser posteriormente removidos das tendências. trends: As tendências mostram quais as publicações, etiquetas e notícias que estão a ganhar destaque no seu servidor. trends_as_landing_page: Mostrar conteúdo em destaque a utilizadores sem sessão iniciada e visitantes, ao invés de uma descrição deste servidor. Requer que os destaques estejam ativados. @@ -302,7 +301,6 @@ pt-PT: status_page_url: URL da página de estado theme: Tema predefinido thumbnail: Miniatura do servidor - timeline_preview: Permitir acesso não autenticado às cronologias públicas trendable_by_default: Permitir tendências sem revisão prévia trends: Ativar destaques trends_as_landing_page: Usar destaques como página de apresentação diff --git a/config/locales/simple_form.ro.yml b/config/locales/simple_form.ro.yml index ae8e2e065c3..3dc6380b6bf 100644 --- a/config/locales/simple_form.ro.yml +++ b/config/locales/simple_form.ro.yml @@ -98,7 +98,6 @@ ro: status_page_url: URL-ul unei pagini unde oamenii pot vedea starea acestui server în timpul unei întreruperi theme: Tema pe care vizitatorii deconectați și utilizatorii noi o văd. thumbnail: O imagine de aproximativ 2:1 afișată alături de informațiile serverului dvs. - timeline_preview: Vizitatorii deconectați vor putea să răsfoiască cele mai recente postări publice disponibile pe server. trendable_by_default: Omiteți revizuirea manuală a conținutului în tendințe. Elementele individuale pot fi în continuare eliminate din tendințe după fapt. trends: Tendințele arată ce postări, hashtag-uri și știri câștigă teren pe serverul dvs. trends_as_landing_page: Afișați conținut în tendințe utilizatorilor deconectați și vizitatorilor în loc de o descriere a acestui server. Necesită ca tendințele să fie activate. diff --git a/config/locales/simple_form.ru.yml b/config/locales/simple_form.ru.yml index cf59942e7fb..c38b545af0b 100644 --- a/config/locales/simple_form.ru.yml +++ b/config/locales/simple_form.ru.yml @@ -102,7 +102,6 @@ ru: status_page_url: URL страницы, на которой люди могут видеть статус этого сервера во время отключения theme: Тема, которую видят вышедшие из системы посетители и новые пользователи. thumbnail: Изображение примерно 2:1, отображаемое рядом с информацией о вашем сервере. - timeline_preview: Посетители, вышедшие из системы, смогут просматривать последние публичные сообщения, имеющиеся на сервере. trendable_by_default: Пропустить ручной просмотр трендового контента. Отдельные элементы могут быть удалены из трендов уже постфактум. trends: Тренды показывают, какие посты, хэштеги и новостные истории набирают обороты на вашем сервере. trends_as_landing_page: Показывать популярный контент для выходов пользователей и посетителей, а не для описания этого сервера. Требует включения тенденций. @@ -296,7 +295,6 @@ ru: status_page_url: Страница уведомлений theme: Тема по умолчанию thumbnail: Изображение сервера - timeline_preview: Разрешить доступ к публичным лентам без авторизации trendable_by_default: Разрешить треды без предварительной проверки trends: Включить тренды trends_as_landing_page: Использовать тенденции в качестве целевой страницы diff --git a/config/locales/simple_form.sco.yml b/config/locales/simple_form.sco.yml index 1a08061dcc1..6a22045fbd6 100644 --- a/config/locales/simple_form.sco.yml +++ b/config/locales/simple_form.sco.yml @@ -77,7 +77,6 @@ sco: site_title: Hou fowk kin refer tae yer server asides its domain nemm. theme: Theme thit logged oot visitors an new uisers see. thumbnail: A rochly 2:1 image displayit alangsides yer server information. - timeline_preview: Logged oot visitors wull be able tae broose the maist recent public posts available on the server. trendable_by_default: Jouk the review bi haun o trendin content. Individual items kin stull get taen aff trends efter the fact. trends: Trends shaw whit posts, hashtags an news stories is gettin traction on yer server. form_challenge: @@ -227,7 +226,6 @@ sco: site_title: Server nemm theme: Defaut theme thumbnail: Server thoomnail - timeline_preview: Alloo unauthenticated access tae public timelines trendable_by_default: Alloo trends athoot prior review trends: Turn on trends interactions: diff --git a/config/locales/simple_form.si.yml b/config/locales/simple_form.si.yml index 8aac332bf22..6c47c4005e9 100644 --- a/config/locales/simple_form.si.yml +++ b/config/locales/simple_form.si.yml @@ -102,7 +102,6 @@ si: status_page_url: ඇනහිටීමක් අතරතුර මෙම සේවාදායකයේ තත්ත්වය මිනිසුන්ට දැකිය හැකි පිටුවක URL එක theme: අමුත්තන් ලොග් අවුට් කළ සහ නව පරිශීලකයින් දකින තේමාව. thumbnail: ඔබගේ සේවාදායක තොරතුරු සමඟ ආසන්න වශයෙන් 2:1 රූපයක් දර්ශනය වේ. - timeline_preview: ලොග් අවුට් වූ අමුත්තන්ට සේවාදායකයේ ඇති නවතම පොදු සටහන් බ්‍රවුස් කිරීමට හැකි වනු ඇත. trendable_by_default: ප්‍රවණතා අන්තර්ගතයන් අතින් සමාලෝචනය කිරීම මඟ හරින්න. කාරණයෙන් පසුවත් තනි අයිතම ප්‍රවණතා වලින් ඉවත් කළ හැකිය. trends: ප්‍රවණතා මඟින් ඔබේ සේවාදායකයේ ආකර්ෂණය ලබා ගන්නා පළ කිරීම්, හැෂ් ටැග් සහ ප්‍රවෘත්ති කථා පෙන්වයි. trends_as_landing_page: මෙම සේවාදායකයේ විස්තරයක් වෙනුවට පිටව ගිය පරිශීලකයින්ට සහ අමුත්තන්ට ප්‍රවණතා අන්තර්ගතය පෙන්වන්න. ප්‍රවණතා සක්‍රීය කිරීම අවශ්‍ය වේ. @@ -290,7 +289,6 @@ si: status_page_url: තත්ව පිටු URL එක theme: පෙරනිමි තේමාව thumbnail: සේවාදායක සිඟිති රුව - timeline_preview: පොදු කාලරේඛා වෙත සත්‍යාපනය නොකළ ප්‍රවේශයට ඉඩ දෙන්න. trendable_by_default: පූර්ව සමාලෝචනයකින් තොරව ප්‍රවණතා වලට ඉඩ දෙන්න. trends: ප්‍රවණතා සක්‍රීය කරන්න trends_as_landing_page: ගොඩබෑමේ පිටුව ලෙස ප්‍රවණතා භාවිතා කරන්න diff --git a/config/locales/simple_form.sk.yml b/config/locales/simple_form.sk.yml index b6896c73e18..7db8fa67e24 100644 --- a/config/locales/simple_form.sk.yml +++ b/config/locales/simple_form.sk.yml @@ -2,12 +2,21 @@ sk: simple_form: hints: + account: + attribution_domains: Jeden na riadok. Chráni vás pred falošným pripisovaním autorstva. + discoverable: Vaše verejné príspevky a profil môžu byť zobrazované a odporúčané v rôznych častiach Mastodonu a váš profil môže byť navrhovaný ostatným. + display_name: Vaše meno a priezvisko alebo prezývka. + fields: Váš web, zámená, vek, čokoľvek, čo chcete o sebe uviesť. + indexable: Vaše verejné príspevky sa môžu zobrazovať vo výsledkoch vyhľadávania na Mastodone. Ľudia, ktorí s nimi interagovali, ich môžu nájsť vždy. + note: 'Môžete @označiť iných ľudí alebo #hashtagy.' + show_collections: Ľudia si budú môcť prezrieť, ktoré účty sledujete a ktoré účty sledujú vás. Ľudia, ktorých sledujete, o tom budú vždy vedieť. + unlocked: Ľudia vás budú môcť sledovať bez vášho schválenia. Zrušenie vám dá možnosť kontrolovať žiadosti o sledovanie a rozhodovať sa o prijímaní alebo zamietaní nových sledujúcich. account_alias: acct: Urči prezyvku@domenu účtu, s ktorého sa chceš presunúť account_migration: acct: Urči prezyvku@domenu účtu, na ktorý sa chceš presunúť account_warning_preset: - text: Môžeš používať rovnakú syntaxiu ako v rámci príspevkov, čiže URL, haštagy, a spomenutia + text: Môžete používať syntax príspevk, ako sú adresy URL, hashtagy a označenia admin_account_action: include_statuses: Užívateľ uvidí, ktoré príspevky majú za následok moderačný zásah, alebo upozornenie send_email_notification: Užívateľ dostane vysvetlenie ohľadom toho, čo sa stalo s ich účtom @@ -17,29 +26,37 @@ sk: defaults: autofollow: Ľudia ktorí sa zaregistrujú prostredníctvom pozvánky, ťa budú inheď nasledovať avatar: WEBP, PNG, GIF, alebo JPG. Najviac %{size}. Bude zmenšený na %{dimensions}px - bot: Tento účet vykonáva hlavne automatizované akcie, a je pravdepodobne nespravovaný + bot: Tento účet vykonáva hlavne automatizované akcie a je pravdepodobne nespravovaný context: Jedno, alebo viac kritérií, v ktorých má byť filtrovanie uplatnené current_password: Z bezpečtnostných dôvodov prosím zadaj heslo súčasného účtu current_username: Pre potvrdenie prosím zadaj prezývku súčasného účtu digest: Odoslané iba v prípade dlhodobej neprítomnosti, a len ak si obdržal/a nejaké osobné správy kým si bol/a preč - email: Bude ti odoslaný potvrdzujúci email + email: Odošleme vám potvrdzujúci e-mail header: WEBP, PNG, GIF, alebo JPG. Najviac %{size}. Bude zmenšený na %{dimensions}px inbox_url: Skopíruj adresu z hlavnej stránky mostíka, ktorý chceš používať - irreversible: Vytriedené príspevky zmiznú nenávratne, aj keď triedenie neskôr zrušíš - locale: Jazyk užívateľského rozhrania, emailových, a nástenkových oboznámení - password: Zadaj aspoň osem znakov + irreversible: Filtrované príspevky nenávratne zmiznú, aj keď filter neskôr zrušíte + locale: Jazyk používateľského rozhrania, e-mailových a push upozornení + password: Heslo musí obsahovať aspoň 8 znakov phrase: Zhoda sa nájde nezávisle od toho, či je text napísaný, veľkými, alebo malými písmenami, či už v tele, alebo v hlavičke scopes: Ktoré API budú povolené aplikácii pre prístup. Ak vyberieš vrcholný stupeň, nemusíš už potom vyberať po jednom. - setting_aggregate_reblogs: Nezobrazuj nové vyzdvihnutia pre príspevky, ktoré už boli len nedávno povýšené (týka sa iba nanovo získaných povýšení) - setting_default_sensitive: Chúlostivé médiá sú štandardne ukryté, a môžu byť zobrazené kliknutím - setting_display_media_default: Ukry médiá označené ako chúlostivé - setting_display_media_hide_all: Vždy ukry všetky médiá - setting_display_media_show_all: Vždy zobrazuj médiá - setting_use_blurhash: Prechody sú založené na farbách skrytých vizuálov, ale zahaľujú akékoľvek podrobnosti - setting_use_pending_items: Skry aktualizovanie časovej osi tak, aby bola načitávaná iba po kliknutí, namiesto samostatného posúvania + setting_aggregate_reblogs: Nezobrazovať nové zdieľania pre nedávno zdieľané príspevky (týka sa iba nových zdieľaní) + setting_always_send_emails: Pri bežnom používaní Mastodonu nebudete dostávať e-mailové upozornenia + setting_default_sensitive: Citlivé médiá sú predvolene ukryté a môžu byť zobrazené kliknutím + setting_display_media_default: Skrývať médiá označené ako citlivé + setting_display_media_hide_all: Vždy skrývať médiá + setting_display_media_show_all: Vždy zobrazovať médiá + setting_system_scrollbars_ui: Platí len pre počítačové prehliadače využívajúce technológiu Chrome alebo Safari + setting_use_blurhash: Prechody sú založené na farbách skrytých vizuálov, ale skrývajú akékoľvek podrobnosti + setting_use_pending_items: Časová os bude aktualizovaná až po kliknutí, feed sa nebúde posúvať automaticky whole_word: Ak je kľúčové slovo, alebo fráza poskladaná iba s písmen a čísel, bude použité iba ak sa zhoduje s celým výrazom domain_allow: domain: Táto doména bude schopná získavať dáta z tohto servera, a prichádzajúce dáta ním budú spracovávané a uložené + featured_tag: + name: 'Nedávno ste použili napríklad tieto hashtagy:' + form_admin_settings: + site_contact_email: Spôsob, ako vás môžu ľudia kontaktovať pre právne účely alebo podporu. + site_contact_username: Ako vás môžu ľudia na Mastodone nájsť. + thumbnail: 'Obrázok v pomere približne 2 : 1, ktorý sa zobrazí pri informáciách o serveri.' form_challenge: current_password: Vstupuješ do zabezpečenej časti imports: @@ -51,16 +68,23 @@ sk: sign_up_block: Nové registrácie nebudú možné sessions: otp: 'Napíš sem dvoj-faktorový kód z telefónu, alebo použi jeden z tvojích obnovovacích kódov:' + settings: + indexable: Váš profil sa môže zobraziť vo výsledkoch vyhľadávania cez Google, Bing a ďalšie. + show_application: Tebe sa táto informácia zobrazí vždy. tag: name: Zmeniť môžeš iba veľkosť písmen, napríklad aby boli ľahšie čítateľné user: - chosen_languages: Keď je zaškrtnuté, vo verejnej osi budú zobrazené iba príspevky vo vybraných jazykoch + chosen_languages: Po zaškrtnutí budú na verejných časových osiach zobrazované iba príspevky vo vybraných jazykoch labels: account: + attribution_domains: Weby, ktoré vám môžu pripisovať autorstvo + discoverable: Zobrazovať profil a príspevky v objavovacích algoritmoch fields: - name: Označenie - value: Obsah - unlocked: Automaticky prijímaj nových nasledovateľov + name: Definícia + value: Hodnota + indexable: Zobrazovať verejné príspevky vo vyhľadávaní + show_collections: Zobrazovať v profile sledované a sledujúce účty + unlocked: Automaticky schvaľovať nové sledovania account_alias: acct: Adresa starého účtu account_migration: @@ -77,7 +101,7 @@ sk: disable: Deaktivuj none: Neurob nič silence: Utíš - suspend: Vylúč a nenávratne vymaž dáta na účte + suspend: Vylúčiť warning_preset_id: Použi varovnú predlohu announcement: all_day: Celodenná udalosť @@ -86,19 +110,19 @@ sk: text: Oboznámenie defaults: autofollow: Pozvi k následovaniu tvojho profilu - avatar: Maskot + avatar: Profilová fotka bot: Toto je automatizovaný bot účet - chosen_languages: Filtruj jazyky - confirm_new_password: Znovu tvoje nové heslo, pre potvrdenie + chosen_languages: Filtrovanie jazykov + confirm_new_password: Overenie nového hesla confirm_password: Over heslo - context: Triedenie kontextov + context: Kontexty filtra current_password: Súčasné heslo data: Dáta display_name: Zobrazované meno - email: Emailová adresa + email: E-mailová adresa expires_in: Expiruj po fields: Metadáta profilu - header: Obrázok v hlavičke + header: Obrázok v záhlaví inbox_url: URL adresa prechodnej schránky irreversible: Zahoď, namiesto ukrytia locale: Jazyk rozhrania @@ -108,25 +132,31 @@ sk: otp_attempt: Dvoj-faktorový overovací kód password: Heslo phrase: Kľúčové slovo, alebo fráza - setting_advanced_layout: Zapni pokročilé užívateľské rozhranie - setting_aggregate_reblogs: Zoskupuj vyzdvihnutia v časovej osi - setting_auto_play_gif: Automaticky prehrávaj animované GIFy - setting_boost_modal: Zobrazuj potvrdzovacie okno pred povýšením - setting_default_language: Píšeš v jazyku - setting_default_sensitive: Označ všetky mediálne súbory ako chúlostivé - setting_delete_modal: Zobrazuj potvrdzovacie okno pred vymazaním toot-u + setting_advanced_layout: Zapnúť pokročilé používateľské rozhranie + setting_aggregate_reblogs: Zoskupovať zdieľania na časových osiach + setting_always_send_emails: Vždy posielať e-mailové upozornenia + setting_auto_play_gif: Automaticky prehrávať animácie GIF + setting_boost_modal: Zobrazovať potvrdzovacie okno pred zdieľaním + setting_default_language: Jazyk príspevkov + setting_default_quote_policy: Kto vás môže citovať + setting_default_sensitive: Vždy označovať médiá ako citlivé + setting_delete_modal: Zobrazovať potvrdzovacie okno pred vymazaním príspevku + setting_disable_hover_cards: Vypnúť náhľady profilov pri ukázaní kurzorom + setting_disable_swiping: Vypnúť gestá posúvaním setting_display_media: Zobrazovanie médií setting_display_media_default: Štandard setting_display_media_hide_all: Ukry všetky setting_display_media_show_all: Ukáž všetky - setting_expand_spoilers: Stále rozbaľ príspevky označené varovaním o chúlostivom obsahu + setting_expand_spoilers: Stále rozbaľovať príspevky označené varovaním o obsahu setting_hide_network: Ukry svoju sieť kontaktov - setting_reduce_motion: Mierni pohyb pri animáciách - setting_system_font_ui: Použi základné systémové písmo + setting_missing_alt_text_modal: Zobrazovať potvrdzovacie okno pred uverejnením média bez opisu + setting_reduce_motion: Stlmiť animácie + setting_system_font_ui: Používať predvolené písmo systému + setting_system_scrollbars_ui: Používať predvolený posuvník systému setting_theme: Vzhľad webu - setting_trends: Ukáž dnešné trendy + setting_trends: Zobrazovať dnešné trendy setting_unfollow_modal: Vyžaduj potvrdenie pred tým, než niekoho prestaneš sledovať - setting_use_blurhash: Ukáž farebné prechody pre skryté médiá + setting_use_blurhash: Zobrazovať farebné prechody skrytých médií setting_use_pending_items: Pomalý režim severity: Závažnosť sign_in_token_attempt: Bezpečnostný kód @@ -135,10 +165,11 @@ sk: username_or_email: Prezývka, alebo email whole_word: Celé slovo featured_tag: - name: Haštag + name: Hashtag form_admin_settings: peers_api_enabled: Zverejni zoznam objavených serverov v API status_page_url: URL adresa stránky stavu + thumbnail: Náhľad servera interactions: must_be_follower: Blokuj oboznámenia od užívateľov, ktorí ma nenasledujú must_be_following: Blokuj oboznámenia od ľudí, ktorých nesledujem @@ -153,17 +184,32 @@ sk: sign_up_requires_approval: Obmedz registrácie severity: Pravidlo notification_emails: + appeal: Niekto sa odvoláva voči moderátorskému rozhodnutiu digest: Zasielať súhrnné emaily - favourite: Zaslať email, ak si niekto obľúbi tvoj príspevok - follow: Niekto ťa začal nasledovať - follow_request: Zaslať email, ak ti niekto pošle žiadosť o sledovanie - mention: Zaslať email, ak ťa niekto spomenie vo svojom príspevku - pending_account: Zaslať email, ak treba prehodnotiť nový účet - reblog: Zaslať email, ak niekto re-tootne tvoj príspevok + favourite: Niekto ohviezdičkuje váš príspevok + follow: Niekto vás začal sledovať + follow_request: Niekto vám posiela žiadosť o sledovanie + mention: Niekto vás označí + pending_account: Je potrebná kontrola nového účtu + quote: Niekto vás cituje + reblog: Niekto zdieľa váš príspevok + report: Niekto niečo nahlásil + software_updates: + all: Upozorňovať na všetky novinky + critical: Upozorňovať iba na kritické novinky + label: Je dostupná nová verzia Mastodonu + none: Nikdy neupozorňovať na novinky (neodporúčané) + patch: Upozorňovať na novinky s riešením chýb + trending_tag: Je potrebné skontrolovať nový trend + settings: + indexable: Zobrazovať profil v internetových vyhľadávačoch + show_application: Zobrazovať apku, z ktorej sú uverejňované príspevky tag: - listable: Povoľ zobrazovanie tohto haštagu v návrhoch vyhľadávaní - name: Haštag - trendable: Povoľ zobrazovanie tohto haštagu medzi trendujúcimi + listable: Povoliť zobrazovanie tohto hashtagu v návrhoch vyhľadávaní + name: Hashtag + trendable: Povoliť zobrazovanie tohto hashtagu medzi trendujúcimi + user: + time_zone: Časové pásmo 'no': Nie recommended: Odporúčané required: diff --git a/config/locales/simple_form.sl.yml b/config/locales/simple_form.sl.yml index 9a2850119cd..2894a2665e2 100644 --- a/config/locales/simple_form.sl.yml +++ b/config/locales/simple_form.sl.yml @@ -101,7 +101,6 @@ sl: status_page_url: URL strani, kjer je moč videti stanje tega strežnika med prekinjenim delovanjem theme: Tema, ki jo vidijo odjavljeni obiskovalci in novi uporabniki. thumbnail: Slika v razmerju stranic približno 2:1, prikazana vzdolž podatkov o vašem strežniku. - timeline_preview: Odjavljeni obiskovalci bodo lahko brskali po najnovejših javnih objavah, ki so na voljo na strežniku. trendable_by_default: Preskočite ročni pregled vsebine v trendu. Posamezne elemente še vedno lahko odstranite iz trenda post festum. trends: Trendi prikažejo, katere objave, ključniki in novice privlačijo zanimanje na vašem strežniku. trends_as_landing_page: Odjavljenim uporabnikom in obiskovalcem namesto opisa tega strežnika pokažite vsebine v trendu. Trendi morajo biti omogočeni. @@ -286,7 +285,6 @@ sl: status_page_url: URL strani stanja theme: Privzeta tema thumbnail: Sličica strežnika - timeline_preview: Omogoči neoverjen dostop do javnih časovnic trendable_by_default: Dovoli trende brez predhodnega pregleda trends: Omogoči trende trends_as_landing_page: Uporabi trende za pristopno stran diff --git a/config/locales/simple_form.sq.yml b/config/locales/simple_form.sq.yml index ad26b87a5aa..dee0d44a636 100644 --- a/config/locales/simple_form.sq.yml +++ b/config/locales/simple_form.sq.yml @@ -56,6 +56,8 @@ sq: scopes: Cilat API do të lejohen të përdorin aplikacioni. Nëse përzgjidhni një shkallë të epërme, nuk ju duhet të përzgjidhni individualet një nga një. setting_aggregate_reblogs: Mos shfaq përforcime të reja për mesazhe që janë përforcuar tani së fundi (prek vetëm përforcime të marra rishtas) setting_always_send_emails: Normalisht s’do të dërgohen njoftime, kur përdorni aktivisht Mastodon-in + setting_default_quote_policy_private: Në Mastodon s’mund të citohen nga të tjerë postim Vetëm-për-ndjekësit. + setting_default_quote_policy_unlisted: Kur njerëzit ju citojnë, nga rrjedha kohore e gjërave në modë do të kalohen si të fshehura edhe postimet e tyre. setting_default_sensitive: Media rezervat fshihet, si parazgjedhje, dhe mund të shfaqet me një klikim setting_display_media_default: Fshih media me shenjën rezervat setting_display_media_hide_all: Fshih përherë mediat @@ -102,7 +104,6 @@ sq: status_page_url: URL e faqe ku njerëzit mund të shohin gjendjen e këtij shërbyesi, gjatë një ndërprerje të funksionimit theme: Temë që shohin vizitorët që kanë bërë daljen dhe përdorues të rinj. thumbnail: Një figurë afërsisht 2:1 e shfaqur tok me hollësi mbi shërbyesin tuaj. - timeline_preview: Vizitorët që kanë bërë daljen do të jenë në gjendje të shfletojnë postimet më të freskëta publike të passhme në shërbyes. trendable_by_default: Anashkalo shqyrtim dorazi lënde në modë. Gjëra individuale prapë mund të hiqen nga lëndë në modë pas publikimi. trends: Gjërat në modë shfaqin cilat postime, hashtagë dhe histori të reja po tërheqin vëmendjen në shërbyesin tuaj. trends_as_landing_page: Shfaq lëndë në modë për përdorues jo të futur në llogari dhe për vizitorë, në vend se të një përshkrimi të këtij shërbyesi. Lyp që të jenë të aktivizuara gjërat në modë. @@ -141,12 +142,16 @@ sq: arbitration_address: Mund të jetë e njëjtë me adresën Fizike më sipër, ose “N/A”, nëse përdoret email. arbitration_website: Mund të jetë një formular web, ose “N/A”, nëse përdoret email. choice_of_law: Qytet, rajon, territor ose shtet, ligjet e brendshme të të cilit do të administrojnë çfarëdo dhe tërë pretendimet. + dmca_address: Për operatorë në ShBA, përdorni adresën e regjistruar te DMCA Designated Agent Directory. Regjistrimi me A P.O. Box bëhet me kërkesë të drejtpërdrejtë, përdorni DMCA Designated Agent Post Office Box Waiver Request që t’i dërgoni email Copyright Office-it dhe t’i përshkruani se jeni një moderator shtëpiak lënde që ka frikë nga hakmarrje apo ndëshkim për veprimet tuaja dhe që ka nevojë të përdor një P.O. Box për heqjen e adresës së shtëpisë tuaj nga sytë e publikut. dmca_email: Mund të jetë i njëjti email i përdorur për “Adresë email për njoftime ligjore” më sipër. domain: Identifikues unik për shërbimin internetor që po ofroni. jurisdiction: Vendosni vendin ku jeton cilido që paguan faturat. Nëse është një shoqëri apo tjetër njësi, vendosni vendin ku është regjistruar, si dhe qytetin, rajonin, territorin apo shtetin përkatës. min_age: S’duhet të jetë nën moshën minimum të domosdoshme nga ligjet në juridiksionin tuaj. user: chosen_languages: Në iu vëntë shenjë, te rrjedha kohore publike do të shfaqen vetëm mesazhe në gjuhët e përzgjedhura + date_of_birth: + one: Na duhet të sigurohemi se jeni të paktën %{count} që të përdorni %{domain}. S’do ta depozitojmë këtë. + other: Na duhet të sigurohemi se jeni të paktën %{count} që të përdorni %{domain}. S’do ta depozitojmë këtë. role: Roli kontrollon cilat leje ka përdoruesi. user_role: color: Ngjyrë për t’u përdorur për rolin nëpër UI, si RGB në format gjashtëmbëdhjetësh @@ -154,6 +159,10 @@ sq: name: Emër publik për rolin, nëse roli është ujdisur të shfaqet si një stemë permissions_as_keys: Përdoruesit me këtë rol do të mund të… position: Role më të lartë vendosin zgjidhje përplasje në disa raste. Disa veprime mund të kryhen vetëm mbi role të një shkalle më të ulët + username_block: + allow_with_approval: Në vend të pengimit aty për aty të regjistrimit, regjistrime me përkim do të duan miratimin tuaj + comparison: Ju lutemi, mbani parasysh Problemin Scunthorpe, kur bllokohen përkime të pjesshme + username: Do të merret si përkim, pavarësisht shkrimit me të mëdha apo të vogla dhe pavarësisht homoglifesh të tilla si "4" për "a", ose "3" për "e" webhook: events: Përzgjidhni akte për dërgim template: Hartoni ngarkesë tuajën JSON, duke përdorur ndërkëmbim ndryshoresh. Lëreni të zbrazët, për JSON-in parazgjedhje. @@ -226,6 +235,7 @@ sq: setting_auto_play_gif: Vetëluaji GIF-et e animuar setting_boost_modal: Shfaq dialog ripohimi përpara përforcimi setting_default_language: Gjuhë postimi + setting_default_privacy: Dukshmëri postimi setting_default_quote_policy: Cilët mund të citojnë setting_default_sensitive: Mediave vëru përherë shenjë si rezervat setting_delete_modal: Shfaq dialog ripohimi përpara fshirjes së një mesazhi @@ -235,6 +245,7 @@ sq: setting_display_media_default: Parazgjedhje setting_display_media_hide_all: Fshihi krejt setting_display_media_show_all: Shfaqi krejt + setting_emoji_style: Stil emoji-sh setting_expand_spoilers: Mesazhet me sinjalizime mbi lëndën, zgjeroji përherë setting_hide_network: Fshiheni rrjetin tuaj setting_missing_alt_text_modal: Shfaq dialog ripohimi, para postimi mediash pa tekst alternativ @@ -271,12 +282,16 @@ sq: content_cache_retention_period: Periudhë mbajtjeje lënde të largët custom_css: CSS Vetjake favicon: Favikonë + local_live_feed_access: Hyrje te prurje të atypëratyshme që përmbajnë postime vendore + local_topic_feed_access: Hyrje te prurje hashtag-ësh dhe lidhjesh që përmbajnë postime vendore mascot: Simbol vetjak (e dikurshme) media_cache_retention_period: Periudhë mbajtjeje lënde media min_age: Domosdosmëri moshe minimum peers_api_enabled: Publiko te API listë shërbyesish të zbuluar profile_directory: Aktivizo drejtori profilesh registrations_mode: Kush mund të regjistrohet + remote_live_feed_access: Hyrje te prurje të atypëratyshme që përmbajnë postime nga larg + remote_topic_feed_access: Hyrje te prurje hashtag-ësh dhe lidhjesh që përmbajnë postime nga larg require_invite_text: Kërko një arsye për pjesëmarrje show_domain_blocks: Shfaq bllokime përkatësish show_domain_blocks_rationale: Shfaq pse janë bllokuar përkatësitë @@ -289,7 +304,6 @@ sq: status_page_url: URL faqeje gjendjesh theme: Temë parazgjedhje thumbnail: Miniaturë shërbyesi - timeline_preview: Lejo hyrje pa mirëfilltësim te rrjedha kohore publike trendable_by_default: Lejoni gjëra në modë pa shqyrtim paraprak trends: Aktivizo gjëra në modë trends_as_landing_page: Përdor gjërat në modë si faqe hyrëse @@ -317,6 +331,7 @@ sq: follow_request: Dikush kërkoi t’ju ndjekë mention: Dikush ju përmendi pending_account: Llogaria e re lyp shqyrtim + quote: Dikush ju citoi reblog: Dikush përforcoi gjendjen tuaj report: Parashtrohet raportim i ri software_updates: @@ -363,6 +378,10 @@ sq: name: Emër permissions_as_keys: Leje position: Përparësi + username_block: + allow_with_approval: Lejo regjistrim me miratim + comparison: Metodë krahasimi + username: Fjalë për t’u vëzhguar webhook: events: Akte të aktivizuar template: Gjedhe ngarkese diff --git a/config/locales/simple_form.sr-Latn.yml b/config/locales/simple_form.sr-Latn.yml index 213075e6b43..1a8f2b13ed2 100644 --- a/config/locales/simple_form.sr-Latn.yml +++ b/config/locales/simple_form.sr-Latn.yml @@ -97,7 +97,6 @@ sr-Latn: status_page_url: URL stranice gde ljudi mogu da vide status servera dok je server oboren theme: Tema koju vide posetioci koji nisu prijavljeni i novi korisnici. thumbnail: Slika u razmeri od približno 2:1 koja se prikazuje pored informacija o Vašem serveru. - timeline_preview: Posetioci koji nisu prijavljeni će moći da pregledaju najnovije javne objave dostupne na serveru. trendable_by_default: Preskoči ručni pregled sadržaja koji je u trendu. Pojedinačne stavke se nakon toga i dalje mogu ukloniti iz trendova. trends: Trendovi pokazuju koje objave, heš oznake i vesti postaju sve popularnije na Vašem serveru. trends_as_landing_page: Prikaži sadržaj u trendu odjavljenim korisnicima i posetiocima umesto opisa ovog servera. Zahteva da trendovi budu omogućeni. @@ -264,7 +263,6 @@ sr-Latn: status_page_url: URL statusne stranice theme: Podrazumevana tema thumbnail: Sličica servera - timeline_preview: Dozvoli neautorizovan pristup javnim vremenskim osama trendable_by_default: Dozvoli trendove bez prethodnog pregleda trends: Omogući trendove trends_as_landing_page: Koristite trendove kao stranicu dočeka diff --git a/config/locales/simple_form.sr.yml b/config/locales/simple_form.sr.yml index 96c5732ebdb..ad3b0f60b5a 100644 --- a/config/locales/simple_form.sr.yml +++ b/config/locales/simple_form.sr.yml @@ -97,7 +97,6 @@ sr: status_page_url: URL странице где људи могу да виде статус сервера док је сервер оборен theme: Тема коју виде посетиоци који нису пријављени и нови корисници. thumbnail: Слика у размери од приближно 2:1 која се приказује поред информација о Вашем серверу. - timeline_preview: Посетиоци који нису пријављени ће моћи да прегледају најновије јавне објаве доступне на серверу. trendable_by_default: Прескочи ручни преглед садржаја који је у тренду. Појединачне ставке се након тога и даље могу уклонити из трендова. trends: Трендови показују које објаве, хеш ознаке и вести постају све популарније на Вашем серверу. trends_as_landing_page: Прикажи садржај у тренду одјављеним корисницима и посетиоцима уместо описа овог сервера. Захтева да трендови буду омогућени. @@ -264,7 +263,6 @@ sr: status_page_url: URL статусне странице theme: Подразумевана тема thumbnail: Сличица сервера - timeline_preview: Дозволи неауторизован приступ јавним временским осама trendable_by_default: Дозволи трендове без претходног прегледа trends: Омогући трендове trends_as_landing_page: Користите трендове као страницу дочека diff --git a/config/locales/simple_form.sv.yml b/config/locales/simple_form.sv.yml index c4be2a70908..4eba2503572 100644 --- a/config/locales/simple_form.sv.yml +++ b/config/locales/simple_form.sv.yml @@ -103,7 +103,6 @@ sv: status_page_url: URL till en sida där personer kan se serverns status under ett driftavbrott theme: Tema som utloggade besökare och nya användare ser. thumbnail: En bild i cirka 2:1-proportioner som visas tillsammans med din serverinformation. - timeline_preview: Utloggade besökare kommer kunna bläddra bland de senaste offentliga inläggen som finns på servern. trendable_by_default: Hoppa över manuell granskning av trendande innehåll. Enskilda objekt kan ändå raderas från trender retroaktivt. trends: Trender visar vilka inlägg, hashtaggar och nyheter det pratas om på din server. trends_as_landing_page: Visa trendande innehåll för utloggade användare och besökare istället för en beskrivning om servern. Kräver att trender är aktiverat. @@ -299,7 +298,6 @@ sv: status_page_url: URL för statussida theme: Standardtema thumbnail: Serverns tumnagelbild - timeline_preview: Tillåt oautentiserad åtkomst till offentliga tidslinjer trendable_by_default: Tillåt trender utan föregående granskning trends: Aktivera trender trends_as_landing_page: Använd trender som landningssida diff --git a/config/locales/simple_form.th.yml b/config/locales/simple_form.th.yml index 8ec163d433e..5246e8baf54 100644 --- a/config/locales/simple_form.th.yml +++ b/config/locales/simple_form.th.yml @@ -99,7 +99,6 @@ th: status_page_url: URL ของหน้าที่ผู้คนสามารถเห็นสถานะของเซิร์ฟเวอร์นี้ในระหว่างการหยุดทำงาน theme: ชุดรูปแบบที่ผู้เยี่ยมชมที่ออกจากระบบและผู้ใช้ใหม่เห็น thumbnail: แสดงภาพ 2:1 โดยประมาณควบคู่ไปกับข้อมูลเซิร์ฟเวอร์ของคุณ - timeline_preview: ผู้เยี่ยมชมที่ออกจากระบบจะสามารถเรียกดูโพสต์สาธารณะล่าสุดที่มีในเซิร์ฟเวอร์ trendable_by_default: ข้ามการตรวจทานเนื้อหาที่กำลังนิยมด้วยตนเอง ยังคงสามารถเอารายการแต่ละรายการออกจากแนวโน้มได้หลังจากเกิดเหตุ trends: แนวโน้มแสดงว่าโพสต์, แฮชแท็ก และเรื่องข่าวใดกำลังได้รับความสนใจในเซิร์ฟเวอร์ของคุณ trends_as_landing_page: แสดงเนื้อหาที่กำลังนิยมแก่ผู้ใช้และผู้เยี่ยมชมที่ออกจากระบบแทนที่จะเป็นคำอธิบายของเซิร์ฟเวอร์นี้ ต้องมีการเปิดใช้งานแนวโน้ม @@ -270,7 +269,6 @@ th: status_page_url: URL ของหน้าสถานะ theme: ชุดรูปแบบเริ่มต้น thumbnail: ภาพขนาดย่อเซิร์ฟเวอร์ - timeline_preview: อนุญาตการเข้าถึงเส้นเวลาสาธารณะที่ไม่ได้รับรองความถูกต้อง trendable_by_default: อนุญาตแนวโน้มโดยไม่มีการตรวจทานล่วงหน้า trends: เปิดใช้งานแนวโน้ม trends_as_landing_page: ใช้แนวโน้มเป็นหน้าเริ่มต้น diff --git a/config/locales/simple_form.tr.yml b/config/locales/simple_form.tr.yml index 9901691c9ec..eed2a95ef69 100644 --- a/config/locales/simple_form.tr.yml +++ b/config/locales/simple_form.tr.yml @@ -105,7 +105,6 @@ tr: status_page_url: İnsanların bir kesinti halinde sunucunun durumunu görebilecekleri bir sayfanın URL'si theme: Giriş yapmamış ziyaretçilerin ve yeni kullanıcıların gördüğü tema. thumbnail: Sunucu bilginizin yanında gösterilen yaklaşık 2:1'lik görüntü. - timeline_preview: Giriş yapmamış ziyaretçiler, sunucuda mevcut olan en son genel gönderileri tarayabilecekler. trendable_by_default: Öne çıkan içeriğin elle incelenmesini atla. Tekil öğeler sonrada öne çıkanlardan kaldırılabilir. trends: Öne çıkanlar, sunucunuzda ilgi toplayan gönderileri, etiketleri ve haber yazılarını gösterir. trends_as_landing_page: Giriş yapmış kullanıcılar ve ziyaretçilere sunucunun açıklması yerine öne çıkan içeriği göster. Öne çıkanların etkin olması gerekir. @@ -284,12 +283,16 @@ tr: content_cache_retention_period: Uzak içerik saklama süresi custom_css: Özel CSS favicon: Yer imi simgesi + local_live_feed_access: Yerel gönderileri ön plana çıkaran canlı akışlara erişim + local_topic_feed_access: Yerel gönderileri ön plana çıkaran etiket ve bağlantı akışlarına erişim mascot: Özel maskot (eski) media_cache_retention_period: Medya önbelleği saklama süresi min_age: Azami yaş gereksinimi peers_api_enabled: API'de keşfedilen sunucuların listesini yayınla profile_directory: Profil dizinini etkinleştir registrations_mode: Kim kaydolabilir + remote_live_feed_access: Uzaktan gönderileri ön plana çıkaran canlı akışlara erişim + remote_topic_feed_access: Uzaktan gönderileri ön plana çıkaran etiket ve bağlantı akışlarına erişim require_invite_text: Katılmak için bir gerekçe iste show_domain_blocks: Engellenen alan adlarını göster show_domain_blocks_rationale: Alan adlarının neden engellendiğini göster @@ -302,7 +305,6 @@ tr: status_page_url: Durum sayfası URL'si theme: Öntanımlı tema thumbnail: Sunucu küçük resmi - timeline_preview: Genel zaman çizelgelerine yetkisiz erişime izin ver trendable_by_default: Ön incelemesiz öne çıkanlara izin ver trends: Öne çıkanları etkinleştir trends_as_landing_page: Giriş sayfası olarak öne çıkanları kullan diff --git a/config/locales/simple_form.uk.yml b/config/locales/simple_form.uk.yml index 017e041ecda..abcf8e18d4e 100644 --- a/config/locales/simple_form.uk.yml +++ b/config/locales/simple_form.uk.yml @@ -102,7 +102,6 @@ uk: status_page_url: URL сторінки, на якій люди можуть бачити статус цього сервера під час його збою в роботі theme: Тема, яку бачать відвідувачі, що вийшли з системи, та нові користувачі. thumbnail: Зображення приблизно 2:1, що показується поряд з відомостями про ваш сервер. - timeline_preview: Зареєстровані відвідувачі зможуть переглядати останні публічні дописи, доступні на сервері. trendable_by_default: Пропустити ручний огляд популярних матеріалів. Індивідуальні елементи все ще можна вилучити з популярних постфактум. trends: Популярні показують, які дописи, хештеґи та новини набувають популярності на вашому сервері. trends_as_landing_page: Показувати популярні матеріали для зареєстрованих користувачів і відвідувачів замість опису цього сервера. Для активації потрібні тренди. @@ -288,7 +287,6 @@ uk: status_page_url: URL сторінки статусу theme: Стандартна тема thumbnail: Мініатюра сервера - timeline_preview: Дозволити неавтентифікований доступ до публічних стрічок trendable_by_default: Дозволити популярне без попереднього огляду trends: Увімкнути популярні trends_as_landing_page: Використовуйте тенденції як цільову сторінку diff --git a/config/locales/simple_form.vi.yml b/config/locales/simple_form.vi.yml index e7e308a1b0e..0711711e5d7 100644 --- a/config/locales/simple_form.vi.yml +++ b/config/locales/simple_form.vi.yml @@ -105,7 +105,6 @@ vi: status_page_url: URL của trang nơi mọi người có thể xem trạng thái của máy chủ này khi ngừng hoạt động theme: Chủ đề mà khách truy cập đăng xuất và người mới nhìn thấy. thumbnail: 'Một hình ảnh tỉ lệ 2: 1 được hiển thị cùng với thông tin máy chủ của bạn.' - timeline_preview: Khách truy cập đã đăng xuất sẽ có thể xem các tút công khai gần đây nhất trên máy chủ. trendable_by_default: Bỏ qua việc duyệt thủ công nội dung xu hướng. Các mục riêng lẻ vẫn có thể bị xóa khỏi xu hướng sau này. trends: Hiển thị những tút, hashtag và tin tức đang được thảo luận nhiều trên máy chủ của bạn. trends_as_landing_page: Hiển thị nội dung xu hướng cho người dùng chưa đăng nhập thay vì mô tả về máy chủ này. Yêu cầu xu hướng được kích hoạt. @@ -283,12 +282,16 @@ vi: content_cache_retention_period: Khoảng thời gian lưu giữ nội dung máy chủ khác custom_css: Tùy chỉnh CSS favicon: Favicon + local_live_feed_access: Truy cập bảng tin gồm những tút của máy chủ + local_topic_feed_access: Truy cập hashtag và bảng tin liên kết gồm những tút của máy chủ mascot: Tùy chỉnh linh vật (kế thừa) media_cache_retention_period: Thời hạn lưu trữ cache media min_age: Độ tuổi tối thiểu peers_api_enabled: Công khai danh sách các máy chủ được phát hiện trong API profile_directory: Cho phép hiện danh bạ thành viên registrations_mode: Ai có thể đăng ký + remote_live_feed_access: Truy cập bảng tin gồm những tút từ máy chủ khác + remote_topic_feed_access: Truy cập hashtag và bảng tin liên kết gồm những tút từ máy chủ khác require_invite_text: Yêu cầu lí do đăng ký show_domain_blocks: Xem máy chủ chặn show_domain_blocks_rationale: Hiện lý do máy chủ bị chặn @@ -301,7 +304,6 @@ vi: status_page_url: URL trang trạng thái theme: Chủ đề mặc định thumbnail: Hình thu nhỏ của máy chủ - timeline_preview: Cho phép truy cập vào dòng thời gian công khai trendable_by_default: Cho phép lên xu hướng mà không cần duyệt trước trends: Bật xu hướng trends_as_landing_page: Dùng trang xu hướng làm trang chào mừng diff --git a/config/locales/simple_form.zh-CN.yml b/config/locales/simple_form.zh-CN.yml index efd37217a4b..dbe628205f2 100644 --- a/config/locales/simple_form.zh-CN.yml +++ b/config/locales/simple_form.zh-CN.yml @@ -105,7 +105,6 @@ zh-CN: status_page_url: 配置一个网址,当服务中断时,人们可以通过该网址查看服务器的状态。 theme: 给未登录访客和新用户使用的主题。 thumbnail: 与服务器信息一并展示的约 2:1 比例的图像。 - timeline_preview: 未登录访客将能够浏览服务器上的最新公开嘟文。 trendable_by_default: 跳过对热门内容的手工审核。个别项目仍可在之后从趋势中删除。 trends: 热门页中会显示正在你服务器上受到关注的嘟文、标签和新闻故事。 trends_as_landing_page: 向注销的用户和访问者显示热门内容,而不是对该服务器的描述,需要启用热门。 @@ -283,12 +282,16 @@ zh-CN: content_cache_retention_period: 外站内容保留期 custom_css: 自定义 CSS favicon: Favicon + local_live_feed_access: 展示本站嘟文的实时动态访问权限 + local_topic_feed_access: 展示本站嘟文的话题标签及实时动态访问权限 mascot: 自定义吉祥物(旧) media_cache_retention_period: 媒体缓存保留期 min_age: 最低年龄要求 peers_api_enabled: 在API中公开的已知实例的服务器的列表 profile_directory: 启用用户目录 registrations_mode: 谁可以注册 + remote_live_feed_access: 展示外站嘟文的实时动态访问权限 + remote_topic_feed_access: 展示外站嘟文的话题标签及实时动态访问权限 require_invite_text: 注册时需要提供理由 show_domain_blocks: 显示站点屏蔽列表 show_domain_blocks_rationale: 显示站点屏蔽原因 @@ -301,7 +304,6 @@ zh-CN: status_page_url: 状态页网址 theme: 默认主题 thumbnail: 本站缩略图 - timeline_preview: 允许未登录用户访问公共时间线 trendable_by_default: 允许在未审核的情况下将话题置为热门 trends: 启用热门 trends_as_landing_page: 使用热门页作为登陆页面 diff --git a/config/locales/simple_form.zh-HK.yml b/config/locales/simple_form.zh-HK.yml index de4a76c0edb..6e79264e98f 100644 --- a/config/locales/simple_form.zh-HK.yml +++ b/config/locales/simple_form.zh-HK.yml @@ -95,7 +95,6 @@ zh-HK: status_page_url: 可在服務中斷期間,查看此伺服器狀態的網頁網址 theme: 未登入訪客和新使用者看到的主題。 thumbnail: 一幅約 2:1 的圖片顯示在你的伺服器資訊的旁邊。 - timeline_preview: 未登入的訪客能夠瀏覽伺服器上最新的公開帖文。 trendable_by_default: 跳過對趨勢內容的手動審查,事後仍可從趨勢中刪除個別項目。 trends: 趨勢顯示哪些帖文、標籤和新聞故事在你的伺服器上較有吸引力。 trends_as_landing_page: 向未登入的使用者及訪客展示趨勢內容,而非只有此伺服器的描述。需要啟用趨勢。 @@ -261,7 +260,6 @@ zh-HK: status_page_url: 狀態頁網址 theme: 預設主題 thumbnail: 伺服器縮圖 - timeline_preview: 允許未經認證的人存取公共時間軸 trendable_by_default: 允許未經審核的趨勢 trends: 啟用趨勢 trends_as_landing_page: 使用趨勢作為登陸頁面 diff --git a/config/locales/simple_form.zh-TW.yml b/config/locales/simple_form.zh-TW.yml index 6bf08313944..00684c32715 100644 --- a/config/locales/simple_form.zh-TW.yml +++ b/config/locales/simple_form.zh-TW.yml @@ -105,7 +105,6 @@ zh-TW: status_page_url: 當服務中斷時,可以提供使用者了解伺服器資訊頁面之 URL theme: 未登入之訪客或新使用者所見之佈景主題。 thumbnail: 大約 2:1 圖片會顯示於您伺服器資訊之旁。 - timeline_preview: 未登入之訪客能夠瀏覽此伺服器上最新的公開嘟文。 trendable_by_default: 跳過手動審核熱門內容。仍能於登上熱門趨勢後移除個別內容。 trends: 熱門趨勢將顯示於您伺服器上正在吸引大量注意力的嘟文、主題標籤、或者新聞。 trends_as_landing_page: 顯示熱門趨勢內容至未登入使用者及訪客而不是關於此伺服器之描述。需要啟用熱門趨勢。 @@ -283,12 +282,16 @@ zh-TW: content_cache_retention_period: 遠端內容保留期限 custom_css: 自訂 CSS favicon: 網站圖示 (Favicon) + local_live_feed_access: 允許瀏覽本站嘟文之即時內容 + local_topic_feed_access: 允許瀏覽本站嘟文之主題標籤與連結 mascot: 自訂吉祥物 (legacy) media_cache_retention_period: 多媒體快取資料保留期間 min_age: 最低年齡要求 peers_api_enabled: 於 API 中公開已知伺服器的列表 profile_directory: 啟用個人檔案目錄 registrations_mode: 誰能註冊 + remote_live_feed_access: 允許瀏覽聯邦宇宙嘟文之即時內容 + remote_topic_feed_access: 允許瀏覽聯邦宇宙嘟文之主題標籤與連結 require_invite_text: 要求「加入原因」 show_domain_blocks: 顯示封鎖的網域 show_domain_blocks_rationale: 顯示網域被封鎖之原因 @@ -301,7 +304,6 @@ zh-TW: status_page_url: 狀態頁面 URL theme: 預設佈景主題 thumbnail: 伺服器縮圖 - timeline_preview: 允許未登入使用者瀏覽公開時間軸 trendable_by_default: 允許熱門趨勢直接顯示,不需經過審核 trends: 啟用熱門趨勢 trends_as_landing_page: 以熱門趨勢作為登陸頁面 diff --git a/config/locales/sk.yml b/config/locales/sk.yml index 65aca0b47ed..ac3d5d8ee96 100644 --- a/config/locales/sk.yml +++ b/config/locales/sk.yml @@ -14,7 +14,7 @@ sk: other: Sledujúci following: Nasledujem instance_actor_flash: Toto konto je virtuálny aktér, ktorý predstavuje samotný server, a nie konkrétneho používateľa. Používa sa na účely federácie a nemal by byť pozastavený. - last_active: naposledy aktívny + last_active: posledná aktivita link_verified_on: Vlastníctvo tohto odkazu bolo skontrolované %{date} nothing_here: Nič tu nie je! pin_errors: @@ -41,7 +41,7 @@ sk: approve: Schváľ approved_msg: Úspešne schválená prihláška %{username} are_you_sure: Si si istý/á? - avatar: Maskot + avatar: Profilová fotka by_domain: Doména change_email: changed_msg: E-mail úspešne zmenený! @@ -60,13 +60,13 @@ sk: confirmed: Potvrdený confirming: Potvrdzujúci custom: Vlastné - delete: Vymaž dáta + delete: Vymazať dáta deleted: Vymazané demote: Degraduj destroyed_msg: "%{username} je teraz zaradený do fronty na okamžité vymazanie" disable: Zablokuj disable_sign_in_token_auth: Vypni overovanie e-mailovým tokenom - disable_two_factor_authentication: Vypni dvoj-faktorové overovanie + disable_two_factor_authentication: Vypnúť dvojstupňové overenie disabled: Blokovaný display_name: Ukáž meno domain: Doména @@ -119,14 +119,14 @@ sk: push_subscription_expires: PuSH odoberanie expiruje redownload: Obnov profil redownloaded_msg: Úspešne obnovený profil %{username} z pôvodného - reject: Zamietni + reject: Zamietnuť rejected_msg: Úspešne zamietnutá prihláška %{username} remote_suspension_irreversible: Údaje tohto účtu boli nenávratne zmazané. remote_suspension_reversible_hint_html: Účet bol pozastavený na ich serveri a údaje budú úplne odstránené dňa %{date}. Dovtedy môže vzdialený server účet obnoviť bez akýchkoľvek nepriaznivých účinkov. Ak chceš odstrániť všetky údaje účtu ihneď, môžeš tak urobiť nižšie. - remove_avatar: Vymaž avatar - remove_header: Vymaž záhlavie + remove_avatar: Vymazať profilovú fotku + remove_header: Vymazať záhlavie removed_avatar_msg: Úspešne odstránený obrázok avatara %{username} - removed_header_msg: Úspešne odstránený obrázok hlavičky %{username} + removed_header_msg: Obrázok v záhlaví profilu %{username} bol úspešne odstránený resend_confirmation: already_confirmed: Tento užívateľ je už potvrdený send: Odošli potvrdzovací odkaz znovu @@ -142,7 +142,7 @@ sk: only_password: Iba heslo password_and_2fa: Heslo a dvoj-faktorové overovanie sensitive: Citlivé na silu - sensitized: Označený ako chúlostivý + sensitized: Označený ako citlivý shared_inbox_url: URL zdieľanej schránky show: created_reports: Vytvorené hlásenia @@ -190,15 +190,15 @@ sk: create_unavailable_domain: Vytvor nedostupnú doménu create_user_role: Vytvoriť rolu demote_user: Zniž užívateľskú rolu - destroy_announcement: Vymaž oboznámenie + destroy_announcement: Vymazať oznámenie destroy_canonical_email_block: Zruš blokovanie emailu - destroy_custom_emoji: Vymaž vlastné emotikony + destroy_custom_emoji: Vymazať vlastné emotikony destroy_domain_allow: Zmaž povolenie pre doménu destroy_domain_block: Zruš blokovanie domény destroy_instance: Vyčistiť doménu - destroy_ip_block: Vymaž IP pravidlo - destroy_status: Vymaž príspevok - destroy_unavailable_domain: Vymaž nedostupnú doménu + destroy_ip_block: Vymazať IP pravidlo + destroy_status: Vymazať príspevok + destroy_unavailable_domain: Vymazať nedostupnú doménu destroy_user_role: Zničiť rolu disable_2fa_user: Vypni dvoj-faktorové overovanie disable_custom_emoji: Vypni vlastné emotikony @@ -208,14 +208,14 @@ sk: memorialize_account: Zmena na „in memoriam“ promote_user: Povýš užívateľskú rolu publish_terms_of_service: Zverejni podmienky prevozu - reject_appeal: Zamietni námietku - reject_user: Zamietni užívateľa - remove_avatar_user: Vymaž avatar + reject_appeal: Zamietnuť odvolanie + reject_user: Zamietnuť používateľa + remove_avatar_user: Vymazať profilovú fotku reopen_report: Znovu otvor hlásenie resend_user: Preposlať overovací email reset_password_user: Obnov heslo resolve_report: Vyrieš nahlásený problém - sensitive_account: Vynúť všetky médiá na účte ako chúlostivé + sensitive_account: Označiť všetky médiá na účte ako citlivé silence_account: Utíš účet suspend_account: Pozastav účet unassigned_report: Odober priradenie nahlásenia @@ -263,12 +263,12 @@ sk: reopen_report_html: "%{name} znovu otvoril/a nahlásenie %{target}" reset_password_user_html: "%{name} resetoval/a heslo používateľa %{target}" resolve_report_html: "%{name} vyriešil/a nahlásenie %{target}" - sensitive_account_html: "%{name} označil/a médium od %{target} za chúlostivé" + sensitive_account_html: "%{name} uvádza médiá od %{target} ako citlivé" silence_account_html: "%{name} obmedzil/a účet %{target}" suspend_account_html: "%{name} zablokoval/a účet používateľa %{target}" unassigned_report_html: "%{name} odobral/a report od %{target}" unblock_email_account_html: "%{name} odblokoval/a %{target}ovu/inu emailovú adresu" - unsensitive_account_html: "%{name} odznačil/a médium od %{target} ako chúlostivé" + unsensitive_account_html: "%{name} ruší uvádzanie médií od %{target} ako citlivé" unsilence_account_html: "%{name} zrušil/a obmedzenie %{target}ovho/inho účtu" unsuspend_account_html: "%{name} spojazdnil/a účet %{target}" update_announcement_html: "%{name} aktualizoval/a oboznámenie %{target}" @@ -291,6 +291,8 @@ sk: new: create: Vytvor oznam title: Nové oznámenie + preview: + disclaimer: Keďže si používatelia nemôžu e-mailové upozornenia vypnúť, mali by byť využívané iba na dôležité oznamy, napríklad upozornenia o úniku osobných údajov alebo rušení servera. publish: Zverejni published_msg: Oboznámenie úspešne zverejnené! scheduled_for: Načasované na %{time} @@ -307,7 +309,7 @@ sk: copy_failed_msg: Nebolo možné vytvoriť miestnu kópiu tohto emoji create_new_category: Vytvor novú kategóriu created_msg: Emoji úspešne vytvorené! - delete: Vymaž + delete: Vymazať destroyed_msg: Emoji úspešne zničené! disable: Zakáž disabled: Vypnuté @@ -354,7 +356,7 @@ sk: add_new: Povolená doména created_msg: Doména bola úspešne povolená destroyed_msg: Doména bola odstránená zo zoznamu povolených - export: Exportuj + export: Export import: Nahraj undo: Odober zo zoznamu povolených domain_blocks: @@ -370,7 +372,7 @@ sk: domain: Doména edit: Uprav blokovanie domény existing_domain_block_html: Pre účet %{name} si už nahodil/a přísnejšie obmedzenie, najskôr ho teda musíš odblokovať. - export: Exportuj + export: Export import: Nahraj new: create: Vytvor blokovanie domény @@ -393,10 +395,10 @@ sk: undo: Odvolaj blokovanie domény view: Ukáž blokovanie domén email_domain_blocks: - add_new: Pridaj nový + add_new: Pridať nový allow_registrations_with_approval: Povoľ registrovanie so schválením created_msg: Úspešne zablokovaná emailová doména - delete: Vymaž + delete: Vymazať dns: types: mx: MX záznam @@ -411,7 +413,7 @@ sk: export_domain_allows: new: title: Nahraj povolené domény - no_file: Nevybraný žiaden súbor + no_file: Nebol vybraný žiadny súbor export_domain_blocks: import: existing_relationships_warning: Existujúce vzťahy nasledovania @@ -419,7 +421,7 @@ sk: title: Nahraj zákazy domén new: title: Nahraj zákazy domén - no_file: Nevybraný žiaden súbor + no_file: Nebol vybraný žiadny súbor follow_recommendations: description_html: "Odporúčania na sledovanie pomáhaju novým užívateľom rýchlo nájsť zaujímavý obsah. Ak užívateľ zatiaľ nedostatočne interagoval s ostatnými aby si vyformoval personalizované odporúčania na sledovanie, tak mu budú odporúčané tieto účty. Sú prepočítavané na dennej báze z mixu účtov s nedávnym najvyšším záujmom a najvyšším počtom lokálnych sledujúcich pre daný jazyk." language: Pre jazyk @@ -430,6 +432,7 @@ sk: unsuppress: Obnoviť odporúčanie na sledovanie instances: availability: + failure_threshold_reached: Limit neúspešných pokusov bol dosiahnutý %{date}. no_failures_recorded: Žiadne zlyhania nezaznamenané. title: Dostupnosť back_to_all: Všetko @@ -489,7 +492,7 @@ sk: ip_blocks: add_new: Vytvor pravidlo created_msg: Nové IP pravidlo úspešne pridané - delete: Vymaž + delete: Vymazať expires_in: '1209600': 2 týždne '15778476': 6 mesiacov @@ -504,8 +507,8 @@ sk: relationships: title: Vzťahy užívateľa %{acct} relays: - add_new: Pridaj nový federovací mostík - delete: Vymaž + add_new: Pridať nový federovací mostík + delete: Vymazať description_html: "Federovací mostík je prechodný server, ktorý obmieňa veľké množstvá verejných príspevkov medzi tými servermi ktoré na od neho odoberajú, aj doňho prispievajú. Môže to pomôcť malým a stredným instanciám objavovať federovaný obsah, čo inak vyžaduje aby miestni užívatelia ručne následovali iných ľudí zo vzdialených instancií." disable: Vypni disabled: Vypnutý @@ -532,6 +535,7 @@ sk: action_log: Denník auditu action_taken_by: Zákrok vykonal/a actions: + silence_description_html: Účet bude viditeľný iba pre účty, ktoré ho už sledujú alebo si ho vyhľadali ručne, čo výrazne zredukuje jeho dosah. Toto nastavenie je kedykoľvek možné zmeniť. Ukončí všetky hlásenia voči tomuto účtu. suspend_description_html: Tento účet a všetok jeho obsah bude nedostupný a nakoniec zmazaný, interaktovať s ním bude nemožné. Zvrátiteľné v rámci 30 dní. Uzatvára všetky hlásenia voči tomuto účtu. add_to_report: Pridaj viac do hlásenia already_suspended_badges: @@ -548,18 +552,18 @@ sk: confirm: Potvrď confirm_action: Potvrď moderovací úkon proti @%{acct} created_at: Nahlásené - delete_and_resolve: Vymaž príspevky + delete_and_resolve: Vymazať príspevky forwarded: Preposlané forwarded_to: Preposlané na %{domain} mark_as_resolved: Označiť ako vyriešené - mark_as_sensitive: Označ ako chúlostivé + mark_as_sensitive: Označiť ako citlivý obsah mark_as_unresolved: Označ ako nevyriešené no_one_assigned: Nikoho notes: create: Pridaj poznámku create_and_resolve: Vyrieš s poznámkou create_and_unresolve: Otvor znovu, s poznámkou - delete: Vymaž + delete: Vymazať placeholder: Opíš aké opatrenia boli urobené, alebo akékoľvek iné súvisiace aktualizácie… title: Poznámky remote_user_placeholder: vzdialený užívateľ z %{instance} @@ -576,8 +580,9 @@ sk: action_preambles: suspend_html: 'Chystáš sa pozastaviť účet @%{acct}. To urobí:' actions: - delete_html: Vymaž pohoršujúce príspevky - mark_as_sensitive_html: Označ médiá pohoršujúcich príspevkov za chúlostivé + delete_html: Vymazať príspevky porušujúce pravidlá + mark_as_sensitive_html: Označiť médiá v príspevkoch porušujúcich pravidlá ako citlivé + silence_html: Zásadne obmedzí dosah profilu @%{acct} zmenou jeho viditeľnosti spolu s jeho obsahom iba pre ľudí, ktorí ho už sledujú alebo si ho ručne vyhľadali close_report: 'Označ hlásenie #%{id} za vyriešené' target_origin: Pôvod nahláseného účtu title: Hlásenia @@ -598,7 +603,7 @@ sk: invites: Pozvánky moderation: Moderácia special: Špeciálne - delete: Vymaž + delete: Vymazať edit: Uprav postavenie %{name} everyone: Východzie oprávnenia permissions_count: @@ -609,7 +614,7 @@ sk: privileges: administrator: Správca administrator_description: Užívatelia s týmto povolením, obídu všetky povolenia - delete_user_data: Vymaž užívateľské dáta + delete_user_data: Vymazať používateľské dáta invite_users: Pozvi užívateľov manage_announcements: Spravuj oboznámenia manage_appeals: Spravuj námietky @@ -626,7 +631,7 @@ sk: title: Postavenia rules: add_new: Pridaj pravidlo - delete: Vymaž + delete: Vymazať edit: Uprav pravidlo empty: Žiadne pravidlá servera ešte neboli určené. title: Serverové pravidlá @@ -660,9 +665,11 @@ sk: none: Nikto sa nemôže registrovať open: Ktokoľvek sa môže zaregistrovať warning_hint: Odporúčame používať "Pre registráciu je potrebné schválenie", pokiaľ si niesi istý/á, že tvoj moderovací tím vie zvládnuť spam a záškodné registrácie včas. + security: + authorized_fetch_hint: Vyžadovanie overenia od federovaných serverov umožňuje dôkladnejšie vykonávania blokov na úrovni používateľa aj severa. Prináša to so sebou však aj zhoršenie výkonu a dosahu vašich odpovedí a môže spôsobiť problémy s kompatibilitou s niektorými federovanými službami. Okrem toho to nezabráni prístupu k vašim verejným príspevkom a účtom. title: Nastavenia servera site_uploads: - delete: Vymaž nahratý súbor + delete: Vymazať nahratý súbor destroyed_msg: Nahratie bolo zo stránky úspešne vymazané! software_updates: critical_update: Kritické — prosím aktualizuj rýchlo @@ -680,10 +687,10 @@ sk: back_to_account: Späť na účet back_to_report: Späť na stránku hlásenia batch: - remove_from_report: Vymaž z hlásenia + remove_from_report: Vymazať z hlásenia report: Hlásenie deleted: Vymazané - favourites: Obľúbené + favourites: Ohviezdičkovania history: História verzií in_reply_to: Odpoveď na language: Jazyk @@ -717,7 +724,7 @@ sk: action: Pozri tu pre viac informácií tags: review: Prehodnoť stav - updated_msg: Nastavenia haštagov boli úspešne aktualizované + updated_msg: Nastavenia hashtagov boli úspešne aktualizované title: Spravovanie trends: allow: Povoľ @@ -758,10 +765,10 @@ sk: trending: Populárne warning_presets: add_new: Pridaj nové - delete: Vymaž + delete: Vymazať edit_preset: Uprav varovnú predlohu webhooks: - delete: Vymaž + delete: Vymazať disable: Vypni disabled: Vypnuté enable: Povoľ @@ -789,22 +796,19 @@ sk: new_trending_statuses: title: Populárne príspevky new_trending_tags: - title: Populárne haštagy + title: Populárne hashtagy aliases: add_new: Vytvor alias created_msg: Nový alias úspešne vytvorený. Teraz môžeš začať presun zo starého účtu. deleted_msg: Alias úspešne odstránený. Presun z tamtoho účtu na tento už viac nebude možný. remove: Odpoj alias appearance: - advanced_web_interface: Pokročilé webové rozhranie - advanced_web_interface_hint: 'Ak chceš využiť celkovú šírku tvojej obrazovky, pokročilé webové rozhranie ti umožňuje nastaviť mnoho rôznych stĺpcov, aby si videl/a toľko informácií naraz, koľko chceš: Domov, oboznámenia, federovanú časovú os, a ľubovolný počet zoznamov, či haštagov.' animations_and_accessibility: Animácie a prístupnosť - confirmation_dialogs: Potvrdzovacie dialógy - discovery: Nájdenie + discovery: Objavovanie localization: body: Mastodon je prekladaný dobrovoľníkmi. guide_link_text: Prispievať môže každý. - sensitive_content: Chúlostivý obsah + sensitive_content: Citlivý obsah application_mailer: unsubscribe: Prestaň odoberať view: 'Zobraziť:' @@ -813,7 +817,7 @@ sk: applications: created: Aplikácia bola vytvorená úspešne destroyed: Aplikáciu sa podarilo odstrániť - logout: Odhlás sa + logout: Odhlásiť sa regenerate_token: Znovu vygeneruj prístupový token token_regenerated: Prístupový token bol úspešne vygenerovaný znova warning: Na tieto údaje dávaj ohromný pozor. Nikdy ich s nikým nezďieľaj! @@ -827,8 +831,8 @@ sk: login_link: prihlás sa proceed_to_login_html: Teraz môžeš pokračovať na %{login_link}. welcome_title: Vitaj, %{name}! - delete_account: Vymaž účet - delete_account_html: Pokiaľ chceš svoj účet odtiaľto vymazať, môžeš tak urobiť tu. Budeš požiadaný/á o potvrdenie tohto kroku. + delete_account: Odstránenie účtu + delete_account_html: Pokiaľ chcete odstrániť svoj účet, môžete to urobiť tu. Toto rozhodnutie ešte budete musieť potvrdiť. description: prefix_invited_by_user: "@%{name} ťa pozýva na tento Mastodon server!" prefix_sign_up: Zaregistruj sa na Mastodone už dnes! @@ -839,9 +843,9 @@ sk: invalid_reset_password_token: Token na obnovu hesla vypršal. Prosím vypítaj si nový. log_in_with: Prihlás sa s login: Prihlás sa - logout: Odhlás sa - migrate_account: Presúvam sa na iný účet - migrate_account_html: Ak si želáš presmerovať tento účet na nejaký iný, môžeš si to nastaviť tu. + logout: Odhlásiť sa + migrate_account: Presun na iný účet + migrate_account_html: Ak chcete presmerovať tento účet na nejaký iný, môžete to nastaviť tu. or_log_in_with: Alebo prihlás s progress: confirm: Potvrď email @@ -865,8 +869,21 @@ sk: title: Prihlás sa na %{domain} status: account_status: Stav účtu - redirecting_to: Tvoj účet je neaktívny, lebo v súčasnosti presmerováva na %{acct}. + confirming: Čaká sa na dokončenie overenia e-mailu. + functional: Váš účet je funkčný. + pending: Vaša žiadosť je na kontrole naším tímom. Môže to trvať. Po jej prípadnom schválení dostanete e-mail. + redirecting_to: Váš účet je neaktívny, pretože v súčasnosti presmerúva na %{acct}. + self_destruct: Keďže %{domain} končí, budete mať k účtu iba obmedzený prístup. + view_strikes: Zobraziť predošlé sankcie vášho účtu use_security_key: Použi bezpečnostný kľúč + author_attribution: + example_title: Názorný text + hint_html: Píšete novinové alebo blogové články mimo Mastodonu? Rozhodujte o tom, ako sú vám pripisované, keď ich niekto zdieľa na Mastodone. + instructions: 'Vložte tento kód do kódu HTML vo vašom článku:' + more_from_html: Viac od %{name} + s_blog: Blog %{name} + then_instructions: Potom do poľa nižšie zadajte názov domény média. + title: Uvádzanie autorstva challenge: confirm: Pokračuj hint_html: "Tip: Hodinu nebudeme znovu vyžadovať tvoje heslo." @@ -890,7 +907,7 @@ sk: challenge_not_passed: Údaje, ktoré si zadal/a, sú nesprávne confirm_password: Napíš svoje terajšie heslo pre overenie tvojej identity confirm_username: Zadaj svoju prezývku, na potvrdenie úkonu - proceed: Vymaž účet + proceed: Odstrániť účet success_msg: Tvoj účet bol úspešne vymazaný warning: before: 'Než budeš pokračovať, prosím pozorne si prečítaj tieto poznámky:' @@ -913,14 +930,15 @@ sk: reject_appeal: Zamietni námietku title_actions: disable: Zmrazenie účtu - mark_statuses_as_sensitive: Označenie príspevkov za chúlostivé + mark_statuses_as_sensitive: Označenie príspevkov ako citlivé none: Varovanie - sensitive: Označenie účtu ako chúlostivý + sensitive: Označenie účtu ako citlivého silence: Obmedzenie účtu your_appeal_approved: Tvoja námietka bola schválená your_appeal_pending: Odoslal si námietku edit_profile: basic_information: Základné informácie + hint_html: "Upravte, čo ľudia vidia vo vašom verejom profile a pri vašich príspevkoch. S vyplneným profilom a nahratou profilovou fotkou sa zvýšia šance, že vás iní ľudia budú sledovať a budú s vami komunikovať." other: Ostatné errors: '400': Požiadavka, ktorú si odoslal/a, bola buď nesprávna, alebo znehodnotená. @@ -944,9 +962,9 @@ sk: archive_takeout: date: Dátum download: Stiahni si svoj archív - hint_html: Môžeš si vyžiadať archív svojích príspevkov a nahratých médií. Exportované dáta budú v ActivityPub formáte, čítateľné hociakým kompatibilným softvérom. Archív si je možné vyžiadať každých sedem dní. - in_progress: Balím tvoj archív... - request: Vyžiadaj si tvoj archív + hint_html: Môžete si vyžiadať archív svojich príspevkov a nahratých médií. Dáta budú exportované vo formáte ActivityPub, ktorý prečíta ľubovoľný kompatibilný softvér. Archív si je možné vyžiadať každých sedem dní. + in_progress: Prebieha kompilácia archívu… + request: Požiadať o archív size: Veľkosť blocks: Blokujete bookmarks: Záložky @@ -955,9 +973,10 @@ sk: mutes: Stíšil/a si storage: Úložisko médií featured_tags: - add_new: Pridaj nový + add_new: Pridať nový errors: - limit: Už si si predvolil/a najvyšší možný počet haštagov + limit: Už ste si predvolili najvyšší možný počet hashtagov + hint_html: "Zobrazte vo svojom profile vaše najvýznamnejšie hashtagy. Zvýraznené hashtagy majú viditeľné miesto vo vašom profile a umožňujú vám rýchly prístup k vašim príspevkom, aby ste mali svoje diela a dlhodobé projekty vždy poruke." filters: contexts: account: Profily @@ -968,29 +987,29 @@ sk: edit: add_keyword: Pridaj kľúčové slovo keywords: Kľúčové slová - title: Uprav triedenie + title: Upraviť filter errors: invalid_context: Nebola poskytnutá žiadna, alebo ide o neplatnú súvislosť index: - delete: Vymaž + delete: Vymazať empty: Nemáš žiadné filtrovanie. expires_on: Expiruje dňa %{date} - title: Triedenia + title: Filtre new: save: Uložiť nový filter - title: Pridaj nové triedenie + title: Pridať nový filter statuses: batch: remove: Odstrániť z filtrovania generic: all: Všetko cancel: Zruš - changes_saved_msg: Zmeny boli úspešne uložené! + changes_saved_msg: Zmeny boli úspešne uložené. confirm: Potvrď copy: Kopíruj - delete: Vymaž - order_by: Zoraď podľa - save_changes: Ulož zmeny + delete: Vymazať + order_by: Zoradiť podľa + save_changes: Uložiť zmeny today: dnes validation_errors: few: Niečo ešte nieje celkom v poriadku! Prosím skontroluj %{count} chýb uvedených nižšie @@ -1004,11 +1023,11 @@ sk: failures: Zlyhaní(a) imported: Nahrané modes: - merge: Spoj dohromady - merge_long: Ponechaj existujúce záznamy a pridaj k nim nové - overwrite: Prepíš - overwrite_long: Nahraď súčasné záznamy novými - preface: Môžeš nahrať dáta ktoré si exportoval/a z iného Mastodon serveru, ako sú napríklad zoznamy ľudí ktorých sleduješ, alebo blokuješ. + merge: Pridať + merge_long: Ponechať existujúce záznamy a pridať k nim nové + overwrite: Prepísať + overwrite_long: Nahradiť súčasné záznamy novými + preface: Môžete importovať dáta exportované z iného serveru na Mastodone, napríklad zoznam sledovaných alebo blokovaných účtov. recent_imports: Nedávne nahrania states: finished: Dokončené @@ -1021,7 +1040,7 @@ sk: lists: Nahrávanie zoznamov type_groups: constructive: Sledovania a záložky - destructive: Blokovania a utíšenia + destructive: Blokovania a stíšenia types: blocking: Zoznam blokovaných bookmarks: Záložky @@ -1057,7 +1076,7 @@ sk: title: Pozvi ľudí lists: errors: - limit: Dosiahli ste maximálny počet zoznamov + limit: Bol dosiahnutý maximálny počet zoznamov login_activities: authentication_methods: password: heslom @@ -1065,6 +1084,9 @@ sk: title: História overení mail_subscriptions: unsubscribe: + emails: + notification_emails: + reblog: e-mailové upozornenia na zdieľania title: Ukonči odber media_attachments: validations: @@ -1082,8 +1104,8 @@ sk: not_found: nebolo možné nájsť on_cooldown: Si v spánkovom stave followers_count: Následovatelia v čase presunu - incoming_migrations: Presúvam sa z iného účtu - incoming_migrations_html: K presunutiu z iného účtu na tento, si najskôr potrebuješ vytvoriť alias pre účet. + incoming_migrations: Presun z iného účtu + incoming_migrations_html: Ak sa chcete na tento účet presunúť z iného účtu, najprv si vytvorte nový alias. moved_msg: Tvoj účet teraz presmerováva na %{acct} a tvoji sledovatelia sú presúvaní tam. not_redirecting: Tvoj účet v súčasnosti nepresmerováva na žiaden iný účet. on_cooldown: Účet si si presunul/a len nedávno. Táto vymoženosť bude znovu sprístupnená za %{count} dní. @@ -1108,12 +1130,12 @@ sk: carry_mutes_over_text: Tento užívateľ sa presunul z účtu %{acct}, ktorý si mal/a stíšený. notification_mailer: favourite: - body: 'Tvoj príspevok bol obľúbený užívateľom %{name}:' + body: "%{name} hviezdičkuje váš príspevok:" subject: "%{name} si obľúbil/a tvoj príspevok" - title: Novo obľúbené + title: Nové ohviezdičkovanie follow: - body: "%{name} ťa teraz nasleduje!" - subject: "%{name} ťa teraz nasleduje" + body: "%{name} vás teraz sleduje." + subject: "%{name} vás teraz sleduje" title: Nový sledovateľ follow_request: action: Spravuj žiadosti o sledovanie @@ -1128,15 +1150,17 @@ sk: poll: subject: Anketa od %{name} skončila reblog: - body: 'Tvoj príspevok bol vyzdvihnutý užívateľom %{name}:' - subject: "%{name} vyzdvihli tvoj príspevok" - title: Novo vyzdvyhnuté + body: "%{name} zdieľa váš príspevok:" + subject: "%{name} zdieľa váš príspevok" + title: Nové zdieľanie status: subject: "%{name} práve prispel/a" update: subject: "%{name} upravil/a príspevok" notifications: - email_events_hint: 'Vyber si udalosti, pre ktoré chceš dostávať oboznámenia:' + administration_emails: Administrátorské e-mailové upozornenia + email_events: Udalosti pre e-mailové upozornenia + email_events_hint: 'Vyberte udalosti, pre ktoré chcete dostávať upozornenia:' otp_authentication: enable: Povoľ pagination: @@ -1157,11 +1181,16 @@ sk: too_many_options: nemôže zahŕňať viac ako %{max} položiek preferences: other: Ostatné - posting_defaults: Východiskové nastavenia príspevkov + posting_defaults: Predvolené nastavenia príspevkov public_timelines: Verejné časové osi privacy: + hint_html: "Upravte si spôsob nachádzania vášho profilu a príspevkov. Tieto funkcie vám môžu pomôcť osloviť väčšie publikum na Mastodone. Skontrolujte tieto nastavenia, aby bolo všetko tak, ako to chcete." privacy: Súkromie + privacy_hint_html: Rozhodujte o tom, koľko svojej aktivity chcete ukázať ostatným. Ľudia nachádzajú zaujímavé profily a aplikácie aj v profiloch iných, v zoznamoch sledovateľov a sledovaných. Máte možnosť ich skryť. + reach: Dosah + reach_hint_html: Rozhodnite o tom, či chcete aby vás iní ľudia nachádzali a sledovali. Chcete, aby sa vaše príspevky zobrazovali vo feede Objavovanie? Chcete, aby bol váš účet zobrazovaný ostatným v návrhoch na sledovanie? Chcete automatický schváliť všetky sledovania vás alebo o nich chcete jednotlivo rozhodovať? search: Vyhľadávanie + search_hint_html: Rozhodujte o tom, ako je možné vás nájsť. Chcete, aby vás ľudia mohli nájsť cez vaše verejné príspevky? Chcete, aby ľudia mimo Mastodonu mohli nachádzať váš profil pri prehľadávaní internetu? Upozorňujeme, že verejné informácie nie je možné úplne odizolovať od vyhľadávačov. title: Súkromie a dosah privacy_policy: title: Pravidlá ochrany súkromia @@ -1177,21 +1206,21 @@ sk: confirm_follow_selected_followers: Si si istý/á, že chceš nasledovať vybraných sledujúcich? confirm_remove_selected_followers: Si si istý/á, že chceš odstrániť vybraných sledovateľov? confirm_remove_selected_follows: Si si istý/á, že chceš odstrániť vybraných sledovaných? - dormant: Spiace + dormant: Neaktívne follow_failure: Nemožno nasledovať niektoré z vybraných účtov. follow_selected_followers: Následuj označených sledovatelov - followers: Sledovatelia - following: Nasledovaní + followers: Sledujú vás + following: Sledované vami invited: Pozvaný/á - last_active: Naposledy aktívny + last_active: Naposledy aktívne most_recent: Najnovšie - moved: Presunuli sa - mutual: Spoločné + moved: Presunuté + mutual: Vzájomné primary: Hlavné relationship: Vzťah - remove_selected_domains: Vymaž všetkých následovateľov z vybraných domén + remove_selected_domains: Vymazať všetky sledujúce účty z vybraných domén remove_selected_followers: Odstráň vybraných následovatrľov - remove_selected_follows: Prestaň sledovať vybraných užívateľov + remove_selected_follows: Zrušiť sledovanie vybraných účtov status: Stav účtu remote_follow: missing_resource: Nemožno nájsť potrebnú presmerovaciu adresu k tvojmu účtu @@ -1204,7 +1233,7 @@ sk: over_daily_limit: Prekročil/a si denný limit %{limit} predplánovaných príspevkov over_total_limit: Prekročil/a si limit %{limit} predplánovaných príspevkov sessions: - activity: Najnovšia aktivita + activity: Posledná aktivita browser: Prehliadač browsers: chrome: Google Chrome @@ -1216,10 +1245,10 @@ sk: safari: Apple Safari unknown_browser: Neznámy prehliadač weibo: Sina/Tencent Weibo - current_session: Aktuálna sezóna + current_session: Vaše aktuálne prihlásenie date: Dátum description: "%{browser} na %{platform}" - explanation: Tieto sú prehliadače ktoré sú teraz prihlásené na tvoj Mastodon účet. + explanation: Tieto prehliadače sú práve prihlásené do vášho účtu na Mastodone. ip: IP adresa platforms: ios: Apple iOS @@ -1227,9 +1256,10 @@ sk: mac: MacOSX unknown_platform: Neznáma platforma windows: Microsoft Windows - revoke: Zamietni - revoke_success: Sezóna úspešne zamietnutá - title: Sezóny + revoke: Zrušiť + revoke_success: Prihlásenie bolo zrušené + title: Aktívne prihlásenia + view_authentication_history: Zobraziť históriu prihlásení účtu settings: account: Účet account_settings: Nastavenia účtu @@ -1239,19 +1269,30 @@ sk: back: Späť na Mastodon delete: Vymazanie účtu development: Vývoj - edit_profile: Uprav profil - featured_tags: Zvýraznené haštagy - import: Importuj + edit_profile: Úprava profilu + featured_tags: Zvýraznené hashtagy + import: Import import_and_export: Import a export migrate: Presuň účet - preferences: Voľby + notifications: E-mailové upozornenia + preferences: Predvoľby profile: Profil - relationships: Sledovania a následovatelia - two_factor_authentication: Dvojfázové overenie + relationships: Sledované a sledujúce účty + severed_relationships: Prerušené vzťahy + statuses_cleanup: Automatické mazanie príspevkov + two_factor_authentication: Dvojstupňové overenie webauthn_authentication: Bezpečnostné kľúče severed_relationships: - lost_followers: Stratení nasledovatelia - lost_follows: Stratené sledovania + download: Stiahnuť (%{count}) + event_type: + account_suspension: Pozastavenie účtu (%{target_name}) + domain_block: Pozastavenie servera (%{target_name}) + user_domain_block: Zablokovali ste %{target_name} + lost_followers: Zrušenie sledovania účtami + lost_follows: Zrušenie sledovania účtov + preamble: Pri blokovaní domény alebo pri pozastavení pripojenia s iným serverom moderátorským tímom vášho servera môžete prísť o sledované a sledujúce účty. Keď sa to stane, tu si môžete stiahnuť zoznam prerušených vzťahov, ktorý môžete skontrolovať a prípadne importovať na inom serveri. + purged: Informácie o tomto serveri boli odstránené administrátorským tímom vášho servera. + type: Udalosť statuses: attached: description: 'Priložené: %{attached}' @@ -1260,14 +1301,14 @@ sk: many: "%{count} obrázkov" one: "%{count} obrázok" other: "%{count} obrázky" - boosted_from_html: Vyzdvihnuté od %{acct_link} + boosted_from_html: Zdieľané od %{acct_link} content_warning: 'Varovanie o obsahu: %{warning}' default_language: Rovnaký ako jazyk rozhrania disallowed_hashtags: - few: 'obsah nepovolených haštagov: %{tags}' - many: 'obsah nepovolených haštagov: %{tags}' - one: 'obsahoval nepovolený haštag: %{tags}' - other: 'obsahoval nepovolené haštagy: %{tags}' + few: 'obsahoval nepovolené hashtagy: %{tags}' + many: 'obsahoval nepovolené hashtagy: %{tags}' + one: 'obsahoval nepovolený hashtag: %{tags}' + other: 'obsahoval nepovolené hashtagy: %{tags}' edited_at_html: Upravené %{date} errors: in_reply_not_found: Príspevok, na ktorý sa snažíš odpovedať, pravdepodobne neexistuje. @@ -1275,29 +1316,50 @@ sk: pin_errors: limit: Už si si pripol ten najvyšší možný počet hlášok ownership: Nieje možné pripnúť hlášku od niekoho iného - reblog: Vyzdvihnutie sa nedá pripnúť + reblog: Zdieľanie nie je možné pripnúť title: '%{name}: „%{quote}"' visibilities: + direct: Súkromné označenie + private: Iba pre sledujúce účty public: Verejné + public_long: Ktokoľvek na Mastodone aj mimo neho + unlisted: Tiché verejné + unlisted_long: Skryté z výsledkov vyhľadávania, populárnych tém a verejných časových osí na Mastodone statuses_cleanup: + enabled: Automaticky mazať staré príspevky + enabled_hint: Automaticky vymaže vaše príspevky po dosiahnutí stanoveného veku, pokiaľ nespadajú do niektorej z výnimiek nižšie exceptions: Výnimky - ignore_favs: Ignoruj obľúbené - ignore_reblogs: Ignoruj vyzdvihnutia - keep_direct: Ponechaj súkromné správy - keep_pinned: Ponechaj pripnuté príspevky - keep_pinned_hint: Nevymaže žiadne s tvojich pripnutých príspevkov - keep_polls: Ponechaj ankety - keep_self_bookmark: Ponechaj príspevky, ktoré sú záložkami - keep_self_fav: Ponechať príspevky, ktoré si si obľúbil/a + explanation: Keďže je mazanie príspevkov drahým procesom, bude sa to diať pomaly a postupne v časoch, keď server nie je inak vyťažovaný. Preto môže príspevkom po dosiahnutí stanoveného veku ešte chvíľu trvať, než budú vymazané. + ignore_favs: Ignorovať hviezdičky + ignore_reblogs: Ignorovať zdieľania + interaction_exceptions: Výnimky podľa interakcií + interaction_exceptions_explanation: Vymazanie príspevkov nie je zaručené, pokiaľ klesnú pod limit hviezdičkovaní alebo zdieľaní až po kontrole. + keep_direct: Ponechať súkromné správy + keep_direct_hint: Vaše súkromné správy nebudú vymazané + keep_media: Ponechať príspevky s médiami + keep_media_hint: Vaše príspevky s mediálnymi prílohami nebudú vymazané + keep_pinned: Ponechať pripnuté príspevky + keep_pinned_hint: Vaše pripnuté príspevky nebudú vymazané + keep_polls: Ponechať ankety + keep_polls_hint: Vaše ankety nebudú vymazané + keep_self_bookmark: Ponechať príspevky označené záložkou + keep_self_bookmark_hint: Vaše príspevky označené záložkou nebudú vymazané + keep_self_fav: Ponechať ohviezdičkované príspevky + keep_self_fav_hint: Vaše ohviezdičkované príspevky nebudú vymazané min_age: '1209600': 2 týždne - '15778476': 6 mesačné - '2629746': 1 mesačné - '31556952': 1 ročné - '5259492': 2 mesačné + '15778476': 6 mesiacov + '2629746': 1 mesiac + '31556952': 1 rok + '5259492': 2 mesiace '604800': 1 týždeň - '63113904': 2 ročné - '7889238': 3 mesačné + '63113904': 2 roky + '7889238': 3 mesiace + min_age_label: Časová hranica + min_favs: Ponechať príspevky s aspoň týmto počtom hviezdičiek + min_favs_hint: Vaše príspevky, ktoré majú aspoň tento počet hviezdičiek, nebudú vymazané. Nevypĺňajte, pokiaľ chcete mazať príspevky bez ohľadu na ich počet hviezdičiek + min_reblogs: Ponechať príspevky s aspoň týmto počtom zdieľaní + min_reblogs_hint: Vaše príspevky, ktoré majú aspoň tento počet zdieľaní, nebudú vymazané. Nevypĺňajte, pokiaľ chcete mazať príspevky bez ohľadu na ich počet zdieľaní stream_entries: sensitive_content: Senzitívny obsah tags: @@ -1309,18 +1371,25 @@ sk: time: formats: default: "%b %d, %R, %H:%M" + with_time_zone: "%b %d, %Y, %H:%M %Z" translation: errors: too_many_requests: V poslednej dobe bolo na prekladateľskú službu vykonaných priveľa požiadaviek. two_factor_authentication: - disable: Zakáž - enabled: Dvojfázové overovanie je povolené - enabled_success: Dvojfázové overovanie úspešne povolené - generate_recovery_codes: Vygeneruj zálohové kódy - lost_recovery_codes: Zálohové kódy ti umožnia dostať sa k svojmu účtu ak stratíš telefón. Pokiaľ si stratila svoje zálohové kódy, môžeš si ich tu znovu vygenerovať. Tvoje staré zálohové kódy budú zneplatnené. - recovery_codes: Zálohuj kódy pre obnovu - recovery_codes_regenerated: Zálohové kódy boli úspešne zvova vygenerované - recovery_instructions_html: Keď hocikedy stratíš prístup k svojmu telefónu, môžeš použiť jeden z prístupových kódov nižšie pre obnovenie prístupu k svojmu účtu. Skladuj tieto prístupové kódy na bezpečnom mieste. Napríklad ich môžeš vytlačiť a uložiť ich spolu s inými dôležitými dokumentami. + add: Pridať + disable: Vypnúť dvojstupňové overenie + disabled_success: Dvojstupňové overenie bolo úspešne vypnuté + edit: Upraviť + enabled: Dvojstupňové overovanie je zapnuté + enabled_success: Dvojstupňové overovanie bolo úspešne zapnuté + generate_recovery_codes: Vygenerovať záložné kódy + lost_recovery_codes: Záložné kódy vás umožnia prístup k účtu v prípade straty mobilného telefónu. Pokiaľ ste svoje zálohové kódy stratili, môžete si tu vygenerovať nové. Staré zálohové kódy budú deaktivované. + methods: Metódy dvojstupňového overenia + otp: Overovacia apka + recovery_codes: Zálohovať záložné kódy + recovery_codes_regenerated: Záložné kódy boli úspešne znova vygenerované + recovery_instructions_html: Ak niekedy prídete o prístup k svojmu mobilnému telefónu, prístup k účtu môžete obnoviť použitím jedného zo záložných kódov nižšie. Záložné kódy si bezpečne uložte. Môžete si ich napríklad vytlačiť a založiť k iným dôležitým dokumentom. + webauthn: Bezpečnostné kľúče user_mailer: appeal_approved: action: Nastavenia účtu @@ -1331,7 +1400,7 @@ sk: backup_ready: explanation: Vyžiadal/a si si úplnú zálohu svojho Mastodon účtu. extra: Teraz je pripravená na stiahnutie! - subject: Tvoj archív je pripravený na stiahnutie + subject: Váš archív je pripravený na stiahnutie title: Odber archívu failed_2fa: details: 'Tu sú podrobnosti o pokuse o prihlásenie:' @@ -1349,9 +1418,9 @@ sk: title: delete_statuses: Príspevky vymazané disable: Účet bol zamrazený - mark_statuses_as_sensitive: Príspevky označené za chúlostivé + mark_statuses_as_sensitive: Príspevky označené ako citlivé none: Varovanie - sensitive: Účet označený za chúlostivý + sensitive: Účty označené ako citlivé silence: Účet bol obmedzený suspend: Tvoj účet bol vylúčený welcome: @@ -1360,9 +1429,11 @@ sk: apps_step: Stiahni naše oficiálne aplikácie. apps_title: Mastodon aplikácie edit_profile_action: Prispôsob + edit_profile_step: Naštartuje svoje interakcie vyplnením svojho profilu. edit_profile_title: Prispôsob si svoj profil explanation: Tu nájdeš nejaké tipy do začiatku feature_action: Zisti viac + feature_creativity: Mastodon vám pri tvorbe obsahu a vyjadrovaní sa online umožňuje používať audio, video, obrázky a fotky, opisy pre zleplšenie prístupnosti, ankety, varovania o obsahu, animované profilové fotky, vlastné emoji, upravené náhľady a ďalšie. Nech už chcete zverejňovať svoje vizuálne diela, hudbu či podcasty, Mastodon je tu pre vás. follow_action: Nasleduj follow_title: Prispôsob svoj domáci kanál follows_title: Koho nasledovať @@ -1371,10 +1442,15 @@ sk: subject: Vitaj na Mastodone title: Vitaj na palube, %{name}! users: - follow_limit_reached: Nemôžeš nasledovať viac ako %{limit} ľudí + follow_limit_reached: Nemôžete sledovať viac ako %{limit} ľudí invalid_otp_token: Neplatný kód pre dvojfaktorovú autentikáciu otp_lost_help_html: Pokiaľ si stratil/a prístup k obom, môžeš dať vedieť %{email} rate_limited: Príliš veľa pokusov o overenie, skús to znova neskôr. signed_in_as: 'Prihlásená/ý ako:' verification: + extra_instructions_html: Tip: Odkaz na vašom webe môže byť neviditeľný. Najdôležitejšia časť je rel="me", zabraňuje tomu, že sa za vás bude niekto vydávať na weboch s obsahom generovaným používateľmi. V záhlaví stránky môžete dokonca namiesto tagu a použiť tag link, ale kód HTML musí byť prístupný bez potreby spustenia JavaScriptu. + here_is_how: Ako na to + hint_html: "Každý na Mastodone môže overiť svoju totožnosť. Okamžite, zadarmo a navždy s využitím otvorených webových štandardov. Potrebujete len svoju vlastnú webovú stránku. Keď odkaz na ňu uvediete vo svojom profile, skontrolujeme, či je prepojená s vaším profilom a úspešné overenie zvýrazníme vizuálnym indikátorom." + instructions_html: Skopírujte kód nižšie a vložte ho do kódu HTML svojho webu. Potom pridajte svoju webovú stránku do jedného z extra polí v karte Úprava profilu a uložte zmeny. verification: Overenie + website_verification: Overenie webu diff --git a/config/locales/sl.yml b/config/locales/sl.yml index 123e8c47c07..3b957a1569a 100644 --- a/config/locales/sl.yml +++ b/config/locales/sl.yml @@ -1145,10 +1145,7 @@ sl: hint_html: Če se želite preseliti iz drugega računa v tega, lahko tukaj ustvarite vzdevek, ki je potreben, preden lahko nadaljujete s selitvijo sledilcev iz starega računa v tega. To dejanje je samo po sebi neškodljivo in povratno. Selitev računa sprožite iz starega računa. remove: Razveži vzdevek appearance: - advanced_web_interface: Napredni spletni vmesnik - advanced_web_interface_hint: 'Če želite uporabiti celotno širino zaslona, vam napredni spletni vmesnik omogoča, da si nastavite več različnih stolpcev in da si hkrati ogledate toliko informacij, kot želite: domačo stran, obvestila, združeno časovnico, poljubno število seznamov in ključnikov.' animations_and_accessibility: Animacije in dostopnost - confirmation_dialogs: Potrditvena okna discovery: Odkrito localization: body: Mastodon prevajamo prostovoljci. diff --git a/config/locales/sq.yml b/config/locales/sq.yml index 4b1cf77cb6c..7842a7569f7 100644 --- a/config/locales/sq.yml +++ b/config/locales/sq.yml @@ -190,6 +190,7 @@ sq: create_relay: Krijoni Rele create_unavailable_domain: Krijo Përkatësi të Papërdorshme create_user_role: Krijoni Rol + create_username_block: Krijoni Rregull Emrash Përdoruesish demote_user: Zhgradoje Përdoruesin destroy_announcement: Fshije Lajmërimin destroy_canonical_email_block: Fshini Bllokim Email-esh @@ -203,6 +204,7 @@ sq: destroy_status: Fshi Gjendje destroy_unavailable_domain: Fshi Përkatësi të Papërdorshme destroy_user_role: Asgjësoje Rolin + destroy_username_block: Fshini Rregull Emrash Përdoruesish disable_2fa_user: Çaktivizo 2FA-në disable_custom_emoji: Çaktivizo Emotikon Vetjak disable_relay: Çaktivizoje Relenë @@ -237,6 +239,7 @@ sq: update_report: Përditësoni Raportimin update_status: Përditëso Gjendjen update_user_role: Përditësoni Rol + update_username_block: Përditësoni Rregull Emrash Përdoruesish actions: approve_appeal_html: "%{name} miratoi apelim vendimi moderimi nga %{target}" approve_user_html: "%{name} miratoi regjistrim nga %{target}" @@ -255,6 +258,7 @@ sq: create_relay_html: "%{name} krijoi një rele %{target}" create_unavailable_domain_html: "%{name} ndali dërgimin drejt përkatësisë %{target}" create_user_role_html: "%{name} krijoi rolin %{target}" + create_username_block_html: "%{name} shtoi rregull për emra përdoruesish që përmbajnë %{target}" demote_user_html: "%{name} zhgradoi përdoruesin %{target}" destroy_announcement_html: "%{name} fshiu lajmërimin për %{target}" destroy_canonical_email_block_html: "%{name} zhbllokoi email me hashin %{target}" @@ -268,6 +272,7 @@ sq: destroy_status_html: "%{name} hoqi gjendje nga %{target}" destroy_unavailable_domain_html: "%{name} rinisi dërgimin drejt përkatësisë %{target}" destroy_user_role_html: "%{name} fshiu rolin %{target}" + destroy_username_block_html: "%{name} hoqi rregull për emra përdoruesish që përmbajnë %{target}" disable_2fa_user_html: "%{name} çaktivizoi domosdoshmërinë për dyfaktorësh për përdoruesin %{target}" disable_custom_emoji_html: "%{name} çaktivizoi emoxhin %{target}" disable_relay_html: "%{name} çaktivizoi relenë %{target}" @@ -302,6 +307,7 @@ sq: update_report_html: "%{name} përditësoi raportimin %{target}" update_status_html: "%{name} përditësoi gjendjen me %{target}" update_user_role_html: "%{name} ndryshoi rolin për %{target}" + update_username_block_html: "%{name} përditësoi rregull për emra përdoruesish që përmbajnë %{target}" deleted_account: fshiu llogarinë empty: S’u gjetën regjistra. filter_by_action: Filtroji sipas veprimit @@ -505,6 +511,7 @@ sq: select_capabilities: Përzgjidhni Aftësi sign_in: Hyni status: Gjendje + title: Shërbyes Shërbimesh Ndihmëse Fediversi title: FASP follow_recommendations: description_html: "Rekomandimet për ndjekje ndihmojnë përdoruesit e rinj të gjejnë shpejt lëndë me interes. Kur një përdorues nuk ka ndërvepruar mjaftueshëm me të tjerët, që të formohen rekomandime të personalizuara ndjekjeje, rekomandohen këto llogari. Ato përzgjidhen çdo ditë, prej një përzierje llogarish me shkallën më të lartë të angazhimit dhe numrin më të lartë të ndjekësve vendorë për një gjuhë të dhënë." @@ -835,6 +842,10 @@ sq: all: Për këdo disabled: Për askënd users: Për përdorues vendorë që kanë bërë hyrjen + feed_access: + modes: + authenticated: Vetëm përdorues të mirëfilltësuar + public: Kushdo registrations: moderation_recommandation: Ju lutemi, sigurohuni si keni një ekip adekuat dhe reagues moderimi, përpara se të hapni regjistrimet për këdo! preamble: Kontrolloni cilët mund të krijojnë llogari në shërbyesin tuaj. @@ -1075,6 +1086,25 @@ sq: other: Përdorur nga %{count} vetë gjatë javës së kaluar title: Rekomandime & Prirje trending: Në modë + username_blocks: + add_new: Shtoni të ri + block_registrations: Blloko regjistrimet + comparison: + contains: Përmban + equals: Është baras me + contains_html: Përmban %{string} + created_msg: U krijua me sukses rregull emrash përdoruesish + delete: Fshije + edit: + title: Përpunoni rregull emrash përdoruesi + matches_exactly_html: Baras me %{string} + new: + create: Krijoni rregull + title: Krijoni rregull të ri emrash përdoruesish + no_username_block_selected: S’u ndryshua ndonjë rregull emrash përdoruesishm ngaqë s’u përzgjodh ndonjë + not_permitted: Jo i lejuar + title: Rregulla emrash përdoruesish + updated_msg: Rregulli i emrave të përdoruesve u përditësua me sukses warning_presets: add_new: Shtoni të ri delete: Fshije @@ -1147,10 +1177,7 @@ sq: hint_html: Nëse doni të kaloni nga një llogari tjetër në këtë këtu, këtu mund të krijoni një alias, i cili është i domosdoshëm përpara se të ecni më tej me kalimin e ndjekësve prej llogarisë së vjetër te kjo këtu. Ky veprim, në vetvete, është i padëmshëm dhe i prapakthyeshëm. Migrimi i llogarisë fillohet prej llogarisë së vjetër. remove: Hiqe aliasin appearance: - advanced_web_interface: Ndërfaqe web e thelluar - advanced_web_interface_hint: 'Nëse doni të shfrytëzoni krejt gjerësinë e ekranit tuaj, ndërfaqja e thelluar web ju lejon të formësoni shumë shtylla për të parë në të njëjtën kohë aq hollësi sa doni: Kreu, njoftime, rrjedhë kohore të federuarash, çfarëdo numri listash dhe hashtag-ësh.' animations_and_accessibility: Animacione dhe përdorim nga persona me aftësi të kufizuara - confirmation_dialogs: Dialogë ripohimesh discovery: Zbulim localization: body: Mastodon-i përkthehet nga vullnetarë. @@ -1548,6 +1575,13 @@ sq: expires_at: Skadon më uses: Përdorime title: Ftoni njerëz + link_preview: + author_html: Nga %{name} + potentially_sensitive_content: + action: Klikoni për shfaqje + confirm_visit: Jeni i sigurt se doni të hapet kjo lidhje? + hide_button: Fshihe + label: Lëndë potencalisht me spec lists: errors: limit: Keni mbërritur në numrin maksimum të listave @@ -1648,6 +1682,10 @@ sq: title: Përmendje e re poll: subject: Përfundoi një pyetësor nga %{name} + quote: + body: 'Postimi juaj u citua nga %{name}:' + subject: "%{name} citoi postimin tuaj" + title: Citim i ri reblog: body: 'Gjendja juaj u përforcua nga %{name}:' subject: "%{name} përforcoi gjendjen tuaj" @@ -1696,6 +1734,9 @@ sq: self_vote: S’mund të votoni në pyetësorët tuaj too_few_options: duhet të ketë më tepër se një element too_many_options: s’mund të përmbajë më tepër se %{max} elementë + vote: Votoni + posting_defaults: + explanation: Këto rregullime do të përdoren si parazgjedhje, kur krijoni postime të reja, por mund t’i përpunoni për postim, brenda hartuesit. preferences: other: Tjetër posting_defaults: Parazgjedhje postimesh @@ -1851,6 +1892,9 @@ sq: other: "%{count} video" boosted_from_html: Përforcuar nga %{acct_link} content_warning: 'Sinjalizim lënde: %{warning}' + content_warnings: + hide: Fshihe postimin + show: Shfaq më tepër default_language: Njësoj me gjuhën e ndërfaqes disallowed_hashtags: one: 'përmbante një hashtag të palejuar: %{tags}' @@ -1858,15 +1902,24 @@ sq: edited_at_html: Përpunuar më %{date} errors: in_reply_not_found: Gjendja të cilës po provoni t’i përgjigjeni s’duket se ekziston. + quoted_status_not_found: Postimi që po rrekeni të citoni nuk duket se ekziston. over_character_limit: u tejkalua kufi shenjash prej %{max} pin_errors: direct: Postimet që janë të dukshme vetëm për përdoruesit e përmendur s’mund të fiksohen limit: Keni fiksuar tashmë numrin maksimum të mesazheve ownership: S’mund të fiksohen mesazhet e të tjerëve reblog: S’mund të fiksohet një përforcim + quote_policies: + followers: Vetëm ndjekës + nobody: Thjesht unë + public: Cilido title: '%{name}: "%{quote}"' visibilities: + direct: Përmendje private + private: Vetëm ndjekës public: Publike + public_long: Cilido që hyn e del në Mastodon + unlisted_long: Fshehur nga përfundime kërkimi në Mastodon, rrjedha kohore gjërash në modë dhe publike statuses_cleanup: enabled: Fshi automatikisht postime të vjetra enabled_hint: Fshin automatikisht postimet tuaja, pasi mbërrijnë një prag të caktuar moshe, hiq rastin kur ka përputhje me një nga përjashtimet më poshtë diff --git a/config/locales/sr-Latn.yml b/config/locales/sr-Latn.yml index 3173aa34384..9f422b058b6 100644 --- a/config/locales/sr-Latn.yml +++ b/config/locales/sr-Latn.yml @@ -1003,10 +1003,7 @@ sr-Latn: hint_html: Ako želite da se preselite sa drugog naloga na ovaj, ovde možete napraviti pseudonim, koji je neophodan pre nego što možete nastaviti sa prebacivanjem pratilaca sa starog naloga na ovaj. Ova radnja sama po sebi je bezopasna i reverzibilna. Preseljenje naloga se inicira sa starog naloga. remove: Odveži pseudonim appearance: - advanced_web_interface: Napredno veb okruženje - advanced_web_interface_hint: 'Ako želite da iskoristite celu širinu ekrana, napredno veb okruženje vam omogućuje da konfigurišete mnogo različitih kolona da biste videli onoliko informacija u isto vreme koliko želite: početnu stranicu, obaveštenja, združenu vremensku liniju, bilo koji broj lista i heš oznaka.' animations_and_accessibility: Animacije i pristupačnost - confirmation_dialogs: Dijalozi potvrde discovery: Otkrivanje localization: body: Mastodon prevode dobrovoljci. diff --git a/config/locales/sr.yml b/config/locales/sr.yml index 9fc9ed255f7..b8d3ad1fc14 100644 --- a/config/locales/sr.yml +++ b/config/locales/sr.yml @@ -1033,10 +1033,7 @@ sr: hint_html: Ако желите да се преселите са другог налога на овај, овде можете направити псеудоним, који је неопходан пре него што можете наставити са пребацивањем пратилаца са старог налога на овај. Ова радња сама по себи је безопасна и реверзибилна. Пресељење налога се иницира са старог налога. remove: Одвежи псеудоним appearance: - advanced_web_interface: Напредно веб окружење - advanced_web_interface_hint: 'Ако желите да искористите целу ширину екрана, напредно веб окружење вам омогућује да конфигуришете много различитих колона да бисте видели онолико информација у исто време колико желите: почетну страницу, обавештења, здружену временску линију, било који број листа и хеш ознака.' animations_and_accessibility: Анимације и приступачност - confirmation_dialogs: Дијалози потврде discovery: Откривање localization: body: Mastodon преводе добровољци. diff --git a/config/locales/sv.yml b/config/locales/sv.yml index 4a844f8a941..df222cf147a 100644 --- a/config/locales/sv.yml +++ b/config/locales/sv.yml @@ -1182,10 +1182,7 @@ sv: hint_html: Om du vill flytta från ett annat konto till detta kan du skapa ett alias här, detta krävs innan du kan fortsätta med att flytta följare från det gamla kontot till detta. Denna åtgärd är ofarlig och kan ångras. Kontomigreringen initieras från det gamla kontot.. remove: Avlänka alias appearance: - advanced_web_interface: Avancerat webbgränssnitt - advanced_web_interface_hint: 'Om du vill utnyttja hela skärmens bredd så kan du i det avancerade webbgränssnittet ställa in många olika kolumner för att se så mycket information samtidigt som du vill: Hem, notiser, federerad tidslinje, valfritt antal listor och hashtaggar.' animations_and_accessibility: Animationer och tillgänglighet - confirmation_dialogs: Bekräftelsedialoger discovery: Upptäck localization: body: Mastodon översätts av volontärer. diff --git a/config/locales/th.yml b/config/locales/th.yml index 9f4aeab65ff..46236daa91e 100644 --- a/config/locales/th.yml +++ b/config/locales/th.yml @@ -1091,10 +1091,7 @@ th: hint_html: หากคุณต้องการย้ายจากบัญชีอื่นไปยังบัญชีนี้ ที่นี่คุณสามารถสร้างนามแฝง ซึ่งจำเป็นก่อนที่คุณจะสามารถดำเนินการต่อด้วยการย้ายผู้ติดตามจากบัญชีเก่าไปยังบัญชีนี้ การกระทำนี้โดยตัวการกระทำเอง ไม่เป็นอันตรายและย้อนกลับได้ การโยกย้ายบัญชีเริ่มต้นจากบัญชีเก่า remove: เลิกเชื่อมโยงนามแฝง appearance: - advanced_web_interface: ส่วนติดต่อเว็บขั้นสูง - advanced_web_interface_hint: 'หากคุณต้องการใช้ประโยชน์จากความกว้างหน้าจอทั้งหมดของคุณ ส่วนติดต่อเว็บขั้นสูงอนุญาตให้คุณกำหนดค่าคอลัมน์ต่าง ๆ จำนวนมากเพื่อให้เห็นข้อมูลได้มากในเวลาเดียวกันเท่าที่คุณต้องการ: หน้าแรก, การแจ้งเตือน, เส้นเวลาที่ติดต่อกับภายนอก, รายการและแฮชแท็กจำนวนเท่าใดก็ได้' animations_and_accessibility: ภาพเคลื่อนไหวและการช่วยการเข้าถึง - confirmation_dialogs: กล่องโต้ตอบการยืนยัน discovery: การค้นพบ localization: body: Mastodon ได้รับการแปลโดยอาสาสมัคร diff --git a/config/locales/tr.yml b/config/locales/tr.yml index 50319622df6..547cb5d30c8 100644 --- a/config/locales/tr.yml +++ b/config/locales/tr.yml @@ -848,6 +848,10 @@ tr: all: Herkes için disabled: Hiç kimseye users: Oturum açan yerel kullanıcılara + feed_access: + modes: + authenticated: Sadece yetkilendirilmiş kullanıcılar + public: Herkes registrations: moderation_recommandation: Lütfen kayıtları herkese açmadan önce yeterli ve duyarlı bir denetleyici ekibine sahip olduğunuzdan emin olun! preamble: Sunucunuzda kimin hesap oluşturabileceğini denetleyin. @@ -1182,10 +1186,7 @@ tr: hint_html: Başka bir hesaptan bu hesaba taşınmak istiyorsanız, takipçileri eski hesaptan bu hesaba taşımadan önce gerekli olan takma adı burada oluşturabilirsiniz. Bu eylem kendi başına zararsızdır ve geri döndürülebilir. Hesap taşıma işlemi eski hesaptan başlatılır. remove: Takma adların bağlantısını kaldır appearance: - advanced_web_interface: Gelişmiş web arayüzü - advanced_web_interface_hint: 'Tüm ekran genişliğinizden yararlanmak istiyorsanız, gelişmiş web arayüzü istediğiniz kadar bilgi görecek kadar çok sayıda farklı sütunu yapılandırmanıza olanak tanır: Anasayfa, bildirimler, birleşik zaman çizelgesi, istediğiniz sayıda liste ve etiket.' animations_and_accessibility: Animasyonlar ve erişilebilirlik - confirmation_dialogs: Onay iletişim kutuları discovery: Keşfet localization: body: Mastodon, gönüllüler tarafından çevrilmektedir. @@ -1587,6 +1588,13 @@ tr: expires_at: Bitiş tarihi uses: Kullanım title: İnsanları davet et + link_preview: + author_html: 'Yazan: %{name}' + potentially_sensitive_content: + action: Göstermek için tıklayın + confirm_visit: Bu bağlantıyı açmak istediğinizden emin misiniz? + hide_button: Gizle + label: Potansiyel olarak hassas içerik lists: errors: limit: Azami liste sayısına ulaştınız @@ -1897,6 +1905,9 @@ tr: other: "%{count} videolar" boosted_from_html: "%{acct_link} kişisinden yeniden paylaştı" content_warning: 'İçerik uyarısı: %{warning}' + content_warnings: + hide: Gönderiyi gizle + show: Daha fazlasını göster default_language: Arayüz diliyle aynı disallowed_hashtags: one: 'izin verilmeyen bir etiket içeriyordu: %{tags}' diff --git a/config/locales/uk.yml b/config/locales/uk.yml index 7afa383dc06..1d667b9eab4 100644 --- a/config/locales/uk.yml +++ b/config/locales/uk.yml @@ -1160,10 +1160,7 @@ uk: hint_html: Якщо ви збираєтеся мігрувати з іншого облікового запису на цей, ви можете налаштувати псевдонім, який потрібен для перенесення підписок зі старою облікового запису. Ця дія сама по собі нешкідлива і її можна скасувати. Міграція облікового запису починається зі старого облікового запису. remove: Від'єднати псевдонім appearance: - advanced_web_interface: Розширений вебінтерфейс - advanced_web_interface_hint: 'Якщо ви бажаєте використовувати всю ширину вашого екрана, розширений вебінтерфейс дає змогу налаштовувати одночасний показ багатьох стовпчиків: головна, сповіщення, федеративна стрічка, будь-яка кількість списків і хештеґів.' animations_and_accessibility: Анімація та доступність - confirmation_dialogs: Діалоги підтвердження discovery: Виявлення localization: body: Mastodon перекладено волонтерами. diff --git a/config/locales/vi.yml b/config/locales/vi.yml index 0af555c913e..ffad1d1cbcc 100644 --- a/config/locales/vi.yml +++ b/config/locales/vi.yml @@ -834,6 +834,10 @@ vi: all: Tới mọi người disabled: Không ai users: Để đăng nhập người cục bộ + feed_access: + modes: + authenticated: Chỉ những người dùng đã xác minh + public: Mọi người registrations: moderation_recommandation: Vui lòng đảm bảo rằng bạn có một đội ngũ kiểm duyệt và phản ứng nhanh trước khi mở đăng ký cho mọi người! preamble: Kiểm soát những ai có thể tạo tài khoản trên máy chủ của bạn. @@ -1163,10 +1167,7 @@ vi: hint_html: Nếu bạn muốn chuyển từ máy chủ khác sang máy chủ này, bắt buộc bạn phải tạo tên người dùng mới thì mới có thể tiến hành chuyển được người theo dõi. Hành động này không ảnh hưởng gì và có thể đảo ngược. Việc di chuyển tài khoản được bắt đầu từ tài khoản cũ. remove: Bỏ liên kết bí danh appearance: - advanced_web_interface: Bố cục - advanced_web_interface_hint: Xếp giao diện thành nhiều cột, hợp với màn hình rộng. animations_and_accessibility: Hiệu ứng - confirmation_dialogs: Hộp thoại xác nhận discovery: Khám phá localization: body: Mastodon được dịch bởi tình nguyện viên. @@ -1548,6 +1549,13 @@ vi: expires_at: Hết hạn uses: Sử dụng title: Mời bạn bè + link_preview: + author_html: Bởi %{name} + potentially_sensitive_content: + action: Nhấn để xem + confirm_visit: Bạn có chắc muốn mở liên kết này? + hide_button: Ẩn + label: Có khả năng là nội dung nhạy cảm lists: errors: limit: Bạn đã đạt đến số lượng danh sách tối đa @@ -1855,6 +1863,9 @@ vi: other: "%{count} video" boosted_from_html: Đã đăng lại từ %{acct_link} content_warning: 'Cảnh báo nội dung: %{warning}' + content_warnings: + hide: Ẩn tút + show: Mở rộng default_language: Giống giao diện disallowed_hashtags: other: 'chứa các hashtag bị cấm: %{tags}' diff --git a/config/locales/zh-CN.yml b/config/locales/zh-CN.yml index 3200bdfd23e..ba114cfbcf2 100644 --- a/config/locales/zh-CN.yml +++ b/config/locales/zh-CN.yml @@ -834,6 +834,10 @@ zh-CN: all: 对所有人 disabled: 不对任何人 users: 对已登录的本站用户 + feed_access: + modes: + authenticated: 仅已登录用户 + public: 所有人 registrations: moderation_recommandation: 在向所有人开放注册之前,请确保你拥有一个人手足够且反应迅速的管理团队! preamble: 控制谁可以在你的服务器上创建账号。 @@ -1163,10 +1167,7 @@ zh-CN: hint_html: 如果你想从另一个账号迁移到这里,可以先在这里创建一个别名。要把旧账号的关注者迁移过来,这一步是必须的。设置别名的操作是无害且可撤销的账号迁移的操作会从旧账号发起。 remove: 取消关联别名 appearance: - advanced_web_interface: 高级 Web 界面 - advanced_web_interface_hint: 在高级网页界面支持自定义多栏显示,你可以利用整个屏幕的宽度,同时查看首页、通知、跨站时间线及任意数量的列表和话题。 animations_and_accessibility: 动画与可访问性 - confirmation_dialogs: 确认对话框 discovery: 发现 localization: body: Mastodon 由志愿者翻译。 @@ -1548,6 +1549,13 @@ zh-CN: expires_at: 失效时间 uses: 已使用次数 title: 邀请用户 + link_preview: + author_html: 来自 %{name} + potentially_sensitive_content: + action: 点击查看 + confirm_visit: 您确定要打开此链接吗? + hide_button: 隐藏 + label: 可能为敏感内容 lists: errors: limit: 你已达到列表数量的上限 @@ -1855,6 +1863,9 @@ zh-CN: other: "%{count} 段视频" boosted_from_html: 转嘟自 %{acct_link} content_warning: 内容警告:%{warning} + content_warnings: + hide: 隐藏嘟文 + show: 显示更多 default_language: 与界面显示语言相同 disallowed_hashtags: other: 包含以下被禁止的话题:%{tags} @@ -1877,7 +1888,7 @@ zh-CN: direct: 私下提及 private: 仅关注者 public: 公开 - public_long: 所有人(无论是否注册了 Mastodon) + public_long: 任何人(无论是否注册了 Mastodon) unlisted: 悄悄公开 unlisted_long: 不显示在Mastodon的搜索结果、热门趋势、公共时间线上 statuses_cleanup: diff --git a/config/locales/zh-HK.yml b/config/locales/zh-HK.yml index c0e6029819f..6045808fee3 100644 --- a/config/locales/zh-HK.yml +++ b/config/locales/zh-HK.yml @@ -1001,10 +1001,7 @@ zh-HK: hint_html: 如果你想由另一個帳戶轉移到此帳號,你可以在此處創建別名 (alias),然後系統容許你將關注者由舊帳戶轉移到此帳號。此操作是無害且可以還原的帳號遷移程序,需要在舊帳號啟動。 remove: 取消連結別名 (Alias) appearance: - advanced_web_interface: 進階網頁介面 - advanced_web_interface_hint: 如果你想善用整個螢幕闊度,你可以啟用「進階網頁介面」,在畫面上配置多個不同的欄目,讓你能根據需要,同時查看盡可能多的信息,支援的欄位包括:主頁、通知、其他站點和任何的列表和標籤。 animations_and_accessibility: 動畫和輔助功能 - confirmation_dialogs: 確認對話框 discovery: 探索 localization: body: Mastodon 是由志願者翻譯的。 diff --git a/config/locales/zh-TW.yml b/config/locales/zh-TW.yml index 101ea1850a2..ea0ff5164c0 100644 --- a/config/locales/zh-TW.yml +++ b/config/locales/zh-TW.yml @@ -836,6 +836,10 @@ zh-TW: all: 至任何人 disabled: 至沒有人 users: 套用至所有登入的本站使用者 + feed_access: + modes: + authenticated: 僅限已登入之使用者 + public: 任何人 registrations: moderation_recommandation: 對所有人開放註冊之前,請確保您有人手充足且反應靈敏的管理員團隊! preamble: 控制誰能於您伺服器上建立帳號。 @@ -1165,10 +1169,7 @@ zh-TW: hint_html: 如果想由其他帳號轉移至此帳號,您能於此處新增別名,稍後系統將容許您將跟隨者由舊帳號轉移至此。此項作業是無害且可復原的帳號的遷移程序需要於舊帳號啟動。 remove: 取消連結別名 appearance: - advanced_web_interface: 進階網頁介面 - advanced_web_interface_hint: 進階網頁介面能使您設定許多不同的欄位來善用螢幕空間,依需要同時查看許多不同的資訊如:首頁、通知、聯邦宇宙時間軸、任意數量的列表與主題標籤。 animations_and_accessibility: 動畫與無障礙設定 - confirmation_dialogs: 確認對話框 discovery: 探索 localization: body: Mastodon 是由志願者所翻譯。 @@ -1550,6 +1551,13 @@ zh-TW: expires_at: 失效時間 uses: 已使用次數 title: 邀請使用者 + link_preview: + author_html: 來自 %{name} + potentially_sensitive_content: + action: 點擊以顯示 + confirm_visit: 您確定要開啟此連結嗎? + hide_button: 隱藏 + label: 可能為敏感內容 lists: errors: limit: 您所建立之列表數量已達上限 @@ -1857,6 +1865,9 @@ zh-TW: other: "%{count} 段影片" boosted_from_html: 轉嘟自 %{acct_link} content_warning: 內容警告: %{warning} + content_warnings: + hide: 隱藏嘟文 + show: 顯示更多 default_language: 與介面語言相同 disallowed_hashtags: other: 含有不得使用的標籤: %{tags} diff --git a/config/settings.yml b/config/settings.yml index 7d2f0a00c07..c6478e57d46 100644 --- a/config/settings.yml +++ b/config/settings.yml @@ -12,7 +12,10 @@ defaults: &defaults registrations_mode: 'none' profile_directory: true closed_registrations_message: '' - timeline_preview: true + local_live_feed_access: 'public' + remote_live_feed_access: 'public' + local_topic_feed_access: 'public' + remote_topic_feed_access: 'public' show_staff_badge: true preview_sensitive_media: false noindex: false @@ -29,7 +32,7 @@ defaults: &defaults require_invite_text: false backups_retention_period: 7 captcha_enabled: false - allow_referer_origin: false + allow_referrer_origin: false development: <<: *defaults diff --git a/db/migrate/20251002140103_migrate_timeline_preview_setting.rb b/db/migrate/20251002140103_migrate_timeline_preview_setting.rb new file mode 100644 index 00000000000..4d180bd8f39 --- /dev/null +++ b/db/migrate/20251002140103_migrate_timeline_preview_setting.rb @@ -0,0 +1,21 @@ +# frozen_string_literal: true + +class MigrateTimelinePreviewSetting < ActiveRecord::Migration[8.0] + class Setting < ApplicationRecord; end + + def up + setting = Setting.find_by(var: 'timeline_preview') + return unless setting.present? && setting.attributes['value'].present? + + value = YAML.safe_load(setting.attributes['value'], permitted_classes: [ActiveSupport::HashWithIndifferentAccess, Symbol]) + + Setting.upsert_all( + %w(local_live_feed_access remote_live_feed_access local_topic_feed_access remote_topic_feed_access).map do |var| + { var: var, value: value ? "--- public\n" : "--- authenticated\n" } + end, + unique_by: :var + ) + end + + def down; end +end diff --git a/db/migrate/20251007100627_add_index_follows_on_target_account_id_and_account_id.rb b/db/migrate/20251007100627_add_index_follows_on_target_account_id_and_account_id.rb new file mode 100644 index 00000000000..23c08d2d061 --- /dev/null +++ b/db/migrate/20251007100627_add_index_follows_on_target_account_id_and_account_id.rb @@ -0,0 +1,9 @@ +# frozen_string_literal: true + +class AddIndexFollowsOnTargetAccountIdAndAccountId < ActiveRecord::Migration[8.0] + disable_ddl_transaction! + + def change + add_index :follows, [:target_account_id, :account_id], algorithm: :concurrently + end +end diff --git a/db/migrate/20251007100813_remove_index_follows_on_target_account_id.rb b/db/migrate/20251007100813_remove_index_follows_on_target_account_id.rb new file mode 100644 index 00000000000..142086f3582 --- /dev/null +++ b/db/migrate/20251007100813_remove_index_follows_on_target_account_id.rb @@ -0,0 +1,9 @@ +# frozen_string_literal: true + +class RemoveIndexFollowsOnTargetAccountId < ActiveRecord::Migration[8.0] + disable_ddl_transaction! + + def change + remove_index :follows, [:target_account_id], algorithm: :concurrently + end +end diff --git a/db/migrate/20251007142305_change_defaults_for_account_id_scheme.rb b/db/migrate/20251007142305_change_defaults_for_account_id_scheme.rb new file mode 100644 index 00000000000..6c07236968a --- /dev/null +++ b/db/migrate/20251007142305_change_defaults_for_account_id_scheme.rb @@ -0,0 +1,7 @@ +# frozen_string_literal: true + +class ChangeDefaultsForAccountIdScheme < ActiveRecord::Migration[8.0] + def change + change_column_default :accounts, :id_scheme, from: 0, to: 1 + end +end diff --git a/db/schema.rb b/db/schema.rb index 78e75f787af..8910bac36a8 100644 --- a/db/schema.rb +++ b/db/schema.rb @@ -10,7 +10,7 @@ # # It's strongly recommended that you check this file into your version control system. -ActiveRecord::Schema[8.0].define(version: 2025_09_24_170259) do +ActiveRecord::Schema[8.0].define(version: 2025_10_07_142305) do # These are extensions that must be enabled in order to support this database enable_extension "pg_catalog.plpgsql" @@ -199,7 +199,7 @@ ActiveRecord::Schema[8.0].define(version: 2025_09_24_170259) do t.boolean "indexable", default: false, null: false t.string "attribution_domains", default: [], array: true t.string "following_url", default: "", null: false - t.integer "id_scheme", default: 0 + t.integer "id_scheme", default: 1 t.index "(((setweight(to_tsvector('simple'::regconfig, (display_name)::text), 'A'::\"char\") || setweight(to_tsvector('simple'::regconfig, (username)::text), 'B'::\"char\")) || setweight(to_tsvector('simple'::regconfig, (COALESCE(domain, ''::character varying))::text), 'C'::\"char\")))", name: "search_index", using: :gin t.index "lower((username)::text), COALESCE(lower((domain)::text), ''::text)", name: "index_accounts_on_username_and_domain_lower", unique: true t.index ["domain", "id"], name: "index_accounts_on_domain_and_id" @@ -571,7 +571,7 @@ ActiveRecord::Schema[8.0].define(version: 2025_09_24_170259) do t.boolean "notify", default: false, null: false t.string "languages", array: true t.index ["account_id", "target_account_id"], name: "index_follows_on_account_id_and_target_account_id", unique: true - t.index ["target_account_id"], name: "index_follows_on_target_account_id" + t.index ["target_account_id", "account_id"], name: "index_follows_on_target_account_id_and_account_id" end create_table "generated_annual_reports", force: :cascade do |t| diff --git a/docker-compose.yml b/docker-compose.yml index e0159beae70..3cc3b7f4880 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -59,7 +59,7 @@ services: web: # You can uncomment the following line if you want to not use the prebuilt image, for example if you have local code changes # build: . - image: ghcr.io/mastodon/mastodon:v4.4.4 + image: ghcr.io/mastodon/mastodon:v4.4.7 restart: always env_file: .env.production command: bundle exec puma -C config/puma.rb @@ -83,7 +83,7 @@ services: # build: # dockerfile: ./streaming/Dockerfile # context: . - image: ghcr.io/mastodon/mastodon-streaming:v4.4.4 + image: ghcr.io/mastodon/mastodon-streaming:v4.4.7 restart: always env_file: .env.production command: node ./streaming/index.js @@ -102,7 +102,7 @@ services: sidekiq: # You can uncomment the following line if you want to not use the prebuilt image, for example if you have local code changes # build: . - image: ghcr.io/mastodon/mastodon:v4.4.4 + image: ghcr.io/mastodon/mastodon:v4.4.7 restart: always env_file: .env.production command: bundle exec sidekiq @@ -115,7 +115,7 @@ services: volumes: - ./public/system:/mastodon/public/system healthcheck: - test: ['CMD-SHELL', "ps aux | grep '[s]idekiq\ 7' || false"] + test: ['CMD-SHELL', "ps aux | grep '[s]idekiq\ [78]' || false"] ## Uncomment to enable federation with tor instances along with adding the following ENV variables ## http_hidden_proxy=http://privoxy:8118 diff --git a/lib/mastodon/cli/accounts.rb b/lib/mastodon/cli/accounts.rb index 1b33f56055a..25e966bd8ea 100644 --- a/lib/mastodon/cli/accounts.rb +++ b/lib/mastodon/cli/accounts.rb @@ -165,14 +165,17 @@ module Mastodon::CLI user.role_id = nil end - password = SecureRandom.hex if options[:reset_password] - user.password = password if options[:reset_password] user.email = options[:email] if options[:email] user.disabled = false if options[:enable] user.disabled = true if options[:disable] user.approved = true if options[:approve] user.disable_two_factor! if options[:disable_2fa] + # Password changes are a little different, as we also need to ensure + # sessions, subscriptions, and access tokens are revoked after changing: + password = SecureRandom.hex if options[:reset_password] + user.change_password!(password) if options[:reset_password] + if user.save user.confirm if options[:confirm] diff --git a/lib/mastodon/version.rb b/lib/mastodon/version.rb index 043f22b28e5..b8f6436fde3 100644 --- a/lib/mastodon/version.rb +++ b/lib/mastodon/version.rb @@ -17,7 +17,7 @@ module Mastodon end def default_prerelease - 'alpha.2' + 'beta.1' end def prerelease diff --git a/package.json b/package.json index 0fd14de6565..16095441d87 100644 --- a/package.json +++ b/package.json @@ -189,9 +189,9 @@ "storybook": "^9.1.1", "stylelint": "^16.19.1", "stylelint-config-prettier-scss": "^1.0.0", - "stylelint-config-standard-scss": "^15.0.1", + "stylelint-config-standard-scss": "^16.0.0", "typescript": "~5.9.0", - "typescript-eslint": "^8.29.1", + "typescript-eslint": "^8.45.0", "vitest": "^3.2.4" }, "resolutions": { diff --git a/spec/controllers/auth/registrations_controller_spec.rb b/spec/controllers/auth/registrations_controller_spec.rb index 04c2d5dbbbb..c7bbe130920 100644 --- a/spec/controllers/auth/registrations_controller_spec.rb +++ b/spec/controllers/auth/registrations_controller_spec.rb @@ -12,11 +12,11 @@ RSpec.describe Auth::RegistrationsController do allow(Rails.configuration.x).to receive(:single_user_mode).and_return(true) end - it 'redirects to root' do + it 'redirects to sign-in' do Fabricate(:account) get path - expect(response).to redirect_to '/' + expect(response).to redirect_to '/auth/sign_in' expect(Rails.configuration.x).to have_received(:single_user_mode) end end @@ -27,10 +27,10 @@ RSpec.describe Auth::RegistrationsController do allow(Rails.configuration.x).to receive(:single_user_mode).and_return(false) end - it 'redirects to root' do + it 'redirects to sign-in' do get path - expect(response).to redirect_to '/' + expect(response).to redirect_to '/auth/sign_in' expect(Rails.configuration.x).to have_received(:single_user_mode) end end diff --git a/spec/controllers/concerns/account_controller_concern_spec.rb b/spec/controllers/concerns/account_controller_concern_spec.rb index df6278a6e98..b5c8c166433 100644 --- a/spec/controllers/concerns/account_controller_concern_spec.rb +++ b/spec/controllers/concerns/account_controller_concern_spec.rb @@ -58,7 +58,7 @@ RSpec.describe AccountControllerConcern do expect(response) .to have_http_status(200) .and have_http_link_header(webfinger_url(resource: account.to_webfinger_s)).for(rel: 'lrdd', type: 'application/jrd+json') - .and have_http_link_header(account_url(account, protocol: :https)).for(rel: 'alternate', type: 'application/activity+json') + .and have_http_link_header(ActivityPub::TagManager.instance.uri_for(account)).for(rel: 'alternate', type: 'application/activity+json') expect(response.body) .to include(account.username) end diff --git a/spec/controllers/follower_accounts_controller_spec.rb b/spec/controllers/follower_accounts_controller_spec.rb index e14ed00e609..dab6aadbaab 100644 --- a/spec/controllers/follower_accounts_controller_spec.rb +++ b/spec/controllers/follower_accounts_controller_spec.rb @@ -49,8 +49,8 @@ RSpec.describe FollowerAccountsController do expect(response.parsed_body) .to include( orderedItems: contain_exactly( - include(follow_from_bob.account.username), - include(follow_from_chris.account.username) + ActivityPub::TagManager.instance.uri_for(follow_from_bob.account), + ActivityPub::TagManager.instance.uri_for(follow_from_chris.account) ), totalItems: eq(2), partOf: be_present diff --git a/spec/controllers/following_accounts_controller_spec.rb b/spec/controllers/following_accounts_controller_spec.rb index fea4d4845c8..666c655d743 100644 --- a/spec/controllers/following_accounts_controller_spec.rb +++ b/spec/controllers/following_accounts_controller_spec.rb @@ -49,8 +49,8 @@ RSpec.describe FollowingAccountsController do expect(response.parsed_body) .to include( orderedItems: contain_exactly( - include(follow_of_bob.target_account.username), - include(follow_of_chris.target_account.username) + ActivityPub::TagManager.instance.uri_for(follow_of_bob.target_account), + ActivityPub::TagManager.instance.uri_for(follow_of_chris.target_account) ), totalItems: eq(2), partOf: be_present diff --git a/spec/lib/activitypub/activity/create_spec.rb b/spec/lib/activitypub/activity/create_spec.rb index 80a5c6907c4..2f2f91e369e 100644 --- a/spec/lib/activitypub/activity/create_spec.rb +++ b/spec/lib/activitypub/activity/create_spec.rb @@ -938,6 +938,30 @@ RSpec.describe ActivityPub::Activity::Create do end end + context 'with an unverifiable quote of a dead post' do + let(:quoted_status) { Fabricate(:status) } + + let(:object_json) do + build_object( + type: 'Note', + content: 'woah what she said is amazing', + quote: { type: 'Tombstone' } + ) + end + + it 'creates a status with an unverified quote' do + expect { subject.perform }.to change(sender.statuses, :count).by(1) + + status = sender.statuses.first + expect(status).to_not be_nil + expect(status.quote).to_not be_nil + expect(status.quote).to have_attributes( + state: 'deleted', + approval_uri: nil + ) + end + end + context 'with an unverifiable unknown post' do let(:unknown_post_uri) { 'https://unavailable.example.com/unavailable-post' } diff --git a/spec/lib/activitypub/forwarder_spec.rb b/spec/lib/activitypub/forwarder_spec.rb new file mode 100644 index 00000000000..f72e3342183 --- /dev/null +++ b/spec/lib/activitypub/forwarder_spec.rb @@ -0,0 +1,61 @@ +# frozen_string_literal: true + +require 'rails_helper' + +RSpec.describe ActivityPub::Forwarder do + subject { described_class.new(account, payload, status) } + + let(:account) { Fabricate(:account) } + let(:remote_account) { Fabricate(:account, domain: 'example.com') } + let(:status) { Fabricate(:status, account: remote_account) } + + let(:signature) { { type: 'RsaSignature2017', signatureValue: 'foo' } } + let(:payload) do + { + '@context': [ + 'https://www.w3.org/ns/activitystreams', + 'https://w3id.org/security/v1', + ], + signature: signature, + type: 'Delete', + object: ActivityPub::TagManager.instance.uri_for(status), + }.deep_stringify_keys + end + + describe '#forwardable?' do + context 'when payload has an inlined signature' do + it 'returns true' do + expect(subject.forwardable?).to be true + end + end + + context 'when payload has an no inlined signature' do + let(:signature) { nil } + + it 'returns true' do + expect(subject.forwardable?).to be false + end + end + end + + describe '#forward!' do + let(:alice) { Fabricate(:account) } + let(:bob) { Fabricate(:account) } + let(:eve) { Fabricate(:account, domain: 'remote1.example.com', inbox_url: 'https://remote1.example.com/users/eve/inbox', protocol: :activitypub) } + let(:mallory) { Fabricate(:account, domain: 'remote2.example.com', inbox_url: 'https://remote2.example.com/users/mallory/inbox', protocol: :activitypub) } + + before do + alice.statuses.create!(reblog: status) + Fabricate(:quote, status: Fabricate(:status, account: bob), quoted_status: status, state: :accepted) + + eve.follow!(alice) + mallory.follow!(bob) + end + + it 'correctly forwards to expected remote followers' do + expect { subject.forward! } + .to enqueue_sidekiq_job(ActivityPub::LowPriorityDeliveryWorker).with(Oj.dump(payload), anything, eve.preferred_inbox_url) + .and enqueue_sidekiq_job(ActivityPub::LowPriorityDeliveryWorker).with(Oj.dump(payload), anything, mallory.preferred_inbox_url) + end + end +end diff --git a/spec/lib/activitypub/tag_manager_spec.rb b/spec/lib/activitypub/tag_manager_spec.rb index 70e084a9c92..cad46ad9032 100644 --- a/spec/lib/activitypub/tag_manager_spec.rb +++ b/spec/lib/activitypub/tag_manager_spec.rb @@ -23,7 +23,7 @@ RSpec.describe ActivityPub::TagManager do describe '#url_for' do context 'with a local account' do - let(:account) { Fabricate(:account) } + let(:account) { Fabricate(:account, id_scheme: :username_ap_id) } it 'returns a string starting with web domain and with the expected path' do expect(subject.url_for(account)) @@ -49,7 +49,8 @@ RSpec.describe ActivityPub::TagManager do end context 'with a local status' do - let(:status) { Fabricate(:status) } + let(:account) { Fabricate(:account, id_scheme: :username_ap_id) } + let(:status) { Fabricate(:status, account: account) } it 'returns a string starting with web domain and with the expected path' do expect(subject.url_for(status)) @@ -58,7 +59,6 @@ RSpec.describe ActivityPub::TagManager do context 'when using a numeric ID based scheme' do let(:account) { Fabricate(:account, id_scheme: :numeric_ap_id) } - let(:status) { Fabricate(:status, account: account) } it 'returns a string starting with web domain and with the expected path' do expect(subject.url_for(status)) @@ -86,7 +86,7 @@ RSpec.describe ActivityPub::TagManager do end context 'with a local account' do - let(:account) { Fabricate(:account) } + let(:account) { Fabricate(:account, id_scheme: :username_ap_id) } it 'returns a string starting with web domain and with the expected path' do expect(subject.uri_for(account)) @@ -112,7 +112,8 @@ RSpec.describe ActivityPub::TagManager do end context 'with a local status' do - let(:status) { Fabricate(:status) } + let(:account) { Fabricate(:account, id_scheme: :username_ap_id) } + let(:status) { Fabricate(:status, account: account) } it 'returns a string starting with web domain and with the expected path' do expect(subject.uri_for(status)) @@ -121,7 +122,6 @@ RSpec.describe ActivityPub::TagManager do context 'when using a numeric ID based scheme' do let(:account) { Fabricate(:account, id_scheme: :numeric_ap_id) } - let(:status) { Fabricate(:status, account: account) } it 'returns a string starting with web domain and with the expected path' do expect(subject.uri_for(status)) @@ -140,7 +140,8 @@ RSpec.describe ActivityPub::TagManager do end context 'with a local conversation' do - let(:status) { Fabricate(:status) } + let(:account) { Fabricate(:account, id_scheme: :username_ap_id) } + let(:status) { Fabricate(:status, account: account) } it 'returns a string starting with web domain and with the expected path' do expect(subject.uri_for(status.conversation)) @@ -149,7 +150,6 @@ RSpec.describe ActivityPub::TagManager do context 'when using a numeric ID based scheme' do let(:account) { Fabricate(:account, id_scheme: :numeric_ap_id) } - let(:status) { Fabricate(:status, account: account) } it 'returns a string starting with web domain and with the expected path' do expect(subject.uri_for(status.conversation)) @@ -181,7 +181,7 @@ RSpec.describe ActivityPub::TagManager do end context 'with a local account' do - let(:account) { Fabricate(:account) } + let(:account) { Fabricate(:account, id_scheme: :username_ap_id) } it 'returns a string starting with web domain and with the expected path' do expect(subject.key_uri_for(account)) @@ -218,7 +218,9 @@ RSpec.describe ActivityPub::TagManager do describe '#approval_uri_for' do context 'with a valid local approval' do - let(:quote) { Fabricate(:quote, state: :accepted) } + let(:quoted_account) { Fabricate(:account, id_scheme: :username_ap_id) } + let(:quoted_status) { Fabricate(:status, account: quoted_account) } + let(:quote) { Fabricate(:quote, state: :accepted, quoted_status: quoted_status) } it 'returns a string with the web domain and expected path' do expect(subject.approval_uri_for(quote)) @@ -227,8 +229,6 @@ RSpec.describe ActivityPub::TagManager do context 'when using a numeric ID based scheme' do let(:quoted_account) { Fabricate(:account, id_scheme: :numeric_ap_id) } - let(:quoted_status) { Fabricate(:status, account: quoted_account) } - let(:quote) { Fabricate(:quote, state: :accepted, quoted_status: quoted_status) } it 'returns a string with the web domain and expected path' do expect(subject.approval_uri_for(quote)) @@ -238,7 +238,9 @@ RSpec.describe ActivityPub::TagManager do end context 'with an unapproved local quote' do - let(:quote) { Fabricate(:quote, state: :rejected) } + let(:quoted_account) { Fabricate(:account, id_scheme: :username_ap_id) } + let(:quoted_status) { Fabricate(:status, account: quoted_account) } + let(:quote) { Fabricate(:quote, state: :rejected, quoted_status: quoted_status) } it 'returns nil' do expect(subject.approval_uri_for(quote)) @@ -247,8 +249,6 @@ RSpec.describe ActivityPub::TagManager do context 'when using a numeric ID based scheme' do let(:quoted_account) { Fabricate(:account, id_scheme: :numeric_ap_id) } - let(:quoted_status) { Fabricate(:status, account: quoted_account) } - let(:quote) { Fabricate(:quote, state: :rejected, quoted_status: quoted_status) } it 'returns nil' do expect(subject.approval_uri_for(quote)) @@ -260,7 +260,7 @@ RSpec.describe ActivityPub::TagManager do context 'with a valid remote approval' do let(:quoted_account) { Fabricate(:account, domain: 'example.com') } let(:quoted_status) { Fabricate(:status, account: quoted_account) } - let(:quote) { Fabricate(:quote, state: :accepted, quoted_status: quoted_status, approval_uri: 'https://example.com/approvals/1') } + let(:quote) { Fabricate(:quote, status: Fabricate(:status), state: :accepted, quoted_status: quoted_status, approval_uri: 'https://example.com/approvals/1') } it 'returns the expected URI' do expect(subject.approval_uri_for(quote)).to eq quote.approval_uri @@ -268,7 +268,9 @@ RSpec.describe ActivityPub::TagManager do end context 'with an unapproved local quote but check_approval override' do - let(:quote) { Fabricate(:quote, state: :rejected) } + let(:quoted_account) { Fabricate(:account, id_scheme: :username_ap_id) } + let(:quoted_status) { Fabricate(:status, account: quoted_account) } + let(:quote) { Fabricate(:quote, state: :rejected, quoted_status: quoted_status) } it 'returns a string with the web domain and expected path' do expect(subject.approval_uri_for(quote, check_approval: false)) @@ -277,8 +279,6 @@ RSpec.describe ActivityPub::TagManager do context 'when using a numeric ID based scheme' do let(:quoted_account) { Fabricate(:account, id_scheme: :numeric_ap_id) } - let(:quoted_status) { Fabricate(:status, account: quoted_account) } - let(:quote) { Fabricate(:quote, state: :rejected, quoted_status: quoted_status) } it 'returns a string with the web domain and expected path' do expect(subject.approval_uri_for(quote, check_approval: false)) @@ -290,7 +290,8 @@ RSpec.describe ActivityPub::TagManager do describe '#replies_uri_for' do context 'with a local status' do - let(:status) { Fabricate(:status) } + let(:account) { Fabricate(:account, id_scheme: :username_ap_id) } + let(:status) { Fabricate(:status, account: account) } it 'returns a string starting with web domain and with the expected path' do expect(subject.replies_uri_for(status)) @@ -299,7 +300,6 @@ RSpec.describe ActivityPub::TagManager do context 'when using a numeric ID based scheme' do let(:account) { Fabricate(:account, id_scheme: :numeric_ap_id) } - let(:status) { Fabricate(:status, account: account) } it 'returns a string starting with web domain and with the expected path' do expect(subject.replies_uri_for(status)) @@ -311,7 +311,8 @@ RSpec.describe ActivityPub::TagManager do describe '#likes_uri_for' do context 'with a local status' do - let(:status) { Fabricate(:status) } + let(:account) { Fabricate(:account, id_scheme: :username_ap_id) } + let(:status) { Fabricate(:status, account: account) } it 'returns a string starting with web domain and with the expected path' do expect(subject.likes_uri_for(status)) @@ -320,7 +321,6 @@ RSpec.describe ActivityPub::TagManager do context 'when using a numeric ID based scheme' do let(:account) { Fabricate(:account, id_scheme: :numeric_ap_id) } - let(:status) { Fabricate(:status, account: account) } it 'returns a string starting with web domain and with the expected path' do expect(subject.likes_uri_for(status)) @@ -332,7 +332,8 @@ RSpec.describe ActivityPub::TagManager do describe '#shares_uri_for' do context 'with a local status' do - let(:status) { Fabricate(:status) } + let(:account) { Fabricate(:account, id_scheme: :username_ap_id) } + let(:status) { Fabricate(:status, account: account) } it 'returns a string starting with web domain and with the expected path' do expect(subject.shares_uri_for(status)) @@ -341,7 +342,6 @@ RSpec.describe ActivityPub::TagManager do context 'when using a numeric ID based scheme' do let(:account) { Fabricate(:account, id_scheme: :numeric_ap_id) } - let(:status) { Fabricate(:status, account: account) } it 'returns a string starting with web domain and with the expected path' do expect(subject.shares_uri_for(status)) @@ -353,7 +353,7 @@ RSpec.describe ActivityPub::TagManager do describe '#following_uri_for' do context 'with a local account' do - let(:account) { Fabricate(:account) } + let(:account) { Fabricate(:account, id_scheme: :username_ap_id) } it 'returns a string starting with web domain and with the expected path' do expect(subject.following_uri_for(account)) @@ -373,7 +373,7 @@ RSpec.describe ActivityPub::TagManager do describe '#followers_uri_for' do context 'with a local account' do - let(:account) { Fabricate(:account) } + let(:account) { Fabricate(:account, id_scheme: :username_ap_id) } it 'returns a string starting with web domain and with the expected path' do expect(subject.followers_uri_for(account)) @@ -400,7 +400,7 @@ RSpec.describe ActivityPub::TagManager do end context 'with a local account' do - let(:account) { Fabricate(:account) } + let(:account) { Fabricate(:account, id_scheme: :username_ap_id) } it 'returns a string starting with web domain and with the expected path' do expect(subject.inbox_uri_for(account)) @@ -427,7 +427,7 @@ RSpec.describe ActivityPub::TagManager do end context 'with a local account' do - let(:account) { Fabricate(:account) } + let(:account) { Fabricate(:account, id_scheme: :username_ap_id) } it 'returns a string starting with web domain and with the expected path' do expect(subject.outbox_uri_for(account)) @@ -452,7 +452,7 @@ RSpec.describe ActivityPub::TagManager do end it 'returns followers collection for unlisted status' do - status = Fabricate(:status, visibility: :unlisted) + status = Fabricate(:status, visibility: :unlisted, account: Fabricate(:account, id_scheme: :username_ap_id)) expect(subject.to(status)).to eq [account_followers_url(status.account)] end @@ -462,7 +462,7 @@ RSpec.describe ActivityPub::TagManager do end it 'returns followers collection for private status' do - status = Fabricate(:status, visibility: :private) + status = Fabricate(:status, visibility: :private, account: Fabricate(:account, id_scheme: :username_ap_id)) expect(subject.to(status)).to eq [account_followers_url(status.account)] end @@ -514,7 +514,7 @@ RSpec.describe ActivityPub::TagManager do describe '#cc' do it 'returns followers collection for public status' do - status = Fabricate(:status, visibility: :public) + status = Fabricate(:status, visibility: :public, account: Fabricate(:account, id_scheme: :username_ap_id)) expect(subject.cc(status)).to eq [account_followers_url(status.account)] end @@ -591,8 +591,9 @@ RSpec.describe ActivityPub::TagManager do end describe '#uri_to_local_id' do + let(:account) { Fabricate(:account, id_scheme: :username_ap_id) } + it 'returns the local ID' do - account = Fabricate(:account) expect(subject.uri_to_local_id(subject.uri_for(account), :username)).to eq account.username end end diff --git a/spec/lib/mastodon/cli/accounts_spec.rb b/spec/lib/mastodon/cli/accounts_spec.rb index 111703a18bb..927c6ca8deb 100644 --- a/spec/lib/mastodon/cli/accounts_spec.rb +++ b/spec/lib/mastodon/cli/accounts_spec.rb @@ -361,11 +361,20 @@ RSpec.describe Mastodon::CLI::Accounts do context 'with --reset-password option' do let(:options) { { reset_password: true } } + let(:user) { Fabricate(:user, password: original_password) } + let(:original_password) { 'foobar12345' } + let(:new_password) { 'new_password12345' } + it 'returns a new password for the user' do - allow(SecureRandom).to receive(:hex).and_return('new_password') + allow(SecureRandom).to receive(:hex).and_return(new_password) + allow(Account).to receive(:find_local).and_return(user.account) + allow(user).to receive(:change_password!).and_call_original expect { subject } - .to output_results('new_password') + .to output_results(new_password) + + expect(user).to have_received(:change_password!).with(new_password) + expect(user.reload).to_not be_external_or_valid_password(original_password) end end diff --git a/spec/lib/permalink_redirector_spec.rb b/spec/lib/permalink_redirector_spec.rb index 5a544c3d38e..81fa05449e9 100644 --- a/spec/lib/permalink_redirector_spec.rb +++ b/spec/lib/permalink_redirector_spec.rb @@ -10,39 +10,77 @@ RSpec.describe PermalinkRedirector do Fabricate(:status, account: remote_account, id: 123, url: 'https://example.com/status-123') end - it 'returns path for legacy account links' do - redirector = described_class.new('accounts/2') - expect(redirector.redirect_path).to eq 'https://example.com/@alice' - end - - it 'returns path for legacy status links' do - redirector = described_class.new('statuses/123') - expect(redirector.redirect_path).to eq 'https://example.com/status-123' - end - - it 'returns path for pretty account links' do - redirector = described_class.new('@alice@example.com') - expect(redirector.redirect_path).to eq 'https://example.com/@alice' - end - - it 'returns path for pretty status links' do - redirector = described_class.new('@alice/123') - expect(redirector.redirect_path).to eq 'https://example.com/status-123' - end - - it 'returns path for legacy status links with a query param' do - redirector = described_class.new('statuses/123?foo=bar') - expect(redirector.redirect_path).to eq 'https://example.com/status-123' - end - - it 'returns path for pretty status links with a query param' do - redirector = described_class.new('@alice/123?foo=bar') - expect(redirector.redirect_path).to eq 'https://example.com/status-123' - end - it 'returns path for deck URLs with query params' do redirector = described_class.new('/deck/directory?local=true') expect(redirector.redirect_path).to eq '/directory?local=true' end + + context 'when account is not suspended' do + it 'returns path for legacy account links' do + redirector = described_class.new('accounts/2') + expect(redirector.redirect_path).to eq 'https://example.com/@alice' + end + + it 'returns path for legacy status links' do + redirector = described_class.new('statuses/123') + expect(redirector.redirect_path).to eq 'https://example.com/status-123' + end + + it 'returns path for pretty account links' do + redirector = described_class.new('@alice@example.com') + expect(redirector.redirect_path).to eq 'https://example.com/@alice' + end + + it 'returns path for pretty status links' do + redirector = described_class.new('@alice/123') + expect(redirector.redirect_path).to eq 'https://example.com/status-123' + end + + it 'returns path for legacy status links with a query param' do + redirector = described_class.new('statuses/123?foo=bar') + expect(redirector.redirect_path).to eq 'https://example.com/status-123' + end + + it 'returns path for pretty status links with a query param' do + redirector = described_class.new('@alice/123?foo=bar') + expect(redirector.redirect_path).to eq 'https://example.com/status-123' + end + end + + context 'when account is suspended' do + before do + remote_account.suspend! + end + + it 'returns nil for legacy account links' do + redirector = described_class.new('accounts/2') + expect(redirector.redirect_path).to be_nil + end + + it 'returns nil for legacy status links' do + redirector = described_class.new('statuses/123') + expect(redirector.redirect_path).to be_nil + end + + it 'returns nil for pretty account links' do + redirector = described_class.new('@alice@example.com') + expect(redirector.redirect_path).to be_nil + end + + it 'returns nil for pretty status links' do + redirector = described_class.new('@alice/123') + expect(redirector.redirect_path).to be_nil + end + + it 'returns nil for legacy status links with a query param' do + redirector = described_class.new('statuses/123?foo=bar') + expect(redirector.redirect_path).to be_nil + end + + it 'returns nil for pretty status links with a query param' do + redirector = described_class.new('@alice/123?foo=bar') + expect(redirector.redirect_path).to be_nil + end + end end end diff --git a/spec/mailers/previews/notification_mailer_preview.rb b/spec/mailers/previews/notification_mailer_preview.rb index ae2d6802bcf..29ab047dfb1 100644 --- a/spec/mailers/previews/notification_mailer_preview.rb +++ b/spec/mailers/previews/notification_mailer_preview.rb @@ -35,7 +35,9 @@ class NotificationMailerPreview < ActionMailer::Preview # Preview this email at http://localhost:3000/rails/mailers/notification_mailer/quote def quote - activity = Quote.first + notification = Notification.where(type: 'quote').order(:created_at).last + activity = notification.activity + mailer_for(activity.quoted_account, activity).quote end diff --git a/spec/mailers/user_mailer_spec.rb b/spec/mailers/user_mailer_spec.rb index 88f9d12cac8..82021cd3d02 100644 --- a/spec/mailers/user_mailer_spec.rb +++ b/spec/mailers/user_mailer_spec.rb @@ -141,7 +141,9 @@ RSpec.describe UserMailer do end describe '#warning' do - let(:strike) { Fabricate(:account_warning, target_account: receiver.account, text: 'dont worry its just the testsuite', action: 'suspend') } + let(:status) { Fabricate(:status, account: receiver.account) } + let(:quote) { Fabricate(:quote, state: :accepted, status: status) } + let(:strike) { Fabricate(:account_warning, target_account: receiver.account, text: 'dont worry its just the testsuite', action: 'suspend', status_ids: [quote.status_id]) } let(:mail) { described_class.warning(receiver, strike) } it 'renders warning notification' do diff --git a/spec/models/remote_follow_spec.rb b/spec/models/remote_follow_spec.rb index b3ec7b737e2..aad32825625 100644 --- a/spec/models/remote_follow_spec.rb +++ b/spec/models/remote_follow_spec.rb @@ -68,7 +68,7 @@ RSpec.describe RemoteFollow do Addressable::URI.new( host: 'quitter.no', path: '/main/ostatussub', - query_values: { profile: "https://#{Rails.configuration.x.local_domain}/users/alice" }, + query_values: { profile: ActivityPub::TagManager.instance.uri_for(account) }, scheme: 'https' ).to_s end diff --git a/spec/models/user_spec.rb b/spec/models/user_spec.rb index a9ab15a956e..7088266b34e 100644 --- a/spec/models/user_spec.rb +++ b/spec/models/user_spec.rb @@ -382,12 +382,15 @@ RSpec.describe User do let(:current_sign_in_at) { Time.zone.now } - before do - user.disable! - end - it 'disables user' do + allow(redis).to receive(:publish) + + user.disable! + expect(user).to have_attributes(disabled: true) + + expect(redis) + .to have_received(:publish).with("timeline:system:#{user.account.id}", Oj.dump(event: :kill)).once end end diff --git a/spec/requests/activitypub/outboxes_spec.rb b/spec/requests/activitypub/outboxes_spec.rb index 22b2f97c071..c109214635b 100644 --- a/spec/requests/activitypub/outboxes_spec.rb +++ b/spec/requests/activitypub/outboxes_spec.rb @@ -215,7 +215,7 @@ RSpec.describe 'ActivityPub Outboxes' do def targets_followers_collection?(item, account) item[:to].include?( - account_followers_url(account, ActionMailer::Base.default_url_options) + ActivityPub::TagManager.instance.followers_uri_for(account) ) end end diff --git a/spec/requests/api/v1/timelines/link_spec.rb b/spec/requests/api/v1/timelines/link_spec.rb index 37a3b36872f..fa911345d69 100644 --- a/spec/requests/api/v1/timelines/link_spec.rb +++ b/spec/requests/api/v1/timelines/link_spec.rb @@ -87,7 +87,7 @@ RSpec.describe 'Link' do context 'when the instance does not allow public preview' do before do - Form::AdminSettings.new(timeline_preview: false).save + Form::AdminSettings.new(local_topic_feed_access: 'authenticated', remote_topic_feed_access: 'authenticated').save end it_behaves_like 'forbidden for wrong scope', 'profile' diff --git a/spec/requests/api/v1/timelines/public_spec.rb b/spec/requests/api/v1/timelines/public_spec.rb index 1e459bf3ec1..5ae9f76c4f8 100644 --- a/spec/requests/api/v1/timelines/public_spec.rb +++ b/spec/requests/api/v1/timelines/public_spec.rb @@ -98,7 +98,7 @@ RSpec.describe 'Public' do context 'when the instance does not allow public preview' do before do - Form::AdminSettings.new(timeline_preview: false).save + Form::AdminSettings.new(local_live_feed_access: 'authenticated', remote_live_feed_access: 'authenticated').save end it_behaves_like 'forbidden for wrong scope', 'profile' diff --git a/spec/requests/api/v1/timelines/tag_spec.rb b/spec/requests/api/v1/timelines/tag_spec.rb index 75348fe1b4e..5a723b11e42 100644 --- a/spec/requests/api/v1/timelines/tag_spec.rb +++ b/spec/requests/api/v1/timelines/tag_spec.rb @@ -99,7 +99,7 @@ RSpec.describe 'Tag' do context 'when the instance does not allow public preview' do before do - Form::AdminSettings.new(timeline_preview: false).save + Form::AdminSettings.new(local_topic_feed_access: 'authenticated', remote_topic_feed_access: 'authenticated').save end it_behaves_like 'forbidden for wrong scope', 'profile' diff --git a/spec/requests/link_headers_spec.rb b/spec/requests/link_headers_spec.rb index 5010f7f221f..c782744f016 100644 --- a/spec/requests/link_headers_spec.rb +++ b/spec/requests/link_headers_spec.rb @@ -11,7 +11,7 @@ RSpec.describe 'Link headers' do expect(response) .to have_http_link_header(webfinger_url(resource: account.to_webfinger_s)).for(rel: 'lrdd', type: 'application/jrd+json') - .and have_http_link_header(account_url(account)).for(rel: 'alternate', type: 'application/activity+json') + .and have_http_link_header(ActivityPub::TagManager.instance.uri_for(account)).for(rel: 'alternate', type: 'application/activity+json') end end end diff --git a/spec/requests/oauth/userinfo_spec.rb b/spec/requests/oauth/userinfo_spec.rb index 0aa5a211200..280a3a35418 100644 --- a/spec/requests/oauth/userinfo_spec.rb +++ b/spec/requests/oauth/userinfo_spec.rb @@ -19,7 +19,7 @@ RSpec.describe 'OAuth Userinfo Endpoint' do expect(response.content_type).to start_with('application/json') expect(response.parsed_body).to include({ iss: root_url, - sub: account_url(account), + sub: ActivityPub::TagManager.instance.uri_for(account), name: account.display_name, preferred_username: account.username, profile: short_account_url(account), diff --git a/spec/requests/well_known/webfinger_spec.rb b/spec/requests/well_known/webfinger_spec.rb index 0c4a3c03474..593cecbb896 100644 --- a/spec/requests/well_known/webfinger_spec.rb +++ b/spec/requests/well_known/webfinger_spec.rb @@ -27,7 +27,7 @@ RSpec.describe 'The /.well-known/webfinger endpoint' do expect(response.parsed_body) .to include( subject: eq(alice.to_webfinger_s), - aliases: include("https://#{Rails.configuration.x.local_domain}/@alice", "https://#{Rails.configuration.x.local_domain}/users/alice") + aliases: include("https://#{Rails.configuration.x.local_domain}/@alice", ActivityPub::TagManager.instance.uri_for(alice)) ) end end diff --git a/spec/serializers/activitypub/note_serializer_spec.rb b/spec/serializers/activitypub/note_serializer_spec.rb index 04179e9bf4d..0d11386d57b 100644 --- a/spec/serializers/activitypub/note_serializer_spec.rb +++ b/spec/serializers/activitypub/note_serializer_spec.rb @@ -58,6 +58,21 @@ RSpec.describe ActivityPub::NoteSerializer do end end + context 'with a deleted quote' do + let(:quoted_status) { Fabricate(:status) } + + before do + Fabricate(:quote, status: parent, quoted_status: nil, state: :accepted) + end + + it 'has the expected shape' do + expect(subject).to include({ + 'type' => 'Note', + 'quote' => { 'type' => 'Tombstone' }, + }) + end + end + context 'with a quote policy' do let(:parent) { Fabricate(:status, quote_approval_policy: Status::QUOTE_APPROVAL_POLICY_FLAGS[:followers] << 16) } diff --git a/spec/services/activitypub/process_status_update_service_spec.rb b/spec/services/activitypub/process_status_update_service_spec.rb index 7af2c67387f..56a8c71cbe8 100644 --- a/spec/services/activitypub/process_status_update_service_spec.rb +++ b/spec/services/activitypub/process_status_update_service_spec.rb @@ -1053,6 +1053,44 @@ RSpec.describe ActivityPub::ProcessStatusUpdateService do end end + context 'when the status swaps a verified quote with an ID-less Tombstone through an explicit update' do + let(:quoted_account) { Fabricate(:account, domain: 'quoted.example.com') } + let(:quoted_status) { Fabricate(:status, account: quoted_account) } + let(:second_quoted_status) { Fabricate(:status, account: quoted_account) } + let!(:quote) { Fabricate(:quote, status: status, quoted_status: quoted_status, approval_uri: approval_uri, state: :accepted) } + let(:approval_uri) { 'https://quoted.example.com/approvals/1' } + + let(:payload) do + { + '@context': [ + 'https://www.w3.org/ns/activitystreams', + { + '@id': 'https://w3id.org/fep/044f#quote', + '@type': '@id', + }, + { + '@id': 'https://w3id.org/fep/044f#quoteAuthorization', + '@type': '@id', + }, + ], + id: 'foo', + type: 'Note', + summary: 'Show more', + content: 'Hello universe', + updated: '2021-09-08T22:39:25Z', + quote: { type: 'Tombstone' }, + } + end + + it 'updates the URI and unverifies the quote' do + expect { subject.call(status, json, json) } + .to change { status.quote.quoted_status }.from(quoted_status).to(nil) + .and change { status.quote.state }.from('accepted').to('deleted') + + expect { quote.reload }.to raise_error(ActiveRecord::RecordNotFound) + end + end + context 'when the status swaps a verified quote with another verifiable quote through an explicit update' do let(:quoted_account) { Fabricate(:account, domain: 'quoted.example.com') } let(:second_quoted_account) { Fabricate(:account, domain: 'second-quoted.example.com') } diff --git a/spec/services/remove_status_service_spec.rb b/spec/services/remove_status_service_spec.rb index f2b46f05b00..3cb2eceec59 100644 --- a/spec/services/remove_status_service_spec.rb +++ b/spec/services/remove_status_service_spec.rb @@ -129,4 +129,20 @@ RSpec.describe RemoveStatusService, :inline_jobs do ) ) end + + context 'when removed status is a quote of a local user', inline_jobs: false do + let(:original_status) { Fabricate(:status, account: alice) } + let(:status) { Fabricate(:status, account: jeff) } + + before do + bill.follow!(jeff) + Fabricate(:quote, status: status, quoted_status: original_status, state: :accepted) + original_status.discard + end + + it 'sends deletion without crashing' do + expect { subject.call(status.reload) } + .to enqueue_sidekiq_job(ActivityPub::DeliveryWorker).with(/Delete/, jeff.id, bill.inbox_url) + end + end end diff --git a/spec/system/admin/dashboard_spec.rb b/spec/system/admin/dashboard_spec.rb index 06d31cde44e..d0cedd2ed19 100644 --- a/spec/system/admin/dashboard_spec.rb +++ b/spec/system/admin/dashboard_spec.rb @@ -9,6 +9,7 @@ RSpec.describe 'Admin Dashboard' do before do stub_system_checks Fabricate :software_update + Fabricate :tag, requested_review_at: 5.minutes.ago sign_in(user) end @@ -18,6 +19,7 @@ RSpec.describe 'Admin Dashboard' do expect(page) .to have_title(I18n.t('admin.dashboard.title')) .and have_content(I18n.t('admin.system_checks.software_version_patch_check.message_html')) + .and have_content('0 pending hashtags') end private diff --git a/spec/system/streaming/channel_subscriptions_spec.rb b/spec/system/streaming/channel_subscriptions_spec.rb index 54e125c293d..447ea64f22f 100644 --- a/spec/system/streaming/channel_subscriptions_spec.rb +++ b/spec/system/streaming/channel_subscriptions_spec.rb @@ -1,7 +1,6 @@ # frozen_string_literal: true require 'rails_helper' -require 'debug' RSpec.describe 'Channel Subscriptions', :inline_jobs, :streaming do let(:application) { Fabricate(:application, confidential: false) } @@ -15,6 +14,25 @@ RSpec.describe 'Channel Subscriptions', :inline_jobs, :streaming do streaming_client.close end + context 'when the access token has insufficient scope to read statuses' do + let(:scopes) { 'profile' } + + it 'cannot subscribe to the public:local channel' do + streaming_client.authenticate(access_token.token) + + streaming_client.connect + streaming_client.subscribe('public:local') + + # Receive the error back from the subscription attempt: + message = streaming_client.wait_for_message + + expect(message).to include( + error: 'Access token does not have the required scopes', + status: 401 + ) + end + end + context 'when the access token has read scope' do let(:scopes) { 'read' } @@ -39,11 +57,52 @@ RSpec.describe 'Channel Subscriptions', :inline_jobs, :streaming do ) ) end + + it 'can subscribing to the user:notifications channel' do + streaming_client.authenticate(access_token.token) + + streaming_client.connect + streaming_client.subscribe('user:notification') + + # We need to perform an action that triggers a notification as there is + # no positive acknowledgement of subscriptions: + first_status = PostStatusService.new.call(user_account, text: 'Test') + ReblogService.new.call(bob_account, first_status) + + message = streaming_client.wait_for_message + + expect(message).to include( + event: 'notification', + stream: ['user:notification'] + ) + end end - context 'when the access token cannot read notifications' do + context 'when the access token has read:statuses scope' do let(:scopes) { 'read:statuses' } + it 'can subscribing to the public:local channel' do + streaming_client.authenticate(access_token.token) + + streaming_client.connect + streaming_client.subscribe('public:local') + + # We need to publish a status as there is no positive acknowledgement of + # subscriptions: + status = PostStatusService.new.call(bob_account, text: 'Hello @alice') + + # And then we want to receive that status: + message = streaming_client.wait_for_message + + expect(message).to include( + stream: be_an(Array).and(contain_exactly('public:local')), + event: 'update', + payload: include( + id: status.id.to_s + ) + ) + end + it 'cannot subscribing to the user:notifications channel' do streaming_client.authenticate(access_token.token) @@ -59,4 +118,27 @@ RSpec.describe 'Channel Subscriptions', :inline_jobs, :streaming do ) end end + + context 'when the access token has read:notifications scope' do + let(:scopes) { 'read:notifications' } + + it 'can subscribing to the user:notifications channel' do + streaming_client.authenticate(access_token.token) + + streaming_client.connect + streaming_client.subscribe('user:notification') + + # We need to perform an action that triggers a notification as there is + # no positive acknowledgement of subscriptions: + first_status = PostStatusService.new.call(user_account, text: 'Test') + ReblogService.new.call(bob_account, first_status) + + message = streaming_client.wait_for_message + + expect(message).to include( + event: 'notification', + stream: ['user:notification'] + ) + end + end end diff --git a/spec/system/streaming/streaming_spec.rb b/spec/system/streaming/streaming_spec.rb index c12bd1b18fe..f5d3ba11426 100644 --- a/spec/system/streaming/streaming_spec.rb +++ b/spec/system/streaming/streaming_spec.rb @@ -74,4 +74,52 @@ RSpec.describe 'Streaming', :inline_jobs, :streaming do expect(streaming_client.open?).to be(false) end end + + context 'with a disabled user account' do + before do + user.disable! + end + + it 'receives an 401 unauthorized error when trying to connect' do + streaming_client.connect + + expect(streaming_client.status).to eq(401) + expect(streaming_client.open?).to be(false) + end + end + + context 'when the user account is disabled whilst connected' do + it 'terminates the connection for the user' do + streaming_client.connect + + user.disable! + + expect(streaming_client.wait_for(:closed).code).to be(1000) + expect(streaming_client.open?).to be(false) + end + end + + context 'with a suspended user account' do + before do + user.account.suspend! + end + + it 'receives an 401 unauthorized error when trying to connect' do + streaming_client.connect + + expect(streaming_client.status).to eq(401) + expect(streaming_client.open?).to be(false) + end + end + + context 'when the user account is suspended whilst connected' do + it 'terminates the connection for the user' do + streaming_client.connect + + user.account.suspend! + + expect(streaming_client.wait_for(:closed).code).to be(1000) + expect(streaming_client.open?).to be(false) + end + end end diff --git a/streaming/index.js b/streaming/index.js index da8aa657e81..952b4584ab9 100644 --- a/streaming/index.js +++ b/streaming/index.js @@ -78,17 +78,6 @@ const parseJSON = (json, req) => { } }; -const PUBLIC_CHANNELS = [ - 'public', - 'public:media', - 'public:local', - 'public:local:media', - 'public:remote', - 'public:remote:media', - 'hashtag', - 'hashtag:local', -]; - // Used for priming the counters/gauges for the various metrics that are // per-channel const CHANNEL_NAMES = [ @@ -97,7 +86,14 @@ const CHANNEL_NAMES = [ 'user:notification', 'list', 'direct', - ...PUBLIC_CHANNELS + 'public', + 'public:media', + 'public:local', + 'public:local:media', + 'public:remote', + 'public:remote:media', + 'hashtag', + 'hashtag:local', ]; const startServer = async () => { @@ -355,7 +351,7 @@ const startServer = async () => { * @returns {Promise} */ const accountFromToken = async (token, req) => { - const result = await pgPool.query('SELECT oauth_access_tokens.id, oauth_access_tokens.resource_owner_id, users.account_id, users.chosen_languages, oauth_access_tokens.scopes FROM oauth_access_tokens INNER JOIN users ON oauth_access_tokens.resource_owner_id = users.id WHERE oauth_access_tokens.token = $1 AND oauth_access_tokens.revoked_at IS NULL LIMIT 1', [token]); + const result = await pgPool.query('SELECT oauth_access_tokens.id, oauth_access_tokens.resource_owner_id, users.account_id, users.chosen_languages, oauth_access_tokens.scopes FROM oauth_access_tokens INNER JOIN users ON oauth_access_tokens.resource_owner_id = users.id INNER JOIN accounts ON accounts.id = users.account_id WHERE oauth_access_tokens.token = $1 AND oauth_access_tokens.revoked_at IS NULL AND users.disabled IS FALSE AND accounts.suspended_at IS NULL LIMIT 1', [token]); if (result.rows.length === 0) { throw new AuthenticationError('Invalid access token'); @@ -434,12 +430,6 @@ const startServer = async () => { const checkScopes = (req, logger, channelName) => new Promise((resolve, reject) => { logger.debug(`Checking OAuth scopes for ${channelName}`); - // When accessing public channels, no scopes are needed - if (channelName && PUBLIC_CHANNELS.includes(channelName)) { - resolve(); - return; - } - // The `read` scope has the highest priority, if the token has it // then it can access all streams const requiredScopes = ['read']; diff --git a/streaming/lint-staged.config.mjs b/streaming/lint-staged.config.mjs index 430a999b9ab..5f9230acbd5 100644 --- a/streaming/lint-staged.config.mjs +++ b/streaming/lint-staged.config.mjs @@ -1,5 +1,4 @@ const config = { - '*': 'prettier --ignore-unknown --write', '*.{js,ts}': 'eslint --fix', '**/*.ts': () => 'tsc -p tsconfig.json --noEmit', }; diff --git a/yarn.lock b/yarn.lock index 9e977816978..69908cafc72 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2397,6 +2397,18 @@ __metadata: languageName: node linkType: hard +"@formatjs/ecma402-abstract@npm:2.3.6": + version: 2.3.6 + resolution: "@formatjs/ecma402-abstract@npm:2.3.6" + dependencies: + "@formatjs/fast-memoize": "npm:2.2.7" + "@formatjs/intl-localematcher": "npm:0.6.2" + decimal.js: "npm:^10.4.3" + tslib: "npm:^2.8.0" + checksum: 10c0/63be2a73d3168bf45ab5d50db58376e852db5652d89511ae6e44f1fa03ad96ebbfe9b06a1dfaa743db06e40eb7f33bd77530b9388289855cca79a0e3fc29eacf + languageName: node + linkType: hard + "@formatjs/fast-memoize@npm:2.2.7": version: 2.2.7 resolution: "@formatjs/fast-memoize@npm:2.2.7" @@ -2417,6 +2429,17 @@ __metadata: languageName: node linkType: hard +"@formatjs/icu-messageformat-parser@npm:2.11.4": + version: 2.11.4 + resolution: "@formatjs/icu-messageformat-parser@npm:2.11.4" + dependencies: + "@formatjs/ecma402-abstract": "npm:2.3.6" + "@formatjs/icu-skeleton-parser": "npm:1.8.16" + tslib: "npm:^2.8.0" + checksum: 10c0/3ea9e9dae18282881d19a5f88107b6013f514ec8675684ed2c04bee2a174032377858937243e3bd9c9263a470988a3773a53bf8d208a34a78e7843ce66f87f3b + languageName: node + linkType: hard + "@formatjs/icu-skeleton-parser@npm:1.8.14": version: 1.8.14 resolution: "@formatjs/icu-skeleton-parser@npm:1.8.14" @@ -2427,6 +2450,16 @@ __metadata: languageName: node linkType: hard +"@formatjs/icu-skeleton-parser@npm:1.8.16": + version: 1.8.16 + resolution: "@formatjs/icu-skeleton-parser@npm:1.8.16" + dependencies: + "@formatjs/ecma402-abstract": "npm:2.3.6" + tslib: "npm:^2.8.0" + checksum: 10c0/6fa1586dc11c925cd8d17e927cc635d238c969a6b7e97282a924376f78622fc25336c407589d19796fb6f8124a0e7765f99ecdb1aac014edcfbe852e7c3d87f3 + languageName: node + linkType: hard + "@formatjs/intl-localematcher@npm:0.6.1": version: 0.6.1 resolution: "@formatjs/intl-localematcher@npm:0.6.1" @@ -2436,33 +2469,42 @@ __metadata: languageName: node linkType: hard -"@formatjs/intl-pluralrules@npm:^5.4.4": - version: 5.4.4 - resolution: "@formatjs/intl-pluralrules@npm:5.4.4" +"@formatjs/intl-localematcher@npm:0.6.2": + version: 0.6.2 + resolution: "@formatjs/intl-localematcher@npm:0.6.2" dependencies: - "@formatjs/ecma402-abstract": "npm:2.3.4" - "@formatjs/intl-localematcher": "npm:0.6.1" - decimal.js: "npm:^10.4.3" tslib: "npm:^2.8.0" - checksum: 10c0/8a8ec9f2fad40d9fa654a68de06fb18aaa6f0eafa908f41397f057366740625c12da627c6de68e0396fcd67ceaaa2c5c20a4b102f71ac8694abd9e76cceca949 + checksum: 10c0/22a17a4c67160b6c9f52667914acfb7b79cd6d80630d4ac6d4599ce447cb89d2a64f7d58fa35c3145ddb37fef893f0a45b9a55e663a4eb1f2ae8b10a89fac235 languageName: node linkType: hard -"@formatjs/intl@npm:3.1.6": - version: 3.1.6 - resolution: "@formatjs/intl@npm:3.1.6" +"@formatjs/intl-pluralrules@npm:^5.4.4": + version: 5.4.6 + resolution: "@formatjs/intl-pluralrules@npm:5.4.6" dependencies: - "@formatjs/ecma402-abstract": "npm:2.3.4" + "@formatjs/ecma402-abstract": "npm:2.3.6" + "@formatjs/intl-localematcher": "npm:0.6.2" + decimal.js: "npm:^10.4.3" + tslib: "npm:^2.8.0" + checksum: 10c0/95dd6fb3e9bd84ce44cc194f6f815d690703bd60b75bf2ae895535d2d9a1a675765879de9b54f854882fc1335cbfac6a535873d5b2d75cc5ca93c6ca172aa272 + languageName: node + linkType: hard + +"@formatjs/intl@npm:3.1.8": + version: 3.1.8 + resolution: "@formatjs/intl@npm:3.1.8" + dependencies: + "@formatjs/ecma402-abstract": "npm:2.3.6" "@formatjs/fast-memoize": "npm:2.2.7" - "@formatjs/icu-messageformat-parser": "npm:2.11.2" - intl-messageformat: "npm:10.7.16" + "@formatjs/icu-messageformat-parser": "npm:2.11.4" + intl-messageformat: "npm:10.7.18" tslib: "npm:^2.8.0" peerDependencies: typescript: ^5.6.0 peerDependenciesMeta: typescript: optional: true - checksum: 10c0/a31f8d2569c9f2384f67a76f1cc2c8bfc2721c97a7dee0e971b6cfc0f223449bab0cfdc29140e3b71d74b04573c20ee8600909d256293e296a809da69a141530 + checksum: 10c0/b291e867bcde491737f70254ec30898e120f36784b5ee2911dcc271fbd744e90382f03232ac7f5a55d46071f4ffccfc84b63445734117b75ca1ced659f6b7827 languageName: node linkType: hard @@ -2486,6 +2528,25 @@ __metadata: languageName: node linkType: hard +"@formatjs/ts-transformer@npm:3.14.2": + version: 3.14.2 + resolution: "@formatjs/ts-transformer@npm:3.14.2" + dependencies: + "@formatjs/icu-messageformat-parser": "npm:2.11.4" + "@types/node": "npm:^22.0.0" + chalk: "npm:^4.1.2" + json-stable-stringify: "npm:^1.3.0" + tslib: "npm:^2.8.0" + typescript: "npm:^5.6.0" + peerDependencies: + ts-jest: ^29 + peerDependenciesMeta: + ts-jest: + optional: true + checksum: 10c0/990cf49cdc318e37825ec26b1b24d7368e89c5d03184867a4accd8b35d6d6d99a20a8abe6366c9870e56da9e04f4672990ca428686306c9ad8204b401c7d19f8 + languageName: node + linkType: hard + "@gamestdio/websocket@npm:^0.3.2": version: 0.3.2 resolution: "@gamestdio/websocket@npm:0.3.2" @@ -2854,13 +2915,13 @@ __metadata: stringz: "npm:^2.1.0" stylelint: "npm:^16.19.1" stylelint-config-prettier-scss: "npm:^1.0.0" - stylelint-config-standard-scss: "npm:^15.0.1" + stylelint-config-standard-scss: "npm:^16.0.0" substring-trie: "npm:^1.0.2" tesseract.js: "npm:^6.0.0" tiny-queue: "npm:^0.2.1" twitter-text: "npm:3.1.0" typescript: "npm:~5.9.0" - typescript-eslint: "npm:^8.29.1" + typescript-eslint: "npm:^8.45.0" use-debounce: "npm:^10.0.0" vite: "npm:^7.1.1" vite-plugin-manifest-sri: "npm:^0.2.0" @@ -4503,106 +4564,106 @@ __metadata: languageName: node linkType: hard -"@typescript-eslint/eslint-plugin@npm:8.38.0": - version: 8.38.0 - resolution: "@typescript-eslint/eslint-plugin@npm:8.38.0" +"@typescript-eslint/eslint-plugin@npm:8.45.0": + version: 8.45.0 + resolution: "@typescript-eslint/eslint-plugin@npm:8.45.0" dependencies: "@eslint-community/regexpp": "npm:^4.10.0" - "@typescript-eslint/scope-manager": "npm:8.38.0" - "@typescript-eslint/type-utils": "npm:8.38.0" - "@typescript-eslint/utils": "npm:8.38.0" - "@typescript-eslint/visitor-keys": "npm:8.38.0" + "@typescript-eslint/scope-manager": "npm:8.45.0" + "@typescript-eslint/type-utils": "npm:8.45.0" + "@typescript-eslint/utils": "npm:8.45.0" + "@typescript-eslint/visitor-keys": "npm:8.45.0" graphemer: "npm:^1.4.0" ignore: "npm:^7.0.0" natural-compare: "npm:^1.4.0" ts-api-utils: "npm:^2.1.0" peerDependencies: - "@typescript-eslint/parser": ^8.38.0 + "@typescript-eslint/parser": ^8.45.0 eslint: ^8.57.0 || ^9.0.0 - typescript: ">=4.8.4 <5.9.0" - checksum: 10c0/199b82e9f0136baecf515df7c31bfed926a7c6d4e6298f64ee1a77c8bdd7a8cb92a2ea55a5a345c9f2948a02f7be6d72530efbe803afa1892b593fbd529d0c27 + typescript: ">=4.8.4 <6.0.0" + checksum: 10c0/0c60a0e5d07fa8618348db38b5a81e66143d528e1b3cdb5678bbc6c60590cd559b27c98c36f5663230fc4cf6920dff2cd604de30b58df26a37fcfcc5dc1dbd45 languageName: node linkType: hard -"@typescript-eslint/parser@npm:8.38.0": - version: 8.38.0 - resolution: "@typescript-eslint/parser@npm:8.38.0" +"@typescript-eslint/parser@npm:8.45.0": + version: 8.45.0 + resolution: "@typescript-eslint/parser@npm:8.45.0" dependencies: - "@typescript-eslint/scope-manager": "npm:8.38.0" - "@typescript-eslint/types": "npm:8.38.0" - "@typescript-eslint/typescript-estree": "npm:8.38.0" - "@typescript-eslint/visitor-keys": "npm:8.38.0" + "@typescript-eslint/scope-manager": "npm:8.45.0" + "@typescript-eslint/types": "npm:8.45.0" + "@typescript-eslint/typescript-estree": "npm:8.45.0" + "@typescript-eslint/visitor-keys": "npm:8.45.0" debug: "npm:^4.3.4" peerDependencies: eslint: ^8.57.0 || ^9.0.0 - typescript: ">=4.8.4 <5.9.0" - checksum: 10c0/5580c2a328f0c15f85e4a0961a07584013cc0aca85fe868486187f7c92e9e3f6602c6e3dab917b092b94cd492ed40827c6f5fea42730bef88eb17592c947adf4 + typescript: ">=4.8.4 <6.0.0" + checksum: 10c0/8b419bcf795b112a39fcac05dcf147835059345b6399035ffa3f76a9d8e320f3fac79cae2fe4320dcda83fa059b017ca7626a7b4e3da08a614415c8867d169b8 languageName: node linkType: hard -"@typescript-eslint/project-service@npm:8.38.0": - version: 8.38.0 - resolution: "@typescript-eslint/project-service@npm:8.38.0" +"@typescript-eslint/project-service@npm:8.45.0": + version: 8.45.0 + resolution: "@typescript-eslint/project-service@npm:8.45.0" dependencies: - "@typescript-eslint/tsconfig-utils": "npm:^8.38.0" - "@typescript-eslint/types": "npm:^8.38.0" + "@typescript-eslint/tsconfig-utils": "npm:^8.45.0" + "@typescript-eslint/types": "npm:^8.45.0" debug: "npm:^4.3.4" peerDependencies: - typescript: ">=4.8.4 <5.9.0" - checksum: 10c0/87d2f55521e289bbcdc666b1f4587ee2d43039cee927310b05abaa534b528dfb1b5565c1545bb4996d7fbdf9d5a3b0aa0e6c93a8f1289e3fcfd60d246364a884 + typescript: ">=4.8.4 <6.0.0" + checksum: 10c0/98af065a1a3ed9d3d1eb265e09d3e9c2ae676d500a8c1d764f5609fe2c1b86749516b709804eb814fae688be7809d11748b9ae691d43c28da51dac390ca81fa9 languageName: node linkType: hard -"@typescript-eslint/scope-manager@npm:8.38.0": - version: 8.38.0 - resolution: "@typescript-eslint/scope-manager@npm:8.38.0" +"@typescript-eslint/scope-manager@npm:8.45.0": + version: 8.45.0 + resolution: "@typescript-eslint/scope-manager@npm:8.45.0" dependencies: - "@typescript-eslint/types": "npm:8.38.0" - "@typescript-eslint/visitor-keys": "npm:8.38.0" - checksum: 10c0/ceaf489ea1f005afb187932a7ee363dfe1e0f7cc3db921283991e20e4c756411a5e25afbec72edd2095d6a4384f73591f4c750cf65b5eaa650c90f64ef9fe809 + "@typescript-eslint/types": "npm:8.45.0" + "@typescript-eslint/visitor-keys": "npm:8.45.0" + checksum: 10c0/54cd36206f6b4fc8e1e48576ed01e0d6ab20c2a9c4c7d90d5cc3a2d317dd8a13abe148ffecf471b16f1224aba5749e0905472745626bef9ae5bed771776f4abe languageName: node linkType: hard -"@typescript-eslint/tsconfig-utils@npm:8.38.0, @typescript-eslint/tsconfig-utils@npm:^8.38.0": - version: 8.38.0 - resolution: "@typescript-eslint/tsconfig-utils@npm:8.38.0" +"@typescript-eslint/tsconfig-utils@npm:8.45.0, @typescript-eslint/tsconfig-utils@npm:^8.45.0": + version: 8.45.0 + resolution: "@typescript-eslint/tsconfig-utils@npm:8.45.0" peerDependencies: - typescript: ">=4.8.4 <5.9.0" - checksum: 10c0/1a90da16bf1f7cfbd0303640a8ead64a0080f2b1d5969994bdac3b80abfa1177f0c6fbf61250bae082e72cf5014308f2f5cc98edd6510202f13420a7ffd07a84 + typescript: ">=4.8.4 <6.0.0" + checksum: 10c0/227a9b7a5baaf35466fd369992cb933192515df1156ddf22f438deb344c2523695208e1036f5590b20603f31724de75a47fe0ee84e2fd4c8e9f3606f23f68112 languageName: node linkType: hard -"@typescript-eslint/type-utils@npm:8.38.0": - version: 8.38.0 - resolution: "@typescript-eslint/type-utils@npm:8.38.0" +"@typescript-eslint/type-utils@npm:8.45.0": + version: 8.45.0 + resolution: "@typescript-eslint/type-utils@npm:8.45.0" dependencies: - "@typescript-eslint/types": "npm:8.38.0" - "@typescript-eslint/typescript-estree": "npm:8.38.0" - "@typescript-eslint/utils": "npm:8.38.0" + "@typescript-eslint/types": "npm:8.45.0" + "@typescript-eslint/typescript-estree": "npm:8.45.0" + "@typescript-eslint/utils": "npm:8.45.0" debug: "npm:^4.3.4" ts-api-utils: "npm:^2.1.0" peerDependencies: eslint: ^8.57.0 || ^9.0.0 - typescript: ">=4.8.4 <5.9.0" - checksum: 10c0/27795c4bd0be395dda3424e57d746639c579b7522af1c17731b915298a6378fd78869e8e141526064b6047db2c86ba06444469ace19c98cda5779d06f4abd37c + typescript: ">=4.8.4 <6.0.0" + checksum: 10c0/ce0f4c209c2418ebeb65e7de053499fb68bf6000bdd71068594fdb8c8ac3dbbd62935a3cea233989491f7da3ef5db87e7efd2910133c6abf6d0cbf57248f6442 languageName: node linkType: hard -"@typescript-eslint/types@npm:8.38.0, @typescript-eslint/types@npm:^8.34.1, @typescript-eslint/types@npm:^8.38.0": - version: 8.38.0 - resolution: "@typescript-eslint/types@npm:8.38.0" - checksum: 10c0/f0ac0060c98c0f3d1871f107177b6ae25a0f1846ca8bd8cfc7e1f1dd0ddce293cd8ac4a5764d6a767de3503d5d01defcd68c758cb7ba6de52f82b209a918d0d2 +"@typescript-eslint/types@npm:8.45.0, @typescript-eslint/types@npm:^8.34.1, @typescript-eslint/types@npm:^8.45.0": + version: 8.45.0 + resolution: "@typescript-eslint/types@npm:8.45.0" + checksum: 10c0/0213a0573c671d13bc91961a2b2e814ec7f6381ff093bce6704017bd96b2fc7fee25906c815cedb32a0601cf5071ca6c7c5f940d087c3b0d3dd7d4bc03478278 languageName: node linkType: hard -"@typescript-eslint/typescript-estree@npm:8.38.0": - version: 8.38.0 - resolution: "@typescript-eslint/typescript-estree@npm:8.38.0" +"@typescript-eslint/typescript-estree@npm:8.45.0": + version: 8.45.0 + resolution: "@typescript-eslint/typescript-estree@npm:8.45.0" dependencies: - "@typescript-eslint/project-service": "npm:8.38.0" - "@typescript-eslint/tsconfig-utils": "npm:8.38.0" - "@typescript-eslint/types": "npm:8.38.0" - "@typescript-eslint/visitor-keys": "npm:8.38.0" + "@typescript-eslint/project-service": "npm:8.45.0" + "@typescript-eslint/tsconfig-utils": "npm:8.45.0" + "@typescript-eslint/types": "npm:8.45.0" + "@typescript-eslint/visitor-keys": "npm:8.45.0" debug: "npm:^4.3.4" fast-glob: "npm:^3.3.2" is-glob: "npm:^4.0.3" @@ -4610,33 +4671,33 @@ __metadata: semver: "npm:^7.6.0" ts-api-utils: "npm:^2.1.0" peerDependencies: - typescript: ">=4.8.4 <5.9.0" - checksum: 10c0/00a00f6549877f4ae5c2847fa5ac52bf42cbd59a87533856c359e2746e448ed150b27a6137c92fd50c06e6a4b39e386d6b738fac97d80d05596e81ce55933230 + typescript: ">=4.8.4 <6.0.0" + checksum: 10c0/8c2f44a00fe859a6cd4b50157c484c5b6a1c7af5d48e89ae79c5f4924947964962fc8f478ad4c2ade788907fceee9b72d4e376508ea79b51392f91082a37d239 languageName: node linkType: hard -"@typescript-eslint/utils@npm:8.38.0, @typescript-eslint/utils@npm:^8.27.0, @typescript-eslint/utils@npm:^8.8.1": - version: 8.38.0 - resolution: "@typescript-eslint/utils@npm:8.38.0" +"@typescript-eslint/utils@npm:8.45.0, @typescript-eslint/utils@npm:^8.27.0, @typescript-eslint/utils@npm:^8.8.1": + version: 8.45.0 + resolution: "@typescript-eslint/utils@npm:8.45.0" dependencies: "@eslint-community/eslint-utils": "npm:^4.7.0" - "@typescript-eslint/scope-manager": "npm:8.38.0" - "@typescript-eslint/types": "npm:8.38.0" - "@typescript-eslint/typescript-estree": "npm:8.38.0" + "@typescript-eslint/scope-manager": "npm:8.45.0" + "@typescript-eslint/types": "npm:8.45.0" + "@typescript-eslint/typescript-estree": "npm:8.45.0" peerDependencies: eslint: ^8.57.0 || ^9.0.0 - typescript: ">=4.8.4 <5.9.0" - checksum: 10c0/e97a45bf44f315f9ed8c2988429e18c88e3369c9ee3227ee86446d2d49f7325abebbbc9ce801e178f676baa986d3e1fd4b5391f1640c6eb8944c123423ae43bb + typescript: ">=4.8.4 <6.0.0" + checksum: 10c0/b3c83a23813b15e20e303d7153789508c01e06dec355b1a80547c59aa36998d498102f45fcd13f111031fac57270608abb04d20560248d4448fd00b1cf4dc4ab languageName: node linkType: hard -"@typescript-eslint/visitor-keys@npm:8.38.0": - version: 8.38.0 - resolution: "@typescript-eslint/visitor-keys@npm:8.38.0" +"@typescript-eslint/visitor-keys@npm:8.45.0": + version: 8.45.0 + resolution: "@typescript-eslint/visitor-keys@npm:8.45.0" dependencies: - "@typescript-eslint/types": "npm:8.38.0" + "@typescript-eslint/types": "npm:8.45.0" eslint-visitor-keys: "npm:^4.2.1" - checksum: 10c0/071a756e383f41a6c9e51d78c8c64bd41cd5af68b0faef5fbaec4fa5dbd65ec9e4cd610c2e2cdbe9e2facc362995f202850622b78e821609a277b5b601a1d4ec + checksum: 10c0/119adcf50c902dad7f7757bcdd88fad0a23a171d309d9b7cefe78af12e451cf84c04ae611f4c31f7e23f16c2b47665ad92e6e5648fc77d542ef306f465bf1f29 languageName: node linkType: hard @@ -5406,21 +5467,21 @@ __metadata: linkType: hard "babel-plugin-formatjs@npm:^10.5.37": - version: 10.5.39 - resolution: "babel-plugin-formatjs@npm:10.5.39" + version: 10.5.41 + resolution: "babel-plugin-formatjs@npm:10.5.41" dependencies: "@babel/core": "npm:^7.26.10" "@babel/helper-plugin-utils": "npm:^7.26.5" "@babel/plugin-syntax-jsx": "npm:^7.25.9" "@babel/traverse": "npm:^7.26.10" "@babel/types": "npm:^7.26.10" - "@formatjs/icu-messageformat-parser": "npm:2.11.2" - "@formatjs/ts-transformer": "npm:3.14.0" + "@formatjs/icu-messageformat-parser": "npm:2.11.4" + "@formatjs/ts-transformer": "npm:3.14.2" "@types/babel__core": "npm:^7.20.5" "@types/babel__helper-plugin-utils": "npm:^7.10.3" "@types/babel__traverse": "npm:^7.20.6" tslib: "npm:^2.8.0" - checksum: 10c0/08ddc1516e6504bc794257cc7a5b788068afce5f0bdb1c98458d6e7eb9e5b96385f5f4912f92909aad72b4e20083c1472e16d7c05d008bd84a5f3a6d38bb1e95 + checksum: 10c0/bbe0e182185c72e4136a4cf37b2366952ad5b1d090de00a132757d2a65a5a6aef95ada93dffdc4ed0cf4338a0ff29c5a0d025d77e8b774b088c69bd68ac07ca6 languageName: node linkType: hard @@ -6048,9 +6109,9 @@ __metadata: linkType: hard "core-js@npm:^3.30.2, core-js@npm:^3.45.0": - version: 3.45.1 - resolution: "core-js@npm:3.45.1" - checksum: 10c0/c38e5fae5a05ee3a129c45e10056aafe61dbb15fd35d27e0c289f5490387541c89741185e0aeb61acb558559c6697e016c245cca738fa169a73f2b06cd30e6b6 + version: 3.46.0 + resolution: "core-js@npm:3.46.0" + checksum: 10c0/12d559d39a58227881bc6c86c36d24dcfbe2d56e52dac42e35e8643278172596ab67f57ede98baf40b153ca1b830f37420ea32c3f7417c0c5a1fed46438ae187 languageName: node linkType: hard @@ -6112,15 +6173,15 @@ __metadata: linkType: hard "cross-env@npm:^10.0.0": - version: 10.0.0 - resolution: "cross-env@npm:10.0.0" + version: 10.1.0 + resolution: "cross-env@npm:10.1.0" dependencies: "@epic-web/invariant": "npm:^1.0.0" cross-spawn: "npm:^7.0.6" bin: cross-env: dist/bin/cross-env.js cross-env-shell: dist/bin/cross-env-shell.js - checksum: 10c0/d16ffc3734106577d57b6253d81ab50294623bd59f96e161033eaf99c1c308ffbaba8463c23a6c0f72e841eff467cb7007a0a551f27554fcf2bbf6598cd828f9 + checksum: 10c0/834a862db456ba1fedf6c6da43436b123ae38f514fa286d6f0937c14fa83f13469f77f70f2812db041ae2d84f82bac627040b8686030aca27fbdf113dfa38b63 languageName: node linkType: hard @@ -8318,15 +8379,15 @@ __metadata: languageName: node linkType: hard -"intl-messageformat@npm:10.7.16, intl-messageformat@npm:^10.7.16": - version: 10.7.16 - resolution: "intl-messageformat@npm:10.7.16" +"intl-messageformat@npm:10.7.18, intl-messageformat@npm:^10.7.16": + version: 10.7.18 + resolution: "intl-messageformat@npm:10.7.18" dependencies: - "@formatjs/ecma402-abstract": "npm:2.3.4" + "@formatjs/ecma402-abstract": "npm:2.3.6" "@formatjs/fast-memoize": "npm:2.2.7" - "@formatjs/icu-messageformat-parser": "npm:2.11.2" + "@formatjs/icu-messageformat-parser": "npm:2.11.4" tslib: "npm:^2.8.0" - checksum: 10c0/537735bf6439f0560f132895d117df6839957ac04cdd58d861f6da86803d40bfc19059e3d341ddb8de87214b73a6329b57f9acdb512bb0f745dcf08729507b9b + checksum: 10c0/d54da9987335cb2bca26246304cea2ca6b1cb44ca416d6b28f3aa62b11477c72f7ce0bf3f11f5d236ceb1842bdc3378a926e606496d146fde18783ec92c314e1 languageName: node linkType: hard @@ -8340,8 +8401,8 @@ __metadata: linkType: hard "ioredis@npm:^5.3.2": - version: 5.8.0 - resolution: "ioredis@npm:5.8.0" + version: 5.8.1 + resolution: "ioredis@npm:5.8.1" dependencies: "@ioredis/commands": "npm:1.4.0" cluster-key-slot: "npm:^1.1.0" @@ -8352,7 +8413,7 @@ __metadata: redis-errors: "npm:^1.2.0" redis-parser: "npm:^3.0.0" standard-as-callback: "npm:^2.1.0" - checksum: 10c0/66fad6283c6d9052b4aa0987d592c1bf6c9471304eb0edf0c9d18024b1b38028adf29c05f1cf114b90f5bdb516576f897a654946e8c29568f404ac33cd3b9d19 + checksum: 10c0/4ed66444017150da027bce940a24bf726994691e2a7b3aa11d52f8aeb37f258068cc171af4d9c61247acafc28eb086fa8a7c79420b8e8d2907d2f74f39584465 languageName: node linkType: hard @@ -8941,16 +9002,16 @@ __metadata: languageName: node linkType: hard -"json-stable-stringify@npm:^1.1.1": - version: 1.2.1 - resolution: "json-stable-stringify@npm:1.2.1" +"json-stable-stringify@npm:^1.1.1, json-stable-stringify@npm:^1.3.0": + version: 1.3.0 + resolution: "json-stable-stringify@npm:1.3.0" dependencies: call-bind: "npm:^1.0.8" - call-bound: "npm:^1.0.3" + call-bound: "npm:^1.0.4" isarray: "npm:^2.0.5" jsonify: "npm:^0.0.1" object-keys: "npm:^1.1.1" - checksum: 10c0/e623e7ce89282f089d56454087edb717357e8572089b552fbc6980fb7814dc3943f7d0e4f1a19429a36ce9f4428b6c8ee6883357974457aaaa98daba5adebeea + checksum: 10c0/8b3ff19e4c23c0ad591a49bc3a015d89a538db787d12fe9c4072e1d64d8cfa481f8c37719c629c3d84e848847617bf49f5fee894cf1d25959ab5b67e1c517f31 languageName: node linkType: hard @@ -10339,8 +10400,8 @@ __metadata: linkType: hard "pino@npm:^9.0.0": - version: 9.12.0 - resolution: "pino@npm:9.12.0" + version: 9.13.1 + resolution: "pino@npm:9.13.1" dependencies: atomic-sleep: "npm:^1.0.0" on-exit-leak-free: "npm:^2.1.0" @@ -10355,7 +10416,7 @@ __metadata: thread-stream: "npm:^3.0.0" bin: pino: bin.js - checksum: 10c0/5cfe093e972a8471a90f7f380c01379eed3fd937038acb97d1de9180f097c044855ca89a2e70baa699aec3e8dcaec037d03e2c90dde235102a3e17b40f54cc1f + checksum: 10c0/c99e879f9538f7255488ad276a46a857cf9114217b754b850b7f1441e31b724a6d6f0697228ead954d3d9601522704e03cad5d441c228108073eed2f37ea0e41 languageName: node linkType: hard @@ -11142,16 +11203,16 @@ __metadata: linkType: hard "react-intl@npm:^7.1.10": - version: 7.1.11 - resolution: "react-intl@npm:7.1.11" + version: 7.1.14 + resolution: "react-intl@npm:7.1.14" dependencies: - "@formatjs/ecma402-abstract": "npm:2.3.4" - "@formatjs/icu-messageformat-parser": "npm:2.11.2" - "@formatjs/intl": "npm:3.1.6" + "@formatjs/ecma402-abstract": "npm:2.3.6" + "@formatjs/icu-messageformat-parser": "npm:2.11.4" + "@formatjs/intl": "npm:3.1.8" "@types/hoist-non-react-statics": "npm:^3.3.1" "@types/react": "npm:16 || 17 || 18 || 19" hoist-non-react-statics: "npm:^3.3.2" - intl-messageformat: "npm:10.7.16" + intl-messageformat: "npm:10.7.18" tslib: "npm:^2.8.0" peerDependencies: react: 16 || 17 || 18 || 19 @@ -11159,7 +11220,7 @@ __metadata: peerDependenciesMeta: typescript: optional: true - checksum: 10c0/f20770fb7bcce7a67acec70b9183f5320b7f3f9bbcb263ca8f4787817297674d1be158687f94d1e2803a9c8696d4f93dd86a28898aba8bc5197e858313e3dd06 + checksum: 10c0/b4361427ea05b4c9e7d87635a323854ca871710e01cd2a46b5da70b34b78a50661c04b2065258f3f49be134ca414c429c804bc34edc277784a9ffa0c04a30b04 languageName: node linkType: hard @@ -11804,8 +11865,8 @@ __metadata: linkType: hard "rollup-plugin-visualizer@npm:^6.0.3": - version: 6.0.3 - resolution: "rollup-plugin-visualizer@npm:6.0.3" + version: 6.0.4 + resolution: "rollup-plugin-visualizer@npm:6.0.4" dependencies: open: "npm:^8.0.0" picomatch: "npm:^4.0.2" @@ -11821,7 +11882,7 @@ __metadata: optional: true bin: rollup-plugin-visualizer: dist/bin/cli.js - checksum: 10c0/595d68936a6338744e8facd165fceedf7f2ebedc44863e640e725198001ed62948cc4a5d8403aa74e679de92957e4def3b1dffc4a9f8de71e4245929566553a3 + checksum: 10c0/e5d472bec0c863c9c3c46f55b303a9457e854bf1b654215e727a586da12897e2cfc30029f029c6c44dd8e9e61ce0d22f113a68ed8e5fe2256abeb58f265c0a89 languageName: node linkType: hard @@ -12800,62 +12861,62 @@ __metadata: languageName: node linkType: hard -"stylelint-config-recommended-scss@npm:^15.0.1": - version: 15.0.1 - resolution: "stylelint-config-recommended-scss@npm:15.0.1" +"stylelint-config-recommended-scss@npm:^16.0.1": + version: 16.0.2 + resolution: "stylelint-config-recommended-scss@npm:16.0.2" dependencies: postcss-scss: "npm:^4.0.9" - stylelint-config-recommended: "npm:^16.0.0" - stylelint-scss: "npm:^6.12.0" + stylelint-config-recommended: "npm:^17.0.0" + stylelint-scss: "npm:^6.12.1" peerDependencies: postcss: ^8.3.3 - stylelint: ^16.16.0 + stylelint: ^16.24.0 peerDependenciesMeta: postcss: optional: true - checksum: 10c0/8c5854e143145241dbff3d921298eb59e837aa695c0e6d7f08acf75de81f3f8307d39a931781bf8ac7cbe6bf9079a402fee89566206e9cfb1d728ef6b6486890 + checksum: 10c0/d4e30a881e248d8b039347bf967526f6afe6d6a07f18e2747e14568de32273e819ba478be7a61a0dd63178931b4e891050a34e73d296ab533aa434209a7f3146 languageName: node linkType: hard -"stylelint-config-recommended@npm:^16.0.0": +"stylelint-config-recommended@npm:^17.0.0": + version: 17.0.0 + resolution: "stylelint-config-recommended@npm:17.0.0" + peerDependencies: + stylelint: ^16.23.0 + checksum: 10c0/49e5d1c0f58197b2c5585b85fad814fed9bdec44c9870368c46a762664c5ff158c1145b6337456ae194409d692992b5b87421d62880422f71d8a3360417f5ad1 + languageName: node + linkType: hard + +"stylelint-config-standard-scss@npm:^16.0.0": version: 16.0.0 - resolution: "stylelint-config-recommended@npm:16.0.0" - peerDependencies: - stylelint: ^16.16.0 - checksum: 10c0/b2b4ea2633a606a0f686521aa5e8908810c9dd21fd4525c86b34213de1e362b445fd5472b6e5ff251d46f999e2ca2c6c704f2efc1c08d5a532084427f4e1c9d8 - languageName: node - linkType: hard - -"stylelint-config-standard-scss@npm:^15.0.1": - version: 15.0.1 - resolution: "stylelint-config-standard-scss@npm:15.0.1" + resolution: "stylelint-config-standard-scss@npm:16.0.0" dependencies: - stylelint-config-recommended-scss: "npm:^15.0.1" - stylelint-config-standard: "npm:^38.0.0" + stylelint-config-recommended-scss: "npm:^16.0.1" + stylelint-config-standard: "npm:^39.0.0" peerDependencies: postcss: ^8.3.3 - stylelint: ^16.18.0 + stylelint: ^16.23.1 peerDependenciesMeta: postcss: optional: true - checksum: 10c0/85b4c85a9ecd97176ac104fb4590cd48047b6253b830d08749c024752b9bc8871bbf69eca592769d69cd4c6e3f90005960630f1c2cdaf85dbfabdb5621ecc55f + checksum: 10c0/eb77f23824c5d649b193cb71d7f9b538b32b8cc1769451b2993270361127243d4011baf891ec265711b8e34e69ce28acb57ab6c3947b51fa3713ac26f4276439 languageName: node linkType: hard -"stylelint-config-standard@npm:^38.0.0": - version: 38.0.0 - resolution: "stylelint-config-standard@npm:38.0.0" +"stylelint-config-standard@npm:^39.0.0": + version: 39.0.1 + resolution: "stylelint-config-standard@npm:39.0.1" dependencies: - stylelint-config-recommended: "npm:^16.0.0" + stylelint-config-recommended: "npm:^17.0.0" peerDependencies: - stylelint: ^16.18.0 - checksum: 10c0/8b52c7b7d6287c7495a8fe3a681e07ea9478374e7e66b28d61779072d46cd5b845530b2410df7496a008a8efafe834fb46cf07792f4cf57f996e39f24a801b90 + stylelint: ^16.23.0 + checksum: 10c0/70a9862a2cedcc2a1807bd92fc91c40877270cf8a39576b91ae056d6de51d3b68104b26f71056ff22461b4319e9ec988d009abf10ead513b2ec15569d82e865a languageName: node linkType: hard -"stylelint-scss@npm:^6.12.0": - version: 6.12.0 - resolution: "stylelint-scss@npm:6.12.0" +"stylelint-scss@npm:^6.12.1": + version: 6.12.1 + resolution: "stylelint-scss@npm:6.12.1" dependencies: css-tree: "npm:^3.0.1" is-plain-object: "npm:^5.0.0" @@ -12867,7 +12928,7 @@ __metadata: postcss-value-parser: "npm:^4.2.0" peerDependencies: stylelint: ^16.0.2 - checksum: 10c0/c0ba314badd22118047e374febf8dabac56bd351d612ed9c9fc2da5dc760996c2768605aa8d4e483cf0b0fe649c35ae5a003c8a872ee5bec1bbc2d8d45673ff5 + checksum: 10c0/9a0903d34be3c75a72bef32402899db5f6b94c0823c5944fdf1acb2c3dc61c1f70fbb322558f8cb7e42dd01ed5e0dec22ed298f03b7bacc9f467c28330acae71 languageName: node linkType: hard @@ -13420,18 +13481,18 @@ __metadata: languageName: node linkType: hard -"typescript-eslint@npm:^8.28.0, typescript-eslint@npm:^8.29.1": - version: 8.38.0 - resolution: "typescript-eslint@npm:8.38.0" +"typescript-eslint@npm:^8.28.0, typescript-eslint@npm:^8.45.0": + version: 8.45.0 + resolution: "typescript-eslint@npm:8.45.0" dependencies: - "@typescript-eslint/eslint-plugin": "npm:8.38.0" - "@typescript-eslint/parser": "npm:8.38.0" - "@typescript-eslint/typescript-estree": "npm:8.38.0" - "@typescript-eslint/utils": "npm:8.38.0" + "@typescript-eslint/eslint-plugin": "npm:8.45.0" + "@typescript-eslint/parser": "npm:8.45.0" + "@typescript-eslint/typescript-estree": "npm:8.45.0" + "@typescript-eslint/utils": "npm:8.45.0" peerDependencies: eslint: ^8.57.0 || ^9.0.0 - typescript: ">=4.8.4 <5.9.0" - checksum: 10c0/486b9862ee08f7827d808a2264ce03b58087b11c4c646c0da3533c192a67ae3fcb4e68d7a1e69d0f35a1edc274371a903a50ecfe74012d5eaa896cb9d5a81e0b + typescript: ">=4.8.4 <6.0.0" + checksum: 10c0/2342b0bffe6f719711adbb42116f90cb1fe1670e2e74dde2739482c9d61c2a975ee16e2d560684613050544b543342ec1b11b46e158a48ecc605f5882d2d5da7 languageName: node linkType: hard @@ -13813,8 +13874,8 @@ __metadata: linkType: hard "vite-plugin-pwa@npm:^1.0.2": - version: 1.0.3 - resolution: "vite-plugin-pwa@npm:1.0.3" + version: 1.1.0 + resolution: "vite-plugin-pwa@npm:1.1.0" dependencies: debug: "npm:^4.3.6" pretty-bytes: "npm:^6.1.1" @@ -13829,7 +13890,7 @@ __metadata: peerDependenciesMeta: "@vite-pwa/assets-generator": optional: true - checksum: 10c0/03fc24bd12ae4a4130979da4877e3dabddf13d7d6ff2bd68e5e8497a2643b8874a78e6c2502874277ddf2f28593d0a3b025d78af2335bdcc5d2966295784fd46 + checksum: 10c0/dc199ccbb3cd0a9f740edcbbc8efa7820f67481ae80a15340ca769c21d4f7452d9a9c1d184eac4f6e3fd1ecd9f7fdfd31cc8f9520e43e6795860fe187c77103a languageName: node linkType: hard @@ -13878,8 +13939,8 @@ __metadata: linkType: hard "vite@npm:^5.0.0 || ^6.0.0 || ^7.0.0-0, vite@npm:^7.1.1": - version: 7.1.7 - resolution: "vite@npm:7.1.7" + version: 7.1.10 + resolution: "vite@npm:7.1.10" dependencies: esbuild: "npm:^0.25.0" fdir: "npm:^6.5.0" @@ -13928,7 +13989,7 @@ __metadata: optional: true bin: vite: bin/vite.js - checksum: 10c0/3f6bd61a65aaa81368f4dda804f0e23b103664724218ccb5a0b1a0c7e284df498107b57ced951dc40ae4c5d472435bc8fb5c836414e729ee7e102809eaf6ff80 + checksum: 10c0/ea296971a3094b0e463a91af58de64dca56c8c5c563237e59d158641f8ad7f600f624c4f7c05c18fad68f414e23d50d7145118169b8dcd4bc85283c63c7185bb languageName: node linkType: hard