From 195b89d33619e0ce4271cef33fc29379254206f1 Mon Sep 17 00:00:00 2001 From: Michael Stanclift Date: Wed, 3 Jan 2024 13:02:53 -0600 Subject: [PATCH 01/61] Fix .opus file uploads being misidentified by Paperclip (#28580) --- app/models/concerns/attachmentable.rb | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/app/models/concerns/attachmentable.rb b/app/models/concerns/attachmentable.rb index 4cdbdeb473..3b7db1fcef 100644 --- a/app/models/concerns/attachmentable.rb +++ b/app/models/concerns/attachmentable.rb @@ -11,11 +11,12 @@ module Attachmentable # For some file extensions, there exist different content # type variants, and browsers often send the wrong one, # for example, sending an audio .ogg file as video/ogg, - # likewise, MimeMagic also misreports them as such. For + # likewise, kt-paperclip also misreports them as such. For # those files, it is necessary to use the output of the # `file` utility instead INCORRECT_CONTENT_TYPES = %w( audio/vorbis + audio/opus video/ogg video/webm ).freeze From dfdadb92e834cc099d16d7539a661105e1d12390 Mon Sep 17 00:00:00 2001 From: Claire Date: Thu, 4 Jan 2024 10:07:05 +0100 Subject: [PATCH 02/61] Add ability to require approval when users sign up using specific email domains (#28468) --- .../admin/email_domain_blocks_controller.rb | 4 ++-- .../admin/email_domain_blocks_controller.rb | 2 +- app/models/email_domain_block.rb | 23 +++++++++++-------- app/models/user.rb | 8 ++++++- .../admin/email_domain_block_serializer.rb | 2 +- .../_email_domain_block.html.haml | 4 ++++ .../admin/email_domain_blocks/new.html.haml | 3 +++ config/locales/en.yml | 1 + ...ow_with_approval_to_email_domain_blocks.rb | 7 ++++++ db/schema.rb | 3 ++- .../email_domain_blocks_controller_spec.rb | 3 ++- .../auth/registrations_controller_spec.rb | 19 +++++++++++++++ spec/services/app_sign_up_service_spec.rb | 21 +++++++++++++++++ 13 files changed, 84 insertions(+), 16 deletions(-) create mode 100644 db/migrate/20231222100226_add_allow_with_approval_to_email_domain_blocks.rb diff --git a/app/controllers/admin/email_domain_blocks_controller.rb b/app/controllers/admin/email_domain_blocks_controller.rb index 4a3228ec30..ff754bc0b4 100644 --- a/app/controllers/admin/email_domain_blocks_controller.rb +++ b/app/controllers/admin/email_domain_blocks_controller.rb @@ -40,7 +40,7 @@ module Admin (@email_domain_block.other_domains || []).uniq.each do |domain| next if EmailDomainBlock.where(domain: domain).exists? - other_email_domain_block = EmailDomainBlock.create!(domain: domain, parent: @email_domain_block) + other_email_domain_block = EmailDomainBlock.create!(domain: domain, allow_with_approval: @email_domain_block.allow_with_approval, parent: @email_domain_block) log_action :create, other_email_domain_block end end @@ -65,7 +65,7 @@ module Admin end def resource_params - params.require(:email_domain_block).permit(:domain, other_domains: []) + params.require(:email_domain_block).permit(:domain, :allow_with_approval, other_domains: []) end def form_email_domain_block_batch_params diff --git a/app/controllers/api/v1/admin/email_domain_blocks_controller.rb b/app/controllers/api/v1/admin/email_domain_blocks_controller.rb index 850eda6224..df54b9f0a4 100644 --- a/app/controllers/api/v1/admin/email_domain_blocks_controller.rb +++ b/app/controllers/api/v1/admin/email_domain_blocks_controller.rb @@ -55,7 +55,7 @@ class Api::V1::Admin::EmailDomainBlocksController < Api::BaseController end def resource_params - params.permit(:domain) + params.permit(:domain, :allow_with_approval) end def insert_pagination_headers diff --git a/app/models/email_domain_block.rb b/app/models/email_domain_block.rb index 60e90208db..f1b14c8b08 100644 --- a/app/models/email_domain_block.rb +++ b/app/models/email_domain_block.rb @@ -4,11 +4,12 @@ # # Table name: email_domain_blocks # -# id :bigint(8) not null, primary key -# domain :string default(""), not null -# created_at :datetime not null -# updated_at :datetime not null -# parent_id :bigint(8) +# id :bigint(8) not null, primary key +# domain :string default(""), not null +# created_at :datetime not null +# updated_at :datetime not null +# parent_id :bigint(8) +# allow_with_approval :boolean default(FALSE), not null # class EmailDomainBlock < ApplicationRecord @@ -42,8 +43,8 @@ class EmailDomainBlock < ApplicationRecord @attempt_ip = attempt_ip end - def match? - blocking? || invalid_uri? + def match?(...) + blocking?(...) || invalid_uri? end private @@ -52,8 +53,8 @@ class EmailDomainBlock < ApplicationRecord @uris.any?(&:nil?) end - def blocking? - blocks = EmailDomainBlock.where(domain: domains_with_variants).order(Arel.sql('char_length(domain) desc')) + def blocking?(allow_with_approval: false) + blocks = EmailDomainBlock.where(domain: domains_with_variants, allow_with_approval: allow_with_approval).order(Arel.sql('char_length(domain) desc')) blocks.each { |block| block.history.add(@attempt_ip) } if @attempt_ip.present? blocks.any? end @@ -86,4 +87,8 @@ class EmailDomainBlock < ApplicationRecord def self.block?(domain_or_domains, attempt_ip: nil) Matcher.new(domain_or_domains, attempt_ip: attempt_ip).match? end + + def self.requires_approval?(domain_or_domains, attempt_ip: nil) + Matcher.new(domain_or_domains, attempt_ip: attempt_ip).match?(allow_with_approval: true) + end end diff --git a/app/models/user.rb b/app/models/user.rb index a1574c02ad..be1e84b49c 100644 --- a/app/models/user.rb +++ b/app/models/user.rb @@ -418,7 +418,7 @@ class User < ApplicationRecord def set_approved self.approved = begin - if sign_up_from_ip_requires_approval? + if sign_up_from_ip_requires_approval? || sign_up_email_requires_approval? false else open_registrations? || valid_invitation? || external? @@ -430,6 +430,12 @@ class User < ApplicationRecord !sign_up_ip.nil? && IpBlock.where(severity: :sign_up_requires_approval).where('ip >>= ?', sign_up_ip.to_s).exists? end + def sign_up_email_requires_approval? + return false unless email.present? || unconfirmed_email.present? + + EmailDomainBlock.requires_approval?(email.presence || unconfirmed_email, attempt_ip: sign_up_ip) + end + def open_registrations? Setting.registrations_mode == 'open' end diff --git a/app/serializers/rest/admin/email_domain_block_serializer.rb b/app/serializers/rest/admin/email_domain_block_serializer.rb index a026ff680e..afe7722cb5 100644 --- a/app/serializers/rest/admin/email_domain_block_serializer.rb +++ b/app/serializers/rest/admin/email_domain_block_serializer.rb @@ -1,7 +1,7 @@ # frozen_string_literal: true class REST::Admin::EmailDomainBlockSerializer < ActiveModel::Serializer - attributes :id, :domain, :created_at, :history + attributes :id, :domain, :created_at, :history, :allow_with_approval def id object.id.to_s diff --git a/app/views/admin/email_domain_blocks/_email_domain_block.html.haml b/app/views/admin/email_domain_blocks/_email_domain_block.html.haml index 7cb973c4b4..f6a6e82667 100644 --- a/app/views/admin/email_domain_blocks/_email_domain_block.html.haml +++ b/app/views/admin/email_domain_blocks/_email_domain_block.html.haml @@ -12,3 +12,7 @@ · = t('admin.email_domain_blocks.attempts_over_week', count: email_domain_block.history.reduce(0) { |sum, day| sum + day.accounts }) + + - if email_domain_block.allow_with_approval? + · + = t('admin.email_domain_blocks.allow_registrations_with_approval') diff --git a/app/views/admin/email_domain_blocks/new.html.haml b/app/views/admin/email_domain_blocks/new.html.haml index fa1d950ad2..3d31487733 100644 --- a/app/views/admin/email_domain_blocks/new.html.haml +++ b/app/views/admin/email_domain_blocks/new.html.haml @@ -7,6 +7,9 @@ .fields-group = f.input :domain, wrapper: :with_block_label, label: t('admin.email_domain_blocks.domain'), input_html: { readonly: defined?(@resolved_records) } + .fields-group + = f.input :allow_with_approval, wrapper: :with_label, hint: false, label: I18n.t('admin.email_domain_blocks.allow_registrations_with_approval') + - if defined?(@resolved_records) %p.hint= t('admin.email_domain_blocks.resolved_dns_records_hint_html') diff --git a/config/locales/en.yml b/config/locales/en.yml index 15d682d173..50f814a81d 100644 --- a/config/locales/en.yml +++ b/config/locales/en.yml @@ -425,6 +425,7 @@ en: view: View domain block email_domain_blocks: add_new: Add new + allow_registrations_with_approval: Allow registrations with approval attempts_over_week: one: "%{count} attempt over the last week" other: "%{count} sign-up attempts over the last week" diff --git a/db/migrate/20231222100226_add_allow_with_approval_to_email_domain_blocks.rb b/db/migrate/20231222100226_add_allow_with_approval_to_email_domain_blocks.rb new file mode 100644 index 0000000000..01e8edfed4 --- /dev/null +++ b/db/migrate/20231222100226_add_allow_with_approval_to_email_domain_blocks.rb @@ -0,0 +1,7 @@ +# frozen_string_literal: true + +class AddAllowWithApprovalToEmailDomainBlocks < ActiveRecord::Migration[7.1] + def change + add_column :email_domain_blocks, :allow_with_approval, :boolean, default: false, null: false + end +end diff --git a/db/schema.rb b/db/schema.rb index 126ed8785a..4ea9744f40 100644 --- a/db/schema.rb +++ b/db/schema.rb @@ -10,7 +10,7 @@ # # It's strongly recommended that you check this file into your version control system. -ActiveRecord::Schema[7.1].define(version: 2023_12_12_073317) do +ActiveRecord::Schema[7.1].define(version: 2023_12_22_100226) do # These are extensions that must be enabled in order to support this database enable_extension "plpgsql" @@ -435,6 +435,7 @@ ActiveRecord::Schema[7.1].define(version: 2023_12_12_073317) do t.datetime "created_at", precision: nil, null: false t.datetime "updated_at", precision: nil, null: false t.bigint "parent_id" + t.boolean "allow_with_approval", default: false, null: false t.index ["domain"], name: "index_email_domain_blocks_on_domain", unique: true end diff --git a/spec/controllers/admin/email_domain_blocks_controller_spec.rb b/spec/controllers/admin/email_domain_blocks_controller_spec.rb index 4286600144..9379fe374a 100644 --- a/spec/controllers/admin/email_domain_blocks_controller_spec.rb +++ b/spec/controllers/admin/email_domain_blocks_controller_spec.rb @@ -12,13 +12,14 @@ RSpec.describe Admin::EmailDomainBlocksController do describe 'GET #index' do around do |example| default_per_page = EmailDomainBlock.default_per_page - EmailDomainBlock.paginates_per 1 + EmailDomainBlock.paginates_per 2 example.run EmailDomainBlock.paginates_per default_per_page end it 'returns http success' do 2.times { Fabricate(:email_domain_block) } + Fabricate(:email_domain_block, allow_with_approval: true) get :index, params: { page: 2 } expect(response).to have_http_status(200) end diff --git a/spec/controllers/auth/registrations_controller_spec.rb b/spec/controllers/auth/registrations_controller_spec.rb index 37172f8d24..bd1c616595 100644 --- a/spec/controllers/auth/registrations_controller_spec.rb +++ b/spec/controllers/auth/registrations_controller_spec.rb @@ -135,6 +135,25 @@ RSpec.describe Auth::RegistrationsController do end end + context 'when user has an email address requiring approval' do + subject do + Setting.registrations_mode = 'open' + Fabricate(:email_domain_block, allow_with_approval: true, domain: 'example.com') + request.headers['Accept-Language'] = accept_language + post :create, params: { user: { account_attributes: { username: 'test' }, email: 'test@example.com', password: '12345678', password_confirmation: '12345678', agreement: 'true' } } + end + + it 'creates unapproved user and redirects to setup' do + subject + expect(response).to redirect_to auth_setup_path + + user = User.find_by(email: 'test@example.com') + expect(user).to_not be_nil + expect(user.locale).to eq(accept_language) + expect(user.approved).to be(false) + end + end + context 'with Approval-based registrations without invite' do subject do Setting.registrations_mode = 'approved' diff --git a/spec/services/app_sign_up_service_spec.rb b/spec/services/app_sign_up_service_spec.rb index 0adb473f17..86e64dab21 100644 --- a/spec/services/app_sign_up_service_spec.rb +++ b/spec/services/app_sign_up_service_spec.rb @@ -27,6 +27,27 @@ RSpec.describe AppSignUpService, type: :service do end end + context 'when the email address requires approval' do + before do + Setting.registrations_mode = 'open' + Fabricate(:email_domain_block, allow_with_approval: true, domain: 'email.com') + end + + it 'creates an unapproved user', :aggregate_failures do + access_token = subject.call(app, remote_ip, params) + expect(access_token).to_not be_nil + expect(access_token.scopes.to_s).to eq 'read write' + + user = User.find_by(id: access_token.resource_owner_id) + expect(user).to_not be_nil + expect(user.confirmed?).to be false + expect(user.approved?).to be false + + expect(user.account).to_not be_nil + expect(user.invite_request).to be_nil + end + end + context 'when registrations are closed' do before do Setting.registrations_mode = 'none' From 38e5d1b53f042f17d18092471302445a902fae07 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Thu, 4 Jan 2024 10:15:56 +0100 Subject: [PATCH 03/61] Update dependency net-ldap to v0.19.0 (#28588) 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 295461bd35..8d01167537 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -474,7 +474,7 @@ GEM net-imap (0.4.4) date net-protocol - net-ldap (0.18.0) + net-ldap (0.19.0) net-pop (0.1.2) net-protocol net-protocol (0.2.2) From 0f3f98c01f33b0fd5968c8247f15dd0961afc9bc Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Thu, 4 Jan 2024 10:16:12 +0100 Subject: [PATCH 04/61] Update dependency react-redux-loading-bar to v5.0.8 (#28587) 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 3cd45a11d6..fd18bd9635 100644 --- a/yarn.lock +++ b/yarn.lock @@ -13673,8 +13673,8 @@ __metadata: linkType: hard "react-redux-loading-bar@npm:^5.0.4": - version: 5.0.7 - resolution: "react-redux-loading-bar@npm:5.0.7" + version: 5.0.8 + resolution: "react-redux-loading-bar@npm:5.0.8" dependencies: prop-types: "npm:^15.7.2" react-lifecycles-compat: "npm:^3.0.4" @@ -13683,7 +13683,7 @@ __metadata: react-dom: ^0.14.0 || ^15.0.0 || ^16.0.0 || ^17.0.0 || ^18.0.0 react-redux: ^3.0.0 || ^4.0.0 || ^5.0.0 || ^6.0.0 || ^7.0.0 || ^8.0.0 || ^9.0.0 redux: ^3.0.0 || ^4.0.0 || ^5.0.0 - checksum: 45333093e7d28df923a657ad89ffe4673d7bd135ef57c0143fb4d868f21b57aeb9044691f553f7d2afbcc9080a1f8cd3cec5b274c80cb57faf0e87a70f7a2cce + checksum: 797c1abf8bcc947feb127380e6d363db264c12bc94e578d635f86f1d806b0ec714dc3723e54c884937448b17f9042cfc995fe7a1deaf558efc01681e43e4669c languageName: node linkType: hard From 9c268c9413a5bb6f1bad5c531dfdd0391326873f Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Thu, 4 Jan 2024 09:16:29 +0000 Subject: [PATCH 05/61] Update dependency axios to v1.6.4 (#28586) 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 fd18bd9635..b2ffa3b9ea 100644 --- a/yarn.lock +++ b/yarn.lock @@ -4678,13 +4678,13 @@ __metadata: linkType: hard "axios@npm:^1.4.0": - version: 1.6.3 - resolution: "axios@npm:1.6.3" + version: 1.6.4 + resolution: "axios@npm:1.6.4" dependencies: - follow-redirects: "npm:^1.15.0" + follow-redirects: "npm:^1.15.4" form-data: "npm:^4.0.0" proxy-from-env: "npm:^1.1.0" - checksum: dcc6d982353db33e6893ef01cdf81d0a0548dbd8fba0cb046dc4aee1a6a16226721faa4c2a13b2673d47130509629cdb93bb991b3a2bd4ef17a5ac27a8bba0da + checksum: daac697fa1ea9865cb48e9edb7eacd99e8a9214997f2d8e886cb61c380a613e5c270078bfc153ac96206680106c223f005f0e4bf2f3b2ddd88e559ecf970521f languageName: node linkType: hard @@ -8163,13 +8163,13 @@ __metadata: languageName: node linkType: hard -"follow-redirects@npm:^1.0.0, follow-redirects@npm:^1.15.0": - version: 1.15.3 - resolution: "follow-redirects@npm:1.15.3" +"follow-redirects@npm:^1.0.0, follow-redirects@npm:^1.15.4": + version: 1.15.4 + resolution: "follow-redirects@npm:1.15.4" peerDependenciesMeta: debug: optional: true - checksum: 915a2cf22e667bdf47b1a43cc6b7dce14d95039e9bbf9a24d0e739abfbdfa00077dd43c86d4a7a19efefcc7a99af144920a175eedc3888d268af5df67c272ee5 + checksum: 5f37ed9170c9eb19448c5418fdb0f2b73f644b5364834e70791a76ecc7db215246f9773bbef4852cfae4067764ffc852e047f744b661b0211532155b73556a6a languageName: node linkType: hard From 9826b7780ab4f0a6cbb633bf159fcea4db1b7ed9 Mon Sep 17 00:00:00 2001 From: Emelia Smith Date: Thu, 4 Jan 2024 10:18:03 +0100 Subject: [PATCH 06/61] Streaming: use standard cors package instead of custom implementation (#28523) --- streaming/index.js | 16 ++-------------- streaming/package.json | 2 ++ yarn.lock | 25 +++++++++++++++++++++++-- 3 files changed, 27 insertions(+), 16 deletions(-) diff --git a/streaming/index.js b/streaming/index.js index fb3e3fb2be..42d0afc7c5 100644 --- a/streaming/index.js +++ b/streaming/index.js @@ -5,6 +5,7 @@ const http = require('http'); const path = require('path'); const url = require('url'); +const cors = require('cors'); const dotenv = require('dotenv'); const express = require('express'); const Redis = require('ioredis'); @@ -187,6 +188,7 @@ const startServer = async () => { const pgPool = new pg.Pool(pgConfigFromEnv(process.env)); const server = http.createServer(app); + app.use(cors()); /** * @type {Object.): void>>} @@ -327,19 +329,6 @@ const startServer = async () => { } }; - /** - * @param {any} req - * @param {any} res - * @param {function(Error=): void} next - */ - const allowCrossDomain = (req, res, next) => { - res.header('Access-Control-Allow-Origin', '*'); - res.header('Access-Control-Allow-Headers', 'Authorization, Accept, Cache-Control'); - res.header('Access-Control-Allow-Methods', 'GET, OPTIONS'); - - next(); - }; - /** * @param {any} req * @param {any} res @@ -987,7 +976,6 @@ const startServer = async () => { api.use(setRequestId); api.use(setRemoteAddress); - api.use(allowCrossDomain); api.use(authenticationMiddleware); api.use(errorMiddleware); diff --git a/streaming/package.json b/streaming/package.json index 0cfc5b3276..2d70acb829 100644 --- a/streaming/package.json +++ b/streaming/package.json @@ -16,6 +16,7 @@ "check:types": "tsc --noEmit" }, "dependencies": { + "cors": "^2.8.5", "dotenv": "^16.0.3", "express": "^4.18.2", "ioredis": "^5.3.2", @@ -28,6 +29,7 @@ "ws": "^8.12.1" }, "devDependencies": { + "@types/cors": "^2.8.16", "@types/express": "^4.17.17", "@types/npmlog": "^7.0.0", "@types/pg": "^8.6.6", diff --git a/yarn.lock b/yarn.lock index b2ffa3b9ea..7b7f0e3153 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2468,12 +2468,14 @@ __metadata: version: 0.0.0-use.local resolution: "@mastodon/streaming@workspace:streaming" dependencies: + "@types/cors": "npm:^2.8.16" "@types/express": "npm:^4.17.17" "@types/npmlog": "npm:^7.0.0" "@types/pg": "npm:^8.6.6" "@types/uuid": "npm:^9.0.0" "@types/ws": "npm:^8.5.9" bufferutil: "npm:^4.0.7" + cors: "npm:^2.8.5" dotenv: "npm:^16.0.3" eslint-define-config: "npm:^2.0.0" express: "npm:^4.18.2" @@ -3027,6 +3029,15 @@ __metadata: languageName: node linkType: hard +"@types/cors@npm:^2.8.16": + version: 2.8.16 + resolution: "@types/cors@npm:2.8.16" + dependencies: + "@types/node": "npm:*" + checksum: ebcfb325b102739249bbaa4845cf1cf4830baf5490a32bcd1a85cd9b8c4d4b9eaaaea94423e454b5b7c9da77e46a64db80d2381d3bc3f940d15d13814e87b70a + languageName: node + linkType: hard + "@types/emoji-mart@npm:^3.0.9": version: 3.0.14 resolution: "@types/emoji-mart@npm:3.0.14" @@ -5973,6 +5984,16 @@ __metadata: languageName: node linkType: hard +"cors@npm:^2.8.5": + version: 2.8.5 + resolution: "cors@npm:2.8.5" + dependencies: + object-assign: "npm:^4" + vary: "npm:^1" + checksum: 373702b7999409922da80de4a61938aabba6929aea5b6fd9096fefb9e8342f626c0ebd7507b0e8b0b311380744cc985f27edebc0a26e0ddb784b54e1085de761 + languageName: node + linkType: hard + "cosmiconfig@npm:^7.0.0": version: 7.1.0 resolution: "cosmiconfig@npm:7.1.0" @@ -11953,7 +11974,7 @@ __metadata: languageName: node linkType: hard -"object-assign@npm:^4.0.1, object-assign@npm:^4.1.1": +"object-assign@npm:^4, object-assign@npm:^4.0.1, object-assign@npm:^4.1.1": version: 4.1.1 resolution: "object-assign@npm:4.1.1" checksum: 1f4df9945120325d041ccf7b86f31e8bcc14e73d29171e37a7903050e96b81323784ec59f93f102ec635bcf6fa8034ba3ea0a8c7e69fa202b87ae3b6cec5a414 @@ -16728,7 +16749,7 @@ __metadata: languageName: node linkType: hard -"vary@npm:~1.1.2": +"vary@npm:^1, vary@npm:~1.1.2": version: 1.1.2 resolution: "vary@npm:1.1.2" checksum: f15d588d79f3675135ba783c91a4083dcd290a2a5be9fcb6514220a1634e23df116847b1cc51f66bfb0644cf9353b2abb7815ae499bab06e46dd33c1a6bf1f4f From 06374d07c3ce5eab2560ae85b56939cef575aee8 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Thu, 4 Jan 2024 10:19:38 +0100 Subject: [PATCH 07/61] Update dependency cssnano to v6.0.3 (#28581) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- yarn.lock | 196 +++++++++++++++++++++++++++--------------------------- 1 file changed, 98 insertions(+), 98 deletions(-) diff --git a/yarn.lock b/yarn.lock index 7b7f0e3153..99c3eedb26 100644 --- a/yarn.lock +++ b/yarn.lock @@ -5208,7 +5208,7 @@ __metadata: languageName: node linkType: hard -"browserslist@npm:^4.0.0, browserslist@npm:^4.21.10, browserslist@npm:^4.21.4, browserslist@npm:^4.22.2": +"browserslist@npm:^4.0.0, browserslist@npm:^4.21.10, browserslist@npm:^4.22.2": version: 4.22.2 resolution: "browserslist@npm:4.22.2" dependencies: @@ -6140,7 +6140,7 @@ __metadata: languageName: node linkType: hard -"css-declaration-sorter@npm:^7.0.0": +"css-declaration-sorter@npm:^7.1.1": version: 7.1.1 resolution: "css-declaration-sorter@npm:7.1.1" peerDependencies: @@ -6228,7 +6228,7 @@ __metadata: languageName: node linkType: hard -"css-tree@npm:^2.2.1, css-tree@npm:^2.3.1": +"css-tree@npm:^2.3.1": version: 2.3.1 resolution: "css-tree@npm:2.3.1" dependencies: @@ -6278,42 +6278,42 @@ __metadata: languageName: node linkType: hard -"cssnano-preset-default@npm:^6.0.2": - version: 6.0.2 - resolution: "cssnano-preset-default@npm:6.0.2" +"cssnano-preset-default@npm:^6.0.3": + version: 6.0.3 + resolution: "cssnano-preset-default@npm:6.0.3" dependencies: - css-declaration-sorter: "npm:^7.0.0" + css-declaration-sorter: "npm:^7.1.1" cssnano-utils: "npm:^4.0.1" postcss-calc: "npm:^9.0.1" - postcss-colormin: "npm:^6.0.1" - postcss-convert-values: "npm:^6.0.1" + postcss-colormin: "npm:^6.0.2" + postcss-convert-values: "npm:^6.0.2" postcss-discard-comments: "npm:^6.0.1" postcss-discard-duplicates: "npm:^6.0.1" postcss-discard-empty: "npm:^6.0.1" postcss-discard-overridden: "npm:^6.0.1" - postcss-merge-longhand: "npm:^6.0.1" - postcss-merge-rules: "npm:^6.0.2" + postcss-merge-longhand: "npm:^6.0.2" + postcss-merge-rules: "npm:^6.0.3" postcss-minify-font-values: "npm:^6.0.1" postcss-minify-gradients: "npm:^6.0.1" - postcss-minify-params: "npm:^6.0.1" - postcss-minify-selectors: "npm:^6.0.1" + postcss-minify-params: "npm:^6.0.2" + postcss-minify-selectors: "npm:^6.0.2" postcss-normalize-charset: "npm:^6.0.1" postcss-normalize-display-values: "npm:^6.0.1" postcss-normalize-positions: "npm:^6.0.1" postcss-normalize-repeat-style: "npm:^6.0.1" postcss-normalize-string: "npm:^6.0.1" postcss-normalize-timing-functions: "npm:^6.0.1" - postcss-normalize-unicode: "npm:^6.0.1" + postcss-normalize-unicode: "npm:^6.0.2" postcss-normalize-url: "npm:^6.0.1" postcss-normalize-whitespace: "npm:^6.0.1" postcss-ordered-values: "npm:^6.0.1" - postcss-reduce-initial: "npm:^6.0.1" + postcss-reduce-initial: "npm:^6.0.2" postcss-reduce-transforms: "npm:^6.0.1" - postcss-svgo: "npm:^6.0.1" - postcss-unique-selectors: "npm:^6.0.1" + postcss-svgo: "npm:^6.0.2" + postcss-unique-selectors: "npm:^6.0.2" peerDependencies: postcss: ^8.4.31 - checksum: c6f97674704c3a2a2473440549eac38ac722feebabbd39f2d4d1b8fae7f137f8fd0dfb88929e1ff737d54008de583c39e96f9dc450f2d71f8be6fc3bac2840a3 + checksum: d100a1f8ab71adbb6df85e00f4a9e5d04ac06fc50343157eef853aded3f75dd0489dd845a5b2fb43ca701bd88c39c5aa88673f842bc1f94f4318c7b38ced1963 languageName: node linkType: hard @@ -6327,23 +6327,14 @@ __metadata: linkType: hard "cssnano@npm:^6.0.1": - version: 6.0.2 - resolution: "cssnano@npm:6.0.2" + version: 6.0.3 + resolution: "cssnano@npm:6.0.3" dependencies: - cssnano-preset-default: "npm:^6.0.2" + cssnano-preset-default: "npm:^6.0.3" lilconfig: "npm:^3.0.0" peerDependencies: postcss: ^8.4.31 - checksum: 5f4146a6c8937d24b0d1d33e3acd85db7913c7558cc80b23169f86c9a552d091a26e0af6adcc535f8355561872f797a917b9353e38fe935bbaf08ec2b66f5ff8 - languageName: node - linkType: hard - -"csso@npm:5.0.5": - version: 5.0.5 - resolution: "csso@npm:5.0.5" - dependencies: - css-tree: "npm:~2.2.0" - checksum: ab4beb1e97dd7e207c10e9925405b45f15a6cd1b4880a8686ad573aa6d476aed28b4121a666cffd26c37a26179f7b54741f7c257543003bfb244d06a62ad569b + checksum: d1669eb987fd96159bae262ef2f76c1a64fffefe8fa593918a6bda377977798b60fb4a6a871a9b9a9deb11258130ee254fdb8c3144769b3060ad9f2a95a4ed0a languageName: node linkType: hard @@ -6356,6 +6347,15 @@ __metadata: languageName: node linkType: hard +"csso@npm:^5.0.5": + version: 5.0.5 + resolution: "csso@npm:5.0.5" + dependencies: + css-tree: "npm:~2.2.0" + checksum: ab4beb1e97dd7e207c10e9925405b45f15a6cd1b4880a8686ad573aa6d476aed28b4121a666cffd26c37a26179f7b54741f7c257543003bfb244d06a62ad569b + languageName: node + linkType: hard + "cssom@npm:^0.5.0": version: 0.5.0 resolution: "cssom@npm:0.5.0" @@ -12743,29 +12743,29 @@ __metadata: languageName: node linkType: hard -"postcss-colormin@npm:^6.0.1": - version: 6.0.1 - resolution: "postcss-colormin@npm:6.0.1" +"postcss-colormin@npm:^6.0.2": + version: 6.0.2 + resolution: "postcss-colormin@npm:6.0.2" dependencies: - browserslist: "npm:^4.21.4" + browserslist: "npm:^4.22.2" caniuse-api: "npm:^3.0.0" colord: "npm:^2.9.1" postcss-value-parser: "npm:^4.2.0" peerDependencies: postcss: ^8.4.31 - checksum: b0056812b3436b05b6b84284a1ebe68a72299f23e7eeb0b7b40a775978d06a1cbe235f3665e3f694f5de76fe7d9b93db607536d07697b31a59fd4e8705e5b64d + checksum: 229681f9b89ba0909b4c69563837b0c32cc3d1c17ed1b00c33d4abfb0a0ef455124968e4885b5f92c64482e92074cd1958018ec111ed5d118f1e24baeda19c14 languageName: node linkType: hard -"postcss-convert-values@npm:^6.0.1": - version: 6.0.1 - resolution: "postcss-convert-values@npm:6.0.1" +"postcss-convert-values@npm:^6.0.2": + version: 6.0.2 + resolution: "postcss-convert-values@npm:6.0.2" dependencies: - browserslist: "npm:^4.21.4" + browserslist: "npm:^4.22.2" postcss-value-parser: "npm:^4.2.0" peerDependencies: postcss: ^8.4.31 - checksum: 53b951d7475206969c63b8427a2dea0ccba0a7cb08122e5f05aee8d12b09c870c070b101c9f8eceda76ff4d0fd9e5fa9385e83f143d658bb729dbb6a3583b872 + checksum: 882d0b7839ef07ac8ffbf9cb48db0f610939a3496bd0321c7f23096ead676f13e09ab3d9c20ff3dbe2c887e855826051ca7dffeaffce5068cfdc9aaa573a3842 languageName: node linkType: hard @@ -12828,29 +12828,29 @@ __metadata: languageName: node linkType: hard -"postcss-merge-longhand@npm:^6.0.1": - version: 6.0.1 - resolution: "postcss-merge-longhand@npm:6.0.1" +"postcss-merge-longhand@npm:^6.0.2": + version: 6.0.2 + resolution: "postcss-merge-longhand@npm:6.0.2" dependencies: postcss-value-parser: "npm:^4.2.0" - stylehacks: "npm:^6.0.1" + stylehacks: "npm:^6.0.2" peerDependencies: postcss: ^8.4.31 - checksum: 2c0eb81b6c6d3d2af3b129c46d10317b7923f218db1cadcb4723091fb951fe4624638002b65f235151129d4ce9b4775a6ed0d5fa13419c0df580f72e15fa4ad3 + checksum: 2b3fae51bffc5962258d638bc7f415237593b515f369233e023f0eae5b13116297463c04b8c47a7b7af51cba5faaa7f517b653f6123e51935d670d4d4de5a26d languageName: node linkType: hard -"postcss-merge-rules@npm:^6.0.2": - version: 6.0.2 - resolution: "postcss-merge-rules@npm:6.0.2" +"postcss-merge-rules@npm:^6.0.3": + version: 6.0.3 + resolution: "postcss-merge-rules@npm:6.0.3" dependencies: - browserslist: "npm:^4.21.4" + browserslist: "npm:^4.22.2" caniuse-api: "npm:^3.0.0" cssnano-utils: "npm:^4.0.1" - postcss-selector-parser: "npm:^6.0.5" + postcss-selector-parser: "npm:^6.0.15" peerDependencies: postcss: ^8.4.31 - checksum: 138a9921423420116b20e5761a1139392f0bcfcf34264fe11e254917d9c3170e3c0478a1b409e227d22bb0d9820b0168a871a240215d114e9c1e218ee6c132e6 + checksum: c8355db11aa60bedcb1e6535fcd70f6ecec2dadd5c2975d3accf0eedbc92af782ac1f5e91a53866816ce332e4cbf1b94749a9425067935be066bc0c974e30fee languageName: node linkType: hard @@ -12878,27 +12878,27 @@ __metadata: languageName: node linkType: hard -"postcss-minify-params@npm:^6.0.1": - version: 6.0.1 - resolution: "postcss-minify-params@npm:6.0.1" +"postcss-minify-params@npm:^6.0.2": + version: 6.0.2 + resolution: "postcss-minify-params@npm:6.0.2" dependencies: - browserslist: "npm:^4.21.4" + browserslist: "npm:^4.22.2" cssnano-utils: "npm:^4.0.1" postcss-value-parser: "npm:^4.2.0" peerDependencies: postcss: ^8.4.31 - checksum: 0b34817f032ec9793fad4d33f3ba5551531073a36c9120d77194a3edeee860132951ed6954913494e5a6752ae8da1bc5cdb2a44fa5f428621afae8edddb0ca80 + checksum: 6638460d2be4a2eca8adee8409b70d6c6a19aff8cf93fda1b45c9da627b258b6baaa6acb48f51d26cd287704a235f9c9ae2e4744335b1fd47e163177c33896df languageName: node linkType: hard -"postcss-minify-selectors@npm:^6.0.1": - version: 6.0.1 - resolution: "postcss-minify-selectors@npm:6.0.1" +"postcss-minify-selectors@npm:^6.0.2": + version: 6.0.2 + resolution: "postcss-minify-selectors@npm:6.0.2" dependencies: - postcss-selector-parser: "npm:^6.0.5" + postcss-selector-parser: "npm:^6.0.15" peerDependencies: postcss: ^8.4.31 - checksum: ffc7ebb286beda2b2aa0ed13abafc89b5ffe232a48d57d3f2b9f69e167e354482a6f5279e9118bed753bf6e82d3cfb21228a6b07acd93d0dc9e01bbf0e7ebc75 + checksum: 5437b586c1237fc442e7e6078d4f23c987efc456366368b07a0da67332b04bd55821cedf0441e73e1209689f63139e272d930508e2963ba6e27c46561a661128 languageName: node linkType: hard @@ -13010,15 +13010,15 @@ __metadata: languageName: node linkType: hard -"postcss-normalize-unicode@npm:^6.0.1": - version: 6.0.1 - resolution: "postcss-normalize-unicode@npm:6.0.1" +"postcss-normalize-unicode@npm:^6.0.2": + version: 6.0.2 + resolution: "postcss-normalize-unicode@npm:6.0.2" dependencies: - browserslist: "npm:^4.21.4" + browserslist: "npm:^4.22.2" postcss-value-parser: "npm:^4.2.0" peerDependencies: postcss: ^8.4.31 - checksum: 8057748dade94dc2dd63a3b75a85e394c2e9a7076053886ff08aa9b7729d383f204eda52d882e5361ae1ec493036e90b2e18dcc5f8c9b3a8f1cbfada12bcc05b + checksum: ea696194f65ad31de2a9c022f1946a07c298f04070706d88a20061845e1e052e645c74b5bc785595814db87d14e435f85e968a44855dedc207d8c0b5d43b1aee languageName: node linkType: hard @@ -13056,15 +13056,15 @@ __metadata: languageName: node linkType: hard -"postcss-reduce-initial@npm:^6.0.1": - version: 6.0.1 - resolution: "postcss-reduce-initial@npm:6.0.1" +"postcss-reduce-initial@npm:^6.0.2": + version: 6.0.2 + resolution: "postcss-reduce-initial@npm:6.0.2" dependencies: - browserslist: "npm:^4.21.4" + browserslist: "npm:^4.22.2" caniuse-api: "npm:^3.0.0" peerDependencies: postcss: ^8.4.31 - checksum: 3f8f6c26ceeb79ddc285b0e01183fe30e911dd26b3abcdca56568e2bef3747f2b7f22ee3f9117e9752e1e93c10bcd88bd6a2842ca525b54336726292ebd3c3ad + checksum: d35ad6f9725cdceb390a97a461e8594df7fbed4c55497c90d07c42f8343bf80139e720eaebc580bf480bf10e92959490aa308af66d8802ba71c327bdf08c93a1 languageName: node linkType: hard @@ -13104,36 +13104,36 @@ __metadata: languageName: node linkType: hard -"postcss-selector-parser@npm:^6.0.11, postcss-selector-parser@npm:^6.0.13, postcss-selector-parser@npm:^6.0.2, postcss-selector-parser@npm:^6.0.4, postcss-selector-parser@npm:^6.0.5": - version: 6.0.13 - resolution: "postcss-selector-parser@npm:6.0.13" +"postcss-selector-parser@npm:^6.0.11, postcss-selector-parser@npm:^6.0.13, postcss-selector-parser@npm:^6.0.15, postcss-selector-parser@npm:^6.0.2, postcss-selector-parser@npm:^6.0.4": + version: 6.0.15 + resolution: "postcss-selector-parser@npm:6.0.15" dependencies: cssesc: "npm:^3.0.0" util-deprecate: "npm:^1.0.2" - checksum: 51f099b27f7c7198ea1826470ef0adfa58b3bd3f59b390fda123baa0134880a5fa9720137b6009c4c1373357b144f700b0edac73335d0067422063129371444e + checksum: 48b425d6cef497bcf6b7d136f6fd95cfca43026955e07ec9290d3c15457de3a862dbf251dd36f42c07a0d5b5ab6f31e41acefeff02528995a989b955505e440b languageName: node linkType: hard -"postcss-svgo@npm:^6.0.1": - version: 6.0.1 - resolution: "postcss-svgo@npm:6.0.1" +"postcss-svgo@npm:^6.0.2": + version: 6.0.2 + resolution: "postcss-svgo@npm:6.0.2" dependencies: postcss-value-parser: "npm:^4.2.0" - svgo: "npm:^3.0.5" + svgo: "npm:^3.2.0" peerDependencies: postcss: ^8.4.31 - checksum: 021da9b0d0696fce970f407891a0d6c05e51d1908af435026e0cd5936a75cd8502a7d504cd0e6a33b6f3369fee41f01b848e5bd919aecc3e804ce6308e91a6cc + checksum: db607404d09af256c7957a0ace822d651a00a52a1796da603f93ba3f0a095ac7595e1f624b9dc53f362ab10e382845d7873f485980f9c92fcb86256833f5e835 languageName: node linkType: hard -"postcss-unique-selectors@npm:^6.0.1": - version: 6.0.1 - resolution: "postcss-unique-selectors@npm:6.0.1" +"postcss-unique-selectors@npm:^6.0.2": + version: 6.0.2 + resolution: "postcss-unique-selectors@npm:6.0.2" dependencies: - postcss-selector-parser: "npm:^6.0.5" + postcss-selector-parser: "npm:^6.0.15" peerDependencies: postcss: ^8.4.31 - checksum: 637e35775d0ee8fbcf4a81b28d3832c5076de7c0232eb7769d4fbbf783f26793e2ec95e18461ae3b9f5f5cd63c3de9db102464487ba2488d4947aad24dc8841f + checksum: a0fe112d1094f90e1bfcfd2174a74b2fd0630a24449e9942923d02956c7d64ea4add5adede53d9efb3f6d40cd388ac150d032a115f6a46b73d5f3d3d26fa1bb7 languageName: node linkType: hard @@ -15606,15 +15606,15 @@ __metadata: languageName: node linkType: hard -"stylehacks@npm:^6.0.1": - version: 6.0.1 - resolution: "stylehacks@npm:6.0.1" +"stylehacks@npm:^6.0.2": + version: 6.0.2 + resolution: "stylehacks@npm:6.0.2" dependencies: - browserslist: "npm:^4.21.4" - postcss-selector-parser: "npm:^6.0.4" + browserslist: "npm:^4.22.2" + postcss-selector-parser: "npm:^6.0.15" peerDependencies: postcss: ^8.4.31 - checksum: 0877016f5b2a06b8ceaf39382b0c33da11ea93268209444f67f29b1ce465994058f305fc3bc90dda21e8664c959561fbb06ba12b82289c3b26ba832c6979d513 + checksum: 658cac8b28edcb94d1db67808ab3aaa511cb1b9293594fc95607ee42ac4f57e742d9a1fa3ff5d5849db692971dc2a310e9ac1ed0bd4ea4bc48c80f5a6ef823fc languageName: node linkType: hard @@ -15838,20 +15838,20 @@ __metadata: languageName: node linkType: hard -"svgo@npm:^3.0.5": - version: 3.1.0 - resolution: "svgo@npm:3.1.0" +"svgo@npm:^3.2.0": + version: 3.2.0 + resolution: "svgo@npm:3.2.0" dependencies: "@trysound/sax": "npm:0.2.0" commander: "npm:^7.2.0" css-select: "npm:^5.1.0" - css-tree: "npm:^2.2.1" + css-tree: "npm:^2.3.1" css-what: "npm:^6.1.0" - csso: "npm:5.0.5" + csso: "npm:^5.0.5" picocolors: "npm:^1.0.0" bin: svgo: ./bin/svgo - checksum: b3f00b3319dee6ddc53f8b8ac5acef581860e1708c98b492169e096621edc1bdf46e3778099e3dffb5116bf0d4c074a686099843dbc020c73b3ccfae7b6a88f0 + checksum: 28fa9061ccbcf2e3616d48d1feb613aaa05f8f290a329beb0e585914f1864385152934a7d4d683a4609fafbae3d51666633437c359c5c5ef74fb58ad09092a7c languageName: node linkType: hard From f06c1f1552f289bd357e4f05cd6486832cf5028f Mon Sep 17 00:00:00 2001 From: Matt Jankowski Date: Thu, 4 Jan 2024 04:20:32 -0500 Subject: [PATCH 08/61] Fix `Capybara/ClickLinkOrButtonStyle` cop in spec/features (#28576) --- Gemfile.lock | 2 +- spec/features/admin/accounts_spec.rb | 8 ++--- spec/features/admin/custom_emojis_spec.rb | 2 +- spec/features/admin/domain_blocks_spec.rb | 18 +++++----- .../admin/email_domain_blocks_spec.rb | 2 +- spec/features/admin/ip_blocks_spec.rb | 2 +- spec/features/admin/software_updates_spec.rb | 4 +-- spec/features/admin/statuses_spec.rb | 2 +- .../links/preview_card_providers_spec.rb | 2 +- spec/features/admin/trends/links_spec.rb | 2 +- spec/features/admin/trends/statuses_spec.rb | 2 +- spec/features/admin/trends/tags_spec.rb | 2 +- spec/features/captcha_spec.rb | 2 +- spec/features/log_in_spec.rb | 6 ++-- spec/features/oauth_spec.rb | 36 +++++++++---------- spec/support/stories/profile_stories.rb | 2 +- spec/system/new_statuses_spec.rb | 4 +-- 17 files changed, 49 insertions(+), 49 deletions(-) diff --git a/Gemfile.lock b/Gemfile.lock index 8d01167537..c3f27966d6 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -676,7 +676,7 @@ GEM unicode-display_width (>= 2.4.0, < 3.0) rubocop-ast (1.30.0) parser (>= 3.2.1.0) - rubocop-capybara (2.19.0) + rubocop-capybara (2.20.0) rubocop (~> 1.41) rubocop-factory_bot (2.24.0) rubocop (~> 1.33) diff --git a/spec/features/admin/accounts_spec.rb b/spec/features/admin/accounts_spec.rb index ad9c51485a..6d7bab1844 100644 --- a/spec/features/admin/accounts_spec.rb +++ b/spec/features/admin/accounts_spec.rb @@ -22,7 +22,7 @@ describe 'Admin::Accounts' do context 'without selecting any accounts' do it 'displays a notice about account selection' do - click_button button_for_suspend + click_on button_for_suspend expect(page).to have_content(selection_error_text) end @@ -32,7 +32,7 @@ describe 'Admin::Accounts' do it 'suspends the account' do batch_checkbox_for(approved_user_account).check - click_button button_for_suspend + click_on button_for_suspend expect(approved_user_account.reload).to be_suspended end @@ -42,7 +42,7 @@ describe 'Admin::Accounts' do it 'approves the account user' do batch_checkbox_for(unapproved_user_account).check - click_button button_for_approve + click_on button_for_approve expect(unapproved_user_account.reload.user).to be_approved end @@ -52,7 +52,7 @@ describe 'Admin::Accounts' do it 'rejects and removes the account' do batch_checkbox_for(unapproved_user_account).check - click_button button_for_reject + click_on button_for_reject expect { unapproved_user_account.reload }.to raise_error(ActiveRecord::RecordNotFound) end diff --git a/spec/features/admin/custom_emojis_spec.rb b/spec/features/admin/custom_emojis_spec.rb index 3fea8f06fe..8a8b6efcd1 100644 --- a/spec/features/admin/custom_emojis_spec.rb +++ b/spec/features/admin/custom_emojis_spec.rb @@ -16,7 +16,7 @@ describe 'Admin::CustomEmojis' do context 'without selecting any records' do it 'displays a notice about selection' do - click_button button_for_enable + click_on button_for_enable expect(page).to have_content(selection_error_text) end diff --git a/spec/features/admin/domain_blocks_spec.rb b/spec/features/admin/domain_blocks_spec.rb index 4379ac91db..6a1405cdf6 100644 --- a/spec/features/admin/domain_blocks_spec.rb +++ b/spec/features/admin/domain_blocks_spec.rb @@ -14,7 +14,7 @@ describe 'blocking domains through the moderation interface' do fill_in 'domain_block_domain', with: 'example.com' select I18n.t('admin.domain_blocks.new.severity.silence'), from: 'domain_block_severity' - click_button I18n.t('admin.domain_blocks.new.create') + click_on I18n.t('admin.domain_blocks.new.create') expect(DomainBlock.exists?(domain: 'example.com', severity: 'silence')).to be true expect(DomainBlockWorker).to have_received(:perform_async) @@ -27,14 +27,14 @@ describe 'blocking domains through the moderation interface' do fill_in 'domain_block_domain', with: 'example.com' select I18n.t('admin.domain_blocks.new.severity.suspend'), from: 'domain_block_severity' - click_button I18n.t('admin.domain_blocks.new.create') + click_on I18n.t('admin.domain_blocks.new.create') # It doesn't immediately block but presents a confirmation screen expect(page).to have_title(I18n.t('admin.domain_blocks.confirm_suspension.title', domain: 'example.com')) expect(DomainBlockWorker).to_not have_received(:perform_async) # Confirming creates a block - click_button I18n.t('admin.domain_blocks.confirm_suspension.confirm') + click_on I18n.t('admin.domain_blocks.confirm_suspension.confirm') expect(DomainBlock.exists?(domain: 'example.com', severity: 'suspend')).to be true expect(DomainBlockWorker).to have_received(:perform_async) @@ -49,14 +49,14 @@ describe 'blocking domains through the moderation interface' do fill_in 'domain_block_domain', with: 'example.com' select I18n.t('admin.domain_blocks.new.severity.suspend'), from: 'domain_block_severity' - click_button I18n.t('admin.domain_blocks.new.create') + click_on I18n.t('admin.domain_blocks.new.create') # It doesn't immediately block but presents a confirmation screen expect(page).to have_title(I18n.t('admin.domain_blocks.confirm_suspension.title', domain: 'example.com')) expect(DomainBlockWorker).to_not have_received(:perform_async) # Confirming updates the block - click_button I18n.t('admin.domain_blocks.confirm_suspension.confirm') + click_on I18n.t('admin.domain_blocks.confirm_suspension.confirm') expect(domain_block.reload.severity).to eq 'suspend' expect(DomainBlockWorker).to have_received(:perform_async) @@ -71,14 +71,14 @@ describe 'blocking domains through the moderation interface' do fill_in 'domain_block_domain', with: 'subdomain.example.com' select I18n.t('admin.domain_blocks.new.severity.suspend'), from: 'domain_block_severity' - click_button I18n.t('admin.domain_blocks.new.create') + click_on I18n.t('admin.domain_blocks.new.create') # It doesn't immediately block but presents a confirmation screen expect(page).to have_title(I18n.t('admin.domain_blocks.confirm_suspension.title', domain: 'subdomain.example.com')) expect(DomainBlockWorker).to_not have_received(:perform_async) # Confirming creates the block - click_button I18n.t('admin.domain_blocks.confirm_suspension.confirm') + click_on I18n.t('admin.domain_blocks.confirm_suspension.confirm') expect(DomainBlock.where(domain: 'subdomain.example.com', severity: 'suspend')).to exist expect(DomainBlockWorker).to have_received(:perform_async) @@ -96,14 +96,14 @@ describe 'blocking domains through the moderation interface' do visit edit_admin_domain_block_path(domain_block) select I18n.t('admin.domain_blocks.new.severity.suspend'), from: 'domain_block_severity' - click_button I18n.t('generic.save_changes') + click_on I18n.t('generic.save_changes') # It doesn't immediately block but presents a confirmation screen expect(page).to have_title(I18n.t('admin.domain_blocks.confirm_suspension.title', domain: 'example.com')) expect(DomainBlockWorker).to_not have_received(:perform_async) # Confirming updates the block - click_button I18n.t('admin.domain_blocks.confirm_suspension.confirm') + click_on I18n.t('admin.domain_blocks.confirm_suspension.confirm') expect(DomainBlockWorker).to have_received(:perform_async) expect(domain_block.reload.severity).to eq 'suspend' diff --git a/spec/features/admin/email_domain_blocks_spec.rb b/spec/features/admin/email_domain_blocks_spec.rb index 80efe72e95..14959cbe74 100644 --- a/spec/features/admin/email_domain_blocks_spec.rb +++ b/spec/features/admin/email_domain_blocks_spec.rb @@ -16,7 +16,7 @@ describe 'Admin::EmailDomainBlocks' do context 'without selecting any records' do it 'displays a notice about selection' do - click_button button_for_delete + click_on button_for_delete expect(page).to have_content(selection_error_text) end diff --git a/spec/features/admin/ip_blocks_spec.rb b/spec/features/admin/ip_blocks_spec.rb index 465c889190..c9b16f6f78 100644 --- a/spec/features/admin/ip_blocks_spec.rb +++ b/spec/features/admin/ip_blocks_spec.rb @@ -16,7 +16,7 @@ describe 'Admin::IpBlocks' do context 'without selecting any records' do it 'displays a notice about selection' do - click_button button_for_delete + click_on button_for_delete expect(page).to have_content(selection_error_text) end diff --git a/spec/features/admin/software_updates_spec.rb b/spec/features/admin/software_updates_spec.rb index a2373d35a6..4a635d1a79 100644 --- a/spec/features/admin/software_updates_spec.rb +++ b/spec/features/admin/software_updates_spec.rb @@ -11,13 +11,13 @@ describe 'finding software updates through the admin interface' do it 'shows a link to the software updates page, which links to release notes' do visit settings_profile_path - click_link I18n.t('admin.critical_update_pending') + click_on I18n.t('admin.critical_update_pending') expect(page).to have_title(I18n.t('admin.software_updates.title')) expect(page).to have_content('99.99.99') - click_link I18n.t('admin.software_updates.release_notes') + click_on I18n.t('admin.software_updates.release_notes') expect(page).to have_current_path('https://github.com/mastodon/mastodon/releases/v99', url: true) end end diff --git a/spec/features/admin/statuses_spec.rb b/spec/features/admin/statuses_spec.rb index a21c901a92..531d0de953 100644 --- a/spec/features/admin/statuses_spec.rb +++ b/spec/features/admin/statuses_spec.rb @@ -17,7 +17,7 @@ describe 'Admin::Statuses' do context 'without selecting any records' do it 'displays a notice about selection' do - click_button button_for_report + click_on button_for_report expect(page).to have_content(selection_error_text) end diff --git a/spec/features/admin/trends/links/preview_card_providers_spec.rb b/spec/features/admin/trends/links/preview_card_providers_spec.rb index cf9796abf3..dca89117b1 100644 --- a/spec/features/admin/trends/links/preview_card_providers_spec.rb +++ b/spec/features/admin/trends/links/preview_card_providers_spec.rb @@ -16,7 +16,7 @@ describe 'Admin::Trends::Links::PreviewCardProviders' do context 'without selecting any records' do it 'displays a notice about selection' do - click_button button_for_allow + click_on button_for_allow expect(page).to have_content(selection_error_text) end diff --git a/spec/features/admin/trends/links_spec.rb b/spec/features/admin/trends/links_spec.rb index 8b1b991a5a..99638bc069 100644 --- a/spec/features/admin/trends/links_spec.rb +++ b/spec/features/admin/trends/links_spec.rb @@ -16,7 +16,7 @@ describe 'Admin::Trends::Links' do context 'without selecting any records' do it 'displays a notice about selection' do - click_button button_for_allow + click_on button_for_allow expect(page).to have_content(selection_error_text) end diff --git a/spec/features/admin/trends/statuses_spec.rb b/spec/features/admin/trends/statuses_spec.rb index a578ab0559..779a15d38f 100644 --- a/spec/features/admin/trends/statuses_spec.rb +++ b/spec/features/admin/trends/statuses_spec.rb @@ -16,7 +16,7 @@ describe 'Admin::Trends::Statuses' do context 'without selecting any records' do it 'displays a notice about selection' do - click_button button_for_allow + click_on button_for_allow expect(page).to have_content(selection_error_text) end diff --git a/spec/features/admin/trends/tags_spec.rb b/spec/features/admin/trends/tags_spec.rb index 7502bc8c6f..52e49c3a5d 100644 --- a/spec/features/admin/trends/tags_spec.rb +++ b/spec/features/admin/trends/tags_spec.rb @@ -16,7 +16,7 @@ describe 'Admin::Trends::Tags' do context 'without selecting any records' do it 'displays a notice about selection' do - click_button button_for_allow + click_on button_for_allow expect(page).to have_content(selection_error_text) end diff --git a/spec/features/captcha_spec.rb b/spec/features/captcha_spec.rb index 906aec4af9..15c37eb463 100644 --- a/spec/features/captcha_spec.rb +++ b/spec/features/captcha_spec.rb @@ -23,7 +23,7 @@ describe 'email confirmation flow when captcha is enabled' do expect(user.reload.confirmed?).to be false # It redirects to app and confirms user - click_button I18n.t('challenge.confirm') + click_on I18n.t('challenge.confirm') expect(user.reload.confirmed?).to be true expect(page).to have_current_path(/\A#{client_app.confirmation_redirect_uri}/, url: true) diff --git a/spec/features/log_in_spec.rb b/spec/features/log_in_spec.rb index 7e5196aba9..c64e19d2b7 100644 --- a/spec/features/log_in_spec.rb +++ b/spec/features/log_in_spec.rb @@ -19,7 +19,7 @@ describe 'Log in' do it 'A valid email and password user is able to log in' do fill_in 'user_email', with: email fill_in 'user_password', with: password - click_button I18n.t('auth.login') + click_on I18n.t('auth.login') expect(subject).to have_css('div.app-holder') end @@ -27,7 +27,7 @@ describe 'Log in' do it 'A invalid email and password user is not able to log in' do fill_in 'user_email', with: 'invalid_email' fill_in 'user_password', with: 'invalid_password' - click_button I18n.t('auth.login') + click_on I18n.t('auth.login') expect(subject).to have_css('.flash-message', text: failure_message('invalid')) end @@ -38,7 +38,7 @@ describe 'Log in' do it 'A unconfirmed user is able to log in' do fill_in 'user_email', with: email fill_in 'user_password', with: password - click_button I18n.t('auth.login') + click_on I18n.t('auth.login') expect(subject).to have_css('div.admin-wrapper') end diff --git a/spec/features/oauth_spec.rb b/spec/features/oauth_spec.rb index 0e612b56a5..967956cc8e 100644 --- a/spec/features/oauth_spec.rb +++ b/spec/features/oauth_spec.rb @@ -20,7 +20,7 @@ describe 'Using OAuth from an external app' do expect(page).to have_content(I18n.t('doorkeeper.authorizations.buttons.authorize')) # Upon authorizing, it redirects to the apps' callback URL - click_button I18n.t('doorkeeper.authorizations.buttons.authorize') + click_on I18n.t('doorkeeper.authorizations.buttons.authorize') expect(page).to have_current_path(/\A#{client_app.redirect_uri}/, url: true) # It grants the app access to the account @@ -35,7 +35,7 @@ describe 'Using OAuth from an external app' do expect(page).to have_content(I18n.t('doorkeeper.authorizations.buttons.deny')) # Upon denying, it redirects to the apps' callback URL - click_button I18n.t('doorkeeper.authorizations.buttons.deny') + click_on I18n.t('doorkeeper.authorizations.buttons.deny') expect(page).to have_current_path(/\A#{client_app.redirect_uri}/, url: true) # It does not grant the app access to the account @@ -63,17 +63,17 @@ describe 'Using OAuth from an external app' do # Failing to log-in presents the form again fill_in 'user_email', with: email fill_in 'user_password', with: 'wrong password' - click_button I18n.t('auth.login') + click_on I18n.t('auth.login') expect(page).to have_content(I18n.t('auth.login')) # Logging in redirects to an authorization page fill_in 'user_email', with: email fill_in 'user_password', with: password - click_button I18n.t('auth.login') + click_on I18n.t('auth.login') expect(page).to have_content(I18n.t('doorkeeper.authorizations.buttons.authorize')) # Upon authorizing, it redirects to the apps' callback URL - click_button I18n.t('doorkeeper.authorizations.buttons.authorize') + click_on I18n.t('doorkeeper.authorizations.buttons.authorize') expect(page).to have_current_path(/\A#{client_app.redirect_uri}/, url: true) # It grants the app access to the account @@ -90,17 +90,17 @@ describe 'Using OAuth from an external app' do # Failing to log-in presents the form again fill_in 'user_email', with: email fill_in 'user_password', with: 'wrong password' - click_button I18n.t('auth.login') + click_on I18n.t('auth.login') expect(page).to have_content(I18n.t('auth.login')) # Logging in redirects to an authorization page fill_in 'user_email', with: email fill_in 'user_password', with: password - click_button I18n.t('auth.login') + click_on I18n.t('auth.login') expect(page).to have_content(I18n.t('doorkeeper.authorizations.buttons.authorize')) # Upon denying, it redirects to the apps' callback URL - click_button I18n.t('doorkeeper.authorizations.buttons.deny') + click_on I18n.t('doorkeeper.authorizations.buttons.deny') expect(page).to have_current_path(/\A#{client_app.redirect_uri}/, url: true) # It does not grant the app access to the account @@ -120,27 +120,27 @@ describe 'Using OAuth from an external app' do # Failing to log-in presents the form again fill_in 'user_email', with: email fill_in 'user_password', with: 'wrong password' - click_button I18n.t('auth.login') + click_on I18n.t('auth.login') expect(page).to have_content(I18n.t('auth.login')) # Logging in redirects to a two-factor authentication page fill_in 'user_email', with: email fill_in 'user_password', with: password - click_button I18n.t('auth.login') + click_on I18n.t('auth.login') expect(page).to have_content(I18n.t('simple_form.hints.sessions.otp')) # Filling in an incorrect two-factor authentication code presents the form again fill_in 'user_otp_attempt', with: 'wrong' - click_button I18n.t('auth.login') + click_on I18n.t('auth.login') expect(page).to have_content(I18n.t('simple_form.hints.sessions.otp')) # Filling in the correct TOTP code redirects to an app authorization page fill_in 'user_otp_attempt', with: user.current_otp - click_button I18n.t('auth.login') + click_on I18n.t('auth.login') expect(page).to have_content(I18n.t('doorkeeper.authorizations.buttons.authorize')) # Upon authorizing, it redirects to the apps' callback URL - click_button I18n.t('doorkeeper.authorizations.buttons.authorize') + click_on I18n.t('doorkeeper.authorizations.buttons.authorize') expect(page).to have_current_path(/\A#{client_app.redirect_uri}/, url: true) # It grants the app access to the account @@ -157,27 +157,27 @@ describe 'Using OAuth from an external app' do # Failing to log-in presents the form again fill_in 'user_email', with: email fill_in 'user_password', with: 'wrong password' - click_button I18n.t('auth.login') + click_on I18n.t('auth.login') expect(page).to have_content(I18n.t('auth.login')) # Logging in redirects to a two-factor authentication page fill_in 'user_email', with: email fill_in 'user_password', with: password - click_button I18n.t('auth.login') + click_on I18n.t('auth.login') expect(page).to have_content(I18n.t('simple_form.hints.sessions.otp')) # Filling in an incorrect two-factor authentication code presents the form again fill_in 'user_otp_attempt', with: 'wrong' - click_button I18n.t('auth.login') + click_on I18n.t('auth.login') expect(page).to have_content(I18n.t('simple_form.hints.sessions.otp')) # Filling in the correct TOTP code redirects to an app authorization page fill_in 'user_otp_attempt', with: user.current_otp - click_button I18n.t('auth.login') + click_on I18n.t('auth.login') expect(page).to have_content(I18n.t('doorkeeper.authorizations.buttons.authorize')) # Upon denying, it redirects to the apps' callback URL - click_button I18n.t('doorkeeper.authorizations.buttons.deny') + click_on I18n.t('doorkeeper.authorizations.buttons.deny') expect(page).to have_current_path(/\A#{client_app.redirect_uri}/, url: true) # It does not grant the app access to the account diff --git a/spec/support/stories/profile_stories.rb b/spec/support/stories/profile_stories.rb index 82667ca080..2b345ddef1 100644 --- a/spec/support/stories/profile_stories.rb +++ b/spec/support/stories/profile_stories.rb @@ -18,7 +18,7 @@ module ProfileStories visit new_user_session_path fill_in 'user_email', with: email fill_in 'user_password', with: password - click_button I18n.t('auth.login') + click_on I18n.t('auth.login') end def with_alice_as_local_user diff --git a/spec/system/new_statuses_spec.rb b/spec/system/new_statuses_spec.rb index 244101f4d4..02f2e28393 100644 --- a/spec/system/new_statuses_spec.rb +++ b/spec/system/new_statuses_spec.rb @@ -24,7 +24,7 @@ describe 'NewStatuses' do within('.compose-form') do fill_in "What's on your mind?", with: status_text - click_button 'Publish!' + click_on 'Publish!' end expect(subject).to have_css('.status__content__text', text: status_text) @@ -37,7 +37,7 @@ describe 'NewStatuses' do within('.compose-form') do fill_in "What's on your mind?", with: status_text - click_button 'Publish!' + click_on 'Publish!' end expect(subject).to have_css('.status__content__text', text: status_text) From 1af5c3770153e7c3569d13c431e988049956ae8b Mon Sep 17 00:00:00 2001 From: Matt Jankowski Date: Thu, 4 Jan 2024 04:21:27 -0500 Subject: [PATCH 09/61] Use heredoc on federation CLI warning strings (#28578) --- lib/mastodon/cli/federation.rb | 26 +++++++++++++++++++------- 1 file changed, 19 insertions(+), 7 deletions(-) diff --git a/lib/mastodon/cli/federation.rb b/lib/mastodon/cli/federation.rb index 4a4dde3686..8bb46ecb1a 100644 --- a/lib/mastodon/cli/federation.rb +++ b/lib/mastodon/cli/federation.rb @@ -48,19 +48,31 @@ module Mastodon::CLI exit(1) unless ask('Type in the domain of the server to confirm:') == Rails.configuration.x.local_domain - say('This operation WILL NOT be reversible.', :yellow) - say('While the data won\'t be erased locally, the server will be in a BROKEN STATE afterwards.', :yellow) - say('The deletion process itself may take a long time, and will be handled by Sidekiq, so do not shut it down until it has finished (you will be able to re-run this command to see the state of the self-destruct process).', :yellow) + say(<<~WARNING, :yellow) + This operation WILL NOT be reversible. + While the data won't be erased locally, the server will be in a BROKEN STATE afterwards. + The deletion process itself may take a long time, and will be handled by Sidekiq, so do not shut it down until it has finished (you will be able to re-run this command to see the state of the self-destruct process). + WARNING exit(1) if no?('Are you sure you want to proceed?') - self_destruct_value = Rails.application.message_verifier('self-destruct').generate(Rails.configuration.x.local_domain) - say('To switch Mastodon to self-destruct mode, add the following variable to your evironment (e.g. by adding a line to your `.env.production`) and restart all Mastodon processes:', :green) - say(" SELF_DESTRUCT=#{self_destruct_value}", :green) - say("\nYou can re-run this command to see the state of the self-destruct process.", :green) + say(<<~INSTRUCTIONS, :green) + To switch Mastodon to self-destruct mode, add the following variable to your evironment (e.g. by adding a line to your `.env.production`) and restart all Mastodon processes: + SELF_DESTRUCT=#{self_destruct_value} + You can re-run this command to see the state of the self-destruct process. + INSTRUCTIONS rescue Interrupt exit(1) end + + private + + def self_destruct_value + Rails + .application + .message_verifier('self-destruct') + .generate(Rails.configuration.x.local_domain) + end end end end From bdf4750633703d97269522759ea6f2f8ecbd4976 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Thu, 4 Jan 2024 09:24:13 +0000 Subject: [PATCH 10/61] New Crowdin Translations (automated) (#28590) Co-authored-by: GitHub Actions --- app/javascript/mastodon/locales/ia.json | 25 +++++++++++++++++++++++- app/javascript/mastodon/locales/lad.json | 1 + app/javascript/mastodon/locales/nn.json | 2 +- app/javascript/mastodon/locales/no.json | 2 +- config/locales/devise.ie.yml | 7 +++++++ config/locales/doorkeeper.ie.yml | 3 +++ config/locales/lad.yml | 21 ++++++++++++++++++++ config/locales/simple_form.ie.yml | 12 ++++++++++++ 8 files changed, 70 insertions(+), 3 deletions(-) diff --git a/app/javascript/mastodon/locales/ia.json b/app/javascript/mastodon/locales/ia.json index 35397b8e12..9781d6aa77 100644 --- a/app/javascript/mastodon/locales/ia.json +++ b/app/javascript/mastodon/locales/ia.json @@ -38,12 +38,14 @@ "confirmation_modal.cancel": "Cancellar", "confirmations.delete.confirm": "Deler", "confirmations.delete_list.confirm": "Deler", + "confirmations.edit.confirm": "Modificar", "confirmations.logout.confirm": "Clauder le session", "copy_icon_button.copied": "Copiate al area de transferentia", "copypaste.copy_to_clipboard": "Copiar al area de transferentia", "disabled_account_banner.account_settings": "Parametros de conto", "dismissable_banner.dismiss": "Dimitter", "emoji_button.activity": "Activitate", + "emoji_button.clear": "Rader", "emoji_button.custom": "Personalisate", "emoji_button.search_results": "Resultatos de recerca", "empty_column.account_unavailable": "Profilo non disponibile", @@ -69,16 +71,37 @@ "navigation_bar.about": "A proposito de", "navigation_bar.advanced_interface": "Aperir in un interfacie web avantiate", "navigation_bar.blocks": "Usatores blocate", + "navigation_bar.discover": "Discoperir", + "navigation_bar.edit_profile": "Modificar profilo", "navigation_bar.favourites": "Favoritos", "navigation_bar.lists": "Listas", "navigation_bar.logout": "Clauder le session", "navigation_bar.preferences": "Preferentias", + "navigation_bar.search": "Cercar", "navigation_bar.security": "Securitate", "notifications.column_settings.alert": "Notificationes de scriptorio", "notifications.column_settings.filter_bar.advanced": "Monstrar tote le categorias", "notifications.column_settings.sound": "Reproducer sono", "notifications.filter.all": "Toto", + "notifications.grant_permission": "Conceder permission.", + "notifications.group": "{count} notificationes", "onboarding.compose.template": "Salute #Mastodon!", "onboarding.profile.save_and_continue": "Salvar e continuar", - "onboarding.share.title": "Compartir tu profilo" + "onboarding.share.title": "Compartir tu profilo", + "onboarding.steps.share_profile.title": "Compartir tu profilo de Mastodon", + "relative_time.just_now": "ora", + "relative_time.today": "hodie", + "reply_indicator.cancel": "Cancellar", + "report.next": "Sequente", + "report.placeholder": "Commentos additional", + "report.reasons.dislike": "Non me place", + "search.quick_action.go_to_account": "Vader al profilo {x}", + "search_results.accounts": "Profilos", + "search_results.see_all": "Vider toto", + "status.delete": "Deler", + "status.share": "Compartir", + "status.translate": "Traducer", + "status.translated_from_with": "Traducite ab {lang} usante {provider}", + "tabs_bar.home": "Initio", + "tabs_bar.notifications": "Notificationes" } diff --git a/app/javascript/mastodon/locales/lad.json b/app/javascript/mastodon/locales/lad.json index ce6cb56473..2067edcc70 100644 --- a/app/javascript/mastodon/locales/lad.json +++ b/app/javascript/mastodon/locales/lad.json @@ -501,6 +501,7 @@ "onboarding.steps.setup_profile.title": "Personaliza tu profil", "onboarding.steps.share_profile.body": "Informe a tus amigos komo toparte en Mastodon", "onboarding.steps.share_profile.title": "Partaja tu profil de Mastodon", + "password_confirmation.mismatching": "Los dos kodes son desferentes", "picture_in_picture.restore": "Restora", "poll.closed": "Serrado", "poll.refresh": "Arefreska", diff --git a/app/javascript/mastodon/locales/nn.json b/app/javascript/mastodon/locales/nn.json index e5b1d2b378..ec2ff82144 100644 --- a/app/javascript/mastodon/locales/nn.json +++ b/app/javascript/mastodon/locales/nn.json @@ -606,7 +606,7 @@ "search.quick_action.status_search": "Innlegg som samsvarer med {x}", "search.search_or_paste": "Søk eller lim inn URL", "search_popout.full_text_search_disabled_message": "Ikkje tilgjengeleg på {domain}.", - "search_popout.full_text_search_logged_out_message": "Bare tilgjengelig ved innlogging.", + "search_popout.full_text_search_logged_out_message": "Bare tilgjengelig når man er logget inn.", "search_popout.language_code": "ISO-språkkode", "search_popout.options": "Søkjealternativ", "search_popout.quick_actions": "Hurtighandlinger", diff --git a/app/javascript/mastodon/locales/no.json b/app/javascript/mastodon/locales/no.json index c0f50283ac..50da3bb2be 100644 --- a/app/javascript/mastodon/locales/no.json +++ b/app/javascript/mastodon/locales/no.json @@ -606,7 +606,7 @@ "search.quick_action.status_search": "Innlegg som samsvarer med {x}", "search.search_or_paste": "Søk eller lim inn URL", "search_popout.full_text_search_disabled_message": "Ikke tilgjengelig på {domain}.", - "search_popout.full_text_search_logged_out_message": "Bare tilgjengelig ved innlogging.", + "search_popout.full_text_search_logged_out_message": "Bare tilgjengelig når man er logget inn.", "search_popout.language_code": "ISO språkkode", "search_popout.options": "Alternativer for søk", "search_popout.quick_actions": "Hurtighandlinger", diff --git a/config/locales/devise.ie.yml b/config/locales/devise.ie.yml index e4f2e6fb19..687e7115a6 100644 --- a/config/locales/devise.ie.yml +++ b/config/locales/devise.ie.yml @@ -46,6 +46,10 @@ ie: title: 2FA desvalidat two_factor_enabled: title: 2FA permisset + two_factor_recovery_codes_changed: + explanation: Li anteyan codes de recuperation ha esset ínvalidat, e novis generat. + subject: 'Mastodon: 2-factor codes de recuperation regenerat' + title: 2FA codes de recuperation changeat unlock_instructions: subject: 'Mastodon: Desserral instructiones' webauthn_credential: @@ -55,8 +59,11 @@ ie: webauthn_disabled: subject: 'Mastodon: Autentication con claves de securitá desactivisat' title: Claves de securitá desactivisat + webauthn_enabled: + title: Claves de securitá activisat omniauth_callbacks: failure: Ne posset autenticar te de %{kind} pro "%{reason}". + success: Successosimen autenticat de conto %{kind}. passwords: no_token: Tu ne posse accessar ti-ci págine sin venir de un email pri reiniciar li passa-parol. Si tu ha venit de un email pri reiniciar li passa-parol, ples far cert que tu usat li complet URL providet. send_instructions: Si tui email-adresse existe in nor database, tu va reciver un ligament por recuperar li passa-parol a tui email-adresse in quelc minutes. Ples vider tui spam-emails si tu ne recivet ti email. diff --git a/config/locales/doorkeeper.ie.yml b/config/locales/doorkeeper.ie.yml index 86a5de7b37..b778871e3a 100644 --- a/config/locales/doorkeeper.ie.yml +++ b/config/locales/doorkeeper.ie.yml @@ -31,6 +31,7 @@ ie: redirect_uri: Usar un linea per URI index: application: Aplication + callback_url: URL de retrovocada delete: Deleter empty: Tu have null aplicationes. name: Nómine @@ -42,6 +43,7 @@ ie: show: actions: Actiones application_id: Clave de client + callback_urls: URLs de retrovocada secret: Secrete de client title: 'Aplication: %{name}' authorizations: @@ -51,6 +53,7 @@ ie: error: title: Alquo ha errat new: + review_permissions: Inspecter permissiones title: Autorisation besonat authorized_applications: buttons: diff --git a/config/locales/lad.yml b/config/locales/lad.yml index 5c541d9f99..323ade8ddb 100644 --- a/config/locales/lad.yml +++ b/config/locales/lad.yml @@ -383,7 +383,11 @@ lad: confirm_suspension: cancel: Anula confirm: Suspende + permanent_action: Si kites la suspensyon no restoraras dingunos datos ni relasyones. + remove_all_data: Esto efasara todo el kontenido, multimedia i datos de profiles de los kuentos en este domeno de tu sirvidor. + stop_communication: Tu sirvidor deshara de komunikarse kon estos sirvidores. title: Konfirma bloko de domeno para %{domain} + undo_relationships: Esto kitara todas las relasyones de segimyento entre tu kuentos en estos sirvidores i el tu sirvidor. created_msg: El bloko de domeno esta siendo prosesado destroyed_msg: El bloko de domeno se dezizo domain: Domeno @@ -772,6 +776,8 @@ lad: type: Tipo types: major: Versyon prinsipala + minor: Versyon minora + patch: Versyon de remendo – koreksyones de yerros i trokamientos simples version: Versyon statuses: account: Autor @@ -829,8 +835,10 @@ lad: message_html: No ay dingun prosedura Sidekiq en egzekusion para la(s) kola(s) %{value}. Por favor, reviza tu konfigurasyon de Sidekiq software_version_critical_check: action: Amostra aktualizasyones desponivles + message_html: Una aktualizasyon kritika de Mastodon esta desponivle. Por favor aktualiza pishin. software_version_patch_check: action: Amostra aktualizasyones desponivles + message_html: Una aktualizasyon de Mastodon kon koreksyon de yerros esta desponivle. upload_check_privacy_error: action: Klika aki para mas enformasyon message_html: "Tu sirvidor de web es mal konfigurado. La privasita de tus utilizadores esta en riziko." @@ -945,6 +953,7 @@ lad: next_steps: Puedes achetar la apelasyon para dezazer la dechizyon de moderasyon, o ignorarla. subject: "%{username} esta apelando a una dechizyon de moderasyon en %{instance}" new_critical_software_updates: + body: Ay mueva versyon kritika de Mastodon. Es posivle ke keras aktualizar pishin! subject: Ay aktualizasyones kritikas de Mastodon desponivles para %{instance}! new_pending_account: body: Los peratim del muevo kuento estan abashos. Puedes achetar o refuzar esta aplikasyon. @@ -1045,13 +1054,17 @@ lad: accept: Acheta back: Atras preamble: Estas son establesidas i aplikadas por los moderadores de %{domain}. + preamble_invited: Antes de kontinuar, por favor reviza las reglas del sirvidor establesidas por los moderatores de %{domain}. title: Algunas reglas bazikas. title_invited: Fuites envitado. security: Sigurita set_new_password: Establese muevo kod setup: email_below_hint_html: Mira en tu kuti de spam o solisita de muevo. Si el adreso de posta elektronika ke aparese aki es yerrado, puedes trokarlo aki. + email_settings_hint_html: Klika el atadjiko ke te embimos para verifikar %{email}. Asperaremos aki. link_not_received: No risivites un atadijo? + new_confirmation_instructions_sent: Resiviras un muevo mesaj de posta elektronika kon el atadjio de konfirmasyon en unos minutos! + title: Reviza tu kuti de arivo sign_in: preamble_html: Konektate kon tus kredensiales de %{domain}. Si tu kuento esta balabayado en otruno servidor, no puedras konektarte aki. title: Konektate kon %{domain} @@ -1246,9 +1259,11 @@ lad: imports: errors: empty: Dosya CSV vaziya + incompatible_type: Inkompativle kon el tipo de importo eskojido invalid_csv_file: 'Dosya CSV no valida. Yerro: %{error}' over_rows_processing_limit: kontiene mas de %{count} filas too_large: Dosya es mas grande + failures: Yerros imported: Importado modes: merge: Une @@ -1671,6 +1686,9 @@ lad: month: "%b %Y" time: "%H:%M" with_time_zone: "%d de %b del %Y, %H:%M %Z" + translation: + errors: + too_many_requests: Ay demaziadas solisitudes de servisyo de traduksyon. two_factor_authentication: add: Adjusta disable: Inkapasita autentifikasyon en dos pasos @@ -1750,9 +1768,12 @@ lad: title: Bienvenido, %{name}! users: follow_limit_reached: No puedes segir a mas de %{limit} personas + go_to_sso_account_settings: Va a la konfigurasyon de kuento de tu prokurador de identita invalid_otp_token: Kodiche de dos pasos no valido + otp_lost_help_html: Si pedriste akseso a los dos, puedes kontaktarte kon %{email} signed_in_as: 'Konektado komo:' verification: + here_is_how: Ansina es komo verification: Verifikasyon verified_links: Tus atadijos verifikados webauthn_credentials: diff --git a/config/locales/simple_form.ie.yml b/config/locales/simple_form.ie.yml index bde52e2a78..bd055b1c9e 100644 --- a/config/locales/simple_form.ie.yml +++ b/config/locales/simple_form.ie.yml @@ -86,6 +86,7 @@ ie: ip_block: comment: Facultativ. Ne obliviar pro quo tu adjuntet ti-ci regul. expires_in: IP-adresses es un ressurse finit, quelcvez partit e transferet de manu a manu. Pro to, un índefinit bloccada de IP ne es recomandat. + ip: Intrar un adresse IPv4 o IPv6. Tu posse bloccar un tot intervalle de ili con li sintaxe CIDR. Atention a ne bloccar te self! severities: no_access: Bloccar accesse a omni ressurses sign_up_block: Nov registrationes ne va esser possibil @@ -93,6 +94,10 @@ ie: severity: Selecter quo va evenir con demandes ex ti-ci IP rule: text: Descrir un regul o postulation por usatores sur ti-ci servitor. Prova scrir un descrition curt e simplic + sessions: + otp: 'Intrar li 2-factor code generat del app sur tui portabile o usar un de tui codes de recuperation:' + settings: + show_application: Totvez, tu va sempre posser vider quel app ha publicat tui posta. user: role: Permissiones de usator decidet per su rol user_role: @@ -111,6 +116,7 @@ ie: name: Etiquette value: Contenete indexable: Includer public postas in resultates de sercha + unlocked: Automaticmen acceptar nov sequitores account_alias: acct: Usator-nómine del anteyan conto account_migration: @@ -158,6 +164,7 @@ ie: max_uses: Max grand númere de usas new_password: Nov passa-parol note: Biografie + otp_attempt: 2-factor code password: Passa-parol phrase: Clave-parol o frase setting_advanced_layout: Possibilisar web-interfacie avansat @@ -165,10 +172,12 @@ ie: setting_default_language: Lingue in quel postar setting_default_privacy: Privatie de postada setting_default_sensitive: Sempre marcar medie quam sensitiv + setting_display_media: Exposition de medie setting_display_media_default: Predefinitiones setting_display_media_hide_all: Celar omno setting_display_media_show_all: Monstrar omno setting_expand_spoilers: Sempre expander postas marcat con admonitiones de contenete + setting_hide_network: Celar tui grafica social setting_system_font_ui: Usar predefinit fonte de sistema setting_theme: Tema de situ setting_trends: Monstrar li hodial tendenties @@ -179,6 +188,7 @@ ie: title: Titul type: Specie de importation username: Nómine de usator + username_or_email: Usator-nómine o E-posta whole_word: Plen parol featured_tag: name: Hashtag @@ -193,11 +203,13 @@ ie: custom_css: Custom CSS profile_directory: Possibilisar profilarium registrations_mode: Qui posse registrar se + require_invite_text: Exiger un rason por adherer se show_domain_blocks: Vider bloccas de dominia show_domain_blocks_rationale: Monstrar pro quo cert dominias esset bloccat site_contact_email: Contact e-mail adresse site_contact_username: Usator-nómine de contact site_extended_description: Extendet descrition + site_short_description: Descrition del servitor site_title: Nómine de servitor theme: Predefenit tema trendable_by_default: Possibilisar tendenties sin priori inspection From da7290839aa140e5aa082dc1d57bfa59933178c3 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Thu, 4 Jan 2024 10:24:43 +0100 Subject: [PATCH 11/61] Update dependency stylelint-config-standard-scss to v13 (#28589) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- package.json | 2 +- yarn.lock | 24 ++++++++++++------------ 2 files changed, 13 insertions(+), 13 deletions(-) diff --git a/package.json b/package.json index 82cfd689a5..a5b6a228ca 100644 --- a/package.json +++ b/package.json @@ -202,7 +202,7 @@ "prettier": "^3.0.0", "react-test-renderer": "^18.2.0", "stylelint": "^16.0.2", - "stylelint-config-standard-scss": "^12.0.0", + "stylelint-config-standard-scss": "^13.0.0", "typescript": "^5.0.4", "webpack-dev-server": "^3.11.3", "yargs": "^17.7.2" diff --git a/yarn.lock b/yarn.lock index 99c3eedb26..e1c8ab3fb8 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2433,7 +2433,7 @@ __metadata: stacktrace-js: "npm:^2.0.2" stringz: "npm:^2.1.0" stylelint: "npm:^16.0.2" - stylelint-config-standard-scss: "npm:^12.0.0" + stylelint-config-standard-scss: "npm:^13.0.0" substring-trie: "npm:^1.0.2" terser-webpack-plugin: "npm:^4.2.3" tesseract.js: "npm:^2.1.5" @@ -15644,30 +15644,30 @@ __metadata: languageName: node linkType: hard -"stylelint-config-standard-scss@npm:^12.0.0": - version: 12.0.0 - resolution: "stylelint-config-standard-scss@npm:12.0.0" +"stylelint-config-standard-scss@npm:^13.0.0": + version: 13.0.0 + resolution: "stylelint-config-standard-scss@npm:13.0.0" dependencies: stylelint-config-recommended-scss: "npm:^14.0.0" - stylelint-config-standard: "npm:^35.0.0" + stylelint-config-standard: "npm:^36.0.0" peerDependencies: postcss: ^8.3.3 - stylelint: ^16.0.2 + stylelint: ^16.1.0 peerDependenciesMeta: postcss: optional: true - checksum: 7f3ccfb4175f9c50b69d30ca35a97887008c5ba493dbe7d5bce0b57b1eafd21b268177b82404368e7780600077cba784f98e1046671724be3b29a00c6a7913a4 + checksum: 4abf317676184f4aaace6ce72b9fc9e2dffe051d43dd5637afc5803b062ea381e2807ae983c045dff22e96af58388a8b1fe9a8bdda9f97bc3660280cf24fb4d3 languageName: node linkType: hard -"stylelint-config-standard@npm:^35.0.0": - version: 35.0.0 - resolution: "stylelint-config-standard@npm:35.0.0" +"stylelint-config-standard@npm:^36.0.0": + version: 36.0.0 + resolution: "stylelint-config-standard@npm:36.0.0" dependencies: stylelint-config-recommended: "npm:^14.0.0" peerDependencies: - stylelint: ^16.0.0 - checksum: 791fbc26cc3029ce3c2423a643e903545b5e4cd605251b18f0ce790bac6fbaaf380469845c1ff45f4e320126af9f8a9dc1ca85d0df9274277ae60da91e81895b + stylelint: ^16.1.0 + checksum: 1fc9adddfc5cf0a1d7a443182a0731712a3950ace72a24081b4ede2b0bb6fc1eebd003c009f1d8d06c3a64ba9b31b0ed12512db2f91c8fa549238d8341580e4b languageName: node linkType: hard From 419c659bc445fa258550b7e1bf00251663ca6a21 Mon Sep 17 00:00:00 2001 From: Claire Date: Thu, 4 Jan 2024 15:14:46 +0100 Subject: [PATCH 12/61] Add fallback redirection when getting a webfinger query `WEB_DOMAIN@WEB_DOMAIN` (#28592) --- app/controllers/well_known/webfinger_controller.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/controllers/well_known/webfinger_controller.rb b/app/controllers/well_known/webfinger_controller.rb index 364fbf8a18..72f0ea890f 100644 --- a/app/controllers/well_known/webfinger_controller.rb +++ b/app/controllers/well_known/webfinger_controller.rb @@ -21,7 +21,7 @@ module WellKnown username = username_from_resource @account = begin - if username == Rails.configuration.x.local_domain + if username == Rails.configuration.x.local_domain || username == Rails.configuration.x.web_domain Account.representative else Account.find_local!(username) From d0fd14f851871659834ae600f043d81e352cdc1f Mon Sep 17 00:00:00 2001 From: Claire Date: Thu, 4 Jan 2024 15:17:38 +0100 Subject: [PATCH 13/61] Fix scrolling to detailed status not always working (#28577) --- .../mastodon/features/status/index.jsx | 19 +++++++++++-------- 1 file changed, 11 insertions(+), 8 deletions(-) diff --git a/app/javascript/mastodon/features/status/index.jsx b/app/javascript/mastodon/features/status/index.jsx index 67a9697311..c581255c99 100644 --- a/app/javascript/mastodon/features/status/index.jsx +++ b/app/javascript/mastodon/features/status/index.jsx @@ -582,16 +582,20 @@ class Status extends ImmutablePureComponent { )); } - setRef = c => { + setContainerRef = c => { this.node = c; }; + setStatusRef = c => { + this.statusNode = c; + }; + _scrollStatusIntoView () { const { status, multiColumn } = this.props; if (status) { - window.requestAnimationFrame(() => { - this.node?.querySelector('.detailed-status__wrapper')?.scrollIntoView(true); + requestIdleCallback(() => { + this.statusNode?.scrollIntoView(true); // In the single-column interface, `scrollIntoView` will put the post behind the header, // so compensate for that. @@ -629,9 +633,8 @@ class Status extends ImmutablePureComponent { } // Scroll to focused post if it is loaded - const child = this.node?.querySelector('.detailed-status__wrapper'); - if (child) { - return [0, child.offsetTop]; + if (this.statusNode) { + return [0, this.statusNode.offsetTop]; } // Do not scroll otherwise, `componentDidUpdate` will take care of that @@ -692,11 +695,11 @@ class Status extends ImmutablePureComponent { /> -
+
{ancestors} -
+
Date: Thu, 4 Jan 2024 11:40:28 -0500 Subject: [PATCH 14/61] Solve remaining `db/*migrate*` cops (#28579) --- .rubocop_todo.yml | 4 - .../20170901141119_truncate_preview_cards.rb | 10 +-- ...024224956_migrate_account_conversations.rb | 2 +- ..._preserve_old_layout_for_existing_users.rb | 2 +- ...04024901_migrate_settings_to_user_roles.rb | 77 ++++++++++++------- 5 files changed, 54 insertions(+), 41 deletions(-) diff --git a/.rubocop_todo.yml b/.rubocop_todo.yml index bc66bc4add..d68832e85e 100644 --- a/.rubocop_todo.yml +++ b/.rubocop_todo.yml @@ -165,7 +165,6 @@ Rails/WhereExists: - 'app/validators/reaction_validator.rb' - 'app/validators/vote_validator.rb' - 'app/workers/move_worker.rb' - - 'db/migrate/20190529143559_preserve_old_layout_for_existing_users.rb' - 'lib/tasks/tests.rake' - 'spec/models/account_spec.rb' - 'spec/services/activitypub/process_collection_service_spec.rb' @@ -253,8 +252,6 @@ Style/GuardClause: - 'app/workers/redownload_media_worker.rb' - 'app/workers/remote_account_refresh_worker.rb' - 'config/initializers/devise.rb' - - 'db/migrate/20170901141119_truncate_preview_cards.rb' - - 'db/post_migrate/20220704024901_migrate_settings_to_user_roles.rb' - 'lib/devise/strategies/two_factor_ldap_authenticatable.rb' - 'lib/devise/strategies/two_factor_pam_authenticatable.rb' - 'lib/mastodon/cli/accounts.rb' @@ -275,7 +272,6 @@ Style/HashAsLastArrayItem: - 'app/models/status.rb' - 'app/services/batched_remove_status_service.rb' - 'app/services/notify_service.rb' - - 'db/migrate/20181024224956_migrate_account_conversations.rb' # This cop supports unsafe autocorrection (--autocorrect-all). Style/HashTransformValues: diff --git a/db/migrate/20170901141119_truncate_preview_cards.rb b/db/migrate/20170901141119_truncate_preview_cards.rb index 22a7731099..b4ba8c45ea 100644 --- a/db/migrate/20170901141119_truncate_preview_cards.rb +++ b/db/migrate/20170901141119_truncate_preview_cards.rb @@ -22,11 +22,9 @@ class TruncatePreviewCards < ActiveRecord::Migration[5.1] end def down - if ActiveRecord::Base.connection.table_exists? 'deprecated_preview_cards' - drop_table :preview_cards - rename_table :deprecated_preview_cards, :preview_cards - else - raise ActiveRecord::IrreversibleMigration, 'Previous preview cards table has already been removed' - end + raise ActiveRecord::IrreversibleMigration, 'Previous preview cards table has already been removed' unless ActiveRecord::Base.connection.table_exists? 'deprecated_preview_cards' + + drop_table :preview_cards + rename_table :deprecated_preview_cards, :preview_cards end end diff --git a/db/migrate/20181024224956_migrate_account_conversations.rb b/db/migrate/20181024224956_migrate_account_conversations.rb index 93ef5da615..d879fd88a2 100644 --- a/db/migrate/20181024224956_migrate_account_conversations.rb +++ b/db/migrate/20181024224956_migrate_account_conversations.rb @@ -105,7 +105,7 @@ class MigrateAccountConversations < ActiveRecord::Migration[5.2] end end - notifications_about_direct_statuses.includes(:account, mention: { status: [:account, mentions: :account] }).find_each do |notification| + notifications_about_direct_statuses.includes(:account, mention: { status: [:account, { mentions: :account }] }).find_each do |notification| MigrationAccountConversation.add_status(notification.account, notification.target_status) migrated += 1 diff --git a/db/migrate/20190529143559_preserve_old_layout_for_existing_users.rb b/db/migrate/20190529143559_preserve_old_layout_for_existing_users.rb index 88dcea4360..4597ec5ef4 100644 --- a/db/migrate/20190529143559_preserve_old_layout_for_existing_users.rb +++ b/db/migrate/20190529143559_preserve_old_layout_for_existing_users.rb @@ -9,7 +9,7 @@ class PreserveOldLayoutForExistingUsers < ActiveRecord::Migration[5.2] # on the to-be-changed default User.where(User.arel_table[:current_sign_in_at].gteq(1.month.ago)).find_each do |user| - next if Setting.unscoped.where(thing_type: 'User', thing_id: user.id, var: 'advanced_layout').exists? + next if Setting.unscoped.exists?(thing_type: 'User', thing_id: user.id, var: 'advanced_layout') user.settings.advanced_layout = true end diff --git a/db/post_migrate/20220704024901_migrate_settings_to_user_roles.rb b/db/post_migrate/20220704024901_migrate_settings_to_user_roles.rb index 254690cc3a..00afee26d0 100644 --- a/db/post_migrate/20220704024901_migrate_settings_to_user_roles.rb +++ b/db/post_migrate/20220704024901_migrate_settings_to_user_roles.rb @@ -6,36 +6,55 @@ class MigrateSettingsToUserRoles < ActiveRecord::Migration[6.1] class UserRole < ApplicationRecord; end def up - owner_role = UserRole.find_by(name: 'Owner') - admin_role = UserRole.find_by(name: 'Admin') - moderator_role = UserRole.find_by(name: 'Moderator') - everyone_role = UserRole.find_by(id: -99) - - min_invite_role = Setting.min_invite_role - show_staff_badge = Setting.show_staff_badge - - if everyone_role - everyone_role.permissions &= ~::UserRole::FLAGS[:invite_users] unless min_invite_role == 'user' - everyone_role.save - end - - if owner_role - owner_role.highlighted = show_staff_badge - owner_role.save - end - - if admin_role - admin_role.permissions |= ::UserRole::FLAGS[:invite_users] if %w(admin moderator).include?(min_invite_role) - admin_role.highlighted = show_staff_badge - admin_role.save - end - - if moderator_role - moderator_role.permissions |= ::UserRole::FLAGS[:invite_users] if %w(moderator).include?(min_invite_role) - moderator_role.highlighted = show_staff_badge - moderator_role.save - end + process_role_everyone + process_role_owner + process_role_admin + process_role_moderator end def down; end + + private + + def process_role_everyone + everyone_role = UserRole.find_by(id: -99) + return unless everyone_role + + everyone_role.permissions &= ~::UserRole::FLAGS[:invite_users] unless min_invite_role == 'user' + everyone_role.save + end + + def process_role_owner + owner_role = UserRole.find_by(name: 'Owner') + return unless owner_role + + owner_role.highlighted = show_staff_badge + owner_role.save + end + + def process_role_admin + admin_role = UserRole.find_by(name: 'Admin') + return unless admin_role + + admin_role.permissions |= ::UserRole::FLAGS[:invite_users] if %w(admin moderator).include?(min_invite_role) + admin_role.highlighted = show_staff_badge + admin_role.save + end + + def process_role_moderator + moderator_role = UserRole.find_by(name: 'Moderator') + return unless moderator_role + + moderator_role.permissions |= ::UserRole::FLAGS[:invite_users] if %w(moderator).include?(min_invite_role) + moderator_role.highlighted = show_staff_badge + moderator_role.save + end + + def min_invite_role + Setting.min_invite_role + end + + def show_staff_badge + Setting.show_staff_badge + end end From 964a0ecf37c46bafba3e33aceacc9f80c78d9779 Mon Sep 17 00:00:00 2001 From: Matt Jankowski Date: Thu, 4 Jan 2024 11:55:00 -0500 Subject: [PATCH 15/61] Add sleep statement to nudge thread scheduler in request pool spec (#28596) --- spec/lib/request_pool_spec.rb | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/spec/lib/request_pool_spec.rb b/spec/lib/request_pool_spec.rb index f179e6ca94..bdb0859d76 100644 --- a/spec/lib/request_pool_spec.rb +++ b/spec/lib/request_pool_spec.rb @@ -33,11 +33,13 @@ describe RequestPool do subject - threads = Array.new(20) do |_i| + threads = Array.new(3) do Thread.new do - 20.times do + 2.times do subject.with('http://example.com') do |http_client| http_client.get('/').flush + # Nudge scheduler to yield and exercise the full pool + sleep(0) end end end From 5f4643b895191ecc8ad8136008e0a0b33f88851c Mon Sep 17 00:00:00 2001 From: Claire Date: Fri, 5 Jan 2024 11:45:36 +0100 Subject: [PATCH 16/61] Add `PAPERCLIP_ROOT_URL` to Content-Security-Policy when used (#28561) --- app/lib/content_security_policy.rb | 11 ++++++++++- spec/lib/content_security_policy_spec.rb | 12 ++++++++++++ 2 files changed, 22 insertions(+), 1 deletion(-) diff --git a/app/lib/content_security_policy.rb b/app/lib/content_security_policy.rb index 966e41f03b..210f37cea0 100644 --- a/app/lib/content_security_policy.rb +++ b/app/lib/content_security_policy.rb @@ -10,7 +10,7 @@ class ContentSecurityPolicy end def media_hosts - [assets_host, cdn_host_value].compact + [assets_host, cdn_host_value, paperclip_root_url].compact end private @@ -23,6 +23,15 @@ class ContentSecurityPolicy s3_alias_host || s3_cloudfront_host || azure_alias_host || s3_hostname_host end + def paperclip_root_url + root_url = ENV.fetch('PAPERCLIP_ROOT_URL', nil) + return if root_url.blank? + + (Addressable::URI.parse(assets_host) + root_url).tap do |uri| + uri.path += '/' unless uri.path.blank? || uri.path.end_with?('/') + end.to_s + end + def url_from_base_host host_to_url(base_host) end diff --git a/spec/lib/content_security_policy_spec.rb b/spec/lib/content_security_policy_spec.rb index 4286f14980..27a3e80257 100644 --- a/spec/lib/content_security_policy_spec.rb +++ b/spec/lib/content_security_policy_spec.rb @@ -125,5 +125,17 @@ describe ContentSecurityPolicy do expect(subject.media_hosts).to contain_exactly(subject.assets_host, 'https://asset-host.s3.example') end end + + context 'when PAPERCLIP_ROOT_URL is configured' do + around do |example| + ClimateControl.modify PAPERCLIP_ROOT_URL: 'https://paperclip-host.example' do + example.run + end + end + + it 'uses the provided URL in the content security policy' do + expect(subject.media_hosts).to contain_exactly(subject.assets_host, 'https://paperclip-host.example') + end + end end end From 9ecf99df149eb75f27562ab8ee8f4022b57604dc Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Fri, 5 Jan 2024 11:45:55 +0100 Subject: [PATCH 17/61] Update dependency net-http to v0.4.1 (#28606) 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 c3f27966d6..d1dfd6e86a 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -467,7 +467,7 @@ GEM multi_json (1.15.0) multipart-post (2.3.0) mutex_m (0.2.0) - net-http (0.4.0) + net-http (0.4.1) uri net-http-persistent (4.0.2) connection_pool (~> 2.2) From 6b63652656f9b1af5b8d1838591c071c5e19880f Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Fri, 5 Jan 2024 11:46:32 +0100 Subject: [PATCH 18/61] Update dependency rubocop-rspec to v2.26.0 (#28595) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- Gemfile.lock | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Gemfile.lock b/Gemfile.lock index d1dfd6e86a..009293167f 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -678,7 +678,7 @@ GEM parser (>= 3.2.1.0) rubocop-capybara (2.20.0) rubocop (~> 1.41) - rubocop-factory_bot (2.24.0) + rubocop-factory_bot (2.25.0) rubocop (~> 1.33) rubocop-performance (1.20.1) rubocop (>= 1.48.1, < 2.0) @@ -688,7 +688,7 @@ GEM rack (>= 1.1) rubocop (>= 1.33.0, < 2.0) rubocop-ast (>= 1.30.0, < 2.0) - rubocop-rspec (2.25.0) + rubocop-rspec (2.26.0) rubocop (~> 1.40) rubocop-capybara (~> 2.17) rubocop-factory_bot (~> 2.22) From d537b3926fda5693d4f08a6ea30684479f5e7668 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Fri, 5 Jan 2024 11:46:38 +0100 Subject: [PATCH 19/61] Update dependency sass-loader to v10.5.2 (#28594) 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 e1c8ab3fb8..8849124e18 100644 --- a/yarn.lock +++ b/yarn.lock @@ -14550,8 +14550,8 @@ __metadata: linkType: hard "sass-loader@npm:^10.2.0": - version: 10.5.1 - resolution: "sass-loader@npm:10.5.1" + version: 10.5.2 + resolution: "sass-loader@npm:10.5.2" dependencies: klona: "npm:^2.0.4" loader-utils: "npm:^2.0.0" @@ -14570,7 +14570,7 @@ __metadata: optional: true sass: optional: true - checksum: 841448d02045b0c65595eab4cb701384b01a2adcb3594beacbb767b0cee5bd9d444027f4fc3a10acef3fe1c7eb6510fccffdee72a20e9877777789a5e349cb49 + checksum: 5ba4a83459fbb50e21d4f4b1b59baf1ddf8dd404099b6d1f2ec887c6903659e505879915030dd9efb1c6dd5fde2d515a19f418487b73d1cc59f6aad60c79bcf5 languageName: node linkType: hard From 9699ea22d6be08d5809c0a05500e6778f96a09a2 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Fri, 5 Jan 2024 11:47:22 +0100 Subject: [PATCH 20/61] Update dependency postcss to v8.4.33 (#28602) 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 8849124e18..70d98332ad 100644 --- a/yarn.lock +++ b/yarn.lock @@ -13145,13 +13145,13 @@ __metadata: linkType: hard "postcss@npm:^8.2.15, postcss@npm:^8.4.24, postcss@npm:^8.4.32": - version: 8.4.32 - resolution: "postcss@npm:8.4.32" + version: 8.4.33 + resolution: "postcss@npm:8.4.33" dependencies: nanoid: "npm:^3.3.7" picocolors: "npm:^1.0.0" source-map-js: "npm:^1.0.2" - checksum: 39308a9195fa34d4dbdd7b58a896cff0c7809f84f7a4ac1b95b68ca86c9138a395addff33075668ed3983d41b90aac05754c445237a9365eb1c3a5602ebd03ad + checksum: 16eda83458fcd8a91bece287b5920c7f57164c3ea293e6c80d0ea71ce7843007bcd8592260a5160b9a7f02693e6ac93e2495b02d8c7596d3f3f72c1447e3ba79 languageName: node linkType: hard From 6ad0fb5a77dcdb12d3bf61617978dcd6e6f6fb20 Mon Sep 17 00:00:00 2001 From: Claire Date: Fri, 5 Jan 2024 12:07:57 +0100 Subject: [PATCH 21/61] Fix NULL MX handling and tighten DNS resolving specs (#28607) --- app/validators/email_mx_validator.rb | 1 + .../admin/email_domain_blocks_controller_spec.rb | 10 ++++++++++ spec/rails_helper.rb | 4 ++++ spec/validators/email_mx_validator_spec.rb | 2 +- 4 files changed, 16 insertions(+), 1 deletion(-) diff --git a/app/validators/email_mx_validator.rb b/app/validators/email_mx_validator.rb index a30a0c820d..7943778943 100644 --- a/app/validators/email_mx_validator.rb +++ b/app/validators/email_mx_validator.rb @@ -47,6 +47,7 @@ class EmailMxValidator < ActiveModel::Validator dns.timeouts = 5 records = dns.getresources(domain, Resolv::DNS::Resource::IN::MX).to_a.map { |e| e.exchange.to_s } + next if records == [''] # This domain explicitly rejects emails ([domain] + records).uniq.each do |hostname| ips.concat(dns.getresources(hostname, Resolv::DNS::Resource::IN::A).to_a.map { |e| e.address.to_s }) diff --git a/spec/controllers/admin/email_domain_blocks_controller_spec.rb b/spec/controllers/admin/email_domain_blocks_controller_spec.rb index 9379fe374a..4de3ef0f62 100644 --- a/spec/controllers/admin/email_domain_blocks_controller_spec.rb +++ b/spec/controllers/admin/email_domain_blocks_controller_spec.rb @@ -35,6 +35,16 @@ RSpec.describe Admin::EmailDomainBlocksController do describe 'POST #create' do context 'when resolve button is pressed' do before do + resolver = instance_double(Resolv::DNS) + + allow(resolver).to receive(:getresources) + .with('example.com', Resolv::DNS::Resource::IN::MX) + .and_return([]) + allow(resolver).to receive(:getresources).with('example.com', Resolv::DNS::Resource::IN::A).and_return([]) + allow(resolver).to receive(:getresources).with('example.com', Resolv::DNS::Resource::IN::AAAA).and_return([]) + allow(resolver).to receive(:timeouts=).and_return(nil) + allow(Resolv::DNS).to receive(:open).and_yield(resolver) + post :create, params: { email_domain_block: { domain: 'example.com' } } end diff --git a/spec/rails_helper.rb b/spec/rails_helper.rb index c9352a4d5d..e5d432b45f 100644 --- a/spec/rails_helper.rb +++ b/spec/rails_helper.rb @@ -128,6 +128,10 @@ RSpec.configure do |config| self.use_transactional_tests = true end + config.before do |example| + allow(Resolv::DNS).to receive(:open).and_raise('Real DNS queries are disabled, stub Resolv::DNS as needed') unless example.metadata[:type] == :system + end + config.before do |example| unless example.metadata[:paperclip_processing] allow_any_instance_of(Paperclip::Attachment).to receive(:post_process).and_return(true) # rubocop:disable RSpec/AnyInstance diff --git a/spec/validators/email_mx_validator_spec.rb b/spec/validators/email_mx_validator_spec.rb index 876d73c184..21b1ad0a11 100644 --- a/spec/validators/email_mx_validator_spec.rb +++ b/spec/validators/email_mx_validator_spec.rb @@ -111,7 +111,7 @@ describe EmailMxValidator do allow(resolver).to receive(:getresources).with('example.com', Resolv::DNS::Resource::IN::A).and_return([]) allow(resolver).to receive(:getresources).with('example.com', Resolv::DNS::Resource::IN::AAAA).and_return([]) allow(resolver).to receive(:getresources).with('mail.example.com', Resolv::DNS::Resource::IN::A).and_return([instance_double(Resolv::DNS::Resource::IN::A, address: '2.3.4.5')]) - allow(resolver).to receive(:getresources).with('mail.example.com', Resolv::DNS::Resource::IN::AAAA).and_return([instance_double(Resolv::DNS::Resource::IN::A, address: 'fd00::2')]) + allow(resolver).to receive(:getresources).with('mail.example.com', Resolv::DNS::Resource::IN::AAAA).and_return([instance_double(Resolv::DNS::Resource::IN::AAAA, address: 'fd00::2')]) allow(resolver).to receive(:timeouts=).and_return(nil) allow(Resolv::DNS).to receive(:open).and_yield(resolver) From 43d800ada64478e3a9119ca9313b47018b811243 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Fri, 5 Jan 2024 12:29:19 +0100 Subject: [PATCH 22/61] New Crowdin Translations (automated) (#28604) Co-authored-by: GitHub Actions --- app/javascript/mastodon/locales/el.json | 11 +++++ app/javascript/mastodon/locales/ia.json | 16 +++++++ app/javascript/mastodon/locales/sq.json | 2 + app/javascript/mastodon/locales/zh-CN.json | 6 +-- config/locales/activerecord.ia.yml | 1 + config/locales/activerecord.ie.yml | 2 + config/locales/be.yml | 1 + config/locales/ca.yml | 1 + config/locales/cy.yml | 1 + config/locales/da.yml | 1 + config/locales/devise.el.yml | 2 +- config/locales/devise.ia.yml | 24 ++++++++++ config/locales/devise.ie.yml | 5 ++ config/locales/doorkeeper.el.yml | 10 ++-- config/locales/doorkeeper.ia.yml | 54 ++++++++++++++++++++++ config/locales/doorkeeper.ie.yml | 9 ++++ config/locales/el.yml | 9 +++- config/locales/es-AR.yml | 1 + config/locales/es-MX.yml | 1 + config/locales/es.yml | 1 + config/locales/eu.yml | 1 + config/locales/fo.yml | 1 + config/locales/fy.yml | 1 + config/locales/gl.yml | 1 + config/locales/he.yml | 1 + config/locales/hu.yml | 1 + config/locales/ia.yml | 23 +++++++++ config/locales/ie.yml | 26 +++++++++++ config/locales/it.yml | 1 + config/locales/ko.yml | 1 + config/locales/lt.yml | 1 + config/locales/nl.yml | 1 + config/locales/nn.yml | 1 + config/locales/no.yml | 1 + config/locales/pl.yml | 1 + config/locales/pt-BR.yml | 1 + config/locales/pt-PT.yml | 1 + config/locales/simple_form.ia.yml | 45 ++++++++++++++++++ config/locales/simple_form.ie.yml | 39 ++++++++++++++++ config/locales/simple_form.sk.yml | 2 + config/locales/sk.yml | 1 + config/locales/sl.yml | 1 + config/locales/sq.yml | 1 + config/locales/sr-Latn.yml | 1 + config/locales/sr.yml | 1 + config/locales/th.yml | 1 + config/locales/tr.yml | 1 + config/locales/uk.yml | 1 + config/locales/vi.yml | 1 + config/locales/zh-CN.yml | 1 + config/locales/zh-HK.yml | 1 + 51 files changed, 309 insertions(+), 10 deletions(-) diff --git a/app/javascript/mastodon/locales/el.json b/app/javascript/mastodon/locales/el.json index 17a0c9d4da..53e55fa950 100644 --- a/app/javascript/mastodon/locales/el.json +++ b/app/javascript/mastodon/locales/el.json @@ -260,6 +260,9 @@ "filter_modal.select_filter.subtitle": "Χρησιμοποιήστε μια υπάρχουσα κατηγορία ή δημιουργήστε μια νέα", "filter_modal.select_filter.title": "Φιλτράρισμα αυτής της ανάρτησης", "filter_modal.title.status": "Φιλτράρισμα μιας ανάρτησης", + "firehose.all": "Όλα", + "firehose.local": "Αυτός ο διακομιστής", + "firehose.remote": "Άλλοι διακομιστές", "follow_request.authorize": "Εξουσιοδότησε", "follow_request.reject": "Απέρριψε", "follow_requests.unlocked_explanation": "Παρόλο που ο λογαριασμός σου δεν είναι κλειδωμένος, το προσωπικό του {domain} θεώρησαν πως ίσως να θέλεις να ελέγξεις χειροκίνητα αυτά τα αιτήματα ακολούθησης.", @@ -285,11 +288,15 @@ "hashtag.column_settings.tag_toggle": "Προσθήκη επιπλέον ταμπελών για την κολώνα", "hashtag.follow": "Παρακολούθηση ετικέτας", "hashtag.unfollow": "Διακοπή παρακολούθησης ετικέτας", + "home.actions.go_to_suggestions": "Βρείτε άτομα για να ακολουθήσετε", "home.column_settings.basic": "Βασικές ρυθμίσεις", "home.column_settings.show_reblogs": "Εμφάνιση προωθήσεων", "home.column_settings.show_replies": "Εμφάνιση απαντήσεων", "home.explore_prompt.body": "Your home feed will have a mix of posts from the hashtags you've chosen to follow, the people you've chosen to follow, and the posts they boost. If that feels too quiet, you may want to:\nΗ τροφοδοσία της αρχικής σελίδας σας είναι ένα μίγμα από αναρτήσεις με τις ετικέτες και τα άτομα που επιλέξατε να ακολουθείτε, και τις αναρτήσεις που προωθούν. Εάν αυτό σας φαίνεται πολύ ήσυχο, μπορεί να θέλετε:", + "home.explore_prompt.title": "Αυτό είναι το σπίτι σας στο Mastodon.", "home.hide_announcements": "Απόκρυψη ανακοινώσεων", + "home.pending_critical_update.link": "Δείτε ενημερώσεις", + "home.pending_critical_update.title": "Κρίσιμη ενημέρωση ασφαλείας διαθέσιμη!", "home.show_announcements": "Εμφάνιση ανακοινώσεων", "interaction_modal.description.follow": "Με έναν λογαριασμό Mastodon, μπορείς να ακολουθήσεις τον/την {name} ώστε να λαμβάνεις τις αναρτήσεις του/της στη δική σου ροή.", "interaction_modal.description.reblog": "Με ένα λογαριασμό Mastodon, μπορείς να ενισχύσεις αυτή την ανάρτηση για να τη μοιραστείς με τους δικούς σου ακολούθους.", @@ -314,6 +321,7 @@ "keyboard_shortcuts.direct": "για το άνοιγμα της στήλης ιδιωτικών επισημάνσεων", "keyboard_shortcuts.down": "κίνηση προς τα κάτω στη λίστα", "keyboard_shortcuts.enter": "Εμφάνιση ανάρτησης", + "keyboard_shortcuts.favourite": "Αγαπημένη δημοσίευση", "keyboard_shortcuts.federated": "Άνοιγμα ροής συναλλαγών", "keyboard_shortcuts.heading": "Συντομεύσεις πληκτρολογίου", "keyboard_shortcuts.home": "Άνοιγμα ροής αρχικής σελίδας", @@ -358,6 +366,7 @@ "lists.search": "Αναζήτησε μεταξύ των ανθρώπων που ακουλουθείς", "lists.subheading": "Οι λίστες σου", "load_pending": "{count, plural, one {# νέο στοιχείο} other {# νέα στοιχεία}}", + "loading_indicator.label": "Φόρτωση…", "media_gallery.toggle_visible": "{number, plural, one {Απόκρυψη εικόνας} other {Απόκρυψη εικόνων}}", "moved_to_account_banner.text": "Ο λογαριασμός σου {disabledAccount} είναι προσωρινά απενεργοποιημένος επειδή μεταφέρθηκες στον {movedToAccount}.", "mute_modal.duration": "Διάρκεια", @@ -380,6 +389,7 @@ "navigation_bar.lists": "Λίστες", "navigation_bar.logout": "Αποσύνδεση", "navigation_bar.mutes": "Αποσιωπημένοι χρήστες", + "navigation_bar.opened_in_classic_interface": "Δημοσιεύσεις, λογαριασμοί και άλλες συγκεκριμένες σελίδες ανοίγονται από προεπιλογή στην κλασική διεπαφή ιστού.", "navigation_bar.personal": "Προσωπικά", "navigation_bar.pins": "Καρφιτσωμένες αναρτήσεις", "navigation_bar.preferences": "Προτιμήσεις", @@ -403,6 +413,7 @@ "notifications.column_settings.admin.report": "Νέες αναφορές:", "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.filter_bar.show_bar": "Εμφάνιση μπάρας φίλτρου", diff --git a/app/javascript/mastodon/locales/ia.json b/app/javascript/mastodon/locales/ia.json index 9781d6aa77..00cafe260b 100644 --- a/app/javascript/mastodon/locales/ia.json +++ b/app/javascript/mastodon/locales/ia.json @@ -1,4 +1,8 @@ { + "about.blocks": "Servitores moderate", + "about.contact": "Contacto:", + "about.disclaimer": "Mastodon es software libere, de codice aperte, e un marca de Mastodon gGmbH.", + "account.account_note_header": "Nota", "account.add_or_remove_from_list": "Adder o remover ab listas", "account.badges.group": "Gruppo", "account.block": "Blocar @{name}", @@ -21,9 +25,12 @@ "bundle_column_error.return": "Retornar al initio", "bundle_modal_error.close": "Clauder", "bundle_modal_error.retry": "Tentar novemente", + "column.about": "A proposito de", "column.blocks": "Usatores blocate", + "column.bookmarks": "Marcapaginas", "column.directory": "Navigar profilos", "column.favourites": "Favoritos", + "column.firehose": "Fluxos in directe", "column.home": "Initio", "column.lists": "Listas", "column.notifications": "Notificationes", @@ -33,6 +40,7 @@ "compose.language.change": "Cambiar le lingua", "compose.language.search": "Cercar linguas...", "compose.published.open": "Aperir", + "compose_form.direct_message_warning_learn_more": "Apprender plus", "compose_form.poll.add_option": "Adder un option", "compose_form.poll.remove_option": "Remover iste option", "confirmation_modal.cancel": "Cancellar", @@ -41,6 +49,7 @@ "confirmations.edit.confirm": "Modificar", "confirmations.logout.confirm": "Clauder le session", "copy_icon_button.copied": "Copiate al area de transferentia", + "copypaste.copied": "Copiate", "copypaste.copy_to_clipboard": "Copiar al area de transferentia", "disabled_account_banner.account_settings": "Parametros de conto", "dismissable_banner.dismiss": "Dimitter", @@ -52,6 +61,7 @@ "errors.unexpected_crash.report_issue": "Signalar un defecto", "explore.search_results": "Resultatos de recerca", "explore.trending_links": "Novas", + "filter_modal.select_filter.prompt_new": "Nove categoria: {name}", "firehose.all": "Toto", "firehose.local": "Iste servitor", "firehose.remote": "Altere servitores", @@ -64,8 +74,13 @@ "keyboard_shortcuts.my_profile": "Aperir tu profilo", "lightbox.close": "Clauder", "lightbox.next": "Sequente", + "lightbox.previous": "Precedente", "link_preview.author": "Per {name}", "lists.account.add": "Adder al lista", + "lists.delete": "Deler lista", + "lists.edit": "Modificar lista", + "lists.new.create": "Adder lista", + "lists.subheading": "Tu listas", "mute_modal.duration": "Duration", "mute_modal.hide_notifications": "Celar notificationes de iste usator?", "navigation_bar.about": "A proposito de", @@ -83,6 +98,7 @@ "notifications.column_settings.filter_bar.advanced": "Monstrar tote le categorias", "notifications.column_settings.sound": "Reproducer sono", "notifications.filter.all": "Toto", + "notifications.filter.favourites": "Favoritos", "notifications.grant_permission": "Conceder permission.", "notifications.group": "{count} notificationes", "onboarding.compose.template": "Salute #Mastodon!", diff --git a/app/javascript/mastodon/locales/sq.json b/app/javascript/mastodon/locales/sq.json index 48eac1487e..f45266c845 100644 --- a/app/javascript/mastodon/locales/sq.json +++ b/app/javascript/mastodon/locales/sq.json @@ -32,6 +32,7 @@ "account.featured_tags.last_status_never": "Pa postime", "account.featured_tags.title": "Hashtagë të zgjedhur të {name}", "account.follow": "Ndiqeni", + "account.follow_back": "Ndiqe gjithashtu", "account.followers": "Ndjekës", "account.followers.empty": "Këtë përdorues ende s’e ndjek kush.", "account.followers_counter": "{count, plural, one {{counter} Ndjekës} other {{counter} Ndjekës}}", @@ -52,6 +53,7 @@ "account.mute_notifications_short": "Mos shfaq njoftime", "account.mute_short": "Mos i shfaq", "account.muted": "Heshtuar", + "account.mutual": "Reciproke", "account.no_bio": "S’u dha përshkrim.", "account.open_original_page": "Hap faqen origjinale", "account.posts": "Mesazhe", diff --git a/app/javascript/mastodon/locales/zh-CN.json b/app/javascript/mastodon/locales/zh-CN.json index 575e0c7aeb..720e4331b3 100644 --- a/app/javascript/mastodon/locales/zh-CN.json +++ b/app/javascript/mastodon/locales/zh-CN.json @@ -53,7 +53,7 @@ "account.mute_notifications_short": "关闭通知", "account.mute_short": "隐藏", "account.muted": "已隐藏", - "account.mutual": "互相关注", + "account.mutual": "互粉好友", "account.no_bio": "未提供描述。", "account.open_original_page": "打开原始页面", "account.posts": "嘟文", @@ -446,7 +446,7 @@ "notifications.column_settings.filter_bar.advanced": "显示所有类别", "notifications.column_settings.filter_bar.category": "快速过滤栏", "notifications.column_settings.filter_bar.show_bar": "显示过滤栏", - "notifications.column_settings.follow": "新关注者:", + "notifications.column_settings.follow": "新粉丝:", "notifications.column_settings.follow_request": "新关注请求:", "notifications.column_settings.mention": "提及:", "notifications.column_settings.poll": "投票结果:", @@ -700,7 +700,7 @@ "time_remaining.moments": "即将结束", "time_remaining.seconds": "剩余 {number, plural, one {# 秒} other {# 秒}}", "timeline_hint.remote_resource_not_displayed": "不会显示来自其它服务器的{resource}", - "timeline_hint.resources.followers": "关注者", + "timeline_hint.resources.followers": "粉丝", "timeline_hint.resources.follows": "关注", "timeline_hint.resources.statuses": "更早的嘟文", "trends.counter_by_accounts": "过去 {days, plural, other {{days} 天}}有{count, plural, other { {counter} 人}}讨论", diff --git a/config/locales/activerecord.ia.yml b/config/locales/activerecord.ia.yml index 480fd56f63..7d1e7d7190 100644 --- a/config/locales/activerecord.ia.yml +++ b/config/locales/activerecord.ia.yml @@ -3,6 +3,7 @@ ia: activerecord: attributes: user: + email: Adresse de e-mail password: Contrasigno user/account: username: Nomine de usator diff --git a/config/locales/activerecord.ie.yml b/config/locales/activerecord.ie.yml index 588105ae96..0b22dd886c 100644 --- a/config/locales/activerecord.ie.yml +++ b/config/locales/activerecord.ie.yml @@ -19,6 +19,7 @@ ie: account: attributes: username: + invalid: deve contener solmen lítteres, númeres e sublineas reserved: es reservat admin/webhook: attributes: @@ -39,6 +40,7 @@ ie: user: attributes: email: + blocked: usa un ne-permisset provisor de e-posta unreachable: sembla ne exister role_id: elevated: ne posse esser plu alt quam tui actual rol diff --git a/config/locales/be.yml b/config/locales/be.yml index d8703b7992..ca9b0d2b88 100644 --- a/config/locales/be.yml +++ b/config/locales/be.yml @@ -439,6 +439,7 @@ be: view: Праглядзець новы блок дамену email_domain_blocks: add_new: Дадаць + allow_registrations_with_approval: Дазволіць рэгістрацыю з дазволам attempts_over_week: few: "%{count} спробы рэгіістрацыі за апошні тыдзень" many: "%{count} спроб рэгіістрацыі за апошні тыдзень" diff --git a/config/locales/ca.yml b/config/locales/ca.yml index 0d7605f023..25f19ef25f 100644 --- a/config/locales/ca.yml +++ b/config/locales/ca.yml @@ -425,6 +425,7 @@ ca: view: Veure el bloqueig del domini email_domain_blocks: add_new: Afegir nou + allow_registrations_with_approval: Registre permès amb validació attempts_over_week: one: "%{count} intent en la darrera setmana" other: "%{count} intents de registre en la darrera setmana" diff --git a/config/locales/cy.yml b/config/locales/cy.yml index 9dd533b2ad..70b994903e 100644 --- a/config/locales/cy.yml +++ b/config/locales/cy.yml @@ -453,6 +453,7 @@ cy: view: Gweld bloc parth email_domain_blocks: add_new: Ychwanegu + allow_registrations_with_approval: Caniatáu cofrestriadau wedi'u cymeradwyo attempts_over_week: few: "%{count} ymgais i gofrestru dros yr wythnos ddiwethaf" many: "%{count} ymgais i gofrestru dros yr wythnos ddiwethaf" diff --git a/config/locales/da.yml b/config/locales/da.yml index 6403ac1ccb..3d6850ca5e 100644 --- a/config/locales/da.yml +++ b/config/locales/da.yml @@ -425,6 +425,7 @@ da: view: Vis domæneblokering email_domain_blocks: add_new: Tilføj ny + allow_registrations_with_approval: Tillad registreringer med godkendelse attempts_over_week: one: "%{count} tilmeldingsforsøg over den seneste uge" other: "%{count} tilmeldingsforsøg over den seneste uge" diff --git a/config/locales/devise.el.yml b/config/locales/devise.el.yml index ba3ee59fab..13daa4b97a 100644 --- a/config/locales/devise.el.yml +++ b/config/locales/devise.el.yml @@ -34,7 +34,7 @@ el: explanation: Το συνθηματικό του λογαριασμού σου άλλαξε. extra: Αν δεν άλλαξες εσύ το συνθηματικό σου, ίσως κάποιος να έχει αποκτήσει πρόσβαση στο λογαριασμό σου. Παρακαλούμε άλλαξε το συνθηματικό σου άμεσα ή επικοινώνησε με τον διαχειριστή του κόμβου σου αν έχεις κλειδωθεί απ' έξω. subject: 'Mastodon: Αλλαγή συνθηματικού' - title: Αλλαγή συνθηματικού + title: Ο κωδικός άλλαξε reconfirmation_instructions: explanation: Επιβεβαίωσε τη νέα διεύθυνση για να αλλάξεις το email σου. extra: Αν δεν ζήτησες εσύ αυτή την αλλαγή, παρακαλούμε αγνόησε αυτό το email. Η διεύθυνση email για τον λογαριασμό σου στο Mastodon δεν θα αλλάξει μέχρι να επισκεφτείς τον παραπάνω σύνδεσμο. diff --git a/config/locales/devise.ia.yml b/config/locales/devise.ia.yml index 6ab26788bd..7b0ec29579 100644 --- a/config/locales/devise.ia.yml +++ b/config/locales/devise.ia.yml @@ -1 +1,25 @@ +--- ia: + devise: + mailer: + confirmation_instructions: + action: Verificar adresse de e-mail + action_with_app: Confirmar e retornar a %{app} + title: Verificar adresse de e-mail + email_changed: + title: Nove adresse de e-mail + reconfirmation_instructions: + title: Verificar adresse de e-mail + reset_password_instructions: + action: Cambiar contrasigno + title: Reinitialisar contrasigno + two_factor_disabled: + title: 2FA disactivate + registrations: + updated: Tu conto ha essite actualisate con successo. + unlocks: + unlocked: Tu conto ha essite disblocate con successo. Initia session a continuar. + errors: + messages: + already_confirmed: jam esseva confirmate, tenta initiar session + not_found: non trovate diff --git a/config/locales/devise.ie.yml b/config/locales/devise.ie.yml index 687e7115a6..c6468d34c2 100644 --- a/config/locales/devise.ie.yml +++ b/config/locales/devise.ie.yml @@ -56,6 +56,8 @@ ie: added: subject: 'Mastodon: Nov clave de securitá' title: Un nov clave de securitá ha esset adjuntet + deleted: + subject: 'Mastodon: Clave de securitá deletet' webauthn_disabled: subject: 'Mastodon: Autentication con claves de securitá desactivisat' title: Claves de securitá desactivisat @@ -84,3 +86,6 @@ ie: expired: ha expirat, ples demandar un nov not_found: ne trovat not_locked: ne esset serrat + not_saved: + one: '1 error prohibit ti %{resource} de esser conservat:' + other: "%{count} errores prohibit ti %{resource} de esser conservat:" diff --git a/config/locales/doorkeeper.el.yml b/config/locales/doorkeeper.el.yml index b275af3365..1cb9b3513b 100644 --- a/config/locales/doorkeeper.el.yml +++ b/config/locales/doorkeeper.el.yml @@ -127,6 +127,7 @@ el: bookmarks: Σελιδοδείκτες conversations: Συνομιλίες crypto: Κρυπτογράφηση από άκρο σε άκρο + favourites: Αγαπημένα filters: Φίλτρα follow: Ακολουθείτε, σε Σίγαση και Αποκλεισμοί follows: Ακολουθείτε @@ -169,9 +170,10 @@ el: read:accounts: να βλέπει τα στοιχεία λογαριασμών read:blocks: να βλέπει τους αποκλεισμένους σου read:bookmarks: εμφάνιση των σελιδοδεικτών σας + read:favourites: δείτε τα αγαπημένα σας read:filters: να βλέπει τα φίλτρα σου - read:follows: να βλέπει ποιους ακολουθείς - read:lists: να βλέπει τις λίστες σου + read:follows: δές ποιους ακολουθείς + read:lists: δές τις λίστες σου read:mutes: να βλέπει ποιους αποσιωπείς read:notifications: να βλέπει τις ειδοποιήσεις σου read:reports: να βλέπει τις καταγγελίες σου @@ -183,8 +185,8 @@ el: write:bookmarks: προσθήκη σελιδοδεικτών write:conversations: σίγαση και διαγραφή συνομιλιών write:filters: να δημιουργεί φίλτρα - write:follows: να ακολουθεί ανθρώπους - write:lists: να δημιουργεί λίστες + write:follows: ακολουθήστε ανθρώπους + write:lists: δημιουργία λιστών write:media: να ανεβάζει πολυμέσα write:mutes: να αποσιωπεί ανθρώπους και συζητήσεις write:notifications: να καθαρίζει τις ειδοποιήσεις σου diff --git a/config/locales/doorkeeper.ia.yml b/config/locales/doorkeeper.ia.yml index 6ab26788bd..55f28634a5 100644 --- a/config/locales/doorkeeper.ia.yml +++ b/config/locales/doorkeeper.ia.yml @@ -1 +1,55 @@ +--- ia: + activerecord: + attributes: + doorkeeper/application: + name: Nomine de application + website: Sito web de application + doorkeeper: + applications: + buttons: + cancel: Cancellar + edit: Modificar + edit: + title: Modificar application + index: + application: Application + delete: Deler + name: Nomine + new: Nove application + show: Monstrar + title: Tu applicationes + new: + title: Nove application + show: + actions: Actiones + title: 'Application: %{name}' + authorizations: + error: + title: Ocurreva un error + authorized_applications: + confirmations: + revoke: Es tu secur? + index: + scopes: Permissiones + title: Tu applicationes autorisate + flash: + applications: + create: + notice: Application create. + destroy: + notice: Application delite. + update: + notice: Application actualisate. + grouped_scopes: + title: + accounts: Contos + admin/accounts: Gestion de contos + favourites: Favoritos + lists: Listas + notifications: Notificationes + push: Notificationes push + layouts: + admin: + nav: + applications: Applicationes diff --git a/config/locales/doorkeeper.ie.yml b/config/locales/doorkeeper.ie.yml index b778871e3a..f49eb1d968 100644 --- a/config/locales/doorkeeper.ie.yml +++ b/config/locales/doorkeeper.ie.yml @@ -5,6 +5,7 @@ ie: doorkeeper/application: name: Nómine de aplication redirect_uri: URI de redirection + scopes: Scopes website: Situ web de aplication errors: models: @@ -29,6 +30,7 @@ ie: title: Modificar aplication help: redirect_uri: Usar un linea per URI + scopes: Separar scopes con intersticies. Lassar blanc por usar li scopes predefinit. index: application: Aplication callback_url: URL de retrovocada @@ -36,6 +38,7 @@ ie: empty: Tu have null aplicationes. name: Nómine new: Nov aplication + scopes: Scopes show: Monstrar title: Tui aplicationes new: @@ -44,6 +47,7 @@ ie: actions: Actiones application_id: Clave de client callback_urls: URLs de retrovocada + scopes: Scopes secret: Secrete de client title: 'Aplication: %{name}' authorizations: @@ -120,9 +124,13 @@ ie: admin: nav: applications: Aplicationes + oauth2_provider: Provisor OAuth2 + application: + title: Autorisation OAuth besonat scopes: admin:read: leer li tot data sur li servitor admin:read:accounts: leer sensitiv information de omni contos + admin:read:canonical_email_blocks: leer sensitiv information pri omni canonic bloccas de e-posta admin:read:domain_allows: leer sensitiv information pri omni permisses de dominia admin:read:domain_blocks: leer sensitiv information pri omni bloccas de dominia admin:read:email_domain_blocks: leer sensitiv information pri omni bloccas de dominia basat sur e-posta @@ -137,6 +145,7 @@ ie: admin:write:ip_blocks: fa moderatori actiones sur bloccas de IP admin:write:reports: far moderatori actiones sur raportes follow: modifica li relationes del conto + push: reciver tui pussa-notificationes read: lee omni datas de tui conto read:accounts: vide li informationes pri li conto read:blocks: vider tui bloccas diff --git a/config/locales/el.yml b/config/locales/el.yml index 4c58bfda0a..4c31bfdde0 100644 --- a/config/locales/el.yml +++ b/config/locales/el.yml @@ -962,6 +962,7 @@ el: notification_preferences: Αλλαγή προτιμήσεων email salutation: "%{name}," settings: 'Άλλαξε τις προτιμήσεις email: %{link}' + unsubscribe: Κατάργηση εγγραφής view: 'Προβολή:' view_profile: Προβολή προφίλ view_status: Προβολή ανάρτησης @@ -975,6 +976,8 @@ el: your_token: Το διακριτικό πρόσβασής σου auth: apply_for_account: Ζήτα έναν λογαριασμό + captcha_confirmation: + title: Ελεγχος ασφαλείας confirmations: wrong_email_hint: Εάν αυτή η διεύθυνση email δεν είναι σωστή, μπορείς να την αλλάξεις στις ρυθμίσεις λογαριασμού. delete_account: Διαγραφή λογαριασμού @@ -1238,6 +1241,8 @@ el: status: Κατάσταση success: Τα δεδομένα σου μεταφορτώθηκαν επιτυχώς και θα επεξεργαστούν σύντομα time_started: Ξεκίνησε στις + titles: + following: Εισαγωγή λογαριασμών που ακολουθείτε type: Τύπος εισαγωγής type_groups: destructive: Μπλοκ & σίγαση @@ -1245,7 +1250,7 @@ el: blocking: Λίστα αποκλεισμού bookmarks: Σελιδοδείκτες domain_blocking: Λίστα αποκλεισμένων τομέων - following: Λίστα ακολούθων + following: Λίστα ατόμων που ακολουθείτε muting: Λίστα αποσιωπήσεων upload: Μεταμόρφωση invites: @@ -1420,7 +1425,7 @@ el: follow_failure: Δεν ήταν δυνατή η παρακολούθηση ορισμένων από τους επιλεγμένους λογαριασμούς. follow_selected_followers: Ακολούθησε τους επιλεγμένους ακόλουθους followers: Ακόλουθοι - following: Ακολουθείς + following: Ακολουθείτε invited: Προσκεκλημένοι last_active: Τελευταία ενεργός most_recent: Πιο πρόσφατος diff --git a/config/locales/es-AR.yml b/config/locales/es-AR.yml index 0000c297ad..f214c92d2a 100644 --- a/config/locales/es-AR.yml +++ b/config/locales/es-AR.yml @@ -425,6 +425,7 @@ es-AR: view: Ver bloqueo de dominio email_domain_blocks: add_new: Agregar nuevo + allow_registrations_with_approval: Permitir crear cuentas con aprobación attempts_over_week: one: "%{count} intento durante la última semana" other: "%{count} intentos durante la última semana" diff --git a/config/locales/es-MX.yml b/config/locales/es-MX.yml index 424262ca19..7f5b282873 100644 --- a/config/locales/es-MX.yml +++ b/config/locales/es-MX.yml @@ -425,6 +425,7 @@ es-MX: view: Ver dominio bloqueado email_domain_blocks: add_new: Añadir nuevo + allow_registrations_with_approval: Permitir registros con aprobación attempts_over_week: one: "%{count} intentos durante la última semana" other: "%{count} intentos de registro en la última semana" diff --git a/config/locales/es.yml b/config/locales/es.yml index f4a70e5e57..a1e9401f5a 100644 --- a/config/locales/es.yml +++ b/config/locales/es.yml @@ -425,6 +425,7 @@ es: view: Ver dominio bloqueado email_domain_blocks: add_new: Añadir nuevo + allow_registrations_with_approval: Permitir registros con aprobación attempts_over_week: one: "%{count} intento durante la última semana" other: "%{count} intentos de registro durante la última semana" diff --git a/config/locales/eu.yml b/config/locales/eu.yml index bcf8540e74..0d253e9b3b 100644 --- a/config/locales/eu.yml +++ b/config/locales/eu.yml @@ -427,6 +427,7 @@ eu: view: Ikusi domeinuaren blokeoa email_domain_blocks: add_new: Gehitu berria + allow_registrations_with_approval: Baimendu izen-emateak onarpen bidez attempts_over_week: one: Izen-emateko saiakera %{count} azken astean other: Izen-emateko %{count} saiakera azken astean diff --git a/config/locales/fo.yml b/config/locales/fo.yml index 726c9607e2..00fb9c5560 100644 --- a/config/locales/fo.yml +++ b/config/locales/fo.yml @@ -425,6 +425,7 @@ fo: view: Vís navnaøkisblokering email_domain_blocks: add_new: Stovna + allow_registrations_with_approval: Loyv skrásetingum við góðkenning attempts_over_week: one: "%{count} roynd seinastu vikuna" other: "%{count} tilmeldingarroyndir seinastu vikuna" diff --git a/config/locales/fy.yml b/config/locales/fy.yml index a08b3a401e..9471c03b92 100644 --- a/config/locales/fy.yml +++ b/config/locales/fy.yml @@ -425,6 +425,7 @@ fy: view: Domeinblokkade besjen email_domain_blocks: add_new: Nije tafoegje + allow_registrations_with_approval: Ynskriuwingen mei tastimming tastean attempts_over_week: one: "%{count} registraasjebesykjen yn de ôfrûne wike" other: "%{count} registraasjebesykjen yn de ôfrûne wike" diff --git a/config/locales/gl.yml b/config/locales/gl.yml index c0e76842f7..cff9427c66 100644 --- a/config/locales/gl.yml +++ b/config/locales/gl.yml @@ -425,6 +425,7 @@ gl: view: Ollar dominios bloqueados email_domain_blocks: add_new: Engadir novo + allow_registrations_with_approval: Permitir crear contas con aprobación attempts_over_week: one: "%{count} intento na última semana" other: "%{count} intentos de conexión na última semana" diff --git a/config/locales/he.yml b/config/locales/he.yml index f2cc882141..23a4e0c3a6 100644 --- a/config/locales/he.yml +++ b/config/locales/he.yml @@ -439,6 +439,7 @@ he: view: צפייה בחסימת דומיינים email_domain_blocks: add_new: הוספת חדש + allow_registrations_with_approval: הרשאת הרשמה לאחר אישור attempts_over_week: many: "%{count} נסיונות הרשמה במשך השבוע שעבר" one: "%{count} נסיון במשך השבוע שעבר" diff --git a/config/locales/hu.yml b/config/locales/hu.yml index 5da1a4e066..5c8d1cf9a4 100644 --- a/config/locales/hu.yml +++ b/config/locales/hu.yml @@ -425,6 +425,7 @@ hu: view: Domain tiltásának megtekintése email_domain_blocks: add_new: Új hozzáadása + allow_registrations_with_approval: Regisztráció engedélyezése jóváhagyással attempts_over_week: one: "%{count} próbálkozás a múlt héten" other: "%{count} próbálkozás feliratkozásra a múlt héten" diff --git a/config/locales/ia.yml b/config/locales/ia.yml index 64315d177f..795ed8cc94 100644 --- a/config/locales/ia.yml +++ b/config/locales/ia.yml @@ -50,3 +50,26 @@ ia: '15778476': 6 menses '2629746': 1 mense '86400': 1 die + statuses_cleanup: + min_age: + '1209600': 2 septimanas + '15778476': 6 menses + '2629746': 1 mense + '31556952': 1 anno + '5259492': 2 menses + '604800': 1 septimana + '63113904': 2 annos + '7889238': 3 menses + themes: + default: Mastodon (Obscur) + mastodon-light: Mastodon (Clar) + two_factor_authentication: + add: Adder + disable: Disactivar 2FA + user_mailer: + appeal_approved: + action: Vader a tu conto + welcome: + subject: Benvenite in Mastodon + webauthn_credentials: + delete: Deler diff --git a/config/locales/ie.yml b/config/locales/ie.yml index 87aa1c41cc..638205a7f4 100644 --- a/config/locales/ie.yml +++ b/config/locales/ie.yml @@ -424,6 +424,7 @@ ie: view: Vider dominia-blocca email_domain_blocks: add_new: Adjunter un nov + allow_registrations_with_approval: Permisser registrationes con aprobation attempts_over_week: one: "%{count} registration-prova durant li ultim semane" other: "%{count} registration-prova durant li ultim semane" @@ -439,6 +440,7 @@ ie: title: Bloccar nov email-dominia no_email_domain_block_selected: Null email-dominia-bloccas esset changeat pro que null esset selectet not_permitted: Ne permisset + resolved_dns_records_hint_html: Li dominia-nómine resolue se al seque dominias MX, queles es in fine responsabil por acceptar e-posta. Bloccar un dominia MX va bloccar inscriptiones de quelcunc e-posta quel usa li sam dominia MX, mem si li visibil dominia-nómine es diferent. Esse caut e ne blocca majori provisores de e-posta. resolved_through_html: Resoluet per %{domain} title: Bloccat email-dominias export_domain_allows: @@ -672,11 +674,13 @@ ie: description_html: Con roles por usatores, tu posse customisar li functiones e locs de Mastodon in queles tui usatores posse accesser. edit: Modificar rol '%{name}' everyone: Permissiones predefinit + everyone_full_description_html: Ti es li fundamental rol quel afecta omni usatores, mem tis sin un assignat rol. Omni altri roles hereda permissiones de it. permissions_count: one: "%{count} permission" other: "%{count} permissiones" privileges: administrator: Administrator + administrator_description: Usatores con ti permission va trapassar omni permission delete_user_data: Deleter Data de Usator delete_user_data_description: Possibilisa que usatores mey deleter li data de altri usatores strax invite_users: Invitar Usatores @@ -726,6 +730,8 @@ ie: settings: about: manage_rules: Gerer regules de servitor + preamble: Provider detalliat information pri qualmen li servitor es operat, moderat, payat. + rules_hint: Hay un dedicat area por regules queles vor usatores es expectat obedir. title: Pri appearance: preamble: Customisar li interfacie web de Mastodon. @@ -736,7 +742,10 @@ ie: desc_html: To ci usa extern scrites de hCaptcha, quel posse esser ínquietant pro rasones de securitá e privatie. In plu, it posse far li processu de registration mult plu desfacil (particularimen por tis con deshabilitás). Pro ti rasones, ples considerar alternativ mesuras, tales quam registration per aprobation o invitation. title: Exige que nov usatores solue un CAPTCHA por confirmar lor conto content_retention: + preamble: Decider qualmen usator-generat contenete es inmagasinat in Mastodon. title: Retention de contenete + default_noindex: + desc_html: Afecta omni usatores qui ne ha changeat ti parametre personalmen discovery: follow_recommendations: Seque-recomandationes preamble: Exposir interessant contenete es importantissim por incorporar nov usatores qui fórsan conosse nequi che Mastodon. Decider qualmen diferent utensiles de decovrition functiona che vor servitor. @@ -771,11 +780,13 @@ ie: critical_update: Critic — ples actualisar rapidmen description: On recomanda que vu actualisa vor Mastodon-servitor regularimen por profiter del max recent fixes e facultates. In plu, quelcvez it es critic actualisar Mastodon promptmen por evitar problemas de securitá. Pro ti rasones, Mastodon questiona chascun 30 minutes ca hay actualisationes, e va notificar vos secun vor parametres pri email-notificationes. documentation_link: Aprender plu + release_notes: Version-notas title: Actualisationes disponibil type: Specie types: major: Majori lansament minor: Minori lansament + patch: Lapp-version — bug-corectiones e changes facil a aplicar version: Version statuses: account: Autor @@ -967,6 +978,7 @@ ie: body: Nov versiones de Mastodon ha esset lansat, vu fórsan vole actualisar! subject: Nov versiones Mastodon es disponibil por %{instance}! new_trends: + body: 'Li sequent elementes besona un revision ante que on posse monstrar les publicmen:' new_trending_links: title: Populari ligamentes new_trending_statuses: @@ -1385,10 +1397,12 @@ ie: media_attachments: validations: images_and_video: On ne posse atachar un video a un posta quel ja contene images + not_ready: Ne posse atachar files ancor sub tractament. Prova denov pos ne long! too_many: Ne posse atachar plu quam 4 files migrations: acct: Translocat a cancel: Anullar redirection + cancel_explanation: Anullar li redirection va reactivisar tui actual conto, ma ne va restaurar sequitores queles ha esset movet a ti-ta conto. cancelled_msg: Anullat redirection con successe. errors: already_moved: es li sam conto a equel tu ha ja translocat @@ -1397,6 +1411,9 @@ ie: not_found: ne posset esser trovat followers_count: Sequitores al témpor de translocation incoming_migrations: Translocant de un conto diferent + incoming_migrations_html: Por mover de un altri conto a ti-ci, erstmen tu deve crear un alias de conto. + moved_msg: Tui conto nu redirecte a %{acct} e tui sequitores es in li processu de esser movet. + not_redirecting: Tui conto redirecte a null altri conto actualmen. on_cooldown: Tu ha recentmen migrat tui conto. Ti function va esser disponibil denov pos %{count} dies. past_migrations: Passat migrationes proceed_with_move: Translocar sequitores @@ -1406,7 +1423,12 @@ ie: warning: backreference_required: Li nov conto deve in prim esser configurat por retroreferentiar ti-ci conto before: 'Ante proceder, ples leer ti notas cuidosimen:' + cooldown: Pos mover se, hay un periode de atendida durant quel tu ne va posser mover te denov + disabled_account: Tui actual conto ne va esser completmen usabil pos to. Támen, tu va posser accesser li exportation de data, e anc reactivisation. + followers: Ti-ci action va mover omni sequitores del actual conto al nov conto + only_redirect_html: Alternativmen, tu posse solmen meter un redirection sur tui profil. other_data: Necun altri data va esser translocat automaticmen + redirect: Li profil de tui actual conto va esser actualisat con un anuncie de redirection e va esser excludet de serchas moderation: title: Moderation move_handler: @@ -1805,6 +1827,7 @@ ie: verification: extra_instructions_html: 'Nota: Li ligament in tui websitu posse esser ínvisibil. Li important parte es rel="me" quel prevente fals self-identification in websitus con contenete generat de usatores. Tu posse mem usar un link element in li cap-section del págine vice a, ma li HTML code deve esser accessibil sin executer JavaScript.' here_is_how: Vide qualmen + hint_html: "Verificar tui identitá che Mastodon es por omnes. Basat sur apert web-criteries, líber nu e sempre. Omno quel tu besona es un websitu personal per quel gente reconosse te. Quande tu fa un ligament a tui websitu de tui profil, on va controlar que li websitu have un ligament reciproc a tui profil e monstrar un visual indicator sur it." instructions_html: Copiar e collar li code ci infra in li HTML de tui web-situ. Poy adjunter li adresse de tui web-situ ad-in un del aditional campes sur tui profil ex li section "Modificar profil" e salvar li changes. verification: Verification verified_links: Tui verificat ligamentes @@ -1815,9 +1838,12 @@ ie: success: Tui clave de securitá esset adjuntet con successe. delete: Deleter delete_confirmation: Vole tu vermen deleter ti-ci clave de securitá? + description_html: Si tu activisa autentication per clave de securitá, aperter session va postular que tu usa un de tui claves de securitá. destroy: + error: Un problema evenit durant li deletion de tui clave de securitá. Ples provar denov. success: Tui clave de securitá esset successosimen deletet. invalid_credential: Ínvalid clave de securitá not_enabled: Tu ancor ne ha possibilisat WebAuthn not_supported: Ti-ci navigator ne subtene claves de securitá + otp_required: Por usar claves de securitá, ples activisar 2-factor autentication. registered_on: Adheret ye %{date} diff --git a/config/locales/it.yml b/config/locales/it.yml index 3637313c0d..16b327f3e1 100644 --- a/config/locales/it.yml +++ b/config/locales/it.yml @@ -425,6 +425,7 @@ it: view: Visualizza blocco di dominio email_domain_blocks: add_new: Aggiungi nuovo + allow_registrations_with_approval: Consenti registrazioni con approvazione attempts_over_week: one: "%{count} tentativo nell'ultima settimana" other: "%{count} tentativi di registrazione nell'ultima settimana" diff --git a/config/locales/ko.yml b/config/locales/ko.yml index e6187f4d83..76bb3bd9f1 100644 --- a/config/locales/ko.yml +++ b/config/locales/ko.yml @@ -420,6 +420,7 @@ ko: view: 도메인 차단 보기 email_domain_blocks: add_new: 새로 추가하기 + allow_registrations_with_approval: 승인을 통한 가입 허용 attempts_over_week: other: 지난 주 동안 %{count}건의 가입 시도가 있었습니다 created_msg: 이메일 도메인 차단 규칙을 생성했습니다 diff --git a/config/locales/lt.yml b/config/locales/lt.yml index b1d8772b6b..b194011a42 100644 --- a/config/locales/lt.yml +++ b/config/locales/lt.yml @@ -169,6 +169,7 @@ lt: undo: Atkurti domeno bloką email_domain_blocks: add_new: Pridėti naują + allow_registrations_with_approval: Leisti registracijas su patvirtinimu created_msg: El pašto domenas sėkmingai pridėtas į juodąjį sąrašą delete: Ištrinti domain: Domenas diff --git a/config/locales/nl.yml b/config/locales/nl.yml index 44843b2198..b2894e4abb 100644 --- a/config/locales/nl.yml +++ b/config/locales/nl.yml @@ -425,6 +425,7 @@ nl: view: Domeinblokkade bekijken email_domain_blocks: add_new: Nieuwe toevoegen + allow_registrations_with_approval: Inschrijvingen met toestemming toestaan attempts_over_week: one: "%{count} registratiepoging tijdens de afgelopen week" other: "%{count} registratiepogingen tijdens de afgelopen week" diff --git a/config/locales/nn.yml b/config/locales/nn.yml index 3ee02863db..70cbc27d6d 100644 --- a/config/locales/nn.yml +++ b/config/locales/nn.yml @@ -425,6 +425,7 @@ nn: view: Vis domeneblokkering email_domain_blocks: add_new: Lag ny + allow_registrations_with_approval: Tillat registreringer med godkjenning attempts_over_week: one: "%{count} forsøk i løpet av den siste uken" other: "%{count} forsøk på å opprette konto i løpet av den siste uken" diff --git a/config/locales/no.yml b/config/locales/no.yml index f791c7151e..54f82550b7 100644 --- a/config/locales/no.yml +++ b/config/locales/no.yml @@ -425,6 +425,7 @@ view: Vis domeneblokkering email_domain_blocks: add_new: Lag ny + allow_registrations_with_approval: Tillat registreringer med godkjenning attempts_over_week: one: "%{count} forsøk i løpet av den siste uken" other: "%{count} forsøk på å opprette konto i løpet av den siste uken" diff --git a/config/locales/pl.yml b/config/locales/pl.yml index 79de3b5196..15aefe5f74 100644 --- a/config/locales/pl.yml +++ b/config/locales/pl.yml @@ -439,6 +439,7 @@ pl: view: Zobacz blokadę domeny email_domain_blocks: add_new: Dodaj nową + allow_registrations_with_approval: Zezwól na rejestracje po zatwierdzeniu attempts_over_week: few: "%{count} próby w ciągu ostatniego tygodnia" many: "%{count} prób w ciągu ostatniego tygodnia" diff --git a/config/locales/pt-BR.yml b/config/locales/pt-BR.yml index c8060ad803..2c485283b1 100644 --- a/config/locales/pt-BR.yml +++ b/config/locales/pt-BR.yml @@ -425,6 +425,7 @@ pt-BR: view: Ver domínios bloqueados email_domain_blocks: add_new: Adicionar novo + allow_registrations_with_approval: Permitir inscrições com aprovação attempts_over_week: one: "%{count} tentativa na última semana" other: "%{count} tentativas de inscrição na última semana" diff --git a/config/locales/pt-PT.yml b/config/locales/pt-PT.yml index 89da6b480e..111f0fa8ee 100644 --- a/config/locales/pt-PT.yml +++ b/config/locales/pt-PT.yml @@ -425,6 +425,7 @@ pt-PT: view: Ver domínios bloqueados email_domain_blocks: add_new: Adicionar novo + allow_registrations_with_approval: Permitir inscrições com aprovação attempts_over_week: one: "%{count} tentativa na última semana" other: "%{count} tentativas de inscrição na última semana" diff --git a/config/locales/simple_form.ia.yml b/config/locales/simple_form.ia.yml index 6ab26788bd..552abb2550 100644 --- a/config/locales/simple_form.ia.yml +++ b/config/locales/simple_form.ia.yml @@ -1 +1,46 @@ +--- ia: + simple_form: + labels: + account: + fields: + name: Etiquetta + value: Contento + admin_account_action: + type: Action + defaults: + avatar: Pictura de profilo + confirm_new_password: Confirmar nove contrasigno + confirm_password: Confirmar contrasigno + current_password: Contrasigno actual + new_password: Nove contrasigno + password: Contrasigno + setting_display_media_default: Predefinite + setting_display_media_hide_all: Celar toto + setting_display_media_show_all: Monstrar toto + setting_system_font_ui: Usar typo de litteras predefinite del systema + setting_theme: Thema de sito + setting_trends: Monstrar le tendentias de hodie + sign_in_token_attempt: Codice de securitate + title: Titulo + username: Nomine de usator + username_or_email: Nomine de usator o e-mail + form_admin_settings: + 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_terms: Politica de confidentialitate + site_title: Nomine de servitor + theme: Thema predefinite + trends: Activar tendentias + notification_emails: + software_updates: + label: Un nove version de Mastodon es disponibile + user: + time_zone: Fuso horari + user_role: + name: Nomine + permissions_as_keys: Permissiones + position: Prioritate + 'yes': Si diff --git a/config/locales/simple_form.ie.yml b/config/locales/simple_form.ie.yml index bd055b1c9e..72797bde5e 100644 --- a/config/locales/simple_form.ie.yml +++ b/config/locales/simple_form.ie.yml @@ -8,6 +8,7 @@ ie: fields: Tui websitu, pronómines, etá, quocunc quel tu vole. indexable: Tui public postas posse aparir in sercha-resultates sur Mastodon. E in omni casu, tis qui ha interactet con tui postas va posser serchar e trovar les. note: 'Tu posse @mentionar altri persones o #hashtags.' + show_collections: Gente va posser navigar tra tui sequentes e sequitores. Gente quem tu seque va vider que tu seque les sin egarda. unlocked: Persones va posser sequer te sin petir aprobation. Desselecte si tu vole manualmen tractar petitiones de sequer e decider ca acceptar o rejecter nov sequitores. account_alias: acct: Specificar li usatornomine@dominia del conto ex quel tu vole translocar @@ -58,6 +59,14 @@ ie: setting_display_media_default: Celar medie marcat quam sensitiv setting_display_media_hide_all: Sempre celar medie setting_display_media_show_all: Sempre monstrar medie + setting_use_blurhash: Gradientes es basat sur li colores del celat visuales ma obscura omni detallies + setting_use_pending_items: Celar nov postas detra un clicc vice rular li témpor-linea automaticmen + username: Tu posse usar lítteres, númeres e sublineas + domain_allow: + domain: Ti dominia va posser obtener data de ti-ci servitor, e data venient de it va esser tractat e inmagasinat + email_domain_block: + domain: Ti posse esser li dominia-nómine quel apari in li email-adresse o li MX-registre quel it usa. Ili va esser controlat durant adhesion. + with_dns_records: On va far un prova resoluer li DNS-registres del specificat dominia, e li resultates anc va esser bloccat featured_tag: name: 'Vi quelc hashtags usat max recentmen de te:' filters: @@ -66,8 +75,12 @@ ie: hide: Celar completmen li contenete filtrat, quam si it ne existe warn: Celar li contenete filtrat detra un avise mentionant li titul del filtre form_admin_settings: + activity_api_enabled: Númeres de postas publicat localmen, activ usatores, e nov adhesiones in periodes semanal backups_retention_period: Mantener usator-generat archives por li specificat quantitá de dies. bootstrap_timeline_accounts: Ti-ci contos va esser pinglat al parte superiori del recomandationes por nov usatores. + closed_registrations_message: Monstrat quande adhesiones es cludet + content_cache_retention_period: Omni postas e boosts de altri servitores va esser deletet pos li specificat quantitá de dies. Quelc postas fórsan va esser ínrestaurabil. Omni pertinent marcatores, favorites e boosts anc va esser perdit e ínpossibil a restaurar. + custom_css: On posse aplicar customisat stiles al web-version de Mastodon. mascot: Substitue li ilustration in li avansat interfacie web. peers_api_enabled: Un liste de nómines de dominia queles ti-ci servitor ha incontrat in li fediverse. Ci null data es includet pri ca tu confedera con un cert servitor o ne; it indica solmen que tui servitor conosse it. Usat per servicies colectent general statisticas pri federation. profile_directory: Li profilarium monstra omni usatores volent esser decovribil. @@ -178,6 +191,7 @@ ie: setting_display_media_show_all: Monstrar omno setting_expand_spoilers: Sempre expander postas marcat con admonitiones de contenete setting_hide_network: Celar tui grafica social + setting_reduce_motion: Reducter motion in animationes setting_system_font_ui: Usar predefinit fonte de sistema setting_theme: Tema de situ setting_trends: Monstrar li hodial tendenties @@ -190,6 +204,8 @@ ie: username: Nómine de usator username_or_email: Usator-nómine o E-posta whole_word: Plen parol + email_domain_block: + with_dns_records: Includer archives MX e IPs del dominia featured_tag: name: Hashtag filters: @@ -197,10 +213,14 @@ ie: hide: Celar completmen warn: Celar con un admonition form_admin_settings: + activity_api_enabled: Publicar agregat statisticas pri usator-activitá in li API backups_retention_period: Periode de retener archives de usator bootstrap_timeline_accounts: Sempre recomandar ti-ci contos a nov usatores closed_registrations_message: Customisat missage quande registration ne disponibil + content_cache_retention_period: Periode de retention por cachat contenete custom_css: Custom CSS + media_cache_retention_period: Periode de retention por cachat medie + peers_api_enabled: Publicar liste de conosset servitores per li API profile_directory: Possibilisar profilarium registrations_mode: Qui posse registrar se require_invite_text: Exiger un rason por adherer se @@ -210,11 +230,19 @@ ie: site_contact_username: Usator-nómine de contact site_extended_description: Extendet descrition site_short_description: Descrition del servitor + site_terms: Politica pri Privatie site_title: Nómine de servitor + status_page_url: URL de statu-págine theme: Predefenit tema + thumbnail: Miniatura del servitor + timeline_preview: Permisser accesse ínautenticat al public témpor-lineas trendable_by_default: Possibilisar tendenties sin priori inspection trends: Possibilisar tendenties trends_as_landing_page: Usar tendenties quam frontispicie + interactions: + must_be_follower: Bloccar notificationes de tis qui ne seque te + must_be_following: Bloccar notificationes de tis quem tu ne seque + must_be_following_dm: Bloccar direct missages de tis quem tu ne seque invite: comment: Comentar invite_request: @@ -228,27 +256,38 @@ ie: sign_up_requires_approval: Limitar usator-registrationes severity: Regul notification_emails: + appeal: Alqui apella un decision moderatori + digest: Inviar compendies per email favourite: Alqui favoritisat tui posta follow: Alqui sequet te follow_request: Alqui petit sequer te mention: Alqui mentionat te pending_account: Nov conto besonant inspection + reblog: Alqui boostat tui posta report: Nov raporte es submisset software_updates: all: Notificar pri omni nov actualisationes critical: Notificar solmen pri critical actualisationes label: Un nov version de Mastodon es disponibil + none: Nequande notificar pri actualisationes (ne recomandat) + patch: Notificar pri problema-fixant actualisationes trending_tag: Nov tendentie besonant inspection rule: text: Regul + settings: + indexable: Includer profil-pagine in serchatores + show_application: Monstrar de quel aplication tu fat un posta tag: + listable: Permisser que ti hashtag apari in serchas e suggestiones name: Hashtag trendable: Permisse que ti-ci hashtag apari sub tendenties + usable: Permisser que postas usa ti hashtag user: role: Rol time_zone: Zone temporal user_role: color: Color del insignie + highlighted: Monstrar rol quam insigne sur usator-profiles name: Nómine permissions_as_keys: Permissiones position: Prioritá diff --git a/config/locales/simple_form.sk.yml b/config/locales/simple_form.sk.yml index a89e1a4290..e13a05835f 100644 --- a/config/locales/simple_form.sk.yml +++ b/config/locales/simple_form.sk.yml @@ -149,6 +149,8 @@ sk: text: Prečo sa k nám chceš pridať? ip_block: comment: Komentár + severities: + sign_up_requires_approval: Obmedz registrácie severity: Pravidlo notification_emails: digest: Zasielať súhrnné emaily diff --git a/config/locales/sk.yml b/config/locales/sk.yml index feb84ea984..cfc5ee7087 100644 --- a/config/locales/sk.yml +++ b/config/locales/sk.yml @@ -374,6 +374,7 @@ sk: view: Ukáž blokovanie domén email_domain_blocks: add_new: Pridaj nový + allow_registrations_with_approval: Povoľ registrovanie so schválením created_msg: Emailová doména bola úspešne pridaná do zoznamu zakázaných delete: Vymaž dns: diff --git a/config/locales/sl.yml b/config/locales/sl.yml index ecff5a6672..83d52ae0e7 100644 --- a/config/locales/sl.yml +++ b/config/locales/sl.yml @@ -439,6 +439,7 @@ sl: view: Pokaži domenski blok email_domain_blocks: add_new: Dodaj novo + allow_registrations_with_approval: Dovoli registracije z odobritvijo attempts_over_week: few: "%{count} poskusi prijave zadnji teden" one: "%{count} poskus prijave zadnji teden" diff --git a/config/locales/sq.yml b/config/locales/sq.yml index af1bb4644d..9ab6e85361 100644 --- a/config/locales/sq.yml +++ b/config/locales/sq.yml @@ -425,6 +425,7 @@ sq: view: Shihni bllokim përkatësie email_domain_blocks: add_new: Shtoni të ri + allow_registrations_with_approval: Lejo regjistrim me miratim attempts_over_week: one: "%{count} përpjekje gjatë javës së shkuar" other: "%{count} përpjekje regjistrimi gjatë javës së kaluar" diff --git a/config/locales/sr-Latn.yml b/config/locales/sr-Latn.yml index e8760697e2..02f63ede71 100644 --- a/config/locales/sr-Latn.yml +++ b/config/locales/sr-Latn.yml @@ -432,6 +432,7 @@ sr-Latn: view: Pročitaj blok domena email_domain_blocks: add_new: Dodaj novi + allow_registrations_with_approval: Dozvoli registraciju uz odobrenje attempts_over_week: few: "%{count} pokušaja tokom prethodne nedelje" one: "%{count} pokušaj tokom prethodne nedelje" diff --git a/config/locales/sr.yml b/config/locales/sr.yml index b32d86f652..51613940bc 100644 --- a/config/locales/sr.yml +++ b/config/locales/sr.yml @@ -432,6 +432,7 @@ sr: view: Прочитај блок домена email_domain_blocks: add_new: Додај нови + allow_registrations_with_approval: Дозволи регистрацију уз одобрење attempts_over_week: few: "%{count} покушаја током претходне недеље" one: "%{count} покушај током претходне недеље" diff --git a/config/locales/th.yml b/config/locales/th.yml index 59a6b2c4fb..f553f6a41c 100644 --- a/config/locales/th.yml +++ b/config/locales/th.yml @@ -418,6 +418,7 @@ th: view: ดูการปิดกั้นโดเมน email_domain_blocks: add_new: เพิ่มใหม่ + allow_registrations_with_approval: อนุญาตการลงทะเบียนด้วยการอนุมัติ attempts_over_week: other: "%{count} ความพยายามในการลงทะเบียนในช่วงสัปดาห์ที่ผ่านมา" created_msg: ปิดกั้นโดเมนอีเมลสำเร็จ diff --git a/config/locales/tr.yml b/config/locales/tr.yml index 568607e70d..da8935f6ca 100644 --- a/config/locales/tr.yml +++ b/config/locales/tr.yml @@ -425,6 +425,7 @@ tr: view: Alan adı bloğunu görüntüle email_domain_blocks: add_new: Yeni ekle + allow_registrations_with_approval: Onaylı kayıtlara izin ver attempts_over_week: one: Son haftada %{count} deneme other: Son haftada %{count} kayıt denemesi diff --git a/config/locales/uk.yml b/config/locales/uk.yml index 139b8be30d..7a1957eba7 100644 --- a/config/locales/uk.yml +++ b/config/locales/uk.yml @@ -439,6 +439,7 @@ uk: view: Переглянути заблоковані домени email_domain_blocks: add_new: Додати + allow_registrations_with_approval: Дозволити реєстрації із затвердженням attempts_over_week: few: "%{count} спроби входу за останній тиждень" many: "%{count} спроб входу за останній тиждень" diff --git a/config/locales/vi.yml b/config/locales/vi.yml index c06a84b973..85aabe7176 100644 --- a/config/locales/vi.yml +++ b/config/locales/vi.yml @@ -418,6 +418,7 @@ vi: view: Xem máy chủ chặn email_domain_blocks: add_new: Thêm mới + allow_registrations_with_approval: Cho đăng ký nhưng duyệt thủ công attempts_over_week: other: "%{count} lần thử đăng ký vào tuần trước" created_msg: Đã chặn tên miền email này diff --git a/config/locales/zh-CN.yml b/config/locales/zh-CN.yml index ec4d714233..a573c8f99b 100644 --- a/config/locales/zh-CN.yml +++ b/config/locales/zh-CN.yml @@ -418,6 +418,7 @@ zh-CN: view: 查看域名屏蔽 email_domain_blocks: add_new: 添加新条目 + allow_registrations_with_approval: 注册时需要批准 attempts_over_week: other: 上周有 %{count} 次注册尝试 created_msg: 成功屏蔽电子邮件域名 diff --git a/config/locales/zh-HK.yml b/config/locales/zh-HK.yml index 01a0a026a7..61355a4c53 100644 --- a/config/locales/zh-HK.yml +++ b/config/locales/zh-HK.yml @@ -418,6 +418,7 @@ zh-HK: view: 顯示正被阻隔的網域 email_domain_blocks: add_new: 新增 + allow_registrations_with_approval: 允許經批准的註冊 attempts_over_week: other: 上週嘗試了註冊 %{count} 次 created_msg: 已新增電郵網域阻隔 From e1b49d3454a0c2d492d65e076700882272e982fc Mon Sep 17 00:00:00 2001 From: Matt Jankowski Date: Fri, 5 Jan 2024 07:26:31 -0500 Subject: [PATCH 23/61] Regenerate rubocop todo with version 1.59.0 (#28597) --- .rubocop_todo.yml | 24 +++++++----------------- 1 file changed, 7 insertions(+), 17 deletions(-) diff --git a/.rubocop_todo.yml b/.rubocop_todo.yml index d68832e85e..6ab8957055 100644 --- a/.rubocop_todo.yml +++ b/.rubocop_todo.yml @@ -1,6 +1,6 @@ # This configuration was generated by # `rubocop --auto-gen-config --auto-gen-only-exclude --no-exclude-limit --no-offense-counts --no-auto-gen-timestamp` -# using RuboCop version 1.57.2. +# using RuboCop version 1.59.0. # The point is for the user to remove these configuration records # one by one as the offenses are removed from the code base. # Note that changes in the inspected code, or installation of new @@ -26,7 +26,7 @@ Lint/NonLocalExitFromIterator: # Configuration parameters: AllowedMethods, AllowedPatterns, CountRepeatedAttributes. Metrics/AbcSize: - Max: 100 + Max: 82 # Configuration parameters: CountBlocks, Max. Metrics/BlockNesting: @@ -50,7 +50,7 @@ RSpec/MultipleExpectations: # Configuration parameters: AllowSubject. RSpec/MultipleMemoizedHelpers: - Max: 21 + Max: 17 # Configuration parameters: AllowedGroups. RSpec/NestedGroups: @@ -66,7 +66,6 @@ Rails/ApplicationController: Rails/HasAndBelongsToMany: Exclude: - 'app/models/concerns/account/associations.rb' - - 'app/models/preview_card.rb' - 'app/models/status.rb' - 'app/models/tag.rb' @@ -144,7 +143,6 @@ Rails/WhereExists: Exclude: - 'app/controllers/activitypub/inboxes_controller.rb' - 'app/controllers/admin/email_domain_blocks_controller.rb' - - 'app/controllers/auth/registrations_controller.rb' - 'app/lib/activitypub/activity/create.rb' - 'app/lib/delivery_failure_tracker.rb' - 'app/lib/feed_manager.rb' @@ -160,7 +158,6 @@ Rails/WhereExists: - 'app/serializers/rest/announcement_serializer.rb' - 'app/serializers/rest/tag_serializer.rb' - 'app/services/activitypub/fetch_remote_status_service.rb' - - 'app/services/app_sign_up_service.rb' - 'app/services/vote_service.rb' - 'app/validators/reaction_validator.rb' - 'app/validators/vote_validator.rb' @@ -171,12 +168,6 @@ Rails/WhereExists: - 'spec/services/purge_domain_service_spec.rb' - 'spec/services/unallow_domain_service_spec.rb' -# This cop supports safe autocorrection (--autocorrect). -# Configuration parameters: AllowOnConstant, AllowOnSelfClass. -Style/CaseEquality: - Exclude: - - 'config/initializers/trusted_proxies.rb' - # This cop supports unsafe autocorrection (--autocorrect-all). # Configuration parameters: AllowedMethods, AllowedPatterns. # AllowedMethods: ==, equal?, eql? @@ -204,8 +195,8 @@ Style/FetchEnvVar: - 'config/initializers/devise.rb' - 'config/initializers/paperclip.rb' - 'config/initializers/vapid.rb' - - 'lib/premailer_webpack_strategy.rb' - 'lib/mastodon/redis_config.rb' + - 'lib/premailer_webpack_strategy.rb' - 'lib/tasks/repo.rake' - 'spec/features/profile_spec.rb' @@ -222,7 +213,6 @@ Style/FormatStringToken: # This cop supports unsafe autocorrection (--autocorrect-all). Style/GlobalStdStream: Exclude: - - 'config/boot.rb' - 'config/environments/development.rb' - 'config/environments/production.rb' @@ -411,8 +401,8 @@ Style/TrailingCommaInHashLiteral: - 'config/environments/test.rb' # This cop supports safe autocorrection (--autocorrect). -# Configuration parameters: EnforcedStyle, MinSize, WordRegex. +# Configuration parameters: WordRegex. # SupportedStyles: percent, brackets Style/WordArray: - Exclude: - - 'app/helpers/languages_helper.rb' + EnforcedStyle: percent + MinSize: 3 From b3dab17b586ef34bc8cd64f6b25e3ec661f7defd Mon Sep 17 00:00:00 2001 From: Matt Jankowski Date: Fri, 5 Jan 2024 07:31:18 -0500 Subject: [PATCH 24/61] Remove deprecated `RSpec/FilePath` cop (#28601) --- .rubocop.yml | 9 ++------- 1 file changed, 2 insertions(+), 7 deletions(-) diff --git a/.rubocop.yml b/.rubocop.yml index 8832e28f6e..bedd8f7850 100644 --- a/.rubocop.yml +++ b/.rubocop.yml @@ -118,15 +118,10 @@ Rails/UnusedIgnoredColumns: Rails/NegateInclude: Enabled: false -# Reason: Some single letter camel case files shouldn't be split +# Reason: Deprecated cop, will be removed in 3.0, replaced by SpecFilePathFormat # https://docs.rubocop.org/rubocop-rspec/cops_rspec.html#rspecfilepath RSpec/FilePath: - CustomTransform: - ActivityPub: activitypub - DeepL: deepl - FetchOEmbedService: fetch_oembed_service - OEmbedController: oembed_controller - OStatus: ostatus + Enabled: false # Reason: # https://docs.rubocop.org/rubocop-rspec/cops_rspec.html#rspecnamedsubject From 12bed81187dd5b041a735af8e9cb5a5f96b4b75a Mon Sep 17 00:00:00 2001 From: Matt Jankowski Date: Fri, 5 Jan 2024 10:13:59 -0500 Subject: [PATCH 25/61] Add validation specs to `CustomFilter` model (#28600) --- app/models/custom_filter.rb | 6 +++++- spec/models/custom_filter_spec.rb | 35 +++++++++++++++++++++++++++++++ 2 files changed, 40 insertions(+), 1 deletion(-) create mode 100644 spec/models/custom_filter_spec.rb diff --git a/app/models/custom_filter.rb b/app/models/custom_filter.rb index 9c936fed39..0ee9e35328 100644 --- a/app/models/custom_filter.rb +++ b/app/models/custom_filter.rb @@ -143,6 +143,10 @@ class CustomFilter < ApplicationRecord end def context_must_be_valid - errors.add(:context, I18n.t('filters.errors.invalid_context')) if context.empty? || context.any? { |c| !VALID_CONTEXTS.include?(c) } + errors.add(:context, I18n.t('filters.errors.invalid_context')) if invalid_context_value? + end + + def invalid_context_value? + context.blank? || context.difference(VALID_CONTEXTS).any? end end diff --git a/spec/models/custom_filter_spec.rb b/spec/models/custom_filter_spec.rb new file mode 100644 index 0000000000..9404936337 --- /dev/null +++ b/spec/models/custom_filter_spec.rb @@ -0,0 +1,35 @@ +# frozen_string_literal: true + +require 'rails_helper' + +RSpec.describe CustomFilter do + describe 'Validations' do + it 'requires presence of title' do + record = described_class.new(title: '') + record.valid? + + expect(record).to model_have_error_on_field(:title) + end + + it 'requires presence of context' do + record = described_class.new(context: nil) + record.valid? + + expect(record).to model_have_error_on_field(:context) + end + + it 'requires non-empty of context' do + record = described_class.new(context: []) + record.valid? + + expect(record).to model_have_error_on_field(:context) + end + + it 'requires valid context value' do + record = described_class.new(context: ['invalid']) + record.valid? + + expect(record).to model_have_error_on_field(:context) + end + end +end From 5a6d533c5390832f86c3352af0f6023f9ad07156 Mon Sep 17 00:00:00 2001 From: Jean Boussier Date: Fri, 5 Jan 2024 22:57:47 +0100 Subject: [PATCH 26/61] Enable Rails 7.1 Marshalling format (#28609) --- app/controllers/concerns/cache_concern.rb | 155 +--------------------- app/models/custom_filter.rb | 19 +-- app/models/custom_filter_keyword.rb | 10 +- config/application.rb | 2 + lib/mastodon/redis_config.rb | 2 +- 5 files changed, 8 insertions(+), 180 deletions(-) diff --git a/app/controllers/concerns/cache_concern.rb b/app/controllers/concerns/cache_concern.rb index 2dfe5e263a..62f763fe2f 100644 --- a/app/controllers/concerns/cache_concern.rb +++ b/app/controllers/concerns/cache_concern.rb @@ -3,150 +3,6 @@ module CacheConcern extend ActiveSupport::Concern - module ActiveRecordCoder - EMPTY_HASH = {}.freeze - - class << self - def dump(record) - instances = InstanceTracker.new - serialized_associations = serialize_associations(record, instances) - serialized_records = instances.map { |r| serialize_record(r) } - [serialized_associations, *serialized_records] - end - - def load(payload) - instances = InstanceTracker.new - serialized_associations, *serialized_records = payload - serialized_records.each { |attrs| instances.push(deserialize_record(*attrs)) } - deserialize_associations(serialized_associations, instances) - end - - private - - # Records without associations, or which have already been visited before, - # are serialized by their id alone. - # - # Records with associations are serialized as a two-element array including - # their id and the record's association cache. - # - def serialize_associations(record, instances) - return unless record - - if (id = instances.lookup(record)) - payload = id - else - payload = instances.push(record) - - cached_associations = record.class.reflect_on_all_associations.select do |reflection| - record.association_cached?(reflection.name) - end - - unless cached_associations.empty? - serialized_associations = cached_associations.map do |reflection| - association = record.association(reflection.name) - - serialized_target = if reflection.collection? - association.target.map { |target_record| serialize_associations(target_record, instances) } - else - serialize_associations(association.target, instances) - end - - [reflection.name, serialized_target] - end - - payload = [payload, serialized_associations] - end - end - - payload - end - - def deserialize_associations(payload, instances) - return unless payload - - id, associations = payload - record = instances.fetch(id) - - associations&.each do |name, serialized_target| - begin - association = record.association(name) - rescue ActiveRecord::AssociationNotFoundError - raise AssociationMissingError, "undefined association: #{name}" - end - - target = if association.reflection.collection? - serialized_target.map! { |serialized_record| deserialize_associations(serialized_record, instances) } - else - deserialize_associations(serialized_target, instances) - end - - association.target = target - end - - record - end - - def serialize_record(record) - arguments = [record.class.name, attributes_for_database(record)] - arguments << true if record.new_record? - arguments - end - - def attributes_for_database(record) - attributes = record.attributes_for_database - attributes.transform_values! { |attr| attr.is_a?(::ActiveModel::Type::Binary::Data) ? attr.to_s : attr } - attributes - end - - def deserialize_record(class_name, attributes_from_database, new_record = false) # rubocop:disable Style/OptionalBooleanParameter - begin - klass = Object.const_get(class_name) - rescue NameError - raise ClassMissingError, "undefined class: #{class_name}" - end - - # Ideally we'd like to call `klass.instantiate`, however it doesn't allow to pass - # wether the record was persisted or not. - attributes = klass.attributes_builder.build_from_database(attributes_from_database, EMPTY_HASH) - klass.allocate.init_with_attributes(attributes, new_record) - end - end - - class Error < StandardError - end - - class ClassMissingError < Error - end - - class AssociationMissingError < Error - end - - class InstanceTracker - def initialize - @instances = [] - @ids = {}.compare_by_identity - end - - def map(&block) - @instances.map(&block) - end - - def fetch(...) - @instances.fetch(...) - end - - def push(instance) - id = @ids[instance] = @instances.size - @instances << instance - id - end - - def lookup(instance) - @ids[instance] - end - end - end - class_methods do def vary_by(value, **kwargs) before_action(**kwargs) do |controller| @@ -196,11 +52,7 @@ module CacheConcern raw = raw.cache_ids.to_a if raw.is_a?(ActiveRecord::Relation) return [] if raw.empty? - cached_keys_with_value = begin - Rails.cache.read_multi(*raw).transform_keys(&:id).transform_values { |r| ActiveRecordCoder.load(r) } - rescue ActiveRecordCoder::Error - {} # The serialization format may have changed, let's pretend it's a cache miss. - end + cached_keys_with_value = Rails.cache.read_multi(*raw).transform_keys(&:id) uncached_ids = raw.map(&:id) - cached_keys_with_value.keys @@ -208,10 +60,7 @@ module CacheConcern unless uncached_ids.empty? uncached = klass.where(id: uncached_ids).with_includes.index_by(&:id) - - uncached.each_value do |item| - Rails.cache.write(item, ActiveRecordCoder.dump(item)) - end + Rails.cache.write_multi(uncached.values.to_h { |i| [i, i] }) end raw.filter_map { |item| cached_keys_with_value[item.id] || uncached[item.id] } diff --git a/app/models/custom_filter.rb b/app/models/custom_filter.rb index 0ee9e35328..371267fc28 100644 --- a/app/models/custom_filter.rb +++ b/app/models/custom_filter.rb @@ -17,23 +17,8 @@ class CustomFilter < ApplicationRecord self.ignored_columns += %w(whole_word irreversible) - # NOTE: We previously used `alias_attribute` but this does not play nicely - # with cache - def title - phrase - end - - def title=(value) - self.phrase = value - end - - def filter_action - action - end - - def filter_action=(value) - self.action = value - end + alias_attribute :title, :phrase + alias_attribute :filter_action, :action VALID_CONTEXTS = %w( home diff --git a/app/models/custom_filter_keyword.rb b/app/models/custom_filter_keyword.rb index 1812a43081..3158b3b79a 100644 --- a/app/models/custom_filter_keyword.rb +++ b/app/models/custom_filter_keyword.rb @@ -17,15 +17,7 @@ class CustomFilterKeyword < ApplicationRecord validates :keyword, presence: true - # NOTE: We previously used `alias_attribute` but this does not play nicely - # with cache - def phrase - keyword - end - - def phrase=(value) - self.keyword = value - end + alias_attribute :phrase, :keyword before_save :prepare_cache_invalidation! before_destroy :prepare_cache_invalidation! diff --git a/config/application.rb b/config/application.rb index 990a89383e..bab1b46cb0 100644 --- a/config/application.rb +++ b/config/application.rb @@ -63,6 +63,8 @@ module Mastodon # Initialize configuration defaults for originally generated Rails version. config.load_defaults 7.0 + config.active_record.marshalling_format_version = 7.1 + # Please, add to the `ignore` list any other `lib` subdirectories that do # not contain `.rb` files, or that should not be reloaded or eager loaded. # Common ones are `templates`, `generators`, or `middleware`, for example. diff --git a/lib/mastodon/redis_config.rb b/lib/mastodon/redis_config.rb index e885712f89..10672a5358 100644 --- a/lib/mastodon/redis_config.rb +++ b/lib/mastodon/redis_config.rb @@ -34,7 +34,7 @@ REDIS_CACHE_PARAMS = { driver: :hiredis, url: ENV['CACHE_REDIS_URL'], expires_in: 10.minutes, - namespace: cache_namespace, + namespace: "#{cache_namespace}:7.1", connect_timeout: 5, pool: { size: Sidekiq.server? ? Sidekiq[:concurrency] : Integer(ENV['MAX_THREADS'] || 5), From 8a312ad79bb756d92b5ca4c9a176bd96c702e73e Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Mon, 8 Jan 2024 10:57:12 +0100 Subject: [PATCH 27/61] Update dependency puma to v6.4.2 (#28640) 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 009293167f..45d228e48f 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -544,7 +544,7 @@ GEM psych (5.1.2) stringio public_suffix (5.0.4) - puma (6.4.1) + puma (6.4.2) nio4r (~> 2.0) pundit (2.3.1) activesupport (>= 3.0.0) From 352625c49107e2e25c802e24a1631e173432832b Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Mon, 8 Jan 2024 10:59:06 +0100 Subject: [PATCH 28/61] Update libretranslate/libretranslate Docker tag to v1.5.3 (#28639) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- .devcontainer/docker-compose.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.devcontainer/docker-compose.yml b/.devcontainer/docker-compose.yml index 40dc72c12d..21ee078d60 100644 --- a/.devcontainer/docker-compose.yml +++ b/.devcontainer/docker-compose.yml @@ -70,7 +70,7 @@ services: hard: -1 libretranslate: - image: libretranslate/libretranslate:v1.5.2 + image: libretranslate/libretranslate:v1.5.3 restart: unless-stopped volumes: - lt-data:/home/libretranslate/.local From a27a82939dffe06134327468a192b2badf4aee46 Mon Sep 17 00:00:00 2001 From: Matt Jankowski Date: Mon, 8 Jan 2024 05:16:33 -0500 Subject: [PATCH 29/61] Remove the 7.1 marshalling format "todo" from new_framework_defaults (#28625) --- config/initializers/new_framework_defaults_7_1.rb | 9 --------- 1 file changed, 9 deletions(-) diff --git a/config/initializers/new_framework_defaults_7_1.rb b/config/initializers/new_framework_defaults_7_1.rb index 2fa0e42746..1475fe2fd9 100644 --- a/config/initializers/new_framework_defaults_7_1.rb +++ b/config/initializers/new_framework_defaults_7_1.rb @@ -158,15 +158,6 @@ Rails.application.config.add_autoload_paths_to_load_path = false # rather than to rely on a global default. # Rails.application.config.active_record.default_column_serializer = nil -# Enable a performance optimization that serializes Active Record models -# in a faster and more compact way. -# -# To perform a rolling deploy of a Rails 7.1 upgrade, wherein servers that have -# not yet been upgraded must be able to read caches from upgraded servers, -# leave this optimization off on the first deploy, then enable it on a -# subsequent deploy. -# Rails.application.config.active_record.marshalling_format_version = 7.1 - # Run `after_commit` and `after_*_commit` callbacks in the order they are defined in a model. # This matches the behaviour of all other callbacks. # In previous versions of Rails, they ran in the inverse order. From e09419f22a98266be029c5121b7302ab439c0a3a Mon Sep 17 00:00:00 2001 From: Matt Jankowski Date: Mon, 8 Jan 2024 05:17:38 -0500 Subject: [PATCH 30/61] Move old framework defaults file to regular config value (#28623) --- config/initializers/new_framework_defaults_7_0.rb | 10 ---------- config/initializers/open_redirects.rb | 10 ++++++++++ 2 files changed, 10 insertions(+), 10 deletions(-) delete mode 100644 config/initializers/new_framework_defaults_7_0.rb create mode 100644 config/initializers/open_redirects.rb diff --git a/config/initializers/new_framework_defaults_7_0.rb b/config/initializers/new_framework_defaults_7_0.rb deleted file mode 100644 index edaf819447..0000000000 --- a/config/initializers/new_framework_defaults_7_0.rb +++ /dev/null @@ -1,10 +0,0 @@ -# frozen_string_literal: true - -# TODO -# The Rails 7.0 framework default here is to set this true. However, we have a -# location in devise that redirects where we don't have an easy ability to -# override a method or set a config option, but where the redirect does not -# provide this option. -# https://github.com/heartcombo/devise/blob/v4.9.2/app/controllers/devise/confirmations_controller.rb#L28 -# Once a solution is found, this line can be removed. -Rails.application.config.action_controller.raise_on_open_redirects = false diff --git a/config/initializers/open_redirects.rb b/config/initializers/open_redirects.rb new file mode 100644 index 0000000000..c953a990c6 --- /dev/null +++ b/config/initializers/open_redirects.rb @@ -0,0 +1,10 @@ +# frozen_string_literal: true + +# TODO +# Starting with Rails 7.0, the framework default here is to set this true. +# However, we have a location in devise that redirects where we don't have an +# easy ability to override the method or set a config option, and where the +# redirect does not supply this option itself. +# https://github.com/heartcombo/devise/blob/v4.9.2/app/controllers/devise/confirmations_controller.rb#L28 +# Once a solution is found, this line can be removed. +Rails.application.config.action_controller.raise_on_open_redirects = false From 8d06baf8127d453c889279ab413f2ecfac4192aa Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Mon, 8 Jan 2024 10:17:53 +0000 Subject: [PATCH 31/61] Update dependency strong_migrations to v1.7.0 (#28621) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- Gemfile | 2 +- Gemfile.lock | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/Gemfile b/Gemfile index cfcbcc0d3c..a56702fad2 100644 --- a/Gemfile +++ b/Gemfile @@ -90,7 +90,7 @@ gem 'sidekiq-bulk', '~> 0.2.0' gem 'simple-navigation', '~> 4.4' gem 'simple_form', '~> 5.2' gem 'stoplight', '~> 3.0.1' -gem 'strong_migrations', '1.6.4' +gem 'strong_migrations', '1.7.0' gem 'tty-prompt', '~> 0.23', require: false gem 'twitter-text', '~> 3.1.0' gem 'tzinfo-data', '~> 1.2023' diff --git a/Gemfile.lock b/Gemfile.lock index 45d228e48f..fd6fa563c2 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -748,7 +748,7 @@ GEM stoplight (3.0.2) redlock (~> 1.0) stringio (3.1.0) - strong_migrations (1.6.4) + strong_migrations (1.7.0) activerecord (>= 5.2) swd (1.3.0) activesupport (>= 3) @@ -952,7 +952,7 @@ DEPENDENCIES simplecov-lcov (~> 0.8) stackprof stoplight (~> 3.0.1) - strong_migrations (= 1.6.4) + strong_migrations (= 1.7.0) test-prof thor (~> 1.2) tty-prompt (~> 0.23) From c9e67521583ac0e393c8dafef561e9eff528bf58 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Mon, 8 Jan 2024 11:18:57 +0100 Subject: [PATCH 32/61] Update dependency rubocop-rspec to v2.26.1 (#28611) 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 fd6fa563c2..f032850eb8 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -688,7 +688,7 @@ GEM rack (>= 1.1) rubocop (>= 1.33.0, < 2.0) rubocop-ast (>= 1.30.0, < 2.0) - rubocop-rspec (2.26.0) + rubocop-rspec (2.26.1) rubocop (~> 1.40) rubocop-capybara (~> 2.17) rubocop-factory_bot (~> 2.22) From fe2667bb0d3487a32b9da5250402a90482a85fe2 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Mon, 8 Jan 2024 11:19:33 +0100 Subject: [PATCH 33/61] Update dependency rubocop-performance to v1.20.2 (#28641) 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 f032850eb8..e694dce0fb 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -680,7 +680,7 @@ GEM rubocop (~> 1.41) rubocop-factory_bot (2.25.0) rubocop (~> 1.33) - rubocop-performance (1.20.1) + rubocop-performance (1.20.2) rubocop (>= 1.48.1, < 2.0) rubocop-ast (>= 1.30.0, < 2.0) rubocop-rails (2.23.1) From a0e237a96fca2774d3c9ed43063a45e395bb7f40 Mon Sep 17 00:00:00 2001 From: Renaud Chaput Date: Mon, 8 Jan 2024 11:57:40 +0100 Subject: [PATCH 34/61] Upgrade Redux packages (#28585) --- .eslintrc.js | 11 +- .../emoji_picker_dropdown_container.js | 3 +- .../containers/language_dropdown_container.js | 3 +- .../containers/announcements_container.js | 3 +- .../mastodon/features/home_timeline/index.jsx | 2 +- .../mastodon/features/list_adder/index.jsx | 2 +- .../mastodon/features/lists/index.jsx | 2 +- .../mastodon/features/notifications/index.jsx | 2 +- .../mastodon/features/report/comment.jsx | 2 +- .../mastodon/features/status/index.jsx | 2 +- .../subscribed_languages_modal/index.jsx | 2 +- .../features/ui/components/list_panel.jsx | 2 +- .../ui/containers/status_list_container.js | 2 +- app/javascript/mastodon/reducers/accounts.ts | 3 +- app/javascript/mastodon/reducers/modal.ts | 3 +- .../mastodon/reducers/relationships.ts | 5 +- app/javascript/mastodon/selectors/accounts.ts | 2 +- app/javascript/mastodon/selectors/index.js | 2 +- .../mastodon/store/middlewares/errors.ts | 32 ++++-- .../mastodon/store/middlewares/loading_bar.ts | 24 +++- .../mastodon/store/middlewares/sounds.ts | 35 ++++-- .../mastodon/store/typed_functions.ts | 6 +- config/webpack/rules/babel.js | 8 +- package.json | 9 +- yarn.lock | 104 +++++++++--------- 25 files changed, 167 insertions(+), 104 deletions(-) diff --git a/.eslintrc.js b/.eslintrc.js index e2d16a54a8..1b36bcee25 100644 --- a/.eslintrc.js +++ b/.eslintrc.js @@ -245,7 +245,7 @@ module.exports = defineConfig({ }, // Immutable / Redux / data store { - pattern: '{immutable,react-redux,react-immutable-proptypes,react-immutable-pure-component,reselect}', + pattern: '{immutable,@reduxjs/toolkit,react-redux,react-immutable-proptypes,react-immutable-pure-component}', group: 'external', position: 'before', }, @@ -353,7 +353,14 @@ module.exports = defineConfig({ '@typescript-eslint/consistent-type-exports': 'error', '@typescript-eslint/consistent-type-imports': 'error', "@typescript-eslint/prefer-nullish-coalescing": ['error', { ignorePrimitives: { boolean: true } }], - + "@typescript-eslint/no-restricted-imports": [ + "warn", + { + "name": "react-redux", + "importNames": ["useSelector", "useDispatch"], + "message": "Use typed hooks `useAppDispatch` and `useAppSelector` instead." + } + ], 'jsdoc/require-jsdoc': 'off', // Those rules set stricter rules for TS files diff --git a/app/javascript/mastodon/features/compose/containers/emoji_picker_dropdown_container.js b/app/javascript/mastodon/features/compose/containers/emoji_picker_dropdown_container.js index a0e50029df..8cf906b20a 100644 --- a/app/javascript/mastodon/features/compose/containers/emoji_picker_dropdown_container.js +++ b/app/javascript/mastodon/features/compose/containers/emoji_picker_dropdown_container.js @@ -1,6 +1,7 @@ +import { createSelector } from '@reduxjs/toolkit'; import { Map as ImmutableMap } from 'immutable'; import { connect } from 'react-redux'; -import { createSelector } from 'reselect'; + import { useEmoji } from '../../../actions/emojis'; import { changeSetting } from '../../../actions/settings'; diff --git a/app/javascript/mastodon/features/compose/containers/language_dropdown_container.js b/app/javascript/mastodon/features/compose/containers/language_dropdown_container.js index e1e2f04024..ba4b5f05a5 100644 --- a/app/javascript/mastodon/features/compose/containers/language_dropdown_container.js +++ b/app/javascript/mastodon/features/compose/containers/language_dropdown_container.js @@ -1,6 +1,7 @@ +import { createSelector } from '@reduxjs/toolkit'; import { Map as ImmutableMap } from 'immutable'; import { connect } from 'react-redux'; -import { createSelector } from 'reselect'; + import { changeComposeLanguage } from 'mastodon/actions/compose'; import { useLanguage } from 'mastodon/actions/languages'; diff --git a/app/javascript/mastodon/features/getting_started/containers/announcements_container.js b/app/javascript/mastodon/features/getting_started/containers/announcements_container.js index c33e624324..3bb1b8e8d1 100644 --- a/app/javascript/mastodon/features/getting_started/containers/announcements_container.js +++ b/app/javascript/mastodon/features/getting_started/containers/announcements_container.js @@ -1,6 +1,7 @@ +import { createSelector } from '@reduxjs/toolkit'; import { Map as ImmutableMap } from 'immutable'; import { connect } from 'react-redux'; -import { createSelector } from 'reselect'; + import { addReaction, removeReaction, dismissAnnouncement } from 'mastodon/actions/announcements'; diff --git a/app/javascript/mastodon/features/home_timeline/index.jsx b/app/javascript/mastodon/features/home_timeline/index.jsx index 7c9c7a4e52..613eb4b896 100644 --- a/app/javascript/mastodon/features/home_timeline/index.jsx +++ b/app/javascript/mastodon/features/home_timeline/index.jsx @@ -6,9 +6,9 @@ import { defineMessages, injectIntl, FormattedMessage } from 'react-intl'; import classNames from 'classnames'; import { Helmet } from 'react-helmet'; +import { createSelector } from '@reduxjs/toolkit'; import { List as ImmutableList } from 'immutable'; import { connect } from 'react-redux'; -import { createSelector } from 'reselect'; import { ReactComponent as CampaignIcon } from '@material-symbols/svg-600/outlined/campaign.svg'; import { ReactComponent as HomeIcon } from '@material-symbols/svg-600/outlined/home-fill.svg'; diff --git a/app/javascript/mastodon/features/list_adder/index.jsx b/app/javascript/mastodon/features/list_adder/index.jsx index 1ba9972e00..4e7bd46bdf 100644 --- a/app/javascript/mastodon/features/list_adder/index.jsx +++ b/app/javascript/mastodon/features/list_adder/index.jsx @@ -2,10 +2,10 @@ import PropTypes from 'prop-types'; import { injectIntl } from 'react-intl'; +import { createSelector } from '@reduxjs/toolkit'; import ImmutablePropTypes from 'react-immutable-proptypes'; import ImmutablePureComponent from 'react-immutable-pure-component'; import { connect } from 'react-redux'; -import { createSelector } from 'reselect'; import { setupListAdder, resetListAdder } from '../../actions/lists'; import NewListForm from '../lists/components/new_list_form'; diff --git a/app/javascript/mastodon/features/lists/index.jsx b/app/javascript/mastodon/features/lists/index.jsx index 58e85b4d28..9014394351 100644 --- a/app/javascript/mastodon/features/lists/index.jsx +++ b/app/javascript/mastodon/features/lists/index.jsx @@ -4,10 +4,10 @@ import { defineMessages, injectIntl, FormattedMessage } from 'react-intl'; import { Helmet } from 'react-helmet'; +import { createSelector } from '@reduxjs/toolkit'; import ImmutablePropTypes from 'react-immutable-proptypes'; import ImmutablePureComponent from 'react-immutable-pure-component'; import { connect } from 'react-redux'; -import { createSelector } from 'reselect'; import { ReactComponent as ListAltIcon } from '@material-symbols/svg-600/outlined/list_alt.svg'; diff --git a/app/javascript/mastodon/features/notifications/index.jsx b/app/javascript/mastodon/features/notifications/index.jsx index 379932b7b7..762c96ccca 100644 --- a/app/javascript/mastodon/features/notifications/index.jsx +++ b/app/javascript/mastodon/features/notifications/index.jsx @@ -5,10 +5,10 @@ import { defineMessages, injectIntl, FormattedMessage } from 'react-intl'; import { Helmet } from 'react-helmet'; +import { createSelector } from '@reduxjs/toolkit'; import { List as ImmutableList } from 'immutable'; import ImmutablePropTypes from 'react-immutable-proptypes'; import { connect } from 'react-redux'; -import { createSelector } from 'reselect'; import { ReactComponent as DoneAllIcon } from '@material-symbols/svg-600/outlined/done_all.svg'; import { ReactComponent as NotificationsIcon } from '@material-symbols/svg-600/outlined/notifications-fill.svg'; diff --git a/app/javascript/mastodon/features/report/comment.jsx b/app/javascript/mastodon/features/report/comment.jsx index ec59746923..b80c14fcb9 100644 --- a/app/javascript/mastodon/features/report/comment.jsx +++ b/app/javascript/mastodon/features/report/comment.jsx @@ -3,10 +3,10 @@ import { useCallback, useEffect, useRef } from 'react'; import { useIntl, defineMessages, FormattedMessage } from 'react-intl'; +import { createSelector } from '@reduxjs/toolkit'; import { OrderedSet, List as ImmutableList } from 'immutable'; import ImmutablePropTypes from 'react-immutable-proptypes'; import { shallowEqual } from 'react-redux'; -import { createSelector } from 'reselect'; import Toggle from 'react-toggle'; diff --git a/app/javascript/mastodon/features/status/index.jsx b/app/javascript/mastodon/features/status/index.jsx index c581255c99..3832489764 100644 --- a/app/javascript/mastodon/features/status/index.jsx +++ b/app/javascript/mastodon/features/status/index.jsx @@ -6,11 +6,11 @@ import classNames from 'classnames'; import { Helmet } from 'react-helmet'; import { withRouter } from 'react-router-dom'; +import { createSelector } from '@reduxjs/toolkit'; import Immutable from 'immutable'; import ImmutablePropTypes from 'react-immutable-proptypes'; import ImmutablePureComponent from 'react-immutable-pure-component'; import { connect } from 'react-redux'; -import { createSelector } from 'reselect'; import { ReactComponent as VisibilityIcon } from '@material-symbols/svg-600/outlined/visibility.svg'; import { ReactComponent as VisibilityOffIcon } from '@material-symbols/svg-600/outlined/visibility_off.svg'; diff --git a/app/javascript/mastodon/features/subscribed_languages_modal/index.jsx b/app/javascript/mastodon/features/subscribed_languages_modal/index.jsx index 147e11d1be..ac34f7986c 100644 --- a/app/javascript/mastodon/features/subscribed_languages_modal/index.jsx +++ b/app/javascript/mastodon/features/subscribed_languages_modal/index.jsx @@ -2,11 +2,11 @@ import PropTypes from 'prop-types'; import { defineMessages, FormattedMessage, injectIntl } from 'react-intl'; +import { createSelector } from '@reduxjs/toolkit'; import { is, List as ImmutableList, Set as ImmutableSet } from 'immutable'; import ImmutablePropTypes from 'react-immutable-proptypes'; import ImmutablePureComponent from 'react-immutable-pure-component'; import { connect } from 'react-redux'; -import { createSelector } from 'reselect'; import { ReactComponent as CloseIcon } from '@material-symbols/svg-600/outlined/close.svg'; diff --git a/app/javascript/mastodon/features/ui/components/list_panel.jsx b/app/javascript/mastodon/features/ui/components/list_panel.jsx index 8dbd28f094..ff600730a0 100644 --- a/app/javascript/mastodon/features/ui/components/list_panel.jsx +++ b/app/javascript/mastodon/features/ui/components/list_panel.jsx @@ -1,9 +1,9 @@ import PropTypes from 'prop-types'; +import { createSelector } from '@reduxjs/toolkit'; import ImmutablePropTypes from 'react-immutable-proptypes'; import ImmutablePureComponent from 'react-immutable-pure-component'; import { connect } from 'react-redux'; -import { createSelector } from 'reselect'; import { ReactComponent as ListAltIcon } from '@material-symbols/svg-600/outlined/list_alt.svg'; diff --git a/app/javascript/mastodon/features/ui/containers/status_list_container.js b/app/javascript/mastodon/features/ui/containers/status_list_container.js index 36a8f58f8b..3e7ae2add0 100644 --- a/app/javascript/mastodon/features/ui/containers/status_list_container.js +++ b/app/javascript/mastodon/features/ui/containers/status_list_container.js @@ -1,6 +1,6 @@ +import { createSelector } from '@reduxjs/toolkit'; import { Map as ImmutableMap, List as ImmutableList } from 'immutable'; import { connect } from 'react-redux'; -import { createSelector } from 'reselect'; import { debounce } from 'lodash'; diff --git a/app/javascript/mastodon/reducers/accounts.ts b/app/javascript/mastodon/reducers/accounts.ts index f7270eb60a..e6f07340c0 100644 --- a/app/javascript/mastodon/reducers/accounts.ts +++ b/app/javascript/mastodon/reducers/accounts.ts @@ -1,7 +1,6 @@ +import type { Reducer } from '@reduxjs/toolkit'; import { Map as ImmutableMap } from 'immutable'; -import type { Reducer } from 'redux'; - import { followAccountSuccess, unfollowAccountSuccess, diff --git a/app/javascript/mastodon/reducers/modal.ts b/app/javascript/mastodon/reducers/modal.ts index 73a2afb916..368f26542c 100644 --- a/app/javascript/mastodon/reducers/modal.ts +++ b/app/javascript/mastodon/reducers/modal.ts @@ -1,6 +1,5 @@ -import { Record as ImmutableRecord, Stack } from 'immutable'; - import type { Reducer } from '@reduxjs/toolkit'; +import { Record as ImmutableRecord, Stack } from 'immutable'; import { COMPOSE_UPLOAD_CHANGE_SUCCESS } from '../actions/compose'; import type { ModalType } from '../actions/modal'; diff --git a/app/javascript/mastodon/reducers/relationships.ts b/app/javascript/mastodon/reducers/relationships.ts index 2ba61839c7..dcca11b203 100644 --- a/app/javascript/mastodon/reducers/relationships.ts +++ b/app/javascript/mastodon/reducers/relationships.ts @@ -1,7 +1,6 @@ -import { Map as ImmutableMap } from 'immutable'; - import { isFulfilled } from '@reduxjs/toolkit'; -import type { Reducer } from 'redux'; +import type { Reducer } from '@reduxjs/toolkit'; +import { Map as ImmutableMap } from 'immutable'; import type { ApiRelationshipJSON } from 'mastodon/api_types/relationships'; import type { Account } from 'mastodon/models/account'; diff --git a/app/javascript/mastodon/selectors/accounts.ts b/app/javascript/mastodon/selectors/accounts.ts index 66193136c4..cee3a87bca 100644 --- a/app/javascript/mastodon/selectors/accounts.ts +++ b/app/javascript/mastodon/selectors/accounts.ts @@ -1,5 +1,5 @@ +import { createSelector } from '@reduxjs/toolkit'; import { Record as ImmutableRecord } from 'immutable'; -import { createSelector } from 'reselect'; import { accountDefaultValues } from 'mastodon/models/account'; import type { Account, AccountShape } from 'mastodon/models/account'; diff --git a/app/javascript/mastodon/selectors/index.js b/app/javascript/mastodon/selectors/index.js index 8a07ba774d..b1c60403e9 100644 --- a/app/javascript/mastodon/selectors/index.js +++ b/app/javascript/mastodon/selectors/index.js @@ -1,5 +1,5 @@ +import { createSelector } from '@reduxjs/toolkit'; import { List as ImmutableList, Map as ImmutableMap } from 'immutable'; -import { createSelector } from 'reselect'; import { toServerSideType } from 'mastodon/utils/filters'; diff --git a/app/javascript/mastodon/store/middlewares/errors.ts b/app/javascript/mastodon/store/middlewares/errors.ts index 9f28f5ff53..e11aa78178 100644 --- a/app/javascript/mastodon/store/middlewares/errors.ts +++ b/app/javascript/mastodon/store/middlewares/errors.ts @@ -1,20 +1,34 @@ -import type { AnyAction, Middleware } from 'redux'; +import { isAction } from '@reduxjs/toolkit'; +import type { Action, Middleware } from '@reduxjs/toolkit'; import type { RootState } from '..'; import { showAlertForError } from '../../actions/alerts'; const defaultFailSuffix = 'FAIL'; +const isFailedAction = new RegExp(`${defaultFailSuffix}$`, 'g'); -export const errorsMiddleware: Middleware = +interface ActionWithMaybeAlertParams extends Action { + skipAlert?: boolean; + skipNotFound?: boolean; + error?: unknown; +} + +function isActionWithmaybeAlertParams( + action: unknown, +): action is ActionWithMaybeAlertParams { + return isAction(action); +} + +export const errorsMiddleware: Middleware, RootState> = ({ dispatch }) => (next) => - (action: AnyAction & { skipAlert?: boolean; skipNotFound?: boolean }) => { - if (action.type && !action.skipAlert) { - const isFail = new RegExp(`${defaultFailSuffix}$`, 'g'); - - if (typeof action.type === 'string' && action.type.match(isFail)) { - dispatch(showAlertForError(action.error, action.skipNotFound)); - } + (action) => { + if ( + isActionWithmaybeAlertParams(action) && + !action.skipAlert && + action.type.match(isFailedAction) + ) { + dispatch(showAlertForError(action.error, action.skipNotFound)); } return next(action); diff --git a/app/javascript/mastodon/store/middlewares/loading_bar.ts b/app/javascript/mastodon/store/middlewares/loading_bar.ts index 83056ee49f..d259be899b 100644 --- a/app/javascript/mastodon/store/middlewares/loading_bar.ts +++ b/app/javascript/mastodon/store/middlewares/loading_bar.ts @@ -3,9 +3,11 @@ import { isPending as isThunkActionPending, isFulfilled as isThunkActionFulfilled, isRejected as isThunkActionRejected, + isAction, } from '@reduxjs/toolkit'; +import type { Middleware, UnknownAction } from '@reduxjs/toolkit'; + import { showLoading, hideLoading } from 'react-redux-loading-bar'; -import type { AnyAction, Middleware } from 'redux'; import type { RootState } from '..'; @@ -19,14 +21,28 @@ const defaultTypeSuffixes: Config['promiseTypeSuffixes'] = [ 'REJECTED', ]; +interface ActionWithSkipLoading extends UnknownAction { + skipLoading: boolean; +} + +function isActionWithSkipLoading( + action: unknown, +): action is ActionWithSkipLoading { + return ( + isAction(action) && + 'skipLoading' in action && + typeof action.skipLoading === 'boolean' + ); +} + export const loadingBarMiddleware = ( config: Config = {}, -): Middleware => { +): Middleware<{ skipLoading?: boolean }, RootState> => { const promiseTypeSuffixes = config.promiseTypeSuffixes ?? defaultTypeSuffixes; return ({ dispatch }) => (next) => - (action: AnyAction) => { + (action) => { let isPending = false; let isFulfilled = false; let isRejected = false; @@ -39,7 +55,7 @@ export const loadingBarMiddleware = ( else if (isThunkActionFulfilled(action)) isFulfilled = true; else if (isThunkActionRejected(action)) isRejected = true; } else if ( - action.type && + isActionWithSkipLoading(action) && !action.skipLoading && typeof action.type === 'string' ) { diff --git a/app/javascript/mastodon/store/middlewares/sounds.ts b/app/javascript/mastodon/store/middlewares/sounds.ts index 09ade7d753..51839f427a 100644 --- a/app/javascript/mastodon/store/middlewares/sounds.ts +++ b/app/javascript/mastodon/store/middlewares/sounds.ts @@ -1,4 +1,5 @@ -import type { Middleware, AnyAction } from 'redux'; +import { isAction } from '@reduxjs/toolkit'; +import type { Middleware, UnknownAction } from '@reduxjs/toolkit'; import ready from 'mastodon/ready'; import { assetHost } from 'mastodon/utils/config'; @@ -10,6 +11,21 @@ interface AudioSource { type: string; } +interface ActionWithMetaSound extends UnknownAction { + meta: { sound: string }; +} + +function isActionWithMetaSound(action: unknown): action is ActionWithMetaSound { + return ( + isAction(action) && + 'meta' in action && + typeof action.meta === 'object' && + !!action.meta && + 'sound' in action.meta && + typeof action.meta.sound === 'string' + ); +} + const createAudio = (sources: AudioSource[]) => { const audio = new Audio(); sources.forEach(({ type, src }) => { @@ -34,7 +50,10 @@ const play = (audio: HTMLAudioElement) => { void audio.play(); }; -export const soundsMiddleware = (): Middleware => { +export const soundsMiddleware = (): Middleware< + Record, + RootState +> => { const soundCache: Record = {}; void ready(() => { @@ -50,15 +69,15 @@ export const soundsMiddleware = (): Middleware => { ]); }); - return () => - (next) => - (action: AnyAction & { meta?: { sound?: string } }) => { - const sound = action.meta?.sound; + return () => (next) => (action) => { + if (isActionWithMetaSound(action)) { + const sound = action.meta.sound; if (sound && Object.hasOwn(soundCache, sound)) { play(soundCache[sound]); } + } - return next(action); - }; + return next(action); + }; }; diff --git a/app/javascript/mastodon/store/typed_functions.ts b/app/javascript/mastodon/store/typed_functions.ts index f1e71385a8..46a10b8b47 100644 --- a/app/javascript/mastodon/store/typed_functions.ts +++ b/app/javascript/mastodon/store/typed_functions.ts @@ -1,7 +1,7 @@ -import type { TypedUseSelectorHook } from 'react-redux'; -import { useDispatch, useSelector } from 'react-redux'; - import { createAsyncThunk } from '@reduxjs/toolkit'; +import type { TypedUseSelectorHook } from 'react-redux'; +// eslint-disable-next-line @typescript-eslint/no-restricted-imports +import { useDispatch, useSelector } from 'react-redux'; import type { AppDispatch, RootState } from './store'; diff --git a/config/webpack/rules/babel.js b/config/webpack/rules/babel.js index 2811a1674d..c7bf886e79 100644 --- a/config/webpack/rules/babel.js +++ b/config/webpack/rules/babel.js @@ -7,8 +7,14 @@ module.exports = { include: [ settings.source_path, ...settings.resolved_paths, + 'node_modules/@reduxjs' ].map(p => resolve(p)), - exclude: /node_modules/, + exclude: function(modulePath) { + return ( + /node_modules/.test(modulePath) && + !/@reduxjs/.test(modulePath) + ); + }, use: [ { loader: 'babel-loader', diff --git a/package.json b/package.json index a5b6a228ca..16ed4decaa 100644 --- a/package.json +++ b/package.json @@ -51,7 +51,7 @@ "@github/webauthn-json": "^2.1.1", "@material-symbols/svg-600": "^0.14.0", "@rails/ujs": "^7.1.1", - "@reduxjs/toolkit": "^1.9.5", + "@reduxjs/toolkit": "^2.0.1", "@svgr/webpack": "^5.5.0", "arrow-key-navigation": "^1.2.0", "async-mutex": "^0.4.0", @@ -106,8 +106,8 @@ "react-motion": "^0.5.2", "react-notification": "^6.8.5", "react-overlays": "^5.2.1", - "react-redux": "^8.0.4", - "react-redux-loading-bar": "^5.0.4", + "react-redux": "^9.0.4", + "react-redux-loading-bar": "^5.0.8", "react-router": "^5.3.4", "react-router-dom": "^5.3.4", "react-router-scroll-4": "^1.0.0-beta.1", @@ -116,12 +116,9 @@ "react-swipeable-views": "^0.14.0", "react-textarea-autosize": "^8.4.1", "react-toggle": "^4.1.3", - "redux": "^4.2.1", "redux-immutable": "^4.0.0", - "redux-thunk": "^2.4.2", "regenerator-runtime": "^0.14.0", "requestidlecallback": "^0.3.0", - "reselect": "^4.1.8", "rimraf": "^5.0.1", "sass": "^1.62.1", "sass-loader": "^10.2.0", diff --git a/yarn.lock b/yarn.lock index 70d98332ad..71ed44a446 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1483,7 +1483,7 @@ __metadata: languageName: node linkType: hard -"@babel/runtime@npm:^7.0.0, @babel/runtime@npm:^7.1.2, @babel/runtime@npm:^7.11.2, @babel/runtime@npm:^7.12.0, @babel/runtime@npm:^7.12.1, @babel/runtime@npm:^7.12.13, @babel/runtime@npm:^7.12.5, @babel/runtime@npm:^7.13.8, @babel/runtime@npm:^7.18.3, @babel/runtime@npm:^7.2.0, @babel/runtime@npm:^7.20.13, @babel/runtime@npm:^7.22.3, @babel/runtime@npm:^7.23.2, @babel/runtime@npm:^7.3.1, @babel/runtime@npm:^7.5.5, @babel/runtime@npm:^7.6.3, @babel/runtime@npm:^7.8.4, @babel/runtime@npm:^7.8.7, @babel/runtime@npm:^7.9.2": +"@babel/runtime@npm:^7.0.0, @babel/runtime@npm:^7.1.2, @babel/runtime@npm:^7.11.2, @babel/runtime@npm:^7.12.0, @babel/runtime@npm:^7.12.13, @babel/runtime@npm:^7.12.5, @babel/runtime@npm:^7.13.8, @babel/runtime@npm:^7.18.3, @babel/runtime@npm:^7.2.0, @babel/runtime@npm:^7.20.13, @babel/runtime@npm:^7.22.3, @babel/runtime@npm:^7.23.2, @babel/runtime@npm:^7.3.1, @babel/runtime@npm:^7.5.5, @babel/runtime@npm:^7.6.3, @babel/runtime@npm:^7.8.4, @babel/runtime@npm:^7.8.7, @babel/runtime@npm:^7.9.2": version: 7.23.7 resolution: "@babel/runtime@npm:7.23.7" dependencies: @@ -2302,7 +2302,7 @@ __metadata: "@github/webauthn-json": "npm:^2.1.1" "@material-symbols/svg-600": "npm:^0.14.0" "@rails/ujs": "npm:^7.1.1" - "@reduxjs/toolkit": "npm:^1.9.5" + "@reduxjs/toolkit": "npm:^2.0.1" "@svgr/webpack": "npm:^5.5.0" "@testing-library/jest-dom": "npm:^6.0.0" "@testing-library/react": "npm:^14.0.0" @@ -2410,8 +2410,8 @@ __metadata: react-motion: "npm:^0.5.2" react-notification: "npm:^6.8.5" react-overlays: "npm:^5.2.1" - react-redux: "npm:^8.0.4" - react-redux-loading-bar: "npm:^5.0.4" + react-redux: "npm:^9.0.4" + react-redux-loading-bar: "npm:^5.0.8" react-router: "npm:^5.3.4" react-router-dom: "npm:^5.3.4" react-router-scroll-4: "npm:^1.0.0-beta.1" @@ -2421,12 +2421,9 @@ __metadata: react-test-renderer: "npm:^18.2.0" react-textarea-autosize: "npm:^8.4.1" react-toggle: "npm:^4.1.3" - redux: "npm:^4.2.1" redux-immutable: "npm:^4.0.0" - redux-thunk: "npm:^2.4.2" regenerator-runtime: "npm:^0.14.0" requestidlecallback: "npm:^0.3.0" - reselect: "npm:^4.1.8" rimraf: "npm:^5.0.1" sass: "npm:^1.62.1" sass-loader: "npm:^10.2.0" @@ -2622,23 +2619,23 @@ __metadata: languageName: node linkType: hard -"@reduxjs/toolkit@npm:^1.9.5": - version: 1.9.7 - resolution: "@reduxjs/toolkit@npm:1.9.7" +"@reduxjs/toolkit@npm:^2.0.1": + version: 2.0.1 + resolution: "@reduxjs/toolkit@npm:2.0.1" dependencies: - immer: "npm:^9.0.21" - redux: "npm:^4.2.1" - redux-thunk: "npm:^2.4.2" - reselect: "npm:^4.1.8" + immer: "npm:^10.0.3" + redux: "npm:^5.0.0" + redux-thunk: "npm:^3.1.0" + reselect: "npm:^5.0.1" peerDependencies: react: ^16.9.0 || ^17.0.0 || ^18 - react-redux: ^7.2.1 || ^8.0.2 + react-redux: ^7.2.1 || ^8.1.3 || ^9.0.0 peerDependenciesMeta: react: optional: true react-redux: optional: true - checksum: fa0aa4b7c6973ac87ce0ac7e45faa02c73b66c4ee0bc950d178494539a42a1bb908d109297102458b7ea14d5e7dae356e7a7ce9a1b9849b0e8451e6dd70fca9c + checksum: 161b9b8e11d9688890ab97b604a4c10c0d41b1369425a5fa821586932db4cd5a391d15799732b3612e6120a6336458ff577ff254219315c05ecd68da5d15fd79 languageName: node linkType: hard @@ -9128,10 +9125,10 @@ __metadata: languageName: node linkType: hard -"immer@npm:^9.0.21": - version: 9.0.21 - resolution: "immer@npm:9.0.21" - checksum: 03ea3ed5d4d72e8bd428df4a38ad7e483ea8308e9a113d3b42e0ea2cc0cc38340eb0a6aca69592abbbf047c685dbda04e3d34bf2ff438ab57339ed0a34cc0a05 +"immer@npm:^10.0.3": + version: 10.0.3 + resolution: "immer@npm:10.0.3" + checksum: 282a4f8479a40f7d12b2b3243c095e3e892bf99058e2ffcdd6b8e9fd143e6a90f2717ab9b6c8b97c927ffb8054465c8f647056f41660dbfd672e240cf1063503 languageName: node linkType: hard @@ -13104,7 +13101,17 @@ __metadata: languageName: node linkType: hard -"postcss-selector-parser@npm:^6.0.11, postcss-selector-parser@npm:^6.0.13, postcss-selector-parser@npm:^6.0.15, postcss-selector-parser@npm:^6.0.2, postcss-selector-parser@npm:^6.0.4": +"postcss-selector-parser@npm:^6.0.11, postcss-selector-parser@npm:^6.0.13, postcss-selector-parser@npm:^6.0.2, postcss-selector-parser@npm:^6.0.4": + version: 6.0.13 + resolution: "postcss-selector-parser@npm:6.0.13" + dependencies: + cssesc: "npm:^3.0.0" + util-deprecate: "npm:^1.0.2" + checksum: 51f099b27f7c7198ea1826470ef0adfa58b3bd3f59b390fda123baa0134880a5fa9720137b6009c4c1373357b144f700b0edac73335d0067422063129371444e + languageName: node + linkType: hard + +"postcss-selector-parser@npm:^6.0.15": version: 6.0.15 resolution: "postcss-selector-parser@npm:6.0.15" dependencies: @@ -13693,7 +13700,7 @@ __metadata: languageName: node linkType: hard -"react-redux-loading-bar@npm:^5.0.4": +"react-redux-loading-bar@npm:^5.0.8": version: 5.0.8 resolution: "react-redux-loading-bar@npm:5.0.8" dependencies: @@ -13708,35 +13715,25 @@ __metadata: languageName: node linkType: hard -"react-redux@npm:^8.0.4": - version: 8.1.3 - resolution: "react-redux@npm:8.1.3" +"react-redux@npm:^9.0.4": + version: 9.0.4 + resolution: "react-redux@npm:9.0.4" dependencies: - "@babel/runtime": "npm:^7.12.1" - "@types/hoist-non-react-statics": "npm:^3.3.1" "@types/use-sync-external-store": "npm:^0.0.3" - hoist-non-react-statics: "npm:^3.3.2" - react-is: "npm:^18.0.0" use-sync-external-store: "npm:^1.0.0" peerDependencies: - "@types/react": ^16.8 || ^17.0 || ^18.0 - "@types/react-dom": ^16.8 || ^17.0 || ^18.0 - react: ^16.8 || ^17.0 || ^18.0 - react-dom: ^16.8 || ^17.0 || ^18.0 - react-native: ">=0.59" - redux: ^4 || ^5.0.0-beta.0 + "@types/react": ^18.2.25 + react: ^18.0 + react-native: ">=0.69" + redux: ^5.0.0 peerDependenciesMeta: "@types/react": optional: true - "@types/react-dom": - optional: true - react-dom: - optional: true react-native: optional: true redux: optional: true - checksum: 64c8be2765568dc66a3c442a41dd0ed74fe048d5ceb7a4fe72e5bac3d3687996a7115f57b5156af7406521087065a0e60f9194318c8ca99c55e9ce48558980ce + checksum: 23af10014b129aeb051de729bde01de21175170b860deefb7ad83483feab5816253f770a4cea93333fc22a53ac9ac699b27f5c3705c388dab53dbcb2906a571a languageName: node linkType: hard @@ -14039,16 +14036,16 @@ __metadata: languageName: node linkType: hard -"redux-thunk@npm:^2.4.2": - version: 2.4.2 - resolution: "redux-thunk@npm:2.4.2" +"redux-thunk@npm:^3.1.0": + version: 3.1.0 + resolution: "redux-thunk@npm:3.1.0" peerDependencies: - redux: ^4 - checksum: e202d6ef7dfa7df08ed24cb221aa89d6c84dbaa7d65fe90dbd8e826d0c10d801f48388f9a7598a4fd970ecbc93d335014570a61ca7bc8bf569eab5de77b31a3c + redux: ^5.0.0 + checksum: 21557f6a30e1b2e3e470933247e51749be7f1d5a9620069a3125778675ce4d178d84bdee3e2a0903427a5c429e3aeec6d4df57897faf93eb83455bc1ef7b66fd languageName: node linkType: hard -"redux@npm:^4.0.0, redux@npm:^4.2.1": +"redux@npm:^4.0.0": version: 4.2.1 resolution: "redux@npm:4.2.1" dependencies: @@ -14057,6 +14054,13 @@ __metadata: languageName: node linkType: hard +"redux@npm:^5.0.0": + version: 5.0.1 + resolution: "redux@npm:5.0.1" + checksum: b10c28357194f38e7d53b760ed5e64faa317cc63de1fb95bc5d9e127fab956392344368c357b8e7a9bedb0c35b111e7efa522210cfdc3b3c75e5074718e9069c + languageName: node + linkType: hard + "reflect.getprototypeof@npm:^1.0.4": version: 1.0.4 resolution: "reflect.getprototypeof@npm:1.0.4" @@ -14226,10 +14230,10 @@ __metadata: languageName: node linkType: hard -"reselect@npm:^4.1.8": - version: 4.1.8 - resolution: "reselect@npm:4.1.8" - checksum: 06a305a504affcbb67dd0561ddc8306b35796199c7e15b38934c80606938a021eadcf68cfd58e7bb5e17786601c37602a3362a4665c7bf0a96c1041ceee9d0b7 +"reselect@npm:^5.0.1": + version: 5.0.1 + resolution: "reselect@npm:5.0.1" + checksum: 0724b4555cd6411849de334a75177780f127af849eb71c4b709966d07ade8090d125c0c926dc6cf936866d23ebadda6aad1da93cd8340525323b889f25d56d51 languageName: node linkType: hard From 4ed663a94fc53e5bd352e92afaff55f187218078 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Mon, 8 Jan 2024 11:02:55 +0000 Subject: [PATCH 35/61] Update DefinitelyTyped types (non-major) (#28638) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- yarn.lock | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/yarn.lock b/yarn.lock index 71ed44a446..da8ddf214a 100644 --- a/yarn.lock +++ b/yarn.lock @@ -3027,11 +3027,11 @@ __metadata: linkType: hard "@types/cors@npm:^2.8.16": - version: 2.8.16 - resolution: "@types/cors@npm:2.8.16" + version: 2.8.17 + resolution: "@types/cors@npm:2.8.17" dependencies: "@types/node": "npm:*" - checksum: ebcfb325b102739249bbaa4845cf1cf4830baf5490a32bcd1a85cd9b8c4d4b9eaaaea94423e454b5b7c9da77e46a64db80d2381d3bc3f940d15d13814e87b70a + checksum: 457364c28c89f3d9ed34800e1de5c6eaaf344d1bb39af122f013322a50bc606eb2aa6f63de4e41a7a08ba7ef454473926c94a830636723da45bf786df032696d languageName: node linkType: hard @@ -3490,13 +3490,13 @@ __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.46 - resolution: "@types/react@npm:18.2.46" + version: 18.2.47 + resolution: "@types/react@npm:18.2.47" dependencies: "@types/prop-types": "npm:*" "@types/scheduler": "npm:*" csstype: "npm:^3.0.2" - checksum: 814cc67107e5e69501d65bfc371cc2c716665d2a3608d395a2f81e24c3a2875db28e2cad717dfb17017eabcffd1d68ee2c9e09ecaba3f7108d5b7fbb9888ebab + checksum: e98ea1827fe60636d0f7ce206397159a29fc30613fae43e349e32c10ad3c0b7e0ed2ded2f3239e07bd5a3cba8736b6114ba196acccc39905ca4a06f56a8d2841 languageName: node linkType: hard From 8a44b182e8c4890517ba978393a65a0a8f2a3579 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Mon, 8 Jan 2024 12:03:04 +0100 Subject: [PATCH 36/61] Update dependency axios to v1.6.5 (#28620) 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 da8ddf214a..f50fa76d1a 100644 --- a/yarn.lock +++ b/yarn.lock @@ -4686,13 +4686,13 @@ __metadata: linkType: hard "axios@npm:^1.4.0": - version: 1.6.4 - resolution: "axios@npm:1.6.4" + version: 1.6.5 + resolution: "axios@npm:1.6.5" dependencies: follow-redirects: "npm:^1.15.4" form-data: "npm:^4.0.0" proxy-from-env: "npm:^1.1.0" - checksum: daac697fa1ea9865cb48e9edb7eacd99e8a9214997f2d8e886cb61c380a613e5c270078bfc153ac96206680106c223f005f0e4bf2f3b2ddd88e559ecf970521f + checksum: aeb9acf87590d8aa67946072ced38e01ca71f5dfe043782c0ccea667e5dd5c45830c08afac9be3d7c894f09684b8ab2a458f497d197b73621233bcf202d9d468 languageName: node linkType: hard From 2ae53e655c3431336ce685c091e212b70db7792c Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Mon, 8 Jan 2024 12:04:25 +0100 Subject: [PATCH 37/61] Update dependency jsdom to v23.2.0 (#28612) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- yarn.lock | 44 ++++++++++++++++++++++++++++++++------------ 1 file changed, 32 insertions(+), 12 deletions(-) diff --git a/yarn.lock b/yarn.lock index f50fa76d1a..bec7709804 100644 --- a/yarn.lock +++ b/yarn.lock @@ -42,6 +42,17 @@ __metadata: languageName: node linkType: hard +"@asamuzakjp/dom-selector@npm:^2.0.1": + version: 2.0.1 + resolution: "@asamuzakjp/dom-selector@npm:2.0.1" + dependencies: + bidi-js: "npm:^1.0.3" + css-tree: "npm:^2.3.1" + is-potential-custom-element-name: "npm:^1.0.1" + checksum: 232895f16f2f9dfc637764df2529084d16e1c122057766a79b16e1d40808e09fffae28c0f0cc8376f8a1564a85dba9d4b2f140a9a0b65f4f95c960192b797037 + languageName: node + linkType: hard + "@babel/code-frame@npm:^7.0.0, @babel/code-frame@npm:^7.10.4, @babel/code-frame@npm:^7.12.13, @babel/code-frame@npm:^7.22.13, @babel/code-frame@npm:^7.23.5": version: 7.23.5 resolution: "@babel/code-frame@npm:7.23.5" @@ -4950,6 +4961,15 @@ __metadata: languageName: node linkType: hard +"bidi-js@npm:^1.0.3": + version: 1.0.3 + resolution: "bidi-js@npm:1.0.3" + dependencies: + require-from-string: "npm:^2.0.2" + checksum: fdddea4aa4120a34285486f2267526cd9298b6e8b773ad25e765d4f104b6d7437ab4ba542e6939e3ac834a7570bcf121ee2cf6d3ae7cd7082c4b5bedc8f271e1 + languageName: node + linkType: hard + "big-integer@npm:^1.6.44": version: 1.6.51 resolution: "big-integer@npm:1.6.51" @@ -6376,12 +6396,12 @@ __metadata: languageName: node linkType: hard -"cssstyle@npm:^3.0.0": - version: 3.0.0 - resolution: "cssstyle@npm:3.0.0" +"cssstyle@npm:^4.0.1": + version: 4.0.1 + resolution: "cssstyle@npm:4.0.1" dependencies: rrweb-cssom: "npm:^0.6.0" - checksum: 23acee092c1cec670fb7b8110e48abd740dc4e574d3b74848743067cb3377a86a1f64cf02606aabd7bb153785e68c2c1e09ce53295ddf7a4b470b3c7c55ec807 + checksum: cadf9a8b23e11f4c6d63f21291096a0b0be868bd4ab9c799daa2c5b18330e39e5281605f01da906e901b42f742df0f3b3645af6465e83377ff7d15a88ee432a0 languageName: node linkType: hard @@ -10637,10 +10657,11 @@ __metadata: linkType: hard "jsdom@npm:^23.0.0": - version: 23.0.1 - resolution: "jsdom@npm:23.0.1" + version: 23.2.0 + resolution: "jsdom@npm:23.2.0" dependencies: - cssstyle: "npm:^3.0.0" + "@asamuzakjp/dom-selector": "npm:^2.0.1" + cssstyle: "npm:^4.0.1" data-urls: "npm:^5.0.0" decimal.js: "npm:^10.4.3" form-data: "npm:^4.0.0" @@ -10648,7 +10669,6 @@ __metadata: http-proxy-agent: "npm:^7.0.0" https-proxy-agent: "npm:^7.0.2" is-potential-custom-element-name: "npm:^1.0.1" - nwsapi: "npm:^2.2.7" parse5: "npm:^7.1.2" rrweb-cssom: "npm:^0.6.0" saxes: "npm:^6.0.0" @@ -10659,14 +10679,14 @@ __metadata: whatwg-encoding: "npm:^3.1.1" whatwg-mimetype: "npm:^4.0.0" whatwg-url: "npm:^14.0.0" - ws: "npm:^8.14.2" + ws: "npm:^8.16.0" xml-name-validator: "npm:^5.0.0" peerDependencies: canvas: ^2.11.2 peerDependenciesMeta: canvas: optional: true - checksum: 13b2b3693ccb40215d1cce77bac7a295414ee4c0a06e30167f8087c9867145ba23dbd592bd95a801cadd7b3698bfd20b9c3f2c26fd8422607f22609ed2e404ef + checksum: b062af50f7be59d914ba75236b7817c848ef3cd007aea1d6b8020a41eb263b7d5bd2652298106e9756b56892f773d990598778d02adab7d0d0d8e58726fc41d3 languageName: node linkType: hard @@ -11964,7 +11984,7 @@ __metadata: languageName: node linkType: hard -"nwsapi@npm:^2.2.2, nwsapi@npm:^2.2.7": +"nwsapi@npm:^2.2.2": version: 2.2.7 resolution: "nwsapi@npm:2.2.7" checksum: 44be198adae99208487a1c886c0a3712264f7bbafa44368ad96c003512fed2753d4e22890ca1e6edb2690c3456a169f2a3c33bfacde1905cf3bf01c7722464db @@ -17577,7 +17597,7 @@ __metadata: languageName: node linkType: hard -"ws@npm:^8.11.0, ws@npm:^8.12.1, ws@npm:^8.14.2": +"ws@npm:^8.11.0, ws@npm:^8.12.1, ws@npm:^8.16.0": version: 8.16.0 resolution: "ws@npm:8.16.0" peerDependencies: From 832b92ac3eebb5d65f5c6a6a3d90129e26f2d59f Mon Sep 17 00:00:00 2001 From: Matt Jankowski Date: Mon, 8 Jan 2024 06:05:10 -0500 Subject: [PATCH 38/61] Add attachment check to spec/service/suspend_account_service spec (#28619) --- spec/services/suspend_account_service_spec.rb | 15 +++++++++++---- 1 file changed, 11 insertions(+), 4 deletions(-) diff --git a/spec/services/suspend_account_service_spec.rb b/spec/services/suspend_account_service_spec.rb index b309ce511e..dcc8dbfd37 100644 --- a/spec/services/suspend_account_service_spec.rb +++ b/spec/services/suspend_account_service_spec.rb @@ -16,17 +16,24 @@ RSpec.describe SuspendAccountService, type: :service do list.accounts << account account.suspend! + + Fabricate(:media_attachment, file: attachment_fixture('boop.ogg'), account: account) end - it 'unmerges from feeds of local followers and preserves suspended flag' do + it 'unmerges from feeds of local followers and changes file mode and preserves suspended flag' do expect { subject } - .to_not change_suspended_flag + .to change_file_mode + .and not_change_suspended_flag expect(FeedManager.instance).to have_received(:unmerge_from_home).with(account, local_follower) expect(FeedManager.instance).to have_received(:unmerge_from_list).with(account, list) end - def change_suspended_flag - change(account, :suspended?) + def change_file_mode + change { File.stat(account.media_attachments.first.file.path).mode } + end + + def not_change_suspended_flag + not_change(account, :suspended?) end end From 57f49c819184d7ecb6d789889671d5d6c7b4167a Mon Sep 17 00:00:00 2001 From: Matt Jankowski Date: Mon, 8 Jan 2024 06:09:50 -0500 Subject: [PATCH 39/61] Use Arel `nulls_first` method in ordering CustomEmojiFilter scope (#28614) --- app/models/custom_emoji_filter.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/models/custom_emoji_filter.rb b/app/models/custom_emoji_filter.rb index ed7a8dda15..870cc71974 100644 --- a/app/models/custom_emoji_filter.rb +++ b/app/models/custom_emoji_filter.rb @@ -31,7 +31,7 @@ class CustomEmojiFilter def scope_for(key, value) case key.to_s when 'local' - CustomEmoji.local.left_joins(:category).reorder(Arel.sql('custom_emoji_categories.name ASC NULLS FIRST, custom_emojis.shortcode ASC')) + CustomEmoji.local.left_joins(:category).reorder(CustomEmojiCategory.arel_table[:name].asc.nulls_first).order(shortcode: :asc) when 'remote' CustomEmoji.remote when 'by_domain' From 202951e6d97e808a487499b1e680887309fab61a Mon Sep 17 00:00:00 2001 From: Matt Jankowski Date: Mon, 8 Jan 2024 06:15:36 -0500 Subject: [PATCH 40/61] Use Arel `in_order_of` method to generate CASE for `DomainBlock.by_severity` (#28617) --- app/models/domain_block.rb | 2 +- lib/mastodon/cli/maintenance.rb | 3 ++- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/app/models/domain_block.rb b/app/models/domain_block.rb index ff23f8fcc4..f8058324a3 100644 --- a/app/models/domain_block.rb +++ b/app/models/domain_block.rb @@ -31,7 +31,7 @@ class DomainBlock < ApplicationRecord scope :matches_domain, ->(value) { where(arel_table[:domain].matches("%#{value}%")) } scope :with_user_facing_limitations, -> { where(severity: [:silence, :suspend]) } scope :with_limitations, -> { where(severity: [:silence, :suspend]).or(where(reject_media: true)) } - scope :by_severity, -> { order(Arel.sql('(CASE severity WHEN 0 THEN 1 WHEN 1 THEN 2 WHEN 2 THEN 0 END), domain')) } + scope :by_severity, -> { in_order_of(:severity, %w(noop silence suspend)).order(:domain) } def to_log_human_identifier domain diff --git a/lib/mastodon/cli/maintenance.rb b/lib/mastodon/cli/maintenance.rb index 7b3a9852a6..f37662aa06 100644 --- a/lib/mastodon/cli/maintenance.rb +++ b/lib/mastodon/cli/maintenance.rb @@ -41,7 +41,8 @@ module Mastodon::CLI class SoftwareUpdate < ApplicationRecord; end class DomainBlock < ApplicationRecord - scope :by_severity, -> { order(Arel.sql('(CASE severity WHEN 0 THEN 1 WHEN 1 THEN 2 WHEN 2 THEN 0 END), domain')) } + enum severity: { silence: 0, suspend: 1, noop: 2 } + scope :by_severity, -> { in_order_of(:severity, %w(noop silence suspend)).order(:domain) } end class PreviewCard < ApplicationRecord From aa6d07dbd9c9ae20e690c88f34d3764d91ee2cef Mon Sep 17 00:00:00 2001 From: Matt Jankowski Date: Mon, 8 Jan 2024 06:20:59 -0500 Subject: [PATCH 41/61] Use normalizes to prepare CustomEmoji `domain` value (#28624) --- app/models/custom_emoji.rb | 6 +----- spec/models/custom_emoji_spec.rb | 21 ++++++++++++++++----- 2 files changed, 17 insertions(+), 10 deletions(-) diff --git a/app/models/custom_emoji.rb b/app/models/custom_emoji.rb index 97b1c63bf3..550f005d59 100644 --- a/app/models/custom_emoji.rb +++ b/app/models/custom_emoji.rb @@ -41,7 +41,7 @@ class CustomEmoji < ApplicationRecord has_attached_file :image, styles: { static: { format: 'png', convert_options: '-coalesce +profile "!icc,*" +set date:modify +set date:create +set date:timestamp' } }, validate_media_type: false - before_validation :downcase_domain + normalizes :domain, with: ->(domain) { domain.downcase } validates_attachment :image, content_type: { content_type: IMAGE_MIME_TYPES }, presence: true, size: { less_than: LIMIT } validates :shortcode, uniqueness: { scope: :domain }, format: { with: SHORTCODE_ONLY_RE }, length: { minimum: 2 } @@ -95,8 +95,4 @@ class CustomEmoji < ApplicationRecord def remove_entity_cache Rails.cache.delete(EntityCache.instance.to_key(:emoji, shortcode, domain)) end - - def downcase_domain - self.domain = domain.downcase unless domain.nil? - end end diff --git a/spec/models/custom_emoji_spec.rb b/spec/models/custom_emoji_spec.rb index 06affd634a..a0903e5978 100644 --- a/spec/models/custom_emoji_spec.rb +++ b/spec/models/custom_emoji_spec.rb @@ -78,12 +78,23 @@ RSpec.describe CustomEmoji do end end - describe 'pre_validation' do - let(:custom_emoji) { Fabricate(:custom_emoji, domain: 'wWw.MaStOdOn.CoM') } + describe 'Normalizations' do + describe 'downcase domain value' do + context 'with a mixed case domain value' do + it 'normalizes the value to downcased' do + custom_emoji = Fabricate.build(:custom_emoji, domain: 'wWw.MaStOdOn.CoM') - it 'downcases' do - custom_emoji.valid? - expect(custom_emoji.domain).to eq('www.mastodon.com') + expect(custom_emoji.domain).to eq('www.mastodon.com') + end + end + + context 'with a nil domain value' do + it 'leaves the value as nil' do + custom_emoji = Fabricate.build(:custom_emoji, domain: nil) + + expect(custom_emoji.domain).to be_nil + end + end end end end From 1bc5a52139b4a33568c7c9bab96bd24a291fc482 Mon Sep 17 00:00:00 2001 From: Matt Jankowski Date: Mon, 8 Jan 2024 06:22:16 -0500 Subject: [PATCH 42/61] Extract SQL heredoc method for Announcement scopes (#28613) --- app/models/announcement.rb | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/app/models/announcement.rb b/app/models/announcement.rb index 83a8d3682c..00529766a4 100644 --- a/app/models/announcement.rb +++ b/app/models/announcement.rb @@ -21,8 +21,8 @@ class Announcement < ApplicationRecord scope :unpublished, -> { where(published: false) } scope :published, -> { where(published: true) } scope :without_muted, ->(account) { joins("LEFT OUTER JOIN announcement_mutes ON announcement_mutes.announcement_id = announcements.id AND announcement_mutes.account_id = #{account.id}").where(announcement_mutes: { id: nil }) } - scope :chronological, -> { order(Arel.sql('COALESCE(announcements.starts_at, announcements.scheduled_at, announcements.published_at, announcements.created_at) ASC')) } - scope :reverse_chronological, -> { order(Arel.sql('COALESCE(announcements.starts_at, announcements.scheduled_at, announcements.published_at, announcements.created_at) DESC')) } + scope :chronological, -> { order(coalesced_chronology_timestamps.asc) } + scope :reverse_chronological, -> { order(coalesced_chronology_timestamps.desc) } has_many :announcement_mutes, dependent: :destroy has_many :announcement_reactions, dependent: :destroy @@ -33,6 +33,16 @@ class Announcement < ApplicationRecord before_validation :set_published, on: :create + class << self + def coalesced_chronology_timestamps + Arel.sql( + <<~SQL.squish + COALESCE(announcements.starts_at, announcements.scheduled_at, announcements.published_at, announcements.created_at) + SQL + ) + end + end + def to_log_human_identifier text end From 157fc699547e409a2849a1842456ce36d5d545b1 Mon Sep 17 00:00:00 2001 From: Claire Date: Mon, 8 Jan 2024 13:29:05 +0100 Subject: [PATCH 43/61] Make request_pool_spec tests more robust (#28610) --- spec/lib/request_pool_spec.rb | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-) diff --git a/spec/lib/request_pool_spec.rb b/spec/lib/request_pool_spec.rb index bdb0859d76..a31d078327 100644 --- a/spec/lib/request_pool_spec.rb +++ b/spec/lib/request_pool_spec.rb @@ -33,14 +33,12 @@ describe RequestPool do subject - threads = Array.new(3) do + threads = Array.new(5) do Thread.new do - 2.times do - subject.with('http://example.com') do |http_client| - http_client.get('/').flush - # Nudge scheduler to yield and exercise the full pool - sleep(0) - end + subject.with('http://example.com') do |http_client| + http_client.get('/').flush + # Nudge scheduler to yield and exercise the full pool + sleep(0.01) end end end From cc67943df293e3d3d721cc416e613ed3ac1cff7f Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Mon, 8 Jan 2024 13:46:25 +0100 Subject: [PATCH 44/61] New Crowdin Translations (automated) (#28627) Co-authored-by: GitHub Actions --- app/javascript/mastodon/locales/br.json | 97 ++++++++++-- app/javascript/mastodon/locales/de.json | 2 +- app/javascript/mastodon/locales/ia.json | 193 ++++++++++++++++++++++- app/javascript/mastodon/locales/ja.json | 4 +- app/javascript/mastodon/locales/lad.json | 1 + app/javascript/mastodon/locales/vi.json | 38 ++--- config/locales/bg.yml | 1 + config/locales/br.yml | 30 +++- config/locales/de.yml | 1 + config/locales/devise.ia.yml | 6 + config/locales/devise.ie.yml | 24 +++ config/locales/doorkeeper.br.yml | 1 + config/locales/doorkeeper.ia.yml | 13 ++ config/locales/doorkeeper.ie.yml | 21 +++ config/locales/et.yml | 1 + config/locales/fr-QC.yml | 1 + config/locales/fr.yml | 1 + config/locales/ia.yml | 47 ++++++ config/locales/ie.yml | 18 +++ config/locales/is.yml | 1 + config/locales/ja.yml | 1 + config/locales/lad.yml | 1 + config/locales/nl.yml | 2 +- config/locales/nn.yml | 2 +- config/locales/simple_form.br.yml | 7 +- config/locales/simple_form.ie.yml | 27 ++++ config/locales/sk.yml | 2 + config/locales/sv.yml | 1 + config/locales/vi.yml | 4 +- config/locales/zh-TW.yml | 1 + 30 files changed, 510 insertions(+), 39 deletions(-) diff --git a/app/javascript/mastodon/locales/br.json b/app/javascript/mastodon/locales/br.json index bea8b27b77..462a5b3393 100644 --- a/app/javascript/mastodon/locales/br.json +++ b/app/javascript/mastodon/locales/br.json @@ -21,6 +21,7 @@ "account.blocked": "Stanket", "account.browse_more_on_origin_server": "Furchal pelloc'h war ar profil orin", "account.cancel_follow_request": "Nullañ ar reked heuliañ", + "account.copy": "Eilañ al liamm war-zu ho profil", "account.disable_notifications": "Paouez d'am c'hemenn pa vez embannet traoù gant @{name}", "account.domain_blocked": "Domani stanket", "account.edit_profile": "Kemmañ ar profil", @@ -28,8 +29,9 @@ "account.endorse": "Lakaat war-wel war ar profil", "account.featured_tags.last_status_at": "Toud diwezhañ : {date}", "account.featured_tags.last_status_never": "Toud ebet", - "account.featured_tags.title": "Penngerioù-klik {name}", + "account.featured_tags.title": "Hashtagoù pennañ {name}", "account.follow": "Heuliañ", + "account.follow_back": "Heuliañ d'ho tro", "account.followers": "Tud koumanantet", "account.followers.empty": "Den na heul an implijer·ez-mañ c'hoazh.", "account.followers_counter": "{count, plural, other{{counter} Heulier·ez}}", @@ -38,6 +40,7 @@ "account.follows.empty": "An implijer·ez-mañ na heul den ebet.", "account.go_to_profile": "Gwelet ar profil", "account.hide_reblogs": "Kuzh skignadennoù gant @{name}", + "account.in_memoriam": "E koun.", "account.joined_short": "Amañ abaoe", "account.languages": "Cheñch ar yezhoù koumanantet", "account.link_verified_on": "Gwiriet eo bet perc'hennidigezh al liamm d'an deiziad-mañ : {date}", @@ -49,11 +52,13 @@ "account.mute_notifications_short": "Kuzhat ar c'hemennoù", "account.mute_short": "Kuzhat", "account.muted": "Kuzhet", + "account.no_bio": "Deskrivadur ebet da gaout.", "account.open_original_page": "Digeriñ ar bajenn orin", - "account.posts": "Toudoù", - "account.posts_with_replies": "Toudoù ha respontoù", + "account.posts": "Embannadurioù", + "account.posts_with_replies": "Embannadurioù ha respontoù", "account.report": "Disklêriañ @{name}", "account.requested": "O c'hortoz an asant. Klikit evit nullañ ar goulenn heuliañ", + "account.requested_follow": "Gant {name} eo bet goulennet ho heuliañ", "account.share": "Skignañ profil @{name}", "account.show_reblogs": "Diskouez skignadennoù @{name}", "account.statuses_counter": "{count, plural, one {{counter} Toud} two {{counter} Doud} other {{counter} a Doudoù}}", @@ -102,6 +107,7 @@ "column.community": "Red-amzer lec'hel", "column.directory": "Mont a-dreuz ar profiloù", "column.domain_blocks": "Domani berzet", + "column.favourites": "Muiañ-karet", "column.follow_requests": "Rekedoù heuliañ", "column.home": "Degemer", "column.lists": "Listennoù", @@ -122,6 +128,9 @@ "community.column_settings.remote_only": "Nemet a-bell", "compose.language.change": "Cheñch yezh", "compose.language.search": "Klask yezhoù...", + "compose.published.body": "Embannet.", + "compose.published.open": "Digeriñ", + "compose.saved.body": "Enrollet.", "compose_form.direct_message_warning_learn_more": "Gouzout hiroc'h", "compose_form.encryption_warning": "Toudoù war Mastodon na vezont ket sifret penn-da-benn. Na rannit ket titouroù kizidik dre Mastodon.", "compose_form.hashtag_warning": "This post won't be listed under any hashtag as it is unlisted. Only public posts can be searched by hashtag.", @@ -158,6 +167,7 @@ "confirmations.discard_edit_media.message": "Bez ez eus kemmoù n'int ket enrollet e deskrivadur ar media pe ar rakwel, nullañ anezho evelato?", "confirmations.domain_block.confirm": "Berzañ an domani a-bezh", "confirmations.domain_block.message": "Ha sur oc'h e fell deoc'h berzañ an {domain} a-bezh? Peurvuiañ eo trawalc'h berzañ pe mudañ un nebeud implijer·ezed·ien. Ne welot danvez ebet o tont eus an domani-mañ. Dilamet e vo ar c'houmanantoù war an domani-mañ.", + "confirmations.edit.confirm": "Kemmañ", "confirmations.logout.confirm": "Digevreañ", "confirmations.logout.message": "Ha sur oc'h e fell deoc'h digevreañ ?", "confirmations.mute.confirm": "Kuzhat", @@ -172,7 +182,9 @@ "conversation.mark_as_read": "Merkañ evel lennet", "conversation.open": "Gwelout ar gaozeadenn", "conversation.with": "Gant {names}", + "copy_icon_button.copied": "Eilet er golver", "copypaste.copied": "Eilet", + "copypaste.copy_to_clipboard": "Eilañ er golver", "directory.federated": "Eus ar fedibed anavezet", "directory.local": "Eus {domain} hepken", "directory.new_arrivals": "Degouezhet a-nevez", @@ -209,7 +221,8 @@ "empty_column.domain_blocks": "N'eus domani kuzh ebet c'hoazh.", "empty_column.explore_statuses": "N'eus tuadur ebet evit c'hoazh. Distroit diwezhatoc'h !", "empty_column.follow_requests": "N'ho peus reked heuliañ ebet c'hoazh. Pa vo resevet unan e teuio war wel amañ.", - "empty_column.hashtag": "N'eus netra er ger-klik-mañ c'hoazh.", + "empty_column.followed_tags": "N'emaoc'h oc'h heuliañ hashtag ebet evit poent. Pa vioc'h e vo d'o gwelet amañ.", + "empty_column.hashtag": "N'eus netra en hashtag-mañ c'hoazh.", "empty_column.home": "Goullo eo ho red-amzer degemer! Kit da weladenniñ {public} pe implijit ar c'hlask evit kregiñ ganti ha kejañ gant implijer·ien·ezed all.", "empty_column.list": "Goullo eo al listenn-mañ evit c'hoazh. Pa vo embannet toudoù nevez gant e izili e teuint war wel amañ.", "empty_column.lists": "N'ho peus roll ebet c'hoazh. Pa vo krouet unan ganeoc'h e vo diskouezet amañ.", @@ -223,7 +236,11 @@ "errors.unexpected_crash.copy_stacktrace": "Eilañ ar roudoù diveugañ er golver", "errors.unexpected_crash.report_issue": "Danevellañ ur fazi", "explore.search_results": "Disoc'hoù an enklask", + "explore.suggested_follows": "Tud", "explore.title": "Furchal", + "explore.trending_links": "Keleier", + "explore.trending_statuses": "Embannadurioù", + "explore.trending_tags": "Hashtagoù", "filter_modal.added.context_mismatch_title": "Kenarroud digenglotus !", "filter_modal.added.expired_title": "Sil deuet d'e dermen !", "filter_modal.added.review_and_configure_title": "Arventennoù ar sil", @@ -237,9 +254,13 @@ "filter_modal.select_filter.subtitle": "Implijout ur rummad a zo anezhañ pe krouiñ unan nevez", "filter_modal.select_filter.title": "Silañ an toud-mañ", "filter_modal.title.status": "Silañ un toud", + "firehose.all": "Pep tra", + "firehose.local": "Ar servijer-mañ", + "firehose.remote": "Servijerioù all", "follow_request.authorize": "Aotren", "follow_request.reject": "Nac'hañ", "follow_requests.unlocked_explanation": "Daoust ma n'eo ket ho kont prennet, skipailh {domain} a soñj e fellfe deoc'h gwiriekaat pedadennoù heuliañ deus ar c'hontoù-se diwar-zorn.", + "followed_tags": "Hashtagoù o heuliañ", "footer.about": "Diwar-benn", "footer.directory": "Kavlec'h ar profiloù", "footer.get_app": "Pellgargañ an arload", @@ -247,29 +268,40 @@ "footer.keyboard_shortcuts": "Berradennoù klavier", "footer.privacy_policy": "Reolennoù prevezded", "footer.source_code": "Gwelet kod mammenn", + "footer.status": "Statud", "generic.saved": "Enrollet", "getting_started.heading": "Loc'hañ", - "hashtag.column_header.tag_mode.all": "ha {additional}", + "hashtag.column_header.tag_mode.all": "ha(g) {additional}", "hashtag.column_header.tag_mode.any": "pe {additional}", "hashtag.column_header.tag_mode.none": "hep {additional}", "hashtag.column_settings.select.no_options_message": "N'eus bet kavet ali ebet", - "hashtag.column_settings.select.placeholder": "Ouzhpennañ gerioù-klik…", - "hashtag.column_settings.tag_mode.all": "An holl elfennoù-mañ", + "hashtag.column_settings.select.placeholder": "Ouzhpennañ hashtagoù…", + "hashtag.column_settings.tag_mode.all": "An holl anezho", "hashtag.column_settings.tag_mode.any": "Unan e mesk anezho", "hashtag.column_settings.tag_mode.none": "Hini ebet anezho", "hashtag.column_settings.tag_toggle": "Endelc'her gerioù-alc'hwez ouzhpenn evit ar bannad-mañ", + "hashtag.counter_by_uses": "{count, plural, one {{counter} embannadur} other {{counter} embannadur}}", + "hashtag.counter_by_uses_today": "{count, plural, one {{counter} embannadur} other {{counter} embannadur}} hiziv", "hashtag.follow": "Heuliañ ar ger-klik", - "hashtag.unfollow": "Diheuliañ ar ger-klik", + "hashtag.unfollow": "Paouez heuliañ an hashtag", + "hashtags.and_other": "…{count, plural, one {hag # all} other {ha # all}}", + "home.actions.go_to_explore": "Gwelet petra zo diouzh ar c'hiz", + "home.actions.go_to_suggestions": "Kavout tud da heuliañ", "home.column_settings.basic": "Diazez", "home.column_settings.show_reblogs": "Diskouez ar skignadennoù", "home.column_settings.show_replies": "Diskouez ar respontoù", + "home.explore_prompt.title": "Homañ eo ho pajenn degemer e-barzh Mastodon.", "home.hide_announcements": "Kuzhat ar c'hemennoù", + "home.pending_critical_update.body": "Hizivait ho servijer Mastodon kerkent ha ma c'hallit mar plij!", + "home.pending_critical_update.link": "Gwelet an hizivadennoù", "home.show_announcements": "Diskouez ar c'hemennoù", "interaction_modal.description.follow": "Gant ur gont Mastodon e c'hellit heuliañ {name} evit resev an toudoù a embann war ho red degemer.", "interaction_modal.description.reblog": "Gant ur gont Mastodon e c'hellit skignañ an toud-mañ evit rannañ anezhañ gant ho heulierien·ezed.", "interaction_modal.description.reply": "Gant ur gont Mastodon e c'hellit respont d'an toud-mañ.", + "interaction_modal.no_account_yet": "N'eo ket war vMastodon?", "interaction_modal.on_another_server": "War ur servijer all", "interaction_modal.on_this_server": "War ar servijer-mañ", + "interaction_modal.title.favourite": "Ouzhpennañ embannadur {name} d'ar re vuiañ-karet", "interaction_modal.title.follow": "Heuliañ {name}", "interaction_modal.title.reblog": "Skignañ toud {name}", "interaction_modal.title.reply": "Respont da doud {name}", @@ -285,6 +317,8 @@ "keyboard_shortcuts.direct": "to open direct messages column", "keyboard_shortcuts.down": "Diskennañ er roll", "keyboard_shortcuts.enter": "Digeriñ an toud", + "keyboard_shortcuts.favourite": "Ouzhpennañ an embannadur d'ar re vuiañ-karet", + "keyboard_shortcuts.favourites": "Digeriñ roll an embannadurioù muiañ-karet", "keyboard_shortcuts.federated": "Digeriñ ar red-amzer kevredet", "keyboard_shortcuts.heading": "Berradennoù klavier", "keyboard_shortcuts.home": "Digeriñ ho red-amzer degemer", @@ -314,6 +348,7 @@ "lightbox.next": "Da-heul", "lightbox.previous": "A-raok", "limited_account_hint.action": "Diskouez an aelad memes tra", + "link_preview.author": "Gant {name}", "lists.account.add": "Ouzhpennañ d'al listenn", "lists.account.remove": "Lemel kuit eus al listenn", "lists.delete": "Dilemel al listenn", @@ -328,6 +363,7 @@ "lists.search": "Klask e-touez tud heuliet ganeoc'h", "lists.subheading": "Ho listennoù", "load_pending": "{count, plural, one {# dra nevez} other {# dra nevez}}", + "loading_indicator.label": "O kargañ…", "media_gallery.toggle_visible": "{number, plural, one {Kuzhat ar skeudenn} other {Kuzhat ar skeudenn}}", "mute_modal.duration": "Padelezh", "mute_modal.hide_notifications": "Kuzhat kemenadennoù eus an implijer-se ?", @@ -341,8 +377,10 @@ "navigation_bar.domain_blocks": "Domanioù kuzhet", "navigation_bar.edit_profile": "Kemmañ ar profil", "navigation_bar.explore": "Furchal", + "navigation_bar.favourites": "Muiañ-karet", "navigation_bar.filters": "Gerioù kuzhet", "navigation_bar.follow_requests": "Pedadoù heuliañ", + "navigation_bar.followed_tags": "Hashtagoù o heuliañ", "navigation_bar.follows_and_followers": "Heuliadennoù ha heulier·ezed·ien", "navigation_bar.lists": "Listennoù", "navigation_bar.logout": "Digennaskañ", @@ -369,6 +407,7 @@ "notifications.column_settings.admin.report": "Disklêriadurioù nevez :", "notifications.column_settings.admin.sign_up": "Enskrivadurioù nevez :", "notifications.column_settings.alert": "Kemennoù war ar burev", + "notifications.column_settings.favourite": "Muiañ-karet:", "notifications.column_settings.filter_bar.advanced": "Skrammañ an-holl rummadoù", "notifications.column_settings.filter_bar.category": "Barrenn siloù prim", "notifications.column_settings.filter_bar.show_bar": "Diskouezh barrenn siloù", @@ -386,6 +425,7 @@ "notifications.column_settings.update": "Kemmoù :", "notifications.filter.all": "Pep tra", "notifications.filter.boosts": "Skignadennoù", + "notifications.filter.favourites": "Muiañ-karet", "notifications.filter.follows": "Heuliañ", "notifications.filter.mentions": "Menegoù", "notifications.filter.polls": "Disoc'hoù ar sontadegoù", @@ -399,15 +439,28 @@ "notifications_permission_banner.enable": "Lezel kemennoù war ar burev", "notifications_permission_banner.how_to_control": "Evit reseviñ kemennoù pa ne vez ket digoret Mastodon, lezelit kemennoù war ar burev. Gallout a rit kontrollañ peseurt eskemmoù a c'henel kemennoù war ar burev gant ar {icon} nozelenn a-us kentre ma'z int lezelet.", "notifications_permission_banner.title": "Na vankit netra morse", + "onboarding.action.back": "Distreiñ", + "onboarding.actions.back": "Distreiñ", "onboarding.actions.go_to_explore": "See what's trending", "onboarding.actions.go_to_home": "Go to your home feed", + "onboarding.compose.template": "Salud #Mastodon!", "onboarding.follows.lead": "You curate your own home feed. The more people you follow, the more active and interesting it will be. These profiles may be a good starting point—you can always unfollow them later!", "onboarding.follows.title": "Popular on Mastodon", + "onboarding.profile.display_name": "Anv diskouezet", + "onboarding.profile.display_name_hint": "Hoc'h anv klok pe hoc'h anv fentus…", + "onboarding.profile.note": "Berr-ha-berr", + "onboarding.profile.note_hint": "Gallout a rit @menegiñ tud all pe #hashtagoù…", + "onboarding.profile.save_and_continue": "Enrollañ ha kenderc'hel", + "onboarding.profile.upload_avatar": "Enporzhiañ ur skeudenn profil", + "onboarding.share.message": "Me a zo {username} war #Mastodon! Heuilhit ac'hanon war {url}", + "onboarding.share.title": "Skignañ ho profil", "onboarding.start.lead": "Your new Mastodon account is ready to go. Here's how you can make the most of it:", "onboarding.start.skip": "Want to skip right ahead?", + "onboarding.start.title": "Deuet oc'h a-benn!", "onboarding.steps.follow_people.body": "You curate your own feed. Lets fill it with interesting people.", "onboarding.steps.follow_people.title": "Follow {count, plural, one {one person} other {# people}}", "onboarding.steps.publish_status.body": "Say hello to the world.", + "onboarding.steps.publish_status.title": "Grit hoc'h embannadur kentañ", "onboarding.steps.setup_profile.body": "Others are more likely to interact with you with a filled out profile.", "onboarding.steps.setup_profile.title": "Customize your profile", "onboarding.steps.share_profile.body": "Let your friends know how to find you on Mastodon!", @@ -415,6 +468,7 @@ "picture_in_picture.restore": "Adlakaat", "poll.closed": "Serret", "poll.refresh": "Azbevaat", + "poll.reveal": "Gwelet an disoc'hoù", "poll.total_people": "{count, plural, one {# den} other {# a zen}}", "poll.total_votes": "{count, plural, one {# votadenn} other {# votadenn}}", "poll.vote": "Mouezhiañ", @@ -433,6 +487,7 @@ "privacy.unlisted.short": "Anlistennet", "privacy_policy.last_updated": "Hizivadenn ziwezhañ {date}", "privacy_policy.title": "Reolennoù Prevezded", + "recommended": "Erbedet", "refresh": "Freskaat", "regeneration_indicator.label": "O kargañ…", "regeneration_indicator.sublabel": "War brientiñ emañ ho red degemer!", @@ -450,6 +505,7 @@ "reply_indicator.cancel": "Nullañ", "report.block": "Stankañ", "report.block_explanation": "Ne vo ket gwelet toudoù ar gont-se ken. Ne welo ket ho toudoù ha ne c'hello ket ho heuliañ ken. Gouzout a raio eo bet stanket ganeoc'h.", + "report.categories.legal": "Lezennel", "report.categories.other": "All", "report.categories.spam": "Spam", "report.categories.violation": "Torret e vez gant an endalc'had unan pe meur a reolenn", @@ -467,6 +523,7 @@ "report.placeholder": "Askelennoù ouzhpenn", "report.reasons.dislike": "Ne blij ket din", "report.reasons.dislike_description": "An dra-se na fell ket deoc'h gwelet", + "report.reasons.legal": "Enep al lezenn eo", "report.reasons.other": "Un abeg all eo", "report.reasons.other_description": "Ar gudenn na glot ket gant ar rummadoù all", "report.reasons.spam": "Spam eo", @@ -482,16 +539,31 @@ "report.thanks.title": "Ne fell ket deoc'h gwelet an dra-se ?", "report.thanks.title_actionable": "Trugarez evit bezañ disklêriet, emaomp o vont da glask pelloc'h.", "report.unfollow": "Diheuliañ @{name}", - "report_notification.attached_statuses": "{count, plural, one {# post} other {# posts}} attached", + "report_notification.attached_statuses": "{count, plural, one {{count} embannadur} other {{count} embannadur}} stag", + "report_notification.categories.legal": "Lezennel", "report_notification.categories.other": "All", "report_notification.categories.spam": "Spam", "report_notification.categories.violation": "Torradur da reolennoù ar servijer", "report_notification.open": "Digeriñ an disklêriadur", "search.placeholder": "Klask", + "search.quick_action.account_search": "Profiloù a glot gant {x}", + "search.quick_action.go_to_account": "Mont d'ar profil {x}", + "search.quick_action.go_to_hashtag": "Mont d'an hashtag {x}", + "search.quick_action.open_url": "Digeriñ an URL e-barzh Mastodon", + "search.quick_action.status_search": "Embannadurioù a glot gant {x}", "search.search_or_paste": "Klask pe pegañ un URL", + "search_popout.full_text_search_disabled_message": "N'eo ket da gaout war {domain}.", + "search_popout.language_code": "Kod yezh ISO", + "search_popout.options": "Dibarzhioù klask", + "search_popout.quick_actions": "Oberoù prim", + "search_popout.recent": "Klaskoù nevesañ", + "search_popout.specific_date": "deiziad resis", + "search_popout.user": "implijer·ez", + "search_results.accounts": "Profiloù", "search_results.all": "Pep tra", - "search_results.hashtags": "Gerioù-klik", + "search_results.hashtags": "Hashtagoù", "search_results.nothing_found": "Disoc'h ebet gant ar gerioù-se", + "search_results.see_all": "Gwelet pep tra", "search_results.statuses": "Toudoù", "search_results.title": "Klask {q}", "server_banner.active_users": "implijerien·ezed oberiant", @@ -513,11 +585,15 @@ "status.edited": "Aozet {date}", "status.edited_x_times": "Edited {count, plural, one {# time} other {# times}}", "status.embed": "Enframmañ", + "status.favourite": "Muiañ-karet", "status.filter": "Silañ ar c'hannad-mañ", "status.filtered": "Silet", + "status.hide": "Kuzhat an embannadur", "status.history.created": "Krouet gant {name} {date}", "status.history.edited": "Kemmet gant {name} {date}", "status.load_more": "Kargañ muioc'h", + "status.media.open": "Klikit evit digeriñ", + "status.media.show": "Klikit evit diskouez", "status.media_hidden": "Media kuzhet", "status.mention": "Menegiñ @{name}", "status.more": "Muioc'h", @@ -592,6 +668,7 @@ "upload_modal.preview_label": "Rakwel ({ratio})", "upload_progress.label": "O pellgargañ...", "upload_progress.processing": "War ober…", + "username.taken": "Tapet eo an anv implijer-mañ dija. Klaskit skrivañ unan all", "video.close": "Serriñ ar video", "video.download": "Pellgargañ ar restr", "video.exit_fullscreen": "Kuitaat ar mod skramm leun", diff --git a/app/javascript/mastodon/locales/de.json b/app/javascript/mastodon/locales/de.json index ddcbc58cee..2608b91563 100644 --- a/app/javascript/mastodon/locales/de.json +++ b/app/javascript/mastodon/locales/de.json @@ -62,7 +62,7 @@ "account.requested": "Die Genehmigung steht noch aus. Klicke hier, um die Follower-Anfrage zurückzuziehen", "account.requested_follow": "{name} möchte dir folgen", "account.share": "Profil von @{name} teilen", - "account.show_reblogs": "Geteilte Beiträge von @{name} wieder anzeigen", + "account.show_reblogs": "Geteilte Beiträge von @{name} anzeigen", "account.statuses_counter": "{count, plural, one {{counter} Beitrag} other {{counter} Beiträge}}", "account.unblock": "Blockierung von @{name} aufheben", "account.unblock_domain": "Blockierung von {domain} aufheben", diff --git a/app/javascript/mastodon/locales/ia.json b/app/javascript/mastodon/locales/ia.json index 00cafe260b..e790306e9c 100644 --- a/app/javascript/mastodon/locales/ia.json +++ b/app/javascript/mastodon/locales/ia.json @@ -2,6 +2,7 @@ "about.blocks": "Servitores moderate", "about.contact": "Contacto:", "about.disclaimer": "Mastodon es software libere, de codice aperte, e un marca de Mastodon gGmbH.", + "about.rules": "Regulas del servitor", "account.account_note_header": "Nota", "account.add_or_remove_from_list": "Adder o remover ab listas", "account.badges.group": "Gruppo", @@ -10,14 +11,43 @@ "account.blocked": "Blocate", "account.copy": "Copiar ligamine a profilo", "account.edit_profile": "Modificar profilo", + "account.endorse": "Evidentiar sur le profilo", + "account.featured_tags.last_status_at": "Ultime message in {date}", + "account.featured_tags.last_status_never": "Necun messages", + "account.follow": "Sequer", + "account.follow_back": "Sequer etiam", + "account.followers": "Sequitores", + "account.following": "Sequente", "account.go_to_profile": "Vader al profilo", + "account.hide_reblogs": "Celar boosts de @{name}", + "account.languages": "Cambiar le linguas subscribite", + "account.link_verified_on": "Le proprietate de iste ligamine esseva verificate le {date}", + "account.locked_info": "Le stato de confidentialitate de iste conto es definite a blocate. Le proprietario revisa manualmente qui pote sequer lo.", + "account.mention": "Mentionar @{name}", "account.moved_to": "{name} indicava que lor nove conto ora es:", + "account.mute": "Silentiar @{name}", + "account.mute_notifications_short": "Silentiar le notificationes", + "account.mute_short": "Silentiar", + "account.muted": "Silentiate", + "account.no_bio": "Nulle description fornite.", + "account.posts": "Messages", + "account.posts_with_replies": "Messages e responsas", "account.share": "Compartir profilo de @{name}", + "account.show_reblogs": "Monstrar responsas de @{name}", "account.unblock": "Disblocar @{name}", + "account.unblock_domain": "Disblocar dominio {domain}", "account.unblock_short": "Disblocar", "account.unendorse": "Non evidentiar sur le profilo", + "account.unmute": "Non plus silentiar @{name}", + "account.unmute_notifications_short": "Non plus silentiar le notificationes", + "account.unmute_short": "Non plus silentiar", "account_note.placeholder": "Clicca pro adder un nota", "admin.dashboard.retention.cohort_size": "Nove usatores", + "admin.impact_report.instance_followers": "Sequitores que nostre usatores poterea perder", + "admin.impact_report.instance_follows": "Sequitores que lor usatores poterea perder", + "alert.rate_limited.message": "Retenta depost {retry_time, time, medium}.", + "alert.unexpected.message": "Ocurreva un error inexpectate.", + "announcement.announcement": "Annuncio", "audio.hide": "Celar audio", "autosuggest_hashtag.per_week": "{count} per septimana", "bundle_column_error.network.title": "Error de rete", @@ -25,99 +55,260 @@ "bundle_column_error.return": "Retornar al initio", "bundle_modal_error.close": "Clauder", "bundle_modal_error.retry": "Tentar novemente", + "closed_registrations_modal.find_another_server": "Trovar altere servitor", "column.about": "A proposito de", "column.blocks": "Usatores blocate", "column.bookmarks": "Marcapaginas", + "column.community": "Chronologia local", + "column.direct": "Mentiones private", "column.directory": "Navigar profilos", + "column.domain_blocks": "Dominios blocate", "column.favourites": "Favoritos", "column.firehose": "Fluxos in directe", "column.home": "Initio", "column.lists": "Listas", + "column.mutes": "Usatores silentiate", "column.notifications": "Notificationes", + "column.public": "Chronologia federate", "column_header.hide_settings": "Celar le parametros", + "column_header.moveLeft_settings": "Mover columna al sinistra", + "column_header.moveRight_settings": "Mover columna al dextra", "column_header.show_settings": "Monstrar le parametros", "column_subheading.settings": "Parametros", "compose.language.change": "Cambiar le lingua", "compose.language.search": "Cercar linguas...", + "compose.published.body": "Message publicate.", "compose.published.open": "Aperir", + "compose.saved.body": "Message salvate.", "compose_form.direct_message_warning_learn_more": "Apprender plus", + "compose_form.lock_disclaimer": "Tu conto non es {locked}. Quicunque pote sequer te pro vider tu messages solo pro sequitores.", + "compose_form.lock_disclaimer.lock": "blocate", "compose_form.poll.add_option": "Adder un option", "compose_form.poll.remove_option": "Remover iste option", + "compose_form.publish": "Publicar", + "compose_form.publish_form": "Nove message", + "compose_form.publish_loud": "{publish}!", + "compose_form.save_changes": "Salvar le cambiamentos", + "compose_form.spoiler.marked": "Remover advertimento de contento", + "compose_form.spoiler.unmarked": "Adder advertimento de contento", + "compose_form.spoiler_placeholder": "Scribe tu advertimento hic", "confirmation_modal.cancel": "Cancellar", + "confirmations.block.confirm": "Blocar", "confirmations.delete.confirm": "Deler", + "confirmations.delete.message": "Es tu secur que tu vole deler iste message?", "confirmations.delete_list.confirm": "Deler", + "confirmations.delete_list.message": "Es tu secur que tu vole deler permanentemente iste lista?", + "confirmations.domain_block.confirm": "Blocar le dominio complete", "confirmations.edit.confirm": "Modificar", "confirmations.logout.confirm": "Clauder le session", + "confirmations.logout.message": "Es tu secur que tu vole clauder le session?", + "confirmations.mute.confirm": "Silentiar", + "confirmations.mute.message": "Es tu secur que tu vole silentiar {name}?", + "confirmations.reply.confirm": "Responder", + "conversation.delete": "Deler conversation", + "conversation.mark_as_read": "Marcar como legite", + "conversation.open": "Vider conversation", + "conversation.with": "Con {names}", "copy_icon_button.copied": "Copiate al area de transferentia", "copypaste.copied": "Copiate", "copypaste.copy_to_clipboard": "Copiar al area de transferentia", + "directory.federated": "Ab le fediverso cognoscite", + "directory.local": "Solmente ab {domain}", + "directory.recently_active": "Recentemente active", "disabled_account_banner.account_settings": "Parametros de conto", + "disabled_account_banner.text": "Tu conto {disabledAccount} es actualmente disactivate.", "dismissable_banner.dismiss": "Dimitter", "emoji_button.activity": "Activitate", "emoji_button.clear": "Rader", "emoji_button.custom": "Personalisate", + "emoji_button.recent": "Frequentemente usate", + "emoji_button.search": "Cercar...", "emoji_button.search_results": "Resultatos de recerca", + "empty_column.account_suspended": "Conto suspendite", + "empty_column.account_timeline": "Nulle messages hic!", "empty_column.account_unavailable": "Profilo non disponibile", + "empty_column.blocks": "Tu non ha blocate alcun usator ancora.", "errors.unexpected_crash.report_issue": "Signalar un defecto", "explore.search_results": "Resultatos de recerca", + "explore.title": "Explorar", "explore.trending_links": "Novas", + "explore.trending_statuses": "Messages", + "explore.trending_tags": "Hashtags", + "filter_modal.added.review_and_configure_title": "Parametros de filtro", + "filter_modal.added.settings_link": "pagina de parametros", + "filter_modal.added.short_explanation": "Iste message esseva addite al sequente categoria de filtros: {title}.", + "filter_modal.added.title": "Filtro addite!", "filter_modal.select_filter.prompt_new": "Nove categoria: {name}", + "filter_modal.select_filter.search": "Cercar o crear", + "filter_modal.select_filter.title": "Filtrar iste message", + "filter_modal.title.status": "Filtrar un message", "firehose.all": "Toto", "firehose.local": "Iste servitor", "firehose.remote": "Altere servitores", "footer.about": "A proposito de", "footer.directory": "Directorio de profilos", + "footer.get_app": "Obtene le application", + "footer.keyboard_shortcuts": "Accessos directe de claviero", "footer.privacy_policy": "Politica de confidentialitate", "footer.source_code": "Vider le codice fonte", "footer.status": "Stato", + "generic.saved": "Salvate", + "getting_started.heading": "Prime passos", + "hashtag.column_header.tag_mode.all": "e {additional}", + "hashtag.column_header.tag_mode.any": "o {additional}", + "hashtag.column_settings.select.no_options_message": "Nulle suggestiones trovate", + "hashtag.column_settings.select.placeholder": "Insere hashtags…", + "hashtag.follow": "Sequer hashtag", + "home.column_settings.show_reblogs": "Monstrar boosts", + "home.column_settings.show_replies": "Monstrar responsas", + "home.hide_announcements": "Celar annuncios", + "home.pending_critical_update.body": "Actualisa tu servitor de Mastodon le plus tosto possibile!", "home.pending_critical_update.link": "Vider actualisationes", + "home.show_announcements": "Monstrar annuncios", + "interaction_modal.no_account_yet": "Non sur Mstodon?", + "interaction_modal.on_another_server": "In un servitor differente", + "interaction_modal.on_this_server": "In iste servitor", + "interaction_modal.title.follow": "Sequer {name}", + "interaction_modal.title.reblog": "Facer boost al message de {name}", + "interaction_modal.title.reply": "Responder al message de {name}", + "keyboard_shortcuts.blocked": "Aperir lista de usatores blocate", + "keyboard_shortcuts.boost": "Facer boost al message", + "keyboard_shortcuts.description": "Description", + "keyboard_shortcuts.enter": "Aperir message", + "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.local": "Aperir le chronologia local", + "keyboard_shortcuts.muted": "Aperir lista de usatores silentiate", "keyboard_shortcuts.my_profile": "Aperir tu profilo", + "keyboard_shortcuts.notifications": "Aperir columna de notificationes", + "keyboard_shortcuts.reply": "Responder al message", + "keyboard_shortcuts.spoilers": "Monstrar/celar le campo CW", + "keyboard_shortcuts.toot": "Initiar un nove message", "lightbox.close": "Clauder", "lightbox.next": "Sequente", "lightbox.previous": "Precedente", "link_preview.author": "Per {name}", "lists.account.add": "Adder al lista", + "lists.account.remove": "Remover ab le lista", "lists.delete": "Deler lista", "lists.edit": "Modificar lista", + "lists.edit.submit": "Cambiar titulo", + "lists.exclusive": "Celar iste messages ab le initio", "lists.new.create": "Adder lista", + "lists.new.title_placeholder": "Nove titulo del lista", + "lists.replies_policy.title": "Monstrar responsas a:", "lists.subheading": "Tu listas", "mute_modal.duration": "Duration", "mute_modal.hide_notifications": "Celar notificationes de iste usator?", "navigation_bar.about": "A proposito de", "navigation_bar.advanced_interface": "Aperir in un interfacie web avantiate", "navigation_bar.blocks": "Usatores blocate", + "navigation_bar.bookmarks": "Marcapaginas", + "navigation_bar.community_timeline": "Chronologia local", + "navigation_bar.direct": "Mentiones private", "navigation_bar.discover": "Discoperir", + "navigation_bar.domain_blocks": "Dominios blocate", "navigation_bar.edit_profile": "Modificar profilo", "navigation_bar.favourites": "Favoritos", + "navigation_bar.filters": "Parolas silentiate", "navigation_bar.lists": "Listas", "navigation_bar.logout": "Clauder le session", + "navigation_bar.mutes": "Usatores silentiate", "navigation_bar.preferences": "Preferentias", + "navigation_bar.public_timeline": "Chronologia federate", "navigation_bar.search": "Cercar", "navigation_bar.security": "Securitate", + "notification.update": "{name} modificava un message", + "notifications.clear": "Rader notificationes", "notifications.column_settings.alert": "Notificationes de scriptorio", "notifications.column_settings.filter_bar.advanced": "Monstrar tote le categorias", + "notifications.column_settings.follow": "Nove sequitores:", + "notifications.column_settings.mention": "Mentiones:", + "notifications.column_settings.push": "Notificationes push", "notifications.column_settings.sound": "Reproducer sono", + "notifications.column_settings.status": "Nove messages:", "notifications.filter.all": "Toto", "notifications.filter.favourites": "Favoritos", + "notifications.filter.mentions": "Mentiones", "notifications.grant_permission": "Conceder permission.", "notifications.group": "{count} notificationes", "onboarding.compose.template": "Salute #Mastodon!", "onboarding.profile.save_and_continue": "Salvar e continuar", + "onboarding.share.next_steps": "Sequente passos possibile:", "onboarding.share.title": "Compartir tu profilo", + "onboarding.steps.follow_people.title": "Personalisa tu fluxo de initio", + "onboarding.steps.publish_status.title": "Face tu prime message", + "onboarding.steps.setup_profile.title": "Personalisa tu profilo", "onboarding.steps.share_profile.title": "Compartir tu profilo de Mastodon", + "poll.closed": "Claudite", + "poll.reveal": "Vider le resultatos", + "privacy.change": "Cambiar privacitate del message", + "privacy.private.long": "Visibile solmente pro sequitores", + "privacy.public.long": "Visibile pro totos", + "privacy.public.short": "Public", + "privacy_policy.last_updated": "Ultime actualisation {date}", + "privacy_policy.title": "Politica de confidentialitate", "relative_time.just_now": "ora", "relative_time.today": "hodie", "reply_indicator.cancel": "Cancellar", + "report.block": "Blocar", + "report.categories.other": "Alteres", + "report.category.title_account": "profilo", + "report.category.title_status": "message", + "report.close": "Preste", + "report.mute": "Silentiar", "report.next": "Sequente", "report.placeholder": "Commentos additional", "report.reasons.dislike": "Non me place", + "report_notification.categories.other": "Alteres", "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_popout.full_text_search_disabled_message": "Non disponibile sur {domain}.", + "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.user": "usator", "search_results.accounts": "Profilos", + "search_results.hashtags": "Hashtags", "search_results.see_all": "Vider toto", + "search_results.statuses": "Messages", + "server_banner.learn_more": "Apprender plus", + "sign_in_banner.create_account": "Crear un conto", + "sign_in_banner.sign_in": "Initiar le session", + "status.block": "Blocar @{name}", + "status.copy": "Copiar ligamine a message", "status.delete": "Deler", + "status.direct_indicator": "Mention private", + "status.edit": "Modificar", + "status.filter": "Filtrar iste message", + "status.hide": "Celar le message", + "status.history.created": "create per {name} le {date}", + "status.history.edited": "modificate per {name} le {date}", + "status.media.open": "Clicca pro aperir", + "status.media.show": "Clicca pro monstrar", + "status.more": "Plus", + "status.mute_conversation": "Silentiar conversation", + "status.read_more": "Leger plus", "status.share": "Compartir", "status.translate": "Traducer", "status.translated_from_with": "Traducite ab {lang} usante {provider}", "tabs_bar.home": "Initio", - "tabs_bar.notifications": "Notificationes" + "tabs_bar.notifications": "Notificationes", + "timeline_hint.resources.statuses": "Messages ancian", + "trends.trending_now": "Ora in tendentias", + "upload_form.undo": "Deler", + "upload_modal.choose_image": "Seliger un imagine", + "upload_modal.detect_text": "Deteger texto ab un pictura", + "video.close": "Clauder le video", + "video.download": "Discargar le file", + "video.fullscreen": "Schermo plen", + "video.hide": "Celar video", + "video.mute": "Silentiar le sono", + "video.pause": "Pausa", + "video.play": "Reproducer", + "video.unmute": "Non plus silentiar le sono" } diff --git a/app/javascript/mastodon/locales/ja.json b/app/javascript/mastodon/locales/ja.json index 3246415759..e7aafe852a 100644 --- a/app/javascript/mastodon/locales/ja.json +++ b/app/javascript/mastodon/locales/ja.json @@ -32,6 +32,7 @@ "account.featured_tags.last_status_never": "投稿がありません", "account.featured_tags.title": "{name}の注目ハッシュタグ", "account.follow": "フォロー", + "account.follow_back": "フォローバック", "account.followers": "フォロワー", "account.followers.empty": "まだ誰もフォローしていません。", "account.followers_counter": "{counter} フォロワー", @@ -52,6 +53,7 @@ "account.mute_notifications_short": "通知をオフにする", "account.mute_short": "ミュート", "account.muted": "ミュート済み", + "account.mutual": "相互フォロー中", "account.no_bio": "説明が提供されていません。", "account.open_original_page": "元のページを開く", "account.posts": "投稿", @@ -486,7 +488,7 @@ "onboarding.profile.display_name_hint": "フルネーム、あるいは面白い名前など", "onboarding.profile.lead": "あとでいつでも修正できますし、設定画面にはこれ以外のカスタマイズ項目もあります。", "onboarding.profile.note": "自己紹介", - "onboarding.profile.note_hint": "ほかの人に @言及 したり、#ハッシュタグ を付けたりできます", + "onboarding.profile.note_hint": "ほかのユーザーへのメンション (@mention) や、 #ハッシュタグ が使用できます", "onboarding.profile.save_and_continue": "保存して続ける", "onboarding.profile.title": "プロフィールの設定", "onboarding.profile.upload_avatar": "プロフィール画像をアップロード", diff --git a/app/javascript/mastodon/locales/lad.json b/app/javascript/mastodon/locales/lad.json index 2067edcc70..2a911483de 100644 --- a/app/javascript/mastodon/locales/lad.json +++ b/app/javascript/mastodon/locales/lad.json @@ -501,6 +501,7 @@ "onboarding.steps.setup_profile.title": "Personaliza tu profil", "onboarding.steps.share_profile.body": "Informe a tus amigos komo toparte en Mastodon", "onboarding.steps.share_profile.title": "Partaja tu profil de Mastodon", + "password_confirmation.exceeds_maxlength": "La konfirmasyon de kod es demaziado lunga", "password_confirmation.mismatching": "Los dos kodes son desferentes", "picture_in_picture.restore": "Restora", "poll.closed": "Serrado", diff --git a/app/javascript/mastodon/locales/vi.json b/app/javascript/mastodon/locales/vi.json index 03c6502651..9de043bb20 100644 --- a/app/javascript/mastodon/locales/vi.json +++ b/app/javascript/mastodon/locales/vi.json @@ -240,7 +240,7 @@ "empty_column.follow_requests": "Bạn chưa có yêu cầu theo dõi nào.", "empty_column.followed_tags": "Bạn chưa theo dõi hashtag nào. Khi bạn theo dõi, chúng sẽ hiện lên ở đây.", "empty_column.hashtag": "Chưa có tút nào dùng hashtag này.", - "empty_column.home": "Trang chính của bạn đang trống! Hãy theo dõi nhiều người hơn để lấp đầy.", + "empty_column.home": "Trang chủ của bạn đang trống! Hãy theo dõi nhiều người hơn để lấp đầy.", "empty_column.list": "Chưa có tút. Khi những người trong danh sách này đăng tút mới, chúng sẽ xuất hiện ở đây.", "empty_column.lists": "Bạn chưa tạo danh sách nào.", "empty_column.mutes": "Bạn chưa ẩn bất kỳ ai.", @@ -336,38 +336,38 @@ "intervals.full.days": "{number, plural, other {# ngày}}", "intervals.full.hours": "{number, plural, other {# giờ}}", "intervals.full.minutes": "{number, plural, other {# phút}}", - "keyboard_shortcuts.back": "trở lại", + "keyboard_shortcuts.back": "quay lại", "keyboard_shortcuts.blocked": "mở danh sách người đã chặn", "keyboard_shortcuts.boost": "đăng lại", - "keyboard_shortcuts.column": "mở các mục", + "keyboard_shortcuts.column": "mở các cột", "keyboard_shortcuts.compose": "mở khung soạn tút", "keyboard_shortcuts.description": "Mô tả", - "keyboard_shortcuts.direct": "mở mục nhắn riêng", + "keyboard_shortcuts.direct": "mở nhắn riêng", "keyboard_shortcuts.down": "di chuyển xuống dưới danh sách", - "keyboard_shortcuts.enter": "viết tút mới", + "keyboard_shortcuts.enter": "mở tút", "keyboard_shortcuts.favourite": "thích tút", "keyboard_shortcuts.favourites": "mở lượt thích", "keyboard_shortcuts.federated": "mở mạng liên hợp", "keyboard_shortcuts.heading": "Danh sách phím tắt", - "keyboard_shortcuts.home": "mở trang chính", + "keyboard_shortcuts.home": "mở trang chủ", "keyboard_shortcuts.hotkey": "Phím tắt", "keyboard_shortcuts.legend": "hiện bảng hướng dẫn này", "keyboard_shortcuts.local": "mở máy chủ của bạn", "keyboard_shortcuts.mention": "nhắc đến ai đó", "keyboard_shortcuts.muted": "mở danh sách người đã ẩn", "keyboard_shortcuts.my_profile": "mở hồ sơ của bạn", - "keyboard_shortcuts.notifications": "mở mục thông báo", + "keyboard_shortcuts.notifications": "mở thông báo", "keyboard_shortcuts.open_media": "mở ảnh hoặc video", - "keyboard_shortcuts.pinned": "mở danh sách tút ghim", - "keyboard_shortcuts.profile": "mở hồ sơ của người viết tút", + "keyboard_shortcuts.pinned": "mở những tút đã ghim", + "keyboard_shortcuts.profile": "mở trang của người đăng tút", "keyboard_shortcuts.reply": "trả lời", "keyboard_shortcuts.requests": "mở danh sách yêu cầu theo dõi", "keyboard_shortcuts.search": "mở tìm kiếm", "keyboard_shortcuts.spoilers": "hiện/ẩn nội dung nhạy cảm", - "keyboard_shortcuts.start": "mở mục \"Dành cho người mới\"", - "keyboard_shortcuts.toggle_hidden": "ẩn/hiện văn bản bên dưới spoil", + "keyboard_shortcuts.start": "mở \"Dành cho người mới\"", + "keyboard_shortcuts.toggle_hidden": "ẩn/hiện nội dung ẩn", "keyboard_shortcuts.toggle_sensitivity": "ẩn/hiện ảnh hoặc video", - "keyboard_shortcuts.toot": "viết tút mới", + "keyboard_shortcuts.toot": "soạn tút mới", "keyboard_shortcuts.unfocus": "đưa con trỏ ra khỏi ô soạn thảo hoặc ô tìm kiếm", "keyboard_shortcuts.up": "di chuyển lên trên danh sách", "lightbox.close": "Đóng", @@ -404,7 +404,7 @@ "navigation_bar.blocks": "Người đã chặn", "navigation_bar.bookmarks": "Đã lưu", "navigation_bar.community_timeline": "Cộng đồng", - "navigation_bar.compose": "Viết tút mới", + "navigation_bar.compose": "Soạn tút mới", "navigation_bar.direct": "Nhắn riêng", "navigation_bar.discover": "Khám phá", "navigation_bar.domain_blocks": "Máy chủ đã ẩn", @@ -436,7 +436,7 @@ "notification.poll": "Cuộc bình chọn đã kết thúc", "notification.reblog": "{name} đăng lại tút của bạn", "notification.status": "{name} đăng tút mới", - "notification.update": "{name} đã viết lại một tút", + "notification.update": "{name} đã sửa tút", "notifications.clear": "Xóa hết thông báo", "notifications.clear_confirmation": "Bạn thật sự muốn xóa vĩnh viễn tất cả thông báo của mình?", "notifications.column_settings.admin.report": "Báo cáo mới:", @@ -477,7 +477,7 @@ "onboarding.action.back": "Quay lại", "onboarding.actions.back": "Quay lại", "onboarding.actions.go_to_explore": "Xem những gì đang thịnh hành", - "onboarding.actions.go_to_home": "Đến trang chính", + "onboarding.actions.go_to_home": "Đến trang chủ", "onboarding.compose.template": "Xin chào #Mastodon!", "onboarding.follows.empty": "Không có kết quả có thể được hiển thị lúc này. Bạn có thể thử sử dụng tính năng tìm kiếm hoặc duyệt qua trang khám phá để tìm những người theo dõi hoặc thử lại sau.", "onboarding.follows.lead": "Bạn quản lý bảng tin của riêng bạn. Bạn càng theo dõi nhiều người, nó sẽ càng sôi động và thú vị. Để bắt đầu, đây là vài gợi ý:", @@ -501,7 +501,7 @@ "onboarding.start.skip": "Muốn bỏ qua luôn?", "onboarding.start.title": "Xong rồi bạn!", "onboarding.steps.follow_people.body": "Theo dõi những người thú vị trên Mastodon.", - "onboarding.steps.follow_people.title": "Cá nhân hóa trang chính", + "onboarding.steps.follow_people.title": "Cá nhân hóa trang chủ", "onboarding.steps.publish_status.body": "Chào cộng đồng bằng lời nói, ảnh hoặc video {emoji}", "onboarding.steps.publish_status.title": "Đăng tút đầu tiên", "onboarding.steps.setup_profile.body": "Tạo sự tương tác bằng một hồ sơ hoàn chỉnh.", @@ -539,7 +539,7 @@ "recommended": "Đề xuất", "refresh": "Làm mới", "regeneration_indicator.label": "Đang tải…", - "regeneration_indicator.sublabel": "Trang chính của bạn đang được cập nhật!", + "regeneration_indicator.sublabel": "Trang chủ của bạn đang được cập nhật!", "relative_time.days": "{number} ngày", "relative_time.full.days": "{number, plural, other {# ngày}}", "relative_time.full.hours": "{number, plural, other {# giờ}}", @@ -591,7 +591,7 @@ "report.thanks.title": "Không muốn xem thứ này?", "report.thanks.title_actionable": "Cảm ơn đã báo cáo, chúng tôi sẽ xem xét kỹ.", "report.unfollow": "Bỏ theo dõi @{name}", - "report.unfollow_explanation": "Bạn đang theo dõi người này. Để không thấy tút của họ trên trang chính nữa, hãy bỏ theo dõi.", + "report.unfollow_explanation": "Bạn đang theo dõi người này. Để không thấy tút của họ trên trang chủ nữa, hãy bỏ theo dõi.", "report_notification.attached_statuses": "{count, plural, other {{count} tút}} đính kèm", "report_notification.categories.legal": "Pháp lý", "report_notification.categories.other": "Khác", @@ -692,7 +692,7 @@ "subscribed_languages.lead": "Chỉ các tút đăng bằng các ngôn ngữ đã chọn mới được xuất hiện trên bảng tin của bạn. Không chọn gì cả để đọc tút đăng bằng mọi ngôn ngữ.", "subscribed_languages.save": "Lưu thay đổi", "subscribed_languages.target": "Đổi ngôn ngữ mong muốn cho {target}", - "tabs_bar.home": "Trang chính", + "tabs_bar.home": "Trang chủ", "tabs_bar.notifications": "Thông báo", "time_remaining.days": "{number, plural, other {# ngày}}", "time_remaining.hours": "{number, plural, other {# giờ}}", diff --git a/config/locales/bg.yml b/config/locales/bg.yml index b06c5404c7..1865aa5fca 100644 --- a/config/locales/bg.yml +++ b/config/locales/bg.yml @@ -425,6 +425,7 @@ bg: view: Преглед на блокиране на домейн email_domain_blocks: add_new: Добавяне на ново + allow_registrations_with_approval: Позволяване на регистрации с одобрение attempts_over_week: one: "%{count} опит за изминалата седмица" other: "%{count} опита за регистрация през изминалата седмица" diff --git a/config/locales/br.yml b/config/locales/br.yml index e869374573..8a70a90cfe 100644 --- a/config/locales/br.yml +++ b/config/locales/br.yml @@ -40,8 +40,10 @@ br: change_role: no_role: Roll ebet confirm: Kadarnaat + confirmed: Kadarnaet confirming: O kadarnaat custom: Personelaet + delete: Dilemel ar roadennoù deleted: Dilamet demote: Argilañ disable: Skornañ @@ -61,6 +63,7 @@ br: all: Pep tra local: Lec'hel remote: A-bell + media_attachments: Restroù media stag moderation: active: Oberiant all: Pep tra @@ -68,6 +71,7 @@ br: silenced: Bevennet suspended: Astalet title: Habaskadur + most_recent_activity: Obererezh nevesañ perform_full_suspension: Astalañ promote: Brudañ protocol: Komenad @@ -76,15 +80,19 @@ br: remove_header: Dilemel an talbenn reset: Adderaouekaat reset_password: Adderaouekaat ar ger-tremen + resubscribe: Adkoumanantiñ role: Roll search: Klask + security: Surentez silence: Bevenniñ silenced: Bevennet statuses: Toudoù + subscribe: Koumanantiñ suspend: Astalañ suspended: Astalet title: Kontoù undo_silenced: Dizober ar bevennañ + unsubscribe: Digoumanantiñ username: Anv warn: Diwall web: Web @@ -167,6 +175,7 @@ br: title: Habaskadur purge: Spurjañ title: Kevread + total_storage: Restroù media stag invites: filter: all: Pep tra @@ -265,6 +274,8 @@ br: tags: dashboard: tag_uses_measure: implijoù hollek + not_usable: N'haller ket en implijout + title: Hashtagoù diouzh ar c'hiz title: Luskadoù warning_presets: add_new: Ouzhpenniñ unan nevez @@ -281,6 +292,9 @@ br: new_appeal: actions: none: ur c'hemenn diwall + new_trends: + new_trending_tags: + title: Hashtagoù diouzh ar c'hiz appearance: discovery: Dizoloadur application_mailer: @@ -289,6 +303,8 @@ br: auth: delete_account: Dilemel ar gont delete_account_html: Ma fell deoc'h dilemel ho kont e c'hellit klikañ amañ. Goulennet e vo ganeoc'h kadarnaat an obererezh. + description: + prefix_invited_by_user: Pedet oc'h gant @%{name} da zont e-barzh ar servijer Mastodon-mañ! login: Mont tre logout: Digennaskañ migrate_account_html: Ma fell deoc'h adkas ar gont-mañ war-zu unan all e c'hellit arventenniñ an dra-se amañ. @@ -383,6 +399,10 @@ br: table: uses: Implijoù title: Pediñ tud + media_attachments: + validations: + images_and_video: N'haller stagañ ur video ouzh un embannadur a zo fotoioù gantañ dija + too_many: N'haller ket stagañ muioc'h eget 4 restr migrations: incoming_migrations_html: Evit dilojañ ur gont all da homañ e rankit sevel un alias da gentañ. moderation: @@ -417,13 +437,16 @@ br: next: Da-heul older: Koshoc'h prev: A-raok + polls: + errors: + self_vote: N'hallit ket votiñ en ho sontadegoù deoc'h-c'hwi preferences: other: All posting_defaults: Arventennoù embann dre ziouer relationships: dormant: O kousket followers: Heulier·ezed·ien - following: O heuliañ + following: Koumanantoù invited: Pedet moved: Dilojet mutual: Kenetre @@ -463,6 +486,7 @@ br: account_settings: Arventennoù ar gont development: Diorren edit_profile: Kemmañ ar profil + featured_tags: Hashtagoù pennañ import: Enporzhiañ import_and_export: Enporzhiañ hag ezporzhiañ preferences: Gwellvezioù @@ -475,6 +499,8 @@ br: one: "%{count} skeudenn" other: "%{count} skeudenn" two: "%{count} skeudenn" + pin_errors: + ownership: N'hallit ket spilhennañ embannadurioù ar re all poll: vote: Mouezhiañ show_more: Diskouez muioc'h @@ -483,6 +509,7 @@ br: public: Publik statuses_cleanup: keep_direct: Mirout ar c'hannadoù eeun + keep_media: Derc'hel an embannadurioù gant restroù stag min_age: '1209600': 2 sizhunvezh '2629746': 1 mizvezh @@ -514,6 +541,7 @@ br: subject: Donemat e Mastodoñ title: Degemer mat e bourzh, %{name}! users: + follow_limit_reached: N'hallit ket heulian muioc'h eget %{limit} a zen signed_in_as: 'Aet-tre evel:' verification: verification: Amprouadur diff --git a/config/locales/de.yml b/config/locales/de.yml index e084fdf702..4542871d80 100644 --- a/config/locales/de.yml +++ b/config/locales/de.yml @@ -425,6 +425,7 @@ de: view: Domain-Sperre ansehen email_domain_blocks: add_new: Neue hinzufügen + allow_registrations_with_approval: Registrierungen mit Genehmigung erlauben attempts_over_week: one: "%{count} Registrierungsversuch in der vergangenen Woche" other: "%{count} Registrierungsversuche in der vergangenen Woche" diff --git a/config/locales/devise.ia.yml b/config/locales/devise.ia.yml index 7b0ec29579..c45994160c 100644 --- a/config/locales/devise.ia.yml +++ b/config/locales/devise.ia.yml @@ -1,6 +1,8 @@ --- ia: devise: + failure: + locked: Tu conto es blocate. mailer: confirmation_instructions: action: Verificar adresse de e-mail @@ -8,6 +10,8 @@ ia: title: Verificar adresse de e-mail email_changed: title: Nove adresse de e-mail + password_change: + title: Contrasigno cambiate reconfirmation_instructions: title: Verificar adresse de e-mail reset_password_instructions: @@ -15,6 +19,8 @@ ia: title: Reinitialisar contrasigno two_factor_disabled: title: 2FA disactivate + two_factor_enabled: + title: 2FA activate registrations: updated: Tu conto ha essite actualisate con successo. unlocks: diff --git a/config/locales/devise.ie.yml b/config/locales/devise.ie.yml index c6468d34c2..05a41147d8 100644 --- a/config/locales/devise.ie.yml +++ b/config/locales/devise.ie.yml @@ -3,6 +3,8 @@ ie: devise: confirmations: confirmed: Tui e-mail adresse ha esset confirmat successosimen. + send_instructions: Pos quelc minutes tu va reciver un e-posta con instructiones pri qualmen confirmar tui adresse electronic. Ples confirmar tui spamiere si tu ne vide li e-posta. + send_paranoid_instructions: Si tui email-adresse existe in nor database, pos quelc minutes tu va reciver un e-posta con instructiones pri qualmen confirmar tui adresse electronic. Ples confirmar tui spamiere si tu ne recivet ti-ci email. failure: already_authenticated: Tu ha ja intrat. inactive: Tui conto ancor ne ha esset activat. @@ -20,6 +22,8 @@ ie: action_with_app: Confirma e retorna a%{app} explanation: Tu ha creat un conto sur %{host} con ti-ci e-posta, quel tu posse activar per un sol clicc. Si it ne esset tu qui creat li conto, ples ignorar ti-ci missage. explanation_when_pending: Tu ha demandat un invitation a %{host} con ti-ci e-posta. Pos confirmation de tui adresse, noi va inspecter tui aplication. Tu posse inloggar por changear detallies o deleter li conto, ma li pluparte del functiones va restar ínusabil til quande tui conto es aprobat. Tui data va esser deletet si tui conto es rejectet, e in ti casu tu ne besona far quelcunc cose. Si it ne esset tu qui creat li conto, ples ignorar ti-ci missage. + extra_html: Ples vider anc li regules del servitor e nor termines de servicie. + subject: 'Mastodon: Instructiones de confirmation por %{instance}' title: Verificar e-posta email_changed: explanation: 'Li e-mail adresse de tui es changeat a:' @@ -33,6 +37,7 @@ ie: title: Passa-parol changeat reconfirmation_instructions: explanation: Confirmar li nov adresse por changeat tui e-posta. + extra: Ples ignorar ti-ci e-posta si li change ne esset efectuat per te. Li adresse electronic por li conto Mastodon ne va changear se si tu ne accesse li ligament in supra. subject: 'Mastodon: E-posta de confirmation por %{instance}' title: Verificar e-posta reset_password_instructions: @@ -43,8 +48,11 @@ ie: title: Reiniciar passa-parol two_factor_disabled: explanation: 2-factor autentication por tui conto ha esset desactivisat. Aperter session nu es possibil solmen per email-adresse e passa-parol. + subject: 'Mastodon: 2-factor autentication desactivat' title: 2FA desvalidat two_factor_enabled: + explanation: 2-factor autentication ha esset activat por tui conto. Un gage generat per li acuplat apli TOTP va esser besonat por intrar. + subject: 'Mastodon: 2-factor autentication activat' title: 2FA permisset two_factor_recovery_codes_changed: explanation: Li anteyan codes de recuperation ha esset ínvalidat, e novis generat. @@ -54,14 +62,20 @@ ie: subject: 'Mastodon: Desserral instructiones' webauthn_credential: added: + explanation: Li sequent clave de securitá ha esset adjuntet a tui conto subject: 'Mastodon: Nov clave de securitá' title: Un nov clave de securitá ha esset adjuntet deleted: + explanation: Li sequent clave de securitá ha esset deletet de tui conto subject: 'Mastodon: Clave de securitá deletet' + title: Un ex tui claves de securitá ha esset deletet webauthn_disabled: + explanation: Autentication per claves de securitá ha esset desactivat por tui conto. Ja on posse intrar solmen con li gage generat per li acuplat apli TOTP. subject: 'Mastodon: Autentication con claves de securitá desactivisat' title: Claves de securitá desactivisat webauthn_enabled: + explanation: Autentication per clave de securitá ha esset activat por tui conto. Ja li clave de securitá posse esser usat por intrar. + subject: 'Mastodon: Autentication per clave de securitá activat' title: Claves de securitá activisat omniauth_callbacks: failure: Ne posset autenticar te de %{kind} pro "%{reason}". @@ -73,12 +87,22 @@ ie: updated: Tui passa-parol ha esset changeat successosimen. Tu nu ha apertet session. updated_not_active: Tui passa-parol ha esset changeat successosimen. registrations: + destroyed: Adío! Tui conto ha esset anullat con successe. Noi espera revider te pos ne long. signed_up: Benevenit! Tu ha successat registrar te. + signed_up_but_inactive: Tu ha registrat te con successe, támen noi ne posset far te intrar pro que tui conto ancor ne ha esset activat. + signed_up_but_locked: Tu ha registrat te con successe, támen noi ne posset far te intrar pro que tui conto es serrat. + signed_up_but_pending: Un missage con un ligament de confirmation ha esset inviat a tui adresse electronic. Pos har cliccat sur li ligament, noi va inspecter tui aplication. Tu va reciver un notification si it es aprobat. + signed_up_but_unconfirmed: Un missage con un ligament de confirmation ha esset inviat a tui adresse electronic. Ples sequer li ligament por activar tui conto, e confirmar tui spamiere si tu ne ha recivet li e-posta. + update_needs_confirmation: Tu ha actualisat tui conto con successe, ma noi deve verificar tui nov adresse electronic. Ples confirmar tui e-postas e sequer li ligament de confirmation por confirmar li nov adresse, e inspecter tui spamiere si tu ne ha recivet li e-posta. updated: Tui conto ha esset actualisat successosimen. sessions: already_signed_out: Exeat successosimen. signed_in: Intrat successosimen. signed_out: Exeat successosimen. + unlocks: + send_instructions: Pos quelc minutes tu va reciver un e-posta con instructiones pri qualmen desserrar tui adresse electronic. Ples confirmar tui spamiere si tu ne vide li e-posta. + send_paranoid_instructions: Si tui conto existe, pos quelc minutes tu va reciver un e-posta con instructiones pri qualmen desserrar it. Ples confirmar tui spamiere si tu ne recive li e-posta. + unlocked: Tui conto ha esset desserrat con successe. Ples intrar por continuar. errors: messages: already_confirmed: esset ja confirmat, ples prova intrar diff --git a/config/locales/doorkeeper.br.yml b/config/locales/doorkeeper.br.yml index 3de6230d4c..7b7f4155bd 100644 --- a/config/locales/doorkeeper.br.yml +++ b/config/locales/doorkeeper.br.yml @@ -102,6 +102,7 @@ br: bookmarks: Sinedoù filters: Siloù lists: Listennoù + media: Restroù media stag mutes: Kuzhet search: Klask statuses: Toudoù diff --git a/config/locales/doorkeeper.ia.yml b/config/locales/doorkeeper.ia.yml index 55f28634a5..ec85df24fc 100644 --- a/config/locales/doorkeeper.ia.yml +++ b/config/locales/doorkeeper.ia.yml @@ -10,6 +10,8 @@ ia: buttons: cancel: Cancellar edit: Modificar + confirmations: + destroy: Es tu secur? edit: title: Modificar application index: @@ -45,11 +47,22 @@ ia: title: accounts: Contos admin/accounts: Gestion de contos + bookmarks: Marcapaginas + conversations: Conversationes favourites: Favoritos lists: Listas notifications: Notificationes push: Notificationes push + search: Cercar + statuses: Messages layouts: admin: nav: applications: Applicationes + oauth2_provider: Fornitor OAuth2 + scopes: + write:accounts: modificar tu profilo + write:favourites: messages favorite + write:lists: crear listas + write:notifications: rader tu notificationes + write:statuses: publicar messages diff --git a/config/locales/doorkeeper.ie.yml b/config/locales/doorkeeper.ie.yml index f49eb1d968..0119f3573f 100644 --- a/config/locales/doorkeeper.ie.yml +++ b/config/locales/doorkeeper.ie.yml @@ -28,7 +28,10 @@ ie: destroy: Es tu cert? edit: title: Modificar aplication + form: + error: Ups! Ples inspecter tui formul por possibil erras help: + native_redirect_uri: Usar %{native_redirect_uri} por local provas redirect_uri: Usar un linea per URI scopes: Separar scopes con intersticies. Lassar blanc por usar li scopes predefinit. index: @@ -57,8 +60,11 @@ ie: error: title: Alquo ha errat new: + prompt_html: "%{client_name}, un aplication de triesim partise, vole permission por accesser tui conto. Si tu ne fide it, ne autorisa it." review_permissions: Inspecter permissiones title: Autorisation besonat + show: + title: Copiar ti-ci code de autorisation e glutinar it al demanda. authorized_applications: buttons: revoke: Revocar @@ -66,6 +72,7 @@ ie: revoke: Es tu cert? index: authorized_at: Autorisat ye %{date} + description_html: Hay aplicationes queles posse accesser tui conto tra li API. Si trova si aplicationes queles tu ne reconosse, o un aplication quel ha conduit se mal, tu posse revocar su accesse. last_used_at: Ultimmen usat ye %{date} never_used: Nequande usat scopes: Permissiones @@ -73,14 +80,25 @@ ie: title: Tui autorisat aplicationes errors: messages: + access_denied: Demanda negat per li proprietario del ressurse o servitor de autorisation. + credential_flow_not_configured: Falliment de flution Resource Owner Pasword Credentials pro ínconfigurat Doorkeeper.configure.resource_owner_from_credentials. invalid_client: Fallit autentification pro ínconosset client, manca de client-autentification, o ne subtenet metode de autentification. + invalid_grant: Li providet autorisation ó es ínvalid, expirat, revocat, ne acorda con li URI de redirection usat in li demanda de autorisation, ó ha esset emisset a un altri client. invalid_redirect_uri: Li uri de redirection includet ne es valid. invalid_request: + missing_param: 'Mancant postulat parametre: %{value}.' + request_not_authorized: Demanda besonant autorisation. Hay un mancant o ínvalid parametre besonat por autorisar li demanda. unknown: Li petition manca un postulat parametre, include un ne apoyat parametre-valore, o es altrimen mal format. + invalid_resource_owner: Sive li credentiales de ressurse-proprietario providet es ínvalid, sive li ressurse-proprietario ne posse esser trovat + invalid_scope: Li scope demandat es ínvalid, ínconosset, o malformat. invalid_token: expired: Li access-clave expirat revoked: Li access-clave esset revocat unknown: Li accesse-clave es ínvalid + resource_owner_authenticator_not_configured: Sercha por Proprietario de Ressurse fallit pro ínconfigurat Doorkeeper.configure.resource_owner_authenticator. + server_error: Li servitor de autorisation incontrat un ínexpectat condition quel impedit it a plenar li demanda. + temporarily_unavailable: Li servitor de autorisation actualmen ne posse tractar li demanda pro un temporari supercargada o mantention del servitor. + unauthorized_client: Li client ne es autorisat a efectuar li demanda con ti-ci metode. unsupported_grant_type: Li tip de autorisation concedet ne es subtenet per li autorisant servitor. unsupported_response_type: Li autorisant servitor ne subtene ti-ci tip de response. flash: @@ -108,6 +126,7 @@ ie: blocks: Bloccas bookmarks: Marcatores conversations: Conversationes + crypto: Incription del cap al fine favourites: Favorites filters: Filtres follow: Seques, silentias e bloccas @@ -144,6 +163,7 @@ ie: admin:write:email_domain_blocks: far actiones de moderation sur bloccas de dominia basat sur e-posta admin:write:ip_blocks: fa moderatori actiones sur bloccas de IP admin:write:reports: far moderatori actiones sur raportes + crypto: usar incription del cap al fine follow: modifica li relationes del conto push: reciver tui pussa-notificationes read: lee omni datas de tui conto @@ -162,6 +182,7 @@ ie: write: modificar li tot data de tui conto write:accounts: modifica tui profile write:blocks: bloccar contos e dominias + write:bookmarks: marcar postas write:conversations: silentiar e deleter conversationes write:favourites: favorit postas write:filters: crea filtres diff --git a/config/locales/et.yml b/config/locales/et.yml index 2d48edc295..806238431d 100644 --- a/config/locales/et.yml +++ b/config/locales/et.yml @@ -425,6 +425,7 @@ et: view: Vaata domeeniblokeeringut email_domain_blocks: add_new: Lisa uus + allow_registrations_with_approval: Luba kinnitamisega registreerimine attempts_over_week: one: "%{count} katse viimase nädala kestel" other: "%{count} liitumiskatset viimase nädala kestel" diff --git a/config/locales/fr-QC.yml b/config/locales/fr-QC.yml index 00a59463cd..3d85ced151 100644 --- a/config/locales/fr-QC.yml +++ b/config/locales/fr-QC.yml @@ -425,6 +425,7 @@ fr-QC: view: Afficher les blocages de domaines email_domain_blocks: add_new: Ajouter + allow_registrations_with_approval: Autoriser les inscriptions avec approbation attempts_over_week: one: "%{count} tentative au cours de la dernière semaine" other: "%{count} tentatives au cours de la dernière semaine" diff --git a/config/locales/fr.yml b/config/locales/fr.yml index 0a6601bbc1..5c6166ddc3 100644 --- a/config/locales/fr.yml +++ b/config/locales/fr.yml @@ -425,6 +425,7 @@ fr: view: Afficher les blocages de domaines email_domain_blocks: add_new: Ajouter + allow_registrations_with_approval: Autoriser les inscriptions avec approbation attempts_over_week: one: "%{count} tentative au cours de la dernière semaine" other: "%{count} tentatives au cours de la dernière semaine" diff --git a/config/locales/ia.yml b/config/locales/ia.yml index 795ed8cc94..c4f236881d 100644 --- a/config/locales/ia.yml +++ b/config/locales/ia.yml @@ -1,28 +1,61 @@ --- ia: + about: + contact_missing: Non definite admin: accounts: + are_you_sure: Es tu secur? + by_domain: Dominio + custom: Personalisate delete: Deler datos deleted: Delite + disable_two_factor_authentication: Disactivar 2FA display_name: Nomine visibile + domain: Dominio enabled: Activate location: all: Toto title: Location moderation: disabled: Disactivate + most_recent_activity: Activitate plus recente + most_recent_ip: IP plus recente + public: Public reset: Reinitialisar reset_password: Reinitialisar contrasigno search: Cercar security: Securitate + security_measures: + only_password: Solmente contrasigno + password_and_2fa: Contrasigno e 2FA + statuses: Messages + title: Contos username: Nomine de usator + action_logs: + action_types: + reset_password_user: Reinitialisar contrasigno + announcements: + new: + create: Crear annuncio + title: Nove annuncio + title: Annuncios custom_emojis: + by_domain: Dominio copy: Copiar create_new_category: Crear nove categoria delete: Deler + disable: Disactivar + disabled: Disactivate + dashboard: + active_users: usatores active + new_users: nove usatores + website: Sito web + domain_allows: + add_new: Permitter federation con dominio domain_blocks: confirm_suspension: cancel: Cancellar + domain: Dominio export: Exportar import: Importar email_domain_blocks: @@ -38,9 +71,11 @@ ia: instance_languages_dimension: Linguas principal delivery: unavailable: Non disponibile + empty: Necun dominios trovate. private_comment: Commento private public_comment: Commento public invites: + deactivate_all: Disactivar toto filter: available: Disponibile ip_blocks: @@ -50,6 +85,18 @@ ia: '15778476': 6 menses '2629746': 1 mense '86400': 1 die + new: + title: Crear un nove regula IP + title: Regulas IP + relays: + delete: Deler + disable: Disactivar + disabled: Disactivate + enable: Activar + enabled: Activate + reports: + are_you_sure: Es tu secur? + cancel: Cancellar statuses_cleanup: min_age: '1209600': 2 septimanas diff --git a/config/locales/ie.yml b/config/locales/ie.yml index 638205a7f4..c85e97b51d 100644 --- a/config/locales/ie.yml +++ b/config/locales/ie.yml @@ -288,6 +288,7 @@ ie: update_status_html: "%{name} actualisat posta de %{target}" update_user_role_html: "%{name} changeat li rol %{target}" deleted_account: deletet conto + empty: Null registres trovat. filter_by_action: Filtrar per action filter_by_user: Filtrar per usator title: Jurnale de audit @@ -468,6 +469,9 @@ ie: unsuppress: Restaurar seque-recomandation instances: availability: + description_html: + one: Si liveration al dominia falli por %{count} die sin successe, null provas in plu va esser efectuat til quande un liveration del dominia es recivet. + other: Si liveration al dominia falli por %{count} dies sin successe, null provas in plu va esser efectuat til quande un liveration del dominia es recivet. failure_threshold_reached: Límite de falliment atinget ye %{date}. failures_recorded: one: Fallit prova por %{count} die. @@ -523,6 +527,7 @@ ie: private_comment: Privat comenta public_comment: Public comenta purge: Purgar + purge_description_html: Si tu crede que ti-ci dominia es for linea por sempre, tu posse deleter omni archives de conto e associat data de ti-ci dominia de tui magasinage. Alquant témpor va esser possibilmen besonat. title: Federation total_blocked_by_us: Bloccat de nos total_followed_by_them: Sequet de les @@ -737,6 +742,7 @@ ie: preamble: Customisar li interfacie web de Mastodon. title: Aspecte branding: + preamble: Li reclamage de tui servitor diferentia it de altri servitores in li retage. Ti-ci information posse esser monstrat tra mult ambientes, tales quam li interfacie web de Mastodon, nativ aplicationes, previsiones de ligamentes sur altri web-situs, altri missage-aplicationes, etc. Pro to it es recomendat a mantener li information clar, curt, e concis. title: Marca captcha_enabled: desc_html: To ci usa extern scrites de hCaptcha, quel posse esser ínquietant pro rasones de securitá e privatie. In plu, it posse far li processu de registration mult plu desfacil (particularimen por tis con deshabilitás). Pro ti rasones, ples considerar alternativ mesuras, tales quam registration per aprobation o invitation. @@ -746,6 +752,7 @@ ie: title: Retention de contenete default_noindex: desc_html: Afecta omni usatores qui ne ha changeat ti parametre personalmen + title: Predefinir que usatores ne apari in índexes de serchatores discovery: follow_recommendations: Seque-recomandationes preamble: Exposir interessant contenete es importantissim por incorporar nov usatores qui fórsan conosse nequi che Mastodon. Decider qualmen diferent utensiles de decovrition functiona che vor servitor. @@ -832,12 +839,16 @@ ie: message_html: Li cluster Elasticsearch es ínsalubri (statu rubi), functiones por serchar ne disponibil elasticsearch_health_yellow: message_html: Li cluster Elasticsearch es ínsalubri (statu yelb); investigar li rason vell esser un bon idé + elasticsearch_index_mismatch: + message_html: Índex-mappamentes de Elasticsearch es oldijat. Ples executer tootctl search deploy --only=%{value} elasticsearch_preset: action: Vider li documentation message_html: Tui cluster Elasticsearch have plu quam un node, ma Mastodon ne es configurat por usar les. elasticsearch_preset_single_node: action: Vider li documentation message_html: Tui cluster Elasticsearch have solmen un node, ples configurar ES_PRESET quam single_node_cluster. + elasticsearch_reset_chewy: + message_html: Tui sistema-índex por Elasticsearch ha oldijat pro un change de parametres. Ples executer tootctl search deploy --reset-chewy por actualisar it. elasticsearch_running_check: message_html: Ne posset conexer a Elasticsearch. Ples confirmar que it ha esset executet, o desactivar serchada de plen textu elasticsearch_version_check: @@ -846,6 +857,8 @@ ie: rules_check: action: Gerer regules de servitor message_html: Tu ancor ne ha definit quelcunc regules de servitor. + sidekiq_process_check: + message_html: Null processe Sidekiq executet por li caude %{value}(s). Ples reviser tui configuration Sidekiq software_version_critical_check: action: Vider actualisationes disponibil message_html: Un critical actualisation por Mastodon es disposibil, ples actualisar tam rapidmen possibil. @@ -935,6 +948,7 @@ ie: webhooks: add_new: Adjunter punctu terminal delete: Deleter + description_html: Un webhook possibilisa que Mastodon pussa actual notificationes pri selectet evenimentes a tui propri aplication, por que it mey automaticmen activar reactiones. disable: Desactivisar disabled: Desactivisat edit: Redacter punctu terminal @@ -1409,6 +1423,7 @@ ie: missing_also_known_as: ne es un alias de ti-ci conto move_to_self: ne posse esser li conto actual not_found: ne posset esser trovat + on_cooldown: Tu es in un periode de refrigidation followers_count: Sequitores al témpor de translocation incoming_migrations: Translocant de un conto diferent incoming_migrations_html: Por mover de un altri conto a ti-ci, erstmen tu deve crear un alias de conto. @@ -1483,7 +1498,9 @@ ie: units: billion: B million: M + quadrillion: Q thousand: m + trillion: T otp_authentication: code_hint: Inmetter li code generat de tui aplication de autentication por confirmar description_html: Si tu activisa 2-factor autentication per un aplication de autentication, aperter un session va postular que tu have possession de tui telefon, quel va generar codes por que tu mey inmetter les. @@ -1843,6 +1860,7 @@ ie: error: Un problema evenit durant li deletion de tui clave de securitá. Ples provar denov. success: Tui clave de securitá esset successosimen deletet. invalid_credential: Ínvalid clave de securitá + nickname_hint: Scrir li moc-nómine de tui nov clave de securitá not_enabled: Tu ancor ne ha possibilisat WebAuthn not_supported: Ti-ci navigator ne subtene claves de securitá otp_required: Por usar claves de securitá, ples activisar 2-factor autentication. diff --git a/config/locales/is.yml b/config/locales/is.yml index bf16d877db..7083a226dd 100644 --- a/config/locales/is.yml +++ b/config/locales/is.yml @@ -425,6 +425,7 @@ is: view: Skoða útilokun á léni email_domain_blocks: add_new: Bæta við nýju + allow_registrations_with_approval: Leyfa skráningar með samþykki attempts_over_week: one: "%{count} tilraun síðustu viku" other: "%{count} tilraunir til nýskráningar í síðustu viku" diff --git a/config/locales/ja.yml b/config/locales/ja.yml index 8682f37eec..97ec886112 100644 --- a/config/locales/ja.yml +++ b/config/locales/ja.yml @@ -418,6 +418,7 @@ ja: view: ドメインブロックを表示 email_domain_blocks: add_new: 新規追加 + allow_registrations_with_approval: 承認制での新規登録を可能にする attempts_over_week: other: 先週は%{count}回サインアップが試みられました created_msg: メールドメインブロックに追加しました diff --git a/config/locales/lad.yml b/config/locales/lad.yml index 323ade8ddb..550036b340 100644 --- a/config/locales/lad.yml +++ b/config/locales/lad.yml @@ -421,6 +421,7 @@ lad: view: Ve domeno blokado email_domain_blocks: add_new: Adjustar muevo + allow_registrations_with_approval: Permite enrejistrasyones kon aprovasyon attempts_over_week: one: "\"%{count} prova durante la ultima semana" other: "%{count} provas de enrejistrarse durante la ultima semana" diff --git a/config/locales/nl.yml b/config/locales/nl.yml index b2894e4abb..34769e08ec 100644 --- a/config/locales/nl.yml +++ b/config/locales/nl.yml @@ -425,7 +425,7 @@ nl: view: Domeinblokkade bekijken email_domain_blocks: add_new: Nieuwe toevoegen - allow_registrations_with_approval: Inschrijvingen met toestemming toestaan + allow_registrations_with_approval: Inschrijvingen met goedkeuring toestaan attempts_over_week: one: "%{count} registratiepoging tijdens de afgelopen week" other: "%{count} registratiepogingen tijdens de afgelopen week" diff --git a/config/locales/nn.yml b/config/locales/nn.yml index 70cbc27d6d..de23096ed1 100644 --- a/config/locales/nn.yml +++ b/config/locales/nn.yml @@ -425,7 +425,7 @@ nn: view: Vis domeneblokkering email_domain_blocks: add_new: Lag ny - allow_registrations_with_approval: Tillat registreringer med godkjenning + allow_registrations_with_approval: Tillat registreringar med godkjenning attempts_over_week: one: "%{count} forsøk i løpet av den siste uken" other: "%{count} forsøk på å opprette konto i løpet av den siste uken" diff --git a/config/locales/simple_form.br.yml b/config/locales/simple_form.br.yml index 09fe1f6d1d..9e8aefad49 100644 --- a/config/locales/simple_form.br.yml +++ b/config/locales/simple_form.br.yml @@ -54,9 +54,11 @@ br: username: Anv whole_word: Ger a-bezh featured_tag: - name: Ger-klik + name: Hashtag invite: comment: Evezhiadenn + invite_request: + text: Perak e fell deoc'h enskrivañ? ip_block: comment: Evezhiadenn ip: IP @@ -66,8 +68,9 @@ br: rule: text: Reolenn tag: - name: Ger-klik + name: Hashtag trendable: Aotren an hashtag-mañ da zont war wel dindan tuadurioù + usable: Aotren an embannadurioù da implijout an hashtag-mañ user: role: Roll user_role: diff --git a/config/locales/simple_form.ie.yml b/config/locales/simple_form.ie.yml index 72797bde5e..dfd0836412 100644 --- a/config/locales/simple_form.ie.yml +++ b/config/locales/simple_form.ie.yml @@ -62,6 +62,7 @@ ie: setting_use_blurhash: Gradientes es basat sur li colores del celat visuales ma obscura omni detallies setting_use_pending_items: Celar nov postas detra un clicc vice rular li témpor-linea automaticmen username: Tu posse usar lítteres, númeres e sublineas + whole_word: Quande li clave-parol o frase es solmen alfanumeric, it va esser aplicat solmen si it egala al tot parol domain_allow: domain: Ti dominia va posser obtener data de ti-ci servitor, e data venient de it va esser tractat e inmagasinat email_domain_block: @@ -82,20 +83,29 @@ ie: content_cache_retention_period: Omni postas e boosts de altri servitores va esser deletet pos li specificat quantitá de dies. Quelc postas fórsan va esser ínrestaurabil. Omni pertinent marcatores, favorites e boosts anc va esser perdit e ínpossibil a restaurar. custom_css: On posse aplicar customisat stiles al web-version de Mastodon. mascot: Substitue li ilustration in li avansat interfacie web. + media_cache_retention_period: Descargat files de media va esser deletet pos li specificat quantitá de dies quande li valore es positiv, e re-descargat sur demanda. peers_api_enabled: Un liste de nómines de dominia queles ti-ci servitor ha incontrat in li fediverse. Ci null data es includet pri ca tu confedera con un cert servitor o ne; it indica solmen que tui servitor conosse it. Usat per servicies colectent general statisticas pri federation. profile_directory: Li profilarium monstra omni usatores volent esser decovribil. + require_invite_text: Quande registrationes besona manual aprobation, fa que li textu "Pro quo tu vole registrar te?" es obligatori vice facultativ site_contact_email: Qualmen on posse contacter te por inquestes legal o de apoy. site_contact_username: Qualmen li gente posse atinger te sur Mastodon. + site_extended_description: Quelcunc information in plu quel posse esser util a visitores e a tui usatores. On posse structurar it con li sintaxe Markdown. site_short_description: Un curt descrition por auxiliar identificar tui servitor. Qui gere it, por qual persones it es? + site_terms: Usar tui propri politica de privatie, o lassar blanc por usar li predefinitiones. Posse esser structurat con li sintaxe Markdown. site_title: Quant persones posse aluder a tui servitor ultra su nómine de dominia. status_page_url: URL de un págine monstrant li statu de ti-ci servitor durant un ruptura de servicie theme: Li dessine quel ínregistrat visitantes e nov usatores vide. thumbnail: Un image de dimensiones circa 2:1 monstrat along tui servitor-information. timeline_preview: Ínregistrat visitantes va posser vider li max recent public postas disponibil che li servitor. + trendable_by_default: Pretersaltar un manual revision de contenete in tendentie. Mem pos to on posse remover índividual pezzes de tendentie. trends: Tendenties monstra quel postas, hashtags e novas es ganiant atention sur tui servitor. trends_as_landing_page: Monstrar populari contenete a ínregistrat visitantes vice un description del servitor. Besona que tendenties es activisat. form_challenge: current_password: Tu nu intra un area secur + imports: + data: File CSV exportat de un altri servitor Mastodon + invite_request: + text: To va auxiliar nos a reviser tui aplication ip_block: comment: Facultativ. Ne obliviar pro quo tu adjuntet ti-ci regul. expires_in: IP-adresses es un ressurse finit, quelcvez partit e transferet de manu a manu. Pro to, un índefinit bloccada de IP ne es recomandat. @@ -109,15 +119,21 @@ ie: text: Descrir un regul o postulation por usatores sur ti-ci servitor. Prova scrir un descrition curt e simplic sessions: otp: 'Intrar li 2-factor code generat del app sur tui portabile o usar un de tui codes de recuperation:' + webauthn: Si it es un clave USB, inserter it con certitá e, si necessi, tappa it. settings: + indexable: Tui págine de profil va posser aparir in sercha-resultates sur Google, Bing, e altres. show_application: Totvez, tu va sempre posser vider quel app ha publicat tui posta. + tag: + name: Tu posse changear solmen li minu/majusculitá del lítteres, por exemple, por far it plu leibil user: + chosen_languages: Quande selectet, solmen postas in ti lingues va esser monstrat in public témpor-lineas role: Permissiones de usator decidet per su rol user_role: color: Color a usar por li rol tra li UI, quam RGB (rubi-verdi-blu) in formate hex highlighted: Va far li rol publicmen visibil name: Public nómine del rol, si li rol va esser monstrat quam signe permissions_as_keys: Usatores con ti-ci rol va haver accesse a... + position: Plu alt roles decide un resolution de conflict in cert situationes. Cert actiones posse esser efectuat solmen a roles con plu bass prioritá webhook: events: Selecter evenimentes a misser template: Composir tui propri carga JSON usant interpolation de variabiles. Lassa blanc por JSON predefinit. @@ -129,6 +145,7 @@ ie: name: Etiquette value: Contenete indexable: Includer public postas in resultates de sercha + show_collections: Monstrar persones queles on seque e sequitores sur profil unlocked: Automaticmen acceptar nov sequitores account_alias: acct: Usator-nómine del anteyan conto @@ -138,6 +155,7 @@ ie: text: Textu prefigurat title: Titul admin_account_action: + include_statuses: Includer raportat postas in li e-posta send_email_notification: Notificar li usator per e-posta text: Admonition customisat type: Action @@ -172,6 +190,7 @@ ie: fields: Campes aditional header: Cap-image honeypot: "%{label} (ne plenar)" + inbox_url: URL del inbuxe de relé irreversible: Lassar cader vice celar locale: Lingue del interfacie max_uses: Max grand númere de usas @@ -181,10 +200,15 @@ ie: password: Passa-parol phrase: Clave-parol o frase setting_advanced_layout: Possibilisar web-interfacie avansat + setting_aggregate_reblogs: Gruppar boosts in témpor-lineas setting_always_send_emails: Sempre misser notificationes de e-posta + setting_auto_play_gif: Reproducter automaticmen animat GIFs + setting_boost_modal: Monstrar dialog de confirmation ante boostar setting_default_language: Lingue in quel postar setting_default_privacy: Privatie de postada setting_default_sensitive: Sempre marcar medie quam sensitiv + setting_delete_modal: Monstrar dialog de confirmation ante deleter un posta + setting_disable_swiping: Desactivar motiones de glissar setting_display_media: Exposition de medie setting_display_media_default: Predefinitiones setting_display_media_hide_all: Celar omno @@ -196,6 +220,7 @@ ie: setting_theme: Tema de situ setting_trends: Monstrar li hodial tendenties setting_unfollow_modal: Monstrar dialog de confirmation ante dessequer alquem + setting_use_blurhash: Monstrar colorosi gradientes por celat medie setting_use_pending_items: Mode lent severity: Severitá sign_in_token_attempt: Code de securitá @@ -219,6 +244,7 @@ ie: closed_registrations_message: Customisat missage quande registration ne disponibil content_cache_retention_period: Periode de retention por cachat contenete custom_css: Custom CSS + mascot: Customisat mascot (hereditat) media_cache_retention_period: Periode de retention por cachat medie peers_api_enabled: Publicar liste de conosset servitores per li API profile_directory: Possibilisar profilarium @@ -293,6 +319,7 @@ ie: position: Prioritá webhook: events: Evenimentes activisat + template: Modelle de carga url: URL de punctu terminal 'no': 'No' not_recommended: Ne recomandat diff --git a/config/locales/sk.yml b/config/locales/sk.yml index cfc5ee7087..89d41b4616 100644 --- a/config/locales/sk.yml +++ b/config/locales/sk.yml @@ -548,6 +548,7 @@ sk: delete_html: Vymaž pohoršujúce príspevky mark_as_sensitive_html: Označ médiá pohoršujúcich príspevkov za chúlostivé close_report: 'Označ hlásenie #%{id} za vyriešené' + target_origin: Pôvod nahláseného účtu title: Hlásenia unassign: Odober unknown_action_msg: 'Neznáma akcia: %{action}' @@ -636,6 +637,7 @@ sk: application: Aplikácia back_to_account: Späť na účet batch: + remove_from_report: Vymaž z hlásenia report: Hlásenie deleted: Vymazané favourites: Obľúbené diff --git a/config/locales/sv.yml b/config/locales/sv.yml index f7a6f33a08..9a2bedbdfe 100644 --- a/config/locales/sv.yml +++ b/config/locales/sv.yml @@ -425,6 +425,7 @@ sv: view: Visa domänblock email_domain_blocks: add_new: Lägg till ny + allow_registrations_with_approval: Tillåt registreringar med godkännande attempts_over_week: one: "%{count} försök under den senaste veckan" other: "%{count} registreringsförsök under den senaste veckan" diff --git a/config/locales/vi.yml b/config/locales/vi.yml index 85aabe7176..f37132b6eb 100644 --- a/config/locales/vi.yml +++ b/config/locales/vi.yml @@ -1217,7 +1217,7 @@ vi: filters: contexts: account: Trang hồ sơ - home: Trang chính và danh sách + home: Trang chủ và danh sách notifications: Thông báo public: Tút công khai thread: Thảo luận @@ -1796,7 +1796,7 @@ vi: edit_profile_action: Cài đặt trang hồ sơ edit_profile_step: Bạn có thể chỉnh sửa trang hồ sơ của mình bằng cách tải lên ảnh đại diện, ảnh bìa, đổi biệt danh và hơn thế nữa. Bạn cũng có thể tự phê duyệt những người theo dõi mới. explanation: Dưới đây là một số mẹo để giúp bạn bắt đầu - final_action: Viết tút mới + final_action: Soạn tút mới final_step: 'Viết tút mới! Ngay cả khi chưa có người theo dõi, người khác vẫn có thể xem tút công khai của bạn trên bảng tin máy chủ và qua hashtag. Hãy giới thiệu bản thân với hashtag #introductions.' full_handle: Tên đầy đủ của bạn full_handle_hint: Đây cũng là địa chỉ được dùng để giao tiếp với tất cả mọi người. diff --git a/config/locales/zh-TW.yml b/config/locales/zh-TW.yml index 61650f8943..3f3057cc05 100644 --- a/config/locales/zh-TW.yml +++ b/config/locales/zh-TW.yml @@ -418,6 +418,7 @@ zh-TW: view: 顯示已封鎖網域 email_domain_blocks: add_new: 加入新項目 + allow_registrations_with_approval: 經允許後可註冊 attempts_over_week: other: 上週共有 %{count} 次註冊嘗試 created_msg: 已成功將電子郵件網域加入黑名單 From e827c4692c251e60509d30350660244b403b5760 Mon Sep 17 00:00:00 2001 From: Matt Jankowski Date: Mon, 8 Jan 2024 08:26:12 -0500 Subject: [PATCH 45/61] Use Arel `matches` method in CustomEmoji search (#28615) --- app/models/custom_emoji.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/models/custom_emoji.rb b/app/models/custom_emoji.rb index 550f005d59..1c9b443959 100644 --- a/app/models/custom_emoji.rb +++ b/app/models/custom_emoji.rb @@ -86,7 +86,7 @@ class CustomEmoji < ApplicationRecord end def search(shortcode) - where('"custom_emojis"."shortcode" ILIKE ?', "%#{shortcode}%") + where(arel_table[:shortcode].matches("%#{sanitize_sql_like(shortcode)}%")) end end From c52a593a3071d6a81e5ba00bc49c00f71a2aed6d Mon Sep 17 00:00:00 2001 From: Matt Jankowski Date: Mon, 8 Jan 2024 08:33:45 -0500 Subject: [PATCH 46/61] Remove unused scope `User.emailable` (#28647) --- app/models/user.rb | 1 - 1 file changed, 1 deletion(-) diff --git a/app/models/user.rb b/app/models/user.rb index be1e84b49c..55f654137a 100644 --- a/app/models/user.rb +++ b/app/models/user.rb @@ -117,7 +117,6 @@ class User < ApplicationRecord scope :active, -> { confirmed.where(arel_table[:current_sign_in_at].gteq(ACTIVE_DURATION.ago)).joins(:account).where(accounts: { suspended_at: nil }) } scope :matches_email, ->(value) { where(arel_table[:email].matches("#{value}%")) } scope :matches_ip, ->(value) { left_joins(:ips).where('user_ips.ip <<= ?', value).group('users.id') } - scope :emailable, -> { confirmed.enabled.joins(:account).merge(Account.searchable) } before_validation :sanitize_languages before_validation :sanitize_role From 4ccba94489a0bb69b549b3c4356a390a1751854a Mon Sep 17 00:00:00 2001 From: Matt Jankowski Date: Mon, 8 Jan 2024 08:35:53 -0500 Subject: [PATCH 47/61] Remove unused `*_silenced_accounts` scopes on Status (#28644) --- app/models/status.rb | 2 -- 1 file changed, 2 deletions(-) diff --git a/app/models/status.rb b/app/models/status.rb index 3faa507000..a498da288a 100644 --- a/app/models/status.rb +++ b/app/models/status.rb @@ -108,8 +108,6 @@ class Status < ApplicationRecord scope :without_reblogs, -> { where(statuses: { reblog_of_id: nil }) } scope :with_public_visibility, -> { where(visibility: :public) } scope :tagged_with, ->(tag_ids) { joins(:statuses_tags).where(statuses_tags: { tag_id: tag_ids }) } - scope :excluding_silenced_accounts, -> { left_outer_joins(:account).where(accounts: { silenced_at: nil }) } - scope :including_silenced_accounts, -> { left_outer_joins(:account).where.not(accounts: { silenced_at: nil }) } scope :not_excluded_by_account, ->(account) { where.not(account_id: account.excluded_from_timeline_account_ids) } scope :not_domain_blocked_by_account, ->(account) { account.excluded_from_timeline_domains.blank? ? left_outer_joins(:account) : left_outer_joins(:account).where('accounts.domain IS NULL OR accounts.domain NOT IN (?)', account.excluded_from_timeline_domains) } scope :tagged_with_all, lambda { |tag_ids| From 3e7a9266ea0d30960ef9ad537443bb66c64d1bb5 Mon Sep 17 00:00:00 2001 From: Matt Jankowski Date: Mon, 8 Jan 2024 08:36:47 -0500 Subject: [PATCH 48/61] Remove unused `EmojiFormatter#count_tag_nesting` method (#28643) --- app/lib/emoji_formatter.rb | 10 ---------- 1 file changed, 10 deletions(-) diff --git a/app/lib/emoji_formatter.rb b/app/lib/emoji_formatter.rb index 15b98dc57e..2a3683c499 100644 --- a/app/lib/emoji_formatter.rb +++ b/app/lib/emoji_formatter.rb @@ -66,16 +66,6 @@ class EmojiFormatter @emoji_map ||= custom_emojis.each_with_object({}) { |e, h| h[e.shortcode] = [full_asset_url(e.image.url), full_asset_url(e.image.url(:static))] } end - def count_tag_nesting(tag) - if tag[1] == '/' - -1 - elsif tag[-2] == '/' - 0 - else - 1 - end - end - def tag_for_emoji(shortcode, emoji) return content_tag(:span, ":#{shortcode}:", translate: 'no') if raw_shortcode? From cd58e37b25ae42aea55db2ed57c09c1263054fd0 Mon Sep 17 00:00:00 2001 From: Matt Jankowski Date: Mon, 8 Jan 2024 08:38:52 -0500 Subject: [PATCH 49/61] Remove unused `DomainBlock#affected_accounts_count` method (#28642) --- app/models/domain_block.rb | 5 ----- 1 file changed, 5 deletions(-) diff --git a/app/models/domain_block.rb b/app/models/domain_block.rb index f8058324a3..8da099256a 100644 --- a/app/models/domain_block.rb +++ b/app/models/domain_block.rb @@ -85,11 +85,6 @@ class DomainBlock < ApplicationRecord (reject_media || !other_block.reject_media) && (reject_reports || !other_block.reject_reports) end - def affected_accounts_count - scope = suspend? ? accounts.where(suspended_at: created_at) : accounts.where(silenced_at: created_at) - scope.count - end - def public_domain return domain unless obfuscate? From 9322396e58d9a715744d01d48fdb495c8d0e9037 Mon Sep 17 00:00:00 2001 From: Matt Jankowski Date: Mon, 8 Jan 2024 08:48:31 -0500 Subject: [PATCH 50/61] Use normalizes to prepare `Account#username` value (#28646) --- app/models/account.rb | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/app/models/account.rb b/app/models/account.rb index 2145cfcb64..886b29b873 100644 --- a/app/models/account.rb +++ b/app/models/account.rb @@ -108,6 +108,8 @@ class Account < ApplicationRecord validates :shared_inbox_url, absence: true, if: :local?, on: :create validates :followers_url, absence: true, if: :local?, on: :create + normalizes :username, with: ->(username) { username.squish } + scope :remote, -> { where.not(domain: nil) } scope :local, -> { where(domain: nil) } scope :partitioned, -> { order(Arel.sql('row_number() over (partition by domain)')) } @@ -475,7 +477,6 @@ class Account < ApplicationRecord end before_validation :prepare_contents, if: :local? - before_validation :prepare_username, on: :create before_create :generate_keys before_destroy :clean_feed_manager @@ -493,10 +494,6 @@ class Account < ApplicationRecord note&.strip! end - def prepare_username - username&.squish! - end - def generate_keys return unless local? && private_key.blank? && public_key.blank? From 3e43cd095c5e1ad20bbb70d0e8d2cc09fff776f1 Mon Sep 17 00:00:00 2001 From: Matt Jankowski Date: Mon, 8 Jan 2024 10:26:14 -0500 Subject: [PATCH 51/61] Remove unused scope `Announcement.without_muted` (#28645) --- app/models/announcement.rb | 1 - spec/models/announcement_spec.rb | 16 ---------------- 2 files changed, 17 deletions(-) diff --git a/app/models/announcement.rb b/app/models/announcement.rb index 00529766a4..cbcaef3daa 100644 --- a/app/models/announcement.rb +++ b/app/models/announcement.rb @@ -20,7 +20,6 @@ class Announcement < ApplicationRecord scope :unpublished, -> { where(published: false) } scope :published, -> { where(published: true) } - scope :without_muted, ->(account) { joins("LEFT OUTER JOIN announcement_mutes ON announcement_mutes.announcement_id = announcements.id AND announcement_mutes.account_id = #{account.id}").where(announcement_mutes: { id: nil }) } scope :chronological, -> { order(coalesced_chronology_timestamps.asc) } scope :reverse_chronological, -> { order(coalesced_chronology_timestamps.desc) } diff --git a/spec/models/announcement_spec.rb b/spec/models/announcement_spec.rb index e37b81a52e..c016a316cd 100644 --- a/spec/models/announcement_spec.rb +++ b/spec/models/announcement_spec.rb @@ -25,22 +25,6 @@ describe Announcement do end end - describe '#without_muted' do - let!(:announcement) { Fabricate(:announcement) } - let(:account) { Fabricate(:account) } - let(:muted_announcement) { Fabricate(:announcement) } - - before do - Fabricate(:announcement_mute, account: account, announcement: muted_announcement) - end - - it 'returns the announcements not muted by the account' do - results = described_class.without_muted(account) - expect(results).to include(announcement) - expect(results).to_not include(muted_announcement) - end - end - context 'with timestamped announcements' do let!(:adam_announcement) { Fabricate(:announcement, starts_at: 100.days.ago, scheduled_at: 10.days.ago, published_at: 10.days.ago, ends_at: 5.days.from_now) } let!(:brenda_announcement) { Fabricate(:announcement, starts_at: 10.days.ago, scheduled_at: 100.days.ago, published_at: 10.days.ago, ends_at: 5.days.from_now) } From e677eb164cfb69c11692ca5cd2072c26ca1d9509 Mon Sep 17 00:00:00 2001 From: Matt Jankowski Date: Mon, 8 Jan 2024 10:26:30 -0500 Subject: [PATCH 52/61] Remove unused `Announcement#time_range?` (#28648) --- app/models/announcement.rb | 4 ---- spec/models/announcement_spec.rb | 26 -------------------------- 2 files changed, 30 deletions(-) diff --git a/app/models/announcement.rb b/app/models/announcement.rb index cbcaef3daa..86f7037a56 100644 --- a/app/models/announcement.rb +++ b/app/models/announcement.rb @@ -54,10 +54,6 @@ class Announcement < ApplicationRecord update!(published: false, scheduled_at: nil) end - def time_range? - starts_at? && ends_at? - end - def mentions @mentions ||= Account.from_text(text) end diff --git a/spec/models/announcement_spec.rb b/spec/models/announcement_spec.rb index c016a316cd..612ba8bb0d 100644 --- a/spec/models/announcement_spec.rb +++ b/spec/models/announcement_spec.rb @@ -113,32 +113,6 @@ describe Announcement do end end - describe '#time_range?' do - it 'returns false when starts_at and ends_at are missing' do - record = Fabricate.build(:announcement, starts_at: nil, ends_at: nil) - - expect(record.time_range?).to be(false) - end - - it 'returns false when starts_at is present and ends_at is missing' do - record = Fabricate.build(:announcement, starts_at: 5.days.from_now, ends_at: nil) - - expect(record.time_range?).to be(false) - end - - it 'returns false when starts_at is missing and ends_at is present' do - record = Fabricate.build(:announcement, starts_at: nil, ends_at: 5.days.from_now) - - expect(record.time_range?).to be(false) - end - - it 'returns true when starts_at and ends_at are present' do - record = Fabricate.build(:announcement, starts_at: 5.days.from_now, ends_at: 10.days.from_now) - - expect(record.time_range?).to be(true) - end - end - describe '#reactions' do context 'with announcement_reactions present' do let!(:account) { Fabricate(:account) } From cd4b4d47346b4d874315fc2560f4cb1e0b1cb2a0 Mon Sep 17 00:00:00 2001 From: Matt Jankowski Date: Mon, 8 Jan 2024 10:31:13 -0500 Subject: [PATCH 53/61] Replace unused `by_recent_sign_in` scope (#28616) --- app/models/account.rb | 10 +++++++++- app/models/account_filter.rb | 10 +--------- 2 files changed, 10 insertions(+), 10 deletions(-) diff --git a/app/models/account.rb b/app/models/account.rb index 886b29b873..003b41b015 100644 --- a/app/models/account.rb +++ b/app/models/account.rb @@ -131,7 +131,7 @@ class Account < ApplicationRecord scope :discoverable, -> { searchable.without_silenced.where(discoverable: true).joins(:account_stat) } scope :followable_by, ->(account) { joins(arel_table.join(Follow.arel_table, Arel::Nodes::OuterJoin).on(arel_table[:id].eq(Follow.arel_table[:target_account_id]).and(Follow.arel_table[:account_id].eq(account.id))).join_sources).where(Follow.arel_table[:id].eq(nil)).joins(arel_table.join(FollowRequest.arel_table, Arel::Nodes::OuterJoin).on(arel_table[:id].eq(FollowRequest.arel_table[:target_account_id]).and(FollowRequest.arel_table[:account_id].eq(account.id))).join_sources).where(FollowRequest.arel_table[:id].eq(nil)) } scope :by_recent_status, -> { includes(:account_stat).merge(AccountStat.order('last_status_at DESC NULLS LAST')).references(:account_stat) } - scope :by_recent_sign_in, -> { order(Arel.sql('users.current_sign_in_at DESC NULLS LAST')) } + scope :by_recent_activity, -> { left_joins(:user, :account_stat).order(coalesced_activity_timestamps.desc).order(id: :desc) } scope :popular, -> { order('account_stats.followers_count desc') } scope :by_domain_and_subdomains, ->(domain) { where(domain: Instance.by_domain_and_subdomains(domain).select(:domain)) } scope :not_excluded_by_account, ->(account) { where.not(id: account.excluded_from_timeline_account_ids) } @@ -444,6 +444,14 @@ class Account < ApplicationRecord DeliveryFailureTracker.without_unavailable(urls) end + def coalesced_activity_timestamps + Arel.sql( + <<~SQL.squish + COALESCE(users.current_sign_in_at, account_stats.last_status_at, to_timestamp(0)) + SQL + ) + end + def from_text(text) return [] if text.blank? diff --git a/app/models/account_filter.rb b/app/models/account_filter.rb index 55d34e85c3..42b1c49538 100644 --- a/app/models/account_filter.rb +++ b/app/models/account_filter.rb @@ -104,15 +104,7 @@ class AccountFilter def order_scope(value) case value.to_s when 'active' - accounts_with_users - .left_joins(:account_stat) - .order( - Arel.sql( - <<~SQL.squish - COALESCE(users.current_sign_in_at, account_stats.last_status_at, to_timestamp(0)) DESC, accounts.id DESC - SQL - ) - ) + Account.by_recent_activity when 'recent' Account.recent else From 557c27e03b8a646644d1b1878d45d60931ace5a3 Mon Sep 17 00:00:00 2001 From: Matt Jankowski Date: Mon, 8 Jan 2024 11:43:38 -0500 Subject: [PATCH 54/61] Update haml_lint to version 0.53.0 (#28652) --- Gemfile.lock | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Gemfile.lock b/Gemfile.lock index e694dce0fb..442022e81a 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -336,8 +336,8 @@ GEM activesupport (>= 5.1) haml (>= 4.0.6) railties (>= 5.1) - haml_lint (0.52.0) - haml (>= 4.0) + haml_lint (0.53.0) + haml (>= 5.0) parallel (~> 1.10) rainbow rubocop (>= 1.0) From f7b61959cf932de6d1c0317b5b46a4b0a34a6b22 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Tue, 9 Jan 2024 09:05:16 +0100 Subject: [PATCH 55/61] Update babel monorepo to v7.23.8 (#28656) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- yarn.lock | 37 +++++++++++++------------------------ 1 file changed, 13 insertions(+), 24 deletions(-) diff --git a/yarn.lock b/yarn.lock index bec7709804..7bf70258be 100644 --- a/yarn.lock +++ b/yarn.lock @@ -746,22 +746,21 @@ __metadata: languageName: node linkType: hard -"@babel/plugin-transform-classes@npm:^7.23.5": - version: 7.23.5 - resolution: "@babel/plugin-transform-classes@npm:7.23.5" +"@babel/plugin-transform-classes@npm:^7.23.8": + version: 7.23.8 + resolution: "@babel/plugin-transform-classes@npm:7.23.8" dependencies: "@babel/helper-annotate-as-pure": "npm:^7.22.5" - "@babel/helper-compilation-targets": "npm:^7.22.15" + "@babel/helper-compilation-targets": "npm:^7.23.6" "@babel/helper-environment-visitor": "npm:^7.22.20" "@babel/helper-function-name": "npm:^7.23.0" - "@babel/helper-optimise-call-expression": "npm:^7.22.5" "@babel/helper-plugin-utils": "npm:^7.22.5" "@babel/helper-replace-supers": "npm:^7.22.20" "@babel/helper-split-export-declaration": "npm:^7.22.6" globals: "npm:^11.1.0" peerDependencies: "@babel/core": ^7.0.0-0 - checksum: 07988f52b4893151887d1ea6ff79e5fe834078c5731bd09babd5659edbbae21ea4e2de326a02443a63fd776b4c945da6177f07875b56fe66e0b7899e830a9e92 + checksum: 227ac5166501e04d9e7fbd5eda6869b084ffa4af6830ac12544ac6ea14953ca00eb1762b0df9349c0f6c8d2a799385910f558066cd0fb85b9ca437b1131a6043 languageName: node linkType: hard @@ -1345,8 +1344,8 @@ __metadata: linkType: hard "@babel/preset-env@npm:^7.11.0, @babel/preset-env@npm:^7.12.1, @babel/preset-env@npm:^7.22.4": - version: 7.23.7 - resolution: "@babel/preset-env@npm:7.23.7" + version: 7.23.8 + resolution: "@babel/preset-env@npm:7.23.8" dependencies: "@babel/compat-data": "npm:^7.23.5" "@babel/helper-compilation-targets": "npm:^7.23.6" @@ -1381,7 +1380,7 @@ __metadata: "@babel/plugin-transform-block-scoping": "npm:^7.23.4" "@babel/plugin-transform-class-properties": "npm:^7.23.3" "@babel/plugin-transform-class-static-block": "npm:^7.23.4" - "@babel/plugin-transform-classes": "npm:^7.23.5" + "@babel/plugin-transform-classes": "npm:^7.23.8" "@babel/plugin-transform-computed-properties": "npm:^7.23.3" "@babel/plugin-transform-destructuring": "npm:^7.23.3" "@babel/plugin-transform-dotall-regex": "npm:^7.23.3" @@ -1430,7 +1429,7 @@ __metadata: semver: "npm:^6.3.1" peerDependencies: "@babel/core": ^7.0.0-0 - checksum: ac9def873cec52ee02a550bde6e22eced16d1ae331bb8ebc82c03e4c91c12ac17e3e4027647e61612937bcc25ac46e71370aaf99dc2e85dbd11f7777ffeed54e + checksum: e602ad954645f1a509644e3d2c72b3c63bdc2273c377e7a83b78f076eca215887ea3624ffc36aaad03deb9ac8acd89e247fd4562b96e0f2b679485e20d8ff25f languageName: node linkType: hard @@ -1495,11 +1494,11 @@ __metadata: linkType: hard "@babel/runtime@npm:^7.0.0, @babel/runtime@npm:^7.1.2, @babel/runtime@npm:^7.11.2, @babel/runtime@npm:^7.12.0, @babel/runtime@npm:^7.12.13, @babel/runtime@npm:^7.12.5, @babel/runtime@npm:^7.13.8, @babel/runtime@npm:^7.18.3, @babel/runtime@npm:^7.2.0, @babel/runtime@npm:^7.20.13, @babel/runtime@npm:^7.22.3, @babel/runtime@npm:^7.23.2, @babel/runtime@npm:^7.3.1, @babel/runtime@npm:^7.5.5, @babel/runtime@npm:^7.6.3, @babel/runtime@npm:^7.8.4, @babel/runtime@npm:^7.8.7, @babel/runtime@npm:^7.9.2": - version: 7.23.7 - resolution: "@babel/runtime@npm:7.23.7" + version: 7.23.8 + resolution: "@babel/runtime@npm:7.23.8" dependencies: regenerator-runtime: "npm:^0.14.0" - checksum: 3e304133ee55b0750e03e53cb4efb47fb2bdcdb5795f85bbffa10595196c34b9be60eb65bd6d833c87f49fc827f0365f86f95f51d85b188004d3128bb5129c93 + checksum: ba5e8fbb32ef04f6cab5e89c54a0497c2fde7b730595cc1af93496270314f13ff2c6a9360fdb2f0bdd4d6b376752ce3cf85642bd6b876969a6a62954934c2df8 languageName: node linkType: hard @@ -13121,17 +13120,7 @@ __metadata: languageName: node linkType: hard -"postcss-selector-parser@npm:^6.0.11, postcss-selector-parser@npm:^6.0.13, postcss-selector-parser@npm:^6.0.2, postcss-selector-parser@npm:^6.0.4": - version: 6.0.13 - resolution: "postcss-selector-parser@npm:6.0.13" - dependencies: - cssesc: "npm:^3.0.0" - util-deprecate: "npm:^1.0.2" - checksum: 51f099b27f7c7198ea1826470ef0adfa58b3bd3f59b390fda123baa0134880a5fa9720137b6009c4c1373357b144f700b0edac73335d0067422063129371444e - languageName: node - linkType: hard - -"postcss-selector-parser@npm:^6.0.15": +"postcss-selector-parser@npm:^6.0.11, postcss-selector-parser@npm:^6.0.13, postcss-selector-parser@npm:^6.0.15, postcss-selector-parser@npm:^6.0.2, postcss-selector-parser@npm:^6.0.4": version: 6.0.15 resolution: "postcss-selector-parser@npm:6.0.15" dependencies: From 8e7d5fe2acf7282b0284f3f598c630e5eb58d0eb Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Tue, 9 Jan 2024 10:30:33 +0100 Subject: [PATCH 56/61] New Crowdin Translations (automated) (#28658) Co-authored-by: GitHub Actions --- app/javascript/mastodon/locales/fi.json | 10 +++++----- config/locales/fi.yml | 1 + 2 files changed, 6 insertions(+), 5 deletions(-) diff --git a/app/javascript/mastodon/locales/fi.json b/app/javascript/mastodon/locales/fi.json index 004898651b..00df0e537a 100644 --- a/app/javascript/mastodon/locales/fi.json +++ b/app/javascript/mastodon/locales/fi.json @@ -21,7 +21,7 @@ "account.blocked": "Estetty", "account.browse_more_on_origin_server": "Selaile lisää alkuperäisellä palvelimella", "account.cancel_follow_request": "Peruuta seurantapyyntö", - "account.copy": "Kopioi profiililinkki", + "account.copy": "Kopioi linkki profiiliin", "account.direct": "Mainitse @{name} yksityisesti", "account.disable_notifications": "Lopeta ilmoittamasta minulle, kun @{name} julkaisee", "account.domain_blocked": "Verkkotunnus estetty", @@ -53,7 +53,7 @@ "account.mute_notifications_short": "Mykistä ilmoitukset", "account.mute_short": "Mykistä", "account.muted": "Mykistetty", - "account.mutual": "Molemmat", + "account.mutual": "Seuraatte toisianne", "account.no_bio": "Kuvausta ei ole annettu.", "account.open_original_page": "Avaa alkuperäinen sivu", "account.posts": "Julkaisut", @@ -193,7 +193,7 @@ "conversation.mark_as_read": "Merkitse luetuksi", "conversation.open": "Näytä keskustelu", "conversation.with": "{names} kanssa", - "copy_icon_button.copied": "Kopioitiin leikepöydälle", + "copy_icon_button.copied": "Sisältö kopioitiin leikepöydälle", "copypaste.copied": "Kopioitu", "copypaste.copy_to_clipboard": "Kopioi leikepöydälle", "directory.federated": "Koko tunnettu fediversumi", @@ -483,10 +483,10 @@ "onboarding.follows.lead": "Kokoat oman kotisyötteesi itse. Mitä enemmän ihmisiä seuraat, sitä aktiivisempi ja kiinnostavampi syöte on. Nämä profiilit voivat olla alkuun hyvä lähtökohta — voit aina lopettaa niiden seuraamisen myöhemmin!", "onboarding.follows.title": "Mukauta kotisyötettäsi", "onboarding.profile.discoverable": "Aseta profiilini löydettäväksi", - "onboarding.profile.discoverable_hint": "Kun olet määrittänyt itsesi löydettäväksi Mastodonista, julkaisusi voivat näkyä hakutuloksissa ja suosituissa kohteissa ja profiiliasi voidaan ehdottaa käyttäjille, jotka ovat kiinnostuneet samoista aiheista kuin sinä.", + "onboarding.profile.discoverable_hint": "Kun olet määrittänyt itsesi löydettäväksi Mastodonista, julkaisusi voivat näkyä hakutuloksissa ja suosituissa kohteissa. Lisäksi profiiliasi voidaan ehdottaa käyttäjille, jotka ovat kiinnostuneita kanssasi samoista aiheista.", "onboarding.profile.display_name": "Näyttönimi", "onboarding.profile.display_name_hint": "Koko nimesi tai lempinimesi…", - "onboarding.profile.lead": "Voit viimeistellä tämän milloin tahansa asetuksista, jotka tarjoavat vielä enemmän mukautusvalintoja.", + "onboarding.profile.lead": "Voit viimeistellä tämän milloin tahansa asetuksista. Sieltä löydät myös lisää mukautusvaihtoehtoja.", "onboarding.profile.note": "Elämäkerta", "onboarding.profile.note_hint": "Voit @mainita muita käyttäjiä tai #aihetunnisteita…", "onboarding.profile.save_and_continue": "Tallenna ja jatka", diff --git a/config/locales/fi.yml b/config/locales/fi.yml index 93545b6a1b..75052c949d 100644 --- a/config/locales/fi.yml +++ b/config/locales/fi.yml @@ -425,6 +425,7 @@ fi: view: Näytä verkkotunnuksen esto email_domain_blocks: add_new: Lisää uusi + allow_registrations_with_approval: Salli rekisteröitymiset hyväksynnällä attempts_over_week: one: "%{count} yritystä viimeisen viikon aikana" other: "%{count} rekisteröitymisyritystä viimeisen viikon aikana" From 68f06f1fd4ef6173c22b61f2ea7ce22b76f85076 Mon Sep 17 00:00:00 2001 From: Matt Jankowski Date: Tue, 9 Jan 2024 04:31:32 -0500 Subject: [PATCH 57/61] Fix haml-lint `LineLength` cop for `settings/preferences/notifications/show` (#28655) --- .haml-lint_todo.yml | 5 ++--- .../settings/preferences/notifications/show.html.haml | 8 +++++++- 2 files changed, 9 insertions(+), 4 deletions(-) diff --git a/.haml-lint_todo.yml b/.haml-lint_todo.yml index 29646f28e8..09764c2f30 100644 --- a/.haml-lint_todo.yml +++ b/.haml-lint_todo.yml @@ -1,13 +1,13 @@ # This configuration was generated by # `haml-lint --auto-gen-config` -# on 2023-12-15 11:02:19 -0500 using Haml-Lint version 0.52.0. +# on 2024-01-08 14:02:57 -0500 using Haml-Lint version 0.53.0. # The point is for the user to remove these configuration records # one by one as the lints are removed from the code base. # Note that changes in the inspected code, or installation of new # versions of Haml-Lint, may require this file to be generated again. linters: - # Offense count: 11 + # Offense count: 10 LineLength: exclude: - 'app/views/admin/roles/_form.html.haml' @@ -17,5 +17,4 @@ linters: - 'app/views/settings/applications/_fields.html.haml' - 'app/views/settings/imports/index.html.haml' - 'app/views/settings/preferences/appearance/show.html.haml' - - 'app/views/settings/preferences/notifications/show.html.haml' - 'app/views/settings/preferences/other/show.html.haml' diff --git a/app/views/settings/preferences/notifications/show.html.haml b/app/views/settings/preferences/notifications/show.html.haml index 5cc101069c..d9d496c7fa 100644 --- a/app/views/settings/preferences/notifications/show.html.haml +++ b/app/views/settings/preferences/notifications/show.html.haml @@ -33,7 +33,13 @@ - if SoftwareUpdate.check_enabled? && current_user.can?(:view_devops) .fields-group - = ff.input :'notification_emails.software_updates', wrapper: :with_label, label: I18n.t('simple_form.labels.notification_emails.software_updates.label'), collection: %w(none critical patch all), label_method: ->(setting) { I18n.t("simple_form.labels.notification_emails.software_updates.#{setting}") }, include_blank: false, hint: false + = ff.input :'notification_emails.software_updates', + collection: %w(none critical patch all), + hint: false, + include_blank: false, + label_method: ->(setting) { I18n.t("simple_form.labels.notification_emails.software_updates.#{setting}") }, + label: I18n.t('simple_form.labels.notification_emails.software_updates.label'), + wrapper: :with_label %h4= t 'notifications.other_settings' From 5dc634796aba951f6a085e1ed0e1b807e25d7d41 Mon Sep 17 00:00:00 2001 From: Matt Jankowski Date: Tue, 9 Jan 2024 04:40:08 -0500 Subject: [PATCH 58/61] Misc coverage improvements re: sidekiq/inline (#28651) --- spec/models/notification_spec.rb | 82 +++++++++++++++++++ .../services/fan_out_on_write_service_spec.rb | 3 + spec/services/remove_status_service_spec.rb | 11 ++- 3 files changed, 95 insertions(+), 1 deletion(-) diff --git a/spec/models/notification_spec.rb b/spec/models/notification_spec.rb index d6e2282022..172d1c65b9 100644 --- a/spec/models/notification_spec.rb +++ b/spec/models/notification_spec.rb @@ -58,6 +58,88 @@ RSpec.describe Notification do end end + describe 'Setting account from activity_type' do + context 'when activity_type is a Status' do + it 'sets the notification from_account correctly' do + status = Fabricate(:status) + + notification = Fabricate.build(:notification, activity_type: 'Status', activity: status) + + expect(notification.from_account).to eq(status.account) + end + end + + context 'when activity_type is a Follow' do + it 'sets the notification from_account correctly' do + follow = Fabricate(:follow) + + notification = Fabricate.build(:notification, activity_type: 'Follow', activity: follow) + + expect(notification.from_account).to eq(follow.account) + end + end + + context 'when activity_type is a Favourite' do + it 'sets the notification from_account correctly' do + favourite = Fabricate(:favourite) + + notification = Fabricate.build(:notification, activity_type: 'Favourite', activity: favourite) + + expect(notification.from_account).to eq(favourite.account) + end + end + + context 'when activity_type is a FollowRequest' do + it 'sets the notification from_account correctly' do + follow_request = Fabricate(:follow_request) + + notification = Fabricate.build(:notification, activity_type: 'FollowRequest', activity: follow_request) + + expect(notification.from_account).to eq(follow_request.account) + end + end + + context 'when activity_type is a Poll' do + it 'sets the notification from_account correctly' do + poll = Fabricate(:poll) + + notification = Fabricate.build(:notification, activity_type: 'Poll', activity: poll) + + expect(notification.from_account).to eq(poll.account) + end + end + + context 'when activity_type is a Report' do + it 'sets the notification from_account correctly' do + report = Fabricate(:report) + + notification = Fabricate.build(:notification, activity_type: 'Report', activity: report) + + expect(notification.from_account).to eq(report.account) + end + end + + context 'when activity_type is a Mention' do + it 'sets the notification from_account correctly' do + mention = Fabricate(:mention) + + notification = Fabricate.build(:notification, activity_type: 'Mention', activity: mention) + + expect(notification.from_account).to eq(mention.status.account) + end + end + + context 'when activity_type is an Account' do + it 'sets the notification from_account correctly' do + account = Fabricate(:account) + + notification = Fabricate.build(:notification, activity_type: 'Account', account: account) + + expect(notification.account).to eq(account) + end + end + end + describe '.preload_cache_collection_target_statuses' do subject do described_class.preload_cache_collection_target_statuses(notifications) do |target_statuses| diff --git a/spec/services/fan_out_on_write_service_spec.rb b/spec/services/fan_out_on_write_service_spec.rb index f657f298de..6ad041193b 100644 --- a/spec/services/fan_out_on_write_service_spec.rb +++ b/spec/services/fan_out_on_write_service_spec.rb @@ -20,6 +20,8 @@ RSpec.describe FanOutOnWriteService, type: :service do ProcessMentionsService.new.call(status) ProcessHashtagsService.new.call(status) + Fabricate(:media_attachment, status: status, account: alice) + allow(redis).to receive(:publish) subject.call(status) @@ -49,6 +51,7 @@ RSpec.describe FanOutOnWriteService, type: :service do it 'is broadcast to the public stream' do expect(redis).to have_received(:publish).with('timeline:public', anything) expect(redis).to have_received(:publish).with('timeline:public:local', anything) + expect(redis).to have_received(:publish).with('timeline:public:media', anything) end end diff --git a/spec/services/remove_status_service_spec.rb b/spec/services/remove_status_service_spec.rb index 08ce0b0456..cd3224e028 100644 --- a/spec/services/remove_status_service_spec.rb +++ b/spec/services/remove_status_service_spec.rb @@ -20,7 +20,8 @@ RSpec.describe RemoveStatusService, type: :service do end context 'when removed status is not a reblog' do - let!(:status) { PostStatusService.new.call(alice, text: "Hello @#{bob.pretty_acct} ThisIsASecret") } + let!(:media_attachment) { Fabricate(:media_attachment, account: alice) } + let!(:status) { PostStatusService.new.call(alice, text: "Hello @#{bob.pretty_acct} ThisIsASecret", media_ids: [media_attachment.id]) } before do FavouriteService.new.call(jeff, status) @@ -37,6 +38,14 @@ RSpec.describe RemoveStatusService, type: :service do expect(HomeFeed.new(jeff).get(10).pluck(:id)).to_not include(status.id) end + it 'publishes to public media timeline' do + allow(redis).to receive(:publish).with(any_args) + + subject.call(status) + + expect(redis).to have_received(:publish).with('timeline:public:media', Oj.dump(event: :delete, payload: status.id.to_s)) + end + it 'sends Delete activity to followers' do subject.call(status) expect(a_request(:post, hank.inbox_url).with( From 7cd88ae2f489195d4868172e716baf0efc4a5d28 Mon Sep 17 00:00:00 2001 From: Claire Date: Thu, 4 Jan 2024 15:17:38 +0100 Subject: [PATCH 59/61] [Glitch] Fix scrolling to detailed status not always working Port d0fd14f851871659834ae600f043d81e352cdc1f to glitch-soc Signed-off-by: Claire --- .../flavours/glitch/features/status/index.jsx | 19 +++++++++++-------- 1 file changed, 11 insertions(+), 8 deletions(-) diff --git a/app/javascript/flavours/glitch/features/status/index.jsx b/app/javascript/flavours/glitch/features/status/index.jsx index 266c974c4e..605919f670 100644 --- a/app/javascript/flavours/glitch/features/status/index.jsx +++ b/app/javascript/flavours/glitch/features/status/index.jsx @@ -610,7 +610,7 @@ class Status extends ImmutablePureComponent { this.setState({ isExpanded: value }); }; - setRef = c => { + setContainerRef = c => { this.node = c; }; @@ -618,12 +618,16 @@ class Status extends ImmutablePureComponent { this.column = c; }; + setStatusRef = c => { + this.statusNode = c; + }; + _scrollStatusIntoView () { const { status, multiColumn } = this.props; if (status) { - window.requestAnimationFrame(() => { - this.node?.querySelector('.detailed-status__wrapper')?.scrollIntoView(true); + requestIdleCallback(() => { + this.statusNode?.scrollIntoView(true); // In the single-column interface, `scrollIntoView` will put the post behind the header, // so compensate for that. @@ -661,9 +665,8 @@ class Status extends ImmutablePureComponent { } // Scroll to focused post if it is loaded - const child = this.node?.querySelector('.detailed-status__wrapper'); - if (child) { - return [0, child.offsetTop]; + if (this.statusNode) { + return [0, this.statusNode.offsetTop]; } // Do not scroll otherwise, `componentDidUpdate` will take care of that @@ -730,11 +733,11 @@ class Status extends ImmutablePureComponent { /> -
+
{ancestors} -
+
Date: Wed, 10 Jan 2024 18:03:31 +0100 Subject: [PATCH 60/61] Increase Metrics/AbcSize limit --- .rubocop_todo.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.rubocop_todo.yml b/.rubocop_todo.yml index 6ab8957055..1162cc0211 100644 --- a/.rubocop_todo.yml +++ b/.rubocop_todo.yml @@ -26,7 +26,7 @@ Lint/NonLocalExitFromIterator: # Configuration parameters: AllowedMethods, AllowedPatterns, CountRepeatedAttributes. Metrics/AbcSize: - Max: 82 + Max: 90 # Configuration parameters: CountBlocks, Max. Metrics/BlockNesting: From 09376a82073614908eb35373fc7a29e070136eb2 Mon Sep 17 00:00:00 2001 From: Renaud Chaput Date: Mon, 8 Jan 2024 11:57:40 +0100 Subject: [PATCH 61/61] [Glitch] Upgrade Redux packages Port a0e237a96fca2774d3c9ed43063a45e395bb7f40 to glitch-soc Signed-off-by: Claire --- .../emoji_picker_dropdown_container.js | 3 +- .../containers/language_dropdown_container.js | 3 +- .../containers/announcements_container.js | 3 +- .../glitch/features/getting_started/index.jsx | 2 +- .../glitch/features/home_timeline/index.jsx | 2 +- .../glitch/features/list_adder/index.jsx | 2 +- .../flavours/glitch/features/lists/index.jsx | 2 +- .../glitch/features/notifications/index.jsx | 2 +- .../glitch/features/report/comment.jsx | 2 +- .../flavours/glitch/features/status/index.jsx | 2 +- .../subscribed_languages_modal/index.jsx | 2 +- .../features/ui/components/list_panel.jsx | 2 +- .../ui/containers/status_list_container.js | 2 +- .../flavours/glitch/reducers/accounts.ts | 3 +- .../flavours/glitch/reducers/modal.ts | 3 +- .../flavours/glitch/reducers/relationships.ts | 5 ++- .../flavours/glitch/selectors/accounts.ts | 2 +- .../flavours/glitch/selectors/index.js | 2 +- .../glitch/store/middlewares/errors.ts | 32 ++++++++++++----- .../glitch/store/middlewares/loading_bar.ts | 24 ++++++++++--- .../glitch/store/middlewares/sounds.ts | 35 ++++++++++++++----- .../flavours/glitch/store/typed_functions.ts | 6 ++-- 22 files changed, 95 insertions(+), 46 deletions(-) diff --git a/app/javascript/flavours/glitch/features/compose/containers/emoji_picker_dropdown_container.js b/app/javascript/flavours/glitch/features/compose/containers/emoji_picker_dropdown_container.js index a0e50029df..8cf906b20a 100644 --- a/app/javascript/flavours/glitch/features/compose/containers/emoji_picker_dropdown_container.js +++ b/app/javascript/flavours/glitch/features/compose/containers/emoji_picker_dropdown_container.js @@ -1,6 +1,7 @@ +import { createSelector } from '@reduxjs/toolkit'; import { Map as ImmutableMap } from 'immutable'; import { connect } from 'react-redux'; -import { createSelector } from 'reselect'; + import { useEmoji } from '../../../actions/emojis'; import { changeSetting } from '../../../actions/settings'; diff --git a/app/javascript/flavours/glitch/features/compose/containers/language_dropdown_container.js b/app/javascript/flavours/glitch/features/compose/containers/language_dropdown_container.js index 8a50da4c44..9388cb0059 100644 --- a/app/javascript/flavours/glitch/features/compose/containers/language_dropdown_container.js +++ b/app/javascript/flavours/glitch/features/compose/containers/language_dropdown_container.js @@ -1,6 +1,7 @@ +import { createSelector } from '@reduxjs/toolkit'; import { Map as ImmutableMap } from 'immutable'; import { connect } from 'react-redux'; -import { createSelector } from 'reselect'; + import { changeComposeLanguage } from 'flavours/glitch/actions/compose'; import { useLanguage } from 'flavours/glitch/actions/languages'; diff --git a/app/javascript/flavours/glitch/features/getting_started/containers/announcements_container.js b/app/javascript/flavours/glitch/features/getting_started/containers/announcements_container.js index 893da21df9..2a504a3094 100644 --- a/app/javascript/flavours/glitch/features/getting_started/containers/announcements_container.js +++ b/app/javascript/flavours/glitch/features/getting_started/containers/announcements_container.js @@ -1,6 +1,7 @@ +import { createSelector } from '@reduxjs/toolkit'; import { Map as ImmutableMap } from 'immutable'; import { connect } from 'react-redux'; -import { createSelector } from 'reselect'; + import { addReaction, removeReaction, dismissAnnouncement } from 'flavours/glitch/actions/announcements'; diff --git a/app/javascript/flavours/glitch/features/getting_started/index.jsx b/app/javascript/flavours/glitch/features/getting_started/index.jsx index ea2537482b..5c40963f2e 100644 --- a/app/javascript/flavours/glitch/features/getting_started/index.jsx +++ b/app/javascript/flavours/glitch/features/getting_started/index.jsx @@ -4,11 +4,11 @@ import { defineMessages, injectIntl } from 'react-intl'; import { Helmet } from 'react-helmet'; +import { createSelector } from '@reduxjs/toolkit'; import { List as ImmutableList } from 'immutable'; import ImmutablePropTypes from 'react-immutable-proptypes'; import ImmutablePureComponent from 'react-immutable-pure-component'; import { connect } from 'react-redux'; -import { createSelector } from 'reselect'; import { fetchFollowRequests } from 'flavours/glitch/actions/accounts'; import { fetchLists } from 'flavours/glitch/actions/lists'; diff --git a/app/javascript/flavours/glitch/features/home_timeline/index.jsx b/app/javascript/flavours/glitch/features/home_timeline/index.jsx index 20351833a0..bca42ec140 100644 --- a/app/javascript/flavours/glitch/features/home_timeline/index.jsx +++ b/app/javascript/flavours/glitch/features/home_timeline/index.jsx @@ -6,9 +6,9 @@ import { defineMessages, injectIntl, FormattedMessage } from 'react-intl'; import classNames from 'classnames'; import { Helmet } from 'react-helmet'; +import { createSelector } from '@reduxjs/toolkit'; import { List as ImmutableList } from 'immutable'; import { connect } from 'react-redux'; -import { createSelector } from 'reselect'; import { fetchAnnouncements, toggleShowAnnouncements } from 'flavours/glitch/actions/announcements'; import { IconWithBadge } from 'flavours/glitch/components/icon_with_badge'; diff --git a/app/javascript/flavours/glitch/features/list_adder/index.jsx b/app/javascript/flavours/glitch/features/list_adder/index.jsx index 1ba9972e00..4e7bd46bdf 100644 --- a/app/javascript/flavours/glitch/features/list_adder/index.jsx +++ b/app/javascript/flavours/glitch/features/list_adder/index.jsx @@ -2,10 +2,10 @@ import PropTypes from 'prop-types'; import { injectIntl } from 'react-intl'; +import { createSelector } from '@reduxjs/toolkit'; import ImmutablePropTypes from 'react-immutable-proptypes'; import ImmutablePureComponent from 'react-immutable-pure-component'; import { connect } from 'react-redux'; -import { createSelector } from 'reselect'; import { setupListAdder, resetListAdder } from '../../actions/lists'; import NewListForm from '../lists/components/new_list_form'; diff --git a/app/javascript/flavours/glitch/features/lists/index.jsx b/app/javascript/flavours/glitch/features/lists/index.jsx index e09d517d74..2c393684ec 100644 --- a/app/javascript/flavours/glitch/features/lists/index.jsx +++ b/app/javascript/flavours/glitch/features/lists/index.jsx @@ -4,10 +4,10 @@ import { defineMessages, injectIntl, FormattedMessage } from 'react-intl'; import { Helmet } from 'react-helmet'; +import { createSelector } from '@reduxjs/toolkit'; import ImmutablePropTypes from 'react-immutable-proptypes'; import ImmutablePureComponent from 'react-immutable-pure-component'; import { connect } from 'react-redux'; -import { createSelector } from 'reselect'; import { fetchLists } from 'flavours/glitch/actions/lists'; import ColumnBackButtonSlim from 'flavours/glitch/components/column_back_button_slim'; diff --git a/app/javascript/flavours/glitch/features/notifications/index.jsx b/app/javascript/flavours/glitch/features/notifications/index.jsx index 7dc5190f70..dc923fbdf5 100644 --- a/app/javascript/flavours/glitch/features/notifications/index.jsx +++ b/app/javascript/flavours/glitch/features/notifications/index.jsx @@ -6,10 +6,10 @@ import { defineMessages, injectIntl, FormattedMessage } from 'react-intl'; import classNames from 'classnames'; import { Helmet } from 'react-helmet'; +import { createSelector } from '@reduxjs/toolkit'; import { List as ImmutableList } from 'immutable'; import ImmutablePropTypes from 'react-immutable-proptypes'; import { connect } from 'react-redux'; -import { createSelector } from 'reselect'; import { debounce } from 'lodash'; diff --git a/app/javascript/flavours/glitch/features/report/comment.jsx b/app/javascript/flavours/glitch/features/report/comment.jsx index 81efa7b5f7..40079b2c68 100644 --- a/app/javascript/flavours/glitch/features/report/comment.jsx +++ b/app/javascript/flavours/glitch/features/report/comment.jsx @@ -3,10 +3,10 @@ import { useCallback, useEffect, useRef } from 'react'; import { useIntl, defineMessages, FormattedMessage } from 'react-intl'; +import { createSelector } from '@reduxjs/toolkit'; import { OrderedSet, List as ImmutableList } from 'immutable'; import ImmutablePropTypes from 'react-immutable-proptypes'; import { shallowEqual } from 'react-redux'; -import { createSelector } from 'reselect'; import Toggle from 'react-toggle'; diff --git a/app/javascript/flavours/glitch/features/status/index.jsx b/app/javascript/flavours/glitch/features/status/index.jsx index 605919f670..36c53b819d 100644 --- a/app/javascript/flavours/glitch/features/status/index.jsx +++ b/app/javascript/flavours/glitch/features/status/index.jsx @@ -6,11 +6,11 @@ import classNames from 'classnames'; import { Helmet } from 'react-helmet'; import { withRouter } from 'react-router-dom'; +import { createSelector } from '@reduxjs/toolkit'; import Immutable from 'immutable'; import ImmutablePropTypes from 'react-immutable-proptypes'; import ImmutablePureComponent from 'react-immutable-pure-component'; import { connect } from 'react-redux'; -import { createSelector } from 'reselect'; import { HotKeys } from 'react-hotkeys'; diff --git a/app/javascript/flavours/glitch/features/subscribed_languages_modal/index.jsx b/app/javascript/flavours/glitch/features/subscribed_languages_modal/index.jsx index c0268fbeb8..1ef4740662 100644 --- a/app/javascript/flavours/glitch/features/subscribed_languages_modal/index.jsx +++ b/app/javascript/flavours/glitch/features/subscribed_languages_modal/index.jsx @@ -2,11 +2,11 @@ import PropTypes from 'prop-types'; import { defineMessages, FormattedMessage, injectIntl } from 'react-intl'; +import { createSelector } from '@reduxjs/toolkit'; import { is, List as ImmutableList, Set as ImmutableSet } from 'immutable'; import ImmutablePropTypes from 'react-immutable-proptypes'; import ImmutablePureComponent from 'react-immutable-pure-component'; import { connect } from 'react-redux'; -import { createSelector } from 'reselect'; import { followAccount } from 'flavours/glitch/actions/accounts'; import { Button } from 'flavours/glitch/components/button'; diff --git a/app/javascript/flavours/glitch/features/ui/components/list_panel.jsx b/app/javascript/flavours/glitch/features/ui/components/list_panel.jsx index 9210bb4f39..abf97a7c54 100644 --- a/app/javascript/flavours/glitch/features/ui/components/list_panel.jsx +++ b/app/javascript/flavours/glitch/features/ui/components/list_panel.jsx @@ -1,9 +1,9 @@ import PropTypes from 'prop-types'; +import { createSelector } from '@reduxjs/toolkit'; import ImmutablePropTypes from 'react-immutable-proptypes'; import ImmutablePureComponent from 'react-immutable-pure-component'; import { connect } from 'react-redux'; -import { createSelector } from 'reselect'; import { fetchLists } from 'flavours/glitch/actions/lists'; diff --git a/app/javascript/flavours/glitch/features/ui/containers/status_list_container.js b/app/javascript/flavours/glitch/features/ui/containers/status_list_container.js index f34d099b24..7d31240d8f 100644 --- a/app/javascript/flavours/glitch/features/ui/containers/status_list_container.js +++ b/app/javascript/flavours/glitch/features/ui/containers/status_list_container.js @@ -1,6 +1,6 @@ +import { createSelector } from '@reduxjs/toolkit'; import { Map as ImmutableMap, List as ImmutableList } from 'immutable'; import { connect } from 'react-redux'; -import { createSelector } from 'reselect'; import { debounce } from 'lodash'; diff --git a/app/javascript/flavours/glitch/reducers/accounts.ts b/app/javascript/flavours/glitch/reducers/accounts.ts index c7459d1d5a..345bff06ce 100644 --- a/app/javascript/flavours/glitch/reducers/accounts.ts +++ b/app/javascript/flavours/glitch/reducers/accounts.ts @@ -1,7 +1,6 @@ +import type { Reducer } from '@reduxjs/toolkit'; import { Map as ImmutableMap } from 'immutable'; -import type { Reducer } from 'redux'; - import { followAccountSuccess, unfollowAccountSuccess, diff --git a/app/javascript/flavours/glitch/reducers/modal.ts b/app/javascript/flavours/glitch/reducers/modal.ts index 73a2afb916..368f26542c 100644 --- a/app/javascript/flavours/glitch/reducers/modal.ts +++ b/app/javascript/flavours/glitch/reducers/modal.ts @@ -1,6 +1,5 @@ -import { Record as ImmutableRecord, Stack } from 'immutable'; - import type { Reducer } from '@reduxjs/toolkit'; +import { Record as ImmutableRecord, Stack } from 'immutable'; import { COMPOSE_UPLOAD_CHANGE_SUCCESS } from '../actions/compose'; import type { ModalType } from '../actions/modal'; diff --git a/app/javascript/flavours/glitch/reducers/relationships.ts b/app/javascript/flavours/glitch/reducers/relationships.ts index 5d75529475..6ef84b0bb7 100644 --- a/app/javascript/flavours/glitch/reducers/relationships.ts +++ b/app/javascript/flavours/glitch/reducers/relationships.ts @@ -1,7 +1,6 @@ -import { Map as ImmutableMap } from 'immutable'; - import { isFulfilled } from '@reduxjs/toolkit'; -import type { Reducer } from 'redux'; +import type { Reducer } from '@reduxjs/toolkit'; +import { Map as ImmutableMap } from 'immutable'; import type { ApiRelationshipJSON } from 'flavours/glitch/api_types/relationships'; import type { Account } from 'flavours/glitch/models/account'; diff --git a/app/javascript/flavours/glitch/selectors/accounts.ts b/app/javascript/flavours/glitch/selectors/accounts.ts index 9b375c5b95..159aafd34f 100644 --- a/app/javascript/flavours/glitch/selectors/accounts.ts +++ b/app/javascript/flavours/glitch/selectors/accounts.ts @@ -1,5 +1,5 @@ +import { createSelector } from '@reduxjs/toolkit'; import { Record as ImmutableRecord } from 'immutable'; -import { createSelector } from 'reselect'; import { accountDefaultValues } from 'flavours/glitch/models/account'; import type { Account, AccountShape } from 'flavours/glitch/models/account'; diff --git a/app/javascript/flavours/glitch/selectors/index.js b/app/javascript/flavours/glitch/selectors/index.js index 98100e1f1b..0bec708116 100644 --- a/app/javascript/flavours/glitch/selectors/index.js +++ b/app/javascript/flavours/glitch/selectors/index.js @@ -1,5 +1,5 @@ +import { createSelector } from '@reduxjs/toolkit'; import { List as ImmutableList, Map as ImmutableMap } from 'immutable'; -import { createSelector } from 'reselect'; import { toServerSideType } from 'flavours/glitch/utils/filters'; diff --git a/app/javascript/flavours/glitch/store/middlewares/errors.ts b/app/javascript/flavours/glitch/store/middlewares/errors.ts index 9f28f5ff53..e11aa78178 100644 --- a/app/javascript/flavours/glitch/store/middlewares/errors.ts +++ b/app/javascript/flavours/glitch/store/middlewares/errors.ts @@ -1,20 +1,34 @@ -import type { AnyAction, Middleware } from 'redux'; +import { isAction } from '@reduxjs/toolkit'; +import type { Action, Middleware } from '@reduxjs/toolkit'; import type { RootState } from '..'; import { showAlertForError } from '../../actions/alerts'; const defaultFailSuffix = 'FAIL'; +const isFailedAction = new RegExp(`${defaultFailSuffix}$`, 'g'); -export const errorsMiddleware: Middleware = +interface ActionWithMaybeAlertParams extends Action { + skipAlert?: boolean; + skipNotFound?: boolean; + error?: unknown; +} + +function isActionWithmaybeAlertParams( + action: unknown, +): action is ActionWithMaybeAlertParams { + return isAction(action); +} + +export const errorsMiddleware: Middleware, RootState> = ({ dispatch }) => (next) => - (action: AnyAction & { skipAlert?: boolean; skipNotFound?: boolean }) => { - if (action.type && !action.skipAlert) { - const isFail = new RegExp(`${defaultFailSuffix}$`, 'g'); - - if (typeof action.type === 'string' && action.type.match(isFail)) { - dispatch(showAlertForError(action.error, action.skipNotFound)); - } + (action) => { + if ( + isActionWithmaybeAlertParams(action) && + !action.skipAlert && + action.type.match(isFailedAction) + ) { + dispatch(showAlertForError(action.error, action.skipNotFound)); } return next(action); diff --git a/app/javascript/flavours/glitch/store/middlewares/loading_bar.ts b/app/javascript/flavours/glitch/store/middlewares/loading_bar.ts index 83056ee49f..d259be899b 100644 --- a/app/javascript/flavours/glitch/store/middlewares/loading_bar.ts +++ b/app/javascript/flavours/glitch/store/middlewares/loading_bar.ts @@ -3,9 +3,11 @@ import { isPending as isThunkActionPending, isFulfilled as isThunkActionFulfilled, isRejected as isThunkActionRejected, + isAction, } from '@reduxjs/toolkit'; +import type { Middleware, UnknownAction } from '@reduxjs/toolkit'; + import { showLoading, hideLoading } from 'react-redux-loading-bar'; -import type { AnyAction, Middleware } from 'redux'; import type { RootState } from '..'; @@ -19,14 +21,28 @@ const defaultTypeSuffixes: Config['promiseTypeSuffixes'] = [ 'REJECTED', ]; +interface ActionWithSkipLoading extends UnknownAction { + skipLoading: boolean; +} + +function isActionWithSkipLoading( + action: unknown, +): action is ActionWithSkipLoading { + return ( + isAction(action) && + 'skipLoading' in action && + typeof action.skipLoading === 'boolean' + ); +} + export const loadingBarMiddleware = ( config: Config = {}, -): Middleware => { +): Middleware<{ skipLoading?: boolean }, RootState> => { const promiseTypeSuffixes = config.promiseTypeSuffixes ?? defaultTypeSuffixes; return ({ dispatch }) => (next) => - (action: AnyAction) => { + (action) => { let isPending = false; let isFulfilled = false; let isRejected = false; @@ -39,7 +55,7 @@ export const loadingBarMiddleware = ( else if (isThunkActionFulfilled(action)) isFulfilled = true; else if (isThunkActionRejected(action)) isRejected = true; } else if ( - action.type && + isActionWithSkipLoading(action) && !action.skipLoading && typeof action.type === 'string' ) { diff --git a/app/javascript/flavours/glitch/store/middlewares/sounds.ts b/app/javascript/flavours/glitch/store/middlewares/sounds.ts index 3bf7d2a357..52d5f6b507 100644 --- a/app/javascript/flavours/glitch/store/middlewares/sounds.ts +++ b/app/javascript/flavours/glitch/store/middlewares/sounds.ts @@ -1,4 +1,5 @@ -import type { Middleware, AnyAction } from 'redux'; +import { isAction } from '@reduxjs/toolkit'; +import type { Middleware, UnknownAction } from '@reduxjs/toolkit'; import ready from 'flavours/glitch/ready'; import { assetHost } from 'flavours/glitch/utils/config'; @@ -10,6 +11,21 @@ interface AudioSource { type: string; } +interface ActionWithMetaSound extends UnknownAction { + meta: { sound: string }; +} + +function isActionWithMetaSound(action: unknown): action is ActionWithMetaSound { + return ( + isAction(action) && + 'meta' in action && + typeof action.meta === 'object' && + !!action.meta && + 'sound' in action.meta && + typeof action.meta.sound === 'string' + ); +} + const createAudio = (sources: AudioSource[]) => { const audio = new Audio(); sources.forEach(({ type, src }) => { @@ -34,7 +50,10 @@ const play = (audio: HTMLAudioElement) => { void audio.play(); }; -export const soundsMiddleware = (): Middleware => { +export const soundsMiddleware = (): Middleware< + Record, + RootState +> => { const soundCache: Record = {}; void ready(() => { @@ -50,15 +69,15 @@ export const soundsMiddleware = (): Middleware => { ]); }); - return () => - (next) => - (action: AnyAction & { meta?: { sound?: string } }) => { - const sound = action.meta?.sound; + return () => (next) => (action) => { + if (isActionWithMetaSound(action)) { + const sound = action.meta.sound; if (sound && Object.hasOwn(soundCache, sound)) { play(soundCache[sound]); } + } - return next(action); - }; + return next(action); + }; }; diff --git a/app/javascript/flavours/glitch/store/typed_functions.ts b/app/javascript/flavours/glitch/store/typed_functions.ts index f1e71385a8..46a10b8b47 100644 --- a/app/javascript/flavours/glitch/store/typed_functions.ts +++ b/app/javascript/flavours/glitch/store/typed_functions.ts @@ -1,7 +1,7 @@ -import type { TypedUseSelectorHook } from 'react-redux'; -import { useDispatch, useSelector } from 'react-redux'; - import { createAsyncThunk } from '@reduxjs/toolkit'; +import type { TypedUseSelectorHook } from 'react-redux'; +// eslint-disable-next-line @typescript-eslint/no-restricted-imports +import { useDispatch, useSelector } from 'react-redux'; import type { AppDispatch, RootState } from './store';