From ab1a5b48226b301cf634f4d109af36c2d1667507 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Mon, 4 Aug 2025 08:46:38 +0200 Subject: [PATCH 01/23] Update Node.js to 22.18 (#35621) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- .nvmrc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.nvmrc b/.nvmrc index 4a203c23d83..f1c8f6b0d0f 100644 --- a/.nvmrc +++ b/.nvmrc @@ -1 +1 @@ -22.17 +22.18 From bf46cffd9eb6a8aa3e623c9bfdadc3b67b4959e6 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Mon, 4 Aug 2025 08:48:16 +0200 Subject: [PATCH 02/23] Update peter-evans/create-pull-request action to v7.0.8 (#35648) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- .github/workflows/crowdin-download-stable.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/crowdin-download-stable.yml b/.github/workflows/crowdin-download-stable.yml index 6d9a0586298..8e18a9d0a0f 100644 --- a/.github/workflows/crowdin-download-stable.yml +++ b/.github/workflows/crowdin-download-stable.yml @@ -50,7 +50,7 @@ jobs: # Create or update the pull request - name: Create Pull Request - uses: peter-evans/create-pull-request@v7.0.6 + uses: peter-evans/create-pull-request@v7.0.8 with: commit-message: 'New Crowdin translations' title: 'New Crowdin Translations for ${{ github.base_ref || github.ref_name }} (automated)' From 05cdd3f6eb1b53174ed18bdd8697cfff9649a146 Mon Sep 17 00:00:00 2001 From: David Roetzel Date: Mon, 4 Aug 2025 09:43:34 +0200 Subject: [PATCH 03/23] Track delivery failures to FASP (#35628) --- app/lib/fasp/request.rb | 4 ++++ app/models/fasp/provider.rb | 4 ++++ spec/lib/fasp/request_spec.rb | 23 +++++++++++++++++++++++ spec/models/fasp/provider_spec.rb | 8 ++++++++ 4 files changed, 39 insertions(+) diff --git a/app/lib/fasp/request.rb b/app/lib/fasp/request.rb index 2002e90bb06..51950a004a2 100644 --- a/app/lib/fasp/request.rb +++ b/app/lib/fasp/request.rb @@ -32,8 +32,12 @@ class Fasp::Request .send(verb, url, body:) validate!(response) + @provider.delivery_failure_tracker.track_success! response.parse if response.body.present? + rescue *::Mastodon::HTTP_CONNECTION_ERRORS + @provider.delivery_failure_tracker.track_failure! + raise end def request_headers(_verb, _url, body = '') diff --git a/app/models/fasp/provider.rb b/app/models/fasp/provider.rb index 37d0b581ca1..9f7be482fed 100644 --- a/app/models/fasp/provider.rb +++ b/app/models/fasp/provider.rb @@ -118,6 +118,10 @@ class Fasp::Provider < ApplicationRecord save! end + def delivery_failure_tracker + @delivery_failure_tracker ||= DeliveryFailureTracker.new(base_url, resolution: :minutes) + end + private def create_keypair diff --git a/spec/lib/fasp/request_spec.rb b/spec/lib/fasp/request_spec.rb index 9b354c8f44b..380b7951242 100644 --- a/spec/lib/fasp/request_spec.rb +++ b/spec/lib/fasp/request_spec.rb @@ -27,6 +27,14 @@ RSpec.describe Fasp::Request do 'Signature-Input' => /.+/, }) end + + it 'tracks that a successful connection was made' do + provider.delivery_failure_tracker.track_failure! + + expect do + subject.send(method, '/test_path') + end.to change(provider.delivery_failure_tracker, :failures).from(1).to(0) + end end context 'when the response is not signed' do @@ -55,6 +63,21 @@ RSpec.describe Fasp::Request do end end end + + context 'when the request raises an error' do + before do + stub_request(method, 'https://reqprov.example.com/fasp/test_path') + .to_raise(HTTP::ConnectionError) + end + + it "records the failure using the provider's delivery failure tracker" do + expect do + subject.send(method, '/test_path') + end.to raise_error(HTTP::ConnectionError) + + expect(provider.delivery_failure_tracker.failures).to eq 1 + end + end end describe '#get' do diff --git a/spec/models/fasp/provider_spec.rb b/spec/models/fasp/provider_spec.rb index 52df4638fdc..9fd2c4c2348 100644 --- a/spec/models/fasp/provider_spec.rb +++ b/spec/models/fasp/provider_spec.rb @@ -206,4 +206,12 @@ RSpec.describe Fasp::Provider do end end end + + describe '#delivery_failure_tracker' do + subject { Fabricate(:fasp_provider) } + + it 'returns a `DeliverFailureTracker` instance' do + expect(subject.delivery_failure_tracker).to be_a(DeliveryFailureTracker) + end + end end From 927cfea5aefb5f210b2ae8af307b812b91d0f4c3 Mon Sep 17 00:00:00 2001 From: Claire Date: Mon, 4 Aug 2025 09:49:08 +0200 Subject: [PATCH 04/23] Update dependency ruby-saml to v1.18.1 (#35650) --- Gemfile.lock | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Gemfile.lock b/Gemfile.lock index 19a97ef4962..3c5fc08ff12 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -805,7 +805,7 @@ GEM ruby-prof (1.7.2) base64 ruby-progressbar (1.13.0) - ruby-saml (1.18.0) + ruby-saml (1.18.1) nokogiri (>= 1.13.10) rexml ruby-vips (2.2.4) From 3caa318dfe6b5bb8c379a03941f1f42a84df0f7f Mon Sep 17 00:00:00 2001 From: Claire Date: Mon, 4 Aug 2025 09:49:12 +0200 Subject: [PATCH 05/23] Fix WebUI crashing for accounts with `null` URL (#35651) --- app/javascript/mastodon/api_types/accounts.ts | 2 +- app/javascript/mastodon/models/account.ts | 7 ++++--- app/serializers/rest/account_serializer.rb | 2 +- 3 files changed, 6 insertions(+), 5 deletions(-) diff --git a/app/javascript/mastodon/api_types/accounts.ts b/app/javascript/mastodon/api_types/accounts.ts index b93054a1f6f..913a201fef4 100644 --- a/app/javascript/mastodon/api_types/accounts.ts +++ b/app/javascript/mastodon/api_types/accounts.ts @@ -37,7 +37,7 @@ export interface BaseApiAccountJSON { roles?: ApiAccountJSON[]; statuses_count: number; uri: string; - url: string; + url?: string; username: string; moved?: ApiAccountJSON; suspended?: boolean; diff --git a/app/javascript/mastodon/models/account.ts b/app/javascript/mastodon/models/account.ts index 75a5c09b9d8..3b0c41be818 100644 --- a/app/javascript/mastodon/models/account.ts +++ b/app/javascript/mastodon/models/account.ts @@ -45,7 +45,7 @@ const AccountRoleFactory = ImmutableRecord({ // Account export interface AccountShape extends Required< - Omit + Omit > { emojis: ImmutableList; fields: ImmutableList; @@ -55,6 +55,7 @@ export interface AccountShape note_plain: string | null; hidden: boolean; moved: string | null; + url: string; } export type Account = RecordOf; @@ -148,8 +149,8 @@ export function createAccountFromServerJSON(serverJSON: ApiAccountJSON) { note_emojified: emojify(accountNote, emojiMap), note_plain: unescapeHTML(accountNote), url: - accountJSON.url.startsWith('http://') || - accountJSON.url.startsWith('https://') + accountJSON.url?.startsWith('http://') || + accountJSON.url?.startsWith('https://') ? accountJSON.url : accountJSON.uri, }); diff --git a/app/serializers/rest/account_serializer.rb b/app/serializers/rest/account_serializer.rb index 354d384464d..b102f79fdb9 100644 --- a/app/serializers/rest/account_serializer.rb +++ b/app/serializers/rest/account_serializer.rb @@ -65,7 +65,7 @@ class REST::AccountSerializer < ActiveModel::Serializer end def url - ActivityPub::TagManager.instance.url_for(object) + ActivityPub::TagManager.instance.url_for(object) || ActivityPub::TagManager.instance.uri_for(object) end def uri From 3d3d2c93d6b03050fb3d048276e6b2933ac33501 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Mon, 4 Aug 2025 10:12:11 +0200 Subject: [PATCH 06/23] Update DefinitelyTyped types (non-major) (#35647) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- yarn.lock | 39 ++++++++++++++++++++------------------- 1 file changed, 20 insertions(+), 19 deletions(-) diff --git a/yarn.lock b/yarn.lock index 377f2999c85..6e55410e31c 100644 --- a/yarn.lock +++ b/yarn.lock @@ -3925,11 +3925,11 @@ __metadata: linkType: hard "@types/cors@npm:^2.8.16": - version: 2.8.18 - resolution: "@types/cors@npm:2.8.18" + version: 2.8.19 + resolution: "@types/cors@npm:2.8.19" dependencies: "@types/node": "npm:*" - checksum: 10c0/9dd1075de0e3a40c304826668960c797e67e597a734fb8e8ab404561f31ef2bd553ef5500eb86da7e91a344bee038a59931d2fbf182fbce09f13816f51fdd80e + checksum: 10c0/b5dd407040db7d8aa1bd36e79e5f3f32292f6b075abc287529e9f48df1a25fda3e3799ba30b4656667ffb931d3b75690c1d6ca71e39f7337ea6dfda8581916d0 languageName: node linkType: hard @@ -4016,14 +4016,14 @@ __metadata: linkType: hard "@types/express@npm:^4.17.17": - version: 4.17.22 - resolution: "@types/express@npm:4.17.22" + version: 4.17.23 + resolution: "@types/express@npm:4.17.23" dependencies: "@types/body-parser": "npm:*" "@types/express-serve-static-core": "npm:^4.17.33" "@types/qs": "npm:*" "@types/serve-static": "npm:*" - checksum: 10c0/15c10a5ebb40a0356baa95ed374a2150d862786c9fccbdd724df12acc9c8cb08fbe1d34b446b1bcef2dbe5305cb3013fb39fba791baa54ef6df8056482776abb + checksum: 10c0/60490cd4f73085007247e7d4fafad0a7abdafa34fa3caba2757512564ca5e094ece7459f0f324030a63d513f967bb86579a8682af76ae2fd718e889b0a2a4fe8 languageName: node linkType: hard @@ -4035,12 +4035,13 @@ __metadata: linkType: hard "@types/hoist-non-react-statics@npm:^3.3.1": - version: 3.3.6 - resolution: "@types/hoist-non-react-statics@npm:3.3.6" + version: 3.3.7 + resolution: "@types/hoist-non-react-statics@npm:3.3.7" dependencies: - "@types/react": "npm:*" hoist-non-react-statics: "npm:^3.3.0" - checksum: 10c0/149a4c217d81f21f8a1e152160a59d5b99b6a9aa6d354385d5f5bc02760cbf1e170a8442ba92eb653befff44b0c5bc2234bb77ce33e0d11a65f779e8bab5c321 + peerDependencies: + "@types/react": "*" + checksum: 10c0/ed8f4e88338f7d021d0f956adf6089d2a12b2e254a03c05292324f2e986d2376eb9efdb8a4f04596823e8fca88c9d06361d20dab4a2a00dc935fb36ac911de55 languageName: node linkType: hard @@ -4096,9 +4097,9 @@ __metadata: linkType: hard "@types/lodash@npm:^4.14.195": - version: 4.17.17 - resolution: "@types/lodash@npm:4.17.17" - checksum: 10c0/8e75df02a15f04d4322c5a503e4efd0e7a92470570ce80f17e9f11ce2b1f1a7c994009c9bcff39f07e0f9ffd8ccaff09b3598997c404b801abd5a7eee5a639dc + version: 4.17.20 + resolution: "@types/lodash@npm:4.17.20" + checksum: 10c0/98cdd0faae22cbb8079a01a3bb65aa8f8c41143367486c1cbf5adc83f16c9272a2a5d2c1f541f61d0d73da543c16ee1d21cf2ef86cb93cd0cc0ac3bced6dd88f languageName: node linkType: hard @@ -4154,13 +4155,13 @@ __metadata: linkType: hard "@types/pg@npm:^8.6.6": - version: 8.15.4 - resolution: "@types/pg@npm:8.15.4" + version: 8.15.5 + resolution: "@types/pg@npm:8.15.5" dependencies: "@types/node": "npm:*" pg-protocol: "npm:*" pg-types: "npm:^2.2.0" - checksum: 10c0/7f9295cb2d934681bba84f7caad529c3b100d87e83ad0732c7fe496f4f79e42a795097321db54e010fcff22cb5e410cf683b4c9941907ee4564c822242816e91 + checksum: 10c0/19a3cc1811918753f8c827733648c3a85c7b0355bf207c44eb1a3b79b2e6a0d85cb5457ec550d860fc9be7e88c7587a3600958ec8c61fa1ad573061c63af93f0 languageName: node linkType: hard @@ -4172,9 +4173,9 @@ __metadata: linkType: hard "@types/prop-types@npm:*, @types/prop-types@npm:^15.7.5": - version: 15.7.14 - resolution: "@types/prop-types@npm:15.7.14" - checksum: 10c0/1ec775160bfab90b67a782d735952158c7e702ca4502968aa82565bd8e452c2de8601c8dfe349733073c31179116cf7340710160d3836aa8a1ef76d1532893b1 + version: 15.7.15 + resolution: "@types/prop-types@npm:15.7.15" + checksum: 10c0/b59aad1ad19bf1733cf524fd4e618196c6c7690f48ee70a327eb450a42aab8e8a063fbe59ca0a5701aebe2d92d582292c0fb845ea57474f6a15f6994b0e260b2 languageName: node linkType: hard From 1228e000a1058e2437b00a0de95d8b278077c358 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Mon, 4 Aug 2025 10:33:17 +0200 Subject: [PATCH 07/23] Update dependency pg to v1.6.1 (#35559) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- Gemfile.lock | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Gemfile.lock b/Gemfile.lock index 3c5fc08ff12..2901f24ed24 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -607,7 +607,7 @@ GEM parslet (2.0.0) pastel (0.8.0) tty-color (~> 0.5) - pg (1.6.0) + pg (1.6.1) pghero (3.7.0) activerecord (>= 7.1) playwright-ruby-client (1.54.0) From 895975e2abe4de55307e4067bbfc599e7920a5f2 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Mon, 4 Aug 2025 10:33:41 +0200 Subject: [PATCH 08/23] Update dependency haml_lint to v0.66.0 (#35649) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- Gemfile.lock | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Gemfile.lock b/Gemfile.lock index 2901f24ed24..2b6ba0d4852 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -287,7 +287,7 @@ GEM activesupport (>= 5.1) haml (>= 4.0.6) railties (>= 5.1) - haml_lint (0.65.1) + haml_lint (0.66.0) haml (>= 5.0) parallel (~> 1.10) rainbow @@ -721,7 +721,7 @@ GEM connection_pool redlock (1.3.2) redis (>= 3.0.0, < 6.0) - regexp_parser (2.10.0) + regexp_parser (2.11.0) reline (0.6.2) io-console (~> 0.5) request_store (1.7.0) From 59e729e3fef1afaf611e1dd47ed32394fcfbe9e7 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Mon, 4 Aug 2025 10:34:04 +0200 Subject: [PATCH 09/23] Update dependency ioredis to v5.7.0 (#35617) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- yarn.lock | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/yarn.lock b/yarn.lock index 6e55410e31c..8148fab1c86 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2511,10 +2511,10 @@ __metadata: languageName: node linkType: hard -"@ioredis/commands@npm:^1.1.1": - version: 1.2.0 - resolution: "@ioredis/commands@npm:1.2.0" - checksum: 10c0/a5d3c29dd84d8a28b7c67a441ac1715cbd7337a7b88649c0f17c345d89aa218578d2b360760017c48149ef8a70f44b051af9ac0921a0622c2b479614c4f65b36 +"@ioredis/commands@npm:^1.3.0": + version: 1.3.0 + resolution: "@ioredis/commands@npm:1.3.0" + checksum: 10c0/5ab990a8f69c20daf3d7d64307aa9f13ee727c92ab4c7664a6943bb500227667a0c368892e9c4913f06416377db47dba78d58627fe723da476d25f2c04a6d5aa languageName: node linkType: hard @@ -8353,10 +8353,10 @@ __metadata: linkType: hard "ioredis@npm:^5.3.2": - version: 5.6.1 - resolution: "ioredis@npm:5.6.1" + version: 5.7.0 + resolution: "ioredis@npm:5.7.0" dependencies: - "@ioredis/commands": "npm:^1.1.1" + "@ioredis/commands": "npm:^1.3.0" cluster-key-slot: "npm:^1.1.0" debug: "npm:^4.3.4" denque: "npm:^2.1.0" @@ -8365,7 +8365,7 @@ __metadata: redis-errors: "npm:^1.2.0" redis-parser: "npm:^3.0.0" standard-as-callback: "npm:^2.1.0" - checksum: 10c0/26ae49cf448e807e454a9bdea5a9dfdcf669e2fdbf2df341900a0fb693c5662fea7e39db3227ce8972d1bda0ba7da9b7410e5163b12d8878a579548d847220ac + checksum: 10c0/c63c521a953bfaf29f8c8871b122af38e439328336fa238f83bfbb066556f64daf69ed7a4ec01fc7b9ee1f0862059dd188b8c684150125d362d36642399b30ee languageName: node linkType: hard From f68bd21600aaab5a928de7eda56a132efeefd9f2 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Mon, 4 Aug 2025 11:20:50 +0200 Subject: [PATCH 10/23] New Crowdin Translations (automated) (#35634) Co-authored-by: GitHub Actions --- app/javascript/mastodon/locales/fi.json | 2 +- app/javascript/mastodon/locales/la.json | 7 +++ app/javascript/mastodon/locales/nan.json | 3 + app/javascript/mastodon/locales/pl.json | 70 +++++++++++++++++++++++- app/javascript/mastodon/locales/tr.json | 7 +++ config/locales/activerecord.pl.yml | 6 ++ config/locales/da.yml | 2 +- config/locales/el.yml | 2 + config/locales/et.yml | 3 + config/locales/fo.yml | 2 + config/locales/nan.yml | 54 ++++++++++++++++++ config/locales/pl.yml | 66 ++++++++++++++++++++++ config/locales/ru.yml | 34 ++++++------ config/locales/simple_form.da.yml | 2 +- config/locales/simple_form.el.yml | 1 + config/locales/simple_form.fo.yml | 1 + config/locales/simple_form.pl.yml | 12 ++++ config/locales/simple_form.tr.yml | 9 +++ config/locales/tr.yml | 29 +++++++++- 19 files changed, 290 insertions(+), 22 deletions(-) diff --git a/app/javascript/mastodon/locales/fi.json b/app/javascript/mastodon/locales/fi.json index 6efe46693d4..9e52dcb069f 100644 --- a/app/javascript/mastodon/locales/fi.json +++ b/app/javascript/mastodon/locales/fi.json @@ -756,7 +756,7 @@ "reply_indicator.cancel": "Peruuta", "reply_indicator.poll": "Äänestys", "report.block": "Estä", - "report.block_explanation": "Et näe hänen julkaisujaan. Hän voi nähdä julkaisujasi eikä seurata sinua. Hän näkee, että olet estänyt hänet.", + "report.block_explanation": "Et näe hänen julkaisujaan. Hän ei voi nähdä julkaisujasi eikä seurata sinua. Hän näkee, että olet estänyt hänet.", "report.categories.legal": "Lakiseikat", "report.categories.other": "Muu", "report.categories.spam": "Roskaposti", diff --git a/app/javascript/mastodon/locales/la.json b/app/javascript/mastodon/locales/la.json index 5d34aafafce..720e940996f 100644 --- a/app/javascript/mastodon/locales/la.json +++ b/app/javascript/mastodon/locales/la.json @@ -1,6 +1,7 @@ { "about.blocks": "Servī moderātī", "about.contact": "Ratio:", + "about.default_locale": "Default", "about.disclaimer": "Mastodon est software līberum, apertum fontem, et nōtam commercium Mastodon gGmbH.", "about.domain_blocks.no_reason_available": "Ratio abdere est", "about.domain_blocks.preamble": "Mastodon genērāliter sinit tē contentum ex aliīs servientibus in fedīversō vidēre et cum usoribus ab iīs interāgere. Haē sunt exceptionēs quae in hōc particulārī servientē factae sunt.", @@ -8,6 +9,7 @@ "about.domain_blocks.silenced.title": "Limitātus", "about.domain_blocks.suspended.explanation": "Nulla data ab hōc servientē processābuntur, servābuntur aut commūtābuntur, faciendumque omnem interactionem aut communicātiōnem cum usoribus ab hōc servientē impossibilem.", "about.domain_blocks.suspended.title": "suspensus", + "about.language_label": "Linguae", "about.not_available": "Haec informātiō in hōc servientē nōn praebita est.", "about.powered_by": "Nuntii socīālēs decentralizātī ā {mastodon} sustentātī.", "about.rules": "Servo praecepta", @@ -41,7 +43,12 @@ "account.followers": "Sectatores", "account.followers.empty": "Nemo hunc usorem adhuc sequitur.", "account.followers_counter": "{count, plural, one {{counter} sectator} other {{counter} sectatores}}", + "account.followers_you_know_counter": "{counter} scis", + "account.following": "Sequentia", "account.following_counter": "{count, plural, one {{counter} sectans} other {{counter} sectans}}", + "account.follows.empty": "Hic usor adhuc neminem sequitur.", + "account.follows_you": "Sequitur te", + "account.go_to_profile": "Vade ad profile", "account.moved_to": "{name} significavit eum suam rationem novam nunc esse:", "account.muted": "Confutatus", "account.requested_follow": "{name} postulavit ut te sequeretur", diff --git a/app/javascript/mastodon/locales/nan.json b/app/javascript/mastodon/locales/nan.json index a5611c6c9de..40b3c06281c 100644 --- a/app/javascript/mastodon/locales/nan.json +++ b/app/javascript/mastodon/locales/nan.json @@ -876,6 +876,9 @@ "status.quote_error.filtered": "Lí所設定ê過濾器kā tse khàm起來", "status.quote_error.not_available": "鋪文bē當看", "status.quote_error.pending_approval": "鋪文當咧送", + "status.quote_error.pending_approval_popout.body": "因為無kâng ê服侍器有無kâng ê協定,佇聯邦宇宙分享ê引文可能愛開時間來顯示。", + "status.quote_error.pending_approval_popout.title": "Leh送引文?請sió等leh", + "status.quote_post_author": "引用 @{name} ê PO文ah", "status.read_more": "讀詳細", "status.reblog": "轉送", "status.reblog_private": "照原PO ê通看見ê範圍轉送", diff --git a/app/javascript/mastodon/locales/pl.json b/app/javascript/mastodon/locales/pl.json index bbe5789d2a4..58c3f1fa574 100644 --- a/app/javascript/mastodon/locales/pl.json +++ b/app/javascript/mastodon/locales/pl.json @@ -1,6 +1,7 @@ { "about.blocks": "Serwery moderowane", "about.contact": "Kontakt:", + "about.default_locale": "Domyślny", "about.disclaimer": "Mastodon jest darmowym, otwartym oprogramowaniem i znakiem towarowym Mastodon gGmbH.", "about.domain_blocks.no_reason_available": "Powód niedostępny", "about.domain_blocks.preamble": "Domyślnie Mastodon pozwala ci przeglądać i reagować na treści od innych użytkowników z jakiegokolwiek serwera w fediwersum. Poniżej znajduje się lista wyjątków, które zostały stworzone na tym konkretnym serwerze.", @@ -8,6 +9,7 @@ "about.domain_blocks.silenced.title": "Ograniczone", "about.domain_blocks.suspended.explanation": "Żadne dane z tego serwera nie będą przetwarzane, przechowywane lub wymieniane, co uniemożliwia jakąkolwiek interakcję lub komunikację z użytkownikami z tego serwera.", "about.domain_blocks.suspended.title": "Zawieszono", + "about.language_label": "Język", "about.not_available": "Ta informacja nie została udostępniona na tym serwerze.", "about.powered_by": "Zdecentralizowane media społecznościowe napędzane przez {mastodon}", "about.rules": "Regulamin serwera", @@ -19,13 +21,21 @@ "account.block_domain": "Blokuj wszystko z {domain}", "account.block_short": "Zablokuj", "account.blocked": "Zablokowany(-a)", + "account.blocking": "Blokowanie", "account.cancel_follow_request": "Nie obserwuj", "account.copy": "Skopiuj link do profilu", "account.direct": "Napisz bezpośrednio do @{name}", "account.disable_notifications": "Przestań powiadamiać mnie o wpisach @{name}", + "account.domain_blocking": "Blokowanie domeny", "account.edit_profile": "Edytuj profil", "account.enable_notifications": "Powiadamiaj mnie o wpisach @{name}", "account.endorse": "Wyróżnij na profilu", + "account.familiar_followers_many": "Obserwowane przez: {name1}, {name2} i {othersCount, plural, one {jeszcze jedną osobę, którą znasz} few {# inne osoby, które znasz} many {# innych osób, które znasz} other {# innych osób, które znasz}}", + "account.familiar_followers_one": "Obserwowane przez {name1}", + "account.familiar_followers_two": "Obserwowane przez {name1} i {name2}", + "account.featured": "Wyróżnione", + "account.featured.accounts": "Profile", + "account.featured.hashtags": "Tagi", "account.featured_tags.last_status_at": "Ostatni post {date}", "account.featured_tags.last_status_never": "Brak postów", "account.follow": "Obserwuj", @@ -33,9 +43,11 @@ "account.followers": "Obserwujący", "account.followers.empty": "Nikt jeszcze nie obserwuje tego użytkownika.", "account.followers_counter": "{count, plural, one {{counter} obserwujący} few {{counter} obserwujących} many {{counter} obserwujących} other {{counter} obserwujących}}", + "account.followers_you_know_counter": "{counter} które znasz", "account.following": "Obserwowani", "account.following_counter": "{count, plural, one {{counter} obserwowany} few {{counter} obserwowanych} many {{counter} obserwowanych} other {{counter} obserwowanych}}", "account.follows.empty": "Ten użytkownik nie obserwuje jeszcze nikogo.", + "account.follows_you": "Obserwuje cię", "account.go_to_profile": "Przejdź do profilu", "account.hide_reblogs": "Ukryj podbicia od @{name}", "account.in_memoriam": "Ku pamięci.", @@ -50,18 +62,23 @@ "account.mute_notifications_short": "Wycisz powiadomienia", "account.mute_short": "Wycisz", "account.muted": "Wyciszony", + "account.muting": "Wyciszenie", + "account.mutual": "Obserwujecie siebie nazwajem", "account.no_bio": "Brak opisu.", "account.open_original_page": "Otwórz stronę oryginalną", "account.posts": "Wpisy", "account.posts_with_replies": "Wpisy i odpowiedzi", + "account.remove_from_followers": "Usuń {name} z obserwujących", "account.report": "Zgłoś @{name}", "account.requested": "Oczekująca prośba, kliknij aby anulować", "account.requested_follow": "{name} chce cię zaobserwować", + "account.requests_to_follow_you": "Prośby o obserwowanie", "account.share": "Udostępnij profil @{name}", "account.show_reblogs": "Pokazuj podbicia od @{name}", "account.statuses_counter": "{count, plural, one {{counter} wpis} few {{counter} wpisy} many {{counter} wpisów} other {{counter} wpisów}}", "account.unblock": "Odblokuj @{name}", "account.unblock_domain": "Odblokuj domenę {domain}", + "account.unblock_domain_short": "Odblokuj", "account.unblock_short": "Odblokuj", "account.unendorse": "Nie wyświetlaj w profilu", "account.unfollow": "Nie obserwuj", @@ -202,6 +219,12 @@ "confirmations.delete_list.confirm": "Usuń", "confirmations.delete_list.message": "Czy na pewno chcesz trwale usunąć tę listę?", "confirmations.delete_list.title": "Usunąć listę?", + "confirmations.discard_draft.confirm": "Odrzuć i kontynuuj", + "confirmations.discard_draft.edit.cancel": "Wznów edytowanie", + "confirmations.discard_draft.edit.message": "Kontynuowanie spowoduje utratę wszystkich zmian wprowadzonych przez Ciebie w aktualnie edytowanym poście.", + "confirmations.discard_draft.edit.title": "Odrzucić zmiany w poście?", + "confirmations.discard_draft.post.cancel": "Wznów wersję roboczą", + "confirmations.discard_draft.post.title": "Anulować wersję roboczą?", "confirmations.discard_edit_media.confirm": "Odrzuć", "confirmations.discard_edit_media.message": "Masz niezapisane zmiany w opisie lub podglądzie, odrzucić je mimo to?", "confirmations.follow_to_list.confirm": "Zaobserwuj i dodaj do listy", @@ -218,6 +241,9 @@ "confirmations.redraft.confirm": "Usuń i popraw", "confirmations.redraft.message": "Czy na pewno chcesz usunąć i poprawić ten wpis? Polubienia, podbicia i komentarze pierwotnego wpisu zostaną utracone.", "confirmations.redraft.title": "Usunąć i poprawić wpis?", + "confirmations.remove_from_followers.confirm": "Usuń obserwującego", + "confirmations.remove_from_followers.message": "{name} przestanie Cię obserwować. Czy na pewno chcesz kontynuować?", + "confirmations.remove_from_followers.title": "Usunąć obserwującego?", "confirmations.unfollow.confirm": "Nie obserwuj", "confirmations.unfollow.message": "Czy na pewno nie chcesz obserwować {name}?", "confirmations.unfollow.title": "Cofnąć obserwację?", @@ -307,9 +333,15 @@ "errors.unexpected_crash.copy_stacktrace": "Skopiuj stacktrace do schowka", "errors.unexpected_crash.report_issue": "Zgłoś problem", "explore.suggested_follows": "Ludzie", + "explore.title": "Na czasie", "explore.trending_links": "Aktualności", "explore.trending_statuses": "Wpisy", "explore.trending_tags": "Hasztagi", + "featured_carousel.header": "{count, plural, one {Przypięty post} other {Przypięte posty}}", + "featured_carousel.next": "Następny", + "featured_carousel.post": "Opublikuj", + "featured_carousel.previous": "Poprzedni", + "featured_carousel.slide": "{index} z {total}", "filter_modal.added.context_mismatch_explanation": "To filtrowanie nie dotyczy kategorii, w której pojawił się ten wpis. Jeśli chcesz, aby wpis był filtrowany również w tym kontekście, musisz edytować ustawienia filtrowania.", "filter_modal.added.context_mismatch_title": "Niewłaściwy kontekst!", "filter_modal.added.expired_explanation": "Ta kategoria filtrowania wygasła, aby ją zastosować, należy zmienić datę wygaśnięcia.", @@ -362,6 +394,8 @@ "generic.saved": "Zapisano", "getting_started.heading": "Pierwsze kroki", "hashtag.admin_moderation": "Otwórz interfejs moderacji #{name}", + "hashtag.browse": "Przeglądaj posty z #{hashtag}", + "hashtag.browse_from_account": "Przeglądaj posty od @{name} z #{hashtag}", "hashtag.column_header.tag_mode.all": "i {additional}", "hashtag.column_header.tag_mode.any": "lub {additional}", "hashtag.column_header.tag_mode.none": "bez {additional}", @@ -374,7 +408,10 @@ "hashtag.counter_by_accounts": "{count, plural, one {{counter} osoba} few {{counter} osoby} many {{counter} osób} other {{counter} osób}}", "hashtag.counter_by_uses": "{count, plural, one {{counter} wpis} few {{counter} wpisy} many {{counter} wpisów} other {{counter} wpisów}}", "hashtag.counter_by_uses_today": "{count, plural, one {{counter} wpis} few {{counter} wpisy} many {{counter} wpisów} other {{counter} wpisów}} dzisiaj", + "hashtag.feature": "Wyróżnij w profilu", "hashtag.follow": "Obserwuj hasztag", + "hashtag.mute": "Wycisz #{hashtag}", + "hashtag.unfeature": "Nie wyróżniaj w profilu", "hashtag.unfollow": "Przestań obserwować hashtag", "hashtags.and_other": "…i {count, plural, other {jeszcze #}}", "hints.profiles.followers_may_be_missing": "Niektórzy obserwujący ten profil mogą być niewidoczni.", @@ -383,6 +420,7 @@ "hints.profiles.see_more_followers": "Zobacz więcej obserwujących na {domain}", "hints.profiles.see_more_follows": "Zobacz więcej obserwowanych na {domain}", "hints.profiles.see_more_posts": "Zobacz więcej wpisów na {domain}", + "home.column_settings.show_quotes": "Pokaż cytaty", "home.column_settings.show_reblogs": "Pokazuj podbicia", "home.column_settings.show_replies": "Pokazuj odpowiedzi", "home.hide_announcements": "Ukryj ogłoszenia", @@ -456,6 +494,8 @@ "keyboard_shortcuts.translate": "aby przetłumaczyć wpis", "keyboard_shortcuts.unfocus": "Opuść pole tekstowe", "keyboard_shortcuts.up": "Przesuń w górę na liście", + "learn_more_link.got_it": "Rozumiem", + "learn_more_link.learn_more": "Dowiedz się więcej", "lightbox.close": "Zamknij", "lightbox.next": "Następne", "lightbox.previous": "Poprzednie", @@ -505,8 +545,10 @@ "mute_modal.you_wont_see_mentions": "Nie zobaczysz wpisów wzmiankujących tę osobę.", "mute_modal.you_wont_see_posts": "Nie zobaczysz wpisów tej osoby, ale ona może widzieć twoje.", "navigation_bar.about": "O serwerze", + "navigation_bar.account_settings": "Hasło i zabezpieczenia", "navigation_bar.administration": "Administracja", "navigation_bar.advanced_interface": "Otwórz w widoku zaawansowanym", + "navigation_bar.automated_deletion": "Automatyczne usuwanie postów", "navigation_bar.blocks": "Zablokowani", "navigation_bar.bookmarks": "Zakładki", "navigation_bar.direct": "Wzmianki bezpośrednie", @@ -516,13 +558,21 @@ "navigation_bar.follow_requests": "Prośby o obserwowanie", "navigation_bar.followed_tags": "Obserwowane hasztagi", "navigation_bar.follows_and_followers": "Obserwowani i obserwujący", + "navigation_bar.import_export": "Import i eksport", "navigation_bar.lists": "Listy", "navigation_bar.logout": "Wyloguj", "navigation_bar.moderation": "Moderacja", + "navigation_bar.more": "Więcej", "navigation_bar.mutes": "Wyciszeni", "navigation_bar.opened_in_classic_interface": "Wpisy, konta i inne określone strony są domyślnie otwierane w widoku klasycznym.", "navigation_bar.preferences": "Ustawienia", + "navigation_bar.privacy_and_reach": "Prywatność i zasięg", "navigation_bar.search": "Szukaj", + "navigation_bar.search_trends": "Szukaj / Na czasie", + "navigation_panel.collapse_followed_tags": "Zwiń menu obserwowanych hashtagów", + "navigation_panel.collapse_lists": "Zwiń menu listy", + "navigation_panel.expand_followed_tags": "Rozwiń menu obserwowanych hashtagów", + "navigation_panel.expand_lists": "Rozwiń menu listy", "not_signed_in_indicator.not_signed_in": "Zaloguj się, aby uzyskać dostęp.", "notification.admin.report": "{name} zgłosił {target}", "notification.admin.report_account": "{name} zgłosił(a) {count, plural, one {1 wpis} few {# wpisy} other {# wpisów}} z {target} w kategorii {category}", @@ -749,6 +799,7 @@ "report_notification.categories.violation": "Naruszenie zasad", "report_notification.categories.violation_sentence": "naruszenie zasad", "report_notification.open": "Otwórz zgłoszenie", + "search.clear": "Wyczyść wyszukiwanie", "search.no_recent_searches": "Brak ostatnich wyszukiwań", "search.placeholder": "Szukaj", "search.quick_action.account_search": "Profile pasujące do {x}", @@ -790,6 +841,8 @@ "status.bookmark": "Dodaj zakładkę", "status.cancel_reblog_private": "Cofnij podbicie", "status.cannot_reblog": "Ten wpis nie może zostać podbity", + "status.context.load_new_replies": "Dostępne są nowe odpowiedzi", + "status.context.loading": "Sprawdzanie kolejnych odpowiedzi", "status.continued_thread": "Ciąg dalszy wątku", "status.copy": "Skopiuj odnośnik do wpisu", "status.delete": "Usuń", @@ -815,6 +868,10 @@ "status.mute_conversation": "Wycisz konwersację", "status.open": "Rozszerz ten wpis", "status.pin": "Przypnij do profilu", + "status.quote_error.filtered": "Ukryte z powodu jednego z Twoich filtrów", + "status.quote_error.not_available": "Post niedostępny", + "status.quote_error.pending_approval": "Post oczekujący", + "status.quote_post_author": "Zacytowano post @{name}", "status.read_more": "Czytaj dalej", "status.reblog": "Podbij", "status.reblog_private": "Podbij dla odbiorców oryginalnego wpisu", @@ -844,8 +901,13 @@ "subscribed_languages.save": "Zapisz zmiany", "subscribed_languages.target": "Zmień subskrybowane języki dla {target}", "tabs_bar.home": "Strona główna", + "tabs_bar.menu": "Menu", "tabs_bar.notifications": "Powiadomienia", + "tabs_bar.publish": "Nowy post", + "tabs_bar.search": "Szukaj", + "terms_of_service.effective_as_of": "Obowiązuje od {date}", "terms_of_service.title": "Warunki korzystania z usługi", + "terms_of_service.upcoming_changes_on": "Nadchodzące zmiany od {date}", "time_remaining.days": "{number, plural, one {Pozostał # dzień} few {Pozostały # dni} many {Pozostało # dni} other {Pozostało # dni}}", "time_remaining.hours": "{number, plural, one {Pozostała # godzina} few {Pozostały # godziny} many {Pozostało # godzin} other {Pozostało # godzin}}", "time_remaining.minutes": "{number, plural, one {Pozostała # minuta} few {Pozostały # minuty} many {Pozostało # minut} other {Pozostało # minut}}", @@ -876,6 +938,12 @@ "video.expand": "Rozszerz film", "video.fullscreen": "Pełny ekran", "video.hide": "Ukryj film", + "video.mute": "Wycisz", "video.pause": "Pauzuj", - "video.play": "Odtwórz" + "video.play": "Odtwórz", + "video.skip_backward": "Skocz do tyłu", + "video.skip_forward": "Skocz do przodu", + "video.unmute": "Wyłącz wyciszenie", + "video.volume_down": "Zmniejsz głośność", + "video.volume_up": "Zwiększ głośność" } diff --git a/app/javascript/mastodon/locales/tr.json b/app/javascript/mastodon/locales/tr.json index fb2a9237bcb..a7fa70a28a5 100644 --- a/app/javascript/mastodon/locales/tr.json +++ b/app/javascript/mastodon/locales/tr.json @@ -498,6 +498,8 @@ "keyboard_shortcuts.translate": "bir gönderiyi çevirmek için", "keyboard_shortcuts.unfocus": "Aramada bir gönderiye odaklanmamak için", "keyboard_shortcuts.up": "Listede yukarıya çıkmak için", + "learn_more_link.got_it": "Anladım", + "learn_more_link.learn_more": "Daha fazla bilgi edin", "lightbox.close": "Kapat", "lightbox.next": "Sonraki", "lightbox.previous": "Önceki", @@ -873,6 +875,11 @@ "status.open": "Bu gönderiyi genişlet", "status.pin": "Profile sabitle", "status.quote_error.filtered": "Bazı filtrelerinizden dolayı gizlenmiştir", + "status.quote_error.not_available": "Gönderi kullanılamıyor", + "status.quote_error.pending_approval": "Gönderi beklemede", + "status.quote_error.pending_approval_popout.body": "Fediverse genelinde paylaşılan alıntıların görüntülenmesi zaman alabilir, çünkü farklı sunucuların farklı protokolleri vardır.", + "status.quote_error.pending_approval_popout.title": "Bekleyen bir teklif mi var? Sakin olun.", + "status.quote_post_author": "@{name} adlı kullanıcının bir gönderisini alıntıladı", "status.read_more": "Devamını okuyun", "status.reblog": "Yeniden paylaş", "status.reblog_private": "Özgün görünürlük ile yeniden paylaş", diff --git a/config/locales/activerecord.pl.yml b/config/locales/activerecord.pl.yml index 62edc03c0ea..29cace6db53 100644 --- a/config/locales/activerecord.pl.yml +++ b/config/locales/activerecord.pl.yml @@ -49,8 +49,14 @@ pl: attributes: reblog: taken: status już istnieje + terms_of_service: + attributes: + effective_date: + too_soon: jest zbyt wcześnie, musi być później niż %{date} user: attributes: + date_of_birth: + below_limit: jest poniżej granicy wiekowej email: blocked: używa niedozwolonego dostawcy poczty elektronicznej unreachable: wydaje się nie istnieć diff --git a/config/locales/da.yml b/config/locales/da.yml index 67e5a716227..1b56425ee2b 100644 --- a/config/locales/da.yml +++ b/config/locales/da.yml @@ -1905,7 +1905,7 @@ da: ownership: Andres indlæg kan ikke fastgøres reblog: En fremhævelse kan ikke fastgøres quote_policies: - followers: Kun dine følgere + followers: Kun egne følgere nobody: Ingen public: Alle title: '%{name}: "%{quote}"' diff --git a/config/locales/el.yml b/config/locales/el.yml index 73e46ee13c0..2ad8bc6899c 100644 --- a/config/locales/el.yml +++ b/config/locales/el.yml @@ -1905,6 +1905,8 @@ el: ownership: Δεν μπορείς να καρφιτσώσεις ανάρτηση κάποιου άλλου reblog: Οι ενισχύσεις δεν καρφιτσώνονται quote_policies: + followers: Μόνο οι ακόλουθοί σου + nobody: Κανένας public: Όλοι title: '%{name}: "%{quote}"' visibilities: diff --git a/config/locales/et.yml b/config/locales/et.yml index e9935cc72b5..7d96b4c57ed 100644 --- a/config/locales/et.yml +++ b/config/locales/et.yml @@ -325,6 +325,8 @@ et: create: Loo teadaanne title: Uus teadaanne preview: + disclaimer: Kuna kasutajd ei saa neist postiitustest keelduda, siis peaksid teavituskirjad keskenduma vaid olulistele teemadele nagi võimalik isiklike andmete leke või serveri tegevuse lõpetamine. + explanation_html: 'See e-kiri saadetakse %{display_count}-le kasutajale. E-kirjas sisaldub järgnev tekst:' title: Info teavituse üle vaatamine publish: Postita published_msg: Teadaande avaldamine õnnestus! @@ -992,6 +994,7 @@ et: explanation_html: Esitatud teenusetingimuste näidis on mõeldud ainult teavitamise eesmärgil ja seda ei tohiks tõlgendada kui juriidilist nõuannet mis tahes küsimuses. Palun konsulteeri olukorra ja konkreetsete juriidiliste küsimuste osas oma õigusnõustajaga. title: Teenuse tingimuste seadistamine history: Ajalugu + notified_on_html: 'Kasutajad on teavitatud: %{date}' notify_users: Teata kasutajatele preview: explanation_html: 'See e-kiri saadetakse %{display_count}-le kasutajale, kes olid liitunud enne %{date}. E-kirjas sisaldub järgnev tekst:' diff --git a/config/locales/fo.yml b/config/locales/fo.yml index 2dd500d694d..edac267254c 100644 --- a/config/locales/fo.yml +++ b/config/locales/fo.yml @@ -1905,6 +1905,8 @@ fo: ownership: Postar hjá øðrum kunnu ikki festast reblog: Ein stimbran kann ikki festast quote_policies: + followers: Einans tey, ið fylgja tær + nobody: Eingin public: Øll title: '%{name}: "%{quote}"' visibilities: diff --git a/config/locales/nan.yml b/config/locales/nan.yml index f6c4f0dc383..a6203584284 100644 --- a/config/locales/nan.yml +++ b/config/locales/nan.yml @@ -255,6 +255,7 @@ nan: create_relay_html: "%{name} 建立中繼 %{target}" create_unavailable_domain_html: "%{name} 停止送kàu域名 %{target}" create_user_role_html: "%{name} 建立 %{target} 角色" + create_username_block_html: "%{name} 加添用者ê名包含 %{target} ê規則ah" demote_user_html: "%{name} kā用者 %{target} 降級" destroy_announcement_html: "%{name} kā公告 %{target} thâi掉ah" destroy_canonical_email_block_html: "%{name} kā hash是 %{target} ê電子phue取消封鎖ah" @@ -268,6 +269,7 @@ nan: destroy_status_html: "%{name} kā %{target} ê PO文thâi掉" destroy_unavailable_domain_html: "%{name} 恢復送kàu域名 %{target}" destroy_user_role_html: "%{name} thâi掉 %{target} 角色" + destroy_username_block_html: "%{name} thâi掉用者ê名包含 %{target} ê規則ah" disable_2fa_user_html: "%{name} 停止使用者 %{target} 用雙因素驗證" disable_custom_emoji_html: "%{name} kā 新ê emoji %{target} 停止使用ah" disable_relay_html: "%{name} 停止使用中繼 %{target}" @@ -302,6 +304,7 @@ nan: update_report_html: "%{name} 更新 %{target} ê檢舉" update_status_html: "%{name} kā %{target} ê PO文更新" update_user_role_html: "%{name} 更改 %{target} 角色" + update_username_block_html: "%{name} 更新用者ê名包含 %{target} ê規則ah" deleted_account: thâi掉ê口座 empty: Tshuē無log。 filter_by_action: 照動作過濾 @@ -639,6 +642,57 @@ nan: other: "%{count} 篇筆記" action_log: 審查日誌 action_taken_by: 操作由 + actions: + delete_description_html: 受檢舉ê PO文ē thâi掉,而且ē用tsi̍t ue̍h橫tsuā記錄,幫tsān lí提升kâng tsi̍t ê用戶未來ê違規。 + mark_as_sensitive_description_html: 受檢舉ê PO文內ê媒體ē標做敏感,而且ē用tsi̍t ue̍h橫tsuā記錄,幫tsān lí提升kâng tsi̍t ê用戶未來ê違規。 + other_description_html: 看其他控制tsit ê口座ê所行,kap自訂聯絡受檢舉ê口座ê選項。 + resolve_description_html: Buē用行動控制受檢舉ê口座,mā無用橫tsuā記錄,而且tsit ê報告ē關掉。 + silence_description_html: 本口座kan-ta ē hōo早前跟tuè ê á是手動tshiau ê看見,大大限制看見ê範圍。設定隨時ē當回復。請關所有tuì tsit ê口座ê檢舉。 + suspend_description_html: Tsit ê口座kap伊ê內容ē bē當用,落尾ē thâi掉,mā bē當hām伊互動。30 kang以內通回復。請關所有tuì tsit ê口座ê檢舉。 + actions_description_html: 決定行siánn物行動來解決tsit ê檢舉。Nā lí tuì受檢舉ê口座採用處罰,電子phue通知ē送予in,除非選擇 Pùn-sò phue 類別。 + actions_description_remote_html: 決定行siánn物行動來解決tsit ê檢舉。Tse kan-ta ē影響 lí ê 服侍器hām tsit ê遠距離服侍器聯絡kap處理伊ê內容ê方法。 + actions_no_posts: Tsit份檢舉無beh thâi掉ê相關PO文 + add_to_report: 加添其他ê內容kàu檢舉 + already_suspended_badges: + local: 已經佇tsit ê服侍器停止權限ah + remote: 已經佇in ê服侍器停止權限ah + are_you_sure: Lí kám確定? + assign_to_self: 分配hōo家kī + assigned: 分配管理者 + by_target_domain: 受檢舉ê口座ê網域 + cancel: 取消 + category: 類別 + category_description_html: Tsit ê 受檢舉ê口座kap/á是內容,ē佇kap tsit ê口座ê聯絡內底引用。 + comment: + none: 無 + comment_description_html: 為著提供其他資訊,%{name} 寫: + confirm: 確認 + confirm_action: 確認kā %{acct} 審核ê動作 + created_at: 檢舉tī + delete_and_resolve: Thâi掉PO文 + forwarded: 轉送ah + forwarded_replies_explanation: 本報告是tuì別站ê用者送ê,關係別站ê內容。本報告轉hōo lí,因為受檢舉ê內容是回應lí ê服侍器ê用者。 + forwarded_to: 有轉送kàu %{domain} + mark_as_resolved: 標做「解決ah」 + mark_as_sensitive: 標做敏感 + mark_as_unresolved: 標做「無解決」 + no_one_assigned: 無lâng + notes: + create: 加添筆記 + create_and_resolve: 標「處理ah」,留筆記 + create_and_unresolve: 留筆記,koh重開 + delete: Thâi掉 + placeholder: 描述有行siánn物行動,á是其他關聯ê更新…… + title: 筆記 + notes_description_html: 檢視á是留筆記hōo別ê管理者kap未來ê家己 + processed_msg: '檢舉 #%{id} 處理成功ah' + quick_actions_description_html: 緊行行動,á是giú kàu下kha,看檢舉ê內容: + remote_user_placeholder: tuì %{instance} 來ê遠距離用者 + reopen: 重頭phah開檢舉 + report: '檢舉 #%{id}' + roles: + privileges: + manage_announcements: 管理公告 statuses: language: 語言 trends: diff --git a/config/locales/pl.yml b/config/locales/pl.yml index 36897280f5d..29de53637cd 100644 --- a/config/locales/pl.yml +++ b/config/locales/pl.yml @@ -196,6 +196,7 @@ pl: create_relay: Utwórz przekaźnik create_unavailable_domain: Utwórz niedostępną domenę create_user_role: Utwórz rolę + create_username_block: Utwórz zasadę nazwy użytkownika demote_user: Zdegraduj użytkownika destroy_announcement: Usuń ogłoszenie destroy_canonical_email_block: Usuń blokadę e-mail @@ -209,6 +210,7 @@ pl: destroy_status: Usuń wpis destroy_unavailable_domain: Usuń niedostępną domenę destroy_user_role: Zlikwiduj rolę + destroy_username_block: Usuń zasadę nazwy użytkownika disable_2fa_user: Wyłącz 2FA disable_custom_emoji: Wyłącz niestandardowe emoji disable_relay: Wyłącz przekaźnik @@ -243,6 +245,7 @@ pl: update_report: Wiadomości or raporcie update_status: Aktualizuj wpis update_user_role: Aktualizuj rolę + update_username_block: Zaktualizuj zasadę nazwy użytkownika actions: approve_appeal_html: "%{name} zatwierdził(-a) odwołanie decyzji moderacyjnej od %{target}" approve_user_html: "%{name} zatwierdził rejestrację od %{target}" @@ -261,6 +264,7 @@ pl: create_relay_html: "%{name} utworzył przekaźnik %{target}" create_unavailable_domain_html: "%{name} przestał(a) doręczać na domenę %{target}" create_user_role_html: "%{name} utworzył rolę %{target}" + create_username_block_html: Użytkownik %{name} dodał zasadę dla nazw użytkowników zawierających %{target} demote_user_html: "%{name} zdegradował(a) użytkownika %{target}" destroy_announcement_html: "%{name} usunął(-ęła) ogłoszenie %{target}" destroy_canonical_email_block_html: "%{name} odblokował(a) e-mail z hashem %{target}" @@ -274,6 +278,7 @@ pl: destroy_status_html: "%{name} usunął(-ęła) wpis użytkownika %{target}" destroy_unavailable_domain_html: "%{name} wznowił(a) doręczanie do domeny %{target}" destroy_user_role_html: "%{name} usunął rolę %{target}" + destroy_username_block_html: Użytkownik %{name} usunął zasadę dla nazw użytkowników zawierających %{target} disable_2fa_user_html: "%{name} wyłączył(a) uwierzytelnianie dwuskładnikowe użytkownikowi %{target}" disable_custom_emoji_html: "%{name} wyłączył(a) emoji %{target}" disable_relay_html: "%{name} wyłączył przekaźnik %{target}" @@ -308,6 +313,7 @@ pl: update_report_html: "%{target} zaktualizowany przez %{name}" update_status_html: "%{name} zaktualizował(a) wpis użytkownika %{target}" update_user_role_html: "%{name} zmienił rolę %{target}" + update_username_block_html: Użytkownik %{name} zaktualizował zasadę dla nazw użytkowników zawierających %{target} deleted_account: usunięte konto empty: Nie znaleziono aktywności w dzienniku. filter_by_action: Filtruj według działania @@ -315,6 +321,7 @@ pl: title: Dziennik działań administracyjnych unavailable_instance: "(domena niedostępna)" announcements: + back: Powrót do ogłoszeń destroyed_msg: Pomyślnie usunięto ogłoszenie! edit: title: Edytuj ogłoszenie @@ -323,6 +330,9 @@ pl: new: create: Utwórz ogłoszenie title: Nowe ogłoszenie + preview: + explanation_html: 'Wiadomość e-mail zostanie wysłana do %{display_count} użytkowników. Otrzymają oni wiadomość o następującej treści:' + title: Podgląd powiadomienia publish: Opublikuj published_msg: Pomyślnie opublikowano ogłoszenie! scheduled_for: Zaplanowano na %{time} @@ -491,6 +501,29 @@ pl: new: title: Importuj zablokowane domeny no_file: Nie wybrano pliku + fasp: + debug: + callbacks: + created_at: 'Utworzono:' + delete: Usuń + ip: Adres IP + providers: + active: Aktywne + base_url: Podstawowy adres URL + delete: Usuń + edit: Edytuj dostawców + finish_registration: Zakończ rejestrację + name: Nazwa + providers: Dostawca + registration_requested: Wymagana rejestracja + registrations: + confirm: Zatwierdź + reject: Odrzuć + save: Zapisz + sign_in: Zaloguj się + status: Status + title: Dostawcy usług pomocniczych Fediverse (Fediverse Auxiliary Service Providers) + title: FASP follow_recommendations: description_html: "Polecane obserwacje pomagają nowym użytkownikom szybko odnaleźć interesujące treści. Jeżeli użytkownik nie wchodził w interakcje z innymi wystarczająco często, aby powstały spersonalizowane rekomendacje, polecane są te konta. Są one obliczane każdego dnia na podstawie kombinacji kont o największej liczbie niedawnej aktywności i największej liczbie lokalnych obserwatorów dla danego języka." language: Dla języka @@ -565,6 +598,8 @@ pl: all: Wszystkie limited: Ograniczone title: Moderacja + moderation_notes: + title: Notatki moderacyjne private_comment: Prywatny komentarz public_comment: Publiczny komentarz purge: Wyczyść @@ -779,11 +814,16 @@ pl: title: Role rules: add_new: Dodaj zasadę + add_translation: Dodaj tłumaczenie delete: Usuń description_html: Chociaż większość twierdzi, że przeczytała i zgadza się z warunkami korzystania z usługi, zwykle ludzie nie czytają ich, dopóki nie pojawi się problem. Ułatw użytkownikom szybkie przejrzenie zasad serwera, umieszczając je na prostej liście punktowanej. Postaraj się, aby poszczególne zasady były krótkie i proste, ale staraj się też nie dzielić ich na wiele oddzielnych elementów. edit: Edytuj zasadę empty: Jeszcze nie zdefiniowano zasad serwera. + move_down: Przenieś w dół + move_up: Przenieś w górę title: Regulamin serwera + translation: Tłumaczenie + translations: Tłumaczenia settings: about: manage_rules: Zarządzaj regułami serwera @@ -809,6 +849,7 @@ pl: discovery: follow_recommendations: Polecane konta preamble: Prezentowanie interesujących treści ma kluczowe znaczenie dla nowych użytkowników, którzy mogą nie znać nikogo z Mastodona. Kontroluj, jak różne funkcje odkrywania działają na Twoim serwerze. + privacy: Prywatność profile_directory: Katalog profilów public_timelines: Publiczne osie czasu publish_statistics: Publikuj statystyki @@ -1066,6 +1107,22 @@ pl: other: Użyte przez %{count} osób w ciągu ostatniego tygodnia title: Rekomendacje i Trendy trending: Popularne + username_blocks: + add_new: Dodaj nową + comparison: + contains: Zawiera + equals: Równa się + contains_html: Zawiera %{string} + delete: Usuń + edit: + title: Edytuj zasadę nazwy użytkownika + matches_exactly_html: Równa się %{string} + new: + create: Dodaj zasadę + title: Utwórz zasadę nazwy użytkownika + not_permitted: Brak uprawnień + title: Zasady nazwy użytkownika + updated_msg: Pomyślnie zaktualizowano zasadę nazwy użytkownika warning_presets: add_new: Dodaj nowy delete: Usuń @@ -1332,6 +1389,10 @@ pl: basic_information: Podstawowe informacje hint_html: "Dostosuj to, co ludzie widzą na Twoim profilu publicznym i obok Twoich wpisów. Inne osoby są bardziej skłonne obserwować Cię i wchodzić z Tobą w interakcje, gdy masz wypełniony profil i zdjęcie profilowe." other: Inne + emoji_styles: + auto: Automatycznie + native: Natywny + twemoji: Twemoji errors: '400': Wysłane zgłoszenie jest nieprawidłowe lub uszkodzone. '403': Nie masz uprawnień, aby wyświetlić tę stronę. @@ -1899,12 +1960,17 @@ pl: edited_at_html: Edytowane %{date} errors: in_reply_not_found: Post, na który próbujesz odpowiedzieć, nie istnieje. + quoted_status_not_found: Wpis, który próbujesz zacytować, nie istnieje. over_character_limit: limit %{max} znaków przekroczony pin_errors: direct: Nie możesz przypiąć wpisu, który jest widoczny tylko dla wspomnianych użytkowników limit: Przekroczyłeś maksymalną liczbę przypiętych wpisów ownership: Nie możesz przypiąć cudzego wpisu reblog: Nie możesz przypiąć podbicia wpisu + quote_policies: + followers: Tylko obserwujący + nobody: Nikt + public: Wszyscy title: '%{name}: "%{quote}"' visibilities: direct: Bezpośredni diff --git a/config/locales/ru.yml b/config/locales/ru.yml index c825cac33dd..17ba89bef09 100644 --- a/config/locales/ru.yml +++ b/config/locales/ru.yml @@ -1682,37 +1682,37 @@ ru: notification_mailer: admin: report: - subject: "%{name} отправил жалобу" + subject: Поступила жалоба от %{name} sign_up: - subject: "%{name} зарегистрирован" + subject: "%{name} зарегистрировался (-лась) на сервере" favourite: body: "%{name} добавил(а) ваш пост в избранное:" subject: "%{name} добавил(а) ваш пост в избранное" - title: Понравившийся статус + title: Ваш пост добавили в избранное follow: body: "%{name} теперь подписан(а) на вас!" subject: "%{name} теперь подписан(а) на вас" title: Новый подписчик follow_request: - action: Управление запросами на подписку + action: Перейти к запросам на подписку body: "%{name} отправил(а) вам запрос на подписку" subject: "%{name} хочет подписаться на вас" title: Новый запрос на подписку mention: action: Ответить - body: 'Вас упомянул(а) %{name} в:' + body: "%{name} упомянул(а) вас:" subject: "%{name} упомянул(а) вас" title: Новое упоминание poll: subject: Опрос %{name} завершился reblog: - body: 'Ваш пост был продвинут %{name}:' + body: "%{name} продвинул(а) ваш пост:" subject: "%{name} продвинул(а) ваш пост" - title: Новое продвижение + title: Ваш пост продвинули status: - subject: "%{name} только что запостил(а)" + subject: "%{name} опубликовал(а) новый пост" update: - subject: "%{name} изменил(а) пост" + subject: "%{name} отредактировал(а) пост" notifications: email_events: События для уведомлений по электронной почте email_events_hint: 'Выберите события, для которых вы хотели бы получать уведомления:' @@ -1891,17 +1891,17 @@ ru: user_domain_block: Вы заблокировали %{target_name} lost_followers: Потерянные подписчики lost_follows: Потерянные подписки - preamble: Вы можете потерять подписчиков и последователей, если заблокируете домен или, если ваши модераторы решат приостановить работу удаленного сервера. Когда это произойдет, вы сможете загрузить списки разорванных отношений, чтобы проверить их и, возможно, импортировать на другой сервер. + preamble: Когда вы блокируете сервер или это делают модераторы вашего сервера, вы теряете подписчиков и перестаёте быть подписаны на пользователей с заблокированного сервера. После блокировки вы сможете скачать списки пользователей, отношения с которыми были разорваны, чтобы рассмотреть их или чтобы импортировать их на другом сервере. purged: Информация об этом сервере была удалена администраторами вашего сервера. type: Событие statuses: attached: audio: - few: "%{count} аудиозаписи" - many: "%{count} аудиозаписей" - one: "%{count} аудиозапись" - other: "%{count} аудиозаписи" - description: 'Вложение: %{attached}' + few: "%{count} аудиофайла" + many: "%{count} аудиофайлов" + one: "%{count} аудиофайл" + other: "%{count} аудиофайлов" + description: Прикреплено %{attached} image: few: "%{count} изображения" many: "%{count} изображений" @@ -1913,14 +1913,14 @@ ru: one: "%{count} видео" other: "%{count} видео" boosted_from_html: Продвижение польз. %{acct_link} - content_warning: 'Спойлер: %{warning}' + content_warning: 'Предупреждение о содержании: %{warning}' default_language: Тот же, что язык интерфейса disallowed_hashtags: few: 'содержались запрещённые хэштеги: %{tags}' many: 'содержались запрещённые хэштеги: %{tags}' one: 'содержался запрещённый хэштег: %{tags}' other: 'содержались запрещённые хэштеги: %{tags}' - edited_at_html: Редактировано %{date} + edited_at_html: 'Дата последнего изменения: %{date}' errors: in_reply_not_found: Пост, на который вы пытаетесь ответить, не существует или удалён. over_character_limit: превышен лимит символов (%{max}) diff --git a/config/locales/simple_form.da.yml b/config/locales/simple_form.da.yml index 98412270e98..c5a436c2e2f 100644 --- a/config/locales/simple_form.da.yml +++ b/config/locales/simple_form.da.yml @@ -56,7 +56,7 @@ da: scopes: De API'er, som applikationen vil kunne tilgå. Vælges en topniveaudstrækning, vil detailvalg være unødvendige. setting_aggregate_reblogs: Vis ikke nye fremhævelser for nyligt fremhævede indlæg (påvirker kun nyligt modtagne fremhævelser) setting_always_send_emails: Normalt sendes ingen e-mailnotifikationer under aktivt brug af Mastodon - setting_default_quote_policy: Denne indstilling træder kun i kraft for indlæg, der oprettes med den næste Mastodon-version, men du kan vælge din præference som forberedelse. + setting_default_quote_policy: Denne indstilling træder kun i kraft for indlæg oprettet med den næste Mastodon-version, men egne præference kan vælges som forberedelse. setting_default_sensitive: Sensitive medier er som standard skjult og kan vises med et klik setting_display_media_default: Skjul medier med sensitiv-markering setting_display_media_hide_all: Skjul altid medier diff --git a/config/locales/simple_form.el.yml b/config/locales/simple_form.el.yml index 717ed59b1da..b3c3c2c6d95 100644 --- a/config/locales/simple_form.el.yml +++ b/config/locales/simple_form.el.yml @@ -56,6 +56,7 @@ el: scopes: Ποια API θα επιτρέπεται στην εφαρμογή να χρησιμοποιήσεις. Αν επιλέξεις κάποιο υψηλό εύρος εφαρμογής, δε χρειάζεται να επιλέξεις και το καθένα ξεχωριστά. setting_aggregate_reblogs: Απόκρυψη των νέων αναρτήσεων για τις αναρτήσεις που έχουν ενισχυθεί πρόσφατα (επηρεάζει μόνο τις νέες ενισχύσεις) setting_always_send_emails: Κανονικά οι ειδοποιήσεις μέσω ηλεκτρονικού ταχυδρομείου δεν θα αποστέλλονται όταν χρησιμοποιείτε ενεργά το Mastodon + setting_default_quote_policy: Αυτή η ρύθμιση θα τεθεί σε ισχύ μόνο για αναρτήσεις που δημιουργήθηκαν με την επόμενη έκδοση του Mastodon, αλλά μπορείτε να επιλέξετε την προτίμησή σας κατά την προετοιμασία. setting_default_sensitive: Τα ευαίσθητα πολυμέσα είναι κρυμμένα και εμφανίζονται με ένα κλικ setting_display_media_default: Απόκρυψη ευαίσθητων πολυμέσων setting_display_media_hide_all: Μόνιμη απόκρυψη όλων των πολυμέσων diff --git a/config/locales/simple_form.fo.yml b/config/locales/simple_form.fo.yml index b9176cb6399..f620d54280a 100644 --- a/config/locales/simple_form.fo.yml +++ b/config/locales/simple_form.fo.yml @@ -56,6 +56,7 @@ fo: scopes: Hvørji API nýtsluskipanin fær atgongd til. Velur tú eitt vav á hægsta stigi, so er ikki neyðugt at velja tey einstøku. setting_aggregate_reblogs: Vís ikki nýggjar stimbranir fyri postar, sum nýliga eru stimbraðir (ávirkar einans stimbranir, ið eru móttiknar fyri kortum) setting_always_send_emails: Vanliga vera teldupostfráboðanir ikki sendar, tá tú virkin brúkar Mastodon + setting_default_quote_policy: Hendan stillingin verður bara virkin fyri postar, sum verða stovnaðir í næstu Mastodon útgávuni, men sum fyrireiking til tað, kanst tú velja tína stilling longu nú. setting_default_sensitive: Viðkvæmar miðlafílur eru fjaldar og kunnu avdúkast við einum klikki setting_display_media_default: Fjal miðlafílur, sum eru merktar sum viðkvæmar setting_display_media_hide_all: Fjal altíð miðlafílur diff --git a/config/locales/simple_form.pl.yml b/config/locales/simple_form.pl.yml index c049822b817..6faef6aa9ca 100644 --- a/config/locales/simple_form.pl.yml +++ b/config/locales/simple_form.pl.yml @@ -221,6 +221,7 @@ pl: setting_boost_modal: Pytaj o potwierdzenie przed podbiciem setting_default_language: Język wpisów setting_default_privacy: Widoczność wpisów + setting_default_quote_policy: Kto może cytować setting_default_sensitive: Zawsze oznaczaj zawartość multimedialną jako wrażliwą setting_delete_modal: Pytaj o potwierdzenie przed usunięciem wpisu setting_disable_hover_cards: Wyłącz podgląd profilu po najechaniu @@ -229,6 +230,7 @@ pl: setting_display_media_default: Domyślne setting_display_media_hide_all: Ukryj wszystko setting_display_media_show_all: Pokaż wszystko + setting_emoji_style: Styl emoji setting_expand_spoilers: Zawsze rozwijaj wpisy oznaczone ostrzeżeniem o zawartości setting_hide_network: Ukryj swoją sieć setting_missing_alt_text_modal: Pokaż okno potwierdzenia przed opublikowaniem materiałów bez pomocniczego opisu obrazów @@ -266,6 +268,7 @@ pl: favicon: Favicon mascot: Własna ikona media_cache_retention_period: Okres przechowywania pamięci podręcznej + min_age: Wymagany minimalny wiek peers_api_enabled: Opublikuj listę odkrytych serwerów w API profile_directory: Włącz katalog profilów registrations_mode: Kto może się zarejestrować @@ -331,6 +334,7 @@ pl: usable: Pozwól na umieszczanie tego hashtagu w lokalnych wpisach terms_of_service: changelog: Co się zmieniło? + effective_date: Data wejścia w życie text: Warunki korzystania z usługi terms_of_service_generator: admin_email: Adres e-mail przeznaczony do celów prawnych @@ -341,7 +345,11 @@ pl: dmca_email: Adres e-mail dla zgłoszeń naruszenia DMCA/praw autorskich domain: Domena jurisdiction: Jurysdykcja + min_age: Wiek minimalny user: + date_of_birth_1i: Dzień + date_of_birth_2i: Miesiąc + date_of_birth_3i: Rok role: Rola time_zone: Strefa czasowa user_role: @@ -350,6 +358,10 @@ pl: name: Nazwa permissions_as_keys: Uprawnienia position: Priorytet + username_block: + allow_with_approval: Zezwól na rejestracje po zatwierdzeniu + comparison: Metoda porównania + username: Słowo do dopasowania webhook: events: Włączone zdarzenia template: Szablon zawartości diff --git a/config/locales/simple_form.tr.yml b/config/locales/simple_form.tr.yml index e359b657d67..2dffa398050 100644 --- a/config/locales/simple_form.tr.yml +++ b/config/locales/simple_form.tr.yml @@ -56,6 +56,7 @@ tr: scopes: Uygulamanın erişmesine izin verilen API'ler. Üst seviye bir kapsam seçtiyseniz, bireysel kapsam seçmenize gerek yoktur. setting_aggregate_reblogs: Yakın zamanda teşvik edilmiş gönderiler için yeni teşvikleri göstermeyin (yalnızca yeni alınan teşvikleri etkiler) setting_always_send_emails: Normalde, Mastodon'u aktif olarak kullanırken e-posta bildirimleri gönderilmeyecektir + setting_default_quote_policy: Bu ayar yalnızca bir sonraki Mastodon sürümüyle oluşturulan gönderiler için geçerli olacak, ancak hazırlık aşamasında tercihinizi seçebilirsiniz. setting_default_sensitive: Hassas medya varsayılan olarak gizlidir ve bir tıklama ile gösterilebilir setting_display_media_default: Hassas olarak işaretlenmiş medyayı gizle setting_display_media_hide_all: Medyayı her zaman gizle @@ -159,6 +160,10 @@ tr: name: Rolün, eğer rozet olarak görüntülenmesi ayarlandıysa kullanılacak herkese açık ismi permissions_as_keys: Bu role sahip kullanıcıların şunlara erişimi var... position: Belirli durumlarda çatışmayı çözmek için daha yüksek rol belirleyicidir. Bazı eylemler ancak daha düşük öncelikteki rollere uygulanabilir + username_block: + allow_with_approval: Kayıt işlemini tamamen engellemek yerine, eşleşen kayıtlar onayınızı gerektirecektir + comparison: Kısmi eşleşmeleri engellerken lütfen Scunthorpe Problemini aklınızda bulundurun + username: '"a" için "4" veya "e" için "3" gibi büyük/küçük harfe ve yaygın homogliflere bakılmaksızın eşleştirilecektir' webhook: events: Gönderilecek etkinlikleri seçin template: Değişken değerleme kullanarak kendi JSON yükünüzü oluşturun. Varsayılan JSON için boş bırakın. @@ -370,6 +375,10 @@ tr: name: Ad permissions_as_keys: İzinler position: Öncelik + username_block: + allow_with_approval: Onay ile kayıtlara izin ver + comparison: Karşılaştırma yöntemi + username: Eşleşecek kelime webhook: events: Etkin olaylar template: Yük şablonu diff --git a/config/locales/tr.yml b/config/locales/tr.yml index f697e3b199e..595e4bfcbf3 100644 --- a/config/locales/tr.yml +++ b/config/locales/tr.yml @@ -1,7 +1,7 @@ --- tr: about: - about_mastodon_html: Jetub Maxücretsiz ve açık kaynaklı bir sosyal ağdır. Merkezi olmayan yapısı sayesinde diğer ticari sosyal platformların aksine iletişimininizin tek bir firmada tutulmasının/yönetilmesinin önüne geçer. Güvendiğiniz bir sunucuyu seçerek oradaki kişilerle etkileşimde bulunabilirsiniz. Herkes kendi Jetub Max sunucusunu kurabilir ve sorunsuz bir şekilde Jetub Maxsosyal ağına dahil edebilir! + about_mastodon_html: 'Geleceğin sosyal ağı: Reklam yok, kurumsal gözetim yok, etik tasarım ve merkeziyetsizlik! Mastodon ile verilerinizin sahibi olun!' contact_missing: Ayarlanmadı contact_unavailable: Bulunamadı hosted_on: Mastodon %{domain} üzerinde barındırılıyor @@ -190,6 +190,7 @@ tr: create_relay: Aktarıcı Oluştur create_unavailable_domain: Mevcut Olmayan Alan Adı Oluştur create_user_role: Rol Oluştur + create_username_block: Kullanıcı Adı Kuralı Oluştur demote_user: Kullanıcıyı Düşür destroy_announcement: Duyuru Sil destroy_canonical_email_block: E-Posta Engelini Sil @@ -203,6 +204,7 @@ tr: destroy_status: Durumu Sil destroy_unavailable_domain: Mevcut Olmayan Alan Adı Sil destroy_user_role: Rolü Kaldır + destroy_username_block: Kullanıcı Adı Kuralını Sil disable_2fa_user: 2AD Kapat disable_custom_emoji: Özel İfadeyi Devre Dışı Bırak disable_relay: Aktarıcıyı Devre Dışı Bırak @@ -237,6 +239,7 @@ tr: update_report: Raporu Güncelle update_status: Durumu Güncelle update_user_role: Rolü Güncelle + update_username_block: Kullanıcı Adı Kuralını Güncelle actions: approve_appeal_html: "%{name}, %{target} kullanıcısının yönetim kararına itirazını kabul etti" approve_user_html: "%{name}, %{target} konumundan kaydı onayladı" @@ -255,6 +258,7 @@ tr: create_relay_html: "%{name}, %{target} aktarıcısını oluşturdu" create_unavailable_domain_html: "%{name}, %{target} alan adına teslimatı durdurdu" create_user_role_html: "%{name}, %{target} rolünü oluşturdu" + create_username_block_html: "%{name}, %{target} içeren kullanıcı adları için kural ekledi" demote_user_html: "%{name}, %{target} kullanıcısını düşürdü" destroy_announcement_html: "%{name}, %{target} duyurusunu sildi" destroy_canonical_email_block_html: "%{name}, %{target} karmasıyla e-posta engelini kaldırdı" @@ -268,6 +272,7 @@ tr: destroy_status_html: "%{name}, %{target} kullanıcısının gönderisini kaldırdı" destroy_unavailable_domain_html: "%{name}, %{target} alan adına teslimatı sürdürdü" destroy_user_role_html: "%{name}, %{target} rolünü sildi" + destroy_username_block_html: "%{name}, %{target} içeren kullanıcı adları için kural silindi" disable_2fa_user_html: "%{name}, %{target} kullanıcısının iki aşamalı doğrulama gereksinimini kapattı" disable_custom_emoji_html: "%{name}, %{target} emojisini devre dışı bıraktı" disable_relay_html: "%{name}, %{target} aktarıcısını devre dışı bıraktı" @@ -302,6 +307,7 @@ tr: update_report_html: "%{name}, %{target} raporunu güncelledi" update_status_html: "%{name}, %{target} kullanıcısının gönderisini güncelledi" update_user_role_html: "%{name}, %{target} rolünü değiştirdi" + update_username_block_html: "%{name}, %{target} içeren kullanıcı adları için kural güncellendi" deleted_account: hesap silindi empty: Kayıt bulunamadı. filter_by_action: Eyleme göre filtre @@ -1085,6 +1091,25 @@ tr: other: Geçen hafta %{count} kişi tarafından kullanıldı title: Öneriler ve Öne Çıkanlar trending: Öne çıkanlar + username_blocks: + add_new: Yeni ekle + block_registrations: Kayıtları engelle + comparison: + contains: İçerir + equals: Eşit + contains_html: "%{string} içerir" + created_msg: Kullanıcı adı kuralı başarıyla oluşturuldu + delete: Sil + edit: + title: Kullanıcı adı kuralını düzenle + matches_exactly_html: "%{string} değerine eşittir" + new: + create: Kural oluştur + title: Yeni kullanıcı adı kuralı oluştur + no_username_block_selected: Hiçbir kullanıcı adı kuralı değiştirilmedi çünkü hiçbiri seçilmedi + not_permitted: İzin verilmiyor + title: Kullanıcı adı kuralları + updated_msg: Kullanıcı adı kuralı başarıyla güncellendi warning_presets: add_new: Yeni ekle delete: Sil @@ -1880,6 +1905,8 @@ tr: ownership: Başkasının gönderisi sabitlenemez reblog: Bir gönderi sabitlenemez quote_policies: + followers: Yalnızca takipçileriniz + nobody: Hiç kimse public: Herkes title: '%{name}: "%{quote}"' visibilities: From 80aadc55dff3f1b1c00cceea12f94bcdd09458f6 Mon Sep 17 00:00:00 2001 From: Claire Date: Mon, 4 Aug 2025 12:44:59 +0200 Subject: [PATCH 11/23] Add missing mailer for quote notifications (#35652) --- app/mailers/notification_mailer.rb | 10 ++++++++- app/models/notification.rb | 1 + app/models/user_settings.rb | 1 + app/views/notification_mailer/quote.html.haml | 16 ++++++++++++++ app/views/notification_mailer/quote.text.erb | 5 +++++ .../preferences/notifications/show.html.haml | 1 + config/locales/en.yml | 4 ++++ config/locales/simple_form.en.yml | 1 + spec/mailers/notification_mailer_spec.rb | 21 +++++++++++++++++++ .../previews/notification_mailer_preview.rb | 6 ++++++ .../api/web/push_subscriptions_spec.rb | 1 + 11 files changed, 66 insertions(+), 1 deletion(-) create mode 100644 app/views/notification_mailer/quote.html.haml create mode 100644 app/views/notification_mailer/quote.text.erb diff --git a/app/mailers/notification_mailer.rb b/app/mailers/notification_mailer.rb index a20992dcb56..54dde1bb0dd 100644 --- a/app/mailers/notification_mailer.rb +++ b/app/mailers/notification_mailer.rb @@ -6,7 +6,7 @@ class NotificationMailer < ApplicationMailer :routing before_action :process_params - with_options only: %i(mention favourite reblog) do + with_options only: %i(mention favourite reblog quote) do before_action :set_status after_action :thread_by_conversation! end @@ -27,6 +27,14 @@ class NotificationMailer < ApplicationMailer end end + def quote + return if @status.blank? + + locale_for_account(@me) do + mail subject: default_i18n_subject(name: @status.account.acct) + end + end + def follow locale_for_account(@me) do mail subject: default_i18n_subject(name: @account.acct) diff --git a/app/models/notification.rb b/app/models/notification.rb index f70991d801b..acef474a591 100644 --- a/app/models/notification.rb +++ b/app/models/notification.rb @@ -30,6 +30,7 @@ class Notification < ApplicationRecord 'FollowRequest' => :follow_request, 'Favourite' => :favourite, 'Poll' => :poll, + 'Quote' => :quote, }.freeze # Please update app/javascript/api_types/notification.ts if you change this diff --git a/app/models/user_settings.rb b/app/models/user_settings.rb index fd8659dc970..5558ffe04a4 100644 --- a/app/models/user_settings.rb +++ b/app/models/user_settings.rb @@ -43,6 +43,7 @@ class UserSettings setting :reblog, default: false setting :favourite, default: false setting :mention, default: true + setting :quote, default: true setting :follow_request, default: true setting :report, default: true setting :pending_account, default: true diff --git a/app/views/notification_mailer/quote.html.haml b/app/views/notification_mailer/quote.html.haml new file mode 100644 index 00000000000..1a2d8f8c76f --- /dev/null +++ b/app/views/notification_mailer/quote.html.haml @@ -0,0 +1,16 @@ += content_for :heading do + = render 'application/mailer/heading', + image_url: frontend_asset_url('images/mailer-new/heading/boost.png'), + subtitle: t('notification_mailer.quote.body', name: @status.account.pretty_acct), + title: t('notification_mailer.quote.title') +%table.email-w-full{ cellspacing: 0, cellpadding: 0, border: 0, role: 'presentation' } + %tr + %td.email-body-padding-td + %table.email-inner-card-table{ cellspacing: 0, cellpadding: 0, border: 0, role: 'presentation' } + %tr + %td.email-inner-card-td + = render 'status', status: @status, time_zone: @me.user_time_zone + %table.email-w-full{ cellspacing: 0, cellpadding: 0, border: 0, role: 'presentation' } + %tr + %td.email-padding-top-24 + = render 'application/mailer/button', text: t('notification_mailer.mention.action'), url: web_url("@#{@status.account.pretty_acct}/#{@status.id}") diff --git a/app/views/notification_mailer/quote.text.erb b/app/views/notification_mailer/quote.text.erb new file mode 100644 index 00000000000..6e3c67b7651 --- /dev/null +++ b/app/views/notification_mailer/quote.text.erb @@ -0,0 +1,5 @@ +<%= raw t('application_mailer.salutation', name: display_name(@me)) %> + +<%= raw t('notification_mailer.quote.body', name: @status.account.pretty_acct) %> + +<%= render 'status', status: @status %> diff --git a/app/views/settings/preferences/notifications/show.html.haml b/app/views/settings/preferences/notifications/show.html.haml index a8e179d0191..08bcc32e9b4 100644 --- a/app/views/settings/preferences/notifications/show.html.haml +++ b/app/views/settings/preferences/notifications/show.html.haml @@ -18,6 +18,7 @@ = ff.input :'notification_emails.reblog', wrapper: :with_label, label: I18n.t('simple_form.labels.notification_emails.reblog') = ff.input :'notification_emails.favourite', wrapper: :with_label, label: I18n.t('simple_form.labels.notification_emails.favourite') = ff.input :'notification_emails.mention', wrapper: :with_label, label: I18n.t('simple_form.labels.notification_emails.mention') + = ff.input :'notification_emails.quote', wrapper: :with_label, label: I18n.t('simple_form.labels.notification_emails.quote') .fields-group = ff.input :always_send_emails, wrapper: :with_label, label: I18n.t('simple_form.labels.defaults.setting_always_send_emails'), hint: I18n.t('simple_form.hints.defaults.setting_always_send_emails') diff --git a/config/locales/en.yml b/config/locales/en.yml index 59272bb3542..06db5e3cfce 100644 --- a/config/locales/en.yml +++ b/config/locales/en.yml @@ -1687,6 +1687,10 @@ en: title: New mention poll: subject: A poll by %{name} has ended + quote: + body: 'Your post was quoted by %{name}:' + subject: "%{name} quoted your post" + title: New quote reblog: body: 'Your post was boosted by %{name}:' subject: "%{name} boosted your post" diff --git a/config/locales/simple_form.en.yml b/config/locales/simple_form.en.yml index 8da54f626f7..d79899e908b 100644 --- a/config/locales/simple_form.en.yml +++ b/config/locales/simple_form.en.yml @@ -329,6 +329,7 @@ en: follow_request: Someone requested to follow you mention: Someone mentioned you pending_account: New account needs review + quote: Someone quoted you reblog: Someone boosted your post report: New report is submitted software_updates: diff --git a/spec/mailers/notification_mailer_spec.rb b/spec/mailers/notification_mailer_spec.rb index 25eb4ada263..b88277367dd 100644 --- a/spec/mailers/notification_mailer_spec.rb +++ b/spec/mailers/notification_mailer_spec.rb @@ -51,6 +51,27 @@ RSpec.describe NotificationMailer do it_behaves_like 'delivery without status' end + describe 'quote' do + let(:quote) { Fabricate(:quote, state: :accepted, status: foreign_status, quoted_status: own_status) } + let(:notification) { Notification.create!(account: receiver.account, activity: quote) } + let(:mail) { prepared_mailer_for(own_status.account).quote } + + it_behaves_like 'localized subject', 'notification_mailer.quote.subject', name: 'bob' + + it 'renders the email' do + expect(mail) + .to be_present + .and(have_subject('bob quoted your post')) + .and(have_body_text('Your post was quoted by bob')) + .and(have_body_text('The body of the foreign status')) + .and have_thread_headers + .and have_standard_headers('quote').for(receiver) + end + + it_behaves_like 'delivery to non functional user' + it_behaves_like 'delivery without status' + end + describe 'follow' do let(:follow) { sender.follow!(receiver.account) } let(:notification) { Notification.create!(account: receiver.account, activity: follow) } diff --git a/spec/mailers/previews/notification_mailer_preview.rb b/spec/mailers/previews/notification_mailer_preview.rb index a63c20c27c5..ae2d6802bcf 100644 --- a/spec/mailers/previews/notification_mailer_preview.rb +++ b/spec/mailers/previews/notification_mailer_preview.rb @@ -33,6 +33,12 @@ class NotificationMailerPreview < ActionMailer::Preview mailer_for(activity.reblog.account, activity).reblog end + # Preview this email at http://localhost:3000/rails/mailers/notification_mailer/quote + def quote + activity = Quote.first + mailer_for(activity.quoted_account, activity).quote + end + private def mailer_for(account, activity) diff --git a/spec/requests/api/web/push_subscriptions_spec.rb b/spec/requests/api/web/push_subscriptions_spec.rb index 91d7b85bc58..05e6f28d1ff 100644 --- a/spec/requests/api/web/push_subscriptions_spec.rb +++ b/spec/requests/api/web/push_subscriptions_spec.rb @@ -29,6 +29,7 @@ RSpec.describe 'API Web Push Subscriptions' do mention: false, poll: true, status: false, + quote: true, }, }, } From c8ec6498308d4cdc528c35d160d207c9df1efe69 Mon Sep 17 00:00:00 2001 From: Eugen Rochko Date: Mon, 4 Aug 2025 14:49:17 +0200 Subject: [PATCH 12/23] Fix "new replies available" miscounting previously known replies (#35654) --- app/workers/fetch_reply_worker.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/workers/fetch_reply_worker.rb b/app/workers/fetch_reply_worker.rb index 227d38a5f2d..4f11b75cc51 100644 --- a/app/workers/fetch_reply_worker.rb +++ b/app/workers/fetch_reply_worker.rb @@ -10,6 +10,6 @@ class FetchReplyWorker batch = WorkerBatch.new(options.delete('batch_id')) if options['batch_id'] result = FetchRemoteStatusService.new.call(child_url, **options.symbolize_keys) ensure - batch&.remove_job(jid, increment: result.present?) + batch&.remove_job(jid, increment: result&.previously_new_record?) end end From d8397040d790b9e7c3d5ba88017cd36642211bcc Mon Sep 17 00:00:00 2001 From: Eugen Rochko Date: Mon, 4 Aug 2025 15:10:19 +0200 Subject: [PATCH 13/23] Fix allow with approval option not working on username blocks (#35655) --- app/models/username_block.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/models/username_block.rb b/app/models/username_block.rb index 227def66e14..18db4ca34ee 100644 --- a/app/models/username_block.rb +++ b/app/models/username_block.rb @@ -43,7 +43,7 @@ class UsernameBlock < ApplicationRecord def self.matches?(str, allow_with_approval: false) normalized_str = str.downcase.gsub(Regexp.union(HOMOGLYPHS.keys), HOMOGLYPHS) - where(allow_with_approval: allow_with_approval).matches_exactly(normalized_str).or(matches_partially(normalized_str)).any? + matches_exactly(normalized_str).or(matches_partially(normalized_str)).where(allow_with_approval: allow_with_approval).any? end def to_log_human_identifier From eb273f904fe5af485203753ae790a9d66346f3ee Mon Sep 17 00:00:00 2001 From: David Roetzel Date: Mon, 4 Aug 2025 16:04:40 +0200 Subject: [PATCH 14/23] Make `WorkerBatch` spec more robust (#35656) --- spec/models/worker_batch_spec.rb | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/spec/models/worker_batch_spec.rb b/spec/models/worker_batch_spec.rb index 7c6b8aa8c6d..b204decb89e 100644 --- a/spec/models/worker_batch_spec.rb +++ b/spec/models/worker_batch_spec.rb @@ -54,7 +54,7 @@ RSpec.describe WorkerBatch do end it 'persists the job IDs' do - expect(subject.jobs).to eq %w(foo bar) + expect(subject.jobs).to contain_exactly('foo', 'bar') end end end @@ -67,7 +67,7 @@ RSpec.describe WorkerBatch do end it 'removes the job from pending jobs' do - expect(subject.jobs).to eq %w(bar baz) + expect(subject.jobs).to contain_exactly('bar', 'baz') end it 'decrements the number of pending jobs' do From 5ed9410de0c6ffdb1eb43a2f008a9118180f580c Mon Sep 17 00:00:00 2001 From: Claire Date: Mon, 4 Aug 2025 16:15:02 +0200 Subject: [PATCH 15/23] Disable ActiveRecord query cache in `Create` critical path (#35662) --- app/lib/activitypub/activity/create.rb | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/app/lib/activitypub/activity/create.rb b/app/lib/activitypub/activity/create.rb index ab84a5dd472..9db7ec1a150 100644 --- a/app/lib/activitypub/activity/create.rb +++ b/app/lib/activitypub/activity/create.rb @@ -17,9 +17,11 @@ class ActivityPub::Activity::Create < ActivityPub::Activity return reject_payload! if unsupported_object_type? || non_matching_uri_hosts?(@account.uri, object_uri) || tombstone_exists? || !related_to_local_activity? with_redis_lock("create:#{object_uri}") do - return if delete_arrived_first?(object_uri) || poll_vote? + Status.uncached do + return if delete_arrived_first?(object_uri) || poll_vote? - @status = find_existing_status + @status = find_existing_status + end if @status.nil? process_status From 49dcbd22d67abd8f522fcb39c6ed4639ce03562c Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Mon, 4 Aug 2025 16:19:48 +0200 Subject: [PATCH 16/23] Update eslint (non-major) (#35661) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- package.json | 2 +- yarn.lock | 848 ++++++++++++++++++++++++++------------------------- 2 files changed, 429 insertions(+), 421 deletions(-) diff --git a/package.json b/package.json index 736f29fb814..ec7b918ef0a 100644 --- a/package.json +++ b/package.json @@ -168,7 +168,7 @@ "eslint": "^9.23.0", "eslint-import-resolver-typescript": "^4.2.5", "eslint-plugin-formatjs": "^5.3.1", - "eslint-plugin-import": "~2.31.0", + "eslint-plugin-import": "~2.32.0", "eslint-plugin-jsdoc": "^52.0.0", "eslint-plugin-jsx-a11y": "~6.10.2", "eslint-plugin-promise": "~7.2.1", diff --git a/yarn.lock b/yarn.lock index 8148fab1c86..a8baa769411 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1794,31 +1794,31 @@ __metadata: languageName: node linkType: hard -"@emnapi/core@npm:^1.3.1": - version: 1.3.1 - resolution: "@emnapi/core@npm:1.3.1" +"@emnapi/core@npm:^1.4.3": + version: 1.4.5 + resolution: "@emnapi/core@npm:1.4.5" dependencies: - "@emnapi/wasi-threads": "npm:1.0.1" + "@emnapi/wasi-threads": "npm:1.0.4" tslib: "npm:^2.4.0" - checksum: 10c0/d3be1044ad704e2c486641bc18908523490f28c7d38bd12d9c1d4ce37d39dae6c4aecd2f2eaf44c6e3bd90eaf04e0591acc440b1b038cdf43cce078a355a0ea0 + checksum: 10c0/da4a57f65f325d720d0e0d1a9c6618b90c4c43a5027834a110476984e1d47c95ebaed4d316b5dddb9c0ed9a493ffeb97d1934f9677035f336d8a36c1f3b2818f languageName: node linkType: hard -"@emnapi/runtime@npm:^1.3.1": - version: 1.3.1 - resolution: "@emnapi/runtime@npm:1.3.1" +"@emnapi/runtime@npm:^1.4.3": + version: 1.4.5 + resolution: "@emnapi/runtime@npm:1.4.5" dependencies: tslib: "npm:^2.4.0" - checksum: 10c0/060ffede50f1b619c15083312b80a9e62a5b0c87aa8c1b54854c49766c9d69f8d1d3d87bd963a647071263a320db41b25eaa50b74d6a80dcc763c23dbeaafd6c + checksum: 10c0/37a0278be5ac81e918efe36f1449875cbafba947039c53c65a1f8fc238001b866446fc66041513b286baaff5d6f9bec667f5164b3ca481373a8d9cb65bfc984b languageName: node linkType: hard -"@emnapi/wasi-threads@npm:1.0.1": - version: 1.0.1 - resolution: "@emnapi/wasi-threads@npm:1.0.1" +"@emnapi/wasi-threads@npm:1.0.4": + version: 1.0.4 + resolution: "@emnapi/wasi-threads@npm:1.0.4" dependencies: tslib: "npm:^2.4.0" - checksum: 10c0/1e0c8036b8d53e9b07cc9acf021705ef6c86ab6b13e1acda7fffaf541a2d3565072afb92597419173ced9ea14f6bf32fce149106e669b5902b825e8b499e5c6c + checksum: 10c0/2c91a53e62f875800baf035c4d42c9c0d18e5afd9a31ca2aac8b435aeaeaeaac386b5b3d0d0e70aa7a5a9852bbe05106b1f680cd82cce03145c703b423d41313 languageName: node linkType: hard @@ -2152,30 +2152,30 @@ __metadata: languageName: node linkType: hard -"@eslint/config-array@npm:^0.19.2": - version: 0.19.2 - resolution: "@eslint/config-array@npm:0.19.2" +"@eslint/config-array@npm:^0.21.0": + version: 0.21.0 + resolution: "@eslint/config-array@npm:0.21.0" dependencies: "@eslint/object-schema": "npm:^2.1.6" debug: "npm:^4.3.1" minimatch: "npm:^3.1.2" - checksum: 10c0/dd68da9abb32d336233ac4fe0db1e15a0a8d794b6e69abb9e57545d746a97f6f542496ff9db0d7e27fab1438546250d810d90b1904ac67677215b8d8e7573f3d + checksum: 10c0/0ea801139166c4aa56465b309af512ef9b2d3c68f9198751bbc3e21894fe70f25fbf26e1b0e9fffff41857bc21bfddeee58649ae6d79aadcd747db0c5dca771f languageName: node linkType: hard -"@eslint/config-helpers@npm:^0.2.0": - version: 0.2.0 - resolution: "@eslint/config-helpers@npm:0.2.0" - checksum: 10c0/743a64653e13177029108f57ab47460ded08e3412c86216a14b7e8ab2dc79c2b64be45bf55c5ef29f83692a707dc34cf1e9217e4b8b4b272a0d9b691fdaf6a2a +"@eslint/config-helpers@npm:^0.3.0": + version: 0.3.0 + resolution: "@eslint/config-helpers@npm:0.3.0" + checksum: 10c0/013ae7b189eeae8b30cc2ee87bc5c9c091a9cd615579003290eb28bebad5d78806a478e74ba10b3fe08ed66975b52af7d2cd4b4b43990376412b14e5664878c8 languageName: node linkType: hard -"@eslint/core@npm:^0.12.0": - version: 0.12.0 - resolution: "@eslint/core@npm:0.12.0" +"@eslint/core@npm:^0.15.0, @eslint/core@npm:^0.15.1": + version: 0.15.1 + resolution: "@eslint/core@npm:0.15.1" dependencies: "@types/json-schema": "npm:^7.0.15" - checksum: 10c0/d032af81195bb28dd800c2b9617548c6c2a09b9490da3c5537fd2a1201501666d06492278bb92cfccac1f7ac249e58601dd87f813ec0d6a423ef0880434fa0c3 + checksum: 10c0/abaf641940776638b8c15a38d99ce0dac551a8939310ec81b9acd15836a574cf362588eaab03ab11919bc2a0f9648b19ea8dee33bf12675eb5b6fd38bda6f25e languageName: node linkType: hard @@ -2196,10 +2196,10 @@ __metadata: languageName: node linkType: hard -"@eslint/js@npm:9.23.0, @eslint/js@npm:^9.23.0": - version: 9.23.0 - resolution: "@eslint/js@npm:9.23.0" - checksum: 10c0/4e70869372b6325389e0ab51cac6d3062689807d1cef2c3434857571422ce11dde3c62777af85c382b9f94d937127598d605d2086787f08611351bf99faded81 +"@eslint/js@npm:9.32.0, @eslint/js@npm:^9.23.0": + version: 9.32.0 + resolution: "@eslint/js@npm:9.32.0" + checksum: 10c0/f71e8f9146638d11fb15238279feff98801120a4d4130f1c587c4f09b024ff5ec01af1ba88e97ba6b7013488868898a668f77091300cc3d4394c7a8ed32d2667 languageName: node linkType: hard @@ -2210,13 +2210,13 @@ __metadata: languageName: node linkType: hard -"@eslint/plugin-kit@npm:^0.2.7": - version: 0.2.7 - resolution: "@eslint/plugin-kit@npm:0.2.7" +"@eslint/plugin-kit@npm:^0.3.4": + version: 0.3.4 + resolution: "@eslint/plugin-kit@npm:0.3.4" dependencies: - "@eslint/core": "npm:^0.12.0" + "@eslint/core": "npm:^0.15.1" levn: "npm:^0.4.1" - checksum: 10c0/0a1aff1ad63e72aca923217e556c6dfd67d7cd121870eb7686355d7d1475d569773528a8b2111b9176f3d91d2ea81f7413c34600e8e5b73d59e005d70780b633 + checksum: 10c0/64331ca100f62a0115d10419a28059d0f377e390192163b867b9019517433d5073d10b4ec21f754fa01faf832aceb34178745924baab2957486f8bf95fd628d2 languageName: node linkType: hard @@ -2362,26 +2362,6 @@ __metadata: languageName: node linkType: hard -"@formatjs/ts-transformer@npm:3.13.34": - version: 3.13.34 - resolution: "@formatjs/ts-transformer@npm:3.13.34" - dependencies: - "@formatjs/icu-messageformat-parser": "npm:2.11.2" - "@types/json-stable-stringify": "npm:^1.1.0" - "@types/node": "npm:^22.0.0" - chalk: "npm:^4.1.2" - json-stable-stringify: "npm:^1.1.1" - tslib: "npm:^2.8.0" - typescript: "npm:^5.6.0" - peerDependencies: - ts-jest: ^29 - peerDependenciesMeta: - ts-jest: - optional: true - checksum: 10c0/2e53af5a53cab71be0ba2fc16ba856c95bf336c063cc835486cd3a68d01013c5c08026b34667f4bdf99422e74faa8eb1f26d5fe8006f3a1ae9c77e065599362e - languageName: node - linkType: hard - "@formatjs/ts-transformer@npm:3.14.0": version: 3.14.0 resolution: "@formatjs/ts-transformer@npm:3.14.0" @@ -2683,7 +2663,7 @@ __metadata: eslint: "npm:^9.23.0" eslint-import-resolver-typescript: "npm:^4.2.5" eslint-plugin-formatjs: "npm:^5.3.1" - eslint-plugin-import: "npm:~2.31.0" + eslint-plugin-import: "npm:~2.32.0" eslint-plugin-jsdoc: "npm:^52.0.0" eslint-plugin-jsx-a11y: "npm:~6.10.2" eslint-plugin-promise: "npm:~7.2.1" @@ -2835,14 +2815,14 @@ __metadata: languageName: node linkType: hard -"@napi-rs/wasm-runtime@npm:^0.2.7": - version: 0.2.7 - resolution: "@napi-rs/wasm-runtime@npm:0.2.7" +"@napi-rs/wasm-runtime@npm:^0.2.11": + version: 0.2.12 + resolution: "@napi-rs/wasm-runtime@npm:0.2.12" dependencies: - "@emnapi/core": "npm:^1.3.1" - "@emnapi/runtime": "npm:^1.3.1" - "@tybys/wasm-util": "npm:^0.9.0" - checksum: 10c0/04a5edd79144bfa4e821a373fb6d4939f10c578c5f3633b5e67a57d0f5e36a593f595834d26654ea757bba7cd80b6c42d0d1405d6a8460c5d774e8cd5c9548a4 + "@emnapi/core": "npm:^1.4.3" + "@emnapi/runtime": "npm:^1.4.3" + "@tybys/wasm-util": "npm:^0.10.0" + checksum: 10c0/6d07922c0613aab30c6a497f4df297ca7c54e5b480e00035e0209b872d5c6aab7162fc49477267556109c2c7ed1eb9c65a174e27e9b87568106a87b0a6e3ca7d languageName: node linkType: hard @@ -3823,12 +3803,12 @@ __metadata: languageName: node linkType: hard -"@tybys/wasm-util@npm:^0.9.0": - version: 0.9.0 - resolution: "@tybys/wasm-util@npm:0.9.0" +"@tybys/wasm-util@npm:^0.10.0": + version: 0.10.0 + resolution: "@tybys/wasm-util@npm:0.10.0" dependencies: tslib: "npm:^2.4.0" - checksum: 10c0/f9fde5c554455019f33af6c8215f1a1435028803dc2a2825b077d812bed4209a1a64444a4ca0ce2ea7e1175c8d88e2f9173a36a33c199e8a5c671aa31de8242d + checksum: 10c0/044feba55c1e2af703aa4946139969badb183ce1a659a75ed60bc195a90e73a3f3fc53bcd643497c9954597763ddb051fec62f80962b2ca6fc716ba897dc696e languageName: node linkType: hard @@ -4414,145 +4394,106 @@ __metadata: languageName: node linkType: hard -"@typescript-eslint/eslint-plugin@npm:8.29.1": - version: 8.29.1 - resolution: "@typescript-eslint/eslint-plugin@npm:8.29.1" +"@typescript-eslint/eslint-plugin@npm:8.38.0": + version: 8.38.0 + resolution: "@typescript-eslint/eslint-plugin@npm:8.38.0" dependencies: "@eslint-community/regexpp": "npm:^4.10.0" - "@typescript-eslint/scope-manager": "npm:8.29.1" - "@typescript-eslint/type-utils": "npm:8.29.1" - "@typescript-eslint/utils": "npm:8.29.1" - "@typescript-eslint/visitor-keys": "npm:8.29.1" + "@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" graphemer: "npm:^1.4.0" - ignore: "npm:^5.3.1" + ignore: "npm:^7.0.0" natural-compare: "npm:^1.4.0" - ts-api-utils: "npm:^2.0.1" + ts-api-utils: "npm:^2.1.0" peerDependencies: - "@typescript-eslint/parser": ^8.0.0 || ^8.0.0-alpha.0 + "@typescript-eslint/parser": ^8.38.0 eslint: ^8.57.0 || ^9.0.0 typescript: ">=4.8.4 <5.9.0" - checksum: 10c0/a3ed7556edcac374cab622862f2f9adedc91ca305d6937db6869a0253d675858c296cb5413980e8404fc39737117faaf35b00c6804664b3c542bdc417502532f + checksum: 10c0/199b82e9f0136baecf515df7c31bfed926a7c6d4e6298f64ee1a77c8bdd7a8cb92a2ea55a5a345c9f2948a02f7be6d72530efbe803afa1892b593fbd529d0c27 languageName: node linkType: hard -"@typescript-eslint/parser@npm:8.29.1": - version: 8.29.1 - resolution: "@typescript-eslint/parser@npm:8.29.1" +"@typescript-eslint/parser@npm:8.38.0": + version: 8.38.0 + resolution: "@typescript-eslint/parser@npm:8.38.0" dependencies: - "@typescript-eslint/scope-manager": "npm:8.29.1" - "@typescript-eslint/types": "npm:8.29.1" - "@typescript-eslint/typescript-estree": "npm:8.29.1" - "@typescript-eslint/visitor-keys": "npm:8.29.1" + "@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" debug: "npm:^4.3.4" peerDependencies: eslint: ^8.57.0 || ^9.0.0 typescript: ">=4.8.4 <5.9.0" - checksum: 10c0/af3570ff58c42c2014e5c117bebf91120737fb139d94415ca2711844990e95252c3006ccc699871fe3f592cc1a3f4ebfdc9dd5f6cb29b6b128c2524fcf311b75 + checksum: 10c0/5580c2a328f0c15f85e4a0961a07584013cc0aca85fe868486187f7c92e9e3f6602c6e3dab917b092b94cd492ed40827c6f5fea42730bef88eb17592c947adf4 languageName: node linkType: hard -"@typescript-eslint/project-service@npm:8.33.0": - version: 8.33.0 - resolution: "@typescript-eslint/project-service@npm:8.33.0" +"@typescript-eslint/project-service@npm:8.38.0": + version: 8.38.0 + resolution: "@typescript-eslint/project-service@npm:8.38.0" dependencies: - "@typescript-eslint/tsconfig-utils": "npm:^8.33.0" - "@typescript-eslint/types": "npm:^8.33.0" + "@typescript-eslint/tsconfig-utils": "npm:^8.38.0" + "@typescript-eslint/types": "npm:^8.38.0" debug: "npm:^4.3.4" - checksum: 10c0/a863d9e3be5ffb53c9d57b25b7a35149dae01afd942dd7fc36bd72a4230676ae12d0f37a789cddaf1baf71e3b35f09436bebbd081336e667b4181b48d0afe8f5 - languageName: node - linkType: hard - -"@typescript-eslint/scope-manager@npm:8.29.1": - version: 8.29.1 - resolution: "@typescript-eslint/scope-manager@npm:8.29.1" - dependencies: - "@typescript-eslint/types": "npm:8.29.1" - "@typescript-eslint/visitor-keys": "npm:8.29.1" - checksum: 10c0/8b87a04f01ebc13075e352509bca8f31c757c3220857fa473ac155f6bdf7f30fe82765d0c3d8e790f7fad394a32765bd9f716b97c08e17581d358c76086d51af - languageName: node - linkType: hard - -"@typescript-eslint/scope-manager@npm:8.33.0": - version: 8.33.0 - resolution: "@typescript-eslint/scope-manager@npm:8.33.0" - dependencies: - "@typescript-eslint/types": "npm:8.33.0" - "@typescript-eslint/visitor-keys": "npm:8.33.0" - checksum: 10c0/eb259add242ce40642e7272b414c92ae9407d97cb304981f17f0de0846d5c4ab47d41816ef13da3d3976fe0b7a74df291525be27e4fe4f0ab5d35e86d340faa0 - languageName: node - linkType: hard - -"@typescript-eslint/tsconfig-utils@npm:8.33.0, @typescript-eslint/tsconfig-utils@npm:^8.33.0": - version: 8.33.0 - resolution: "@typescript-eslint/tsconfig-utils@npm:8.33.0" peerDependencies: typescript: ">=4.8.4 <5.9.0" - checksum: 10c0/6e9a8e73e65b925f908f31e00be4f1b8d7e89f45d97fa703f468115943c297fc2cc6f9daa0c12b9607f39186f033ac244515f11710df7e1df8302c815ed57389 + checksum: 10c0/87d2f55521e289bbcdc666b1f4587ee2d43039cee927310b05abaa534b528dfb1b5565c1545bb4996d7fbdf9d5a3b0aa0e6c93a8f1289e3fcfd60d246364a884 languageName: node linkType: hard -"@typescript-eslint/type-utils@npm:8.29.1": - version: 8.29.1 - resolution: "@typescript-eslint/type-utils@npm:8.29.1" +"@typescript-eslint/scope-manager@npm:8.38.0": + version: 8.38.0 + resolution: "@typescript-eslint/scope-manager@npm:8.38.0" dependencies: - "@typescript-eslint/typescript-estree": "npm:8.29.1" - "@typescript-eslint/utils": "npm:8.29.1" + "@typescript-eslint/types": "npm:8.38.0" + "@typescript-eslint/visitor-keys": "npm:8.38.0" + checksum: 10c0/ceaf489ea1f005afb187932a7ee363dfe1e0f7cc3db921283991e20e4c756411a5e25afbec72edd2095d6a4384f73591f4c750cf65b5eaa650c90f64ef9fe809 + 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" + peerDependencies: + typescript: ">=4.8.4 <5.9.0" + checksum: 10c0/1a90da16bf1f7cfbd0303640a8ead64a0080f2b1d5969994bdac3b80abfa1177f0c6fbf61250bae082e72cf5014308f2f5cc98edd6510202f13420a7ffd07a84 + 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" + dependencies: + "@typescript-eslint/types": "npm:8.38.0" + "@typescript-eslint/typescript-estree": "npm:8.38.0" + "@typescript-eslint/utils": "npm:8.38.0" debug: "npm:^4.3.4" - ts-api-utils: "npm:^2.0.1" + ts-api-utils: "npm:^2.1.0" peerDependencies: eslint: ^8.57.0 || ^9.0.0 typescript: ">=4.8.4 <5.9.0" - checksum: 10c0/72cc01dbac866b0a7c7b1f637ad03ffd22f6d3617f70f06f485cf3096fddfc821fdc56de1a072cc6af70250c63698a3e5a910f67fe46eea941955b6e0da1b2bd + checksum: 10c0/27795c4bd0be395dda3424e57d746639c579b7522af1c17731b915298a6378fd78869e8e141526064b6047db2c86ba06444469ace19c98cda5779d06f4abd37c languageName: node linkType: hard -"@typescript-eslint/types@npm:8.29.1": - version: 8.29.1 - resolution: "@typescript-eslint/types@npm:8.29.1" - checksum: 10c0/bbcb9e4f38df4485092b51ac6bb62d65f321d914ab58dc0ff1eaa7787dc0b4a39e237c2617b9f2c2bcb91a343f30de523e3544f69affa1ee4287a3ef2fc10ce7 +"@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 languageName: node linkType: hard -"@typescript-eslint/types@npm:8.33.0": - version: 8.33.0 - resolution: "@typescript-eslint/types@npm:8.33.0" - checksum: 10c0/348b64eb408719d7711a433fc9716e0c2aab8b3f3676f5a1cc2e00269044132282cf655deb6d0dd9817544116909513de3b709005352d186949d1014fad1a3cb - languageName: node - linkType: hard - -"@typescript-eslint/types@npm:^8.33.0, @typescript-eslint/types@npm:^8.34.1": - version: 8.36.0 - resolution: "@typescript-eslint/types@npm:8.36.0" - checksum: 10c0/cacb941a0caad6ab556c416051b97ec33b364b7c8e0703e2729ae43f12daf02b42eef12011705329107752e3f1685ca82cfffe181d637f85907293cb634bee31 - languageName: node - linkType: hard - -"@typescript-eslint/typescript-estree@npm:8.29.1": - version: 8.29.1 - resolution: "@typescript-eslint/typescript-estree@npm:8.29.1" +"@typescript-eslint/typescript-estree@npm:8.38.0": + version: 8.38.0 + resolution: "@typescript-eslint/typescript-estree@npm:8.38.0" dependencies: - "@typescript-eslint/types": "npm:8.29.1" - "@typescript-eslint/visitor-keys": "npm:8.29.1" - debug: "npm:^4.3.4" - fast-glob: "npm:^3.3.2" - is-glob: "npm:^4.0.3" - minimatch: "npm:^9.0.4" - semver: "npm:^7.6.0" - ts-api-utils: "npm:^2.0.1" - peerDependencies: - typescript: ">=4.8.4 <5.9.0" - checksum: 10c0/33c46c667d9262e5625d5d0064338711b342e62c5675ded6811a2cb13ee5de2f71b90e9d0be5cb338b11b1a329c376a6bbf6c3d24fa8fb457b2eefc9f3298513 - languageName: node - linkType: hard - -"@typescript-eslint/typescript-estree@npm:8.33.0": - version: 8.33.0 - resolution: "@typescript-eslint/typescript-estree@npm:8.33.0" - dependencies: - "@typescript-eslint/project-service": "npm:8.33.0" - "@typescript-eslint/tsconfig-utils": "npm:8.33.0" - "@typescript-eslint/types": "npm:8.33.0" - "@typescript-eslint/visitor-keys": "npm:8.33.0" + "@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" debug: "npm:^4.3.4" fast-glob: "npm:^3.3.2" is-glob: "npm:^4.0.3" @@ -4561,163 +4502,166 @@ __metadata: ts-api-utils: "npm:^2.1.0" peerDependencies: typescript: ">=4.8.4 <5.9.0" - checksum: 10c0/677b12b2e5780ffaef508bddbf8712fe2c3413f3d14fd8fd0cfbe22952a81c6642b3cc26984cf27fdfc3dd2457ae5f8aa04437d3b0ae32987a1895f9648ca7b2 + checksum: 10c0/00a00f6549877f4ae5c2847fa5ac52bf42cbd59a87533856c359e2746e448ed150b27a6137c92fd50c06e6a4b39e386d6b738fac97d80d05596e81ce55933230 languageName: node linkType: hard -"@typescript-eslint/utils@npm:8.29.1": - version: 8.29.1 - resolution: "@typescript-eslint/utils@npm:8.29.1" - dependencies: - "@eslint-community/eslint-utils": "npm:^4.4.0" - "@typescript-eslint/scope-manager": "npm:8.29.1" - "@typescript-eslint/types": "npm:8.29.1" - "@typescript-eslint/typescript-estree": "npm:8.29.1" - peerDependencies: - eslint: ^8.57.0 || ^9.0.0 - typescript: ">=4.8.4 <5.9.0" - checksum: 10c0/1b2704b769b0c9353cf26a320ecf9775ba51c94c7c30e2af80ca31f4cb230f319762ab06535fcb26b6963144bbeaa53233b34965907c506283861b013f5b95fc - languageName: node - linkType: hard - -"@typescript-eslint/utils@npm:^8.27.0, @typescript-eslint/utils@npm:^8.8.1": - version: 8.33.0 - resolution: "@typescript-eslint/utils@npm:8.33.0" +"@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" dependencies: "@eslint-community/eslint-utils": "npm:^4.7.0" - "@typescript-eslint/scope-manager": "npm:8.33.0" - "@typescript-eslint/types": "npm:8.33.0" - "@typescript-eslint/typescript-estree": "npm:8.33.0" + "@typescript-eslint/scope-manager": "npm:8.38.0" + "@typescript-eslint/types": "npm:8.38.0" + "@typescript-eslint/typescript-estree": "npm:8.38.0" peerDependencies: eslint: ^8.57.0 || ^9.0.0 typescript: ">=4.8.4 <5.9.0" - checksum: 10c0/a0adb9e13d8f8d8f86ae2e905f3305ad60732e760364b291de66a857a551485d37c23e923299078a47f75d3cca643e1f2aefa010a0beb4cb0d08d0507c1038e1 + checksum: 10c0/e97a45bf44f315f9ed8c2988429e18c88e3369c9ee3227ee86446d2d49f7325abebbbc9ce801e178f676baa986d3e1fd4b5391f1640c6eb8944c123423ae43bb languageName: node linkType: hard -"@typescript-eslint/visitor-keys@npm:8.29.1": - version: 8.29.1 - resolution: "@typescript-eslint/visitor-keys@npm:8.29.1" +"@typescript-eslint/visitor-keys@npm:8.38.0": + version: 8.38.0 + resolution: "@typescript-eslint/visitor-keys@npm:8.38.0" dependencies: - "@typescript-eslint/types": "npm:8.29.1" - eslint-visitor-keys: "npm:^4.2.0" - checksum: 10c0/0c12e83c84a754161c89e594a96454799669979c7021a8936515ec574a1fa1d6e3119e0eacf502e07a0fa7254974558ea7a48901c8bfed3c46579a61b655e4f5 + "@typescript-eslint/types": "npm:8.38.0" + eslint-visitor-keys: "npm:^4.2.1" + checksum: 10c0/071a756e383f41a6c9e51d78c8c64bd41cd5af68b0faef5fbaec4fa5dbd65ec9e4cd610c2e2cdbe9e2facc362995f202850622b78e821609a277b5b601a1d4ec languageName: node linkType: hard -"@typescript-eslint/visitor-keys@npm:8.33.0": - version: 8.33.0 - resolution: "@typescript-eslint/visitor-keys@npm:8.33.0" - dependencies: - "@typescript-eslint/types": "npm:8.33.0" - eslint-visitor-keys: "npm:^4.2.0" - checksum: 10c0/41660f241e78314f69d251792f369ef1eeeab3b40fe4ab11b794d402c95bcb82b61d3e91763e7ab9b0f22011a7ac9c8f9dfd91734d61c9f4eaf4f7660555b53b +"@unrs/resolver-binding-android-arm-eabi@npm:1.11.1": + version: 1.11.1 + resolution: "@unrs/resolver-binding-android-arm-eabi@npm:1.11.1" + conditions: os=android & cpu=arm languageName: node linkType: hard -"@unrs/resolver-binding-darwin-arm64@npm:1.3.2": - version: 1.3.2 - resolution: "@unrs/resolver-binding-darwin-arm64@npm:1.3.2" +"@unrs/resolver-binding-android-arm64@npm:1.11.1": + version: 1.11.1 + resolution: "@unrs/resolver-binding-android-arm64@npm:1.11.1" + conditions: os=android & cpu=arm64 + languageName: node + linkType: hard + +"@unrs/resolver-binding-darwin-arm64@npm:1.11.1": + version: 1.11.1 + resolution: "@unrs/resolver-binding-darwin-arm64@npm:1.11.1" conditions: os=darwin & cpu=arm64 languageName: node linkType: hard -"@unrs/resolver-binding-darwin-x64@npm:1.3.2": - version: 1.3.2 - resolution: "@unrs/resolver-binding-darwin-x64@npm:1.3.2" +"@unrs/resolver-binding-darwin-x64@npm:1.11.1": + version: 1.11.1 + resolution: "@unrs/resolver-binding-darwin-x64@npm:1.11.1" conditions: os=darwin & cpu=x64 languageName: node linkType: hard -"@unrs/resolver-binding-freebsd-x64@npm:1.3.2": - version: 1.3.2 - resolution: "@unrs/resolver-binding-freebsd-x64@npm:1.3.2" +"@unrs/resolver-binding-freebsd-x64@npm:1.11.1": + version: 1.11.1 + resolution: "@unrs/resolver-binding-freebsd-x64@npm:1.11.1" conditions: os=freebsd & cpu=x64 languageName: node linkType: hard -"@unrs/resolver-binding-linux-arm-gnueabihf@npm:1.3.2": - version: 1.3.2 - resolution: "@unrs/resolver-binding-linux-arm-gnueabihf@npm:1.3.2" +"@unrs/resolver-binding-linux-arm-gnueabihf@npm:1.11.1": + version: 1.11.1 + resolution: "@unrs/resolver-binding-linux-arm-gnueabihf@npm:1.11.1" conditions: os=linux & cpu=arm languageName: node linkType: hard -"@unrs/resolver-binding-linux-arm-musleabihf@npm:1.3.2": - version: 1.3.2 - resolution: "@unrs/resolver-binding-linux-arm-musleabihf@npm:1.3.2" +"@unrs/resolver-binding-linux-arm-musleabihf@npm:1.11.1": + version: 1.11.1 + resolution: "@unrs/resolver-binding-linux-arm-musleabihf@npm:1.11.1" conditions: os=linux & cpu=arm languageName: node linkType: hard -"@unrs/resolver-binding-linux-arm64-gnu@npm:1.3.2": - version: 1.3.2 - resolution: "@unrs/resolver-binding-linux-arm64-gnu@npm:1.3.2" +"@unrs/resolver-binding-linux-arm64-gnu@npm:1.11.1": + version: 1.11.1 + resolution: "@unrs/resolver-binding-linux-arm64-gnu@npm:1.11.1" conditions: os=linux & cpu=arm64 & libc=glibc languageName: node linkType: hard -"@unrs/resolver-binding-linux-arm64-musl@npm:1.3.2": - version: 1.3.2 - resolution: "@unrs/resolver-binding-linux-arm64-musl@npm:1.3.2" +"@unrs/resolver-binding-linux-arm64-musl@npm:1.11.1": + version: 1.11.1 + resolution: "@unrs/resolver-binding-linux-arm64-musl@npm:1.11.1" conditions: os=linux & cpu=arm64 & libc=musl languageName: node linkType: hard -"@unrs/resolver-binding-linux-ppc64-gnu@npm:1.3.2": - version: 1.3.2 - resolution: "@unrs/resolver-binding-linux-ppc64-gnu@npm:1.3.2" +"@unrs/resolver-binding-linux-ppc64-gnu@npm:1.11.1": + version: 1.11.1 + resolution: "@unrs/resolver-binding-linux-ppc64-gnu@npm:1.11.1" conditions: os=linux & cpu=ppc64 & libc=glibc languageName: node linkType: hard -"@unrs/resolver-binding-linux-s390x-gnu@npm:1.3.2": - version: 1.3.2 - resolution: "@unrs/resolver-binding-linux-s390x-gnu@npm:1.3.2" +"@unrs/resolver-binding-linux-riscv64-gnu@npm:1.11.1": + version: 1.11.1 + resolution: "@unrs/resolver-binding-linux-riscv64-gnu@npm:1.11.1" + conditions: os=linux & cpu=riscv64 & libc=glibc + languageName: node + linkType: hard + +"@unrs/resolver-binding-linux-riscv64-musl@npm:1.11.1": + version: 1.11.1 + resolution: "@unrs/resolver-binding-linux-riscv64-musl@npm:1.11.1" + conditions: os=linux & cpu=riscv64 & libc=musl + languageName: node + linkType: hard + +"@unrs/resolver-binding-linux-s390x-gnu@npm:1.11.1": + version: 1.11.1 + resolution: "@unrs/resolver-binding-linux-s390x-gnu@npm:1.11.1" conditions: os=linux & cpu=s390x & libc=glibc languageName: node linkType: hard -"@unrs/resolver-binding-linux-x64-gnu@npm:1.3.2": - version: 1.3.2 - resolution: "@unrs/resolver-binding-linux-x64-gnu@npm:1.3.2" +"@unrs/resolver-binding-linux-x64-gnu@npm:1.11.1": + version: 1.11.1 + resolution: "@unrs/resolver-binding-linux-x64-gnu@npm:1.11.1" conditions: os=linux & cpu=x64 & libc=glibc languageName: node linkType: hard -"@unrs/resolver-binding-linux-x64-musl@npm:1.3.2": - version: 1.3.2 - resolution: "@unrs/resolver-binding-linux-x64-musl@npm:1.3.2" +"@unrs/resolver-binding-linux-x64-musl@npm:1.11.1": + version: 1.11.1 + resolution: "@unrs/resolver-binding-linux-x64-musl@npm:1.11.1" conditions: os=linux & cpu=x64 & libc=musl languageName: node linkType: hard -"@unrs/resolver-binding-wasm32-wasi@npm:1.3.2": - version: 1.3.2 - resolution: "@unrs/resolver-binding-wasm32-wasi@npm:1.3.2" +"@unrs/resolver-binding-wasm32-wasi@npm:1.11.1": + version: 1.11.1 + resolution: "@unrs/resolver-binding-wasm32-wasi@npm:1.11.1" dependencies: - "@napi-rs/wasm-runtime": "npm:^0.2.7" + "@napi-rs/wasm-runtime": "npm:^0.2.11" conditions: cpu=wasm32 languageName: node linkType: hard -"@unrs/resolver-binding-win32-arm64-msvc@npm:1.3.2": - version: 1.3.2 - resolution: "@unrs/resolver-binding-win32-arm64-msvc@npm:1.3.2" +"@unrs/resolver-binding-win32-arm64-msvc@npm:1.11.1": + version: 1.11.1 + resolution: "@unrs/resolver-binding-win32-arm64-msvc@npm:1.11.1" conditions: os=win32 & cpu=arm64 languageName: node linkType: hard -"@unrs/resolver-binding-win32-ia32-msvc@npm:1.3.2": - version: 1.3.2 - resolution: "@unrs/resolver-binding-win32-ia32-msvc@npm:1.3.2" +"@unrs/resolver-binding-win32-ia32-msvc@npm:1.11.1": + version: 1.11.1 + resolution: "@unrs/resolver-binding-win32-ia32-msvc@npm:1.11.1" conditions: os=win32 & cpu=ia32 languageName: node linkType: hard -"@unrs/resolver-binding-win32-x64-msvc@npm:1.3.2": - version: 1.3.2 - resolution: "@unrs/resolver-binding-win32-x64-msvc@npm:1.3.2" +"@unrs/resolver-binding-win32-x64-msvc@npm:1.11.1": + version: 1.11.1 + resolution: "@unrs/resolver-binding-win32-x64-msvc@npm:1.11.1" conditions: os=win32 & cpu=x64 languageName: node linkType: hard @@ -5177,17 +5121,19 @@ __metadata: languageName: node linkType: hard -"array-includes@npm:^3.1.6, array-includes@npm:^3.1.8": - version: 3.1.8 - resolution: "array-includes@npm:3.1.8" +"array-includes@npm:^3.1.6, array-includes@npm:^3.1.8, array-includes@npm:^3.1.9": + version: 3.1.9 + resolution: "array-includes@npm:3.1.9" dependencies: - call-bind: "npm:^1.0.7" + call-bind: "npm:^1.0.8" + call-bound: "npm:^1.0.4" define-properties: "npm:^1.2.1" - es-abstract: "npm:^1.23.2" - es-object-atoms: "npm:^1.0.0" - get-intrinsic: "npm:^1.2.4" - is-string: "npm:^1.0.7" - checksum: 10c0/5b1004d203e85873b96ddc493f090c9672fd6c80d7a60b798da8a14bff8a670ff95db5aafc9abc14a211943f05220dacf8ea17638ae0af1a6a47b8c0b48ce370 + es-abstract: "npm:^1.24.0" + es-object-atoms: "npm:^1.1.1" + get-intrinsic: "npm:^1.3.0" + is-string: "npm:^1.1.1" + math-intrinsics: "npm:^1.1.0" + checksum: 10c0/0235fa69078abeac05ac4250699c44996bc6f774a9cbe45db48674ce6bd142f09b327d31482ff75cf03344db4ea03eae23edb862d59378b484b47ed842574856 languageName: node linkType: hard @@ -5212,29 +5158,30 @@ __metadata: languageName: node linkType: hard -"array.prototype.findlastindex@npm:^1.2.5": - version: 1.2.5 - resolution: "array.prototype.findlastindex@npm:1.2.5" +"array.prototype.findlastindex@npm:^1.2.6": + version: 1.2.6 + resolution: "array.prototype.findlastindex@npm:1.2.6" dependencies: - call-bind: "npm:^1.0.7" + call-bind: "npm:^1.0.8" + call-bound: "npm:^1.0.4" define-properties: "npm:^1.2.1" - es-abstract: "npm:^1.23.2" + es-abstract: "npm:^1.23.9" es-errors: "npm:^1.3.0" - es-object-atoms: "npm:^1.0.0" - es-shim-unscopables: "npm:^1.0.2" - checksum: 10c0/962189487728b034f3134802b421b5f39e42ee2356d13b42d2ddb0e52057ffdcc170b9524867f4f0611a6f638f4c19b31e14606e8bcbda67799e26685b195aa3 + es-object-atoms: "npm:^1.1.1" + es-shim-unscopables: "npm:^1.1.0" + checksum: 10c0/82559310d2e57ec5f8fc53d7df420e3abf0ba497935de0a5570586035478ba7d07618cb18e2d4ada2da514c8fb98a034aaf5c06caa0a57e2f7f4c4adedef5956 languageName: node linkType: hard -"array.prototype.flat@npm:^1.3.1, array.prototype.flat@npm:^1.3.2": - version: 1.3.2 - resolution: "array.prototype.flat@npm:1.3.2" +"array.prototype.flat@npm:^1.3.1, array.prototype.flat@npm:^1.3.3": + version: 1.3.3 + resolution: "array.prototype.flat@npm:1.3.3" dependencies: - call-bind: "npm:^1.0.2" - define-properties: "npm:^1.2.0" - es-abstract: "npm:^1.22.1" - es-shim-unscopables: "npm:^1.0.0" - checksum: 10c0/a578ed836a786efbb6c2db0899ae80781b476200617f65a44846cb1ed8bd8b24c8821b83703375d8af639c689497b7b07277060024b9919db94ac3e10dc8a49b + call-bind: "npm:^1.0.8" + define-properties: "npm:^1.2.1" + es-abstract: "npm:^1.23.5" + es-shim-unscopables: "npm:^1.0.2" + checksum: 10c0/d90e04dfbc43bb96b3d2248576753d1fb2298d2d972e29ca7ad5ec621f0d9e16ff8074dae647eac4f31f4fb7d3f561a7ac005fb01a71f51705a13b5af06a7d8a languageName: node linkType: hard @@ -5702,7 +5649,7 @@ __metadata: languageName: node linkType: hard -"call-bind@npm:^1.0.2, call-bind@npm:^1.0.7, call-bind@npm:^1.0.8": +"call-bind@npm:^1.0.7, call-bind@npm:^1.0.8": version: 1.0.8 resolution: "call-bind@npm:1.0.8" dependencies: @@ -5714,7 +5661,7 @@ __metadata: languageName: node linkType: hard -"call-bound@npm:^1.0.2, call-bound@npm:^1.0.3": +"call-bound@npm:^1.0.2, call-bound@npm:^1.0.3, call-bound@npm:^1.0.4": version: 1.0.4 resolution: "call-bound@npm:1.0.4" dependencies: @@ -6384,7 +6331,7 @@ __metadata: languageName: node linkType: hard -"define-properties@npm:^1.1.3, define-properties@npm:^1.2.0, define-properties@npm:^1.2.1": +"define-properties@npm:^1.1.3, define-properties@npm:^1.2.1": version: 1.2.1 resolution: "define-properties@npm:1.2.1" dependencies: @@ -6703,26 +6650,26 @@ __metadata: languageName: node linkType: hard -"es-abstract@npm:^1.17.5, es-abstract@npm:^1.22.1, es-abstract@npm:^1.23.2, es-abstract@npm:^1.23.3, es-abstract@npm:^1.23.5, es-abstract@npm:^1.23.6, es-abstract@npm:^1.23.9": - version: 1.23.9 - resolution: "es-abstract@npm:1.23.9" +"es-abstract@npm:^1.17.5, es-abstract@npm:^1.23.2, es-abstract@npm:^1.23.3, es-abstract@npm:^1.23.5, es-abstract@npm:^1.23.6, es-abstract@npm:^1.23.9, es-abstract@npm:^1.24.0": + version: 1.24.0 + resolution: "es-abstract@npm:1.24.0" dependencies: array-buffer-byte-length: "npm:^1.0.2" arraybuffer.prototype.slice: "npm:^1.0.4" available-typed-arrays: "npm:^1.0.7" call-bind: "npm:^1.0.8" - call-bound: "npm:^1.0.3" + call-bound: "npm:^1.0.4" data-view-buffer: "npm:^1.0.2" data-view-byte-length: "npm:^1.0.2" data-view-byte-offset: "npm:^1.0.1" es-define-property: "npm:^1.0.1" es-errors: "npm:^1.3.0" - es-object-atoms: "npm:^1.0.0" + es-object-atoms: "npm:^1.1.1" es-set-tostringtag: "npm:^2.1.0" es-to-primitive: "npm:^1.3.0" function.prototype.name: "npm:^1.1.8" - get-intrinsic: "npm:^1.2.7" - get-proto: "npm:^1.0.0" + get-intrinsic: "npm:^1.3.0" + get-proto: "npm:^1.0.1" get-symbol-description: "npm:^1.1.0" globalthis: "npm:^1.0.4" gopd: "npm:^1.2.0" @@ -6734,21 +6681,24 @@ __metadata: is-array-buffer: "npm:^3.0.5" is-callable: "npm:^1.2.7" is-data-view: "npm:^1.0.2" + is-negative-zero: "npm:^2.0.3" is-regex: "npm:^1.2.1" + is-set: "npm:^2.0.3" is-shared-array-buffer: "npm:^1.0.4" is-string: "npm:^1.1.1" is-typed-array: "npm:^1.1.15" - is-weakref: "npm:^1.1.0" + is-weakref: "npm:^1.1.1" math-intrinsics: "npm:^1.1.0" - object-inspect: "npm:^1.13.3" + object-inspect: "npm:^1.13.4" object-keys: "npm:^1.1.1" object.assign: "npm:^4.1.7" own-keys: "npm:^1.0.1" - regexp.prototype.flags: "npm:^1.5.3" + regexp.prototype.flags: "npm:^1.5.4" safe-array-concat: "npm:^1.1.3" safe-push-apply: "npm:^1.0.0" safe-regex-test: "npm:^1.1.0" set-proto: "npm:^1.0.0" + stop-iteration-iterator: "npm:^1.1.0" string.prototype.trim: "npm:^1.2.10" string.prototype.trimend: "npm:^1.0.9" string.prototype.trimstart: "npm:^1.0.8" @@ -6757,8 +6707,8 @@ __metadata: typed-array-byte-offset: "npm:^1.0.4" typed-array-length: "npm:^1.0.7" unbox-primitive: "npm:^1.1.0" - which-typed-array: "npm:^1.1.18" - checksum: 10c0/1de229c9e08fe13c17fe5abaec8221545dfcd57e51f64909599a6ae896df84b8fd2f7d16c60cb00d7bf495b9298ca3581aded19939d4b7276854a4b066f8422b + which-typed-array: "npm:^1.1.19" + checksum: 10c0/b256e897be32df5d382786ce8cce29a1dd8c97efbab77a26609bd70f2ed29fbcfc7a31758cb07488d532e7ccccdfca76c1118f2afe5a424cdc05ca007867c318 languageName: node linkType: hard @@ -6828,12 +6778,12 @@ __metadata: languageName: node linkType: hard -"es-shim-unscopables@npm:^1.0.0, es-shim-unscopables@npm:^1.0.2": - version: 1.0.2 - resolution: "es-shim-unscopables@npm:1.0.2" +"es-shim-unscopables@npm:^1.0.2, es-shim-unscopables@npm:^1.1.0": + version: 1.1.0 + resolution: "es-shim-unscopables@npm:1.1.0" dependencies: - hasown: "npm:^2.0.0" - checksum: 10c0/f495af7b4b7601a4c0cfb893581c352636e5c08654d129590386a33a0432cf13a7bdc7b6493801cadd990d838e2839b9013d1de3b880440cb537825e834fe783 + hasown: "npm:^2.0.2" + checksum: 10c0/1b9702c8a1823fc3ef39035a4e958802cf294dd21e917397c561d0b3e195f383b978359816b1732d02b255ccf63e1e4815da0065b95db8d7c992037be3bbbcdb languageName: node linkType: hard @@ -6966,6 +6916,21 @@ __metadata: languageName: node linkType: hard +"eslint-import-context@npm:^0.1.8": + version: 0.1.9 + resolution: "eslint-import-context@npm:0.1.9" + dependencies: + get-tsconfig: "npm:^4.10.1" + stable-hash-x: "npm:^0.2.0" + peerDependencies: + unrs-resolver: ^1.0.0 + peerDependenciesMeta: + unrs-resolver: + optional: true + checksum: 10c0/07851103443b70af681c5988e2702e681ff9b956e055e11d4bd9b2322847fa0d9e8da50c18fc7cb1165106b043f34fbd0384d7011c239465c4645c52132e56f3 + languageName: node + linkType: hard + "eslint-import-resolver-node@npm:^0.3.9": version: 0.3.9 resolution: "eslint-import-resolver-node@npm:0.3.9" @@ -6978,15 +6943,16 @@ __metadata: linkType: hard "eslint-import-resolver-typescript@npm:^4.2.5": - version: 4.2.5 - resolution: "eslint-import-resolver-typescript@npm:4.2.5" + version: 4.4.4 + resolution: "eslint-import-resolver-typescript@npm:4.4.4" dependencies: - debug: "npm:^4.4.0" - get-tsconfig: "npm:^4.10.0" + debug: "npm:^4.4.1" + eslint-import-context: "npm:^0.1.8" + get-tsconfig: "npm:^4.10.1" is-bun-module: "npm:^2.0.0" - stable-hash: "npm:^0.0.5" - tinyglobby: "npm:^0.2.12" - unrs-resolver: "npm:^1.3.2" + stable-hash-x: "npm:^0.2.0" + tinyglobby: "npm:^0.2.14" + unrs-resolver: "npm:^1.7.11" peerDependencies: eslint: "*" eslint-plugin-import: "*" @@ -6996,28 +6962,28 @@ __metadata: optional: true eslint-plugin-import-x: optional: true - checksum: 10c0/9134c4dd6e8b3cf1356d6bff68939153c81255c0ac7f694e829c3c7f5e785936591cfe43209d866c8a3b379d3a8dcd203651ec49bd99361fcb54dc0c2b9ce8fc + checksum: 10c0/3bf8ad77c21660f77a0e455555ab179420f68ae7a132906c85a217ccce51cb6680cf70027cab32a358d193e5b9e476f6ba2e595585242aa97d4f6435ca22104e languageName: node linkType: hard -"eslint-module-utils@npm:^2.12.0": - version: 2.12.0 - resolution: "eslint-module-utils@npm:2.12.0" +"eslint-module-utils@npm:^2.12.1": + version: 2.12.1 + resolution: "eslint-module-utils@npm:2.12.1" dependencies: debug: "npm:^3.2.7" peerDependenciesMeta: eslint: optional: true - checksum: 10c0/4d8b46dcd525d71276f9be9ffac1d2be61c9d54cc53c992e6333cf957840dee09381842b1acbbb15fc6b255ebab99cd481c5007ab438e5455a14abe1a0468558 + checksum: 10c0/6f4efbe7a91ae49bf67b4ab3644cb60bc5bd7db4cb5521de1b65be0847ffd3fb6bce0dd68f0995e1b312d137f768e2a1f842ee26fe73621afa05f850628fdc40 languageName: node linkType: hard "eslint-plugin-formatjs@npm:^5.3.1": - version: 5.3.1 - resolution: "eslint-plugin-formatjs@npm:5.3.1" + version: 5.4.0 + resolution: "eslint-plugin-formatjs@npm:5.4.0" dependencies: "@formatjs/icu-messageformat-parser": "npm:2.11.2" - "@formatjs/ts-transformer": "npm:3.13.34" + "@formatjs/ts-transformer": "npm:3.14.0" "@types/eslint": "npm:^9.6.1" "@types/picomatch": "npm:^3" "@typescript-eslint/utils": "npm:^8.27.0" @@ -7027,42 +6993,42 @@ __metadata: unicode-emoji-utils: "npm:^1.2.0" peerDependencies: eslint: ^9.23.0 - checksum: 10c0/fb8ba06e0718cd098f2393aea04eb4a6037ca3ead1c9450bd38926d0adecba4cefdebfb661c56c36685e0f003331520c3330544c45803f397b827713ab5e1d7d + checksum: 10c0/5c74a53988df68ffed4e68bb58a4ee75cdcd92b7d94f699e2edbcdd8c2c45930f500c7211da0a4616714d7d83bbbdc105328e5aacf0c9c7582a78fdfc9fa2b55 languageName: node linkType: hard -"eslint-plugin-import@npm:~2.31.0": - version: 2.31.0 - resolution: "eslint-plugin-import@npm:2.31.0" +"eslint-plugin-import@npm:~2.32.0": + version: 2.32.0 + resolution: "eslint-plugin-import@npm:2.32.0" dependencies: "@rtsao/scc": "npm:^1.1.0" - array-includes: "npm:^3.1.8" - array.prototype.findlastindex: "npm:^1.2.5" - array.prototype.flat: "npm:^1.3.2" - array.prototype.flatmap: "npm:^1.3.2" + array-includes: "npm:^3.1.9" + array.prototype.findlastindex: "npm:^1.2.6" + array.prototype.flat: "npm:^1.3.3" + array.prototype.flatmap: "npm:^1.3.3" debug: "npm:^3.2.7" doctrine: "npm:^2.1.0" eslint-import-resolver-node: "npm:^0.3.9" - eslint-module-utils: "npm:^2.12.0" + eslint-module-utils: "npm:^2.12.1" hasown: "npm:^2.0.2" - is-core-module: "npm:^2.15.1" + is-core-module: "npm:^2.16.1" is-glob: "npm:^4.0.3" minimatch: "npm:^3.1.2" object.fromentries: "npm:^2.0.8" object.groupby: "npm:^1.0.3" - object.values: "npm:^1.2.0" + object.values: "npm:^1.2.1" semver: "npm:^6.3.1" - string.prototype.trimend: "npm:^1.0.8" + string.prototype.trimend: "npm:^1.0.9" tsconfig-paths: "npm:^3.15.0" peerDependencies: eslint: ^2 || ^3 || ^4 || ^5 || ^6 || ^7.2.0 || ^8 || ^9 - checksum: 10c0/e21d116ddd1900e091ad120b3eb68c5dd5437fe2c930f1211781cd38b246f090a6b74d5f3800b8255a0ed29782591521ad44eb21c5534960a8f1fb4040fd913a + checksum: 10c0/bfb1b8fc8800398e62ddfefbf3638d185286edfed26dfe00875cc2846d954491b4f5112457831588b757fa789384e1ae585f812614c4797f0499fa234fd4a48b languageName: node linkType: hard "eslint-plugin-jsdoc@npm:^52.0.0": - version: 52.0.1 - resolution: "eslint-plugin-jsdoc@npm:52.0.1" + version: 52.0.2 + resolution: "eslint-plugin-jsdoc@npm:52.0.2" dependencies: "@es-joy/jsdoccomment": "npm:~0.52.0" are-docs-informative: "npm:^0.0.2" @@ -7076,7 +7042,7 @@ __metadata: spdx-expression-parse: "npm:^4.0.0" peerDependencies: eslint: ^7.0.0 || ^8.0.0 || ^9.0.0 - checksum: 10c0/0dac74a5ea1db8d15eea5a29a6dadd1361029230f414794abfd143b8cd0129d1cd862481d31eb0374b215d0841f41209fb8b4e36ac69b758094d7c77052432c0 + checksum: 10c0/e36d8c75a5a100f71f4f5287ce12ffdf15474194b2877dbe1e06c3c24a1c0c0c7f13c2d92cb289a80515b6fe1e43c4c0b19814b5c5b22a46ac2ca7df23ab55ad languageName: node linkType: hard @@ -7126,8 +7092,8 @@ __metadata: linkType: hard "eslint-plugin-react@npm:^7.37.4": - version: 7.37.4 - resolution: "eslint-plugin-react@npm:7.37.4" + version: 7.37.5 + resolution: "eslint-plugin-react@npm:7.37.5" dependencies: array-includes: "npm:^3.1.8" array.prototype.findlast: "npm:^1.2.5" @@ -7139,7 +7105,7 @@ __metadata: hasown: "npm:^2.0.2" jsx-ast-utils: "npm:^2.4.1 || ^3.0.0" minimatch: "npm:^3.1.2" - object.entries: "npm:^1.1.8" + object.entries: "npm:^1.1.9" object.fromentries: "npm:^2.0.8" object.values: "npm:^1.2.1" prop-types: "npm:^15.8.1" @@ -7149,29 +7115,29 @@ __metadata: string.prototype.repeat: "npm:^1.0.0" peerDependencies: eslint: ^3 || ^4 || ^5 || ^6 || ^7 || ^8 || ^9.7 - checksum: 10c0/4acbbdb19669dfa9a162ed8847c3ad1918f6aea1ceb675ee320b5d903b4e463fdef25e15233295b6d0a726fef2ea8b015c527da769c7690932ddc52d5b82ba12 + checksum: 10c0/c850bfd556291d4d9234f5ca38db1436924a1013627c8ab1853f77cac73ec19b020e861e6c7b783436a48b6ffcdfba4547598235a37ad4611b6739f65fd8ad57 languageName: node linkType: hard "eslint-plugin-storybook@npm:^9.0.4": - version: 9.0.4 - resolution: "eslint-plugin-storybook@npm:9.0.4" + version: 9.1.1 + resolution: "eslint-plugin-storybook@npm:9.1.1" dependencies: "@typescript-eslint/utils": "npm:^8.8.1" peerDependencies: eslint: ">=8" - storybook: ^9.0.4 - checksum: 10c0/b5dbcd15feab63d71f4bd5da26306043339620ddf64bb623de3a7542ee81828b4137af93e199c3e49fb0e5a76d582a21fb580626011ae2340dd6fc684f438358 + storybook: ^9.1.1 + checksum: 10c0/4cf80aa078633021b153a3a5b790a39c9919b5fa7203727c15d8ae066e75d6e134d7d718e66a6a5db9815275f32942a2deae1979aeb36be2543572507faced2c languageName: node linkType: hard -"eslint-scope@npm:^8.3.0": - version: 8.3.0 - resolution: "eslint-scope@npm:8.3.0" +"eslint-scope@npm:^8.4.0": + version: 8.4.0 + resolution: "eslint-scope@npm:8.4.0" dependencies: esrecurse: "npm:^4.3.0" estraverse: "npm:^5.2.0" - checksum: 10c0/23bf54345573201fdf06d29efa345ab508b355492f6c6cc9e2b9f6d02b896f369b6dd5315205be94b8853809776c4d13353b85c6b531997b164ff6c3328ecf5b + checksum: 10c0/407f6c600204d0f3705bd557f81bd0189e69cd7996f408f8971ab5779c0af733d1af2f1412066b40ee1588b085874fc37a2333986c6521669cdbdd36ca5058e0 languageName: node linkType: hard @@ -7182,7 +7148,7 @@ __metadata: languageName: node linkType: hard -"eslint-visitor-keys@npm:^4.2.0, eslint-visitor-keys@npm:^4.2.1": +"eslint-visitor-keys@npm:^4.2.1": version: 4.2.1 resolution: "eslint-visitor-keys@npm:4.2.1" checksum: 10c0/fcd43999199d6740db26c58dbe0c2594623e31ca307e616ac05153c9272f12f1364f5a0b1917a8e962268fdecc6f3622c1c2908b4fcc2e047a106fe6de69dc43 @@ -7190,17 +7156,17 @@ __metadata: linkType: hard "eslint@npm:^9.23.0": - version: 9.23.0 - resolution: "eslint@npm:9.23.0" + version: 9.32.0 + resolution: "eslint@npm:9.32.0" dependencies: "@eslint-community/eslint-utils": "npm:^4.2.0" "@eslint-community/regexpp": "npm:^4.12.1" - "@eslint/config-array": "npm:^0.19.2" - "@eslint/config-helpers": "npm:^0.2.0" - "@eslint/core": "npm:^0.12.0" + "@eslint/config-array": "npm:^0.21.0" + "@eslint/config-helpers": "npm:^0.3.0" + "@eslint/core": "npm:^0.15.0" "@eslint/eslintrc": "npm:^3.3.1" - "@eslint/js": "npm:9.23.0" - "@eslint/plugin-kit": "npm:^0.2.7" + "@eslint/js": "npm:9.32.0" + "@eslint/plugin-kit": "npm:^0.3.4" "@humanfs/node": "npm:^0.16.6" "@humanwhocodes/module-importer": "npm:^1.0.1" "@humanwhocodes/retry": "npm:^0.4.2" @@ -7211,9 +7177,9 @@ __metadata: cross-spawn: "npm:^7.0.6" debug: "npm:^4.3.2" escape-string-regexp: "npm:^4.0.0" - eslint-scope: "npm:^8.3.0" - eslint-visitor-keys: "npm:^4.2.0" - espree: "npm:^10.3.0" + eslint-scope: "npm:^8.4.0" + eslint-visitor-keys: "npm:^4.2.1" + espree: "npm:^10.4.0" esquery: "npm:^1.5.0" esutils: "npm:^2.0.2" fast-deep-equal: "npm:^3.1.3" @@ -7235,11 +7201,11 @@ __metadata: optional: true bin: eslint: bin/eslint.js - checksum: 10c0/9616c308dfa8d09db8ae51019c87d5d05933742214531b077bd6ab618baab3bec7938256c14dcad4dc47f5ba93feb0bc5e089f68799f076374ddea21b6a9be45 + checksum: 10c0/e8a23924ec5f8b62e95483002ca25db74e25c23bd9c6d98a9f656ee32f820169bee3bfdf548ec728b16694f198b3db857d85a49210ee4a035242711d08fdc602 languageName: node linkType: hard -"espree@npm:^10.0.1, espree@npm:^10.3.0, espree@npm:^10.4.0": +"espree@npm:^10.0.1, espree@npm:^10.4.0": version: 10.4.0 resolution: "espree@npm:10.4.0" dependencies: @@ -7592,12 +7558,12 @@ __metadata: languageName: node linkType: hard -"for-each@npm:^0.3.3": - version: 0.3.3 - resolution: "for-each@npm:0.3.3" +"for-each@npm:^0.3.3, for-each@npm:^0.3.5": + version: 0.3.5 + resolution: "for-each@npm:0.3.5" dependencies: - is-callable: "npm:^1.1.3" - checksum: 10c0/22330d8a2db728dbf003ec9182c2d421fbcd2969b02b4f97ec288721cda63eb28f2c08585ddccd0f77cb2930af8d958005c9e72f47141dc51816127a118f39aa + is-callable: "npm:^1.2.7" + checksum: 10c0/0e0b50f6a843a282637d43674d1fb278dda1dd85f4f99b640024cfb10b85058aac0cc781bf689d5fe50b4b7f638e91e548560723a4e76e04fe96ae35ef039cee languageName: node linkType: hard @@ -7833,12 +7799,12 @@ __metadata: languageName: node linkType: hard -"get-tsconfig@npm:^4.10.0": - version: 4.10.0 - resolution: "get-tsconfig@npm:4.10.0" +"get-tsconfig@npm:^4.10.1": + version: 4.10.1 + resolution: "get-tsconfig@npm:4.10.1" dependencies: resolve-pkg-maps: "npm:^1.0.0" - checksum: 10c0/c9b5572c5118923c491c04285c73bd55b19e214992af957c502a3be0fc0043bb421386ffd45ca3433c0a7fba81221ca300479e8393960acf15d0ed4563f38a86 + checksum: 10c0/7f8e3dabc6a49b747920a800fb88e1952fef871cdf51b79e98db48275a5de6cdaf499c55ee67df5fa6fe7ce65f0063e26de0f2e53049b408c585aa74d39ffa21 languageName: node linkType: hard @@ -7925,9 +7891,9 @@ __metadata: linkType: hard "globals@npm:^16.0.0": - version: 16.0.0 - resolution: "globals@npm:16.0.0" - checksum: 10c0/8906d5f01838df64a81d6c2a7b7214312e2216cf65c5ed1546dc9a7d0febddf55ffa906cf04efd5b01eec2534d6f14859a89535d1a68241832810e41ef3fd5bb + version: 16.3.0 + resolution: "globals@npm:16.3.0" + checksum: 10c0/c62dc20357d1c0bf2be4545d6c4141265d1a229bf1c3294955efb5b5ef611145391895e3f2729f8603809e81b30b516c33e6c2597573844449978606aad6eb38 languageName: node linkType: hard @@ -8045,7 +8011,7 @@ __metadata: languageName: node linkType: hard -"hasown@npm:^2.0.0, hasown@npm:^2.0.2": +"hasown@npm:^2.0.2": version: 2.0.2 resolution: "hasown@npm:2.0.2" dependencies: @@ -8223,17 +8189,17 @@ __metadata: languageName: node linkType: hard -"ignore@npm:^5.2.0, ignore@npm:^5.3.1": +"ignore@npm:^5.2.0": version: 5.3.2 resolution: "ignore@npm:5.3.2" checksum: 10c0/f9f652c957983634ded1e7f02da3b559a0d4cc210fca3792cb67f1b153623c9c42efdc1c4121af171e295444459fc4a9201101fb041b1104a3c000bccb188337 languageName: node linkType: hard -"ignore@npm:^7.0.3": - version: 7.0.4 - resolution: "ignore@npm:7.0.4" - checksum: 10c0/90e1f69ce352b9555caecd9cbfd07abe7626d312a6f90efbbb52c7edca6ea8df065d66303863b30154ab1502afb2da8bc59d5b04e1719a52ef75bbf675c488eb +"ignore@npm:^7.0.0, ignore@npm:^7.0.3": + version: 7.0.5 + resolution: "ignore@npm:7.0.5" + checksum: 10c0/ae00db89fe873064a093b8999fe4cc284b13ef2a178636211842cceb650b9c3e390d3339191acb145d81ed5379d2074840cf0c33a20bdbd6f32821f79eb4ad5d languageName: node linkType: hard @@ -8447,14 +8413,14 @@ __metadata: languageName: node linkType: hard -"is-callable@npm:^1.1.3, is-callable@npm:^1.2.7": +"is-callable@npm:^1.2.7": version: 1.2.7 resolution: "is-callable@npm:1.2.7" checksum: 10c0/ceebaeb9d92e8adee604076971dd6000d38d6afc40bb843ea8e45c5579b57671c3f3b50d7f04869618242c6cee08d1b67806a8cb8edaaaf7c0748b3720d6066f languageName: node linkType: hard -"is-core-module@npm:^2.13.0, is-core-module@npm:^2.15.1, is-core-module@npm:^2.16.0": +"is-core-module@npm:^2.13.0, is-core-module@npm:^2.16.0, is-core-module@npm:^2.16.1": version: 2.16.1 resolution: "is-core-module@npm:2.16.1" dependencies: @@ -8571,6 +8537,13 @@ __metadata: languageName: node linkType: hard +"is-negative-zero@npm:^2.0.3": + version: 2.0.3 + resolution: "is-negative-zero@npm:2.0.3" + checksum: 10c0/bcdcf6b8b9714063ffcfa9929c575ac69bfdabb8f4574ff557dfc086df2836cf07e3906f5bbc4f2a5c12f8f3ba56af640c843cdfc74da8caed86c7c7d66fd08e + languageName: node + linkType: hard + "is-node-process@npm:^1.0.1, is-node-process@npm:^1.2.0": version: 1.2.0 resolution: "is-node-process@npm:1.2.0" @@ -8658,7 +8631,7 @@ __metadata: languageName: node linkType: hard -"is-string@npm:^1.0.7, is-string@npm:^1.1.1": +"is-string@npm:^1.1.1": version: 1.1.1 resolution: "is-string@npm:1.1.1" dependencies: @@ -8702,7 +8675,7 @@ __metadata: languageName: node linkType: hard -"is-weakref@npm:^1.0.2, is-weakref@npm:^1.1.0": +"is-weakref@npm:^1.0.2, is-weakref@npm:^1.1.1": version: 1.1.1 resolution: "is-weakref@npm:1.1.1" dependencies: @@ -9697,6 +9670,15 @@ __metadata: languageName: node linkType: hard +"napi-postinstall@npm:^0.3.0": + version: 0.3.2 + resolution: "napi-postinstall@npm:0.3.2" + bin: + napi-postinstall: lib/cli.js + checksum: 10c0/77c67eb9871d24afe7bad30e6115c441d099d6a0e42dc1c49c4a722ff682425e08dc6dd2b03eca10db9b547e724c38fb51325c35039e7ac10dcb714bb88d7326 + languageName: node + linkType: hard + "natural-compare@npm:^1.4.0": version: 1.4.0 resolution: "natural-compare@npm:1.4.0" @@ -9821,7 +9803,7 @@ __metadata: languageName: node linkType: hard -"object-inspect@npm:^1.13.3": +"object-inspect@npm:^1.13.3, object-inspect@npm:^1.13.4": version: 1.13.4 resolution: "object-inspect@npm:1.13.4" checksum: 10c0/d7f8711e803b96ea3191c745d6f8056ce1f2496e530e6a19a0e92d89b0fa3c76d910c31f0aa270432db6bd3b2f85500a376a83aaba849a8d518c8845b3211692 @@ -9849,14 +9831,15 @@ __metadata: languageName: node linkType: hard -"object.entries@npm:^1.1.8": - version: 1.1.8 - resolution: "object.entries@npm:1.1.8" +"object.entries@npm:^1.1.9": + version: 1.1.9 + resolution: "object.entries@npm:1.1.9" dependencies: - call-bind: "npm:^1.0.7" + call-bind: "npm:^1.0.8" + call-bound: "npm:^1.0.4" define-properties: "npm:^1.2.1" - es-object-atoms: "npm:^1.0.0" - checksum: 10c0/db9ea979d2956a3bc26c262da4a4d212d36f374652cc4c13efdd069c1a519c16571c137e2893d1c46e1cb0e15c88fd6419eaf410c945f329f09835487d7e65d3 + es-object-atoms: "npm:^1.1.1" + checksum: 10c0/d4b8c1e586650407da03370845f029aa14076caca4e4d4afadbc69cfb5b78035fd3ee7be417141abdb0258fa142e59b11923b4c44d8b1255b28f5ffcc50da7db languageName: node linkType: hard @@ -9883,7 +9866,7 @@ __metadata: languageName: node linkType: hard -"object.values@npm:^1.1.6, object.values@npm:^1.2.0, object.values@npm:^1.2.1": +"object.values@npm:^1.1.6, object.values@npm:^1.2.1": version: 1.2.1 resolution: "object.values@npm:1.2.1" dependencies: @@ -11614,7 +11597,7 @@ __metadata: languageName: node linkType: hard -"regexp.prototype.flags@npm:^1.5.3": +"regexp.prototype.flags@npm:^1.5.3, regexp.prototype.flags@npm:^1.5.4": version: 1.5.4 resolution: "regexp.prototype.flags@npm:1.5.4" dependencies: @@ -12456,10 +12439,10 @@ __metadata: languageName: node linkType: hard -"stable-hash@npm:^0.0.5": - version: 0.0.5 - resolution: "stable-hash@npm:0.0.5" - checksum: 10c0/ca670cb6d172f1c834950e4ec661e2055885df32fee3ebf3647c5df94993b7c2666a5dbc1c9a62ee11fc5c24928579ec5e81bb5ad31971d355d5a341aab493b3 +"stable-hash-x@npm:^0.2.0": + version: 0.2.0 + resolution: "stable-hash-x@npm:0.2.0" + checksum: 10c0/c757df58366ee4bb266a9486b8932eab7c1ba730469eaf4b68d2dee404814e9f84089c44c9b5205f8c7d99a0ab036cce2af69139ce5ed44b635923c011a8aea8 languageName: node linkType: hard @@ -12535,6 +12518,16 @@ __metadata: languageName: node linkType: hard +"stop-iteration-iterator@npm:^1.1.0": + version: 1.1.0 + resolution: "stop-iteration-iterator@npm:1.1.0" + dependencies: + es-errors: "npm:^1.3.0" + internal-slot: "npm:^1.1.0" + checksum: 10c0/de4e45706bb4c0354a4b1122a2b8cc45a639e86206807ce0baf390ee9218d3ef181923fa4d2b67443367c491aa255c5fbaa64bb74648e3c5b48299928af86c09 + languageName: node + linkType: hard + "storybook@npm:^9.0.4": version: 9.0.4 resolution: "storybook@npm:9.0.4" @@ -12665,7 +12658,7 @@ __metadata: languageName: node linkType: hard -"string.prototype.trimend@npm:^1.0.8, string.prototype.trimend@npm:^1.0.9": +"string.prototype.trimend@npm:^1.0.9": version: 1.0.9 resolution: "string.prototype.trimend@npm:1.0.9" dependencies: @@ -13112,7 +13105,7 @@ __metadata: languageName: node linkType: hard -"tinyglobby@npm:^0.2.10, tinyglobby@npm:^0.2.12, tinyglobby@npm:^0.2.13, tinyglobby@npm:^0.2.14": +"tinyglobby@npm:^0.2.10, tinyglobby@npm:^0.2.13, tinyglobby@npm:^0.2.14": version: 0.2.14 resolution: "tinyglobby@npm:0.2.14" dependencies: @@ -13244,7 +13237,7 @@ __metadata: languageName: node linkType: hard -"ts-api-utils@npm:^2.0.1, ts-api-utils@npm:^2.1.0": +"ts-api-utils@npm:^2.1.0": version: 2.1.0 resolution: "ts-api-utils@npm:2.1.0" peerDependencies: @@ -13417,16 +13410,17 @@ __metadata: linkType: hard "typescript-eslint@npm:^8.28.0, typescript-eslint@npm:^8.29.1": - version: 8.29.1 - resolution: "typescript-eslint@npm:8.29.1" + version: 8.38.0 + resolution: "typescript-eslint@npm:8.38.0" dependencies: - "@typescript-eslint/eslint-plugin": "npm:8.29.1" - "@typescript-eslint/parser": "npm:8.29.1" - "@typescript-eslint/utils": "npm:8.29.1" + "@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" peerDependencies: eslint: ^8.57.0 || ^9.0.0 typescript: ">=4.8.4 <5.9.0" - checksum: 10c0/31319c891d224ec8d7cf96ad7e6c84480b3d17d4c46c5beccca06fc7891f41eabd5593e44867e69dbfb79459f5545c2cc2e985c950bdd7b4e7c3bb1ec8941030 + checksum: 10c0/486b9862ee08f7827d808a2264ce03b58087b11c4c646c0da3533c192a67ae3fcb4e68d7a1e69d0f35a1edc274371a903a50ecfe74012d5eaa896cb9d5a81e0b languageName: node linkType: hard @@ -13601,26 +13595,35 @@ __metadata: languageName: node linkType: hard -"unrs-resolver@npm:^1.3.2": - version: 1.3.2 - resolution: "unrs-resolver@npm:1.3.2" +"unrs-resolver@npm:^1.7.11": + version: 1.11.1 + resolution: "unrs-resolver@npm:1.11.1" dependencies: - "@unrs/resolver-binding-darwin-arm64": "npm:1.3.2" - "@unrs/resolver-binding-darwin-x64": "npm:1.3.2" - "@unrs/resolver-binding-freebsd-x64": "npm:1.3.2" - "@unrs/resolver-binding-linux-arm-gnueabihf": "npm:1.3.2" - "@unrs/resolver-binding-linux-arm-musleabihf": "npm:1.3.2" - "@unrs/resolver-binding-linux-arm64-gnu": "npm:1.3.2" - "@unrs/resolver-binding-linux-arm64-musl": "npm:1.3.2" - "@unrs/resolver-binding-linux-ppc64-gnu": "npm:1.3.2" - "@unrs/resolver-binding-linux-s390x-gnu": "npm:1.3.2" - "@unrs/resolver-binding-linux-x64-gnu": "npm:1.3.2" - "@unrs/resolver-binding-linux-x64-musl": "npm:1.3.2" - "@unrs/resolver-binding-wasm32-wasi": "npm:1.3.2" - "@unrs/resolver-binding-win32-arm64-msvc": "npm:1.3.2" - "@unrs/resolver-binding-win32-ia32-msvc": "npm:1.3.2" - "@unrs/resolver-binding-win32-x64-msvc": "npm:1.3.2" + "@unrs/resolver-binding-android-arm-eabi": "npm:1.11.1" + "@unrs/resolver-binding-android-arm64": "npm:1.11.1" + "@unrs/resolver-binding-darwin-arm64": "npm:1.11.1" + "@unrs/resolver-binding-darwin-x64": "npm:1.11.1" + "@unrs/resolver-binding-freebsd-x64": "npm:1.11.1" + "@unrs/resolver-binding-linux-arm-gnueabihf": "npm:1.11.1" + "@unrs/resolver-binding-linux-arm-musleabihf": "npm:1.11.1" + "@unrs/resolver-binding-linux-arm64-gnu": "npm:1.11.1" + "@unrs/resolver-binding-linux-arm64-musl": "npm:1.11.1" + "@unrs/resolver-binding-linux-ppc64-gnu": "npm:1.11.1" + "@unrs/resolver-binding-linux-riscv64-gnu": "npm:1.11.1" + "@unrs/resolver-binding-linux-riscv64-musl": "npm:1.11.1" + "@unrs/resolver-binding-linux-s390x-gnu": "npm:1.11.1" + "@unrs/resolver-binding-linux-x64-gnu": "npm:1.11.1" + "@unrs/resolver-binding-linux-x64-musl": "npm:1.11.1" + "@unrs/resolver-binding-wasm32-wasi": "npm:1.11.1" + "@unrs/resolver-binding-win32-arm64-msvc": "npm:1.11.1" + "@unrs/resolver-binding-win32-ia32-msvc": "npm:1.11.1" + "@unrs/resolver-binding-win32-x64-msvc": "npm:1.11.1" + napi-postinstall: "npm:^0.3.0" dependenciesMeta: + "@unrs/resolver-binding-android-arm-eabi": + optional: true + "@unrs/resolver-binding-android-arm64": + optional: true "@unrs/resolver-binding-darwin-arm64": optional: true "@unrs/resolver-binding-darwin-x64": @@ -13637,6 +13640,10 @@ __metadata: optional: true "@unrs/resolver-binding-linux-ppc64-gnu": optional: true + "@unrs/resolver-binding-linux-riscv64-gnu": + optional: true + "@unrs/resolver-binding-linux-riscv64-musl": + optional: true "@unrs/resolver-binding-linux-s390x-gnu": optional: true "@unrs/resolver-binding-linux-x64-gnu": @@ -13651,7 +13658,7 @@ __metadata: optional: true "@unrs/resolver-binding-win32-x64-msvc": optional: true - checksum: 10c0/f9b6d18193bcaae7ef9e284a74c85d4cb3d8c833851f1b23254a947297e672826223d82798dbff818455fefeda02084340aca904300fd5060468c2f243767cc1 + checksum: 10c0/c91b112c71a33d6b24e5c708dab43ab80911f2df8ee65b87cd7a18fb5af446708e98c4b415ca262026ad8df326debcc7ca6a801b2935504d87fd6f0b9d70dce1 languageName: node linkType: hard @@ -14148,17 +14155,18 @@ __metadata: languageName: node linkType: hard -"which-typed-array@npm:^1.1.16, which-typed-array@npm:^1.1.18": - version: 1.1.18 - resolution: "which-typed-array@npm:1.1.18" +"which-typed-array@npm:^1.1.16, which-typed-array@npm:^1.1.19": + version: 1.1.19 + resolution: "which-typed-array@npm:1.1.19" dependencies: available-typed-arrays: "npm:^1.0.7" call-bind: "npm:^1.0.8" - call-bound: "npm:^1.0.3" - for-each: "npm:^0.3.3" + call-bound: "npm:^1.0.4" + for-each: "npm:^0.3.5" + get-proto: "npm:^1.0.1" gopd: "npm:^1.2.0" has-tostringtag: "npm:^1.0.2" - checksum: 10c0/0412f4a91880ca1a2a63056187c2e3de6b129b2b5b6c17bc3729f0f7041047ae48fb7424813e51506addb2c97320003ee18b8c57469d2cde37983ef62126143c + checksum: 10c0/702b5dc878addafe6c6300c3d0af5983b175c75fcb4f2a72dfc3dd38d93cf9e89581e4b29c854b16ea37e50a7d7fca5ae42ece5c273d8060dcd603b2404bbb3f languageName: node linkType: hard From 0153a239dbecd59df6b36c5469f85a340daf4dc1 Mon Sep 17 00:00:00 2001 From: Claire Date: Mon, 4 Aug 2025 16:34:05 +0200 Subject: [PATCH 17/23] Avoid nested transactions when fetching quote posts (#35657) --- app/lib/activitypub/activity/create.rb | 15 ++++++++++----- .../activitypub/process_status_update_service.rb | 6 ++++-- 2 files changed, 14 insertions(+), 7 deletions(-) diff --git a/app/lib/activitypub/activity/create.rb b/app/lib/activitypub/activity/create.rb index 9db7ec1a150..c47c2afc523 100644 --- a/app/lib/activitypub/activity/create.rb +++ b/app/lib/activitypub/activity/create.rb @@ -66,6 +66,7 @@ class ActivityPub::Activity::Create < ActivityPub::Activity resolve_thread(@status) resolve_unresolved_mentions(@status) fetch_replies(@status) + fetch_and_verify_quote distribute forward_for_reply end @@ -206,11 +207,6 @@ class ActivityPub::Activity::Create < ActivityPub::Activity @quote.status = status @quote.save - - embedded_quote = safe_prefetched_embed(@account, @status_parser.quoted_object, @json['context']) - ActivityPub::VerifyQuoteService.new.call(@quote, fetchable_quoted_uri: @quote_uri, prefetched_quoted_object: embedded_quote, request_id: @options[:request_id], depth: @options[:depth]) - rescue Mastodon::RecursionLimitExceededError, Mastodon::UnexpectedResponseError, *Mastodon::HTTP_CONNECTION_ERRORS - ActivityPub::RefetchAndVerifyQuoteWorker.perform_in(rand(30..600).seconds, @quote.id, @quote_uri, { 'request_id' => @options[:request_id] }) end def process_tags @@ -380,6 +376,15 @@ class ActivityPub::Activity::Create < ActivityPub::Activity Rails.logger.warn "Error fetching replies: #{e}" end + def fetch_and_verify_quote + return if @quote.nil? + + embedded_quote = safe_prefetched_embed(@account, @status_parser.quoted_object, @json['context']) + ActivityPub::VerifyQuoteService.new.call(@quote, fetchable_quoted_uri: @quote_uri, prefetched_quoted_object: embedded_quote, request_id: @options[:request_id], depth: @options[:depth]) + rescue Mastodon::RecursionLimitExceededError, Mastodon::UnexpectedResponseError, *Mastodon::HTTP_CONNECTION_ERRORS + ActivityPub::RefetchAndVerifyQuoteWorker.perform_in(rand(30..600).seconds, @quote.id, @quote_uri, { 'request_id' => @options[:request_id] }) + end + def conversation_from_uri(uri) return nil if uri.nil? return Conversation.find_by(id: OStatus::TagManager.instance.unique_tag_to_local_id(uri, 'Conversation')) if OStatus::TagManager.instance.local_id?(uri) diff --git a/app/services/activitypub/process_status_update_service.rb b/app/services/activitypub/process_status_update_service.rb index 0ada876d890..023eef19a02 100644 --- a/app/services/activitypub/process_status_update_service.rb +++ b/app/services/activitypub/process_status_update_service.rb @@ -18,6 +18,7 @@ class ActivityPub::ProcessStatusUpdateService < BaseService @poll_changed = false @quote_changed = false @request_id = request_id + @quote = nil # Only native types can be updated at the moment return @status if !expected_type? || already_updated_more_recently? @@ -49,6 +50,7 @@ class ActivityPub::ProcessStatusUpdateService < BaseService create_edits! end + fetch_and_verify_quote!(@quote, @status_parser.quote_uri) if @quote.present? download_media_files! queue_poll_notifications! @@ -312,10 +314,10 @@ class ActivityPub::ProcessStatusUpdateService < BaseService @quote_changed = true end + @quote = quote quote.save - - fetch_and_verify_quote!(quote, quote_uri) elsif @status.quote.present? + @quote = nil @status.quote.destroy! @quote_changed = true end From 32791c97456ad88940b656a3432f6207cf96b807 Mon Sep 17 00:00:00 2001 From: Claire Date: Mon, 4 Aug 2025 17:27:46 +0200 Subject: [PATCH 18/23] Accept remote quotes of local quotes according to set policy (#35629) --- app/lib/activitypub/activity/quote_request.rb | 23 ++++++++++- .../accept_quote_request_serializer.rb | 23 +++++++++++ .../activitypub/quote_request_serializer.rb | 1 + .../activity/quote_request_spec.rb | 41 ++++++++++++++++++- .../accept_quote_request_serializer_spec.rb | 25 +++++++++++ 5 files changed, 110 insertions(+), 3 deletions(-) create mode 100644 app/serializers/activitypub/accept_quote_request_serializer.rb create mode 100644 spec/serializers/activitypub/accept_quote_request_serializer_spec.rb diff --git a/app/lib/activitypub/activity/quote_request.rb b/app/lib/activitypub/activity/quote_request.rb index 2de03df1580..40a38b09d36 100644 --- a/app/lib/activitypub/activity/quote_request.rb +++ b/app/lib/activitypub/activity/quote_request.rb @@ -9,12 +9,31 @@ class ActivityPub::Activity::QuoteRequest < ActivityPub::Activity quoted_status = status_from_uri(object_uri) return if quoted_status.nil? || !quoted_status.account.local? || !quoted_status.distributable? - # For now, we don't support being quoted by external servers - reject_quote_request!(quoted_status) + if Mastodon::Feature.outgoing_quotes_enabled? && StatusPolicy.new(@account, quoted_status).quote? + accept_quote_request!(quoted_status) + else + reject_quote_request!(quoted_status) + end end private + def accept_quote_request!(quoted_status) + status = status_from_uri(@json['instrument']) + # TODO: import inlined quote post if possible + status ||= ActivityPub::FetchRemoteStatusService.new.call(@json['instrument'], on_behalf_of: @account.followers.local.first, request_id: @options[:request_id]) + # TODO: raise if status is nil + + # Sanity check + return unless status.quote.quoted_status == quoted_status + + status.quote.update!(activity_uri: @json['id']) + status.quote.accept! + + json = Oj.dump(serialize_payload(status.quote, ActivityPub::AcceptQuoteRequestSerializer)) + ActivityPub::DeliveryWorker.perform_async(json, quoted_status.account_id, @account.inbox_url) + end + def reject_quote_request!(quoted_status) quote = Quote.new( quoted_status: quoted_status, diff --git a/app/serializers/activitypub/accept_quote_request_serializer.rb b/app/serializers/activitypub/accept_quote_request_serializer.rb new file mode 100644 index 00000000000..26ecd099b64 --- /dev/null +++ b/app/serializers/activitypub/accept_quote_request_serializer.rb @@ -0,0 +1,23 @@ +# frozen_string_literal: true + +class ActivityPub::AcceptQuoteRequestSerializer < ActivityPub::Serializer + attributes :id, :type, :actor, :result + + has_one :object, serializer: ActivityPub::QuoteRequestSerializer + + def id + [ActivityPub::TagManager.instance.uri_for(object.quoted_account), '#accepts/quote_requests/', object.id].join + end + + def type + 'Accept' + end + + def actor + ActivityPub::TagManager.instance.uri_for(object.quoted_account) + end + + def result + ActivityPub::TagManager.instance.approval_uri_for(object) + end +end diff --git a/app/serializers/activitypub/quote_request_serializer.rb b/app/serializers/activitypub/quote_request_serializer.rb index 840b653a1c7..2b3363fb576 100644 --- a/app/serializers/activitypub/quote_request_serializer.rb +++ b/app/serializers/activitypub/quote_request_serializer.rb @@ -23,6 +23,7 @@ class ActivityPub::QuoteRequestSerializer < ActivityPub::Serializer end def instrument + # TODO: inline object? ActivityPub::TagManager.instance.uri_for(object.status) end end diff --git a/spec/lib/activitypub/activity/quote_request_spec.rb b/spec/lib/activitypub/activity/quote_request_spec.rb index dac0b438cbd..24a245c8981 100644 --- a/spec/lib/activitypub/activity/quote_request_spec.rb +++ b/spec/lib/activitypub/activity/quote_request_spec.rb @@ -2,7 +2,7 @@ require 'rails_helper' -RSpec.describe ActivityPub::Activity::QuoteRequest do +RSpec.describe ActivityPub::Activity::QuoteRequest, feature: :outgoing_quotes do let(:sender) { Fabricate(:account, domain: 'example.com') } let(:recipient) { Fabricate(:account) } let(:quoted_post) { Fabricate(:status, account: recipient) } @@ -47,5 +47,44 @@ RSpec.describe ActivityPub::Activity::QuoteRequest do end, recipient.id, sender.inbox_url) end end + + context 'when trying to quote a quotable local status' do + let(:status_json) 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: 'https://example.com/unknown-status', + type: 'Note', + summary: 'Show more', + content: 'Hello universe', + quote: ActivityPub::TagManager.instance.uri_for(quoted_post), + attributedTo: ActivityPub::TagManager.instance.uri_for(sender), + }.deep_stringify_keys + end + + before do + stub_request(:get, 'https://example.com/unknown-status').to_return(status: 200, body: Oj.dump(status_json), headers: { 'Content-Type': 'application/activity+json' }) + quoted_post.update(quote_approval_policy: Status::QUOTE_APPROVAL_POLICY_FLAGS[:public] << 16) + end + + it 'accepts the quote and sends an Accept activity' do + expect { subject.perform } + .to change { quoted_post.reload.quotes.accepted.count }.by(1) + .and enqueue_sidekiq_job(ActivityPub::DeliveryWorker) + .with(satisfying do |body| + outgoing_json = Oj.load(body) + outgoing_json['type'] == 'Accept' && %w(type id actor object instrument).all? { |key| json[key] == outgoing_json['object'][key] } + end, recipient.id, sender.inbox_url) + end + end end end diff --git a/spec/serializers/activitypub/accept_quote_request_serializer_spec.rb b/spec/serializers/activitypub/accept_quote_request_serializer_spec.rb new file mode 100644 index 00000000000..986d9112b79 --- /dev/null +++ b/spec/serializers/activitypub/accept_quote_request_serializer_spec.rb @@ -0,0 +1,25 @@ +# frozen_string_literal: true + +require 'rails_helper' + +RSpec.describe ActivityPub::AcceptQuoteRequestSerializer do + subject { serialized_record_json(record, described_class, adapter: ActivityPub::Adapter) } + + describe 'serializing an object' do + let(:record) { Fabricate(:quote, state: :accepted) } + + it 'returns expected attributes' do + expect(subject.deep_symbolize_keys) + .to include( + actor: eq(ActivityPub::TagManager.instance.uri_for(record.quoted_account)), + id: match("#accepts/quote_requests/#{record.id}"), + object: include( + type: 'QuoteRequest', + instrument: ActivityPub::TagManager.instance.uri_for(record.status), + object: ActivityPub::TagManager.instance.uri_for(record.quoted_status) + ), + type: 'Accept' + ) + end + end +end From cb0b608fa7d23e5e09015662c82b88488470adf1 Mon Sep 17 00:00:00 2001 From: Claire Date: Mon, 4 Aug 2025 18:06:59 +0200 Subject: [PATCH 19/23] Ensure quoted user is given access to see the post (#35665) --- app/lib/activitypub/activity/quote_request.rb | 1 + app/models/quote.rb | 6 ++++++ app/services/post_status_service.rb | 10 +++------- 3 files changed, 10 insertions(+), 7 deletions(-) diff --git a/app/lib/activitypub/activity/quote_request.rb b/app/lib/activitypub/activity/quote_request.rb index 40a38b09d36..424aafe993b 100644 --- a/app/lib/activitypub/activity/quote_request.rb +++ b/app/lib/activitypub/activity/quote_request.rb @@ -27,6 +27,7 @@ class ActivityPub::Activity::QuoteRequest < ActivityPub::Activity # Sanity check return unless status.quote.quoted_status == quoted_status + status.quote.ensure_quoted_access status.quote.update!(activity_uri: @json['id']) status.quote.accept! diff --git a/app/models/quote.rb b/app/models/quote.rb index a6c9dd0caca..fea812924cc 100644 --- a/app/models/quote.rb +++ b/app/models/quote.rb @@ -56,6 +56,12 @@ class Quote < ApplicationRecord accepted? || !legacy? end + def ensure_quoted_access + status.mentions.create!(account: quoted_account, silent: true) + rescue ActiveRecord::RecordInvalid, ActiveRecord::RecordNotUnique + nil + end + def schedule_refresh_if_stale! return unless quoted_status_id.present? && approval_uri.present? && updated_at <= BACKGROUND_REFRESH_INTERVAL.ago diff --git a/app/services/post_status_service.rb b/app/services/post_status_service.rb index 73e78f00478..75116e2a266 100644 --- a/app/services/post_status_service.rb +++ b/app/services/post_status_service.rb @@ -93,14 +93,10 @@ class PostStatusService < BaseService def attach_quote!(status) return if @quoted_status.nil? - # NOTE: for now this is only for convenience in testing, as we don't support the request flow nor serialize quotes in ActivityPub - # we only support incoming quotes so far - status.quote = Quote.create(quoted_status: @quoted_status, status: status) - if @quoted_status.local? && StatusPolicy.new(@status.account, @quoted_status).quote? - # TODO: produce a QuoteAuthorization - status.quote.accept! - end + status.quote.ensure_quoted_access + + status.quote.accept! if @quoted_status.local? && StatusPolicy.new(@status.account, @quoted_status).quote? end def safeguard_mentions!(status) From 28b0e5ee787988426da5805374040ec05ffae3cd Mon Sep 17 00:00:00 2001 From: Echo Date: Mon, 4 Aug 2025 19:15:46 +0200 Subject: [PATCH 20/23] Provides legacy fallback for browser that don't support regex flag v (#35659) --- .../mastodon/features/emoji/constants.ts | 11 ----- .../mastodon/features/emoji/render.ts | 10 +++-- .../mastodon/features/emoji/utils.ts | 43 ++++++++++++++++--- app/javascript/mastodon/polyfills/index.ts | 11 +++++ package.json | 1 + yarn.lock | 8 ++++ 6 files changed, 63 insertions(+), 21 deletions(-) diff --git a/app/javascript/mastodon/features/emoji/constants.ts b/app/javascript/mastodon/features/emoji/constants.ts index a5ec9e6e2b4..09022371b22 100644 --- a/app/javascript/mastodon/features/emoji/constants.ts +++ b/app/javascript/mastodon/features/emoji/constants.ts @@ -15,17 +15,6 @@ export const SKIN_TONE_CODES = [ 0x1f3ff, // Dark skin tone ] as const; -// TODO: Test and create fallback for browsers that do not handle the /v flag. -export const UNICODE_EMOJI_REGEX = /\p{RGI_Emoji}/v; -// See: https://www.unicode.org/reports/tr51/#valid-emoji-tag-sequences -export const UNICODE_FLAG_EMOJI_REGEX = - /\p{RGI_Emoji_Flag_Sequence}|\p{RGI_Emoji_Tag_Sequence}/v; -export const CUSTOM_EMOJI_REGEX = /:([a-z0-9_]+):/i; -export const ANY_EMOJI_REGEX = new RegExp( - `(${UNICODE_EMOJI_REGEX.source}|${CUSTOM_EMOJI_REGEX.source})`, - 'gv', -); - // Emoji rendering modes. A mode is what we are using to render emojis, a style is what the user has selected. export const EMOJI_MODE_NATIVE = 'native'; export const EMOJI_MODE_NATIVE_WITH_FLAGS = 'native-flags'; diff --git a/app/javascript/mastodon/features/emoji/render.ts b/app/javascript/mastodon/features/emoji/render.ts index 6486e65a709..8d2299fd89e 100644 --- a/app/javascript/mastodon/features/emoji/render.ts +++ b/app/javascript/mastodon/features/emoji/render.ts @@ -9,7 +9,6 @@ import { EMOJI_TYPE_UNICODE, EMOJI_TYPE_CUSTOM, EMOJI_STATE_MISSING, - ANY_EMOJI_REGEX, } from './constants'; import { searchCustomEmojisByShortcodes, @@ -32,7 +31,12 @@ import type { LocaleOrCustom, UnicodeEmojiToken, } from './types'; -import { emojiLogger, stringHasAnyEmoji, stringHasUnicodeFlags } from './utils'; +import { + anyEmojiRegex, + emojiLogger, + stringHasAnyEmoji, + stringHasUnicodeFlags, +} from './utils'; const log = emojiLogger('render'); @@ -207,7 +211,7 @@ export function tokenizeText(text: string): TokenizedText { const tokens = []; let lastIndex = 0; - for (const match of text.matchAll(ANY_EMOJI_REGEX)) { + for (const match of text.matchAll(anyEmojiRegex())) { if (match.index > lastIndex) { tokens.push(text.slice(lastIndex, match.index)); } diff --git a/app/javascript/mastodon/features/emoji/utils.ts b/app/javascript/mastodon/features/emoji/utils.ts index 89f8d926466..ce359199296 100644 --- a/app/javascript/mastodon/features/emoji/utils.ts +++ b/app/javascript/mastodon/features/emoji/utils.ts @@ -1,23 +1,32 @@ import debug from 'debug'; -import { - CUSTOM_EMOJI_REGEX, - UNICODE_EMOJI_REGEX, - UNICODE_FLAG_EMOJI_REGEX, -} from './constants'; +import { emojiRegexPolyfill } from '@/mastodon/polyfills'; export function emojiLogger(segment: string) { return debug(`emojis:${segment}`); } export function stringHasUnicodeEmoji(input: string): boolean { - return UNICODE_EMOJI_REGEX.test(input); + return new RegExp(EMOJI_REGEX, supportedFlags()).test(input); } export function stringHasUnicodeFlags(input: string): boolean { - return UNICODE_FLAG_EMOJI_REGEX.test(input); + if (supportsRegExpSets()) { + return new RegExp( + '\\p{RGI_Emoji_Flag_Sequence}|\\p{RGI_Emoji_Tag_Sequence}', + 'v', + ).test(input); + } + return new RegExp( + // First range is regional indicator symbols, + // Second is a black flag + 0-9|a-z tag chars + cancel tag. + // See: https://en.wikipedia.org/wiki/Regional_indicator_symbol + '(?:\uD83C[\uDDE6-\uDDFF]){2}|\uD83C\uDFF4(?:\uDB40[\uDC30-\uDC7A])+\uDB40\uDC7F', + ).test(input); } +// Constant as this is supported by all browsers. +const CUSTOM_EMOJI_REGEX = /:([a-z0-9_]+):/i; export function stringHasCustomEmoji(input: string) { return CUSTOM_EMOJI_REGEX.test(input); } @@ -25,3 +34,23 @@ export function stringHasCustomEmoji(input: string) { export function stringHasAnyEmoji(input: string) { return stringHasUnicodeEmoji(input) || stringHasCustomEmoji(input); } + +export function anyEmojiRegex() { + return new RegExp( + `${EMOJI_REGEX}|${CUSTOM_EMOJI_REGEX.source}`, + supportedFlags('gi'), + ); +} + +function supportsRegExpSets() { + return 'unicodeSets' in RegExp.prototype; +} + +function supportedFlags(flags = '') { + if (supportsRegExpSets()) { + return `${flags}v`; + } + return flags; +} + +const EMOJI_REGEX = emojiRegexPolyfill?.source ?? '\\p{RGI_Emoji}'; diff --git a/app/javascript/mastodon/polyfills/index.ts b/app/javascript/mastodon/polyfills/index.ts index c001421c363..0ff0dd72690 100644 --- a/app/javascript/mastodon/polyfills/index.ts +++ b/app/javascript/mastodon/polyfills/index.ts @@ -20,5 +20,16 @@ export function loadPolyfills() { 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(), + loadEmojiPolyfills(), ]); } + +// In the case of no /v support, rely on the emojibase data. +async function loadEmojiPolyfills() { + if (!('unicodeSets' in RegExp.prototype)) { + emojiRegexPolyfill = (await import('emojibase-regex/emoji')).default; + } +} + +// Null unless polyfill is needed. +export let emojiRegexPolyfill: RegExp | null = null; diff --git a/package.json b/package.json index ec7b918ef0a..6109b42875b 100644 --- a/package.json +++ b/package.json @@ -69,6 +69,7 @@ "emoji-mart": "npm:emoji-mart-lazyload@latest", "emojibase": "^16.0.0", "emojibase-data": "^16.0.3", + "emojibase-regex": "^16.0.0", "escape-html": "^1.0.3", "fast-glob": "^3.3.3", "fuzzysort": "^3.0.0", diff --git a/yarn.lock b/yarn.lock index a8baa769411..26f7cd409e9 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2659,6 +2659,7 @@ __metadata: emoji-mart: "npm:emoji-mart-lazyload@latest" emojibase: "npm:^16.0.0" emojibase-data: "npm:^16.0.3" + emojibase-regex: "npm:^16.0.0" escape-html: "npm:^1.0.3" eslint: "npm:^9.23.0" eslint-import-resolver-typescript: "npm:^4.2.5" @@ -6565,6 +6566,13 @@ __metadata: languageName: node linkType: hard +"emojibase-regex@npm:^16.0.0": + version: 16.0.0 + resolution: "emojibase-regex@npm:16.0.0" + checksum: 10c0/8ee5ff798e51caa581434b1cb2f9737e50195093c4efa1739df21a50a5496f80517924787d865e8cf7d6a0b4c90dbedc04bdc506dcbcc582e14cdf0bb47af0f0 + languageName: node + linkType: hard + "emojibase@npm:^16.0.0": version: 16.0.0 resolution: "emojibase@npm:16.0.0" From 570c9d16be2f2e0e95da6723aa5281f600424fba Mon Sep 17 00:00:00 2001 From: Echo Date: Mon, 4 Aug 2025 19:16:12 +0200 Subject: [PATCH 21/23] Performance regression fixes (#35664) --- .dockerignore | 2 ++ .../mastodon/features/emoji/emoji_html.tsx | 19 ++++++++++++++++++- .../mastodon/features/emoji/hooks.ts | 2 +- 3 files changed, 21 insertions(+), 2 deletions(-) diff --git a/.dockerignore b/.dockerignore index 9d990ab9ce6..fe87f6e6006 100644 --- a/.dockerignore +++ b/.dockerignore @@ -5,6 +5,7 @@ .gitattributes .gitignore .github +.vscode public/system public/assets public/packs @@ -20,6 +21,7 @@ postgres14 redis elasticsearch chart +storybook-static .yarn/ !.yarn/patches !.yarn/plugins diff --git a/app/javascript/mastodon/features/emoji/emoji_html.tsx b/app/javascript/mastodon/features/emoji/emoji_html.tsx index fdda62a3e61..ed6f7a20465 100644 --- a/app/javascript/mastodon/features/emoji/emoji_html.tsx +++ b/app/javascript/mastodon/features/emoji/emoji_html.tsx @@ -1,5 +1,7 @@ import type { ComponentPropsWithoutRef, ElementType } from 'react'; +import { isModernEmojiEnabled } from '@/mastodon/utils/environment'; + import { useEmojify } from './hooks'; import type { CustomEmojiMapArg } from './types'; @@ -12,7 +14,7 @@ type EmojiHTMLProps = Omit< as?: Element; }; -export const EmojiHTML = ({ +export const ModernEmojiHTML = ({ extraEmojis, htmlString, as: asElement, // Rename for syntax highlighting @@ -29,3 +31,18 @@ export const EmojiHTML = ({ ); }; + +export const EmojiHTML = ( + props: EmojiHTMLProps, +) => { + if (isModernEmojiEnabled()) { + return ; + } + const Wrapper = props.as ?? 'div'; + return ( + + ); +}; diff --git a/app/javascript/mastodon/features/emoji/hooks.ts b/app/javascript/mastodon/features/emoji/hooks.ts index 47af37b3731..3f397f4ef03 100644 --- a/app/javascript/mastodon/features/emoji/hooks.ts +++ b/app/javascript/mastodon/features/emoji/hooks.ts @@ -8,7 +8,6 @@ import { isModernEmojiEnabled } from '@/mastodon/utils/environment'; import { toSupportedLocale } from './locale'; import { determineEmojiMode } from './mode'; -import { emojifyElement } from './render'; import type { CustomEmojiMapArg, EmojiAppState, @@ -39,6 +38,7 @@ export function useEmojify(text: string, extraEmojis?: CustomEmojiMapArg) { async (input: string) => { const wrapper = document.createElement('div'); wrapper.innerHTML = input; + const { emojifyElement } = await import('./render'); const result = await emojifyElement(wrapper, appState, extra); if (result) { setEmojifiedText(result.innerHTML); From 081d38679f965ac20ff1a6c72e2fc1108c34ac30 Mon Sep 17 00:00:00 2001 From: Claire Date: Mon, 4 Aug 2025 20:12:37 +0200 Subject: [PATCH 22/23] Add quote notifications to WebUI (#35653) --- .../mastodon/api_types/notifications.ts | 2 ++ .../notifications/components/notification.jsx | 35 ++++++++++++++++++- .../components/notification_group.tsx | 6 ++++ .../components/notification_quote.tsx | 33 +++++++++++++++++ app/javascript/mastodon/locales/en.json | 1 + .../mastodon/models/notification_group.ts | 4 +++ .../400-24px/format_quote-fill.svg | 1 + .../material-icons/400-24px/format_quote.svg | 1 + 8 files changed, 82 insertions(+), 1 deletion(-) create mode 100644 app/javascript/mastodon/features/notifications_v2/components/notification_quote.tsx create mode 100644 app/javascript/material-icons/400-24px/format_quote-fill.svg create mode 100644 app/javascript/material-icons/400-24px/format_quote.svg diff --git a/app/javascript/mastodon/api_types/notifications.ts b/app/javascript/mastodon/api_types/notifications.ts index 190d8c83966..69fd17a2563 100644 --- a/app/javascript/mastodon/api_types/notifications.ts +++ b/app/javascript/mastodon/api_types/notifications.ts @@ -13,6 +13,7 @@ export const allNotificationTypes = [ 'favourite', 'reblog', 'mention', + 'quote', 'poll', 'status', 'update', @@ -28,6 +29,7 @@ export type NotificationWithStatusType = | 'reblog' | 'status' | 'mention' + | 'quote' | 'poll' | 'update'; diff --git a/app/javascript/mastodon/features/notifications/components/notification.jsx b/app/javascript/mastodon/features/notifications/components/notification.jsx index b38e5da1594..ced09881a43 100644 --- a/app/javascript/mastodon/features/notifications/components/notification.jsx +++ b/app/javascript/mastodon/features/notifications/components/notification.jsx @@ -8,9 +8,9 @@ import { Link, withRouter } from 'react-router-dom'; import ImmutablePropTypes from 'react-immutable-proptypes'; import ImmutablePureComponent from 'react-immutable-pure-component'; - import EditIcon from '@/material-icons/400-24px/edit.svg?react'; import FlagIcon from '@/material-icons/400-24px/flag-fill.svg?react'; +import FormatQuoteIcon from '@/material-icons/400-24px/format_quote.svg?react'; import HomeIcon from '@/material-icons/400-24px/home-fill.svg?react'; import InsertChartIcon from '@/material-icons/400-24px/insert_chart.svg?react'; import PersonIcon from '@/material-icons/400-24px/person-fill.svg?react'; @@ -42,6 +42,7 @@ const messages = defineMessages({ adminReport: { id: 'notification.admin.report', defaultMessage: '{name} reported {target}' }, relationshipsSevered: { id: 'notification.relationships_severance_event', defaultMessage: 'Lost connections with {name}' }, moderationWarning: { id: 'notification.moderation_warning', defaultMessage: 'You have received a moderation warning' }, + quote: { id: 'notification.label.quote', defaultMessage: '{name} quoted your post'} }); const notificationForScreenReader = (intl, message, timestamp) => { @@ -251,6 +252,36 @@ class Notification extends ImmutablePureComponent { ); } + renderQuote (notification, link) { + const { intl, unread } = this.props; + + return ( + +
+
+ + + + + +
+ +
+
+ ); + } + renderStatus (notification, link) { const { intl, unread, status } = this.props; @@ -467,6 +498,8 @@ class Notification extends ImmutablePureComponent { return this.renderFollowRequest(notification, account, link); case 'mention': return this.renderMention(notification); + case 'quote': + return this.renderQuote(notification); case 'favourite': return this.renderFavourite(notification, link); case 'reblog': diff --git a/app/javascript/mastodon/features/notifications_v2/components/notification_group.tsx b/app/javascript/mastodon/features/notifications_v2/components/notification_group.tsx index f0f2139ad21..eba39e17b7a 100644 --- a/app/javascript/mastodon/features/notifications_v2/components/notification_group.tsx +++ b/app/javascript/mastodon/features/notifications_v2/components/notification_group.tsx @@ -15,6 +15,7 @@ import { NotificationFollowRequest } from './notification_follow_request'; import { NotificationMention } from './notification_mention'; import { NotificationModerationWarning } from './notification_moderation_warning'; import { NotificationPoll } from './notification_poll'; +import { NotificationQuote } from './notification_quote'; import { NotificationReblog } from './notification_reblog'; import { NotificationSeveredRelationships } from './notification_severed_relationships'; import { NotificationStatus } from './notification_status'; @@ -91,6 +92,11 @@ export const NotificationGroup: React.FC<{ ); break; + case 'quote': + content = ( + + ); + break; case 'follow': content = ( diff --git a/app/javascript/mastodon/features/notifications_v2/components/notification_quote.tsx b/app/javascript/mastodon/features/notifications_v2/components/notification_quote.tsx new file mode 100644 index 00000000000..595bed806c6 --- /dev/null +++ b/app/javascript/mastodon/features/notifications_v2/components/notification_quote.tsx @@ -0,0 +1,33 @@ +import { FormattedMessage } from 'react-intl'; + +import FormatQuoteIcon from '@/material-icons/400-24px/format_quote.svg?react'; +import type { NotificationGroupQuote } from 'mastodon/models/notification_group'; + +import type { LabelRenderer } from './notification_group_with_status'; +import { NotificationWithStatus } from './notification_with_status'; + +const quoteLabelRenderer: LabelRenderer = (displayName) => ( + +); + +export const NotificationQuote: React.FC<{ + notification: NotificationGroupQuote; + unread: boolean; +}> = ({ notification, unread }) => { + return ( + + ); +}; diff --git a/app/javascript/mastodon/locales/en.json b/app/javascript/mastodon/locales/en.json index 329ac90589e..c91516695b0 100644 --- a/app/javascript/mastodon/locales/en.json +++ b/app/javascript/mastodon/locales/en.json @@ -600,6 +600,7 @@ "notification.label.mention": "Mention", "notification.label.private_mention": "Private mention", "notification.label.private_reply": "Private reply", + "notification.label.quote": "{name} quoted your post", "notification.label.reply": "Reply", "notification.mention": "Mention", "notification.mentioned_you": "{name} mentioned you", diff --git a/app/javascript/mastodon/models/notification_group.ts b/app/javascript/mastodon/models/notification_group.ts index d98e755aa2c..9394cbbed88 100644 --- a/app/javascript/mastodon/models/notification_group.ts +++ b/app/javascript/mastodon/models/notification_group.ts @@ -36,6 +36,7 @@ export type NotificationGroupFavourite = export type NotificationGroupReblog = BaseNotificationWithStatus<'reblog'>; export type NotificationGroupStatus = BaseNotificationWithStatus<'status'>; export type NotificationGroupMention = BaseNotificationWithStatus<'mention'>; +export type NotificationGroupQuote = BaseNotificationWithStatus<'quote'>; export type NotificationGroupPoll = BaseNotificationWithStatus<'poll'>; export type NotificationGroupUpdate = BaseNotificationWithStatus<'update'>; export type NotificationGroupFollow = BaseNotification<'follow'>; @@ -87,6 +88,7 @@ export type NotificationGroup = | NotificationGroupReblog | NotificationGroupStatus | NotificationGroupMention + | NotificationGroupQuote | NotificationGroupPoll | NotificationGroupUpdate | NotificationGroupFollow @@ -137,6 +139,7 @@ export function createNotificationGroupFromJSON( case 'reblog': case 'status': case 'mention': + case 'quote': case 'poll': case 'update': { const { status_id: statusId, ...groupWithoutStatus } = group; @@ -209,6 +212,7 @@ export function createNotificationGroupFromNotificationJSON( case 'reblog': case 'status': case 'mention': + case 'quote': case 'poll': case 'update': return { diff --git a/app/javascript/material-icons/400-24px/format_quote-fill.svg b/app/javascript/material-icons/400-24px/format_quote-fill.svg new file mode 100644 index 00000000000..f4afa3ed17f --- /dev/null +++ b/app/javascript/material-icons/400-24px/format_quote-fill.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/app/javascript/material-icons/400-24px/format_quote.svg b/app/javascript/material-icons/400-24px/format_quote.svg new file mode 100644 index 00000000000..c354385ea93 --- /dev/null +++ b/app/javascript/material-icons/400-24px/format_quote.svg @@ -0,0 +1 @@ + \ No newline at end of file From 5318957ab3b22e74e531b8c65a73089e13328f4d Mon Sep 17 00:00:00 2001 From: Claire Date: Mon, 4 Aug 2025 22:58:59 +0200 Subject: [PATCH 23/23] Fix serialization of quote post notification groups (#35670) --- app/serializers/rest/notification_group_serializer.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/serializers/rest/notification_group_serializer.rb b/app/serializers/rest/notification_group_serializer.rb index f4af842e38d..347659bdfef 100644 --- a/app/serializers/rest/notification_group_serializer.rb +++ b/app/serializers/rest/notification_group_serializer.rb @@ -24,7 +24,7 @@ class REST::NotificationGroupSerializer < ActiveModel::Serializer end def status_type? - [:favourite, :reblog, :status, :mention, :poll, :update].include?(object.type) + [:favourite, :reblog, :status, :mention, :poll, :update, :quote].include?(object.type) end def report_type?