From 2ec9bff36e3a7efef501ec796d27cd73cede904c Mon Sep 17 00:00:00 2001
From: Matt Jankowski <matt@jankowski.online>
Date: Mon, 22 Apr 2024 04:04:05 -0400
Subject: [PATCH 01/19] Fix Rubocop `Rails/UniqueValidationWithoutIndex` cop
 (#27461)

Co-authored-by: Claire <claire.github-309c@sitedethib.com>
---
 .rubocop_todo.yml                             |  9 ----
 ...o_webauthn_credentials_user_id_nickname.rb | 49 +++++++++++++++++++
 ...d_index_to_account_alias_uri_account_id.rb | 49 +++++++++++++++++++
 ...om_filter_statuses_status_custom_filter.rb | 49 +++++++++++++++++++
 ...59_add_index_to_identities_uid_provider.rb | 49 +++++++++++++++++++
 db/schema.rb                                  |  4 ++
 lib/tasks/tests.rake                          | 39 +++++++++++++++
 7 files changed, 239 insertions(+), 9 deletions(-)
 create mode 100644 db/migrate/20231018192110_add_index_to_webauthn_credentials_user_id_nickname.rb
 create mode 100644 db/migrate/20231018193209_add_index_to_account_alias_uri_account_id.rb
 create mode 100644 db/migrate/20231018193355_add_index_to_custom_filter_statuses_status_custom_filter.rb
 create mode 100644 db/migrate/20231018193659_add_index_to_identities_uid_provider.rb

diff --git a/.rubocop_todo.yml b/.rubocop_todo.yml
index 0bc9d2831..3f2e9aee6 100644
--- a/.rubocop_todo.yml
+++ b/.rubocop_todo.yml
@@ -54,15 +54,6 @@ Rails/OutputSafety:
   Exclude:
     - 'config/initializers/simple_form.rb'
 
-# Configuration parameters: Include.
-# Include: app/models/**/*.rb
-Rails/UniqueValidationWithoutIndex:
-  Exclude:
-    - 'app/models/account_alias.rb'
-    - 'app/models/custom_filter_status.rb'
-    - 'app/models/identity.rb'
-    - 'app/models/webauthn_credential.rb'
-
 # This cop supports unsafe autocorrection (--autocorrect-all).
 # Configuration parameters: AllowedMethods, AllowedPatterns.
 # AllowedMethods: ==, equal?, eql?
diff --git a/db/migrate/20231018192110_add_index_to_webauthn_credentials_user_id_nickname.rb b/db/migrate/20231018192110_add_index_to_webauthn_credentials_user_id_nickname.rb
new file mode 100644
index 000000000..2e608eead
--- /dev/null
+++ b/db/migrate/20231018192110_add_index_to_webauthn_credentials_user_id_nickname.rb
@@ -0,0 +1,49 @@
+# frozen_string_literal: true
+
+class AddIndexToWebauthnCredentialsUserIdNickname < ActiveRecord::Migration[7.0]
+  disable_ddl_transaction!
+
+  def up
+    add_index_to_table
+  rescue ActiveRecord::RecordNotUnique
+    remove_duplicates_and_reindex
+  end
+
+  def down
+    remove_index_from_table
+  end
+
+  private
+
+  def remove_duplicates_and_reindex
+    deduplicate_records
+    reindex_records
+  rescue ActiveRecord::RecordNotUnique
+    retry
+  end
+
+  def reindex_records
+    remove_index_from_table
+    add_index_to_table
+  end
+
+  def add_index_to_table
+    add_index :webauthn_credentials, [:user_id, :nickname], unique: true, algorithm: :concurrently
+  end
+
+  def remove_index_from_table
+    remove_index :webauthn_credentials, [:user_id, :nickname]
+  end
+
+  def deduplicate_records
+    safety_assured do
+      execute <<~SQL.squish
+        DELETE FROM webauthn_credentials
+          WHERE id NOT IN (
+          SELECT DISTINCT ON(user_id, nickname) id FROM webauthn_credentials
+          ORDER BY user_id, nickname, id ASC
+        )
+      SQL
+    end
+  end
+end
diff --git a/db/migrate/20231018193209_add_index_to_account_alias_uri_account_id.rb b/db/migrate/20231018193209_add_index_to_account_alias_uri_account_id.rb
new file mode 100644
index 000000000..4d9036fdf
--- /dev/null
+++ b/db/migrate/20231018193209_add_index_to_account_alias_uri_account_id.rb
@@ -0,0 +1,49 @@
+# frozen_string_literal: true
+
+class AddIndexToAccountAliasUriAccountId < ActiveRecord::Migration[7.0]
+  disable_ddl_transaction!
+
+  def up
+    add_index_to_table
+  rescue ActiveRecord::RecordNotUnique
+    remove_duplicates_and_reindex
+  end
+
+  def down
+    remove_index_from_table
+  end
+
+  private
+
+  def remove_duplicates_and_reindex
+    deduplicate_records
+    reindex_records
+  rescue ActiveRecord::RecordNotUnique
+    retry
+  end
+
+  def reindex_records
+    remove_index_from_table
+    add_index_to_table
+  end
+
+  def add_index_to_table
+    add_index :account_aliases, [:account_id, :uri], unique: true, algorithm: :concurrently
+  end
+
+  def remove_index_from_table
+    remove_index :account_aliases, [:account_id, :uri]
+  end
+
+  def deduplicate_records
+    safety_assured do
+      execute <<~SQL.squish
+        DELETE FROM account_aliases
+          WHERE id NOT IN (
+          SELECT DISTINCT ON(account_id, uri) id FROM account_aliases
+          ORDER BY account_id, uri, id ASC
+        )
+      SQL
+    end
+  end
+end
diff --git a/db/migrate/20231018193355_add_index_to_custom_filter_statuses_status_custom_filter.rb b/db/migrate/20231018193355_add_index_to_custom_filter_statuses_status_custom_filter.rb
new file mode 100644
index 000000000..4a23a8a94
--- /dev/null
+++ b/db/migrate/20231018193355_add_index_to_custom_filter_statuses_status_custom_filter.rb
@@ -0,0 +1,49 @@
+# frozen_string_literal: true
+
+class AddIndexToCustomFilterStatusesStatusCustomFilter < ActiveRecord::Migration[7.0]
+  disable_ddl_transaction!
+
+  def up
+    add_index_to_table
+  rescue ActiveRecord::RecordNotUnique
+    remove_duplicates_and_reindex
+  end
+
+  def down
+    remove_index_from_table
+  end
+
+  private
+
+  def remove_duplicates_and_reindex
+    deduplicate_records
+    reindex_records
+  rescue ActiveRecord::RecordNotUnique
+    retry
+  end
+
+  def reindex_records
+    remove_index_from_table
+    add_index_to_table
+  end
+
+  def add_index_to_table
+    add_index :custom_filter_statuses, [:status_id, :custom_filter_id], unique: true, algorithm: :concurrently
+  end
+
+  def remove_index_from_table
+    remove_index :custom_filter_statuses, [:status_id, :custom_filter_id]
+  end
+
+  def deduplicate_records
+    safety_assured do
+      execute <<~SQL.squish
+        DELETE FROM custom_filter_statuses
+          WHERE id NOT IN (
+          SELECT DISTINCT ON(status_id, custom_filter_id) id FROM custom_filter_statuses
+          ORDER BY status_id, custom_filter_id, id ASC
+        )
+      SQL
+    end
+  end
+end
diff --git a/db/migrate/20231018193659_add_index_to_identities_uid_provider.rb b/db/migrate/20231018193659_add_index_to_identities_uid_provider.rb
new file mode 100644
index 000000000..f0ba08b57
--- /dev/null
+++ b/db/migrate/20231018193659_add_index_to_identities_uid_provider.rb
@@ -0,0 +1,49 @@
+# frozen_string_literal: true
+
+class AddIndexToIdentitiesUidProvider < ActiveRecord::Migration[7.0]
+  disable_ddl_transaction!
+
+  def up
+    add_index_to_table
+  rescue ActiveRecord::RecordNotUnique
+    remove_duplicates_and_reindex
+  end
+
+  def down
+    remove_index_from_table
+  end
+
+  private
+
+  def remove_duplicates_and_reindex
+    deduplicate_records
+    reindex_records
+  rescue ActiveRecord::RecordNotUnique
+    retry
+  end
+
+  def reindex_records
+    remove_index_from_table
+    add_index_to_table
+  end
+
+  def add_index_to_table
+    add_index :identities, [:uid, :provider], unique: true, algorithm: :concurrently
+  end
+
+  def remove_index_from_table
+    remove_index :identities, [:uid, :provider]
+  end
+
+  def deduplicate_records
+    safety_assured do
+      execute <<~SQL.squish
+        DELETE FROM identities
+          WHERE id NOT IN (
+          SELECT DISTINCT ON(uid, provider) id FROM identities
+          ORDER BY uid, provider, id ASC
+        )
+      SQL
+    end
+  end
+end
diff --git a/db/schema.rb b/db/schema.rb
index 27c486487..6a52333a8 100644
--- a/db/schema.rb
+++ b/db/schema.rb
@@ -20,6 +20,7 @@ ActiveRecord::Schema[7.1].define(version: 2024_03_22_161611) do
     t.string "uri", default: "", null: false
     t.datetime "created_at", precision: nil, null: false
     t.datetime "updated_at", precision: nil, null: false
+    t.index ["account_id", "uri"], name: "index_account_aliases_on_account_id_and_uri", unique: true
     t.index ["account_id"], name: "index_account_aliases_on_account_id"
   end
 
@@ -395,6 +396,7 @@ ActiveRecord::Schema[7.1].define(version: 2024_03_22_161611) do
     t.datetime "created_at", null: false
     t.datetime "updated_at", null: false
     t.index ["custom_filter_id"], name: "index_custom_filter_statuses_on_custom_filter_id"
+    t.index ["status_id", "custom_filter_id"], name: "index_custom_filter_statuses_on_status_id_and_custom_filter_id", unique: true
     t.index ["status_id"], name: "index_custom_filter_statuses_on_status_id"
   end
 
@@ -545,6 +547,7 @@ ActiveRecord::Schema[7.1].define(version: 2024_03_22_161611) do
     t.datetime "created_at", precision: nil, null: false
     t.datetime "updated_at", precision: nil, null: false
     t.bigint "user_id"
+    t.index ["uid", "provider"], name: "index_identities_on_uid_and_provider", unique: true
     t.index ["user_id"], name: "index_identities_on_user_id"
   end
 
@@ -1235,6 +1238,7 @@ ActiveRecord::Schema[7.1].define(version: 2024_03_22_161611) do
     t.datetime "created_at", precision: nil, null: false
     t.datetime "updated_at", precision: nil, null: false
     t.index ["external_id"], name: "index_webauthn_credentials_on_external_id", unique: true
+    t.index ["user_id", "nickname"], name: "index_webauthn_credentials_on_user_id_and_nickname", unique: true
     t.index ["user_id"], name: "index_webauthn_credentials_on_user_id"
   end
 
diff --git a/lib/tasks/tests.rake b/lib/tasks/tests.rake
index 6afc013ed..0caebf92a 100644
--- a/lib/tasks/tests.rake
+++ b/lib/tasks/tests.rake
@@ -8,6 +8,7 @@ namespace :tests do
         '2' => 2017_10_10_025614,
         '2_4' => 2018_05_14_140000,
         '2_4_3' => 2018_07_07_154237,
+        '3_3_0' => 2020_12_18_054746,
       }.each do |release, version|
         ActiveRecord::Tasks::DatabaseTasks
           .migration_connection
@@ -111,9 +112,41 @@ namespace :tests do
         exit(1)
       end
 
+      unless Identity.where(provider: 'foo', uid: 0).count == 1
+        puts 'Identities not deduplicated as expected'
+        exit(1)
+      end
+
+      unless WebauthnCredential.where(user_id: 1, nickname: 'foo').count == 1
+        puts 'Webauthn credentials not deduplicated as expected'
+        exit(1)
+      end
+
+      unless AccountAlias.where(account_id: 1, uri: 'https://example.com/users/foobar').count == 1
+        puts 'Account aliases not deduplicated as expected'
+        exit(1)
+      end
+
       puts 'No errors found. Database state is consistent with a successful migration process.'
     end
 
+    desc 'Populate the database with test data for 3.3.0'
+    task populate_v3_3_0: :environment do # rubocop:disable Naming/VariableNumber
+      ActiveRecord::Base.connection.execute(<<~SQL.squish)
+        INSERT INTO "webauthn_credentials"
+          (user_id, nickname, external_id, public_key, created_at, updated_at)
+        VALUES
+          (1, 'foo', 1, 'foo', now(), now()),
+          (1, 'foo', 2, 'bar', now(), now());
+
+        INSERT INTO "account_aliases"
+          (account_id, uri, acct, created_at, updated_at)
+        VALUES
+          (1, 'https://example.com/users/foobar', 'foobar@example.com', now(), now()),
+          (1, 'https://example.com/users/foobar', 'foobar@example.com', now(), now());
+      SQL
+    end
+
     desc 'Populate the database with test data for 2.4.3'
     task populate_v2_4_3: :environment do # rubocop:disable Naming/VariableNumber
       user_key = OpenSSL::PKey::RSA.new(2048)
@@ -189,6 +222,12 @@ namespace :tests do
         VALUES
           (5, 'User', 4, 'default_language', E'--- kmr\n', now(), now()),
           (6, 'User', 1, 'interactions', E'--- !ruby/hash:ActiveSupport::HashWithIndifferentAccess\nmust_be_follower: false\nmust_be_following: true\nmust_be_following_dm: false\n', now(), now());
+
+        INSERT INTO "identities"
+          (provider, uid, user_id, created_at, updated_at)
+        VALUES
+          ('foo', 0, 1, now(), now()),
+          ('foo', 0, 1, now(), now());
       SQL
     end
 

From 223936c2e8237d83fcf403c8dcca80aa201157f0 Mon Sep 17 00:00:00 2001
From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com>
Date: Mon, 22 Apr 2024 10:13:04 +0200
Subject: [PATCH 02/19] Update eslint (non-major) to v7.7.0 (#30026)

Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
---
 yarn.lock | 159 ++++++++++++++++++++++++++++--------------------------
 1 file changed, 84 insertions(+), 75 deletions(-)

diff --git a/yarn.lock b/yarn.lock
index c0d1e91b6..e0001120a 100644
--- a/yarn.lock
+++ b/yarn.lock
@@ -2154,7 +2154,7 @@ __metadata:
   languageName: node
   linkType: hard
 
-"@eslint-community/regexpp@npm:^4.5.1, @eslint-community/regexpp@npm:^4.6.1":
+"@eslint-community/regexpp@npm:^4.10.0, @eslint-community/regexpp@npm:^4.6.1":
   version: 4.10.0
   resolution: "@eslint-community/regexpp@npm:4.10.0"
   checksum: 10c0/c5f60ef1f1ea7649fa7af0e80a5a79f64b55a8a8fa5086de4727eb4c86c652aedee407a9c143b8995d2c0b2d75c1222bec9ba5d73dbfc1f314550554f0979ef4
@@ -3619,10 +3619,10 @@ __metadata:
   languageName: node
   linkType: hard
 
-"@types/json-schema@npm:*, @types/json-schema@npm:^7.0.12, @types/json-schema@npm:^7.0.5, @types/json-schema@npm:^7.0.8":
-  version: 7.0.14
-  resolution: "@types/json-schema@npm:7.0.14"
-  checksum: 10c0/da68689ccd44cb93ca4c9a4af3b25c6091ecf45fb370d1ed0d0ac5b780e235bf0b9bdc1f7e28f19e6713b22567c3db11fefcbcc6d48ac6b356d035a8f9f4ea30
+"@types/json-schema@npm:*, @types/json-schema@npm:^7.0.12, @types/json-schema@npm:^7.0.15, @types/json-schema@npm:^7.0.5, @types/json-schema@npm:^7.0.8":
+  version: 7.0.15
+  resolution: "@types/json-schema@npm:7.0.15"
+  checksum: 10c0/a996a745e6c5d60292f36731dd41341339d4eeed8180bb09226e5c8d23759067692b1d88e5d91d72ee83dfc00d3aca8e7bd43ea120516c17922cbcb7c3e252db
   languageName: node
   linkType: hard
 
@@ -3897,10 +3897,10 @@ __metadata:
   languageName: node
   linkType: hard
 
-"@types/semver@npm:^7.5.0":
-  version: 7.5.4
-  resolution: "@types/semver@npm:7.5.4"
-  checksum: 10c0/dee66a71d9f089c118be74b5937d4fef42864d68d9472a3f4f5399b9e3ad74d56a8e155020c846667b9ecf9de78fdb9ea55a53fff5067af28e06779b282b6c40
+"@types/semver@npm:^7.5.0, @types/semver@npm:^7.5.8":
+  version: 7.5.8
+  resolution: "@types/semver@npm:7.5.8"
+  checksum: 10c0/8663ff927234d1c5fcc04b33062cb2b9fcfbe0f5f351ed26c4d1e1581657deebd506b41ff7fdf89e787e3d33ce05854bc01686379b89e9c49b564c4cfa988efa
   languageName: node
   linkType: hard
 
@@ -4041,45 +4041,45 @@ __metadata:
   linkType: hard
 
 "@typescript-eslint/eslint-plugin@npm:^7.0.0":
-  version: 7.5.0
-  resolution: "@typescript-eslint/eslint-plugin@npm:7.5.0"
+  version: 7.7.0
+  resolution: "@typescript-eslint/eslint-plugin@npm:7.7.0"
   dependencies:
-    "@eslint-community/regexpp": "npm:^4.5.1"
-    "@typescript-eslint/scope-manager": "npm:7.5.0"
-    "@typescript-eslint/type-utils": "npm:7.5.0"
-    "@typescript-eslint/utils": "npm:7.5.0"
-    "@typescript-eslint/visitor-keys": "npm:7.5.0"
+    "@eslint-community/regexpp": "npm:^4.10.0"
+    "@typescript-eslint/scope-manager": "npm:7.7.0"
+    "@typescript-eslint/type-utils": "npm:7.7.0"
+    "@typescript-eslint/utils": "npm:7.7.0"
+    "@typescript-eslint/visitor-keys": "npm:7.7.0"
     debug: "npm:^4.3.4"
     graphemer: "npm:^1.4.0"
-    ignore: "npm:^5.2.4"
+    ignore: "npm:^5.3.1"
     natural-compare: "npm:^1.4.0"
-    semver: "npm:^7.5.4"
-    ts-api-utils: "npm:^1.0.1"
+    semver: "npm:^7.6.0"
+    ts-api-utils: "npm:^1.3.0"
   peerDependencies:
     "@typescript-eslint/parser": ^7.0.0
     eslint: ^8.56.0
   peerDependenciesMeta:
     typescript:
       optional: true
-  checksum: 10c0/932a7b5a09c0138ef5a0bf00f8e6039fa209d4047092ffc187de048543c21f7ce24dc14f25f4c87b6f3bbb62335fc952e259e271fde88baf793217bde6460cfa
+  checksum: 10c0/d1f4c40523d284bce4b8272750c68aae5c0289ddb1c9267dd3477e0bfb8c8855bfb0c6e86dfec9911ca8302ef729d5f4e47d686a566f363b0f89bf7dc7670b5c
   languageName: node
   linkType: hard
 
 "@typescript-eslint/parser@npm:^7.0.0":
-  version: 7.5.0
-  resolution: "@typescript-eslint/parser@npm:7.5.0"
+  version: 7.7.0
+  resolution: "@typescript-eslint/parser@npm:7.7.0"
   dependencies:
-    "@typescript-eslint/scope-manager": "npm:7.5.0"
-    "@typescript-eslint/types": "npm:7.5.0"
-    "@typescript-eslint/typescript-estree": "npm:7.5.0"
-    "@typescript-eslint/visitor-keys": "npm:7.5.0"
+    "@typescript-eslint/scope-manager": "npm:7.7.0"
+    "@typescript-eslint/types": "npm:7.7.0"
+    "@typescript-eslint/typescript-estree": "npm:7.7.0"
+    "@typescript-eslint/visitor-keys": "npm:7.7.0"
     debug: "npm:^4.3.4"
   peerDependencies:
     eslint: ^8.56.0
   peerDependenciesMeta:
     typescript:
       optional: true
-  checksum: 10c0/65521202ff024e79594272fbb7e4731ecf9d2fdd2f58fc81450bfd2bca94ce9c17b0eadd7338c01701f5cf16d38b6c025ed3fc322380b1e4b5424b7484098cda
+  checksum: 10c0/d756c2292737499a93913647af7493aded5dc720a5f4ab6f8e96d6cc81f19cf6a1769a1df0f516f8facd276d34f8464f1711e57b0216082e32eb6b75da81b12e
   languageName: node
   linkType: hard
 
@@ -4093,30 +4093,30 @@ __metadata:
   languageName: node
   linkType: hard
 
-"@typescript-eslint/scope-manager@npm:7.5.0":
-  version: 7.5.0
-  resolution: "@typescript-eslint/scope-manager@npm:7.5.0"
+"@typescript-eslint/scope-manager@npm:7.7.0":
+  version: 7.7.0
+  resolution: "@typescript-eslint/scope-manager@npm:7.7.0"
   dependencies:
-    "@typescript-eslint/types": "npm:7.5.0"
-    "@typescript-eslint/visitor-keys": "npm:7.5.0"
-  checksum: 10c0/a017b151a6b39ef591f8e2e65598e005e1b4b2d5494e4b91bddb5856b3a4d57dd8a58d2bc7a140e627eb574f93a2c8fe55f1307aa264c928ffd31d9e190bc5dd
+    "@typescript-eslint/types": "npm:7.7.0"
+    "@typescript-eslint/visitor-keys": "npm:7.7.0"
+  checksum: 10c0/014a3631c12bfbd5e33146a48e4b9eb5cc1c5c95bb458de33f8847eed33c04d7b9e66283971e48297673c4b92c3239d67e6dc3717efbe5836e0269a538c13d2e
   languageName: node
   linkType: hard
 
-"@typescript-eslint/type-utils@npm:7.5.0":
-  version: 7.5.0
-  resolution: "@typescript-eslint/type-utils@npm:7.5.0"
+"@typescript-eslint/type-utils@npm:7.7.0":
+  version: 7.7.0
+  resolution: "@typescript-eslint/type-utils@npm:7.7.0"
   dependencies:
-    "@typescript-eslint/typescript-estree": "npm:7.5.0"
-    "@typescript-eslint/utils": "npm:7.5.0"
+    "@typescript-eslint/typescript-estree": "npm:7.7.0"
+    "@typescript-eslint/utils": "npm:7.7.0"
     debug: "npm:^4.3.4"
-    ts-api-utils: "npm:^1.0.1"
+    ts-api-utils: "npm:^1.3.0"
   peerDependencies:
     eslint: ^8.56.0
   peerDependenciesMeta:
     typescript:
       optional: true
-  checksum: 10c0/12915d4d1872638f5281e222a0d191676c478f250699c84864862e95a59e708222acefbf7ffdafc0872a007261219a3a2b1e667ff45eeafea7c4bcc5b955262c
+  checksum: 10c0/064c28d4087a97fd175e07e02c0a9cf4526f61cc6a17b4199fba626932979210037643a30f868bda8174fad567a8ac6aed34120631d1ecfd502e0ea1e830f9e9
   languageName: node
   linkType: hard
 
@@ -4127,10 +4127,10 @@ __metadata:
   languageName: node
   linkType: hard
 
-"@typescript-eslint/types@npm:7.5.0":
-  version: 7.5.0
-  resolution: "@typescript-eslint/types@npm:7.5.0"
-  checksum: 10c0/f3394f71f422dbd89f63b230f20e9769c12e47a287ff30ca03a80714e57ea21279b6f12a8ab14bafb00b59926f20a88894b2d1e72679f7ff298bae112679d4b3
+"@typescript-eslint/types@npm:7.7.0":
+  version: 7.7.0
+  resolution: "@typescript-eslint/types@npm:7.7.0"
+  checksum: 10c0/eb50793650c9a911c73586150807912e7b7a0ae12eeb26c7a322ac8ebb8edef15960cc9a4b7049dbb89b82500079963145f67d15583f5de270fe8290974db533
   languageName: node
   linkType: hard
 
@@ -4153,39 +4153,39 @@ __metadata:
   languageName: node
   linkType: hard
 
-"@typescript-eslint/typescript-estree@npm:7.5.0":
-  version: 7.5.0
-  resolution: "@typescript-eslint/typescript-estree@npm:7.5.0"
+"@typescript-eslint/typescript-estree@npm:7.7.0":
+  version: 7.7.0
+  resolution: "@typescript-eslint/typescript-estree@npm:7.7.0"
   dependencies:
-    "@typescript-eslint/types": "npm:7.5.0"
-    "@typescript-eslint/visitor-keys": "npm:7.5.0"
+    "@typescript-eslint/types": "npm:7.7.0"
+    "@typescript-eslint/visitor-keys": "npm:7.7.0"
     debug: "npm:^4.3.4"
     globby: "npm:^11.1.0"
     is-glob: "npm:^4.0.3"
-    minimatch: "npm:9.0.3"
-    semver: "npm:^7.5.4"
-    ts-api-utils: "npm:^1.0.1"
+    minimatch: "npm:^9.0.4"
+    semver: "npm:^7.6.0"
+    ts-api-utils: "npm:^1.3.0"
   peerDependenciesMeta:
     typescript:
       optional: true
-  checksum: 10c0/ea3a270c725d6be273188b86110e0393052cd64d1c54a56eb5ea405e6d3fbbe84fb3b1ce1b8496a4078ac1eefd37aedcf12be91876764f6de31d5aa5131c7bcd
+  checksum: 10c0/19da9bf0948c9800fde19c5a408a80a3a4cf357ff67d47b516df5d2a05701a4fdd2b9ab5b692866bd84bfc17cea9132d1575a1423e01763a4c2918b5d77d0b34
   languageName: node
   linkType: hard
 
-"@typescript-eslint/utils@npm:7.5.0":
-  version: 7.5.0
-  resolution: "@typescript-eslint/utils@npm:7.5.0"
+"@typescript-eslint/utils@npm:7.7.0":
+  version: 7.7.0
+  resolution: "@typescript-eslint/utils@npm:7.7.0"
   dependencies:
     "@eslint-community/eslint-utils": "npm:^4.4.0"
-    "@types/json-schema": "npm:^7.0.12"
-    "@types/semver": "npm:^7.5.0"
-    "@typescript-eslint/scope-manager": "npm:7.5.0"
-    "@typescript-eslint/types": "npm:7.5.0"
-    "@typescript-eslint/typescript-estree": "npm:7.5.0"
-    semver: "npm:^7.5.4"
+    "@types/json-schema": "npm:^7.0.15"
+    "@types/semver": "npm:^7.5.8"
+    "@typescript-eslint/scope-manager": "npm:7.7.0"
+    "@typescript-eslint/types": "npm:7.7.0"
+    "@typescript-eslint/typescript-estree": "npm:7.7.0"
+    semver: "npm:^7.6.0"
   peerDependencies:
     eslint: ^8.56.0
-  checksum: 10c0/c815ed6909769648953d6963c069038f7cac0c979051b25718feb30e0d3337b9647b75b8de00ac03fe960f0cc8dc4e8a81d4aac4719090a99785e0068712bd24
+  checksum: 10c0/c5f18ce198b420bdc201fd4278b4fa97bfe86178db565f3c4e1991bb452c9ea0b657e7980572555e2ec2fe218d07c42c794d217b9369903019cf784eea7e2164
   languageName: node
   linkType: hard
 
@@ -4216,13 +4216,13 @@ __metadata:
   languageName: node
   linkType: hard
 
-"@typescript-eslint/visitor-keys@npm:7.5.0":
-  version: 7.5.0
-  resolution: "@typescript-eslint/visitor-keys@npm:7.5.0"
+"@typescript-eslint/visitor-keys@npm:7.7.0":
+  version: 7.7.0
+  resolution: "@typescript-eslint/visitor-keys@npm:7.7.0"
   dependencies:
-    "@typescript-eslint/types": "npm:7.5.0"
-    eslint-visitor-keys: "npm:^3.4.1"
-  checksum: 10c0/eecf02b8dd54e83738a143aca87b902af4b357028a90fd34ed7a2f40a3ae2f6a188b9ba53903f23c80e868f1fffbb039e9ddb63525438d659707cc7bfb269317
+    "@typescript-eslint/types": "npm:7.7.0"
+    eslint-visitor-keys: "npm:^3.4.3"
+  checksum: 10c0/0f3b9720a962c04462a75d4872714c07320c8f672841881ada797ae960f9f6bd0e5f7494178917034f42635ef76f0f09fa3c8d4bd84f31ec58ee968fe75bada7
   languageName: node
   linkType: hard
 
@@ -9397,7 +9397,7 @@ __metadata:
   languageName: node
   linkType: hard
 
-"ignore@npm:^5.2.0, ignore@npm:^5.2.4, ignore@npm:^5.3.1":
+"ignore@npm:^5.2.0, ignore@npm:^5.3.1":
   version: 5.3.1
   resolution: "ignore@npm:5.3.1"
   checksum: 10c0/703f7f45ffb2a27fb2c5a8db0c32e7dee66b33a225d28e8db4e1be6474795f606686a6e3bcc50e1aa12f2042db4c9d4a7d60af3250511de74620fbed052ea4cd
@@ -11761,7 +11761,7 @@ __metadata:
   languageName: node
   linkType: hard
 
-"minimatch@npm:9.0.3, minimatch@npm:^9.0.1":
+"minimatch@npm:9.0.3":
   version: 9.0.3
   resolution: "minimatch@npm:9.0.3"
   dependencies:
@@ -11788,6 +11788,15 @@ __metadata:
   languageName: node
   linkType: hard
 
+"minimatch@npm:^9.0.1, minimatch@npm:^9.0.4":
+  version: 9.0.4
+  resolution: "minimatch@npm:9.0.4"
+  dependencies:
+    brace-expansion: "npm:^2.0.1"
+  checksum: 10c0/2c16f21f50e64922864e560ff97c587d15fd491f65d92a677a344e970fe62aafdbeafe648965fa96d33c061b4d0eabfe0213466203dd793367e7f28658cf6414
+  languageName: node
+  linkType: hard
+
 "minimist@npm:^1.2.0, minimist@npm:^1.2.6":
   version: 1.2.8
   resolution: "minimist@npm:1.2.8"
@@ -16861,12 +16870,12 @@ __metadata:
   languageName: node
   linkType: hard
 
-"ts-api-utils@npm:^1.0.1":
-  version: 1.0.3
-  resolution: "ts-api-utils@npm:1.0.3"
+"ts-api-utils@npm:^1.0.1, ts-api-utils@npm:^1.3.0":
+  version: 1.3.0
+  resolution: "ts-api-utils@npm:1.3.0"
   peerDependencies:
     typescript: ">=4.2.0"
-  checksum: 10c0/9408338819c3aca2a709f0bc54e3f874227901506cacb1163612a6c8a43df224174feb965a5eafdae16f66fc68fd7bfee8d3275d0fa73fbb8699e03ed26520c9
+  checksum: 10c0/f54a0ba9ed56ce66baea90a3fa087a484002e807f28a8ccb2d070c75e76bde64bd0f6dce98b3802834156306050871b67eec325cb4e918015a360a3f0868c77c
   languageName: node
   linkType: hard
 

From 88f946890d29cd78dd71e4bd17a13da93d9e92ee Mon Sep 17 00:00:00 2001
From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com>
Date: Mon, 22 Apr 2024 10:13:28 +0200
Subject: [PATCH 03/19] Update peter-evans/create-pull-request action to v6.0.4
 (#30025)

Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
---
 .github/workflows/crowdin-download.yml | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/.github/workflows/crowdin-download.yml b/.github/workflows/crowdin-download.yml
index 14b0542d7..256dcffc7 100644
--- a/.github/workflows/crowdin-download.yml
+++ b/.github/workflows/crowdin-download.yml
@@ -52,7 +52,7 @@ jobs:
 
       # Create or update the pull request
       - name: Create Pull Request
-        uses: peter-evans/create-pull-request@v6.0.3
+        uses: peter-evans/create-pull-request@v6.0.4
         with:
           commit-message: 'New Crowdin translations'
           title: 'New Crowdin Translations (automated)'

From 3e21af3e4aecef9298c0e2392750b2d005f75c0a Mon Sep 17 00:00:00 2001
From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com>
Date: Mon, 22 Apr 2024 08:14:09 +0000
Subject: [PATCH 04/19] Update dependency @types/react to v18.2.79 (#30024)

Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
---
 yarn.lock | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

diff --git a/yarn.lock b/yarn.lock
index e0001120a..1f5a3275b 100644
--- a/yarn.lock
+++ b/yarn.lock
@@ -3862,12 +3862,12 @@ __metadata:
   linkType: hard
 
 "@types/react@npm:*, @types/react@npm:16 || 17 || 18, @types/react@npm:>=16.9.11, @types/react@npm:^18.2.7":
-  version: 18.2.78
-  resolution: "@types/react@npm:18.2.78"
+  version: 18.2.79
+  resolution: "@types/react@npm:18.2.79"
   dependencies:
     "@types/prop-types": "npm:*"
     csstype: "npm:^3.0.2"
-  checksum: 10c0/5eb8e1dd98c29aeddf40b90f466d1a9ce83b113d42a096633d632b834e7ae9821f24ba7999928de9d98cca37764532a7ea35355a8103a377d8baa750f1841b5c
+  checksum: 10c0/c8a8a005d8830a48cc1ef93c3510c4935a2a03e5557dbecaa8f1038450cbfcb18eb206fa7fba7077d54b8da21faeb25577e897a333392770a7797f625b62c78a
   languageName: node
   linkType: hard
 

From 24e67c4394bc545fc4b3e9bc4c3b87b0d98f36ee Mon Sep 17 00:00:00 2001
From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com>
Date: Mon, 22 Apr 2024 10:24:08 +0200
Subject: [PATCH 05/19] Update dependency postcss-preset-env to v9.5.8 (#30018)

Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
---
 yarn.lock | 164 +++++++++++++++++++++++++++---------------------------
 1 file changed, 82 insertions(+), 82 deletions(-)

diff --git a/yarn.lock b/yarn.lock
index 1f5a3275b..e6e130e2d 100644
--- a/yarn.lock
+++ b/yarn.lock
@@ -1561,10 +1561,10 @@ __metadata:
   languageName: node
   linkType: hard
 
-"@csstools/color-helpers@npm:^4.1.0":
-  version: 4.1.0
-  resolution: "@csstools/color-helpers@npm:4.1.0"
-  checksum: 10c0/0e41fd04dd28361717b161e7000c3a3b64b8b01119e93758297ea0b8a87c04121c3e3ef02e29c56fdd133227dd879163aa4b52e2370853d9fe64af6b6821668d
+"@csstools/color-helpers@npm:^4.2.0":
+  version: 4.2.0
+  resolution: "@csstools/color-helpers@npm:4.2.0"
+  checksum: 10c0/3f1feac43c2ef35f38b3b06fe74e0acc130283d7efb6874f6624e45e178c1a7b3c7e39816c7421cddbffc2666430906aa6f0d3dd7c7209db1369c0afd4a29b1b
   languageName: node
   linkType: hard
 
@@ -1578,16 +1578,16 @@ __metadata:
   languageName: node
   linkType: hard
 
-"@csstools/css-color-parser@npm:^1.6.3":
-  version: 1.6.3
-  resolution: "@csstools/css-color-parser@npm:1.6.3"
+"@csstools/css-color-parser@npm:^2.0.0":
+  version: 2.0.0
+  resolution: "@csstools/css-color-parser@npm:2.0.0"
   dependencies:
-    "@csstools/color-helpers": "npm:^4.1.0"
+    "@csstools/color-helpers": "npm:^4.2.0"
     "@csstools/css-calc": "npm:^1.2.0"
   peerDependencies:
     "@csstools/css-parser-algorithms": ^2.6.1
     "@csstools/css-tokenizer": ^2.2.4
-  checksum: 10c0/3b15d9974105fe6e5d5e839953ee06153bc308bd62feacdeb88b7da7486ef1625254d0df908c68654596e477ca6be0c312d0c02a62d6dc4bddee61821be17d27
+  checksum: 10c0/295f844a194dec4f51439e8760dbb4a142901b8b60cd9d676a62c15c0e8408eb7bcdcbb40be52cdd5f67d020e655a1c3267a28923cfc4f6bae2b74aa48fce426
   languageName: node
   linkType: hard
 
@@ -1629,33 +1629,33 @@ __metadata:
   languageName: node
   linkType: hard
 
-"@csstools/postcss-color-function@npm:^3.0.13":
-  version: 3.0.13
-  resolution: "@csstools/postcss-color-function@npm:3.0.13"
+"@csstools/postcss-color-function@npm:^3.0.14":
+  version: 3.0.14
+  resolution: "@csstools/postcss-color-function@npm:3.0.14"
   dependencies:
-    "@csstools/css-color-parser": "npm:^1.6.3"
+    "@csstools/css-color-parser": "npm:^2.0.0"
     "@csstools/css-parser-algorithms": "npm:^2.6.1"
     "@csstools/css-tokenizer": "npm:^2.2.4"
     "@csstools/postcss-progressive-custom-properties": "npm:^3.2.0"
     "@csstools/utilities": "npm:^1.0.0"
   peerDependencies:
     postcss: ^8.4
-  checksum: 10c0/9d0fa25cd258653ad3227ccf1ee89dfee7099284c28b1d9ae7f7e8b15ed526e4e8cc7724f8e21cc073ed186891c3acb5b9c190a75e3c38d9c75e49197a824db6
+  checksum: 10c0/81592b0eb3ad7022313ecafd028908b167de42acc6765f708c9b10631f86123c2b803aca27378f021c2b3dab8cc47770c0364fe5a3c1e18ec006deaf72e17c38
   languageName: node
   linkType: hard
 
-"@csstools/postcss-color-mix-function@npm:^2.0.13":
-  version: 2.0.13
-  resolution: "@csstools/postcss-color-mix-function@npm:2.0.13"
+"@csstools/postcss-color-mix-function@npm:^2.0.14":
+  version: 2.0.14
+  resolution: "@csstools/postcss-color-mix-function@npm:2.0.14"
   dependencies:
-    "@csstools/css-color-parser": "npm:^1.6.3"
+    "@csstools/css-color-parser": "npm:^2.0.0"
     "@csstools/css-parser-algorithms": "npm:^2.6.1"
     "@csstools/css-tokenizer": "npm:^2.2.4"
     "@csstools/postcss-progressive-custom-properties": "npm:^3.2.0"
     "@csstools/utilities": "npm:^1.0.0"
   peerDependencies:
     postcss: ^8.4
-  checksum: 10c0/6011ce0b328cd3ee1d5720dc6eb23da807ba5a218a4a3c65a4844a82c0ff37e69d27cbee14abf9b928a3068f429ab86f2dd2bebab4ab64cd8fc7e39e562d7073
+  checksum: 10c0/1dd3c63bbbbb9d3094699f169bbb9d26e86a49accb5f9abaa2441b54cb8a6f4cd332409666684a275eca867e3ef0ea3f6eafdf9fb87f2cbfa17c6296fb1ed4d7
   languageName: node
   linkType: hard
 
@@ -1684,46 +1684,46 @@ __metadata:
   languageName: node
   linkType: hard
 
-"@csstools/postcss-gamut-mapping@npm:^1.0.6":
-  version: 1.0.6
-  resolution: "@csstools/postcss-gamut-mapping@npm:1.0.6"
+"@csstools/postcss-gamut-mapping@npm:^1.0.7":
+  version: 1.0.7
+  resolution: "@csstools/postcss-gamut-mapping@npm:1.0.7"
   dependencies:
-    "@csstools/css-color-parser": "npm:^1.6.3"
+    "@csstools/css-color-parser": "npm:^2.0.0"
     "@csstools/css-parser-algorithms": "npm:^2.6.1"
     "@csstools/css-tokenizer": "npm:^2.2.4"
   peerDependencies:
     postcss: ^8.4
-  checksum: 10c0/a258a2ceac9d9be4374ec5b504895bd1de1196fe7d8c1377863a25c6cb50ee1fb1c65387c5440bae3c5d59e6ebf4e0c1990595c5cd09291224b31a1d23bdc250
+  checksum: 10c0/7b349db44fcd697d57172ab63b7a02a56c0b49bce17e48cb72aa0fa246bd2be83fe693c507fd400a9ed83597a711d18ece9319ee3af8000c8fd3a2761e228a11
   languageName: node
   linkType: hard
 
-"@csstools/postcss-gradients-interpolation-method@npm:^4.0.14":
-  version: 4.0.14
-  resolution: "@csstools/postcss-gradients-interpolation-method@npm:4.0.14"
+"@csstools/postcss-gradients-interpolation-method@npm:^4.0.15":
+  version: 4.0.15
+  resolution: "@csstools/postcss-gradients-interpolation-method@npm:4.0.15"
   dependencies:
-    "@csstools/css-color-parser": "npm:^1.6.3"
+    "@csstools/css-color-parser": "npm:^2.0.0"
     "@csstools/css-parser-algorithms": "npm:^2.6.1"
     "@csstools/css-tokenizer": "npm:^2.2.4"
     "@csstools/postcss-progressive-custom-properties": "npm:^3.2.0"
     "@csstools/utilities": "npm:^1.0.0"
   peerDependencies:
     postcss: ^8.4
-  checksum: 10c0/88147b2d7067b9bc6c90340c0be8450ca1175a7e927ff7b682c26d377237bec12f1cbe0dd930dd72dec661603348d1e71ca2a56f0a3b6fa2ca7d3f1b962f001d
+  checksum: 10c0/dc0bbf6a4787d5ad3f9fe268dfa9776ecdc25b6cc0a49486bf53238341a339647f1e475240ead3cec1f4af9a237f6518ace015103e90ce8afe4d44539a566e04
   languageName: node
   linkType: hard
 
-"@csstools/postcss-hwb-function@npm:^3.0.12":
-  version: 3.0.12
-  resolution: "@csstools/postcss-hwb-function@npm:3.0.12"
+"@csstools/postcss-hwb-function@npm:^3.0.13":
+  version: 3.0.13
+  resolution: "@csstools/postcss-hwb-function@npm:3.0.13"
   dependencies:
-    "@csstools/css-color-parser": "npm:^1.6.3"
+    "@csstools/css-color-parser": "npm:^2.0.0"
     "@csstools/css-parser-algorithms": "npm:^2.6.1"
     "@csstools/css-tokenizer": "npm:^2.2.4"
     "@csstools/postcss-progressive-custom-properties": "npm:^3.2.0"
     "@csstools/utilities": "npm:^1.0.0"
   peerDependencies:
     postcss: ^8.4
-  checksum: 10c0/20e0b2a4547fe619f38fe56c33974750d4a8b64a67a4169740ee0e67a9dec9f3a243f2370408901aacc35690aa36135028fafbbc866ff934b66cc4c9e4e89cac
+  checksum: 10c0/684c3d408ceb027e7276c4f25c9a17ef9bd52f0948268cf58b5184097e9b71f5364a41b42bab44691938c6fadffcba0c8e66f809a339a8b282f4a432d32d00ef
   languageName: node
   linkType: hard
 
@@ -1875,18 +1875,18 @@ __metadata:
   languageName: node
   linkType: hard
 
-"@csstools/postcss-oklab-function@npm:^3.0.13":
-  version: 3.0.13
-  resolution: "@csstools/postcss-oklab-function@npm:3.0.13"
+"@csstools/postcss-oklab-function@npm:^3.0.14":
+  version: 3.0.14
+  resolution: "@csstools/postcss-oklab-function@npm:3.0.14"
   dependencies:
-    "@csstools/css-color-parser": "npm:^1.6.3"
+    "@csstools/css-color-parser": "npm:^2.0.0"
     "@csstools/css-parser-algorithms": "npm:^2.6.1"
     "@csstools/css-tokenizer": "npm:^2.2.4"
     "@csstools/postcss-progressive-custom-properties": "npm:^3.2.0"
     "@csstools/utilities": "npm:^1.0.0"
   peerDependencies:
     postcss: ^8.4
-  checksum: 10c0/26915f65ccc8b631a08542c4b088f9e5155f95a6c1f3a6bd2a33207f96d33438b930de60f493a5bbfee1b9f2abc8dfcab3ecbf20b5c7445d729fc434234fb046
+  checksum: 10c0/dfe0b12c2256dded995c64825fac9507be9c747d776cfa09eeefff6dee0efa5eed6a92a1ecba39069a751a7fc3cefa8891c34209a7a3c7ea33d356c95d01a02d
   languageName: node
   linkType: hard
 
@@ -1901,18 +1901,18 @@ __metadata:
   languageName: node
   linkType: hard
 
-"@csstools/postcss-relative-color-syntax@npm:^2.0.13":
-  version: 2.0.13
-  resolution: "@csstools/postcss-relative-color-syntax@npm:2.0.13"
+"@csstools/postcss-relative-color-syntax@npm:^2.0.14":
+  version: 2.0.14
+  resolution: "@csstools/postcss-relative-color-syntax@npm:2.0.14"
   dependencies:
-    "@csstools/css-color-parser": "npm:^1.6.3"
+    "@csstools/css-color-parser": "npm:^2.0.0"
     "@csstools/css-parser-algorithms": "npm:^2.6.1"
     "@csstools/css-tokenizer": "npm:^2.2.4"
     "@csstools/postcss-progressive-custom-properties": "npm:^3.2.0"
     "@csstools/utilities": "npm:^1.0.0"
   peerDependencies:
     postcss: ^8.4
-  checksum: 10c0/5c9fdec029e3d9a5c688d2e04995fec0cf6d91b48dbc5f450cf9c9dbb45e2819afbd63b3279676087a13f54914b0ec7d005e478b70b43e94fc8eeef9c5973390
+  checksum: 10c0/64cd5f8054e4403f4e25ed11a5b9d157098af639dbc30ac25b94660b3af489c0bacc49fc439cba1ccceefa4caa5831a913e3d1d889a9796cc6fbf3902c7c31c1
   languageName: node
   linkType: hard
 
@@ -1940,15 +1940,15 @@ __metadata:
   languageName: node
   linkType: hard
 
-"@csstools/postcss-text-decoration-shorthand@npm:^3.0.5":
-  version: 3.0.5
-  resolution: "@csstools/postcss-text-decoration-shorthand@npm:3.0.5"
+"@csstools/postcss-text-decoration-shorthand@npm:^3.0.6":
+  version: 3.0.6
+  resolution: "@csstools/postcss-text-decoration-shorthand@npm:3.0.6"
   dependencies:
-    "@csstools/color-helpers": "npm:^4.1.0"
+    "@csstools/color-helpers": "npm:^4.2.0"
     postcss-value-parser: "npm:^4.2.0"
   peerDependencies:
     postcss: ^8.4
-  checksum: 10c0/e7e08c643c7084e60c0b22982e00ce21c579af3810ebbebac6838801b2ac622026ce96fd0cbca785613b1559f2337833cfc0f525685f8543ee39078a32fd7f89
+  checksum: 10c0/5abdc4fad1c3f15e9d47c7af3995dec9cdf4e6f87c5857eb2e149764779b8389f4f4b21d11e6f2509c57c554a0dc5c11f68f212acd04bbc47defa15911ac3eb9
   languageName: node
   linkType: hard
 
@@ -13078,18 +13078,18 @@ __metadata:
   languageName: node
   linkType: hard
 
-"postcss-color-functional-notation@npm:^6.0.8":
-  version: 6.0.8
-  resolution: "postcss-color-functional-notation@npm:6.0.8"
+"postcss-color-functional-notation@npm:^6.0.9":
+  version: 6.0.9
+  resolution: "postcss-color-functional-notation@npm:6.0.9"
   dependencies:
-    "@csstools/css-color-parser": "npm:^1.6.3"
+    "@csstools/css-color-parser": "npm:^2.0.0"
     "@csstools/css-parser-algorithms": "npm:^2.6.1"
     "@csstools/css-tokenizer": "npm:^2.2.4"
     "@csstools/postcss-progressive-custom-properties": "npm:^3.2.0"
     "@csstools/utilities": "npm:^1.0.0"
   peerDependencies:
     postcss: ^8.4
-  checksum: 10c0/ae2ff7769970fb403ea71d5613e041d97bb647cfc54e4a428bcc75f98ff06c888b064384df12b18f609bfcc4395c31d6db4ad2b9c9385a829ba594d2692c31d1
+  checksum: 10c0/120f7bc23bf46dd1c008b3aa806fb02dd988ae180f9c0c10dca9f5ea3473bf20d7743aafae1441df5b4a3945a63ebb0dae1d4d55f7c8bcd34540529b627c4e3e
   languageName: node
   linkType: hard
 
@@ -13298,18 +13298,18 @@ __metadata:
   languageName: node
   linkType: hard
 
-"postcss-lab-function@npm:^6.0.13":
-  version: 6.0.13
-  resolution: "postcss-lab-function@npm:6.0.13"
+"postcss-lab-function@npm:^6.0.14":
+  version: 6.0.14
+  resolution: "postcss-lab-function@npm:6.0.14"
   dependencies:
-    "@csstools/css-color-parser": "npm:^1.6.3"
+    "@csstools/css-color-parser": "npm:^2.0.0"
     "@csstools/css-parser-algorithms": "npm:^2.6.1"
     "@csstools/css-tokenizer": "npm:^2.2.4"
     "@csstools/postcss-progressive-custom-properties": "npm:^3.2.0"
     "@csstools/utilities": "npm:^1.0.0"
   peerDependencies:
     postcss: ^8.4
-  checksum: 10c0/3ffb82d0012e49df49b44f38a131f4b13ba3edeeca5ecc0062c1c1b6bd8961c06f05b1dd8ec620c50c2c406fc61a505d79488745185d69ed325603600f0a1bc8
+  checksum: 10c0/0b5d998ddb98ec6243448f1eca216f6e23872431885b152843feef1e844fc5b6b3ebe16ea8940f3d6abea732aa0c51b2ec0e57437e4326e5b2cb2bcb949e6d9f
   languageName: node
   linkType: hard
 
@@ -13465,16 +13465,16 @@ __metadata:
   languageName: node
   linkType: hard
 
-"postcss-nesting@npm:^12.1.1":
-  version: 12.1.1
-  resolution: "postcss-nesting@npm:12.1.1"
+"postcss-nesting@npm:^12.1.2":
+  version: 12.1.2
+  resolution: "postcss-nesting@npm:12.1.2"
   dependencies:
     "@csstools/selector-resolve-nested": "npm:^1.1.0"
     "@csstools/selector-specificity": "npm:^3.0.3"
     postcss-selector-parser: "npm:^6.0.13"
   peerDependencies:
     postcss: ^8.4
-  checksum: 10c0/8fac718e69ee2ac93179cc59810a8184581c04715fe34621ec5d504fc680cad4a11219ed0c918cbe15c468994c9aba88e729f35eef698c5d44cadd824425c47d
+  checksum: 10c0/39d1d100f61863f904393b17169be83cdf82bd50d530efb3e3ae0c7b0f838b254e10e5d12e25119cf31dce9e351a2b770a03f9b2029ff33bef0ec924c0d2f642
   languageName: node
   linkType: hard
 
@@ -13629,17 +13629,17 @@ __metadata:
   linkType: hard
 
 "postcss-preset-env@npm:^9.5.2":
-  version: 9.5.6
-  resolution: "postcss-preset-env@npm:9.5.6"
+  version: 9.5.8
+  resolution: "postcss-preset-env@npm:9.5.8"
   dependencies:
     "@csstools/postcss-cascade-layers": "npm:^4.0.4"
-    "@csstools/postcss-color-function": "npm:^3.0.13"
-    "@csstools/postcss-color-mix-function": "npm:^2.0.13"
+    "@csstools/postcss-color-function": "npm:^3.0.14"
+    "@csstools/postcss-color-mix-function": "npm:^2.0.14"
     "@csstools/postcss-exponential-functions": "npm:^1.0.5"
     "@csstools/postcss-font-format-keywords": "npm:^3.0.2"
-    "@csstools/postcss-gamut-mapping": "npm:^1.0.6"
-    "@csstools/postcss-gradients-interpolation-method": "npm:^4.0.14"
-    "@csstools/postcss-hwb-function": "npm:^3.0.12"
+    "@csstools/postcss-gamut-mapping": "npm:^1.0.7"
+    "@csstools/postcss-gradients-interpolation-method": "npm:^4.0.15"
+    "@csstools/postcss-hwb-function": "npm:^3.0.13"
     "@csstools/postcss-ic-unit": "npm:^3.0.6"
     "@csstools/postcss-initial": "npm:^1.0.1"
     "@csstools/postcss-is-pseudo-class": "npm:^4.0.6"
@@ -13653,12 +13653,12 @@ __metadata:
     "@csstools/postcss-media-queries-aspect-ratio-number-values": "npm:^2.0.7"
     "@csstools/postcss-nested-calc": "npm:^3.0.2"
     "@csstools/postcss-normalize-display-values": "npm:^3.0.2"
-    "@csstools/postcss-oklab-function": "npm:^3.0.13"
+    "@csstools/postcss-oklab-function": "npm:^3.0.14"
     "@csstools/postcss-progressive-custom-properties": "npm:^3.2.0"
-    "@csstools/postcss-relative-color-syntax": "npm:^2.0.13"
+    "@csstools/postcss-relative-color-syntax": "npm:^2.0.14"
     "@csstools/postcss-scope-pseudo-class": "npm:^3.0.1"
     "@csstools/postcss-stepped-value-functions": "npm:^3.0.6"
-    "@csstools/postcss-text-decoration-shorthand": "npm:^3.0.5"
+    "@csstools/postcss-text-decoration-shorthand": "npm:^3.0.6"
     "@csstools/postcss-trigonometric-functions": "npm:^3.0.6"
     "@csstools/postcss-unset-value": "npm:^3.0.1"
     autoprefixer: "npm:^10.4.19"
@@ -13669,7 +13669,7 @@ __metadata:
     cssdb: "npm:^8.0.0"
     postcss-attribute-case-insensitive: "npm:^6.0.3"
     postcss-clamp: "npm:^4.1.0"
-    postcss-color-functional-notation: "npm:^6.0.8"
+    postcss-color-functional-notation: "npm:^6.0.9"
     postcss-color-hex-alpha: "npm:^9.0.4"
     postcss-color-rebeccapurple: "npm:^9.0.3"
     postcss-custom-media: "npm:^10.0.4"
@@ -13682,30 +13682,30 @@ __metadata:
     postcss-font-variant: "npm:^5.0.0"
     postcss-gap-properties: "npm:^5.0.1"
     postcss-image-set-function: "npm:^6.0.3"
-    postcss-lab-function: "npm:^6.0.13"
+    postcss-lab-function: "npm:^6.0.14"
     postcss-logical: "npm:^7.0.1"
-    postcss-nesting: "npm:^12.1.1"
+    postcss-nesting: "npm:^12.1.2"
     postcss-opacity-percentage: "npm:^2.0.0"
     postcss-overflow-shorthand: "npm:^5.0.1"
     postcss-page-break: "npm:^3.0.4"
     postcss-place: "npm:^9.0.1"
-    postcss-pseudo-class-any-link: "npm:^9.0.1"
+    postcss-pseudo-class-any-link: "npm:^9.0.2"
     postcss-replace-overflow-wrap: "npm:^4.0.0"
     postcss-selector-not: "npm:^7.0.2"
   peerDependencies:
     postcss: ^8.4
-  checksum: 10c0/21738ecac400cca9a96841959308538516ed00ca80d4c53beb20e080c7d963120fa77b7435b02e1beefc20043abce666419b81eccf6dacdc4298f540778c111d
+  checksum: 10c0/5f77272eb7a938e5bedc3a0877f3fb0cdc6f20c8829730ccafbbd999db78ba4e6ac60f485aa7c292f70e011cf3edfadb7d2cc5459cbf9851abc25139eeb061b7
   languageName: node
   linkType: hard
 
-"postcss-pseudo-class-any-link@npm:^9.0.1":
-  version: 9.0.1
-  resolution: "postcss-pseudo-class-any-link@npm:9.0.1"
+"postcss-pseudo-class-any-link@npm:^9.0.2":
+  version: 9.0.2
+  resolution: "postcss-pseudo-class-any-link@npm:9.0.2"
   dependencies:
     postcss-selector-parser: "npm:^6.0.13"
   peerDependencies:
     postcss: ^8.4
-  checksum: 10c0/2d33f486af442a0ee095b7b8875701ed3f54ea3f80d2c4d1c1b35d105088b569c847e1c71fde2adf6cefb4920e8fb7d057ff1ad56e62c65892c7b68e26213b98
+  checksum: 10c0/cc2cb455a793b1f5dc0ac290e02296eafb317d9ce987dc9f2102027e22f265299666dbd1e78f1d7836fce549dead73f41e24251c08a2dd0cf482f3cc43cf7909
   languageName: node
   linkType: hard
 

From a15139bc02d279b9ef85e95990f41e3e88838d20 Mon Sep 17 00:00:00 2001
From: Matt Jankowski <matt@jankowski.online>
Date: Mon, 22 Apr 2024 04:30:38 -0400
Subject: [PATCH 06/19] Fix intermittent order based failure in
 `UpdateStatusService` spec (#30008)

---
 spec/services/update_status_service_spec.rb | 10 +++++-----
 1 file changed, 5 insertions(+), 5 deletions(-)

diff --git a/spec/services/update_status_service_spec.rb b/spec/services/update_status_service_spec.rb
index 930f673e1..47be53f4f 100644
--- a/spec/services/update_status_service_spec.rb
+++ b/spec/services/update_status_service_spec.rb
@@ -40,7 +40,7 @@ RSpec.describe UpdateStatusService do
     end
 
     it 'saves edit history' do
-      expect(status.edits.pluck(:text)).to eq %w(Foo Bar)
+      expect(status.edits.ordered.pluck(:text)).to eq %w(Foo Bar)
     end
   end
 
@@ -58,7 +58,7 @@ RSpec.describe UpdateStatusService do
     end
 
     it 'saves edit history' do
-      expect(status.edits.pluck(:text, :spoiler_text)).to eq [['Foo', ''], ['Foo', 'Bar']]
+      expect(status.edits.ordered.pluck(:text, :spoiler_text)).to eq [['Foo', ''], ['Foo', 'Bar']]
     end
   end
 
@@ -85,7 +85,7 @@ RSpec.describe UpdateStatusService do
     end
 
     it 'saves edit history' do
-      expect(status.edits.pluck(:ordered_media_attachment_ids)).to eq [[detached_media_attachment.id], [attached_media_attachment.id]]
+      expect(status.edits.ordered.pluck(:ordered_media_attachment_ids)).to eq [[detached_media_attachment.id], [attached_media_attachment.id]]
     end
   end
 
@@ -107,7 +107,7 @@ RSpec.describe UpdateStatusService do
     end
 
     it 'saves edit history' do
-      expect(status.edits.map { |edit| edit.ordered_media_attachments.map(&:description) }).to eq [['Old description'], ['New description']]
+      expect(status.edits.ordered.map { |edit| edit.ordered_media_attachments.map(&:description) }).to eq [['Old description'], ['New description']]
     end
   end
 
@@ -136,7 +136,7 @@ RSpec.describe UpdateStatusService do
     end
 
     it 'saves edit history' do
-      expect(status.edits.pluck(:poll_options)).to eq [%w(Foo Bar), %w(Bar Baz Foo)]
+      expect(status.edits.ordered.pluck(:poll_options)).to eq [%w(Foo Bar), %w(Bar Baz Foo)]
     end
 
     it 'requeues expiration notification' do

From 18737aad49911f00b94f9cf6fc582670cbdeda93 Mon Sep 17 00:00:00 2001
From: Matt Jankowski <matt@jankowski.online>
Date: Mon, 22 Apr 2024 04:31:20 -0400
Subject: [PATCH 07/19] Rely on dotenv autoload instead of explicit call
 (#30007)

---
 config/application.rb | 2 --
 1 file changed, 2 deletions(-)

diff --git a/config/application.rb b/config/application.rb
index a17a48b09..b777018b5 100644
--- a/config/application.rb
+++ b/config/application.rb
@@ -52,8 +52,6 @@ require_relative '../lib/active_record/batches'
 require_relative '../lib/simple_navigation/item_extensions'
 require_relative '../lib/http_extensions'
 
-Dotenv::Rails.load
-
 Bundler.require(:pam_authentication) if ENV['PAM_ENABLED'] == 'true'
 
 require_relative '../lib/mastodon/redis_config'

From 3655fb6a22576ac1b0e0fed4910483f8550c6529 Mon Sep 17 00:00:00 2001
From: "github-actions[bot]"
 <41898282+github-actions[bot]@users.noreply.github.com>
Date: Mon, 22 Apr 2024 10:42:35 +0200
Subject: [PATCH 08/19] New Crowdin Translations (automated) (#30014)

Co-authored-by: GitHub Actions <noreply@github.com>
---
 app/javascript/mastodon/locales/be.json |   1 +
 app/javascript/mastodon/locales/es.json |   2 +-
 app/javascript/mastodon/locales/fi.json |  14 +-
 app/javascript/mastodon/locales/fr.json |   4 +-
 app/javascript/mastodon/locales/ia.json | 195 ++++++++++++++++++++++++
 app/javascript/mastodon/locales/id.json |  17 +++
 app/javascript/mastodon/locales/ja.json |   6 +
 config/locales/devise.ia.yml            |   2 +
 config/locales/fi.yml                   |   8 +-
 config/locales/ia.yml                   |  61 ++++++++
 config/locales/ja.yml                   |   2 +
 config/locales/simple_form.fi.yml       |   2 +-
 config/locales/simple_form.ia.yml       |  45 ++++++
 13 files changed, 344 insertions(+), 15 deletions(-)

diff --git a/app/javascript/mastodon/locales/be.json b/app/javascript/mastodon/locales/be.json
index 276f7c712..2b7673312 100644
--- a/app/javascript/mastodon/locales/be.json
+++ b/app/javascript/mastodon/locales/be.json
@@ -297,6 +297,7 @@
   "filter_modal.select_filter.subtitle": "Скарыстайцеся існуючай катэгорыяй або стварыце новую",
   "filter_modal.select_filter.title": "Фільтраваць гэты допіс",
   "filter_modal.title.status": "Фільтраваць допіс",
+  "filtered_notifications_banner.mentions": "{count, plural, one {згадванне} few {згадванні} many {згадванняў} other {згадвання}}",
   "filtered_notifications_banner.pending_requests": "Апавяшчэнні ад {count, plural, =0 {# людзей якіх} one {# чалавека якіх} few {# чалавек якіх} many {# людзей якіх} other {# чалавека якіх}} вы магчыма ведаеце",
   "filtered_notifications_banner.title": "Адфільтраваныя апавяшчэнні",
   "firehose.all": "Усе",
diff --git a/app/javascript/mastodon/locales/es.json b/app/javascript/mastodon/locales/es.json
index 68e5349a5..149a37d74 100644
--- a/app/javascript/mastodon/locales/es.json
+++ b/app/javascript/mastodon/locales/es.json
@@ -642,7 +642,7 @@
   "report.statuses.subtitle": "Selecciona todos los que correspondan",
   "report.statuses.title": "¿Hay alguna publicación que respalde este informe?",
   "report.submit": "Enviar",
-  "report.target": "Reportando",
+  "report.target": "Reportando {target}",
   "report.thanks.take_action": "Aquí están tus opciones para controlar lo que ves en Mastodon:",
   "report.thanks.take_action_actionable": "Mientras revisamos esto, puedes tomar medidas contra @{name}:",
   "report.thanks.title": "¿No quieres esto?",
diff --git a/app/javascript/mastodon/locales/fi.json b/app/javascript/mastodon/locales/fi.json
index a32bb1315..246bb56fc 100644
--- a/app/javascript/mastodon/locales/fi.json
+++ b/app/javascript/mastodon/locales/fi.json
@@ -298,7 +298,7 @@
   "filter_modal.select_filter.title": "Suodata tämä julkaisu",
   "filter_modal.title.status": "Suodata julkaisu",
   "filtered_notifications_banner.mentions": "{count, plural, one {maininta} other {mainintaa}}",
-  "filtered_notifications_banner.pending_requests": "Ilmoitukset {count, plural, =0 {ei keltään} one {yhdeltä henkilöltä} other {# henkilöltä}}, jonka saatat tuntea",
+  "filtered_notifications_banner.pending_requests": "Sinulle on ilmoituksia mahdollisesti tuntemiltasi henkilöiltä seuraavasti: {count, plural, =0 {Ei keltään} one {Yhdeltä henkilöltä} other {# henkilöltä}}",
   "filtered_notifications_banner.title": "Suodatetut ilmoitukset",
   "firehose.all": "Kaikki",
   "firehose.local": "Tämä palvelin",
@@ -306,11 +306,11 @@
   "follow_request.authorize": "Valtuuta",
   "follow_request.reject": "Hylkää",
   "follow_requests.unlocked_explanation": "Vaikkei tiliäsi ole lukittu, palvelimen {domain} ylläpito on arvioinut, että saatat olla halukas tarkistamaan nämä seuraamispyynnöt erikseen.",
-  "follow_suggestions.curated_suggestion": "Ylläpidon valinta",
+  "follow_suggestions.curated_suggestion": "Ehdotus ylläpidolta",
   "follow_suggestions.dismiss": "Älä näytä uudelleen",
   "follow_suggestions.hints.featured": "Tämän profiilin on valinnut palvelimen {domain} tiimi.",
-  "follow_suggestions.hints.friends_of_friends": "Tämä profiili on suosittu seuraamiesi henkilöiden parissa.",
-  "follow_suggestions.hints.most_followed": "Tämä profiili on yksi seuratuimmista palvelimella {domain}.",
+  "follow_suggestions.hints.friends_of_friends": "Seuraamasi käyttäjät suosivat tätä profiilia.",
+  "follow_suggestions.hints.most_followed": "Tämä profiili on palvelimen {domain} seuratuimpia.",
   "follow_suggestions.hints.most_interactions": "Tämä profiili on viime aikoina saanut paljon huomiota palvelimella {domain}.",
   "follow_suggestions.hints.similar_to_recently_followed": "Tämä profiili on samankaltainen kuin profiilit, joita olet viimeksi seurannut.",
   "follow_suggestions.personalized_suggestion": "Mukautettu ehdotus",
@@ -473,10 +473,10 @@
   "notification.poll": "Kysely, johon osallistuit, on päättynyt",
   "notification.reblog": "{name} tehosti julkaisuasi",
   "notification.relationships_severance_event": "Menetettiin yhteydet palvelimeen {name}",
-  "notification.relationships_severance_event.account_suspension": "Palvelimen {from} ylläpitäjä on jäädyttänyt verkkotunnuksen {target}, minkä takia et voi enää vastaanottaa heidän päivityksiään tai olla vuorovaikutuksessa heidän kanssaan.",
-  "notification.relationships_severance_event.domain_block": "Palvelimen {from} ylläpitäjä on estänyt verkkotunnuksen {target}, mukaan lukien {followersCount} seuraajistasi ja {followingCount, plural, one {# seuratuistasi} other {# seuratuistasi}}.",
+  "notification.relationships_severance_event.account_suspension": "Palvelimen {from} ylläpitäjä on jäädyttänyt palvelimen {target} vuorovaikutuksen. Enää et voi siis vastaanottaa päivityksiä heiltä tai olla yhteyksissä heidän kanssaan.",
+  "notification.relationships_severance_event.domain_block": "Palvelimen {from} ylläpitäjä on estänyt palvelimen {target} vuorovaikutuksen – mukaan lukien {followersCount} seuraajistasi ja {followingCount, plural, one {# seuratuistasi} other {# seuratuistasi}}.",
   "notification.relationships_severance_event.learn_more": "Lue lisää",
-  "notification.relationships_severance_event.user_domain_block": "Olet estänyt verkkotunnuksen {target}, mikä poisti {followersCount} seuraajistasi ja {followingCount, plural, one {# seuratuistasi} other {# seuratuistasi}}.",
+  "notification.relationships_severance_event.user_domain_block": "Olet estänyt palvelimen {target}, mikä poisti {followersCount} seuraajistasi ja {followingCount, plural, one {# seuratuistasi} other {# seuratuistasi}}.",
   "notification.status": "{name} julkaisi juuri",
   "notification.update": "{name} muokkasi julkaisua",
   "notification_requests.accept": "Hyväksy",
diff --git a/app/javascript/mastodon/locales/fr.json b/app/javascript/mastodon/locales/fr.json
index 58ab46d5c..1a5803623 100644
--- a/app/javascript/mastodon/locales/fr.json
+++ b/app/javascript/mastodon/locales/fr.json
@@ -550,10 +550,10 @@
   "onboarding.share.message": "Je suis {username} sur #Mastodon ! Suivez-moi sur {url}",
   "onboarding.share.next_steps": "Étapes suivantes possibles :",
   "onboarding.share.title": "Partager votre profil",
-  "onboarding.start.lead": "Your new Mastodon account is ready to go. Here's how you can make the most of it:",
+  "onboarding.start.lead": "Vous faites désormais partie de Mastodon, une plateforme de médias sociaux unique et décentralisée où c'est vous, et non un algorithme, qui créez votre propre expérience. Nous allons vous aider à vous lancer dans cette nouvelle frontière sociale :",
   "onboarding.start.skip": "Vous n’avez donc pas besoin d’aide pour commencer ?",
   "onboarding.start.title": "Vous avez réussi !",
-  "onboarding.steps.follow_people.body": "You curate your own feed. Lets fill it with interesting people.",
+  "onboarding.steps.follow_people.body": "Suivre des personnes intéressantes, c'est la raison d'être de Mastodon.",
   "onboarding.steps.follow_people.title": "Personnaliser votre flux principal",
   "onboarding.steps.publish_status.body": "Dites bonjour au monde avec du texte, des photos, des vidéos ou des sondages {emoji}",
   "onboarding.steps.publish_status.title": "Rédigez votre premier message",
diff --git a/app/javascript/mastodon/locales/ia.json b/app/javascript/mastodon/locales/ia.json
index e0ae8b58c..808b57278 100644
--- a/app/javascript/mastodon/locales/ia.json
+++ b/app/javascript/mastodon/locales/ia.json
@@ -375,12 +375,14 @@
   "keyboard_shortcuts.compose": "Focalisar al area de composition de texto",
   "keyboard_shortcuts.description": "Description",
   "keyboard_shortcuts.direct": "aperir le columna de mentiones private",
+  "keyboard_shortcuts.down": "Displaciar a basso in le lista",
   "keyboard_shortcuts.enter": "Aperir message",
   "keyboard_shortcuts.favourite": "Message favorite",
   "keyboard_shortcuts.favourites": "Aperir lista de favoritos",
   "keyboard_shortcuts.federated": "Aperir le chronologia federate",
   "keyboard_shortcuts.heading": "Accessos directe de claviero",
   "keyboard_shortcuts.home": "Aperir le chronologia de initio",
+  "keyboard_shortcuts.hotkey": "Clave accelerator",
   "keyboard_shortcuts.legend": "Monstrar iste legenda",
   "keyboard_shortcuts.local": "Aperir le chronologia local",
   "keyboard_shortcuts.mention": "Mentionar le author",
@@ -391,10 +393,18 @@
   "keyboard_shortcuts.pinned": "Aperir le lista de messages fixate",
   "keyboard_shortcuts.profile": "Aperir le profilo del autor",
   "keyboard_shortcuts.reply": "Responder al message",
+  "keyboard_shortcuts.requests": "Aperir le lista de requestas de sequimento",
+  "keyboard_shortcuts.search": "Focalisar barra de recerca",
   "keyboard_shortcuts.spoilers": "Monstrar/celar le campo CW",
+  "keyboard_shortcuts.start": "Aperir columna “comenciar”",
+  "keyboard_shortcuts.toggle_hidden": "Monstrar/celar texto detra advertimento de contento",
   "keyboard_shortcuts.toggle_sensitivity": "Monstrar/celar multimedia",
   "keyboard_shortcuts.toot": "Initiar un nove message",
+  "keyboard_shortcuts.unfocus": "Disfocalisar le area de composition de texto/de recerca",
+  "keyboard_shortcuts.up": "Displaciar in alto in le lista",
   "lightbox.close": "Clauder",
+  "lightbox.compress": "Comprimer le quadro de visualisation de imagine",
+  "lightbox.expand": "Expander le quadro de visualisation de imagine",
   "lightbox.next": "Sequente",
   "lightbox.previous": "Precedente",
   "limited_account_hint.action": "Monstrar profilo in omne caso",
@@ -408,13 +418,19 @@
   "lists.exclusive": "Celar iste messages sur le pagina de initio",
   "lists.new.create": "Adder lista",
   "lists.new.title_placeholder": "Nove titulo del lista",
+  "lists.replies_policy.followed": "Qualcunque usator sequite",
+  "lists.replies_policy.list": "Membros del lista",
   "lists.replies_policy.none": "Nemo",
   "lists.replies_policy.title": "Monstrar responsas a:",
+  "lists.search": "Cercar inter le gente que tu seque",
   "lists.subheading": "Tu listas",
+  "load_pending": "{count, plural, one {# nove entrata} other {# nove entratas}}",
   "loading_indicator.label": "Cargante…",
   "media_gallery.toggle_visible": "{number, plural, one {Celar imagine} other {Celar imagines}}",
+  "moved_to_account_banner.text": "Tu conto {disabledAccount} es actualmente disactivate perque tu ha cambiate de conto a {movedToAccount}.",
   "mute_modal.hide_from_notifications": "Celar ab notificationes",
   "mute_modal.hide_options": "Celar optiones",
+  "mute_modal.indefinite": "Usque io dissilentia iste persona",
   "mute_modal.show_options": "Monstrar optiones",
   "mute_modal.they_can_mention_and_follow": "Illes pote mentionar te e sequer te, ma tu non potera vider los.",
   "mute_modal.they_wont_know": "Illes non sapera que illes ha essite silentiate.",
@@ -433,6 +449,9 @@
   "navigation_bar.explore": "Explorar",
   "navigation_bar.favourites": "Favoritos",
   "navigation_bar.filters": "Parolas silentiate",
+  "navigation_bar.follow_requests": "Requestas de sequimento",
+  "navigation_bar.followed_tags": "Hashtags sequite",
+  "navigation_bar.follows_and_followers": "Sequites e sequitores",
   "navigation_bar.lists": "Listas",
   "navigation_bar.logout": "Clauder le session",
   "navigation_bar.mutes": "Usatores silentiate",
@@ -443,10 +462,21 @@
   "navigation_bar.public_timeline": "Chronologia federate",
   "navigation_bar.search": "Cercar",
   "navigation_bar.security": "Securitate",
+  "not_signed_in_indicator.not_signed_in": "Es necessari aperir session pro acceder a iste ressource.",
+  "notification.admin.report": "{name} ha signalate {target}",
+  "notification.admin.sign_up": "{name} se ha inscribite",
   "notification.favourite": "{name} ha marcate tu message como favorite",
+  "notification.follow": "{name} te ha sequite",
+  "notification.follow_request": "{name} ha requestate de sequer te",
+  "notification.mention": "{name} te ha mentionate",
   "notification.own_poll": "Tu sondage ha finite",
+  "notification.poll": "Un sondage in le qual tu ha votate ha finite",
   "notification.reblog": "{name} ha impulsate tu message",
+  "notification.relationships_severance_event": "Connexiones perdite con {name}",
+  "notification.relationships_severance_event.account_suspension": "Un administrator de {from} ha suspendiute {target}. Isto significa que tu non pote plus reciper actualisationes de iste persona o interager con ille.",
+  "notification.relationships_severance_event.domain_block": "Un administrator de {from} ha blocate {target}, includente {followersCount} de tu sequitores e {followingCount, plural, one {# conto} other {# contos}} que tu seque.",
   "notification.relationships_severance_event.learn_more": "Apprender plus",
+  "notification.relationships_severance_event.user_domain_block": "Tu ha blocate {target}, assi removente {followersCount} de tu sequitores e {followingCount, plural, one {# conto} other {# contos}} que tu seque.",
   "notification.status": "{name} ha justo ora publicate",
   "notification.update": "{name} ha modificate un message",
   "notification_requests.accept": "Acceptar",
@@ -455,10 +485,14 @@
   "notification_requests.title": "Notificationes filtrate",
   "notifications.clear": "Rader notificationes",
   "notifications.clear_confirmation": "Es tu secur que tu vole rader permanentemente tote tu notificationes?",
+  "notifications.column_settings.admin.report": "Nove signalationes:",
+  "notifications.column_settings.admin.sign_up": "Nove inscriptiones:",
   "notifications.column_settings.alert": "Notificationes de scriptorio",
   "notifications.column_settings.favourite": "Favoritos:",
   "notifications.column_settings.filter_bar.advanced": "Monstrar tote le categorias",
+  "notifications.column_settings.filter_bar.category": "Barra de filtro rapide",
   "notifications.column_settings.follow": "Nove sequitores:",
+  "notifications.column_settings.follow_request": "Nove requestas de sequimento:",
   "notifications.column_settings.mention": "Mentiones:",
   "notifications.column_settings.poll": "Resultatos del sondage:",
   "notifications.column_settings.push": "Notificationes push",
@@ -467,99 +501,226 @@
   "notifications.column_settings.sound": "Reproducer sono",
   "notifications.column_settings.status": "Nove messages:",
   "notifications.column_settings.unread_notifications.category": "Notificationes non legite",
+  "notifications.column_settings.unread_notifications.highlight": "Marcar le notificationes non legite",
+  "notifications.column_settings.update": "Modificationes:",
   "notifications.filter.all": "Toto",
   "notifications.filter.boosts": "Impulsos",
   "notifications.filter.favourites": "Favoritos",
+  "notifications.filter.follows": "Sequites",
   "notifications.filter.mentions": "Mentiones",
   "notifications.filter.polls": "Resultatos del sondage",
   "notifications.filter.statuses": "Actualisationes de personas que tu seque",
   "notifications.grant_permission": "Conceder permission.",
   "notifications.group": "{count} notificationes",
   "notifications.mark_as_read": "Marcar cata notification como legite",
+  "notifications.permission_denied": "Le notificationes de scriptorio es indisponibile a causa de un requesta anteriormente refusate de permissiones del navigator",
+  "notifications.permission_denied_alert": "Le notificationes de scriptorio non pote esser activate perque le permission del navigator ha essite refusate anteriormente",
+  "notifications.permission_required": "Le notificationes de scriptorio es indisponibile perque le permission necessari non ha essite concedite.",
+  "notifications.policy.filter_new_accounts.hint": "Create in le ultime {days, plural, one {die} other {# dies}}",
   "notifications.policy.filter_new_accounts_title": "Nove contos",
+  "notifications.policy.filter_not_followers_hint": "Includente le personas que te ha sequite durante minus de {days, plural, one {un die} other {# dies}}",
+  "notifications.policy.filter_not_followers_title": "Personas qui non te seque",
+  "notifications.policy.filter_not_following_hint": "Usque tu les approba manualmente",
+  "notifications.policy.filter_not_following_title": "Personas que tu non seque",
+  "notifications.policy.filter_private_mentions_hint": "Filtrate, excepte si es in responsa a tu proprie mention o si tu seque le expeditor",
+  "notifications.policy.filter_private_mentions_title": "Mentiones private indesirate",
+  "notifications.policy.title": "Filtrar notificationes de…",
   "notifications_permission_banner.enable": "Activar notificationes de scriptorio",
+  "notifications_permission_banner.how_to_control": "Pro reciper notificationes quando Mastodon non es aperte, activa le notificationes de scriptorio. Post lor activation, es possibile controlar precisemente qual typos de interaction genera notificationes de scriptorio per medio del button {icon} hic supra.",
+  "notifications_permission_banner.title": "Non mancar jammais a un cosa",
+  "onboarding.action.back": "Porta me retro",
+  "onboarding.actions.back": "Porta me retro",
+  "onboarding.actions.go_to_explore": "Porta me al tendentias",
   "onboarding.actions.go_to_home": "Porta me a mi fluxo de initio",
   "onboarding.compose.template": "Salute #Mastodon!",
+  "onboarding.follows.empty": "Regrettabilemente, non es possibile monstrar resultatos al momento. Tu pote tentar usar le recerca o percurrer le pagina de exploration pro cercar personas a sequer, o tentar lo de novo plus tarde.",
   "onboarding.follows.lead": "Le fluxo de initio es le maniera principal de discoperir Mastodon. Quanto plus personas tu seque, tanto plus active e interessante illo essera. Pro comenciar, ecce alcun suggestiones:",
   "onboarding.follows.title": "Personalisar tu fluxo de initio",
+  "onboarding.profile.discoverable": "Render mi profilo discoperibile",
   "onboarding.profile.discoverable_hint": "Quando tu opta pro devenir discoperibile sur Mastodon, tu messages pote apparer in resultatos de recerca e in tendentias, e tu profilo pote esser suggerite al personas con interesses simile al tues.",
+  "onboarding.profile.display_name": "Nomine a monstrar",
+  "onboarding.profile.display_name_hint": "Tu nomine complete o tu supernomine…",
+  "onboarding.profile.lead": "Tu pote sempre completar isto plus tarde in le parametros, ubi se trova mesmo plus optiones de personalisation.",
+  "onboarding.profile.note": "Bio",
+  "onboarding.profile.note_hint": "Tu pote @mentionar altere personas o #hashtags…",
   "onboarding.profile.save_and_continue": "Salvar e continuar",
+  "onboarding.profile.title": "Configuration del profilo",
+  "onboarding.profile.upload_avatar": "Incargar imagine de profilo",
+  "onboarding.profile.upload_header": "Actualisar capite de profilo",
+  "onboarding.share.lead": "Face saper al gente como illes pote trovar te sur Mastodon!",
+  "onboarding.share.message": "Io es {username} sur Mastodon! Veni sequer me a {url}",
   "onboarding.share.next_steps": "Sequente passos possibile:",
   "onboarding.share.title": "Compartir tu profilo",
+  "onboarding.start.lead": "Tu face ora parte de Mastodon, un platteforma de medios social unic e decentralisate ubi es tu, e non un algorithmo, qui crea tu proprie experientia. Nos va adjutar te a lancear te in iste nove frontiera social:",
+  "onboarding.start.skip": "Non require adjuta a comenciar?",
+  "onboarding.start.title": "Tu ha arrivate!",
+  "onboarding.steps.follow_people.body": "Sequer personas interessante es le ration de esser de Mastodon.",
   "onboarding.steps.follow_people.title": "Personalisar tu fluxo de initio",
+  "onboarding.steps.publish_status.body": "Saluta le mundo con texto, photos, videos o sondages {emoji}",
   "onboarding.steps.publish_status.title": "Face tu prime message",
   "onboarding.steps.setup_profile.body": "Impulsa tu interactiones con un profilo comprehensive.",
   "onboarding.steps.setup_profile.title": "Personalisa tu profilo",
+  "onboarding.steps.share_profile.body": "Face saper a tu amicos como trovar te sur Mastodon",
   "onboarding.steps.share_profile.title": "Compartir tu profilo de Mastodon",
+  "onboarding.tips.2fa": "<strong>Lo sapeva tu?</strong> Tu pote securisar tu conto configurante le authentication bifactorial in le parametros de tu conto. Isto functiona con le application TOTP de tu preferentia, sin necessitate de un numero de telephono!",
+  "onboarding.tips.accounts_from_other_servers": "<strong>Lo sapeva tu?</strong> Perque Mastodon es decentralisate, le profilos que tu incontra pote esser hospitate sur servitores altere que le tue. Nonobstante, tu pote interager con illos sin problema! Lor servitor se trova in le secunde medietate de lor nomine de usator!",
+  "onboarding.tips.migration": "<strong>Lo sapeva tu?</strong> Si tu pensa que {domain} non es un bon servitor pro te in le futuro, tu pote cambiar a un altere servitor Mastodon sin perder tu sequitores. Tu pote mesmo hospitar tu proprie servitor!",
+  "onboarding.tips.verification": "<strong>Lo sapeva tu?</strong> Pro verificar tu conto, insere un ligamine a tu profilo Mastodon sur tu proprie sito web e adde le sito web a tu profilo. Nulle moneta o documentos necessari!",
+  "password_confirmation.exceeds_maxlength": "Le confirmation del contrasigno excede le longitude maxime del contrasigno",
+  "password_confirmation.mismatching": "Le confirmation del contrasigno non corresponde",
+  "picture_in_picture.restore": "Restaurar",
   "poll.closed": "Claudite",
+  "poll.refresh": "Refrescar",
   "poll.reveal": "Vider le resultatos",
+  "poll.total_people": "{count, plural, one {# persona} other {# personas}}",
+  "poll.total_votes": "{count, plural, one {# voto} other {# votos}}",
+  "poll.vote": "Votar",
+  "poll.voted": "Tu ha votate pro iste responsa",
+  "poll.votes": "{votes, plural, one {# voto} other {# votos}}",
+  "poll_button.add_poll": "Adder un inquesta",
+  "poll_button.remove_poll": "Remover un inquesta",
   "privacy.change": "Cambiar le confidentialitate del message",
   "privacy.direct.long": "Tote le personas mentionate in le message",
+  "privacy.direct.short": "Personas specific",
+  "privacy.private.long": "Solmente tu sequitores",
+  "privacy.private.short": "Sequitores",
+  "privacy.public.long": "Quicunque, sur Mastodon o non",
   "privacy.public.short": "Public",
   "privacy.unlisted.additional": "Isto es exactemente como public, excepte que le message non apparera in fluxos in directo, in hashtags, in Explorar, o in le recerca de Mastodon, mesmo si tu ha optate pro render tote le conto discoperibile.",
+  "privacy.unlisted.long": "Minus fanfares algorithmic",
+  "privacy.unlisted.short": "Public, non listate",
   "privacy_policy.last_updated": "Ultime actualisation {date}",
   "privacy_policy.title": "Politica de confidentialitate",
+  "recommended": "Recommendate",
+  "refresh": "Refrescar",
+  "regeneration_indicator.label": "Cargamento…",
   "regeneration_indicator.sublabel": "Tu fluxo de initio es in preparation!",
+  "relative_time.days": "{number}d",
+  "relative_time.full.days": "{number, plural, one {# die} other {# dies}} retro",
+  "relative_time.full.hours": "{number, plural, one {# hora} other {# horas}} retro",
+  "relative_time.full.just_now": "justo ora",
+  "relative_time.full.minutes": "{number, plural, one {# minuta} other {# minutas}} retro",
+  "relative_time.full.seconds": "{number, plural, one {# secunda} other {# secundas}} retro",
+  "relative_time.hours": "{number}h",
   "relative_time.just_now": "ora",
+  "relative_time.minutes": "{number}m",
+  "relative_time.seconds": "{number}s",
   "relative_time.today": "hodie",
+  "reply_indicator.attachments": "{count, plural, one {# annexo} other {# annexos}}",
   "reply_indicator.cancel": "Cancellar",
+  "reply_indicator.poll": "Inquesta",
   "report.block": "Blocar",
   "report.block_explanation": "Tu non videra le messages de iste persona. Ille non potera vider tu messages o sequer te. Ille potera saper de esser blocate.",
+  "report.categories.legal": "Juridic",
   "report.categories.other": "Alteres",
+  "report.categories.spam": "Spam",
+  "report.categories.violation": "Le contento viola un o plus regulas del servitor",
+  "report.category.subtitle": "Elige le option plus adequate",
+  "report.category.title": "Describe le problema con iste {type}",
   "report.category.title_account": "profilo",
   "report.category.title_status": "message",
   "report.close": "Facite",
+  "report.comment.title": "Ha il altere cosas que nos deberea saper?",
+  "report.forward": "Reinviar a {target}",
+  "report.forward_hint": "Le conto es de un altere servitor. Inviar un copia anonymisate del signalation a illo tamben?",
   "report.mute": "Silentiar",
   "report.mute_explanation": "Tu non videra le messages de iste persona. Ille pote totevia sequer te e vider tu messages e non sapera de esser silentiate.",
   "report.next": "Sequente",
   "report.placeholder": "Commentos additional",
   "report.reasons.dislike": "Non me place",
+  "report.reasons.dislike_description": "Non es qualcosa que tu vole vider",
+  "report.reasons.legal": "Es illegal",
+  "report.reasons.legal_description": "Tu crede que viola le lege de tu pais o del pais del servitor",
+  "report.reasons.other": "Es altere cosa",
+  "report.reasons.other_description": "Le problema non entra in altere categorias",
+  "report.reasons.spam": "Es spam",
+  "report.reasons.spam_description": "Ligamines malevolente, interaction false, o responsas repetitive",
+  "report.reasons.violation": "Viola le regulas del servitor",
+  "report.reasons.violation_description": "Tu sape que viola regulas specific",
+  "report.rules.subtitle": "Selige tote le responsas appropriate",
+  "report.rules.title": "Qual regulas es violate?",
+  "report.statuses.subtitle": "Selige tote le responsas appropriate",
   "report.statuses.title": "Existe alcun messages que appoia iste reporto?",
+  "report.submit": "Submitter",
+  "report.target": "Signalamento de {target}",
+  "report.thanks.take_action": "Ecce tu optiones pro controlar lo que tu vide sur Mastodon:",
+  "report.thanks.take_action_actionable": "Durante que nos revide isto, tu pote prender mesuras contra @{name}:",
+  "report.thanks.title": "Non vole vider isto?",
+  "report.thanks.title_actionable": "Gratias pro signalar, nos investigara isto.",
+  "report.unfollow": "Cessar de sequer @{name}",
   "report.unfollow_explanation": "Tu seque iste conto. Pro non plus vider su messages in tu fluxo de initio, cessa de sequer lo.",
   "report_notification.attached_statuses": "{count, plural, one {{count} message} other {{count} messages}} annexate",
+  "report_notification.categories.legal": "Juridic",
   "report_notification.categories.other": "Alteres",
+  "report_notification.categories.spam": "Spam",
+  "report_notification.categories.violation": "Violation del regulas",
   "report_notification.open": "Aperir reporto",
   "search.no_recent_searches": "Nulle recercas recente",
+  "search.placeholder": "Cercar",
+  "search.quick_action.account_search": "Profilos correspondente a {x}",
   "search.quick_action.go_to_account": "Vader al profilo {x}",
   "search.quick_action.go_to_hashtag": "Vader al hashtag {x}",
   "search.quick_action.open_url": "Aperir URL in Mastodon",
   "search.quick_action.status_search": "Messages correspondente a {x}",
+  "search.search_or_paste": "Cerca o colla un URL",
   "search_popout.full_text_search_disabled_message": "Non disponibile sur {domain}.",
+  "search_popout.full_text_search_logged_out_message": "Solmente disponibile al initiar le session.",
   "search_popout.language_code": "Codice de lingua ISO",
   "search_popout.options": "Optiones de recerca",
   "search_popout.quick_actions": "Actiones rapide",
   "search_popout.recent": "Recercas recente",
+  "search_popout.specific_date": "data specific",
   "search_popout.user": "usator",
   "search_results.accounts": "Profilos",
+  "search_results.all": "Toto",
   "search_results.hashtags": "Hashtags",
+  "search_results.nothing_found": "Nihil trovate pro iste terminos de recerca",
   "search_results.see_all": "Vider toto",
   "search_results.statuses": "Messages",
+  "search_results.title": "Cercar {q}",
+  "server_banner.about_active_users": "Personas que ha usate iste servitor in le ultime 30 dies (usatores active per mense)",
   "server_banner.active_users": "usatores active",
+  "server_banner.administered_by": "Administrate per:",
+  "server_banner.introduction": "{domain} face parte del rete social decentralisate actionate per {mastodon}.",
   "server_banner.learn_more": "Apprender plus",
   "server_banner.server_stats": "Statos del servitor:",
   "sign_in_banner.create_account": "Crear un conto",
   "sign_in_banner.sign_in": "Aperir session",
+  "sign_in_banner.sso_redirect": "Aperir session o crear conto",
   "sign_in_banner.text": "Aperi session pro sequer profilos o hashtags, marcar messages como favorite, e condivider e responder a messages. Tu pote etiam interager desde tu conto sur un altere servitor.",
+  "status.admin_account": "Aperir le interfacie de moderation pro @{name}",
+  "status.admin_domain": "Aperir le interfacie de moderation pro {domain}",
   "status.admin_status": "Aperir iste message in le interfacie de moderation",
   "status.block": "Blocar @{name}",
+  "status.bookmark": "Adder al marcapaginas",
   "status.cancel_reblog_private": "Disfacer impulso",
   "status.cannot_reblog": "Iste message non pote esser impulsate",
   "status.copy": "Copiar ligamine a message",
   "status.delete": "Deler",
+  "status.detailed_status": "Vista detaliate del conversation",
   "status.direct": "Mentionar privatemente @{name}",
   "status.direct_indicator": "Mention private",
   "status.edit": "Modificar",
+  "status.edited": "Ultime modification le {date}",
   "status.edited_x_times": "Modificate {count, plural, one {{count} vice} other {{count} vices}}",
+  "status.embed": "Incastrar",
   "status.favourite": "Adder al favoritos",
+  "status.favourites": "{count, plural, one {favorite} other {favorites}}",
   "status.filter": "Filtrar iste message",
+  "status.filtered": "Filtrate",
   "status.hide": "Celar le message",
   "status.history.created": "create per {name} le {date}",
   "status.history.edited": "modificate per {name} le {date}",
+  "status.load_more": "Cargar plus",
   "status.media.open": "Clicca pro aperir",
   "status.media.show": "Clicca pro monstrar",
+  "status.media_hidden": "Medios celate",
+  "status.mention": "Mentionar @{name}",
   "status.more": "Plus",
+  "status.mute": "Silentiar @{name}",
   "status.mute_conversation": "Silentiar conversation",
   "status.open": "Expander iste message",
+  "status.pin": "Fixar sur profilo",
   "status.pinned": "Message fixate",
   "status.read_more": "Leger plus",
   "status.reblog": "Impulsar",
@@ -592,13 +753,47 @@
   "subscribed_languages.target": "Cambiar le linguas subscribite pro {target}",
   "tabs_bar.home": "Initio",
   "tabs_bar.notifications": "Notificationes",
+  "time_remaining.days": "{number, plural, one {# die} other {# dies}} restante",
+  "time_remaining.hours": "{number, plural, one {# hora} other {# horas}} restante",
+  "time_remaining.minutes": "{number, plural, one {# minuta} other {# minutas}} restante",
+  "time_remaining.moments": "Qualque momentos restante",
+  "time_remaining.seconds": "{number, plural, one {# secunda} other {# secundas}} restante",
+  "timeline_hint.remote_resource_not_displayed": "Le {resource} de altere servitores non appare hic.",
+  "timeline_hint.resources.followers": "Sequitores",
+  "timeline_hint.resources.follows": "Sequites",
   "timeline_hint.resources.statuses": "Messages ancian",
+  "trends.counter_by_accounts": "{count, plural, one {{counter} persona} other {{counter} personas}} in le passate {days, plural, one {die} other {{days} dies}}",
   "trends.trending_now": "Ora in tendentias",
+  "ui.beforeunload": "Tu esbosso essera predite si tu exi de Mastodon.",
+  "units.short.billion": "{count}B",
+  "units.short.million": "{count}M",
+  "units.short.thousand": "{count}K",
+  "upload_area.title": "Traher e deponer pro incargar",
   "upload_button.label": "Adde imagines, un video o un file de audio",
+  "upload_error.limit": "Limite de incargamento de files excedite.",
+  "upload_error.poll": "Incargamento de files non permittite con sondages.",
+  "upload_form.audio_description": "Describe lo pro le gente con difficultates auditive",
+  "upload_form.description": "Describe lo pro le gente con difficultates visual",
+  "upload_form.edit": "Modificar",
+  "upload_form.thumbnail": "Cambiar le miniatura",
+  "upload_form.video_description": "Describe lo pro le gente con difficultates auditive o visual",
+  "upload_modal.analyzing_picture": "Analysa imagine…",
+  "upload_modal.apply": "Applicar",
+  "upload_modal.applying": "Applicante…",
   "upload_modal.choose_image": "Seliger un imagine",
+  "upload_modal.description_placeholder": "Le clown uzbek dogmatic justo foras quasi se asphyxiava",
   "upload_modal.detect_text": "Deteger texto de un imagine",
+  "upload_modal.edit_media": "Modificar le medio",
+  "upload_modal.hint": "Clicca o trahe le circulo sur le previsualisation pro eliger le puncto focal que essera sempre visibile sur tote le miniaturas.",
+  "upload_modal.preparing_ocr": "Preparation del OCR…",
+  "upload_modal.preview_label": "Previsualisation ({ratio})",
+  "upload_progress.label": "Incargante...",
+  "upload_progress.processing": "Processante…",
+  "username.taken": "Iste nomine de usator es ja in uso. Proba con un altere",
   "video.close": "Clauder le video",
   "video.download": "Discargar le file",
+  "video.exit_fullscreen": "Sortir del schermo plen",
+  "video.expand": "Expander video",
   "video.fullscreen": "Schermo plen",
   "video.hide": "Celar video",
   "video.mute": "Silentiar le sono",
diff --git a/app/javascript/mastodon/locales/id.json b/app/javascript/mastodon/locales/id.json
index 764c08111..90a48b634 100644
--- a/app/javascript/mastodon/locales/id.json
+++ b/app/javascript/mastodon/locales/id.json
@@ -21,6 +21,7 @@
   "account.blocked": "Terblokir",
   "account.browse_more_on_origin_server": "Lihat lebih lanjut di profil asli",
   "account.cancel_follow_request": "Batalkan permintaan ikut",
+  "account.copy": "Salin tautan ke profil",
   "account.direct": "Sebut secara pribadi @{name}",
   "account.disable_notifications": "Berhenti memberitahu saya ketika @{name} memposting",
   "account.domain_blocked": "Domain diblokir",
@@ -31,6 +32,7 @@
   "account.featured_tags.last_status_never": "Tidak ada kiriman",
   "account.featured_tags.title": "Tagar {name} yang difiturkan",
   "account.follow": "Ikuti",
+  "account.follow_back": "Ikuti balik",
   "account.followers": "Pengikut",
   "account.followers.empty": "Pengguna ini belum ada pengikut.",
   "account.followers_counter": "{count, plural, other {{counter} Pengikut}}",
@@ -51,6 +53,7 @@
   "account.mute_notifications_short": "Senyapkan Notifikasi",
   "account.mute_short": "Senyapkan",
   "account.muted": "Dibisukan",
+  "account.mutual": "Saling ikuti",
   "account.no_bio": "Tidak ada deskripsi yang diberikan.",
   "account.open_original_page": "Buka halaman asli",
   "account.posts": "Kiriman",
@@ -75,6 +78,10 @@
   "admin.dashboard.retention.average": "Rata-rata",
   "admin.dashboard.retention.cohort": "Bulan pendaftaran",
   "admin.dashboard.retention.cohort_size": "Pengguna baru",
+  "admin.impact_report.instance_accounts": "Akun profil yang akan terhapus",
+  "admin.impact_report.instance_followers": "Pengikut yang akan kehilangan oleh pengguna kita",
+  "admin.impact_report.instance_follows": "Pengikut yang akan kehilangan oleh pengguna lain",
+  "admin.impact_report.title": "Ringkasan dampak",
   "alert.rate_limited.message": "Mohon ulangi setelah {retry_time, time, medium}.",
   "alert.rate_limited.title": "Jumlah akses dibatasi",
   "alert.unexpected.message": "Terjadi kesalahan yang tidak terduga.",
@@ -82,6 +89,14 @@
   "announcement.announcement": "Pengumuman",
   "attachments_list.unprocessed": "(tidak diproses)",
   "audio.hide": "Sembunyikan audio",
+  "block_modal.remote_users_caveat": "Kami akan meminta {domain} server untuk menghargai keputusan Anda. Namun, kepatuhan tak dapat dipastikan karena beberapa server dapat menangani blokir secara beragam. Postingan publik masih dapat terlihat oleh pengguna tanpa masuk.",
+  "block_modal.show_less": "Tampilkan lebih sedikit",
+  "block_modal.show_more": "Tampilkan lebih banyak",
+  "block_modal.they_cant_mention": "Mereka tidak dapat menyebut atau mengikuti Anda.",
+  "block_modal.they_cant_see_posts": "Mereka tidak dapat melihat postingan Anda dan Anda tidak dapat melihat postingan mereka.",
+  "block_modal.they_will_know": "Mereka dapat melihat bahwa mereka diblokir.",
+  "block_modal.title": "Blokir pengguna?",
+  "block_modal.you_wont_see_mentions": "Anda tidak akan melihat kiriman yang menyebutkan mereka.",
   "boost_modal.combo": "Anda dapat menekan {combo} untuk melewati ini",
   "bundle_column_error.copy_stacktrace": "Salin laporan kesalahan",
   "bundle_column_error.error.body": "Laman yang diminta tidak dapat ditampilkan. Mungkin karena sebuah kutu dalam kode kami, atau masalah kompatibilitas peramban.",
@@ -104,8 +119,10 @@
   "column.blocks": "Pengguna yang diblokir",
   "column.bookmarks": "Markah",
   "column.community": "Linimasa Lokal",
+  "column.direct": "Sebut secara pribadi",
   "column.directory": "Jelajahi profil",
   "column.domain_blocks": "Domain tersembunyi",
+  "column.favourites": "Favorit",
   "column.follow_requests": "Permintaan mengikuti",
   "column.home": "Beranda",
   "column.lists": "List",
diff --git a/app/javascript/mastodon/locales/ja.json b/app/javascript/mastodon/locales/ja.json
index 16e7e6c44..30c9eb77a 100644
--- a/app/javascript/mastodon/locales/ja.json
+++ b/app/javascript/mastodon/locales/ja.json
@@ -297,6 +297,7 @@
   "filter_modal.select_filter.subtitle": "既存のカテゴリーを使用するか新規作成します",
   "filter_modal.select_filter.title": "この投稿をフィルターする",
   "filter_modal.title.status": "投稿をフィルターする",
+  "filtered_notifications_banner.mentions": "{count, plural, one {メンション} other {メンション}}",
   "filtered_notifications_banner.pending_requests": "{count, plural, =0 {アカウント} other {#アカウント}}からの通知がブロックされています",
   "filtered_notifications_banner.title": "ブロック済みの通知",
   "firehose.all": "すべて",
@@ -488,6 +489,8 @@
   "notifications.column_settings.admin.sign_up": "新規登録:",
   "notifications.column_settings.alert": "デスクトップ通知",
   "notifications.column_settings.favourite": "お気に入り:",
+  "notifications.column_settings.filter_bar.advanced": "すべてのカテゴリを表示",
+  "notifications.column_settings.filter_bar.category": "クイックフィルターバー:",
   "notifications.column_settings.follow": "新しいフォロワー:",
   "notifications.column_settings.follow_request": "新しいフォローリクエスト:",
   "notifications.column_settings.mention": "返信:",
@@ -698,9 +701,11 @@
   "status.direct": "@{name}さんに非公開で投稿",
   "status.direct_indicator": "非公開の返信",
   "status.edit": "編集",
+  "status.edited": "最終更新日 {date}",
   "status.edited_x_times": "{count}回編集",
   "status.embed": "埋め込み",
   "status.favourite": "お気に入り",
+  "status.favourites": "{count, plural, one {お気に入り} other {お気に入り}}",
   "status.filter": "この投稿をフィルターする",
   "status.filtered": "フィルターされました",
   "status.hide": "投稿を非表示",
@@ -721,6 +726,7 @@
   "status.reblog": "ブースト",
   "status.reblog_private": "ブースト",
   "status.reblogged_by": "{name}さんがブースト",
+  "status.reblogs": "{count, plural, one {ブースト} other {ブースト}}",
   "status.reblogs.empty": "まだ誰もブーストしていません。ブーストされるとここに表示されます。",
   "status.redraft": "削除して下書きに戻す",
   "status.remove_bookmark": "ブックマークを削除",
diff --git a/config/locales/devise.ia.yml b/config/locales/devise.ia.yml
index 4b4d1f441..62f106bcf 100644
--- a/config/locales/devise.ia.yml
+++ b/config/locales/devise.ia.yml
@@ -2,6 +2,8 @@
 ia:
   devise:
     failure:
+      already_authenticated: Tu jam initiava le session.
+      inactive: Tu conto ancora non es activate.
       locked: Tu conto es blocate.
     mailer:
       confirmation_instructions:
diff --git a/config/locales/fi.yml b/config/locales/fi.yml
index ab92e106a..f82a592ec 100644
--- a/config/locales/fi.yml
+++ b/config/locales/fi.yml
@@ -770,7 +770,7 @@ fi:
         disabled: Ei kenellekkään
         users: Kirjautuneille paikallisille käyttäjille
       registrations:
-        moderation_recommandation: Varmista, että sinulla on riittävä ja toimintavalmis joukko moderaattoreita ennen kuin avaat rekisteröitymiset kaikille!
+        moderation_recommandation: Varmista, että sinulla on riittävä ja toimintavalmis joukko moderaattoreita, ennen kuin vapautat rekisteröitymismenettelyn kaikille!
         preamble: Määritä, kuka voi luoda tilin palvelimellesi.
         title: Rekisteröityminen
       registrations_mode:
@@ -972,7 +972,7 @@ fi:
       webhook: Webhook
   admin_mailer:
     auto_close_registrations:
-      body: Viimeaikaisen moderaattoritoiminnan puutteen vuoksi palvelimen %{instance} rekisteröitymiset on vaihdettu automaattisesti manuaaliseen tarkasteluun, jotta palvelinta %{instance} ei käytetä mahdollisten huonojen toimijoiden alustana. Voit vaihtaa takaisin avoimiin rekisteröitymisiin milloin tahansa.
+      body: Palvelimen %{instance} moderaattorit eivät ole olleet viime aikoina aktiivisia. Tästä syystä rekisteröitymismenettely on automaattisesti vaihdettu erillishyväksyntöjä edellyttäväksi. Näin vähennetään riskiä palvelimen %{instance} käyttöön haitallisten toimijoiden alustana. Voit koska tahansa palauttaa käyttöön vapaat rekisteröitymiset.
       subject: Rekisteröitymiset palvelimelle %{instance} on automaattisesti vaihdettu vaatimaan hyväksyntää
     new_appeal:
       actions:
@@ -1882,8 +1882,8 @@ fi:
       follows_title: Ehdotuksia seurattavaksi
       follows_view_more: Näytä lisää seurattavia henkilöitä
       hashtags_recent_count:
-        one: "%{people} henkilö viimeisenä 2 päivänä"
-        other: "%{people} henkilöä viimeisenä 2 päivänä"
+        one: "%{people} henkilö viimeisen 2 päivän aikana"
+        other: "%{people} henkilöä viimeisen 2 päivän aikana"
       hashtags_subtitle: Tutki, mikä on ollut suosittua viimeisenä 2 päivänä
       hashtags_title: Suositut aihetunnisteet
       hashtags_view_more: Näytä lisää suosittuja aihetunnisteita
diff --git a/config/locales/ia.yml b/config/locales/ia.yml
index 5065ca7bb..3ba7a5148 100644
--- a/config/locales/ia.yml
+++ b/config/locales/ia.yml
@@ -53,7 +53,10 @@ ia:
         all: Toto
         title: Location
       moderation:
+        active: Active
+        all: Toto
         disabled: Disactivate
+      moderation_notes: Notas de moderation
       most_recent_activity: Activitate plus recente
       most_recent_ip: IP plus recente
       public: Public
@@ -83,13 +86,19 @@ ia:
     action_logs:
       action_types:
         confirm_user: Confirmar le usator
+        create_account_warning: Crear un advertimento
         create_announcement: Crear annuncio
+        create_ip_block: Crear un regula IP
+        destroy_announcement: Deler annuncio
         destroy_ip_block: Deler le regula IP
         destroy_status: Deler le message
         destroy_unavailable_domain: Deler le dominio non disponibile
         disable_2fa_user: Disactivar 2FA
+        disable_custom_emoji: Disactivar emoji personalisate
         disable_user: Disactivar le usator
+        enable_custom_emoji: Activar emoji personalisate
         enable_user: Activar le usator
+        promote_user: Promover usator
         reset_password_user: Reinitialisar contrasigno
         update_announcement: Actualisar annuncio
         update_custom_emoji: Actualisar emoji personalisate
@@ -112,8 +121,10 @@ ia:
       title: Annuncios
     custom_emojis:
       by_domain: Dominio
+      copied_msg: Copia local del emoji create con successo
       copy: Copiar
       create_new_category: Crear nove categoria
+      created_msg: Emoji create con successo!
       delete: Deler
       disable: Disactivar
       disabled: Disactivate
@@ -125,16 +136,22 @@ ia:
       upload: Incargar
     dashboard:
       active_users: usatores active
+      interactions: interactiones
       media_storage: Immagazinage de medios
       new_users: nove usatores
       opened_reports: reportos aperte
+      top_languages: Linguas le plus active
+      top_servers: Servitores le plus active
       website: Sito web
     domain_allows:
       add_new: Permitter federation con dominio
+      export: Exportar
+      import: Importar
     domain_blocks:
       confirm_suspension:
         cancel: Cancellar
       domain: Dominio
+      edit: Modificar un bloco de dominio
       export: Exportar
       import: Importar
       private_comment: Commento private
@@ -145,19 +162,31 @@ ia:
       domain: Dominio
       new:
         create: Adder un dominio
+        title: Blocar un nove dominio de e-mail
+      title: Dominios de e-mail blocate
     export_domain_allows:
       no_file: Necun file seligite
+    export_domain_blocks:
+      no_file: Necun file seligite
     follow_recommendations:
       language: Per lingua
       status: Stato
+      title: Sequer le recommendationes
     instances:
+      back_to_warning: Advertimento
+      by_domain: Dominio
+      content_policies:
+        reason: Ration public
       dashboard:
+        instance_accounts_dimension: Contos le plus sequite
         instance_languages_dimension: Linguas principal
       delivery:
         unavailable: Non disponibile
       empty: Necun dominios trovate.
       private_comment: Commento private
       public_comment: Commento public
+      total_blocked_by_us: Blocate per nos
+      total_followed_by_us: Sequite per nos
     invites:
       deactivate_all: Disactivar toto
       filter:
@@ -179,12 +208,17 @@ ia:
       disabled: Disactivate
       enable: Activar
       enabled: Activate
+      save_and_enable: Salveguardar e activar
+      status: Stato
     reports:
       add_to_report: Adder plus al reporto
       are_you_sure: Es tu secur?
       cancel: Cancellar
+      category: Categoria
+      confirm: Confirmar
       delete_and_resolve: Deler le messages
       notes:
+        create: Adder un nota
         delete: Deler
       skip_to_actions: Saltar al actiones
       status: Stato
@@ -193,6 +227,11 @@ ia:
     roles:
       everyone: Permissiones predefinite
       privileges:
+        delete_user_data: Deler le datos de usator
+        manage_announcements: Gerer le annuncios
+        manage_invites: Gerer le invitationes
+        manage_rules: Gerer le regulas
+        manage_settings: Gerer le parametros
         manage_users: Gerer usatores
     rules:
       delete: Deler
@@ -294,6 +333,13 @@ ia:
       not_found: non poterea esser trovate
   preferences:
     public_timelines: Chronologias public
+  statuses:
+    poll:
+      vote: Votar
+    show_more: Monstrar plus
+    visibilities:
+      private_long: Solmente monstrar a sequitores
+      public: Public
   statuses_cleanup:
     min_age:
       '1209600': 2 septimanas
@@ -307,11 +353,26 @@ ia:
   themes:
     default: Mastodon (Obscur)
     mastodon-light: Mastodon (Clar)
+    system: Automatic (usar thema del systema)
   two_factor_authentication:
     add: Adder
     disable: Disactivar 2FA
+    edit: Modificar
   user_mailer:
+    appeal_approved:
+      action: Parametros de conto
     welcome:
+      apps_android_action: Obtene lo sur Google Play
+      apps_ios_action: Discargar sur le App Store
+      apps_step: Discarga nostre applicationes official.
+      apps_title: Applicationes de Mastodon
+      edit_profile_action: Personalisar
+      edit_profile_title: Personalisar tu profilo
+      feature_action: Apprender plus
+      share_title: Compartir tu profilo de Mastodon
       subject: Benvenite in Mastodon
+  verification:
+    verified_links: Tu ligamines verificate
   webauthn_credentials:
+    add: Adder un nove clave de securitate
     delete: Deler
diff --git a/config/locales/ja.yml b/config/locales/ja.yml
index f9cbb6a75..da9a42141 100644
--- a/config/locales/ja.yml
+++ b/config/locales/ja.yml
@@ -1849,6 +1849,8 @@ ja:
       follows_subtitle: 人気アカウントをフォロー
       follows_title: フォローを増やしてみませんか?
       follows_view_more: フォローするユーザーを探す
+      hashtags_recent_count:
+        other: 過去 2 日間で %{people} 人が共有
       hashtags_subtitle: 過去2日間のトレンドを見る
       hashtags_title: トレンドのハッシュタグ
       hashtags_view_more: トレンドのハッシュタグをもっと見る
diff --git a/config/locales/simple_form.fi.yml b/config/locales/simple_form.fi.yml
index b1c2e91a1..c3fbd4372 100644
--- a/config/locales/simple_form.fi.yml
+++ b/config/locales/simple_form.fi.yml
@@ -116,7 +116,7 @@ fi:
           sign_up_requires_approval: Uudet rekisteröitymiset edellyttävät hyväksyntääsi
         severity: Valitse, mitä tapahtuu tämän IP-osoitteen pyynnöille
       rule:
-        hint: Valinnainen. Anna lisätietoja säännöstä
+        hint: Vapaaehtoinen. Anna yksityiskohtaisempia tietoja säännöstä
         text: Kuvaile sääntöä tai edellytystä palvelimesi käyttäjille. Suosi tiivistä, yksinkertaista ilmaisua
       sessions:
         otp: 'Näppäile mobiilisovelluksessa näkyvä kaksivaiheisen todennuksen tunnusluku, tai käytä tarvittaessa palautuskoodia:'
diff --git a/config/locales/simple_form.ia.yml b/config/locales/simple_form.ia.yml
index 16dbcbd18..2f04ce982 100644
--- a/config/locales/simple_form.ia.yml
+++ b/config/locales/simple_form.ia.yml
@@ -1,20 +1,44 @@
 ---
 ia:
   simple_form:
+    hints:
+      account:
+        note: 'Tu pote @mentionar altere personas o #hashtags.'
+      defaults:
+        setting_display_media_hide_all: Sempre celar le medios
+        setting_display_media_show_all: Sempre monstrar le medios
+      webhook:
+        events: Selige le eventos a inviar
+        url: Ubi le eventos essera inviate
     labels:
       account:
+        discoverable: Evidentiar le profilo e messages in le algorithmos de discoperta
         fields:
           name: Etiquetta
           value: Contento
+        indexable: Includer messages public in le resultatos de recerca
+        show_collections: Monstrar sequites e sequitores in le profilo
+        unlocked: Acceptar automaticamente nove sequitores
+      account_warning_preset:
+        title: Titulo
       admin_account_action:
         type: Action
+        types:
+          none: Inviar un advertimento
+      announcement:
+        text: Annuncio
       defaults:
+        autofollow: Invitar a sequer tu conto
         avatar: Pictura de profilo
         confirm_new_password: Confirmar nove contrasigno
         confirm_password: Confirmar contrasigno
         current_password: Contrasigno actual
+        display_name: Nomine a monstrar
+        email: Adresse de e-mail
+        locale: Lingua de interfacie
         new_password: Nove contrasigno
         password: Contrasigno
+        setting_advanced_layout: Activar le interfacie web avantiate
         setting_default_language: Lingua de publication
         setting_display_media_default: Predefinite
         setting_display_media_hide_all: Celar toto
@@ -26,29 +50,50 @@ ia:
         title: Titulo
         username: Nomine de usator
         username_or_email: Nomine de usator o e-mail
+      featured_tag:
+        name: Hashtag
+      filters:
+        actions:
+          hide: Celar completemente
+          warn: Celar con un advertimento
       form_admin_settings:
         bootstrap_timeline_accounts: Recommenda sempre iste contos a nove usatores
         custom_css: CSS personalisate
         profile_directory: Activar directorio de profilos
         site_contact_email: Adresse de e-mail de contacto
         site_contact_username: Nomine de usator de contacto
+        site_short_description: Description de servitor
         site_terms: Politica de confidentialitate
         site_title: Nomine de servitor
+        status_page_url: URL del pagina de stato
         theme: Thema predefinite
         trends: Activar tendentias
       ip_block:
+        comment: Commento
         severity: Regula
       notification_emails:
         software_updates:
+          all: Notificar sur tote le actualisationes
+          critical: Notificar solmente sur actualisationes critic
           label: Un nove version de Mastodon es disponibile
+          none: Nunquam notificar sur actualisationes (non recommendate)
       rule:
+        hint: Information additional
         text: Regula
       settings:
         indexable: Includer pagina de profilo in le motores de recerca
+      tag:
+        listable: Permitter a iste hashtag apparer in le recercas e suggestiones
+        name: Hashtag
+        usable: Permitter al messages usar iste hashtag
       user:
         time_zone: Fuso horari
       user_role:
         name: Nomine
         permissions_as_keys: Permissiones
         position: Prioritate
+    not_recommended: Non recommendate
+    recommended: Recommendate
+    required:
+      text: requirite
     'yes': Si

From 75163d9daf831a0562bcf35bffb883c2e7b239b7 Mon Sep 17 00:00:00 2001
From: Tim Rogers <rogers.timothy.john@gmail.com>
Date: Mon, 22 Apr 2024 03:53:08 -0500
Subject: [PATCH 09/19] Fixed rendering error on /start when not logged in
 (#30023)

---
 .../mastodon/features/onboarding/index.jsx    | 71 ++++++++++---------
 1 file changed, 37 insertions(+), 34 deletions(-)

diff --git a/app/javascript/mastodon/features/onboarding/index.jsx b/app/javascript/mastodon/features/onboarding/index.jsx
index 5900b9ec7..529d53f25 100644
--- a/app/javascript/mastodon/features/onboarding/index.jsx
+++ b/app/javascript/mastodon/features/onboarding/index.jsx
@@ -16,6 +16,7 @@ import EditNoteIcon from '@/material-icons/400-24px/edit_note.svg?react';
 import PersonAddIcon from '@/material-icons/400-24px/person_add.svg?react';
 import { focusCompose } from 'mastodon/actions/compose';
 import { Icon }  from 'mastodon/components/icon';
+import { NotSignedInIndicator } from 'mastodon/components/not_signed_in_indicator';
 import Column from 'mastodon/features/ui/components/column';
 import { me } from 'mastodon/initial_state';
 import { useAppSelector } from 'mastodon/store';
@@ -42,42 +43,44 @@ const Onboarding = () => {
 
   return (
     <Column>
-      <Switch>
-        <Route path='/start' exact>
-          <div className='scrollable privacy-policy'>
-            <div className='column-title'>
-              <img src={illustration} alt='' className='onboarding__illustration' />
-              <h3><FormattedMessage id='onboarding.start.title' defaultMessage="You've made it!" /></h3>
-              <p><FormattedMessage id='onboarding.start.lead' defaultMessage="Your new Mastodon account is ready to go. Here's how you can make the most of it:" /></p>
+      {account ? (
+        <Switch>
+          <Route path='/start' exact>
+            <div className='scrollable privacy-policy'>
+              <div className='column-title'>
+                <img src={illustration} alt='' className='onboarding__illustration' />
+                <h3><FormattedMessage id='onboarding.start.title' defaultMessage="You've made it!" /></h3>
+                <p><FormattedMessage id='onboarding.start.lead' defaultMessage="Your new Mastodon account is ready to go. Here's how you can make the most of it:" /></p>
+              </div>
+
+              <div className='onboarding__steps'>
+                <Step to='/start/profile' completed={(!account.get('avatar').endsWith('missing.png')) || (account.get('display_name').length > 0 && account.get('note').length > 0)} icon='address-book-o' iconComponent={AccountCircleIcon} label={<FormattedMessage id='onboarding.steps.setup_profile.title' defaultMessage='Customize your profile' />} description={<FormattedMessage id='onboarding.steps.setup_profile.body' defaultMessage='Others are more likely to interact with you with a filled out profile.' />} />
+                <Step to='/start/follows' completed={(account.get('following_count') * 1) >= 1} icon='user-plus' iconComponent={PersonAddIcon} label={<FormattedMessage id='onboarding.steps.follow_people.title' defaultMessage='Find at least {count, plural, one {one person} other {# people}} to follow' values={{ count: 7 }} />} description={<FormattedMessage id='onboarding.steps.follow_people.body' defaultMessage="You curate your own home feed. Let's fill it with interesting people." />} />
+                <Step onClick={handleComposeClick} completed={(account.get('statuses_count') * 1) >= 1} icon='pencil-square-o' iconComponent={EditNoteIcon} label={<FormattedMessage id='onboarding.steps.publish_status.title' defaultMessage='Make your first post' />} description={<FormattedMessage id='onboarding.steps.publish_status.body' defaultMessage='Say hello to the world.' values={{ emoji: <img className='emojione' alt='🐘' src={`${assetHost}/emoji/1f418.svg`} /> }} />} />
+                <Step to='/start/share' icon='copy' iconComponent={ContentCopyIcon} label={<FormattedMessage id='onboarding.steps.share_profile.title' defaultMessage='Share your profile' />} description={<FormattedMessage id='onboarding.steps.share_profile.body' defaultMessage='Let your friends know how to find you on Mastodon!' />} />
+              </div>
+
+              <p className='onboarding__lead'><FormattedMessage id='onboarding.start.skip' defaultMessage="Don't need help getting started?" /></p>
+
+              <div className='onboarding__links'>
+                <Link to='/explore' className='onboarding__link'>
+                  <FormattedMessage id='onboarding.actions.go_to_explore' defaultMessage='Take me to trending' />
+                  <Icon icon={ArrowRightAltIcon} />
+                </Link>
+
+                <Link to='/home' className='onboarding__link'>
+                  <FormattedMessage id='onboarding.actions.go_to_home' defaultMessage='Take me to my home feed' />
+                  <Icon icon={ArrowRightAltIcon} />
+                </Link>
+              </div>
             </div>
+          </Route>
 
-            <div className='onboarding__steps'>
-              <Step to='/start/profile' completed={(!account.get('avatar').endsWith('missing.png')) || (account.get('display_name').length > 0 && account.get('note').length > 0)} icon='address-book-o' iconComponent={AccountCircleIcon} label={<FormattedMessage id='onboarding.steps.setup_profile.title' defaultMessage='Customize your profile' />} description={<FormattedMessage id='onboarding.steps.setup_profile.body' defaultMessage='Others are more likely to interact with you with a filled out profile.' />} />
-              <Step to='/start/follows' completed={(account.get('following_count') * 1) >= 1} icon='user-plus' iconComponent={PersonAddIcon} label={<FormattedMessage id='onboarding.steps.follow_people.title' defaultMessage='Find at least {count, plural, one {one person} other {# people}} to follow' values={{ count: 7 }} />} description={<FormattedMessage id='onboarding.steps.follow_people.body' defaultMessage="You curate your own home feed. Let's fill it with interesting people." />} />
-              <Step onClick={handleComposeClick} completed={(account.get('statuses_count') * 1) >= 1} icon='pencil-square-o' iconComponent={EditNoteIcon} label={<FormattedMessage id='onboarding.steps.publish_status.title' defaultMessage='Make your first post' />} description={<FormattedMessage id='onboarding.steps.publish_status.body' defaultMessage='Say hello to the world.' values={{ emoji: <img className='emojione' alt='🐘' src={`${assetHost}/emoji/1f418.svg`} /> }} />} />
-              <Step to='/start/share' icon='copy' iconComponent={ContentCopyIcon} label={<FormattedMessage id='onboarding.steps.share_profile.title' defaultMessage='Share your profile' />} description={<FormattedMessage id='onboarding.steps.share_profile.body' defaultMessage='Let your friends know how to find you on Mastodon!' />} />
-            </div>
-
-            <p className='onboarding__lead'><FormattedMessage id='onboarding.start.skip' defaultMessage="Don't need help getting started?" /></p>
-
-            <div className='onboarding__links'>
-              <Link to='/explore' className='onboarding__link'>
-                <FormattedMessage id='onboarding.actions.go_to_explore' defaultMessage='Take me to trending' />
-                <Icon icon={ArrowRightAltIcon} />
-              </Link>
-
-              <Link to='/home' className='onboarding__link'>
-                <FormattedMessage id='onboarding.actions.go_to_home' defaultMessage='Take me to my home feed' />
-                <Icon icon={ArrowRightAltIcon} />
-              </Link>
-            </div>
-          </div>
-        </Route>
-
-        <Route path='/start/profile' component={Profile} />
-        <Route path='/start/follows' component={Follows} />
-        <Route path='/start/share' component={Share} />
-      </Switch>
+          <Route path='/start/profile' component={Profile} />
+          <Route path='/start/follows' component={Follows} />
+          <Route path='/start/share' component={Share} />
+        </Switch>
+      ) : <NotSignedInIndicator />}
 
       <Helmet>
         <meta name='robots' content='noindex' />

From 1ca6ff8ca537a51dc2ed83ee3a262e7ec01b9f00 Mon Sep 17 00:00:00 2001
From: Tim Rogers <rogers.timothy.john@gmail.com>
Date: Mon, 22 Apr 2024 04:00:24 -0500
Subject: [PATCH 10/19] Fixed crash when supplying FFMPEG_BINARY environment
 variable (#30022)

---
 app/lib/video_metadata_extractor.rb | 2 +-
 config/initializers/ffmpeg.rb       | 5 +++--
 lib/paperclip/image_extractor.rb    | 2 +-
 lib/paperclip/transcoder.rb         | 2 +-
 4 files changed, 6 insertions(+), 5 deletions(-)

diff --git a/app/lib/video_metadata_extractor.rb b/app/lib/video_metadata_extractor.rb
index f27d34868..df5409375 100644
--- a/app/lib/video_metadata_extractor.rb
+++ b/app/lib/video_metadata_extractor.rb
@@ -22,7 +22,7 @@ class VideoMetadataExtractor
   private
 
   def ffmpeg_command_output
-    command = Terrapin::CommandLine.new('ffprobe', '-i :path -print_format :format -show_format -show_streams -show_error -loglevel :loglevel')
+    command = Terrapin::CommandLine.new(Rails.configuration.x.ffprobe_binary, '-i :path -print_format :format -show_format -show_streams -show_error -loglevel :loglevel')
     command.run(path: @path, format: 'json', loglevel: 'fatal')
   end
 
diff --git a/config/initializers/ffmpeg.rb b/config/initializers/ffmpeg.rb
index 30ea617fc..87f85eeec 100644
--- a/config/initializers/ffmpeg.rb
+++ b/config/initializers/ffmpeg.rb
@@ -1,5 +1,6 @@
 # frozen_string_literal: true
 
-if ENV['FFMPEG_BINARY'].present?
-  FFMPEG.ffmpeg_binary = ENV['FFMPEG_BINARY']
+Rails.application.configure do
+  config.x.ffmpeg_binary = ENV['FFMPEG_BINARY'] || 'ffmpeg'
+  config.x.ffprobe_binary = ENV['FFPROBE_BINARY'] || 'ffprobe'
 end
diff --git a/lib/paperclip/image_extractor.rb b/lib/paperclip/image_extractor.rb
index 17fe4326f..8a565d046 100644
--- a/lib/paperclip/image_extractor.rb
+++ b/lib/paperclip/image_extractor.rb
@@ -35,7 +35,7 @@ module Paperclip
       dst.binmode
 
       begin
-        command = Terrapin::CommandLine.new('ffmpeg', '-i :source -loglevel :loglevel -y :destination', logger: Paperclip.logger)
+        command = Terrapin::CommandLine.new(Rails.configuration.x.ffmpeg_binary, '-i :source -loglevel :loglevel -y :destination', logger: Paperclip.logger)
         command.run(source: @file.path, destination: dst.path, loglevel: 'fatal')
       rescue Terrapin::ExitStatusError
         dst.close(true)
diff --git a/lib/paperclip/transcoder.rb b/lib/paperclip/transcoder.rb
index d2d946d3a..3efffa355 100644
--- a/lib/paperclip/transcoder.rb
+++ b/lib/paperclip/transcoder.rb
@@ -61,7 +61,7 @@ module Paperclip
       command_arguments, interpolations = prepare_command(destination)
 
       begin
-        command = Terrapin::CommandLine.new('ffmpeg', command_arguments.join(' '), logger: Paperclip.logger)
+        command = Terrapin::CommandLine.new(Rails.configuration.x.ffmpeg_binary, command_arguments.join(' '), logger: Paperclip.logger)
         command.run(interpolations)
       rescue Terrapin::ExitStatusError => e
         raise Paperclip::Error, "Error while transcoding #{@basename}: #{e}"

From 56b095edebebfcb0931edebd27ecd36504e19c5c Mon Sep 17 00:00:00 2001
From: Matt Jankowski <matt@jankowski.online>
Date: Mon, 22 Apr 2024 05:01:24 -0400
Subject: [PATCH 11/19] Update Gemfile.lock ruby and bundler versions (#30011)

---
 Gemfile.lock | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/Gemfile.lock b/Gemfile.lock
index aadd52d64..990994a48 100644
--- a/Gemfile.lock
+++ b/Gemfile.lock
@@ -951,7 +951,7 @@ DEPENDENCIES
   xorcist (~> 1.1)
 
 RUBY VERSION
-   ruby 3.2.2p53
+   ruby 3.2.3p157
 
 BUNDLED WITH
-   2.5.7
+   2.5.9

From ffbbf74c50bc6a3d91e194ee7ac446dae2db5c76 Mon Sep 17 00:00:00 2001
From: Matt Jankowski <matt@jankowski.online>
Date: Mon, 22 Apr 2024 05:01:36 -0400
Subject: [PATCH 12/19] Limit `http` gem version to 5.1.x series (#30010)

---
 Gemfile      | 2 +-
 Gemfile.lock | 2 +-
 2 files changed, 2 insertions(+), 2 deletions(-)

diff --git a/Gemfile b/Gemfile
index 3f621ddc5..e26efcbd5 100644
--- a/Gemfile
+++ b/Gemfile
@@ -54,7 +54,7 @@ gem 'fast_blank', '~> 1.0'
 gem 'fastimage'
 gem 'hiredis', '~> 0.6'
 gem 'htmlentities', '~> 4.3'
-gem 'http', '~> 5.1'
+gem 'http', '~> 5.1.0'
 gem 'http_accept_language', '~> 2.1'
 gem 'httplog', '~> 1.6.2'
 gem 'i18n', '1.14.1' # TODO: Remove version when resolved: https://github.com/glebm/i18n-tasks/issues/552 / https://github.com/ruby-i18n/i18n/pull/688
diff --git a/Gemfile.lock b/Gemfile.lock
index 990994a48..2198efa79 100644
--- a/Gemfile.lock
+++ b/Gemfile.lock
@@ -860,7 +860,7 @@ DEPENDENCIES
   hcaptcha (~> 7.1)
   hiredis (~> 0.6)
   htmlentities (~> 4.3)
-  http (~> 5.1)
+  http (~> 5.1.0)
   http_accept_language (~> 2.1)
   httplog (~> 1.6.2)
   i18n (= 1.14.1)

From 33e829763dd7e4629ce62389c488aee12c35e94b Mon Sep 17 00:00:00 2001
From: Matt Jankowski <matt@jankowski.online>
Date: Mon, 22 Apr 2024 08:22:16 -0400
Subject: [PATCH 13/19] Use shared `form` partial for `admin/domain_blocks`
 views (#29609)

---
 app/views/admin/domain_blocks/_form.html.haml | 46 ++++++++++++++
 app/views/admin/domain_blocks/edit.html.haml  | 61 ++-----------------
 app/views/admin/domain_blocks/new.html.haml   | 59 ++----------------
 3 files changed, 56 insertions(+), 110 deletions(-)
 create mode 100644 app/views/admin/domain_blocks/_form.html.haml

diff --git a/app/views/admin/domain_blocks/_form.html.haml b/app/views/admin/domain_blocks/_form.html.haml
new file mode 100644
index 000000000..f1785a1fd
--- /dev/null
+++ b/app/views/admin/domain_blocks/_form.html.haml
@@ -0,0 +1,46 @@
+.fields-row
+  .fields-row__column.fields-row__column-6.fields-group
+    = form.input :domain,
+                 disabled: form.object.persisted?,
+                 hint: t('admin.domain_blocks.new.hint'),
+                 label: t('admin.domain_blocks.domain'),
+                 readonly: form.object.persisted?,
+                 required: true,
+                 wrapper: :with_label
+  .fields-row__column.fields-row__column-6.fields-group
+    = form.input :severity,
+                 collection: DomainBlock.severities.keys,
+                 hint: t('admin.domain_blocks.new.severity.desc_html'),
+                 include_blank: false,
+                 label_method: ->(type) { t("admin.domain_blocks.new.severity.#{type}") },
+                 wrapper: :with_label
+.fields-group
+  = form.input :reject_media,
+               as: :boolean,
+               hint: I18n.t('admin.domain_blocks.reject_media_hint'),
+               label: I18n.t('admin.domain_blocks.reject_media'),
+               wrapper: :with_label
+.fields-group
+  = form.input :reject_reports,
+               as: :boolean,
+               hint: I18n.t('admin.domain_blocks.reject_reports_hint'),
+               label: I18n.t('admin.domain_blocks.reject_reports'),
+               wrapper: :with_label
+.fields-group
+  = form.input :obfuscate,
+               as: :boolean,
+               hint: I18n.t('admin.domain_blocks.obfuscate_hint'),
+               label: I18n.t('admin.domain_blocks.obfuscate'),
+               wrapper: :with_label
+.field-group
+  = form.input :private_comment,
+               as: :string,
+               hint: t('admin.domain_blocks.private_comment_hint'),
+               label: I18n.t('admin.domain_blocks.private_comment'),
+               wrapper: :with_label
+.field-group
+  = form.input :public_comment,
+               as: :string,
+               hint: t('admin.domain_blocks.public_comment_hint'),
+               label: I18n.t('admin.domain_blocks.public_comment'),
+               wrapper: :with_label
diff --git a/app/views/admin/domain_blocks/edit.html.haml b/app/views/admin/domain_blocks/edit.html.haml
index 7c0a9823a..40c46b8b6 100644
--- a/app/views/admin/domain_blocks/edit.html.haml
+++ b/app/views/admin/domain_blocks/edit.html.haml
@@ -1,63 +1,12 @@
 - content_for :page_title do
   = t('admin.domain_blocks.edit')
 
-= simple_form_for @domain_block, url: admin_domain_block_path(@domain_block), method: :put do |f|
+= simple_form_for @domain_block, url: admin_domain_block_path(@domain_block), method: :put do |form|
   = render 'shared/error_messages', object: @domain_block
 
-  .fields-row
-    .fields-row__column.fields-row__column-6.fields-group
-      = f.input :domain,
-                disabled: true,
-                hint: t('admin.domain_blocks.new.hint'),
-                label: t('admin.domain_blocks.domain'),
-                readonly: true,
-                required: true,
-                wrapper: :with_label
-
-    .fields-row__column.fields-row__column-6.fields-group
-      = f.input :severity,
-                collection: DomainBlock.severities.keys,
-                hint: t('admin.domain_blocks.new.severity.desc_html'),
-                include_blank: false,
-                label_method: ->(type) { t("admin.domain_blocks.new.severity.#{type}") },
-                wrapper: :with_label
-
-  .fields-group
-    = f.input :reject_media,
-              as: :boolean,
-              hint: I18n.t('admin.domain_blocks.reject_media_hint'),
-              label: I18n.t('admin.domain_blocks.reject_media'),
-              wrapper: :with_label
-
-  .fields-group
-    = f.input :reject_reports,
-              as: :boolean,
-              hint: I18n.t('admin.domain_blocks.reject_reports_hint'),
-              label: I18n.t('admin.domain_blocks.reject_reports'),
-              wrapper: :with_label
-
-  .fields-group
-    = f.input :obfuscate,
-              as: :boolean,
-              hint: I18n.t('admin.domain_blocks.obfuscate_hint'),
-              label: I18n.t('admin.domain_blocks.obfuscate'),
-              wrapper: :with_label
-
-  .field-group
-    = f.input :private_comment,
-              as: :string,
-              hint: t('admin.domain_blocks.private_comment_hint'),
-              label: I18n.t('admin.domain_blocks.private_comment'),
-              wrapper: :with_label
-
-  .field-group
-    = f.input :public_comment,
-              as: :string,
-              hint: t('admin.domain_blocks.public_comment_hint'),
-              label: I18n.t('admin.domain_blocks.public_comment'),
-              wrapper: :with_label
+  = render form
 
   .actions
-    = f.button :button,
-               t('generic.save_changes'),
-               type: :submit
+    = form.button :button,
+                  t('generic.save_changes'),
+                  type: :submit
diff --git a/app/views/admin/domain_blocks/new.html.haml b/app/views/admin/domain_blocks/new.html.haml
index 6a9855529..78bcfcba8 100644
--- a/app/views/admin/domain_blocks/new.html.haml
+++ b/app/views/admin/domain_blocks/new.html.haml
@@ -1,61 +1,12 @@
 - content_for :page_title do
   = t('.title')
 
-= simple_form_for @domain_block, url: admin_domain_blocks_path do |f|
+= simple_form_for @domain_block, url: admin_domain_blocks_path do |form|
   = render 'shared/error_messages', object: @domain_block
 
-  .fields-row
-    .fields-row__column.fields-row__column-6.fields-group
-      = f.input :domain,
-                hint: t('.hint'),
-                label: t('admin.domain_blocks.domain'),
-                required: true,
-                wrapper: :with_label
-
-    .fields-row__column.fields-row__column-6.fields-group
-      = f.input :severity,
-                collection: DomainBlock.severities.keys,
-                hint: t('.severity.desc_html'),
-                include_blank: false,
-                label_method: ->(type) { t(".severity.#{type}") },
-                wrapper: :with_label
-
-  .fields-group
-    = f.input :reject_media,
-              as: :boolean,
-              hint: I18n.t('admin.domain_blocks.reject_media_hint'),
-              label: I18n.t('admin.domain_blocks.reject_media'),
-              wrapper: :with_label
-
-  .fields-group
-    = f.input :reject_reports,
-              as: :boolean,
-              hint: I18n.t('admin.domain_blocks.reject_reports_hint'),
-              label: I18n.t('admin.domain_blocks.reject_reports'),
-              wrapper: :with_label
-
-  .fields-group
-    = f.input :obfuscate,
-              as: :boolean,
-              hint: I18n.t('admin.domain_blocks.obfuscate_hint'),
-              label: I18n.t('admin.domain_blocks.obfuscate'),
-              wrapper: :with_label
-
-  .field-group
-    = f.input :private_comment,
-              as: :string,
-              hint: t('admin.domain_blocks.private_comment_hint'),
-              label: I18n.t('admin.domain_blocks.private_comment'),
-              wrapper: :with_label
-
-  .field-group
-    = f.input :public_comment,
-              as: :string,
-              hint: t('admin.domain_blocks.public_comment_hint'),
-              label: I18n.t('admin.domain_blocks.public_comment'),
-              wrapper: :with_label
+  = render form
 
   .actions
-    = f.button :button,
-               t('.create'),
-               type: :submit
+    = form.button :button,
+                  t('.create'),
+                  type: :submit

From 2ef098d01c69f667383f5d523a48ce7a09405957 Mon Sep 17 00:00:00 2001
From: Claire <claire.github-309c@sitedethib.com>
Date: Mon, 22 Apr 2024 16:02:24 +0200
Subject: [PATCH 14/19] Revert "Rely on dotenv autoload instead of explicit
 call (#30007)" (#30028)

---
 config/application.rb | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/config/application.rb b/config/application.rb
index b777018b5..a17a48b09 100644
--- a/config/application.rb
+++ b/config/application.rb
@@ -52,6 +52,8 @@ require_relative '../lib/active_record/batches'
 require_relative '../lib/simple_navigation/item_extensions'
 require_relative '../lib/http_extensions'
 
+Dotenv::Rails.load
+
 Bundler.require(:pam_authentication) if ENV['PAM_ENABLED'] == 'true'
 
 require_relative '../lib/mastodon/redis_config'

From 483fabf48a0a89aed405e6472ad07552bc8befd5 Mon Sep 17 00:00:00 2001
From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com>
Date: Mon, 22 Apr 2024 16:02:47 +0200
Subject: [PATCH 15/19] Update dependency http to '~> 5.2.0' (#30027)

Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
Co-authored-by: Claire <claire.github-309c@sitedethib.com>
---
 Gemfile                | 2 +-
 Gemfile.lock           | 9 +++++----
 config/application.rb  | 1 -
 lib/http_extensions.rb | 8 --------
 4 files changed, 6 insertions(+), 14 deletions(-)
 delete mode 100644 lib/http_extensions.rb

diff --git a/Gemfile b/Gemfile
index e26efcbd5..a10613b30 100644
--- a/Gemfile
+++ b/Gemfile
@@ -54,7 +54,7 @@ gem 'fast_blank', '~> 1.0'
 gem 'fastimage'
 gem 'hiredis', '~> 0.6'
 gem 'htmlentities', '~> 4.3'
-gem 'http', '~> 5.1.0'
+gem 'http', '~> 5.2.0'
 gem 'http_accept_language', '~> 2.1'
 gem 'httplog', '~> 1.6.2'
 gem 'i18n', '1.14.1' # TODO: Remove version when resolved: https://github.com/glebm/i18n-tasks/issues/552 / https://github.com/ruby-i18n/i18n/pull/688
diff --git a/Gemfile.lock b/Gemfile.lock
index 2198efa79..ab7375460 100644
--- a/Gemfile.lock
+++ b/Gemfile.lock
@@ -318,11 +318,12 @@ GEM
     hiredis (0.6.3)
     hkdf (0.3.0)
     htmlentities (4.3.4)
-    http (5.1.1)
+    http (5.2.0)
       addressable (~> 2.8)
+      base64 (~> 0.1)
       http-cookie (~> 1.0)
       http-form_data (~> 2.2)
-      llhttp-ffi (~> 0.4.0)
+      llhttp-ffi (~> 0.5.0)
     http-cookie (1.0.5)
       domain_name (~> 0.5)
     http-form_data (2.3.0)
@@ -403,7 +404,7 @@ GEM
       railties (>= 5.2)
       rexml
     link_header (0.0.8)
-    llhttp-ffi (0.4.0)
+    llhttp-ffi (0.5.0)
       ffi-compiler (~> 1.0)
       rake (~> 13.0)
     lograge (0.14.0)
@@ -860,7 +861,7 @@ DEPENDENCIES
   hcaptcha (~> 7.1)
   hiredis (~> 0.6)
   htmlentities (~> 4.3)
-  http (~> 5.1.0)
+  http (~> 5.2.0)
   http_accept_language (~> 2.1)
   httplog (~> 1.6.2)
   i18n (= 1.14.1)
diff --git a/config/application.rb b/config/application.rb
index a17a48b09..1b3878992 100644
--- a/config/application.rb
+++ b/config/application.rb
@@ -50,7 +50,6 @@ require_relative '../lib/rails/engine_extensions'
 require_relative '../lib/active_record/database_tasks_extensions'
 require_relative '../lib/active_record/batches'
 require_relative '../lib/simple_navigation/item_extensions'
-require_relative '../lib/http_extensions'
 
 Dotenv::Rails.load
 
diff --git a/lib/http_extensions.rb b/lib/http_extensions.rb
deleted file mode 100644
index 048f85f87..000000000
--- a/lib/http_extensions.rb
+++ /dev/null
@@ -1,8 +0,0 @@
-# frozen_string_literal: true
-
-# Monkey patching until https://github.com/httprb/http/pull/757 is merged
-unless HTTP::Request::METHODS.include?(:purge)
-  methods = HTTP::Request::METHODS.dup
-  HTTP::Request.send(:remove_const, :METHODS)
-  HTTP::Request.const_set(:METHODS, methods.push(:purge).freeze)
-end

From 1471c0d4e060efcc9f3cb7be72151dc95c81029c Mon Sep 17 00:00:00 2001
From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com>
Date: Tue, 23 Apr 2024 10:41:33 +0200
Subject: [PATCH 16/19] Update dependency rubocop to v1.63.3 (#30031)

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 ab7375460..7068f5dd5 100644
--- a/Gemfile.lock
+++ b/Gemfile.lock
@@ -644,7 +644,7 @@ GEM
       rspec-mocks (~> 3.0)
       sidekiq (>= 5, < 8)
     rspec-support (3.13.1)
-    rubocop (1.63.2)
+    rubocop (1.63.3)
       json (~> 2.3)
       language_server-protocol (>= 3.17.0)
       parallel (~> 1.10)

From 91c7406b599f1b09a68fe38c6e812b338478841a Mon Sep 17 00:00:00 2001
From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com>
Date: Tue, 23 Apr 2024 10:41:50 +0200
Subject: [PATCH 17/19] Update dependency postcss-preset-env to v9.5.9 (#30029)

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 e6e130e2d..b9f1c3d4d 100644
--- a/yarn.lock
+++ b/yarn.lock
@@ -13157,9 +13157,9 @@ __metadata:
   languageName: node
   linkType: hard
 
-"postcss-custom-properties@npm:^13.3.7":
-  version: 13.3.7
-  resolution: "postcss-custom-properties@npm:13.3.7"
+"postcss-custom-properties@npm:^13.3.8":
+  version: 13.3.8
+  resolution: "postcss-custom-properties@npm:13.3.8"
   dependencies:
     "@csstools/cascade-layer-name-parser": "npm:^1.0.9"
     "@csstools/css-parser-algorithms": "npm:^2.6.1"
@@ -13168,7 +13168,7 @@ __metadata:
     postcss-value-parser: "npm:^4.2.0"
   peerDependencies:
     postcss: ^8.4
-  checksum: 10c0/5d8767efae956f98d9a62a8f54d913c9ea95eaab1c906679ddeee64d87f0fb37d99c8ac1d16ec199794ed7c13a42d39ca2ea0a98df1056d400d4cbc9f31d6b94
+  checksum: 10c0/03dd1918f897005b23d09615ebb2c3faf4a01cac67462069c9cfa87c024b2a878f64948b0cf668971bc0ca00cfc349080879b3864deb3808a32d52ff2b473319
   languageName: node
   linkType: hard
 
@@ -13629,8 +13629,8 @@ __metadata:
   linkType: hard
 
 "postcss-preset-env@npm:^9.5.2":
-  version: 9.5.8
-  resolution: "postcss-preset-env@npm:9.5.8"
+  version: 9.5.9
+  resolution: "postcss-preset-env@npm:9.5.9"
   dependencies:
     "@csstools/postcss-cascade-layers": "npm:^4.0.4"
     "@csstools/postcss-color-function": "npm:^3.0.14"
@@ -13673,7 +13673,7 @@ __metadata:
     postcss-color-hex-alpha: "npm:^9.0.4"
     postcss-color-rebeccapurple: "npm:^9.0.3"
     postcss-custom-media: "npm:^10.0.4"
-    postcss-custom-properties: "npm:^13.3.7"
+    postcss-custom-properties: "npm:^13.3.8"
     postcss-custom-selectors: "npm:^7.1.8"
     postcss-dir-pseudo-class: "npm:^8.0.1"
     postcss-double-position-gradients: "npm:^5.0.6"
@@ -13694,7 +13694,7 @@ __metadata:
     postcss-selector-not: "npm:^7.0.2"
   peerDependencies:
     postcss: ^8.4
-  checksum: 10c0/5f77272eb7a938e5bedc3a0877f3fb0cdc6f20c8829730ccafbbd999db78ba4e6ac60f485aa7c292f70e011cf3edfadb7d2cc5459cbf9851abc25139eeb061b7
+  checksum: 10c0/dbe020e3fc08f0b71a3ee9d3c8a66a93bb6ba62281ac89fa59c82b8632ca58d6a911ddd9c65f15355c36aad63477633fc101cc0f3ce494dbc757193ba42eb61c
   languageName: node
   linkType: hard
 

From d754b15afb01dfbccb25ca1a4d01127a7c0ac919 Mon Sep 17 00:00:00 2001
From: "github-actions[bot]"
 <41898282+github-actions[bot]@users.noreply.github.com>
Date: Tue, 23 Apr 2024 11:07:05 +0200
Subject: [PATCH 18/19] New Crowdin Translations (automated) (#30034)

Co-authored-by: GitHub Actions <noreply@github.com>
---
 app/javascript/mastodon/locales/ia.json |  2 +-
 config/locales/activerecord.ia.yml      | 44 +++++++++++++++++++++++++
 config/locales/devise.ia.yml            | 11 +++++++
 config/locales/doorkeeper.ia.yml        | 18 ++++++++++
 config/locales/ia.yml                   | 12 +++++++
 5 files changed, 86 insertions(+), 1 deletion(-)

diff --git a/app/javascript/mastodon/locales/ia.json b/app/javascript/mastodon/locales/ia.json
index 808b57278..73634b99c 100644
--- a/app/javascript/mastodon/locales/ia.json
+++ b/app/javascript/mastodon/locales/ia.json
@@ -781,7 +781,7 @@
   "upload_modal.apply": "Applicar",
   "upload_modal.applying": "Applicante…",
   "upload_modal.choose_image": "Seliger un imagine",
-  "upload_modal.description_placeholder": "Le clown uzbek dogmatic justo foras quasi se asphyxiava",
+  "upload_modal.description_placeholder": "Cinque expertos del zoo jam bibeva whisky frigide",
   "upload_modal.detect_text": "Deteger texto de un imagine",
   "upload_modal.edit_media": "Modificar le medio",
   "upload_modal.hint": "Clicca o trahe le circulo sur le previsualisation pro eliger le puncto focal que essera sempre visibile sur tote le miniaturas.",
diff --git a/config/locales/activerecord.ia.yml b/config/locales/activerecord.ia.yml
index eec89ad52..b1dd90bc3 100644
--- a/config/locales/activerecord.ia.yml
+++ b/config/locales/activerecord.ia.yml
@@ -2,14 +2,58 @@
 ia:
   activerecord:
     attributes:
+      poll:
+        expires_at: Data limite
+        options: Optiones
       user:
+        agreement: Accordo de servicio
         email: Adresse de e-mail
+        locale: Region
         password: Contrasigno
       user/account:
         username: Nomine de usator
+      user/invite_request:
+        text: Motivo
     errors:
       models:
+        account:
+          attributes:
+            username:
+              invalid: debe continer solmente litteras, numeros e tractos de sublineamento
+              reserved: es reservate
+        admin/webhook:
+          attributes:
+            url:
+              invalid: non es un URL valide
+        doorkeeper/application:
+          attributes:
+            website:
+              invalid: non es un URL valide
+        import:
+          attributes:
+            data:
+              malformed: es mal formate
         status:
           attributes:
             reblog:
               taken: del message jam existe
+        user:
+          attributes:
+            email:
+              blocked: usa un fornitor de e-mail prohibite
+              unreachable: non pare exister
+            role_id:
+              elevated: non pote esser superior a tu rolo actual
+        user_role:
+          attributes:
+            permissions_as_keys:
+              dangerous: includer permissiones non secur pro le rolo de base
+              elevated: non pote includer permissiones que tu rolo actual non possede
+              own_role: non pote esser cambiate con tu rolo actual
+            position:
+              elevated: non pote esser superior a tu rolo actual
+              own_role: non pote esser cambiate con tu rolo actual
+        webhook:
+          attributes:
+            events:
+              invalid_permissions: non pote includer eventos pro le quales tu non ha le derectos
diff --git a/config/locales/devise.ia.yml b/config/locales/devise.ia.yml
index 62f106bcf..d180a46a6 100644
--- a/config/locales/devise.ia.yml
+++ b/config/locales/devise.ia.yml
@@ -1,10 +1,21 @@
 ---
 ia:
   devise:
+    confirmations:
+      confirmed: Tu conto de e-mail ha essite confirmate con successo.
+      send_instructions: Tu recipera un e-mail con instructiones pro confirmar tu adresse de e-mail in poc minutas. Per favor verifica tu dossier de spam si tu non lo recipe.
+      send_paranoid_instructions: Si tu adresse de e-mail existe in nostre base de datos, tu recipera un e-mail con instructiones pro confirmar tu adresse de e-mail in poc minutas. Per favor verifica tu dossier de spam si tu non lo recipe.
     failure:
       already_authenticated: Tu jam initiava le session.
       inactive: Tu conto ancora non es activate.
+      invalid: "%{authentication_keys} o contrasigno non valide."
+      last_attempt: Tu ha solmente un altere tentativa ante que tu conto es serrate.
       locked: Tu conto es blocate.
+      not_found_in_database: "%{authentication_keys} o contrasigno non valide."
+      omniauth_user_creation_failure: Error creante un conto pro iste identitate.
+      pending: Tu conto es ancora sub revision.
+      timeout: Tu session ha expirate. Per favor reaperi session pro continuar.
+      unauthenticated: Es necessari aperir session o crear un conto ante de continuar.
     mailer:
       confirmation_instructions:
         action: Verificar adresse de e-mail
diff --git a/config/locales/doorkeeper.ia.yml b/config/locales/doorkeeper.ia.yml
index 443342b40..b41531a1b 100644
--- a/config/locales/doorkeeper.ia.yml
+++ b/config/locales/doorkeeper.ia.yml
@@ -5,9 +5,16 @@ ia:
       doorkeeper/application:
         name: Nomine de application
         website: Sito web de application
+    errors:
+      models:
+        doorkeeper/application:
+          attributes:
+            redirect_uri:
+              invalid_uri: debe esser un URI valide.
   doorkeeper:
     applications:
       buttons:
+        authorize: Autorisar
         cancel: Cancellar
         edit: Modificar
       confirmations:
@@ -28,6 +35,8 @@ ia:
         actions: Actiones
         title: 'Application: %{name}'
     authorizations:
+      buttons:
+        authorize: Autorisar
       error:
         title: Ocurreva un error
     authorized_applications:
@@ -50,14 +59,17 @@ ia:
       title:
         accounts: Contos
         admin/accounts: Gestion de contos
+        admin/reports: Gestion de reportos
         all: Accesso plen a tu conto de Mastodon
         bookmarks: Marcapaginas
         conversations: Conversationes
         favourites: Favoritos
+        filters: Filtros
         lists: Listas
         mutes: Silentiates
         notifications: Notificationes
         push: Notificationes push
+        reports: Reportos
         search: Cercar
         statuses: Messages
     layouts:
@@ -67,16 +79,21 @@ ia:
           oauth2_provider: Fornitor OAuth2
     scopes:
       admin:read: leger tote le datos in le servitor
+      admin:write: modificar tote le datos in le servitor
       read: leger tote le datos de tu conto
       read:accounts: vider informationes de conto
+      read:bookmarks: vider tu marcapaginas
       read:favourites: vider tu favoritos
       read:filters: vider tu filtros
+      read:follows: vider tu sequites
       read:lists: vider tu listas
       read:notifications: vider tu notificationes
       read:reports: vider tu reportos
       read:statuses: vider tote le messages
+      write: modificar tote le datos de tu conto
       write:accounts: modificar tu profilo
       write:blocks: blocar contos e dominios
+      write:bookmarks: adder messages al marcapaginas
       write:conversations: silentiar e deler conversationes
       write:favourites: messages favorite
       write:filters: crear filtros
@@ -85,4 +102,5 @@ ia:
       write:media: incargar files de medios
       write:mutes: silentiar personas e conversationes
       write:notifications: rader tu notificationes
+      write:reports: signalar altere personas
       write:statuses: publicar messages
diff --git a/config/locales/ia.yml b/config/locales/ia.yml
index 3ba7a5148..a167b5d8c 100644
--- a/config/locales/ia.yml
+++ b/config/locales/ia.yml
@@ -22,6 +22,7 @@ ia:
   admin:
     account_moderation_notes:
       create: Lassar un nota
+      created_msg: Nota de moderation create con successo!
     accounts:
       add_email_domain_block: Blocar dominio de e-mail
       are_you_sure: Es tu secur?
@@ -74,13 +75,19 @@ ia:
       security_measures:
         only_password: Solmente contrasigno
         password_and_2fa: Contrasigno e 2FA
+      show:
+        created_reports: Reportos facite
+        targeted_reports: Signalate per alteres
       silenced: Limitate
       statuses: Messages
       subscribe: Subscriber
+      suspended: Suspendite
       title: Contos
       unblock_email: Disblocar adresse de e-mail
       unblocked_email_msg: Adresse de e-mail de %{username} disblocate con successo
       unconfirmed_email: E-mail non confirmate
+      undo_silenced: Disfacer le limite
+      undo_suspension: Disfacer le suspension
       username: Nomine de usator
       view_domain: Vider summario de dominio
     action_logs:
@@ -100,6 +107,9 @@ ia:
         enable_user: Activar le usator
         promote_user: Promover usator
         reset_password_user: Reinitialisar contrasigno
+        silence_account: Limitar conto
+        unblock_email_account: Disblocar adresse de e-mail
+        unsilence_account: Disfacer le limite de conto
         update_announcement: Actualisar annuncio
         update_custom_emoji: Actualisar emoji personalisate
         update_ip_block: Actualisar le regula IP
@@ -133,6 +143,7 @@ ia:
       enabled_msg: Emoji activate con successo
       new:
         title: Adder nove emoji personalisate
+      title: Emojis personalisate
       upload: Incargar
     dashboard:
       active_users: usatores active
@@ -150,6 +161,7 @@ ia:
     domain_blocks:
       confirm_suspension:
         cancel: Cancellar
+        stop_communication: Tu servitor stoppara le communication con iste servitores.
       domain: Dominio
       edit: Modificar un bloco de dominio
       export: Exportar

From 049b159beb672ca50b239a2275f78870ee7787da Mon Sep 17 00:00:00 2001
From: Emelia Smith <ThisIsMissEm@users.noreply.github.com>
Date: Tue, 23 Apr 2024 13:47:00 +0200
Subject: [PATCH 19/19] Add read:me OAuth 2.0 scope, allowing more limited
 access to user data (#29087)

---
 .../api/v1/accounts/credentials_controller.rb      |  2 +-
 config/initializers/doorkeeper.rb                  |  1 +
 config/locales/doorkeeper.en.yml                   |  1 +
 spec/requests/api/v1/accounts/credentials_spec.rb  | 14 ++++++++++++++
 4 files changed, 17 insertions(+), 1 deletion(-)

diff --git a/app/controllers/api/v1/accounts/credentials_controller.rb b/app/controllers/api/v1/accounts/credentials_controller.rb
index 8f31336b9..e8f712457 100644
--- a/app/controllers/api/v1/accounts/credentials_controller.rb
+++ b/app/controllers/api/v1/accounts/credentials_controller.rb
@@ -1,7 +1,7 @@
 # frozen_string_literal: true
 
 class Api::V1::Accounts::CredentialsController < Api::BaseController
-  before_action -> { doorkeeper_authorize! :read, :'read:accounts' }, except: [:update]
+  before_action -> { doorkeeper_authorize! :read, :'read:accounts', :'read:me' }, except: [:update]
   before_action -> { doorkeeper_authorize! :write, :'write:accounts' }, only: [:update]
   before_action :require_user!
 
diff --git a/config/initializers/doorkeeper.rb b/config/initializers/doorkeeper.rb
index 428e47391..1e8f9ad50 100644
--- a/config/initializers/doorkeeper.rb
+++ b/config/initializers/doorkeeper.rb
@@ -89,6 +89,7 @@ Doorkeeper.configure do
                   :'write:reports',
                   :'write:statuses',
                   :read,
+                  :'read:me',
                   :'read:accounts',
                   :'read:blocks',
                   :'read:bookmarks',
diff --git a/config/locales/doorkeeper.en.yml b/config/locales/doorkeeper.en.yml
index 0432a5e3f..98776f219 100644
--- a/config/locales/doorkeeper.en.yml
+++ b/config/locales/doorkeeper.en.yml
@@ -174,6 +174,7 @@ en:
       read:filters: see your filters
       read:follows: see your follows
       read:lists: see your lists
+      read:me: read only your account's basic information
       read:mutes: see your mutes
       read:notifications: see your notifications
       read:reports: see your reports
diff --git a/spec/requests/api/v1/accounts/credentials_spec.rb b/spec/requests/api/v1/accounts/credentials_spec.rb
index 737348c2d..8ae9c78a0 100644
--- a/spec/requests/api/v1/accounts/credentials_spec.rb
+++ b/spec/requests/api/v1/accounts/credentials_spec.rb
@@ -28,6 +28,20 @@ RSpec.describe 'credentials API' do
         locked: true,
       })
     end
+
+    describe 'allows the read:me scope' do
+      let(:scopes) { 'read:me' }
+
+      it 'returns the response successfully' do
+        subject
+
+        expect(response).to have_http_status(200)
+
+        expect(body_as_json).to include({
+          locked: true,
+        })
+      end
+    end
   end
 
   describe 'PATCH /api/v1/accounts/update_credentials' do