From 2fc4475ea3a17d733887d5205f91f251e1899554 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Tue, 25 Mar 2025 09:57:15 +0100 Subject: [PATCH 01/12] fix(deps): update babel monorepo to v7.27.0 (#34263) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- yarn.lock | 112 +++++++++++++++++++++++++++--------------------------- 1 file changed, 56 insertions(+), 56 deletions(-) diff --git a/yarn.lock b/yarn.lock index 11d9c907c3..ef3ef8f7e9 100644 --- a/yarn.lock +++ b/yarn.lock @@ -96,16 +96,16 @@ __metadata: languageName: node linkType: hard -"@babel/generator@npm:^7.26.10, @babel/generator@npm:^7.7.2": - version: 7.26.10 - resolution: "@babel/generator@npm:7.26.10" +"@babel/generator@npm:^7.26.10, @babel/generator@npm:^7.27.0, @babel/generator@npm:^7.7.2": + version: 7.27.0 + resolution: "@babel/generator@npm:7.27.0" dependencies: - "@babel/parser": "npm:^7.26.10" - "@babel/types": "npm:^7.26.10" + "@babel/parser": "npm:^7.27.0" + "@babel/types": "npm:^7.27.0" "@jridgewell/gen-mapping": "npm:^0.3.5" "@jridgewell/trace-mapping": "npm:^0.3.25" jsesc: "npm:^3.0.2" - checksum: 10c0/88b3b3ea80592fc89349c4e1a145e1386e4042866d2507298adf452bf972f68d13bf699a845e6ab8c028bd52c2247013eb1221b86e1db5c9779faacba9c4b10e + checksum: 10c0/7cb10693d2b365c278f109a745dc08856cae139d262748b77b70ce1d97da84627f79648cab6940d847392c0e5d180441669ed958b3aee98d9c7d274b37c553bd languageName: node linkType: hard @@ -141,20 +141,20 @@ __metadata: languageName: node linkType: hard -"@babel/helper-create-class-features-plugin@npm:^7.25.9": - version: 7.25.9 - resolution: "@babel/helper-create-class-features-plugin@npm:7.25.9" +"@babel/helper-create-class-features-plugin@npm:^7.25.9, @babel/helper-create-class-features-plugin@npm:^7.27.0": + version: 7.27.0 + resolution: "@babel/helper-create-class-features-plugin@npm:7.27.0" dependencies: "@babel/helper-annotate-as-pure": "npm:^7.25.9" "@babel/helper-member-expression-to-functions": "npm:^7.25.9" "@babel/helper-optimise-call-expression": "npm:^7.25.9" - "@babel/helper-replace-supers": "npm:^7.25.9" + "@babel/helper-replace-supers": "npm:^7.26.5" "@babel/helper-skip-transparent-expression-wrappers": "npm:^7.25.9" - "@babel/traverse": "npm:^7.25.9" + "@babel/traverse": "npm:^7.27.0" semver: "npm:^6.3.1" peerDependencies: "@babel/core": ^7.0.0 - checksum: 10c0/b2bdd39f38056a76b9ba00ec5b209dd84f5c5ebd998d0f4033cf0e73d5f2c357fbb49d1ce52db77a2709fb29ee22321f84a5734dc9914849bdfee9ad12ce8caf + checksum: 10c0/c4945903136d934050e070f69a4d72ec425f1f70634e0ddf14ad36695f935125a6df559f8d5b94cc1ed49abd4ce9c5be8ef3ba033fa8d09c5dd78d1a9b97d8cc languageName: node linkType: hard @@ -248,16 +248,16 @@ __metadata: languageName: node linkType: hard -"@babel/helper-replace-supers@npm:^7.25.9": - version: 7.25.9 - resolution: "@babel/helper-replace-supers@npm:7.25.9" +"@babel/helper-replace-supers@npm:^7.25.9, @babel/helper-replace-supers@npm:^7.26.5": + version: 7.26.5 + resolution: "@babel/helper-replace-supers@npm:7.26.5" dependencies: "@babel/helper-member-expression-to-functions": "npm:^7.25.9" "@babel/helper-optimise-call-expression": "npm:^7.25.9" - "@babel/traverse": "npm:^7.25.9" + "@babel/traverse": "npm:^7.26.5" peerDependencies: "@babel/core": ^7.0.0 - checksum: 10c0/0b40d7d2925bd3ba4223b3519e2e4d2456d471ad69aa458f1c1d1783c80b522c61f8237d3a52afc9e47c7174129bbba650df06393a6787d5722f2ec7f223c3f4 + checksum: 10c0/b19b1245caf835207aaaaac3a494f03a16069ae55e76a2e1350b5acd560e6a820026997a8160e8ebab82ae873e8208759aa008eb8422a67a775df41f0a4633d4 languageName: node linkType: hard @@ -313,14 +313,14 @@ __metadata: languageName: node linkType: hard -"@babel/parser@npm:^7.1.0, @babel/parser@npm:^7.14.7, @babel/parser@npm:^7.20.7, @babel/parser@npm:^7.26.10, @babel/parser@npm:^7.26.9": - version: 7.26.10 - resolution: "@babel/parser@npm:7.26.10" +"@babel/parser@npm:^7.1.0, @babel/parser@npm:^7.14.7, @babel/parser@npm:^7.20.7, @babel/parser@npm:^7.26.10, @babel/parser@npm:^7.27.0": + version: 7.27.0 + resolution: "@babel/parser@npm:7.27.0" dependencies: - "@babel/types": "npm:^7.26.10" + "@babel/types": "npm:^7.27.0" bin: parser: ./bin/babel-parser.js - checksum: 10c0/c47f5c0f63cd12a663e9dc94a635f9efbb5059d98086a92286d7764357c66bceba18ccbe79333e01e9be3bfb8caba34b3aaebfd8e62c3d5921c8cf907267be75 + checksum: 10c0/ba2ed3f41735826546a3ef2a7634a8d10351df221891906e59b29b0a0cd748f9b0e7a6f07576858a9de8e77785aad925c8389ddef146de04ea2842047c9d2859 languageName: node linkType: hard @@ -851,7 +851,7 @@ __metadata: languageName: node linkType: hard -"@babel/plugin-transform-modules-commonjs@npm:^7.25.9, @babel/plugin-transform-modules-commonjs@npm:^7.26.3": +"@babel/plugin-transform-modules-commonjs@npm:^7.26.3": version: 7.26.3 resolution: "@babel/plugin-transform-modules-commonjs@npm:7.26.3" dependencies: @@ -1208,18 +1208,18 @@ __metadata: languageName: node linkType: hard -"@babel/plugin-transform-typescript@npm:^7.25.9": - version: 7.25.9 - resolution: "@babel/plugin-transform-typescript@npm:7.25.9" +"@babel/plugin-transform-typescript@npm:^7.27.0": + version: 7.27.0 + resolution: "@babel/plugin-transform-typescript@npm:7.27.0" dependencies: "@babel/helper-annotate-as-pure": "npm:^7.25.9" - "@babel/helper-create-class-features-plugin": "npm:^7.25.9" - "@babel/helper-plugin-utils": "npm:^7.25.9" + "@babel/helper-create-class-features-plugin": "npm:^7.27.0" + "@babel/helper-plugin-utils": "npm:^7.26.5" "@babel/helper-skip-transparent-expression-wrappers": "npm:^7.25.9" "@babel/plugin-syntax-typescript": "npm:^7.25.9" peerDependencies: "@babel/core": ^7.0.0-0 - checksum: 10c0/c607ddb45f7e33cfcb928aad05cb1b18b1ecb564d2329d8f8e427f75192511aa821dee42d26871f1bdffbd883853e150ba81436664646c6e6b13063e65ce1475 + checksum: 10c0/028e75dd6195495dc2d105ca8ded19d62aef90a215d597451cee57c35325960a87963913aa9a21b8ade190c638b588422292ea7e23b21565baf53c469254dbd4 languageName: node linkType: hard @@ -1379,17 +1379,17 @@ __metadata: linkType: hard "@babel/preset-typescript@npm:^7.21.5": - version: 7.26.0 - resolution: "@babel/preset-typescript@npm:7.26.0" + version: 7.27.0 + resolution: "@babel/preset-typescript@npm:7.27.0" dependencies: - "@babel/helper-plugin-utils": "npm:^7.25.9" + "@babel/helper-plugin-utils": "npm:^7.26.5" "@babel/helper-validator-option": "npm:^7.25.9" "@babel/plugin-syntax-jsx": "npm:^7.25.9" - "@babel/plugin-transform-modules-commonjs": "npm:^7.25.9" - "@babel/plugin-transform-typescript": "npm:^7.25.9" + "@babel/plugin-transform-modules-commonjs": "npm:^7.26.3" + "@babel/plugin-transform-typescript": "npm:^7.27.0" peerDependencies: "@babel/core": ^7.0.0-0 - checksum: 10c0/20d86bc45d2bbfde2f84fc7d7b38746fa6481d4bde6643039ad4b1ff0b804c6d210ee43e6830effd8571f2ff43fa7ffd27369f42f2b3a2518bb92dc86c780c61 + checksum: 10c0/986b20edab3c18727d911a6e1a14095c1271afc6cc625b02f42b371f06c1e041e5d7c1baf2afe8b0029b60788a06f02fd6844dedfe54183b148ab9a7429438a9 languageName: node linkType: hard @@ -1403,47 +1403,47 @@ __metadata: linkType: hard "@babel/runtime@npm:^7.0.0, @babel/runtime@npm:^7.1.2, @babel/runtime@npm:^7.11.2, @babel/runtime@npm:^7.12.0, @babel/runtime@npm:^7.12.13, @babel/runtime@npm:^7.12.5, @babel/runtime@npm:^7.13.8, @babel/runtime@npm:^7.18.3, @babel/runtime@npm:^7.2.0, @babel/runtime@npm:^7.20.13, @babel/runtime@npm:^7.22.3, @babel/runtime@npm:^7.3.1, @babel/runtime@npm:^7.5.5, @babel/runtime@npm:^7.6.3, @babel/runtime@npm:^7.8.4, @babel/runtime@npm:^7.8.7, @babel/runtime@npm:^7.9.2": - version: 7.26.10 - resolution: "@babel/runtime@npm:7.26.10" + version: 7.27.0 + resolution: "@babel/runtime@npm:7.27.0" dependencies: regenerator-runtime: "npm:^0.14.0" - checksum: 10c0/6dc6d88c7908f505c4f7770fb4677dfa61f68f659b943c2be1f2a99cb6680343462867abf2d49822adc435932919b36c77ac60125793e719ea8745f2073d3745 + checksum: 10c0/35091ea9de48bd7fd26fb177693d64f4d195eb58ab2b142b893b7f3fa0f1d7c677604d36499ae0621a3703f35ba0c6a8f6c572cc8f7dc0317213841e493cf663 languageName: node linkType: hard -"@babel/template@npm:^7.25.9, @babel/template@npm:^7.26.9, @babel/template@npm:^7.3.3": - version: 7.26.9 - resolution: "@babel/template@npm:7.26.9" +"@babel/template@npm:^7.25.9, @babel/template@npm:^7.26.9, @babel/template@npm:^7.27.0, @babel/template@npm:^7.3.3": + version: 7.27.0 + resolution: "@babel/template@npm:7.27.0" dependencies: "@babel/code-frame": "npm:^7.26.2" - "@babel/parser": "npm:^7.26.9" - "@babel/types": "npm:^7.26.9" - checksum: 10c0/019b1c4129cc01ad63e17529089c2c559c74709d225f595eee017af227fee11ae8a97a6ab19ae6768b8aa22d8d75dcb60a00b28f52e9fa78140672d928bc1ae9 + "@babel/parser": "npm:^7.27.0" + "@babel/types": "npm:^7.27.0" + checksum: 10c0/13af543756127edb5f62bf121f9b093c09a2b6fe108373887ccffc701465cfbcb17e07cf48aa7f440415b263f6ec006e9415c79dfc2e8e6010b069435f81f340 languageName: node linkType: hard -"@babel/traverse@npm:^7.25.0, @babel/traverse@npm:^7.25.9, @babel/traverse@npm:^7.26.10, @babel/traverse@npm:^7.26.8": - version: 7.26.10 - resolution: "@babel/traverse@npm:7.26.10" +"@babel/traverse@npm:^7.25.0, @babel/traverse@npm:^7.25.9, @babel/traverse@npm:^7.26.10, @babel/traverse@npm:^7.26.5, @babel/traverse@npm:^7.26.8, @babel/traverse@npm:^7.27.0": + version: 7.27.0 + resolution: "@babel/traverse@npm:7.27.0" dependencies: "@babel/code-frame": "npm:^7.26.2" - "@babel/generator": "npm:^7.26.10" - "@babel/parser": "npm:^7.26.10" - "@babel/template": "npm:^7.26.9" - "@babel/types": "npm:^7.26.10" + "@babel/generator": "npm:^7.27.0" + "@babel/parser": "npm:^7.27.0" + "@babel/template": "npm:^7.27.0" + "@babel/types": "npm:^7.27.0" debug: "npm:^4.3.1" globals: "npm:^11.1.0" - checksum: 10c0/4e86bb4e3c30a6162bb91df86329df79d96566c3e2d9ccba04f108c30473a3a4fd360d9990531493d90f6a12004f10f616bf9b9229ca30c816b708615e9de2ac + checksum: 10c0/c7af29781960dacaae51762e8bc6c4b13d6ab4b17312990fbca9fc38e19c4ad7fecaae24b1cf52fb844e8e6cdc76c70ad597f90e496bcb3cc0a1d66b41a0aa5b languageName: node linkType: hard -"@babel/types@npm:^7.0.0, @babel/types@npm:^7.0.0-beta.49, @babel/types@npm:^7.12.6, @babel/types@npm:^7.20.7, @babel/types@npm:^7.25.0, @babel/types@npm:^7.25.9, @babel/types@npm:^7.26.10, @babel/types@npm:^7.26.9, @babel/types@npm:^7.3.3, @babel/types@npm:^7.4.4": - version: 7.26.10 - resolution: "@babel/types@npm:7.26.10" +"@babel/types@npm:^7.0.0, @babel/types@npm:^7.0.0-beta.49, @babel/types@npm:^7.12.6, @babel/types@npm:^7.20.7, @babel/types@npm:^7.25.0, @babel/types@npm:^7.25.9, @babel/types@npm:^7.26.10, @babel/types@npm:^7.27.0, @babel/types@npm:^7.3.3, @babel/types@npm:^7.4.4": + version: 7.27.0 + resolution: "@babel/types@npm:7.27.0" dependencies: "@babel/helper-string-parser": "npm:^7.25.9" "@babel/helper-validator-identifier": "npm:^7.25.9" - checksum: 10c0/7a7f83f568bfc3dfabfaf9ae3a97ab5c061726c0afa7dcd94226d4f84a81559da368ed79671e3a8039d16f12476cf110381a377ebdea07587925f69628200dac + checksum: 10c0/6f1592eabe243c89a608717b07b72969be9d9d2fce1dee21426238757ea1fa60fdfc09b29de9e48d8104311afc6e6fb1702565a9cc1e09bc1e76f2b2ddb0f6e1 languageName: node linkType: hard From 90bf67f0531f9e7f02a1aa01df16699c5da30c6f Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Tue, 25 Mar 2025 10:05:59 +0100 Subject: [PATCH 02/12] New Crowdin Translations (automated) (#34265) Co-authored-by: GitHub Actions --- app/javascript/mastodon/locales/cs.json | 2 +- app/javascript/mastodon/locales/ka.json | 40 ++++++++++++------------- app/javascript/mastodon/locales/lv.json | 8 ++--- config/locales/activerecord.lv.yml | 4 +++ config/locales/devise.lv.yml | 2 +- config/locales/doorkeeper.lv.yml | 14 ++++----- config/locales/lv.yml | 12 ++++---- config/locales/simple_form.zh-CN.yml | 2 ++ config/locales/zh-CN.yml | 5 ++++ 9 files changed, 50 insertions(+), 39 deletions(-) diff --git a/app/javascript/mastodon/locales/cs.json b/app/javascript/mastodon/locales/cs.json index f9b24a58ff..aff66c97f8 100644 --- a/app/javascript/mastodon/locales/cs.json +++ b/app/javascript/mastodon/locales/cs.json @@ -110,7 +110,7 @@ "annual_report.summary.most_used_hashtag.most_used_hashtag": "nejpoužívanější hashtag", "annual_report.summary.most_used_hashtag.none": "Žádné", "annual_report.summary.new_posts.new_posts": "nové příspěvky", - "annual_report.summary.percentile.text": "To vás umisťuje do vrcholu{domain} uživatelů.", + "annual_report.summary.percentile.text": "To vás umisťuje do horních uživatelů domény {domain}.", "annual_report.summary.percentile.we_wont_tell_bernie": "To, že jste zdejší smetánka, zůstane mezi námi ;).", "annual_report.summary.thanks": "Děkujeme, že jste součástí Mastodonu!", "attachments_list.unprocessed": "(nezpracováno)", diff --git a/app/javascript/mastodon/locales/ka.json b/app/javascript/mastodon/locales/ka.json index d1587e1c2c..4dec178650 100644 --- a/app/javascript/mastodon/locales/ka.json +++ b/app/javascript/mastodon/locales/ka.json @@ -6,20 +6,20 @@ "account.badges.group": "ჯგუფი", "account.block": "დაბლოკე @{name}", "account.block_domain": "დაიმალოს ყველაფერი დომენიდან {domain}", - "account.blocked": "დაიბლოკა", + "account.blocked": "დაბლოკილია", "account.cancel_follow_request": "Withdraw follow request", "account.domain_blocked": "დომენი დამალულია", "account.edit_profile": "პროფილის ცვლილება", "account.endorse": "გამორჩევა პროფილზე", - "account.featured_tags.last_status_never": "პოსტები არ არის", + "account.featured_tags.last_status_never": "პოსტების გარეშე", "account.follow": "გაყოლა", "account.followers": "მიმდევრები", "account.hide_reblogs": "დაიმალოს ბუსტები @{name}-სგან", "account.media": "მედია", "account.mention": "ასახელეთ @{name}", "account.mute": "გააჩუმე @{name}", - "account.muted": "გაჩუმებული", - "account.posts": "ტუტები", + "account.muted": "დადუმებულია", + "account.posts": "პოსტები", "account.posts_with_replies": "ტუტები და პასუხები", "account.report": "დაარეპორტე @{name}", "account.requested": "დამტკიცების მოლოდინში. დააწკაპუნეთ რომ უარყოთ დადევნების მოთხონვა", @@ -42,7 +42,7 @@ "column.community": "ლოკალური თაიმლაინი", "column.domain_blocks": "დამალული დომენები", "column.follow_requests": "დადევნების მოთხოვნები", - "column.home": "სახლი", + "column.home": "საწყისი", "column.lists": "სიები", "column.mutes": "გაჩუმებული მომხმარებლები", "column.notifications": "შეტყობინებები", @@ -52,9 +52,9 @@ "column_header.hide_settings": "პარამეტრების დამალვა", "column_header.moveLeft_settings": "სვეტის მარცხნივ გადატანა", "column_header.moveRight_settings": "სვეტის მარჯვნივ გადატანა", - "column_header.pin": "აპინვა", + "column_header.pin": "მიმაგრება", "column_header.show_settings": "პარამეტრების ჩვენება", - "column_header.unpin": "პინის მოხსნა", + "column_header.unpin": "მოხსნა", "column_subheading.settings": "პარამეტრები", "community.column_settings.media_only": "მხოლოდ მედია", "compose_form.direct_message_warning_learn_more": "გაიგე მეტი", @@ -66,21 +66,21 @@ "compose_form.publish_form": "Publish", "compose_form.spoiler.marked": "გაფრთხილების უკან ტექსტი დამალულია", "compose_form.spoiler.unmarked": "ტექსტი არაა დამალული", - "confirmation_modal.cancel": "უარყოფა", + "confirmation_modal.cancel": "გაუქმება", "confirmations.block.confirm": "ბლოკი", - "confirmations.delete.confirm": "გაუქმება", + "confirmations.delete.confirm": "წაშლა", "confirmations.delete.message": "დარწმუნებული ხართ, გსურთ გააუქმოთ ეს სტატუსი?", - "confirmations.delete_list.confirm": "გაუქმება", + "confirmations.delete_list.confirm": "წაშლა", "confirmations.delete_list.message": "დარწმუნებული ხართ, გსურთ სამუდამოდ გააუქმოთ ეს სია?", - "confirmations.mute.confirm": "გაჩუმება", + "confirmations.mute.confirm": "დადუმება", "confirmations.redraft.confirm": "გაუქმება და გადანაწილება", "confirmations.unfollow.confirm": "ნუღარ მიჰყვები", "confirmations.unfollow.message": "დარწმუნებული ხართ, აღარ გსურთ მიჰყვებოდეთ {name}-ს?", "embed.instructions": "ეს სტატუსი ჩასვით თქვენს ვებ-საიტზე შემდეგი კოდის კოპირებით.", "embed.preview": "ესაა თუ როგორც გამოჩნდება:", "emoji_button.activity": "აქტივობა", - "emoji_button.custom": "პერსონალიზირებული", - "emoji_button.flags": "დროშები", + "emoji_button.custom": "მომხმარებლის", + "emoji_button.flags": "ალმები", "emoji_button.food": "საჭმელი და სასლმელი", "emoji_button.label": "ემოჯის ჩასმა", "emoji_button.nature": "ბუმება", @@ -119,7 +119,7 @@ "keyboard_shortcuts.federated": "to open federated timeline", "keyboard_shortcuts.heading": "კლავიატურის სწრაფი ბმულები", "keyboard_shortcuts.home": "to open home timeline", - "keyboard_shortcuts.hotkey": "ცხელი კლავიში", + "keyboard_shortcuts.hotkey": "მალსახმობი ღილაკი", "keyboard_shortcuts.legend": "ამ ლეგენდის გამოსაჩენად", "keyboard_shortcuts.local": "to open local timeline", "keyboard_shortcuts.mention": "ავტორის დასახელებლად", @@ -180,20 +180,20 @@ "relative_time.just_now": "ახლა", "relative_time.minutes": "{number}წთ", "relative_time.seconds": "{number}წმ", - "reply_indicator.cancel": "უარყოფა", + "reply_indicator.cancel": "გაუქმება", "report.forward": "ფორვარდი {target}-ს", "report.forward_hint": "ანგარიში სხვა სერვერიდანაა. გავაგზავნოთ რეპორტის ანონიმური ასლიც?", "report.placeholder": "დამატებითი კომენტარები", - "report.submit": "დასრულება", + "report.submit": "გადაცემა", "report.target": "არეპორტებთ {target}", "report_notification.attached_statuses": "{count, plural, one {# post} other {# posts}} attached", "search.placeholder": "ძებნა", "search_results.hashtags": "ჰეშტეგები", - "search_results.statuses": "ტუტები", - "sign_in_banner.sign_in": "Sign in", + "search_results.statuses": "პოსტები", + "sign_in_banner.sign_in": "შესვლა", "status.admin_status": "Open this status in the moderation interface", "status.block": "დაბლოკე @{name}", - "status.cancel_reblog_private": "ბუსტის მოშორება", + "status.cancel_reblog_private": "ბუსტის მოხსნა", "status.cannot_reblog": "ეს პოსტი ვერ დაიბუსტება", "status.copy": "Copy link to status", "status.delete": "წაშლა", @@ -222,7 +222,7 @@ "status.title.with_attachments": "{user} posted {attachmentCount, plural, one {an attachment} other {# attachments}}", "status.unmute_conversation": "საუბარზე გაჩუმების მოშორება", "status.unpin": "პროფილიდან პინის მოშორება", - "tabs_bar.home": "სახლი", + "tabs_bar.home": "საწყისი", "tabs_bar.notifications": "შეტყობინებები", "trends.counter_by_accounts": "{count, plural, one {{counter} person} other {{counter} people}} in the past {days, plural, one {day} other {# days}}", "ui.beforeunload": "თქვენი დრაფტი გაუქმდება თუ დატოვებთ მასტოდონს.", diff --git a/app/javascript/mastodon/locales/lv.json b/app/javascript/mastodon/locales/lv.json index 08e52077e9..6cf1558198 100644 --- a/app/javascript/mastodon/locales/lv.json +++ b/app/javascript/mastodon/locales/lv.json @@ -173,7 +173,7 @@ "compose.published.open": "Atvērt", "compose.saved.body": "Ziņa saglabāta.", "compose_form.direct_message_warning_learn_more": "Uzzināt vairāk", - "compose_form.encryption_warning": "Mastodon ieraksti nav pilnībā šifrēti. Nedalies ar jebkādu jutīgu informāciju caur Mastodon!", + "compose_form.encryption_warning": "Mastodon ieraksti nav pilnībā šifrēti. Nedalies ar jebkādu jūtīgu informāciju caur Mastodon!", "compose_form.hashtag_warning": "Šis ieraksts netiks uzrādīts nevienā tēmturī, jo tas nav redzams visiem. Tikai visiem redzamos ierakstus var meklēt pēc tēmtura.", "compose_form.lock_disclaimer": "Tavs konts nav {locked}. Ikviens var Tev sekot, lai redzētu tikai sekotājiem paredzētos ierakstus.", "compose_form.lock_disclaimer.lock": "slēgts", @@ -474,9 +474,9 @@ "notification.moderation_warning": "Ir saņemts satura pārraudzības brīdinājums", "notification.moderation_warning.action_delete_statuses": "Daži no Taviem ierakstiem tika noņemti.", "notification.moderation_warning.action_disable": "Tavs konts tika atspējots.", - "notification.moderation_warning.action_mark_statuses_as_sensitive": "Daži no Taviem ierakstiem tika atzīmēti kā jutīgi.", + "notification.moderation_warning.action_mark_statuses_as_sensitive": "Daži no Taviem ierakstiem tika atzīmēti kā jūtīgi.", "notification.moderation_warning.action_none": "Konts ir saņēmis satura pārraudzības brīdinājumu.", - "notification.moderation_warning.action_sensitive": "Tavi ieraksti turpmāk tiks atzīmēti kā jutīgi.", + "notification.moderation_warning.action_sensitive": "Tavi ieraksti turpmāk tiks atzīmēti kā jūtīgi.", "notification.moderation_warning.action_silence": "Tavs konts tika ierobežots.", "notification.moderation_warning.action_suspend": "Tava konta darbība tika apturēta.", "notification.own_poll": "Tava aptauja ir noslēgusies", @@ -702,7 +702,7 @@ "status.reply": "Atbildēt", "status.replyAll": "Atbildēt uz tematu", "status.report": "Ziņot par @{name}", - "status.sensitive_warning": "Sensitīvs saturs", + "status.sensitive_warning": "Jūtīgs saturs", "status.share": "Kopīgot", "status.show_less_all": "Rādīt mazāk visiem", "status.show_more_all": "Rādīt vairāk visiem", diff --git a/config/locales/activerecord.lv.yml b/config/locales/activerecord.lv.yml index 959c57019b..c7030221a7 100644 --- a/config/locales/activerecord.lv.yml +++ b/config/locales/activerecord.lv.yml @@ -49,6 +49,10 @@ lv: attributes: reblog: taken: ziņai jau pastāv + terms_of_service: + attributes: + effective_date: + too_soon: ir pārāk agri, jābūt vēlāk kā %{date} user: attributes: date_of_birth: diff --git a/config/locales/devise.lv.yml b/config/locales/devise.lv.yml index b5b8f22296..c3f4f0df89 100644 --- a/config/locales/devise.lv.yml +++ b/config/locales/devise.lv.yml @@ -2,7 +2,7 @@ lv: devise: confirmations: - confirmed: Tava e-pasta adrese ir veiksmīgi apstiprināta. + confirmed: Tava e-pasta adrese tika sekmīgi apstiprināta. send_instructions: Pēc dažām minūtēm saņemsi e-pasta ziņojum ar norādēm, kā apstiprināt savu e-pasta adresi. Lūgums pārbaudīt mēstuļu mapi, ja nesaņēmi šo e-pasta ziņojumu. send_paranoid_instructions: Ja Tava e-pasta adrese ir mūsu datubāzē, pēc dažām minūtēm saņemsi e-pasta ziņojumu ar norādēm, kā apstiprināt savu e-pasta adresi. Lūgums pārbaudīt mēstuļu mapi, ja nesaņēmi šo e-pasta ziņojumu. failure: diff --git a/config/locales/doorkeeper.lv.yml b/config/locales/doorkeeper.lv.yml index af892d79fa..15c1e7692a 100644 --- a/config/locales/doorkeeper.lv.yml +++ b/config/locales/doorkeeper.lv.yml @@ -150,13 +150,13 @@ lv: title: OAuth nepieciešama autorizācija scopes: admin:read: lasīt visus datus uz servera - admin:read:accounts: lasīt sensitīvu informāciju no visiem kontiem - admin:read:canonical_email_blocks: lasīt sensitīvu informāciju par visiem kanoniskajiem e-pasta blokiem - admin:read:domain_allows: lasīt visu domēnu sensitīvo informāciju, ko atļauj - admin:read:domain_blocks: lasīt sensitīvu informāciju par visiem domēna blokiem - admin:read:email_domain_blocks: lasīt sensitīvu informāciju par visiem e-pasta domēna blokiem - admin:read:ip_blocks: lasīt sensitīvu informāciju par visiem IP blokiem - admin:read:reports: lasīt sensitīvu informāciju no visiem pārskatiem un kontiem, par kuriem ziņots + admin:read:accounts: lasīt jūtīgu informāciju no visiem kontiem + admin:read:canonical_email_blocks: lasīt jūtīgu informāciju par visiem kanoniskajiem e-pasta blokiem + admin:read:domain_allows: lasīt jūtīgu informāciju par visiem atļautajiem domēniem + admin:read:domain_blocks: lasīt jūtīgu informāciju par visiem domēna blokiem + admin:read:email_domain_blocks: lasīt jūtīgu informāciju par visiem e-pasta domēna blokiem + admin:read:ip_blocks: lasīt jūtīgu informāciju par visiem IP blokiem + admin:read:reports: lasīt jūtīgu informāciju no visiem pārskatiem un kontiem, par kuriem ziņots admin:write: modificēt visus datus uz servera admin:write:accounts: veikt satura pārraudzības darbības kontos admin:write:canonical_email_blocks: veikt satura pārraudzības darbības kanoniskajos e-pasta blokos diff --git a/config/locales/lv.yml b/config/locales/lv.yml index 66c5821bd1..46e170244b 100644 --- a/config/locales/lv.yml +++ b/config/locales/lv.yml @@ -144,8 +144,8 @@ lv: security_measures: only_password: Tikai parole password_and_2fa: Parole un 2FA - sensitive: Sensitīvs - sensitized: Atzīmēts kā sensitīvs + sensitive: Uzspiest atzīmēšanu kā jūtīgu + sensitized: Atzīmēts kā jūtīgu shared_inbox_url: Koplietotās iesūtnes URL show: created_reports: Sastādītie ziņojumi @@ -163,7 +163,7 @@ lv: unblock_email: Atbloķēt e-pasta adresi unblocked_email_msg: Veiksmīgi atbloķēta %{username} e-pasta adrese unconfirmed_email: Neapstiprināts e-pasts - undo_sensitized: Atcelt sensitivizēšanu + undo_sensitized: Atcelt uzspiestu atzīmēšanu kā jūtīgu undo_silenced: Atsaukt ierobežojumu undo_suspension: Atsaukt apturēšanu unsilenced_msg: Veiksmīgi atsaukts %{username} konta ierobežojums @@ -225,12 +225,12 @@ lv: resend_user: Atkārtoti nosūtīt Apstiprinājuma Pastu reset_password_user: Atiestatīt Paroli resolve_report: Atrisināt Ziņojumu - sensitive_account: Piespiedu sensitīvizēt kontu + sensitive_account: Uzspiesti atzimēt kontu kā jūtīgu silence_account: Ierobežot Kontu suspend_account: Apturēt Kontu unassigned_report: Atcelt Pārskata Piešķiršanu unblock_email_account: Atbloķēt e-pasta adresi - unsensitive_account: Atsaukt Konta Piespiedu Sensitivizēšanu + unsensitive_account: Atsaukt uzspiestu konta atzīmēšanu kā jūtīgu unsilence_account: Atcelt Konta Ierobežošanu unsuspend_account: Atcelt konta apturēšanu update_announcement: Atjaunināt Paziņojumu @@ -621,7 +621,7 @@ lv: add_to_report: Pievienot varāk paziņošanai are_you_sure: Vai esi pārliecināts? assign_to_self: Piešķirt man - assigned: Piešķirtais moderators + assigned: Piešķirtais satura pārraudzītājs by_target_domain: Ziņotā konta domēns cancel: Atcelt category: Kategorija diff --git a/config/locales/simple_form.zh-CN.yml b/config/locales/simple_form.zh-CN.yml index 00d669dc19..d1857df502 100644 --- a/config/locales/simple_form.zh-CN.yml +++ b/config/locales/simple_form.zh-CN.yml @@ -88,6 +88,7 @@ zh-CN: favicon: WEBP、PNG、GIF 或 JPG。使用自定义图标覆盖 Mastodon 的默认图标。 mascot: 覆盖高级网页界面中的绘图形象。 media_cache_retention_period: 来自外站用户嘟文的媒体文件将被缓存到你的实例上。当该值被设为正值时,缓存的媒体文件将在指定天数后被清除。如果媒体文件在被清除后重新被请求,且源站内容仍然可用,它将被重新下载。由于链接预览卡拉取第三方站点的频率受到限制,建议将此值设置为至少 14 天,如果小于该值,链接预览卡将不会按需更新。 + min_age: 用户注册时必须确认出生日期 peers_api_enabled: 本站在联邦宇宙中遇到的站点列表。 此处不包含关于您是否与给定站点联合的数据,只是您的实例知道它。 这由收集一般意义上的联合统计信息的服务使用。 profile_directory: 个人资料目录会列出所有选择可被发现的用户。 require_invite_text: 当注册需要手动批准时,将“你为什么想要加入?”设为必填项 @@ -142,6 +143,7 @@ zh-CN: min_age: 不应低于您所在地法律管辖权要求的最低年龄。 user: chosen_languages: 仅选中语言的嘟文会出现在公共时间线上(全不选则显示所有语言的嘟文) + date_of_birth: 我们必须确认%{age}岁以上的用户才能使用Mastodon。我们不会存储该信息。 role: 角色用于控制用户拥有的权限。 user_role: color: 在界面各处用于标记该角色的颜色,以十六进制 RGB 格式表示 diff --git a/config/locales/zh-CN.yml b/config/locales/zh-CN.yml index 457f676e84..5542975143 100644 --- a/config/locales/zh-CN.yml +++ b/config/locales/zh-CN.yml @@ -317,6 +317,7 @@ zh-CN: title: 新公告 preview: explanation_html: 此电子邮件将发送给 %{display_count} 用户。电子邮件将包含以下文本: + title: 预览公告通知 publish: 发布 published_msg: 公告已发布! scheduled_for: 定时在 %{time} @@ -1864,6 +1865,10 @@ zh-CN: recovery_instructions_html: 如果你的手机无法使用,你可以使用下列任意一个恢复代码来重新获得对账号的访问权。请妥善保管好你的恢复代码(例如,你可以将它们打印出来,然后和其他重要的文件放在一起)。 webauthn: 安全密钥 user_mailer: + announcement_published: + description: "%{domain}管理员发布了一则公告:" + subject: 服务公告 + title: "%{domain}服务公告" appeal_approved: action: 账号设置 explanation: 你于 %{appeal_date} 对 %{strike_date} 在你账号上做出的处罚提出的申诉已被批准,你的账号已回到正常状态。 From 2453b9419843a5925485f8881c038d6aaccbbe6f Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Tue, 25 Mar 2025 10:06:51 +0100 Subject: [PATCH 03/12] chore(deps): update dependency nokogiri to v1.18.6 (#34267) 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 f8c830291a..2f0498f7b6 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -440,7 +440,7 @@ GEM net-smtp (0.5.1) net-protocol nio4r (2.7.4) - nokogiri (1.18.5) + nokogiri (1.18.6) mini_portile2 (~> 2.8.2) racc (~> 1.4) oj (3.16.10) From 9bba2aab331c8cbc41eaedd4605a888edc7b8fd2 Mon Sep 17 00:00:00 2001 From: Matt Jankowski Date: Tue, 25 Mar 2025 05:07:22 -0400 Subject: [PATCH 04/12] Convert `intents` spec controller->request (#34261) --- .../intents_spec.rb} | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) rename spec/{controllers/intents_controller_spec.rb => requests/intents_spec.rb} (90%) diff --git a/spec/controllers/intents_controller_spec.rb b/spec/requests/intents_spec.rb similarity index 90% rename from spec/controllers/intents_controller_spec.rb rename to spec/requests/intents_spec.rb index 668d833ea7..b62f570d7a 100644 --- a/spec/controllers/intents_controller_spec.rb +++ b/spec/requests/intents_spec.rb @@ -2,15 +2,15 @@ require 'rails_helper' -RSpec.describe IntentsController do - render_views - +RSpec.describe 'Intents' do let(:user) { Fabricate(:user) } before { sign_in user, scope: :user } - describe 'GET #show' do - subject { get :show, params: { uri: uri } } + describe 'GET /intent' do + subject { response } + + before { get intent_path(uri: uri) } context 'when schema is web+mastodon' do context 'when host is follow' do From ef8f62c3820b433198ef3425604bbe255f04ef03 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Tue, 25 Mar 2025 09:09:25 +0000 Subject: [PATCH 05/12] chore(deps): update dependency mime-types to v3.6.2 (#34266) 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 2f0498f7b6..a78de95ed8 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -417,10 +417,10 @@ GEM redis (>= 3.0.5) matrix (0.4.2) memory_profiler (1.1.0) - mime-types (3.6.1) + mime-types (3.6.2) logger mime-types-data (~> 3.2015) - mime-types-data (3.2025.0304) + mime-types-data (3.2025.0318) mini_mime (1.1.5) mini_portile2 (2.8.8) minitest (5.25.5) From 40bb8ec32509bc16318aa822c9d623fe63dc3128 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Tue, 25 Mar 2025 11:18:00 +0100 Subject: [PATCH 06/12] chore(deps): update dependency selenium-webdriver to v4.30.1 (#34250) 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 a78de95ed8..0daa305f70 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -789,7 +789,7 @@ GEM activerecord (>= 4.0.0) railties (>= 4.0.0) securerandom (0.4.1) - selenium-webdriver (4.29.1) + selenium-webdriver (4.30.1) base64 (~> 0.2) logger (~> 1.4) rexml (~> 3.2, >= 3.2.5) From 38f5e74122f8a863b8c240fc69d38dd7c852fb17 Mon Sep 17 00:00:00 2001 From: Claire Date: Tue, 25 Mar 2025 13:30:10 +0100 Subject: [PATCH 07/12] Add `Deprecation` headers on deprecated endpoints (#34262) Co-authored-by: Damien Mathieu <42@dmathieu.com> --- .../v1/accounts/identity_proofs_controller.rb | 4 ++ app/controllers/api/v1/filters_controller.rb | 4 ++ .../api/v1/instances_controller.rb | 12 ++--- .../api/v1/suggestions_controller.rb | 3 ++ .../api/v1/trends/tags_controller.rb | 4 ++ .../api/v2/instances_controller.rb | 12 ++++- .../concerns/deprecation_concern.rb | 17 +++++++ app/javascript/mastodon/api.ts | 25 +++++++++- spec/requests/api/v1/trends/tags_spec.rb | 4 ++ spec/requests/api/v1/trends_spec.rb | 48 +++++++++++++++++++ 10 files changed, 121 insertions(+), 12 deletions(-) create mode 100644 app/controllers/concerns/deprecation_concern.rb create mode 100644 spec/requests/api/v1/trends_spec.rb diff --git a/app/controllers/api/v1/accounts/identity_proofs_controller.rb b/app/controllers/api/v1/accounts/identity_proofs_controller.rb index 48f293f47a..02a45e8758 100644 --- a/app/controllers/api/v1/accounts/identity_proofs_controller.rb +++ b/app/controllers/api/v1/accounts/identity_proofs_controller.rb @@ -1,6 +1,10 @@ # frozen_string_literal: true class Api::V1::Accounts::IdentityProofsController < Api::BaseController + include DeprecationConcern + + deprecate_api '2022-03-30' + before_action :require_user! before_action :set_account diff --git a/app/controllers/api/v1/filters_controller.rb b/app/controllers/api/v1/filters_controller.rb index ed98acce30..5e9ba5153c 100644 --- a/app/controllers/api/v1/filters_controller.rb +++ b/app/controllers/api/v1/filters_controller.rb @@ -1,6 +1,10 @@ # frozen_string_literal: true class Api::V1::FiltersController < Api::BaseController + include DeprecationConcern + + deprecate_api '2022-11-14' + before_action -> { doorkeeper_authorize! :read, :'read:filters' }, only: [:index, :show] before_action -> { doorkeeper_authorize! :write, :'write:filters' }, except: [:index, :show] before_action :require_user! diff --git a/app/controllers/api/v1/instances_controller.rb b/app/controllers/api/v1/instances_controller.rb index 49da75ed28..e01267c000 100644 --- a/app/controllers/api/v1/instances_controller.rb +++ b/app/controllers/api/v1/instances_controller.rb @@ -1,15 +1,9 @@ # frozen_string_literal: true -class Api::V1::InstancesController < Api::BaseController - skip_before_action :require_authenticated_user!, unless: :limited_federation_mode? - skip_around_action :set_locale +class Api::V1::InstancesController < Api::V2::InstancesController + include DeprecationConcern - vary_by '' - - # Override `current_user` to avoid reading session cookies unless in limited federation mode - def current_user - super if limited_federation_mode? - end + deprecate_api '2022-11-14' def show cache_even_if_authenticated! diff --git a/app/controllers/api/v1/suggestions_controller.rb b/app/controllers/api/v1/suggestions_controller.rb index 9ba1cef63c..918ec45beb 100644 --- a/app/controllers/api/v1/suggestions_controller.rb +++ b/app/controllers/api/v1/suggestions_controller.rb @@ -2,6 +2,9 @@ class Api::V1::SuggestionsController < Api::BaseController include Authorization + include DeprecationConcern + + deprecate_api '2021-05-16' before_action -> { doorkeeper_authorize! :read, :'read:accounts' }, only: :index before_action -> { doorkeeper_authorize! :write, :'write:accounts' }, except: :index diff --git a/app/controllers/api/v1/trends/tags_controller.rb b/app/controllers/api/v1/trends/tags_controller.rb index 10a3442344..f84f1c0252 100644 --- a/app/controllers/api/v1/trends/tags_controller.rb +++ b/app/controllers/api/v1/trends/tags_controller.rb @@ -1,12 +1,16 @@ # frozen_string_literal: true class Api::V1::Trends::TagsController < Api::BaseController + include DeprecationConcern + before_action :set_tags after_action :insert_pagination_headers DEFAULT_TAGS_LIMIT = 10 + deprecate_api '2022-03-30', only: :index, if: -> { request.path == '/api/v1/trends' } + def index cache_if_unauthenticated! render json: @tags, each_serializer: REST::TagSerializer, relationships: TagRelationshipsPresenter.new(@tags, current_user&.account_id) diff --git a/app/controllers/api/v2/instances_controller.rb b/app/controllers/api/v2/instances_controller.rb index 8346e28830..62adf95260 100644 --- a/app/controllers/api/v2/instances_controller.rb +++ b/app/controllers/api/v2/instances_controller.rb @@ -1,6 +1,16 @@ # frozen_string_literal: true -class Api::V2::InstancesController < Api::V1::InstancesController +class Api::V2::InstancesController < Api::BaseController + skip_before_action :require_authenticated_user!, unless: :limited_federation_mode? + skip_around_action :set_locale + + vary_by '' + + # Override `current_user` to avoid reading session cookies unless in limited federation mode + def current_user + super if limited_federation_mode? + end + def show cache_even_if_authenticated! render_with_cache json: InstancePresenter.new, serializer: REST::InstanceSerializer, root: 'instance' diff --git a/app/controllers/concerns/deprecation_concern.rb b/app/controllers/concerns/deprecation_concern.rb new file mode 100644 index 0000000000..ad8de724a1 --- /dev/null +++ b/app/controllers/concerns/deprecation_concern.rb @@ -0,0 +1,17 @@ +# frozen_string_literal: true + +module DeprecationConcern + extend ActiveSupport::Concern + + class_methods do + def deprecate_api(date, sunset: nil, **kwargs) + deprecation_timestamp = "@#{date.to_datetime.to_i}" + sunset = sunset&.to_date&.httpdate + + before_action(**kwargs) do + response.headers['Deprecation'] = deprecation_timestamp + response.headers['Sunset'] = sunset if sunset + end + end + end +end diff --git a/app/javascript/mastodon/api.ts b/app/javascript/mastodon/api.ts index f0663ded40..a41b058d2c 100644 --- a/app/javascript/mastodon/api.ts +++ b/app/javascript/mastodon/api.ts @@ -1,4 +1,9 @@ -import type { AxiosResponse, Method, RawAxiosRequestHeaders } from 'axios'; +import type { + AxiosError, + AxiosResponse, + Method, + RawAxiosRequestHeaders, +} from 'axios'; import axios from 'axios'; import LinkHeader from 'http-link-header'; @@ -41,7 +46,7 @@ const authorizationTokenFromInitialState = (): RawAxiosRequestHeaders => { // eslint-disable-next-line import/no-default-export export default function api(withAuthorization = true) { - return axios.create({ + const instance = axios.create({ transitional: { clarifyTimeoutError: true, }, @@ -60,6 +65,22 @@ export default function api(withAuthorization = true) { }, ], }); + + instance.interceptors.response.use( + (response: AxiosResponse) => { + if (response.headers.deprecation) { + console.warn( + `Deprecated request: ${response.config.method} ${response.config.url}`, + ); + } + return response; + }, + (error: AxiosError) => { + return Promise.reject(error); + }, + ); + + return instance; } type RequestParamsOrData = Record; diff --git a/spec/requests/api/v1/trends/tags_spec.rb b/spec/requests/api/v1/trends/tags_spec.rb index 14ab73fc96..097393e58d 100644 --- a/spec/requests/api/v1/trends/tags_spec.rb +++ b/spec/requests/api/v1/trends/tags_spec.rb @@ -15,6 +15,8 @@ RSpec.describe 'API V1 Trends Tags' do .and not_have_http_link_header expect(response.content_type) .to start_with('application/json') + expect(response.headers['Deprecation']) + .to be_nil end end @@ -31,6 +33,8 @@ RSpec.describe 'API V1 Trends Tags' do .and have_http_link_header(api_v1_trends_tags_url(offset: 2)).for(rel: 'next') expect(response.content_type) .to start_with('application/json') + expect(response.headers['Deprecation']) + .to be_nil end def prepare_trends diff --git a/spec/requests/api/v1/trends_spec.rb b/spec/requests/api/v1/trends_spec.rb new file mode 100644 index 0000000000..5bfabdca1c --- /dev/null +++ b/spec/requests/api/v1/trends_spec.rb @@ -0,0 +1,48 @@ +# frozen_string_literal: true + +require 'rails_helper' + +RSpec.describe 'deprecated API V1 Trends Tags' do + describe 'GET /api/v1/trends' do + context 'when trends are disabled' do + before { Setting.trends = false } + + it 'returns http success' do + get '/api/v1/trends' + + expect(response) + .to have_http_status(200) + .and not_have_http_link_header + expect(response.content_type) + .to start_with('application/json') + expect(response.headers['Deprecation']) + .to start_with '@' + end + end + + context 'when trends are enabled' do + before { Setting.trends = true } + + it 'returns http success' do + prepare_trends + stub_const('Api::V1::Trends::TagsController::DEFAULT_TAGS_LIMIT', 2) + get '/api/v1/trends' + + expect(response) + .to have_http_status(200) + .and have_http_link_header(api_v1_trends_tags_url(offset: 2)).for(rel: 'next') + expect(response.content_type) + .to start_with('application/json') + expect(response.headers['Deprecation']) + .to start_with '@' + end + + def prepare_trends + Fabricate.times(3, :tag, trendable: true).each do |tag| + 2.times { |i| Trends.tags.add(tag, i) } + end + Trends::Tags.new(threshold: 1).refresh + end + end + end +end From 8c3eeb4d29dd5ed492de3518eea51454d26c6e49 Mon Sep 17 00:00:00 2001 From: Claire Date: Tue, 25 Mar 2025 14:11:49 +0100 Subject: [PATCH 08/12] Fix filters not applying in detailed view (#34259) --- .../status/components/detailed_status.tsx | 37 ++++++++++++++----- .../mastodon/features/status/index.jsx | 2 +- app/javascript/mastodon/selectors/index.js | 5 ++- app/javascript/mastodon/utils/filters.ts | 2 + 4 files changed, 34 insertions(+), 12 deletions(-) diff --git a/app/javascript/mastodon/features/status/components/detailed_status.tsx b/app/javascript/mastodon/features/status/components/detailed_status.tsx index f004398fea..26a1adb2bf 100644 --- a/app/javascript/mastodon/features/status/components/detailed_status.tsx +++ b/app/javascript/mastodon/features/status/components/detailed_status.tsx @@ -15,6 +15,7 @@ import AlternateEmailIcon from '@/material-icons/400-24px/alternate_email.svg?re import { AnimatedNumber } from 'mastodon/components/animated_number'; import { ContentWarning } from 'mastodon/components/content_warning'; import EditedTimestamp from 'mastodon/components/edited_timestamp'; +import { FilterWarning } from 'mastodon/components/filter_warning'; import type { StatusLike } from 'mastodon/components/hashtag_bar'; import { getHashtagBarForStatus } from 'mastodon/components/hashtag_bar'; import { Icon } from 'mastodon/components/icon'; @@ -70,6 +71,7 @@ export const DetailedStatus: React.FC<{ }) => { const properStatus = status?.get('reblog') ?? status; const [height, setHeight] = useState(0); + const [showDespiteFilter, setShowDespiteFilter] = useState(false); const nodeRef = useRef(); const handleOpenVideo = useCallback( @@ -82,6 +84,10 @@ export const DetailedStatus: React.FC<{ [onOpenVideo, status], ); + const handleFilterToggle = useCallback(() => { + setShowDespiteFilter(!showDespiteFilter); + }, [showDespiteFilter, setShowDespiteFilter]); + const handleExpandedToggle = useCallback(() => { if (onToggleHidden) onToggleHidden(status); }, [onToggleHidden, status]); @@ -292,8 +298,12 @@ export const DetailedStatus: React.FC<{ const { statusContentProps, hashtagBar } = getHashtagBarForStatus( status as StatusLike, ); + + const matchedFilters = status.get('matched_filters'); + const expanded = - !status.get('hidden') || status.get('spoiler_text').length === 0; + (!matchedFilters || showDespiteFilter) && + (!status.get('hidden') || status.get('spoiler_text').length === 0); return (
@@ -334,17 +344,26 @@ export const DetailedStatus: React.FC<{ )} - {status.get('spoiler_text').length > 0 && ( - )} + {status.get('spoiler_text').length > 0 && + (!matchedFilters || showDespiteFilter) && ( + + )} + {expanded && ( <> { }); const mapStateToProps = (state, props) => { - const status = getStatus(state, { id: props.params.statusId }); + const status = getStatus(state, { id: props.params.statusId, contextType: 'detailed' }); let ancestorsIds = ImmutableList(); let descendantsIds = ImmutableList(); diff --git a/app/javascript/mastodon/selectors/index.js b/app/javascript/mastodon/selectors/index.js index d1523abc44..d08df9fe31 100644 --- a/app/javascript/mastodon/selectors/index.js +++ b/app/javascript/mastodon/selectors/index.js @@ -15,9 +15,10 @@ export const makeGetStatus = () => { (state, { id }) => state.getIn(['accounts', state.getIn(['statuses', id, 'account'])]), (state, { id }) => state.getIn(['accounts', state.getIn(['statuses', state.getIn(['statuses', id, 'reblog']), 'account'])]), getFilters, + (_, { contextType }) => contextType === 'detailed', ], - (statusBase, statusReblog, accountBase, accountReblog, filters) => { + (statusBase, statusReblog, accountBase, accountReblog, filters, warnInsteadOfHide) => { if (!statusBase || statusBase.get('isLoading')) { return null; } @@ -31,7 +32,7 @@ export const makeGetStatus = () => { let filtered = false; if ((accountReblog || accountBase).get('id') !== me && filters) { let filterResults = statusReblog?.get('filtered') || statusBase.get('filtered') || ImmutableList(); - if (filterResults.some((result) => filters.getIn([result.get('filter'), 'filter_action']) === 'hide')) { + if (!warnInsteadOfHide && filterResults.some((result) => filters.getIn([result.get('filter'), 'filter_action']) === 'hide')) { return null; } filterResults = filterResults.filter(result => filters.has(result.get('filter'))); diff --git a/app/javascript/mastodon/utils/filters.ts b/app/javascript/mastodon/utils/filters.ts index d299e80c40..c944599bb9 100644 --- a/app/javascript/mastodon/utils/filters.ts +++ b/app/javascript/mastodon/utils/filters.ts @@ -6,6 +6,8 @@ export const toServerSideType = (columnType: string) => { case 'thread': case 'account': return columnType; + case 'detailed': + return 'thread'; default: if (columnType.includes('list:')) { return 'home'; From 2eb6d815d63b91d4d3b6e7eb1a717350a7093e2b Mon Sep 17 00:00:00 2001 From: Claire Date: Tue, 25 Mar 2025 16:20:36 +0100 Subject: [PATCH 09/12] Fix bookmarks and favourites not being filtered (#34260) --- app/javascript/mastodon/features/bookmarked_statuses/index.jsx | 1 + app/javascript/mastodon/features/favourited_statuses/index.jsx | 1 + app/javascript/mastodon/selectors/index.js | 2 +- app/javascript/mastodon/utils/filters.ts | 3 +++ 4 files changed, 6 insertions(+), 1 deletion(-) diff --git a/app/javascript/mastodon/features/bookmarked_statuses/index.jsx b/app/javascript/mastodon/features/bookmarked_statuses/index.jsx index 5494ad44b0..122baafd6c 100644 --- a/app/javascript/mastodon/features/bookmarked_statuses/index.jsx +++ b/app/javascript/mastodon/features/bookmarked_statuses/index.jsx @@ -99,6 +99,7 @@ class Bookmarks extends ImmutablePureComponent { onLoadMore={this.handleLoadMore} emptyMessage={emptyMessage} bindToDocument={!multiColumn} + timelineId='bookmarks' /> diff --git a/app/javascript/mastodon/features/favourited_statuses/index.jsx b/app/javascript/mastodon/features/favourited_statuses/index.jsx index 8e65ff5b68..9e0b982239 100644 --- a/app/javascript/mastodon/features/favourited_statuses/index.jsx +++ b/app/javascript/mastodon/features/favourited_statuses/index.jsx @@ -99,6 +99,7 @@ class Favourites extends ImmutablePureComponent { onLoadMore={this.handleLoadMore} emptyMessage={emptyMessage} bindToDocument={!multiColumn} + timelineId='favourites' /> diff --git a/app/javascript/mastodon/selectors/index.js b/app/javascript/mastodon/selectors/index.js index d08df9fe31..dfd6f19893 100644 --- a/app/javascript/mastodon/selectors/index.js +++ b/app/javascript/mastodon/selectors/index.js @@ -15,7 +15,7 @@ export const makeGetStatus = () => { (state, { id }) => state.getIn(['accounts', state.getIn(['statuses', id, 'account'])]), (state, { id }) => state.getIn(['accounts', state.getIn(['statuses', state.getIn(['statuses', id, 'reblog']), 'account'])]), getFilters, - (_, { contextType }) => contextType === 'detailed', + (_, { contextType }) => ['detailed', 'bookmarks', 'favourites'].includes(contextType), ], (statusBase, statusReblog, accountBase, accountReblog, filters, warnInsteadOfHide) => { diff --git a/app/javascript/mastodon/utils/filters.ts b/app/javascript/mastodon/utils/filters.ts index c944599bb9..a4a1c38294 100644 --- a/app/javascript/mastodon/utils/filters.ts +++ b/app/javascript/mastodon/utils/filters.ts @@ -8,6 +8,9 @@ export const toServerSideType = (columnType: string) => { return columnType; case 'detailed': return 'thread'; + case 'bookmarks': + case 'favourites': + return 'home'; default: if (columnType.includes('list:')) { return 'home'; From 81b88095b4ca27a2f6122f145a0c760520c8e0ba Mon Sep 17 00:00:00 2001 From: Echo Date: Tue, 25 Mar 2025 16:20:56 +0100 Subject: [PATCH 10/12] Allow devcontainer to be accessed from local network (#34269) --- .devcontainer/compose.yaml | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/.devcontainer/compose.yaml b/.devcontainer/compose.yaml index 4d5ed0f25f..5da1ec3a24 100644 --- a/.devcontainer/compose.yaml +++ b/.devcontainer/compose.yaml @@ -21,12 +21,13 @@ services: ES_HOST: es ES_PORT: '9200' LIBRE_TRANSLATE_ENDPOINT: http://libretranslate:5000 + LOCAL_DOMAIN: ${LOCAL_DOMAIN:-localhost:3000} # Overrides default command so things don't shut down after the process ends. command: sleep infinity ports: - - '127.0.0.1:3000:3000' - - '127.0.0.1:3035:3035' - - '127.0.0.1:4000:4000' + - '3000:3000' + - '3035:3035' + - '4000:4000' networks: - external_network - internal_network From 3edac14f022ae720d524ebae4ed95e36ed3f3797 Mon Sep 17 00:00:00 2001 From: Claire Date: Tue, 25 Mar 2025 16:50:05 +0100 Subject: [PATCH 11/12] Fix follower synchronization mechanism erroneously removing followers from multi-page collections (#34272) --- .../synchronize_followers_service.rb | 3 ++ .../synchronize_followers_service_spec.rb | 41 +++++++++++++++---- 2 files changed, 36 insertions(+), 8 deletions(-) diff --git a/app/services/activitypub/synchronize_followers_service.rb b/app/services/activitypub/synchronize_followers_service.rb index b01974dcc6..f9baca38b9 100644 --- a/app/services/activitypub/synchronize_followers_service.rb +++ b/app/services/activitypub/synchronize_followers_service.rb @@ -57,6 +57,9 @@ class ActivityPub::SynchronizeFollowersService < BaseService collection = fetch_collection(collection['first']) if collection['first'].present? return unless collection.is_a?(Hash) + # Abort if we'd have to paginate through more than one page of followers + return if collection['next'].present? + case collection['type'] when 'Collection', 'CollectionPage' as_array(collection['items']) diff --git a/spec/services/activitypub/synchronize_followers_service_spec.rb b/spec/services/activitypub/synchronize_followers_service_spec.rb index 974368b7d7..3399e4fdf0 100644 --- a/spec/services/activitypub/synchronize_followers_service_spec.rb +++ b/spec/services/activitypub/synchronize_followers_service_spec.rb @@ -27,14 +27,14 @@ RSpec.describe ActivityPub::SynchronizeFollowersService do }.with_indifferent_access end + before do + alice.follow!(actor) + bob.follow!(actor) + mallory.request_follow!(actor) + end + shared_examples 'synchronizes followers' do before do - alice.follow!(actor) - bob.follow!(actor) - mallory.request_follow!(actor) - - allow(ActivityPub::DeliveryWorker).to receive(:perform_async) - subject.call(actor, collection_uri) end @@ -46,7 +46,7 @@ RSpec.describe ActivityPub::SynchronizeFollowersService do expect(mallory) .to be_following(actor) # Convert follow request to follow when accepted expect(ActivityPub::DeliveryWorker) - .to have_received(:perform_async).with(anything, eve.id, actor.inbox_url) # Send Undo Follow to actor + .to have_enqueued_sidekiq_job(anything, eve.id, actor.inbox_url) # Send Undo Follow to actor end end @@ -76,7 +76,7 @@ RSpec.describe ActivityPub::SynchronizeFollowersService do it_behaves_like 'synchronizes followers' end - context 'when the endpoint is a paginated Collection of actor URIs' do + context 'when the endpoint is a single-page paginated Collection of actor URIs' do let(:payload) do { '@context': 'https://www.w3.org/ns/activitystreams', @@ -96,5 +96,30 @@ RSpec.describe ActivityPub::SynchronizeFollowersService do it_behaves_like 'synchronizes followers' end + + context 'when the endpoint is a paginated Collection of actor URIs with a next page' do + let(:payload) do + { + '@context': 'https://www.w3.org/ns/activitystreams', + type: 'Collection', + id: collection_uri, + first: { + type: 'CollectionPage', + partOf: collection_uri, + items: items, + next: "#{collection_uri}/page2", + }, + }.with_indifferent_access + end + + before do + stub_request(:get, collection_uri).to_return(status: 200, body: Oj.dump(payload), headers: { 'Content-Type': 'application/activity+json' }) + end + + it 'does not change followers' do + expect { subject.call(actor, collection_uri) } + .to_not(change { actor.followers.reload.reorder(id: :asc).pluck(:id) }) + end + end end end From e1dbbf6c9db6dbf3f356dae4c59fa05299372370 Mon Sep 17 00:00:00 2001 From: Matt Jankowski Date: Tue, 25 Mar 2025 12:22:41 -0400 Subject: [PATCH 12/12] Isolate assertions in v2/notifications intermittent failure cases (#34271) --- spec/requests/api/v2/notifications_spec.rb | 30 ++++++++++------------ 1 file changed, 14 insertions(+), 16 deletions(-) diff --git a/spec/requests/api/v2/notifications_spec.rb b/spec/requests/api/v2/notifications_spec.rb index a7608e1419..a434deaed9 100644 --- a/spec/requests/api/v2/notifications_spec.rb +++ b/spec/requests/api/v2/notifications_spec.rb @@ -158,14 +158,13 @@ RSpec.describe 'Notifications' do expect(response).to have_http_status(200) expect(response.content_type) .to start_with('application/json') - expect(response.parsed_body[:notification_groups]).to contain_exactly( - a_hash_including( - type: 'favourite', - sample_account_ids: have_attributes(size: 5), - page_min_id: notification_ids.first.to_s, - page_max_id: notification_ids.last.to_s - ) - ) + expect(response.parsed_body[:notification_groups].size) + .to eq(1) + expect(response.parsed_body.dig(:notification_groups, 0)) + .to include(type: 'favourite') + .and(include(sample_account_ids: have_attributes(size: 5))) + .and(include(page_max_id: notification_ids.last.to_s)) + .and(include(page_min_id: notification_ids.first.to_s)) end end @@ -180,14 +179,13 @@ RSpec.describe 'Notifications' do expect(response).to have_http_status(200) expect(response.content_type) .to start_with('application/json') - expect(response.parsed_body[:notification_groups]).to contain_exactly( - a_hash_including( - type: 'favourite', - sample_account_ids: have_attributes(size: 5), - page_min_id: notification_ids.first.to_s, - page_max_id: notification_ids.last.to_s - ) - ) + expect(response.parsed_body[:notification_groups].size) + .to eq(1) + expect(response.parsed_body.dig(:notification_groups, 0)) + .to include(type: 'favourite') + .and(include(sample_account_ids: have_attributes(size: 5))) + .and(include(page_max_id: notification_ids.last.to_s)) + .and(include(page_min_id: notification_ids.first.to_s)) end end end