From 884bbf7ae239a9b07055e1a7d0238b213c2c8520 Mon Sep 17 00:00:00 2001 From: Matt Jankowski Date: Tue, 12 Nov 2024 10:43:55 -0500 Subject: [PATCH 01/64] Prepare the way for banning a bunch of usernames (#32856) --- spec/lib/feed_manager_spec.rb | 16 ++++++++-------- .../models/concerns/account/interactions_spec.rb | 4 ++-- 2 files changed, 10 insertions(+), 10 deletions(-) diff --git a/spec/lib/feed_manager_spec.rb b/spec/lib/feed_manager_spec.rb index 1d70499674..afb007af42 100644 --- a/spec/lib/feed_manager_spec.rb +++ b/spec/lib/feed_manager_spec.rb @@ -343,16 +343,16 @@ RSpec.describe FeedManager do end describe '#push_to_list' do - let(:owner) { Fabricate(:account, username: 'owner') } + let(:list_owner) { Fabricate(:account, username: 'list_owner') } let(:alice) { Fabricate(:account, username: 'alice') } let(:bob) { Fabricate(:account, username: 'bob') } let(:eve) { Fabricate(:account, username: 'eve') } - let(:list) { Fabricate(:list, account: owner) } + let(:list) { Fabricate(:list, account: list_owner) } before do - owner.follow!(alice) - owner.follow!(bob) - owner.follow!(eve) + list_owner.follow!(alice) + list_owner.follow!(bob) + list_owner.follow!(eve) list.accounts << alice list.accounts << bob @@ -377,7 +377,7 @@ RSpec.describe FeedManager do end it 'pushes statuses that are replies to list owner' do - status = Fabricate(:status, text: 'Hello world', account: owner) + status = Fabricate(:status, text: 'Hello world', account: list_owner) reply = Fabricate(:status, text: 'Nay', thread: status, account: bob) expect(subject.push_to_list(list, reply)).to be true end @@ -400,7 +400,7 @@ RSpec.describe FeedManager do end it 'pushes statuses that are replies to list owner' do - status = Fabricate(:status, text: 'Hello world', account: owner) + status = Fabricate(:status, text: 'Hello world', account: list_owner) reply = Fabricate(:status, text: 'Nay', thread: status, account: bob) expect(subject.push_to_list(list, reply)).to be true end @@ -429,7 +429,7 @@ RSpec.describe FeedManager do end it 'pushes statuses that are replies to list owner' do - status = Fabricate(:status, text: 'Hello world', account: owner) + status = Fabricate(:status, text: 'Hello world', account: list_owner) reply = Fabricate(:status, text: 'Nay', thread: status, account: bob) expect(subject.push_to_list(list, reply)).to be true end diff --git a/spec/models/concerns/account/interactions_spec.rb b/spec/models/concerns/account/interactions_spec.rb index 4868054df7..f7ec3a3912 100644 --- a/spec/models/concerns/account/interactions_spec.rb +++ b/spec/models/concerns/account/interactions_spec.rb @@ -3,10 +3,10 @@ require 'rails_helper' RSpec.describe Account::Interactions do - let(:account) { Fabricate(:account, username: 'account') } + let(:account) { Fabricate(:account) } let(:account_id) { account.id } let(:account_ids) { [account_id] } - let(:target_account) { Fabricate(:account, username: 'target') } + let(:target_account) { Fabricate(:account) } let(:target_account_id) { target_account.id } let(:target_account_ids) { [target_account_id] } From ace426830879b9f4f34fe80430be4ac3235f8c01 Mon Sep 17 00:00:00 2001 From: Matt Jankowski Date: Tue, 12 Nov 2024 12:27:23 -0500 Subject: [PATCH 02/64] Remove unused `api/v1/polls#create` route (#32860) --- config/routes/api.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/config/routes/api.rb b/config/routes/api.rb index 95fdf332a0..86e41a2abe 100644 --- a/config/routes/api.rb +++ b/config/routes/api.rb @@ -225,7 +225,7 @@ namespace :api, format: false do resources :featured_tags, only: [:index, :create, :destroy] - resources :polls, only: [:create, :show] do + resources :polls, only: [:show] do resources :votes, only: :create, module: :polls end From 2bd56f726a99472b722f9ffafc7c2e4c6ea57350 Mon Sep 17 00:00:00 2001 From: Emelia Smith Date: Tue, 12 Nov 2024 23:06:13 +0100 Subject: [PATCH 03/64] Add client_secret_expires_at to OAuth Applications (#30317) --- app/serializers/rest/credential_application_serializer.rb | 8 +++++++- spec/requests/api/v1/apps/credentials_spec.rb | 1 + spec/requests/api/v1/apps_spec.rb | 1 + 3 files changed, 9 insertions(+), 1 deletion(-) diff --git a/app/serializers/rest/credential_application_serializer.rb b/app/serializers/rest/credential_application_serializer.rb index bfec7d03e8..0532390c9a 100644 --- a/app/serializers/rest/credential_application_serializer.rb +++ b/app/serializers/rest/credential_application_serializer.rb @@ -1,7 +1,7 @@ # frozen_string_literal: true class REST::CredentialApplicationSerializer < REST::ApplicationSerializer - attributes :client_id, :client_secret + attributes :client_id, :client_secret, :client_secret_expires_at def client_id object.uid @@ -10,4 +10,10 @@ class REST::CredentialApplicationSerializer < REST::ApplicationSerializer def client_secret object.secret end + + # Added for future forwards compatibility when we may decide to expire OAuth + # Applications. Set to zero means that the client_secret never expires. + def client_secret_expires_at + 0 + end end diff --git a/spec/requests/api/v1/apps/credentials_spec.rb b/spec/requests/api/v1/apps/credentials_spec.rb index 8e5fa14b7e..3aca53ed0a 100644 --- a/spec/requests/api/v1/apps/credentials_spec.rb +++ b/spec/requests/api/v1/apps/credentials_spec.rb @@ -44,6 +44,7 @@ RSpec.describe 'Credentials' do expect(response.parsed_body) .to not_include(client_id: be_present) .and not_include(client_secret: be_present) + .and not_include(client_secret_expires_at: be_present) end end diff --git a/spec/requests/api/v1/apps_spec.rb b/spec/requests/api/v1/apps_spec.rb index cf43e14d62..4e9147ba32 100644 --- a/spec/requests/api/v1/apps_spec.rb +++ b/spec/requests/api/v1/apps_spec.rb @@ -42,6 +42,7 @@ RSpec.describe 'Apps' do id: app.id.to_s, client_id: app.uid, client_secret: app.secret, + client_secret_expires_at: 0, name: client_name, website: website, scopes: ['read', 'write'], From a6d829e86fb228be6a8ed8f19b2276e07d5a89e2 Mon Sep 17 00:00:00 2001 From: Matt Jankowski Date: Wed, 13 Nov 2024 03:39:58 -0500 Subject: [PATCH 04/64] Fix error in CLI EmailDomainBlocks when supplying `--with-dns-records` (#32863) --- lib/mastodon/cli/email_domain_blocks.rb | 2 +- .../lib/mastodon/cli/email_domain_blocks_spec.rb | 16 ++++++++++++++++ 2 files changed, 17 insertions(+), 1 deletion(-) diff --git a/lib/mastodon/cli/email_domain_blocks.rb b/lib/mastodon/cli/email_domain_blocks.rb index 7b2da8ef9f..a830ca3661 100644 --- a/lib/mastodon/cli/email_domain_blocks.rb +++ b/lib/mastodon/cli/email_domain_blocks.rb @@ -48,7 +48,7 @@ module Mastodon::CLI if options[:with_dns_records] Resolv::DNS.open do |dns| dns.timeouts = 5 - other_domains = dns.getresources(@email_domain_block.domain, Resolv::DNS::Resource::IN::MX).to_a + other_domains = dns.getresources(domain, Resolv::DNS::Resource::IN::MX).to_a.map { |e| e.exchange.to_s }.compact_blank end end diff --git a/spec/lib/mastodon/cli/email_domain_blocks_spec.rb b/spec/lib/mastodon/cli/email_domain_blocks_spec.rb index a5fbd23e65..6ce1a7c5f3 100644 --- a/spec/lib/mastodon/cli/email_domain_blocks_spec.rb +++ b/spec/lib/mastodon/cli/email_domain_blocks_spec.rb @@ -63,6 +63,22 @@ RSpec.describe Mastodon::CLI::EmailDomainBlocks do .and(change(EmailDomainBlock, :count).by(1)) end end + + context 'with --with-dns-records true' do + let(:domain) { 'host.example' } + let(:arguments) { [domain] } + let(:options) { { with_dns_records: true } } + + before do + configure_mx(domain: domain, exchange: 'other.host') + end + + it 'adds a new block for parent and children' do + expect { subject } + .to output_results('Added 2') + .and(change(EmailDomainBlock, :count).by(2)) + end + end end describe '#remove' do From baad7953849307fa4a6bcdd878b9b2207226352d Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Wed, 13 Nov 2024 10:33:02 +0100 Subject: [PATCH 05/64] New Crowdin Translations (automated) (#32868) Co-authored-by: GitHub Actions --- app/javascript/mastodon/locales/ca.json | 1 + app/javascript/mastodon/locales/da.json | 1 + app/javascript/mastodon/locales/de.json | 1 + app/javascript/mastodon/locales/eo.json | 11 ++-- app/javascript/mastodon/locales/es-AR.json | 1 + app/javascript/mastodon/locales/es-MX.json | 5 +- app/javascript/mastodon/locales/es.json | 1 + app/javascript/mastodon/locales/fi.json | 13 +++++ app/javascript/mastodon/locales/fo.json | 1 + app/javascript/mastodon/locales/gl.json | 8 +++ app/javascript/mastodon/locales/hu.json | 1 + app/javascript/mastodon/locales/is.json | 1 + app/javascript/mastodon/locales/ko.json | 1 + app/javascript/mastodon/locales/nl.json | 1 + app/javascript/mastodon/locales/nn.json | 22 +++++++ app/javascript/mastodon/locales/pt-BR.json | 1 + app/javascript/mastodon/locales/ru.json | 4 ++ app/javascript/mastodon/locales/sq.json | 1 + app/javascript/mastodon/locales/sv.json | 1 + app/javascript/mastodon/locales/tr.json | 1 + app/javascript/mastodon/locales/uk.json | 1 + app/javascript/mastodon/locales/vi.json | 1 + app/javascript/mastodon/locales/zh-CN.json | 1 + app/javascript/mastodon/locales/zh-TW.json | 1 + config/locales/ca.yml | 8 +++ config/locales/da.yml | 8 +++ config/locales/de.yml | 8 +++ config/locales/fi.yml | 10 +++- config/locales/fo.yml | 8 +++ config/locales/gl.yml | 8 +++ config/locales/hu.yml | 8 +++ config/locales/is.yml | 8 +++ config/locales/ko.yml | 8 +++ config/locales/lt.yml | 8 +++ config/locales/nn.yml | 11 ++++ config/locales/pt-BR.yml | 16 ++++- config/locales/ru.yml | 68 ++++++++++++---------- config/locales/simple_form.ko.yml | 2 +- config/locales/simple_form.lt.yml | 1 + config/locales/simple_form.nl.yml | 2 +- config/locales/simple_form.nn.yml | 1 + config/locales/simple_form.pl.yml | 1 + config/locales/simple_form.ru.yml | 1 + config/locales/simple_form.sv.yml | 1 + config/locales/sq.yml | 8 +++ config/locales/sv.yml | 16 +++-- config/locales/tr.yml | 8 +++ config/locales/vi.yml | 8 +++ config/locales/zh-CN.yml | 8 +++ config/locales/zh-TW.yml | 10 +++- 50 files changed, 278 insertions(+), 47 deletions(-) diff --git a/app/javascript/mastodon/locales/ca.json b/app/javascript/mastodon/locales/ca.json index 160a74af4f..53bfc4474c 100644 --- a/app/javascript/mastodon/locales/ca.json +++ b/app/javascript/mastodon/locales/ca.json @@ -97,6 +97,7 @@ "annual_report.summary.highlighted_post.possessive": "de {name}", "annual_report.summary.most_used_app.most_used_app": "l'aplicació més utilitzada", "annual_report.summary.most_used_hashtag.most_used_hashtag": "l'etiqueta més utilitzada", + "annual_report.summary.most_used_hashtag.none": "Cap", "annual_report.summary.new_posts.new_posts": "publicacions noves", "annual_report.summary.thanks": "Gràcies per formar part de Mastodon!", "attachments_list.unprocessed": "(sense processar)", diff --git a/app/javascript/mastodon/locales/da.json b/app/javascript/mastodon/locales/da.json index 927d0a7cb8..4ba1f4d9e1 100644 --- a/app/javascript/mastodon/locales/da.json +++ b/app/javascript/mastodon/locales/da.json @@ -101,6 +101,7 @@ "annual_report.summary.highlighted_post.possessive": "{name}s", "annual_report.summary.most_used_app.most_used_app": "mest benyttede app", "annual_report.summary.most_used_hashtag.most_used_hashtag": "mest benyttede hashtag", + "annual_report.summary.most_used_hashtag.none": "Intet", "annual_report.summary.new_posts.new_posts": "nye indlæg", "annual_report.summary.percentile.text": "Det betyder, at man er i topaf Mastodon-brugere.", "annual_report.summary.percentile.we_wont_tell_bernie": "Vi fortæller det ikke til Bernie.", diff --git a/app/javascript/mastodon/locales/de.json b/app/javascript/mastodon/locales/de.json index e7679a363c..bd24ccd48f 100644 --- a/app/javascript/mastodon/locales/de.json +++ b/app/javascript/mastodon/locales/de.json @@ -101,6 +101,7 @@ "annual_report.summary.highlighted_post.possessive": "{name}", "annual_report.summary.most_used_app.most_used_app": "am häufigsten verwendete App", "annual_report.summary.most_used_hashtag.most_used_hashtag": "am häufigsten verwendeter Hashtag", + "annual_report.summary.most_used_hashtag.none": "Kein", "annual_report.summary.new_posts.new_posts": "neue Beiträge", "annual_report.summary.percentile.text": "Damit gehörst du zu den oberstender Mastodon-Nutzer*innen.", "annual_report.summary.percentile.we_wont_tell_bernie": "Wir werden Bernie nichts verraten.", diff --git a/app/javascript/mastodon/locales/eo.json b/app/javascript/mastodon/locales/eo.json index 757bb39866..731e11f27a 100644 --- a/app/javascript/mastodon/locales/eo.json +++ b/app/javascript/mastodon/locales/eo.json @@ -90,6 +90,7 @@ "annual_report.summary.archetype.replier": "La plej societema", "annual_report.summary.followers.followers": "sekvantoj", "annual_report.summary.highlighted_post.by_replies": "afiŝo kun la plej multaj respondoj", + "annual_report.summary.most_used_hashtag.none": "Nenio", "annual_report.summary.new_posts.new_posts": "novaj afiŝoj", "annual_report.summary.thanks": "Dankon pro esti parto de Mastodon!", "attachments_list.unprocessed": "(neprilaborita)", @@ -219,7 +220,7 @@ "dismissable_banner.community_timeline": "Jen la plej novaj publikaj afiŝoj de uzantoj, kies kontojn gastigas {domain}.", "dismissable_banner.dismiss": "Eksigi", "dismissable_banner.explore_links": "Tiuj novaĵoj estas aktuale priparolataj de uzantoj en tiu ĉi kaj aliaj serviloj, sur la malcentrigita reto.", - "dismissable_banner.explore_statuses": "Ĉi tiuj estas afiŝoj de la tuta socia reto, kiuj populariĝas hodiaŭ. Pli novaj afiŝoj kun pli da diskonigoj kaj plej ŝatataj estas rangigitaj pli alte.", + "dismissable_banner.explore_statuses": "Jen afiŝoj en la socia reto kiuj populariĝis hodiaŭ. Novaj afiŝoj kun pli da diskonigoj kaj stelumoj aperas pli alte.", "dismissable_banner.explore_tags": "Ĉi tiuj kradvostoj populariĝas en ĉi tiu kaj aliaj serviloj en la malcentraliza reto nun.", "dismissable_banner.public_timeline": "Ĉi tiuj estas la plej lastatempaj publikaj afiŝoj de homoj en la socia reto, kiujn homoj sur {domain} sekvas.", "domain_block_modal.block": "Bloki servilon", @@ -646,7 +647,7 @@ "onboarding.start.lead": "Vi nun estas parto de Mastodon, unika, malcentralizita socia amaskomunikilara platformo, kie vi—ne algoritmo—zorgas vian propran sperton. Ni komencu vin sur ĉi tiu nova socia limo:", "onboarding.start.skip": "Ĉu vi ne bezonas helpon por komenci?", "onboarding.start.title": "Vi atingas ĝin!", - "onboarding.steps.follow_people.body": "Sekvi interesajn homojn estas pri kio Mastodonto temas.", + "onboarding.steps.follow_people.body": "You curate your own feed. Lets fill it with interesting people.", "onboarding.steps.follow_people.title": "Agordu vian hejman fluon", "onboarding.steps.publish_status.body": "Salutu la mondon per teksto, fotoj, filmetoj aŭ balotenketoj {emoji}", "onboarding.steps.publish_status.title": "Fari vian unuan afiŝon", @@ -780,9 +781,9 @@ "server_banner.is_one_of_many": "{domain} estas unu el la multaj sendependaj Mastodon-serviloj, kiujn vi povas uzi por partopreni en la fediverso.", "server_banner.server_stats": "Statistikoj de la servilo:", "sign_in_banner.create_account": "Krei konton", - "sign_in_banner.follow_anyone": "Sekvi iun ajn tra la fediverso kaj vidi ĉion en kronologia ordo. Neniuj algoritmoj, reklamoj aŭ klakbetoj videblas.", - "sign_in_banner.mastodon_is": "Mastodonto estas la plej bona maniero por resti flank-al-flanke kun kio okazas.", - "sign_in_banner.sign_in": "Saluti", + "sign_in_banner.follow_anyone": "Sekvu iun ajn tra la fediverso kaj vidu ĉion laŭ templinio. Nul algoritmo, reklamo aŭ kliklogilo ĉeestas.", + "sign_in_banner.mastodon_is": "Mastodon estas la plej bona maniero resti ĝisdata pri aktualaĵoj.", + "sign_in_banner.sign_in": "Ensaluti", "sign_in_banner.sso_redirect": "Ensalutu aŭ Registriĝi", "status.admin_account": "Malfermi fasadon de moderigado por @{name}", "status.admin_domain": "Malfermu moderigan interfacon por {domain}", diff --git a/app/javascript/mastodon/locales/es-AR.json b/app/javascript/mastodon/locales/es-AR.json index 9dc7b0d6c0..406c526983 100644 --- a/app/javascript/mastodon/locales/es-AR.json +++ b/app/javascript/mastodon/locales/es-AR.json @@ -101,6 +101,7 @@ "annual_report.summary.highlighted_post.possessive": "{name}", "annual_report.summary.most_used_app.most_used_app": "la aplicación más usada", "annual_report.summary.most_used_hashtag.most_used_hashtag": "la etiqueta más usada", + "annual_report.summary.most_used_hashtag.none": "Ninguna", "annual_report.summary.new_posts.new_posts": "nuevos mensajes", "annual_report.summary.percentile.text": "Eso te pone en la cimade los usuarios de Mastodon.", "annual_report.summary.percentile.we_wont_tell_bernie": "No se lo diremos a Bernie.", diff --git a/app/javascript/mastodon/locales/es-MX.json b/app/javascript/mastodon/locales/es-MX.json index 4faa35e5c8..63dc31c6df 100644 --- a/app/javascript/mastodon/locales/es-MX.json +++ b/app/javascript/mastodon/locales/es-MX.json @@ -89,9 +89,9 @@ "announcement.announcement": "Anuncio", "annual_report.summary.archetype.booster": "El cazador de tendencias", "annual_report.summary.archetype.lurker": "El acechador", - "annual_report.summary.archetype.oracle": "El oráculo", + "annual_report.summary.archetype.oracle": "El oraculo", "annual_report.summary.archetype.pollster": "El encuestador", - "annual_report.summary.archetype.replier": "El más sociable", + "annual_report.summary.archetype.replier": "La mariposa sociable", "annual_report.summary.followers.followers": "seguidores", "annual_report.summary.followers.total": "{count} en total", "annual_report.summary.here_it_is": "Aquí está tu resumen de {year}:", @@ -101,6 +101,7 @@ "annual_report.summary.highlighted_post.possessive": "de {name}", "annual_report.summary.most_used_app.most_used_app": "aplicación más usada", "annual_report.summary.most_used_hashtag.most_used_hashtag": "etiqueta más usada", + "annual_report.summary.most_used_hashtag.none": "Ninguna", "annual_report.summary.new_posts.new_posts": "nuevas publicaciones", "annual_report.summary.percentile.text": "Eso te pone en el topde usuarios de Mastodon.", "annual_report.summary.percentile.we_wont_tell_bernie": "No se lo diremos a Bernie.", diff --git a/app/javascript/mastodon/locales/es.json b/app/javascript/mastodon/locales/es.json index d14b718016..258b19f411 100644 --- a/app/javascript/mastodon/locales/es.json +++ b/app/javascript/mastodon/locales/es.json @@ -101,6 +101,7 @@ "annual_report.summary.highlighted_post.possessive": "de {name}", "annual_report.summary.most_used_app.most_used_app": "aplicación más usada", "annual_report.summary.most_used_hashtag.most_used_hashtag": "etiqueta más usada", + "annual_report.summary.most_used_hashtag.none": "Ninguna", "annual_report.summary.new_posts.new_posts": "nuevas publicaciones", "annual_report.summary.percentile.text": "Eso te pone en el topde usuarios de Mastodon.", "annual_report.summary.percentile.we_wont_tell_bernie": "No se lo diremos a Bernie.", diff --git a/app/javascript/mastodon/locales/fi.json b/app/javascript/mastodon/locales/fi.json index 32069b1a03..2763c39168 100644 --- a/app/javascript/mastodon/locales/fi.json +++ b/app/javascript/mastodon/locales/fi.json @@ -87,10 +87,22 @@ "alert.unexpected.title": "Hups!", "alt_text_badge.title": "Vaihtoehtoinen teksti", "announcement.announcement": "Tiedote", + "annual_report.summary.archetype.booster": "Tehostaja", + "annual_report.summary.archetype.lurker": "Lymyilijä", + "annual_report.summary.archetype.oracle": "Oraakkeli", + "annual_report.summary.archetype.pollster": "Mielipidetutkija", "annual_report.summary.archetype.replier": "Sosiaalinen perhonen", + "annual_report.summary.followers.followers": "seuraajaa", + "annual_report.summary.followers.total": "{count} yhteensä", + "annual_report.summary.here_it_is": "Tässä on katsaus vuoteesi {year}:", + "annual_report.summary.highlighted_post.by_favourites": "suosikkeihin lisätyin julkaisu", "annual_report.summary.highlighted_post.by_reblogs": "tehostetuin julkaisu", + "annual_report.summary.highlighted_post.by_replies": "julkaisu, jolla on eniten vastauksia", + "annual_report.summary.highlighted_post.possessive": "Käyttäjän {name}", "annual_report.summary.most_used_app.most_used_app": "käytetyin sovellus", "annual_report.summary.most_used_hashtag.most_used_hashtag": "käytetyin aihetunniste", + "annual_report.summary.new_posts.new_posts": "uutta julkaisua", + "annual_report.summary.percentile.text": "Olet osa huippujoukkoa, johon kuuluuMastodon-käyttäjistä.", "annual_report.summary.thanks": "Kiitos, että olet osa Mastodonia!", "attachments_list.unprocessed": "(käsittelemätön)", "audio.hide": "Piilota ääni", @@ -513,6 +525,7 @@ "notification.admin.report_statuses_other": "{name} raportoi käyttäjän {target}", "notification.admin.sign_up": "{name} rekisteröityi", "notification.admin.sign_up.name_and_others": "{name} ja {count, plural, one {# muu} other {# muuta}} rekisteröityivät", + "notification.annual_report.message": "Vuoden {year} #Wrapstodon odottaa! Paljasta vuotesi kohokohdat ikimuistoiset hetket Mastodonissa!", "notification.annual_report.view": "Näytä #Wrapstodon", "notification.favourite": "{name} lisäsi julkaisusi suosikkeihinsa", "notification.favourite.name_and_others_with_link": "{name} ja {count, plural, one {# muu} other {# muuta}} lisäsivät julkaisusi suosikkeihinsa", diff --git a/app/javascript/mastodon/locales/fo.json b/app/javascript/mastodon/locales/fo.json index 6b26ed84fd..789efaa40e 100644 --- a/app/javascript/mastodon/locales/fo.json +++ b/app/javascript/mastodon/locales/fo.json @@ -101,6 +101,7 @@ "annual_report.summary.highlighted_post.possessive": "hjá {name}", "annual_report.summary.most_used_app.most_used_app": "mest brúkta app", "annual_report.summary.most_used_hashtag.most_used_hashtag": "mest brúkta frámerki", + "annual_report.summary.most_used_hashtag.none": "Einki", "annual_report.summary.new_posts.new_posts": "nýggir postar", "annual_report.summary.percentile.text": "Tað fær teg í toppav Mastodon brúkarum.", "annual_report.summary.percentile.we_wont_tell_bernie": "Vit fara ikki at fortelja Bernie tað.", diff --git a/app/javascript/mastodon/locales/gl.json b/app/javascript/mastodon/locales/gl.json index 23f444715b..c69a431f4b 100644 --- a/app/javascript/mastodon/locales/gl.json +++ b/app/javascript/mastodon/locales/gl.json @@ -87,6 +87,11 @@ "alert.unexpected.title": "Vaites!", "alt_text_badge.title": "Texto Alt", "announcement.announcement": "Anuncio", + "annual_report.summary.archetype.booster": "A axencia de noticias", + "annual_report.summary.archetype.lurker": "Volleur", + "annual_report.summary.archetype.oracle": "Sabichón/e", + "annual_report.summary.archetype.pollster": "O INE", + "annual_report.summary.archetype.replier": "Lareteire", "annual_report.summary.followers.followers": "seguidoras", "annual_report.summary.followers.total": "{count} en total", "annual_report.summary.here_it_is": "Este é o resumo do teu {year}:", @@ -96,6 +101,7 @@ "annual_report.summary.highlighted_post.possessive": "de {name}", "annual_report.summary.most_used_app.most_used_app": "app que mais usaches", "annual_report.summary.most_used_hashtag.most_used_hashtag": "o cancelo mais utilizado", + "annual_report.summary.most_used_hashtag.none": "Nada", "annual_report.summary.new_posts.new_posts": "novas publicacións", "annual_report.summary.percentile.text": "Sitúante no top das usuarias de Mastodon.", "annual_report.summary.thanks": "Grazas por ser parte de Mastodon!", @@ -520,6 +526,8 @@ "notification.admin.report_statuses_other": "{name} denunciou a {target}", "notification.admin.sign_up": "{name} rexistrouse", "notification.admin.sign_up.name_and_others": "{name} e {count, plural, one {# máis} other {# máis}} crearon unha conta", + "notification.annual_report.message": "A #VidaEnMastodon de {year} agarda por ti! Desvela os momentos máis destacados e historias reseñables en Mastodon!", + "notification.annual_report.view": "Ver #VidaEnMastodon", "notification.favourite": "{name} marcou como favorita a túa publicación", "notification.favourite.name_and_others_with_link": "{name} e {count, plural, one {# máis} other {# máis}} favoreceron a túa publicación", "notification.follow": "{name} comezou a seguirte", diff --git a/app/javascript/mastodon/locales/hu.json b/app/javascript/mastodon/locales/hu.json index cdc113d8d7..2ba7aef34b 100644 --- a/app/javascript/mastodon/locales/hu.json +++ b/app/javascript/mastodon/locales/hu.json @@ -101,6 +101,7 @@ "annual_report.summary.highlighted_post.possessive": "{name} fióktól", "annual_report.summary.most_used_app.most_used_app": "legtöbbet használt app", "annual_report.summary.most_used_hashtag.most_used_hashtag": "legtöbbet használt hashtag", + "annual_report.summary.most_used_hashtag.none": "Nincs", "annual_report.summary.new_posts.new_posts": "új bejegyzés", "annual_report.summary.percentile.text": "Ezzel acsúcs Mastodon felhasználó között vagy.", "annual_report.summary.percentile.we_wont_tell_bernie": "Nem mondjuk el Bernie-nek.", diff --git a/app/javascript/mastodon/locales/is.json b/app/javascript/mastodon/locales/is.json index adc86faf40..ecfc642969 100644 --- a/app/javascript/mastodon/locales/is.json +++ b/app/javascript/mastodon/locales/is.json @@ -101,6 +101,7 @@ "annual_report.summary.highlighted_post.possessive": "{name}", "annual_report.summary.most_used_app.most_used_app": "mest notaða forrit", "annual_report.summary.most_used_hashtag.most_used_hashtag": "mest notaða myllumerki", + "annual_report.summary.most_used_hashtag.none": "Ekkert", "annual_report.summary.new_posts.new_posts": "nýjar færslur", "annual_report.summary.percentile.text": "Það setur þig á meðal efstunotenda Mastodon.", "annual_report.summary.percentile.we_wont_tell_bernie": "Við förum ekkert að raupa um þetta.", diff --git a/app/javascript/mastodon/locales/ko.json b/app/javascript/mastodon/locales/ko.json index b5c8d4bd21..43f1e59e5e 100644 --- a/app/javascript/mastodon/locales/ko.json +++ b/app/javascript/mastodon/locales/ko.json @@ -101,6 +101,7 @@ "annual_report.summary.highlighted_post.possessive": "{name} 님의", "annual_report.summary.most_used_app.most_used_app": "가장 많이 사용한 앱", "annual_report.summary.most_used_hashtag.most_used_hashtag": "가장 많이 사용한 해시태그", + "annual_report.summary.most_used_hashtag.none": "없음", "annual_report.summary.new_posts.new_posts": "새 게시물", "annual_report.summary.percentile.text": "마스토돈 사용자의 상위입니다.", "annual_report.summary.percentile.we_wont_tell_bernie": "엄마한테 말 안 할게요.", diff --git a/app/javascript/mastodon/locales/nl.json b/app/javascript/mastodon/locales/nl.json index b66fcf09c0..eb21d2ad1d 100644 --- a/app/javascript/mastodon/locales/nl.json +++ b/app/javascript/mastodon/locales/nl.json @@ -101,6 +101,7 @@ "annual_report.summary.highlighted_post.possessive": "{name}'s", "annual_report.summary.most_used_app.most_used_app": "meest gebruikte app", "annual_report.summary.most_used_hashtag.most_used_hashtag": "meest gebruikte hashtag", + "annual_report.summary.most_used_hashtag.none": "Geen", "annual_report.summary.new_posts.new_posts": "nieuwe berichten", "annual_report.summary.percentile.text": "Dat zet je in de topvan Mastodon-gebruikers.", "annual_report.summary.percentile.we_wont_tell_bernie": "We zullen Bernie niets vertellen.", diff --git a/app/javascript/mastodon/locales/nn.json b/app/javascript/mastodon/locales/nn.json index cc56754193..b45ff90585 100644 --- a/app/javascript/mastodon/locales/nn.json +++ b/app/javascript/mastodon/locales/nn.json @@ -87,6 +87,24 @@ "alert.unexpected.title": "Oi sann!", "alt_text_badge.title": "Alternativ tekst", "announcement.announcement": "Kunngjering", + "annual_report.summary.archetype.booster": "Den som jaktar på noko kult", + "annual_report.summary.archetype.lurker": "Den som heng på hjørnet", + "annual_report.summary.archetype.oracle": "Orakelet", + "annual_report.summary.archetype.pollster": "Meiningsmålaren", + "annual_report.summary.archetype.replier": "Den sosiale sumarfuglen", + "annual_report.summary.followers.followers": "fylgjarar", + "annual_report.summary.followers.total": "{count} i alt", + "annual_report.summary.here_it_is": "Her er eit gjensyn med {year}:", + "annual_report.summary.highlighted_post.by_favourites": "det mest omtykte innlegget", + "annual_report.summary.highlighted_post.by_reblogs": "det mest framheva innlegget", + "annual_report.summary.highlighted_post.by_replies": "innlegget med flest svar", + "annual_report.summary.highlighted_post.possessive": "som {name} laga", + "annual_report.summary.most_used_app.most_used_app": "mest brukte app", + "annual_report.summary.most_used_hashtag.most_used_hashtag": "mest brukte emneknagg", + "annual_report.summary.new_posts.new_posts": "nye innlegg", + "annual_report.summary.percentile.text": "Du er av deiivrigaste Mastodon-brukarane.", + "annual_report.summary.percentile.we_wont_tell_bernie": "Ikkje eit ord til pressa.", + "annual_report.summary.thanks": "Takk for at du er med i Mastodon!", "attachments_list.unprocessed": "(ubehandla)", "audio.hide": "Gøym lyd", "block_modal.remote_users_caveat": "Me vil be tenaren {domain} om å respektere di avgjerd. Me kan ikkje garantera at det vert gjort, sidan nokre tenarar kan handtera blokkering ulikt. Offentlege innlegg kan framleis vera synlege for ikkje-innlogga brukarar.", @@ -197,6 +215,7 @@ "confirmations.unfollow.title": "Slutt å fylgja brukaren?", "content_warning.hide": "Gøym innlegg", "content_warning.show": "Vis likevel", + "content_warning.show_more": "Vis meir", "conversation.delete": "Slett samtale", "conversation.mark_as_read": "Marker som lesen", "conversation.open": "Sjå samtale", @@ -305,6 +324,7 @@ "filter_modal.select_filter.subtitle": "Bruk ein eksisterande kategori eller opprett ein ny", "filter_modal.select_filter.title": "Filtrer dette innlegget", "filter_modal.title.status": "Filtrer eit innlegg", + "filter_warning.matches_filter": "Passar med filteret «{title}»", "filtered_notifications_banner.pending_requests": "Frå {count, plural, =0 {ingen} one {éin person} other {# personar}} du kanskje kjenner", "filtered_notifications_banner.title": "Filtrerte varslingar", "firehose.all": "Alle", @@ -506,6 +526,8 @@ "notification.admin.report_statuses_other": "{name} rapporterte {target}", "notification.admin.sign_up": "{name} er registrert", "notification.admin.sign_up.name_and_others": "{name} og {count, plural, one {# annan} other {# andre}} vart med", + "notification.annual_report.message": "#Året ditt for {year} ventar! Sjå kva som skjedde i løpet av Mastodon-året ditt!", + "notification.annual_report.view": "Sjå #Året ditt", "notification.favourite": "{name} markerte innlegget ditt som favoritt", "notification.favourite.name_and_others_with_link": "{name} og {count, plural, one {# annan} other {# andre}} favorittmerka innlegget ditt", "notification.follow": "{name} fylgde deg", diff --git a/app/javascript/mastodon/locales/pt-BR.json b/app/javascript/mastodon/locales/pt-BR.json index 5e69741f20..e2fbaff02b 100644 --- a/app/javascript/mastodon/locales/pt-BR.json +++ b/app/javascript/mastodon/locales/pt-BR.json @@ -101,6 +101,7 @@ "annual_report.summary.highlighted_post.possessive": "{name}", "annual_report.summary.most_used_app.most_used_app": "aplicativo mais usado", "annual_report.summary.most_used_hashtag.most_used_hashtag": "hashtag mais usada", + "annual_report.summary.most_used_hashtag.none": "Nenhuma", "annual_report.summary.new_posts.new_posts": "novas publicações", "annual_report.summary.percentile.text": "Isso o coloca no topodos usuários de Mastodon.", "annual_report.summary.percentile.we_wont_tell_bernie": "Não contaremos à Bernie.", diff --git a/app/javascript/mastodon/locales/ru.json b/app/javascript/mastodon/locales/ru.json index f5617550e1..e336e39e01 100644 --- a/app/javascript/mastodon/locales/ru.json +++ b/app/javascript/mastodon/locales/ru.json @@ -89,9 +89,11 @@ "announcement.announcement": "Объявление", "annual_report.summary.archetype.booster": "Репостер", "annual_report.summary.archetype.lurker": "Молчун", + "annual_report.summary.archetype.oracle": "Шаман", "annual_report.summary.archetype.pollster": "Опросчик", "annual_report.summary.archetype.replier": "Душа компании", "annual_report.summary.followers.followers": "подписчиков", + "annual_report.summary.followers.total": "{count} за всё время", "annual_report.summary.here_it_is": "Вот ваши итоги {year} года:", "annual_report.summary.highlighted_post.by_favourites": "пост с наибольшим количеством звёздочек", "annual_report.summary.highlighted_post.by_reblogs": "пост с наибольшим количеством продвижений", @@ -99,7 +101,9 @@ "annual_report.summary.highlighted_post.possessive": "{name}", "annual_report.summary.most_used_app.most_used_app": "наиболее часто используемое приложение", "annual_report.summary.most_used_hashtag.most_used_hashtag": "наиболее часто используемый хэштег", + "annual_report.summary.most_used_hashtag.none": "Нет", "annual_report.summary.new_posts.new_posts": "новых постов", + "annual_report.summary.percentile.text": "Всё это помещает вас в топпользователей Mastodon.", "annual_report.summary.thanks": "Спасибо за то, что были вместе с Mastodon!", "attachments_list.unprocessed": "(не обработан)", "audio.hide": "Скрыть аудио", diff --git a/app/javascript/mastodon/locales/sq.json b/app/javascript/mastodon/locales/sq.json index 0faee304c6..d1d92c69f6 100644 --- a/app/javascript/mastodon/locales/sq.json +++ b/app/javascript/mastodon/locales/sq.json @@ -96,6 +96,7 @@ "annual_report.summary.highlighted_post.possessive": "nga {name}", "annual_report.summary.most_used_app.most_used_app": "aplikacioni më i përdorur", "annual_report.summary.most_used_hashtag.most_used_hashtag": "hashtag-u më i përdorur", + "annual_report.summary.most_used_hashtag.none": "Asnjë", "annual_report.summary.new_posts.new_posts": "postime të reja", "annual_report.summary.percentile.text": "Kjo ju vë në kryetë përdoruesve të Mastodon-it.", "annual_report.summary.percentile.we_wont_tell_bernie": "Nuk do t’ia themi Bernit.", diff --git a/app/javascript/mastodon/locales/sv.json b/app/javascript/mastodon/locales/sv.json index ef2d912c00..df24db9634 100644 --- a/app/javascript/mastodon/locales/sv.json +++ b/app/javascript/mastodon/locales/sv.json @@ -101,6 +101,7 @@ "annual_report.summary.highlighted_post.possessive": "{name}s", "annual_report.summary.most_used_app.most_used_app": "mest använda app", "annual_report.summary.most_used_hashtag.most_used_hashtag": "mest använda hashtag", + "annual_report.summary.most_used_hashtag.none": "Inga", "annual_report.summary.new_posts.new_posts": "nya inlägg", "annual_report.summary.percentile.text": "Det placerar dig i toppav Mastodon-användare.", "annual_report.summary.percentile.we_wont_tell_bernie": "Vi berättar inte för Bernie.", diff --git a/app/javascript/mastodon/locales/tr.json b/app/javascript/mastodon/locales/tr.json index 4699b9f4bd..ece97614ad 100644 --- a/app/javascript/mastodon/locales/tr.json +++ b/app/javascript/mastodon/locales/tr.json @@ -101,6 +101,7 @@ "annual_report.summary.highlighted_post.possessive": "{name}", "annual_report.summary.most_used_app.most_used_app": "en çok kullanılan uygulama", "annual_report.summary.most_used_hashtag.most_used_hashtag": "en çok kullanılan etiket", + "annual_report.summary.most_used_hashtag.none": "Yok", "annual_report.summary.new_posts.new_posts": "yeni gönderiler", "annual_report.summary.percentile.text": "Mastodon kullanıcılarınınüst dilimindesiniz.", "annual_report.summary.percentile.we_wont_tell_bernie": "Bernie'ye söylemeyiz.", diff --git a/app/javascript/mastodon/locales/uk.json b/app/javascript/mastodon/locales/uk.json index dcbf8cec58..0e0906eb37 100644 --- a/app/javascript/mastodon/locales/uk.json +++ b/app/javascript/mastodon/locales/uk.json @@ -101,6 +101,7 @@ "annual_report.summary.highlighted_post.possessive": "{name}", "annual_report.summary.most_used_app.most_used_app": "найчастіше використовуваний застосунок", "annual_report.summary.most_used_hashtag.most_used_hashtag": "найчастіший хештег", + "annual_report.summary.most_used_hashtag.none": "Немає", "annual_report.summary.new_posts.new_posts": "нові дописи", "annual_report.summary.percentile.text": "Це виводить вас в топ користувачів Mastodon.", "annual_report.summary.percentile.we_wont_tell_bernie": "Ми не скажемо Bernie.", diff --git a/app/javascript/mastodon/locales/vi.json b/app/javascript/mastodon/locales/vi.json index 2b5401a878..73016ed8c9 100644 --- a/app/javascript/mastodon/locales/vi.json +++ b/app/javascript/mastodon/locales/vi.json @@ -101,6 +101,7 @@ "annual_report.summary.highlighted_post.possessive": "{name}", "annual_report.summary.most_used_app.most_used_app": "app dùng nhiều nhất", "annual_report.summary.most_used_hashtag.most_used_hashtag": "hashtag dùng nhiều nhất", + "annual_report.summary.most_used_hashtag.none": "Không có", "annual_report.summary.new_posts.new_posts": "tút mới", "annual_report.summary.percentile.text": "Bạn nằm trong topthành viên Mastodon.", "annual_report.summary.percentile.we_wont_tell_bernie": "Chúng tôi sẽ không kể cho Bernie.", diff --git a/app/javascript/mastodon/locales/zh-CN.json b/app/javascript/mastodon/locales/zh-CN.json index 57b2011bb1..887410dd51 100644 --- a/app/javascript/mastodon/locales/zh-CN.json +++ b/app/javascript/mastodon/locales/zh-CN.json @@ -101,6 +101,7 @@ "annual_report.summary.highlighted_post.possessive": "{name} 的", "annual_report.summary.most_used_app.most_used_app": "最常用的应用", "annual_report.summary.most_used_hashtag.most_used_hashtag": "最常用的话题", + "annual_report.summary.most_used_hashtag.none": "无", "annual_report.summary.new_posts.new_posts": "新发嘟", "annual_report.summary.percentile.text": "这使你跻身 Mastodon 用户的前", "annual_report.summary.percentile.we_wont_tell_bernie": "我们打死也不会告诉Bernie。", diff --git a/app/javascript/mastodon/locales/zh-TW.json b/app/javascript/mastodon/locales/zh-TW.json index 91d7f6e45d..56ddd9745e 100644 --- a/app/javascript/mastodon/locales/zh-TW.json +++ b/app/javascript/mastodon/locales/zh-TW.json @@ -101,6 +101,7 @@ "annual_report.summary.highlighted_post.possessive": "{name} 的", "annual_report.summary.most_used_app.most_used_app": "最常使用的應用程式", "annual_report.summary.most_used_hashtag.most_used_hashtag": "最常使用的主題標籤", + "annual_report.summary.most_used_hashtag.none": "無最常用之主題標籤", "annual_report.summary.new_posts.new_posts": "新嘟文", "annual_report.summary.percentile.text": "這讓您成為前Mastodon 的使用者。", "annual_report.summary.percentile.we_wont_tell_bernie": "我們不會告訴 Bernie。", diff --git a/config/locales/ca.yml b/config/locales/ca.yml index 9d861fa30c..00c8f57a85 100644 --- a/config/locales/ca.yml +++ b/config/locales/ca.yml @@ -187,6 +187,7 @@ ca: create_domain_block: Crea un bloqueig de domini create_email_domain_block: Crea un blocatge del domini del correu electrònic create_ip_block: Crear regla IP + create_relay: Crea un repetidor create_unavailable_domain: Crea un domini no disponible create_user_role: Crea Rol demote_user: Degrada l'usuari @@ -198,14 +199,17 @@ ca: destroy_email_domain_block: Elimina el blocatge del domini del correu electrònic destroy_instance: Purga Domini destroy_ip_block: Eliminar regla IP + destroy_relay: Esborra el repetidor destroy_status: Elimina la publicació destroy_unavailable_domain: Esborra domini no disponible destroy_user_role: Destrueix Rol disable_2fa_user: Desactiva 2FA disable_custom_emoji: Desactiva l'emoji personalitzat + disable_relay: Desactiva el repetidor disable_sign_in_token_auth_user: Desactivar l'autenticació de token per correu-e per a l'usuari disable_user: Deshabilita l'usuari enable_custom_emoji: Activa l'emoji personalitzat + enable_relay: Activa el repetidor enable_sign_in_token_auth_user: Activar l'autenticació de token per correu-e per a l'usuari enable_user: Activa l'usuari memorialize_account: Memoritza el compte @@ -247,6 +251,7 @@ ca: create_domain_block_html: "%{name} ha bloquejat el domini %{target}" create_email_domain_block_html: "%{name} ha blocat el domini de correu electrònic %{target}" create_ip_block_html: "%{name} ha creat una regla per a l'IP %{target}" + create_relay_html: "%{name} ha creat un repetidor %{target}" create_unavailable_domain_html: "%{name} ha aturat el lliurament al domini %{target}" create_user_role_html: "%{name} ha creat el rol %{target}" demote_user_html: "%{name} ha degradat l'usuari %{target}" @@ -258,14 +263,17 @@ ca: destroy_email_domain_block_html: "%{name} ha desblocat el domini de correu electrònic %{target}" destroy_instance_html: "%{name} ha purgat el domini %{target}" destroy_ip_block_html: "%{name} ha esborrat la regla per a l'IP %{target}" + destroy_relay_html: "%{name} ha esborrat el repetidor %{target}" destroy_status_html: "%{name} ha eliminat el tut de %{target}" destroy_unavailable_domain_html: "%{name} ha représ el lliurament delivery al domini %{target}" destroy_user_role_html: "%{name} ha esborrat el rol %{target}" disable_2fa_user_html: "%{name} ha desactivat el requisit de dos factors per a l'usuari %{target}" disable_custom_emoji_html: "%{name} ha desactivat l'emoji %{target}" + disable_relay_html: "%{name} ha desactivat el repetidor %{target}" disable_sign_in_token_auth_user_html: "%{name} ha desactivat l'autenticació de token per correu-e per a %{target}" disable_user_html: "%{name} ha desactivat l'accés del usuari %{target}" enable_custom_emoji_html: "%{name} ha activat l'emoji %{target}" + enable_relay_html: "%{name} ha activat el repetidor %{target}" enable_sign_in_token_auth_user_html: "%{name} ha activat l'autenticació de token per correu-e per a %{target}" enable_user_html: "%{name} ha activat l'accés del usuari %{target}" memorialize_account_html: "%{name} ha convertit el compte %{target} en una pàgina de memorial" diff --git a/config/locales/da.yml b/config/locales/da.yml index 6447afb493..daf683637d 100644 --- a/config/locales/da.yml +++ b/config/locales/da.yml @@ -187,6 +187,7 @@ da: create_domain_block: Opret domæneblokering create_email_domain_block: Opret e-maildomæneblokering create_ip_block: Opret IP-regel + create_relay: Opret Videresendelse create_unavailable_domain: Opret Utilgængeligt Domæne create_user_role: Opret rolle demote_user: Degradér bruger @@ -198,14 +199,17 @@ da: destroy_email_domain_block: Slet e-maildomæneblokering destroy_instance: Udrens domæne destroy_ip_block: Slet IP-regel + destroy_relay: Slet Videresendelse destroy_status: Slet indlæg destroy_unavailable_domain: Slet Utilgængeligt Domæne destroy_user_role: Ødelæg rolle disable_2fa_user: Deaktivér 2FA disable_custom_emoji: Deaktivér tilpasset emoji + disable_relay: Deaktivér Videresendelse disable_sign_in_token_auth_user: Deaktivér e-mailtoken godkendelse for bruger disable_user: Deaktivér bruger enable_custom_emoji: Aktivér tilpasset emoji + enable_relay: Aktivér Relay enable_sign_in_token_auth_user: Aktivér e-mailtoken godkendelse for bruger enable_user: Aktivér bruger memorialize_account: Memoralisér konto @@ -247,6 +251,7 @@ da: create_domain_block_html: "%{name} blokerede domænet %{target}" create_email_domain_block_html: "%{name} blokerede e-maildomænet %{target}" create_ip_block_html: "%{name} oprettede en regel for IP %{target}" + create_relay_html: "%{name} oprettede videresendelsen %{target}" create_unavailable_domain_html: "%{name} stoppede levering til domænet %{target}" create_user_role_html: "%{name} oprettede %{target}-rolle" demote_user_html: "%{name} degraderede brugeren %{target}" @@ -258,14 +263,17 @@ da: destroy_email_domain_block_html: "%{name} afblokerede e-maildomænet %{target}" destroy_instance_html: "%{name} udrensede domænet %{target}" destroy_ip_block_html: "%{name} slettede en regel for IP %{target}" + destroy_relay_html: "%{name} oprettede videresendelsen %{target}" destroy_status_html: "%{name} fjernede indlægget fra %{target}" destroy_unavailable_domain_html: "%{name} genoptog levering til domænet %{target}" destroy_user_role_html: "%{name} slettede %{target}-rolle" disable_2fa_user_html: "%{name} deaktiverede tofaktorkravet for brugeren %{target}" disable_custom_emoji_html: "%{name} deaktiverede emojien %{target}" + disable_relay_html: "%{name} deaktiverede videresendelsen %{target}" disable_sign_in_token_auth_user_html: "%{name} deaktiverede e-mailtoken godkendelsen for %{target}" disable_user_html: "%{name} deaktiverede indlogning for brugeren %{target}" enable_custom_emoji_html: "%{name} aktiverede emojien %{target}" + enable_relay_html: "%{name} aktiverede videresendelsen %{target}" enable_sign_in_token_auth_user_html: "%{name} aktiverede e-mailtoken godkendelse for %{target}" enable_user_html: "%{name} aktiverede indlogning for brugeren %{target}" memorialize_account_html: "%{name} gjorde %{target}s konto til en mindeside" diff --git a/config/locales/de.yml b/config/locales/de.yml index 323579f25f..10223f2278 100644 --- a/config/locales/de.yml +++ b/config/locales/de.yml @@ -187,6 +187,7 @@ de: create_domain_block: Domain sperren create_email_domain_block: E-Mail-Domain-Sperre erstellen create_ip_block: IP-Regel erstellen + create_relay: Relay erstellen create_unavailable_domain: Nicht verfügbare Domain erstellen create_user_role: Rolle erstellen demote_user: Benutzer*in herabstufen @@ -198,14 +199,17 @@ de: destroy_email_domain_block: E-Mail-Domain-Sperre entfernen destroy_instance: Domain-Daten entfernen destroy_ip_block: IP-Regel löschen + destroy_relay: Relay löschen destroy_status: Beitrag entfernen destroy_unavailable_domain: Nicht-verfügbare Domain entfernen destroy_user_role: Rolle entfernen disable_2fa_user: 2FA deaktivieren disable_custom_emoji: Eigenes Emoji deaktivieren + disable_relay: Relay deaktivieren disable_sign_in_token_auth_user: E-Mail-Token-Authentisierung für dieses Konto deaktivieren disable_user: Benutzer*in deaktivieren enable_custom_emoji: Eigenes Emoji aktivieren + enable_relay: Relay aktivieren enable_sign_in_token_auth_user: E-Mail-Token-Authentisierung für dieses Konto aktivieren enable_user: Benutzer*in aktivieren memorialize_account: Gedenkkonto @@ -247,6 +251,7 @@ de: create_domain_block_html: "%{name} sperrte die Domain %{target}" create_email_domain_block_html: "%{name} sperrte die E-Mail-Domain %{target}" create_ip_block_html: "%{name} erstellte eine IP-Regel für %{target}" + create_relay_html: "%{name} erstellte ein Relay %{target}" create_unavailable_domain_html: "%{name} beendete die Zustellung an die Domain %{target}" create_user_role_html: "%{name} erstellte die Rolle %{target}" demote_user_html: "%{name} stufte %{target} herunter" @@ -258,14 +263,17 @@ de: destroy_email_domain_block_html: "%{name} entsperrte die E-Mail-Domain %{target}" destroy_instance_html: "%{name} entfernte die Daten der Domain %{target} von diesem Server" destroy_ip_block_html: "%{name} entfernte eine IP-Regel für %{target}" + destroy_relay_html: "%{name} löschte das Relay %{target}" destroy_status_html: "%{name} entfernte einen Beitrag von %{target}" destroy_unavailable_domain_html: "%{name} nahm die Zustellung an die Domain %{target} wieder auf" destroy_user_role_html: "%{name} löschte die Rolle %{target}" disable_2fa_user_html: "%{name} deaktivierte die Zwei-Faktor-Authentisierung für %{target}" disable_custom_emoji_html: "%{name} deaktivierte das Emoji %{target}" + disable_relay_html: "%{name} deaktivierte das Relay %{target}" disable_sign_in_token_auth_user_html: "%{name} deaktivierte die E-Mail-Token-Authentisierung für %{target}" disable_user_html: "%{name} deaktivierte den Zugang für %{target}" enable_custom_emoji_html: "%{name} aktivierte das Emoji %{target}" + enable_relay_html: "%{name} aktivierte das Relay %{target}" enable_sign_in_token_auth_user_html: "%{name} aktivierte die E-Mail-Token-Authentisierung für %{target}" enable_user_html: "%{name} aktivierte den Zugang für %{target}" memorialize_account_html: "%{name} wandelte das Konto von %{target} in eine Gedenkseite um" diff --git a/config/locales/fi.yml b/config/locales/fi.yml index 2f9a76c80d..6fe9c14591 100644 --- a/config/locales/fi.yml +++ b/config/locales/fi.yml @@ -187,6 +187,7 @@ fi: create_domain_block: Luo verkkotunnuksen esto create_email_domain_block: Luo sähköpostiverkkotunnuksen esto create_ip_block: Luo IP-sääntö + create_relay: Luo välittäjä create_unavailable_domain: Luo ei-saatavilla oleva verkkotunnus create_user_role: Luo rooli demote_user: Alenna käyttäjä @@ -198,14 +199,17 @@ fi: destroy_email_domain_block: Poista sähköpostiverkkotunnuksen esto destroy_instance: Tyhjennä verkkotunnus destroy_ip_block: Poista IP-sääntö + destroy_relay: Poista välittäjä destroy_status: Poista julkaisu destroy_unavailable_domain: Poista ei-saatavilla oleva verkkotunnus destroy_user_role: Hävitä rooli disable_2fa_user: Poista kaksivaiheinen todennus käytöstä disable_custom_emoji: Poista mukautettu emoji käytöstä + disable_relay: Poista välittäjä käytöstä disable_sign_in_token_auth_user: Poista sähköpostitunnuksella todennus käytöstä käyttäjältä disable_user: Poista tili käytöstä enable_custom_emoji: Ota mukautettu emoji käyttöön + enable_relay: Ota välittäjä käyttöön enable_sign_in_token_auth_user: Ota sähköpostitunnuksella todennus käyttöön käyttäjälle enable_user: Ota tili käyttöön memorialize_account: Muuta muistotiliksi @@ -216,7 +220,7 @@ fi: reopen_report: Avaa raportti uudelleen resend_user: Lähetä vahvistusviesti uudelleen reset_password_user: Palauta salasana - resolve_report: Selvitä raportti + resolve_report: Ratkaise raportti sensitive_account: Pakota arkaluonteiseksi tiliksi silence_account: Rajoita tiliä suspend_account: Jäädytä tili @@ -247,6 +251,7 @@ fi: create_domain_block_html: "%{name} esti verkkotunnuksen %{target}" create_email_domain_block_html: "%{name} esti sähköpostiverkkotunnuksen %{target}" create_ip_block_html: "%{name} loi säännön IP-osoitteelle %{target}" + create_relay_html: "%{name} loi välittäjän %{target}" create_unavailable_domain_html: "%{name} pysäytti toimituksen verkkotunnukseen %{target}" create_user_role_html: "%{name} loi roolin %{target}" demote_user_html: "%{name} alensi käyttäjän %{target}" @@ -258,14 +263,17 @@ fi: destroy_email_domain_block_html: "%{name} kumosi sähköpostiverkkotunnuksen %{target} eston" destroy_instance_html: "%{name} tyhjensi verkkotunnuksen %{target}" destroy_ip_block_html: "%{name} poisti säännön IP-osoitteelta %{target}" + destroy_relay_html: "%{name} poisti välittäjän %{target}" destroy_status_html: "%{name} poisti käyttäjän %{target} julkaisun" destroy_unavailable_domain_html: "%{name} jatkoi toimitusta verkkotunnukseen %{target}" destroy_user_role_html: "%{name} poisti roolin %{target}" disable_2fa_user_html: "%{name} poisti käyttäjältä %{target} vaatimuksen kaksivaiheiseen todentamiseen" disable_custom_emoji_html: "%{name} poisti emojin %{target} käytöstä" + disable_relay_html: "%{name} poisti välittäjän %{target} käytöstä" disable_sign_in_token_auth_user_html: "%{name} poisti sähköpostitunnuksella todennuksen käytöstä käyttäjältä %{target}" disable_user_html: "%{name} poisti kirjautumisen käytöstä käyttäjältä %{target}" enable_custom_emoji_html: "%{name} otti emojin %{target} käyttöön" + enable_relay_html: "%{name} otti välittäjän %{target} käyttöön" enable_sign_in_token_auth_user_html: "%{name} otti sähköpostitunnuksella todennuksen käyttöön käyttäjälle %{target}" enable_user_html: "%{name} otti kirjautumisen käyttöön käyttäjälle %{target}" memorialize_account_html: "%{name} muutti käyttäjän %{target} tilin muistosivuksi" diff --git a/config/locales/fo.yml b/config/locales/fo.yml index 1060ee1609..6cc1fda6a0 100644 --- a/config/locales/fo.yml +++ b/config/locales/fo.yml @@ -187,6 +187,7 @@ fo: create_domain_block: Stovna navnaøkjablokering create_email_domain_block: Stovna t-post-økisnavnablokk create_ip_block: Stovna IP reglu + create_relay: Stovna reiðlag create_unavailable_domain: Stovna navnaøki, sum ikki er tøkt create_user_role: Stovna leiklut demote_user: Lækka brúkara í tign @@ -198,14 +199,17 @@ fo: destroy_email_domain_block: Strika t-posta-økisnavnablokk destroy_instance: Reinsa navnaøki destroy_ip_block: Strika IP reglu + destroy_relay: Strika reiðlag destroy_status: Strika post destroy_unavailable_domain: Strika navnaøki, sum ikki er tøkt destroy_user_role: Bein burtur leiklut disable_2fa_user: Ger 2FA óvirkið disable_custom_emoji: Ger serligt kenslutekn óvirkið + disable_relay: Ger reiðlag óvirkið disable_sign_in_token_auth_user: Ger váttan við teldupostateknum óvirkna fyri brúkara disable_user: Ger brúkara óvirknan enable_custom_emoji: Ger serligt kenslutekn virkið + enable_relay: Ger reiðlag virkið enable_sign_in_token_auth_user: Ger váttan við teldupostateknum virkna fyri brúkara enable_user: Ger brúkara virknan memorialize_account: Minnst til Konto @@ -247,6 +251,7 @@ fo: create_domain_block_html: "%{name} blokeraði navnaøkið %{target}" create_email_domain_block_html: "%{name} blokeraði teldupostanavnaøkið %{target}" create_ip_block_html: "%{name} gjørdi reglu fyri IP %{target}" + create_relay_html: "%{name} gjørdi eitt reiðlag %{target}" create_unavailable_domain_html: "%{name} steðgaði veiting til navnaøkið %{target}" create_user_role_html: "%{name} stovnaði %{target} leiklutin" demote_user_html: "%{name} lækkaði tignina hjá brúkaranum %{target}" @@ -258,14 +263,17 @@ fo: destroy_email_domain_block_html: "%{name} leysgav teldupostanavnaøkið %{target}" destroy_instance_html: "%{name} reinsaði navnaøkið %{target}" destroy_ip_block_html: "%{name} slettaðar reglur fyri IP %{target}" + destroy_relay_html: "%{name} strikaði reiðlagið %{target}" destroy_status_html: "%{name} slettaði upplegg hjá %{target}" destroy_unavailable_domain_html: "%{name} tók upp aftir veiting til navnaøkið %{target}" destroy_user_role_html: "%{name} slettaði leiklutin hjá %{target}" disable_2fa_user_html: "%{name} slepti kravið um váttan í tveimum stigum fyri brúkaran %{target}" disable_custom_emoji_html: "%{name} gjørdi kensluteknið %{target} óvirkið" + disable_relay_html: "%{name} gjørdi reiðlagið %{target} óvirkið" disable_sign_in_token_auth_user_html: "%{name} gjørdi váttan við teldupostteknum óvirkna fyri %{target}" disable_user_html: "%{name} gjørdi innritan hjá brúkaranum %{target} óvirkna" enable_custom_emoji_html: "%{name} gjørdi kensluteknið %{target} virkið" + enable_relay_html: "%{name} gjørdi reiðlagið %{target} virkið" enable_sign_in_token_auth_user_html: "%{name} gjørdi váttan við teldupostteknum virkna fyri %{target}" enable_user_html: "%{name} gjørdi innritan virkna fyri brúkaran %{target}" memorialize_account_html: "%{name} broytti kontuna hjá %{target} til eina minnissíðu" diff --git a/config/locales/gl.yml b/config/locales/gl.yml index a4f63a50e0..1ad8deb179 100644 --- a/config/locales/gl.yml +++ b/config/locales/gl.yml @@ -187,6 +187,7 @@ gl: create_domain_block: Crear bloquedo do Dominio create_email_domain_block: Crear Bloqueo de Dominio do correo create_ip_block: Crear regra IP + create_relay: Crear Repetidor create_unavailable_domain: Crear dominio Non dispoñible create_user_role: Crear Rol demote_user: Degradar usuaria @@ -198,14 +199,17 @@ gl: destroy_email_domain_block: Eliminar bloqueo do dominio do correo destroy_instance: Purgar Dominio destroy_ip_block: Eliminar regra IP + destroy_relay: Eliminar Repetidor destroy_status: Eliminar publicación destroy_unavailable_domain: Eliminar dominio Non dispoñible destroy_user_role: Eliminar Rol disable_2fa_user: Desactivar 2FA disable_custom_emoji: Desactivar emoticona personalizada + disable_relay: Desactivar Repetidor disable_sign_in_token_auth_user: Desactivar Autenticación por Token no Correo para a Usuaria disable_user: Desactivar usuaria enable_custom_emoji: Activar emoticona personalizada + enable_relay: Activar Repetidor enable_sign_in_token_auth_user: Activar Autenticación con Token no Correo para a Usuaria enable_user: Activar usuaria memorialize_account: Transformar en conta conmemorativa @@ -247,6 +251,7 @@ gl: create_domain_block_html: "%{name} bloqueou o dominio %{target}" create_email_domain_block_html: "%{name} bloqueou o dominio de correo %{target}" create_ip_block_html: "%{name} creou regra para o IP %{target}" + create_relay_html: "%{name} creou un repetidor en %{target}" create_unavailable_domain_html: "%{name} deixou de interactuar co dominio %{target}" create_user_role_html: "%{name} creou o rol %{target}" demote_user_html: "%{name} degradou a usuaria %{target}" @@ -258,14 +263,17 @@ gl: destroy_email_domain_block_html: "%{name} desbloqueou o dominio de correo %{target}" destroy_instance_html: "%{name} purgou o dominio %{target}" destroy_ip_block_html: "%{name} eliminou a regra para o IP %{target}" + destroy_relay_html: "%{name} eliminou o repetidor %{target}" destroy_status_html: "%{name} eliminou a publicación de %{target}" destroy_unavailable_domain_html: "%{name} retomou a interacción co dominio %{target}" destroy_user_role_html: "%{name} eliminou o rol %{target}" disable_2fa_user_html: "%{name} desactivou o requerimento do segundo factor para a usuaria %{target}" disable_custom_emoji_html: "%{name} desactivou o emoji %{target}" + disable_relay_html: "%{name} desactivou o repetidor %{target}" disable_sign_in_token_auth_user_html: "%{name} desactivou a autenticación por token no email para %{target}" disable_user_html: "%{name} desactivou as credenciais para a usuaria %{target}" enable_custom_emoji_html: "%{name} activou o emoji %{target}" + enable_relay_html: "%{name} activou o repetidor %{target}" enable_sign_in_token_auth_user_html: "%{name} activou a autenticación con token no email para %{target}" enable_user_html: "%{name} activou as credenciais para a usuaria %{target}" memorialize_account_html: "%{name} convertiu a conta de %{target} nunha páxina para o recordo" diff --git a/config/locales/hu.yml b/config/locales/hu.yml index 47bd24fccf..1892009238 100644 --- a/config/locales/hu.yml +++ b/config/locales/hu.yml @@ -187,6 +187,7 @@ hu: create_domain_block: Domain tiltás létrehozása create_email_domain_block: E-mail-domain-tiltás létrehozása create_ip_block: IP szabály létrehozása + create_relay: Továbbító létrehozása create_unavailable_domain: Elérhetetlen domain létrehozása create_user_role: Szerepkör létrehozása demote_user: Felhasználó lefokozása @@ -198,14 +199,17 @@ hu: destroy_email_domain_block: E-mail-domain-tiltás törlése destroy_instance: Domain végleges törlése destroy_ip_block: IP szabály törlése + destroy_relay: Továbbító törlése destroy_status: Bejegyzés törlése destroy_unavailable_domain: Elérhetetlen domain törlése destroy_user_role: Szerepkör eltávolítása disable_2fa_user: Kétlépcsős hitelesítés letiltása disable_custom_emoji: Egyéni emodzsi letiltása + disable_relay: Továbbító letiltása disable_sign_in_token_auth_user: A felhasználó tokenes e-mail-hitelesítésének letiltása disable_user: Felhasználói letiltása enable_custom_emoji: Egyéni emodzsi engedélyezése + enable_relay: Továbbító engedélyezése enable_sign_in_token_auth_user: A felhasználó tokenes e-mail-hitelesítésének engedélyezése enable_user: Felhasználó engedélyezése memorialize_account: Fiók emlékké nyilvánítása @@ -247,6 +251,7 @@ hu: create_domain_block_html: "%{name} letiltotta a %{target} domaint" create_email_domain_block_html: "%{name} letiltotta a(z) %{target} e-mail-domaint" create_ip_block_html: "%{name} létrehozta a(z) %{target} IP-címre vonatkozó szabályt" + create_relay_html: "%{name} létrehozta az átirányítót: %{target}" create_unavailable_domain_html: "%{name} leállította a kézbesítést a %{target} domainbe" create_user_role_html: "%{name} létrehozta a(z) %{target} szerepkört" demote_user_html: "%{name} lefokozta %{target} felhasználót" @@ -258,14 +263,17 @@ hu: destroy_email_domain_block_html: "%{name} engedélyezte a(z) %{target} e-mail-domaint" destroy_instance_html: "%{name} véglegesen törölte a(z) %{target} domaint" destroy_ip_block_html: "%{name} törölte a(z) %{target} IP-címre vonatkozó szabályt" + destroy_relay_html: "%{name} törölte az átirányítót: %{target}" destroy_status_html: "%{name} eltávolította %{target} felhasználó bejegyzését" destroy_unavailable_domain_html: "%{name} újraindította a kézbesítést a %{target} domainbe" destroy_user_role_html: "%{name} törölte a(z) %{target} szerepkört" disable_2fa_user_html: "%{name} kikapcsolta a kétlépcsős hitelesítést %{target} felhasználó fiókján" disable_custom_emoji_html: "%{name} letiltotta az emodzsit: %{target}" + disable_relay_html: "%{name} letiltotta az átirányítót: %{target}" disable_sign_in_token_auth_user_html: "%{name} letiltotta a tokenes e-mail-hitelesítést %{target} felhasználóra" disable_user_html: "%{name} letiltotta %{target} felhasználó bejelentkezését" enable_custom_emoji_html: "%{name} engedélyezte az emodzsit: %{target}" + enable_relay_html: "%{name} engedélyezte az átirányítót: %{target}" enable_sign_in_token_auth_user_html: "%{name} engedélyezte a tokenes e-mail-hitelesítést %{target} felhasználóra" enable_user_html: "%{name} engedélyezte %{target} felhasználó bejelentkezését" memorialize_account_html: "%{name} emléket állított %{target} felhasználónak" diff --git a/config/locales/is.yml b/config/locales/is.yml index c50b3dd20d..552df8f064 100644 --- a/config/locales/is.yml +++ b/config/locales/is.yml @@ -187,6 +187,7 @@ is: create_domain_block: Búa til útilokun léns create_email_domain_block: Búa til útilokun tölvupóstléns create_ip_block: Búa til IP-reglu + create_relay: Búa til endurvarpa create_unavailable_domain: Útbúa lén sem ekki er tiltækt create_user_role: Útbúa hlutverk demote_user: Lækka notanda í tign @@ -198,14 +199,17 @@ is: destroy_email_domain_block: Eyða útilokun tölvupóstléns destroy_instance: Henda léni destroy_ip_block: Eyða IP-reglu + destroy_relay: Eyða endurvarpa destroy_status: Eyða færslu destroy_unavailable_domain: Eyða léni sem ekki er tiltækt destroy_user_role: Eyða hlutverki disable_2fa_user: Gera tveggja-þátta auðkenningu óvirka disable_custom_emoji: Gera sérsniðið tjáningartákn óvirkt + disable_relay: Gera endurvarpa óvirkan disable_sign_in_token_auth_user: Gera óvirka auðkenningu með teikni í tölvupósti fyrir notandann disable_user: Gera notanda óvirkan enable_custom_emoji: Virkja sérsniðið tjáningartákn + enable_relay: Virkja endurvarpa enable_sign_in_token_auth_user: Gera virka auðkenningu með teikni í tölvupósti fyrir notandann enable_user: Virkja notanda memorialize_account: Gera aðgang að minningargrein @@ -247,6 +251,7 @@ is: create_domain_block_html: "%{name} útilokaði lénið %{target}" create_email_domain_block_html: "%{name} útilokaði póstlénið %{target}" create_ip_block_html: "%{name} útbjó reglu fyrir IP-vistfangið %{target}" + create_relay_html: "%{name} bjó til endurvarpa %{target}" create_unavailable_domain_html: "%{name} stöðvaði afhendingu til lénsins %{target}" create_user_role_html: "%{name} útbjó %{target} hlutverk" demote_user_html: "%{name} lækkaði notandann %{target} í tign" @@ -258,14 +263,17 @@ is: destroy_email_domain_block_html: "%{name} aflétti útilokun af póstléninu %{target}" destroy_instance_html: "%{name} henti léninu %{target}" destroy_ip_block_html: "%{name} eyddi reglu fyrir IP-vistfangið %{target}" + destroy_relay_html: "%{name} eyddi endurvarpanum %{target}" destroy_status_html: "%{name} fjarlægði færslu frá %{target}" destroy_unavailable_domain_html: "%{name} hóf aftur afhendingu til lénsins %{target}" destroy_user_role_html: "%{name} eyddi hlutverki %{target}" disable_2fa_user_html: "%{name} gerði kröfu um tveggja-þátta innskráningu óvirka fyrir notandann %{target}" disable_custom_emoji_html: "%{name} gerði tjáningartáknið %{target} óvirkt" + disable_relay_html: "%{name} gerði endurvarpann %{target} óvirkan" disable_sign_in_token_auth_user_html: "%{name} gerði óvirka auðkenningu með teikni í tölvupósti fyrir %{target}" disable_user_html: "%{name} gerði innskráningu óvirka fyrir notandann %{target}" enable_custom_emoji_html: "%{name} gerði tjáningartáknið %{target} virkt" + enable_relay_html: "%{name} virkjaði endurvarpann %{target}" enable_sign_in_token_auth_user_html: "%{name} gerði virka auðkenningu með teikni í tölvupósti fyrir %{target}" enable_user_html: "%{name} gerði innskráningu virka fyrir notandann %{target}" memorialize_account_html: "%{name} breytti notandaaðgangnum %{target} í minningargreinarsíðu" diff --git a/config/locales/ko.yml b/config/locales/ko.yml index 6bff1703e6..1fe43f7e75 100644 --- a/config/locales/ko.yml +++ b/config/locales/ko.yml @@ -184,6 +184,7 @@ ko: create_domain_block: 도메인 차단 추가 create_email_domain_block: 이메일 도메인 차단 생성 create_ip_block: IP 규칙 만들기 + create_relay: 릴레이 생성 create_unavailable_domain: 사용 불가능한 도메인 생성 create_user_role: 역할 생성 demote_user: 사용자 강등 @@ -195,14 +196,17 @@ ko: destroy_email_domain_block: 이메일 도메인 차단 삭제 destroy_instance: 도메인 퍼지하기 destroy_ip_block: IP 규칙 삭제 + destroy_relay: 릴레이 삭제 destroy_status: 게시물 삭제 destroy_unavailable_domain: 사용 불가능한 도메인 제거 destroy_user_role: 역할 삭제 disable_2fa_user: 2단계 인증 비활성화 disable_custom_emoji: 커스텀 에모지 비활성화 + disable_relay: 릴레이 비활성화 disable_sign_in_token_auth_user: 사용자의 이메일 토큰 인증 비활성화 disable_user: 사용자 비활성화 enable_custom_emoji: 커스텀 에모지 활성화 + enable_relay: 릴레이 활성화 enable_sign_in_token_auth_user: 사용자의 이메일 토큰 인증 활성화 enable_user: 사용자 활성화 memorialize_account: 고인의 계정으로 전환 @@ -244,6 +248,7 @@ ko: create_domain_block_html: "%{name} 님이 도메인 %{target}를 차단했습니다" create_email_domain_block_html: "%{name} 님이 이메일 도메인 %{target}를 차단했습니다" create_ip_block_html: "%{name} 님이 IP 규칙 %{target}을 만들었습니다" + create_relay_html: "%{name} 님이 릴레이 %{target}를 생성했습니다" create_unavailable_domain_html: "%{name} 님이 도메인 %{target}에 대한 전달을 중지했습니다" create_user_role_html: "%{name} 님이 %{target} 역할을 생성했습니다" demote_user_html: "%{name} 님이 사용자 %{target} 님을 강등했습니다" @@ -255,14 +260,17 @@ ko: destroy_email_domain_block_html: "%{name} 님이 이메일 도메인 %{target}을 차단 해제하였습니다" destroy_instance_html: "%{name} 님이 도메인 %{target}를 제거했습니다" destroy_ip_block_html: "%{name} 님이 IP 규칙 %{target}을 삭제하였습니다" + destroy_relay_html: "%{name} 님이 릴레이 %{target}를 삭제했습니다" destroy_status_html: "%{name} 님이 %{target} 님의 게시물을 삭제했습니다" destroy_unavailable_domain_html: "%{name} 님이 도메인 %{target}에 대한 전달을 재개" destroy_user_role_html: "%{name} 님이 %{target} 역할을 삭제했습니다" disable_2fa_user_html: "%{name} 님이 사용자 %{target} 님의 2단계 인증을 비활성화 했습니다" disable_custom_emoji_html: "%{name} 님이 에모지 %{target}를 비활성화했습니다" + disable_relay_html: "%{name} 님이 릴레이 %{target}를 비활성화했습니다" disable_sign_in_token_auth_user_html: "%{name} 님이 %{target} 님의 이메일 토큰 인증을 비활성화했습니다" disable_user_html: "%{name} 님이 사용자 %{target}의 로그인을 비활성화했습니다" enable_custom_emoji_html: "%{name} 님이 에모지 %{target}를 활성화했습니다" + enable_relay_html: "%{name} 님이 릴레이 %{target}를 활성화했습니다" enable_sign_in_token_auth_user_html: "%{name} 님이 %{target} 님의 이메일 토큰 인증을 활성화했습니다" enable_user_html: "%{name} 님이 사용자 %{target}의 로그인을 활성화했습니다" memorialize_account_html: "%{name} 님이 %{target}의 계정을 고인의 계정 페이지로 전환했습니다" diff --git a/config/locales/lt.yml b/config/locales/lt.yml index 8ba3bad070..3850e2e071 100644 --- a/config/locales/lt.yml +++ b/config/locales/lt.yml @@ -185,6 +185,7 @@ lt: create_domain_allow: Kurti domeno leidimą create_domain_block: Kurti domeno bloką create_ip_block: Kurti IP taisyklę + create_relay: Kurti perdavimą create_unavailable_domain: Kurti nepasiekiamą domeną create_user_role: Kurti vaidmenį demote_user: Pažeminti naudotoją @@ -194,13 +195,16 @@ lt: destroy_domain_block: Ištrinti domeno bloką destroy_instance: Išvalyti domeną destroy_ip_block: Ištrinti IP taisyklę + destroy_relay: Ištrinti perdavimą destroy_status: Ištrinti įrašą destroy_unavailable_domain: Ištrinti nepasiekiamą domeną destroy_user_role: Sunaikinti vaidmenį disable_2fa_user: Išjungti 2FA disable_custom_emoji: Išjungti pasirinktinį jaustuką + disable_relay: Išjungti perdavimą disable_user: Išjungti naudotoją enable_custom_emoji: Įjungti pasirinktinį jaustuką + enable_relay: Įjungti perdavimą enable_user: Įjungti naudotoją memorialize_account: Memorializuoti paskyrą promote_user: Paaukštinti naudotoją @@ -237,6 +241,7 @@ lt: create_domain_allow_html: "%{name} leido federaciją su domenu %{target}" create_domain_block_html: "%{name} užblokavo domeną %{target}" create_ip_block_html: "%{name} sukūrė taisyklę IP %{target}" + create_relay_html: "%{name} sukūrė perdavimą %{target}" create_unavailable_domain_html: "%{name} sustabdė tiekimą į domeną %{target}" create_user_role_html: "%{name} sukūrė %{target} vaidmenį" demote_user_html: "%{name} pažemino naudotoją %{target}" @@ -246,13 +251,16 @@ lt: destroy_domain_block_html: "%{name} atblokavo domeną %{target}" destroy_instance_html: "%{name} išvalė domeną %{target}" destroy_ip_block_html: "%{name} ištrynė taisyklę IP %{target}" + destroy_relay_html: "%{name} ištrynė perdavimą %{target}" destroy_status_html: "%{name} pašalino įrašą %{target}" destroy_unavailable_domain_html: "%{name} pratęsė tiekimą į domeną %{target}" destroy_user_role_html: "%{name} ištrynė %{target} vaidmenį" disable_2fa_user_html: "%{name} išjungė dviejų veiksnių reikalavimą naudotojui %{target}" disable_custom_emoji_html: "%{name} išjungė jaustuką %{target}" + disable_relay_html: "%{name} išjungė perdavimą %{target}" disable_user_html: "%{name} išjungė prisijungimą naudotojui %{target}" enable_custom_emoji_html: "%{name} įjungė jaustuką %{target}" + enable_relay_html: "%{name} įjungė perdavimą %{target}" enable_user_html: "%{name} įjungė prisijungimą naudotojui %{target}" memorialize_account_html: "%{name} pavertė %{target} paskyrą į atminimo puslapį" promote_user_html: "%{name} paaukštino naudotoją %{target}" diff --git a/config/locales/nn.yml b/config/locales/nn.yml index 9ec4f29f42..62b08f42ed 100644 --- a/config/locales/nn.yml +++ b/config/locales/nn.yml @@ -187,6 +187,7 @@ nn: create_domain_block: Opprett domene-blokk create_email_domain_block: Opprett blokkering av e-postdomene create_ip_block: Opprett IP-regel + create_relay: Opprett eit relé create_unavailable_domain: Opprett utilgjengeleg domene create_user_role: Opprett rolle demote_user: Degrader brukar @@ -198,14 +199,17 @@ nn: destroy_email_domain_block: Fjern blokkering av e-postdomene destroy_instance: Slett domene destroy_ip_block: Slett IP-regel + destroy_relay: Slett relé destroy_status: Slett status destroy_unavailable_domain: Slett utilgjengeleg domene destroy_user_role: Øydelegg rolle disable_2fa_user: Skruv av 2FA disable_custom_emoji: Skruv av tilpassa emoji + disable_relay: Skru av reléet disable_sign_in_token_auth_user: Slå av e-post-token-autentisering for brukar disable_user: Skruv av brukar enable_custom_emoji: Skruv på tilpassa emoji + enable_relay: Skru på reléet enable_sign_in_token_auth_user: Slå på e-post-token-autentisering for brukar enable_user: Skruv på brukar memorialize_account: Opprett minnekonto @@ -247,6 +251,7 @@ nn: create_domain_block_html: "%{name} blokkerte domenet %{target}" create_email_domain_block_html: "%{name} blokkerte e-postdomenet %{target}" create_ip_block_html: "%{name} oppretta ein regel for IP-en %{target}" + create_relay_html: "%{name} laga reléet %{target}" create_unavailable_domain_html: "%{name} stogga levering til domenet %{target}" create_user_role_html: "%{name} oppretta rolla %{target}" demote_user_html: "%{name} degraderte brukaren %{target}" @@ -258,14 +263,17 @@ nn: destroy_email_domain_block_html: "%{name} avblokkerte e-postdomenet %{target}" destroy_instance_html: "%{name} tømde domenet %{target}" destroy_ip_block_html: "%{name} sletta ein regel for IP-en %{target}" + destroy_relay_html: "%{name} sletta reléet %{target}" destroy_status_html: "%{name} fjerna innlegget frå %{target}" destroy_unavailable_domain_html: "%{name} tok opp att levering til domenet %{target}" destroy_user_role_html: "%{name} sletta rolla %{target}" disable_2fa_user_html: "%{name} tok vekk krav om tofaktorautentisering for brukaren %{target}" disable_custom_emoji_html: "%{name} deaktiverte emojien %{target}" + disable_relay_html: "%{name} skrudde av reléet %{target}" disable_sign_in_token_auth_user_html: "%{name} deaktiverte e-post-token-autentisering for %{target}" disable_user_html: "%{name} slo av innlogging for brukaren %{target}" enable_custom_emoji_html: "%{name} aktiverte emojien %{target}" + enable_relay_html: "%{name} skrudde på reléet %{target}" enable_sign_in_token_auth_user_html: "%{name} aktiverte e-post-token-autentisering for %{target}" enable_user_html: "%{name} aktiverte innlogging for brukaren %{target}" memorialize_account_html: "%{name} endret %{target}s konto til en minneside" @@ -1381,6 +1389,9 @@ nn: following_html: one: Du skal til å fylgja opp til %{count} brukarkonto frå %{filename} og slutta å fylgja alle andre. other: Du skal til å fylgja opp til %{count} brukarkontoar frå %{filename} og slutta å fylgja alle andre. + lists_html: + one: Du er i ferd med å erstatta listene dine med innhaldet i %{filename}. Opptil %{count} konto vil bli lagt til i dei nye listene. + other: Du er i ferd med å erstatta listene dine med innhaldet i %{filename}. Opptil %{count} kontoar vil bli lagt til i dei nye listene. muting_html: one: Du skal til å byta ut lista di over dempa brukarkontoar med opp til %{count} brukarkonto frå %{filename}. other: Du skal til å byta ut lista di over dempa brukarkontoar med opp til %{count} brukarkontoar frå %{filename}. diff --git a/config/locales/pt-BR.yml b/config/locales/pt-BR.yml index 8b2feb5193..0ff944e108 100644 --- a/config/locales/pt-BR.yml +++ b/config/locales/pt-BR.yml @@ -35,12 +35,12 @@ pt-BR: accounts: add_email_domain_block: Bloquear domínio de email approve: Aprovar - approved_msg: O registro de %{username} foi aprovado + approved_msg: Aprovado com sucesso o pedido de registro de %{username} are_you_sure: Você tem certeza? avatar: Imagem de perfil by_domain: Domínio change_email: - changed_msg: E-mail alterado! + changed_msg: E-mail alterado com sucesso! current_email: E-mail atual label: Alterar e-mail new_email: Novo e-mail @@ -187,6 +187,7 @@ pt-BR: create_domain_block: Bloquear domínio create_email_domain_block: Criar Bloqueio de Domínio de Email create_ip_block: Criar regra de IP + create_relay: Criar Retransmissão create_unavailable_domain: Criar domínio indisponível create_user_role: Criar cargo demote_user: Rebaixar usuário @@ -198,14 +199,17 @@ pt-BR: destroy_email_domain_block: Deletar bloqueio de domínio Email destroy_instance: Limpar domínio destroy_ip_block: Excluir regra de IP + destroy_relay: Excluir Retransmissão destroy_status: Excluir publicação destroy_unavailable_domain: Excluir domínio indisponível destroy_user_role: Destruir cargo disable_2fa_user: Desativar autenticação de dois fatores disable_custom_emoji: Desativar emoji personalizado + disable_relay: Desativar Retransmissão disable_sign_in_token_auth_user: Desativar autenticação via Token de Email para Usuário disable_user: Desativar usuário enable_custom_emoji: Ativar emoji personalizado + enable_relay: Ativar Retransmissão enable_sign_in_token_auth_user: Ativar autenticação via Token de Email para Usuário enable_user: Ativar usuário memorialize_account: Converter conta em memorial @@ -247,6 +251,7 @@ pt-BR: create_domain_block_html: "%{name} bloqueou o domínio %{target}" create_email_domain_block_html: "%{name} bloqueou o domínio de e-mail %{target}" create_ip_block_html: "%{name} criou a regra para o IP %{target}" + create_relay_html: "%{name} criou uma retransmissão %{target}" create_unavailable_domain_html: "%{name} parou a entrega ao domínio %{target}" create_user_role_html: "%{name} criou o cargo %{target}" demote_user_html: "%{name} rebaixou o usuário %{target}" @@ -258,14 +263,17 @@ pt-BR: destroy_email_domain_block_html: "%{name} desbloqueou o domínio de e-mail %{target}" destroy_instance_html: "%{name} limpou o domínio %{target}" destroy_ip_block_html: "%{name} excluiu a regra para o IP %{target}" + destroy_relay_html: "%{name} excluiu uma retransmissão %{target}" destroy_status_html: "%{name} removeu a publicação de %{target}" destroy_unavailable_domain_html: "%{name} retomou a entrega ao domínio %{target}" destroy_user_role_html: "%{name} excluiu o cargo %{target}" disable_2fa_user_html: "%{name} desativou a exigência da autenticação de dois fatores para o usuário %{target}" disable_custom_emoji_html: "%{name} desativou o emoji %{target}" + disable_relay_html: "%{name} desativou uma retransmissão %{target}" disable_sign_in_token_auth_user_html: "%{name} desativou a autenticação via token por e-mail para %{target}" disable_user_html: "%{name} desativou o login para %{target}" enable_custom_emoji_html: "%{name} ativou o emoji %{target}" + enable_relay_html: "%{name} ativou uma retransmissão %{target}" enable_sign_in_token_auth_user_html: "%{name} ativou a autenticação via token por e-mail para %{target}" enable_user_html: "%{name} ativou o login para %{target}" memorialize_account_html: "%{name} transformou a conta de %{target} em um memorial" @@ -1368,6 +1376,10 @@ pt-BR: merge_long: Manter os registros existentes e adicionar novos overwrite: Sobrescrever overwrite_long: Substituir os registros atuais com os novos + overwrite_preambles: + bookmarks_html: + one: Você está prestes a substituir seus salvos por até %{count} publicação de %{filename}. + other: Você está prestes a substituir seus salvos por até %{count} publicações de %{filename}. preface: Você pode importar dados que você exportou de outro servidor, como a lista de pessoas que você segue ou bloqueou. recent_imports: Importações recentes states: diff --git a/config/locales/ru.yml b/config/locales/ru.yml index 831f68b24b..8a84f22115 100644 --- a/config/locales/ru.yml +++ b/config/locales/ru.yml @@ -179,104 +179,112 @@ ru: whitelisted: В белом списке action_logs: action_types: - approve_appeal: Одобрить обжалование - approve_user: Утвердить + approve_appeal: Одобрение обжалований + approve_user: Утверждение регистраций assigned_to_self_report: Присвоение жалоб - change_email_user: Сменить e-mail для пользователя - change_role_user: Изменить роль пользователя + change_email_user: Смена e-mail пользователей + change_role_user: Смена ролей пользователей confirm_user: Подтверждение пользователей create_account_warning: Выдача предупреждения create_announcement: Создание объявлений - create_canonical_email_block: Создать блок электронной почты + create_canonical_email_block: Создание блокировок e-mail create_custom_emoji: Добавление эмодзи create_domain_allow: Разрешение доменов create_domain_block: Блокировка доменов - create_email_domain_block: Создать блок домена электронной почты + create_email_domain_block: Создание доменных блокировок e-mail create_ip_block: Создание правил для IP-адресов + create_relay: Создание ретранслятора create_unavailable_domain: Добавление домена в список недоступных - create_user_role: Создать роль + create_user_role: Создание ролей demote_user: Разжалование пользователей destroy_announcement: Удаление объявлений - destroy_canonical_email_block: Удалить блок электронной почты + destroy_canonical_email_block: Удаление блокировок e-mail destroy_custom_emoji: Удаление эмодзи destroy_domain_allow: Отзыв разрешений для доменов destroy_domain_block: Разблокировка доменов - destroy_email_domain_block: Удалить блок домена электронной почты + destroy_email_domain_block: Удаление доменных блокировок e-mail destroy_instance: Очистить домен destroy_ip_block: Удаление правил для IP-адресов + destroy_relay: Удаление ретранслятора destroy_status: Удаление постов destroy_unavailable_domain: Исключение доменов из списка недоступных - destroy_user_role: Удалить роль + destroy_user_role: Удаление ролей disable_2fa_user: Отключение 2FA disable_custom_emoji: Отключение эмодзи - disable_sign_in_token_auth_user: Отключить аутентификацию пользователя с помощью токена электронной почты + disable_relay: Отключение ретранслятора + disable_sign_in_token_auth_user: Отключение аутентификации по e-mail кодам disable_user: Заморозка пользователей enable_custom_emoji: Включение эмодзи - enable_sign_in_token_auth_user: Включить аутентификацию пользователя с помощью токена электронной почты + enable_relay: Включение ретранслятора + enable_sign_in_token_auth_user: Включение аутентификации по e-mail кодам enable_user: Разморозка пользователей memorialize_account: Присвоение пользователям статуса «мемориала» promote_user: Повышение пользователей - reject_appeal: Отклонить обжалование - reject_user: Отклонить + reject_appeal: Отклонение обжалований + reject_user: Отклонение регистраций remove_avatar_user: Удаление аватаров reopen_report: Возобновление жалоб - resend_user: Повторно отправить письмо с подтверждением + resend_user: Повторная отправка писем с подтверждением reset_password_user: Сброс пароля пользователей resolve_report: Отметка жалоб «решёнными» sensitive_account: Присвоение пользователям отметки «деликатного содержания» silence_account: Скрытие пользователей suspend_account: Блокировка пользователей unassigned_report: Снятие жалоб - unblock_email_account: Разблокировать e-mail адрес + unblock_email_account: Разблокировка e-mail адресов unsensitive_account: Снятие с пользователей отметки «деликатного содержания» unsilence_account: Отмена скрытия пользователей unsuspend_account: Разблокировка пользователей update_announcement: Обновление объявлений update_custom_emoji: Обновление эмодзи update_domain_block: Изменение блокировки домена - update_ip_block: Обновить правило для IP-адреса - update_report: Обновить рапорт + update_ip_block: Обновление правил для IP-адресов + update_report: Изменение жалоб update_status: Изменение постов - update_user_role: Обновить роль + update_user_role: Изменение ролей actions: - approve_appeal_html: "%{name} одобрил апелляцию на умеренное решение от %{target}" + approve_appeal_html: "%{name} одобрил(а) обжалование действий модерации от %{target}" approve_user_html: "%{name} утвердил(а) регистрацию %{target}" assigned_to_self_report_html: "%{name} назначил(а) себя для решения жалобы %{target}" - change_email_user_html: "%{name} изменил адрес электронной почты пользователя %{target}" + change_email_user_html: "%{name} cменил(а) e-mail адрес пользователя %{target}" change_role_user_html: "%{name} изменил(а) роль %{target}" - confirm_user_html: "%{name} подтвержденный адрес электронной почты пользователя %{target}" + confirm_user_html: "%{name} подтвердил(а) e-mail адрес пользователя %{target}" create_account_warning_html: "%{name} выдал(а) предупреждение %{target}" create_announcement_html: "%{name} создал(а) новое объявление %{target}" - create_canonical_email_block_html: "%{name} заблокировал письмо с хэшем %{target}" + create_canonical_email_block_html: "%{name} заблокировал(а) e-mail с хешем %{target}" create_custom_emoji_html: "%{name} загрузил(а) новый эмодзи %{target}" create_domain_allow_html: "%{name} разрешил(а) федерацию с доменом %{target}" create_domain_block_html: "%{name} заблокировал(а) домен %{target}" - create_email_domain_block_html: "%{name} заблокированный почтовый домен %{target}" + create_email_domain_block_html: "%{name} заблокировал(а) e-mail домен %{target}" create_ip_block_html: "%{name} создал(а) правило для IP %{target}" + create_relay_html: "%{name} создал(а) ретранслятор %{target}" create_unavailable_domain_html: "%{name} приостановил доставку на узел %{target}" create_user_role_html: "%{name} создал(а) роль %{target}" demote_user_html: "%{name} разжаловал(а) пользователя %{target}" destroy_announcement_html: "%{name} удалил(а) объявление %{target}" - destroy_canonical_email_block_html: "%{name} разблокированное письмо с хэшем %{target}" + destroy_canonical_email_block_html: "%{name} снял(а) блокировку e-mail с хэшем %{target}" destroy_custom_emoji_html: "%{name} удалил(а) эмодзи %{target}" destroy_domain_allow_html: "%{name} запретил(а) федерацию с доменом %{target}" destroy_domain_block_html: "%{name} снял(а) блокировку с домена %{target}" - destroy_email_domain_block_html: "%{name} разблокированный почтовый домен %{target}" + destroy_email_domain_block_html: "%{name} снял(а) блокировку с e-mail домена %{target}" destroy_instance_html: "%{name} очистил(а) данные для домена %{target}" destroy_ip_block_html: "%{name} удалил(а) правило для IP %{target}" + destroy_relay_html: "%{name} удалил(а) ретранслятор %{target}" destroy_status_html: "%{name} удалил(а) пост пользователя %{target}" destroy_unavailable_domain_html: "%{name} возобновил доставку на узел %{target}" destroy_user_role_html: "%{name} удалил(а) роль %{target}" disable_2fa_user_html: "%{name} отключил(а) требование двухэтапной авторизации для пользователя %{target}" disable_custom_emoji_html: "%{name} отключил(а) эмодзи %{target}" - disable_sign_in_token_auth_user_html: "%{name} отключил аутентификацию по маркеру электронной почты для %{target}" + disable_relay_html: "%{name} отключил(а) ретранслятор %{target}" + disable_sign_in_token_auth_user_html: "%{name} отключил(а) аутентификацию по e-mail кодам для %{target}" disable_user_html: "%{name} заморозил(а) пользователя %{target}" enable_custom_emoji_html: "%{name} включил(а) эмодзи %{target}" - enable_sign_in_token_auth_user_html: "%{name} включил аутентификацию с помощью маркера электронной почты для %{target}" + enable_relay_html: "%{name} включил(а) ретранслятор %{target}" + enable_sign_in_token_auth_user_html: "%{name} включил(а) аутентификацию по e-mail кодам для %{target}" enable_user_html: "%{name} разморозил(а) пользователя %{target}" memorialize_account_html: "%{name} перевел(а) учётную запись пользователя %{target} в статус памятника" promote_user_html: "%{name} повысил(а) пользователя %{target}" - reject_appeal_html: "%{name} отклонил апелляцию на модерацию от %{target}" + reject_appeal_html: "%{name} отклонил(а) обжалование действий модерации от %{target}" reject_user_html: "%{name} отклонил(а) регистрацию %{target}" remove_avatar_user_html: "%{name} убрал(а) аватарку пользователя %{target}" reopen_report_html: "%{name} повторно открыл(а) жалобу %{target}" @@ -295,7 +303,7 @@ ru: update_custom_emoji_html: "%{name} обновил(а) эмодзи %{target}" update_domain_block_html: "%{name} обновил(а) блокировку домена для %{target}" update_ip_block_html: "%{name} изменил(а) правило для IP %{target}" - update_report_html: "%{name} обновленный отчет %{target}" + update_report_html: "%{name} изменил(а) жалобу %{target}" update_status_html: "%{name} изменил(а) пост пользователя %{target}" update_user_role_html: "%{name} изменил(а) роль %{target}" deleted_account: удалённая учётная запись diff --git a/config/locales/simple_form.ko.yml b/config/locales/simple_form.ko.yml index b2ebf5666d..962f062534 100644 --- a/config/locales/simple_form.ko.yml +++ b/config/locales/simple_form.ko.yml @@ -46,7 +46,7 @@ ko: current_password: 보안을 위해 현재 계정의 암호를 입력해주세요 current_username: 확인을 위해, 현재 계정의 사용자명을 입력해주세요 digest: 오랫동안 활동하지 않았을 때 받은 멘션들에 대한 요약 받기 - email: 확인용 이메일을 보냈습니다. + email: 확인용 이메일을 보내게 됩니다 header: WEBP, PNG, GIF 혹은 JPG. 최대 %{size}. %{dimensions}px로 축소됨 inbox_url: 사용 할 릴레이 서버의 프론트페이지에서 URL을 복사합니다 irreversible: 필터링 된 게시물은 나중에 필터가 사라지더라도 돌아오지 않게 됩니다 diff --git a/config/locales/simple_form.lt.yml b/config/locales/simple_form.lt.yml index d9204efaaa..77482d8012 100644 --- a/config/locales/simple_form.lt.yml +++ b/config/locales/simple_form.lt.yml @@ -10,6 +10,7 @@ lt: indexable: Tavo vieši įrašai gali būti rodomi Mastodon paieškos rezultatuose. Žmonės, kurie bendravo su tavo įrašais, gali jų ieškoti nepriklausomai nuo to. note: 'Gali @paminėti kitus žmones arba #saitažodžius.' show_collections: Žmonės galės peržiūrėti tavo sekimus ir sekėjus. Žmonės, kuriuos seki, matys, kad juos seki, nepaisant to. + unlocked: Žmonės galės jus sekti nepaprašę patvirtinimo. Panaikinkite žymėjimą, jei norite peržiūrėti sekimo prašymus ir pasirinkti, ar priimti, ar atmesti naujus sekėjus. account_alias: acct: Nurodyk paskyros, iš kurios nori perkelti, naudotojo vardą@domeną account_migration: diff --git a/config/locales/simple_form.nl.yml b/config/locales/simple_form.nl.yml index 5318059f4a..2bb31aa0f9 100644 --- a/config/locales/simple_form.nl.yml +++ b/config/locales/simple_form.nl.yml @@ -3,7 +3,7 @@ nl: simple_form: hints: account: - attribution_domains_as_text: Eén per regel. Beschermt tegen valse toeschrijvingen. + attribution_domains_as_text: Eén per regel. Beschermt tegen ongeldige attributies. discoverable: Jouw openbare berichten kunnen worden uitgelicht op verschillende plekken binnen Mastodon en jouw account kan worden aanbevolen aan andere gebruikers. display_name: Jouw volledige naam of een leuke bijnaam. fields: Jouw website, persoonlijke voornaamwoorden, leeftijd, alles wat je maar kwijt wilt. diff --git a/config/locales/simple_form.nn.yml b/config/locales/simple_form.nn.yml index 008af2c5ac..46b7af4bdb 100644 --- a/config/locales/simple_form.nn.yml +++ b/config/locales/simple_form.nn.yml @@ -10,6 +10,7 @@ nn: indexable: Dei offentlege innlegga dine kan dukka opp i søkjeresultat på Mastodon. Folk som har reagert på oinnlegga dine kan uansett søkja gjennom dei. note: 'Du kan @nemne folk eller #emneknaggar.' show_collections: Andre kan sjå kven du fylgjer og kven som fylgjer deg. Dei du fylgjer kan alltid sjå at du fylgjer dei. + unlocked: Alle kan fylgja deg utan å måtta be om det. Vel bort dersom du vil gå gjennom førespurnader om å fylgja deg og seia ja eller nei til kvar av dei. account_alias: acct: Angi brukarnamn@domene til brukaren du ynskjer å flytta frå account_migration: diff --git a/config/locales/simple_form.pl.yml b/config/locales/simple_form.pl.yml index 4fba45098d..c5ff55c15d 100644 --- a/config/locales/simple_form.pl.yml +++ b/config/locales/simple_form.pl.yml @@ -10,6 +10,7 @@ pl: indexable: Twoje publiczne wpisy mogą pojawiać się w wynikach wyszukiwania w Mastodonie. Użytkownicy, którzy wchodzili w interakcje z twoimi wpisami będą mogli je znaleźć niezależnie od tego ustawienia. note: 'Możesz @wspomnieć użytkowników albo #hasztagi.' show_collections: Twoja lista obserwowanych i obserwujących będzie widoczna dla wszystkich. Użytkownicy których obserwujesz będą jednak o tym wiedzieli. + unlocked: Inni użytkownicy będą mogli cię obserwować bez proszenia o zgodę. Odznacz, jeżeli chcesz aprobować obserwujących ręcznie po przejrzeniu próśb o obserwowanie. account_alias: acct: Określ nazwę@domenę konta z którego chcesz się przenieść account_migration: diff --git a/config/locales/simple_form.ru.yml b/config/locales/simple_form.ru.yml index d8822d35b9..37626ff9fd 100644 --- a/config/locales/simple_form.ru.yml +++ b/config/locales/simple_form.ru.yml @@ -10,6 +10,7 @@ ru: indexable: Ваши публичные сообщения могут появляться в результатах поиска на Mastodon. Люди, которые взаимодействовали с вашими сообщениями, могут искать их независимо от этого. note: 'Вы можете @упоминать других людей или #хэштеги.' show_collections: Люди смогут просматривать список ваших подписок и подписчиков. Люди, за которыми вы следуете, будут видеть, что вы подписаны на них, несмотря ни на что. + unlocked: Люди смогут подписываться на вас, не запрашивая подтверждения. Снимите флажок, если вы хотите просматривать запросы на подписку и выбирать, принимать или отклонять новых подписчиков. account_alias: acct: Укажите имя_пользователя@домен учётной записи, с которой вы собираетесь мигрировать account_migration: diff --git a/config/locales/simple_form.sv.yml b/config/locales/simple_form.sv.yml index b8303e2945..72c3f000f6 100644 --- a/config/locales/simple_form.sv.yml +++ b/config/locales/simple_form.sv.yml @@ -10,6 +10,7 @@ sv: indexable: Dina offentliga inlägg kan visas i sökresultat på Mastodon. Personer som har interagerat med dina inlägg kan söka dem oavsett. note: 'Du kan @nämna andra personer eller #hashtaggar.' show_collections: Andra kan se vem du följer och vem som följer dig. De du följer kan alltid se att du följer dem. + unlocked: Andra kommer att kunna följa dig utan att begära godkännande. Avmarkera om du vill granska följeslagare och välja om du vill acceptera eller avvisa nya följare. account_alias: acct: Ange användarnamn@domän för kontot som du vill flytta från account_migration: diff --git a/config/locales/sq.yml b/config/locales/sq.yml index 6cff74fb50..e5becbd916 100644 --- a/config/locales/sq.yml +++ b/config/locales/sq.yml @@ -187,6 +187,7 @@ sq: create_domain_block: Krijo Bllokim Përkatësie create_email_domain_block: Krijoni Bllokim Përkatësie Email-esh create_ip_block: Krijoni Rregull IP + create_relay: Krijoni Rele create_unavailable_domain: Krijo Përkatësi të Papërdorshme create_user_role: Krijoni Rol demote_user: Zhgradoje Përdoruesin @@ -198,14 +199,17 @@ sq: destroy_email_domain_block: Fshini Bllokim Përkatësie Email-esh destroy_instance: Spastroje Përkatësinë destroy_ip_block: Fshini Rregull IP + destroy_relay: Fshije Relenë destroy_status: Fshi Gjendje destroy_unavailable_domain: Fshi Përkatësi të Papërdorshme destroy_user_role: Asgjësoje Rolin disable_2fa_user: Çaktivizo 2FA-në disable_custom_emoji: Çaktivizo Emotikon Vetjak + disable_relay: Çaktivizoje Relenë disable_sign_in_token_auth_user: Çaktivizoni për Përdoruesin Mirëfilltësim Me Token Email-i disable_user: Çaktivizo Përdorues enable_custom_emoji: Aktivizo Emotikon Vetjak + enable_relay: Aktivizoje Relenë enable_sign_in_token_auth_user: Aktivizoni për Përdoruesin Mirëfilltësim Me Token Email-i enable_user: Aktivizo Përdorues memorialize_account: Bëje Llogari Përkujtimore @@ -247,6 +251,7 @@ sq: create_domain_block_html: "%{name} bllokoi përkatësinë %{target}" create_email_domain_block_html: "%{name} bllokoi përkatësinë email %{target}" create_ip_block_html: "%{name} krijoi rregull për IP-në %{target}" + create_relay_html: "%{name} krijoi një rele %{target}" create_unavailable_domain_html: "%{name} ndali dërgimin drejt përkatësisë %{target}" create_user_role_html: "%{name} krijoi rolin %{target}" demote_user_html: "%{name} zhgradoi përdoruesin %{target}" @@ -258,14 +263,17 @@ sq: destroy_email_domain_block_html: "%{name} zhbllokoi përkatësi email %{target}" destroy_instance_html: "%{name} spastroi përkatësinë %{target}" destroy_ip_block_html: "%{name} fshiu rregull për IP-në %{target}" + destroy_relay_html: "%{name} fshiu relenë %{target}" destroy_status_html: "%{name} hoqi gjendje nga %{target}" destroy_unavailable_domain_html: "%{name} rinisi dërgimin drejt përkatësisë %{target}" destroy_user_role_html: "%{name} fshiu rolin %{target}" disable_2fa_user_html: "%{name} çaktivizoi domosdoshmërinë për dyfaktorësh për përdoruesin %{target}" disable_custom_emoji_html: "%{name} çaktivizoi emoxhin %{target}" + disable_relay_html: "%{name} çaktivizoi relenë %{target}" disable_sign_in_token_auth_user_html: "%{name} çaktivizoi mirëfilltësim me token email për %{target}" disable_user_html: "%{name} çaktivizoi hyrje për përdoruesin %{target}" enable_custom_emoji_html: "%{name} aktivizoi emoxhin %{target}" + enable_relay_html: "%{name} aktivizoi relenë %{target}" enable_sign_in_token_auth_user_html: "%{name} aktivizoi mirëfilltësim me token email për %{target}" enable_user_html: "%{name} aktivizoi hyrje për përdoruesin %{target}" memorialize_account_html: "%{name} e shndërroi llogarinë e %{target} në një faqe përkujtimore" diff --git a/config/locales/sv.yml b/config/locales/sv.yml index b2ec21b82e..c41795a168 100644 --- a/config/locales/sv.yml +++ b/config/locales/sv.yml @@ -187,6 +187,7 @@ sv: create_domain_block: Skapa blockerad domän create_email_domain_block: Skapa E-post domän block create_ip_block: Skapa IP-regel + create_relay: Skapa ombud create_unavailable_domain: Skapa otillgänglig domän create_user_role: Skapa roll demote_user: Degradera användare @@ -198,14 +199,17 @@ sv: destroy_email_domain_block: Ta bort E-post domän block destroy_instance: Rensa domänen destroy_ip_block: Radera IP-regel + destroy_relay: Radera ombud destroy_status: Radera inlägg destroy_unavailable_domain: Ta bort otillgänglig domän destroy_user_role: Förstör roll disable_2fa_user: Inaktivera 2FA disable_custom_emoji: Inaktivera egna emojis + disable_relay: Inaktivera ombud disable_sign_in_token_auth_user: Inaktivera autentisering med pollett via e-post för användare disable_user: Inaktivera användare enable_custom_emoji: Aktivera egna emojis + enable_relay: Aktivera ombud enable_sign_in_token_auth_user: Aktivera autentisering med pollett via e-post för användare enable_user: Aktivera användare memorialize_account: Minnesmärk konto @@ -247,6 +251,7 @@ sv: create_domain_block_html: "%{name} blockerade domänen %{target}" create_email_domain_block_html: "%{name} blockerade e-post domänet%{target}" create_ip_block_html: "%{name} skapade regel för IP %{target}" + create_relay_html: "%{name} skapade ombudet %{target}" create_unavailable_domain_html: "%{name} stoppade leverans till domänen %{target}" create_user_role_html: "%{name} skapade rollen %{target}" demote_user_html: "%{name} nedgraderade användare %{target}" @@ -258,14 +263,17 @@ sv: destroy_email_domain_block_html: "%{name} avblockerade e-post domänet %{target}" destroy_instance_html: "%{name} rensade domän %{target}" destroy_ip_block_html: "%{name} tog bort regel för IP %{target}" + destroy_relay_html: "%{name} tog bort ombudet %{target}" destroy_status_html: "%{name} tog bort inlägget av %{target}" destroy_unavailable_domain_html: "%{name} återupptog leverans till domänen %{target}" destroy_user_role_html: "%{name} raderade rollen %{target}" disable_2fa_user_html: "%{name} inaktiverade tvåfaktorsautentiseringskrav för användaren %{target}" disable_custom_emoji_html: "%{name} inaktiverade emoji %{target}" + disable_relay_html: "%{name} inaktiverade ombudet %{target}" disable_sign_in_token_auth_user_html: "%{name} inaktiverade e-posttokenautentisering för %{target}" disable_user_html: "%{name} stängde av inloggning för användaren %{target}" enable_custom_emoji_html: "%{name} aktiverade emoji %{target}" + enable_relay_html: "%{name} aktiverat ombudet %{target}" enable_sign_in_token_auth_user_html: "%{name} aktiverade e-posttokenautentisering för %{target}" enable_user_html: "%{name} aktiverade inloggning för användaren %{target}" memorialize_account_html: "%{name} gjorde %{target}s konto till en minnessida" @@ -571,7 +579,7 @@ sv: relationships: title: "%{acct}s relationer" relays: - add_new: Lägg till nytt relä + add_new: Lägg till nytt ombud delete: Radera description_html: Ett federeringsombud är en mellanliggande server som utbyter höga antal offentliga inlägg mellan servrar som prenumererar på och publicerar till det. Det kan hjälpa små och medelstora servrar upptäcka innehåll från fediversumet, vilket annars skulle kräva att lokala användare manuellt följer personer på fjärrservrar. disable: Inaktivera @@ -582,10 +590,10 @@ sv: inbox_url: Ombuds-URL pending: Väntar på ombudets godkännande save_and_enable: Spara och aktivera - setup: Konfigurera en relä-anslutning - signatures_not_enabled: Ombud fungerar inte korrekt medan säkert läge eller begränsat federeringsläge är aktiverade + setup: Konfigurera ett ombud + signatures_not_enabled: Ombud fungerar inte korrekt om säkert läge eller begränsat federeringsläge är aktiverade status: Status - title: Relä + title: Ombud report_notes: created_msg: Anmälningsanteckning har skapats! destroyed_msg: Anmälningsanteckning har raderats! diff --git a/config/locales/tr.yml b/config/locales/tr.yml index 942ee2fbf2..88636ef21b 100644 --- a/config/locales/tr.yml +++ b/config/locales/tr.yml @@ -187,6 +187,7 @@ tr: create_domain_block: Engellenen Alan Adı Oluştur create_email_domain_block: E-Posta Alan Adı Engeli Oluştur create_ip_block: IP kuralı oluştur + create_relay: Aktarıcı Oluştur create_unavailable_domain: Mevcut Olmayan Alan Adı Oluştur create_user_role: Rol Oluştur demote_user: Kullanıcıyı Düşür @@ -198,14 +199,17 @@ tr: destroy_email_domain_block: E-posta Alan Adı Engelini Sil destroy_instance: Alan adını temizle destroy_ip_block: IP kuralını sil + destroy_relay: Aktarıcı Sil destroy_status: Durumu Sil destroy_unavailable_domain: Mevcut Olmayan Alan Adı Sil destroy_user_role: Rolü Kaldır disable_2fa_user: 2AD Kapat disable_custom_emoji: Özel İfadeyi Devre Dışı Bırak + disable_relay: Aktarıcıyı Devre Dışı Bırak disable_sign_in_token_auth_user: Kullanıcı için E-posta Token Doğrulamayı Devre Dışı Bırak disable_user: Kullanıcıyı Devre Dışı Bırak enable_custom_emoji: Özel İfadeyi Etkinleştir + enable_relay: Aktarıcıyı Etkinleştir enable_sign_in_token_auth_user: Kullanıcı için E-posta Token Doğrulamayı Etkinleştir enable_user: Kullanıcıyı Etkinleştir memorialize_account: Hesabı Anıtlaştır @@ -247,6 +251,7 @@ tr: create_domain_block_html: "%{name}, %{target} alan adını engelledi" create_email_domain_block_html: "%{name}, %{target} e-posta alan adını engelledi" create_ip_block_html: "%{name}, %{target} IP adresi için kural oluşturdu" + create_relay_html: "%{name}, %{target} aktarıcısını oluşturdu" create_unavailable_domain_html: "%{name}, %{target} alan adına teslimatı durdurdu" create_user_role_html: "%{name}, %{target} rolünü oluşturdu" demote_user_html: "%{name}, %{target} kullanıcısını düşürdü" @@ -258,14 +263,17 @@ tr: destroy_email_domain_block_html: "%{name}, %{target} e-posta alan adı engelini kaldırdı" destroy_instance_html: "%{name}, %{target} alan adını temizledi" destroy_ip_block_html: "%{name}, %{target} IP adresi kuralını sildi" + destroy_relay_html: "%{name}, %{target} aktarıcısını sildi" destroy_status_html: "%{name}, %{target} kullanıcısının gönderisini kaldırdı" destroy_unavailable_domain_html: "%{name}, %{target} alan adına teslimatı sürdürdü" destroy_user_role_html: "%{name}, %{target} rolünü sildi" disable_2fa_user_html: "%{name}, %{target} kullanıcısının iki aşamalı doğrulama gereksinimini kapattı" disable_custom_emoji_html: "%{name}, %{target} emojisini devre dışı bıraktı" + disable_relay_html: "%{name}, %{target} aktarıcısını devre dışı bıraktı" disable_sign_in_token_auth_user_html: "%{name}, %{target} için e-posta token doğrulamayı devre dışı bıraktı" disable_user_html: "%{name}, %{target} kullanıcısı için oturum açmayı devre dışı bıraktı" enable_custom_emoji_html: "%{name}, %{target} emojisini etkinleştirdi" + enable_relay_html: "%{name}, %{target} aktarıcısını etkinleştirdi" enable_sign_in_token_auth_user_html: "%{name}, %{target} için e-posta token doğrulamayı etkinleştirdi" enable_user_html: "%{name}, %{target} kullanıcısı için oturum açmayı etkinleştirdi" memorialize_account_html: "%{name}, %{target} kullanıcısının hesabını bir anıt sayfaya dönüştürdü" diff --git a/config/locales/vi.yml b/config/locales/vi.yml index 172ce55a3d..1d04f796f8 100644 --- a/config/locales/vi.yml +++ b/config/locales/vi.yml @@ -184,6 +184,7 @@ vi: create_domain_block: Chặn máy chủ create_email_domain_block: Chặn tên miền email create_ip_block: Chặn IP + create_relay: Tạo relay create_unavailable_domain: Bỏ liên hợp create_user_role: Tạo vai trò demote_user: Hạ vai trò @@ -195,14 +196,17 @@ vi: destroy_email_domain_block: Bỏ chặn tên miền email destroy_instance: Thanh trừng máy chủ destroy_ip_block: Bỏ chặn IP + destroy_relay: Xóa relay destroy_status: Xóa tút destroy_unavailable_domain: Cho phép liên hợp destroy_user_role: Xóa vai trò disable_2fa_user: Vô hiệu hóa 2FA disable_custom_emoji: Vô hiệu hóa emoji + disable_relay: Tắt relay disable_sign_in_token_auth_user: Tắt xác minh bằng email cho người dùng disable_user: Vô hiệu hóa đăng nhập enable_custom_emoji: Cho phép emoji + enable_relay: Bật relay enable_sign_in_token_auth_user: Bật xác minh bằng email cho người dùng enable_user: Cho phép đăng nhập memorialize_account: Gán tưởng niệm @@ -244,6 +248,7 @@ vi: create_domain_block_html: "%{name} đã chặn máy chủ %{target}" create_email_domain_block_html: "%{name} đã chặn tên miền email %{target}" create_ip_block_html: "%{name} đã chặn IP %{target}" + create_relay_html: "%{name} đã tạo relay %{target}" create_unavailable_domain_html: "%{name} đã bỏ liên hợp với máy chủ %{target}" create_user_role_html: "%{name} đã tạo vai trò %{target}" demote_user_html: "%{name} đã hạ vai trò của %{target}" @@ -255,14 +260,17 @@ vi: destroy_email_domain_block_html: "%{name} đã bỏ chặn email %{target}" destroy_instance_html: "%{name} đã thanh trừng máy chủ %{target}" destroy_ip_block_html: "%{name} đã bỏ chặn IP %{target}" + destroy_relay_html: "%{name} đã xóa relay %{target}" destroy_status_html: "%{name} đã xóa tút của %{target}" destroy_unavailable_domain_html: "%{name} tiếp tục liên hợp với máy chủ %{target}" destroy_user_role_html: "%{name} đã xóa vai trò %{target}" disable_2fa_user_html: "%{name} đã vô hiệu hóa xác minh hai bước của %{target}" disable_custom_emoji_html: "%{name} đã ẩn emoji %{target}" + disable_relay_html: "%{name} đã tắt relay %{target}" disable_sign_in_token_auth_user_html: "%{name} đã tắt xác minh email của %{target}" disable_user_html: "%{name} đã vô hiệu hóa đăng nhập %{target}" enable_custom_emoji_html: "%{name} đã cho phép emoji %{target}" + enable_relay_html: "%{name} đã bật relay %{target}" enable_sign_in_token_auth_user_html: "%{name} đã bật xác minh email của %{target}" enable_user_html: "%{name} đã bỏ vô hiệu hóa đăng nhập %{target}" memorialize_account_html: "%{name} đã biến tài khoản %{target} thành một trang tưởng niệm" diff --git a/config/locales/zh-CN.yml b/config/locales/zh-CN.yml index 209683e21c..36d316649c 100644 --- a/config/locales/zh-CN.yml +++ b/config/locales/zh-CN.yml @@ -184,6 +184,7 @@ zh-CN: create_domain_block: 封禁新域名 create_email_domain_block: 封禁新的邮箱域名 create_ip_block: 新建 IP 规则 + create_relay: 创建中继站 create_unavailable_domain: 创建不可用域名 create_user_role: 创建角色 demote_user: 给用户降职 @@ -195,14 +196,17 @@ zh-CN: destroy_email_domain_block: 解除邮箱域名封禁 destroy_instance: 删除实例 destroy_ip_block: 删除 IP 规则 + destroy_relay: 删除中继站 destroy_status: 删除嘟文 destroy_unavailable_domain: 删除不可用域名 destroy_user_role: 销毁角色 disable_2fa_user: 停用双因素认证 disable_custom_emoji: 禁用自定义表情符号 + disable_relay: 禁用中继站 disable_sign_in_token_auth_user: 为用户禁用邮件令牌身份验证 disable_user: 禁用用户 enable_custom_emoji: 启用自定义表情符号 + enable_relay: 启用中继站 enable_sign_in_token_auth_user: 为用户启用邮件令牌身份验证 enable_user: 启用用户 memorialize_account: 将账户设为追悼模式 @@ -244,6 +248,7 @@ zh-CN: create_domain_block_html: "%{name} 屏蔽了域名 %{target}" create_email_domain_block_html: "%{name} 封禁了邮箱域名 %{target}" create_ip_block_html: "%{name} 为 IP %{target} 创建了规则" + create_relay_html: "%{name} 添加了中继站 %{target}" create_unavailable_domain_html: "%{name} 停止了向域名 %{target} 的投递" create_user_role_html: "%{name} 创建了 %{target} 角色" demote_user_html: "%{name} 对用户 %{target} 进行了降任操作" @@ -255,14 +260,17 @@ zh-CN: destroy_email_domain_block_html: "%{name} 解封了邮箱域名 %{target}" destroy_instance_html: "%{name} 删除了实例 %{target}" destroy_ip_block_html: "%{name} 删除了 IP %{target} 的规则" + destroy_relay_html: "%{name} 删除了中继站 %{target}" destroy_status_html: "%{name} 删除了 %{target} 的嘟文" destroy_unavailable_domain_html: "%{name} 恢复了向域名 %{target} 的投递" destroy_user_role_html: "%{name} 删除了 %{target} 角色" disable_2fa_user_html: "%{name} 停用了用户 %{target} 的双因素认证" disable_custom_emoji_html: "%{name} 停用了自定义表情 %{target}" + disable_relay_html: "%{name} 停用了中继站 %{target}" disable_sign_in_token_auth_user_html: "%{name} 为 %{target} 禁用了邮件令牌身份验证" disable_user_html: "%{name} 将用户 %{target} 设置为禁止登录" enable_custom_emoji_html: "%{name} 启用了自定义表情 %{target}" + enable_relay_html: "%{name} 启用了中继站 %{target}" enable_sign_in_token_auth_user_html: "%{name} 为 %{target} 启用了邮件令牌身份验证" enable_user_html: "%{name} 将用户 %{target} 设置为允许登录" memorialize_account_html: "%{name} 将 %{target} 设置为追悼账户" diff --git a/config/locales/zh-TW.yml b/config/locales/zh-TW.yml index d8fef10816..495a6a4742 100644 --- a/config/locales/zh-TW.yml +++ b/config/locales/zh-TW.yml @@ -184,6 +184,7 @@ zh-TW: create_domain_block: 新增網域封鎖 create_email_domain_block: 新增電子郵件網域封鎖 create_ip_block: 新增IP規則 + create_relay: 新增中繼 create_unavailable_domain: 新增無法存取的網域 create_user_role: 新增角色 demote_user: 將用戶降級 @@ -195,14 +196,17 @@ zh-TW: destroy_email_domain_block: 刪除電子郵件網域封鎖 destroy_instance: 清除網域 destroy_ip_block: 刪除 IP 規則 + destroy_relay: 刪除中繼 destroy_status: 刪除狀態 destroy_unavailable_domain: 刪除無法存取的網域 destroy_user_role: 移除角色 disable_2fa_user: 停用兩階段驗證 disable_custom_emoji: 停用自訂 emoji 表情符號 + disable_relay: 停用中繼 disable_sign_in_token_auth_user: 停用使用者電子郵件 token 驗證 disable_user: 停用帳號 enable_custom_emoji: 啟用自訂 emoji 表情符號 + enable_relay: 啟用中繼 enable_sign_in_token_auth_user: 啟用使用者電子郵件 token 驗證 enable_user: 啓用帳號 memorialize_account: 設定成追悼帳號 @@ -244,6 +248,7 @@ zh-TW: create_domain_block_html: "%{name} 已封鎖網域 %{target}" create_email_domain_block_html: "%{name} 已封鎖電子郵件網域 %{target}" create_ip_block_html: "%{name} 已設定 IP %{target} 的規則" + create_relay_html: "%{name} 已新增中繼 %{target}" create_unavailable_domain_html: "%{name} 停止發送至網域 %{target}" create_user_role_html: "%{name} 已新增 %{target} 角色" demote_user_html: "%{name} 將使用者 %{target} 降級" @@ -255,14 +260,17 @@ zh-TW: destroy_email_domain_block_html: "%{name} 已解除封鎖電子郵件網域 %{target}" destroy_instance_html: "%{name} 已清除網域 %{target}" destroy_ip_block_html: "%{name} 已刪除 IP %{target} 的規則" + destroy_relay_html: "%{name} 已刪除中繼 %{target}" destroy_status_html: "%{name} 已刪除 %{target} 的嘟文" destroy_unavailable_domain_html: "%{name} 已恢復對網域 %{target} 的發送" destroy_user_role_html: "%{name} 已刪除 %{target} 角色" disable_2fa_user_html: "%{name} 已停用使用者 %{target} 的兩階段驗證 (2FA) " disable_custom_emoji_html: "%{name} 已停用自訂 emoji 表情符號 %{target}" + disable_relay_html: "%{name} 已停用中繼 %{target}" disable_sign_in_token_auth_user_html: "%{name} 已停用 %{target} 之使用者電子郵件 token 驗證" disable_user_html: "%{name} 將使用者 %{target} 設定為禁止登入" enable_custom_emoji_html: "%{name} 已啟用自訂 emoji 表情符號 %{target}" + enable_relay_html: "%{name} 已啟用中繼 %{target}" enable_sign_in_token_auth_user_html: "%{name} 已啟用 %{target} 之使用者電子郵件 token 驗證" enable_user_html: "%{name} 將使用者 %{target} 設定為允許登入" memorialize_account_html: "%{name} 將 %{target} 設定為追悼帳號" @@ -560,7 +568,7 @@ zh-TW: relationships: title: "%{acct} 的關係" relays: - add_new: 新增中繼站 + add_new: 新增中繼 delete: 刪除 description_html: "聯邦中繼站 是種中繼伺服器,會於訂閱並推送至此中繼站的伺服器之間交換大量的公開嘟文。中繼站也能協助小型或中型伺服器自聯邦宇宙中探索內容,而無須本地使用者手動跟隨遠端伺服器的其他使用者。" disable: 停用 From 95d7120ce6671ec1765e8435b248eb2dc7d8ee02 Mon Sep 17 00:00:00 2001 From: Matt Jankowski Date: Wed, 13 Nov 2024 04:35:21 -0500 Subject: [PATCH 06/64] Misc gem version bumps (#32854) --- Gemfile.lock | 36 ++++++++++++++++++------------------ 1 file changed, 18 insertions(+), 18 deletions(-) diff --git a/Gemfile.lock b/Gemfile.lock index 743a78ad54..b832a18df6 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -97,7 +97,7 @@ GEM attr_required (1.0.2) awrence (1.2.1) aws-eventstream (1.3.0) - aws-partitions (1.1001.0) + aws-partitions (1.1004.0) aws-sdk-core (3.212.0) aws-eventstream (~> 1, >= 1.3.0) aws-partitions (~> 1, >= 1.992.0) @@ -112,7 +112,7 @@ GEM aws-sigv4 (~> 1.5) aws-sigv4 (1.10.1) aws-eventstream (~> 1, >= 1.0.2) - azure-blob (0.5.2) + azure-blob (0.5.3) rexml base64 (0.2.0) bcp47_spec (0.2.1) @@ -178,7 +178,7 @@ GEM activerecord (>= 5.a) database_cleaner-core (~> 2.0.0) database_cleaner-core (2.0.1) - date (3.3.4) + date (3.4.0) debug (1.9.2) irb (~> 1.10) reline (>= 0.3.8) @@ -189,10 +189,10 @@ GEM railties (>= 4.1.0) responders warden (~> 1.2.3) - devise-two-factor (6.0.0) - activesupport (~> 7.0) + devise-two-factor (6.1.0) + activesupport (>= 7.0, < 8.1) devise (~> 4.0) - railties (~> 7.0) + railties (>= 7.0, < 8.1) rotp (~> 6.0) devise_pam_authenticatable2 (9.2.0) devise (>= 4.0.0) @@ -330,7 +330,7 @@ GEM azure-blob (~> 0.5.2) hashie (~> 5.0) jmespath (1.6.2) - json (2.7.4) + json (2.8.1) json-canonicalization (1.0.0) json-jwt (1.15.3.1) activesupport (>= 4.2) @@ -407,16 +407,16 @@ GEM mime-types (3.6.0) logger mime-types-data (~> 3.2015) - mime-types-data (3.2024.1001) + mime-types-data (3.2024.1105) mini_mime (1.1.5) mini_portile2 (2.8.7) minitest (5.25.1) - msgpack (1.7.3) + msgpack (1.7.5) multi_json (1.15.0) mutex_m (0.2.0) net-http (0.5.0) uri - net-imap (0.5.0) + net-imap (0.5.1) date net-protocol net-ldap (0.19.0) @@ -554,10 +554,10 @@ GEM opentelemetry-semantic_conventions (1.10.1) opentelemetry-api (~> 1.0) orm_adapter (0.5.0) - ostruct (0.6.0) + ostruct (0.6.1) ox (2.14.18) parallel (1.26.3) - parser (3.3.5.0) + parser (3.3.6.0) ast (~> 2.4.1) racc parslet (2.0.0) @@ -579,7 +579,7 @@ GEM activesupport (>= 7.0.0) rack railties (>= 7.0.0) - psych (5.1.2) + psych (5.2.0) stringio public_suffix (6.0.1) puma (6.4.3) @@ -664,7 +664,7 @@ GEM redlock (1.3.2) redis (>= 3.0.0, < 6.0) regexp_parser (2.9.2) - reline (0.5.10) + reline (0.5.11) io-console (~> 0.5) request_store (1.6.0) rack (>= 1.4) @@ -673,7 +673,7 @@ GEM railties (>= 5.2) rexml (3.3.9) rotp (6.3.0) - rouge (4.4.0) + rouge (4.5.1) rpam2 (4.0.2) rqrcode (2.2.0) chunky_png (~> 1.0) @@ -693,7 +693,7 @@ GEM rspec-mocks (3.13.2) diff-lcs (>= 1.2.0, < 2.0) rspec-support (~> 3.13.0) - rspec-rails (7.0.1) + rspec-rails (7.1.0) actionpack (>= 7.0) activesupport (>= 7.0) railties (>= 7.0) @@ -794,7 +794,7 @@ GEM stackprof (0.2.26) stoplight (4.1.0) redlock (~> 1.0) - stringio (3.1.1) + stringio (3.1.2) strong_migrations (2.1.0) activerecord (>= 6.1) swd (1.3.0) @@ -867,7 +867,7 @@ GEM rack-proxy (>= 0.6.1) railties (>= 5.2) semantic_range (>= 2.3.0) - webrick (1.8.2) + webrick (1.9.0) websocket (1.2.11) websocket-driver (0.7.6) websocket-extensions (>= 0.1.0) From 8f5cbf537026915215d84945efad9a878ac8cdb4 Mon Sep 17 00:00:00 2001 From: Claire Date: Wed, 13 Nov 2024 11:22:11 +0100 Subject: [PATCH 07/64] Fix list creation limit check (#32869) --- app/models/list.rb | 2 +- spec/models/list_spec.rb | 6 +++++- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/app/models/list.rb b/app/models/list.rb index d4915f56fa..bb7dd4cfc0 100644 --- a/app/models/list.rb +++ b/app/models/list.rb @@ -34,7 +34,7 @@ class List < ApplicationRecord private def validate_account_lists_limit - errors.add(:base, I18n.t('lists.errors.limit')) if account.lists.count >= PER_ACCOUNT_LIMIT + errors.add(:base, I18n.t('lists.errors.limit')) if account.owned_lists.count >= PER_ACCOUNT_LIMIT end def clean_feed_manager diff --git a/spec/models/list_spec.rb b/spec/models/list_spec.rb index 62a84dfebf..48c273d3ec 100644 --- a/spec/models/list_spec.rb +++ b/spec/models/list_spec.rb @@ -11,7 +11,11 @@ RSpec.describe List do context 'when account has hit max list limit' do let(:account) { Fabricate :account } - before { stub_const 'List::PER_ACCOUNT_LIMIT', 0 } + before do + stub_const 'List::PER_ACCOUNT_LIMIT', 1 + + Fabricate(:list, account: account) + end context 'when creating a new list' do it { is_expected.to_not allow_value(account).for(:account).against(:base).with_message(I18n.t('lists.errors.limit')) } From 03ecf5df3bee1c667bfdba26887613c8620dc5c5 Mon Sep 17 00:00:00 2001 From: Jaz-Michael King <141073565+jmking-iftas@users.noreply.github.com> Date: Wed, 13 Nov 2024 08:10:01 -0500 Subject: [PATCH 08/64] Adds a range of reserved usernames to reduce potential misuse by malicious actors (#32828) --- config/settings.yml | 21 +++++++++++++++++---- 1 file changed, 17 insertions(+), 4 deletions(-) diff --git a/config/settings.yml b/config/settings.yml index 297bf0281d..673a4c1be2 100644 --- a/config/settings.yml +++ b/config/settings.yml @@ -21,14 +21,27 @@ defaults: &defaults trends_as_landing_page: true trendable_by_default: false reserved_usernames: + - abuse + - account + - accounts - admin - - support - - help - - root - - webmaster + - administration - administrator + - admins + - help + - helpdesk + - instance - mod - moderator + - moderators + - mods + - owner + - root + - security + - server + - staff + - support + - webmaster disallowed_hashtags: # space separated string or list of hashtags without the hash bootstrap_timeline_accounts: '' activity_api_enabled: true From 7fc8292ea540fda71434d24dd78622d8e94d024c Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Wed, 13 Nov 2024 16:08:10 +0100 Subject: [PATCH 09/64] Update dependency react-textarea-autosize to v8.5.5 (#32872) 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 9e3ec41017..7fd68ac8c1 100644 --- a/yarn.lock +++ b/yarn.lock @@ -14787,15 +14787,15 @@ __metadata: linkType: hard "react-textarea-autosize@npm:^8.4.1": - version: 8.5.4 - resolution: "react-textarea-autosize@npm:8.5.4" + version: 8.5.5 + resolution: "react-textarea-autosize@npm:8.5.5" dependencies: "@babel/runtime": "npm:^7.20.13" use-composed-ref: "npm:^1.3.0" use-latest: "npm:^1.2.1" peerDependencies: react: ^16.8.0 || ^17.0.0 || ^18.0.0 - checksum: 10c0/ea92fda2128983c1a8e84c74706ffb4b8bfa1a19c803d210868ec031c1ac3b8ceee8028766ef5d91017265da2bdccf6a85e5b6e5d553005e839f0c47e5758b43 + checksum: 10c0/d708a31b39a409d0246cd8afbd956ce51db58ce0b6411b9d4e1dc876ce93c329d20875933ce5d337662fdcd3699596966dc630149236fee2835d74e302404c98 languageName: node linkType: hard From 980970ddfd659393877cc4fa87d2811bbd0e0a79 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Thu, 14 Nov 2024 10:15:49 +0100 Subject: [PATCH 10/64] Update dependency browser to v6.1.0 (#32878) 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 b832a18df6..106fb0d0fd 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -131,7 +131,7 @@ GEM msgpack (~> 1.2) brakeman (6.2.2) racc - browser (6.0.0) + browser (6.1.0) brpoplpush-redis_script (0.1.3) concurrent-ruby (~> 1.0, >= 1.0.5) redis (>= 1.0, < 6) From aaebf142aac8ae0f52faa847a9e0c206da57a555 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Thu, 14 Nov 2024 10:39:33 +0100 Subject: [PATCH 11/64] New Crowdin Translations (automated) (#32884) Co-authored-by: GitHub Actions --- app/javascript/mastodon/locales/ar.json | 1 + app/javascript/mastodon/locales/eo.json | 5 +++-- app/javascript/mastodon/locales/fr-CA.json | 3 +++ app/javascript/mastodon/locales/fr.json | 3 +++ app/javascript/mastodon/locales/it.json | 1 + app/javascript/mastodon/locales/lad.json | 25 ++++++++++++++++++++++ config/locales/bg.yml | 18 ++++++++++++++++ config/locales/es.yml | 24 ++++++++++----------- config/locales/lad.yml | 9 ++++++++ config/locales/simple_form.bg.yml | 3 +++ config/locales/simple_form.lad.yml | 1 + 11 files changed, 79 insertions(+), 14 deletions(-) diff --git a/app/javascript/mastodon/locales/ar.json b/app/javascript/mastodon/locales/ar.json index 54ed1cb8c8..5c7dfeb128 100644 --- a/app/javascript/mastodon/locales/ar.json +++ b/app/javascript/mastodon/locales/ar.json @@ -86,6 +86,7 @@ "alert.unexpected.title": "المعذرة!", "alt_text_badge.title": "نص بديل", "announcement.announcement": "إعلان", + "annual_report.summary.archetype.booster": "The cool-hunter", "attachments_list.unprocessed": "(غير معالَج)", "audio.hide": "إخفاء المقطع الصوتي", "block_modal.remote_users_caveat": "سوف نطلب من الخادم {domain} أن يحترم قرارك، لكن الالتزام غير مضمون لأن بعض الخواديم قد تتعامل مع نصوص الكتل بشكل مختلف. قد تظل المنشورات العامة مرئية للمستخدمين غير المسجلين الدخول.", diff --git a/app/javascript/mastodon/locales/eo.json b/app/javascript/mastodon/locales/eo.json index 731e11f27a..6d8c82385b 100644 --- a/app/javascript/mastodon/locales/eo.json +++ b/app/javascript/mastodon/locales/eo.json @@ -90,6 +90,7 @@ "annual_report.summary.archetype.replier": "La plej societema", "annual_report.summary.followers.followers": "sekvantoj", "annual_report.summary.highlighted_post.by_replies": "afiŝo kun la plej multaj respondoj", + "annual_report.summary.most_used_app.most_used_app": "plej uzita apo", "annual_report.summary.most_used_hashtag.none": "Nenio", "annual_report.summary.new_posts.new_posts": "novaj afiŝoj", "annual_report.summary.thanks": "Dankon pro esti parto de Mastodon!", @@ -339,7 +340,7 @@ "followed_tags": "Sekvataj kradvortoj", "footer.about": "Pri", "footer.directory": "Profilujo", - "footer.get_app": "Akiru la Programon", + "footer.get_app": "Akiri la apon", "footer.invite": "Inviti homojn", "footer.keyboard_shortcuts": "Fulmoklavoj", "footer.privacy_policy": "Politiko de privateco", @@ -388,7 +389,7 @@ "ignore_notifications_modal.not_followers_title": "Ĉu ignori sciigojn de homoj, kiuj ne sekvas vin?", "ignore_notifications_modal.not_following_title": "Ĉu ignori sciigojn de homoj, kiujn vi ne sekvas?", "ignore_notifications_modal.private_mentions_title": "Ĉu ignori sciigojn de nepetitaj privataj mencioj?", - "interaction_modal.description.favourite": "Per konto ĉe Mastodon, vi povas stelumiti ĉi tiun afiŝon por sciigi la afiŝanton ke vi aprezigas ŝin kaj konservas por la estonteco.", + "interaction_modal.description.favourite": "Per konto ĉe Mastodon, vi povas stelumi ĉi tiun afiŝon por sciigi la afiŝanton ke vi sâtas kaj konservas ĝin por poste.", "interaction_modal.description.follow": "Kun konto ĉe Mastodon, vi povas sekvi {name} por ricevi iliajn afiŝojn en via hejma fluo.", "interaction_modal.description.reblog": "Kun konto ĉe Mastodon, vi povas diskonigi ĉi tiun afiŝon, por ke viaj propraj sekvantoj vidu ĝin.", "interaction_modal.description.reply": "Kun konto ĉe Mastodon, vi povos respondi al ĉi tiu afiŝo.", diff --git a/app/javascript/mastodon/locales/fr-CA.json b/app/javascript/mastodon/locales/fr-CA.json index 65bbc25c21..fed111e7e8 100644 --- a/app/javascript/mastodon/locales/fr-CA.json +++ b/app/javascript/mastodon/locales/fr-CA.json @@ -87,6 +87,9 @@ "alert.unexpected.title": "Oups!", "alt_text_badge.title": "Texte Alt", "announcement.announcement": "Annonce", + "annual_report.summary.archetype.oracle": "L’oracle", + "annual_report.summary.here_it_is": "Voici votre récap de {year} :", + "annual_report.summary.most_used_app.most_used_app": "appli la plus utilisée", "attachments_list.unprocessed": "(non traité)", "audio.hide": "Masquer l'audio", "block_modal.remote_users_caveat": "Nous allons demander au serveur {domain} de respecter votre décision. Cependant, ce respect n'est pas garanti, car certains serveurs peuvent gérer différemment les blocages. Les messages publics peuvent rester visibles par les utilisateur·rice·s non connecté·e·s.", diff --git a/app/javascript/mastodon/locales/fr.json b/app/javascript/mastodon/locales/fr.json index ed751c244b..10bfc22bd8 100644 --- a/app/javascript/mastodon/locales/fr.json +++ b/app/javascript/mastodon/locales/fr.json @@ -87,6 +87,9 @@ "alert.unexpected.title": "Oups !", "alt_text_badge.title": "Texte Alt", "announcement.announcement": "Annonce", + "annual_report.summary.archetype.oracle": "L’oracle", + "annual_report.summary.here_it_is": "Voici votre récap de {year} :", + "annual_report.summary.most_used_app.most_used_app": "appli la plus utilisée", "attachments_list.unprocessed": "(non traité)", "audio.hide": "Masquer l'audio", "block_modal.remote_users_caveat": "Nous allons demander au serveur {domain} de respecter votre décision. Cependant, ce respect n'est pas garanti, car certains serveurs peuvent gérer différemment les blocages. Les messages publics peuvent rester visibles par les utilisateur·rice·s non connecté·e·s.", diff --git a/app/javascript/mastodon/locales/it.json b/app/javascript/mastodon/locales/it.json index bf179ea2f2..06779d337c 100644 --- a/app/javascript/mastodon/locales/it.json +++ b/app/javascript/mastodon/locales/it.json @@ -97,6 +97,7 @@ "annual_report.summary.highlighted_post.possessive": "di {name}", "annual_report.summary.most_used_app.most_used_app": "l'app più utilizzata", "annual_report.summary.most_used_hashtag.most_used_hashtag": "l'hashtag più usato", + "annual_report.summary.most_used_hashtag.none": "Nessuno", "annual_report.summary.new_posts.new_posts": "nuovi post", "annual_report.summary.percentile.text": "Questo ti colloca tra ildei migliori utenti Mastodon.", "annual_report.summary.percentile.we_wont_tell_bernie": "Non lo diremo a Bernie.", diff --git a/app/javascript/mastodon/locales/lad.json b/app/javascript/mastodon/locales/lad.json index 563eb3b190..0a5f82aee3 100644 --- a/app/javascript/mastodon/locales/lad.json +++ b/app/javascript/mastodon/locales/lad.json @@ -87,6 +87,17 @@ "alert.unexpected.title": "Atyo!", "alt_text_badge.title": "Teksto alternativo", "announcement.announcement": "Pregon", + "annual_report.summary.archetype.pollster": "El anketero", + "annual_report.summary.followers.followers": "suivantes", + "annual_report.summary.highlighted_post.by_favourites": "la puvlikasyon mas favoritada", + "annual_report.summary.highlighted_post.by_reblogs": "la puvlikasyon mas repartajada", + "annual_report.summary.highlighted_post.by_replies": "la puvlikasyon kon mas repuestas", + "annual_report.summary.highlighted_post.possessive": "de {name}", + "annual_report.summary.most_used_app.most_used_app": "la aplikasyon mas uzada", + "annual_report.summary.most_used_hashtag.most_used_hashtag": "la etiketa mas uzada", + "annual_report.summary.most_used_hashtag.none": "Dinguno", + "annual_report.summary.new_posts.new_posts": "puvlikasyones muevas", + "annual_report.summary.thanks": "Mersi por ser parte de Mastodon!", "attachments_list.unprocessed": "(no prosesado)", "audio.hide": "Eskonde audio", "block_modal.show_less": "Amostra manko", @@ -97,6 +108,7 @@ "block_modal.you_wont_see_mentions": "No veras publikasyones ke lo enmentan.", "boost_modal.combo": "Puedes klikar {combo} para ometer esto la proksima vez", "boost_modal.reblog": "Repartajar puvlikasyon?", + "boost_modal.undo_reblog": "Departajar puvlikasyon?", "bundle_column_error.copy_stacktrace": "Kopia el raporto de yerro", "bundle_column_error.error.body": "La pajina solisitada no pudo ser renderada. Podria ser por un yerro en muestro kodiche o un problem de kompatibilita kon el navigador.", "bundle_column_error.error.title": "Atyo, no!", @@ -155,6 +167,7 @@ "compose_form.poll.duration": "Durasion de anketa", "compose_form.poll.multiple": "Multiples opsyones", "compose_form.poll.option_placeholder": "Opsyon {number}", + "compose_form.poll.single": "Opsyon unika", "compose_form.poll.switch_to_multiple": "Troka anketa para permeter a eskojer mas ke una opsyon", "compose_form.poll.switch_to_single": "Troka anketa para permeter a eskojer solo una opsyon", "compose_form.poll.type": "Estilo", @@ -213,6 +226,7 @@ "dismissable_banner.public_timeline": "Estas son las publikasyones publikas mas resientes de personas en la red sosyala a las kualas la djente de {domain} sige.", "domain_block_modal.block": "Bloka sirvidor", "domain_block_modal.block_account_instead": "Bloka @{name} en su lugar", + "domain_block_modal.they_can_interact_with_old_posts": "Las personas de este sirvidor pueden enteraktuar kon tus puvlikasyones viejas.", "domain_block_modal.they_cant_follow": "Dingun de este sirvidor puede segirte.", "domain_block_modal.they_wont_know": "No savra ke tiene sido blokado.", "domain_block_modal.title": "Bloka el domeno?", @@ -307,6 +321,7 @@ "follow_suggestions.personalized_suggestion": "Sujestion personalizada", "follow_suggestions.popular_suggestion": "Sujestion populara", "follow_suggestions.popular_suggestion_longer": "Popular en {domain}", + "follow_suggestions.similar_to_recently_followed_longer": "Similares a los profils ke tienes segido resyentemente", "follow_suggestions.view_all": "Ve todos", "follow_suggestions.who_to_follow": "A ken segir", "followed_tags": "Etiketas segidas", @@ -335,6 +350,9 @@ "hashtag.follow": "Sige etiketa", "hashtag.unfollow": "Desige etiketa", "hashtags.and_other": "…i {count, plural, one {}other {# mas}}", + "hints.profiles.followers_may_be_missing": "Puede ser ke algunos suivantes de este profil no se amostren.", + "hints.profiles.follows_may_be_missing": "Puede ser ke algunos kuentos segidos por este profil no se amostren.", + "hints.profiles.posts_may_be_missing": "Puede ser ke algunas puvlikasyones de este profil no se amostren.", "hints.profiles.see_more_followers": "Ve mas suivantes en {domain}", "hints.profiles.see_more_follows": "Ve mas segidos en {domain}", "hints.profiles.see_more_posts": "Ve mas puvlikasyones en {domain}", @@ -352,10 +370,12 @@ "ignore_notifications_modal.new_accounts_title": "Inyorar avizos de kuentos muevos?", "ignore_notifications_modal.not_followers_title": "Inyorar avizos de personas a las kualas no te sigen?", "ignore_notifications_modal.not_following_title": "Inyorar avizos de personas a las kualas no siges?", + "ignore_notifications_modal.private_mentions_title": "Ignorar avizos de mensyones privadas no solisitadas?", "interaction_modal.description.favourite": "Kon un kuento en Mastodon, puedes markar esta publikasyon komo favorita para ke el autor sepa ke te plaze i para guadrarla para dempues.", "interaction_modal.description.follow": "Kon un kuento en Mastodon, puedes segir a {name} para risivir sus publikasyones en tu linya temporal prinsipala.", "interaction_modal.description.reblog": "Kon un kuento en Mastodon, puedes repartajar esta publikasyon para amostrarla a tus suivantes.", "interaction_modal.description.reply": "Kon un kuento en Mastodon, puedes arispondir a esta publikasyon.", + "interaction_modal.description.vote": "Kon un kuento en Mastodon, puedes votar en esta anketa.", "interaction_modal.login.action": "Va a tu sirvidor", "interaction_modal.login.prompt": "Domeno del sirvidor de tu kuento, por enshemplo mastodon.social", "interaction_modal.no_account_yet": "No tyenes kuento de Mastodon?", @@ -367,6 +387,7 @@ "interaction_modal.title.follow": "Sige a {name}", "interaction_modal.title.reblog": "Repartaja publikasyon de {name}", "interaction_modal.title.reply": "Arisponde a publikasyon de {name}", + "interaction_modal.title.vote": "Vota en la anketa de {name}", "intervals.full.days": "{number, plural, one {# diya} other {# diyas}}", "intervals.full.hours": "{number, plural, one {# ora} other {# oras}}", "intervals.full.minutes": "{number, plural, one {# minuto} other {# minutos}}", @@ -466,13 +487,16 @@ "navigation_bar.security": "Segurita", "not_signed_in_indicator.not_signed_in": "Nesesitas konektarse kon tu kuento para akseder este rekurso.", "notification.admin.report": "{name} raporto {target}", + "notification.admin.report_statuses": "{name} raporto {target} por {category}", "notification.admin.report_statuses_other": "{name} raporto {target}", "notification.admin.sign_up": "{name} kriyo un konto", + "notification.annual_report.view": "Ve #Wrapstodon", "notification.favourite": "A {name} le plaze tu publikasyon", "notification.follow": "{name} te ampeso a segir", "notification.follow_request": "{name} tiene solisitado segirte", "notification.label.mention": "Enmenta", "notification.label.private_mention": "Enmentadura privada", + "notification.label.private_reply": "Repuesta privada", "notification.label.reply": "Arisponde", "notification.mention": "Enmenta", "notification.mentioned_you": "{name} te enmento", @@ -536,6 +560,7 @@ "notifications.policy.accept_hint": "Amostra en avizos", "notifications.policy.drop": "Inyora", "notifications.policy.filter": "Filtra", + "notifications.policy.filter_limited_accounts_hint": "Limitadas por moderadores del sirvidor", "notifications.policy.filter_limited_accounts_title": "Kuentos moderados", "notifications.policy.filter_new_accounts.hint": "Kriyadas durante {days, plural, one {el ultimo diya} other {los ultimos # diyas}}", "notifications.policy.filter_new_accounts_title": "Muevos kuentos", diff --git a/config/locales/bg.yml b/config/locales/bg.yml index 1fdd0e3533..7181b35b6d 100644 --- a/config/locales/bg.yml +++ b/config/locales/bg.yml @@ -412,6 +412,7 @@ bg: attempts_over_week: one: "%{count} опит за изминалата седмица" other: "%{count} опита за регистрация през изминалата седмица" + created_msg: Успешно блокиран домейн на е-поща delete: Изтриване dns: types: @@ -420,8 +421,11 @@ bg: new: create: Добавяне на домейн resolve: Преобразуване на домейна + title: Блокиране на нов домейн на имейл + no_email_domain_block_selected: Няма промяна, тъй като няма избрани блокирания на домейн на имейл not_permitted: Няма позволение resolved_through_html: Преобразувано чрез %{domain} + title: Блокирани домейни на имейл export_domain_allows: new: title: Внасяне на позволенията на домейни @@ -842,6 +846,9 @@ bg: message_html: Не сте определили никакви правила на сървъра. sidekiq_process_check: message_html: Не работи процес Sidekiq за %{value} опашка/и. Прегледайте настройките си за Sidekiq + software_version_check: + action: Преглед на наличните обновявания + message_html: Налично е обновяване на Mastodon. software_version_critical_check: action: Преглед на наличните обновявания message_html: Налично e критично обновяване на Mastodon. Обновете възможно най-бързо. @@ -1102,11 +1109,18 @@ bg: status: account_status: Състояние на акаунта functional: Вашият акаунт е в изправност. + pending: Вашето приложение чака преглед от персонала ни. Това може да отнеме време. Ще получите е-писмо, ако приложението ви се одобри. redirecting_to: Вашият акаунт е бездеен, защото сега се пренасочва към %{acct}. self_destruct: Затваряйки %{domain}, ще получите само ограничен достъп до акаунта си. view_strikes: Преглед на предишните предупреждения против акаунта ви too_fast: Образецът подаден пребързо, опитайте пак. use_security_key: Употреба на ключ за сигурност + author_attribution: + example_title: Примерен текст + more_from_html: Още от %{name} + s_blog: Блогът на %{name} + then_instructions: Тогава добавете име на домейна на публикацията в долното поле. + title: Приписване на авторството challenge: confirm: Продължаване hint_html: "Съвет: няма да ви питаме пак за паролата през следващия час." @@ -1450,6 +1464,7 @@ bg: update: subject: "%{name} промени публикация" notifications: + administration_emails: Известия за администратори по е-поща email_events_hint: 'Изберете събития, за които искате да получавате известия:' number: human: @@ -1607,6 +1622,7 @@ bg: import: Импортиране import_and_export: Импортиране и експортиране migrate: Миграция на акаунта + notifications: Известия по е-поща preferences: Предпочитания profile: Профил relationships: Последвания и последователи @@ -1842,6 +1858,7 @@ bg: invalid_otp_token: Невалиден код otp_lost_help_html: Ако загубите достъп до двете, то може да се свържете с %{email} rate_limited: Премного опити за удостоверяване. Опитайте пак по-късно. + seamless_external_login: Влезли сте чрез външна услуга, така че настройките за парола и имейл не са налични. signed_in_as: 'Влезли като:' verification: extra_instructions_html: Съвет:Връзката в уебсайта ви може да е невидима. Важна част е rel="me", която предотврятява имитирането на уебсайтове с породено от потребителите съдържание. Може дори да употребите етикет за връзката в заглавката на странице вместо а, но HTML трябва да достъпен без изпълнение на JavaScript. @@ -1850,6 +1867,7 @@ bg: instructions_html: Копипейстнете кода долу в HTML на уебсайта си. Тогава добавете адреса на уебсайта си в едно от допълнителните полета на профила ви от раздела "Редактиране на профила" и запазане на промените. verification: Проверка verified_links: Вашите потвърдени връзки + website_verification: Потвърждаване на уебсайта webauthn_credentials: add: Добавяне на нов ключ за сигурност create: diff --git a/config/locales/es.yml b/config/locales/es.yml index 8690c1cdfb..ddd53a2387 100644 --- a/config/locales/es.yml +++ b/config/locales/es.yml @@ -67,8 +67,8 @@ es: display_name: Nombre domain: Dominio edit: Editar - email: E-mail - email_status: E-mail Status + email: Correo electrónico + email_status: Estado del correo electrónico enable: Habilitar enable_sign_in_token_auth: Habilitar la autenticación por token de correo electrónico enabled: Habilitada @@ -86,7 +86,7 @@ es: local: Local remote: Remoto title: Localización - login_status: Estado del login + login_status: Estado de inicio de sesión media_attachments: Multimedia memorialize: Convertir en memorial memorialized: Cuenta conmemorativa @@ -102,7 +102,7 @@ es: moderation_notes: Notas de moderación most_recent_activity: Actividad más reciente most_recent_ip: IP más reciente - no_account_selected: Ninguna cuenta se cambió como ninguna fue seleccionada + no_account_selected: Ninguna cuenta se cambió, ya que ninguna fue seleccionada no_limits_imposed: Sin límites impuestos no_role_assigned: Ningún rol asignado not_subscribed: No se está suscrito @@ -132,17 +132,17 @@ es: success: "¡Enlace de confirmación enviado con éxito!" reset: Reiniciar reset_password: Reiniciar contraseña - resubscribe: Re-suscribir + resubscribe: Volver a suscribirse role: Rol search: Buscar search_same_email_domain: Otros usuarios con el mismo dominio de correo search_same_ip: Otros usuarios con la misma IP security: Seguridad security_measures: - only_password: Sólo contraseña + only_password: Solo contraseña password_and_2fa: Contraseña y 2FA sensitive: Sensible - sensitized: marcado como sensible + sensitized: Marcada como sensible shared_inbox_url: URL de bandeja compartida show: created_reports: Reportes hechos por esta cuenta @@ -161,10 +161,10 @@ es: unblocked_email_msg: Se ha desbloqueado correctamente la dirección de correo de %{username} unconfirmed_email: Correo electrónico sin confirmar undo_sensitized: Desmarcar como sensible - undo_silenced: Des-silenciar - undo_suspension: Des-suspender + undo_silenced: Dejar de silenciar + undo_suspension: Deshacer suspensión unsilenced_msg: Se quitó con éxito el límite de la cuenta %{username} - unsubscribe: Desuscribir + unsubscribe: Cancelar suscripción unsuspended_msg: Se quitó con éxito la suspensión de la cuenta de %{username} username: Nombre de usuario view_domain: Ver resumen del dominio @@ -296,7 +296,7 @@ es: empty: No se encontraron registros. filter_by_action: Filtrar por acción filter_by_user: Filtrar por usuario - title: Log de auditoría + title: Registro de auditoría unavailable_instance: "(nombre de dominio no disponible)" announcements: destroyed_msg: "¡Anuncio eliminado con éxito!" @@ -338,7 +338,7 @@ es: listed: Listados new: title: Añadir nuevo emoji personalizado - no_emoji_selected: No se cambió ningún emoji ya que no se seleccionó ninguno + no_emoji_selected: No se cambió ningún emoji, ya que no se seleccionó ninguno not_permitted: No tienes permiso para realizar esta acción overwrite: Sobrescribir shortcode: Código de atajo diff --git a/config/locales/lad.yml b/config/locales/lad.yml index ad241856a4..4486df637e 100644 --- a/config/locales/lad.yml +++ b/config/locales/lad.yml @@ -24,6 +24,7 @@ lad: admin: account_actions: action: Realiza aksion + already_silenced: Este kuento ya tiene sido limitado. already_suspended: Este kuento ya tiene sido suspendido. title: Modera %{acct} account_moderation_notes: @@ -638,6 +639,7 @@ lad: report: 'Raporta #%{id}' reported_account: Kuento raportado reported_by: Raportado por + reported_with_application: Raportado kon aplikasyon resolved: Rezolvido resolved_msg: Tienes rezolvido la denunsia djustamente! skip_to_actions: Va direktamente a las aksyones @@ -752,6 +754,7 @@ lad: desc_html: Esto se baza en eskriptos eksternos de hCaptcha, ke pueden ser una influensya negra a la sigurita i privasita. Ademas, esto puede rezultar en un proseso de enrejistrasyon signifikativamente manko aksesivle para algunas personas (espesyalmente diskapasitadas). Por estas razones, por favor, konsidera otras alternativas komo rejistrasyon por aprovasyon manuala o kon envitasyon. title: Solisita ke los muevos utilizadores rezolven un CAPTCHA para konfirmar su konto content_retention: + danger_zone: Zona de perikolo preamble: Kontrola komo el kontenido jenerado por el utilizador se magazina en Mastodon. title: Retensyon de kontenido default_noindex: @@ -882,9 +885,12 @@ lad: message_html: "Tu magazinaje de objektos es mal konfigurado. La privasita de tus utilizadores esta en riziko." tags: moderation: + not_trendable: No trendavle + not_usable: No uzavle pending_review: Revizion esta asperando reviewed: Revizado title: Estado + trendable: Trendavle unreviewed: No revizado usable: Uzavle name: Nombre @@ -959,6 +965,7 @@ lad: used_by_over_week: one: Uzada por una persona durante la ultima semana other: Uzada por %{count} personas durante la ultima semana + title: Rekomendasyones i trendes trending: En trend warning_presets: add_new: Adjusta muevo @@ -1138,7 +1145,9 @@ lad: too_fast: Formulario enviado demaziado rapido, aprovalo de muevo. use_security_key: Uza la yave de sigurita author_attribution: + example_title: Teksto de enshemplo more_from_html: Mas de %{name} + s_blog: Blog de %{name} challenge: confirm: Kontinua hint_html: "Konsejo: No retornaremos a demandarte por el kod durante la sigiente ora." diff --git a/config/locales/simple_form.bg.yml b/config/locales/simple_form.bg.yml index 5540942d93..17b7bd6239 100644 --- a/config/locales/simple_form.bg.yml +++ b/config/locales/simple_form.bg.yml @@ -3,12 +3,14 @@ bg: simple_form: hints: account: + attribution_domains_as_text: Едно на ред. Защитава от фалшиви атрибути. discoverable: Вашите публични публикации и профил може да се представят или препоръчват в различни области на Mastodon и вашия профил може да се предлага на други потребители. display_name: Вашето пълно име или псевдоним. fields: Вашата начална страница, местоимения, години, всичко що искате. indexable: Вашите обществени публикации може да се появят в резултатите от търсене в Mastodon. Взаимодействалите с публикациите ви може да ги търсят независимо. note: 'Може да @споменавате други хора или #хаштагове.' show_collections: Хората ще може да разглеждат през вашите последвания и последователи. Хората, които сте следвали, ще видят, че ги следвате независимо от това. + unlocked: Хората ще могат да ви последват без изискване на одобрение. Размаркирайте, ако искате да преглеждате заявките за последване и избирате дали да приемете или отхвърлите новите последователи. account_alias: acct: Посочете потребителско_име@домейн на акаунта си, от който искате да се преместите account_migration: @@ -142,6 +144,7 @@ bg: url: До къде ще се изпращат събитията labels: account: + attribution_domains_as_text: Уебсайтове, на които е позволено да приписват авторството ви discoverable: Включване на профил и публикации в алгоритмите за откриване fields: name: Етикет diff --git a/config/locales/simple_form.lad.yml b/config/locales/simple_form.lad.yml index 712c2f4e8a..de37005312 100644 --- a/config/locales/simple_form.lad.yml +++ b/config/locales/simple_form.lad.yml @@ -9,6 +9,7 @@ lad: indexable: Tus publikasyones publikas pueden apareser en rezultados de bushkeda en Mastodon. Personas ke enteraktuaron kon tus publikasyones syempre pueden bushkarlas inkluzo si trokes esta preferensya. note: 'Puedes @enmentar a otra djente o #etiketas.' show_collections: Otra djente podra ver tus segidos i suivantes. Personas a las kualas siges siempre podran ver que las estas sigiendo. + unlocked: Djente va poder segirte sin solisitar tu achetasyon. Deseleksyona si keres revizar solisitasyones de segimyento i dechidir si keres achetar o refuzar a muevos suivantes. account_alias: acct: Espesifika tu nombre de utilizador@domeno del kuento de ande keres migrar account_migration: From ec663eaba13294d803fdb8ddab373d7534c5a644 Mon Sep 17 00:00:00 2001 From: Claire Date: Thu, 14 Nov 2024 13:50:36 +0100 Subject: [PATCH 12/64] Fix Content Warning and filter states not applying to boosted posts properly (#32887) --- app/javascript/mastodon/components/status.jsx | 29 ++++++++++--------- 1 file changed, 15 insertions(+), 14 deletions(-) diff --git a/app/javascript/mastodon/components/status.jsx b/app/javascript/mastodon/components/status.jsx index 96ccf3aad4..f17f0367c1 100644 --- a/app/javascript/mastodon/components/status.jsx +++ b/app/javascript/mastodon/components/status.jsx @@ -393,20 +393,6 @@ class Status extends ImmutablePureComponent { }; let media, statusAvatar, prepend, rebloggedByText; - const matchedFilters = status.get('matched_filters'); - const expanded = (!matchedFilters || this.state.showDespiteFilter) && (!status.get('hidden') || status.get('spoiler_text').length === 0); - - if (hidden) { - return ( - -
- {status.getIn(['account', 'display_name']) || status.getIn(['account', 'username'])} - {status.get('spoiler_text').length > 0 && ({status.get('spoiler_text')})} - {expanded && {status.get('content')}} -
-
- ); - } const connectUp = previousId && previousId === status.get('in_reply_to_id'); const connectToRoot = rootId && rootId === status.get('in_reply_to_id'); @@ -446,6 +432,21 @@ class Status extends ImmutablePureComponent { ); } + const matchedFilters = status.get('matched_filters'); + const expanded = (!matchedFilters || this.state.showDespiteFilter) && (!status.get('hidden') || status.get('spoiler_text').length === 0); + + if (hidden) { + return ( + +
+ {status.getIn(['account', 'display_name']) || status.getIn(['account', 'username'])} + {status.get('spoiler_text').length > 0 && ({status.get('spoiler_text')})} + {expanded && {status.get('content')}} +
+
+ ); + } + if (pictureInPicture.get('inUse')) { media = ; } else if (status.get('media_attachments').size > 0) { From e8b6607ece43e6fcda99e76f8db0ad40d54b50b6 Mon Sep 17 00:00:00 2001 From: Claire Date: Thu, 14 Nov 2024 14:28:00 +0100 Subject: [PATCH 13/64] Fix titles being escaped twice (#32889) --- app/helpers/application_helper.rb | 2 +- app/views/about/show.html.haml | 3 +-- app/views/accounts/show.html.haml | 3 +-- app/views/privacy/show.html.haml | 3 +-- app/views/statuses/show.html.haml | 3 +-- spec/helpers/application_helper_spec.rb | 6 +++--- spec/views/statuses/show.html.haml_spec.rb | 6 +----- 7 files changed, 9 insertions(+), 17 deletions(-) diff --git a/app/helpers/application_helper.rb b/app/helpers/application_helper.rb index e36de19255..3d5025724f 100644 --- a/app/helpers/application_helper.rb +++ b/app/helpers/application_helper.rb @@ -79,7 +79,7 @@ module ApplicationHelper def html_title safe_join( - [content_for(:page_title).to_s.chomp, title] + [content_for(:page_title), title] .compact_blank, ' - ' ) diff --git a/app/views/about/show.html.haml b/app/views/about/show.html.haml index 05d8989add..e8f7b43eaa 100644 --- a/app/views/about/show.html.haml +++ b/app/views/about/show.html.haml @@ -1,5 +1,4 @@ -- content_for :page_title do - = t('about.title') +- content_for :page_title, t('about.title') - content_for :header_tags do = render partial: 'shared/og' diff --git a/app/views/accounts/show.html.haml b/app/views/accounts/show.html.haml index dde9c50847..1f5f81348e 100644 --- a/app/views/accounts/show.html.haml +++ b/app/views/accounts/show.html.haml @@ -1,5 +1,4 @@ -- content_for :page_title do - #{display_name(@account)} (#{acct(@account)}) +- content_for :page_title, "#{display_name(@account)} (#{acct(@account)})" - content_for :header_tags do - if @account.user_prefers_noindex? diff --git a/app/views/privacy/show.html.haml b/app/views/privacy/show.html.haml index 95e506641b..9eb4f7a570 100644 --- a/app/views/privacy/show.html.haml +++ b/app/views/privacy/show.html.haml @@ -1,5 +1,4 @@ -- content_for :page_title do - = t('privacy_policy.title') +- content_for :page_title, t('privacy_policy.title') - content_for :header_tags do = render partial: 'shared/og' diff --git a/app/views/statuses/show.html.haml b/app/views/statuses/show.html.haml index 08bab63073..f669885de0 100644 --- a/app/views/statuses/show.html.haml +++ b/app/views/statuses/show.html.haml @@ -1,5 +1,4 @@ -- content_for :page_title do - = t('statuses.title', name: display_name(@account), quote: truncate(@status.spoiler_text.presence || @status.text, length: 50, omission: '…', escape: false)) +- content_for :page_title, t('statuses.title', name: display_name(@account), quote: truncate(@status.spoiler_text.presence || @status.text, length: 50, omission: '…', escape: false)) - content_for :header_tags do - if @account.user_prefers_noindex? diff --git a/spec/helpers/application_helper_spec.rb b/spec/helpers/application_helper_spec.rb index ffcc5b81b6..557d08e851 100644 --- a/spec/helpers/application_helper_spec.rb +++ b/spec/helpers/application_helper_spec.rb @@ -257,11 +257,11 @@ RSpec.describe ApplicationHelper do expect(helper.html_title).to be_html_safe end - it 'removes extra new lines' do + it 'does not escape twice' do Setting.site_title = 'Site Title' - helper.content_for(:page_title, "Test Value\n") + helper.content_for(:page_title, '"Test Value"'.html_safe) - expect(helper.html_title).to eq 'Test Value - Site Title' + expect(helper.html_title).to eq '"Test Value" - Site Title' expect(helper.html_title).to be_html_safe end end diff --git a/spec/views/statuses/show.html.haml_spec.rb b/spec/views/statuses/show.html.haml_spec.rb index 1afcb046d4..02b1fe7384 100644 --- a/spec/views/statuses/show.html.haml_spec.rb +++ b/spec/views/statuses/show.html.haml_spec.rb @@ -18,7 +18,7 @@ RSpec.describe 'statuses/show.html.haml' do assign(:descendant_threads, []) end - it 'has valid opengraph tags' do + it 'has valid opengraph tags and twitter player tags' do render expect(header_tags) @@ -26,10 +26,6 @@ RSpec.describe 'statuses/show.html.haml' do .and match(//) .and match(//) .and match(%r{}) - end - - it 'has twitter player tag' do - render expect(header_tags) .to match(%r{}) From 62d65504f66e0361d178ea882c97bdcfbc426c25 Mon Sep 17 00:00:00 2001 From: Matt Jankowski Date: Thu, 14 Nov 2024 08:47:29 -0500 Subject: [PATCH 14/64] Add `DomainResource` class to wrap MX lookup/normalize (#32864) --- .../admin/email_domain_blocks_controller.rb | 5 +---- app/lib/domain_resource.rb | 22 +++++++++++++++++++ app/models/user.rb | 8 +------ .../admin/email_domain_blocks/new.html.haml | 4 ++-- lib/mastodon/cli/email_domain_blocks.rb | 7 +----- spec/lib/domain_resource_spec.rb | 19 ++++++++++++++++ 6 files changed, 46 insertions(+), 19 deletions(-) create mode 100644 app/lib/domain_resource.rb create mode 100644 spec/lib/domain_resource_spec.rb diff --git a/app/controllers/admin/email_domain_blocks_controller.rb b/app/controllers/admin/email_domain_blocks_controller.rb index fe822d8c99..9501ebd63a 100644 --- a/app/controllers/admin/email_domain_blocks_controller.rb +++ b/app/controllers/admin/email_domain_blocks_controller.rb @@ -58,10 +58,7 @@ module Admin private def set_resolved_records - Resolv::DNS.open do |dns| - dns.timeouts = 5 - @resolved_records = dns.getresources(@email_domain_block.domain, Resolv::DNS::Resource::IN::MX).to_a - end + @resolved_records = DomainResource.new(@email_domain_block.domain).mx end def resource_params diff --git a/app/lib/domain_resource.rb b/app/lib/domain_resource.rb new file mode 100644 index 0000000000..59a29d8797 --- /dev/null +++ b/app/lib/domain_resource.rb @@ -0,0 +1,22 @@ +# frozen_string_literal: true + +class DomainResource + attr_reader :domain + + RESOLVE_TIMEOUT = 5 + + def initialize(domain) + @domain = domain + end + + def mx + Resolv::DNS.open do |dns| + dns.timeouts = RESOLVE_TIMEOUT + dns + .getresources(domain, Resolv::DNS::Resource::IN::MX) + .to_a + .map { |mx| mx.exchange.to_s } + .compact_blank + end + end +end diff --git a/app/models/user.rb b/app/models/user.rb index 9a215669b9..f717dcd860 100644 --- a/app/models/user.rb +++ b/app/models/user.rb @@ -457,13 +457,7 @@ class User < ApplicationRecord # Doing this conditionally is not very satisfying, but this is consistent # with the MX records validations we do and keeps the specs tractable. - unless self.class.skip_mx_check? - Resolv::DNS.open do |dns| - dns.timeouts = 5 - - records = dns.getresources(domain, Resolv::DNS::Resource::IN::MX).to_a.map { |e| e.exchange.to_s }.compact_blank - end - end + records = DomainResource.new(domain).mx unless self.class.skip_mx_check? EmailDomainBlock.requires_approval?(records + [domain], attempt_ip: sign_up_ip) end diff --git a/app/views/admin/email_domain_blocks/new.html.haml b/app/views/admin/email_domain_blocks/new.html.haml index 2dfdca9376..4db8fbe5e5 100644 --- a/app/views/admin/email_domain_blocks/new.html.haml +++ b/app/views/admin/email_domain_blocks/new.html.haml @@ -30,12 +30,12 @@ %label.batch-table__row__select.batch-table__row__select--aligned.batch-checkbox = f.input_field :other_domains, as: :boolean, - checked_value: record.exchange.to_s, + checked_value: record, include_hidden: false, multiple: true .batch-table__row__content.pending-account .pending-account__header - %samp= record.exchange.to_s + %samp= record %br = t('admin.email_domain_blocks.dns.types.mx') diff --git a/lib/mastodon/cli/email_domain_blocks.rb b/lib/mastodon/cli/email_domain_blocks.rb index a830ca3661..0cc9ccb705 100644 --- a/lib/mastodon/cli/email_domain_blocks.rb +++ b/lib/mastodon/cli/email_domain_blocks.rb @@ -45,12 +45,7 @@ module Mastodon::CLI end other_domains = [] - if options[:with_dns_records] - Resolv::DNS.open do |dns| - dns.timeouts = 5 - other_domains = dns.getresources(domain, Resolv::DNS::Resource::IN::MX).to_a.map { |e| e.exchange.to_s }.compact_blank - end - end + other_domains = DomainResource.new(domain).mx if options[:with_dns_records] email_domain_block = EmailDomainBlock.new(domain: domain, other_domains: other_domains) email_domain_block.save! diff --git a/spec/lib/domain_resource_spec.rb b/spec/lib/domain_resource_spec.rb new file mode 100644 index 0000000000..0d239fd9de --- /dev/null +++ b/spec/lib/domain_resource_spec.rb @@ -0,0 +1,19 @@ +# frozen_string_literal: true + +require 'rails_helper' + +RSpec.describe DomainResource do + describe '#mx' do + subject { described_class.new(domain) } + + let(:domain) { 'example.host' } + let(:exchange) { 'mx.host' } + + before { configure_mx(domain: domain, exchange: exchange) } + + it 'returns array of hostnames' do + expect(subject.mx) + .to eq([exchange]) + end + end +end From 766358e52b86ca0dc6cf9bb091565e97af00b19a Mon Sep 17 00:00:00 2001 From: Matt Jankowski Date: Thu, 14 Nov 2024 09:03:57 -0500 Subject: [PATCH 15/64] Add coverage for malformed version cleanup in `SoftwareUpdateCheckService`, add helper query methods (#32876) --- app/models/software_update.rb | 16 +++++- app/services/software_update_check_service.rb | 2 +- spec/models/software_update_spec.rb | 54 +++++++++++++++++++ .../software_update_check_service_spec.rb | 5 +- 4 files changed, 73 insertions(+), 4 deletions(-) diff --git a/app/models/software_update.rb b/app/models/software_update.rb index 2cb935130a..7e2b15656e 100644 --- a/app/models/software_update.rb +++ b/app/models/software_update.rb @@ -22,6 +22,14 @@ class SoftwareUpdate < ApplicationRecord Gem::Version.new(version) end + def outdated? + runtime_version >= gem_version + end + + def pending? + gem_version > runtime_version + end + class << self def check_enabled? Rails.configuration.x.mastodon.software_update_url.present? @@ -30,11 +38,17 @@ class SoftwareUpdate < ApplicationRecord def pending_to_a return [] unless check_enabled? - all.to_a.filter { |update| update.gem_version > Mastodon::Version.gem_version } + all.to_a.filter(&:pending?) end def urgent_pending? pending_to_a.any?(&:urgent?) end end + + private + + def runtime_version + Mastodon::Version.gem_version + end end diff --git a/app/services/software_update_check_service.rb b/app/services/software_update_check_service.rb index 148f269289..45ec1f50db 100644 --- a/app/services/software_update_check_service.rb +++ b/app/services/software_update_check_service.rb @@ -12,7 +12,7 @@ class SoftwareUpdateCheckService < BaseService def clean_outdated_updates! SoftwareUpdate.find_each do |software_update| - software_update.delete if Mastodon::Version.gem_version >= software_update.gem_version + software_update.delete if software_update.outdated? rescue ArgumentError software_update.delete end diff --git a/spec/models/software_update_spec.rb b/spec/models/software_update_spec.rb index 0a494b0c4c..43e9cd058f 100644 --- a/spec/models/software_update_spec.rb +++ b/spec/models/software_update_spec.rb @@ -3,6 +3,60 @@ require 'rails_helper' RSpec.describe SoftwareUpdate do + describe '#pending?' do + subject { described_class.new(version: update_version) } + + before { allow(Mastodon::Version).to receive(:gem_version).and_return(Gem::Version.new(mastodon_version)) } + + context 'when the runtime version is older than the update' do + let(:mastodon_version) { '4.0.0' } + let(:update_version) { '5.0.0' } + + it { is_expected.to be_pending } + end + + context 'when the runtime version is newer than the update' do + let(:mastodon_version) { '6.0.0' } + let(:update_version) { '5.0.0' } + + it { is_expected.to_not be_pending } + end + + context 'when the runtime version is same as the update' do + let(:mastodon_version) { '4.0.0' } + let(:update_version) { '4.0.0' } + + it { is_expected.to_not be_pending } + end + end + + describe '#outdated?' do + subject { described_class.new(version: update_version) } + + before { allow(Mastodon::Version).to receive(:gem_version).and_return(Gem::Version.new(mastodon_version)) } + + context 'when the runtime version is older than the update' do + let(:mastodon_version) { '4.0.0' } + let(:update_version) { '5.0.0' } + + it { is_expected.to_not be_outdated } + end + + context 'when the runtime version is newer than the update' do + let(:mastodon_version) { '6.0.0' } + let(:update_version) { '5.0.0' } + + it { is_expected.to be_outdated } + end + + context 'when the runtime version is same as the update' do + let(:mastodon_version) { '4.0.0' } + let(:update_version) { '4.0.0' } + + it { is_expected.to be_outdated } + end + end + describe '.pending_to_a' do before do allow(Mastodon::Version).to receive(:gem_version).and_return(Gem::Version.new(mastodon_version)) diff --git a/spec/services/software_update_check_service_spec.rb b/spec/services/software_update_check_service_spec.rb index 4098bd470a..637e1e26c5 100644 --- a/spec/services/software_update_check_service_spec.rb +++ b/spec/services/software_update_check_service_spec.rb @@ -27,6 +27,7 @@ RSpec.describe SoftwareUpdateCheckService do before do Fabricate(:software_update, version: '3.5.0', type: 'major', urgent: false) Fabricate(:software_update, version: '42.13.12', type: 'major', urgent: false) + Fabricate(:software_update, version: 'Malformed', type: 'major', urgent: false) owner_user.settings.update('notification_emails.software_updates': 'all') owner_user.save! @@ -50,7 +51,7 @@ RSpec.describe SoftwareUpdateCheckService do end it 'deletes outdated update records but keeps valid update records' do - expect { subject.call }.to change { SoftwareUpdate.pluck(:version).sort }.from(['3.5.0', '42.13.12']).to(['42.13.12']) + expect { subject.call }.to change { SoftwareUpdate.pluck(:version).sort }.from(['3.5.0', '42.13.12', 'Malformed']).to(['42.13.12']) end end @@ -85,7 +86,7 @@ RSpec.describe SoftwareUpdateCheckService do end it 'updates the list of known updates' do - expect { subject.call }.to change { SoftwareUpdate.pluck(:version).sort }.from(['3.5.0', '42.13.12']).to(['4.2.1', '4.3.0', '5.0.0']) + expect { subject.call }.to change { SoftwareUpdate.pluck(:version).sort }.from(['3.5.0', '42.13.12', 'Malformed']).to(['4.2.1', '4.3.0', '5.0.0']) end context 'when no update is urgent' do From 2de018256ae2ec5e7a508aff6e0e7905ec517118 Mon Sep 17 00:00:00 2001 From: Claire Date: Thu, 14 Nov 2024 20:42:43 +0100 Subject: [PATCH 16/64] Fix filters not being correctly applied to boosted posts (#32895) --- app/javascript/mastodon/components/status.jsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/javascript/mastodon/components/status.jsx b/app/javascript/mastodon/components/status.jsx index f17f0367c1..95ea53521f 100644 --- a/app/javascript/mastodon/components/status.jsx +++ b/app/javascript/mastodon/components/status.jsx @@ -397,6 +397,7 @@ class Status extends ImmutablePureComponent { const connectUp = previousId && previousId === status.get('in_reply_to_id'); const connectToRoot = rootId && rootId === status.get('in_reply_to_id'); const connectReply = nextInReplyToId && nextInReplyToId === status.get('id'); + const matchedFilters = status.get('matched_filters'); if (featured) { prepend = ( @@ -432,7 +433,6 @@ class Status extends ImmutablePureComponent { ); } - const matchedFilters = status.get('matched_filters'); const expanded = (!matchedFilters || this.state.showDespiteFilter) && (!status.get('hidden') || status.get('spoiler_text').length === 0); if (hidden) { From ddfb3d123bb4195f0b086fe19bc90700fa5170b4 Mon Sep 17 00:00:00 2001 From: Emelia Smith Date: Fri, 15 Nov 2024 10:38:01 +0100 Subject: [PATCH 17/64] Improve display of statuses in admin panel (#30813) --- app/controllers/admin/statuses_controller.rb | 2 + .../admin/account_moderation_notes_helper.rb | 4 +- app/javascript/styles/mastodon/admin.scss | 28 +++++++ app/javascript/styles/mastodon/tables.scss | 16 ++-- app/views/admin/reports/_status.html.haml | 78 +++++++++++-------- app/views/admin/statuses/index.html.haml | 21 +++-- app/views/admin/statuses/show.html.haml | 64 ++++++++++++++- config/locales/an.yml | 2 +- config/locales/ar.yml | 2 +- config/locales/be.yml | 2 +- config/locales/bg.yml | 2 +- config/locales/br.yml | 2 +- config/locales/ca.yml | 2 +- config/locales/ckb.yml | 2 +- config/locales/co.yml | 2 +- config/locales/cs.yml | 2 +- config/locales/cy.yml | 2 +- config/locales/da.yml | 2 +- config/locales/de.yml | 2 +- config/locales/el.yml | 2 +- config/locales/en-GB.yml | 2 +- config/locales/en.yml | 8 +- config/locales/eo.yml | 2 +- config/locales/es-AR.yml | 2 +- config/locales/es-MX.yml | 2 +- config/locales/es.yml | 2 +- config/locales/et.yml | 2 +- config/locales/eu.yml | 2 +- config/locales/fa.yml | 2 +- config/locales/fi.yml | 2 +- config/locales/fo.yml | 2 +- config/locales/fr-CA.yml | 2 +- config/locales/fr.yml | 2 +- config/locales/fy.yml | 2 +- config/locales/ga.yml | 2 +- config/locales/gd.yml | 2 +- config/locales/gl.yml | 2 +- config/locales/he.yml | 2 +- config/locales/hu.yml | 2 +- config/locales/hy.yml | 2 +- config/locales/ia.yml | 2 +- config/locales/id.yml | 2 +- config/locales/ie.yml | 2 +- config/locales/io.yml | 2 +- config/locales/is.yml | 2 +- config/locales/it.yml | 2 +- config/locales/ja.yml | 2 +- config/locales/ka.yml | 2 +- config/locales/kab.yml | 2 +- config/locales/kk.yml | 2 +- config/locales/ko.yml | 2 +- config/locales/ku.yml | 2 +- config/locales/lad.yml | 2 +- config/locales/lt.yml | 2 +- config/locales/lv.yml | 2 +- config/locales/ms.yml | 2 +- config/locales/my.yml | 2 +- config/locales/nl.yml | 2 +- config/locales/nn.yml | 2 +- config/locales/no.yml | 2 +- config/locales/oc.yml | 2 +- config/locales/pl.yml | 2 +- config/locales/pt-BR.yml | 2 +- config/locales/pt-PT.yml | 2 +- config/locales/ru.yml | 2 +- config/locales/sc.yml | 2 +- config/locales/sco.yml | 2 +- config/locales/si.yml | 2 +- config/locales/sk.yml | 2 +- config/locales/sl.yml | 2 +- config/locales/sq.yml | 2 +- config/locales/sr-Latn.yml | 2 +- config/locales/sr.yml | 2 +- config/locales/sv.yml | 2 +- config/locales/th.yml | 2 +- config/locales/tr.yml | 2 +- config/locales/uk.yml | 2 +- config/locales/vi.yml | 2 +- config/locales/zh-CN.yml | 2 +- config/locales/zh-HK.yml | 2 +- config/locales/zh-TW.yml | 2 +- 81 files changed, 236 insertions(+), 131 deletions(-) diff --git a/app/controllers/admin/statuses_controller.rb b/app/controllers/admin/statuses_controller.rb index e53b22dca3..40d1a481b2 100644 --- a/app/controllers/admin/statuses_controller.rb +++ b/app/controllers/admin/statuses_controller.rb @@ -16,6 +16,8 @@ module Admin def show authorize [:admin, @status], :show? + + @status_batch_action = Admin::StatusBatchAction.new end def batch diff --git a/app/helpers/admin/account_moderation_notes_helper.rb b/app/helpers/admin/account_moderation_notes_helper.rb index 2a3d954a35..7c931c1157 100644 --- a/app/helpers/admin/account_moderation_notes_helper.rb +++ b/app/helpers/admin/account_moderation_notes_helper.rb @@ -12,12 +12,12 @@ module Admin::AccountModerationNotesHelper ) end - def admin_account_inline_link_to(account) + def admin_account_inline_link_to(account, path: nil) return if account.nil? link_to( account_inline_text(account), - admin_account_path(account.id), + path || admin_account_path(account.id), class: class_names('inline-name-tag', suspended: suspended_account?(account)), title: account.acct ) diff --git a/app/javascript/styles/mastodon/admin.scss b/app/javascript/styles/mastodon/admin.scss index c7b32a9c9e..579b2a4f69 100644 --- a/app/javascript/styles/mastodon/admin.scss +++ b/app/javascript/styles/mastodon/admin.scss @@ -1922,3 +1922,31 @@ a.sparkline { } } } + +.status__card { + padding: 15px; + border-radius: 4px; + background: $ui-base-color; + font-size: 15px; + line-height: 20px; + word-wrap: break-word; + font-weight: 400; + border: 1px solid lighten($ui-base-color, 4%); + color: $primary-text-color; + box-sizing: border-box; + min-height: 100%; + + .status__prepend { + padding: 0 0 15px; + gap: 4px; + align-items: center; + } + + .status__content { + padding-top: 0; + + summary { + display: list-item; + } + } +} diff --git a/app/javascript/styles/mastodon/tables.scss b/app/javascript/styles/mastodon/tables.scss index 0cbf5c1d55..07d1ce12fd 100644 --- a/app/javascript/styles/mastodon/tables.scss +++ b/app/javascript/styles/mastodon/tables.scss @@ -339,16 +339,12 @@ a.table-action-link { } } - .status__content { - padding-top: 0; - - summary { - display: list-item; - } - - strong { - font-weight: 700; - } + // Reset the status card to not have borders, background or padding when + // inline in the table of statuses + .status__card { + border: none; + background: none; + padding: 0; } .nothing-here { diff --git a/app/views/admin/reports/_status.html.haml b/app/views/admin/reports/_status.html.haml index f4630ed25a..3a35fdd272 100644 --- a/app/views/admin/reports/_status.html.haml +++ b/app/views/admin/reports/_status.html.haml @@ -2,40 +2,52 @@ %label.batch-table__row__select.batch-checkbox = f.check_box :status_ids, { multiple: true, include_hidden: false }, status.id .batch-table__row__content - .status__content>< - - if status.proper.spoiler_text.blank? - = prerender_custom_emojis(status_content_format(status.proper), status.proper.emojis) - - else - %details< - %summary>< - %strong> Content warning: #{prerender_custom_emojis(h(status.proper.spoiler_text), status.proper.emojis)} - = prerender_custom_emojis(status_content_format(status.proper), status.proper.emojis) - - - unless status.proper.ordered_media_attachments.empty? - = render partial: 'admin/reports/media_attachments', locals: { status: status.proper } - - .detailed-status__meta - - if status.application - = status.application.name - · - = link_to ActivityPub::TagManager.instance.url_for(status.proper), class: 'detailed-status__datetime', target: stream_link_target, rel: 'noopener noreferrer' do - %time.formatted{ datetime: status.created_at.iso8601, title: l(status.created_at) }= l(status.created_at) - - if status.edited? - · - = link_to t('statuses.edited_at_html', date: content_tag(:time, l(status.edited_at), datetime: status.edited_at.iso8601, title: l(status.edited_at), class: 'formatted')), - admin_account_status_path(status.account_id, status), - class: 'detailed-status__datetime' - - if status.discarded? - · - %span.negative-hint= t('admin.statuses.deleted') - · + .status__card - if status.reblog? - = material_symbol('repeat_active') - = t('statuses.boosted_from_html', acct_link: admin_account_inline_link_to(status.proper.account)) - - else + .status__prepend + = material_symbol('repeat') + = t('statuses.boosted_from_html', acct_link: admin_account_inline_link_to(status.proper.account, path: admin_account_status_path(status.proper.account.id, status.proper.id))) + - elsif status.reply? && status.in_reply_to_id.present? + .status__prepend + = material_symbol('reply') + = t('admin.statuses.replied_to_html', acct_link: admin_account_inline_link_to(status.in_reply_to_account, path: admin_account_status_path(status.thread.account_id, status.in_reply_to_id))) + .status__content>< + - if status.proper.spoiler_text.blank? + = prerender_custom_emojis(status_content_format(status.proper), status.proper.emojis) + - else + %details< + %summary>< + %strong> Content warning: #{prerender_custom_emojis(h(status.proper.spoiler_text), status.proper.emojis)} + = prerender_custom_emojis(status_content_format(status.proper), status.proper.emojis) + + - unless status.proper.ordered_media_attachments.empty? + = render partial: 'admin/reports/media_attachments', locals: { status: status.proper } + + .detailed-status__meta + - if status.application + = status.application.name + · + + = link_to admin_account_status_path(status.account.id, status), class: 'detailed-status__datetime' do + %time.formatted{ datetime: status.created_at.iso8601, title: l(status.created_at) }= l(status.created_at) + - if status.edited? + · + = link_to t('statuses.edited_at_html', date: content_tag(:time, l(status.edited_at), datetime: status.edited_at.iso8601, title: l(status.edited_at), class: 'formatted')), + admin_account_status_path(status.account_id, status), + class: 'detailed-status__datetime' + - if status.discarded? + · + %span.negative-hint= t('admin.statuses.deleted') + · + = material_symbol visibility_icon(status) = t("statuses.visibilities.#{status.visibility}") - - if status.proper.sensitive? · - = material_symbol('visibility_off') - = t('stream_entries.sensitive_content') + + = link_to ActivityPub::TagManager.instance.url_for(status.proper), class: 'detailed-status__link', target: stream_link_target, rel: 'noopener noreferrer' do + = t('admin.statuses.view_publicly') + + - if status.proper.sensitive? + · + = material_symbol('visibility_off') + = t('stream_entries.sensitive_content') diff --git a/app/views/admin/statuses/index.html.haml b/app/views/admin/statuses/index.html.haml index 4d5d037060..57b9fe0e15 100644 --- a/app/views/admin/statuses/index.html.haml +++ b/app/views/admin/statuses/index.html.haml @@ -1,7 +1,5 @@ - content_for :page_title do - = t('admin.statuses.title') - \- - @#{@account.pretty_acct} + = t('admin.statuses.title', name: @account.pretty_acct) .filters .filter-subset @@ -33,11 +31,18 @@ = check_box_tag :batch_checkbox_all, nil, false .batch-table__toolbar__actions - unless @statuses.empty? - = f.button safe_join([material_symbol('flag'), t('admin.statuses.batch.report')]), - class: 'table-action-link', - data: { confirm: t('admin.reports.are_you_sure') }, - name: :report, - type: :submit + - if params[:report_id] + = f.button safe_join([material_symbol('add'), t('admin.statuses.batch.add_to_report', id: params[:report_id])]), + class: 'table-action-link', + data: { confirm: t('admin.reports.are_you_sure') }, + name: :report, + type: :submit + - else + = f.button safe_join([material_symbol('flag'), t('admin.statuses.batch.report')]), + class: 'table-action-link', + data: { confirm: t('admin.reports.are_you_sure') }, + name: :report, + type: :submit .batch-table__body - if @statuses.empty? = nothing_here 'nothing-here--under-tabs' diff --git a/app/views/admin/statuses/show.html.haml b/app/views/admin/statuses/show.html.haml index 9cadde2870..49c23e921c 100644 --- a/app/views/admin/statuses/show.html.haml +++ b/app/views/admin/statuses/show.html.haml @@ -1,7 +1,14 @@ - content_for :page_title do - = t('statuses.title', name: display_name(@account), quote: truncate(@status.spoiler_text.presence || @status.text, length: 50, omission: '…', escape: false)) + = t('admin.statuses.status_title', name: @account.pretty_acct) - content_for :heading_actions do + = form_with model: @status_batch_action, url: batch_admin_account_statuses_path(@account.id) do |f| + = f.hidden_field :status_ids, { multiple: true, value: @status.id } + = f.button safe_join([material_symbol('flag'), t('admin.statuses.batch.report')]), + class: 'button', + data: { confirm: t('admin.reports.are_you_sure') }, + name: :report, + type: :submit = link_to t('admin.statuses.open'), ActivityPub::TagManager.instance.url_for(@status), class: 'button', target: '_blank', rel: 'noopener noreferrer' %h3= t('admin.statuses.metadata') @@ -44,7 +51,56 @@ %hr.spacer/ -%h3= t('admin.statuses.history') +%h3= t('admin.statuses.contents') -%ol.history - = render partial: 'admin/status_edits/status_edit', collection: batched_ordered_status_edits +.status__card + - if @status.reblog? + .status__prepend + = material_symbol('repeat') + = t('statuses.boosted_from_html', acct_link: admin_account_inline_link_to(@status.proper.account, path: admin_account_status_path(@status.proper.account.id, @status.proper.id))) + - elsif @status.reply? && @status.in_reply_to_id.present? + .status__prepend + = material_symbol('reply') + = t('admin.statuses.replied_to_html', acct_link: admin_account_inline_link_to(@status.in_reply_to_account, path: admin_account_status_path(@status.thread.account_id, @status.in_reply_to_id))) + .status__content>< + - if @status.proper.spoiler_text.blank? + = prerender_custom_emojis(status_content_format(@status.proper), @status.proper.emojis) + - else + %details< + %summary>< + %strong> Content warning: #{prerender_custom_emojis(h(@status.proper.spoiler_text), @status.proper.emojis)} + = prerender_custom_emojis(status_content_format(@status.proper), @status.proper.emojis) + + - unless @status.proper.ordered_media_attachments.empty? + = render partial: 'admin/reports/media_attachments', locals: { status: @status.proper } + + .detailed-status__meta + - if @status.application + = @status.application.name + · + %span.detailed-status__datetime + %time.formatted{ datetime: @status.created_at.iso8601, title: l(@status.created_at) }= l(@status.created_at) + - if @status.edited? + · + %span.detailed-status__datetime + = t('statuses.edited_at_html', date: content_tag(:time, l(@status.edited_at), datetime: @status.edited_at.iso8601, title: l(@status.edited_at), class: 'formatted')) + - if @status.discarded? + · + %span.negative-hint= t('admin.statuses.deleted') + - unless @status.reblog? + · + = material_symbol(visibility_icon(@status)) + = t("statuses.visibilities.#{@status.visibility}") + - if @status.proper.sensitive? + · + = material_symbol('visibility_off') + = t('stream_entries.sensitive_content') + +%hr.spacer/ + +%h3= t('admin.statuses.history') +- if @status.edits.empty? + %p= t('admin.statuses.no_history') +- else + %ol.history + = render partial: 'admin/status_edits/status_edit', collection: batched_ordered_status_edits diff --git a/config/locales/an.yml b/config/locales/an.yml index 2db042f1b1..43f8d358cc 100644 --- a/config/locales/an.yml +++ b/config/locales/an.yml @@ -723,7 +723,7 @@ an: original_status: Publicación orichinal reblogs: Impulsos status_changed: Publicación cambiada - title: Estau d'as cuentas + title: Estau d'as cuentas - @%{name} trending: En tendencia visibility: Visibilidat with_media: Con multimedia diff --git a/config/locales/ar.yml b/config/locales/ar.yml index 1a6f0da8c6..bbc481a137 100644 --- a/config/locales/ar.yml +++ b/config/locales/ar.yml @@ -847,7 +847,7 @@ ar: original_status: المنشور الأصلي reblogs: المعاد تدوينها status_changed: عُدّل المنشور - title: منشورات الحساب + title: منشورات الحساب - @%{name} trending: المتداولة visibility: مدى الظهور with_media: تحتوي على وسائط diff --git a/config/locales/be.yml b/config/locales/be.yml index b627672b2d..c59233eb8b 100644 --- a/config/locales/be.yml +++ b/config/locales/be.yml @@ -856,7 +856,7 @@ be: original_status: Зыходны допіс reblogs: Рэпосты status_changed: Допіс зменены - title: Допісы уліковага запісу + title: Допісы уліковага запісу - @%{name} trending: Папулярныя visibility: Бачнасць with_media: З медыя diff --git a/config/locales/bg.yml b/config/locales/bg.yml index 7181b35b6d..e10ce3197c 100644 --- a/config/locales/bg.yml +++ b/config/locales/bg.yml @@ -803,7 +803,7 @@ bg: original_status: Първообразна публикация reblogs: Блогване пак status_changed: Публикацията променена - title: Публикации на акаунта + title: Публикации на акаунта - @%{name} trending: Изгряващи visibility: Видимост with_media: С мултимедия diff --git a/config/locales/br.yml b/config/locales/br.yml index f9fbd34adb..098b20934f 100644 --- a/config/locales/br.yml +++ b/config/locales/br.yml @@ -263,7 +263,7 @@ br: original_status: Toud orin reblogs: Skignadennoù status_changed: Toud kemmet - title: Toudoù ar gont + title: Toudoù ar gont - @%{name} visibility: Gwelusted with_media: Gant mediaoù strikes: diff --git a/config/locales/ca.yml b/config/locales/ca.yml index 00c8f57a85..970fd99fff 100644 --- a/config/locales/ca.yml +++ b/config/locales/ca.yml @@ -841,7 +841,7 @@ ca: original_status: Publicació original reblogs: Impulsos status_changed: Publicació canviada - title: Estats del compte + title: Estats del compte - @%{name} trending: Tendència visibility: Visibilitat with_media: Amb contingut multimèdia diff --git a/config/locales/ckb.yml b/config/locales/ckb.yml index 88dadff014..6e1b11379c 100644 --- a/config/locales/ckb.yml +++ b/config/locales/ckb.yml @@ -520,7 +520,7 @@ ckb: media: title: میدیا no_status_selected: هیچ دۆخیک نەگۆڕاوە وەک ئەوەی هیچ بارێک دەستنیشان نەکراوە - title: دۆخی ئەژمێر + title: دۆخی ئەژمێر - @%{name} with_media: بە میدیا tags: review: پێداچوونەوەی دۆخ diff --git a/config/locales/co.yml b/config/locales/co.yml index dad3e08ffd..b81427e833 100644 --- a/config/locales/co.yml +++ b/config/locales/co.yml @@ -459,7 +459,7 @@ co: media: title: Media no_status_selected: I statuti ùn sò micca stati mudificati perchè manc'unu era selezziunatu - title: Statuti di u contu + title: Statuti di u contu - @%{name} with_media: Cù media system_checks: rules_check: diff --git a/config/locales/cs.yml b/config/locales/cs.yml index 15211b928a..f5f7f4d731 100644 --- a/config/locales/cs.yml +++ b/config/locales/cs.yml @@ -826,7 +826,7 @@ cs: original_status: Původní příspěvek reblogs: Boosty status_changed: Příspěvek změněn - title: Příspěvky účtu + title: Příspěvky účtu - @%{name} trending: Populární visibility: Viditelnost with_media: S médii diff --git a/config/locales/cy.yml b/config/locales/cy.yml index 2d6a0eb38d..ca18de17bc 100644 --- a/config/locales/cy.yml +++ b/config/locales/cy.yml @@ -889,7 +889,7 @@ cy: original_status: Postiad gwreiddiol reblogs: Ailflogiadau status_changed: Postiad wedi'i newid - title: Postiadau cyfrif + title: Postiadau cyfrif - @%{name} trending: Yn trendio visibility: Gwelededd with_media: Gyda chyfryngau diff --git a/config/locales/da.yml b/config/locales/da.yml index daf683637d..e157af9cc2 100644 --- a/config/locales/da.yml +++ b/config/locales/da.yml @@ -841,7 +841,7 @@ da: original_status: Oprindeligt indlæg reblogs: Genblogninger status_changed: Indlæg ændret - title: Kontoindlæg + title: Kontoindlæg - @%{name} trending: Populære visibility: Synlighed with_media: Med medier diff --git a/config/locales/de.yml b/config/locales/de.yml index 10223f2278..e3ee03264e 100644 --- a/config/locales/de.yml +++ b/config/locales/de.yml @@ -841,7 +841,7 @@ de: original_status: Ursprünglicher Beitrag reblogs: Geteilte Beiträge status_changed: Beitrag bearbeitet - title: Beiträge des Kontos + title: Beiträge des Kontos - @%{name} trending: Trends visibility: Sichtbarkeit with_media: Mit Medien diff --git a/config/locales/el.yml b/config/locales/el.yml index 3a145cbdab..26b0ec00a2 100644 --- a/config/locales/el.yml +++ b/config/locales/el.yml @@ -817,7 +817,7 @@ el: original_status: Αρχική ανάρτηση reblogs: Αναδημοσιεύσεις status_changed: Η ανάρτηση άλλαξε - title: Καταστάσεις λογαριασμού + title: Καταστάσεις λογαριασμού - @%{name} trending: Τάσεις visibility: Ορατότητα with_media: Με πολυμέσα diff --git a/config/locales/en-GB.yml b/config/locales/en-GB.yml index fb284479f2..e22ed62051 100644 --- a/config/locales/en-GB.yml +++ b/config/locales/en-GB.yml @@ -832,7 +832,7 @@ en-GB: original_status: Original post reblogs: Reblogs status_changed: Post changed - title: Account posts + title: Account posts - @%{name} trending: Trending visibility: Visibility with_media: With media diff --git a/config/locales/en.yml b/config/locales/en.yml index cf783338e2..2971fe1f25 100644 --- a/config/locales/en.yml +++ b/config/locales/en.yml @@ -826,8 +826,10 @@ en: back_to_account: Back to account page back_to_report: Back to report page batch: + add_to_report: 'Add to report #%{id}' remove_from_report: Remove from report report: Report + contents: Contents deleted: Deleted favourites: Favorites history: Version history @@ -836,13 +838,17 @@ en: media: title: Media metadata: Metadata + no_history: This post hasn't been edited no_status_selected: No posts were changed as none were selected open: Open post original_status: Original post reblogs: Reblogs + replied_to_html: Replied to %{acct_link} status_changed: Post changed - title: Account posts + status_title: Post by @%{name} + title: Account posts - @%{name} trending: Trending + view_publicly: View publicly visibility: Visibility with_media: With media strikes: diff --git a/config/locales/eo.yml b/config/locales/eo.yml index 12cae075f0..b5287d9e2a 100644 --- a/config/locales/eo.yml +++ b/config/locales/eo.yml @@ -814,7 +814,7 @@ eo: original_status: Originala afiŝo reblogs: Reblogaĵoj status_changed: Afiŝo ŝanĝiĝis - title: Afiŝoj de la konto + title: Afiŝoj de la konto - @%{name} trending: Popularaĵoj visibility: Videbleco with_media: Kun aŭdovidaĵoj diff --git a/config/locales/es-AR.yml b/config/locales/es-AR.yml index 79bfdfbdbf..6dc9d99f37 100644 --- a/config/locales/es-AR.yml +++ b/config/locales/es-AR.yml @@ -833,7 +833,7 @@ es-AR: original_status: Mensaje original reblogs: Adhesiones status_changed: Mensaje cambiado - title: Mensajes de la cuenta + title: Mensajes de la cuenta - @%{name} trending: En tendencia visibility: Visibilidad with_media: Con medios diff --git a/config/locales/es-MX.yml b/config/locales/es-MX.yml index fef805680a..7e6570f068 100644 --- a/config/locales/es-MX.yml +++ b/config/locales/es-MX.yml @@ -833,7 +833,7 @@ es-MX: original_status: Publicación original reblogs: Impulsos status_changed: Publicación cambiada - title: Estado de las cuentas + title: Estado de las cuentas - @%{name} trending: En tendencia visibility: Visibilidad with_media: Con multimedia diff --git a/config/locales/es.yml b/config/locales/es.yml index ddd53a2387..32abd9420d 100644 --- a/config/locales/es.yml +++ b/config/locales/es.yml @@ -833,7 +833,7 @@ es: original_status: Publicación original reblogs: Impulsos status_changed: Publicación cambiada - title: Publicaciones de la cuenta + title: Publicaciones de la cuenta - @%{name} trending: En tendencia visibility: Visibilidad with_media: Con multimedia diff --git a/config/locales/et.yml b/config/locales/et.yml index 3be9add91c..f8a4f7f69e 100644 --- a/config/locales/et.yml +++ b/config/locales/et.yml @@ -833,7 +833,7 @@ et: original_status: Algne postitus reblogs: Jagamised status_changed: Muudetud postitus - title: Konto postitused + title: Konto postitused - @%{name} trending: Populaarne visibility: Nähtavus with_media: Meediaga diff --git a/config/locales/eu.yml b/config/locales/eu.yml index e9c3be2d24..a764e88bac 100644 --- a/config/locales/eu.yml +++ b/config/locales/eu.yml @@ -793,7 +793,7 @@ eu: original_status: Jatorrizko bidalketa reblogs: Bultzadak status_changed: Bidalketa aldatuta - title: Kontuaren bidalketak + title: Kontuaren bidalketak - @%{name} trending: Joera visibility: Ikusgaitasuna with_media: Multimediarekin diff --git a/config/locales/fa.yml b/config/locales/fa.yml index 603cfe8de1..38daf70d29 100644 --- a/config/locales/fa.yml +++ b/config/locales/fa.yml @@ -741,7 +741,7 @@ fa: original_status: فرستهٔ اصلی reblogs: تقویت‌ها status_changed: فرسته تغییر کرد - title: نوشته‌های حساب + title: "@%{name} - نوشته‌های حساب" trending: پرطرفدار visibility: نمایانی with_media: دارای عکس یا ویدیو diff --git a/config/locales/fi.yml b/config/locales/fi.yml index 6fe9c14591..efdfdfed04 100644 --- a/config/locales/fi.yml +++ b/config/locales/fi.yml @@ -841,7 +841,7 @@ fi: original_status: Alkuperäinen julkaisu reblogs: Edelleen jako status_changed: Julkaisua muutettu - title: Tilin tilat + title: Tilin tilat - @%{name} trending: Suosituttua visibility: Näkyvyys with_media: Sisältää mediaa diff --git a/config/locales/fo.yml b/config/locales/fo.yml index 6cc1fda6a0..8dab61c267 100644 --- a/config/locales/fo.yml +++ b/config/locales/fo.yml @@ -841,7 +841,7 @@ fo: original_status: Upprunapostur reblogs: Endurbloggar status_changed: Postur broyttur - title: Postar hjá kontu + title: Postar hjá kontu - @%{name} trending: Vælumtókt visibility: Sýni with_media: Við miðli diff --git a/config/locales/fr-CA.yml b/config/locales/fr-CA.yml index 3c771d4c64..bb0501d0e3 100644 --- a/config/locales/fr-CA.yml +++ b/config/locales/fr-CA.yml @@ -836,7 +836,7 @@ fr-CA: original_status: Message original reblogs: Partages status_changed: Publication modifiée - title: Messages du compte + title: Messages du compte - @%{name} trending: Tendances visibility: Visibilité with_media: Avec médias diff --git a/config/locales/fr.yml b/config/locales/fr.yml index 58fc63fc1b..0c35dea62a 100644 --- a/config/locales/fr.yml +++ b/config/locales/fr.yml @@ -836,7 +836,7 @@ fr: original_status: Message original reblogs: Partages status_changed: Publication modifiée - title: Messages du compte + title: Messages du compte - @%{name} trending: Tendances visibility: Visibilité with_media: Avec médias diff --git a/config/locales/fy.yml b/config/locales/fy.yml index a6656f91b8..8a4f519e0c 100644 --- a/config/locales/fy.yml +++ b/config/locales/fy.yml @@ -833,7 +833,7 @@ fy: original_status: Oarspronklik berjocht reblogs: Boosts status_changed: Berjocht wizige - title: Accountberjochten + title: Accountberjochten - @%{name} trending: Trending visibility: Sichtberheid with_media: Mei media diff --git a/config/locales/ga.yml b/config/locales/ga.yml index 5e5ecb238e..67461f3c2a 100644 --- a/config/locales/ga.yml +++ b/config/locales/ga.yml @@ -875,7 +875,7 @@ ga: original_status: Bunphostáil reblogs: Athbhlaganna status_changed: Athraíodh postáil - title: Poist chuntais + title: Poist chuntais - @%{name} trending: Ag treochtáil visibility: Infheictheacht with_media: Le meáin diff --git a/config/locales/gd.yml b/config/locales/gd.yml index c804f42523..89198bd514 100644 --- a/config/locales/gd.yml +++ b/config/locales/gd.yml @@ -861,7 +861,7 @@ gd: original_status: Am post tùsail reblogs: Brosnachaidhean status_changed: Post air atharrachadh - title: Postaichean a’ chunntais + title: Postaichean a’ chunntais - @%{name} trending: A’ treandadh visibility: Faicsinneachd with_media: Le meadhanan riutha diff --git a/config/locales/gl.yml b/config/locales/gl.yml index 1ad8deb179..0f3420a7f3 100644 --- a/config/locales/gl.yml +++ b/config/locales/gl.yml @@ -841,7 +841,7 @@ gl: original_status: Publicación orixinal reblogs: Promocións status_changed: Publicación editada - title: Publicacións da conta + title: Publicacións da conta - @%{name} trending: Popular visibility: Visibilidade with_media: con medios diff --git a/config/locales/he.yml b/config/locales/he.yml index 10b4611b9a..59dc09799d 100644 --- a/config/locales/he.yml +++ b/config/locales/he.yml @@ -861,7 +861,7 @@ he: original_status: הודעה מקורית reblogs: שיתופים status_changed: הודעה שונתה - title: הודעות החשבון + title: הודעות החשבון - @%{name} trending: נושאים חמים visibility: נראות with_media: עם מדיה diff --git a/config/locales/hu.yml b/config/locales/hu.yml index 1892009238..da4ff78dc4 100644 --- a/config/locales/hu.yml +++ b/config/locales/hu.yml @@ -841,7 +841,7 @@ hu: original_status: Eredeti bejegyzés reblogs: Megosztások status_changed: A bejegyzés megváltozott - title: Fiók bejegyzései + title: Fiók bejegyzései - @%{name} trending: Felkapott visibility: Láthatóság with_media: Médiával diff --git a/config/locales/hy.yml b/config/locales/hy.yml index 201922d102..d8cf2a97ba 100644 --- a/config/locales/hy.yml +++ b/config/locales/hy.yml @@ -402,7 +402,7 @@ hy: deleted: Ջնջված է media: title: Մեդիա - title: Օգտատիրոջ գրառումները + title: Օգտատիրոջ գրառումները - @%{name} with_media: Մեդիայի հետ tags: review: Վերանայել գրառումը diff --git a/config/locales/ia.yml b/config/locales/ia.yml index 843e8724b9..1398ae51d4 100644 --- a/config/locales/ia.yml +++ b/config/locales/ia.yml @@ -833,7 +833,7 @@ ia: original_status: Message original reblogs: Republicationes status_changed: Message cambiate - title: Messages del conto + title: Messages del conto - @%{name} trending: Tendentias visibility: Visibilitate with_media: Con multimedia diff --git a/config/locales/id.yml b/config/locales/id.yml index 6a005fddaa..9c31daf420 100644 --- a/config/locales/id.yml +++ b/config/locales/id.yml @@ -711,7 +711,7 @@ id: original_status: Kiriman asli reblogs: Reblog status_changed: Kiriman diubah - title: Status akun + title: Status akun - @%{name} trending: Sedang tren visibility: Visibilitas with_media: Dengan media diff --git a/config/locales/ie.yml b/config/locales/ie.yml index 94c4b7f4f0..d7df83ef69 100644 --- a/config/locales/ie.yml +++ b/config/locales/ie.yml @@ -791,7 +791,7 @@ ie: original_status: Original posta reblogs: Boosts status_changed: Posta modificat - title: Postas del conto + title: Postas del conto - @%{name} trending: Populari visibility: Visibilitá with_media: Con medie diff --git a/config/locales/io.yml b/config/locales/io.yml index 8ce5f3403b..1ff5d98bf2 100644 --- a/config/locales/io.yml +++ b/config/locales/io.yml @@ -779,7 +779,7 @@ io: original_status: Originala posto reblogs: Dissemi status_changed: Posto chanjita - title: Kontoposti + title: Kontoposti - @%{name} trending: Populara visibility: Videbleso with_media: Kun medii diff --git a/config/locales/is.yml b/config/locales/is.yml index 552df8f064..9ba29f2af0 100644 --- a/config/locales/is.yml +++ b/config/locales/is.yml @@ -843,7 +843,7 @@ is: original_status: Upprunaleg færsla reblogs: Endurbirtingar status_changed: Færslu breytt - title: Færslur notandaaðgangs + title: Færslur notandaaðgangs - @%{name} trending: Vinsælt visibility: Sýnileiki with_media: Með myndefni diff --git a/config/locales/it.yml b/config/locales/it.yml index e18cb0e8f6..08e224ad94 100644 --- a/config/locales/it.yml +++ b/config/locales/it.yml @@ -833,7 +833,7 @@ it: original_status: Post originale reblogs: Condivisioni status_changed: Post modificato - title: Gli status dell'account + title: Gli status dell'account - @%{name} trending: Di tendenza visibility: Visibilità with_media: con media diff --git a/config/locales/ja.yml b/config/locales/ja.yml index a70ae680e4..76152c3744 100644 --- a/config/locales/ja.yml +++ b/config/locales/ja.yml @@ -819,7 +819,7 @@ ja: original_status: オリジナルの投稿 reblogs: ブースト status_changed: 投稿を変更しました - title: 投稿一覧 + title: 投稿一覧 - @%{name} trending: トレンド visibility: 公開範囲 with_media: メディアあり diff --git a/config/locales/ka.yml b/config/locales/ka.yml index 2a0365fbf5..93f7a39dc3 100644 --- a/config/locales/ka.yml +++ b/config/locales/ka.yml @@ -190,7 +190,7 @@ ka: media: title: მედია no_status_selected: სატუსები არ შეცვლილა, რადგან არცერთი არ მონიშნულა - title: ანგარიშის სტატუსები + title: ანგარიშის სტატუსები - @%{name} with_media: მედიით title: ადმინისტრაცია admin_mailer: diff --git a/config/locales/kab.yml b/config/locales/kab.yml index 993488f1fc..c74540cfbf 100644 --- a/config/locales/kab.yml +++ b/config/locales/kab.yml @@ -419,7 +419,7 @@ kab: media: title: Amidya open: Ldi tasuffeɣt - title: Tisuffaɣ n umiḍan + title: Tisuffaɣ n umiḍan - @%{name} trending: Ayen mucaɛen visibility: Abani with_media: S umidya diff --git a/config/locales/kk.yml b/config/locales/kk.yml index 537104ba51..4b9cef245e 100644 --- a/config/locales/kk.yml +++ b/config/locales/kk.yml @@ -285,7 +285,7 @@ kk: media: title: Медиa no_status_selected: Бірде-бір статус өзгерген жоқ, себебі ештеңе таңдалмады - title: Аккаунт статустары + title: Аккаунт статустары - @%{name} with_media: Медиамен tags: review: Статусты көрсету diff --git a/config/locales/ko.yml b/config/locales/ko.yml index 1fe43f7e75..36a13397d0 100644 --- a/config/locales/ko.yml +++ b/config/locales/ko.yml @@ -829,7 +829,7 @@ ko: original_status: 원본 게시물 reblogs: 리블로그 status_changed: 게시물 변경됨 - title: 계정 게시물 + title: 계정 게시물 - @%{name} trending: 유행 중 visibility: 공개 설정 with_media: 미디어 있음 diff --git a/config/locales/ku.yml b/config/locales/ku.yml index ddd214441c..54188d2514 100644 --- a/config/locales/ku.yml +++ b/config/locales/ku.yml @@ -720,7 +720,7 @@ ku: original_status: Şandiyê resen reblogs: Ji nû ve nivîsandin status_changed: Şandî hate guhertin - title: Şandiyên ajimêr + title: Şandiyên ajimêr - @%{name} trending: Rojev visibility: Xuyabarî with_media: Bi medya yê re diff --git a/config/locales/lad.yml b/config/locales/lad.yml index 4486df637e..3b33888c71 100644 --- a/config/locales/lad.yml +++ b/config/locales/lad.yml @@ -825,7 +825,7 @@ lad: original_status: Publikasyon orijinala reblogs: Repartajasyones status_changed: Publikasyon trokada - title: Publikasyones del kuento + title: Publikasyones del kuento - @%{name} trending: Trendes visibility: Vizivilita with_media: Kon multimedia diff --git a/config/locales/lt.yml b/config/locales/lt.yml index 3850e2e071..3519cb5b32 100644 --- a/config/locales/lt.yml +++ b/config/locales/lt.yml @@ -601,7 +601,7 @@ lt: no_status_selected: Jokie įrašai nebuvo pakeisti, nes nė vienas buvo pasirinktas open: Atidaryti įrašą original_status: Originalus įrašas - title: Paskyros statusai + title: Paskyros statusai - @%{name} trending: Tendencinga with_media: Su medija system_checks: diff --git a/config/locales/lv.yml b/config/locales/lv.yml index 3e5a1db00e..d793c8e196 100644 --- a/config/locales/lv.yml +++ b/config/locales/lv.yml @@ -830,7 +830,7 @@ lv: original_status: Oriģinālā ziņa reblogs: Reblogi status_changed: Ziņa mainīta - title: Konta ziņas + title: Konta ziņas - @%{name} trending: Aktuāli visibility: Redzamība with_media: Ar multividi diff --git a/config/locales/ms.yml b/config/locales/ms.yml index 90493a30b6..76f914dd16 100644 --- a/config/locales/ms.yml +++ b/config/locales/ms.yml @@ -768,7 +768,7 @@ ms: original_status: Hantaran asal reblogs: Ulang siar status_changed: Hantaran diubah - title: Hantaran akaun + title: Hantaran akaun - @%{name} trending: Sohor kini visibility: Visibiliti with_media: Dengan media diff --git a/config/locales/my.yml b/config/locales/my.yml index 6a330a16c7..b238abb051 100644 --- a/config/locales/my.yml +++ b/config/locales/my.yml @@ -764,7 +764,7 @@ my: original_status: မူရင်းပို့စ် reblogs: Reblog များ status_changed: ပို့စ်ပြောင်းပြီးပါပြီ - title: အကောင့်ပို့စ်များ + title: "@%{name} - အကောင့်ပို့စ်များ" trending: လက်ရှိခေတ်စားနေခြင်း visibility: မြင်နိုင်မှု with_media: မီဒီယာနှင့်အတူ diff --git a/config/locales/nl.yml b/config/locales/nl.yml index 1af30bca98..d4a88b3bea 100644 --- a/config/locales/nl.yml +++ b/config/locales/nl.yml @@ -833,7 +833,7 @@ nl: original_status: Oorspronkelijk bericht reblogs: Boosts status_changed: Bericht veranderd - title: Berichten van account + title: Berichten van account - @%{name} trending: Trending visibility: Zichtbaarheid with_media: Met media diff --git a/config/locales/nn.yml b/config/locales/nn.yml index 62b08f42ed..e04c0168f2 100644 --- a/config/locales/nn.yml +++ b/config/locales/nn.yml @@ -841,7 +841,7 @@ nn: original_status: Opprinnelig innlegg reblogs: Framhevingar status_changed: Innlegg endret - title: Kontostatusar + title: Kontostatusar - @%{name} trending: Populært visibility: Synlighet with_media: Med media diff --git a/config/locales/no.yml b/config/locales/no.yml index 94986f4cae..408fdd5ae1 100644 --- a/config/locales/no.yml +++ b/config/locales/no.yml @@ -786,7 +786,7 @@ original_status: Opprinnelig innlegg reblogs: Fremheve status_changed: Innlegg endret - title: Kontostatuser + title: Kontostatuser - @%{name} trending: Populært visibility: Synlighet with_media: Med media diff --git a/config/locales/oc.yml b/config/locales/oc.yml index a30126c44b..5130977cb3 100644 --- a/config/locales/oc.yml +++ b/config/locales/oc.yml @@ -401,7 +401,7 @@ oc: media: title: Mèdia no_status_selected: Cap d’estatut pas cambiat estant que cap èra pas seleccionat - title: Estatuts del compte + title: Estatuts del compte - @%{name} visibility: Visibilitat with_media: Amb mèdia system_checks: diff --git a/config/locales/pl.yml b/config/locales/pl.yml index d50a042a22..c5d63e1d73 100644 --- a/config/locales/pl.yml +++ b/config/locales/pl.yml @@ -861,7 +861,7 @@ pl: original_status: Oryginalny post reblogs: Podbicia status_changed: Post zmieniony - title: Wpisy konta + title: Wpisy konta - @%{name} trending: Popularne visibility: Widoczność with_media: Z zawartością multimedialną diff --git a/config/locales/pt-BR.yml b/config/locales/pt-BR.yml index 0ff944e108..c5a0f3764a 100644 --- a/config/locales/pt-BR.yml +++ b/config/locales/pt-BR.yml @@ -841,7 +841,7 @@ pt-BR: original_status: Publicação original reblogs: Reblogs status_changed: Publicação alterada - title: Publicações da conta + title: Publicações da conta - @%{name} trending: Em alta visibility: Visibilidade with_media: Com mídia diff --git a/config/locales/pt-PT.yml b/config/locales/pt-PT.yml index 1761ec3f0c..ff80948848 100644 --- a/config/locales/pt-PT.yml +++ b/config/locales/pt-PT.yml @@ -832,7 +832,7 @@ pt-PT: original_status: Publicação original reblogs: Re-publicacões status_changed: Publicação alterada - title: Estado das contas + title: Estado das contas - @%{name} trending: Em tendência visibility: Visibilidade with_media: Com media diff --git a/config/locales/ru.yml b/config/locales/ru.yml index 8a84f22115..09d89cef9d 100644 --- a/config/locales/ru.yml +++ b/config/locales/ru.yml @@ -869,7 +869,7 @@ ru: original_status: Оригинальный пост reblogs: Продвинули status_changed: Пост изменен - title: Посты пользователя + title: Посты пользователя - @%{name} trending: Популярное visibility: Видимость with_media: С файлами diff --git a/config/locales/sc.yml b/config/locales/sc.yml index 9ab62cea71..09f8ba0e0e 100644 --- a/config/locales/sc.yml +++ b/config/locales/sc.yml @@ -582,7 +582,7 @@ sc: open: Aberi sa publicatzione original_status: Publicatzione originale status_changed: Publicatzione modificada - title: Istados de su contu + title: Istados de su contu - @%{name} trending: Populares visibility: Visibilidade with_media: Cun elementos multimediales diff --git a/config/locales/sco.yml b/config/locales/sco.yml index 8cc733a4ac..55e0603d45 100644 --- a/config/locales/sco.yml +++ b/config/locales/sco.yml @@ -713,7 +713,7 @@ sco: original_status: Original post reblogs: Reblogs status_changed: Post chynged - title: Accoont posts + title: Accoont posts - @%{name} trending: Trendin visibility: Visibility with_media: Wi media diff --git a/config/locales/si.yml b/config/locales/si.yml index 270e0ae3fc..b0eb1d3b0c 100644 --- a/config/locales/si.yml +++ b/config/locales/si.yml @@ -607,7 +607,7 @@ si: open: ලිපිය අරින්න original_status: මුල් ලිපිය status_changed: ලිපිය සංශෝධිතයි - title: ගිණුමේ ලිපි + title: ගිණුමේ ලිපි - @%{name} trending: නැගී එන with_media: මාධ්‍ය සමඟ strikes: diff --git a/config/locales/sk.yml b/config/locales/sk.yml index 6ef78a8f21..d576bf0382 100644 --- a/config/locales/sk.yml +++ b/config/locales/sk.yml @@ -684,7 +684,7 @@ sk: open: Otvor príspevok original_status: Pôvodný príspevok status_changed: Príspevok bol zmenený - title: Príspevky na účte + title: Príspevky na účte - @%{name} trending: Populárne visibility: Viditeľnosť with_media: S médiami diff --git a/config/locales/sl.yml b/config/locales/sl.yml index e9c06bcaa6..6ae239d69f 100644 --- a/config/locales/sl.yml +++ b/config/locales/sl.yml @@ -853,7 +853,7 @@ sl: original_status: Izvorna objava reblogs: Ponovljeni blogi status_changed: Objava spremenjena - title: Objave računa + title: Objave računa - @%{name} trending: V trendu visibility: Vidnost with_media: Z mediji diff --git a/config/locales/sq.yml b/config/locales/sq.yml index e5becbd916..b1e2a4f61e 100644 --- a/config/locales/sq.yml +++ b/config/locales/sq.yml @@ -838,7 +838,7 @@ sq: original_status: Postim origjinal reblogs: Riblogime status_changed: Postimi ndryshoi - title: Gjendje llogarish + title: Gjendje llogarish - @%{name} trending: Në modë visibility: Dukshmëri with_media: Me media diff --git a/config/locales/sr-Latn.yml b/config/locales/sr-Latn.yml index f56cdb9cb5..76a0f8afe9 100644 --- a/config/locales/sr-Latn.yml +++ b/config/locales/sr-Latn.yml @@ -807,7 +807,7 @@ sr-Latn: original_status: Originalna objava reblogs: Deljenja status_changed: Objava promenjena - title: Statusi naloga + title: Statusi naloga - @%{name} trending: U trendu visibility: Vidljivost with_media: Sa multimedijom diff --git a/config/locales/sr.yml b/config/locales/sr.yml index 45feb0b5fc..6a75316c23 100644 --- a/config/locales/sr.yml +++ b/config/locales/sr.yml @@ -837,7 +837,7 @@ sr: original_status: Оригинална објава reblogs: Дељења status_changed: Објава промењена - title: Статуси налога + title: Статуси налога - @%{name} trending: У тренду visibility: Видљивост with_media: Са мултимедијом diff --git a/config/locales/sv.yml b/config/locales/sv.yml index c41795a168..11b37f8bfc 100644 --- a/config/locales/sv.yml +++ b/config/locales/sv.yml @@ -841,7 +841,7 @@ sv: original_status: Ursprungligt inlägg reblogs: Ombloggningar status_changed: Inlägg ändrat - title: Kontoinlägg + title: Kontoinlägg - @%{name} trending: Trendande visibility: Synlighet with_media: Med media diff --git a/config/locales/th.yml b/config/locales/th.yml index ea039a2b99..32f2b30292 100644 --- a/config/locales/th.yml +++ b/config/locales/th.yml @@ -819,7 +819,7 @@ th: original_status: โพสต์ดั้งเดิม reblogs: การดัน status_changed: เปลี่ยนโพสต์แล้ว - title: โพสต์ของบัญชี + title: โพสต์ของบัญชี - @%{name} trending: กำลังนิยม visibility: การมองเห็น with_media: มีสื่อ diff --git a/config/locales/tr.yml b/config/locales/tr.yml index 88636ef21b..2eafed1b47 100644 --- a/config/locales/tr.yml +++ b/config/locales/tr.yml @@ -841,7 +841,7 @@ tr: original_status: Özgün gönderi reblogs: Yeniden Paylaşımlar status_changed: Gönderi değişti - title: Hesap durumları + title: Hesap durumları - @%{name} trending: Öne çıkanlar visibility: Görünürlük with_media: Medya ile diff --git a/config/locales/uk.yml b/config/locales/uk.yml index e6a765267f..7ea76b2a75 100644 --- a/config/locales/uk.yml +++ b/config/locales/uk.yml @@ -861,7 +861,7 @@ uk: original_status: Оригінальний допис reblogs: Поширення status_changed: Допис змінено - title: Дописи облікових записів + title: Дописи облікових записів - @%{name} trending: Популярне visibility: Видимість with_media: З медіа diff --git a/config/locales/vi.yml b/config/locales/vi.yml index 1d04f796f8..71c4357f2f 100644 --- a/config/locales/vi.yml +++ b/config/locales/vi.yml @@ -827,7 +827,7 @@ vi: original_status: Tút gốc reblogs: Lượt đăng lại status_changed: Tút đã sửa - title: Tất cả tút + title: Tất cả tút - @%{name} trending: Xu hướng visibility: Hiển thị with_media: Có media diff --git a/config/locales/zh-CN.yml b/config/locales/zh-CN.yml index 36d316649c..cae0efee57 100644 --- a/config/locales/zh-CN.yml +++ b/config/locales/zh-CN.yml @@ -827,7 +827,7 @@ zh-CN: original_status: 原始嘟文 reblogs: 转发 status_changed: 嘟文已编辑 - title: 帐户嘟文 + title: 帐户嘟文 - @%{name} trending: 当前热门 visibility: 可见性 with_media: 含有媒体文件 diff --git a/config/locales/zh-HK.yml b/config/locales/zh-HK.yml index e33ebeadb4..6f0a99a5b3 100644 --- a/config/locales/zh-HK.yml +++ b/config/locales/zh-HK.yml @@ -777,7 +777,7 @@ zh-HK: original_status: 原始帖文 reblogs: 轉發 status_changed: 帖文已變更 - title: 帳戶文章 + title: 帳戶文章 - @%{name} trending: 熱門 visibility: 可見性 with_media: 含有媒體檔案 diff --git a/config/locales/zh-TW.yml b/config/locales/zh-TW.yml index 495a6a4742..ce6bd3e8f5 100644 --- a/config/locales/zh-TW.yml +++ b/config/locales/zh-TW.yml @@ -829,7 +829,7 @@ zh-TW: original_status: 原始嘟文 reblogs: 轉嘟 status_changed: 嘟文已編輯 - title: 帳號嘟文 + title: 帳號嘟文 - @%{name} trending: 熱門 visibility: 可見性 with_media: 含有媒體檔案 From c546aa57cb0b89c5d4ec7f7d7d38656d9e378402 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Fri, 15 Nov 2024 11:30:11 +0100 Subject: [PATCH 18/64] New Crowdin Translations (automated) (#32900) Co-authored-by: GitHub Actions --- app/javascript/mastodon/locales/bg.json | 27 +++++++++++++++++++++++++ app/javascript/mastodon/locales/cy.json | 1 + app/javascript/mastodon/locales/lt.json | 1 + app/javascript/mastodon/locales/lv.json | 4 ++++ config/locales/bg.yml | 9 +++++++++ config/locales/cy.yml | 8 ++++++++ config/locales/devise.lv.yml | 10 ++++----- config/locales/eo.yml | 26 +++++++++++++++++++++++- config/locales/hu.yml | 16 +++++++-------- config/locales/lv.yml | 25 +++++++++++++++-------- config/locales/simple_form.cy.yml | 3 ++- config/locales/simple_form.hu.yml | 4 ++-- config/locales/simple_form.lv.yml | 5 +++-- 13 files changed, 112 insertions(+), 27 deletions(-) diff --git a/app/javascript/mastodon/locales/bg.json b/app/javascript/mastodon/locales/bg.json index 3d5d8a8585..44482f6c96 100644 --- a/app/javascript/mastodon/locales/bg.json +++ b/app/javascript/mastodon/locales/bg.json @@ -87,6 +87,17 @@ "alert.unexpected.title": "Опаа!", "alt_text_badge.title": "Алтернативен текст", "announcement.announcement": "Оповестяване", + "annual_report.summary.archetype.lurker": "Дебнещото", + "annual_report.summary.archetype.oracle": "Оракул", + "annual_report.summary.archetype.pollster": "Анкетьорче", + "annual_report.summary.archetype.replier": "Социална пеперуда", + "annual_report.summary.followers.followers": "последователи", + "annual_report.summary.followers.total": "{count} общо", + "annual_report.summary.highlighted_post.by_favourites": "най-правено като любима публикация", + "annual_report.summary.most_used_app.most_used_app": "най-употребявано приложение", + "annual_report.summary.most_used_hashtag.most_used_hashtag": "най-употребяван хаштаг", + "annual_report.summary.new_posts.new_posts": "нови публикации", + "annual_report.summary.thanks": "Благодарим, че сте част от Mastodon!", "attachments_list.unprocessed": "(необработено)", "audio.hide": "Скриване на звука", "block_modal.remote_users_caveat": "Ще поискаме сървърът {domain} да почита решението ви. Съгласието обаче не се гарантира откак някои сървъри могат да боравят с блоковете по различен начин. Обществените публикации още може да се виждат от невлезли в системата потребители.", @@ -158,6 +169,7 @@ "compose_form.poll.duration": "Времетраене на анкетата", "compose_form.poll.multiple": "Множествен избор", "compose_form.poll.option_placeholder": "Избор {number}", + "compose_form.poll.single": "Единичен избор", "compose_form.poll.switch_to_multiple": "Промяна на анкетата, за да се позволят множество възможни избора", "compose_form.poll.switch_to_single": "Промяна на анкетата, за да се позволи един възможен избор", "compose_form.poll.type": "Стил", @@ -195,6 +207,8 @@ "confirmations.unfollow.message": "Наистина ли искате да не следвате {name}?", "confirmations.unfollow.title": "Спирате ли да следвате потребителя?", "content_warning.hide": "Скриване на публ.", + "content_warning.show": "Нека се покаже", + "content_warning.show_more": "Показване на още", "conversation.delete": "Изтриване на разговора", "conversation.mark_as_read": "Маркиране като прочетено", "conversation.open": "Преглед на разговора", @@ -365,6 +379,9 @@ "home.pending_critical_update.link": "Преглед на обновяванията", "home.pending_critical_update.title": "Налично критично обновяване на сигурността!", "home.show_announcements": "Показване на оповестяванията", + "ignore_notifications_modal.disclaimer": "Mastodon не може да осведоми потребители, че сте пренебрегнали известията им. Пренебрегването на известията няма да спре самите съобщения да не бъдат изпращани.", + "ignore_notifications_modal.filter_to_act_users": "Вие все още ще може да приемате, отхвърляте или докладвате потребители", + "ignore_notifications_modal.filter_to_avoid_confusion": "Прецеждането помага за избягване на възможно объркване", "interaction_modal.description.favourite": "Имайки акаунт в Mastodon, може да сложите тази публикации в любими, за да позволите на автора да узнае, че я цените и да я запазите за по-късно.", "interaction_modal.description.follow": "С акаунт в Mastodon може да последвате {name}, за да получавате публикациите от този акаунт в началния си инфоканал.", "interaction_modal.description.reblog": "С акаунт в Mastodon може да подсилите тази публикация, за да я споделите с последователите си.", @@ -380,6 +397,7 @@ "interaction_modal.title.follow": "Последване на {name}", "interaction_modal.title.reblog": "Подсилване на публикацията на {name}", "interaction_modal.title.reply": "Отговаряне на публикацията на {name}", + "interaction_modal.title.vote": "Гласувайте в анкетата на {name}", "intervals.full.days": "{number, plural, one {# ден} other {# дни}}", "intervals.full.hours": "{number, plural, one {# час} other {# часа}}", "intervals.full.minutes": "{number, plural, one {# минута} other {# минути}}", @@ -420,6 +438,8 @@ "lightbox.close": "Затваряне", "lightbox.next": "Напред", "lightbox.previous": "Назад", + "lightbox.zoom_in": "Увеличение до действителната големина", + "lightbox.zoom_out": "Увеличение до побиране", "limited_account_hint.action": "Показване на профила въпреки това", "limited_account_hint.title": "Този профил е бил скрит от модераторите на {domain}.", "link_preview.author": "От {name}", @@ -441,6 +461,7 @@ "lists.subheading": "Вашите списъци", "load_pending": "{count, plural, one {# нов елемент} other {# нови елемента}}", "loading_indicator.label": "Зареждане…", + "media_gallery.hide": "Скриване", "moved_to_account_banner.text": "Вашият акаунт {disabledAccount} сега е изключен, защото се преместихте в {movedToAccount}.", "mute_modal.hide_from_notifications": "Скриване от известията", "mute_modal.hide_options": "Скриване на възможностите", @@ -489,6 +510,7 @@ "notification.favourite": "{name} направи любима публикацията ви", "notification.favourite.name_and_others_with_link": "{name} и {count, plural, one {# друг} other {# други}} направиха любима ваша публикация", "notification.follow": "{name} ви последва", + "notification.follow.name_and_others": "{name} и {count, plural, one {# друг} other {# други}} ви последваха", "notification.follow_request": "{name} поиска да ви последва", "notification.follow_request.name_and_others": "{name} и {count, plural, one {# друг} other {# други}} поискаха да ви последват", "notification.label.mention": "Споменаване", @@ -496,6 +518,7 @@ "notification.label.private_reply": "Личен отговор", "notification.label.reply": "Отговор", "notification.mention": "Споменаване", + "notification.mentioned_you": "{name} ви спомена", "notification.moderation-warning.learn_more": "Научете повече", "notification.moderation_warning": "Получихте предупреждение за модериране", "notification.moderation_warning.action_delete_statuses": "Някои от публикациите ви са премахнати.", @@ -752,6 +775,7 @@ "status.bookmark": "Отмятане", "status.cancel_reblog_private": "Край на подсилването", "status.cannot_reblog": "Публикацията не може да се подсилва", + "status.continued_thread": "Продължена нишка", "status.copy": "Копиране на връзката към публикация", "status.delete": "Изтриване", "status.detailed_status": "Подробен изглед на разговора", @@ -760,6 +784,7 @@ "status.edit": "Редактиране", "status.edited": "Последно редактирано на {date}", "status.edited_x_times": "Редактирано {count, plural,one {{count} път} other {{count} пъти}}", + "status.embed": "Вземане на кода за вграждане", "status.favourite": "Любимо", "status.favourites": "{count, plural, one {любимо} other {любими}}", "status.filter": "Филтриране на публ.", @@ -784,6 +809,7 @@ "status.reblogs.empty": "Още никого не е подсилвал публикацията. Подсилващият ще се покаже тук.", "status.redraft": "Изтриване и преработване", "status.remove_bookmark": "Премахване на отметката", + "status.replied_in_thread": "Отговорено в нишката", "status.replied_to": "В отговор до {name}", "status.reply": "Отговор", "status.replyAll": "Отговор на нишка", @@ -821,6 +847,7 @@ "upload_error.poll": "Качването на файлове не е позволено с анкети.", "upload_form.audio_description": "Опишете за хора, които са глухи или трудно чуват", "upload_form.description": "Опишете за хора, които са слепи или имат слабо зрение", + "upload_form.drag_and_drop.instructions": "Натиснете интервал или enter, за да подберете мултимедийно прикачване. Провлачвайки, ползвайте клавишите със стрелки, за да премествате мултимедията във всяка дадена посока. Натиснете пак интервал или enter, за да се стовари мултимедийното прикачване в новото си положение или натиснете Esc за отмяна.", "upload_form.edit": "Редактиране", "upload_form.thumbnail": "Промяна на миниобраза", "upload_form.video_description": "Опишете за хора, които са глухи или трудно чуват, слепи или имат слабо зрение", diff --git a/app/javascript/mastodon/locales/cy.json b/app/javascript/mastodon/locales/cy.json index ca83af9215..1fa17e56ea 100644 --- a/app/javascript/mastodon/locales/cy.json +++ b/app/javascript/mastodon/locales/cy.json @@ -101,6 +101,7 @@ "annual_report.summary.highlighted_post.possessive": "{name}", "annual_report.summary.most_used_app.most_used_app": "ap a ddefnyddiwyd fwyaf", "annual_report.summary.most_used_hashtag.most_used_hashtag": "hashnod a ddefnyddiwyd fwyaf", + "annual_report.summary.most_used_hashtag.none": "Dim", "annual_report.summary.new_posts.new_posts": "postiadau newydd", "annual_report.summary.percentile.text": "Rydych chi yn y mwyaf o ddefnyddwyr Mastodon.", "annual_report.summary.percentile.we_wont_tell_bernie": "Ni fyddwn yn dweud wrth Bernie.", diff --git a/app/javascript/mastodon/locales/lt.json b/app/javascript/mastodon/locales/lt.json index d03833e11f..378f642cfe 100644 --- a/app/javascript/mastodon/locales/lt.json +++ b/app/javascript/mastodon/locales/lt.json @@ -101,6 +101,7 @@ "annual_report.summary.highlighted_post.possessive": "{name}", "annual_report.summary.most_used_app.most_used_app": "labiausiai naudota programa", "annual_report.summary.most_used_hashtag.most_used_hashtag": "labiausiai naudotas saitažodis", + "annual_report.summary.most_used_hashtag.none": "Nieko", "annual_report.summary.new_posts.new_posts": "nauji įrašai", "annual_report.summary.percentile.text": "Tai reiškia, kad esate tarppopuliariausių „Mastodon“ naudotojų.", "annual_report.summary.percentile.we_wont_tell_bernie": "Mes nesakysime Bernie.", diff --git a/app/javascript/mastodon/locales/lv.json b/app/javascript/mastodon/locales/lv.json index 30fc0ea348..f6053b2e09 100644 --- a/app/javascript/mastodon/locales/lv.json +++ b/app/javascript/mastodon/locales/lv.json @@ -86,6 +86,10 @@ "alert.unexpected.message": "Radās negaidīta kļūda.", "alert.unexpected.title": "Ups!", "announcement.announcement": "Paziņojums", + "annual_report.summary.followers.followers": "sekotāji", + "annual_report.summary.followers.total": "pavisam {count}", + "annual_report.summary.here_it_is": "Šeit ir {year}. gada pārskats:", + "annual_report.summary.new_posts.new_posts": "jauni ieraksti", "attachments_list.unprocessed": "(neapstrādāti)", "audio.hide": "Slēpt audio", "block_modal.remote_users_caveat": "Mēs vaicāsim serverim {domain} ņemt vērā Tavu lēmumu. Tomēr atbilstība nav nodrošināta, jo atsevišķi serveri var apstrādāt bloķēšanu citādi. Publiski ieraksti joprojām var būt redzami lietotājiem, kuri nav pieteikušies.", diff --git a/config/locales/bg.yml b/config/locales/bg.yml index e10ce3197c..2c5edf0b13 100644 --- a/config/locales/bg.yml +++ b/config/locales/bg.yml @@ -21,9 +21,12 @@ bg: one: Публикация other: Публикации posts_tab_heading: Публикации + self_follow_error: Не е позволено да следвате собствения си акаунт admin: account_actions: action: Изпълняване на действие + already_silenced: Този акаунт вече е ограничен. + already_suspended: Този акаунт вече е спрян. title: Извършване на модериращо действие за %{acct} account_moderation_notes: create: Оставяне на бележка @@ -45,6 +48,7 @@ bg: title: Промяна на имейл за %{username} change_role: changed_msg: Успешно променена роля! + edit_roles: Управление на потребителските роли label: Промяна на ролята no_role: Без роля title: Промяна на ролята за %{username} @@ -875,6 +879,7 @@ bg: name: Име newest: Най-нови oldest: Най-стари + open: Преглед публично reset: Нулиране review: Преглед на състояние search: Търсене @@ -888,6 +893,7 @@ bg: links: allow: Позволяване на връзка allow_provider: Позволяване на публикуващия + confirm_allow: Наистина ли искате да позволите избраните връзки? confirm_allow_provider: Наистина ли искате да позволите избраните доставчици? description_html: Това са връзки, които в момента са много пъти споделяни от акаунти, чиито публикации сървърът ви вижда. Може да помогне на потребителите ви да разберат какво се случва по света. Никоя връзка няма да се показва публично, докато не одобрите публикуващия. Може още и да одобрявате или отхвърляте отделни връзки. disallow: Забранявам връзката @@ -912,6 +918,8 @@ bg: statuses: allow: Позволяване на публикацията allow_account: Позволяване на автора + confirm_allow: Наистина ли искате да позволите избраните статуси? + confirm_allow_account: Наистина ли искате да позволите избраните акаунти? description_html: Това са публикации, за които сървърът ви знае, че са често споделяни или харесвани в момента. Това може да помогне на вашите нови и завръщащи се потребители да открият повече хора за следване. Никоя от публикациите няма да бъде показана публично, докато не одобрите автора и докато авторът не позволи акаунтът му да бъде предлган на другите. Също така можете да позволявате или отхвърляте отделни публикации. disallow: Забраняване на публикацията disallow_account: Забрана на автора @@ -1028,6 +1036,7 @@ bg: guide_link_text: Всеки може да участва. sensitive_content: Деликатно съдържание application_mailer: + notification_preferences: Промяна на предпочитанията за е-поща salutation: "%{name}," unsubscribe: Стоп на абонамента view: 'Преглед:' diff --git a/config/locales/cy.yml b/config/locales/cy.yml index ca18de17bc..f479f0f0a0 100644 --- a/config/locales/cy.yml +++ b/config/locales/cy.yml @@ -199,6 +199,7 @@ cy: create_domain_block: Creu Gwaharddiad Parth create_email_domain_block: Creu Rhwystr Parth E-bost create_ip_block: Creu rheol IP + create_relay: Creu Cyfnewidiad create_unavailable_domain: Creu Parth Ddim ar Gael create_user_role: Creu Rôl demote_user: Diraddio Defnyddiwr @@ -210,14 +211,17 @@ cy: destroy_email_domain_block: Dileu Rhwystr Parth E-bost destroy_instance: Clirio Parth destroy_ip_block: Dileu rheol IP + destroy_relay: Dileu Cyfnewidiad destroy_status: Dileu Postiad destroy_unavailable_domain: Dileu Parth Ddim ar Gael destroy_user_role: Dileu Rôl disable_2fa_user: Diffodd 2FA disable_custom_emoji: Analluogi Emoji Addasedig + disable_relay: Analluogi Cyfnewidiad disable_sign_in_token_auth_user: Analluogi Dilysu Tocyn E-bost Defnyddiwr disable_user: Analluogi Defnyddiwr enable_custom_emoji: Galluogi Emoji Addasedig + enable_relay: Galluogi Cyfnewidiad enable_sign_in_token_auth_user: Galluogi Dilysu Tocyn E-bost Defnyddiwr enable_user: Galluogi Defnyddiwr memorialize_account: Cofadeilio Cyfrif @@ -259,6 +263,7 @@ cy: create_domain_block_html: Mae %{name} wedi rhwystro parth %{target} create_email_domain_block_html: Mae %{name} wedi rhwystro parth e-bost %{target} create_ip_block_html: Mae %{name} wedi creu rheol ar gyfer IP %{target} + create_relay_html: Creodd %{name} gyfnewidiad %{target} create_unavailable_domain_html: Mae %{name} wedi stopio danfon i barth %{target} create_user_role_html: Mae %{name} wedi creu rôl %{target} demote_user_html: Mae %{name} wedi israddio defnyddiwr %{target} @@ -270,14 +275,17 @@ cy: destroy_email_domain_block_html: Mae %{name} wedi dad-rwystro parth e-bost %{target} destroy_instance_html: Mae %{name} wedi dileu parth %{target} destroy_ip_block_html: Mae %{name} dileu rheol ar gyfer IP %{target} + destroy_relay_html: Dileodd %{name} y cyfnewidiad %{target} destroy_status_html: Mae %{name} wedi tynnu postiad gan %{target} destroy_unavailable_domain_html: Mae %{name} wedi ailddechrau anfon i barth %{target} destroy_user_role_html: Mae %{name} wedi dileu rôl %{target} disable_2fa_user_html: Mae %{name} wedi analluogi gofyniad dau ffactor ar gyfer defnyddiwr %{target} disable_custom_emoji_html: Mae %{name} wedi analluogi emoji %{target} + disable_relay_html: Analluogodd %{name} y cyfnewidiad %{target} disable_sign_in_token_auth_user_html: Mae %{name} wedi analluogi dilysiad tocyn e-bost %{target} disable_user_html: Mae %{name} wedi analluogi mewngofnodi defnyddiwr %{target} enable_custom_emoji_html: Mae %{name} wedi analluogi emoji %{target} + enable_relay_html: Galluogodd %{name} y cyfnewidiad %{target} enable_sign_in_token_auth_user_html: Mae %{name} wedi galluogi dilysiad tocyn e-bost %{target} enable_user_html: Mae %{name} wedi galluogi mewngofnodi defnyddiwr %{target} memorialize_account_html: Newidiodd %{name} gyfrif %{target} i dudalen memoriam diff --git a/config/locales/devise.lv.yml b/config/locales/devise.lv.yml index 4470c8109e..5aaa23a731 100644 --- a/config/locales/devise.lv.yml +++ b/config/locales/devise.lv.yml @@ -14,7 +14,7 @@ lv: not_found_in_database: Nederīga %{authentication_keys} vai parole. omniauth_user_creation_failure: Kļūda šīs identitātes konta izveidošanā. pending: Tavs konts joprojām tiek pārskatīts. - timeout: Sesijair beigusies. Lūgums vēlreiz pieteikties, lai turpinātu. + timeout: Sesija ir beigusies. Lūgums vēlreiz pieteikties, lai turpinātu. unauthenticated: Lai turpinātu, jāpiesakās vai jāreģistrējas. unconfirmed: Lai turpinātu, jāapliecina sava e-pasta adrese. mailer: @@ -90,13 +90,13 @@ lv: no_token: Tu nevari piekļūt šai lapai, ja neesi saņēmis paroles atiestatīšanas e-pasta ziņojumu. Ja ienāci no paroles atiestatīšanas e-pasta, lūdzu, pārliecinies, vai izmanto visu norādīto URL. send_instructions: Ja tava e-pasta adrese ir mūsu datu bāzē, pēc dažām minūtēm uz savu e-pasta adresi saņemsi paroles atkopšanas saiti. Lūdzu, pārbaudi spama mapi, ja neesi saņēmis šo e-pastu. send_paranoid_instructions: Ja tava e-pasta adrese ir mūsu datu bāzē, pēc dažām minūtēm uz savu e-pasta adresi saņemsi paroles atkopšanas saiti. Lūdzu, pārbaudi spama mapi, ja neesi saņēmis šo e-pastu. - updated: Tava parole tika veiksmīgi nomainīta. Tu tagad esi pieteicies. + updated: Tava parole tika veiksmīgi nomainīta. Tagad esi pieteicies. updated_not_active: Tava parole ir veiksmīgi nomainīta. registrations: destroyed: Visu labu! Tavs konts ir veiksmīgi atcelts. Mēs ceram tevi drīz atkal redzēt. signed_up: Laipni lūdzam! Tu esi veiksmīgi reģistrējies. - signed_up_but_inactive: Tava reģistrācija bija veiksmīga. Tomēr mēs nevarējām tevi pierakstīt, jo tavs konts vēl nav aktivizēts. - signed_up_but_locked: Tava reģistrācija bija veiksmīga. Tomēr mēs nevarējām tevi pierakstīt, jo tavs konts ir bloķēts. + signed_up_but_inactive: Tava reģistrācija bija veiksmīga. Tomēr mēs nevarējām Tevi pieteikt, jo Tavs konts vēl nav aktivizēts. + signed_up_but_locked: Tava reģistrācija bija veiksmīga. Tomēr mēs nevarējām Tevi pieteikt, jo Tavs konts ir slēgts. signed_up_but_pending: Uz tavu e-pasta adresi ir nosūtīts ziņojums ar apstiprinājuma saiti. Pēc noklikšķināšanas uz saites mēs izskatīsim tavu pieteikumu. Tu tiksi informēts, ja tas tiks apstiprināts. signed_up_but_unconfirmed: Uz tavu e-pasta adresi ir nosūtīts ziņojums ar apstiprinājuma saiti. Lūdzu, seko saitei, lai aktivizētu savu kontu. Lūdzu, pārbaudi spama mapi, ja neesi saņēmis šo e-pastu. update_needs_confirmation: Tu veiksmīgi atjaunināji savu kontu, taču mums ir jāverificē teva jaunā e-pasta adrese. Lūdzu, pārbaudi savu e-pastu un seko apstiprinājuma saitei, lai apstiprinātu savu jauno e-pasta adresi. Lūdzu, pārbaudi spama mapi, ja neesi saņēmis šo e-pastu. @@ -111,7 +111,7 @@ lv: unlocked: Konts tika veiksmīgi atbloķēts. Lūgums pieteikties, lai turpinātu. errors: messages: - already_confirmed: jau tika apstiprināts, lūdzu, mēģini pierakstīties + already_confirmed: jau tika apstiprināts, lūgums mēģināt pieteikties confirmation_period_expired: jāapstiprina %{period} laikā, lūdzu, pieprasi jaunu expired: ir beidzies derīguma termiņš, lūdzu, pieprasi jaunu not_found: nav atrasts diff --git a/config/locales/eo.yml b/config/locales/eo.yml index b5287d9e2a..194b2c17b8 100644 --- a/config/locales/eo.yml +++ b/config/locales/eo.yml @@ -73,7 +73,7 @@ eo: enable_sign_in_token_auth: Ebligu retpoŝtan ĵeton-aŭtentikigon enabled: Ebligita enabled_msg: Sukcese malfrostigis konton de %{username} - followers: Sekvantoj + followers: Sekvoj follows: Sekvatoj header: Kapa bildo inbox_url: Enira URL @@ -187,6 +187,7 @@ eo: create_domain_block: Krei Blokadon De Domajno create_email_domain_block: Krei retpoŝtan domajnan blokon create_ip_block: Krei IP-regulon + create_relay: Krei Relajson create_unavailable_domain: Krei Nehaveblan Domajnon create_user_role: Krei Rolon demote_user: Malpromocii Uzanton @@ -198,13 +199,18 @@ eo: destroy_email_domain_block: Forigi retpoŝtan domajnan blokon destroy_instance: Forigi Domajnon destroy_ip_block: Forigi IP-regulon + destroy_relay: Forigi Relajson destroy_status: Forigi Afiŝon destroy_unavailable_domain: Forigi Nehaveblan Domajnon destroy_user_role: Detrui Rolon disable_2fa_user: Malebligi 2FA disable_custom_emoji: Malebligi proprajn emoĝiojn + disable_relay: Malebligi Relajson + disable_sign_in_token_auth_user: Malebligi aŭtentigon per retpoŝta ĵetono por la uzanto disable_user: Neebligi la uzanton enable_custom_emoji: Ebligi Propran Emoĝion + enable_relay: Ebligi Relajson + enable_sign_in_token_auth_user: Ebligi aŭtentigon per retpoŝta ĵetono por la uzanto enable_user: Ebligi uzanton memorialize_account: Memorigu Konton promote_user: Promocii Uzanton @@ -245,6 +251,7 @@ eo: create_domain_block_html: "%{name} blokis domajnon %{target}" create_email_domain_block_html: "%{name} blokis retpoŝtan domajnon %{target}" create_ip_block_html: "%{name} kreis regulon por IP %{target}" + create_relay_html: "%{name} kreis relajson %{target}" create_unavailable_domain_html: "%{name} ĉesis sendon al domajno %{target}" create_user_role_html: "%{name} kreis rolon de %{target}" demote_user_html: "%{name} degradis uzanton %{target}" @@ -256,13 +263,18 @@ eo: destroy_email_domain_block_html: "%{name} malblokis retpoŝtan domajnon %{target}" destroy_instance_html: "%{name} forigis domajnon %{target}" destroy_ip_block_html: "%{name} forigis regulon por IP %{target}" + destroy_relay_html: "%{name} forigis la relajson %{target}" destroy_status_html: "%{name} forigis mesaĝojn de %{target}" destroy_unavailable_domain_html: "%{name} restartigis sendon al domajno %{target}" destroy_user_role_html: "%{name} forigis rolon de %{target}" disable_2fa_user_html: "%{name} malebligis dufaktoran aŭtentigon por uzanto %{target}" disable_custom_emoji_html: "%{name} malebligis la emoĝion %{target}" + disable_relay_html: "%{name} malebligis la relajson %{target}" + disable_sign_in_token_auth_user_html: "%{name} malebligis la aŭtentigon de retpoŝta ĵetono por %{target}" disable_user_html: "%{name} malebligis ensaluton por uzanto %{target}" enable_custom_emoji_html: "%{name} ebligis la emoĝion %{target}" + enable_relay_html: "%{name} ebligis la relajson %{target}" + enable_sign_in_token_auth_user_html: "%{name} ebligis la aŭtentigon de retpoŝta ĵetono por %{target}" enable_user_html: "%{name} ebligis ensaluton por uzanto %{target}" memorialize_account_html: "%{name} ŝanĝis la konton de %{target} al memora paĝo" promote_user_html: "%{name} plirangigis uzanton %{target}" @@ -270,6 +282,7 @@ eo: reject_user_html: "%{name} malakceptis registriĝon de %{target}" remove_avatar_user_html: "%{name} forigis la profilbildon de %{target}" reopen_report_html: "%{name} remalfermis signalon %{target}" + resend_user_html: "%{name} resendis konfirman retmesaĝon por %{target}" reset_password_user_html: "%{name} restarigis la pasvorton de la uzanto %{target}" resolve_report_html: "%{name} solvis raporton %{target}" sensitive_account_html: "%{name} markis audovidaĵon de %{target} kiel tiklan" @@ -440,6 +453,7 @@ eo: create: Aldoni domajnon resolve: Solvi domajnon title: Bloki novan retpoŝtan domajnon + no_email_domain_block_selected: Neniuj domajn blokoj ŝanĝiĝis ĉar nenio estis elektita not_permitted: Ne permesita resolved_through_html: Solvis tra %{domain} title: Blokis retpoŝtajn domajnojn @@ -467,6 +481,8 @@ eo: title: Rekomendoj de sekvado unsuppress: Regajni sekvorekomendon instances: + audit_log: + title: Novaj Protokoloj Pri Ekzamenoj availability: description_html: one: Se sendo la domajno malsukcesis por %{count} dio, ne estas sendprovo plu escepte de la dojmano. @@ -1054,6 +1070,7 @@ eo: awaiting_review_title: Via registriĝo estas reviziita clicking_this_link: alklakante ĉi tiun ligilon login_link: ensaluti + proceed_to_login_html: Vi nun povas iri al %{login_link}. registration_complete: Via registriĝo sur %{domain} nun finiĝis! welcome_title: Bonvenon, %{name}! wrong_email_hint: Se tiu retadreso ne estas ĝusta, vi povas ŝanĝi ĝin en kontagordoj. @@ -1329,6 +1346,7 @@ eo: unconfirmed: Nekonfirmita status: Stato success: Viaj datumoj estis sukcese alŝutitaj kaj estos traktitaj kiel planite + time_started: Komencis je titles: following: Importado de sekvaj kontoj lists: Importi listojn @@ -1375,6 +1393,7 @@ eo: authentication_methods: otp: 2-faktora autentigprogramaro password: pasvorto + sign_in_token: retpoŝta sekureca kodo webauthn: sekurecaj ŝlosiloj description_html: Se vi vidas nerekonitan agon, eble ŝanĝu vian pasvorton. empty: Neniu autentighistorio disponebla @@ -1385,6 +1404,9 @@ eo: unsubscribe: action: Jes, malabonu complete: Malabonita + emails: + notification_emails: + follow_request: retpoŝtajn petoj de sekvado title: Malaboni media_attachments: validations: @@ -1725,6 +1747,7 @@ eo: default: "%Y.%b.%d, %H:%M" month: "%b %Y" time: "%H:%M" + with_time_zone: "%b %d, %Y, %H:%M %Z" translation: errors: quota_exceeded: La tutservila uzkvoto por la tradukservo estas superita. @@ -1805,6 +1828,7 @@ eo: apps_ios_action: Elŝutu ĉe la App Store apps_step: Elŝutu niajn oficialajn aplikaĵojn. apps_title: Aplikaĵoj de Mastodon + checklist_title: Bonvenan Markolisto edit_profile_action: Agordi edit_profile_title: Agordi vian profilon explanation: Jen kelkaj konsiloj por helpi vin komenci diff --git a/config/locales/hu.yml b/config/locales/hu.yml index da4ff78dc4..56d41daf86 100644 --- a/config/locales/hu.yml +++ b/config/locales/hu.yml @@ -579,21 +579,21 @@ hu: relationships: title: "%{acct} kapcsolatai" relays: - add_new: Új relé hozzáadása + add_new: Új továbbító hozzáadása delete: Törlés - description_html: A föderációs relé egy olyan köztes szerver, mely nagy mennyiségű nyilvános bejegyzést cserél az erre feliratkozó vagy erre publikáló szerverek között. Ezzel segíthetsz kis és közepes szervereknek tartalmat megtalálni a föderációban, mely egyébként csak akkor válna lehetővé, ha a saját felhasználóik más szervereken lévő fiókokat követnének. + description_html: A föderációs továbbító egy olyan köztes kiszolgáló, mely nagy mennyiségű nyilvános bejegyzést cserél az erre feliratkozó vagy erre publikáló kiszolgálók között. Ezzel segíthetsz kis és közepes kiszolgálóknak megtalálni a tartalmakat a föderációban, melyek egyébként csak akkor válnának lehetővé, ha a saját felhasználóik más kiszolgálókon lévő fiókokat követnének. disable: Kikapcsolás disabled: Kikapcsolva enable: Bekapcsolás - enable_hint: Ha bekapcsolod, a szerver minden nyilvános bejegyzésre feliratkozik ezen a relén, valamint az összes nyilvános bejegyzést elküldi ennek. + enable_hint: Ha bekapcsolod, a kiszolgáló minden nyilvános bejegyzésre feliratkozik ezen a továbbítón, valamint az összes nyilvános bejegyzést elküldi ennek. enabled: Bekapcsolva - inbox_url: Relé URL - pending: Várakozás a relé jóváhagyására + inbox_url: Továbbító URL + pending: Várakozás a továbbító jóváhagyására save_and_enable: Mentés és engedélyezés - setup: Relé kapcsolat felállítása - signatures_not_enabled: A relék nem fognak megfelelően működni, amíg a biztonságos mód vagy a korlátozott föderációs mód engedélyezett + setup: Továbbító kapcsolat felállítása + signatures_not_enabled: A továbbítók nem fognak megfelelően működni, amíg a biztonságos mód vagy a korlátozott föderációs mód engedélyezett status: Állapot - title: Relék + title: Továbbítók report_notes: created_msg: Bejelentési feljegyzés létrehozva! destroyed_msg: Bejelentési feljegyzés törölve! diff --git a/config/locales/lv.yml b/config/locales/lv.yml index d793c8e196..33b357b837 100644 --- a/config/locales/lv.yml +++ b/config/locales/lv.yml @@ -293,7 +293,7 @@ lv: empty: Žurnāli nav atrasti. filter_by_action: Filtrēt pēc darbības filter_by_user: Filtrēt pēc lietotāja - title: Auditācijas pieraksti + title: Audita žurnāls unavailable_instance: "(domēna vārds nav pieejams)" announcements: destroyed_msg: Paziņojums ir veiksmīgi izdzēsts! @@ -596,7 +596,7 @@ lv: one: "%{count} piezīme" other: "%{count} piezīmes" zero: "%{count} piezīmju" - action_log: Auditācijas pieraksti + action_log: Audita žurnāls action_taken_by: Veiktā darbība actions: delete_description_html: Raksti, par kurām ziņots, tiks dzēsti, un tiks reģistrēts brīdinājums, lai palīdzētu tev izvērst turpmākos pārkāpumus saistībā ar to pašu kontu. @@ -875,6 +875,7 @@ lv: message_html: Rindā(s) %{value} nedarbojas neviens Sidekiq process. Lūdzu, pārskati savu Sidekiq konfigurāciju software_version_check: action: Skatīt pieejamos atjauninājumus + message_html: Pieejams Mastodon atjauninājums. software_version_critical_check: action: Skatīt pieejamos atjauninājumus message_html: Ir pieejams kritisks Mastodon atjauninājums. Lūdzu, atjaunini to pēc iespējas ātrāk. @@ -1132,7 +1133,7 @@ lv: title: Pārbaudi savu iesūtni sign_in: preamble_html: Jāpiesakās ar saviem %{domain} piekļuves datiem. Ja konts tiek mitināts citā serverī, šeit nevarēs pieteikties. - title: Pierakstīties %{domain} + title: Pieteikties %{domain} sign_up: manual_review: Reģistrācijas domēnā %{domain} manuāli pārbauda mūsu moderatori. Lai palīdzētu mums apstrādāt tavu reģistrāciju, uzraksti mazliet par sevi un to, kāpēc vēlies kontu %{domain}. preamble: Ar kontu šajā Mastodon serverī varēsi sekot jebkuram citam tīklā esošam cilvēkam neatkarīgi no tā, kur tiek mitināts viņa konts. @@ -1418,13 +1419,20 @@ lv: webauthn: drošības atslēgas description_html: Ja pamani darbības, kuras neatpazīsti, jāapsver iespēja nomainīt savu paroli un iespējot divpakāpju autentifikāciju. empty: Nav pieejama autentifikācijas vēsture - failed_sign_in_html: Neizdevies pierakstīšanās mēģinājums ar %{method} no %{ip} (%{browser}) - successful_sign_in_html: Veiksmīga pierakstīšanās ar %{method} no %{ip} (%{browser}) + failed_sign_in_html: Neizdevies pieteikšanās mēģinājums ar %{method} no %{ip} (%{browser}) + successful_sign_in_html: Veiksmīga pieteikšanās ar %{method} no %{ip} (%{browser}) title: Autentifikācijas vēsture mail_subscriptions: unsubscribe: action: Jā, atcelt abonēšanu complete: Anulēts + emails: + notification_emails: + favourite: izlases paziņojumu e-pasta ziņojumi + follow: sekošanas paziņojumu e-pasta ziņojumi + follow_request: sekošanas pieprasījumu e-pasta ziņojumi + mention: pieminēšanas paziņojumu e-pasta ziņojumi + reblog: pastiprinājumu paziņojumu e-pasta ziņojumi title: Atcelt abonēšanu media_attachments: validations: @@ -1656,6 +1664,7 @@ lv: delete: Konta dzēšana development: Izstrāde edit_profile: Labot profilu + export: Izgūt featured_tags: Piedāvātie tēmturi import: Imports import_and_export: Imports un eksports @@ -1802,11 +1811,11 @@ lv: title: Arhīva līdzņemšana suspicious_sign_in: change_password: mainīt paroli - details: 'Šeit ir detalizēta informācija par pierakstīšanos:' - explanation: Esam konstatējuši pierakstīšanos tavā kontā no jaunas IP adreses. + details: 'Šeit ir pieteikšanās izvērsums:' + explanation: Esam noteikuši pieteikšanos Tavā kontā no jaunas IP adreses. further_actions_html: Ja tas nebiji tu, iesakām nekavējoties %{action} un iespējot divu faktoru autentifikāciju, lai tavs konts būtu drošībā. subject: Tavam kontam ir piekļūts no jaunas IP adreses - title: Jauna pierakstīšanās + title: Jauna pieteikšanās warning: appeal: Iesniegt apelāciju appeal_description: Ja uzskatāt, ka tā ir kļūda, varat iesniegt apelāciju %{instance} darbiniekiem. diff --git a/config/locales/simple_form.cy.yml b/config/locales/simple_form.cy.yml index 5f3ac2818c..6c21683b07 100644 --- a/config/locales/simple_form.cy.yml +++ b/config/locales/simple_form.cy.yml @@ -3,13 +3,14 @@ cy: simple_form: hints: account: - attribution_domains_as_text: Un i bob llinell. Yn amddiffyn rhag cydnabyddiaethau ffug. + attribution_domains_as_text: Un i bob llinell. Yn amddiffyn rhag priodoli ffug. discoverable: Mae'n bosibl y bydd eich postiadau cyhoeddus a'ch proffil yn cael sylw neu'n cael eu hargymell mewn gwahanol feysydd o Mastodon ac efallai y bydd eich proffil yn cael ei awgrymu i ddefnyddwyr eraill. display_name: Eich enw llawn neu'ch enw hwyl. fields: Eich tudalen cartref, rhagenwau, oed, neu unrhyw beth. indexable: Mae'n bosib y bydd eich postiadau cyhoeddus yn ymddangos yng nghanlyniadau chwilio ar Mastodon. Mae'n bosibl y bydd pobl sydd wedi rhyngweithio â'ch postiadau yn dal i allu eu chwilio. note: 'Gallwch @grybwyll pobl eraill neu #hashnodau.' show_collections: Bydd pobl yn gallu pori trwy'r rhai rydych yn eu dilyn a'ch dilynwyr. Bydd y bobl rydych chi'n eu dilyn yn gweld eich bod chi'n eu dilyn beth bynnag. + unlocked: Bydd pobl yn gallu eich dilyn heb ofyn am gymeradwyaeth. Dad-diciwch os ydych am adolygu ceisiadau i'ch dilyn a dewis a ydych am dderbyn neu wrthod dilynwyr newydd. account_alias: acct: Rhowch enwdefnyddiwr@parth y cyfrif y hoffech chi symud ohono account_migration: diff --git a/config/locales/simple_form.hu.yml b/config/locales/simple_form.hu.yml index 230965fe87..60922b06b5 100644 --- a/config/locales/simple_form.hu.yml +++ b/config/locales/simple_form.hu.yml @@ -48,7 +48,7 @@ hu: digest: Csak hosszú távollét esetén küldődik és csak ha személyes üzenetet kaptál távollétedben email: Kapsz egy megerősítő e-mailt header: WEBP, PNG, GIF vagy JPG. Legfeljebb %{size}. Át lesz méretezve %{dimensions} képpontosra. - inbox_url: Másold ki a használandó relé szerver kezdőoldalának URL-jét + inbox_url: Másold ki a használandó továbbító kiszolgáló kezdőoldalának URL-jét irreversible: A kiszűrt bejegyzések visszafordíthatatlanul eltűnnek, a szűrő későbbi törlése esetén is locale: A felhasználói felület, e-mailek, push üzenetek nyelve password: Legalább 8 karakter @@ -195,7 +195,7 @@ hu: fields: Profil metaadatai header: Fejléc honeypot: "%{label} (ne töltsd ki)" - inbox_url: Relé inbox-hoz tartozó URL + inbox_url: Továbbító inbox-hoz tartozó URL irreversible: Eldobás elrejtés helyett locale: Felhasználói felület nyelve max_uses: Hányszor használható diff --git a/config/locales/simple_form.lv.yml b/config/locales/simple_form.lv.yml index da8dac3c22..2f4a05dca4 100644 --- a/config/locales/simple_form.lv.yml +++ b/config/locales/simple_form.lv.yml @@ -10,6 +10,7 @@ lv: indexable: Tavi publiskie ieraksti var tikt parādīti Mastodon meklēšanas iznākumā. Cilvēki, kuri ir mijiedarbojušies ar Taviem ierakstiem, var tos meklēt neatkarīgi no tā. note: 'Tu vari @minēt citus cilvēkus vai #mirkļbirkas.' show_collections: Cilvēki varēs pārlūkot Tavus sekotājus un sekojamos. Cilvēki, kuriem Tu seko, redzēs, ka Tu seko viņiem neatkarīgi no tā. + unlocked: Cilvēki varēs Tev sekot bez apstiprinājuma pieprasīšanas. Jānoņem atzīme, ja vēlies pārskatīt sekošanas pieprasījumus un izvēlēties, vai apstiprināt vai noraidīt jaunus sekotājus. account_alias: acct: Norādi konta lietotājvārdu@domēnu, no kura vēlies pārvākties account_migration: @@ -88,7 +89,7 @@ lv: media_cache_retention_period: Informācijas nesēju datnes no ierakstiem, kurus ir veikuši attālie lietotāji, tiek kešoti šajā serverī. Kad ir iestatīta apstiprinoša vērtība, informācijas nesēji tiks izdzēsti pēc norādītā dienu skaita. Ja informācijas nesēju dati tiks pieprasīti pēc tam, kad tie tika izdzēsti, tie tiks atkārtoti lejupielādēti, ja avota saturs joprojām būs pieejams. Saišu priekšskatījuma karšu vaicājumu biežuma ierobežojumu dēļ ir ieteicams iestatīt šo vērtību vismaz 14 dienas vai saišu priekšskatījuma kartes netiks atjauninātas pēc pieprasījuma pirms tā laika. peers_api_enabled: Domēna vārdu saraksts, ar kuriem šis serveris ir saskāries fediversā. Šeit nav iekļauti dati par to, vai tu veic federāciju ar noteiktu serveri, tikai tavs serveris par to zina. To izmanto dienesti, kas apkopo statistiku par federāciju vispārīgā nozīmē. profile_directory: Profilu direktorijā ir uzskaitīti visi lietotāji, kuri ir izvēlējušies būt atklājami. - require_invite_text: 'Ja pierakstīšanai nepieciešama manuāla apstiprināšana, izdari tā, lai teksta: “Kāpēc vēlaties pievienoties?” ievade ir obligāta, nevis opcionāla' + require_invite_text: Ja nepieciešama pašrocīga apstiprināšana, lai pierakstītos, teksta “Kāpēc vēlies pievienoties?” ievade jāpadara par nepieciešamu, nevis izvēles site_contact_email: Kā cilvēki var sazināties ar tevi par juridiskiem vai atbalsta jautājumiem. site_contact_username: Tagad cilvēki var tevi sasniegt Mastodon. site_extended_description: Jebkura papildu informācija, kas var būt noderīga apmeklētājiem un lietotājiem. Var strukturēt ar Markdown sintaksi. @@ -338,5 +339,5 @@ lv: text: nepieciešams title: sessions: - webauthn: Lai pierakstītos, izmanto vienu no savām drošības atslēgām + webauthn: Lai pieteiktos, jāizmanto viena no savām drošības atslēgām 'yes': Jā From 0838cf1e0576cbcb8df1f9a1a57d42abb51f866c Mon Sep 17 00:00:00 2001 From: Claire Date: Fri, 15 Nov 2024 14:37:45 +0100 Subject: [PATCH 19/64] Fix domain attribution field having autocorrect and autocapitalize enabled (#32903) --- app/views/settings/verifications/show.html.haml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/views/settings/verifications/show.html.haml b/app/views/settings/verifications/show.html.haml index 4def10e595..a93ffcebed 100644 --- a/app/views/settings/verifications/show.html.haml +++ b/app/views/settings/verifications/show.html.haml @@ -65,7 +65,7 @@ %p.lead= t('author_attribution.then_instructions') .fields-group - = f.input :attribution_domains_as_text, as: :text, wrapper: :with_block_label, input_html: { placeholder: "example1.com\nexample2.com\nexample3.com", rows: 4 } + = f.input :attribution_domains_as_text, as: :text, wrapper: :with_block_label, input_html: { placeholder: "example1.com\nexample2.com\nexample3.com", rows: 4, autocapitalize: 'none', autocorrect: 'off' } .actions = f.button :button, t('generic.save_changes'), type: :submit From f1ef7b5b433b392956469874392acb146bfc6c57 Mon Sep 17 00:00:00 2001 From: Claire Date: Fri, 15 Nov 2024 16:35:30 +0100 Subject: [PATCH 20/64] Fix uploading higher-than-wide GIF profile picture with libvips enabled (#32911) --- lib/paperclip/vips_lazy_thumbnail.rb | 1 + spec/fixtures/files/avatar-high.gif | Bin 0 -> 75006 bytes .../examples/models/concerns/account_avatar.rb | 9 ++++++++- 3 files changed, 9 insertions(+), 1 deletion(-) create mode 100644 spec/fixtures/files/avatar-high.gif diff --git a/lib/paperclip/vips_lazy_thumbnail.rb b/lib/paperclip/vips_lazy_thumbnail.rb index 4764b04af8..fea4b86064 100644 --- a/lib/paperclip/vips_lazy_thumbnail.rb +++ b/lib/paperclip/vips_lazy_thumbnail.rb @@ -52,6 +52,7 @@ module Paperclip # implement. If cropping ever becomes necessary for other situations, this will # need to be expanded. crop_width = crop_height = [target_width, target_height].min if @target_geometry&.square? + crop_width = crop_height = "'min(iw,ih)'" if crop_width == 'ih' filter = begin if @crop diff --git a/spec/fixtures/files/avatar-high.gif b/spec/fixtures/files/avatar-high.gif new file mode 100644 index 0000000000000000000000000000000000000000..7639f2c507ee72beb745a2ab0677590eb9eb7459 GIT binary patch literal 75006 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 Date: Fri, 15 Nov 2024 15:37:30 +0000 Subject: [PATCH 21/64] Rails 7+: primary_abstract_class recommendation (#32909) --- app/models/application_record.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/models/application_record.rb b/app/models/application_record.rb index 299aad6340..24e9d6aeba 100644 --- a/app/models/application_record.rb +++ b/app/models/application_record.rb @@ -1,7 +1,7 @@ # frozen_string_literal: true class ApplicationRecord < ActiveRecord::Base - self.abstract_class = true + primary_abstract_class include Remotable From 297ce9ef4474c80e10043db7cc61b4fc331c68c1 Mon Sep 17 00:00:00 2001 From: Matt Jankowski Date: Fri, 15 Nov 2024 10:49:26 -0500 Subject: [PATCH 22/64] Move body class to shared partial for web app controller concern views (#31797) --- app/controllers/concerns/web_app_controller_concern.rb | 5 ----- app/views/shared/_web_app.html.haml | 1 + spec/system/about_spec.rb | 1 + spec/system/home_spec.rb | 2 ++ spec/system/privacy_spec.rb | 1 + spec/system/tags_spec.rb | 1 + 6 files changed, 6 insertions(+), 5 deletions(-) diff --git a/app/controllers/concerns/web_app_controller_concern.rb b/app/controllers/concerns/web_app_controller_concern.rb index 9485ecda49..249bb20a25 100644 --- a/app/controllers/concerns/web_app_controller_concern.rb +++ b/app/controllers/concerns/web_app_controller_concern.rb @@ -7,7 +7,6 @@ module WebAppControllerConcern vary_by 'Accept, Accept-Language, Cookie' before_action :redirect_unauthenticated_to_permalinks! - before_action :set_app_body_class content_security_policy do |p| policy = ContentSecurityPolicy.new @@ -24,10 +23,6 @@ module WebAppControllerConcern !(ENV['ONE_CLICK_SSO_LOGIN'] == 'true' && ENV['OMNIAUTH_ONLY'] == 'true' && Devise.omniauth_providers.length == 1) && current_user.nil? end - def set_app_body_class - @body_classes = 'app-body' - end - def redirect_unauthenticated_to_permalinks! return if user_signed_in? && current_account.moved_to_account_id.nil? diff --git a/app/views/shared/_web_app.html.haml b/app/views/shared/_web_app.html.haml index 89d6ee567d..4f9a20a9f4 100644 --- a/app/views/shared/_web_app.html.haml +++ b/app/views/shared/_web_app.html.haml @@ -1,3 +1,4 @@ +- content_for :body_classes, 'app-body' - content_for :header_tags do - if user_signed_in? = preload_pack_asset 'features/compose.js' diff --git a/spec/system/about_spec.rb b/spec/system/about_spec.rb index f832802f91..d7fd7f51a1 100644 --- a/spec/system/about_spec.rb +++ b/spec/system/about_spec.rb @@ -8,5 +8,6 @@ RSpec.describe 'About page' do expect(page) .to have_css('noscript', text: /Mastodon/) + .and have_css('body', class: 'app-body') end end diff --git a/spec/system/home_spec.rb b/spec/system/home_spec.rb index c1ce4e1726..0838b3d8e7 100644 --- a/spec/system/home_spec.rb +++ b/spec/system/home_spec.rb @@ -11,6 +11,7 @@ RSpec.describe 'Home page' do expect(page) .to have_css('noscript', text: /Mastodon/) + .and have_css('body', class: 'app-body') end end @@ -20,6 +21,7 @@ RSpec.describe 'Home page' do expect(page) .to have_css('noscript', text: /Mastodon/) + .and have_css('body', class: 'app-body') end end end diff --git a/spec/system/privacy_spec.rb b/spec/system/privacy_spec.rb index 631440ebb2..f2e4d5a993 100644 --- a/spec/system/privacy_spec.rb +++ b/spec/system/privacy_spec.rb @@ -8,5 +8,6 @@ RSpec.describe 'Privacy policy page' do expect(page) .to have_css('noscript', text: /Mastodon/) + .and have_css('body', class: 'app-body') end end diff --git a/spec/system/tags_spec.rb b/spec/system/tags_spec.rb index f39c6bf0d8..9da5768c7f 100644 --- a/spec/system/tags_spec.rb +++ b/spec/system/tags_spec.rb @@ -13,6 +13,7 @@ RSpec.describe 'Tags' do expect(page) .to have_css('noscript', text: /Mastodon/) + .and have_css('body', class: 'app-body') .and have_private_cache_control end end From 319109029d8eb8b851874b3c80ced3536ba81f29 Mon Sep 17 00:00:00 2001 From: Matt Jankowski Date: Fri, 15 Nov 2024 10:52:37 -0500 Subject: [PATCH 23/64] Fix logic in "last used at per application" oauth token list (#32912) --- .../authorized_applications_controller.rb | 8 +------ app/models/user.rb | 9 ++++++++ spec/models/user_spec.rb | 23 +++++++++++++++++++ 3 files changed, 33 insertions(+), 7 deletions(-) diff --git a/app/controllers/oauth/authorized_applications_controller.rb b/app/controllers/oauth/authorized_applications_controller.rb index 267409a9ce..9e541e5e3c 100644 --- a/app/controllers/oauth/authorized_applications_controller.rb +++ b/app/controllers/oauth/authorized_applications_controller.rb @@ -35,12 +35,6 @@ class Oauth::AuthorizedApplicationsController < Doorkeeper::AuthorizedApplicatio end def set_last_used_at_by_app - @last_used_at_by_app = Doorkeeper::AccessToken - .select('DISTINCT ON (application_id) application_id, last_used_at') - .where(resource_owner_id: current_resource_owner.id) - .where.not(last_used_at: nil) - .order(application_id: :desc, last_used_at: :desc) - .pluck(:application_id, :last_used_at) - .to_h + @last_used_at_by_app = current_resource_owner.applications_last_used end end diff --git a/app/models/user.rb b/app/models/user.rb index f717dcd860..be9ebac699 100644 --- a/app/models/user.rb +++ b/app/models/user.rb @@ -280,6 +280,15 @@ class User < ApplicationRecord save! end + def applications_last_used + Doorkeeper::AccessToken + .where(resource_owner_id: id) + .where.not(last_used_at: nil) + .group(:application_id) + .maximum(:last_used_at) + .to_h + end + def token_for_app(app) return nil if app.nil? || app.owner != self diff --git a/spec/models/user_spec.rb b/spec/models/user_spec.rb index 4393be5a4e..9a5a070d25 100644 --- a/spec/models/user_spec.rb +++ b/spec/models/user_spec.rb @@ -598,4 +598,27 @@ RSpec.describe User do end end end + + describe '#applications_last_used' do + let!(:user) { Fabricate(:user) } + + let!(:never_used_application) { Fabricate :application, owner: user } + let!(:application_one) { Fabricate :application, owner: user } + let!(:application_two) { Fabricate :application, owner: user } + + before do + _other_user_token = Fabricate :access_token, last_used_at: 3.days.ago + _never_used_token = Fabricate :access_token, application: never_used_application, resource_owner_id: user.id, last_used_at: nil + _app_one_old_token = Fabricate :access_token, application: application_one, resource_owner_id: user.id, last_used_at: 5.days.ago + _app_one_new_token = Fabricate :access_token, application: application_one, resource_owner_id: user.id, last_used_at: 1.day.ago + _never_used_token = Fabricate :access_token, application: application_two, resource_owner_id: user.id, last_used_at: 5.days.ago + end + + it 'returns a hash of unique applications with last used values' do + expect(user.applications_last_used) + .to include(application_one.id => be_within(1.0).of(1.day.ago)) + .and include(application_two.id => be_within(1.0).of(5.days.ago)) + .and not_include(never_used_application.id) + end + end end From 54a7c1898e36cda393dc79cde4d44b53e0a5299a Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Fri, 15 Nov 2024 15:55:10 +0000 Subject: [PATCH 24/64] Update dependency uuid to v11 (#32676) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- streaming/package.json | 2 +- yarn.lock | 12 ++++++------ 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/streaming/package.json b/streaming/package.json index 585c4be4e1..380f1c429d 100644 --- a/streaming/package.json +++ b/streaming/package.json @@ -27,7 +27,7 @@ "pino": "^9.0.0", "pino-http": "^10.0.0", "prom-client": "^15.0.0", - "uuid": "^10.0.0", + "uuid": "^11.0.0", "ws": "^8.12.1" }, "devDependencies": { diff --git a/yarn.lock b/yarn.lock index 7fd68ac8c1..1f9ff3426b 100644 --- a/yarn.lock +++ b/yarn.lock @@ -3027,7 +3027,7 @@ __metadata: prom-client: "npm:^15.0.0" typescript: "npm:^5.0.4" utf-8-validate: "npm:^6.0.3" - uuid: "npm:^10.0.0" + uuid: "npm:^11.0.0" ws: "npm:^8.12.1" dependenciesMeta: bufferutil: @@ -17680,12 +17680,12 @@ __metadata: languageName: node linkType: hard -"uuid@npm:^10.0.0": - version: 10.0.0 - resolution: "uuid@npm:10.0.0" +"uuid@npm:^11.0.0": + version: 11.0.1 + resolution: "uuid@npm:11.0.1" bin: - uuid: dist/bin/uuid - checksum: 10c0/eab18c27fe4ab9fb9709a5d5f40119b45f2ec8314f8d4cf12ce27e4c6f4ffa4a6321dc7db6c515068fa373c075b49691ba969f0010bf37f44c37ca40cd6bf7fe + uuid: dist/esm/bin/uuid + checksum: 10c0/cd5a1d7eccfd6da80382ec88cfa28b68dce2c1c1402228b813fc0065ab8b29d20594cffeb67d850bc166ade677a6c35741072bd9dd0cc7d565c1fe8eca14ef22 languageName: node linkType: hard From 7bd7705f591692f9df0346f025a30ef8eda25ae1 Mon Sep 17 00:00:00 2001 From: Matt Jankowski Date: Fri, 15 Nov 2024 11:07:26 -0500 Subject: [PATCH 25/64] Combine shared-setup examples across `spec/controllers/auth/*` specs (#32906) --- .../auth/challenges_controller_spec.rb | 32 ++--- .../auth/confirmations_controller_spec.rb | 25 ++-- .../auth/passwords_controller_spec.rb | 53 ++++--- .../auth/registrations_controller_spec.rb | 135 +++++++++--------- 4 files changed, 121 insertions(+), 124 deletions(-) diff --git a/spec/controllers/auth/challenges_controller_spec.rb b/spec/controllers/auth/challenges_controller_spec.rb index 56fdfa61b5..3c9d2a5964 100644 --- a/spec/controllers/auth/challenges_controller_spec.rb +++ b/spec/controllers/auth/challenges_controller_spec.rb @@ -8,9 +8,7 @@ RSpec.describe Auth::ChallengesController do let(:password) { 'foobar12345' } let(:user) { Fabricate(:user, password: password) } - before do - sign_in user - end + before { sign_in user } describe 'POST #create' do let(:return_to) { edit_user_registration_path } @@ -18,28 +16,24 @@ RSpec.describe Auth::ChallengesController do context 'with correct password' do before { post :create, params: { form_challenge: { return_to: return_to, current_password: password } } } - it 'redirects back' do - expect(response).to redirect_to(return_to) - end - - it 'sets session' do - expect(session[:challenge_passed_at]).to_not be_nil + it 'redirects back and sets challenge passed at in session' do + expect(response) + .to redirect_to(return_to) + expect(session[:challenge_passed_at]) + .to_not be_nil end end context 'with incorrect password' do before { post :create, params: { form_challenge: { return_to: return_to, current_password: 'hhfggjjd562' } } } - it 'renders challenge' do - expect(response).to render_template('auth/challenges/new') - end - - it 'displays error' do - expect(response.body).to include 'Invalid password' - end - - it 'does not set session' do - expect(session[:challenge_passed_at]).to be_nil + it 'renders challenge, displays error, does not set session' do + expect(response) + .to render_template('auth/challenges/new') + expect(response.body) + .to include 'Invalid password' + expect(session[:challenge_passed_at]) + .to be_nil end end end diff --git a/spec/controllers/auth/confirmations_controller_spec.rb b/spec/controllers/auth/confirmations_controller_spec.rb index a5b212e660..09a178f0e8 100644 --- a/spec/controllers/auth/confirmations_controller_spec.rb +++ b/spec/controllers/auth/confirmations_controller_spec.rb @@ -23,12 +23,11 @@ RSpec.describe Auth::ConfirmationsController do get :show, params: { confirmation_token: 'foobar' } end - it 'redirects to login' do - expect(response).to redirect_to(new_user_session_path) - end - - it 'queues up bootstrapping of home timeline' do - expect(BootstrapTimelineWorker).to have_received(:perform_async).with(user.account_id) + it 'redirects to login and queues worker' do + expect(response) + .to redirect_to(new_user_session_path) + expect(BootstrapTimelineWorker) + .to have_received(:perform_async).with(user.account_id) end end @@ -88,13 +87,13 @@ RSpec.describe Auth::ConfirmationsController do get :show, params: { confirmation_token: 'foobar' } end - it 'redirects to login and confirms email' do - expect(response).to redirect_to(new_user_session_path) - expect(user.reload.unconfirmed_email).to be_nil - end - - it 'does not queue up bootstrapping of home timeline' do - expect(BootstrapTimelineWorker).to_not have_received(:perform_async) + it 'redirects to login, confirms email, does not queue worker' do + expect(response) + .to redirect_to(new_user_session_path) + expect(user.reload.unconfirmed_email) + .to be_nil + expect(BootstrapTimelineWorker) + .to_not have_received(:perform_async) end end end diff --git a/spec/controllers/auth/passwords_controller_spec.rb b/spec/controllers/auth/passwords_controller_spec.rb index 9ccbb9e494..90095ac4b8 100644 --- a/spec/controllers/auth/passwords_controller_spec.rb +++ b/spec/controllers/auth/passwords_controller_spec.rb @@ -57,29 +57,30 @@ RSpec.describe Auth::PasswordsController do post :update, params: { user: { password: password, password_confirmation: password, reset_password_token: token } } end - it 'redirect to sign in' do - expect(response).to redirect_to '/auth/sign_in' - end + it 'resets the password' do + expect(response) + .to redirect_to '/auth/sign_in' - it 'changes password' do - this_user = User.find(user.id) + # Change password + expect(User.find(user.id)) + .to be_present + .and be_valid_password(password) - expect(this_user).to_not be_nil - expect(this_user.valid_password?(password)).to be true - end + # Deactivate session + expect(user.session_activations.count) + .to eq 0 + expect { session_activation.reload } + .to raise_error(ActiveRecord::RecordNotFound) - it 'deactivates all sessions' do - expect(user.session_activations.count).to eq 0 - expect { session_activation.reload }.to raise_error(ActiveRecord::RecordNotFound) - end + # Revoke tokens + expect(Doorkeeper::AccessToken.active_for(user).count) + .to eq 0 - it 'revokes all access tokens' do - expect(Doorkeeper::AccessToken.active_for(user).count).to eq 0 - end - - it 'removes push subscriptions' do - expect(Web::PushSubscription.where(user: user).or(Web::PushSubscription.where(access_token: access_token)).count).to eq 0 - expect { web_push_subscription.reload }.to raise_error(ActiveRecord::RecordNotFound) + # Remove push subs + expect(Web::PushSubscription.where(user: user).or(Web::PushSubscription.where(access_token: access_token)).count) + .to eq 0 + expect { web_push_subscription.reload } + .to raise_error(ActiveRecord::RecordNotFound) end end @@ -88,15 +89,13 @@ RSpec.describe Auth::PasswordsController do post :update, params: { user: { password: password, password_confirmation: password, reset_password_token: 'some_invalid_value' } } end - it 'renders reset password' do - expect(response).to render_template(:new) - end + it 'renders reset password and retains password' do + expect(response) + .to render_template(:new) - it 'retains password' do - this_user = User.find(user.id) - - expect(this_user).to_not be_nil - expect(this_user.external_or_valid_password?(user.password)).to be true + expect(User.find(user.id)) + .to be_present + .and be_external_or_valid_password(user.password) end end end diff --git a/spec/controllers/auth/registrations_controller_spec.rb b/spec/controllers/auth/registrations_controller_spec.rb index d1542128e7..739cb455e8 100644 --- a/spec/controllers/auth/registrations_controller_spec.rb +++ b/spec/controllers/auth/registrations_controller_spec.rb @@ -6,25 +6,33 @@ RSpec.describe Auth::RegistrationsController do render_views shared_examples 'checks for enabled registrations' do |path| - it 'redirects if it is in single user mode while it is open for registration' do - Fabricate(:account) - Setting.registrations_mode = 'open' - allow(Rails.configuration.x).to receive(:single_user_mode).and_return(true) + context 'when in single user mode and open for registration' do + before do + Setting.registrations_mode = 'open' + allow(Rails.configuration.x).to receive(:single_user_mode).and_return(true) + end - get path + it 'redirects to root' do + Fabricate(:account) + get path - expect(response).to redirect_to '/' - expect(Rails.configuration.x).to have_received(:single_user_mode) + expect(response).to redirect_to '/' + expect(Rails.configuration.x).to have_received(:single_user_mode) + end end - it 'redirects if it is not open for registration while it is not in single user mode' do - Setting.registrations_mode = 'none' - allow(Rails.configuration.x).to receive(:single_user_mode).and_return(false) + context 'when registrations closed and not in single user mode' do + before do + Setting.registrations_mode = 'none' + allow(Rails.configuration.x).to receive(:single_user_mode).and_return(false) + end - get path + it 'redirects to root' do + get path - expect(response).to redirect_to '/' - expect(Rails.configuration.x).to have_received(:single_user_mode) + expect(response).to redirect_to '/' + expect(Rails.configuration.x).to have_received(:single_user_mode) + end end end @@ -35,12 +43,12 @@ RSpec.describe Auth::RegistrationsController do get :edit end - it 'returns http success' do - expect(response).to have_http_status(200) - end + it 'returns http success and cache headers' do + expect(response) + .to have_http_status(200) - it 'returns private cache control header' do - expect(response.headers['Cache-Control']).to include('private, no-store') + expect(response.headers['Cache-Control']) + .to include('private, no-store') end end @@ -53,14 +61,13 @@ RSpec.describe Auth::RegistrationsController do sign_in(user, scope: :user) end - it 'returns http success' do + it 'returns http success and cache headers' do put :update - expect(response).to have_http_status(200) - end - it 'returns private cache control headers' do - put :update - expect(response.headers['Cache-Control']).to include('private, no-store') + expect(response) + .to have_http_status(200) + expect(response.headers['Cache-Control']) + .to include('private, no-store') end it 'can update the user email' do @@ -174,16 +181,14 @@ RSpec.describe Auth::RegistrationsController do post :create, params: { user: { account_attributes: { username: 'test' }, email: 'test@example.com', password: '12345678', password_confirmation: '12345678', agreement: 'true' } } end - it 'redirects to setup' do + it 'redirects to setup and creates user' do subject - expect(response).to redirect_to auth_setup_path - end - it 'creates user' do - subject - user = User.find_by(email: 'test@example.com') - expect(user).to_not be_nil - expect(user.locale).to eq(accept_language) + expect(response) + .to redirect_to auth_setup_path + expect(User.find_by(email: 'test@example.com')) + .to be_present + .and have_attributes(locale: eq(accept_language)) end end @@ -254,17 +259,18 @@ RSpec.describe Auth::RegistrationsController do post :create, params: { user: { account_attributes: { username: 'test' }, email: 'test@example.com', password: '12345678', password_confirmation: '12345678', agreement: 'true' } } end - it 'redirects to setup' do + it 'redirects to setup and creates user' do subject - expect(response).to redirect_to auth_setup_path - end - it 'creates user' do - subject - 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) + expect(response) + .to redirect_to auth_setup_path + + expect(User.find_by(email: 'test@example.com')) + .to be_present + .and have_attributes( + locale: eq(accept_language), + approved: be(false) + ) end end @@ -276,17 +282,17 @@ RSpec.describe Auth::RegistrationsController do post :create, params: { user: { account_attributes: { username: 'test' }, email: 'test@example.com', password: '12345678', password_confirmation: '12345678', invite_code: invite.code, agreement: 'true' } } end - it 'redirects to setup' do + it 'redirects to setup and creates user' do subject - expect(response).to redirect_to auth_setup_path - end - it 'creates user' do - subject - 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) + expect(response).to redirect_to auth_setup_path + + expect(User.find_by(email: 'test@example.com')) + .to be_present + .and have_attributes( + locale: eq(accept_language), + approved: be(false) + ) end end @@ -300,17 +306,17 @@ RSpec.describe Auth::RegistrationsController do post :create, params: { user: { account_attributes: { username: 'test' }, email: 'test@example.com', password: '12345678', password_confirmation: '12345678', invite_code: invite.code, agreement: 'true' } } end - it 'redirects to setup' do + it 'redirects to setup and creates user' do subject - expect(response).to redirect_to auth_setup_path - end - it 'creates user' do - subject - 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(true) + expect(response).to redirect_to auth_setup_path + + expect(User.find_by(email: 'test@example.com')) + .to be_present + .and have_attributes( + locale: eq(accept_language), + approved: be(true) + ) end end @@ -348,12 +354,11 @@ RSpec.describe Auth::RegistrationsController do delete :destroy end - it 'returns http not found' do - expect(response).to have_http_status(404) - end - - it 'does not delete user' do - expect(User.find(user.id)).to_not be_nil + it 'returns http not found and keeps user' do + expect(response) + .to have_http_status(404) + expect(User.find(user.id)) + .to_not be_nil end end end From 9d3fcc3546df1cef5652ea29e370a86cb87d7a21 Mon Sep 17 00:00:00 2001 From: Matt Jankowski Date: Fri, 15 Nov 2024 11:10:20 -0500 Subject: [PATCH 26/64] Remove unused failure action in api/base controller spec (#32905) --- spec/controllers/api/base_controller_spec.rb | 4 ---- 1 file changed, 4 deletions(-) diff --git a/spec/controllers/api/base_controller_spec.rb b/spec/controllers/api/base_controller_spec.rb index 1e0e7c8f4d..bd4073dfaf 100644 --- a/spec/controllers/api/base_controller_spec.rb +++ b/spec/controllers/api/base_controller_spec.rb @@ -7,10 +7,6 @@ RSpec.describe Api::BaseController do def success head 200 end - - def failure - FakeService.new - end end it 'returns private cache control headers by default' do From 44d92fa4f6aac5c45ad358287af48cd879f5665e Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Fri, 15 Nov 2024 17:15:44 +0100 Subject: [PATCH 27/64] Update dependency uuid to v11.0.3 (#32913) 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 1f9ff3426b..aaecae7a2a 100644 --- a/yarn.lock +++ b/yarn.lock @@ -17681,11 +17681,11 @@ __metadata: linkType: hard "uuid@npm:^11.0.0": - version: 11.0.1 - resolution: "uuid@npm:11.0.1" + version: 11.0.3 + resolution: "uuid@npm:11.0.3" bin: uuid: dist/esm/bin/uuid - checksum: 10c0/cd5a1d7eccfd6da80382ec88cfa28b68dce2c1c1402228b813fc0065ab8b29d20594cffeb67d850bc166ade677a6c35741072bd9dd0cc7d565c1fe8eca14ef22 + checksum: 10c0/cee762fc76d949a2ff9205770334699e0043d52bb766472593a25f150077c9deed821230251ea3d6ab3943a5ea137d2826678797f1d5f6754c7ce5ce27e9f7a6 languageName: node linkType: hard From a1ac2a73fffa2a8e1b3aa71041fd01c1587e0d5f Mon Sep 17 00:00:00 2001 From: Matt Jankowski Date: Sat, 16 Nov 2024 15:48:10 -0500 Subject: [PATCH 28/64] Remove remnants of embed views (#32419) --- app/helpers/statuses_helper.rb | 11 ------ app/views/admin/reports/_status.html.haml | 2 +- .../filters/statuses/_status_filter.html.haml | 2 +- spec/helpers/accounts_helper_spec.rb | 35 ++----------------- spec/helpers/statuses_helper_spec.rb | 24 ------------- 5 files changed, 4 insertions(+), 70 deletions(-) diff --git a/app/helpers/statuses_helper.rb b/app/helpers/statuses_helper.rb index 9bbb03fd82..16b9d3fb53 100644 --- a/app/helpers/statuses_helper.rb +++ b/app/helpers/statuses_helper.rb @@ -1,9 +1,6 @@ # frozen_string_literal: true module StatusesHelper - EMBEDDED_CONTROLLER = 'statuses' - EMBEDDED_ACTION = 'embed' - VISIBLITY_ICONS = { public: 'globe', unlisted: 'lock_open', @@ -60,18 +57,10 @@ module StatusesHelper components.compact_blank.join("\n\n") end - def stream_link_target - embedded_view? ? '_blank' : nil - end - def visibility_icon(status) VISIBLITY_ICONS[status.visibility.to_sym] end - def embedded_view? - params[:controller] == EMBEDDED_CONTROLLER && params[:action] == EMBEDDED_ACTION - end - def prefers_autoplay? ActiveModel::Type::Boolean.new.cast(params[:autoplay]) || current_user&.setting_auto_play_gif end diff --git a/app/views/admin/reports/_status.html.haml b/app/views/admin/reports/_status.html.haml index 3a35fdd272..bd688a1a5d 100644 --- a/app/views/admin/reports/_status.html.haml +++ b/app/views/admin/reports/_status.html.haml @@ -44,7 +44,7 @@ = t("statuses.visibilities.#{status.visibility}") · - = link_to ActivityPub::TagManager.instance.url_for(status.proper), class: 'detailed-status__link', target: stream_link_target, rel: 'noopener noreferrer' do + = link_to ActivityPub::TagManager.instance.url_for(status.proper), class: 'detailed-status__link', rel: 'noopener noreferrer' do = t('admin.statuses.view_publicly') - if status.proper.sensitive? diff --git a/app/views/filters/statuses/_status_filter.html.haml b/app/views/filters/statuses/_status_filter.html.haml index d0d04638d2..3476869e60 100644 --- a/app/views/filters/statuses/_status_filter.html.haml +++ b/app/views/filters/statuses/_status_filter.html.haml @@ -23,7 +23,7 @@ = image_tag(status.account.avatar.url, width: 15, height: 15, alt: '', class: 'avatar') .username= status.account.acct · - = link_to ActivityPub::TagManager.instance.url_for(status), class: 'detailed-status__datetime', target: stream_link_target, rel: 'noopener noreferrer' do + = link_to ActivityPub::TagManager.instance.url_for(status), class: 'detailed-status__datetime', rel: 'noopener noreferrer' do %time.formatted{ datetime: status.created_at.iso8601, title: l(status.created_at) }= l(status.created_at) - if status.edited? · diff --git a/spec/helpers/accounts_helper_spec.rb b/spec/helpers/accounts_helper_spec.rb index 2c949cde69..8526482362 100644 --- a/spec/helpers/accounts_helper_spec.rb +++ b/spec/helpers/accounts_helper_spec.rb @@ -3,16 +3,6 @@ require 'rails_helper' RSpec.describe AccountsHelper do - def set_not_embedded_view - params[:controller] = "not_#{StatusesHelper::EMBEDDED_CONTROLLER}" - params[:action] = "not_#{StatusesHelper::EMBEDDED_ACTION}" - end - - def set_embedded_view - params[:controller] = StatusesHelper::EMBEDDED_CONTROLLER - params[:action] = StatusesHelper::EMBEDDED_ACTION - end - describe '#display_name' do it 'uses the display name when it exists' do account = Account.new(display_name: 'Display', username: 'Username') @@ -28,9 +18,8 @@ RSpec.describe AccountsHelper do end describe '#acct' do - it 'is fully qualified for embedded local accounts' do + it 'is fully qualified for local accounts' do allow(Rails.configuration.x).to receive(:local_domain).and_return('local_domain') - set_embedded_view account = Account.new(domain: nil, username: 'user') acct = helper.acct(account) @@ -38,32 +27,12 @@ RSpec.describe AccountsHelper do expect(acct).to eq '@user@local_domain' end - it 'is fully qualified for embedded foreign accounts' do - set_embedded_view + it 'is fully qualified for remote accounts' do account = Account.new(domain: 'foreign_server.com', username: 'user') acct = helper.acct(account) expect(acct).to eq '@user@foreign_server.com' end - - it 'is fully qualified for non embedded foreign accounts' do - set_not_embedded_view - account = Account.new(domain: 'foreign_server.com', username: 'user') - - acct = helper.acct(account) - - expect(acct).to eq '@user@foreign_server.com' - end - - it 'is fully qualified for non embedded local accounts' do - allow(Rails.configuration.x).to receive(:local_domain).and_return('local_domain') - set_not_embedded_view - account = Account.new(domain: nil, username: 'user') - - acct = helper.acct(account) - - expect(acct).to eq '@user@local_domain' - end end end diff --git a/spec/helpers/statuses_helper_spec.rb b/spec/helpers/statuses_helper_spec.rb index edd3e8f2f7..07ad72eda9 100644 --- a/spec/helpers/statuses_helper_spec.rb +++ b/spec/helpers/statuses_helper_spec.rb @@ -77,28 +77,4 @@ RSpec.describe StatusesHelper do end end end - - describe '#stream_link_target' do - it 'returns nil if it is not an embedded view' do - set_not_embedded_view - - expect(helper.stream_link_target).to be_nil - end - - it 'returns _blank if it is an embedded view' do - set_embedded_view - - expect(helper.stream_link_target).to eq '_blank' - end - end - - def set_not_embedded_view - params[:controller] = "not_#{StatusesHelper::EMBEDDED_CONTROLLER}" - params[:action] = "not_#{StatusesHelper::EMBEDDED_ACTION}" - end - - def set_embedded_view - params[:controller] = StatusesHelper::EMBEDDED_CONTROLLER - params[:action] = StatusesHelper::EMBEDDED_ACTION - end end From 1c6f53e70f3eb59e2870a55c9f271524ff6115a4 Mon Sep 17 00:00:00 2001 From: Matt Jankowski Date: Mon, 18 Nov 2024 03:07:18 -0500 Subject: [PATCH 29/64] Use `with_options` blocks in `Associations` concern (#32840) --- app/models/concerns/account/associations.rb | 101 +++++++++----------- 1 file changed, 47 insertions(+), 54 deletions(-) diff --git a/app/models/concerns/account/associations.rb b/app/models/concerns/account/associations.rb index 637e785953..4e29235b6b 100644 --- a/app/models/concerns/account/associations.rb +++ b/app/models/concerns/account/associations.rb @@ -4,75 +4,68 @@ module Account::Associations extend ActiveSupport::Concern included do - # Local users - has_one :user, inverse_of: :account, dependent: :destroy + # Core associations + with_options dependent: :destroy do + # Association where account owns record + with_options inverse_of: :account do + has_many :account_moderation_notes + has_many :account_pins + has_many :account_warnings + has_many :aliases, class_name: 'AccountAlias' + has_many :bookmarks + has_many :conversations, class_name: 'AccountConversation' + has_many :custom_filters + has_many :favourites + has_many :featured_tags, -> { includes(:tag) } + has_many :list_accounts + has_many :media_attachments + has_many :mentions + has_many :migrations, class_name: 'AccountMigration' + has_many :notification_permissions + has_many :notification_requests + has_many :notifications + has_many :owned_lists, class_name: 'List' + has_many :polls + has_many :report_notes + has_many :reports + has_many :scheduled_statuses + has_many :status_pins + has_many :statuses - # Timelines - has_many :statuses, inverse_of: :account, dependent: :destroy - has_many :favourites, inverse_of: :account, dependent: :destroy - has_many :bookmarks, inverse_of: :account, dependent: :destroy - has_many :mentions, inverse_of: :account, dependent: :destroy - has_many :conversations, class_name: 'AccountConversation', dependent: :destroy, inverse_of: :account - has_many :scheduled_statuses, inverse_of: :account, dependent: :destroy + has_one :deletion_request, class_name: 'AccountDeletionRequest' + has_one :follow_recommendation_suppression + has_one :notification_policy + has_one :statuses_cleanup_policy, class_name: 'AccountStatusesCleanupPolicy' + has_one :user + end - # Notifications - has_many :notifications, inverse_of: :account, dependent: :destroy - has_one :notification_policy, inverse_of: :account, dependent: :destroy - has_many :notification_permissions, inverse_of: :account, dependent: :destroy - has_many :notification_requests, inverse_of: :account, dependent: :destroy + # Association where account is targeted by record + with_options foreign_key: :target_account_id, inverse_of: :target_account do + has_many :strikes, class_name: 'AccountWarning' + has_many :targeted_moderation_notes, class_name: 'AccountModerationNote' + has_many :targeted_reports, class_name: 'Report' + end + end - # Pinned statuses - has_many :status_pins, inverse_of: :account, dependent: :destroy + # Status records pinned by the account has_many :pinned_statuses, -> { reorder('status_pins.created_at DESC') }, through: :status_pins, class_name: 'Status', source: :status - # Endorsements - has_many :account_pins, inverse_of: :account, dependent: :destroy + # Account records endorsed (pinned) by the account has_many :endorsed_accounts, through: :account_pins, class_name: 'Account', source: :target_account - # Media - has_many :media_attachments, dependent: :destroy - has_many :polls, dependent: :destroy - - # Report relationships - has_many :reports, dependent: :destroy, inverse_of: :account - has_many :targeted_reports, class_name: 'Report', foreign_key: :target_account_id, dependent: :destroy, inverse_of: :target_account - - has_many :report_notes, dependent: :destroy - has_many :custom_filters, inverse_of: :account, dependent: :destroy - - # Moderation notes - has_many :account_moderation_notes, dependent: :destroy, inverse_of: :account - has_many :targeted_moderation_notes, class_name: 'AccountModerationNote', foreign_key: :target_account_id, dependent: :destroy, inverse_of: :target_account - has_many :account_warnings, dependent: :destroy, inverse_of: :account - has_many :strikes, class_name: 'AccountWarning', foreign_key: :target_account_id, dependent: :destroy, inverse_of: :target_account - - # Lists (that the account is on, not owned by the account) - has_many :list_accounts, inverse_of: :account, dependent: :destroy + # List records the account has been added to (not owned by the account) has_many :lists, through: :list_accounts - # Lists (owned by the account) - has_many :owned_lists, class_name: 'List', dependent: :destroy, inverse_of: :account - - # Account migrations + # Account record where account has been migrated belongs_to :moved_to_account, class_name: 'Account', optional: true - has_many :migrations, class_name: 'AccountMigration', dependent: :destroy, inverse_of: :account - has_many :aliases, class_name: 'AccountAlias', dependent: :destroy, inverse_of: :account - # Hashtags + # Tag records applied to account has_and_belongs_to_many :tags # rubocop:disable Rails/HasAndBelongsToMany - has_many :featured_tags, -> { includes(:tag) }, dependent: :destroy, inverse_of: :account - # Account deletion requests - has_one :deletion_request, class_name: 'AccountDeletionRequest', inverse_of: :account, dependent: :destroy - - # Follow recommendations + # FollowRecommendation for account (surfaced via view) has_one :follow_recommendation, inverse_of: :account, dependent: nil - has_one :follow_recommendation_suppression, inverse_of: :account, dependent: :destroy - # Account statuses cleanup policy - has_one :statuses_cleanup_policy, class_name: 'AccountStatusesCleanupPolicy', inverse_of: :account, dependent: :destroy - - # Imports + # BulkImport records owned by account has_many :bulk_imports, inverse_of: :account, dependent: :delete_all end end From bcf5d30e01b711b86505f9eeae067dea08e03b41 Mon Sep 17 00:00:00 2001 From: Renaud Chaput Date: Mon, 18 Nov 2024 09:41:09 +0100 Subject: [PATCH 30/64] Add OpenTelemetry VCS attributes (#32904) --- .github/workflows/build-container-image.yml | 1 + Dockerfile | 307 ++++++++++---------- config/initializers/opentelemetry.rb | 7 + lib/mastodon/version.rb | 4 + 4 files changed, 167 insertions(+), 152 deletions(-) diff --git a/.github/workflows/build-container-image.yml b/.github/workflows/build-container-image.yml index 03a0f5bf37..6204319a63 100644 --- a/.github/workflows/build-container-image.yml +++ b/.github/workflows/build-container-image.yml @@ -92,6 +92,7 @@ jobs: build-args: | MASTODON_VERSION_PRERELEASE=${{ inputs.version_prerelease }} MASTODON_VERSION_METADATA=${{ inputs.version_metadata }} + SOURCE_COMMIT=${{ github.sha }} platforms: ${{ inputs.platforms }} provenance: false builder: ${{ steps.buildx.outputs.name || steps.buildx-native.outputs.name }} diff --git a/Dockerfile b/Dockerfile index a6c7d46b57..c91f10de0f 100644 --- a/Dockerfile +++ b/Dockerfile @@ -29,6 +29,8 @@ FROM docker.io/ruby:${RUBY_VERSION}-slim-${DEBIAN_VERSION} AS ruby ARG MASTODON_VERSION_PRERELEASE="" # Append build metadata or fork information to version.rb [--build-arg MASTODON_VERSION_METADATA="pr-123456"] ARG MASTODON_VERSION_METADATA="" +# Will be available as Mastodon::Version.source_commit +ARG SOURCE_COMMIT="" # Allow Ruby on Rails to serve static files # See: https://docs.joinmastodon.org/admin/config/#rails_serve_static_files @@ -45,30 +47,31 @@ ARG GID="991" # Apply Mastodon build options based on options above ENV \ -# Apply Mastodon version information + # Apply Mastodon version information MASTODON_VERSION_PRERELEASE="${MASTODON_VERSION_PRERELEASE}" \ MASTODON_VERSION_METADATA="${MASTODON_VERSION_METADATA}" \ -# Apply Mastodon static files and YJIT options + SOURCE_COMMIT="${SOURCE_COMMIT}" \ + # Apply Mastodon static files and YJIT options RAILS_SERVE_STATIC_FILES=${RAILS_SERVE_STATIC_FILES} \ RUBY_YJIT_ENABLE=${RUBY_YJIT_ENABLE} \ -# Apply timezone + # Apply timezone TZ=${TZ} ENV \ -# Configure the IP to bind Mastodon to when serving traffic + # Configure the IP to bind Mastodon to when serving traffic BIND="0.0.0.0" \ -# Use production settings for Yarn, Node and related nodejs based tools + # Use production settings for Yarn, Node and related nodejs based tools NODE_ENV="production" \ -# Use production settings for Ruby on Rails + # Use production settings for Ruby on Rails RAILS_ENV="production" \ -# Add Ruby and Mastodon installation to the PATH + # Add Ruby and Mastodon installation to the PATH DEBIAN_FRONTEND="noninteractive" \ PATH="${PATH}:/opt/ruby/bin:/opt/mastodon/bin" \ -# Optimize jemalloc 5.x performance + # Optimize jemalloc 5.x performance MALLOC_CONF="narenas:2,background_thread:true,thp:never,dirty_decay_ms:1000,muzzy_decay_ms:0" \ -# Enable libvips, should not be changed + # Enable libvips, should not be changed MASTODON_USE_LIBVIPS=true \ -# Sidekiq will touch tmp/sidekiq_process_has_started_and_will_begin_processing_jobs to indicate it is ready. This can be used for a readiness check in Kubernetes + # Sidekiq will touch tmp/sidekiq_process_has_started_and_will_begin_processing_jobs to indicate it is ready. This can be used for a readiness check in Kubernetes MASTODON_SIDEKIQ_READY_FILENAME=sidekiq_process_has_started_and_will_begin_processing_jobs # Set default shell used for running commands @@ -79,14 +82,14 @@ ARG TARGETPLATFORM RUN echo "Target platform is $TARGETPLATFORM" RUN \ -# Remove automatic apt cache Docker cleanup scripts + # Remove automatic apt cache Docker cleanup scripts rm -f /etc/apt/apt.conf.d/docker-clean; \ -# Sets timezone + # Sets timezone echo "${TZ}" > /etc/localtime; \ -# Creates mastodon user/group and sets home directory + # Creates mastodon user/group and sets home directory groupadd -g "${GID}" mastodon; \ useradd -l -u "${UID}" -g "${GID}" -m -d /opt/mastodon mastodon; \ -# Creates /mastodon symlink to /opt/mastodon + # Creates /mastodon symlink to /opt/mastodon ln -s /opt/mastodon /mastodon; # Set /opt/mastodon as working directory @@ -94,28 +97,28 @@ WORKDIR /opt/mastodon # hadolint ignore=DL3008,DL3005 RUN \ -# Mount Apt cache and lib directories from Docker buildx caches ---mount=type=cache,id=apt-cache-${TARGETPLATFORM},target=/var/cache/apt,sharing=locked \ ---mount=type=cache,id=apt-lib-${TARGETPLATFORM},target=/var/lib/apt,sharing=locked \ -# Apt update & upgrade to check for security updates to Debian image + # Mount Apt cache and lib directories from Docker buildx caches + --mount=type=cache,id=apt-cache-${TARGETPLATFORM},target=/var/cache/apt,sharing=locked \ + --mount=type=cache,id=apt-lib-${TARGETPLATFORM},target=/var/lib/apt,sharing=locked \ + # Apt update & upgrade to check for security updates to Debian image apt-get update; \ apt-get dist-upgrade -yq; \ -# Install jemalloc, curl and other necessary components + # Install jemalloc, curl and other necessary components apt-get install -y --no-install-recommends \ - curl \ - file \ - libjemalloc2 \ - patchelf \ - procps \ - tini \ - tzdata \ - wget \ + curl \ + file \ + libjemalloc2 \ + patchelf \ + procps \ + tini \ + tzdata \ + wget \ ; \ -# Patch Ruby to use jemalloc + # Patch Ruby to use jemalloc patchelf --add-needed libjemalloc.so.2 /usr/local/bin/ruby; \ -# Discard patchelf after use + # Discard patchelf after use apt-get purge -y \ - patchelf \ + patchelf \ ; # Create temporary build layer from base image @@ -132,56 +135,56 @@ ARG TARGETPLATFORM # hadolint ignore=DL3008 RUN \ -# Mount Apt cache and lib directories from Docker buildx caches ---mount=type=cache,id=apt-cache-${TARGETPLATFORM},target=/var/cache/apt,sharing=locked \ ---mount=type=cache,id=apt-lib-${TARGETPLATFORM},target=/var/lib/apt,sharing=locked \ -# Install build tools and bundler dependencies from APT + # Mount Apt cache and lib directories from Docker buildx caches + --mount=type=cache,id=apt-cache-${TARGETPLATFORM},target=/var/cache/apt,sharing=locked \ + --mount=type=cache,id=apt-lib-${TARGETPLATFORM},target=/var/lib/apt,sharing=locked \ + # Install build tools and bundler dependencies from APT apt-get install -y --no-install-recommends \ - autoconf \ - automake \ - build-essential \ - cmake \ - git \ - libgdbm-dev \ - libglib2.0-dev \ - libgmp-dev \ - libicu-dev \ - libidn-dev \ - libpq-dev \ - libssl-dev \ - libtool \ - meson \ - nasm \ - pkg-config \ - shared-mime-info \ - xz-utils \ - # libvips components - libcgif-dev \ - libexif-dev \ - libexpat1-dev \ - libgirepository1.0-dev \ - libheif-dev \ - libimagequant-dev \ - libjpeg62-turbo-dev \ - liblcms2-dev \ - liborc-dev \ - libspng-dev \ - libtiff-dev \ - libwebp-dev \ + autoconf \ + automake \ + build-essential \ + cmake \ + git \ + libgdbm-dev \ + libglib2.0-dev \ + libgmp-dev \ + libicu-dev \ + libidn-dev \ + libpq-dev \ + libssl-dev \ + libtool \ + meson \ + nasm \ + pkg-config \ + shared-mime-info \ + xz-utils \ + # libvips components + libcgif-dev \ + libexif-dev \ + libexpat1-dev \ + libgirepository1.0-dev \ + libheif-dev \ + libimagequant-dev \ + libjpeg62-turbo-dev \ + liblcms2-dev \ + liborc-dev \ + libspng-dev \ + libtiff-dev \ + libwebp-dev \ # ffmpeg components - libdav1d-dev \ - liblzma-dev \ - libmp3lame-dev \ - libopus-dev \ - libsnappy-dev \ - libvorbis-dev \ - libvpx-dev \ - libx264-dev \ - libx265-dev \ + libdav1d-dev \ + liblzma-dev \ + libmp3lame-dev \ + libopus-dev \ + libsnappy-dev \ + libvorbis-dev \ + libvpx-dev \ + libx264-dev \ + libx265-dev \ ; RUN \ -# Configure Corepack + # Configure Corepack rm /usr/local/bin/yarn*; \ corepack enable; \ corepack prepare --activate; @@ -228,28 +231,28 @@ WORKDIR /usr/local/ffmpeg/src/ffmpeg-${FFMPEG_VERSION} # Configure and compile ffmpeg RUN \ ./configure \ - --prefix=/usr/local/ffmpeg \ - --toolchain=hardened \ - --disable-debug \ - --disable-devices \ - --disable-doc \ - --disable-ffplay \ - --disable-network \ - --disable-static \ - --enable-ffmpeg \ - --enable-ffprobe \ - --enable-gpl \ - --enable-libdav1d \ - --enable-libmp3lame \ - --enable-libopus \ - --enable-libsnappy \ - --enable-libvorbis \ - --enable-libvpx \ - --enable-libwebp \ - --enable-libx264 \ - --enable-libx265 \ - --enable-shared \ - --enable-version3 \ + --prefix=/usr/local/ffmpeg \ + --toolchain=hardened \ + --disable-debug \ + --disable-devices \ + --disable-doc \ + --disable-ffplay \ + --disable-network \ + --disable-static \ + --enable-ffmpeg \ + --enable-ffprobe \ + --enable-gpl \ + --enable-libdav1d \ + --enable-libmp3lame \ + --enable-libopus \ + --enable-libsnappy \ + --enable-libvorbis \ + --enable-libvpx \ + --enable-libwebp \ + --enable-libx264 \ + --enable-libx265 \ + --enable-shared \ + --enable-version3 \ ; \ make -j$(nproc); \ make install; @@ -263,17 +266,17 @@ ARG TARGETPLATFORM COPY Gemfile* /opt/mastodon/ RUN \ -# Mount Ruby Gem caches ---mount=type=cache,id=gem-cache-${TARGETPLATFORM},target=/usr/local/bundle/cache/,sharing=locked \ -# Configure bundle to prevent changes to Gemfile and Gemfile.lock + # Mount Ruby Gem caches + --mount=type=cache,id=gem-cache-${TARGETPLATFORM},target=/usr/local/bundle/cache/,sharing=locked \ + # Configure bundle to prevent changes to Gemfile and Gemfile.lock bundle config set --global frozen "true"; \ -# Configure bundle to not cache downloaded Gems + # Configure bundle to not cache downloaded Gems bundle config set --global cache_all "false"; \ -# Configure bundle to only process production Gems + # Configure bundle to only process production Gems bundle config set --local without "development test"; \ -# Configure bundle to not warn about root user + # Configure bundle to not warn about root user bundle config set silence_root_warning "true"; \ -# Download and install required Gems + # Download and install required Gems bundle install -j"$(nproc)"; # Create temporary node specific build layer from build layer @@ -288,9 +291,9 @@ COPY .yarn /opt/mastodon/.yarn # hadolint ignore=DL3008 RUN \ ---mount=type=cache,id=corepack-cache-${TARGETPLATFORM},target=/usr/local/share/.cache/corepack,sharing=locked \ ---mount=type=cache,id=yarn-cache-${TARGETPLATFORM},target=/usr/local/share/.cache/yarn,sharing=locked \ -# Install Node packages + --mount=type=cache,id=corepack-cache-${TARGETPLATFORM},target=/usr/local/share/.cache/corepack,sharing=locked \ + --mount=type=cache,id=yarn-cache-${TARGETPLATFORM},target=/usr/local/share/.cache/yarn,sharing=locked \ + # Install Node packages yarn workspaces focus --production @mastodon/mastodon; # Create temporary assets build layer from build layer @@ -311,10 +314,10 @@ ARG TARGETPLATFORM RUN \ ldconfig; \ -# Use Ruby on Rails to create Mastodon assets + # Use Ruby on Rails to create Mastodon assets SECRET_KEY_BASE_DUMMY=1 \ bundle exec rails assets:precompile; \ -# Cleanup temporary files + # Cleanup temporary files rm -fr /opt/mastodon/tmp; # Prep final Mastodon Ruby layer @@ -324,49 +327,49 @@ ARG TARGETPLATFORM # hadolint ignore=DL3008 RUN \ -# Mount Apt cache and lib directories from Docker buildx caches ---mount=type=cache,id=apt-cache-${TARGETPLATFORM},target=/var/cache/apt,sharing=locked \ ---mount=type=cache,id=apt-lib-${TARGETPLATFORM},target=/var/lib/apt,sharing=locked \ -# Mount Corepack and Yarn caches from Docker buildx caches ---mount=type=cache,id=corepack-cache-${TARGETPLATFORM},target=/usr/local/share/.cache/corepack,sharing=locked \ ---mount=type=cache,id=yarn-cache-${TARGETPLATFORM},target=/usr/local/share/.cache/yarn,sharing=locked \ -# Apt update install non-dev versions of necessary components + # Mount Apt cache and lib directories from Docker buildx caches + --mount=type=cache,id=apt-cache-${TARGETPLATFORM},target=/var/cache/apt,sharing=locked \ + --mount=type=cache,id=apt-lib-${TARGETPLATFORM},target=/var/lib/apt,sharing=locked \ + # Mount Corepack and Yarn caches from Docker buildx caches + --mount=type=cache,id=corepack-cache-${TARGETPLATFORM},target=/usr/local/share/.cache/corepack,sharing=locked \ + --mount=type=cache,id=yarn-cache-${TARGETPLATFORM},target=/usr/local/share/.cache/yarn,sharing=locked \ + # Apt update install non-dev versions of necessary components apt-get install -y --no-install-recommends \ - libexpat1 \ - libglib2.0-0 \ - libicu72 \ - libidn12 \ - libpq5 \ - libreadline8 \ - libssl3 \ - libyaml-0-2 \ + libexpat1 \ + libglib2.0-0 \ + libicu72 \ + libidn12 \ + libpq5 \ + libreadline8 \ + libssl3 \ + libyaml-0-2 \ # libvips components - libcgif0 \ - libexif12 \ - libheif1 \ - libimagequant0 \ - libjpeg62-turbo \ - liblcms2-2 \ - liborc-0.4-0 \ - libspng0 \ - libtiff6 \ - libwebp7 \ - libwebpdemux2 \ - libwebpmux3 \ + libcgif0 \ + libexif12 \ + libheif1 \ + libimagequant0 \ + libjpeg62-turbo \ + liblcms2-2 \ + liborc-0.4-0 \ + libspng0 \ + libtiff6 \ + libwebp7 \ + libwebpdemux2 \ + libwebpmux3 \ # ffmpeg components - libdav1d6 \ - libmp3lame0 \ - libopencore-amrnb0 \ - libopencore-amrwb0 \ - libopus0 \ - libsnappy1v5 \ - libtheora0 \ - libvorbis0a \ - libvorbisenc2 \ - libvorbisfile3 \ - libvpx7 \ - libx264-164 \ - libx265-199 \ + libdav1d6 \ + libmp3lame0 \ + libopencore-amrnb0 \ + libopencore-amrwb0 \ + libopus0 \ + libsnappy1v5 \ + libtheora0 \ + libvorbis0a \ + libvorbisenc2 \ + libvorbisfile3 \ + libvpx7 \ + libx264-164 \ + libx265-199 \ ; # Copy Mastodon sources into final layer @@ -386,7 +389,7 @@ COPY --from=ffmpeg /usr/local/ffmpeg/lib /usr/local/lib RUN \ ldconfig; \ -# Smoketest media processors + # Smoketest media processors vips -v; \ ffmpeg -version; \ ffprobe -version; @@ -396,10 +399,10 @@ RUN \ bundle exec bootsnap precompile --gemfile app/ lib/; RUN \ -# Pre-create and chown system volume to Mastodon user + # Pre-create and chown system volume to Mastodon user mkdir -p /opt/mastodon/public/system; \ chown mastodon:mastodon /opt/mastodon/public/system; \ -# Set Mastodon user as owner of tmp folder + # Set Mastodon user as owner of tmp folder chown -R mastodon:mastodon /opt/mastodon/tmp; # Set the running user for resulting container diff --git a/config/initializers/opentelemetry.rb b/config/initializers/opentelemetry.rb index 8edce03b90..a40cd4e4c5 100644 --- a/config/initializers/opentelemetry.rb +++ b/config/initializers/opentelemetry.rb @@ -65,6 +65,13 @@ if ENV.keys.any? { |name| name.match?(/OTEL_.*_ENDPOINT/) } "#{prefix}#{separator}#{$PROGRAM_NAME.split('/').last}" end c.service_version = Mastodon::Version.to_s + + if Mastodon::Version.source_commit.present? + c.resource = OpenTelemetry::SDK::Resources::Resource.create( + 'vcs.repository.ref.revision' => Mastodon::Version.source_commit, + 'vcs.repository.url.full' => Mastodon::Version.source_base_url + ) + end end end diff --git a/lib/mastodon/version.rb b/lib/mastodon/version.rb index 88aa515296..f132c3a548 100644 --- a/lib/mastodon/version.rb +++ b/lib/mastodon/version.rb @@ -70,6 +70,10 @@ module Mastodon end end + def source_commit + ENV.fetch('SOURCE_COMMIT', nil) + end + def user_agent @user_agent ||= "Mastodon/#{Version} (#{HTTP::Request::USER_AGENT}; +http#{Rails.configuration.x.use_https ? 's' : ''}://#{Rails.configuration.x.web_domain}/)" end From 60801ab9140c5bcce3a3336d3ed46ccfbf3ab129 Mon Sep 17 00:00:00 2001 From: Jeong Arm Date: Mon, 18 Nov 2024 03:48:27 -0500 Subject: [PATCH 31/64] Add missing autofocus on boost modal (#32953) --- app/javascript/mastodon/features/ui/components/boost_modal.tsx | 2 ++ 1 file changed, 2 insertions(+) diff --git a/app/javascript/mastodon/features/ui/components/boost_modal.tsx b/app/javascript/mastodon/features/ui/components/boost_modal.tsx index cdf7138d49..72a28a01f9 100644 --- a/app/javascript/mastodon/features/ui/components/boost_modal.tsx +++ b/app/javascript/mastodon/features/ui/components/boost_modal.tsx @@ -128,6 +128,8 @@ export const BoostModal: React.FC<{ ? messages.cancel_reblog : messages.reblog, )} + /* eslint-disable-next-line jsx-a11y/no-autofocus -- We are in the modal */ + autoFocus /> From 5b68f4b070dd2d569d854ecc3854a2610fb61866 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Mon, 18 Nov 2024 09:56:19 +0100 Subject: [PATCH 32/64] Update libretranslate/libretranslate Docker tag to v1.6.2 (#32951) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- .devcontainer/compose.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.devcontainer/compose.yaml b/.devcontainer/compose.yaml index 5c7263c874..705d26e0ab 100644 --- a/.devcontainer/compose.yaml +++ b/.devcontainer/compose.yaml @@ -69,7 +69,7 @@ services: hard: -1 libretranslate: - image: libretranslate/libretranslate:v1.6.1 + image: libretranslate/libretranslate:v1.6.2 restart: unless-stopped volumes: - lt-data:/home/libretranslate/.local From 49a12a2df9d87321de9a13a5f4e4527bcd9bf69c Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Mon, 18 Nov 2024 08:57:37 +0000 Subject: [PATCH 33/64] Update dependency @formatjs/cli to v6.3.11 (#32950) 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 aaecae7a2a..20d00347b8 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2232,8 +2232,8 @@ __metadata: linkType: hard "@formatjs/cli@npm:^6.1.1": - version: 6.3.8 - resolution: "@formatjs/cli@npm:6.3.8" + version: 6.3.11 + resolution: "@formatjs/cli@npm:6.3.11" peerDependencies: "@glimmer/env": ^0.1.7 "@glimmer/reference": ^0.91.1 || ^0.92.0 @@ -2262,7 +2262,7 @@ __metadata: optional: true bin: formatjs: bin/formatjs - checksum: 10c0/61fb0e56a2da26befad5ca6ff5a8bcf9c383d22634cf288f3cab5661bece7686e6f064adaa500954b37726a7745c73134b459d115d52c931b76d68d998c7b22d + checksum: 10c0/31d5fac85314e97591c4c6a4793abf1d9c6fbf790fbbea779b2a4c0f742f1859804f290e77be06d128274468e44bc27992196aacb4cb6f2fbd141755ca79a98d languageName: node linkType: hard From 02985aae691d23086aa2512974996a1a51999b7c Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Mon, 18 Nov 2024 10:20:37 +0100 Subject: [PATCH 34/64] New Crowdin Translations (automated) (#32927) Co-authored-by: GitHub Actions --- app/javascript/mastodon/locales/bg.json | 4 + app/javascript/mastodon/locales/de.json | 2 +- app/javascript/mastodon/locales/fi.json | 3 +- app/javascript/mastodon/locales/ga.json | 1 + app/javascript/mastodon/locales/he.json | 1 + app/javascript/mastodon/locales/ia.json | 28 +++ app/javascript/mastodon/locales/lv.json | 8 + app/javascript/mastodon/locales/nn.json | 1 + app/javascript/mastodon/locales/sk.json | 6 + app/javascript/mastodon/locales/sl.json | 8 + app/javascript/mastodon/locales/tr.json | 4 +- app/javascript/mastodon/locales/zh-CN.json | 112 +++++------ config/locales/activerecord.zh-CN.yml | 10 +- config/locales/an.yml | 1 - config/locales/ar.yml | 1 - config/locales/be.yml | 1 - config/locales/bg.yml | 1 - config/locales/br.yml | 2 +- config/locales/ca.yml | 1 - config/locales/ckb.yml | 1 - config/locales/co.yml | 1 - config/locales/cs.yml | 1 - config/locales/cy.yml | 1 - config/locales/da.yml | 6 + config/locales/de.yml | 14 +- config/locales/devise.zh-CN.yml | 6 +- config/locales/doorkeeper.ia.yml | 2 + config/locales/doorkeeper.zh-CN.yml | 10 +- config/locales/el.yml | 1 - config/locales/en-GB.yml | 1 - config/locales/eo.yml | 1 - config/locales/es-AR.yml | 16 +- config/locales/es-MX.yml | 16 +- config/locales/es.yml | 44 +++-- config/locales/et.yml | 1 - config/locales/eu.yml | 1 - config/locales/fa.yml | 1 - config/locales/fi.yml | 8 +- config/locales/fo.yml | 8 +- config/locales/fr-CA.yml | 1 - config/locales/fr.yml | 1 - config/locales/fy.yml | 1 - config/locales/ga.yml | 16 +- config/locales/gd.yml | 1 - config/locales/gl.yml | 6 + config/locales/he.yml | 16 +- config/locales/hu.yml | 1 - config/locales/hy.yml | 1 - config/locales/ia.yml | 21 +- config/locales/id.yml | 1 - config/locales/ie.yml | 1 - config/locales/io.yml | 1 - config/locales/is.yml | 8 +- config/locales/it.yml | 8 +- config/locales/ja.yml | 16 +- config/locales/ka.yml | 1 - config/locales/kab.yml | 1 - config/locales/kk.yml | 1 - config/locales/ko.yml | 6 + config/locales/ku.yml | 1 - config/locales/lad.yml | 1 - config/locales/lt.yml | 8 +- config/locales/lv.yml | 1 - config/locales/ms.yml | 1 - config/locales/my.yml | 1 - config/locales/nl.yml | 6 +- config/locales/nn.yml | 8 +- config/locales/no.yml | 1 - config/locales/oc.yml | 1 - config/locales/pl.yml | 1 - config/locales/pt-BR.yml | 13 ++ config/locales/pt-PT.yml | 1 - config/locales/ru.yml | 1 - config/locales/sc.yml | 1 - config/locales/sco.yml | 1 - config/locales/si.yml | 1 - config/locales/simple_form.ga.yml | 1 + config/locales/simple_form.ia.yml | 5 + config/locales/simple_form.pt-BR.yml | 1 + config/locales/simple_form.zh-CN.yml | 34 ++-- config/locales/sk.yml | 1 - config/locales/sl.yml | 1 - config/locales/sq.yml | 8 +- config/locales/sr-Latn.yml | 1 - config/locales/sr.yml | 1 - config/locales/sv.yml | 5 + config/locales/th.yml | 1 - config/locales/tr.yml | 8 +- config/locales/uk.yml | 1 - config/locales/vi.yml | 8 +- config/locales/zh-CN.yml | 212 +++++++++++---------- config/locales/zh-HK.yml | 1 - config/locales/zh-TW.yml | 8 +- 93 files changed, 511 insertions(+), 278 deletions(-) diff --git a/app/javascript/mastodon/locales/bg.json b/app/javascript/mastodon/locales/bg.json index 44482f6c96..8f99992f33 100644 --- a/app/javascript/mastodon/locales/bg.json +++ b/app/javascript/mastodon/locales/bg.json @@ -93,10 +93,14 @@ "annual_report.summary.archetype.replier": "Социална пеперуда", "annual_report.summary.followers.followers": "последователи", "annual_report.summary.followers.total": "{count} общо", + "annual_report.summary.here_it_is": "Ето преглед на вашата {year} година:", "annual_report.summary.highlighted_post.by_favourites": "най-правено като любима публикация", + "annual_report.summary.highlighted_post.by_replies": "публикации с най-много отговори", + "annual_report.summary.highlighted_post.possessive": "на {name}", "annual_report.summary.most_used_app.most_used_app": "най-употребявано приложение", "annual_report.summary.most_used_hashtag.most_used_hashtag": "най-употребяван хаштаг", "annual_report.summary.new_posts.new_posts": "нови публикации", + "annual_report.summary.percentile.text": "Това ви слага най-отгоресред потребителите на Mastodon.", "annual_report.summary.thanks": "Благодарим, че сте част от Mastodon!", "attachments_list.unprocessed": "(необработено)", "audio.hide": "Скриване на звука", diff --git a/app/javascript/mastodon/locales/de.json b/app/javascript/mastodon/locales/de.json index bd24ccd48f..f692681387 100644 --- a/app/javascript/mastodon/locales/de.json +++ b/app/javascript/mastodon/locales/de.json @@ -101,7 +101,7 @@ "annual_report.summary.highlighted_post.possessive": "{name}", "annual_report.summary.most_used_app.most_used_app": "am häufigsten verwendete App", "annual_report.summary.most_used_hashtag.most_used_hashtag": "am häufigsten verwendeter Hashtag", - "annual_report.summary.most_used_hashtag.none": "Kein", + "annual_report.summary.most_used_hashtag.none": "Keiner", "annual_report.summary.new_posts.new_posts": "neue Beiträge", "annual_report.summary.percentile.text": "Damit gehörst du zu den oberstender Mastodon-Nutzer*innen.", "annual_report.summary.percentile.we_wont_tell_bernie": "Wir werden Bernie nichts verraten.", diff --git a/app/javascript/mastodon/locales/fi.json b/app/javascript/mastodon/locales/fi.json index 2763c39168..2c0aacc535 100644 --- a/app/javascript/mastodon/locales/fi.json +++ b/app/javascript/mastodon/locales/fi.json @@ -38,7 +38,7 @@ "account.following": "Seuratut", "account.following_counter": "{count, plural, one {{counter} seurattu} other {{counter} seurattua}}", "account.follows.empty": "Tämä käyttäjä ei vielä seuraa ketään.", - "account.go_to_profile": "Mene profiiliin", + "account.go_to_profile": "Siirry profiiliin", "account.hide_reblogs": "Piilota käyttäjän @{name} tehostukset", "account.in_memoriam": "Muistoissamme.", "account.joined_short": "Liittynyt", @@ -101,6 +101,7 @@ "annual_report.summary.highlighted_post.possessive": "Käyttäjän {name}", "annual_report.summary.most_used_app.most_used_app": "käytetyin sovellus", "annual_report.summary.most_used_hashtag.most_used_hashtag": "käytetyin aihetunniste", + "annual_report.summary.most_used_hashtag.none": "Ei mitään", "annual_report.summary.new_posts.new_posts": "uutta julkaisua", "annual_report.summary.percentile.text": "Olet osa huippujoukkoa, johon kuuluuMastodon-käyttäjistä.", "annual_report.summary.thanks": "Kiitos, että olet osa Mastodonia!", diff --git a/app/javascript/mastodon/locales/ga.json b/app/javascript/mastodon/locales/ga.json index 3181d7978e..137a7c591f 100644 --- a/app/javascript/mastodon/locales/ga.json +++ b/app/javascript/mastodon/locales/ga.json @@ -101,6 +101,7 @@ "annual_report.summary.highlighted_post.possessive": "{name}'s", "annual_report.summary.most_used_app.most_used_app": "aip is mó a úsáidtear", "annual_report.summary.most_used_hashtag.most_used_hashtag": "hashtag is mó a úsáidtear", + "annual_report.summary.most_used_hashtag.none": "Dada", "annual_report.summary.new_posts.new_posts": "postanna nua", "annual_report.summary.percentile.text": "Cuireann sé sin i mbarr úsáideoirí Mastodon.", "annual_report.summary.percentile.we_wont_tell_bernie": "Ní inseoidh muid do Bernie.", diff --git a/app/javascript/mastodon/locales/he.json b/app/javascript/mastodon/locales/he.json index 48ea869dd2..52d61b737b 100644 --- a/app/javascript/mastodon/locales/he.json +++ b/app/javascript/mastodon/locales/he.json @@ -101,6 +101,7 @@ "annual_report.summary.highlighted_post.possessive": "של {name}", "annual_report.summary.most_used_app.most_used_app": "היישומון שהכי בשימוש", "annual_report.summary.most_used_hashtag.most_used_hashtag": "התג בשימוש הרב ביותר", + "annual_report.summary.most_used_hashtag.none": "אף אחד", "annual_report.summary.new_posts.new_posts": "הודעות חדשות", "annual_report.summary.percentile.text": "ממקם אותך באחוזון של משמשי מסטודון.", "annual_report.summary.percentile.we_wont_tell_bernie": "לא נגלה לברני.", diff --git a/app/javascript/mastodon/locales/ia.json b/app/javascript/mastodon/locales/ia.json index e41d390a3f..402829817f 100644 --- a/app/javascript/mastodon/locales/ia.json +++ b/app/javascript/mastodon/locales/ia.json @@ -87,6 +87,25 @@ "alert.unexpected.title": "Ups!", "alt_text_badge.title": "Texto alt", "announcement.announcement": "Annuncio", + "annual_report.summary.archetype.booster": "Le impulsator", + "annual_report.summary.archetype.lurker": "Le lector", + "annual_report.summary.archetype.oracle": "Le oraculo", + "annual_report.summary.archetype.pollster": "Le sondagista", + "annual_report.summary.archetype.replier": "Le responditor", + "annual_report.summary.followers.followers": "sequitores", + "annual_report.summary.followers.total": "{count} in total", + "annual_report.summary.here_it_is": "Ecce tu summario de {year}:", + "annual_report.summary.highlighted_post.by_favourites": "message le plus favorite", + "annual_report.summary.highlighted_post.by_reblogs": "message le plus impulsate", + "annual_report.summary.highlighted_post.by_replies": "message le plus respondite", + "annual_report.summary.highlighted_post.possessive": "{name}, ecce tu…", + "annual_report.summary.most_used_app.most_used_app": "application le plus usate", + "annual_report.summary.most_used_hashtag.most_used_hashtag": "hashtag le plus usate", + "annual_report.summary.most_used_hashtag.none": "Necun", + "annual_report.summary.new_posts.new_posts": "nove messages", + "annual_report.summary.percentile.text": "Isto te pone in le primedel usatores de Mastodon.", + "annual_report.summary.percentile.we_wont_tell_bernie": "Tu es un primo inter pares.", + "annual_report.summary.thanks": "Gratias pro facer parte de Mastodon!", "attachments_list.unprocessed": "(non processate)", "audio.hide": "Celar audio", "block_modal.remote_users_caveat": "Nos demandera al servitor {domain} de respectar tu decision. Nonobstante, le conformitate non es garantite perque alcun servitores pote tractar le blocadas de maniera differente. Le messages public pote esser totevia visibile pro le usatores non authenticate.", @@ -158,6 +177,7 @@ "compose_form.poll.duration": "Durata del sondage", "compose_form.poll.multiple": "Selection multiple", "compose_form.poll.option_placeholder": "Option {number}", + "compose_form.poll.single": "Option singule", "compose_form.poll.switch_to_multiple": "Cambiar le sondage pro permitter selectiones multiple", "compose_form.poll.switch_to_single": "Cambiar le sondage pro permitter selection singule", "compose_form.poll.type": "Stilo", @@ -196,6 +216,7 @@ "confirmations.unfollow.title": "Cessar de sequer le usator?", "content_warning.hide": "Celar le message", "content_warning.show": "Monstrar in omne caso", + "content_warning.show_more": "Monstrar plus", "conversation.delete": "Deler conversation", "conversation.mark_as_read": "Marcar como legite", "conversation.open": "Vider conversation", @@ -304,6 +325,7 @@ "filter_modal.select_filter.subtitle": "Usa un categoria existente o crea un nove", "filter_modal.select_filter.title": "Filtrar iste message", "filter_modal.title.status": "Filtrar un message", + "filter_warning.matches_filter": "Corresponde al filtro “{title}”", "filtered_notifications_banner.pending_requests": "De {count, plural, =0 {nemo} one {un persona} other {# personas}} que tu pote cognoscer", "filtered_notifications_banner.title": "Notificationes filtrate", "firehose.all": "Toto", @@ -383,6 +405,7 @@ "interaction_modal.description.follow": "Con un conto sur Mastodon, tu pote sequer {name} e reciper su messages in tu fluxo de initio.", "interaction_modal.description.reblog": "Con un conto sur Mastodon, tu pote impulsar iste message pro condivider lo con tu proprie sequitores.", "interaction_modal.description.reply": "Con un conto sur Mastodon, tu pote responder a iste message.", + "interaction_modal.description.vote": "Con un conto sur Mastodon, tu pote votar in iste sondage.", "interaction_modal.login.action": "Porta me a casa", "interaction_modal.login.prompt": "Dominio de tu servitor, p.ex. mastodon.social", "interaction_modal.no_account_yet": "Non sur Mstodon?", @@ -394,6 +417,7 @@ "interaction_modal.title.follow": "Sequer {name}", "interaction_modal.title.reblog": "Impulsar le message de {name}", "interaction_modal.title.reply": "Responder al message de {name}", + "interaction_modal.title.vote": "Votar in le sondage de {name}", "intervals.full.days": "{number, plural, one {# die} other {# dies}}", "intervals.full.hours": "{number, plural, one {# hora} other {# horas}}", "intervals.full.minutes": "{number, plural, one {# minuta} other {# minutas}}", @@ -503,9 +527,12 @@ "notification.admin.report_statuses_other": "{name} ha reportate {target}", "notification.admin.sign_up": "{name} se ha inscribite", "notification.admin.sign_up.name_and_others": "{name} e {count, plural, one {# altere usator} other {altere # usatores}} se inscribeva", + "notification.annual_report.message": "Tu summario #Wrapstodon pro {year} attende! Revela le momentos saliente e memorabile de tu anno sur Mastodon!", + "notification.annual_report.view": "Visitar summario #Wrapstodon", "notification.favourite": "{name} ha marcate tu message como favorite", "notification.favourite.name_and_others_with_link": "{name} e {count, plural, one {# altere} other {# alteres}} favoriva tu message", "notification.follow": "{name} te ha sequite", + "notification.follow.name_and_others": "{name} e {count, plural, one {# other} other {# alteres}} te ha sequite", "notification.follow_request": "{name} ha requestate de sequer te", "notification.follow_request.name_and_others": "{name} e {count, plural, one {# altere} other {# alteres}} ha demandate de sequer te", "notification.label.mention": "Mention", @@ -564,6 +591,7 @@ "notifications.column_settings.filter_bar.category": "Barra de filtro rapide", "notifications.column_settings.follow": "Nove sequitores:", "notifications.column_settings.follow_request": "Nove requestas de sequimento:", + "notifications.column_settings.group": "Gruppo", "notifications.column_settings.mention": "Mentiones:", "notifications.column_settings.poll": "Resultatos del sondage:", "notifications.column_settings.push": "Notificationes push", diff --git a/app/javascript/mastodon/locales/lv.json b/app/javascript/mastodon/locales/lv.json index f6053b2e09..d6fcb34828 100644 --- a/app/javascript/mastodon/locales/lv.json +++ b/app/javascript/mastodon/locales/lv.json @@ -89,6 +89,10 @@ "annual_report.summary.followers.followers": "sekotāji", "annual_report.summary.followers.total": "pavisam {count}", "annual_report.summary.here_it_is": "Šeit ir {year}. gada pārskats:", + "annual_report.summary.highlighted_post.possessive": "{name}", + "annual_report.summary.most_used_app.most_used_app": "visizmantotākā lietotne", + "annual_report.summary.most_used_hashtag.most_used_hashtag": "visizmantotākais tēmturis", + "annual_report.summary.most_used_hashtag.none": "Nav", "annual_report.summary.new_posts.new_posts": "jauni ieraksti", "attachments_list.unprocessed": "(neapstrādāti)", "audio.hide": "Slēpt audio", @@ -329,7 +333,11 @@ "hashtag.follow": "Sekot tēmturim", "hashtag.unfollow": "Pārstāt sekot tēmturim", "hashtags.and_other": "… un {count, plural, other {vēl #}}", + "hints.profiles.see_more_followers": "Skatīt vairāk sekotāju {domain}", + "hints.profiles.see_more_follows": "Skatīt vairāk sekojumu {domain}", + "hints.profiles.see_more_posts": "Skatīt vairāk ierakstu {domain}", "hints.threads.replies_may_be_missing": "Var trūkt atbildes no citiem serveriem.", + "hints.threads.see_more": "Skatīt vairāk atbilžu {domain}", "home.column_settings.show_reblogs": "Rādīt pastiprinātos ierakstus", "home.column_settings.show_replies": "Rādīt atbildes", "home.hide_announcements": "Slēpt paziņojumus", diff --git a/app/javascript/mastodon/locales/nn.json b/app/javascript/mastodon/locales/nn.json index b45ff90585..85d19c4f93 100644 --- a/app/javascript/mastodon/locales/nn.json +++ b/app/javascript/mastodon/locales/nn.json @@ -101,6 +101,7 @@ "annual_report.summary.highlighted_post.possessive": "som {name} laga", "annual_report.summary.most_used_app.most_used_app": "mest brukte app", "annual_report.summary.most_used_hashtag.most_used_hashtag": "mest brukte emneknagg", + "annual_report.summary.most_used_hashtag.none": "Ingen", "annual_report.summary.new_posts.new_posts": "nye innlegg", "annual_report.summary.percentile.text": "Du er av deiivrigaste Mastodon-brukarane.", "annual_report.summary.percentile.we_wont_tell_bernie": "Ikkje eit ord til pressa.", diff --git a/app/javascript/mastodon/locales/sk.json b/app/javascript/mastodon/locales/sk.json index 8a01263eb2..1ecbaaffdd 100644 --- a/app/javascript/mastodon/locales/sk.json +++ b/app/javascript/mastodon/locales/sk.json @@ -348,6 +348,8 @@ "hashtag.follow": "Sledovať hashtag", "hashtag.unfollow": "Prestať sledovať hashtag", "hashtags.and_other": "…a {count, plural, other {# ďalších}}", + "hints.profiles.see_more_posts": "Pozri viac príspevkov na {domain}", + "hints.threads.replies_may_be_missing": "Odpovede z ostatných serverov môžu chýbať.", "hints.threads.see_more": "Pozri viac odpovedí na {domain}", "home.column_settings.show_reblogs": "Zobraziť zdieľania", "home.column_settings.show_replies": "Zobraziť odpovede", @@ -360,6 +362,10 @@ "ignore_notifications_modal.filter_to_act_users": "Stále budeš môcť akceptovať, odmietnuť, alebo nahlásiť užívateľov", "ignore_notifications_modal.filter_to_avoid_confusion": "Triedenie pomáha vyvarovať sa možnému zmäteniu", "ignore_notifications_modal.ignore": "Ignoruj upozornenia", + "ignore_notifications_modal.new_accounts_title": "Nevšímať si oznámenia z nových účtov?", + "ignore_notifications_modal.not_followers_title": "Nevšímať si oznámenia od ľudí, ktorí ťa nenasledujú?", + "ignore_notifications_modal.not_following_title": "Nevšímať si oznámenia od ľudí, ktorých nenasleduješ?", + "ignore_notifications_modal.private_mentions_title": "Nevšímať si oznámenia o nevyžiadaných súkromných spomínaniach?", "interaction_modal.description.favourite": "S účtom na Mastodone môžete tento príspevok ohviezdičkovať, tak dať autorovi vedieť, že sa vám páči, a uložiť si ho na neskôr.", "interaction_modal.description.follow": "S účtom na Mastodone môžete {name} sledovať a vidieť ich príspevky vo svojom domovskom kanáli.", "interaction_modal.description.reblog": "S účtom na Mastodone môžete tento príspevok zdeľať so svojimi sledovateľmi.", diff --git a/app/javascript/mastodon/locales/sl.json b/app/javascript/mastodon/locales/sl.json index 32626b80f9..3690c612b7 100644 --- a/app/javascript/mastodon/locales/sl.json +++ b/app/javascript/mastodon/locales/sl.json @@ -86,6 +86,8 @@ "alert.unexpected.message": "Zgodila se je nepričakovana napaka.", "alert.unexpected.title": "Ojoj!", "announcement.announcement": "Obvestilo", + "annual_report.summary.most_used_hashtag.none": "Brez", + "annual_report.summary.new_posts.new_posts": "nove objave", "attachments_list.unprocessed": "(neobdelano)", "audio.hide": "Skrij zvok", "block_modal.remote_users_caveat": "Od strežnika {domain} bomo zahtevali, da spoštuje vašo odločitev. Izpolnjevanje zahteve ni zagotovljeno, ker nekateri strežniki blokiranja obravnavajo drugače. Javne objave bodo morda še vedno vidne neprijavljenim uporabnikom.", @@ -433,6 +435,7 @@ "lists.subheading": "Vaši seznami", "load_pending": "{count, plural, one {# nov element} two {# nova elementa} few {# novi elementi} other {# novih elementov}}", "loading_indicator.label": "Nalaganje …", + "media_gallery.hide": "Skrij", "moved_to_account_banner.text": "Vaš račun {disabledAccount} je trenutno onemogočen, ker ste se prestavili na {movedToAccount}.", "mute_modal.hide_from_notifications": "Skrijte se pred obvestili", "mute_modal.hide_options": "Skrij možnosti", @@ -444,6 +447,7 @@ "mute_modal.you_wont_see_mentions": "Objav, ki jih omenjajo, ne boste videli.", "mute_modal.you_wont_see_posts": "Še vedno vidijo vaše objave, vi pa ne njihovih.", "navigation_bar.about": "O Mastodonu", + "navigation_bar.administration": "Upravljanje", "navigation_bar.advanced_interface": "Odpri v naprednem spletnem vmesniku", "navigation_bar.blocks": "Blokirani uporabniki", "navigation_bar.bookmarks": "Zaznamki", @@ -478,10 +482,12 @@ "notification.favourite": "{name} je vzljubil/a vašo objavo", "notification.follow": "{name} vam sledi", "notification.follow_request": "{name} vam želi slediti", + "notification.label.mention": "Omemba", "notification.label.private_mention": "Zasebna omemba", "notification.label.private_reply": "Zasebni odgovor", "notification.label.reply": "Odgovori", "notification.mention": "Omemba", + "notification.mentioned_you": "{name} vas je omenil/a", "notification.moderation-warning.learn_more": "Več o tem", "notification.moderation_warning": "Prejeli ste opozorilo moderatorjev", "notification.moderation_warning.action_delete_statuses": "Nekatere vaše objave so odstranjene.", @@ -502,6 +508,7 @@ "notification.status": "{name} je pravkar objavil/a", "notification.update": "{name} je uredil(a) objavo", "notification_requests.accept": "Sprejmi", + "notification_requests.confirm_accept_multiple.title": "Ali želite sprejeti zahteve za obvestila?", "notification_requests.confirm_dismiss_multiple.title": "Želite opustiti zahteve za obvestila?", "notification_requests.dismiss": "Zavrni", "notification_requests.edit_selection": "Uredi", @@ -740,6 +747,7 @@ "status.edit": "Uredi", "status.edited": "Zadnje urejanje {date}", "status.edited_x_times": "Urejeno {count, plural, one {#-krat} two {#-krat} few {#-krat} other {#-krat}}", + "status.embed": "Pridobite kodo za vgradnjo", "status.favourite": "Priljubljen_a", "status.favourites": "{count, plural, one {priljubitev} two {priljubitvi} few {priljubitve} other {priljubitev}}", "status.filter": "Filtriraj to objavo", diff --git a/app/javascript/mastodon/locales/tr.json b/app/javascript/mastodon/locales/tr.json index ece97614ad..061f9c6c28 100644 --- a/app/javascript/mastodon/locales/tr.json +++ b/app/javascript/mastodon/locales/tr.json @@ -81,7 +81,7 @@ "admin.impact_report.instance_followers": "Kullanıcılarımızın kaybedeceği takipçiler", "admin.impact_report.instance_follows": "Kullanıcılarının kaybedeceği takipçiler", "admin.impact_report.title": "Etki özeti", - "alert.rate_limited.message": "Lütfen {retry_time, time, medium} saatinden sonra tekrar deneyin.", + "alert.rate_limited.message": "Lütfen sonra tekrar deneyin {retry_time, time, medium}.", "alert.rate_limited.title": "Aşırı istek gönderildi", "alert.unexpected.message": "Beklenmedik bir hata oluştu.", "alert.unexpected.title": "Hay aksi!", @@ -358,7 +358,7 @@ "footer.privacy_policy": "Gizlilik politikası", "footer.source_code": "Kaynak kodu görüntüle", "footer.status": "Durum", - "generic.saved": "Kaydedildi", + "generic.saved": "Kaydet", "getting_started.heading": "Başlarken", "hashtag.column_header.tag_mode.all": "ve {additional}", "hashtag.column_header.tag_mode.any": "ya da {additional}", diff --git a/app/javascript/mastodon/locales/zh-CN.json b/app/javascript/mastodon/locales/zh-CN.json index 887410dd51..cc0f0b9341 100644 --- a/app/javascript/mastodon/locales/zh-CN.json +++ b/app/javascript/mastodon/locales/zh-CN.json @@ -89,7 +89,7 @@ "announcement.announcement": "公告", "annual_report.summary.archetype.booster": "潮流捕手", "annual_report.summary.archetype.lurker": "吃瓜群众", - "annual_report.summary.archetype.oracle": "预言家", + "annual_report.summary.archetype.oracle": "无所不在", "annual_report.summary.archetype.pollster": "投票狂魔", "annual_report.summary.archetype.replier": "评论区原住民", "annual_report.summary.followers.followers": "关注者", @@ -102,13 +102,13 @@ "annual_report.summary.most_used_app.most_used_app": "最常用的应用", "annual_report.summary.most_used_hashtag.most_used_hashtag": "最常用的话题", "annual_report.summary.most_used_hashtag.none": "无", - "annual_report.summary.new_posts.new_posts": "新发嘟", + "annual_report.summary.new_posts.new_posts": "新嘟嘟", "annual_report.summary.percentile.text": "这使你跻身 Mastodon 用户的前", - "annual_report.summary.percentile.we_wont_tell_bernie": "我们打死也不会告诉Bernie。", + "annual_report.summary.percentile.we_wont_tell_bernie": "我们打死也不会告诉扣税国王的(他知道的话要来收你发嘟税了)。", "annual_report.summary.thanks": "感谢你这一年与 Mastodon 一路同行!", "attachments_list.unprocessed": "(未处理)", "audio.hide": "隐藏音频", - "block_modal.remote_users_caveat": "我们将要求服务器 {domain} 尊重您的决定。然而,我们无法保证对方一定遵从,因为某些服务器可能会以不同的方案处理屏蔽操作。公开嘟文仍然可能对未登录的用户可见。", + "block_modal.remote_users_caveat": "我们将要求服务器 {domain} 尊重你的决定。然而,我们无法保证对方一定遵从,因为某些服务器可能会以不同的方案处理屏蔽操作。公开嘟文仍然可能对未登录的用户可见。", "block_modal.show_less": "隐藏", "block_modal.show_more": "显示更多", "block_modal.they_cant_mention": "他们不能提及或关注你。", @@ -132,7 +132,7 @@ "bundle_modal_error.message": "载入这个组件时发生了错误。", "bundle_modal_error.retry": "重试", "closed_registrations.other_server_instructions": "基于 Mastodon 去中心化的特性,你可以在其它服务器上创建账号并继续与此服务器互动。", - "closed_registrations_modal.description": "您目前无法在 {domain} 上创建账户,但请注意,使用 Mastodon 并非需要专门在 {domain} 上注册账户。", + "closed_registrations_modal.description": "你目前无法在 {domain} 上创建账户,但请注意,使用 Mastodon 并非需要专门在 {domain} 上注册账户。", "closed_registrations_modal.find_another_server": "查找其他服务器", "closed_registrations_modal.preamble": "Mastodon 是去中心化的,所以无论在哪个实例创建账号,都可以关注本服务器上的账号并与之交流。 或者你还可以自己搭建实例!", "closed_registrations_modal.title": "注册 Mastodon 账号", @@ -161,8 +161,8 @@ "column_header.unpin": "取消置顶", "column_subheading.settings": "设置", "community.column_settings.local_only": "仅限本站", - "community.column_settings.media_only": "仅限媒体", - "community.column_settings.remote_only": "仅限外部", + "community.column_settings.media_only": "仅媒体", + "community.column_settings.remote_only": "仅外站", "compose.language.change": "更改语言", "compose.language.search": "搜索语言...", "compose.published.body": "嘟文已发布。", @@ -180,11 +180,11 @@ "compose_form.poll.single": "单选", "compose_form.poll.switch_to_multiple": "将投票改为多选", "compose_form.poll.switch_to_single": "将投票改为单选", - "compose_form.poll.type": "样式", + "compose_form.poll.type": "类型", "compose_form.publish": "发布", - "compose_form.publish_form": "发布", + "compose_form.publish_form": "新嘟文", "compose_form.reply": "回复", - "compose_form.save_changes": "更新", + "compose_form.save_changes": "更改", "compose_form.spoiler.marked": "移除内容警告", "compose_form.spoiler.unmarked": "添加内容警告", "compose_form.spoiler_placeholder": "内容警告 (可选)", @@ -197,7 +197,7 @@ "confirmations.delete_list.message": "确定永久删除这个列表吗?", "confirmations.delete_list.title": "确认删除列表?", "confirmations.discard_edit_media.confirm": "丢弃", - "confirmations.discard_edit_media.message": "您还有未保存的媒体描述或预览修改,仍要丢弃吗?", + "confirmations.discard_edit_media.message": "你还有未保存的媒体描述或预览修改,仍要丢弃吗?", "confirmations.edit.confirm": "编辑", "confirmations.edit.message": "编辑此消息将会覆盖当前正在撰写的信息。仍要继续吗?", "confirmations.edit.title": "确认覆盖嘟文?", @@ -229,7 +229,7 @@ "directory.new_arrivals": "新来者", "directory.recently_active": "最近活跃", "disabled_account_banner.account_settings": "账号设置", - "disabled_account_banner.text": "您的账号 {disabledAccount} 目前已被禁用。", + "disabled_account_banner.text": "你的账号 {disabledAccount} 目前已被禁用。", "dismissable_banner.community_timeline": "这些是来自 {domain} 用户的最新公开嘟文。", "dismissable_banner.dismiss": "忽略", "dismissable_banner.explore_links": "这些新闻故事正被本站和分布式网络上其他站点的用户谈论。", @@ -264,7 +264,7 @@ "emoji_button.clear": "清除", "emoji_button.custom": "自定义", "emoji_button.flags": "旗帜", - "emoji_button.food": "食物和饮料", + "emoji_button.food": "食物与饮料", "emoji_button.label": "插入表情符号", "emoji_button.nature": "自然", "emoji_button.not_found": "未找到匹配的表情符号", @@ -288,13 +288,13 @@ "empty_column.favourited_statuses": "你没有喜欢过任何嘟文。喜欢过的嘟文会显示在这里。", "empty_column.favourites": "没有人喜欢过这条嘟文。如果有人喜欢了,就会显示在这里。", "empty_column.follow_requests": "你还没有收到任何关注请求。当你收到一个关注请求时,它会出现在这里。", - "empty_column.followed_tags": "您还没有关注任何话题标签。 当您关注后,它们会出现在这里。", + "empty_column.followed_tags": "你还没有关注任何话题标签。 当你关注后,它们会出现在这里。", "empty_column.hashtag": "这个话题标签下暂时没有内容。", "empty_column.home": "你的主页时间线是空的!快去关注更多人吧。 {suggestions}", "empty_column.list": "列表中还没有任何内容。当列表成员发布新嘟文时,它们将出现在这里。", "empty_column.lists": "你还没有创建过列表。你创建的列表会在这里显示。", "empty_column.mutes": "你没有隐藏任何用户。", - "empty_column.notification_requests": "都看完了!这里没有任何未读通知。当收到新的通知时,它们将根据您的设置显示在这里。", + "empty_column.notification_requests": "都看完了!这里没有任何未读通知。当收到新的通知时,它们将根据你的设置显示在这里。", "empty_column.notifications": "你还没有收到过任何通知,快和其他用户互动吧。", "empty_column.public": "这里什么都没有!写一些公开的嘟文,或者关注其他服务器的用户后,这里就会有嘟文出现了", "error.unexpected_crash.explanation": "此页面无法正确显示,这可能是因为我们的代码中有错误,也可能是因为浏览器兼容问题。", @@ -333,7 +333,7 @@ "firehose.remote": "其他服务器", "follow_request.authorize": "同意", "follow_request.reject": "拒绝", - "follow_requests.unlocked_explanation": "尽管你没有锁嘟,但是 {domain} 的工作人员认为你也许会想手动审核审核这些账号的关注请求。", + "follow_requests.unlocked_explanation": "尽管你没有锁嘟,但是 {domain} 的站务人员认为你也许会想手动审核审核这些账号的关注请求。", "follow_suggestions.curated_suggestion": "站务人员精选", "follow_suggestions.dismiss": "不再显示", "follow_suggestions.featured_longer": "由 {domain} 管理团队精选", @@ -354,7 +354,7 @@ "footer.directory": "用户目录", "footer.get_app": "获取应用", "footer.invite": "邀请", - "footer.keyboard_shortcuts": "快捷键列表", + "footer.keyboard_shortcuts": "快捷键", "footer.privacy_policy": "隐私政策", "footer.source_code": "查看源代码", "footer.status": "状态", @@ -401,18 +401,18 @@ "ignore_notifications_modal.not_followers_title": "是否忽略未关注你的人的通知?", "ignore_notifications_modal.not_following_title": "是否忽略你未关注的人的通知?", "ignore_notifications_modal.private_mentions_title": "是否忽略不请自来的私下提及?", - "interaction_modal.description.favourite": "只需一个 Mastodon 账号,即可喜欢这条嘟文,对嘟文的作者展示您欣赏的态度,并保存嘟文以供日后使用。", + "interaction_modal.description.favourite": "只需一个 Mastodon 账号,即可喜欢这条嘟文,对嘟文的作者展示你欣赏的态度,并保存嘟文以供日后使用。", "interaction_modal.description.follow": "拥有一个 Mastodon 账号,你就可以关注 {name} 并在自己的主页上接收对方的新嘟文。", "interaction_modal.description.reblog": "拥有一个 Mastodon 账号,你就可以向自己的关注者们转发此嘟文。", "interaction_modal.description.reply": "拥有一个 Mastodon 账号,你就可以回复此嘟文。", "interaction_modal.description.vote": "拥有一个 Mastodon 账号,你就可以参与此投票。", "interaction_modal.login.action": "转到主页", - "interaction_modal.login.prompt": "您所入驻的服务器域名,如:mastodon.social", + "interaction_modal.login.prompt": "你所入驻的服务器域名,如:mastodon.social", "interaction_modal.no_account_yet": "不在 Mastodon 上?", "interaction_modal.on_another_server": "在另一服务器", "interaction_modal.on_this_server": "在此服务器", - "interaction_modal.sign_in": "您尚未登录此服务器,您的账号托管在哪?", - "interaction_modal.sign_in_hint": "提示:这是您注册的网站,如果您不记得了,请在邮箱的收件箱中查找欢迎邮件。您还可以输入完整的用户名!(例如 @Mastodon@mastodon.social)", + "interaction_modal.sign_in": "你尚未登录此服务器,你的账号托管在哪?", + "interaction_modal.sign_in_hint": "提示:这是你注册的网站,如果你不记得了,请在邮箱的收件箱中查找欢迎邮件。你还可以输入完整的用户名!(例如 @Mastodon@mastodon.social)", "interaction_modal.title.favourite": "喜欢 {name} 的嘟文", "interaction_modal.title.follow": "关注 {name}", "interaction_modal.title.reblog": "转发 {name} 的嘟文", @@ -424,8 +424,8 @@ "keyboard_shortcuts.back": "返回上一页", "keyboard_shortcuts.blocked": "打开被屏蔽用户列表", "keyboard_shortcuts.boost": "转嘟", - "keyboard_shortcuts.column": "选择某栏", - "keyboard_shortcuts.compose": "选择输入框", + "keyboard_shortcuts.column": "选中某栏", + "keyboard_shortcuts.compose": "选中输入框", "keyboard_shortcuts.description": "说明", "keyboard_shortcuts.direct": "打开私下提及栏", "keyboard_shortcuts.down": "在列表中让光标下移", @@ -447,7 +447,7 @@ "keyboard_shortcuts.profile": "打开作者的个人资料", "keyboard_shortcuts.reply": "回复嘟文", "keyboard_shortcuts.requests": "打开关注请求列表", - "keyboard_shortcuts.search": "选择搜索框", + "keyboard_shortcuts.search": "选中搜索框", "keyboard_shortcuts.spoilers": "显示或隐藏被折叠的正文", "keyboard_shortcuts.start": "打开“开始使用”栏", "keyboard_shortcuts.toggle_hidden": "显示或隐藏被折叠的正文", @@ -473,16 +473,16 @@ "lists.exclusive": "在主页中隐藏这些嘟文", "lists.new.create": "新建列表", "lists.new.title_placeholder": "新列表的标题", - "lists.replies_policy.followed": "任何被关注的用户", + "lists.replies_policy.followed": "所有我关注的用户", "lists.replies_policy.list": "列表成员", - "lists.replies_policy.none": "无人", + "lists.replies_policy.none": "不显示", "lists.replies_policy.title": "显示回复:", "lists.search": "搜索你关注的人", "lists.subheading": "你的列表", "load_pending": "{count} 项", "loading_indicator.label": "加载中…", "media_gallery.hide": "隐藏", - "moved_to_account_banner.text": "您的账号 {disabledAccount} 已禁用,因为您已迁移到 {movedToAccount}。", + "moved_to_account_banner.text": "你的账号 {disabledAccount} 已禁用,因为你已迁移到 {movedToAccount}。", "mute_modal.hide_from_notifications": "从通知中隐藏", "mute_modal.hide_options": "隐藏选项", "mute_modal.indefinite": "直到我取消隐藏他们", @@ -507,19 +507,19 @@ "navigation_bar.filters": "忽略的关键词", "navigation_bar.follow_requests": "关注请求", "navigation_bar.followed_tags": "关注的话题标签", - "navigation_bar.follows_and_followers": "关注和粉丝", + "navigation_bar.follows_and_followers": "关注与关注者", "navigation_bar.lists": "列表", "navigation_bar.logout": "退出登录", - "navigation_bar.moderation": "运营", + "navigation_bar.moderation": "审核", "navigation_bar.mutes": "已隐藏的用户", "navigation_bar.opened_in_classic_interface": "嘟文、账户和其他特定页面默认在经典网页界面中打开。", "navigation_bar.personal": "个人", "navigation_bar.pins": "置顶嘟文", - "navigation_bar.preferences": "首选项", + "navigation_bar.preferences": "偏好设置", "navigation_bar.public_timeline": "跨站公共时间轴", "navigation_bar.search": "搜索", "navigation_bar.security": "安全", - "not_signed_in_indicator.not_signed_in": "您需要登录才能访问此资源。", + "not_signed_in_indicator.not_signed_in": "你需要登录才能访问此资源。", "notification.admin.report": "{name} 举报了 {target}", "notification.admin.report_account": "{name} 举报了来自 {target} 的 {count, plural, other {# 条嘟文}},原因为 {category}", "notification.admin.report_account_other": "{name} 举报了来自 {target} 的 {count, plural, other {# 条嘟文}}", @@ -528,10 +528,10 @@ "notification.admin.sign_up": "{name} 注册了", "notification.admin.sign_up.name_and_others": "{name} 和 {count, plural, other {另外 # 人}}注册了", "notification.annual_report.message": "你的 {year} #Wrapstodon 年度回顾来啦!快来看看这一年你在 Mastodon 上的精彩瞬间!", - "notification.annual_report.view": "查看 #Wrapstodon", + "notification.annual_report.view": "查看 #Wrapstodon 年度回顾", "notification.favourite": "{name} 喜欢了你的嘟文", "notification.favourite.name_and_others_with_link": "{name} 和 {count, plural, other {另外 # 人}} 喜欢了你的嘟文", - "notification.follow": "{name} 开始关注你", + "notification.follow": "{name} 关注了你", "notification.follow.name_and_others": "{name} 和 {count, plural, other {另外 # 人}} 关注了你", "notification.follow_request": "{name} 向你发送了关注请求", "notification.follow_request.name_and_others": "{name} 和 {count, plural, other {另外 # 人}} 向你发送了关注请求", @@ -569,7 +569,7 @@ "notification_requests.confirm_dismiss_multiple.button": "{count, plural, other {拒绝请求}}", "notification_requests.confirm_dismiss_multiple.message": "你将要拒绝 {count, plural, other {# 个通知请求}}。你将无法再轻易访问{count, plural, other {它们}}。是否继续?", "notification_requests.confirm_dismiss_multiple.title": "是否拒绝通知请求?", - "notification_requests.dismiss": "拒绝", + "notification_requests.dismiss": "忽略", "notification_requests.dismiss_multiple": "{count, plural, other {拒绝 # 个请求…}}", "notification_requests.edit_selection": "编辑", "notification_requests.exit_selection": "完成", @@ -597,7 +597,7 @@ "notifications.column_settings.push": "推送通知", "notifications.column_settings.reblog": "转嘟:", "notifications.column_settings.show": "在通知栏显示", - "notifications.column_settings.sound": "播放音效", + "notifications.column_settings.sound": "播放提示音", "notifications.column_settings.status": "新嘟文:", "notifications.column_settings.unread_notifications.category": "未读通知", "notifications.column_settings.unread_notifications.highlight": "高亮显示未读通知", @@ -630,7 +630,7 @@ "notifications.policy.filter_not_following_hint": "直到你手动批准", "notifications.policy.filter_not_following_title": "你没有关注的人", "notifications.policy.filter_private_mentions_hint": "过滤通知,除非通知是在回复提及你自己的内容,或发送者是你关注的人", - "notifications.policy.filter_private_mentions_title": "不请自来的提及", + "notifications.policy.filter_private_mentions_title": "不请自来的私下提及", "notifications.policy.title": "管理来自 … 的通知", "notifications_permission_banner.enable": "启用桌面通知", "notifications_permission_banner.how_to_control": "启用桌面通知以在 Mastodon 未打开时接收通知。你可以通过交互通过上面的 {icon} 按钮来精细控制可以发送桌面通知的交互类型。", @@ -640,9 +640,9 @@ "onboarding.actions.go_to_explore": "看看有什么新鲜事", "onboarding.actions.go_to_home": "转到主页动态", "onboarding.compose.template": "你好 #Mastodon!", - "onboarding.follows.empty": "很抱歉,现在无法显示任何结果。您可以尝试使用搜索或浏览探索页面来查找要关注的人,或稍后再试。", + "onboarding.follows.empty": "很抱歉,现在无法显示任何结果。你可以尝试使用搜索或浏览探索页面来查找要关注的人,或稍后再试。", "onboarding.follows.lead": "你管理你自己的家庭饲料。你关注的人越多,它将越活跃和有趣。 这些配置文件可能是一个很好的起点——你可以随时取消关注它们!", - "onboarding.follows.title": "定制您的主页动态", + "onboarding.follows.title": "定制你的主页动态", "onboarding.profile.discoverable": "让我的资料卡可被他人发现", "onboarding.profile.discoverable_hint": "当你选择在 Mastodon 上启用发现功能时,你的嘟文可能会出现在搜索结果和热门中,你的账户可能会被推荐给与你兴趣相似的人。", "onboarding.profile.display_name": "昵称", @@ -653,28 +653,28 @@ "onboarding.profile.save_and_continue": "保存并继续", "onboarding.profile.title": "设置个人资料", "onboarding.profile.upload_avatar": "上传头像", - "onboarding.profile.upload_header": "上传资料卡头图", + "onboarding.profile.upload_header": "上传个人资料背景横幅", "onboarding.share.lead": "让人们知道他们如何在Mastodon找到你!", "onboarding.share.message": "我是来自 #Mastodon 的 {username}!请在 {url} 关注我。", "onboarding.share.next_steps": "可能的下一步:", "onboarding.share.title": "分享你的个人资料", - "onboarding.start.lead": "你的新 Mastodon 帐户已准备好。下面是如何最大限度地利用它:", + "onboarding.start.lead": "你的新 Mastodon 账户已准备好。下面是如何最大限度地利用它:", "onboarding.start.skip": "想要在前面跳过吗?", "onboarding.start.title": "你已经成功了!", "onboarding.steps.follow_people.body": "You curate your own feed. Lets fill it with interesting people.", - "onboarding.steps.follow_people.title": "定制您的主页动态", + "onboarding.steps.follow_people.title": "定制你的主页动态", "onboarding.steps.publish_status.body": "向世界问声好吧。", "onboarding.steps.publish_status.title": "发布你的第一篇嘟文", "onboarding.steps.setup_profile.body": "Others are more likely to interact with you with a filled out profile.", "onboarding.steps.setup_profile.title": "自定义你的个人资料", - "onboarding.steps.share_profile.body": "Let your friends know how to find you on Mastodon!", + "onboarding.steps.share_profile.body": "让你的朋友知道怎样在 Mastodon 找到你", "onboarding.steps.share_profile.title": "分享你的个人资料", "onboarding.tips.2fa": "你知道吗?你可以在账户设置中配置双因素认证来保护账户安全。可以使用你选择的任何 TOTP 应用,无需电话号码!", "onboarding.tips.accounts_from_other_servers": "你知道吗? 既然Mastodon是去中心化的,你所看到的一些账户将被托管在你以外的服务器上。 但你可以无缝地与他们交互!他们的服务器在他们的用户名的后半部分!", - "onboarding.tips.migration": "您知道吗? 如果你觉得你喜欢 {domain} 不是您未来的一个伟大的服务器选择。 您可以移动到另一个 Mastodon 服务器而不失去您的关注者。 您甚至可以主持您自己的服务器!", - "onboarding.tips.verification": "您知道吗? 您可以通过在自己的网站上放置一个链接到您的 Mastodon 个人资料并将网站添加到您的个人资料来验证您的帐户。 无需收费或文书工作!", + "onboarding.tips.migration": "你知道吗?如果你将来觉得 {domain} 不再符合您的需求,你可以在保留现有关注者的情况下迁移至其他 Mastodon 服务器。你甚至可以部署自己的服务器!", + "onboarding.tips.verification": "你知道吗? 你可以通过在自己的网站上放置一个链接到你的 Mastodon 个人资料并将网站添加到你的个人资料来验证你的账户。 无需收费或文书工作!", "password_confirmation.exceeds_maxlength": "密码确认超过最大密码长度", - "password_confirmation.mismatching": "密码确认不匹配", + "password_confirmation.mismatching": "确认密码与密码不一致。", "picture_in_picture.restore": "恢复", "poll.closed": "已关闭", "poll.refresh": "刷新", @@ -687,9 +687,9 @@ "poll_button.add_poll": "发起投票", "poll_button.remove_poll": "移除投票", "privacy.change": "设置嘟文的可见范围", - "privacy.direct.long": "帖子中提到的每个人", + "privacy.direct.long": "嘟文中提到的每个人", "privacy.direct.short": "特定的人", - "privacy.private.long": "仅限您的关注者", + "privacy.private.long": "仅限你的关注者", "privacy.private.short": "关注者", "privacy.public.long": "所有 Mastodon 内外的人", "privacy.public.short": "公开", @@ -745,12 +745,12 @@ "report.reasons.violation": "违反服务器规则", "report.reasons.violation_description": "你清楚它违反了特定的规则", "report.rules.subtitle": "选择所有适用选项", - "report.rules.title": "哪些规则被违反了?", + "report.rules.title": "违反了哪些规则?", "report.statuses.subtitle": "选择所有适用选项", "report.statuses.title": "是否有任何嘟文可以支持这一报告?", "report.submit": "提交", "report.target": "举报 {target}", - "report.thanks.take_action": "以下是您控制您在 Mastodon 上能看到哪些内容的选项:", + "report.thanks.take_action": "以下是你控制你在 Mastodon 上能看到哪些内容的选项:", "report.thanks.take_action_actionable": "在我们审阅这个问题时,你可以对 @{name} 采取行动", "report.thanks.title": "不想看到这个内容?", "report.thanks.title_actionable": "感谢提交举报,我们将会进行处理。", @@ -780,7 +780,7 @@ "search_popout.options": "搜索选项", "search_popout.quick_actions": "快捷操作", "search_popout.recent": "最近搜索", - "search_popout.specific_date": "指定日期", + "search_popout.specific_date": "具体日期", "search_popout.user": "用户", "search_results.accounts": "用户", "search_results.all": "全部", @@ -789,7 +789,7 @@ "search_results.see_all": "查看全部", "search_results.statuses": "嘟文", "search_results.title": "搜索 {q}", - "server_banner.about_active_users": "过去 30 天内使用此服务器的人(每月活跃用户)", + "server_banner.about_active_users": "过去 30 天内使用此服务器的人(月活跃用户)", "server_banner.active_users": "活跃用户", "server_banner.administered_by": "本站管理员:", "server_banner.is_one_of_many": "{domain} 是可用于参与联邦宇宙的众多独立 Mastodon 服务器之一。", @@ -814,7 +814,7 @@ "status.direct_indicator": "私下提及", "status.edit": "编辑", "status.edited": "最后编辑于 {date}", - "status.edited_x_times": "共编辑 {count, plural, one {{count} 次} other {{count} 次}}", + "status.edited_x_times": "共编辑 {count, plural, other {{count} 次}}", "status.embed": "获取嵌入代码", "status.favourite": "喜欢", "status.favourites": "{count, plural, other {次喜欢}}", @@ -834,7 +834,7 @@ "status.pinned": "置顶嘟文", "status.read_more": "查看更多", "status.reblog": "转嘟", - "status.reblog_private": "转嘟(可见者不变)", + "status.reblog_private": "以相同可见性转嘟", "status.reblogged_by": "{name} 转嘟了", "status.reblogs": "{count, plural, other {次转嘟}}", "status.reblogs.empty": "没有人转嘟过此条嘟文。如果有人转嘟了,就会显示在这里。", @@ -856,7 +856,7 @@ "status.uncached_media_warning": "预览不可用", "status.unmute_conversation": "恢复此对话的通知提醒", "status.unpin": "在个人资料页面取消置顶", - "subscribed_languages.lead": "更改此选择后,仅选定语言的嘟文会出现在您的主页和列表时间轴上。选择「无」将接收所有语言的嘟文。", + "subscribed_languages.lead": "更改此选择后,仅选定语言的嘟文会出现在你的主页和列表时间轴上。选择「无」将接收所有语言的嘟文。", "subscribed_languages.save": "保存更改", "subscribed_languages.target": "更改 {target} 的订阅语言", "tabs_bar.home": "主页", @@ -886,7 +886,7 @@ "upload_form.edit": "编辑", "upload_form.thumbnail": "更改缩略图", "upload_form.video_description": "为听障人士和视障人士添加文字描述", - "upload_modal.analyzing_picture": "分析图片…", + "upload_modal.analyzing_picture": "正在分析图片…", "upload_modal.apply": "应用", "upload_modal.applying": "正在应用…", "upload_modal.choose_image": "选择图像", @@ -908,5 +908,5 @@ "video.mute": "静音", "video.pause": "暂停", "video.play": "播放", - "video.unmute": "解除禁音" + "video.unmute": "取消静音" } diff --git a/config/locales/activerecord.zh-CN.yml b/config/locales/activerecord.zh-CN.yml index a4edf294a3..f620158361 100644 --- a/config/locales/activerecord.zh-CN.yml +++ b/config/locales/activerecord.zh-CN.yml @@ -49,16 +49,16 @@ zh-CN: blocked: 使用了被封禁的电子邮件提供商 unreachable: 似乎不存在 role_id: - elevated: 不能高于您当前的身份 + elevated: 不能高于你现在的身份 user_role: attributes: permissions_as_keys: dangerous: 包含对基本角色不安全的权限 - elevated: 不能包含您当前身份未有的权限 - own_role: 无法以您当前的身份更改 + elevated: 不能包含你当前身份未有的权限 + own_role: 无权以你当前的身份更改 position: - elevated: 不能高于您当前的角色 - own_role: 无法以您当前的身份更改 + elevated: 不能高于你当前的角色 + own_role: 无权以你当前的身份更改 webhook: attributes: events: diff --git a/config/locales/an.yml b/config/locales/an.yml index 43f8d358cc..f941651438 100644 --- a/config/locales/an.yml +++ b/config/locales/an.yml @@ -723,7 +723,6 @@ an: original_status: Publicación orichinal reblogs: Impulsos status_changed: Publicación cambiada - title: Estau d'as cuentas - @%{name} trending: En tendencia visibility: Visibilidat with_media: Con multimedia diff --git a/config/locales/ar.yml b/config/locales/ar.yml index bbc481a137..832f60795f 100644 --- a/config/locales/ar.yml +++ b/config/locales/ar.yml @@ -847,7 +847,6 @@ ar: original_status: المنشور الأصلي reblogs: المعاد تدوينها status_changed: عُدّل المنشور - title: منشورات الحساب - @%{name} trending: المتداولة visibility: مدى الظهور with_media: تحتوي على وسائط diff --git a/config/locales/be.yml b/config/locales/be.yml index c59233eb8b..c97547b8b9 100644 --- a/config/locales/be.yml +++ b/config/locales/be.yml @@ -856,7 +856,6 @@ be: original_status: Зыходны допіс reblogs: Рэпосты status_changed: Допіс зменены - title: Допісы уліковага запісу - @%{name} trending: Папулярныя visibility: Бачнасць with_media: З медыя diff --git a/config/locales/bg.yml b/config/locales/bg.yml index 2c5edf0b13..5688a44f91 100644 --- a/config/locales/bg.yml +++ b/config/locales/bg.yml @@ -807,7 +807,6 @@ bg: original_status: Първообразна публикация reblogs: Блогване пак status_changed: Публикацията променена - title: Публикации на акаунта - @%{name} trending: Изгряващи visibility: Видимост with_media: С мултимедия diff --git a/config/locales/br.yml b/config/locales/br.yml index 098b20934f..fbe91fcbd7 100644 --- a/config/locales/br.yml +++ b/config/locales/br.yml @@ -263,7 +263,7 @@ br: original_status: Toud orin reblogs: Skignadennoù status_changed: Toud kemmet - title: Toudoù ar gont - @%{name} + status_title: Embannadenn gant @%{name} visibility: Gwelusted with_media: Gant mediaoù strikes: diff --git a/config/locales/ca.yml b/config/locales/ca.yml index 970fd99fff..b1af2d95d4 100644 --- a/config/locales/ca.yml +++ b/config/locales/ca.yml @@ -841,7 +841,6 @@ ca: original_status: Publicació original reblogs: Impulsos status_changed: Publicació canviada - title: Estats del compte - @%{name} trending: Tendència visibility: Visibilitat with_media: Amb contingut multimèdia diff --git a/config/locales/ckb.yml b/config/locales/ckb.yml index 6e1b11379c..cfee624e36 100644 --- a/config/locales/ckb.yml +++ b/config/locales/ckb.yml @@ -520,7 +520,6 @@ ckb: media: title: میدیا no_status_selected: هیچ دۆخیک نەگۆڕاوە وەک ئەوەی هیچ بارێک دەستنیشان نەکراوە - title: دۆخی ئەژمێر - @%{name} with_media: بە میدیا tags: review: پێداچوونەوەی دۆخ diff --git a/config/locales/co.yml b/config/locales/co.yml index b81427e833..39d9e9157e 100644 --- a/config/locales/co.yml +++ b/config/locales/co.yml @@ -459,7 +459,6 @@ co: media: title: Media no_status_selected: I statuti ùn sò micca stati mudificati perchè manc'unu era selezziunatu - title: Statuti di u contu - @%{name} with_media: Cù media system_checks: rules_check: diff --git a/config/locales/cs.yml b/config/locales/cs.yml index f5f7f4d731..19a6372224 100644 --- a/config/locales/cs.yml +++ b/config/locales/cs.yml @@ -826,7 +826,6 @@ cs: original_status: Původní příspěvek reblogs: Boosty status_changed: Příspěvek změněn - title: Příspěvky účtu - @%{name} trending: Populární visibility: Viditelnost with_media: S médii diff --git a/config/locales/cy.yml b/config/locales/cy.yml index f479f0f0a0..0daa793f97 100644 --- a/config/locales/cy.yml +++ b/config/locales/cy.yml @@ -897,7 +897,6 @@ cy: original_status: Postiad gwreiddiol reblogs: Ailflogiadau status_changed: Postiad wedi'i newid - title: Postiadau cyfrif - @%{name} trending: Yn trendio visibility: Gwelededd with_media: Gyda chyfryngau diff --git a/config/locales/da.yml b/config/locales/da.yml index e157af9cc2..3a82278b93 100644 --- a/config/locales/da.yml +++ b/config/locales/da.yml @@ -826,8 +826,10 @@ da: back_to_account: Retur til kontoside back_to_report: Retur til anmeldelsesside batch: + add_to_report: 'Føj til rapporten #%{id}' remove_from_report: Fjern fra anmeldelse report: Anmeldelse + contents: Indhold deleted: Slettet favourites: Favoritter history: Versionshistorik @@ -836,13 +838,17 @@ da: media: title: Medier metadata: Metadata + no_history: Dette indlæg er ikke blevet redigeret no_status_selected: Ingen indlæg ændret (ingen valgt) open: Åbn indlæg original_status: Oprindeligt indlæg reblogs: Genblogninger + replied_to_html: Besvarede %{acct_link} status_changed: Indlæg ændret + status_title: Indlæg fra @%{name} title: Kontoindlæg - @%{name} trending: Populære + view_publicly: Vis offentligt visibility: Synlighed with_media: Med medier strikes: diff --git a/config/locales/de.yml b/config/locales/de.yml index e3ee03264e..26ccc8f3ee 100644 --- a/config/locales/de.yml +++ b/config/locales/de.yml @@ -427,9 +427,9 @@ de: not_permitted: Du bist nicht berechtigt, diese Aktion durchzuführen obfuscate: Domain-Name verschleiern obfuscate_hint: Den Domain-Namen öffentlich nur teilweise bekannt geben, sofern die Liste der Domain-Beschränkungen aktiviert ist - private_comment: Interne bzw. nicht-öffentliche Notiz + private_comment: Nicht-öffentliche Notiz private_comment_hint: Kommentar zu dieser Domain-Beschränkung für die interne Nutzung durch die Moderator*innen. - public_comment: Öffentliche Notiz + public_comment: Öffentliche Begründung public_comment_hint: Öffentlicher Hinweis zu dieser Domain-Beschränkung, sofern das Veröffentlichen von Sperrlisten grundsätzlich aktiviert ist. reject_media: Mediendateien ablehnen reject_media_hint: Entfernt lokal gespeicherte Mediendateien und verhindert deren künftiges Herunterladen. Für Sperren irrelevant @@ -502,7 +502,7 @@ de: by_domain: Domain confirm_purge: Möchtest du die Daten von dieser Domain wirklich für immer löschen? content_policies: - comment: Interne Notiz + comment: Nicht-öffentliche Notiz description_html: Du kannst Inhaltsrichtlinien definieren, die auf alle Konten dieser Domain und einer ihrer Subdomains angewendet werden. limited_federation_mode_description_html: Du kannst auswählen, ob du eine Föderation mit dieser Domain erlaubst. policies: @@ -826,8 +826,10 @@ de: back_to_account: Zurück zum Konto back_to_report: Zurück zur Seite mit den Meldungen batch: + add_to_report: Der Meldung Nr. %{id} hinzufügen remove_from_report: Von der Meldung entfernen report: Meldung + contents: Inhalte deleted: Gelöscht favourites: Favoriten history: Versionsverlauf @@ -836,13 +838,17 @@ de: media: title: Medien metadata: Metadaten + no_history: Der Beitrag wurde nicht bearbeitet no_status_selected: Keine Beiträge wurden geändert, weil keine ausgewählt wurden open: Beitrag öffnen original_status: Ursprünglicher Beitrag reblogs: Geteilte Beiträge + replied_to_html: Antwortete %{acct_link} status_changed: Beitrag bearbeitet - title: Beiträge des Kontos - @%{name} + status_title: Beitrag von @%{name} + title: Beiträge des Kontos – @%{name} trending: Trends + view_publicly: Öffentlich anzeigen visibility: Sichtbarkeit with_media: Mit Medien strikes: diff --git a/config/locales/devise.zh-CN.yml b/config/locales/devise.zh-CN.yml index 86e78c1b18..1b5f364d08 100644 --- a/config/locales/devise.zh-CN.yml +++ b/config/locales/devise.zh-CN.yml @@ -9,7 +9,7 @@ zh-CN: already_authenticated: 你已登录。 inactive: 你还没有激活账户。 invalid: "%{authentication_keys} 无效或密码错误。" - last_attempt: 你只有最后一次尝试机会,若未通过,帐号将被锁定。 + last_attempt: 你只有最后一次尝试机会,若未通过,账号将被锁定。 locked: 你的账户已被锁定。 not_found_in_database: "%{authentication_keys}或密码错误。" omniauth_user_creation_failure: 为此身份创建账户时出错。 @@ -33,7 +33,7 @@ zh-CN: title: 新邮箱地址 password_change: explanation: 你的账户密码已更改。 - extra: 如果你并没有申请更改密码,那似乎有人已经入侵你的帐户。请立即更改你的密码;如果你已经无法访问你的帐户,请联系服务器的管理员获取帮助。 + extra: 如果你并没有申请更改密码,那似乎有人已经入侵你的账户。请立即更改你的密码;如果你已经无法访问你的账户,请联系服务器的管理员获取帮助。 subject: Mastodon:密码已被更改 title: 密码已被重置 reconfirmation_instructions: @@ -66,7 +66,7 @@ zh-CN: subject: Mastodon:账户解锁信息 webauthn_credential: added: - explanation: 以下安全密钥已添加到你的帐户 + explanation: 以下安全密钥已添加到你的账户 subject: Mastodon:新的安全密钥 title: 已添加一个新的安全密钥 deleted: diff --git a/config/locales/doorkeeper.ia.yml b/config/locales/doorkeeper.ia.yml index 6bf5e38506..efde9be9c0 100644 --- a/config/locales/doorkeeper.ia.yml +++ b/config/locales/doorkeeper.ia.yml @@ -60,6 +60,7 @@ ia: error: title: Un error ha occurrite new: + prompt_html: "%{client_name} vole haber le permission de acceder a tu conto. Solmente approba iste requesta si tu recognosce e confide in iste fonte." review_permissions: Revider permissiones title: Autorisation necessari show: @@ -82,6 +83,7 @@ ia: access_denied: Le proprietario del ressource o servitor de autorisation ha refusate le requesta. credential_flow_not_configured: Le processo de credentiales de contrasigno del proprietario del ressource ha fallite perque Doorkeeper.configure.resource_owner_from_credentials non es configurate. invalid_client: Le authentication del cliente ha fallite perque le cliente es incognite, necun authentication de cliente es includite, o le methodo de authentication non es supportate. + invalid_code_challenge_method: Le methodo de defia de codice debe esser S256. Le methodo simple (plain) non es supportate. invalid_grant: Le concession de autorisation fornite es invalide, expirate, revocate, non corresponde al URI de redirection usate in le requesta de autorisation, o ha essite emittite a un altere cliente. invalid_redirect_uri: Le URI de redirection includite non es valide. invalid_request: diff --git a/config/locales/doorkeeper.zh-CN.yml b/config/locales/doorkeeper.zh-CN.yml index 08f9885894..848b0d6b6c 100644 --- a/config/locales/doorkeeper.zh-CN.yml +++ b/config/locales/doorkeeper.zh-CN.yml @@ -60,7 +60,7 @@ zh-CN: error: title: 发生错误 new: - prompt_html: "%{client_name} 请求获得访问您账户的权限。 请在确保自己了解并信任此来源后再批准该请求。" + prompt_html: "%{client_name} 请求获得访问你账户的权限。 请在确保自己了解并信任此来源后再批准该请求。" review_permissions: 检查权限 title: 需要授权 show: @@ -85,7 +85,7 @@ zh-CN: invalid_client: 由于应用信息未知、未提交认证信息或使用了不支持的认证方式,认证失败 invalid_code_challenge_method: 代码验证方法必须是 S256,不支持明文。 invalid_grant: 授权方式无效、过期或已被撤销、与授权请求中的回调地址不一致,或使用了其他应用的回调地址 - invalid_redirect_uri: 无效的登录回调地址 + invalid_redirect_uri: 登录回调地址无效。 invalid_request: missing_param: 缺少必需的参数:%{value} request_not_authorized: 请求需要被授权。授权请求所需的参数缺失或无效。 @@ -123,14 +123,14 @@ zh-CN: admin/accounts: 账号管理 admin/all: 所有管理功能 admin/reports: 举报管理 - all: 完全访问您的Mastodon账户 + all: 完全访问你的Mastodon账户 blocks: 屏蔽 bookmarks: 书签 conversations: 会话 crypto: 端到端加密 favourites: 喜欢 filters: 过滤器 - follow: 关注者,隐藏与屏蔽 + follow: 关注,隐藏与屏蔽 follows: 关注 lists: 列表 media: 媒体文件 @@ -163,7 +163,7 @@ zh-CN: admin:write:domain_allows: 在域上执行管理操作 admin:write:domain_blocks: 在域块上执行管理操作 admin:write:email_domain_blocks: 对已屏蔽邮箱域名执行管理操作 - admin:write:ip_blocks: 在 IP 块上执行管理操作 + admin:write:ip_blocks: 针对 IP 段执行管理操作 admin:write:reports: 对举报执行管理操作 crypto: 使用端到端加密 follow: 关注或屏蔽用户 diff --git a/config/locales/el.yml b/config/locales/el.yml index 26b0ec00a2..98ef5f18b7 100644 --- a/config/locales/el.yml +++ b/config/locales/el.yml @@ -817,7 +817,6 @@ el: original_status: Αρχική ανάρτηση reblogs: Αναδημοσιεύσεις status_changed: Η ανάρτηση άλλαξε - title: Καταστάσεις λογαριασμού - @%{name} trending: Τάσεις visibility: Ορατότητα with_media: Με πολυμέσα diff --git a/config/locales/en-GB.yml b/config/locales/en-GB.yml index e22ed62051..76a16aa9db 100644 --- a/config/locales/en-GB.yml +++ b/config/locales/en-GB.yml @@ -832,7 +832,6 @@ en-GB: original_status: Original post reblogs: Reblogs status_changed: Post changed - title: Account posts - @%{name} trending: Trending visibility: Visibility with_media: With media diff --git a/config/locales/eo.yml b/config/locales/eo.yml index 194b2c17b8..120df142b7 100644 --- a/config/locales/eo.yml +++ b/config/locales/eo.yml @@ -830,7 +830,6 @@ eo: original_status: Originala afiŝo reblogs: Reblogaĵoj status_changed: Afiŝo ŝanĝiĝis - title: Afiŝoj de la konto - @%{name} trending: Popularaĵoj visibility: Videbleco with_media: Kun aŭdovidaĵoj diff --git a/config/locales/es-AR.yml b/config/locales/es-AR.yml index 6dc9d99f37..09163c2e4a 100644 --- a/config/locales/es-AR.yml +++ b/config/locales/es-AR.yml @@ -187,6 +187,7 @@ es-AR: create_domain_block: Crear bloqueo de dominio create_email_domain_block: Crear bloqueo de dominio de correo electrónico create_ip_block: Crear regla de dirección IP + create_relay: Crear Relé create_unavailable_domain: Crear dominio no disponible create_user_role: Crear rol demote_user: Descender usuario @@ -198,14 +199,17 @@ es-AR: destroy_email_domain_block: Eliminar bloqueo de dominio de correo electrónico destroy_instance: Purgar dominio destroy_ip_block: Eliminar regla de dirección IP + destroy_relay: Eliminar Relé destroy_status: Eliminar mensaje destroy_unavailable_domain: Eliminar dominio no disponible destroy_user_role: Destruir rol disable_2fa_user: Deshabilitar 2FA disable_custom_emoji: Deshabilitar emoji personalizado + disable_relay: Desactivar Relé disable_sign_in_token_auth_user: Deshabilitar autenticación de token por correo electrónico para el usuario disable_user: Deshabilitar usuario enable_custom_emoji: Habilitar emoji personalizado + enable_relay: Activar Relé enable_sign_in_token_auth_user: Habilitar autenticación de token por correo electrónico para el usuario enable_user: Habilitar usuario memorialize_account: Convertir en cuenta conmemorativa @@ -247,6 +251,7 @@ es-AR: create_domain_block_html: "%{name} bloqueó el dominio %{target}" create_email_domain_block_html: "%{name} bloqueó el dominio de correo electrónico %{target}" create_ip_block_html: "%{name} creó la regla para la dirección IP %{target}" + create_relay_html: "%{name} creó un relé %{target}" create_unavailable_domain_html: "%{name} detuvo la entrega al dominio %{target}" create_user_role_html: "%{name} creó el rol %{target}" demote_user_html: "%{name} bajó de nivel al usuario %{target}" @@ -258,14 +263,17 @@ es-AR: destroy_email_domain_block_html: "%{name} desbloqueó el dominio de correo electrónico %{target}" destroy_instance_html: "%{name} purgó el dominio %{target}" destroy_ip_block_html: "%{name} eliminó la regla para la dirección IP %{target}" + destroy_relay_html: "%{name} eliminó el relé %{target}" destroy_status_html: "%{name} eliminó el mensaje de %{target}" destroy_unavailable_domain_html: "%{name} reanudó la entrega al dominio %{target}" destroy_user_role_html: "%{name} eliminó el rol %{target}" disable_2fa_user_html: "%{name} deshabilitó el requerimiento de dos factores para el usuario %{target}" disable_custom_emoji_html: "%{name} deshabilitó el emoji %{target}" + disable_relay_html: "%{name} desactivó el relé %{target}" disable_sign_in_token_auth_user_html: "%{name} deshabilitó la autenticación de token por correo electrónico para %{target}" disable_user_html: "%{name} deshabilitó el inicio de sesión para el usuario %{target}" enable_custom_emoji_html: "%{name} habilitó el emoji %{target}" + enable_relay_html: "%{name} activó el relé %{target}" enable_sign_in_token_auth_user_html: "%{name} habilitó la autenticación de token por correo electrónico para %{target}" enable_user_html: "%{name} habilitó el inicio de sesión para el usuario %{target}" memorialize_account_html: "%{name} convirtió la cuenta de %{target} en una cuenta conmemorativa" @@ -818,8 +826,10 @@ es-AR: back_to_account: Volver a la página de la cuenta back_to_report: Volver a la página de la denuncia batch: + add_to_report: 'Añadir al informe #%{id}' remove_from_report: Quitar de la denuncia report: Denunciar + contents: Contenidos deleted: Eliminado favourites: Favoritos history: Historial de versiones @@ -828,13 +838,17 @@ es-AR: media: title: Medios metadata: Metadatos + no_history: Esta publicación no ha sido editada no_status_selected: No se cambió ningún mensaje, ya que ninguno fue seleccionado open: Abrir mensaje original_status: Mensaje original reblogs: Adhesiones + replied_to_html: Respondió a %{acct_link} status_changed: Mensaje cambiado - title: Mensajes de la cuenta - @%{name} + status_title: Publicación de @%{name} + title: Publicaciones de la cuenta - @%{name} trending: En tendencia + view_publicly: Ver públicamente visibility: Visibilidad with_media: Con medios strikes: diff --git a/config/locales/es-MX.yml b/config/locales/es-MX.yml index 7e6570f068..53557c091a 100644 --- a/config/locales/es-MX.yml +++ b/config/locales/es-MX.yml @@ -187,6 +187,7 @@ es-MX: create_domain_block: Crear Bloqueo de Dominio create_email_domain_block: Crear bloqueo de dominio de correo electrónico create_ip_block: Crear regla IP + create_relay: Crear Relé create_unavailable_domain: Crear Dominio No Disponible create_user_role: Crear rol demote_user: Degradar Usuario @@ -198,14 +199,17 @@ es-MX: destroy_email_domain_block: Eliminar bloqueo de dominio de correo electrónico destroy_instance: Purgar dominio destroy_ip_block: Eliminar regla IP + destroy_relay: Eliminar Relé destroy_status: Eliminar Estado destroy_unavailable_domain: Eliminar Dominio No Disponible destroy_user_role: Destruir Rol disable_2fa_user: Deshabilitar 2FA disable_custom_emoji: Deshabilitar Emoji Personalizado + disable_relay: Desactivar Relé disable_sign_in_token_auth_user: Deshabilitar la autenticación por token de correo electrónico para el usuario disable_user: Deshabilitar Usuario enable_custom_emoji: Habilitar Emoji Personalizado + enable_relay: Activar Relé enable_sign_in_token_auth_user: Habilitar la autenticación por token de correo electrónico para el usuario enable_user: Habilitar Usuario memorialize_account: Transformar en Cuenta Conmemorativa @@ -247,6 +251,7 @@ es-MX: create_domain_block_html: "%{name} bloqueó el dominio %{target}" create_email_domain_block_html: "%{name} bloqueó el dominio de correo electrónico %{target}" create_ip_block_html: "%{name} creó una regla para la IP %{target}" + create_relay_html: "%{name} creó un relé %{target}" create_unavailable_domain_html: "%{name} detuvo las entregas al dominio %{target}" create_user_role_html: "%{name} creó el rol %{target}" demote_user_html: "%{name} degradó al usuario %{target}" @@ -258,14 +263,17 @@ es-MX: destroy_email_domain_block_html: "%{name} desbloqueó el dominio de correo electrónico %{target}" destroy_instance_html: "%{name} purgó el dominio %{target}" destroy_ip_block_html: "%{name} eliminó una regla para la IP %{target}" + destroy_relay_html: "%{name} eliminó el relé %{target}" destroy_status_html: "%{name} eliminó el estado por %{target}" destroy_unavailable_domain_html: "%{name} reanudó las entregas al dominio %{target}" destroy_user_role_html: "%{name} eliminó el rol %{target}" disable_2fa_user_html: "%{name} desactivó el requisito de dos factores para el usuario %{target}" disable_custom_emoji_html: "%{name} desactivó el emoji %{target}" + disable_relay_html: "%{name} desactivó el relé %{target}" disable_sign_in_token_auth_user_html: "%{name} desactivó la autenticación por token de correo electrónico para %{target}" disable_user_html: "%{name} deshabilitó el inicio de sesión para el usuario %{target}" enable_custom_emoji_html: "%{name} activó el emoji %{target}" + enable_relay_html: "%{name} activó el relé %{target}" enable_sign_in_token_auth_user_html: "%{name} activó autenticación por token de correo electrónico para %{target}" enable_user_html: "%{name} habilitó el inicio de sesión para el usuario %{target}" memorialize_account_html: "%{name} convirtió la cuenta de %{target} en una página in memoriam" @@ -818,8 +826,10 @@ es-MX: back_to_account: Volver a la cuenta back_to_report: Volver a la página de reporte batch: + add_to_report: 'Añadir al informe #%{id}' remove_from_report: Eliminar del reporte report: Reportar + contents: Contenidos deleted: Eliminado favourites: Favoritos history: Historial de versiones @@ -828,13 +838,17 @@ es-MX: media: title: Multimedia metadata: Metadatos + no_history: Esta publicación no ha sido editada no_status_selected: No se cambió ningún estado al no seleccionar ninguno open: Abrir publicación original_status: Publicación original reblogs: Impulsos + replied_to_html: Respondió a %{acct_link} status_changed: Publicación cambiada - title: Estado de las cuentas - @%{name} + status_title: Publicación de @%{name} + title: Publicaciones de la cuenta - @%{name} trending: En tendencia + view_publicly: Ver públicamente visibility: Visibilidad with_media: Con multimedia strikes: diff --git a/config/locales/es.yml b/config/locales/es.yml index 32abd9420d..22123e4309 100644 --- a/config/locales/es.yml +++ b/config/locales/es.yml @@ -57,7 +57,7 @@ es: confirming: Confirmando custom: Personalizado delete: Eliminar datos - deleted: Borrado + deleted: Eliminado demote: Degradar destroyed_msg: Los datos de %{username} están ahora en cola para ser eliminados inminentemente disable: Deshabilitar @@ -116,7 +116,7 @@ es: protocol: Protocolo public: Público push_subscription_expires: Expiración de la suscripción PuSH - redownload: Refrescar avatar + redownload: Refrescar perfil redownloaded_msg: Se actualizó correctamente el perfil de %{username} desde el origen reject: Rechazar rejected_msg: La solicitud de registro de %{username} ha sido rechazada con éxito @@ -187,6 +187,7 @@ es: create_domain_block: Crear Bloqueo de Dominio create_email_domain_block: Crear Bloqueo de Dominio de Correo Electrónico create_ip_block: Crear regla IP + create_relay: Crear Relé create_unavailable_domain: Crear Dominio No Disponible create_user_role: Crear Rol demote_user: Degradar Usuario @@ -198,14 +199,17 @@ es: destroy_email_domain_block: Eliminar Bloqueo de Dominio de Correo Electrónico destroy_instance: Purgar Dominio destroy_ip_block: Eliminar regla IP + destroy_relay: Eliminar Relé destroy_status: Eliminar Publicación destroy_unavailable_domain: Eliminar Dominio No Disponible destroy_user_role: Destruir Rol disable_2fa_user: Deshabilitar 2FA disable_custom_emoji: Deshabilitar Emoji Personalizado + disable_relay: Desactivar Relé disable_sign_in_token_auth_user: Deshabilitar la Autenticación por Token de Correo Electrónico para el Usuario disable_user: Deshabilitar Usuario enable_custom_emoji: Habilitar Emoji Personalizado + enable_relay: Activar Relé enable_sign_in_token_auth_user: Habilitar la Autenticación por Token de Correo Electrónico para el Usuario enable_user: Habilitar Usuario memorialize_account: Transformar en Cuenta Conmemorativa @@ -247,6 +251,7 @@ es: create_domain_block_html: "%{name} bloqueó el dominio %{target}" create_email_domain_block_html: "%{name} bloqueó el dominio de correo electrónico %{target}" create_ip_block_html: "%{name} creó una regla para la IP %{target}" + create_relay_html: "%{name} creó un relé %{target}" create_unavailable_domain_html: "%{name} detuvo las entregas al dominio %{target}" create_user_role_html: "%{name} creó el rol %{target}" demote_user_html: "%{name} degradó al usuario %{target}" @@ -258,14 +263,17 @@ es: destroy_email_domain_block_html: "%{name} desbloqueó el dominio de correo electrónico %{target}" destroy_instance_html: "%{name} purgó el dominio %{target}" destroy_ip_block_html: "%{name} eliminó una regla para la IP %{target}" + destroy_relay_html: "%{name} eliminó el relé %{target}" destroy_status_html: "%{name} eliminó la publicación de %{target}" destroy_unavailable_domain_html: "%{name} reanudó las entregas al dominio %{target}" destroy_user_role_html: "%{name} eliminó el rol %{target}" disable_2fa_user_html: "%{name} desactivó el requisito de dos factores para el usuario %{target}" disable_custom_emoji_html: "%{name} desactivó el emoji %{target}" + disable_relay_html: "%{name} desactivó el relé %{target}" disable_sign_in_token_auth_user_html: "%{name} ha deshabilitado la autenticación por token de correo electrónico para %{target}" disable_user_html: "%{name} deshabilitó el inicio de sesión para el usuario %{target}" enable_custom_emoji_html: "%{name} activó el emoji %{target}" + enable_relay_html: "%{name} activó el relé %{target}" enable_sign_in_token_auth_user_html: "%{name} ha habilitado la autenticación por token de correo electrónico para %{target}" enable_user_html: "%{name} habilitó el inicio de sesión para el usuario %{target}" memorialize_account_html: "%{name} convirtió la cuenta de %{target} en una página in memoriam" @@ -566,7 +574,7 @@ es: '94670856': 3 años new: title: Crear nueva regla IP - no_ip_block_selected: No se han cambiado reglas IP ya que no se ha seleccionado ninguna + no_ip_block_selected: No se han cambiado reglas IP, ya que no se ha seleccionado ninguna title: Reglas IP relationships: title: Relaciones de %{acct} @@ -818,8 +826,10 @@ es: back_to_account: Volver a la cuenta back_to_report: Volver a la página del reporte batch: + add_to_report: 'Añadir al informe #%{id}' remove_from_report: Eliminar del reporte report: Reporte + contents: Contenidos deleted: Eliminado favourites: Favoritos history: Historial de versiones @@ -828,13 +838,17 @@ es: media: title: Multimedia metadata: Metadatos + no_history: Esta publicación no ha sido editada no_status_selected: No se cambió ninguna publicación al no seleccionar ninguna open: Abrir publicación original_status: Publicación original reblogs: Impulsos + replied_to_html: Respondió a %{acct_link} status_changed: Publicación cambiada + status_title: Publicación de @%{name} title: Publicaciones de la cuenta - @%{name} trending: En tendencia + view_publicly: Ver públicamente visibility: Visibilidad with_media: Con multimedia strikes: @@ -910,7 +924,7 @@ es: review: Estado de revisión search: Buscar title: Etiquetas - updated_msg: Hashtags actualizados exitosamente + updated_msg: La configuración de etiquetas se actualizó correctamente title: Administración trends: allow: Permitir @@ -1109,7 +1123,7 @@ es: didnt_get_confirmation: "¿No recibiste un enlace de confirmación?" dont_have_your_security_key: "¿No tienes tu clave de seguridad?" forgot_password: "¿Olvidaste tu contraseña?" - invalid_reset_password_token: El token de reinicio de contraseña es inválido o expiró. Por favor pide uno nuevo. + invalid_reset_password_token: El token de restablecimiento de contraseña no es válido o ha expirado. Por favor solicita uno nuevo. link_to_otp: Introduce un código de dos factores desde tu teléfono o un código de recuperación link_to_webauth: Utilice su dispositivo de clave de seguridad log_in_with: Iniciar sesión con @@ -1258,7 +1272,7 @@ es: '422': content: Verificación de seguridad fallida. ¿Estás bloqueando algunas cookies? title: Verificación de seguridad fallida - '429': Asfixiado + '429': Demasiadas solicitudes '500': content: Lo sentimos, algo ha funcionado mal por nuestra parte. title: Esta página no es correcta @@ -1446,7 +1460,7 @@ es: '604800': 1 semana '86400': 1 día expires_in_prompt: Nunca - generate: Generar + generate: Generar enlace de invitación invalid: Esta invitación no es válida invited_by: 'Fuiste invitado por:' max_uses: @@ -1489,12 +1503,12 @@ es: title: Cancelar suscripición media_attachments: validations: - images_and_video: No se puede adjuntar un video a unapublicación que ya contenga imágenes + images_and_video: No se puede adjuntar un video a una publicación que ya contenga imágenes not_found: Archivos multimedia %{ids} no encontrados, o ya se encuentran adjuntos a otra publicación not_ready: No se pueden adjuntar archivos que no se han terminado de procesar. ¡Inténtalo de nuevo en un momento! too_many: No se pueden adjuntar más de 4 archivos migrations: - acct: username@domain de la nueva cuenta + acct: Movido a cancel: Cancelar redireccionamiento cancel_explanation: Al cancelar el redireccionamiento se reactivará tu cuenta actual, pero no recuperarás los seguidores que hayan sido trasladados a la otra cuenta. cancelled_msg: El redireccionamiento se ha cancelado correctamente. @@ -1729,7 +1743,7 @@ es: migrate: Migración de cuenta notifications: Notificaciones por correo electrónico preferences: Preferencias - profile: Perfil + profile: Perfil público relationships: Siguiendo y seguidores severed_relationships: Relaciones cortadas statuses_cleanup: Eliminación automática de publicaciones @@ -1773,11 +1787,11 @@ es: direct: Las publicaciones que son visibles solo para los usuarios mencionados no pueden fijarse limit: Ya has fijado el número máximo de publicaciones ownership: La publicación de otra persona no puede fijarse - reblog: Un boost no puede fijarse + reblog: Una publicación impulsada no puede fijarse title: "%{name}: «%{quote}»" visibilities: direct: Directa - private: Sólo mostrar a seguidores + private: Solo seguidores private_long: Solo mostrar a tus seguidores public: Pública public_long: Todos pueden ver @@ -1826,8 +1840,8 @@ es: tags: does_not_match_previous_name: no coincide con el nombre anterior themes: - contrast: Alto contraste - default: Mastodon + contrast: Mastodon (alto contraste) + default: Mastodon (oscuro) mastodon-light: Mastodon (claro) system: Automático (usar tema del sistema) time: @@ -1847,7 +1861,7 @@ es: edit: Editar enabled: La autenticación de dos factores está activada enabled_success: Verificación de dos factores activada exitosamente - generate_recovery_codes: generar códigos de recuperación + generate_recovery_codes: Generar códigos de recuperación lost_recovery_codes: Los códigos de recuperación te permiten obtener acceso a tu cuenta si pierdes tu teléfono. Si has perdido tus códigos de recuperación, puedes regenerarlos aquí. Tus viejos códigos de recuperación se harán inválidos. methods: Métodos de autenticación de doble factor otp: Aplicación de autenticación diff --git a/config/locales/et.yml b/config/locales/et.yml index f8a4f7f69e..40db2eede0 100644 --- a/config/locales/et.yml +++ b/config/locales/et.yml @@ -833,7 +833,6 @@ et: original_status: Algne postitus reblogs: Jagamised status_changed: Muudetud postitus - title: Konto postitused - @%{name} trending: Populaarne visibility: Nähtavus with_media: Meediaga diff --git a/config/locales/eu.yml b/config/locales/eu.yml index a764e88bac..dc064ebc7b 100644 --- a/config/locales/eu.yml +++ b/config/locales/eu.yml @@ -793,7 +793,6 @@ eu: original_status: Jatorrizko bidalketa reblogs: Bultzadak status_changed: Bidalketa aldatuta - title: Kontuaren bidalketak - @%{name} trending: Joera visibility: Ikusgaitasuna with_media: Multimediarekin diff --git a/config/locales/fa.yml b/config/locales/fa.yml index 38daf70d29..7cb0714c28 100644 --- a/config/locales/fa.yml +++ b/config/locales/fa.yml @@ -741,7 +741,6 @@ fa: original_status: فرستهٔ اصلی reblogs: تقویت‌ها status_changed: فرسته تغییر کرد - title: "@%{name} - نوشته‌های حساب" trending: پرطرفدار visibility: نمایانی with_media: دارای عکس یا ویدیو diff --git a/config/locales/fi.yml b/config/locales/fi.yml index efdfdfed04..d7755d23b8 100644 --- a/config/locales/fi.yml +++ b/config/locales/fi.yml @@ -826,8 +826,10 @@ fi: back_to_account: Takaisin tilin sivulle back_to_report: Takaisin raporttisivulle batch: + add_to_report: Lisää raporttiin nro %{id} remove_from_report: Poista raportista report: Raportti + contents: Sisältö deleted: Poistettu favourites: Suosikit history: Versiohistoria @@ -836,13 +838,17 @@ fi: media: title: Media metadata: Metadata + no_history: Tätä julkaisua ei ole muokattu no_status_selected: Julkaisuja ei muutettu, koska yhtään ei ollut valittuna open: Avaa julkaisu original_status: Alkuperäinen julkaisu reblogs: Edelleen jako + replied_to_html: Vastaus käyttäjälle %{acct_link} status_changed: Julkaisua muutettu - title: Tilin tilat - @%{name} + status_title: Julkaisu käyttäjältä @%{name} + title: Tilin julkaisut - @%{name} trending: Suosituttua + view_publicly: Näytä julkisesti visibility: Näkyvyys with_media: Sisältää mediaa strikes: diff --git a/config/locales/fo.yml b/config/locales/fo.yml index 8dab61c267..502c027b5d 100644 --- a/config/locales/fo.yml +++ b/config/locales/fo.yml @@ -826,8 +826,10 @@ fo: back_to_account: Aftur til kontusíðu back_to_report: Aftur til meldingarsíðu batch: + add_to_report: 'Legg afturat melding #%{id}' remove_from_report: Strika frá melding report: Melding + contents: Innihald deleted: Strikað favourites: Dámdir postar history: Útgávusøga @@ -836,13 +838,17 @@ fo: media: title: Miðlar metadata: Metadátur + no_history: Hesin posturin er ikki broyttur no_status_selected: Eingir postar vóru broyttir, tí eingir vóru valdir open: Lat post upp original_status: Upprunapostur reblogs: Endurbloggar + replied_to_html: Svaraði %{acct_link} status_changed: Postur broyttur - title: Postar hjá kontu - @%{name} + status_title: Postar hjá @%{name} + title: Kontupostar - @%{name} trending: Vælumtókt + view_publicly: Vís fyri øllum visibility: Sýni with_media: Við miðli strikes: diff --git a/config/locales/fr-CA.yml b/config/locales/fr-CA.yml index bb0501d0e3..9c2bf3398e 100644 --- a/config/locales/fr-CA.yml +++ b/config/locales/fr-CA.yml @@ -836,7 +836,6 @@ fr-CA: original_status: Message original reblogs: Partages status_changed: Publication modifiée - title: Messages du compte - @%{name} trending: Tendances visibility: Visibilité with_media: Avec médias diff --git a/config/locales/fr.yml b/config/locales/fr.yml index 0c35dea62a..650147eb5d 100644 --- a/config/locales/fr.yml +++ b/config/locales/fr.yml @@ -836,7 +836,6 @@ fr: original_status: Message original reblogs: Partages status_changed: Publication modifiée - title: Messages du compte - @%{name} trending: Tendances visibility: Visibilité with_media: Avec médias diff --git a/config/locales/fy.yml b/config/locales/fy.yml index 8a4f519e0c..24be51d9d7 100644 --- a/config/locales/fy.yml +++ b/config/locales/fy.yml @@ -833,7 +833,6 @@ fy: original_status: Oarspronklik berjocht reblogs: Boosts status_changed: Berjocht wizige - title: Accountberjochten - @%{name} trending: Trending visibility: Sichtberheid with_media: Mei media diff --git a/config/locales/ga.yml b/config/locales/ga.yml index 67461f3c2a..deb9986691 100644 --- a/config/locales/ga.yml +++ b/config/locales/ga.yml @@ -196,6 +196,7 @@ ga: create_domain_block: Cruthaigh Bloc Fearainn create_email_domain_block: Cruthaigh Bloc Fearainn Ríomhphoist create_ip_block: Cruthaigh riail IP + create_relay: Cruthaigh Leaschraolacháin create_unavailable_domain: Cruthaigh Fearann ​​Gan Fáil create_user_role: Cruthaigh Ról demote_user: Ísligh úsáideoir @@ -207,14 +208,17 @@ ga: destroy_email_domain_block: Scrios Bloc Fearainn Ríomhphoist destroy_instance: Fearann ​​Purge destroy_ip_block: Scrios riail IP + destroy_relay: Scrios Leaschraolacháin destroy_status: Scrios Postáil destroy_unavailable_domain: Scrios Fearann ​​Gan Fáil destroy_user_role: Scrios ról disable_2fa_user: Díchumasaigh 2FA disable_custom_emoji: Díchumasaigh Emoji Saincheaptha + disable_relay: Díchumasaigh Leaschraolacháin disable_sign_in_token_auth_user: Díchumasaigh Fíordheimhniú Comhartha Ríomhphoist don Úsáideoir disable_user: Díchumasaigh Úsáideoir enable_custom_emoji: Cumasaigh Emoji Saincheaptha + enable_relay: Cumasaigh Leaschraolacháin enable_sign_in_token_auth_user: Cumasaigh Fíordheimhniú Comhartha Ríomhphoist don Úsáideoir enable_user: Cumasaigh Úsáideoir memorialize_account: Cuntas Cuimhneacháin @@ -256,6 +260,7 @@ ga: create_domain_block_html: "%{name} fearann ​​bactha %{target}" create_email_domain_block_html: Chuir %{name} fearann ​​ríomhphoist bactha %{target} create_ip_block_html: Chruthaigh %{name} riail don IP %{target} + create_relay_html: Chruthaigh %{name} athsheoladh %{target} create_unavailable_domain_html: Chuir %{name} deireadh leis an seachadadh chuig fearann ​​%{target} create_user_role_html: Chruthaigh %{name} %{target} ról demote_user_html: "%{name} úsáideoir scriosta %{target}" @@ -267,14 +272,17 @@ ga: destroy_email_domain_block_html: "%{name} fearann ​​ríomhphoist díchoiscthe %{target}" destroy_instance_html: Glanadh %{name} fearann ​​%{target} destroy_ip_block_html: "%{name} scriosta riail le haghaidh IP %{target}" + destroy_relay_html: Scrios %{name} an athsheoladh %{target} destroy_status_html: Bhain %{name} postáil le %{target} destroy_unavailable_domain_html: D'athchrom %{name} ar an seachadadh chuig fearann ​​%{target} destroy_user_role_html: Scrios %{name} ról %{target} disable_2fa_user_html: Dhíchumasaigh %{name} riachtanas dhá fhachtóir don úsáideoir %{target} disable_custom_emoji_html: Dhíchumasaigh %{name} emoji %{target} + disable_relay_html: Dhíchumasaigh %{name} an athsheoladh %{target} disable_sign_in_token_auth_user_html: Dhíchumasaigh %{name} fíordheimhniú comhartha ríomhphoist le haghaidh %{target} disable_user_html: "%{name} logáil isteach díchumasaithe d'úsáideoir %{target}" enable_custom_emoji_html: "%{name} emoji cumasaithe %{target}" + enable_relay_html: Chuir %{name} an sealaíocht %{target} ar chumas enable_sign_in_token_auth_user_html: Chuir %{name} fíordheimhniú comhartha ríomhphoist ar chumas %{target} enable_user_html: "%{name} logáil isteach cumasaithe don úsáideoir %{target}" memorialize_account_html: Rinne %{name} cuntas %{target} a iompú ina leathanach cuimhneacháin @@ -860,8 +868,10 @@ ga: back_to_account: Ar ais go leathanach cuntais back_to_report: Ar ais go leathanach tuairisce batch: + add_to_report: 'Cuir leis an tuairisc # %{id}' remove_from_report: Bain den tuairisc report: Tuairisc + contents: Ábhar deleted: Scriosta favourites: Toghanna history: Stair leagan @@ -870,13 +880,17 @@ ga: media: title: Meáin metadata: Meiteashonraí + no_history: Níl an postáil seo curtha in eagar no_status_selected: Níor athraíodh aon phostáil mar níor roghnaíodh ceann ar bith open: Oscail postáil original_status: Bunphostáil reblogs: Athbhlaganna + replied_to_html: D'fhreagair %{acct_link} status_changed: Athraíodh postáil - title: Poist chuntais - @%{name} + status_title: Postáil le @ %{name} + title: Postálacha cuntais - @%{name} trending: Ag treochtáil + view_publicly: Féach go poiblí visibility: Infheictheacht with_media: Le meáin strikes: diff --git a/config/locales/gd.yml b/config/locales/gd.yml index 89198bd514..78f4516cfc 100644 --- a/config/locales/gd.yml +++ b/config/locales/gd.yml @@ -861,7 +861,6 @@ gd: original_status: Am post tùsail reblogs: Brosnachaidhean status_changed: Post air atharrachadh - title: Postaichean a’ chunntais - @%{name} trending: A’ treandadh visibility: Faicsinneachd with_media: Le meadhanan riutha diff --git a/config/locales/gl.yml b/config/locales/gl.yml index 0f3420a7f3..feda673621 100644 --- a/config/locales/gl.yml +++ b/config/locales/gl.yml @@ -826,8 +826,10 @@ gl: back_to_account: Volver a páxina da conta back_to_report: Volver a denuncias batch: + add_to_report: 'Engadir á denuncia #%{id}' remove_from_report: Eliminar da denuncia report: Denuncia + contents: Contidos deleted: Eliminado favourites: Favoritas history: Historial de versións @@ -836,13 +838,17 @@ gl: media: title: Medios metadata: Metadatos + no_history: Esta publicación foi editada no_status_selected: Non se cambiou ningunha publicación xa que ningunha foi seleccionada open: Abrir publicación original_status: Publicación orixinal reblogs: Promocións + replied_to_html: Respondeu a %{acct_link} status_changed: Publicación editada + status_title: Publicación de @%{name} title: Publicacións da conta - @%{name} trending: Popular + view_publicly: Ver publicamente visibility: Visibilidade with_media: con medios strikes: diff --git a/config/locales/he.yml b/config/locales/he.yml index 59dc09799d..5243cf4768 100644 --- a/config/locales/he.yml +++ b/config/locales/he.yml @@ -193,6 +193,7 @@ he: create_domain_block: יצירת דומיין חסום create_email_domain_block: יצירת חסימת דומיין דוא"ל create_ip_block: יצירת כלל IP + create_relay: יצירת ממסר create_unavailable_domain: יצירת דומיין בלתי זמין create_user_role: יצירת תפקיד demote_user: הורדת משתמש בדרגה @@ -204,14 +205,17 @@ he: destroy_email_domain_block: מחיקת חסימת דומיין דוא"ל destroy_instance: טיהור דומיין destroy_ip_block: מחיקת כלל IP + destroy_relay: מחיקת ממסר destroy_status: מחיקת הודעה destroy_unavailable_domain: מחיקת דומיין בלתי זמין destroy_user_role: מחיקת תפקיד disable_2fa_user: השעיית זיהוי דו-גורמי disable_custom_emoji: השעיית אמוג'י מיוחד + disable_relay: השבתת ממסר disable_sign_in_token_auth_user: השעיית אסימון הזדהות בדוא"ל של משתמש disable_user: השעיית משתמש enable_custom_emoji: הפעלת אמוג'י מיוחד + enable_relay: החייאת ממסר enable_sign_in_token_auth_user: הפעלת אסימון הזדהות בדוא"ל של משתמש enable_user: אפשור משתמש memorialize_account: הנצחת חשבון @@ -253,6 +257,7 @@ he: create_domain_block_html: "%{name} חסם/ה את הדומיין %{target}" create_email_domain_block_html: '%{name} חסם/ה את דומיין הדוא"ל %{target}' create_ip_block_html: "%{name} יצר/ה כלל עבור IP %{target}" + create_relay_html: "%{name} יצרו את הממסר %{target}" create_unavailable_domain_html: "%{name} הפסיק/ה משלוח לדומיין %{target}" create_user_role_html: "%{name} יצר את התפקיד של %{target}" demote_user_html: "%{name} הוריד/ה בדרגה את המשתמש %{target}" @@ -264,14 +269,17 @@ he: destroy_email_domain_block_html: '%{name} הסיר/ה חסימה מדומיין הדוא"ל %{target}' destroy_instance_html: "%{name} טיהר/ה את הדומיין %{target}" destroy_ip_block_html: "%{name} מחק/ה את הכלל עבור IP %{target}" + destroy_relay_html: "%{name} מחקו את הממסר %{target}" destroy_status_html: ההודעה של %{target} הוסרה ע"י %{name} destroy_unavailable_domain_html: "%{name} התחיל/ה מחדש משלוח לדומיין %{target}" destroy_user_role_html: "%{name} ביטל את התפקיד של %{target}" disable_2fa_user_html: "%{name} ביטל/ה את הדרישה לאימות דו-גורמי למשתמש %{target}" disable_custom_emoji_html: "%{name} השבית/ה את האמוג'י %{target}" + disable_relay_html: "%{name} השביתו את הממסר %{target}" disable_sign_in_token_auth_user_html: '%{name} השבית/ה את האימות בעזרת אסימון דוא"ל עבור %{target}' disable_user_html: "%{name} חסם/ה כניסה מהמשתמש/ת %{target}" enable_custom_emoji_html: "%{name} אפשר/ה את האמוג'י %{target}" + enable_relay_html: "%{name} החיו את הממסר %{target}" enable_sign_in_token_auth_user_html: '%{name} אפשר/ה אימות בעזרת אסימון דוא"ל עבור %{target}' enable_user_html: "%{name} אפשר/ה כניסה עבור המשתמש %{target}" memorialize_account_html: "%{name} הפך/ה את חשבונו של %{target} לדף הנצחה" @@ -846,8 +854,10 @@ he: back_to_account: חזרה לדף החשבון back_to_report: חזרה לעמוד הדיווח batch: + add_to_report: להוסיף לדו"ח מספר %{id} remove_from_report: הסרה מהדיווח report: דווח + contents: תוכן deleted: מחוקים favourites: חיבובים history: היסטורית גרסאות @@ -856,13 +866,17 @@ he: media: title: מדיה metadata: נתוני-מטא + no_history: הודעה זו לא נערכה no_status_selected: לא בוצעו שינויים בהודעות שכן לא נבחרו כאלו open: פתח הודעה original_status: הודעה מקורית reblogs: שיתופים + replied_to_html: בתגובה לחשבון %{acct_link} status_changed: הודעה שונתה - title: הודעות החשבון - @%{name} + status_title: פרסום מאת @%{name} + title: פרסומי החשבון - @%{name} trending: נושאים חמים + view_publicly: צפיה בפומבי visibility: נראות with_media: עם מדיה strikes: diff --git a/config/locales/hu.yml b/config/locales/hu.yml index 56d41daf86..f23711d403 100644 --- a/config/locales/hu.yml +++ b/config/locales/hu.yml @@ -841,7 +841,6 @@ hu: original_status: Eredeti bejegyzés reblogs: Megosztások status_changed: A bejegyzés megváltozott - title: Fiók bejegyzései - @%{name} trending: Felkapott visibility: Láthatóság with_media: Médiával diff --git a/config/locales/hy.yml b/config/locales/hy.yml index d8cf2a97ba..3b4aaf3629 100644 --- a/config/locales/hy.yml +++ b/config/locales/hy.yml @@ -402,7 +402,6 @@ hy: deleted: Ջնջված է media: title: Մեդիա - title: Օգտատիրոջ գրառումները - @%{name} with_media: Մեդիայի հետ tags: review: Վերանայել գրառումը diff --git a/config/locales/ia.yml b/config/locales/ia.yml index 1398ae51d4..54401b1c5a 100644 --- a/config/locales/ia.yml +++ b/config/locales/ia.yml @@ -187,6 +187,7 @@ ia: create_domain_block: Crear blocada de dominio create_email_domain_block: Crear blocada de dominio de e-mail create_ip_block: Crear un regula IP + create_relay: Crear repetitor create_unavailable_domain: Crear dominio indisponibile create_user_role: Crear un rolo demote_user: Degradar usator @@ -198,14 +199,17 @@ ia: destroy_email_domain_block: Deler blocada de dominio de e-mail destroy_instance: Purgar dominio destroy_ip_block: Deler le regula IP + destroy_relay: Deler repetitor destroy_status: Deler message destroy_unavailable_domain: Deler dominio indisponibile destroy_user_role: Destruer rolo disable_2fa_user: Disactivar A2F disable_custom_emoji: Disactivar emoji personalisate + disable_relay: Disactivar repetitor disable_sign_in_token_auth_user: Disactivar le authentication per token de e-mail pro le usator disable_user: Disactivar le usator enable_custom_emoji: Activar emoji personalisate + enable_relay: Activar repetitor enable_sign_in_token_auth_user: Activar le authentication per token de e-mail pro le usator enable_user: Activar le usator memorialize_account: Converter conto in memorial @@ -247,6 +251,7 @@ ia: create_domain_block_html: "%{name} blocava dominio %{target}" create_email_domain_block_html: "%{name} blocava le dominio de e-mail %{target}" create_ip_block_html: "%{name} creava regula pro IP %{target}" + create_relay_html: "%{name} ha create un repetitor %{target}" create_unavailable_domain_html: "%{name} stoppava livration al dominio %{target}" create_user_role_html: "%{name} creava rolo de %{target}" demote_user_html: "%{name} degradava usator %{target}" @@ -258,14 +263,17 @@ ia: destroy_email_domain_block_html: "%{name} disblocava le dominio de e-mail %{target}" destroy_instance_html: "%{name} purgava le dominio %{target}" destroy_ip_block_html: "%{name} deleva le regula pro IP %{target}" + destroy_relay_html: "%{name} ha delite le repetitor %{target}" destroy_status_html: "%{name} removeva un message de %{target}" destroy_unavailable_domain_html: "%{name} reprendeva le livration al dominio %{target}" destroy_user_role_html: "%{name} deleva le rolo %{target}" disable_2fa_user_html: "%{name} disactivava le authentication a duo factores pro le usator %{target}" disable_custom_emoji_html: "%{name} disactivava le emoji %{target}" + disable_relay_html: "%{name} ha disactivate le repetitor %{target}" disable_sign_in_token_auth_user_html: "%{name} disactivava le authentication per token de e-mail pro %{target}" disable_user_html: "%{name} disactivava le apertura de session pro le usator %{target}" enable_custom_emoji_html: "%{name} activava le emoji %{target}" + enable_relay_html: "%{name} ha activate le repetitor %{target}" enable_sign_in_token_auth_user_html: "%{name} activava le authentication per token de e-mail pro %{target}" enable_user_html: "%{name} activava le apertura de session pro le usator %{target}" memorialize_account_html: "%{name} converteva le conto de %{target} in un pagina commemorative" @@ -818,8 +826,10 @@ ia: back_to_account: Retornar al pagina del conto back_to_report: Retro al pagina de reporto batch: + add_to_report: 'Adder al reporto #%{id}' remove_from_report: Remover del reporto report: Reporto + contents: Contento deleted: Delite favourites: Favorites history: Historia de versiones @@ -828,13 +838,17 @@ ia: media: title: Multimedia metadata: Metadatos + no_history: Iste message non ha essite modificate no_status_selected: Necun message ha essite cambiate perque necun ha essite seligite open: Aperir message original_status: Message original reblogs: Republicationes + replied_to_html: Respondite a %{acct_link} status_changed: Message cambiate - title: Messages del conto - @%{name} + status_title: Message de @%{name} + title: Messages del conto – @%{name} trending: Tendentias + view_publicly: Vider publicamente visibility: Visibilitate with_media: Con multimedia strikes: @@ -1118,7 +1132,7 @@ ia: migrate_account: Migrar a un altere conto migrate_account_html: Si tu vole rediriger iste conto a un altere, tu pote configurar lo hic. or_log_in_with: O aperi session con - privacy_policy_agreement_html: Io ha legite e accepta le politica de confidentialitate + privacy_policy_agreement_html: Io ha legite e accepta le politica de confidentialitate progress: confirm: Confirmar e-mail details: Tu detalios @@ -1166,8 +1180,11 @@ ia: use_security_key: Usar clave de securitate author_attribution: example_title: Texto de exemplo + hint_html: Scribe tu articulos de novas o de blog foras de Mastodon? Controla le maniera in que tu recipe attribution quando on los condivide sur Mastodon. + instructions: 'Assecura te que iste codice appare in le HTML de tu articulo:' more_from_html: Plus de %{name} s_blog: Blog de %{name} + then_instructions: Postea, adde le nomine de dominio del publication in le campo sequente. title: Attribution de autor challenge: confirm: Continuar diff --git a/config/locales/id.yml b/config/locales/id.yml index 9c31daf420..34b690828d 100644 --- a/config/locales/id.yml +++ b/config/locales/id.yml @@ -711,7 +711,6 @@ id: original_status: Kiriman asli reblogs: Reblog status_changed: Kiriman diubah - title: Status akun - @%{name} trending: Sedang tren visibility: Visibilitas with_media: Dengan media diff --git a/config/locales/ie.yml b/config/locales/ie.yml index d7df83ef69..f006f2c8ad 100644 --- a/config/locales/ie.yml +++ b/config/locales/ie.yml @@ -791,7 +791,6 @@ ie: original_status: Original posta reblogs: Boosts status_changed: Posta modificat - title: Postas del conto - @%{name} trending: Populari visibility: Visibilitá with_media: Con medie diff --git a/config/locales/io.yml b/config/locales/io.yml index 1ff5d98bf2..83c92484ff 100644 --- a/config/locales/io.yml +++ b/config/locales/io.yml @@ -779,7 +779,6 @@ io: original_status: Originala posto reblogs: Dissemi status_changed: Posto chanjita - title: Kontoposti - @%{name} trending: Populara visibility: Videbleso with_media: Kun medii diff --git a/config/locales/is.yml b/config/locales/is.yml index 9ba29f2af0..cad01257fd 100644 --- a/config/locales/is.yml +++ b/config/locales/is.yml @@ -828,8 +828,10 @@ is: back_to_account: Fara aftur á síðu notandaaðgangsins back_to_report: Til baka á kærusíðu batch: + add_to_report: 'Bæta við skýrslu #%{id}' remove_from_report: Fjarlægja úr kæru report: Kæra + contents: Efni deleted: Eytt favourites: Eftirlæti history: Útgáfuferill @@ -838,13 +840,17 @@ is: media: title: Myndefni metadata: Lýsigögn + no_history: Færslunni hefur ekki verið breytt no_status_selected: Engum færslum var breytt þar sem engar voru valdar open: Opna færslu original_status: Upprunaleg færsla reblogs: Endurbirtingar + replied_to_html: Svaraði til %{acct_link} status_changed: Færslu breytt - title: Færslur notandaaðgangs - @%{name} + status_title: Færsla frá @%{name} + title: Færslur notanda - @%{name} trending: Vinsælt + view_publicly: Skoða opinberlega visibility: Sýnileiki with_media: Með myndefni strikes: diff --git a/config/locales/it.yml b/config/locales/it.yml index 08e224ad94..4c083fd006 100644 --- a/config/locales/it.yml +++ b/config/locales/it.yml @@ -818,8 +818,10 @@ it: back_to_account: Torna alla pagina dell'account back_to_report: Torna alla pagina del report batch: + add_to_report: 'Aggiungi alla segnalazione #%{id}' remove_from_report: Rimuovi dal report report: Rapporto + contents: Contenuti deleted: Cancellato favourites: Preferiti history: Cronologia delle versioni @@ -828,13 +830,17 @@ it: media: title: Media metadata: Metadati + no_history: Questo post non è stato modificato no_status_selected: Nessun status è stato modificato perché nessuno era stato selezionato open: Apri il post original_status: Post originale reblogs: Condivisioni + replied_to_html: Risposta a %{acct_link} status_changed: Post modificato - title: Gli status dell'account - @%{name} + status_title: Post di @%{name} + title: Post dell'account - @%{name} trending: Di tendenza + view_publicly: Visualizza pubblicamente visibility: Visibilità with_media: con media strikes: diff --git a/config/locales/ja.yml b/config/locales/ja.yml index 76152c3744..810de2b227 100644 --- a/config/locales/ja.yml +++ b/config/locales/ja.yml @@ -184,6 +184,7 @@ ja: create_domain_block: ドメインブロックを作成 create_email_domain_block: メールドメインブロックを作成 create_ip_block: IPルールを作成 + create_relay: リレーの追加 create_unavailable_domain: 配送できないドメインを作成 create_user_role: ロールを作成 demote_user: ユーザーを降格 @@ -195,14 +196,17 @@ ja: destroy_email_domain_block: メールドメインブロックを削除 destroy_instance: ドメインをブロックする destroy_ip_block: IPルールを削除 + destroy_relay: リレーの削除 destroy_status: 投稿を削除 destroy_unavailable_domain: 配送できないドメインを削除 destroy_user_role: ロールを削除 disable_2fa_user: 二要素認証を無効化 disable_custom_emoji: カスタム絵文字を無効化 + disable_relay: リレーの無効化 disable_sign_in_token_auth_user: ユーザのメールトークン認証を無効化 disable_user: ユーザーを無効化 enable_custom_emoji: カスタム絵文字を有効化 + enable_relay: リレーの有効化 enable_sign_in_token_auth_user: ユーザのメールトークン認証を有効化 enable_user: ユーザーを有効化 memorialize_account: 追悼アカウント化 @@ -244,6 +248,7 @@ ja: create_domain_block_html: "%{name}さんがドメイン %{target}をブロックしました" create_email_domain_block_html: "%{name} さんがメールドメイン %{target} をブロックしました" create_ip_block_html: "%{name}さんがIP %{target}のルールを作成しました" + create_relay_html: "%{name} さんがリレー %{target} を追加しました" create_unavailable_domain_html: "%{name}がドメイン %{target}への配送を停止しました" create_user_role_html: "%{name}さんがロール『%{target}』を作成しました" demote_user_html: "%{name}さんが%{target}さんを降格しました" @@ -252,17 +257,20 @@ ja: destroy_custom_emoji_html: "%{name}さんがカスタム絵文字『%{target}』を削除しました" destroy_domain_allow_html: "%{name}さんが%{target}の連合許可を外しました" destroy_domain_block_html: "%{name}さんがドメイン %{target}のブロックを外しました" - destroy_email_domain_block_html: "%{name} がメールドメイン %{target} のブロックを外しました" + destroy_email_domain_block_html: "%{name} さんがメールドメイン %{target} のブロックを外しました" destroy_instance_html: "%{name}さんがドメイン %{target}をブロックしました" destroy_ip_block_html: "%{name}さんが IP %{target}のルールを削除しました" + destroy_relay_html: "%{name} さんがリレー %{target} を削除しました" destroy_status_html: "%{name}さんが%{target}さんの投稿を削除しました" destroy_unavailable_domain_html: "%{name}がドメイン %{target}への配送を再開しました" destroy_user_role_html: "%{name}さんがロール『%{target}』を削除しました" disable_2fa_user_html: "%{name}さんが%{target}さんの二要素認証を無効化しました" disable_custom_emoji_html: "%{name}さんがカスタム絵文字 %{target}を無効化しました" + disable_relay_html: "%{name} さんがリレー %{target} を無効にしました" disable_sign_in_token_auth_user_html: "%{name} が %{target} のメールトークン認証を無効化しました" disable_user_html: "%{name}さんが%{target}さんのログインを無効化しました" enable_custom_emoji_html: "%{name}さんがカスタム絵文字 %{target}を有効化しました" + enable_relay_html: "%{name} さんがリレー %{target} を有効にしました" enable_sign_in_token_auth_user_html: "%{name} が %{target} のメールトークン認証を有効化しました" enable_user_html: "%{name}さんが%{target}さんのログインを有効化しました" memorialize_account_html: "%{name}さんが%{target}さんを追悼アカウントページに登録しました" @@ -804,8 +812,10 @@ ja: back_to_account: アカウントページに戻る back_to_report: 通報ページに戻る batch: + add_to_report: 'レポート #%{id} に追加' remove_from_report: 通報から削除 report: 通報 + contents: 投稿内容 deleted: 削除済み favourites: お気に入り history: 更新履歴 @@ -814,13 +824,17 @@ ja: media: title: メディア metadata: メタデータ + no_history: この投稿は編集されていません no_status_selected: 何も選択されていないため、変更されていません open: 投稿を開く original_status: オリジナルの投稿 reblogs: ブースト + replied_to_html: "%{acct_link}さんへの返信" status_changed: 投稿を変更しました + status_title: "@%{name} の投稿" title: 投稿一覧 - @%{name} trending: トレンド + view_publicly: 元の投稿を開く visibility: 公開範囲 with_media: メディアあり strikes: diff --git a/config/locales/ka.yml b/config/locales/ka.yml index 93f7a39dc3..f3178be8d3 100644 --- a/config/locales/ka.yml +++ b/config/locales/ka.yml @@ -190,7 +190,6 @@ ka: media: title: მედია no_status_selected: სატუსები არ შეცვლილა, რადგან არცერთი არ მონიშნულა - title: ანგარიშის სტატუსები - @%{name} with_media: მედიით title: ადმინისტრაცია admin_mailer: diff --git a/config/locales/kab.yml b/config/locales/kab.yml index c74540cfbf..1f5c5ded79 100644 --- a/config/locales/kab.yml +++ b/config/locales/kab.yml @@ -419,7 +419,6 @@ kab: media: title: Amidya open: Ldi tasuffeɣt - title: Tisuffaɣ n umiḍan - @%{name} trending: Ayen mucaɛen visibility: Abani with_media: S umidya diff --git a/config/locales/kk.yml b/config/locales/kk.yml index 4b9cef245e..7ab33b3134 100644 --- a/config/locales/kk.yml +++ b/config/locales/kk.yml @@ -285,7 +285,6 @@ kk: media: title: Медиa no_status_selected: Бірде-бір статус өзгерген жоқ, себебі ештеңе таңдалмады - title: Аккаунт статустары - @%{name} with_media: Медиамен tags: review: Статусты көрсету diff --git a/config/locales/ko.yml b/config/locales/ko.yml index 36a13397d0..3394433758 100644 --- a/config/locales/ko.yml +++ b/config/locales/ko.yml @@ -814,8 +814,10 @@ ko: back_to_account: 계정으로 돌아가기 back_to_report: 신고 페이지로 돌아가기 batch: + add_to_report: '신고 #%{id}에 추가' remove_from_report: 신고에서 제거 report: 신고 + contents: 내용 deleted: 삭제됨 favourites: 좋아요 history: 버전 이력 @@ -824,13 +826,17 @@ ko: media: title: 미디어 metadata: 메타데이터 + no_history: 이 게시물은 수정되지 않았습니다 no_status_selected: 아무 것도 선택 되지 않아 어떤 게시물도 바뀌지 않았습니다 open: 게시물 열기 original_status: 원본 게시물 reblogs: 리블로그 + replied_to_html: "%{acct_link} 님에게 답장" status_changed: 게시물 변경됨 + status_title: "@%{name} 님의 게시물" title: 계정 게시물 - @%{name} trending: 유행 중 + view_publicly: 공개시점으로 보기 visibility: 공개 설정 with_media: 미디어 있음 strikes: diff --git a/config/locales/ku.yml b/config/locales/ku.yml index 54188d2514..5337610992 100644 --- a/config/locales/ku.yml +++ b/config/locales/ku.yml @@ -720,7 +720,6 @@ ku: original_status: Şandiyê resen reblogs: Ji nû ve nivîsandin status_changed: Şandî hate guhertin - title: Şandiyên ajimêr - @%{name} trending: Rojev visibility: Xuyabarî with_media: Bi medya yê re diff --git a/config/locales/lad.yml b/config/locales/lad.yml index 3b33888c71..2612ae2131 100644 --- a/config/locales/lad.yml +++ b/config/locales/lad.yml @@ -825,7 +825,6 @@ lad: original_status: Publikasyon orijinala reblogs: Repartajasyones status_changed: Publikasyon trokada - title: Publikasyones del kuento - @%{name} trending: Trendes visibility: Vizivilita with_media: Kon multimedia diff --git a/config/locales/lt.yml b/config/locales/lt.yml index 3519cb5b32..65bd4456ae 100644 --- a/config/locales/lt.yml +++ b/config/locales/lt.yml @@ -589,7 +589,9 @@ lt: back_to_account: Grįžti į paskyros puslapį back_to_report: Grįžti į ataskaitos puslapį batch: + add_to_report: 'Pridėti į ataskaitą #%{id}' remove_from_report: Pašalinti iš ataskaitos + contents: Turinys deleted: Ištrinta favourites: Mėgstami history: Versijų istorija @@ -598,11 +600,15 @@ lt: media: title: Medija metadata: Metaduomenys + no_history: Šis įrašas nebuvo redaguotas no_status_selected: Jokie įrašai nebuvo pakeisti, nes nė vienas buvo pasirinktas open: Atidaryti įrašą original_status: Originalus įrašas - title: Paskyros statusai - @%{name} + replied_to_html: Atsakyta į %{acct_link} + status_title: Paskelbė @%{name} + title: Paskyros įrašai – @%{name} trending: Tendencinga + view_publicly: Peržiūrėti viešai with_media: Su medija system_checks: database_schema_check: diff --git a/config/locales/lv.yml b/config/locales/lv.yml index 33b357b837..1ced1bb7d0 100644 --- a/config/locales/lv.yml +++ b/config/locales/lv.yml @@ -830,7 +830,6 @@ lv: original_status: Oriģinālā ziņa reblogs: Reblogi status_changed: Ziņa mainīta - title: Konta ziņas - @%{name} trending: Aktuāli visibility: Redzamība with_media: Ar multividi diff --git a/config/locales/ms.yml b/config/locales/ms.yml index 76f914dd16..948ad56a54 100644 --- a/config/locales/ms.yml +++ b/config/locales/ms.yml @@ -768,7 +768,6 @@ ms: original_status: Hantaran asal reblogs: Ulang siar status_changed: Hantaran diubah - title: Hantaran akaun - @%{name} trending: Sohor kini visibility: Visibiliti with_media: Dengan media diff --git a/config/locales/my.yml b/config/locales/my.yml index b238abb051..4428843855 100644 --- a/config/locales/my.yml +++ b/config/locales/my.yml @@ -764,7 +764,6 @@ my: original_status: မူရင်းပို့စ် reblogs: Reblog များ status_changed: ပို့စ်ပြောင်းပြီးပါပြီ - title: "@%{name} - အကောင့်ပို့စ်များ" trending: လက်ရှိခေတ်စားနေခြင်း visibility: မြင်နိုင်မှု with_media: မီဒီယာနှင့်အတူ diff --git a/config/locales/nl.yml b/config/locales/nl.yml index d4a88b3bea..048214eca3 100644 --- a/config/locales/nl.yml +++ b/config/locales/nl.yml @@ -818,8 +818,10 @@ nl: back_to_account: Terug naar accountpagina back_to_report: Terug naar de rapportage batch: + add_to_report: 'Toevoegen aan rapport #%{id}' remove_from_report: Uit de rapportage verwijderen report: Rapportage + contents: Inhoud deleted: Verwijderd favourites: Favorieten history: Versiegeschiedenis @@ -828,12 +830,14 @@ nl: media: title: Media metadata: Metagegevens + no_history: Dit bericht is niet bewerkt no_status_selected: Er werden geen berichten gewijzigd, omdat er geen enkele werd geselecteerd open: Bericht tonen original_status: Oorspronkelijk bericht reblogs: Boosts status_changed: Bericht veranderd - title: Berichten van account - @%{name} + status_title: Bericht van @%{name} + title: Accountberichten - @%{name} trending: Trending visibility: Zichtbaarheid with_media: Met media diff --git a/config/locales/nn.yml b/config/locales/nn.yml index e04c0168f2..dbb8b6c693 100644 --- a/config/locales/nn.yml +++ b/config/locales/nn.yml @@ -826,8 +826,10 @@ nn: back_to_account: Tilbake til kontosida back_to_report: Attende til rapporteringssida batch: + add_to_report: 'Legg til rapport #%{id}' remove_from_report: Fjern fra rapport report: Rapport + contents: Innhald deleted: Sletta favourites: Favorittar history: Versjonshistorikk @@ -836,13 +838,17 @@ nn: media: title: Media metadata: Metadata + no_history: Dette innlegget har ikkje blitt redigert no_status_selected: Ingen statusar vart endra sidan ingen vart valde open: Opne innlegg original_status: Opprinnelig innlegg reblogs: Framhevingar + replied_to_html: Svarte %{acct_link} status_changed: Innlegg endret - title: Kontostatusar - @%{name} + status_title: Innlegg av @%{name} + title: Kontoinnlegg - @%{name} trending: Populært + view_publicly: Vis offentleg visibility: Synlighet with_media: Med media strikes: diff --git a/config/locales/no.yml b/config/locales/no.yml index 408fdd5ae1..8bf5daad0e 100644 --- a/config/locales/no.yml +++ b/config/locales/no.yml @@ -786,7 +786,6 @@ original_status: Opprinnelig innlegg reblogs: Fremheve status_changed: Innlegg endret - title: Kontostatuser - @%{name} trending: Populært visibility: Synlighet with_media: Med media diff --git a/config/locales/oc.yml b/config/locales/oc.yml index 5130977cb3..5dec5ebb77 100644 --- a/config/locales/oc.yml +++ b/config/locales/oc.yml @@ -401,7 +401,6 @@ oc: media: title: Mèdia no_status_selected: Cap d’estatut pas cambiat estant que cap èra pas seleccionat - title: Estatuts del compte - @%{name} visibility: Visibilitat with_media: Amb mèdia system_checks: diff --git a/config/locales/pl.yml b/config/locales/pl.yml index c5d63e1d73..48a881a61b 100644 --- a/config/locales/pl.yml +++ b/config/locales/pl.yml @@ -861,7 +861,6 @@ pl: original_status: Oryginalny post reblogs: Podbicia status_changed: Post zmieniony - title: Wpisy konta - @%{name} trending: Popularne visibility: Widoczność with_media: Z zawartością multimedialną diff --git a/config/locales/pt-BR.yml b/config/locales/pt-BR.yml index c5a0f3764a..537dee5f74 100644 --- a/config/locales/pt-BR.yml +++ b/config/locales/pt-BR.yml @@ -826,8 +826,10 @@ pt-BR: back_to_account: Voltar para página da conta back_to_report: Voltar às denúncias batch: + add_to_report: 'Adicionar à denúncia #%{id}' remove_from_report: Remover da denúncia report: Denunciar + contents: Conteúdos deleted: Excluídos favourites: Favoritos history: Histórico de versões @@ -836,13 +838,17 @@ pt-BR: media: title: Mídia metadata: Metadados + no_history: Esta publicação não foi editada no_status_selected: Nenhuma publicação foi modificada porque nenhuma estava selecionada open: Publicação aberta original_status: Publicação original reblogs: Reblogs + replied_to_html: Respondeu à %{acct_link} status_changed: Publicação alterada + status_title: Publicação de @%{name} title: Publicações da conta - @%{name} trending: Em alta + view_publicly: Ver publicamente visibility: Visibilidade with_media: Com mídia strikes: @@ -1377,9 +1383,16 @@ pt-BR: overwrite: Sobrescrever overwrite_long: Substituir os registros atuais com os novos overwrite_preambles: + blocking_html: + one: Você está prestes a trocar seu bloco de listas com mais de %{count} conta de %{filename}. + other: Você está prestes a substituir sua lista de blocos com mais de %{count} contas de %{filename}. bookmarks_html: one: Você está prestes a substituir seus salvos por até %{count} publicação de %{filename}. other: Você está prestes a substituir seus salvos por até %{count} publicações de %{filename}. + preambles: + muting_html: + one: Você está prestes a silenciar %{count} conta de %{filename}. + other: Você está prestes a silenciar mais de %{count} contas de %{filename}. preface: Você pode importar dados que você exportou de outro servidor, como a lista de pessoas que você segue ou bloqueou. recent_imports: Importações recentes states: diff --git a/config/locales/pt-PT.yml b/config/locales/pt-PT.yml index ff80948848..cceceb0534 100644 --- a/config/locales/pt-PT.yml +++ b/config/locales/pt-PT.yml @@ -832,7 +832,6 @@ pt-PT: original_status: Publicação original reblogs: Re-publicacões status_changed: Publicação alterada - title: Estado das contas - @%{name} trending: Em tendência visibility: Visibilidade with_media: Com media diff --git a/config/locales/ru.yml b/config/locales/ru.yml index 09d89cef9d..d9bf96c625 100644 --- a/config/locales/ru.yml +++ b/config/locales/ru.yml @@ -869,7 +869,6 @@ ru: original_status: Оригинальный пост reblogs: Продвинули status_changed: Пост изменен - title: Посты пользователя - @%{name} trending: Популярное visibility: Видимость with_media: С файлами diff --git a/config/locales/sc.yml b/config/locales/sc.yml index 09f8ba0e0e..38ede0a72c 100644 --- a/config/locales/sc.yml +++ b/config/locales/sc.yml @@ -582,7 +582,6 @@ sc: open: Aberi sa publicatzione original_status: Publicatzione originale status_changed: Publicatzione modificada - title: Istados de su contu - @%{name} trending: Populares visibility: Visibilidade with_media: Cun elementos multimediales diff --git a/config/locales/sco.yml b/config/locales/sco.yml index 55e0603d45..ff3a730b17 100644 --- a/config/locales/sco.yml +++ b/config/locales/sco.yml @@ -713,7 +713,6 @@ sco: original_status: Original post reblogs: Reblogs status_changed: Post chynged - title: Accoont posts - @%{name} trending: Trendin visibility: Visibility with_media: Wi media diff --git a/config/locales/si.yml b/config/locales/si.yml index b0eb1d3b0c..cd4abf6451 100644 --- a/config/locales/si.yml +++ b/config/locales/si.yml @@ -607,7 +607,6 @@ si: open: ලිපිය අරින්න original_status: මුල් ලිපිය status_changed: ලිපිය සංශෝධිතයි - title: ගිණුමේ ලිපි - @%{name} trending: නැගී එන with_media: මාධ්‍ය සමඟ strikes: diff --git a/config/locales/simple_form.ga.yml b/config/locales/simple_form.ga.yml index 62d59235bf..f8257a9da9 100644 --- a/config/locales/simple_form.ga.yml +++ b/config/locales/simple_form.ga.yml @@ -10,6 +10,7 @@ ga: indexable: Seans go mbeidh do phostálacha poiblí le feiceáil sna torthaí cuardaigh ar Mastodon. Seans go mbeidh daoine a d’idirghníomhaigh le do phostálacha in ann iad a chuardach beag beann ar. note: 'Is féidir leat @trá a dhéanamh ar dhaoine eile nó #hashtags.' show_collections: Beidh daoine in ann brabhsáil trí do seo a leanas agus do leanúna. Feicfidh na daoine a leanann tú go leanann tú iad beag beann ar. + unlocked: Beidh daoine in ann tú a leanúint gan cead a iarraidh. Díthiceáil an dteastaíonn uait athbhreithniú a dhéanamh ar iarratais leantacha agus roghnaigh cé acu an nglacfaidh nó an diúltóidh tú do leantóirí nua. account_alias: acct: Sonraigh ainm@fearann don chuntas ar mhaith leat aistriú uaidh account_migration: diff --git a/config/locales/simple_form.ia.yml b/config/locales/simple_form.ia.yml index 5ac75aafb1..1a405980c0 100644 --- a/config/locales/simple_form.ia.yml +++ b/config/locales/simple_form.ia.yml @@ -3,12 +3,14 @@ ia: simple_form: hints: account: + attribution_domains_as_text: Un per linea. Protege contra false attributiones. discoverable: Tu messages public e tu profilo pote esser mittite in evidentia o recommendate in varie areas de Mastodon e tu profilo pote esser suggerite a altere usatores. display_name: Tu prenomine e nomine de familia o tu pseudonymo. fields: Tu pagina principal, pronomines, etate, tote lo que tu vole. indexable: Tu messages public pote apparer in le resultatos de recerca sur Mastodon. Le personas qui ha interagite con tu messages pote cercar los in omne caso. note: 'Tu pote @mentionar altere personas o #hashtags.' show_collections: Le gente potera percurrer le listas de personas que tu seque e qui te seque. Le personas que tu seque videra que tu les seque in omne caso. + unlocked: Le personas potera sequer te sin requestar approbation. Dismarca si tu vole revider le requestas de sequimento e seliger si acceptar o rejectar nove sequitores. account_alias: acct: Specifica le nomine_de_usator@dominio del conto desde le qual tu vole migrar account_migration: @@ -129,6 +131,7 @@ ia: name: Tu pote solmente cambiar le litteras inter majusculas e minusculas, per exemplo, pro render lo plus legibile user: chosen_languages: Si marcate, solo le messages in le linguas seligite sera monstrate in chronologias public + role: Le rolo controla qual permissos le usator ha. user_role: color: Color a esser usate pro le rolo in omne parte del UI, como RGB in formato hexadecimal highlighted: Iste rende le rolo publicamente visibile @@ -141,6 +144,7 @@ ia: url: Ubi le eventos essera inviate labels: account: + attribution_domains_as_text: Sitos web autorisate a accreditar te discoverable: Evidentiar le profilo e messages in le algorithmos de discoperta fields: name: Etiquetta @@ -209,6 +213,7 @@ ia: setting_default_privacy: Confidentialitate del messages setting_default_sensitive: Sempre marcar le medios cmo sensbile setting_delete_modal: Monstrar le dialogo de confirmation ante deler un message + setting_disable_hover_cards: Disactivar le previsualisation de profilos al passar del mus setting_disable_swiping: Disactivar le movimentos per glissamento setting_display_media: Visualisation de medios setting_display_media_default: Predefinite diff --git a/config/locales/simple_form.pt-BR.yml b/config/locales/simple_form.pt-BR.yml index 0c6be63aaa..fca59515f0 100644 --- a/config/locales/simple_form.pt-BR.yml +++ b/config/locales/simple_form.pt-BR.yml @@ -10,6 +10,7 @@ pt-BR: indexable: Suas publicações públicas podem aparecer nos resultados da pesquisa em Mastodon. As pessoas que interagiram com suas publicações podem conseguir pesquisá-las independentemente disso. note: 'Você pode @mencionar outras pessoas ou #hashtags.' show_collections: As pessoas poderão navegar entre os seus seguidores e seguidores. As pessoas que você segue verão que você as segue independentemente disso. + unlocked: As pessoas poderão seguir você sem solicitar aprovação. Desmarque caso você queira revisar as solicitações de seguidor e escolha se queira aceitar ou rejeitar novos seguidores. account_alias: acct: Especifique o usuário@domínio de onde veio account_migration: diff --git a/config/locales/simple_form.zh-CN.yml b/config/locales/simple_form.zh-CN.yml index 5f98d73be6..0b7edae913 100644 --- a/config/locales/simple_form.zh-CN.yml +++ b/config/locales/simple_form.zh-CN.yml @@ -4,12 +4,12 @@ zh-CN: hints: account: attribution_domains_as_text: 每行一个域名。这样就可以保护作品免受虚假署名。 - discoverable: 您的公开嘟文和个人资料可能会在 Mastodon 的多个位置展示,您的个人资料可能会被推荐给其他用户。 + discoverable: 你的公开嘟文和个人资料可能会在 Mastodon 的多个位置展示,你的个人资料可能会被推荐给其他用户。 display_name: 你的全名或昵称。 fields: 你的主页、人称代词、年龄,以及任何你想要添加的内容。 - indexable: 您的公开嘟文会出现在 Mastodon 的搜索结果中。无论是否勾选,与您的嘟文有过交互的人都可能通过搜索找到它们。 - note: '你可以提及 @其他人 或 #标签 。' - show_collections: 人们将能够浏览您的关注和追随者。您关注的人会看到您关注他们。 + indexable: 你的公开嘟文会出现在 Mastodon 的搜索结果中。无论是否勾选,与你的嘟文有过交互的人都可能通过搜索找到它们。 + note: '你可以提及 @其他人 或 #话题标签 。' + show_collections: 人们将能够浏览你的关注和追随者。你关注的人会看到你关注他们。 unlocked: 人们将能够在不请求批准的情况下关注你。如果你希望审核关注请求并选择接受或拒绝新的关注者,请取消勾选此项。 account_alias: acct: 指定你想要迁移过来的原账号:用户名@站点域名 @@ -62,7 +62,7 @@ zh-CN: setting_display_media_show_all: 始终显示媒体 setting_use_blurhash: 渐变是基于模糊后的隐藏内容生成的 setting_use_pending_items: 关闭自动滚动更新,时间轴会在点击后更新 - username: 您只能使用字母、数字和下划线 + username: 你只能使用字母、数字和下划线 whole_word: 如果关键词只包含字母和数字,将只在词语完全匹配时才会应用 domain_allow: domain: 该站点将能够从该服务器上拉取数据,并处理和存储收到的数据。 @@ -87,7 +87,7 @@ zh-CN: favicon: WEBP、PNG、GIF 或 JPG。使用自定义图标覆盖 Mastodon 的默认图标。 mascot: 覆盖高级网页界面中的绘图形象。 media_cache_retention_period: 来自外站用户嘟文的媒体文件将被缓存到你的实例上。当该值被设为正值时,缓存的媒体文件将在指定天数后被清除。如果媒体文件在被清除后重新被请求,且源站内容仍然可用,它将被重新下载。由于链接预览卡拉取第三方站点的频率受到限制,建议将此值设置为至少 14 天,如果小于该值,链接预览卡将不会按需更新。 - peers_api_enabled: 此服务器在联邦宇宙中遇到的域名列表。 这里不包含关于您是否与给定服务器联合的数据,只是您的服务器知道它。 这由收集一般意义上的联邦统计信息的服务使用。 + peers_api_enabled: 此服务器在联邦宇宙中遇到的实例列表。 此处不包含关于您是否与给定服务器联合的数据,只是您的服务器知道它。 这由收集一般意义上的联邦统计信息的服务使用。 profile_directory: 个人资料目录会列出所有选择可被发现的用户。 require_invite_text: 当注册需要手动批准时,将“你为什么想要加入?”设为必填项 site_contact_email: 他人需要询恰法务或支持信息时的联络方式 @@ -125,7 +125,7 @@ zh-CN: otp: 输入你手机应用上生成的双因素认证代码,或者任意一个恢复代码: webauthn: 如果是 USB 密钥,请确保将其插入,如有必要,请点击它。 settings: - indexable: 您的个人资料页面可能会出现在Google、Bing等搜索结果中。 + indexable: 你的个人资料页面可能会出现在Google、Bing等搜索结果中。 show_application: 无论如何,你始终可以看到是哪个应用发布了你的嘟文。 tag: name: 你只能改变字母的大小写,让它更易读 @@ -257,7 +257,7 @@ zh-CN: peers_api_enabled: 在API中公开的已知实例的服务器的列表 profile_directory: 启用用户目录 registrations_mode: 谁可以注册 - require_invite_text: 注册前需要提供理由 + require_invite_text: 注册时需要提供理由 show_domain_blocks: 显示域名屏蔽列表 show_domain_blocks_rationale: 显示域名屏蔽原因 site_contact_email: 联系邮箱 @@ -292,13 +292,13 @@ zh-CN: notification_emails: appeal: 有人对审核结果提出申诉 digest: 发送摘要邮件 - favourite: 当有用户喜欢了我的嘟文时,发送电子邮件提醒我 - follow: 有用户关注我时 - follow_request: 有用户向我发送关注请求时 - mention: 有用户提及我时 - pending_account: 有账号需要审核时 - reblog: 有用户转嘟我的嘟文时 - report: 新举报已提交 + favourite: 有用户喜欢了我的嘟文 + follow: 有人关注了我 + follow_request: 有人向我发送了关注请求 + mention: 有人提到了我 + pending_account: 有账号需要审核 + reblog: 有人转嘟了我的嘟文 + report: 有人提交了新举报 software_updates: all: 通知所有更新 critical: 仅在有关键更新时通知 @@ -328,8 +328,8 @@ zh-CN: position: 优先级 webhook: events: 已启用事件 - template: 载荷模板 - url: 对端 URL + template: Payload 模板 + url: 端点 URL 'no': 否 not_recommended: 不推荐 overridden: 已覆盖 diff --git a/config/locales/sk.yml b/config/locales/sk.yml index d576bf0382..c946b8abf1 100644 --- a/config/locales/sk.yml +++ b/config/locales/sk.yml @@ -684,7 +684,6 @@ sk: open: Otvor príspevok original_status: Pôvodný príspevok status_changed: Príspevok bol zmenený - title: Príspevky na účte - @%{name} trending: Populárne visibility: Viditeľnosť with_media: S médiami diff --git a/config/locales/sl.yml b/config/locales/sl.yml index 6ae239d69f..909b89e5a9 100644 --- a/config/locales/sl.yml +++ b/config/locales/sl.yml @@ -853,7 +853,6 @@ sl: original_status: Izvorna objava reblogs: Ponovljeni blogi status_changed: Objava spremenjena - title: Objave računa - @%{name} trending: V trendu visibility: Vidnost with_media: Z mediji diff --git a/config/locales/sq.yml b/config/locales/sq.yml index b1e2a4f61e..e9247ef365 100644 --- a/config/locales/sq.yml +++ b/config/locales/sq.yml @@ -823,8 +823,10 @@ sq: back_to_account: Mbrapsht te faqja e llogarisë back_to_report: Mbrapsht te faqja e raportimit batch: + add_to_report: 'Shtoje te raportimi #%{id}' remove_from_report: Hiqe prej raportimit report: Raportojeni + contents: Lëndë deleted: E fshirë favourites: Të parapëlqyer history: Historik versioni @@ -833,13 +835,17 @@ sq: media: title: Media metadata: Tejtëdhëna + no_history: Ky postim s’është përpunuar no_status_selected: S’u ndryshua ndonjë gjendje, ngaqë s’u përzgjodh ndonjë e tillë open: Hape postimin original_status: Postim origjinal reblogs: Riblogime + replied_to_html: Iu përgjigj %{acct_link} status_changed: Postimi ndryshoi - title: Gjendje llogarish - @%{name} + status_title: Postim nga @%{name} + title: Postime llogarie - @%{name} trending: Në modë + view_publicly: Shiheni publikisht visibility: Dukshmëri with_media: Me media strikes: diff --git a/config/locales/sr-Latn.yml b/config/locales/sr-Latn.yml index 76a0f8afe9..0b3043c47b 100644 --- a/config/locales/sr-Latn.yml +++ b/config/locales/sr-Latn.yml @@ -807,7 +807,6 @@ sr-Latn: original_status: Originalna objava reblogs: Deljenja status_changed: Objava promenjena - title: Statusi naloga - @%{name} trending: U trendu visibility: Vidljivost with_media: Sa multimedijom diff --git a/config/locales/sr.yml b/config/locales/sr.yml index 6a75316c23..e077a40eee 100644 --- a/config/locales/sr.yml +++ b/config/locales/sr.yml @@ -837,7 +837,6 @@ sr: original_status: Оригинална објава reblogs: Дељења status_changed: Објава промењена - title: Статуси налога - @%{name} trending: У тренду visibility: Видљивост with_media: Са мултимедијом diff --git a/config/locales/sv.yml b/config/locales/sv.yml index 11b37f8bfc..c48b45b2e8 100644 --- a/config/locales/sv.yml +++ b/config/locales/sv.yml @@ -826,8 +826,10 @@ sv: back_to_account: Tillbaka till kontosidan back_to_report: Tillbaka till rapportsidan batch: + add_to_report: 'Lägg till i rapport #%{id}' remove_from_report: Ta bort från rapport report: Rapportera + contents: Innehåll deleted: Raderad favourites: Favoriter history: Versionshistorik @@ -836,13 +838,16 @@ sv: media: title: Media metadata: Metadata + no_history: Detta inlägg har inte redigerats no_status_selected: Inga inlägg ändrades eftersom inga valdes open: Öppna inlägg original_status: Ursprungligt inlägg reblogs: Ombloggningar status_changed: Inlägg ändrat + status_title: Inlägg av @%{name} title: Kontoinlägg - @%{name} trending: Trendande + view_publicly: Visa offentligt visibility: Synlighet with_media: Med media strikes: diff --git a/config/locales/th.yml b/config/locales/th.yml index 32f2b30292..5178506bab 100644 --- a/config/locales/th.yml +++ b/config/locales/th.yml @@ -819,7 +819,6 @@ th: original_status: โพสต์ดั้งเดิม reblogs: การดัน status_changed: เปลี่ยนโพสต์แล้ว - title: โพสต์ของบัญชี - @%{name} trending: กำลังนิยม visibility: การมองเห็น with_media: มีสื่อ diff --git a/config/locales/tr.yml b/config/locales/tr.yml index 2eafed1b47..a0002070c6 100644 --- a/config/locales/tr.yml +++ b/config/locales/tr.yml @@ -826,8 +826,10 @@ tr: back_to_account: Hesap sayfasına geri dön back_to_report: Bildirim sayfasına geri dön batch: + add_to_report: 'Rapora ekle #%{id}' remove_from_report: Bildirimden kaldır report: Bildirim + contents: İçerikler deleted: Silindi favourites: Favoriler history: Sürüm geçmişi @@ -836,13 +838,17 @@ tr: media: title: Medya metadata: Üstveri + no_history: Bu gönderi düzenlenmemiş no_status_selected: Hiçbiri seçilmediğinden hiçbir durum değiştirilmedi open: Gönderiyi aç original_status: Özgün gönderi reblogs: Yeniden Paylaşımlar + replied_to_html: Yanıtladı %{acct_link} status_changed: Gönderi değişti - title: Hesap durumları - @%{name} + status_title: Gönderen @%{name} + title: Hesap gönderileri - @%{name} trending: Öne çıkanlar + view_publicly: Herkese Açık Görüntüle visibility: Görünürlük with_media: Medya ile strikes: diff --git a/config/locales/uk.yml b/config/locales/uk.yml index 7ea76b2a75..68ca10c0cc 100644 --- a/config/locales/uk.yml +++ b/config/locales/uk.yml @@ -861,7 +861,6 @@ uk: original_status: Оригінальний допис reblogs: Поширення status_changed: Допис змінено - title: Дописи облікових записів - @%{name} trending: Популярне visibility: Видимість with_media: З медіа diff --git a/config/locales/vi.yml b/config/locales/vi.yml index 71c4357f2f..acc69f96cd 100644 --- a/config/locales/vi.yml +++ b/config/locales/vi.yml @@ -812,8 +812,10 @@ vi: back_to_account: Quay lại trang tài khoản back_to_report: Quay lại trang báo cáo batch: + add_to_report: 'Thêm vào báo cáo #%{id}' remove_from_report: Xóa khỏi báo cáo report: Báo cáo + contents: Nội dung deleted: Đã xóa favourites: Lượt thích history: Lịch sử phiên bản @@ -822,13 +824,17 @@ vi: media: title: Media metadata: Metadata + no_history: Tút này chưa được chỉnh sửa no_status_selected: Bạn chưa chọn bất kỳ tút nào open: Mở tút original_status: Tút gốc reblogs: Lượt đăng lại + replied_to_html: Trả lời đến %{acct_link} status_changed: Tút đã sửa - title: Tất cả tút - @%{name} + status_title: Đăng bởi @%{name} + title: Tút từ tài khoản - @%{name} trending: Xu hướng + view_publicly: Xem công khai visibility: Hiển thị with_media: Có media strikes: diff --git a/config/locales/zh-CN.yml b/config/locales/zh-CN.yml index cae0efee57..7dc0f3d949 100644 --- a/config/locales/zh-CN.yml +++ b/config/locales/zh-CN.yml @@ -10,7 +10,7 @@ zh-CN: followers: other: 关注者 following: 正在关注 - instance_actor_flash: 该账号用来代表虚拟角色,并不代表个人用户,仅代表服务器本身。该账号用于达成互联之目的,不应该被停用。 + instance_actor_flash: 该账号用来代表虚拟角色,并不代表个人用户,仅代表服务器本身。该账号用于联合目的,不应该被停用。 last_active: 最近活动 link_verified_on: 此链接的所有权已在 %{date} 检查 nothing_here: 空空如也! @@ -24,7 +24,7 @@ zh-CN: account_actions: action: 执行操作 already_silenced: 此账户已受限。 - already_suspended: 此帐户已被封禁。 + already_suspended: 此账户已被封禁。 title: 在 %{acct} 上执行管理操作 account_moderation_notes: create: 新建记录 @@ -86,9 +86,9 @@ zh-CN: title: 位置 login_status: 登录状态 media_attachments: 媒体文件 - memorialize: 设置为追悼账户 - memorialized: 被悼念 - memorialized_msg: 成功将 %{username} 转换为悼念账号 + memorialize: 设为追悼账户 + memorialized: 已设为追悼账户 + memorialized_msg: 成功将 %{username} 转换为追悼账户 moderation: active: 活跃 all: 全部 @@ -98,8 +98,8 @@ zh-CN: suspended: 已封禁 title: 管理 moderation_notes: 管理记录 - most_recent_activity: 最后一次活跃的时间 - most_recent_ip: 最后一次活跃的 IP 地址 + most_recent_activity: 最后活跃时间 + most_recent_ip: 最后活跃IP no_account_selected: 因为没有选中任何账号,所以没有更改 no_limits_imposed: 无限制 no_role_assigned: 未定角色 @@ -167,7 +167,7 @@ zh-CN: view_domain: 查看域名摘要 warn: 警告 web: 站内页面 - whitelisted: 允许跨站交互 + whitelisted: 允许联合 action_logs: action_types: approve_appeal: 批准申诉 @@ -209,7 +209,7 @@ zh-CN: enable_relay: 启用中继站 enable_sign_in_token_auth_user: 为用户启用邮件令牌身份验证 enable_user: 启用用户 - memorialize_account: 将账户设为追悼模式 + memorialize_account: 设为追悼账户 promote_user: 给用户升任 reject_appeal: 驳回申诉 reject_user: 拒绝用户 @@ -244,7 +244,7 @@ zh-CN: create_announcement_html: "%{name} 创建了新公告 %{target}" create_canonical_email_block_html: "%{name} 封禁了 hash 为 %{target} 的邮箱地址" create_custom_emoji_html: "%{name} 添加了新的自定义表情 %{target}" - create_domain_allow_html: "%{name} 允许了和域名 %{target} 的跨站交互" + create_domain_allow_html: "%{name} 允许了与实例 %{target} 的联合" create_domain_block_html: "%{name} 屏蔽了域名 %{target}" create_email_domain_block_html: "%{name} 封禁了邮箱域名 %{target}" create_ip_block_html: "%{name} 为 IP %{target} 创建了规则" @@ -255,7 +255,7 @@ zh-CN: destroy_announcement_html: "%{name} 删除了公告 %{target}" destroy_canonical_email_block_html: "%{name} 解封了 hash 为 %{target} 的邮箱地址" destroy_custom_emoji_html: "%{name} 删除了自定义表情 %{target}" - destroy_domain_allow_html: "%{name} 拒绝了和 %{target} 跨站交互" + destroy_domain_allow_html: "%{name} 拒绝了与实例 %{target} 的联合" destroy_domain_block_html: "%{name} 解除了对域名 %{target} 的屏蔽" destroy_email_domain_block_html: "%{name} 解封了邮箱域名 %{target}" destroy_instance_html: "%{name} 删除了实例 %{target}" @@ -301,7 +301,7 @@ zh-CN: empty: 没有找到日志 filter_by_action: 根据行为过滤 filter_by_user: 根据用户过滤 - title: 运营日志 + title: 审核日志 unavailable_instance: "(域名不可用)" announcements: destroyed_msg: 公告已删除! @@ -337,7 +337,7 @@ zh-CN: emoji: 表情 enable: 启用 enabled: 已启用 - enabled_msg: 表情启用成功 + enabled_msg: 已成功启用此表情 image_hint: 最大 %{size} 的 PNG 或 GIF list: 列表 listed: 已显示 @@ -350,7 +350,7 @@ zh-CN: shortcode_hint: 至少 2 个字符,只能使用字母、数字和下划线 title: 自定义表情 uncategorized: 未分类 - unlist: 不公开 + unlist: 隐藏 unlisted: 已隐藏 update_failed_msg: 表情更新失败 updated_msg: 表情更新成功! @@ -370,24 +370,24 @@ zh-CN: pending_users_html: other: "%{count} 个待处理用户" resolved_reports: 已处理的举报 - software: 软件 + software: 软件信息 sources: 注册来源 space: 存储使用情况 title: 信息面板 top_languages: 最活跃的语言 top_servers: 最活跃的服务器 - website: 网页端 + website: 网站 disputes: appeals: - empty: 没有发现申诉。 + empty: 未找到申诉。 title: 申诉 domain_allows: - add_new: 允许和域名跨站交互 - created_msg: 域名已被允许跨站交互 - destroyed_msg: 域名已被禁止跨站交互 + add_new: 允许与此实例联合 + created_msg: 实例已被允许联合 + destroyed_msg: 实例已被禁止联合 export: 导出 import: 导入 - undo: 不允许和该域名跨站交互 + undo: 禁止与此实例联合 domain_blocks: add_new: 添加新屏蔽域名 confirm_suspension: @@ -403,15 +403,15 @@ zh-CN: destroyed_msg: 域名屏蔽已撤销 domain: 域名 edit: 编辑域名屏蔽 - existing_domain_block: 您已经对 %{name} 设置了更严格的限制。 + existing_domain_block: 你已经对 %{name} 设置了更严格的限制。 existing_domain_block_html: 你已经对 %{name} 施加了更严格的限制,你需要先 解封。 export: 导出 import: 导入 new: create: 添加屏蔽 - hint: 域名屏蔽不会阻止该域名下的帐户进入本站的数据库,但是会对来自这个域名的帐户自动进行预先设置的管理操作。 + hint: 域名屏蔽不会阻止该域名下的账户进入本站的数据库,但是会对来自这个域名的账户自动进行预先设置的管理操作。 severity: - desc_html: 选择隐藏会将该域名下帐户发送的嘟文设置为仅关注者可见;选择封禁会将该域名下帐户发送的嘟文、媒体文件以及个人资料数据从本实例上删除;如果你只是想拒绝接收来自该域名的任何媒体文件,请选择。 + desc_html: 选择隐藏会将该域名下账户发送的嘟文设置为仅关注者可见;选择封禁会将该域名下账户发送的嘟文、媒体文件以及个人资料数据从本实例上删除;如果你只是想拒绝接收来自该域名的任何媒体文件,请选择。 noop: 无 silence: 隐藏 suspend: 封禁 @@ -456,9 +456,9 @@ zh-CN: no_file: 没有选择文件 export_domain_blocks: import: - description_html: 您即将导入域名列表,如果您不是此域名列表的作者,请仔细检查核对。 + description_html: 你即将导入域名列表,如果你不是此域名列表的作者,请仔细检查核对。 existing_relationships_warning: 现有的关注关系 - private_comment_description_html: 为了帮助您追踪域名列表来源,导入的域名列表将被添加如下的私人注释:%{comment} + private_comment_description_html: 为了帮助你追踪域名列表来源,导入的域名列表将被添加如下的私人注释:%{comment} private_comment_template: 从 %{source} 导入 %{date} title: 导入域名列表 invalid_domain_block: 由于以下错误,一个或多个域名屏蔽被跳过: %{error} @@ -494,7 +494,7 @@ zh-CN: content_policies: comment: 内部备注 description_html: 你可以设置应用于此域名所有账号和其所有子域名的内容策略。 - limited_federation_mode_description_html: 您可以选择是否允许与该联邦联合。 + limited_federation_mode_description_html: 你可以选择是否允许与此实例联合。 policies: reject_media: 拒收媒体 reject_reports: 拒收举报 @@ -529,7 +529,7 @@ zh-CN: moderation: all: 全部 limited: 受限的 - title: 运营 + title: 审核 private_comment: 私密评论 public_comment: 公开评论 purge: 删除 @@ -543,7 +543,7 @@ zh-CN: totals_time_period_hint_html: 下方显示的总数来自全部历史数据。 unknown_instance: 此服务器上目前没有此域名的记录。 invites: - deactivate_all: 撤销所有邀请链接 + deactivate_all: 全部停用 filter: all: 全部 available: 可用 @@ -563,7 +563,7 @@ zh-CN: '94670856': 3年 new: title: 创建新 IP 规则 - no_ip_block_selected: 因为没有 IP 规则被选中,所以没有更改 + no_ip_block_selected: 未选中任何 IP 规则,所以没有更改 title: IP 规则 relationships: title: "%{acct} 的关系" @@ -580,7 +580,7 @@ zh-CN: pending: 等待中继站的确认 save_and_enable: 保存并启用 setup: 设置中继连接 - signatures_not_enabled: 安全模式或限联模式启用时,中继将不会正常工作 + signatures_not_enabled: 安全模式或白名单模式启用时,中继站可能将不会正常工作 status: 状态 title: 中继站 report_notes: @@ -597,10 +597,10 @@ zh-CN: mark_as_sensitive_description_html: 被举报的嘟文将被标记为敏感,同时该账号将被标记一次处罚,以供未来同一账号再次违规时参考。 other_description_html: 查看更多控制该账号行为的选项,并自定义编写与被举报账号的通信。 resolve_description_html: 不会对被举报账号采取任何动作,举报将被关闭,也不会留下处罚记录。 - silence_description_html: 只有关注或手工搜索此账号才能查看其资料,将严重限制其触达范围。可随时撤销。关闭针对此帐户的所有举报。 - suspend_description_html: 该帐户及其所有内容将无法访问并最终被删除,且无法与该帐户进行互动。 在 30 天内可随时撤销。关闭针对此帐户的所有举报。 + silence_description_html: 只有关注或手工搜索此账号才能查看其资料,将严重限制其触达范围。可随时撤销。关闭针对此账户的所有举报。 + suspend_description_html: 该账户及其所有内容将无法访问并最终被删除,且无法与该账户进行互动。 在 30 天内可随时撤销。关闭针对此账户的所有举报。 actions_description_html: 决定采取何种措施处理此举报。如果对被举报账号采取惩罚性措施,将向其发送一封电子邮件通知。但若选中垃圾信息类别则不会发送通知。 - actions_description_remote_html: 决定采取何种行动来解决此举报。 这只会影响您的服务器如何与该远程帐户的通信并处理其内容。 + actions_description_remote_html: 决定采取何种行动来解决此举报。 这只会影响你的服务器如何与该远程账户的通信并处理其内容。 actions_no_posts: 该举报没有相关嘟文可供删除 add_to_report: 增加更多举报内容 already_suspended_badges: @@ -622,7 +622,7 @@ zh-CN: delete_and_resolve: 删除嘟文 forwarded: 已转发 forwarded_replies_explanation: 该举报来自外站用户,涉及外站内容。之所以转发给你,是因为被举报的内容是对你站点一位用户的回复。 - forwarded_to: 转发举报至 %{domain} + forwarded_to: 转发举报到 %{domain} mark_as_resolved: 标记为已处理 mark_as_sensitive: 标记为敏感内容 mark_as_unresolved: 标记为未处理 @@ -630,7 +630,7 @@ zh-CN: notes: create: 添加记录 create_and_resolve: 添加记录并标记为“已处理” - create_and_unresolve: 添加记录并重开 + create_and_unresolve: 添加备注并重新打开 delete: 删除 placeholder: 描述已经执行的操作,或其他任何相关的跟进情况… title: 备注 @@ -651,10 +651,10 @@ zh-CN: statuses_description_html: 在与该账号的通信中将引用违规内容 summary: action_preambles: - delete_html: 您即将删除 @%{acct} 的一些嘟文。 这将: - mark_as_sensitive_html: 您即将 标记 @%{acct} 的帖一些子为 敏感。这将: - silence_html: 您即将限制 @%{acct} 的帐户。 这将: - suspend_html: 您即将暂停 @%{acct} 的帐户。 这将: + delete_html: 你即将删除 @%{acct} 的一些嘟文。 这将: + mark_as_sensitive_html: 你即将 标记 @%{acct} 的帖一些子为 敏感。这将: + silence_html: 你即将限制 @%{acct} 的账户。 这将: + suspend_html: 你即将暂停 @%{acct} 的账户。 这将: actions: delete_html: 删除违规嘟文 mark_as_sensitive_html: 将违规嘟文的媒体标记为敏感 @@ -664,7 +664,7 @@ zh-CN: close_reports_html: 将针对 @%{acct}所有 报告标记为已解决 delete_data_html: 从现在起 30 天后删除 @%{acct} 的个人资料和内容,除非他们同时解除暂停。 preview_preamble_html: "@%{acct} 将收到包含以下内容的警告:" - record_strike_html: 记录一次针对 @%{acct} 的警示,以帮助您在这个帐户上的未来违规事件中得到重视。 + record_strike_html: 记录一次针对 @%{acct} 的警示,以帮助你在这个账户上的未来违规事件中得到重视。 send_email_html: 向 @%{acct} 发送警告邮件 warning_placeholder: 可选的补充理由,以说明调整的情况。 target_origin: 被举报账号的来源 @@ -685,7 +685,7 @@ zh-CN: moderation: 监察 special: 特殊 delete: 刪除 - description_html: 使用 用户角色,您可以自定义您的用户可以访问的功能和区域。 + description_html: 使用 用户角色,你可以自定义你的用户可以访问的功能和区域。 edit: 编辑 '%{name}' 角色 everyone: 默认权限 everyone_full_description_html: 这是影响到 所有用户基础角色,包括未指定角色的用户。 其他所有的角色都继承着它的权限。 @@ -706,7 +706,7 @@ zh-CN: manage_blocks_description: 允许用户屏蔽邮箱提供商和IP地址 manage_custom_emojis: 管理自定义表情 manage_custom_emojis_description: 允许用户管理服务器上的自定义表情 - manage_federation: 管理邦联 + manage_federation: 管理联合 manage_federation_description: 允许用户屏蔽或允许同其他域名的邦联,并控制消息投递能力 manage_invites: 管理邀请 manage_invites_description: 允许用户浏览和停用邀请链接 @@ -743,7 +743,7 @@ zh-CN: settings: about: manage_rules: 管理服务器规则 - preamble: 提供此服务器如何运营、资金状况等的深入信息。 + preamble: 提供此服务器如何运营、审核及资金状况等详细信息。 rules_hint: 有一个专门区域用于显示用户需要遵守的规则。 title: 关于本站 appearance: @@ -774,7 +774,7 @@ zh-CN: domain_blocks: all: 对所有人 disabled: 不对任何人 - users: 对本地已登录用户 + users: 对已登录的本站用户 registrations: moderation_recommandation: 在向所有人开放注册之前,请确保你拥有一个人手足够且反应迅速的管理团队! preamble: 控制谁可以在你的服务器上创建账号。 @@ -789,7 +789,7 @@ zh-CN: authorized_fetch: 需要跨站认证 authorized_fetch_hint: 要求外站请求通过验证能够使用户级别与服务器级别的封锁更为严格。然而,这将带来额外的性能负担、减少回复触达范围、并可能导致与一些联邦宇宙服务的兼容性问题。此外,这并不能阻止他人针对性地获取公开嘟文与账户。 authorized_fetch_overridden_hint: 由于此设置被环境变量覆盖,目前无法更改。 - federation_authentication: 强制跨站认证 + federation_authentication: 联合时强制要求身份验证 title: 服务器设置 site_uploads: delete: 删除已上传的文件 @@ -809,11 +809,13 @@ zh-CN: statuses: account: 作者 application: 应用 - back_to_account: 返回帐户信息页 + back_to_account: 返回账户信息页 back_to_report: 返回举报页 batch: + add_to_report: '添加到举报 #%{id}' remove_from_report: 从报告中移除 report: 举报 + contents: 内容 deleted: 已删除 favourites: 喜欢 history: 版本历史记录 @@ -822,13 +824,17 @@ zh-CN: media: title: 媒体文件 metadata: 元数据 + no_history: 此嘟文没有编辑历史 no_status_selected: 因为没有嘟文被选中,所以没有更改 open: 展开嘟文 original_status: 原始嘟文 reblogs: 转发 + replied_to_html: 回复给 %{acct_link} status_changed: 嘟文已编辑 - title: 帐户嘟文 - @%{name} + status_title: "@%{name} 的嘟文" + title: 该账号的嘟文 - @%{name} trending: 当前热门 + view_publicly: 以公开身份查看 visibility: 可见性 with_media: 含有媒体文件 strikes: @@ -960,7 +966,7 @@ zh-CN: tag_languages_dimension: 语言排行 tag_servers_dimension: 服务器排行 tag_servers_measure: 不同服务器 - tag_uses_measure: 总使用 + tag_uses_measure: 总使用次数 description_html: 这些是当前此服务器可见嘟文中大量出现的标签。它可以帮助用户发现其他人正关注的话题。在获得批准前不会公开显示任何标签。 listable: 可被推荐 no_tag_selected: 因为没有选中任何标签,所以没有更改 @@ -980,17 +986,17 @@ zh-CN: warning_presets: add_new: 添加新条目 delete: 删除 - edit_preset: 编辑预置警告 + edit_preset: 编辑预设警告 empty: 你尚未定义任何警告预设。 title: 预设警告 webhooks: - add_new: 新增对端 + add_new: 新增端点 delete: 删除 description_html: "Webhook 使 Mastodon 能够推送 关于所选事件的实时通知 到你自己的应用程序,进而由你的应用程序自动触发反应。" disable: 禁用 disabled: 已禁用 edit: 编辑对端 - empty: 你尚未配置任何 Webhook 对端。 + empty: 你尚未配置任何 Webhook 端点。 enable: 启用 enabled: 活跃 enabled_events: @@ -1043,14 +1049,14 @@ zh-CN: aliases: add_new: 创建别名 created_msg: 成功创建了一个新别名。你现在可以从旧账户开始迁移了。 - deleted_msg: 成功移除别名。已经无法从该帐户移动到此帐户了。 - empty: 你没有设置别名 + deleted_msg: 成功移除别名。已经无法从该账户移动到此账户了。 + empty: 你没有设置别名。 hint_html: 如果你想从另一个账号迁移到这里,可以先在这里创建一个别名。要把旧账号的关注者迁移过来,这一步是必须的。设置别名的操作是无害且可撤销的账号迁移的操作会从旧账号发起。 remove: 取消关联别名 appearance: advanced_web_interface: 高级 Web 界面 - advanced_web_interface_hint: 如果你想使用整个屏幕宽度,高级 web 界面允许您配置多个不同的栏目,可以同时看到更多的信息:主页、通知、跨站时间轴、任意数量的列表和话题标签。 - animations_and_accessibility: 动画和访问选项 + advanced_web_interface_hint: 如果你想使用整个屏幕宽度,高级 web 界面允许你配置多个不同的栏目,可以同时看到更多的信息:主页、通知、跨站时间轴、任意数量的列表和话题标签。 + animations_and_accessibility: 动画与可访问性 confirmation_dialogs: 确认对话框 discovery: 发现 localization: @@ -1090,8 +1096,8 @@ zh-CN: registration_complete: 你在 %{domain} 上的注册现已完成! welcome_title: 欢迎你,%{name}! wrong_email_hint: 如果该邮箱地址不正确,你可以在账户设置中进行更改。 - delete_account: 删除帐户 - delete_account_html: 如果你想删除你的帐户,请点击这里继续。你需要确认你的操作。 + delete_account: 删除账户 + delete_account_html: 如果你想删除你的账户,请点击这里继续。你需要确认你的操作。 description: prefix_invited_by_user: "@%{name} 邀请你加入这个Mastodon服务器!" prefix_sign_up: 现在就注册 Mastodon! @@ -1111,8 +1117,8 @@ zh-CN: privacy_policy_agreement_html: 我已阅读并同意 隐私政策 progress: confirm: 确认邮箱 - details: 您的详情 - review: 我们的复审 + details: 你的详情 + review: 我们的审核 rules: 接受规则 providers: cas: CAS @@ -1128,21 +1134,21 @@ zh-CN: preamble: 这些由 %{domain} 监察员设置和执行。 preamble_invited: 在你继续之前,请考虑 %{domain} 的管理员设定的基本规则。 title: 一些基本规则。 - title_invited: 您已经被邀请。 + title_invited: 你已经被邀请。 security: 账户安全 set_new_password: 设置新密码 setup: email_below_hint_html: 请检查你的垃圾邮件文件夹,或请求再发送一次。如果你的邮箱地址不正确,你可以更正它。 - email_settings_hint_html: 请点击我们发送给 %{email} 地址中的确认链接。我在这儿等着您。 + email_settings_hint_html: 请点击我们发送给 %{email} 地址中的确认链接。我在这儿等着你。 link_not_received: 没有收到链接? new_confirmation_instructions_sent: 你将在几分钟内收到一封带有确认链接的新邮件! title: 请检查你的收件箱 sign_in: - preamble_html: 使用您在 %{domain} 的账户和密码登录。如果您的账户托管在其他的服务器上,您将无法在此登录。 + preamble_html: 使用你在 %{domain} 的账户和密码登录。如果你的账户托管在其他的服务器上,你将无法在此登录。 title: 登录到 %{domain} sign_up: - manual_review: 您在 %{domain} 上的注册需要经由管理人员手动审核。 为了帮助我们处理您的注册,请稍微介绍一下您为什么想在 %{domain} 上注册。 - preamble: 有了这个Mastodon服务器上的账户,您就可以关注Mastodon网络上的任何其他人,无论他们的账户在哪里。 + manual_review: 你在 %{domain} 上的注册需要经由管理人员手动审核。 为了帮助我们处理你的注册,请稍微介绍一下你为什么想在 %{domain} 上注册。 + preamble: 有了这个Mastodon服务器上的账户,你就可以关注Mastodon网络上的任何其他人,无论他们的账户在哪里。 title: 让我们在 %{domain} 上开始。 status: account_status: 账户状态 @@ -1157,7 +1163,7 @@ zh-CN: author_attribution: example_title: 示例文本 hint_html: 你是否在 Mastodon 之外撰写新闻或博客文章?控制它们被分享到 Mastodon 时的署名方式。 - instructions: 请确保将这段代码放在您文章的 HTML 中: + instructions: 请确保将这段代码放在你文章的 HTML 中: more_from_html: 来自 %{name} 的更多内容 s_blog: "%{name} 的博客" then_instructions: 然后,在下面的文本框中添加你用于发布文章的域名。 @@ -1218,7 +1224,7 @@ zh-CN: approve_appeal: 批准申诉 associated_report: 相关举报 created_at: 日期 - description_html: 这些是针对您的账户采取的行动和警告,已经由 %{instance} 的工作人员发送给您。 + description_html: 这些是针对你的账户采取的行动和警告,已经由 %{instance} 的工作人员发送给你。 recipient: 发送至 reject_appeal: 驳回申诉 status: '嘟文 #%{id}' @@ -1237,7 +1243,7 @@ zh-CN: your_appeal_rejected: 你的申诉已被驳回 edit_profile: basic_information: 基本信息 - hint_html: "自定义公开资料和嘟文旁边显示的内容。当您填写完整的个人资料并设置了头像时,其他人更有可能关注您并与您互动。" + hint_html: "自定义公开资料和嘟文旁边显示的内容。当你填写完整的个人资料并设置了头像时,其他人更有可能关注你并与你互动。" other: 其他 errors: '400': 你提交的请求无效或格式不正确。 @@ -1275,7 +1281,7 @@ zh-CN: featured_tags: add_new: 添加新条目 errors: - limit: 您所推荐的话题标签数已达上限 + limit: 你所推荐的话题标签数已达上限 hint_html: "什么是精选话题标签? 它们被显示在你的公开个人资料中的突出位置,人们可以在这些标签下浏览你的公共嘟文。 它们是跟踪创作或长期项目的进度的重要工具。" filters: contexts: @@ -1321,7 +1327,7 @@ zh-CN: all_items_on_page_selected_html: other: 此页面上的所有 %{count} 项目已被选中。 all_matching_items_selected_html: - other: 所有 %{count} 匹配您搜索的项目都已被选中。 + other: 所有 %{count} 匹配你搜索的项目都已被选中。 cancel: 取消 changes_saved_msg: 更改保存成功! confirm: 确认 @@ -1332,7 +1338,7 @@ zh-CN: order_by: 排序方式 save_changes: 保存更改 select_all_matching_items: - other: 选择匹配您搜索的所有 %{count} 个项目。 + other: 选择匹配你搜索的所有 %{count} 个项目。 today: 今天 validation_errors: other: 出错啦!检查一下下面 %{count} 处出错的地方吧 @@ -1353,7 +1359,7 @@ zh-CN: overwrite_long: 将当前记录替换为新记录 overwrite_preambles: blocking_html: - other: 你即将使用来自 %{filename} 的最多 %{count} 个帐户替换你的屏蔽列表。 + other: 你即将使用来自 %{filename} 的最多 %{count} 个账户替换你的屏蔽列表。 bookmarks_html: other: 你即将使用来自 %{filename} 的最多 %{count} 条嘟文替换你的书签。 domain_blocking_html: @@ -1363,7 +1369,7 @@ zh-CN: lists_html: other: 你即将使用来自 %{filename} 的内容替换你的列表。最多将会有 %{count} 个账户 被添加到新列表。 muting_html: - other: 你即将使用来自 %{filename} 的最多 %{count} 个帐户替换你的已隐藏账户列表。 + other: 你即将使用来自 %{filename} 的最多 %{count} 个账户替换你的已隐藏账户列表。 preambles: blocking_html: other: 你即将屏蔽来自 %{filename} 的最多 %{count} 个账号。 @@ -1397,7 +1403,7 @@ zh-CN: type: 导入类型 type_groups: constructive: 关注和书签 - destructive: 屏蔽和隐藏 + destructive: 屏蔽与隐藏 types: blocking: 屏蔽列表 bookmarks: 书签 @@ -1430,14 +1436,14 @@ zh-CN: title: 邀请用户 lists: errors: - limit: 您已达到列表数量的上限 + limit: 你已达到列表数量的上限 login_activities: authentication_methods: otp: 双因素认证应用 password: 密码 sign_in_token: 邮件安全码 webauthn: 安全密钥 - description_html: 如有您无法识别的活动,请考虑更改密码并启用双因素认证。 + description_html: 如有你无法识别的活动,请考虑更改密码并启用双因素认证。 empty: 没有可用的认证记录 failed_sign_in_html: 失败的 %{method} 登录尝试,来自 %{ip} (%{browser}) successful_sign_in_html: 通过 %{method} 成功登录,来自 %{ip} (%{browser}) @@ -1495,7 +1501,7 @@ zh-CN: other_data: 不会自动移动其它数据 redirect: 在收到一个跳转通知后,你当前的账号资料将会更新,并被排除在搜索范围外 moderation: - title: 运营 + title: 审核 move_handler: carry_blocks_over_text: 这个用户迁移自你屏蔽过的 %{acct} carry_mutes_over_text: 这个用户由你隐藏过的 %{acct} 迁移而来 @@ -1523,7 +1529,7 @@ zh-CN: title: 新的关注请求 mention: action: 回复 - body: "%{name} 在嘟文中提到了你:" + body: "%{name} 提到了你:" subject: "%{name} 提到了你" title: 新的提及 poll: @@ -1585,7 +1591,7 @@ zh-CN: privacy: 隐私 privacy_hint_html: 控制你愿意向他人透露多少信息。通过浏览他人的关注列表和查看他们发嘟所用的应用,人们可以发现有趣的用户和酷炫的应用,但你可能更喜欢将其隐藏起来。 reach: 范围 - reach_hint_html: 控制您是否希望被新人发现和关注。您是否希望您的嘟文出现在“探索”页面上?您是否希望其他人在关注推荐中看到您?您是想自动接受所有新粉丝,还是对每个粉丝都进行仔细的筛选? + reach_hint_html: 控制你是否希望被新人发现和关注。你是否希望你的嘟文出现在“探索”页面上?你是否希望其他人在关注推荐中看到你?你是想自动接受所有新粉丝,还是对每个粉丝都进行仔细的筛选? search: 搜索 search_hint_html: 控制你希望被找到的方式。你想让人们通过你公开发布的内容来找到你吗?当在网络上搜索时,你是否希望Mastodon之外的人能够找到你的个人资料?请注意,我们无法保证完全排除所有搜索引擎对公开信息的索引。 title: 隐私与可达性 @@ -1593,16 +1599,16 @@ zh-CN: title: 隐私政策 reactions: errors: - limit_reached: 互动种类的限制 - unrecognized_emoji: 不是一个可识别的表情 + limit_reached: 回应种类个数超过限制 + unrecognized_emoji: 不是一个可被识别的表情 redirects: prompt: 如果你信任此链接,请单击以继续跳转。 title: 你正在离开 %{instance} 。 relationships: activity: 账号活动 - confirm_follow_selected_followers: 您确定想要关注所选的关注者吗? - confirm_remove_selected_followers: 您确定想要取关所选的关注者吗? - confirm_remove_selected_follows: 您确定要删除选定的关注着吗? + confirm_follow_selected_followers: 你确定想要关注所选的关注者吗? + confirm_remove_selected_followers: 你确定想要取关所选的关注者吗? + confirm_remove_selected_follows: 您确定要删除选定的关注者吗? dormant: 休眠 follow_failure: 无法关注选中的部分账户。 follow_selected_followers: 关注选中的关注者 @@ -1649,12 +1655,12 @@ zh-CN: generic: 未知浏览器 huawei_browser: 华为浏览器 ie: IE 浏览器 - micro_messenger: 微信 + micro_messenger: MicroMessenger nokia: Nokia S40 Ovi 浏览器 opera: 欧朋浏览器 otter: Otter phantom_js: PhantomJS - qq: QQ浏览器 + qq: QQ 浏览器 safari: Safari uc_browser: UC 浏览器 unknown_browser: 未知浏览器 @@ -1673,7 +1679,7 @@ zh-CN: ios: iOS kai_os: KaiOS linux: Linux - mac: Mac + mac: macOS unknown_platform: 未知平台 windows: Windows windows_mobile: Windows Mobile @@ -1695,15 +1701,15 @@ zh-CN: export: 导出 featured_tags: 精选的话题标签 import: 导入 - import_and_export: 导入和导出 + import_and_export: 导入与导出 migrate: 账户迁移 notifications: 邮件通知 - preferences: 首选项 + preferences: 偏好设置 profile: 个人资料 relationships: 关注管理 severed_relationships: 已断开的关系 statuses_cleanup: 自动删除嘟文 - strikes: 操作记录 + strikes: 管理处罚记录 two_factor_authentication: 双因素认证 webauthn_authentication: 安全密钥 severed_relationships: @@ -1737,7 +1743,7 @@ zh-CN: over_character_limit: 超过了 %{max} 字的限制 pin_errors: direct: 仅对被提及的用户可见的帖子不能被置顶 - limit: 你所固定的嘟文数量已达到上限 + limit: 你置顶的嘟文数量已达上限 ownership: 不能置顶别人的嘟文 reblog: 不能置顶转嘟 title: "%{name}:“%{quote}”" @@ -1747,13 +1753,13 @@ zh-CN: private_long: 只有关注你的用户能看到 public: 公开 public_long: 所有人可见,并会出现在公共时间轴上 - unlisted: 不公开 + unlisted: 悄悄公开 unlisted_long: 所有人可见,但不会出现在公共时间轴上 statuses_cleanup: enabled: 自动删除旧嘟文 - enabled_hint: 达到指定过期时间后自动删除您的嘟文,除非满足下列条件之一 + enabled_hint: 达到指定过期时间后自动删除你的嘟文,除非满足下列条件之一 exceptions: 例外 - explanation: 删除嘟文是一个消耗系统资源的耗时操作,所以这个操作会在服务器空闲时完成。因此,您的嘟文可能会在达到过期阈值之后一段时间才会被删除。 + explanation: 删除嘟文是一个消耗系统资源的耗时操作,所以这个操作会在服务器空闲时完成。因此,你的嘟文可能会在达到过期阈值之后一段时间才会被删除。 ignore_favs: 取消喜欢 ignore_reblogs: 忽略转嘟 interaction_exceptions: 基于互动的例外 @@ -1792,10 +1798,10 @@ zh-CN: tags: does_not_match_previous_name: 和之前的名称不匹配 themes: - contrast: Mastodon(高对比度) - default: Mastodon(暗色主题) - mastodon-light: Mastodon(亮色主题) - system: 自动切换(使用系统主题) + contrast: Mastodon (高对比度) + default: Mastodon (暗色) + mastodon-light: Mastodon (亮色) + system: 自动切换 (使用系统主题) time: formats: default: "%Y年%m月%d日 %H:%M" @@ -1847,10 +1853,10 @@ zh-CN: suspicious_sign_in: change_password: 更改密码 details: 以下是该次登录的详细信息: - explanation: 我们检测到有新 IP 地址登录了您的账号。 - further_actions_html: 如果不是您本人操作,我们建议您立即 %{action} 并启用双因素认证,以确保账号安全。 - subject: 已有新 IP 地址访问了您的账号 - title: 新登录 + explanation: 我们检测到有新 IP 地址登录了你的账号。 + further_actions_html: 如果不是你本人操作,我们建议你立即 %{action} 并启用双因素认证,以确保账号安全。 + subject: 已有新 IP 地址访问了你的账号 + title: 一次新登录 warning: appeal: 提交申诉 appeal_description: 如果你认为此结果有误,可以向 %{instance} 的工作人员提交申诉。 @@ -1895,7 +1901,7 @@ zh-CN: explanation: 下面是几个小贴士,希望它们能帮到你 feature_action: 了解更多 feature_audience: Mastodon 为你提供了无需中间商即可管理受众的独特可能。Mastodon 可被部署在你自己的基础设施上,允许你关注其它任何 Mastodon 在线服务器的用户,或被任何其他在线 Mastodon 服务器的用户关注,并且不受你之外的任何人控制。 - feature_audience_title: 放手去建立起你的受众 + feature_audience_title: 自由吸引你的受众 feature_control: 你最清楚你想在你自己的主页中看到什么动态。没有算法或广告浪费你的时间。你可以用一个账号关注任何 Mastodon 服务器上的任何人,并按时间顺序获得他们发布的嘟文,让你的互联网的角落更合自己的心意。 feature_control_title: 掌控自己的时间线 feature_creativity: Mastodon 支持音频、视频和图片、无障碍描述、投票、内容警告, 动画头像、自定义表情包、缩略图裁剪控制等功能,帮助你在网上尽情表达自己。无论你是要发布你的艺术作品、音乐还是播客,Mastodon 都能为你服务。 diff --git a/config/locales/zh-HK.yml b/config/locales/zh-HK.yml index 6f0a99a5b3..752c9b5cbf 100644 --- a/config/locales/zh-HK.yml +++ b/config/locales/zh-HK.yml @@ -777,7 +777,6 @@ zh-HK: original_status: 原始帖文 reblogs: 轉發 status_changed: 帖文已變更 - title: 帳戶文章 - @%{name} trending: 熱門 visibility: 可見性 with_media: 含有媒體檔案 diff --git a/config/locales/zh-TW.yml b/config/locales/zh-TW.yml index ce6bd3e8f5..701ea0ea53 100644 --- a/config/locales/zh-TW.yml +++ b/config/locales/zh-TW.yml @@ -814,8 +814,10 @@ zh-TW: back_to_account: 返回帳號資訊頁面 back_to_report: 回到檢舉報告頁面 batch: + add_to_report: '新增至報告 #%{id}' remove_from_report: 自檢舉報告中移除 report: 檢舉報告 + contents: 內容 deleted: 已刪除 favourites: 最愛 history: 版本紀錄 @@ -824,13 +826,17 @@ zh-TW: media: title: 媒體檔案 metadata: 詮釋資料 + no_history: 此嘟文未曾被編輯 no_status_selected: 因未選取嘟文,所以什麼事都沒發生。 open: 公開嘟文 original_status: 原始嘟文 reblogs: 轉嘟 + replied_to_html: 回覆給 %{acct_link} status_changed: 嘟文已編輯 - title: 帳號嘟文 - @%{name} + status_title: 由 @%{name} 發嘟 + title: 嘟文帳號 - @%{name} trending: 熱門 + view_publicly: 公開檢視 visibility: 可見性 with_media: 含有媒體檔案 strikes: From be413d67de3357ad7cd601970cb9884431edad9e Mon Sep 17 00:00:00 2001 From: Matt Jankowski Date: Mon, 18 Nov 2024 04:22:09 -0500 Subject: [PATCH 35/64] `Form::Import` spec reduce factories (#32924) --- spec/models/form/import_spec.rb | 57 +++++++++------------------------ 1 file changed, 16 insertions(+), 41 deletions(-) diff --git a/spec/models/form/import_spec.rb b/spec/models/form/import_spec.rb index 22ffdfd877..e14ad6eca0 100644 --- a/spec/models/form/import_spec.rb +++ b/spec/models/form/import_spec.rb @@ -237,51 +237,26 @@ RSpec.describe Form::Import do let(:import_file) { file } let(:import_mode) { mode } - before do - subject.save - end - - it 'creates the expected rows' do - expect(account.bulk_imports.first.rows.pluck(:data)).to match_array(expected_rows) - end + before { subject.save } context 'with a BulkImport' do let(:bulk_import) { account.bulk_imports.first } - it 'creates a non-nil bulk import' do - expect(bulk_import).to_not be_nil - end - - it 'matches the subjects type' do - expect(bulk_import.type.to_sym).to eq subject.type.to_sym - end - - it 'matches the subjects original filename' do - expect(bulk_import.original_filename).to eq subject.data.original_filename - end - - it 'matches the subjects likely_mismatched? value' do - expect(bulk_import.likely_mismatched?).to eq subject.likely_mismatched? - end - - it 'matches the subject overwrite value' do - expect(bulk_import.overwrite?).to eq !!subject.overwrite # rubocop:disable Style/DoubleNegation - end - - it 'has zero processed items' do - expect(bulk_import.processed_items).to eq 0 - end - - it 'has zero imported items' do - expect(bulk_import.imported_items).to eq 0 - end - - it 'has a correct total_items value' do - expect(bulk_import.total_items).to eq bulk_import.rows.count - end - - it 'defaults to unconfirmed true' do - expect(bulk_import.state_unconfirmed?).to be true + it 'creates a bulk import with correct values' do + expect(bulk_import) + .to be_present + .and have_attributes( + type: eq(subject.type), + original_filename: eq(subject.data.original_filename), + likely_mismatched?: eq(subject.likely_mismatched?), + overwrite?: eq(!!subject.overwrite), # rubocop:disable Style/DoubleNegation + processed_items: eq(0), + imported_items: eq(0), + total_items: eq(bulk_import.rows.count), + state_unconfirmed?: be(true) + ) + expect(bulk_import.rows.pluck(:data)) + .to match_array(expected_rows) end end end From 16addf47c72ceb258e0cd020620407bb0e78f6af Mon Sep 17 00:00:00 2001 From: Matt Jankowski Date: Mon, 18 Nov 2024 04:23:07 -0500 Subject: [PATCH 36/64] Reduce long lines in `relationships/show` view (#32922) --- app/views/relationships/show.html.haml | 28 ++++++++++++++++++++++---- 1 file changed, 24 insertions(+), 4 deletions(-) diff --git a/app/views/relationships/show.html.haml b/app/views/relationships/show.html.haml index 7478b8c5ce..b062a4f53d 100644 --- a/app/views/relationships/show.html.haml +++ b/app/views/relationships/show.html.haml @@ -42,13 +42,33 @@ %label.batch-table__toolbar__select.batch-checkbox-all = check_box_tag :batch_checkbox_all, nil, false .batch-table__toolbar__actions - = f.button safe_join([material_symbol('person_add'), t('relationships.follow_selected_followers')]), name: :follow, class: 'table-action-link', type: :submit, data: { confirm: t('relationships.confirm_follow_selected_followers') } if followed_by_relationship? && !mutual_relationship? + - if followed_by_relationship? && !mutual_relationship? + = f.button safe_join([material_symbol('person_add'), t('relationships.follow_selected_followers')]), + class: 'table-action-link', + data: { confirm: t('relationships.confirm_follow_selected_followers') }, + name: :follow, + type: :submit - = f.button safe_join([material_symbol('person_remove'), t('relationships.remove_selected_follows')]), name: :unfollow, class: 'table-action-link', type: :submit, data: { confirm: t('relationships.confirm_remove_selected_follows') } unless followed_by_relationship? + - unless followed_by_relationship? + = f.button safe_join([material_symbol('person_remove'), t('relationships.remove_selected_follows')]), + class: 'table-action-link', + data: { confirm: t('relationships.confirm_remove_selected_follows') }, + name: :unfollow, + type: :submit - = f.button safe_join([material_symbol('delete'), t('relationships.remove_selected_followers')]), name: :remove_from_followers, class: 'table-action-link', type: :submit, data: { confirm: t('relationships.confirm_remove_selected_followers') } unless following_relationship? + - unless following_relationship? + = f.button safe_join([material_symbol('delete'), t('relationships.remove_selected_followers')]), + class: 'table-action-link', + data: { confirm: t('relationships.confirm_remove_selected_followers') }, + name: :remove_from_followers, + type: :submit - = f.button safe_join([material_symbol('delete'), t('relationships.remove_selected_domains')]), name: :remove_domains_from_followers, class: 'table-action-link', type: :submit, data: { confirm: t('admin.reports.are_you_sure') } if followed_by_relationship? + - if followed_by_relationship? + = f.button safe_join([material_symbol('delete'), t('relationships.remove_selected_domains')]), + class: 'table-action-link', + data: { confirm: t('admin.reports.are_you_sure') }, + name: :remove_domains_from_followers, + type: :submit .batch-table__body - if @accounts.empty? = nothing_here 'nothing-here--under-tabs' From c511cbcd6cdcaf7babce610db24db55498891ecc Mon Sep 17 00:00:00 2001 From: Matt Jankowski Date: Mon, 18 Nov 2024 04:23:38 -0500 Subject: [PATCH 37/64] Extract constants for controller `LIMIT` queries (#32921) --- app/controllers/admin/instances_controller.rb | 4 +++- .../api/v1/featured_tags/suggestions_controller.rb | 4 +++- app/controllers/settings/featured_tags_controller.rb | 4 +++- app/controllers/settings/imports_controller.rb | 4 +++- 4 files changed, 12 insertions(+), 4 deletions(-) diff --git a/app/controllers/admin/instances_controller.rb b/app/controllers/admin/instances_controller.rb index d7f88a71f3..a48c4773ed 100644 --- a/app/controllers/admin/instances_controller.rb +++ b/app/controllers/admin/instances_controller.rb @@ -5,6 +5,8 @@ module Admin before_action :set_instances, only: :index before_action :set_instance, except: :index + LOGS_LIMIT = 5 + def index authorize :instance, :index? preload_delivery_failures! @@ -13,7 +15,7 @@ module Admin def show authorize :instance, :show? @time_period = (6.days.ago.to_date...Time.now.utc.to_date) - @action_logs = Admin::ActionLogFilter.new(target_domain: @instance.domain).results.limit(5) + @action_logs = Admin::ActionLogFilter.new(target_domain: @instance.domain).results.limit(LOGS_LIMIT) end def destroy diff --git a/app/controllers/api/v1/featured_tags/suggestions_controller.rb b/app/controllers/api/v1/featured_tags/suggestions_controller.rb index 9c72e4380d..d533b1af7b 100644 --- a/app/controllers/api/v1/featured_tags/suggestions_controller.rb +++ b/app/controllers/api/v1/featured_tags/suggestions_controller.rb @@ -5,6 +5,8 @@ class Api::V1::FeaturedTags::SuggestionsController < Api::BaseController before_action :require_user! before_action :set_recently_used_tags, only: :index + RECENT_TAGS_LIMIT = 10 + def index render json: @recently_used_tags, each_serializer: REST::TagSerializer, relationships: TagRelationshipsPresenter.new(@recently_used_tags, current_user&.account_id) end @@ -12,6 +14,6 @@ class Api::V1::FeaturedTags::SuggestionsController < Api::BaseController private def set_recently_used_tags - @recently_used_tags = Tag.suggestions_for_account(current_account).limit(10) + @recently_used_tags = Tag.suggestions_for_account(current_account).limit(RECENT_TAGS_LIMIT) end end diff --git a/app/controllers/settings/featured_tags_controller.rb b/app/controllers/settings/featured_tags_controller.rb index 90c112e219..7e29dd1d29 100644 --- a/app/controllers/settings/featured_tags_controller.rb +++ b/app/controllers/settings/featured_tags_controller.rb @@ -5,6 +5,8 @@ class Settings::FeaturedTagsController < Settings::BaseController before_action :set_featured_tag, except: [:index, :create] before_action :set_recently_used_tags, only: :index + RECENT_TAGS_LIMIT = 10 + def index @featured_tag = FeaturedTag.new end @@ -38,7 +40,7 @@ class Settings::FeaturedTagsController < Settings::BaseController end def set_recently_used_tags - @recently_used_tags = Tag.suggestions_for_account(current_account).limit(10) + @recently_used_tags = Tag.suggestions_for_account(current_account).limit(RECENT_TAGS_LIMIT) end def featured_tag_params diff --git a/app/controllers/settings/imports_controller.rb b/app/controllers/settings/imports_controller.rb index 569aa07c53..5346a448a3 100644 --- a/app/controllers/settings/imports_controller.rb +++ b/app/controllers/settings/imports_controller.rb @@ -24,6 +24,8 @@ class Settings::ImportsController < Settings::BaseController lists: false, }.freeze + RECENT_IMPORTS_LIMIT = 10 + def index @import = Form::Import.new(current_account: current_account) end @@ -96,6 +98,6 @@ class Settings::ImportsController < Settings::BaseController end def set_recent_imports - @recent_imports = current_account.bulk_imports.reorder(id: :desc).limit(10) + @recent_imports = current_account.bulk_imports.reorder(id: :desc).limit(RECENT_IMPORTS_LIMIT) end end From d8e907fae3a1dacf450595ccfdb2864c1e12f1c3 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Mon, 18 Nov 2024 09:25:11 +0000 Subject: [PATCH 38/64] Update dependency aws-sdk-s3 to v1.171.0 (#32901) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- Gemfile.lock | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/Gemfile.lock b/Gemfile.lock index 106fb0d0fd..c7ab4e66fe 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -97,8 +97,8 @@ GEM attr_required (1.0.2) awrence (1.2.1) aws-eventstream (1.3.0) - aws-partitions (1.1004.0) - aws-sdk-core (3.212.0) + aws-partitions (1.1008.0) + aws-sdk-core (3.213.0) aws-eventstream (~> 1, >= 1.3.0) aws-partitions (~> 1, >= 1.992.0) aws-sigv4 (~> 1.9) @@ -106,7 +106,7 @@ GEM aws-sdk-kms (1.95.0) aws-sdk-core (~> 3, >= 3.210.0) aws-sigv4 (~> 1.5) - aws-sdk-s3 (1.170.1) + aws-sdk-s3 (1.171.0) aws-sdk-core (~> 3, >= 3.210.0) aws-sdk-kms (~> 1) aws-sigv4 (~> 1.5) From 03ee08c2da6634fa1cf566580889e249181200ac Mon Sep 17 00:00:00 2001 From: Matt Jankowski Date: Mon, 18 Nov 2024 04:31:25 -0500 Subject: [PATCH 39/64] Use `nil` instead of `false` for datetime value in spec (#32926) --- spec/models/concerns/account/sensitizes_spec.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/spec/models/concerns/account/sensitizes_spec.rb b/spec/models/concerns/account/sensitizes_spec.rb index 3596c9a126..5416d40570 100644 --- a/spec/models/concerns/account/sensitizes_spec.rb +++ b/spec/models/concerns/account/sensitizes_spec.rb @@ -7,7 +7,7 @@ RSpec.describe Account::Sensitizes do describe '.sensitized' do let(:sensitized_account) { Fabricate :account, sensitized_at: 2.days.ago } - before { Fabricate :account, sensitized_at: false } + before { Fabricate :account, sensitized_at: nil } it 'returns an array of accounts who are sensitized' do expect(Account.sensitized) From 9a46329fbda5926aefc8fdcd9c7a19a2f516885b Mon Sep 17 00:00:00 2001 From: Emelia Smith Date: Mon, 18 Nov 2024 10:34:34 +0100 Subject: [PATCH 40/64] Streaming: add development logging of database queries (#32945) --- streaming/database.js | 33 ++++++++++++++++++++++++++++++++- streaming/index.js | 3 ++- 2 files changed, 34 insertions(+), 2 deletions(-) diff --git a/streaming/database.js b/streaming/database.js index 9f1d742143..60a3b34ef0 100644 --- a/streaming/database.js +++ b/streaming/database.js @@ -116,13 +116,44 @@ let pool; /** * * @param {pg.PoolConfig} config + * @param {string} environment + * @param {import('pino').Logger} logger * @returns {pg.Pool} */ -export function getPool(config) { +export function getPool(config, environment, logger) { if (pool) { return pool; } pool = new pg.Pool(config); + + // Setup logging on pool.query and client.query for checked out clients: + // This is taken from: https://node-postgres.com/guides/project-structure + if (environment === 'development') { + const logQuery = (originalQuery) => { + return async (queryTextOrConfig, values, ...rest) => { + const start = process.hrtime(); + + const result = await originalQuery.apply(pool, [queryTextOrConfig, values, ...rest]); + + const duration = process.hrtime(start); + const durationInMs = (duration[0] * 1000000000 + duration[1]) / 1000000; + + logger.debug({ + query: queryTextOrConfig, + values, + duration: durationInMs + }, 'Executed database query'); + + return result; + }; + }; + + pool.on('connect', (client) => { + const originalQuery = client.query.bind(client); + client.query = logQuery(originalQuery); + }); + } + return pool; } diff --git a/streaming/index.js b/streaming/index.js index 3e362f1860..e00da1bb83 100644 --- a/streaming/index.js +++ b/streaming/index.js @@ -101,7 +101,8 @@ const CHANNEL_NAMES = [ ]; const startServer = async () => { - const pgPool = Database.getPool(Database.configFromEnv(process.env, environment)); + const pgConfig = Database.configFromEnv(process.env, environment); + const pgPool = Database.getPool(pgConfig, environment, logger); const metrics = setupMetrics(CHANNEL_NAMES, pgPool); From 911d7dbbf6884d3a67a074a595a5c26c6b8b5434 Mon Sep 17 00:00:00 2001 From: Eugen Rochko Date: Mon, 18 Nov 2024 10:37:01 +0100 Subject: [PATCH 41/64] Fix `min_id` and `max_id` causing error in search API (#32857) --- app/lib/search_query_transformer.rb | 20 ++++++++------------ lib/exceptions.rb | 1 - spec/lib/search_query_transformer_spec.rb | 2 +- 3 files changed, 9 insertions(+), 14 deletions(-) diff --git a/app/lib/search_query_transformer.rb b/app/lib/search_query_transformer.rb index 1306ed12ed..59352c6e6e 100644 --- a/app/lib/search_query_transformer.rb +++ b/app/lib/search_query_transformer.rb @@ -144,6 +144,8 @@ class SearchQueryTransformer < Parslet::Transform end class PrefixClause + EPOCH_RE = /\A\d+\z/ + attr_reader :operator, :prefix, :term def initialize(prefix, operator, term, options = {}) @@ -168,15 +170,15 @@ class SearchQueryTransformer < Parslet::Transform when 'before' @filter = :created_at @type = :range - @term = { lt: TermValidator.validate_date!(term), time_zone: @options[:current_account]&.user_time_zone.presence || 'UTC' } + @term = { lt: date_from_term(term), time_zone: @options[:current_account]&.user_time_zone.presence || 'UTC' } when 'after' @filter = :created_at @type = :range - @term = { gt: TermValidator.validate_date!(term), time_zone: @options[:current_account]&.user_time_zone.presence || 'UTC' } + @term = { gt: date_from_term(term), time_zone: @options[:current_account]&.user_time_zone.presence || 'UTC' } when 'during' @filter = :created_at @type = :range - @term = { gte: TermValidator.validate_date!(term), lte: TermValidator.validate_date!(term), time_zone: @options[:current_account]&.user_time_zone.presence || 'UTC' } + @term = { gte: date_from_term(term), lte: date_from_term(term), time_zone: @options[:current_account]&.user_time_zone.presence || 'UTC' } when 'in' @operator = :flag @term = term @@ -222,16 +224,10 @@ class SearchQueryTransformer < Parslet::Transform term end - end - class TermValidator - STRICT_DATE_REGEX = /\A\d{4}-\d{2}-\d{2}\z/ # yyyy-MM-dd - EPOCH_MILLIS_REGEX = /\A\d{1,19}\z/ - - def self.validate_date!(value) - return value if value.match?(STRICT_DATE_REGEX) || value.match?(EPOCH_MILLIS_REGEX) - - raise Mastodon::FilterValidationError, "Invalid date #{value}" + def date_from_term(term) + DateTime.iso8601(term) unless term.match?(EPOCH_RE) # This will raise Date::Error if the date is invalid + term end end diff --git a/lib/exceptions.rb b/lib/exceptions.rb index 1910d37a13..135f8126a4 100644 --- a/lib/exceptions.rb +++ b/lib/exceptions.rb @@ -8,7 +8,6 @@ module Mastodon class LengthValidationError < ValidationError; end class DimensionsValidationError < ValidationError; end class StreamValidationError < ValidationError; end - class FilterValidationError < ValidationError; end class RaceConditionError < Error; end class RateLimitExceededError < Error; end class SyntaxError < Error; end diff --git a/spec/lib/search_query_transformer_spec.rb b/spec/lib/search_query_transformer_spec.rb index 9399f3503d..b677d88ed0 100644 --- a/spec/lib/search_query_transformer_spec.rb +++ b/spec/lib/search_query_transformer_spec.rb @@ -34,7 +34,7 @@ RSpec.describe SearchQueryTransformer do let(:query) { "#{operator}:\"abc\"" } it 'raises an exception' do - expect { subject }.to raise_error(Mastodon::FilterValidationError, 'Invalid date abc') + expect { subject }.to raise_error(Date::Error) end end end From c0c34d35e22e5ac9c87a5bffff5b02b06f772f3a Mon Sep 17 00:00:00 2001 From: Matt Jankowski Date: Mon, 18 Nov 2024 04:57:16 -0500 Subject: [PATCH 42/64] Move self destruct check to `config_for` and add constant for verifier string (#32943) --- app/helpers/self_destruct_helper.rb | 6 ++++-- config/mastodon.yml | 1 + lib/mastodon/cli/federation.rb | 2 +- spec/helpers/self_destruct_helper_spec.rb | 22 +++++++++++++--------- 4 files changed, 19 insertions(+), 12 deletions(-) diff --git a/app/helpers/self_destruct_helper.rb b/app/helpers/self_destruct_helper.rb index 78557c25e5..f1927b1e04 100644 --- a/app/helpers/self_destruct_helper.rb +++ b/app/helpers/self_destruct_helper.rb @@ -1,9 +1,11 @@ # frozen_string_literal: true module SelfDestructHelper + VERIFY_PURPOSE = 'self-destruct' + def self.self_destruct? - value = ENV.fetch('SELF_DESTRUCT', nil) - value.present? && Rails.application.message_verifier('self-destruct').verify(value) == ENV['LOCAL_DOMAIN'] + value = Rails.configuration.x.mastodon.self_destruct_value + value.present? && Rails.application.message_verifier(VERIFY_PURPOSE).verify(value) == ENV['LOCAL_DOMAIN'] rescue ActiveSupport::MessageVerifier::InvalidSignature false end diff --git a/config/mastodon.yml b/config/mastodon.yml index 255213b4b7..2c09c59e0a 100644 --- a/config/mastodon.yml +++ b/config/mastodon.yml @@ -1,3 +1,4 @@ --- shared: + self_destruct_value: <%= ENV.fetch('SELF_DESTRUCT', nil) %> software_update_url: <%= ENV.fetch('UPDATE_CHECK_URL', 'https://api.joinmastodon.org/update-check') %> diff --git a/lib/mastodon/cli/federation.rb b/lib/mastodon/cli/federation.rb index c738796557..f512bca358 100644 --- a/lib/mastodon/cli/federation.rb +++ b/lib/mastodon/cli/federation.rb @@ -76,7 +76,7 @@ module Mastodon::CLI def self_destruct_value Rails .application - .message_verifier('self-destruct') + .message_verifier(SelfDestructHelper::VERIFY_PURPOSE) .generate(Rails.configuration.x.local_domain) end end diff --git a/spec/helpers/self_destruct_helper_spec.rb b/spec/helpers/self_destruct_helper_spec.rb index 09d7347eee..dca1590764 100644 --- a/spec/helpers/self_destruct_helper_spec.rb +++ b/spec/helpers/self_destruct_helper_spec.rb @@ -3,19 +3,20 @@ require 'rails_helper' RSpec.describe SelfDestructHelper do - describe 'self_destruct?' do + describe '#self_destruct?' do + before { Rails.configuration.x.mastodon.self_destruct_value = destruct_value } + after { Rails.configuration.x.mastodon.self_destruct_value = nil } + context 'when SELF_DESTRUCT is unset' do + let(:destruct_value) { nil } + it 'returns false' do expect(helper.self_destruct?).to be false end end context 'when SELF_DESTRUCT is set to an invalid value' do - around do |example| - ClimateControl.modify SELF_DESTRUCT: 'true' do - example.run - end - end + let(:destruct_value) { 'true' } it 'returns false' do expect(helper.self_destruct?).to be false @@ -23,9 +24,10 @@ RSpec.describe SelfDestructHelper do end context 'when SELF_DESTRUCT is set to value signed for the wrong purpose' do + let(:destruct_value) { Rails.configuration.x.mastodon.self_destruct_value = Rails.application.message_verifier('foo').generate('example.com') } + around do |example| ClimateControl.modify( - SELF_DESTRUCT: Rails.application.message_verifier('foo').generate('example.com'), LOCAL_DOMAIN: 'example.com' ) do example.run @@ -38,9 +40,10 @@ RSpec.describe SelfDestructHelper do end context 'when SELF_DESTRUCT is set to value signed for the wrong domain' do + let(:destruct_value) { Rails.configuration.x.mastodon.self_destruct_value = Rails.application.message_verifier(described_class::VERIFY_PURPOSE).generate('foo.com') } + around do |example| ClimateControl.modify( - SELF_DESTRUCT: Rails.application.message_verifier('self-destruct').generate('foo.com'), LOCAL_DOMAIN: 'example.com' ) do example.run @@ -53,9 +56,10 @@ RSpec.describe SelfDestructHelper do end context 'when SELF_DESTRUCT is set to a correctly-signed value' do + let(:destruct_value) { Rails.configuration.x.mastodon.self_destruct_value = Rails.application.message_verifier(described_class::VERIFY_PURPOSE).generate('example.com') } + around do |example| ClimateControl.modify( - SELF_DESTRUCT: Rails.application.message_verifier('self-destruct').generate('example.com'), LOCAL_DOMAIN: 'example.com' ) do example.run From 3e44dca0b4d914886dbd4132d5eadd43c4be4304 Mon Sep 17 00:00:00 2001 From: "Andrew W. Lee" Date: Mon, 18 Nov 2024 06:40:02 -0800 Subject: [PATCH 43/64] Change dependency from annotate to annotaterb (#30232) --- .annotaterb.yml | 59 +++++++++++++++++++++++++++++ Gemfile | 2 +- Gemfile.lock | 6 +-- lib/tasks/annotate_rb.rake | 10 +++++ lib/tasks/auto_annotate_models.rake | 46 ---------------------- 5 files changed, 72 insertions(+), 51 deletions(-) create mode 100644 .annotaterb.yml create mode 100644 lib/tasks/annotate_rb.rake delete mode 100644 lib/tasks/auto_annotate_models.rake diff --git a/.annotaterb.yml b/.annotaterb.yml new file mode 100644 index 0000000000..df8e92b247 --- /dev/null +++ b/.annotaterb.yml @@ -0,0 +1,59 @@ +--- +:position: before +:position_in_additional_file_patterns: before +:position_in_class: before +:position_in_factory: before +:position_in_fixture: before +:position_in_routes: before +:position_in_serializer: before +:position_in_test: before +:classified_sort: true +:exclude_controllers: true +:exclude_factories: true +:exclude_fixtures: true +:exclude_helpers: true +:exclude_scaffolds: true +:exclude_serializers: true +:exclude_sti_subclasses: true +:exclude_tests: true +:force: false +:format_markdown: false +:format_rdoc: false +:format_yard: false +:frozen: false +:ignore_model_sub_dir: false +:ignore_unknown_models: false +:include_version: false +:show_complete_foreign_keys: false +:show_foreign_keys: false +:show_indexes: false +:simple_indexes: false +:sort: false +:timestamp: false +:trace: false +:with_comment: true +:with_column_comments: true +:with_table_comments: true +:active_admin: false +:command: +:debug: false +:hide_default_column_types: '' +:hide_limit_column_types: 'integer,boolean' +:ignore_columns: +:ignore_routes: +:models: true +:routes: false +:skip_on_db_migrate: false +:target_action: :do_annotations +:wrapper: +:wrapper_close: +:wrapper_open: +:classes_default_to_s: [] +:additional_file_patterns: [] +:model_dir: + - app/models +:require: [] +:root_dir: + - '' + +:show_check_constraints: false diff --git a/Gemfile b/Gemfile index 47506929b0..c8104d094e 100644 --- a/Gemfile +++ b/Gemfile @@ -172,7 +172,7 @@ group :development do gem 'rubocop-rspec_rails', require: false # Annotates modules with schema - gem 'annotate', '~> 3.2' + gem 'annotaterb', '~> 4.13' # Enhanced error message pages for development gem 'better_errors', '~> 2.9' diff --git a/Gemfile.lock b/Gemfile.lock index c7ab4e66fe..09017e3fa9 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -90,9 +90,7 @@ GEM public_suffix (>= 2.0.2, < 7.0) aes_key_wrap (1.1.0) android_key_attestation (0.3.0) - annotate (3.2.0) - activerecord (>= 3.2, < 8.0) - rake (>= 10.4, < 14.0) + annotaterb (4.13.0) ast (2.4.2) attr_required (1.0.2) awrence (1.2.1) @@ -884,7 +882,7 @@ PLATFORMS DEPENDENCIES active_model_serializers (~> 0.10) addressable (~> 2.8) - annotate (~> 3.2) + annotaterb (~> 4.13) aws-sdk-s3 (~> 1.123) better_errors (~> 2.9) binding_of_caller (~> 1.0) diff --git a/lib/tasks/annotate_rb.rake b/lib/tasks/annotate_rb.rake new file mode 100644 index 0000000000..e8368b2e94 --- /dev/null +++ b/lib/tasks/annotate_rb.rake @@ -0,0 +1,10 @@ +# frozen_string_literal: true + +# This rake task was added by annotate_rb gem. + +# Can set `ANNOTATERB_SKIP_ON_DB_TASKS` to be anything to skip this +if Rails.env.development? && ENV['ANNOTATERB_SKIP_ON_DB_TASKS'].nil? + require 'annotate_rb' + + AnnotateRb::Core.load_rake_tasks +end diff --git a/lib/tasks/auto_annotate_models.rake b/lib/tasks/auto_annotate_models.rake deleted file mode 100644 index 4b5997920a..0000000000 --- a/lib/tasks/auto_annotate_models.rake +++ /dev/null @@ -1,46 +0,0 @@ -# frozen_string_literal: true - -if Rails.env.development? - task :set_annotation_options do - Annotate.set_defaults( - 'routes' => 'false', - 'models' => 'true', - 'position_in_routes' => 'before', - 'position_in_class' => 'before', - 'position_in_test' => 'before', - 'position_in_fixture' => 'before', - 'position_in_factory' => 'before', - 'position_in_serializer' => 'before', - 'show_foreign_keys' => 'false', - 'show_indexes' => 'false', - 'simple_indexes' => 'false', - 'model_dir' => 'app/models', - 'root_dir' => '', - 'include_version' => 'false', - 'require' => '', - 'exclude_tests' => 'true', - 'exclude_fixtures' => 'true', - 'exclude_factories' => 'true', - 'exclude_serializers' => 'true', - 'exclude_scaffolds' => 'true', - 'exclude_controllers' => 'true', - 'exclude_helpers' => 'true', - 'ignore_model_sub_dir' => 'false', - 'ignore_columns' => nil, - 'ignore_routes' => nil, - 'ignore_unknown_models' => 'false', - 'hide_limit_column_types' => 'integer,boolean', - 'skip_on_db_migrate' => 'false', - 'format_bare' => 'true', - 'format_rdoc' => 'false', - 'format_markdown' => 'false', - 'sort' => 'false', - 'force' => 'false', - 'trace' => 'false', - 'wrapper_open' => nil, - 'wrapper_close' => nil - ) - end - - Annotate.load_tasks -end From 477412d62a9b90c83cc56fdfa12b3e5af1c1c0bc Mon Sep 17 00:00:00 2001 From: Matt Jankowski Date: Mon, 18 Nov 2024 09:58:45 -0500 Subject: [PATCH 44/64] Use hash arguments to `select` when possible (Rails 7.2) (#32917) --- .../api/v1/accounts/familiar_followers_controller.rb | 2 +- app/lib/feed_manager.rb | 6 +++--- app/lib/importer/statuses_index_importer.rb | 2 +- app/models/status.rb | 10 +++++----- 4 files changed, 10 insertions(+), 10 deletions(-) diff --git a/app/controllers/api/v1/accounts/familiar_followers_controller.rb b/app/controllers/api/v1/accounts/familiar_followers_controller.rb index a49eb2eb27..81f0a9ed0f 100644 --- a/app/controllers/api/v1/accounts/familiar_followers_controller.rb +++ b/app/controllers/api/v1/accounts/familiar_followers_controller.rb @@ -12,7 +12,7 @@ class Api::V1::Accounts::FamiliarFollowersController < Api::BaseController private def set_accounts - @accounts = Account.without_suspended.where(id: account_ids).select('id, hide_collections') + @accounts = Account.without_suspended.where(id: account_ids).select(:id, :hide_collections) end def familiar_followers diff --git a/app/lib/feed_manager.rb b/app/lib/feed_manager.rb index 97cb25d58f..edd1162f4f 100644 --- a/app/lib/feed_manager.rb +++ b/app/lib/feed_manager.rb @@ -162,7 +162,7 @@ class FeedManager timeline_key = key(:home, into_account.id) timeline_status_ids = redis.zrange(timeline_key, 0, -1) - from_account.statuses.select('id, reblog_of_id').where(id: timeline_status_ids).reorder(nil).find_each do |status| + from_account.statuses.select(:id, :reblog_of_id).where(id: timeline_status_ids).reorder(nil).find_each do |status| remove_from_feed(:home, into_account.id, status, aggregate_reblogs: into_account.user&.aggregates_reblogs?) end end @@ -175,7 +175,7 @@ class FeedManager timeline_key = key(:list, list.id) timeline_status_ids = redis.zrange(timeline_key, 0, -1) - from_account.statuses.select('id, reblog_of_id').where(id: timeline_status_ids).reorder(nil).find_each do |status| + from_account.statuses.select(:id, :reblog_of_id).where(id: timeline_status_ids).reorder(nil).find_each do |status| remove_from_feed(:list, list.id, status, aggregate_reblogs: list.account.user&.aggregates_reblogs?) end end @@ -196,7 +196,7 @@ class FeedManager .where.not(account: into_account.following) .tagged_with_none(TagFollow.where(account: into_account).pluck(:tag_id)) - scope.select('id, reblog_of_id').reorder(nil).find_each do |status| + scope.select(:id, :reblog_of_id).reorder(nil).find_each do |status| remove_from_feed(:home, into_account.id, status, aggregate_reblogs: into_account.user&.aggregates_reblogs?) end end diff --git a/app/lib/importer/statuses_index_importer.rb b/app/lib/importer/statuses_index_importer.rb index 1922f65f6d..5c8a9f28c8 100644 --- a/app/lib/importer/statuses_index_importer.rb +++ b/app/lib/importer/statuses_index_importer.rb @@ -71,7 +71,7 @@ class Importer::StatusesIndexImporter < Importer::BaseImporter end def local_votes_scope - Poll.joins(:votes).where(votes: { account: Account.local }).select('polls.id, polls.status_id') + Poll.joins(:votes).where(votes: { account: Account.local }).select(polls: [:id, :status_id]) end def local_statuses_scope diff --git a/app/models/status.rb b/app/models/status.rb index c58de5114c..5a81b00773 100644 --- a/app/models/status.rb +++ b/app/models/status.rb @@ -356,23 +356,23 @@ class Status < ApplicationRecord end def favourites_map(status_ids, account_id) - Favourite.select('status_id').where(status_id: status_ids).where(account_id: account_id).each_with_object({}) { |f, h| h[f.status_id] = true } + Favourite.select(:status_id).where(status_id: status_ids).where(account_id: account_id).each_with_object({}) { |f, h| h[f.status_id] = true } end def bookmarks_map(status_ids, account_id) - Bookmark.select('status_id').where(status_id: status_ids).where(account_id: account_id).map { |f| [f.status_id, true] }.to_h + Bookmark.select(:status_id).where(status_id: status_ids).where(account_id: account_id).map { |f| [f.status_id, true] }.to_h end def reblogs_map(status_ids, account_id) - unscoped.select('reblog_of_id').where(reblog_of_id: status_ids).where(account_id: account_id).each_with_object({}) { |s, h| h[s.reblog_of_id] = true } + unscoped.select(:reblog_of_id).where(reblog_of_id: status_ids).where(account_id: account_id).each_with_object({}) { |s, h| h[s.reblog_of_id] = true } end def mutes_map(conversation_ids, account_id) - ConversationMute.select('conversation_id').where(conversation_id: conversation_ids).where(account_id: account_id).each_with_object({}) { |m, h| h[m.conversation_id] = true } + ConversationMute.select(:conversation_id).where(conversation_id: conversation_ids).where(account_id: account_id).each_with_object({}) { |m, h| h[m.conversation_id] = true } end def pins_map(status_ids, account_id) - StatusPin.select('status_id').where(status_id: status_ids).where(account_id: account_id).each_with_object({}) { |p, h| h[p.status_id] = true } + StatusPin.select(:status_id).where(status_id: status_ids).where(account_id: account_id).each_with_object({}) { |p, h| h[p.status_id] = true } end def from_text(text) From da826fe959ad58a747023483fadd50c400f5d90f Mon Sep 17 00:00:00 2001 From: Matt Jankowski Date: Mon, 18 Nov 2024 10:07:53 -0500 Subject: [PATCH 45/64] Use hash arguments to `order` when possible (Rails 7.2) (#32915) --- app/models/concerns/account/associations.rb | 2 +- app/models/concerns/account/interactions.rb | 12 ++++++------ app/models/instance_filter.rb | 4 ++-- app/models/tag.rb | 4 ++-- 4 files changed, 11 insertions(+), 11 deletions(-) diff --git a/app/models/concerns/account/associations.rb b/app/models/concerns/account/associations.rb index 4e29235b6b..cafb2d151c 100644 --- a/app/models/concerns/account/associations.rb +++ b/app/models/concerns/account/associations.rb @@ -48,7 +48,7 @@ module Account::Associations end # Status records pinned by the account - has_many :pinned_statuses, -> { reorder('status_pins.created_at DESC') }, through: :status_pins, class_name: 'Status', source: :status + has_many :pinned_statuses, -> { reorder(status_pins: { created_at: :desc }) }, through: :status_pins, class_name: 'Status', source: :status # Account records endorsed (pinned) by the account has_many :endorsed_accounts, through: :account_pins, class_name: 'Account', source: :target_account diff --git a/app/models/concerns/account/interactions.rb b/app/models/concerns/account/interactions.rb index 536afba17f..6f6b8c16d0 100644 --- a/app/models/concerns/account/interactions.rb +++ b/app/models/concerns/account/interactions.rb @@ -80,8 +80,8 @@ module Account::Interactions has_many :passive_relationships, foreign_key: 'target_account_id', inverse_of: :target_account end - has_many :following, -> { order('follows.id desc') }, through: :active_relationships, source: :target_account - has_many :followers, -> { order('follows.id desc') }, through: :passive_relationships, source: :account + has_many :following, -> { order(follows: { id: :desc }) }, through: :active_relationships, source: :target_account + has_many :followers, -> { order(follows: { id: :desc }) }, through: :passive_relationships, source: :account with_options class_name: 'SeveredRelationship', dependent: :destroy do has_many :severed_relationships, foreign_key: 'local_account_id', inverse_of: :local_account @@ -96,16 +96,16 @@ module Account::Interactions has_many :block_relationships, foreign_key: 'account_id', inverse_of: :account has_many :blocked_by_relationships, foreign_key: :target_account_id, inverse_of: :target_account end - has_many :blocking, -> { order('blocks.id desc') }, through: :block_relationships, source: :target_account - has_many :blocked_by, -> { order('blocks.id desc') }, through: :blocked_by_relationships, source: :account + has_many :blocking, -> { order(blocks: { id: :desc }) }, through: :block_relationships, source: :target_account + has_many :blocked_by, -> { order(blocks: { id: :desc }) }, through: :blocked_by_relationships, source: :account # Mute relationships with_options class_name: 'Mute', dependent: :destroy do has_many :mute_relationships, foreign_key: 'account_id', inverse_of: :account has_many :muted_by_relationships, foreign_key: :target_account_id, inverse_of: :target_account end - has_many :muting, -> { order('mutes.id desc') }, through: :mute_relationships, source: :target_account - has_many :muted_by, -> { order('mutes.id desc') }, through: :muted_by_relationships, source: :account + has_many :muting, -> { order(mutes: { id: :desc }) }, through: :mute_relationships, source: :target_account + has_many :muted_by, -> { order(mutes: { id: :desc }) }, through: :muted_by_relationships, source: :account has_many :conversation_mutes, dependent: :destroy has_many :domain_blocks, class_name: 'AccountDomainBlock', dependent: :destroy has_many :announcement_mutes, dependent: :destroy diff --git a/app/models/instance_filter.rb b/app/models/instance_filter.rb index 1d94c919f9..7e71640e52 100644 --- a/app/models/instance_filter.rb +++ b/app/models/instance_filter.rb @@ -28,9 +28,9 @@ class InstanceFilter def scope_for(key, value) case key.to_s when 'limited' - Instance.joins(:domain_block).reorder(Arel.sql('domain_blocks.id desc')) + Instance.joins(:domain_block).reorder(domain_blocks: { id: :desc }) when 'allowed' - Instance.joins(:domain_allow).reorder(Arel.sql('domain_allows.id desc')) + Instance.joins(:domain_allow).reorder(domain_allows: { id: :desc }) when 'by_domain' Instance.matches_domain(value) when 'availability' diff --git a/app/models/tag.rb b/app/models/tag.rb index 93210eb307..67fa9e5d3a 100644 --- a/app/models/tag.rb +++ b/app/models/tag.rb @@ -61,7 +61,7 @@ class Tag < ApplicationRecord scope :recently_used, lambda { |account| joins(:statuses) .where(statuses: { id: account.statuses.select(:id).limit(RECENT_STATUS_LIMIT) }) - .group(:id).order(Arel.sql('count(*) desc')) + .group(:id).order(Arel.star.count.desc) } scope :matches_name, ->(term) { where(arel_table[:name].lower.matches(arel_table.lower("#{sanitize_sql_like(Tag.normalize(term))}%"), nil, true)) } # Search with case-sensitive to use B-tree index @@ -127,7 +127,7 @@ class Tag < ApplicationRecord query = query.merge(Tag.listable) if options[:exclude_unlistable] query = query.merge(matching_name(stripped_term).or(reviewed)) if options[:exclude_unreviewed] - query.order(Arel.sql('length(name) ASC, name ASC')) + query.order(Arel.sql('LENGTH(name)').asc, name: :asc) .limit(limit) .offset(offset) end From 30a79865698b1fbef2b1a6e818ce6984db68d551 Mon Sep 17 00:00:00 2001 From: Matt Jankowski Date: Mon, 18 Nov 2024 10:42:45 -0500 Subject: [PATCH 46/64] Add coverage for fixing the thing with the dates in the search area (#32958) --- spec/lib/search_query_transformer_spec.rb | 1 + 1 file changed, 1 insertion(+) diff --git a/spec/lib/search_query_transformer_spec.rb b/spec/lib/search_query_transformer_spec.rb index b677d88ed0..b69e3afc9d 100644 --- a/spec/lib/search_query_transformer_spec.rb +++ b/spec/lib/search_query_transformer_spec.rb @@ -16,6 +16,7 @@ RSpec.describe SearchQueryTransformer do ['"2022-01-01"', '2022-01-01'], ['12345678', '12345678'], ['"12345678"', '12345678'], + ['"2024-10-31T23:47:20Z"', '2024-10-31T23:47:20Z'], ].each do |value, parsed| context "with #{operator}:#{value}" do let(:query) { "#{operator}:#{value}" } From 295ad6f19a016b3f16e1201ffcbb1b3ad6b455a2 Mon Sep 17 00:00:00 2001 From: Matt Jankowski Date: Mon, 18 Nov 2024 11:37:21 -0500 Subject: [PATCH 47/64] Prep work for coverage addition to `ActivityPub::DeliveryWorker` spec (#32944) --- .../activitypub/delivery_worker_spec.rb | 41 ++++++++++++++----- 1 file changed, 30 insertions(+), 11 deletions(-) diff --git a/spec/workers/activitypub/delivery_worker_spec.rb b/spec/workers/activitypub/delivery_worker_spec.rb index 3dfbef31a4..9e6805c68b 100644 --- a/spec/workers/activitypub/delivery_worker_spec.rb +++ b/spec/workers/activitypub/delivery_worker_spec.rb @@ -5,26 +5,45 @@ require 'rails_helper' RSpec.describe ActivityPub::DeliveryWorker do include RoutingHelper - subject { described_class.new } - - let(:sender) { Fabricate(:account) } + let(:sender) { Fabricate(:account) } let(:payload) { 'test' } + let(:url) { 'https://example.com/api' } before do - allow(sender).to receive(:remote_followers_hash).with('https://example.com/api').and_return('somehash') + allow(sender).to receive(:remote_followers_hash).with(url).and_return('somehash') allow(Account).to receive(:find).with(sender.id).and_return(sender) end describe 'perform' do - it 'performs a request' do - stub_request(:post, 'https://example.com/api').to_return(status: 200) - subject.perform(payload, sender.id, 'https://example.com/api', { synchronize_followers: true }) - expect(a_request(:post, 'https://example.com/api').with(headers: { 'Collection-Synchronization' => "collectionId=\"#{account_followers_url(sender)}\", digest=\"somehash\", url=\"#{account_followers_synchronization_url(sender)}\"" })).to have_been_made.once + context 'with successful request' do + before { stub_request(:post, url).to_return(status: 200) } + + it 'performs a request to synchronize collection' do + subject.perform(payload, sender.id, url, { synchronize_followers: true }) + + expect(request_to_url) + .to have_been_made.once + end + + def request_to_url + a_request(:post, url) + .with( + headers: { + 'Collection-Synchronization' => <<~VALUES.squish, + collectionId="#{account_followers_url(sender)}", digest="somehash", url="#{account_followers_synchronization_url(sender)}" + VALUES + } + ) + end end - it 'raises when request fails' do - stub_request(:post, 'https://example.com/api').to_return(status: 500) - expect { subject.perform(payload, sender.id, 'https://example.com/api') }.to raise_error Mastodon::UnexpectedResponseError + context 'with failing request' do + before { stub_request(:post, url).to_return(status: 500) } + + it 'raises error' do + expect { subject.perform(payload, sender.id, url) } + .to raise_error Mastodon::UnexpectedResponseError + end end end end From 425982841d66734f9f07f393334711454b42def2 Mon Sep 17 00:00:00 2001 From: Matt Jankowski Date: Tue, 19 Nov 2024 03:51:34 -0500 Subject: [PATCH 48/64] Use group/count approach in annual report classes (#32914) --- .../commonly_interacted_with_accounts.rb | 2 +- app/lib/annual_report/most_reblogged_accounts.rb | 2 +- app/lib/annual_report/most_used_apps.rb | 2 +- app/lib/annual_report/top_hashtags.rb | 8 +++++++- .../commonly_interacted_with_accounts_spec.rb | 13 +++++++++++-- .../annual_report/most_reblogged_accounts_spec.rb | 12 ++++++++++-- spec/lib/annual_report/most_used_apps_spec.rb | 11 ++++++++--- spec/lib/annual_report/top_hashtags_spec.rb | 15 +++++++++++++-- 8 files changed, 52 insertions(+), 13 deletions(-) diff --git a/app/lib/annual_report/commonly_interacted_with_accounts.rb b/app/lib/annual_report/commonly_interacted_with_accounts.rb index 30ab671d8a..2316789f2a 100644 --- a/app/lib/annual_report/commonly_interacted_with_accounts.rb +++ b/app/lib/annual_report/commonly_interacted_with_accounts.rb @@ -17,6 +17,6 @@ class AnnualReport::CommonlyInteractedWithAccounts < AnnualReport::Source private def commonly_interacted_with_accounts - report_statuses.where.not(in_reply_to_account_id: @account.id).group(:in_reply_to_account_id).having('count(*) > 1').order(total: :desc).limit(SET_SIZE).pluck(Arel.sql('in_reply_to_account_id, count(*) AS total')) + report_statuses.where.not(in_reply_to_account_id: @account.id).group(:in_reply_to_account_id).having('count(*) > 1').order(count_all: :desc).limit(SET_SIZE).count end end diff --git a/app/lib/annual_report/most_reblogged_accounts.rb b/app/lib/annual_report/most_reblogged_accounts.rb index cfc4022ca7..5c750b19bf 100644 --- a/app/lib/annual_report/most_reblogged_accounts.rb +++ b/app/lib/annual_report/most_reblogged_accounts.rb @@ -17,6 +17,6 @@ class AnnualReport::MostRebloggedAccounts < AnnualReport::Source private def most_reblogged_accounts - report_statuses.where.not(reblog_of_id: nil).joins(reblog: :account).group('accounts.id').having('count(*) > 1').order(total: :desc).limit(SET_SIZE).pluck(Arel.sql('accounts.id, count(*) as total')) + report_statuses.where.not(reblog_of_id: nil).joins(reblog: :account).group('accounts.id').having('count(*) > 1').order(count_all: :desc).limit(SET_SIZE).count end end diff --git a/app/lib/annual_report/most_used_apps.rb b/app/lib/annual_report/most_used_apps.rb index fb1ca1d167..e10ba52503 100644 --- a/app/lib/annual_report/most_used_apps.rb +++ b/app/lib/annual_report/most_used_apps.rb @@ -17,6 +17,6 @@ class AnnualReport::MostUsedApps < AnnualReport::Source private def most_used_apps - report_statuses.joins(:application).group('oauth_applications.name').order(total: :desc).limit(SET_SIZE).pluck(Arel.sql('oauth_applications.name, count(*) as total')) + report_statuses.joins(:application).group('oauth_applications.name').order(count_all: :desc).limit(SET_SIZE).count end end diff --git a/app/lib/annual_report/top_hashtags.rb b/app/lib/annual_report/top_hashtags.rb index 32bd10d698..ae000a8beb 100644 --- a/app/lib/annual_report/top_hashtags.rb +++ b/app/lib/annual_report/top_hashtags.rb @@ -17,6 +17,12 @@ class AnnualReport::TopHashtags < AnnualReport::Source private def top_hashtags - Tag.joins(:statuses).where(statuses: { id: report_statuses.select(:id) }).group(:id).having('count(*) > 1').order(total: :desc).limit(SET_SIZE).pluck(Arel.sql('COALESCE(tags.display_name, tags.name), count(*) AS total')) + Tag.joins(:statuses).where(statuses: { id: report_statuses.select(:id) }).group(coalesced_tag_names).having('count(*) > 1').order(count_all: :desc).limit(SET_SIZE).count + end + + def coalesced_tag_names + Arel.sql(<<~SQL.squish) + COALESCE(tags.display_name, tags.name) + SQL end end diff --git a/spec/lib/annual_report/commonly_interacted_with_accounts_spec.rb b/spec/lib/annual_report/commonly_interacted_with_accounts_spec.rb index 0e31827912..12bf3810db 100644 --- a/spec/lib/annual_report/commonly_interacted_with_accounts_spec.rb +++ b/spec/lib/annual_report/commonly_interacted_with_accounts_spec.rb @@ -21,18 +21,27 @@ RSpec.describe AnnualReport::CommonlyInteractedWithAccounts do let(:account) { Fabricate :account } let(:other_account) { Fabricate :account } + let(:most_other_account) { Fabricate :account } before do _other = Fabricate :status + Fabricate :status, account: account, reply: true, in_reply_to_id: Fabricate(:status, account: other_account).id Fabricate :status, account: account, reply: true, in_reply_to_id: Fabricate(:status, account: other_account).id + + Fabricate :status, account: account, reply: true, in_reply_to_id: Fabricate(:status, account: most_other_account).id + Fabricate :status, account: account, reply: true, in_reply_to_id: Fabricate(:status, account: most_other_account).id + Fabricate :status, account: account, reply: true, in_reply_to_id: Fabricate(:status, account: most_other_account).id end it 'builds a report for an account' do expect(subject.generate) .to include( - commonly_interacted_with_accounts: contain_exactly( - include(account_id: other_account.id.to_s, count: 2) + commonly_interacted_with_accounts: eq( + [ + { account_id: most_other_account.id.to_s, count: 3 }, + { account_id: other_account.id.to_s, count: 2 }, + ] ) ) end diff --git a/spec/lib/annual_report/most_reblogged_accounts_spec.rb b/spec/lib/annual_report/most_reblogged_accounts_spec.rb index 2f04934e47..956549c325 100644 --- a/spec/lib/annual_report/most_reblogged_accounts_spec.rb +++ b/spec/lib/annual_report/most_reblogged_accounts_spec.rb @@ -21,18 +21,26 @@ RSpec.describe AnnualReport::MostRebloggedAccounts do let(:account) { Fabricate :account } let(:other_account) { Fabricate :account } + let(:most_other_account) { Fabricate :account } before do _other = Fabricate :status Fabricate :status, account: account, reblog: Fabricate(:status, account: other_account) Fabricate :status, account: account, reblog: Fabricate(:status, account: other_account) + + Fabricate :status, account: account, reblog: Fabricate(:status, account: most_other_account) + Fabricate :status, account: account, reblog: Fabricate(:status, account: most_other_account) + Fabricate :status, account: account, reblog: Fabricate(:status, account: most_other_account) end it 'builds a report for an account' do expect(subject.generate) .to include( - most_reblogged_accounts: contain_exactly( - include(account_id: other_account.id.to_s, count: 2) + most_reblogged_accounts: eq( + [ + { account_id: most_other_account.id.to_s, count: 3 }, + { account_id: other_account.id.to_s, count: 2 }, + ] ) ) end diff --git a/spec/lib/annual_report/most_used_apps_spec.rb b/spec/lib/annual_report/most_used_apps_spec.rb index d2fcecc4d8..ab7022ef20 100644 --- a/spec/lib/annual_report/most_used_apps_spec.rb +++ b/spec/lib/annual_report/most_used_apps_spec.rb @@ -20,18 +20,23 @@ RSpec.describe AnnualReport::MostUsedApps do context 'with an active account' do let(:account) { Fabricate :account } - let(:application) { Fabricate :application } + let(:application) { Fabricate :application, name: 'App' } + let(:most_application) { Fabricate :application, name: 'Most App' } before do _other = Fabricate :status Fabricate.times 2, :status, account: account, application: application + Fabricate.times 3, :status, account: account, application: most_application end it 'builds a report for an account' do expect(subject.generate) .to include( - most_used_apps: contain_exactly( - include(name: application.name, count: 2) + most_used_apps: eq( + [ + { name: most_application.name, count: 3 }, + { name: application.name, count: 2 }, + ] ) ) end diff --git a/spec/lib/annual_report/top_hashtags_spec.rb b/spec/lib/annual_report/top_hashtags_spec.rb index 58a9152184..b9cc9392ed 100644 --- a/spec/lib/annual_report/top_hashtags_spec.rb +++ b/spec/lib/annual_report/top_hashtags_spec.rb @@ -21,20 +21,31 @@ RSpec.describe AnnualReport::TopHashtags do let(:account) { Fabricate :account } let(:tag) { Fabricate :tag } + let(:most_tag) { Fabricate :tag } before do _other = Fabricate :status + first = Fabricate :status, account: account first.tags << tag + first.tags << most_tag + last = Fabricate :status, account: account last.tags << tag + last.tags << most_tag + + middle = Fabricate :status, account: account + middle.tags << most_tag end it 'builds a report for an account' do expect(subject.generate) .to include( - top_hashtags: contain_exactly( - include(name: tag.name, count: 2) + top_hashtags: eq( + [ + { name: most_tag.name, count: 3 }, + { name: tag.name, count: 2 }, + ] ) ) end From 06fcee099a7a3751aa3ffd4cf743509c7d591129 Mon Sep 17 00:00:00 2001 From: Shlee Date: Tue, 19 Nov 2024 08:54:28 +0000 Subject: [PATCH 49/64] DB Replica database_tasks as ENV (#32908) --- config/database.yml | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/config/database.yml b/config/database.yml index 2898415d80..eba20e849f 100644 --- a/config/database.yml +++ b/config/database.yml @@ -55,10 +55,11 @@ production: prepared_statements: <%= ENV['PREPARED_STATEMENTS'] || 'true' %> replica: <<: *default - database: <%= ENV['REPLICA_DB_NAME'] ||ENV['DB_NAME'] || 'mastodon_production' %> - username: <%= ENV['REPLICA_DB_USER'] ||ENV['DB_USER'] || 'mastodon' %> + database: <%= ENV['REPLICA_DB_NAME'] || ENV['DB_NAME'] || 'mastodon_production' %> + username: <%= ENV['REPLICA_DB_USER'] || ENV['DB_USER'] || 'mastodon' %> password: <%= (ENV['REPLICA_DB_PASS'] || ENV['DB_PASS'] || '').to_json %> - host: <%= ENV['REPLICA_DB_HOST'] ||ENV['DB_HOST'] || 'localhost' %> - port: <%= ENV['REPLICA_DB_PORT'] ||ENV['DB_PORT'] || 5432 %> - prepared_statements: <%= ENV['PREPARED_STATEMENTS'] || 'true' %> + host: <%= ENV['REPLICA_DB_HOST'] || ENV['DB_HOST'] || 'localhost' %> + port: <%= ENV['REPLICA_DB_PORT'] || ENV['DB_PORT'] || 5432 %> + prepared_statements: <%= ENV['REPLICA_PREPARED_STATEMENTS'] || ENV['PREPARED_STATEMENTS'] || 'true' %> replica: true + database_tasks: <%= ENV['REPLICA_DB_TASKS'] || 'true' %> From e856838e0c971a661e732ef6f221afc800d894a6 Mon Sep 17 00:00:00 2001 From: Eugen Rochko Date: Tue, 19 Nov 2024 09:57:12 +0100 Subject: [PATCH 50/64] Fix notification polling showing a loading bar in web UI (#32960) --- app/javascript/mastodon/actions/notification_groups.ts | 3 +++ 1 file changed, 3 insertions(+) diff --git a/app/javascript/mastodon/actions/notification_groups.ts b/app/javascript/mastodon/actions/notification_groups.ts index a3c8095ac4..aa7f50da4e 100644 --- a/app/javascript/mastodon/actions/notification_groups.ts +++ b/app/javascript/mastodon/actions/notification_groups.ts @@ -141,6 +141,9 @@ export const pollRecentNotifications = createDataLoadingThunk( return { notifications }; }, + { + useLoadingBar: false, + }, ); export const processNewNotificationForGroups = createAppAsyncThunk( From 436a5d295b3412300042073fb06ac1cdcc959834 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Tue, 19 Nov 2024 08:57:47 +0000 Subject: [PATCH 51/64] Update dependency aws-sdk-s3 to v1.172.0 (#32964) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- Gemfile.lock | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/Gemfile.lock b/Gemfile.lock index 09017e3fa9..d1be469f48 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -95,16 +95,16 @@ GEM attr_required (1.0.2) awrence (1.2.1) aws-eventstream (1.3.0) - aws-partitions (1.1008.0) + aws-partitions (1.1009.0) aws-sdk-core (3.213.0) aws-eventstream (~> 1, >= 1.3.0) aws-partitions (~> 1, >= 1.992.0) aws-sigv4 (~> 1.9) jmespath (~> 1, >= 1.6.1) - aws-sdk-kms (1.95.0) + aws-sdk-kms (1.96.0) aws-sdk-core (~> 3, >= 3.210.0) aws-sigv4 (~> 1.5) - aws-sdk-s3 (1.171.0) + aws-sdk-s3 (1.172.0) aws-sdk-core (~> 3, >= 3.210.0) aws-sdk-kms (~> 1) aws-sigv4 (~> 1.5) From 9fc2fc2251334f8b4d7d62a0aaf3a097e723d927 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Tue, 19 Nov 2024 10:05:39 +0100 Subject: [PATCH 52/64] New Crowdin Translations (automated) (#32969) Co-authored-by: GitHub Actions --- app/javascript/mastodon/locales/bg.json | 5 ++++- app/javascript/mastodon/locales/de.json | 2 +- app/javascript/mastodon/locales/it.json | 1 + config/locales/bg.yml | 10 ++++++++++ config/locales/it.yml | 8 ++++++++ config/locales/tr.yml | 6 +++--- 6 files changed, 27 insertions(+), 5 deletions(-) diff --git a/app/javascript/mastodon/locales/bg.json b/app/javascript/mastodon/locales/bg.json index 8f99992f33..456247cedf 100644 --- a/app/javascript/mastodon/locales/bg.json +++ b/app/javascript/mastodon/locales/bg.json @@ -87,6 +87,7 @@ "alert.unexpected.title": "Опаа!", "alt_text_badge.title": "Алтернативен текст", "announcement.announcement": "Оповестяване", + "annual_report.summary.archetype.booster": "Якият подсилвател", "annual_report.summary.archetype.lurker": "Дебнещото", "annual_report.summary.archetype.oracle": "Оракул", "annual_report.summary.archetype.pollster": "Анкетьорче", @@ -95,12 +96,14 @@ "annual_report.summary.followers.total": "{count} общо", "annual_report.summary.here_it_is": "Ето преглед на вашата {year} година:", "annual_report.summary.highlighted_post.by_favourites": "най-правено като любима публикация", + "annual_report.summary.highlighted_post.by_reblogs": "най-подсилваната публикация", "annual_report.summary.highlighted_post.by_replies": "публикации с най-много отговори", "annual_report.summary.highlighted_post.possessive": "на {name}", "annual_report.summary.most_used_app.most_used_app": "най-употребявано приложение", "annual_report.summary.most_used_hashtag.most_used_hashtag": "най-употребяван хаштаг", "annual_report.summary.new_posts.new_posts": "нови публикации", "annual_report.summary.percentile.text": "Това ви слага най-отгоресред потребителите на Mastodon.", + "annual_report.summary.percentile.we_wont_tell_bernie": "Няма да кажем на Бърни Сандърс.", "annual_report.summary.thanks": "Благодарим, че сте част от Mastodon!", "attachments_list.unprocessed": "(необработено)", "audio.hide": "Скриване на звука", @@ -638,7 +641,7 @@ "onboarding.steps.follow_people.title": "Персонализиране на началния ви инфоканал", "onboarding.steps.publish_status.body": "Поздравете целия свят.", "onboarding.steps.publish_status.title": "Направете първата си публикация", - "onboarding.steps.setup_profile.body": "Други са по-вероятно да взаимодействат с вас с попълнения профил.", + "onboarding.steps.setup_profile.body": "Подсилете взаимодействията си, имайки изчерпателен профил.", "onboarding.steps.setup_profile.title": "Пригодете профила си", "onboarding.steps.share_profile.body": "Позволете на приятелите си да знаят как да ви намират в Mastodon!", "onboarding.steps.share_profile.title": "Споделяне на профила ви", diff --git a/app/javascript/mastodon/locales/de.json b/app/javascript/mastodon/locales/de.json index f692681387..510cc821f3 100644 --- a/app/javascript/mastodon/locales/de.json +++ b/app/javascript/mastodon/locales/de.json @@ -688,7 +688,7 @@ "poll_button.remove_poll": "Umfrage entfernen", "privacy.change": "Sichtbarkeit anpassen", "privacy.direct.long": "Alle in diesem Beitrag erwähnten Profile", - "privacy.direct.short": "Bestimmte Profile", + "privacy.direct.short": "Ausgewählte Profile", "privacy.private.long": "Nur deine Follower", "privacy.private.short": "Follower", "privacy.public.long": "Alle in und außerhalb von Mastodon", diff --git a/app/javascript/mastodon/locales/it.json b/app/javascript/mastodon/locales/it.json index 06779d337c..c4fcbdc3a4 100644 --- a/app/javascript/mastodon/locales/it.json +++ b/app/javascript/mastodon/locales/it.json @@ -88,6 +88,7 @@ "alt_text_badge.title": "Testo alternativo", "announcement.announcement": "Annuncio", "annual_report.summary.archetype.oracle": "L'oracolo", + "annual_report.summary.archetype.pollster": "Sondaggista", "annual_report.summary.followers.followers": "seguaci", "annual_report.summary.followers.total": "{count} in totale", "annual_report.summary.here_it_is": "Ecco il tuo {year} in sintesi:", diff --git a/config/locales/bg.yml b/config/locales/bg.yml index 5688a44f91..20ee1f6c68 100644 --- a/config/locales/bg.yml +++ b/config/locales/bg.yml @@ -807,6 +807,7 @@ bg: original_status: Първообразна публикация reblogs: Блогване пак status_changed: Публикацията променена + title: Публикации на акаунт - @%{name} trending: Изгряващи visibility: Видимост with_media: С мултимедия @@ -1104,8 +1105,10 @@ bg: security: Сигурност set_new_password: Задаване на нова парола setup: + email_below_hint_html: Проверете папката си за спам или поискайте друго е-писмо. Може да поправите адреса на имейла си, ако е грешен. email_settings_hint_html: Щракнете на връзката за потвърждаване, която ви изпратихме до %{email}. Ще ви почакаме тук. link_not_received: Не получихте ли връзка? + new_confirmation_instructions_sent: До няколко минути ще получите друго е-писмо с връзка за потвърждаване! title: Проверете входящата си поща sign_in: preamble_html: Влезте с идентификационните данни за %{domain}. Ако вашият акаунт е хостван на различен сървър, няма да можете да влезете в този. @@ -1116,6 +1119,7 @@ bg: title: Първоначални настройки за %{domain}. status: account_status: Състояние на акаунта + confirming: Чака се потвърждението на имейла да завърши. functional: Вашият акаунт е в изправност. pending: Вашето приложение чака преглед от персонала ни. Това може да отнеме време. Ще получите е-писмо, ако приложението ви се одобри. redirecting_to: Вашият акаунт е бездеен, защото сега се пренасочва към %{acct}. @@ -1125,6 +1129,8 @@ bg: use_security_key: Употреба на ключ за сигурност author_attribution: example_title: Примерен текст + hint_html: Пишете ли новинарски статии или блогове извън Mastodon? Управлявайте как ви приписват авторството, когато са споделени в Mastodon. + instructions: 'Уверете се, че този код е в HTML на статията ви:' more_from_html: Още от %{name} s_blog: Блогът на %{name} then_instructions: Тогава добавете име на домейна на публикацията в долното поле. @@ -1165,6 +1171,9 @@ bg: before: 'Прочетете внимателно тези бележки преди да продължите:' caches: Съдържание, което може да е кеширано от други сървъри, може да се задържи data_removal: Ваши публикации и други данни ще бъдат завинаги премахнати + email_change_html: Може да промените адреса на имейла си, без да изтривате акаунта си + email_contact_html: Ако още не сте го получили, то обърнете се за помощ към %{email} + email_reconfirmation_html: Ако не сте получили е-писмо за потвърждение, може да го заявите отново irreversible: Няма да може да възстановите или да задействате пак акаунта си more_details_html: За повече детайли прегледайте декларацията за поверителност. username_available: Вашето потребителско име ще стане налично отново @@ -1392,6 +1401,7 @@ bg: unsubscribe: action: Да, да се спре абонамента complete: Спрян абонамент + confirmation_html: Наистина ли искате да спрете абонамента от получаването на %{type} за Mastodon в %{domain} към имейла си при %{email}? Може винаги пак да се абонирате от своите настройки за известяване по е-поща. title: Спиране на абонамента media_attachments: validations: diff --git a/config/locales/it.yml b/config/locales/it.yml index 4c083fd006..3b36bd3f7a 100644 --- a/config/locales/it.yml +++ b/config/locales/it.yml @@ -187,6 +187,7 @@ it: create_domain_block: Crea Blocco del Dominio create_email_domain_block: Crea blocco del dominio e-mail create_ip_block: Crea regola IP + create_relay: Crea Relay create_unavailable_domain: Crea Dominio Non Disponibile create_user_role: Crea Ruolo demote_user: Retrocedi Utente @@ -198,14 +199,17 @@ it: destroy_email_domain_block: Elimina il blocco del dominio e-mail destroy_instance: Elimina Dominio destroy_ip_block: Elimina regola IP + destroy_relay: Elimina Relay destroy_status: Elimina Toot destroy_unavailable_domain: Elimina Dominio Non Disponibile destroy_user_role: Distruggi Ruolo disable_2fa_user: Disabilita A2F disable_custom_emoji: Disabilita Emoji Personalizzata + disable_relay: Disabilita Relay disable_sign_in_token_auth_user: Disabilita l'autenticazione del token e-mail per l'utente disable_user: Disabilita l'Utente enable_custom_emoji: Abilita Emoji Personalizzata + enable_relay: Abilita Relay enable_sign_in_token_auth_user: Abilita l'autenticazione del token e-mail per l'utente enable_user: Abilita l'Utente memorialize_account: Commemora Profilo @@ -247,6 +251,7 @@ it: create_domain_block_html: "%{name} ha bloccato il dominio %{target}" create_email_domain_block_html: "%{name} ha bloccato il dominio e-mail %{target}" create_ip_block_html: "%{name} ha creato una regola per l'IP %{target}" + create_relay_html: "%{name} ha creato un relay %{target}" create_unavailable_domain_html: "%{name} ha interrotto la consegna al dominio %{target}" create_user_role_html: "%{name} ha creato il ruolo %{target}" demote_user_html: "%{name} ha retrocesso l'utente %{target}" @@ -258,14 +263,17 @@ it: destroy_email_domain_block_html: "%{name} ha sbloccato il dominio e-mail %{target}" destroy_instance_html: "%{name} ha eliminato il dominio %{target}" destroy_ip_block_html: "%{name} ha eliminato la regola per l'IP %{target}" + destroy_relay_html: "%{name} ha eliminato il relay %{target}" destroy_status_html: "%{name} ha rimosso il toot di %{target}" destroy_unavailable_domain_html: "%{name} ha ripreso la consegna al dominio %{target}" destroy_user_role_html: "%{name} ha eliminato il ruolo %{target}" disable_2fa_user_html: "%{name} ha disabilitato l'autenticazione a due fattori per l'utente %{target}" disable_custom_emoji_html: "%{name} ha disabilitato emoji %{target}" + disable_relay_html: "%{name} ha disabilitato il relay %{target}" disable_sign_in_token_auth_user_html: "%{name} ha disabilitato l'autenticazione del token e-mail per %{target}" disable_user_html: "%{name} ha disabilitato l'accesso per l'utente %{target}" enable_custom_emoji_html: "%{name} ha abilitato l'emoji %{target}" + enable_relay_html: "%{name} ha abilitato il relay %{target}" enable_sign_in_token_auth_user_html: "%{name} ha abilitato l'autenticazione del token e-mail per %{target}" enable_user_html: "%{name} ha abilitato l'accesso per l'utente %{target}" memorialize_account_html: "%{name} ha trasformato il profilo di %{target} in una pagina commemorativa" diff --git a/config/locales/tr.yml b/config/locales/tr.yml index a0002070c6..48f6c5e240 100644 --- a/config/locales/tr.yml +++ b/config/locales/tr.yml @@ -826,7 +826,7 @@ tr: back_to_account: Hesap sayfasına geri dön back_to_report: Bildirim sayfasına geri dön batch: - add_to_report: 'Rapora ekle #%{id}' + add_to_report: "#%{id} raporuna ekle" remove_from_report: Bildirimden kaldır report: Bildirim contents: İçerikler @@ -845,10 +845,10 @@ tr: reblogs: Yeniden Paylaşımlar replied_to_html: Yanıtladı %{acct_link} status_changed: Gönderi değişti - status_title: Gönderen @%{name} + status_title: "@%{name} gönderisi" title: Hesap gönderileri - @%{name} trending: Öne çıkanlar - view_publicly: Herkese Açık Görüntüle + view_publicly: Herkese açık görüntüle visibility: Görünürlük with_media: Medya ile strikes: From 87e7ad9b8f456af52197fb43116a7d104d697bfb Mon Sep 17 00:00:00 2001 From: Matt Jankowski Date: Tue, 19 Nov 2024 04:15:05 -0500 Subject: [PATCH 53/64] Add `LoginActivity` model spec and `BrowserDetection` concern shared example (#32959) --- spec/models/login_activity_spec.rb | 17 +++++++++ spec/models/session_activation_spec.rb | 34 +---------------- .../models/concerns/browser_detection.rb | 37 +++++++++++++++++++ 3 files changed, 55 insertions(+), 33 deletions(-) create mode 100644 spec/models/login_activity_spec.rb create mode 100644 spec/support/examples/models/concerns/browser_detection.rb diff --git a/spec/models/login_activity_spec.rb b/spec/models/login_activity_spec.rb new file mode 100644 index 0000000000..5b7935e8ba --- /dev/null +++ b/spec/models/login_activity_spec.rb @@ -0,0 +1,17 @@ +# frozen_string_literal: true + +require 'rails_helper' + +RSpec.describe LoginActivity do + include_examples 'BrowserDetection' + + describe 'Associations' do + it { is_expected.to belong_to(:user).required } + end + + describe 'Validations' do + subject { Fabricate.build :login_activity } + + it { is_expected.to define_enum_for(:authentication_method).backed_by_column_of_type(:string) } + end +end diff --git a/spec/models/session_activation_spec.rb b/spec/models/session_activation_spec.rb index bed411c369..bb9b3c785f 100644 --- a/spec/models/session_activation_spec.rb +++ b/spec/models/session_activation_spec.rb @@ -3,39 +3,7 @@ require 'rails_helper' RSpec.describe SessionActivation do - describe '#detection' do - let(:session_activation) { Fabricate(:session_activation, user_agent: 'Chrome/62.0.3202.89') } - - it 'sets a Browser instance as detection' do - expect(session_activation.detection).to be_a Browser::Chrome - end - end - - describe '#browser' do - before do - allow(session_activation).to receive(:detection).and_return(detection) - end - - let(:detection) { instance_double(Browser::Chrome, id: 1) } - let(:session_activation) { Fabricate(:session_activation) } - - it 'returns detection.id' do - expect(session_activation.browser).to be 1 - end - end - - describe '#platform' do - before do - allow(session_activation).to receive(:detection).and_return(detection) - end - - let(:session_activation) { Fabricate(:session_activation) } - let(:detection) { instance_double(Browser::Chrome, platform: instance_double(Browser::Platform, id: 1)) } - - it 'returns detection.platform.id' do - expect(session_activation.platform).to be 1 - end - end + include_examples 'BrowserDetection' describe '.active?' do subject { described_class.active?(id) } diff --git a/spec/support/examples/models/concerns/browser_detection.rb b/spec/support/examples/models/concerns/browser_detection.rb new file mode 100644 index 0000000000..e80fa4595c --- /dev/null +++ b/spec/support/examples/models/concerns/browser_detection.rb @@ -0,0 +1,37 @@ +# frozen_string_literal: true + +RSpec.shared_examples 'BrowserDetection' do + subject { described_class.new(user_agent: 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.1 Safari/605.1.15') } + + describe '#detection' do + it 'sets a Browser instance as detection' do + expect(subject.detection) + .to be_a(Browser::Safari) + end + end + + describe '#browser' do + it 'returns browser name from id' do + expect(subject.browser) + .to eq(:safari) + end + end + + describe '#platform' do + it 'returns detected platform' do + expect(subject.platform) + .to eq(:mac) + end + end + + describe 'Callbacks' do + describe 'populating the user_agent value' do + subject { Fabricate.build described_class.name.underscore.to_sym, user_agent: nil } + + it 'changes nil to empty string' do + expect { subject.save } + .to change(subject, :user_agent).from(nil).to('') + end + end + end +end From f2976ec9a45f7ad6f00a041ec28281db438eb977 Mon Sep 17 00:00:00 2001 From: Matt Jankowski Date: Tue, 19 Nov 2024 05:02:01 -0500 Subject: [PATCH 54/64] Extract `Notification::Groups` concern (#32968) --- app/models/concerns/notification/groups.rb | 123 +++++++++++++++++++++ app/models/notification.rb | 117 +------------------- 2 files changed, 124 insertions(+), 116 deletions(-) create mode 100644 app/models/concerns/notification/groups.rb diff --git a/app/models/concerns/notification/groups.rb b/app/models/concerns/notification/groups.rb new file mode 100644 index 0000000000..2f29bd9cea --- /dev/null +++ b/app/models/concerns/notification/groups.rb @@ -0,0 +1,123 @@ +# frozen_string_literal: true + +module Notification::Groups + extend ActiveSupport::Concern + + # `set_group_key!` needs to be updated if this list changes + GROUPABLE_NOTIFICATION_TYPES = %i(favourite reblog follow).freeze + MAXIMUM_GROUP_SPAN_HOURS = 12 + + def set_group_key! + return if filtered? || GROUPABLE_NOTIFICATION_TYPES.exclude?(type) + + type_prefix = case type + when :favourite, :reblog + [type, target_status&.id].join('-') + when :follow + type + else + raise NotImplementedError + end + redis_key = "notif-group/#{account.id}/#{type_prefix}" + hour_bucket = activity.created_at.utc.to_i / 1.hour.to_i + + # Reuse previous group if it does not span too large an amount of time + previous_bucket = redis.get(redis_key).to_i + hour_bucket = previous_bucket if hour_bucket < previous_bucket + MAXIMUM_GROUP_SPAN_HOURS + + # We do not concern ourselves with race conditions since we use hour buckets + redis.set(redis_key, hour_bucket, ex: MAXIMUM_GROUP_SPAN_HOURS.hours.to_i) + + self.group_key = "#{type_prefix}-#{hour_bucket}" + end + + class_methods do + def paginate_groups(limit, pagination_order, grouped_types: nil) + raise ArgumentError unless %i(asc desc).include?(pagination_order) + + query = reorder(id: pagination_order) + + # Ideally `:types` would be a bind rather than part of the SQL itself, but that does not + # seem to be possible to do with Rails, considering that the expression would occur in + # multiple places, including in a `select` + group_key_sql = begin + if grouped_types.present? + # Normalize `grouped_types` so the number of different SQL query shapes remains small, and + # the queries can be analyzed in monitoring/telemetry tools + grouped_types = (grouped_types.map(&:to_sym) & GROUPABLE_NOTIFICATION_TYPES).sort + + sanitize_sql_array([<<~SQL.squish, { types: grouped_types }]) + COALESCE( + CASE + WHEN notifications.type IN (:types) THEN notifications.group_key + ELSE NULL + END, + 'ungrouped-' || notifications.id + ) + SQL + else + "COALESCE(notifications.group_key, 'ungrouped-' || notifications.id)" + end + end + + unscoped + .with_recursive( + grouped_notifications: [ + # Base case: fetching one notification and annotating it with visited groups + query + .select('notifications.*', "ARRAY[#{group_key_sql}] AS groups") + .limit(1), + # Recursive case, always yielding at most one annotated notification + unscoped + .from( + [ + # Expose the working table as `wt`, but quit early if we've reached the limit + unscoped + .select('id', 'groups') + .from('grouped_notifications') + .where('array_length(grouped_notifications.groups, 1) < :limit', limit: limit) + .arel.as('wt'), + # Recursive query, using `LATERAL` so we can refer to `wt` + query + .where(pagination_order == :desc ? 'notifications.id < wt.id' : 'notifications.id > wt.id') + .where.not("#{group_key_sql} = ANY(wt.groups)") + .limit(1) + .arel.lateral('notifications'), + ] + ) + .select('notifications.*', "array_append(wt.groups, #{group_key_sql}) AS groups"), + ] + ) + .from('grouped_notifications AS notifications') + .order(id: pagination_order) + .limit(limit) + end + + # This returns notifications from the request page, but with at most one notification per group. + # Notifications that have no `group_key` each count as a separate group. + def paginate_groups_by_max_id(limit, max_id: nil, since_id: nil, grouped_types: nil) + query = reorder(id: :desc) + query = query.where(id: ...(max_id.to_i)) if max_id.present? + query = query.where(id: (since_id.to_i + 1)...) if since_id.present? + query.paginate_groups(limit, :desc, grouped_types: grouped_types) + end + + # Differs from :paginate_groups_by_max_id in that it gives the results immediately following min_id, + # whereas since_id gives the items with largest id, but with since_id as a cutoff. + # Results will be in ascending order by id. + def paginate_groups_by_min_id(limit, max_id: nil, min_id: nil, grouped_types: nil) + query = reorder(id: :asc) + query = query.where(id: (min_id.to_i + 1)...) if min_id.present? + query = query.where(id: ...(max_id.to_i)) if max_id.present? + query.paginate_groups(limit, :asc, grouped_types: grouped_types) + end + + def to_a_grouped_paginated_by_id(limit, options = {}) + if options[:min_id].present? + paginate_groups_by_min_id(limit, min_id: options[:min_id], max_id: options[:max_id], grouped_types: options[:grouped_types]).reverse + else + paginate_groups_by_max_id(limit, max_id: options[:max_id], since_id: options[:since_id], grouped_types: options[:grouped_types]).to_a + end + end + end +end diff --git a/app/models/notification.rb b/app/models/notification.rb index 7b90fd92f9..e7ada3399a 100644 --- a/app/models/notification.rb +++ b/app/models/notification.rb @@ -19,6 +19,7 @@ class Notification < ApplicationRecord self.inheritance_column = nil + include Notification::Groups include Paginable include Redisable @@ -31,10 +32,6 @@ class Notification < ApplicationRecord 'Poll' => :poll, }.freeze - # `set_group_key!` needs to be updated if this list changes - GROUPABLE_NOTIFICATION_TYPES = %i(favourite reblog follow).freeze - MAXIMUM_GROUP_SPAN_HOURS = 12 - # Please update app/javascript/api_types/notification.ts if you change this PROPERTIES = { mention: { @@ -130,30 +127,6 @@ class Notification < ApplicationRecord end end - def set_group_key! - return if filtered? || Notification::GROUPABLE_NOTIFICATION_TYPES.exclude?(type) - - type_prefix = case type - when :favourite, :reblog - [type, target_status&.id].join('-') - when :follow - type - else - raise NotImplementedError - end - redis_key = "notif-group/#{account.id}/#{type_prefix}" - hour_bucket = activity.created_at.utc.to_i / 1.hour.to_i - - # Reuse previous group if it does not span too large an amount of time - previous_bucket = redis.get(redis_key).to_i - hour_bucket = previous_bucket if hour_bucket < previous_bucket + MAXIMUM_GROUP_SPAN_HOURS - - # We do not concern ourselves with race conditions since we use hour buckets - redis.set(redis_key, hour_bucket, ex: MAXIMUM_GROUP_SPAN_HOURS.hours.to_i) - - self.group_key = "#{type_prefix}-#{hour_bucket}" - end - class << self def browserable(types: [], exclude_types: [], from_account_id: nil, include_filtered: false) requested_types = if types.empty? @@ -171,94 +144,6 @@ class Notification < ApplicationRecord end end - def paginate_groups(limit, pagination_order, grouped_types: nil) - raise ArgumentError unless %i(asc desc).include?(pagination_order) - - query = reorder(id: pagination_order) - - # Ideally `:types` would be a bind rather than part of the SQL itself, but that does not - # seem to be possible to do with Rails, considering that the expression would occur in - # multiple places, including in a `select` - group_key_sql = begin - if grouped_types.present? - # Normalize `grouped_types` so the number of different SQL query shapes remains small, and - # the queries can be analyzed in monitoring/telemetry tools - grouped_types = (grouped_types.map(&:to_sym) & GROUPABLE_NOTIFICATION_TYPES).sort - - sanitize_sql_array([<<~SQL.squish, { types: grouped_types }]) - COALESCE( - CASE - WHEN notifications.type IN (:types) THEN notifications.group_key - ELSE NULL - END, - 'ungrouped-' || notifications.id - ) - SQL - else - "COALESCE(notifications.group_key, 'ungrouped-' || notifications.id)" - end - end - - unscoped - .with_recursive( - grouped_notifications: [ - # Base case: fetching one notification and annotating it with visited groups - query - .select('notifications.*', "ARRAY[#{group_key_sql}] AS groups") - .limit(1), - # Recursive case, always yielding at most one annotated notification - unscoped - .from( - [ - # Expose the working table as `wt`, but quit early if we've reached the limit - unscoped - .select('id', 'groups') - .from('grouped_notifications') - .where('array_length(grouped_notifications.groups, 1) < :limit', limit: limit) - .arel.as('wt'), - # Recursive query, using `LATERAL` so we can refer to `wt` - query - .where(pagination_order == :desc ? 'notifications.id < wt.id' : 'notifications.id > wt.id') - .where.not("#{group_key_sql} = ANY(wt.groups)") - .limit(1) - .arel.lateral('notifications'), - ] - ) - .select('notifications.*', "array_append(wt.groups, #{group_key_sql}) AS groups"), - ] - ) - .from('grouped_notifications AS notifications') - .order(id: pagination_order) - .limit(limit) - end - - # This returns notifications from the request page, but with at most one notification per group. - # Notifications that have no `group_key` each count as a separate group. - def paginate_groups_by_max_id(limit, max_id: nil, since_id: nil, grouped_types: nil) - query = reorder(id: :desc) - query = query.where(id: ...(max_id.to_i)) if max_id.present? - query = query.where(id: (since_id.to_i + 1)...) if since_id.present? - query.paginate_groups(limit, :desc, grouped_types: grouped_types) - end - - # Differs from :paginate_groups_by_max_id in that it gives the results immediately following min_id, - # whereas since_id gives the items with largest id, but with since_id as a cutoff. - # Results will be in ascending order by id. - def paginate_groups_by_min_id(limit, max_id: nil, min_id: nil, grouped_types: nil) - query = reorder(id: :asc) - query = query.where(id: (min_id.to_i + 1)...) if min_id.present? - query = query.where(id: ...(max_id.to_i)) if max_id.present? - query.paginate_groups(limit, :asc, grouped_types: grouped_types) - end - - def to_a_grouped_paginated_by_id(limit, options = {}) - if options[:min_id].present? - paginate_groups_by_min_id(limit, min_id: options[:min_id], max_id: options[:max_id], grouped_types: options[:grouped_types]).reverse - else - paginate_groups_by_max_id(limit, max_id: options[:max_id], since_id: options[:since_id], grouped_types: options[:grouped_types]).to_a - end - end - def preload_cache_collection_target_statuses(notifications, &_block) notifications.group_by(&:type).each do |type, grouped_notifications| associations = TARGET_STATUS_INCLUDES_BY_TYPE[type] From 2b5faa2ba322d22cf9b345f815db7cbf89874415 Mon Sep 17 00:00:00 2001 From: Eugen Rochko Date: Tue, 19 Nov 2024 11:04:12 +0100 Subject: [PATCH 55/64] Change lists to reflect added and removed users retroactively (#32930) --- .../api/v1/lists/accounts_controller.rb | 13 ++------ app/models/follow_request.rb | 11 +++++-- app/services/add_accounts_to_list_service.rb | 33 +++++++++++++++++++ app/services/follow_service.rb | 5 ++- .../remove_accounts_from_list_service.rb | 29 ++++++++++++++++ app/services/unfollow_service.rb | 8 ++++- app/services/unmute_service.rb | 8 ++++- app/workers/merge_worker.rb | 30 +++++++++++++++-- app/workers/mute_worker.rb | 11 ++++++- app/workers/unmerge_worker.rb | 30 +++++++++++++++-- spec/models/follow_request_spec.rb | 2 +- spec/services/unmute_service_spec.rb | 2 +- 12 files changed, 157 insertions(+), 25 deletions(-) create mode 100644 app/services/add_accounts_to_list_service.rb create mode 100644 app/services/remove_accounts_from_list_service.rb diff --git a/app/controllers/api/v1/lists/accounts_controller.rb b/app/controllers/api/v1/lists/accounts_controller.rb index b1c0e609d0..616159f05f 100644 --- a/app/controllers/api/v1/lists/accounts_controller.rb +++ b/app/controllers/api/v1/lists/accounts_controller.rb @@ -15,17 +15,12 @@ class Api::V1::Lists::AccountsController < Api::BaseController end def create - ApplicationRecord.transaction do - list_accounts.each do |account| - @list.accounts << account - end - end - + AddAccountsToListService.new.call(@list, Account.find(account_ids)) render_empty end def destroy - ListAccount.where(list: @list, account_id: account_ids).destroy_all + RemoveAccountsFromListService.new.call(@list, Account.where(id: account_ids)) render_empty end @@ -43,10 +38,6 @@ class Api::V1::Lists::AccountsController < Api::BaseController end end - def list_accounts - Account.find(account_ids) - end - def account_ids Array(resource_params[:account_ids]) end diff --git a/app/models/follow_request.rb b/app/models/follow_request.rb index c13cc718d8..964d4e279a 100644 --- a/app/models/follow_request.rb +++ b/app/models/follow_request.rb @@ -33,8 +33,15 @@ class FollowRequest < ApplicationRecord def authorize! follow = account.follow!(target_account, reblogs: show_reblogs, notify: notify, languages: languages, uri: uri, bypass_limit: true) - ListAccount.where(follow_request: self).update_all(follow_request_id: nil, follow_id: follow.id) - MergeWorker.perform_async(target_account.id, account.id) if account.local? + + if account.local? + ListAccount.where(follow_request: self).update_all(follow_request_id: nil, follow_id: follow.id) + MergeWorker.perform_async(target_account.id, account.id, 'home') + MergeWorker.push_bulk(List.where(account: account).joins(:list_accounts).where(list_accounts: { account_id: target_account.id }).pluck(:id)) do |list_id| + [target_account.id, list_id, 'list'] + end + end + destroy! end diff --git a/app/services/add_accounts_to_list_service.rb b/app/services/add_accounts_to_list_service.rb new file mode 100644 index 0000000000..df4e4c8314 --- /dev/null +++ b/app/services/add_accounts_to_list_service.rb @@ -0,0 +1,33 @@ +# frozen_string_literal: true + +class AddAccountsToListService < BaseService + def call(list, accounts) + @list = list + @accounts = accounts + + return if @accounts.empty? + + update_list! + merge_into_list! + end + + private + + def update_list! + ApplicationRecord.transaction do + @accounts.each do |account| + @list.accounts << account + end + end + end + + def merge_into_list! + MergeWorker.push_bulk(merge_account_ids) do |account_id| + [account_id, @list.id, 'list'] + end + end + + def merge_account_ids + ListAccount.where(list: @list, account: @accounts).where.not(follow_id: nil).pluck(:account_id) + end +end diff --git a/app/services/follow_service.rb b/app/services/follow_service.rb index af5f996077..cff38b8e6e 100644 --- a/app/services/follow_service.rb +++ b/app/services/follow_service.rb @@ -81,7 +81,10 @@ class FollowService < BaseService follow = @source_account.follow!(@target_account, **follow_options.merge(rate_limit: @options[:with_rate_limit], bypass_limit: @options[:bypass_limit])) LocalNotificationWorker.perform_async(@target_account.id, follow.id, follow.class.name, 'follow') - MergeWorker.perform_async(@target_account.id, @source_account.id) + MergeWorker.perform_async(@target_account.id, @source_account.id, 'home') + MergeWorker.push_bulk(List.where(account: @source_account).joins(:list_accounts).where(list_accounts: { account_id: @target_account.id }).pluck(:id)) do |list_id| + [@target_account.id, list_id, 'list'] + end follow end diff --git a/app/services/remove_accounts_from_list_service.rb b/app/services/remove_accounts_from_list_service.rb new file mode 100644 index 0000000000..bd5b7c439e --- /dev/null +++ b/app/services/remove_accounts_from_list_service.rb @@ -0,0 +1,29 @@ +# frozen_string_literal: true + +class RemoveAccountsFromListService < BaseService + def call(list, accounts) + @list = list + @accounts = accounts + + return if @accounts.empty? + + unmerge_from_list! + update_list! + end + + private + + def update_list! + ListAccount.where(list: @list, account: @accounts).destroy_all + end + + def unmerge_from_list! + UnmergeWorker.push_bulk(unmerge_account_ids) do |account_id| + [account_id, @list.id, 'list'] + end + end + + def unmerge_account_ids + ListAccount.where(list: @list, account: @accounts).where.not(follow_id: nil).pluck(:account_id) + end +end diff --git a/app/services/unfollow_service.rb b/app/services/unfollow_service.rb index fe9a7f0d87..b3f2cd66f6 100644 --- a/app/services/unfollow_service.rb +++ b/app/services/unfollow_service.rb @@ -31,7 +31,13 @@ class UnfollowService < BaseService create_notification(follow) if !@target_account.local? && @target_account.activitypub? create_reject_notification(follow) if @target_account.local? && !@source_account.local? && @source_account.activitypub? - UnmergeWorker.perform_async(@target_account.id, @source_account.id) unless @options[:skip_unmerge] + + unless @options[:skip_unmerge] + UnmergeWorker.perform_async(@target_account.id, @source_account.id, 'home') + UnmergeWorker.push_bulk(List.where(account: @source_account).joins(:list_accounts).where(list_accounts: { account_id: @target_account.id }).pluck(:list_id)) do |list_id| + [@target_account.id, list_id, 'list'] + end + end follow end diff --git a/app/services/unmute_service.rb b/app/services/unmute_service.rb index 6aeea358f7..9262961f7d 100644 --- a/app/services/unmute_service.rb +++ b/app/services/unmute_service.rb @@ -6,6 +6,12 @@ class UnmuteService < BaseService account.unmute!(target_account) - MergeWorker.perform_async(target_account.id, account.id) if account.following?(target_account) + if account.following?(target_account) + MergeWorker.perform_async(target_account.id, account.id, 'home') + + MergeWorker.push_bulk(List.where(account: account).joins(:list_accounts).where(list_accounts: { account_id: target_account.id }).pluck(:id)) do |list_id| + [target_account.id, list_id, 'list'] + end + end end end diff --git a/app/workers/merge_worker.rb b/app/workers/merge_worker.rb index 8e1614ad21..d4dcb326bc 100644 --- a/app/workers/merge_worker.rb +++ b/app/workers/merge_worker.rb @@ -5,18 +5,42 @@ class MergeWorker include Redisable include DatabaseHelper - def perform(from_account_id, into_account_id) + def perform(from_account_id, into_id, type = 'home') with_primary do @from_account = Account.find(from_account_id) + end + + case type + when 'home' + merge_into_home!(into_id) + when 'list' + merge_into_list!(into_id) + end + rescue ActiveRecord::RecordNotFound + true + end + + private + + def merge_into_home!(into_account_id) + with_primary do @into_account = Account.find(into_account_id) end with_read_replica do FeedManager.instance.merge_into_home(@from_account, @into_account) end - rescue ActiveRecord::RecordNotFound - true ensure redis.del("account:#{into_account_id}:regeneration") end + + def merge_into_list!(into_list_id) + with_primary do + @into_list = List.find(into_list_id) + end + + with_read_replica do + FeedManager.instance.merge_into_list(@from_account, @into_list) + end + end end diff --git a/app/workers/mute_worker.rb b/app/workers/mute_worker.rb index c74f657cba..ebd401dc20 100644 --- a/app/workers/mute_worker.rb +++ b/app/workers/mute_worker.rb @@ -2,9 +2,18 @@ class MuteWorker include Sidekiq::Worker + include DatabaseHelper def perform(account_id, target_account_id) - FeedManager.instance.clear_from_home(Account.find(account_id), Account.find(target_account_id)) + with_primary do + @account = Account.find(account_id) + @target_account = Account.find(target_account_id) + end + + with_read_replica do + FeedManager.instance.clear_from_home(@account, @target_account) + FeedManager.instance.clear_from_lists(@account, @target_account) + end rescue ActiveRecord::RecordNotFound true end diff --git a/app/workers/unmerge_worker.rb b/app/workers/unmerge_worker.rb index e8ac535dfe..e8a3bf9b78 100644 --- a/app/workers/unmerge_worker.rb +++ b/app/workers/unmerge_worker.rb @@ -6,16 +6,40 @@ class UnmergeWorker sidekiq_options queue: 'pull' - def perform(from_account_id, into_account_id) + def perform(from_account_id, into_id, type = 'home') with_primary do @from_account = Account.find(from_account_id) + end + + case type + when 'home' + unmerge_from_home!(into_id) + when 'list' + unmerge_from_list!(into_id) + end + rescue ActiveRecord::RecordNotFound + true + end + + private + + def unmerge_from_home!(into_account_id) + with_primary do @into_account = Account.find(into_account_id) end with_read_replica do FeedManager.instance.unmerge_from_home(@from_account, @into_account) end - rescue ActiveRecord::RecordNotFound - true + end + + def unmerge_from_list!(into_list_id) + with_primary do + @into_list = List.find(into_list_id) + end + + with_read_replica do + FeedManager.instance.unmerge_from_list(@from_account, @into_list) + end end end diff --git a/spec/models/follow_request_spec.rb b/spec/models/follow_request_spec.rb index 9cccb82903..237875deab 100644 --- a/spec/models/follow_request_spec.rb +++ b/spec/models/follow_request_spec.rb @@ -30,7 +30,7 @@ RSpec.describe FollowRequest do follow_request.authorize! expect(account).to have_received(:follow!).with(target_account, reblogs: true, notify: false, uri: follow_request.uri, languages: nil, bypass_limit: true) - expect(MergeWorker).to have_received(:perform_async).with(target_account.id, account.id) + expect(MergeWorker).to have_received(:perform_async).with(target_account.id, account.id, 'home') expect(follow_request).to have_received(:destroy!) end diff --git a/spec/services/unmute_service_spec.rb b/spec/services/unmute_service_spec.rb index 92c7a70d65..a052e0dd0a 100644 --- a/spec/services/unmute_service_spec.rb +++ b/spec/services/unmute_service_spec.rb @@ -16,7 +16,7 @@ RSpec.describe UnmuteService do it 'removes the account mute and sets up a merge' do expect { subject.call(account, target_account) } .to remove_account_mute - expect(MergeWorker).to have_enqueued_sidekiq_job(target_account.id, account.id) + expect(MergeWorker).to have_enqueued_sidekiq_job(target_account.id, account.id, 'home') end end From 37f00fb01811f379d0f2978d5b9fa6cec031e7c7 Mon Sep 17 00:00:00 2001 From: Matt Jankowski Date: Tue, 19 Nov 2024 05:36:02 -0500 Subject: [PATCH 56/64] Use hash arguments to `group` when possible (#32916) --- app/lib/annual_report/most_reblogged_accounts.rb | 2 +- app/lib/annual_report/most_used_apps.rb | 2 +- app/models/account_filter.rb | 2 +- app/models/poll.rb | 4 ++-- app/models/user.rb | 2 +- 5 files changed, 6 insertions(+), 6 deletions(-) diff --git a/app/lib/annual_report/most_reblogged_accounts.rb b/app/lib/annual_report/most_reblogged_accounts.rb index 5c750b19bf..69e247f2a6 100644 --- a/app/lib/annual_report/most_reblogged_accounts.rb +++ b/app/lib/annual_report/most_reblogged_accounts.rb @@ -17,6 +17,6 @@ class AnnualReport::MostRebloggedAccounts < AnnualReport::Source private def most_reblogged_accounts - report_statuses.where.not(reblog_of_id: nil).joins(reblog: :account).group('accounts.id').having('count(*) > 1').order(count_all: :desc).limit(SET_SIZE).count + report_statuses.where.not(reblog_of_id: nil).joins(reblog: :account).group(accounts: [:id]).having('count(*) > 1').order(count_all: :desc).limit(SET_SIZE).count end end diff --git a/app/lib/annual_report/most_used_apps.rb b/app/lib/annual_report/most_used_apps.rb index e10ba52503..a2e1aca452 100644 --- a/app/lib/annual_report/most_used_apps.rb +++ b/app/lib/annual_report/most_used_apps.rb @@ -17,6 +17,6 @@ class AnnualReport::MostUsedApps < AnnualReport::Source private def most_used_apps - report_statuses.joins(:application).group('oauth_applications.name').order(count_all: :desc).limit(SET_SIZE).count + report_statuses.joins(:application).group(oauth_applications: [:name]).order(count_all: :desc).limit(SET_SIZE).count end end diff --git a/app/models/account_filter.rb b/app/models/account_filter.rb index e2f359a8c3..f5e9fc7db9 100644 --- a/app/models/account_filter.rb +++ b/app/models/account_filter.rb @@ -61,7 +61,7 @@ class AccountFilter when 'email' accounts_with_users.merge(User.matches_email(value.to_s.strip)) when 'ip' - valid_ip?(value) ? accounts_with_users.merge(User.matches_ip(value).group('users.id, accounts.id')) : Account.none + valid_ip?(value) ? accounts_with_users.merge(User.matches_ip(value).group(users: [:id], accounts: [:id])) : Account.none when 'invited_by' invited_by_scope(value) when 'order' diff --git a/app/models/poll.rb b/app/models/poll.rb index cc4184f80a..ebd4644094 100644 --- a/app/models/poll.rb +++ b/app/models/poll.rb @@ -29,8 +29,8 @@ class Poll < ApplicationRecord has_many :votes, class_name: 'PollVote', inverse_of: :poll, dependent: :delete_all with_options class_name: 'Account', source: :account, through: :votes do - has_many :voters, -> { group('accounts.id') } - has_many :local_voters, -> { group('accounts.id').merge(Account.local) } + has_many :voters, -> { group(accounts: [:id]) } + has_many :local_voters, -> { group(accounts: [:id]).merge(Account.local) } end has_many :notifications, as: :activity, dependent: :destroy diff --git a/app/models/user.rb b/app/models/user.rb index be9ebac699..c90a78f0cc 100644 --- a/app/models/user.rb +++ b/app/models/user.rb @@ -125,7 +125,7 @@ class User < ApplicationRecord scope :signed_in_recently, -> { where(current_sign_in_at: ACTIVE_DURATION.ago..) } scope :not_signed_in_recently, -> { where(current_sign_in_at: ...ACTIVE_DURATION.ago) } scope :matches_email, ->(value) { where(arel_table[:email].matches("#{value}%")) } - scope :matches_ip, ->(value) { left_joins(:ips).merge(IpBlock.contained_by(value)).group('users.id') } + scope :matches_ip, ->(value) { left_joins(:ips).merge(IpBlock.contained_by(value)).group(users: [:id]) } before_validation :sanitize_role before_create :set_approved From 30e9c7137bf6fc2ca17766a58bd6d682971b0c7a Mon Sep 17 00:00:00 2001 From: Claire Date: Tue, 19 Nov 2024 21:21:12 +0100 Subject: [PATCH 57/64] Fix error when viewing statuses to deleted replies in moderation view (#32986) --- app/views/admin/reports/_status.html.haml | 2 +- app/views/admin/statuses/show.html.haml | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/app/views/admin/reports/_status.html.haml b/app/views/admin/reports/_status.html.haml index bd688a1a5d..d20266aa2c 100644 --- a/app/views/admin/reports/_status.html.haml +++ b/app/views/admin/reports/_status.html.haml @@ -10,7 +10,7 @@ - elsif status.reply? && status.in_reply_to_id.present? .status__prepend = material_symbol('reply') - = t('admin.statuses.replied_to_html', acct_link: admin_account_inline_link_to(status.in_reply_to_account, path: admin_account_status_path(status.thread.account_id, status.in_reply_to_id))) + = t('admin.statuses.replied_to_html', acct_link: admin_account_inline_link_to(status.in_reply_to_account, path: status.thread.present? ? admin_account_status_path(status.thread.account_id, status.in_reply_to_id) : nil)) .status__content>< - if status.proper.spoiler_text.blank? = prerender_custom_emojis(status_content_format(status.proper), status.proper.emojis) diff --git a/app/views/admin/statuses/show.html.haml b/app/views/admin/statuses/show.html.haml index 49c23e921c..1ff4763158 100644 --- a/app/views/admin/statuses/show.html.haml +++ b/app/views/admin/statuses/show.html.haml @@ -22,7 +22,7 @@ - if @status.reply? %tr %th= t('admin.statuses.in_reply_to') - %td= admin_account_link_to @status.in_reply_to_account, path: admin_account_status_path(@status.thread.account_id, @status.in_reply_to_id) + %td= admin_account_link_to @status.in_reply_to_account, path: @status.thread.present? ? admin_account_status_path(@status.thread.account_id, @status.in_reply_to_id) : nil %tr %th= t('admin.statuses.application') %td= @status.application&.name @@ -61,7 +61,7 @@ - elsif @status.reply? && @status.in_reply_to_id.present? .status__prepend = material_symbol('reply') - = t('admin.statuses.replied_to_html', acct_link: admin_account_inline_link_to(@status.in_reply_to_account, path: admin_account_status_path(@status.thread.account_id, @status.in_reply_to_id))) + = t('admin.statuses.replied_to_html', acct_link: admin_account_inline_link_to(@status.in_reply_to_account, path: @status.thread.present? ? admin_account_status_path(@status.thread.account_id, @status.in_reply_to_id) : nil)) .status__content>< - if @status.proper.spoiler_text.blank? = prerender_custom_emojis(status_content_format(@status.proper), @status.proper.emojis) From 41b033e381d56eec76cd739d4eceb1dd701b6926 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Wed, 20 Nov 2024 08:42:53 +0100 Subject: [PATCH 58/64] Update dependency opentelemetry-instrumentation-rails to '~> 0.33.0' (#32987) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- Gemfile | 2 +- Gemfile.lock | 12 ++++++------ 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/Gemfile b/Gemfile index c8104d094e..6abb075c1c 100644 --- a/Gemfile +++ b/Gemfile @@ -114,7 +114,7 @@ group :opentelemetry do gem 'opentelemetry-instrumentation-net_http', '~> 0.22.4', require: false gem 'opentelemetry-instrumentation-pg', '~> 0.29.0', require: false gem 'opentelemetry-instrumentation-rack', '~> 0.25.0', require: false - gem 'opentelemetry-instrumentation-rails', '~> 0.32.0', require: false + gem 'opentelemetry-instrumentation-rails', '~> 0.33.0', require: false gem 'opentelemetry-instrumentation-redis', '~> 0.25.3', require: false gem 'opentelemetry-instrumentation-sidekiq', '~> 0.25.2', require: false gem 'opentelemetry-sdk', '~> 1.4', require: false diff --git a/Gemfile.lock b/Gemfile.lock index d1be469f48..d45d17f52b 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -478,13 +478,13 @@ GEM opentelemetry-api (~> 1.0) opentelemetry-instrumentation-active_support (~> 0.1) opentelemetry-instrumentation-base (~> 0.22.1) - opentelemetry-instrumentation-action_pack (0.9.0) + opentelemetry-instrumentation-action_pack (0.10.0) opentelemetry-api (~> 1.0) opentelemetry-instrumentation-base (~> 0.22.1) opentelemetry-instrumentation-rack (~> 0.21) - opentelemetry-instrumentation-action_view (0.7.2) + opentelemetry-instrumentation-action_view (0.7.3) opentelemetry-api (~> 1.0) - opentelemetry-instrumentation-active_support (~> 0.1) + opentelemetry-instrumentation-active_support (~> 0.6) opentelemetry-instrumentation-base (~> 0.22.1) opentelemetry-instrumentation-active_job (0.7.8) opentelemetry-api (~> 1.0) @@ -527,10 +527,10 @@ GEM opentelemetry-instrumentation-rack (0.25.0) opentelemetry-api (~> 1.0) opentelemetry-instrumentation-base (~> 0.22.1) - opentelemetry-instrumentation-rails (0.32.0) + opentelemetry-instrumentation-rails (0.33.0) opentelemetry-api (~> 1.0) opentelemetry-instrumentation-action_mailer (~> 0.2.0) - opentelemetry-instrumentation-action_pack (~> 0.9.0) + opentelemetry-instrumentation-action_pack (~> 0.10.0) opentelemetry-instrumentation-action_view (~> 0.7.0) opentelemetry-instrumentation-active_job (~> 0.7.0) opentelemetry-instrumentation-active_record (~> 0.8.0) @@ -966,7 +966,7 @@ DEPENDENCIES opentelemetry-instrumentation-net_http (~> 0.22.4) opentelemetry-instrumentation-pg (~> 0.29.0) opentelemetry-instrumentation-rack (~> 0.25.0) - opentelemetry-instrumentation-rails (~> 0.32.0) + opentelemetry-instrumentation-rails (~> 0.33.0) opentelemetry-instrumentation-redis (~> 0.25.3) opentelemetry-instrumentation-sidekiq (~> 0.25.2) opentelemetry-sdk (~> 1.4) From b66fbaeec236b0b666f1de7ae525dec2da40441a Mon Sep 17 00:00:00 2001 From: Matt Jankowski Date: Wed, 20 Nov 2024 02:52:00 -0500 Subject: [PATCH 59/64] Add `AccountWarning` case to `Report#history` spec (#32984) --- spec/models/report_spec.rb | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/spec/models/report_spec.rb b/spec/models/report_spec.rb index a0e4f6fafd..b4fbea437f 100644 --- a/spec/models/report_spec.rb +++ b/spec/models/report_spec.rb @@ -108,15 +108,22 @@ RSpec.describe Report do let(:report) { Fabricate(:report, target_account_id: target_account.id, status_ids: [status.id], created_at: 3.days.ago, updated_at: 1.day.ago) } let(:target_account) { Fabricate(:account) } let(:status) { Fabricate(:status) } + let(:account_warning) { Fabricate(:account_warning, report_id: report.id) } before do Fabricate(:action_log, target_type: 'Report', account_id: target_account.id, target_id: report.id, created_at: 2.days.ago) Fabricate(:action_log, target_type: 'Account', account_id: target_account.id, target_id: report.target_account_id, created_at: 2.days.ago) Fabricate(:action_log, target_type: 'Status', account_id: target_account.id, target_id: status.id, created_at: 2.days.ago) + Fabricate(:action_log, target_type: 'AccountWarning', account_id: target_account.id, target_id: account_warning.id, created_at: 2.days.ago) end - it 'returns right logs' do - expect(action_logs.count).to eq 3 + it 'returns expected logs' do + expect(action_logs) + .to have_attributes(count: 4) + .and include(have_attributes(target_type: 'Account')) + .and include(have_attributes(target_type: 'AccountWarning')) + .and include(have_attributes(target_type: 'Report')) + .and include(have_attributes(target_type: 'Status')) end end From 4252b13a4bcd51248a781d9e8978f45fe6a1375b Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Wed, 20 Nov 2024 09:24:50 +0100 Subject: [PATCH 60/64] New Crowdin Translations (automated) (#32990) Co-authored-by: GitHub Actions --- app/javascript/mastodon/locales/ar.json | 1 + app/javascript/mastodon/locales/lt.json | 4 +++- app/javascript/mastodon/locales/pl.json | 19 +++++++++++++++++++ config/locales/lv.yml | 2 ++ config/locales/pl.yml | 15 +++++++++++++++ config/locales/simple_form.es-AR.yml | 2 +- config/locales/sv.yml | 1 + 7 files changed, 42 insertions(+), 2 deletions(-) diff --git a/app/javascript/mastodon/locales/ar.json b/app/javascript/mastodon/locales/ar.json index 5c7dfeb128..7892766d87 100644 --- a/app/javascript/mastodon/locales/ar.json +++ b/app/javascript/mastodon/locales/ar.json @@ -490,6 +490,7 @@ "notification.label.private_reply": "رد خاص", "notification.label.reply": "ردّ", "notification.mention": "إشارة", + "notification.mentioned_you": "{name} mentioned you", "notification.moderation-warning.learn_more": "اعرف المزيد", "notification.moderation_warning": "لقد تلقيت تحذيرًا بالإشراف", "notification.moderation_warning.action_delete_statuses": "تم حذف بعض من منشوراتك.", diff --git a/app/javascript/mastodon/locales/lt.json b/app/javascript/mastodon/locales/lt.json index 378f642cfe..6d4f46f1d4 100644 --- a/app/javascript/mastodon/locales/lt.json +++ b/app/javascript/mastodon/locales/lt.json @@ -69,7 +69,7 @@ "account.unendorse": "Nerodyti profilyje", "account.unfollow": "Nebesekti", "account.unmute": "Atšaukti nutildymą @{name}", - "account.unmute_notifications_short": "Atšaukti nutildymą pranešimams", + "account.unmute_notifications_short": "Atšaukti pranešimų nutildymą", "account.unmute_short": "Atšaukti nutildymą", "account_note.placeholder": "Spustelėk, kad pridėtum pastabą.", "admin.dashboard.daily_retention": "Naudotojų pasilikimo rodiklis pagal dieną po registracijos", @@ -526,6 +526,7 @@ "notification.admin.report_statuses": "{name} pranešė {target} kategorijai {category}", "notification.admin.report_statuses_other": "{name} pranešė {target}", "notification.admin.sign_up": "{name} užsiregistravo", + "notification.admin.sign_up.name_and_others": "{name} ir {count, plural, one {# kitas} few {# kiti} many {# kito} other {# kitų}} užsiregistravo", "notification.annual_report.message": "Jūsų laukia {year} #Wrapstodon! Atskleiskite savo metų svarbiausius įvykius ir įsimintinas akimirkas platformoje „Mastodon“.", "notification.annual_report.view": "Peržiūrėti #Wrapstodon", "notification.favourite": "{name} pamėgo tavo įrašą", @@ -537,6 +538,7 @@ "notification.label.private_reply": "Privatus atsakymas", "notification.label.reply": "Atsakymas", "notification.mention": "Paminėjimas", + "notification.mentioned_you": "{name} paminėjo jus", "notification.moderation-warning.learn_more": "Sužinoti daugiau", "notification.moderation_warning": "Gavai prižiūrėjimo įspėjimą", "notification.moderation_warning.action_delete_statuses": "Kai kurie tavo įrašai buvo pašalintos.", diff --git a/app/javascript/mastodon/locales/pl.json b/app/javascript/mastodon/locales/pl.json index c521fabf39..4558e29cb8 100644 --- a/app/javascript/mastodon/locales/pl.json +++ b/app/javascript/mastodon/locales/pl.json @@ -87,6 +87,24 @@ "alert.unexpected.title": "Ups!", "alt_text_badge.title": "Tekst alternatywny", "announcement.announcement": "Ogłoszenie", + "annual_report.summary.archetype.booster": "Łowca treści", + "annual_report.summary.archetype.lurker": "Czyhający", + "annual_report.summary.archetype.oracle": "Wyrocznia", + "annual_report.summary.archetype.pollster": "Ankieter", + "annual_report.summary.archetype.replier": "Motyl społeczny", + "annual_report.summary.followers.followers": "obserwujących", + "annual_report.summary.followers.total": "łącznie {count}", + "annual_report.summary.here_it_is": "Oto przegląd Twojego {year} roku:", + "annual_report.summary.highlighted_post.by_favourites": "najbardziej ulubiony wpis", + "annual_report.summary.highlighted_post.by_reblogs": "najbardziej promowany wpis", + "annual_report.summary.highlighted_post.by_replies": "wpis z największą liczbą odpowiedzi", + "annual_report.summary.highlighted_post.possessive": "{name}", + "annual_report.summary.most_used_app.most_used_app": "najczęściej używana aplikacja", + "annual_report.summary.most_used_hashtag.most_used_hashtag": "najczęściej używany hashtag", + "annual_report.summary.most_used_hashtag.none": "Brak", + "annual_report.summary.new_posts.new_posts": "nowe wpisy", + "annual_report.summary.percentile.we_wont_tell_bernie": "Nie powiemy Berniemu.", + "annual_report.summary.thanks": "Dziękujemy, że jesteś częścią Mastodona!", "attachments_list.unprocessed": "(nieprzetworzone)", "audio.hide": "Ukryj dźwięk", "block_modal.remote_users_caveat": "Poprosimy serwer {domain} o uszanowanie twojej decyzji. Zgodność nie jest jednak gwarantowana, bo niektóre serwery mogą inaczej obsługiwać blokowanie. Wpisy publiczne mogą być widoczne dla niezalogowanych użytkowników.", @@ -508,6 +526,7 @@ "notification.admin.report_statuses_other": "{name} zgłosił(a) {target}", "notification.admin.sign_up": "Użytkownik {name} zarejestrował się", "notification.admin.sign_up.name_and_others": "zarejestrował(-a) się {name} i {count, plural, one {# inna osoba} few {# inne osoby} other {# innych osób}}", + "notification.annual_report.view": "Zobacz #Wrapstodon", "notification.favourite": "{name} dodaje Twój wpis do ulubionych", "notification.favourite.name_and_others_with_link": "{name} i {count, plural, one {# inna osoba polubiła twój wpis} few {# inne osoby polubiły twój wpis} other {# innych osób polubiło twój wpis}}", "notification.follow": "{name} obserwuje Cię", diff --git a/config/locales/lv.yml b/config/locales/lv.yml index 1ced1bb7d0..3e44adbf46 100644 --- a/config/locales/lv.yml +++ b/config/locales/lv.yml @@ -830,6 +830,7 @@ lv: original_status: Oriģinālā ziņa reblogs: Reblogi status_changed: Ziņa mainīta + status_title: Publicēja @%{name} trending: Aktuāli visibility: Redzamība with_media: Ar multividi @@ -970,6 +971,7 @@ lv: one: Pēdējās nedēļas laikā izmantoja viens cilvēks other: Pēdējās nedēļas laikā izmantoja %{count} cilvēki zero: Pēdējās nedēļas laikā izmantoja %{count} cilvēku + title: Ieteikumi un pašlaik populāri trending: Populārākie warning_presets: add_new: Pievienot jaunu diff --git a/config/locales/pl.yml b/config/locales/pl.yml index 48a881a61b..3592ea53f6 100644 --- a/config/locales/pl.yml +++ b/config/locales/pl.yml @@ -193,6 +193,7 @@ pl: create_domain_block: Utwórz blokadę domeny create_email_domain_block: Utwórz blokadę domeny e-mail create_ip_block: Utwórz regułę IP + create_relay: Utwórz przekaźnik create_unavailable_domain: Utwórz niedostępną domenę create_user_role: Utwórz rolę demote_user: Zdegraduj użytkownika @@ -204,14 +205,17 @@ pl: destroy_email_domain_block: Usuń blokadę domeny e-mail destroy_instance: Wyczyść domenę destroy_ip_block: Usuń regułę IP + destroy_relay: Usuń przekaźnik destroy_status: Usuń wpis destroy_unavailable_domain: Usuń niedostępną domenę destroy_user_role: Zlikwiduj rolę disable_2fa_user: Wyłącz 2FA disable_custom_emoji: Wyłącz niestandardowe emoji + disable_relay: Wyłącz przekaźnik disable_sign_in_token_auth_user: Wyłącz uwierzytelnianie tokenem przez e-mail dla użytkownika disable_user: Wyłącz użytkownika enable_custom_emoji: Włącz niestandardowe emoji + enable_relay: Włącz przekaźnik enable_sign_in_token_auth_user: Włącz uwierzytelnianie tokenem przez e-mail dla użytkownika enable_user: Włącz użytkownika memorialize_account: Upamiętnij konto @@ -253,6 +257,7 @@ pl: create_domain_block_html: "%{name} zablokował(a) domenę %{target}" create_email_domain_block_html: "%{name} dodał(a) domenę e-mail %{target} na czarną listę" create_ip_block_html: "%{name} stworzył(a) regułę dla IP %{target}" + create_relay_html: "%{name} utworzył przekaźnik %{target}" create_unavailable_domain_html: "%{name} przestał(a) doręczać na domenę %{target}" create_user_role_html: "%{name} utworzył rolę %{target}" demote_user_html: "%{name} zdegradował(a) użytkownika %{target}" @@ -264,14 +269,17 @@ pl: destroy_email_domain_block_html: "%{name} usunął(-ęła) domenę e-mail %{target} z czarnej listy" destroy_instance_html: "%{name} usunął domenę %{target}" destroy_ip_block_html: "%{name} usunął(-ęła) regułę dla IP %{target}" + destroy_relay_html: "%{name} usunął przekaźnik %{target}" destroy_status_html: "%{name} usunął(-ęła) wpis użytkownika %{target}" destroy_unavailable_domain_html: "%{name} wznowił(a) doręczanie do domeny %{target}" destroy_user_role_html: "%{name} usunął rolę %{target}" disable_2fa_user_html: "%{name} wyłączył(a) uwierzytelnianie dwuskładnikowe użytkownikowi %{target}" disable_custom_emoji_html: "%{name} wyłączył(a) emoji %{target}" + disable_relay_html: "%{name} wyłączył przekaźnik %{target}" disable_sign_in_token_auth_user_html: "%{name} wyłączył/a uwierzytelnianie tokenem przez e-mail dla %{target}" disable_user_html: "%{name} zablokował(a) możliwość logowania użytkownikowi %{target}" enable_custom_emoji_html: "%{name} włączył(a) emoji %{target}" + enable_relay_html: "%{name} włączył przekaźnik %{target}" enable_sign_in_token_auth_user_html: "%{name} włączył/a uwierzytelnianie tokenem przez e-mail dla %{target}" enable_user_html: "%{name} przywrócił(a) możliwość logowania użytkownikowi %{target}" memorialize_account_html: "%{name} nadał(a) kontu %{target} status in memoriam" @@ -846,8 +854,10 @@ pl: back_to_account: Wróć na konto back_to_report: Wróć do strony zgłoszenia batch: + add_to_report: 'Dodaj do raportu #%{id}' remove_from_report: Usuń ze zgłoszenia report: Zgłoszenie + contents: Zawartość deleted: Usunięto favourites: Ulubione history: Historia wersji @@ -856,12 +866,17 @@ pl: media: title: Multimedia metadata: Metadane + no_history: Ten wpis nie był edytowany no_status_selected: Żaden wpis nie został zmieniony, bo żaden nie został wybrany open: Otwarty post original_status: Oryginalny post reblogs: Podbicia + replied_to_html: Odpowiedziano na %{acct_link} status_changed: Post zmieniony + status_title: Wpis @%{name} + title: Wpisy konta - @%{name} trending: Popularne + view_publicly: Wyświetl publicznie visibility: Widoczność with_media: Z zawartością multimedialną strikes: diff --git a/config/locales/simple_form.es-AR.yml b/config/locales/simple_form.es-AR.yml index dada648d5a..c3a65c0cc2 100644 --- a/config/locales/simple_form.es-AR.yml +++ b/config/locales/simple_form.es-AR.yml @@ -10,7 +10,7 @@ es-AR: indexable: Tus mensajes públicos pueden aparecer en los resultados de la búsqueda en Mastodon. La gente que interactuó con tus mensajes puede ser capaz de buscarlos sin importar el momento. note: 'Podés @mencionar otras cuentas o usar #etiquetas.' show_collections: La gente podrá navegar a través de tus seguidos y seguidores. Sin embargo, la gente que sigás, sabrá que lo estás haciendo. - unlocked: Las personas podrán seguirte sin solicitar aprobación. Desmarca si quieres revisar las solicitudes de seguimiento y elige si quieres aceptar o rechazar nuevos seguidores. + unlocked: Las personas podrán seguirte sin solicitar aprobación. Desmarcá si querés revisar las solicitudes de seguimiento y elegir si querés aceptar o rechazar nuevos seguidores. account_alias: acct: Especificá el nombredeusuario@dominio de la cuenta desde la que querés mudarte account_migration: diff --git a/config/locales/sv.yml b/config/locales/sv.yml index c48b45b2e8..173dd24c88 100644 --- a/config/locales/sv.yml +++ b/config/locales/sv.yml @@ -843,6 +843,7 @@ sv: open: Öppna inlägg original_status: Ursprungligt inlägg reblogs: Ombloggningar + replied_to_html: Svarade på %{acct_link} status_changed: Inlägg ändrat status_title: Inlägg av @%{name} title: Kontoinlägg - @%{name} From 174c687ca0234285fac87d47196bbf0b1b606c33 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Wed, 20 Nov 2024 10:01:13 +0100 Subject: [PATCH 61/64] Update dependency json-schema to v5.1.0 (#32992) 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 d45d17f52b..bb503e157e 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -346,7 +346,7 @@ GEM json-ld-preloaded (3.3.1) json-ld (~> 3.3) rdf (~> 3.3) - json-schema (5.0.1) + json-schema (5.1.0) addressable (~> 2.8) jsonapi-renderer (0.2.2) jwt (2.7.1) From e68b26c8df2056182564abcee230927ed53200c8 Mon Sep 17 00:00:00 2001 From: Claire Date: Wed, 20 Nov 2024 13:41:22 +0100 Subject: [PATCH 62/64] Fix posts made in the future being allowed to trend (#32996) --- app/models/trends/statuses.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/models/trends/statuses.rb b/app/models/trends/statuses.rb index 8757e5aa9c..cdf5929069 100644 --- a/app/models/trends/statuses.rb +++ b/app/models/trends/statuses.rb @@ -106,7 +106,7 @@ class Trends::Statuses < Trends::Base private def eligible?(status) - status.public_visibility? && status.account.discoverable? && !status.account.silenced? && !status.account.sensitized? && status.spoiler_text.blank? && !status.sensitive? && !status.reply? && valid_locale?(status.language) + status.created_at.past? && status.public_visibility? && status.account.discoverable? && !status.account.silenced? && !status.account.sensitized? && status.spoiler_text.blank? && !status.sensitive? && !status.reply? && valid_locale?(status.language) end def calculate_scores(statuses, at_time) From 683db3ab253e60d2a5ba14d0f348e5285704fea8 Mon Sep 17 00:00:00 2001 From: Eugen Rochko Date: Wed, 20 Nov 2024 16:56:35 +0100 Subject: [PATCH 63/64] Add ability to middle-mouse click posts in web UI (#32988) --- app/javascript/mastodon/components/status.jsx | 57 ++++++++----------- .../mastodon/components/status_content.jsx | 4 +- .../components/embedded_status.tsx | 12 +++- 3 files changed, 36 insertions(+), 37 deletions(-) diff --git a/app/javascript/mastodon/components/status.jsx b/app/javascript/mastodon/components/status.jsx index 95ea53521f..669eb22cb6 100644 --- a/app/javascript/mastodon/components/status.jsx +++ b/app/javascript/mastodon/components/status.jsx @@ -3,6 +3,8 @@ import PropTypes from 'prop-types'; import { injectIntl, defineMessages, FormattedMessage } from 'react-intl'; import classNames from 'classnames'; +import { Link } from 'react-router-dom'; + import ImmutablePropTypes from 'react-immutable-proptypes'; import ImmutablePureComponent from 'react-immutable-pure-component'; @@ -164,32 +166,18 @@ class Status extends ImmutablePureComponent { }; handleClick = e => { - if (e && (e.button !== 0 || e.ctrlKey || e.metaKey)) { + e.preventDefault(); + this.handleHotkeyOpen(e); + }; + + handleMouseUp = e => { + // Only handle clicks on the empty space above the content + + if (e.target !== e.currentTarget) { return; } - if (e) { - e.preventDefault(); - } - - this.handleHotkeyOpen(); - }; - - handlePrependAccountClick = e => { - this.handleAccountClick(e, false); - }; - - handleAccountClick = (e, proper = true) => { - if (e && (e.button !== 0 || e.ctrlKey || e.metaKey)) { - return; - } - - if (e) { - e.preventDefault(); - e.stopPropagation(); - } - - this._openProfile(proper); + this.handleClick(e); }; handleExpandedToggle = () => { @@ -287,7 +275,7 @@ class Status extends ImmutablePureComponent { this.props.onMention(this._properStatus().get('account')); }; - handleHotkeyOpen = () => { + handleHotkeyOpen = (e) => { if (this.props.onClick) { this.props.onClick(); return; @@ -300,7 +288,13 @@ class Status extends ImmutablePureComponent { return; } - history.push(`/@${status.getIn(['account', 'acct'])}/${status.get('id')}`); + const path = `/@${status.getIn(['account', 'acct'])}/${status.get('id')}`; + + if (e?.button === 0 && !(e?.ctrlKey || e?.metaKey)) { + history.push(path); + } else if (e?.button === 1 || (e?.button === 0 && (e?.ctrlKey || e?.metaKey))) { + window.open(path, '_blank', 'noreferrer noopener'); + } }; handleHotkeyOpenProfile = () => { @@ -412,7 +406,7 @@ class Status extends ImmutablePureComponent { prepend = (

- }} /> + }} />
); @@ -550,20 +544,19 @@ class Status extends ImmutablePureComponent {
{(connectReply || connectUp || connectToRoot) &&
} - {/* eslint-disable-next-line jsx-a11y/no-static-element-interactions */} -
- + {matchedFilters && } diff --git a/app/javascript/mastodon/components/status_content.jsx b/app/javascript/mastodon/components/status_content.jsx index 4950c896f9..fe485eb3ac 100644 --- a/app/javascript/mastodon/components/status_content.jsx +++ b/app/javascript/mastodon/components/status_content.jsx @@ -204,8 +204,8 @@ class StatusContent extends PureComponent { element = element.parentNode; } - if (deltaX + deltaY < 5 && e.button === 0 && this.props.onClick) { - this.props.onClick(); + if (deltaX + deltaY < 5 && (e.button === 0 || e.button === 1) && this.props.onClick) { + this.props.onClick(e); } this.startXY = null; diff --git a/app/javascript/mastodon/features/notifications_v2/components/embedded_status.tsx b/app/javascript/mastodon/features/notifications_v2/components/embedded_status.tsx index 65ea9b5d5e..ca0d1bc850 100644 --- a/app/javascript/mastodon/features/notifications_v2/components/embedded_status.tsx +++ b/app/javascript/mastodon/features/notifications_v2/components/embedded_status.tsx @@ -43,7 +43,7 @@ export const EmbeddedStatus: React.FC<{ statusId: string }> = ({ ); const handleMouseUp = useCallback>( - ({ clientX, clientY, target, button }) => { + ({ clientX, clientY, target, button, ctrlKey, metaKey }) => { const [startX, startY] = clickCoordinatesRef.current ?? [0, 0]; const [deltaX, deltaY] = [ Math.abs(clientX - startX), @@ -64,8 +64,14 @@ export const EmbeddedStatus: React.FC<{ statusId: string }> = ({ element = element.parentNode as HTMLDivElement | null; } - if (deltaX + deltaY < 5 && button === 0 && account) { - history.push(`/@${account.acct}/${statusId}`); + if (deltaX + deltaY < 5 && account) { + const path = `/@${account.acct}/${statusId}`; + + if (button === 0 && !(ctrlKey || metaKey)) { + history.push(path); + } else if (button === 1 || (button === 0 && (ctrlKey || metaKey))) { + window.open(path, '_blank', 'noreferrer noopener'); + } } clickCoordinatesRef.current = null; From 2526b32ad3cb1142edc6e2cfb272a9e3cef19060 Mon Sep 17 00:00:00 2001 From: Paulo Vilarinho <33267902+PauloVilarinho@users.noreply.github.com> Date: Wed, 20 Nov 2024 16:06:41 -0300 Subject: [PATCH 64/64] block scheduled status from frozen users (#30729) --- .../publish_scheduled_status_worker.rb | 2 ++ .../publish_scheduled_status_worker_spec.rb | 22 +++++++++++++++---- 2 files changed, 20 insertions(+), 4 deletions(-) diff --git a/app/workers/publish_scheduled_status_worker.rb b/app/workers/publish_scheduled_status_worker.rb index aa5c4a834a..0ec081de91 100644 --- a/app/workers/publish_scheduled_status_worker.rb +++ b/app/workers/publish_scheduled_status_worker.rb @@ -9,6 +9,8 @@ class PublishScheduledStatusWorker scheduled_status = ScheduledStatus.find(scheduled_status_id) scheduled_status.destroy! + return true if scheduled_status.account.user.disabled? + PostStatusService.new.call( scheduled_status.account, options_with_objects(scheduled_status.params.with_indifferent_access) diff --git a/spec/workers/publish_scheduled_status_worker_spec.rb b/spec/workers/publish_scheduled_status_worker_spec.rb index 35e510d253..9365e8a4bc 100644 --- a/spec/workers/publish_scheduled_status_worker_spec.rb +++ b/spec/workers/publish_scheduled_status_worker_spec.rb @@ -12,12 +12,26 @@ RSpec.describe PublishScheduledStatusWorker do subject.perform(scheduled_status.id) end - it 'creates a status' do - expect(scheduled_status.account.statuses.first.text).to eq 'Hello world, future!' + context 'when the account is not disabled' do + it 'creates a status' do + expect(scheduled_status.account.statuses.first.text).to eq 'Hello world, future!' + end + + it 'removes the scheduled status' do + expect(ScheduledStatus.find_by(id: scheduled_status.id)).to be_nil + end end - it 'removes the scheduled status' do - expect(ScheduledStatus.find_by(id: scheduled_status.id)).to be_nil + context 'when the account is disabled' do + let(:scheduled_status) { Fabricate(:scheduled_status, account: Fabricate(:account, user: Fabricate(:user, disabled: true))) } + + it 'does not create a status' do + expect(Status.count).to eq 0 + end + + it 'removes the scheduled status' do + expect(ScheduledStatus.find_by(id: scheduled_status.id)).to be_nil + end end end end