From 8125dae5a84e3115be6f487b337ac942c70a81f0 Mon Sep 17 00:00:00 2001 From: Claire Date: Mon, 12 Feb 2024 10:54:06 +0100 Subject: [PATCH 01/37] Rename `ES_CA_CERT` to `ES_CA_FILE` for consistency (#29147) --- config/initializers/chewy.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/config/initializers/chewy.rb b/config/initializers/chewy.rb index 0fb311dbb..0d9fc75e9 100644 --- a/config/initializers/chewy.rb +++ b/config/initializers/chewy.rb @@ -7,7 +7,7 @@ user = ENV.fetch('ES_USER', nil).presence password = ENV.fetch('ES_PASS', nil).presence fallback_prefix = ENV.fetch('REDIS_NAMESPACE', nil).presence prefix = ENV.fetch('ES_PREFIX') { fallback_prefix } -ca_file = ENV.fetch('ES_CA_CERT', nil).presence +ca_file = ENV.fetch('ES_CA_FILE', nil).presence transport_options = { ssl: { ca_file: ca_file } } if ca_file.present? From 6482948547beb35ecd5ad583a49e2c47c35cb0dd Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Mon, 12 Feb 2024 09:59:05 +0000 Subject: [PATCH 02/37] New Crowdin Translations (automated) (#29156) Co-authored-by: GitHub Actions --- app/javascript/mastodon/locales/be.json | 4 ++-- app/javascript/mastodon/locales/bg.json | 12 ++++++------ app/javascript/mastodon/locales/ca.json | 2 +- app/javascript/mastodon/locales/de.json | 12 ++++++------ app/javascript/mastodon/locales/ia.json | 8 ++++++++ app/javascript/mastodon/locales/sv.json | 1 + app/javascript/mastodon/locales/tok.json | 6 ++++-- config/locales/ca.yml | 2 +- config/locales/devise.ia.yml | 2 ++ config/locales/devise.ro.yml | 9 +++++++++ config/locales/doorkeeper.ia.yml | 1 + config/locales/ia.yml | 3 +++ config/locales/simple_form.bg.yml | 2 +- config/locales/simple_form.ia.yml | 1 + config/locales/simple_form.zh-TW.yml | 4 ++-- config/locales/sk.yml | 4 +++- 16 files changed, 51 insertions(+), 22 deletions(-) diff --git a/app/javascript/mastodon/locales/be.json b/app/javascript/mastodon/locales/be.json index daff6563e..7e21703b4 100644 --- a/app/javascript/mastodon/locales/be.json +++ b/app/javascript/mastodon/locales/be.json @@ -152,8 +152,8 @@ "compose_form.poll.switch_to_multiple": "Змяніце апытанне, каб дазволіць некалькі варыянтаў адказу", "compose_form.poll.switch_to_single": "Змяніце апытанне, каб дазволіць адзіны варыянт адказу", "compose_form.poll.type": "Стыль", - "compose_form.publish": "Допіс", - "compose_form.publish_form": "Апублікаваць", + "compose_form.publish": "Даслаць", + "compose_form.publish_form": "Новы допіс", "compose_form.reply": "Адказаць", "compose_form.save_changes": "Абнавіць", "compose_form.spoiler.marked": "Выдаліць папярэджанне аб змесціве", diff --git a/app/javascript/mastodon/locales/bg.json b/app/javascript/mastodon/locales/bg.json index 99c0f8b10..95572a793 100644 --- a/app/javascript/mastodon/locales/bg.json +++ b/app/javascript/mastodon/locales/bg.json @@ -3,7 +3,7 @@ "about.contact": "За контакти:", "about.disclaimer": "Mastodon е безплатен софтуер с отворен изходен код и търговска марка на Mastodon gGmbH.", "about.domain_blocks.no_reason_available": "Няма налична причина", - "about.domain_blocks.preamble": "Mastodon обикновено позволява да разглеждате съдържание и да взаимодействате с други потребители от всякакви сървъри във Федивърс. Има изключения, направени конкретно за този сървър.", + "about.domain_blocks.preamble": "Mastodon обикновено позволява да разглеждате съдържание и да взаимодействате с други потребители от всякакви сървъри във Федивселената. Има изключения, направени конкретно за този сървър.", "about.domain_blocks.silenced.explanation": "Обикновено няма да виждате профили и съдържание, освен ако изрично не го потърсите или се включете в него, следвайки го.", "about.domain_blocks.silenced.title": "Ограничено", "about.domain_blocks.suspended.explanation": "Никакви данни от този сървър няма да се обработват, съхраняват или обменят, правещи невъзможно всяко взаимодействие или комуникация с потребители от тези сървъри.", @@ -110,7 +110,7 @@ "column.about": "Относно", "column.blocks": "Блокирани потребители", "column.bookmarks": "Отметки", - "column.community": "Локална часова ос", + "column.community": "Локален инфопоток", "column.direct": "Частни споменавания", "column.directory": "Разглеждане на профили", "column.domain_blocks": "Блокирани домейни", @@ -228,7 +228,7 @@ "empty_column.account_unavailable": "Профилът не е наличен", "empty_column.blocks": "Още не сте блокирали никакви потребители.", "empty_column.bookmarked_statuses": "Още не сте отметнали публикации. Отметвайки някоя, то тя ще се покаже тук.", - "empty_column.community": "Местната часова ос е празна. Напишете нещо обществено, за да завъртите нещата!", + "empty_column.community": "Локалният инфопоток е празен. Публикувайте нещо, за да започнете!", "empty_column.direct": "Още нямате никакви частни споменавания. Тук ще се показват, изпращайки или получавайки едно.", "empty_column.domain_blocks": "Още няма блокирани домейни.", "empty_column.explore_statuses": "Няма нищо налагащо се в момента. Проверете пак по-късно!", @@ -348,10 +348,10 @@ "keyboard_shortcuts.favourites": "Отваряне на списъка с любими", "keyboard_shortcuts.federated": "Отваряне на федерирания инфопоток", "keyboard_shortcuts.heading": "Клавишни съчетания", - "keyboard_shortcuts.home": "Отваряне на началната часова ос", + "keyboard_shortcuts.home": "Отваряне на личния инфопоток", "keyboard_shortcuts.hotkey": "Бърз клавиш", "keyboard_shortcuts.legend": "Показване на тази легенда", - "keyboard_shortcuts.local": "Отваряне на местна часова ос", + "keyboard_shortcuts.local": "Отваряне на локалния инфопоток", "keyboard_shortcuts.mention": "Споменаване на автора", "keyboard_shortcuts.muted": "Отваряне на списъка със заглушени потребители", "keyboard_shortcuts.my_profile": "Отваряне на профила ви", @@ -402,7 +402,7 @@ "navigation_bar.advanced_interface": "Отваряне в разширен уебинтерфейс", "navigation_bar.blocks": "Блокирани потребители", "navigation_bar.bookmarks": "Отметки", - "navigation_bar.community_timeline": "Локална часова ос", + "navigation_bar.community_timeline": "Локален инфопоток", "navigation_bar.compose": "Съставяне на нова публикация", "navigation_bar.direct": "Частни споменавания", "navigation_bar.discover": "Откриване", diff --git a/app/javascript/mastodon/locales/ca.json b/app/javascript/mastodon/locales/ca.json index 0ae471e02..42de594cd 100644 --- a/app/javascript/mastodon/locales/ca.json +++ b/app/javascript/mastodon/locales/ca.json @@ -532,7 +532,7 @@ "privacy.public.short": "Públic", "privacy.unlisted.additional": "Es comporta igual que públic, excepte que la publicació no apareixerà als canals en directe o etiquetes, l'explora o a la cerca de Mastodon, fins i tot si ho heu activat a nivell de compte.", "privacy.unlisted.long": "Menys fanfàrries algorísmiques", - "privacy.unlisted.short": "Públic tranquil", + "privacy.unlisted.short": "Públic silenciós", "privacy_policy.last_updated": "Darrera actualització {date}", "privacy_policy.title": "Política de Privacitat", "recommended": "Recomanat", diff --git a/app/javascript/mastodon/locales/de.json b/app/javascript/mastodon/locales/de.json index cb90252c7..f29d016b0 100644 --- a/app/javascript/mastodon/locales/de.json +++ b/app/javascript/mastodon/locales/de.json @@ -146,12 +146,12 @@ "compose_form.lock_disclaimer.lock": "geschützt", "compose_form.placeholder": "Was gibt’s Neues?", "compose_form.poll.duration": "Umfragedauer", - "compose_form.poll.multiple": "Mehrfachauswahl", - "compose_form.poll.option_placeholder": "{number}. Auswahlmöglichkeit", + "compose_form.poll.multiple": "Mul­ti­ple-Choice", + "compose_form.poll.option_placeholder": "Option {number}", "compose_form.poll.single": "Einfachauswahl", "compose_form.poll.switch_to_multiple": "Mehrfachauswahl erlauben", "compose_form.poll.switch_to_single": "Nur Einfachauswahl erlauben", - "compose_form.poll.type": "Art", + "compose_form.poll.type": "Stil", "compose_form.publish": "Veröffentlichen", "compose_form.publish_form": "Neuer Beitrag", "compose_form.reply": "Antworten", @@ -277,9 +277,9 @@ "follow_request.authorize": "Genehmigen", "follow_request.reject": "Ablehnen", "follow_requests.unlocked_explanation": "Auch wenn dein Konto öffentlich bzw. nicht geschützt ist, haben die Moderator*innen von {domain} gedacht, dass du diesen Follower lieber manuell bestätigen solltest.", - "follow_suggestions.curated_suggestion": "Vom Server empfohlen", + "follow_suggestions.curated_suggestion": "Auswahl des Herausgebers", "follow_suggestions.dismiss": "Nicht mehr anzeigen", - "follow_suggestions.personalized_suggestion": "Personalisierte Empfehlung", + "follow_suggestions.personalized_suggestion": "Persönliche Empfehlung", "follow_suggestions.popular_suggestion": "Beliebte Empfehlung", "follow_suggestions.view_all": "Alle anzeigen", "follow_suggestions.who_to_follow": "Empfohlene Profile", @@ -528,7 +528,7 @@ "privacy.direct.short": "Bestimmte Profile", "privacy.private.long": "Nur deine Follower", "privacy.private.short": "Follower", - "privacy.public.long": "Alle auf und außerhalb von Mastodon", + "privacy.public.long": "Alle in und außerhalb von Mastodon", "privacy.public.short": "Öffentlich", "privacy.unlisted.additional": "Das Verhalten ist wie bei „Öffentlich“, jedoch erscheint dieser Beitrag nicht in „Live-Feeds“, „Erkunden“, Hashtags oder über die Mastodon-Suchfunktion – selbst wenn du das in den Einstellungen aktiviert hast.", "privacy.unlisted.long": "Weniger im Algorithmus berücksichtigt", diff --git a/app/javascript/mastodon/locales/ia.json b/app/javascript/mastodon/locales/ia.json index 10328efd0..079666285 100644 --- a/app/javascript/mastodon/locales/ia.json +++ b/app/javascript/mastodon/locales/ia.json @@ -2,8 +2,10 @@ "about.blocks": "Servitores moderate", "about.contact": "Contacto:", "about.disclaimer": "Mastodon es software libere, de codice aperte, e un marca de Mastodon gGmbH.", + "about.domain_blocks.no_reason_available": "Ration non disponibile", "about.domain_blocks.silenced.title": "Limitate", "about.domain_blocks.suspended.title": "Suspendite", + "about.not_available": "Iste information non faceva disponibile in iste servitor.", "about.rules": "Regulas del servitor", "account.account_note_header": "Nota", "account.add_or_remove_from_list": "Adder o remover ab listas", @@ -153,6 +155,7 @@ "disabled_account_banner.account_settings": "Parametros de conto", "disabled_account_banner.text": "Tu conto {disabledAccount} es actualmente disactivate.", "dismissable_banner.dismiss": "Dimitter", + "embed.preview": "Hic es como il parera:", "emoji_button.activity": "Activitate", "emoji_button.clear": "Rader", "emoji_button.custom": "Personalisate", @@ -171,6 +174,11 @@ "empty_column.account_timeline": "Nulle messages hic!", "empty_column.account_unavailable": "Profilo non disponibile", "empty_column.blocks": "Tu non ha blocate alcun usator ancora.", + "empty_column.domain_blocks": "Il non ha dominios blocate ancora.", + "empty_column.explore_statuses": "Nihil es in tendentias ora mesme. Retorna postea!", + "empty_column.favourited_statuses": "Tu non ha necun messages favorite ancora. Quando tu marca un como favorito, ille essera monstrate hic.", + "empty_column.followed_tags": "Tu ancora non ha sequite necun hashtags. Quando tu lo face, illes essera monstrate hic.", + "empty_column.hashtag": "Ancora non il ha nihil in iste hashtag.", "errors.unexpected_crash.report_issue": "Signalar un defecto", "explore.search_results": "Resultatos de recerca", "explore.suggested_follows": "Personas", diff --git a/app/javascript/mastodon/locales/sv.json b/app/javascript/mastodon/locales/sv.json index f9356fd27..4a15c60ed 100644 --- a/app/javascript/mastodon/locales/sv.json +++ b/app/javascript/mastodon/locales/sv.json @@ -148,6 +148,7 @@ "compose_form.poll.duration": "Varaktighet för omröstning", "compose_form.poll.multiple": "Flera val", "compose_form.poll.option_placeholder": "Alternativ {number}", + "compose_form.poll.single": "Välj en", "compose_form.poll.switch_to_multiple": "Ändra enkät för att tillåta flera val", "compose_form.poll.switch_to_single": "Ändra enkät för att tillåta ett enda val", "compose_form.poll.type": "Stil", diff --git a/app/javascript/mastodon/locales/tok.json b/app/javascript/mastodon/locales/tok.json index 7270d5206..ba45f8445 100644 --- a/app/javascript/mastodon/locales/tok.json +++ b/app/javascript/mastodon/locales/tok.json @@ -11,12 +11,12 @@ "account.block": "o weka e @{name}", "account.block_domain": "o weka e ma {domain}", "account.block_short": "o weka e jan tawa mi", - "account.blocked": "jan ni li weka tawa mi", + "account.blocked": "jan li weka tawa mi", "account.browse_more_on_origin_server": "sina tawa ma tan pi jan ni la sina ken lukin e mute", "account.cancel_follow_request": "o pini kute", "account.copy": "o pali same e linja pi lipu jan", "account.direct": "len la o mu e @{name}", - "account.disable_notifications": "@{name} li toki la o toki ala e toki ona tawa mi", + "account.disable_notifications": "@{name} li toki la o mu ala e mi", "account.domain_blocked": "ma ni li weka tawa sina", "account.edit_profile": "o ante e lipu mi", "account.enable_notifications": "@{name} li toki la o toki e toki ona tawa mi", @@ -92,6 +92,7 @@ "compose.published.open": "o lukin", "compose.saved.body": "ilo li awen e ijo pana sina.", "compose_form.direct_message_warning_learn_more": "o kama sona e ijo ante", + "compose_form.encryption_warning": "toki li len ala lon ilo Masoton ꞏ o pana ala e sona suli len lon ilo Masoton", "compose_form.placeholder": "sina wile toki e seme?", "compose_form.poll.duration": "tenpo pana", "compose_form.poll.multiple": "pana mute", @@ -117,6 +118,7 @@ "confirmations.discard_edit_media.confirm": "o weka", "confirmations.discard_edit_media.message": "toki sitelen anu lukin lili sitelen la ante pi awen ala li lon. sina wile weka e ante ni?", "confirmations.domain_block.confirm": "o weka.", + "confirmations.domain_block.message": "sina wile ala a wile a len e ma {domain} ꞏ ken suli la len jan taso li pona ꞏ len pi ma ni la sina ken ala lukin e ijo pi ma ni lon lipu toki ale anu lukin toki ꞏ len ni la jan kute sina pi ma ni li weka", "confirmations.edit.confirm": "o ante", "confirmations.logout.confirm": "o weka", "confirmations.logout.message": "sina wile ala wile weka", diff --git a/config/locales/ca.yml b/config/locales/ca.yml index 58f6e2637..f79d63a45 100644 --- a/config/locales/ca.yml +++ b/config/locales/ca.yml @@ -1548,7 +1548,7 @@ ca: unrecognized_emoji: no és un emoji reconegut redirects: prompt: Si confieu en aquest enllaç, feu-hi clic per a continuar. - title: Esteu sortint de %{instance}. + title: Deixeu %{instance}. relationships: activity: Activitat del compte confirm_follow_selected_followers: Segur que vols seguir els seguidors seleccionats? diff --git a/config/locales/devise.ia.yml b/config/locales/devise.ia.yml index c07e75fef..4b4d1f441 100644 --- a/config/locales/devise.ia.yml +++ b/config/locales/devise.ia.yml @@ -39,6 +39,8 @@ ia: webauthn_enabled: title: Claves de securitate activate registrations: + destroyed: A revider! Tu conto esseva cancellate con successo. Nos spera vider te novemente tosto. + signed_up_but_pending: Un message con un ligamine de confirmation esseva inviate a tu conto de email. Post que tu clicca le ligamine, nos revidera tu application. Tu essera notificate si illo es approbate. updated: Tu conto ha essite actualisate con successo. unlocks: unlocked: Tu conto ha essite disblocate con successo. Initia session a continuar. diff --git a/config/locales/devise.ro.yml b/config/locales/devise.ro.yml index 1a6a3ecd7..868bb4b3a 100644 --- a/config/locales/devise.ro.yml +++ b/config/locales/devise.ro.yml @@ -47,14 +47,19 @@ ro: subject: Instrucțiuni pentru resetarea parolei title: Resetare parolă two_factor_disabled: + explanation: Conectarea este acum posibilă folosind doar adresa de e-mail și parola. subject: Autentificare cu doi factori dezactivată + subtitle: Autentificarea cu doi factori pentru contul dvs. a fost dezactivată. title: 2FA dezactivat two_factor_enabled: + explanation: Pentru autentificare va fi necesar un token generat de aplicația TOTP asociată. subject: Autentificare în doi pași activată + subtitle: Autentificarea cu doi factori a fost activată pentru contul dvs. title: 2FA activat two_factor_recovery_codes_changed: explanation: Codurile anterioare de recuperare au fost invalidate și unele noi generate. subject: Recuperare în doi factori + subtitle: Codurile de recuperare anterioare au fost invalidate și s-au generat altele noi. title: Coduri de recuperare 2FA modificate unlock_instructions: subject: Instrucțiuni de deblocare @@ -68,9 +73,13 @@ ro: subject: 'Mastodon: Cheie de securitate ștearsă' title: Una dintre cheile tale de securitate a fost ștearsă webauthn_disabled: + explanation: Autentificarea cu chei de securitate a fost dezactivată pentru contul dvs. + extra: Conectarea este acum posibilă folosind doar token-ul generat de aplicația TOTP asociată. subject: 'Mastodon: Autentificarea cu chei de securitate dezactivată' title: Chei de securitate dezactivate webauthn_enabled: + explanation: Autentificarea cu cheie de securitate a fost activată pentru contul dvs. + extra: Cheia ta de securitate poate fi acum folosită pentru conectare. subject: 'Mastodon: Autentificarea cheii de securitate activată' title: Chei de securitate activate omniauth_callbacks: diff --git a/config/locales/doorkeeper.ia.yml b/config/locales/doorkeeper.ia.yml index e7e6f03cd..443342b40 100644 --- a/config/locales/doorkeeper.ia.yml +++ b/config/locales/doorkeeper.ia.yml @@ -34,6 +34,7 @@ ia: confirmations: revoke: Es tu secur? index: + last_used_at: Ultime uso in %{date} never_used: Nunquam usate scopes: Permissiones title: Tu applicationes autorisate diff --git a/config/locales/ia.yml b/config/locales/ia.yml index bf7da9a31..a85af012f 100644 --- a/config/locales/ia.yml +++ b/config/locales/ia.yml @@ -236,6 +236,8 @@ ia: migrations: errors: not_found: non poterea esser trovate + preferences: + public_timelines: Chronologias public statuses_cleanup: min_age: '1209600': 2 septimanas @@ -254,6 +256,7 @@ ia: disable: Disactivar 2FA user_mailer: welcome: + final_step: 'Comencia a publicar! Mesmo sin sequitores, tu messages public poterea esser reguardate per alteres, per exemplo in le chronologia local o in hashtags. Tu poterea voler introducer te con le hashtag #introductiones.' subject: Benvenite in Mastodon webauthn_credentials: delete: Deler diff --git a/config/locales/simple_form.bg.yml b/config/locales/simple_form.bg.yml index 68e45ef47..a4637a681 100644 --- a/config/locales/simple_form.bg.yml +++ b/config/locales/simple_form.bg.yml @@ -261,7 +261,7 @@ bg: status_page_url: URL адрес на страница със състоянието theme: Стандартна тема thumbnail: Образче на сървъра - timeline_preview: Позволяване на неупълномощен достъп до публични часови оси + timeline_preview: Позволяване на неудостоверен достъп до публични инфопотоци trendable_by_default: Без преглед на налагащото се trends: Включване на налагащи се trends_as_landing_page: Употреба на налагащото се като целева страница diff --git a/config/locales/simple_form.ia.yml b/config/locales/simple_form.ia.yml index 552abb255..af198d932 100644 --- a/config/locales/simple_form.ia.yml +++ b/config/locales/simple_form.ia.yml @@ -26,6 +26,7 @@ ia: username: Nomine de usator username_or_email: Nomine de usator o e-mail form_admin_settings: + bootstrap_timeline_accounts: Recommenda sempre iste contos a nove usatores custom_css: CSS personalisate profile_directory: Activar directorio de profilos site_contact_email: Adresse de e-mail de contacto diff --git a/config/locales/simple_form.zh-TW.yml b/config/locales/simple_form.zh-TW.yml index a31ad5eb1..696fd5fed 100644 --- a/config/locales/simple_form.zh-TW.yml +++ b/config/locales/simple_form.zh-TW.yml @@ -200,12 +200,12 @@ zh-TW: password: 密碼 phrase: 關鍵字或片語 setting_advanced_layout: 啟用進階網頁介面 - setting_aggregate_reblogs: 時間軸中的群組轉嘟 + setting_aggregate_reblogs: 於時間軸中不重複顯示轉嘟 setting_always_send_emails: 總是發送電子郵件通知 setting_auto_play_gif: 自動播放 GIF 動畫 setting_boost_modal: 轉嘟前先詢問我 setting_default_language: 嘟文語言 - setting_default_privacy: 嘟文可見範圍 + setting_default_privacy: 嘟文隱私設定 setting_default_sensitive: 總是將媒體標記為敏感內容 setting_delete_modal: 刪除嘟文前先詢問我 setting_disable_swiping: 停用滑動手勢 diff --git a/config/locales/sk.yml b/config/locales/sk.yml index 88617967f..520b64f88 100644 --- a/config/locales/sk.yml +++ b/config/locales/sk.yml @@ -251,14 +251,16 @@ sk: enable_user_html: "%{name} povolil/a prihlásenie pre používateľa %{target}" memorialize_account_html: "%{name} zmenil/a účet %{target} na pamätnú stránku" reject_appeal_html: "%{name} zamietol/la námietku moderovacieho rozhodnutia od %{target}" + remove_avatar_user_html: "%{name} vymazal/a %{target}/ov/in avatar" reopen_report_html: "%{name} znovu otvoril/a nahlásenie %{target}" resend_user_html: "%{name} znovu odoslal/a potvrdzovací email pre %{target}" reset_password_user_html: "%{name} resetoval/a heslo používateľa %{target}" resolve_report_html: "%{name} vyriešil/a nahlásenie %{target}" - sensitive_account_html: "%{name} označil médium od %{target} za chúlostivé" + sensitive_account_html: "%{name} označil/a médium od %{target} za chúlostivé" silence_account_html: "%{name} obmedzil/a účet %{target}" suspend_account_html: "%{name} zablokoval/a účet používateľa %{target}" unassigned_report_html: "%{name} odobral/a report od %{target}" + unsensitive_account_html: "%{name} odznačil/a médium od %{target} ako chúlostivé" unsuspend_account_html: "%{name} spojazdnil/a účet %{target}" update_announcement_html: "%{name} aktualizoval/a oboznámenie %{target}" update_custom_emoji_html: "%{name} aktualizoval/a emotikonu %{target}" From 58918844a90b9a3f5bd39d3ed525f7bcbe02ef32 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Mon, 12 Feb 2024 11:20:54 +0100 Subject: [PATCH 03/37] Update peter-evans/create-pull-request action to v6 (#29167) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- .github/workflows/crowdin-download.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/crowdin-download.yml b/.github/workflows/crowdin-download.yml index d3988d2f1..a676ff12f 100644 --- a/.github/workflows/crowdin-download.yml +++ b/.github/workflows/crowdin-download.yml @@ -52,7 +52,7 @@ jobs: # Create or update the pull request - name: Create Pull Request - uses: peter-evans/create-pull-request@v5.0.2 + uses: peter-evans/create-pull-request@v6.0.0 with: commit-message: 'New Crowdin translations' title: 'New Crowdin Translations (automated)' From cf0d6bef8b62acd8f4594f56e9096817149a6135 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Mon, 12 Feb 2024 11:21:17 +0100 Subject: [PATCH 04/37] Update eslint (non-major) (#29166) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- yarn.lock | 122 +++++++++++++++++++++++++++--------------------------- 1 file changed, 61 insertions(+), 61 deletions(-) diff --git a/yarn.lock b/yarn.lock index fb3472904..351fd31ab 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1697,14 +1697,14 @@ __metadata: languageName: node linkType: hard -"@es-joy/jsdoccomment@npm:~0.41.0": - version: 0.41.0 - resolution: "@es-joy/jsdoccomment@npm:0.41.0" +"@es-joy/jsdoccomment@npm:~0.42.0": + version: 0.42.0 + resolution: "@es-joy/jsdoccomment@npm:0.42.0" dependencies: comment-parser: "npm:1.4.1" esquery: "npm:^1.5.0" jsdoc-type-pratt-parser: "npm:~4.0.0" - checksum: 1fa27531eba32e4699664da53a0865aeeda1f7e83ac156fe53b7a6b09d2f3816baa94a34845ff019c10289b09572bda5519ec917e3e241088975477fa880f72d + checksum: a8122762d2df3c6501a9c459e2822315a23c0078c4aeb0b40fb3c84b99e21a78e85e67f962d6b5dde5eb751792a1c67c6a170b619573db7151098a19950abe35 languageName: node linkType: hard @@ -3663,14 +3663,14 @@ __metadata: linkType: hard "@typescript-eslint/eslint-plugin@npm:^6.0.0": - version: 6.20.0 - resolution: "@typescript-eslint/eslint-plugin@npm:6.20.0" + version: 6.21.0 + resolution: "@typescript-eslint/eslint-plugin@npm:6.21.0" dependencies: "@eslint-community/regexpp": "npm:^4.5.1" - "@typescript-eslint/scope-manager": "npm:6.20.0" - "@typescript-eslint/type-utils": "npm:6.20.0" - "@typescript-eslint/utils": "npm:6.20.0" - "@typescript-eslint/visitor-keys": "npm:6.20.0" + "@typescript-eslint/scope-manager": "npm:6.21.0" + "@typescript-eslint/type-utils": "npm:6.21.0" + "@typescript-eslint/utils": "npm:6.21.0" + "@typescript-eslint/visitor-keys": "npm:6.21.0" debug: "npm:^4.3.4" graphemer: "npm:^1.4.0" ignore: "npm:^5.2.4" @@ -3683,44 +3683,44 @@ __metadata: peerDependenciesMeta: typescript: optional: true - checksum: 5020faac39be476de056342f58f2bf68bb788f230e2fa4a2e27ceab8a5187dc450beba7333b0aa741a43aeaff45a117558132953f9390b5eca4c2cc004fde716 + checksum: f911a79ee64d642f814a3b6cdb0d324b5f45d9ef955c5033e78903f626b7239b4aa773e464a38c3e667519066169d983538f2bf8e5d00228af587c9d438fb344 languageName: node linkType: hard "@typescript-eslint/parser@npm:^6.17.0": - version: 6.20.0 - resolution: "@typescript-eslint/parser@npm:6.20.0" + version: 6.21.0 + resolution: "@typescript-eslint/parser@npm:6.21.0" dependencies: - "@typescript-eslint/scope-manager": "npm:6.20.0" - "@typescript-eslint/types": "npm:6.20.0" - "@typescript-eslint/typescript-estree": "npm:6.20.0" - "@typescript-eslint/visitor-keys": "npm:6.20.0" + "@typescript-eslint/scope-manager": "npm:6.21.0" + "@typescript-eslint/types": "npm:6.21.0" + "@typescript-eslint/typescript-estree": "npm:6.21.0" + "@typescript-eslint/visitor-keys": "npm:6.21.0" debug: "npm:^4.3.4" peerDependencies: eslint: ^7.0.0 || ^8.0.0 peerDependenciesMeta: typescript: optional: true - checksum: d84ad5e2282b1096c80dedb903c83ecc31eaf7be1aafcb14c18d9ec2d4a319f2fd1e5a9038b944d9f42c36c1c57add5e4292d4026ca7d3d5441d41286700d402 + checksum: a8f99820679decd0d115c0af61903fb1de3b1b5bec412dc72b67670bf636de77ab07f2a68ee65d6da7976039bbf636907f9d5ca546db3f0b98a31ffbc225bc7d languageName: node linkType: hard -"@typescript-eslint/scope-manager@npm:6.20.0": - version: 6.20.0 - resolution: "@typescript-eslint/scope-manager@npm:6.20.0" +"@typescript-eslint/scope-manager@npm:6.21.0": + version: 6.21.0 + resolution: "@typescript-eslint/scope-manager@npm:6.21.0" dependencies: - "@typescript-eslint/types": "npm:6.20.0" - "@typescript-eslint/visitor-keys": "npm:6.20.0" - checksum: f6768ed2dcd2d1771d55ed567ff392a6569ffd683a26500067509dd41769f8838c43686460fe7337144f324fd063df33f5d5646d44e5df4998ceffb3ad1fb790 + "@typescript-eslint/types": "npm:6.21.0" + "@typescript-eslint/visitor-keys": "npm:6.21.0" + checksum: eaf868938d811cbbea33e97e44ba7050d2b6892202cea6a9622c486b85ab1cf801979edf78036179a8ba4ac26f1dfdf7fcc83a68c1ff66be0b3a8e9a9989b526 languageName: node linkType: hard -"@typescript-eslint/type-utils@npm:6.20.0": - version: 6.20.0 - resolution: "@typescript-eslint/type-utils@npm:6.20.0" +"@typescript-eslint/type-utils@npm:6.21.0": + version: 6.21.0 + resolution: "@typescript-eslint/type-utils@npm:6.21.0" dependencies: - "@typescript-eslint/typescript-estree": "npm:6.20.0" - "@typescript-eslint/utils": "npm:6.20.0" + "@typescript-eslint/typescript-estree": "npm:6.21.0" + "@typescript-eslint/utils": "npm:6.21.0" debug: "npm:^4.3.4" ts-api-utils: "npm:^1.0.1" peerDependencies: @@ -3728,23 +3728,23 @@ __metadata: peerDependenciesMeta: typescript: optional: true - checksum: 8f622fbb14268f1d00b2948f995b570f0ef82be02c12be41d90385290a56ea0dbd34d855d6a5aff100b57f3bdd300ff0c300f16c78f12d6064f7ae6e34fd71bf + checksum: 7409c97d1c4a4386b488962739c4f1b5b04dc60cf51f8cd88e6b12541f84d84c6b8b67e491a147a2c95f9ec486539bf4519fb9d418411aef6537b9c156468117 languageName: node linkType: hard -"@typescript-eslint/types@npm:6.20.0": - version: 6.20.0 - resolution: "@typescript-eslint/types@npm:6.20.0" - checksum: 37589003b0e06f83c1945e3748e91af85918cfd997766894642a08e6f355f611cfe11df4e7632dda96e3a9b3441406283fe834ab0906cf81ea97fd43ca2aebe3 +"@typescript-eslint/types@npm:6.21.0": + version: 6.21.0 + resolution: "@typescript-eslint/types@npm:6.21.0" + checksum: 020631d3223bbcff8a0da3efbdf058220a8f48a3de221563996ad1dcc30d6c08dadc3f7608cc08830d21c0d565efd2db19b557b9528921c78aabb605eef2d74d languageName: node linkType: hard -"@typescript-eslint/typescript-estree@npm:6.20.0": - version: 6.20.0 - resolution: "@typescript-eslint/typescript-estree@npm:6.20.0" +"@typescript-eslint/typescript-estree@npm:6.21.0": + version: 6.21.0 + resolution: "@typescript-eslint/typescript-estree@npm:6.21.0" dependencies: - "@typescript-eslint/types": "npm:6.20.0" - "@typescript-eslint/visitor-keys": "npm:6.20.0" + "@typescript-eslint/types": "npm:6.21.0" + "@typescript-eslint/visitor-keys": "npm:6.21.0" debug: "npm:^4.3.4" globby: "npm:^11.1.0" is-glob: "npm:^4.0.3" @@ -3754,34 +3754,34 @@ __metadata: peerDependenciesMeta: typescript: optional: true - checksum: 551f13445a303882d9fc0fbe14ef8507eb8414253fd87a5f13d2e324b5280b626421a238b8ec038e628bc80128dc06c057757f668738e82e64d5b39a9083c27d + checksum: af1438c60f080045ebb330155a8c9bb90db345d5069cdd5d01b67de502abb7449d6c75500519df829f913a6b3f490ade3e8215279b6bdc63d0fb0ae61034df5f languageName: node linkType: hard -"@typescript-eslint/utils@npm:6.20.0, @typescript-eslint/utils@npm:^6.18.1": - version: 6.20.0 - resolution: "@typescript-eslint/utils@npm:6.20.0" +"@typescript-eslint/utils@npm:6.21.0, @typescript-eslint/utils@npm:^6.18.1": + version: 6.21.0 + resolution: "@typescript-eslint/utils@npm:6.21.0" dependencies: "@eslint-community/eslint-utils": "npm:^4.4.0" "@types/json-schema": "npm:^7.0.12" "@types/semver": "npm:^7.5.0" - "@typescript-eslint/scope-manager": "npm:6.20.0" - "@typescript-eslint/types": "npm:6.20.0" - "@typescript-eslint/typescript-estree": "npm:6.20.0" + "@typescript-eslint/scope-manager": "npm:6.21.0" + "@typescript-eslint/types": "npm:6.21.0" + "@typescript-eslint/typescript-estree": "npm:6.21.0" semver: "npm:^7.5.4" peerDependencies: eslint: ^7.0.0 || ^8.0.0 - checksum: 0a8ede3d80a365b52ae96d88e4a9f6e6abf3569c6b60ff9f42ff900cd843ae7c5493cd95f8f2029d90bb0acbf31030980206af98e581d760d6d41e0f80e9fb86 + checksum: ab2df3833b2582d4e5467a484d08942b4f2f7208f8e09d67de510008eb8001a9b7460f2f9ba11c12086fd3cdcac0c626761c7995c2c6b5657d5fa6b82030a32d languageName: node linkType: hard -"@typescript-eslint/visitor-keys@npm:6.20.0": - version: 6.20.0 - resolution: "@typescript-eslint/visitor-keys@npm:6.20.0" +"@typescript-eslint/visitor-keys@npm:6.21.0": + version: 6.21.0 + resolution: "@typescript-eslint/visitor-keys@npm:6.21.0" dependencies: - "@typescript-eslint/types": "npm:6.20.0" + "@typescript-eslint/types": "npm:6.21.0" eslint-visitor-keys: "npm:^3.4.1" - checksum: 852d938f2e5d57200cf62733b42e73a369f797b097d17e8fd3fffd0f7315c3b9e1863eed60bb8d57d6535a3b7f1980f645f96ec6d513950f182bfa8107b33fab + checksum: 7395f69739cfa1cb83c1fb2fad30afa2a814756367302fb4facd5893eff66abc807e8d8f63eba94ed3b0fe0c1c996ac9a1680bcbf0f83717acedc3f2bb724fbf languageName: node linkType: hard @@ -7347,21 +7347,21 @@ __metadata: linkType: hard "eslint-plugin-jsdoc@npm:^48.0.0": - version: 48.0.4 - resolution: "eslint-plugin-jsdoc@npm:48.0.4" + version: 48.0.6 + resolution: "eslint-plugin-jsdoc@npm:48.0.6" dependencies: - "@es-joy/jsdoccomment": "npm:~0.41.0" + "@es-joy/jsdoccomment": "npm:~0.42.0" are-docs-informative: "npm:^0.0.2" comment-parser: "npm:1.4.1" debug: "npm:^4.3.4" escape-string-regexp: "npm:^4.0.0" esquery: "npm:^1.5.0" is-builtin-module: "npm:^3.2.1" - semver: "npm:^7.5.4" + semver: "npm:^7.6.0" spdx-expression-parse: "npm:^4.0.0" peerDependencies: eslint: ^7.0.0 || ^8.0.0 || ^9.0.0 - checksum: c73063d26ca70d37ea00eea9750d1f889e5bfda64ca46dbfc6bf4842b892551c320368220cb46acc9d3d96a89fd5391486650284b82dc722f700e3b5df5c78db + checksum: 7762793fb2a738d248144346e85b8c7ec2f975be1a24d45984a5d24da03723b76c66ead1b8064d60b18be09a9a9835320036a39fef917a1b6c83b916729d70dd languageName: node linkType: hard @@ -14721,14 +14721,14 @@ __metadata: languageName: node linkType: hard -"semver@npm:^7.3.2, semver@npm:^7.3.4, semver@npm:^7.3.5, semver@npm:^7.5.3, semver@npm:^7.5.4": - version: 7.5.4 - resolution: "semver@npm:7.5.4" +"semver@npm:^7.3.2, semver@npm:^7.3.4, semver@npm:^7.3.5, semver@npm:^7.5.3, semver@npm:^7.5.4, semver@npm:^7.6.0": + version: 7.6.0 + resolution: "semver@npm:7.6.0" dependencies: lru-cache: "npm:^6.0.0" bin: semver: bin/semver.js - checksum: 5160b06975a38b11c1ab55950cb5b8a23db78df88275d3d8a42ccf1f29e55112ac995b3a26a522c36e3b5f76b0445f1eef70d696b8c7862a2b4303d7b0e7609e + checksum: fbfe717094ace0aa8d6332d7ef5ce727259815bd8d8815700853f4faf23aacbd7192522f0dc5af6df52ef4fa85a355ebd2f5d39f554bd028200d6cf481ab9b53 languageName: node linkType: hard From 819ede190e1edeab1c42f41d53895e2bf784406d Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Mon, 12 Feb 2024 11:39:31 +0100 Subject: [PATCH 05/37] Update dependency dotenv to v16.4.2 (#29157) 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 351fd31ab..d76af5d9e 100644 --- a/yarn.lock +++ b/yarn.lock @@ -6844,9 +6844,9 @@ __metadata: linkType: hard "dotenv@npm:^16.0.3": - version: 16.4.1 - resolution: "dotenv@npm:16.4.1" - checksum: ef3d95f48f38146df0881a4b58447ae437d2da3f6d645074b84de4e64ef64ba75fc357c5ed66b3c2b813b5369fdeb6a4777d6ade2d50e54eed6aa06dddc98bc4 + version: 16.4.2 + resolution: "dotenv@npm:16.4.2" + checksum: 04373a742f565896de1ab3eadcd15c1543b6d1fc37bb7ab2faa2286a0b3fd432aa02c6fd330ede758432f36865f0fb128afa2e5991e0a789b9011e720ba4a876 languageName: node linkType: hard From b244e5cb81bc49c54194cd340408b0b27c0802db Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Tue, 13 Feb 2024 08:56:46 +0100 Subject: [PATCH 06/37] Update dependency sidekiq-unique-jobs to v7.1.33 (#29175) 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 152436b47..00ca4663a 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -707,7 +707,7 @@ GEM rufus-scheduler (~> 3.2) sidekiq (>= 6, < 8) tilt (>= 1.4.0) - sidekiq-unique-jobs (7.1.31) + sidekiq-unique-jobs (7.1.33) brpoplpush-redis_script (> 0.1.1, <= 2.0.0) concurrent-ruby (~> 1.0, >= 1.0.5) redis (< 5.0) From e25d9dfb25f9e412a5dabe1e27675130a285b0d3 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Tue, 13 Feb 2024 09:02:55 +0100 Subject: [PATCH 07/37] Update dependency dotenv to v16.4.3 (#29174) 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 d76af5d9e..6088034d9 100644 --- a/yarn.lock +++ b/yarn.lock @@ -6844,9 +6844,9 @@ __metadata: linkType: hard "dotenv@npm:^16.0.3": - version: 16.4.2 - resolution: "dotenv@npm:16.4.2" - checksum: 04373a742f565896de1ab3eadcd15c1543b6d1fc37bb7ab2faa2286a0b3fd432aa02c6fd330ede758432f36865f0fb128afa2e5991e0a789b9011e720ba4a876 + version: 16.4.3 + resolution: "dotenv@npm:16.4.3" + checksum: c6a572b2dab5d71accb7064c90b38dfd4068c2487be859a0f053460fcaa685a7718e78db51d643b32e0736b318988c31f8c45cb4ab99cd620278f537177cb0ab languageName: node linkType: hard From 5de1ce23c3debb019f926b297e19a7c37e229871 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Tue, 13 Feb 2024 10:08:55 +0100 Subject: [PATCH 08/37] New Crowdin Translations (automated) (#29182) Co-authored-by: GitHub Actions --- app/javascript/mastodon/locales/bg.json | 2 +- app/javascript/mastodon/locales/es.json | 2 ++ app/javascript/mastodon/locales/ro.json | 30 ++++++++++++++++++++++++ app/javascript/mastodon/locales/tok.json | 13 ++++++++++ 4 files changed, 46 insertions(+), 1 deletion(-) diff --git a/app/javascript/mastodon/locales/bg.json b/app/javascript/mastodon/locales/bg.json index 95572a793..5a6fa175e 100644 --- a/app/javascript/mastodon/locales/bg.json +++ b/app/javascript/mastodon/locales/bg.json @@ -524,7 +524,7 @@ "poll_button.add_poll": "Анкетиране", "poll_button.remove_poll": "Премахване на анкета", "privacy.change": "Промяна на поверителността на публикация", - "privacy.direct.long": "Всеки споменат в публикацията", + "privacy.direct.long": "Споменатите в публикацията", "privacy.direct.short": "Определени хора", "privacy.private.long": "Само последователите ви", "privacy.private.short": "Последователи", diff --git a/app/javascript/mastodon/locales/es.json b/app/javascript/mastodon/locales/es.json index d5e8f4239..3e4f36ba5 100644 --- a/app/javascript/mastodon/locales/es.json +++ b/app/javascript/mastodon/locales/es.json @@ -530,6 +530,8 @@ "privacy.private.short": "Seguidores", "privacy.public.long": "Cualquiera dentro y fuera de Mastodon", "privacy.public.short": "Público", + "privacy.unlisted.additional": "Esto se comporta exactamente igual que el público, excepto que la publicación no aparecerá en la cronología en directo o en las etiquetas, la exploración o búsqueda de Mastodon, incluso si está optado por activar la cuenta de usuario.", + "privacy.unlisted.long": "Menos fanfares algorítmicos", "privacy.unlisted.short": "Público tranquilo", "privacy_policy.last_updated": "Actualizado por última vez {date}", "privacy_policy.title": "Política de Privacidad", diff --git a/app/javascript/mastodon/locales/ro.json b/app/javascript/mastodon/locales/ro.json index d236ba496..547493af1 100644 --- a/app/javascript/mastodon/locales/ro.json +++ b/app/javascript/mastodon/locales/ro.json @@ -21,6 +21,8 @@ "account.blocked": "Blocat", "account.browse_more_on_origin_server": "Vezi mai multe pe profilul original", "account.cancel_follow_request": "Retrage cererea de urmărire", + "account.copy": "Copiază link-ul profilului", + "account.direct": "Menționează pe @{name} în privat", "account.disable_notifications": "Nu îmi mai trimite notificări când postează @{name}", "account.domain_blocked": "Domeniu blocat", "account.edit_profile": "Modifică profilul", @@ -30,6 +32,7 @@ "account.featured_tags.last_status_never": "Fără postări", "account.featured_tags.title": "Haștagurile recomandate de {name}", "account.follow": "Abonează-te", + "account.follow_back": "Urmăreşte înapoi", "account.followers": "Urmăritori", "account.followers.empty": "Acest utilizator nu are încă urmăritori.", "account.followers_counter": "{count, plural, one {Un abonat} few {{counter} abonați} other {{counter} de abonați}}", @@ -38,6 +41,7 @@ "account.follows.empty": "Momentan acest utilizator nu are niciun abonament.", "account.go_to_profile": "Mergi la profil", "account.hide_reblogs": "Ascunde distribuirile de la @{name}", + "account.in_memoriam": "În Memoriam.", "account.joined_short": "Înscris", "account.languages": "Schimbă limbile abonate", "account.link_verified_on": "Proprietatea acestui link a fost verificată pe {date}", @@ -46,7 +50,10 @@ "account.mention": "Menționează pe @{name}", "account.moved_to": "{name} a indicat că noul său cont este acum:", "account.mute": "Pune pe @{name} pe silențios", + "account.mute_notifications_short": "Amuțește notificările", + "account.mute_short": "Ignoră", "account.muted": "Pus pe silențios", + "account.no_bio": "Nicio descriere furnizată.", "account.open_original_page": "Deschide pagina originală", "account.posts": "Postări", "account.posts_with_replies": "Postări și răspunsuri", @@ -69,6 +76,7 @@ "admin.dashboard.retention.average": "În medie", "admin.dashboard.retention.cohort": "Înregistrări lunar", "admin.dashboard.retention.cohort_size": "Utilizatori noi", + "admin.impact_report.title": "Rezumatul impactului", "alert.rate_limited.message": "Vă rugăm să reîncercați după {retry_time, time, medium}.", "alert.rate_limited.title": "Debit limitat", "alert.unexpected.message": "A apărut o eroare neașteptată.", @@ -98,9 +106,11 @@ "column.blocks": "Utilizatori blocați", "column.bookmarks": "Marcaje", "column.community": "Cronologie locală", + "column.direct": "Mențiuni private", "column.directory": "Explorează profiluri", "column.domain_blocks": "Domenii blocate", "column.favourites": "Favorite", + "column.firehose": "Fluxuri live", "column.follow_requests": "Cereri de abonare", "column.home": "Acasă", "column.lists": "Liste", @@ -131,11 +141,19 @@ "compose_form.lock_disclaimer.lock": "privat", "compose_form.placeholder": "La ce te gândești?", "compose_form.poll.duration": "Durata sondajului", + "compose_form.poll.multiple": "Alegeri multiple", + "compose_form.poll.option_placeholder": "Opțiune {number}", + "compose_form.poll.single": "Alegeți unul", "compose_form.poll.switch_to_multiple": "Modifică sondajul pentru a permite mai multe opțiuni", "compose_form.poll.switch_to_single": "Modifică sondajul pentru a permite o singură opțiune", + "compose_form.poll.type": "Stil", + "compose_form.publish": "Postare", "compose_form.publish_form": "Publică", + "compose_form.reply": "Răspundeți", + "compose_form.save_changes": "Actualizare", "compose_form.spoiler.marked": "Elimină avertismentul privind conținutul", "compose_form.spoiler.unmarked": "Adaugă un avertisment privind conținutul", + "compose_form.spoiler_placeholder": "Atenționare de conținut (opțional)", "confirmation_modal.cancel": "Anulează", "confirmations.block.block_and_report": "Blochează și raportează", "confirmations.block.confirm": "Blochează", @@ -151,6 +169,7 @@ "confirmations.domain_block.confirm": "Blochează întregul domeniu", "confirmations.domain_block.message": "Ești absolut sigur că vrei să blochezi tot domeniul {domain}? În cele mai multe cazuri, raportarea sau blocarea anumitor lucruri este suficientă și de preferat. Nu vei mai vedea niciun conținut din acest domeniu în vreun flux public sau în vreo notificare. Abonații tăi din acest domeniu vor fi eliminați.", "confirmations.edit.confirm": "Modifică", + "confirmations.edit.message": "Editarea acum va suprascrie mesajul pe care îl compuneți în prezent. Sunteți sigur că vreți să continuați?", "confirmations.logout.confirm": "Deconectare", "confirmations.logout.message": "Ești sigur că vrei să te deconectezi?", "confirmations.mute.confirm": "Ignoră", @@ -165,6 +184,7 @@ "conversation.mark_as_read": "Marchează ca citit", "conversation.open": "Vizualizează conversația", "conversation.with": "Cu {names}", + "copy_icon_button.copied": "Copiat în clipboard", "copypaste.copied": "Copiat", "copypaste.copy_to_clipboard": "Copiază în clipboard", "directory.federated": "Din fediversul cunoscut", @@ -240,10 +260,17 @@ "filter_modal.select_filter.title": "Filtrează această postare", "filter_modal.title.status": "Filtrează o postare", "firehose.all": "Toate", + "firehose.local": "Acest Server", "firehose.remote": "Alte servere", "follow_request.authorize": "Acceptă", "follow_request.reject": "Respinge", "follow_requests.unlocked_explanation": "Chiar dacă contul tău nu este blocat, personalul {domain} a considerat că ai putea prefera să consulți manual cererile de abonare de la aceste conturi.", + "follow_suggestions.curated_suggestion": "Alegerile Editorilor", + "follow_suggestions.dismiss": "Nu mai afișa din nou", + "follow_suggestions.personalized_suggestion": "Sugestie personalizată", + "follow_suggestions.popular_suggestion": "Sugestie populară", + "follow_suggestions.view_all": "Vizualizați tot", + "follow_suggestions.who_to_follow": "Pe cine să urmăriți", "followed_tags": "Hastaguri urmărite", "footer.about": "Despre", "footer.directory": "Catalogul de profiluri", @@ -272,12 +299,15 @@ "home.hide_announcements": "Ascunde anunțurile", "home.pending_critical_update.body": "Te rugăm să-ți actualizezi serverul de Mastodon cat mai curând posibil!", "home.pending_critical_update.link": "Vezi noutăți", + "home.pending_critical_update.title": "Actualizare critică de securitate disponibilă!", "home.show_announcements": "Afișează anunțurile", + "interaction_modal.description.favourite": "Cu un cont pe Mastodon, poți adăuga această postare la favorite pentru a-l informa pe autorul ei că o apreciezi și pentru a o salva pentru mai târziu.", "interaction_modal.description.follow": "Cu un cont Mastodon, poți urmări pe {name} pentru a vedea postările sale în cronologia ta principală.", "interaction_modal.description.reblog": "Cu un cont pe Mastodon, poți distribui această postare pentru a le-o arăta și celor abonați ție.", "interaction_modal.description.reply": "Cu un cont pe Mastodon, poți răspunde acestei postări.", "interaction_modal.login.action": "Du-mă acasă", "interaction_modal.login.prompt": "Adresa serverului tău acasă, de ex. mastodon.social", + "interaction_modal.no_account_yet": "Nu ești încă pe Mastodon?", "interaction_modal.on_another_server": "Pe un alt server", "interaction_modal.on_this_server": "Pe acest server", "interaction_modal.title.follow": "Urmărește pe {name}", diff --git a/app/javascript/mastodon/locales/tok.json b/app/javascript/mastodon/locales/tok.json index ba45f8445..85f62f404 100644 --- a/app/javascript/mastodon/locales/tok.json +++ b/app/javascript/mastodon/locales/tok.json @@ -6,6 +6,7 @@ "about.not_available": "lon kulupu ni la sina ken alasa ala e sona ni.", "about.rules": "lawa kulupu", "account.account_note_header": "sona awen", + "account.add_or_remove_from_list": "o ante e lipu jan", "account.badges.bot": "ilo nanpa li lawa e ni", "account.badges.group": "kulupu", "account.block": "o weka e @{name}", @@ -83,6 +84,7 @@ "column_header.pin": "o sewi", "column_header.show_settings": "o lukin e lawa", "column_header.unpin": "o sewi ala", + "column_subheading.settings": "ken ilo", "community.column_settings.local_only": "toki tan ni taso", "community.column_settings.media_only": "sitelen taso", "community.column_settings.remote_only": "toki tan ante taso", @@ -177,6 +179,8 @@ "follow_request.reject": "o ala", "follow_suggestions.view_all": "o lukin e ale", "follow_suggestions.who_to_follow": "sina o kute e ni", + "footer.about": "sona", + "footer.directory": "lipu jan", "footer.get_app": "o jo e ilo", "footer.privacy_policy": "lawa len", "footer.source_code": "o lukin e toki ilo", @@ -195,6 +199,7 @@ "interaction_modal.title.follow": "o kute e {name}", "interaction_modal.title.reblog": "o wawa e toki {name}", "keyboard_shortcuts.blocked": "o lukin e lipu sina pi jan weka", + "keyboard_shortcuts.boost": "o pana sin e toki", "keyboard_shortcuts.down": "o tawa anpa lon lipu", "keyboard_shortcuts.enter": "o lukin e toki", "keyboard_shortcuts.favourite": "o suli e toki", @@ -204,6 +209,7 @@ "keyboard_shortcuts.open_media": "o lukin e sitelen", "keyboard_shortcuts.pinned": "o lukin pi lipu sina pi toki sewi", "keyboard_shortcuts.toggle_sensitivity": "o ante e ken lukin", + "keyboard_shortcuts.toot": "o toki", "keyboard_shortcuts.up": "o tawa sewi lon lipu", "lightbox.close": "o pini", "lightbox.compress": "o lili e sitelen", @@ -227,6 +233,7 @@ "media_gallery.toggle_visible": "{number, plural, other {o len e sitelen}}", "mute_modal.duration": "tenpo", "mute_modal.indefinite": "tenpo ale", + "navigation_bar.about": "sona", "navigation_bar.blocks": "jan weka", "navigation_bar.compose": "o pali e toki sin", "navigation_bar.favourites": "toki suli", @@ -261,12 +268,14 @@ "report.close": "o pini", "report.mute": "o kute ala e ona", "report.mute_explanation": "sina kama ala lukin e ijo pana ona. ona li awen ken kute e sina li awen ken lukin e sina li sona ala e weka kute sina e weka lukin sina.", + "report.next": "awen", "report.reasons.dislike": "ni li ike tawa mi", "report.reasons.legal": "ni li ike tawa lawa", "report.reasons.other": "ni li ike tan ante", "report.reasons.spam": "ni li ike tan toki mute", "report.thanks.title": "sina wile ala lukin e ni anu seme?", "report.unfollow": "o pini kute e {name}", + "report_notification.categories.legal": "ike tawa nasin lawa", "search.placeholder": "o alasa", "search.quick_action.go_to_account": "o tawa lipu jan {x}", "search_popout.language_code": "nimi toki kepeken nasin ISO", @@ -275,6 +284,7 @@ "search_results.statuses": "toki", "search_results.title": "o alasa e {q}", "status.block": "o weka e @{name}", + "status.cancel_reblog_private": "o pini e pana", "status.delete": "o weka", "status.edit": "o ante", "status.edited": "ni li ante lon {date}", @@ -305,7 +315,10 @@ "status.unpin": "o sewi ala lon lipu sina", "subscribed_languages.save": "o awen e ante", "tabs_bar.home": "lipu open", + "timeline_hint.resources.followers": "jan kute", + "timeline_hint.resources.follows": "jan lukin", "timeline_hint.resources.statuses": "ijo pi tenpo suli", + "trends.trending_now": "jan mute li toki", "units.short.million": "{count}AAA", "upload_button.label": "o pana e sitelen anu kalama", "upload_error.limit": "ilo li ken ala e suli pi ijo ni.", From 476a043fc5339526536cbb1ba64d0ba2230e870c Mon Sep 17 00:00:00 2001 From: Nicolas Hoffmann Date: Tue, 13 Feb 2024 13:58:21 +0100 Subject: [PATCH 09/37] Fix modal container bounds (#29185) --- app/javascript/styles/mastodon/components.scss | 2 ++ 1 file changed, 2 insertions(+) diff --git a/app/javascript/styles/mastodon/components.scss b/app/javascript/styles/mastodon/components.scss index 427144ed8..af9fc88e7 100644 --- a/app/javascript/styles/mastodon/components.scss +++ b/app/javascript/styles/mastodon/components.scss @@ -5343,6 +5343,8 @@ a.status-card { inset-inline-start: 0; width: 100%; height: 100%; + max-width: 100vw; + max-height: 100vh; box-sizing: border-box; display: flex; flex-direction: column; From e8b66a0525f0468fe6588803ec2a15ff186d08ab Mon Sep 17 00:00:00 2001 From: Emelia Smith Date: Tue, 13 Feb 2024 18:14:49 +0100 Subject: [PATCH 10/37] Ignore legacy moderator and admin columns on User model (#29188) --- app/models/concerns/user/ldap_authenticable.rb | 10 +++++++++- app/models/concerns/user/pam_authenticable.rb | 1 - app/models/user.rb | 2 ++ 3 files changed, 11 insertions(+), 2 deletions(-) diff --git a/app/models/concerns/user/ldap_authenticable.rb b/app/models/concerns/user/ldap_authenticable.rb index d84ff084b..180df9d31 100644 --- a/app/models/concerns/user/ldap_authenticable.rb +++ b/app/models/concerns/user/ldap_authenticable.rb @@ -25,7 +25,15 @@ module User::LdapAuthenticable resource = joins(:account).find_by(accounts: { username: safe_username }) if resource.blank? - resource = new(email: attributes[Devise.ldap_mail.to_sym].first, agreement: true, account_attributes: { username: safe_username }, admin: false, external: true, confirmed_at: Time.now.utc) + resource = new( + email: attributes[Devise.ldap_mail.to_sym].first, + agreement: true, + account_attributes: { + username: safe_username, + }, + external: true, + confirmed_at: Time.now.utc + ) resource.save! end diff --git a/app/models/concerns/user/pam_authenticable.rb b/app/models/concerns/user/pam_authenticable.rb index a682058cc..30dc7d8ae 100644 --- a/app/models/concerns/user/pam_authenticable.rb +++ b/app/models/concerns/user/pam_authenticable.rb @@ -32,7 +32,6 @@ module User::PamAuthenticable self.email = "#{account.username}@#{find_pam_suffix}" if email.nil? && find_pam_suffix self.confirmed_at = Time.now.utc - self.admin = false self.account = account self.external = true diff --git a/app/models/user.rb b/app/models/user.rb index 70c24336f..95fdc431a 100644 --- a/app/models/user.rb +++ b/app/models/user.rb @@ -51,6 +51,8 @@ class User < ApplicationRecord last_sign_in_ip skip_sign_in_token filtered_languages + admin + moderator ) include LanguagesHelper From 46142cdbddd6d3eb5e88386c74b5600abe520c38 Mon Sep 17 00:00:00 2001 From: Emelia Smith Date: Tue, 13 Feb 2024 19:11:47 +0100 Subject: [PATCH 11/37] Disable administrative doorkeeper routes (#29187) --- config/initializers/doorkeeper.rb | 9 +- .../requests/disabled_oauth_endpoints_spec.rb | 83 +++++++++++++++++++ 2 files changed, 90 insertions(+), 2 deletions(-) create mode 100644 spec/requests/disabled_oauth_endpoints_spec.rb diff --git a/config/initializers/doorkeeper.rb b/config/initializers/doorkeeper.rb index fe3871d2e..f9d47a205 100644 --- a/config/initializers/doorkeeper.rb +++ b/config/initializers/doorkeeper.rb @@ -21,9 +21,14 @@ Doorkeeper.configure do user unless user&.otp_required_for_login? end - # If you want to restrict access to the web interface for adding oauth authorized applications, you need to declare the block below. + # Doorkeeper provides some administrative interfaces for managing OAuth + # Applications, allowing creation, edit, and deletion of applications from the + # server. At present, these administrative routes are not integrated into + # Mastodon, and as such, we've disabled them by always return a 403 forbidden + # response for them. This does not affect the ability for users to manage + # their own OAuth Applications. admin_authenticator do - current_user&.admin? || redirect_to(new_user_session_url) + head 403 end # Authorization Code expiration time (default 10 minutes). diff --git a/spec/requests/disabled_oauth_endpoints_spec.rb b/spec/requests/disabled_oauth_endpoints_spec.rb new file mode 100644 index 000000000..7c2c09f38 --- /dev/null +++ b/spec/requests/disabled_oauth_endpoints_spec.rb @@ -0,0 +1,83 @@ +# frozen_string_literal: true + +require 'rails_helper' + +describe 'Disabled OAuth routes' do + # These routes are disabled via the doorkeeper configuration for + # `admin_authenticator`, as these routes should only be accessible by server + # administrators. For now, these routes are not properly designed and + # integrated into Mastodon, so we're disabling them completely + describe 'GET /oauth/applications' do + it 'returns 403 forbidden' do + get oauth_applications_path + + expect(response).to have_http_status(403) + end + end + + describe 'POST /oauth/applications' do + it 'returns 403 forbidden' do + post oauth_applications_path + + expect(response).to have_http_status(403) + end + end + + describe 'GET /oauth/applications/new' do + it 'returns 403 forbidden' do + get new_oauth_application_path + + expect(response).to have_http_status(403) + end + end + + describe 'GET /oauth/applications/:id' do + let(:application) { Fabricate(:application, scopes: 'read') } + + it 'returns 403 forbidden' do + get oauth_application_path(application) + + expect(response).to have_http_status(403) + end + end + + describe 'PATCH /oauth/applications/:id' do + let(:application) { Fabricate(:application, scopes: 'read') } + + it 'returns 403 forbidden' do + patch oauth_application_path(application) + + expect(response).to have_http_status(403) + end + end + + describe 'PUT /oauth/applications/:id' do + let(:application) { Fabricate(:application, scopes: 'read') } + + it 'returns 403 forbidden' do + put oauth_application_path(application) + + expect(response).to have_http_status(403) + end + end + + describe 'DELETE /oauth/applications/:id' do + let(:application) { Fabricate(:application, scopes: 'read') } + + it 'returns 403 forbidden' do + delete oauth_application_path(application) + + expect(response).to have_http_status(403) + end + end + + describe 'GET /oauth/applications/:id/edit' do + let(:application) { Fabricate(:application, scopes: 'read') } + + it 'returns 403 forbidden' do + get edit_oauth_application_path(application) + + expect(response).to have_http_status(403) + end + end +end From 554e2a019e40755fbe6ae02fbf5cfc1862550e20 Mon Sep 17 00:00:00 2001 From: Claire Date: Wed, 14 Feb 2024 13:12:13 +0100 Subject: [PATCH 12/37] Add `sidekiq_unique_jobs:delete_all_locks` task and disable `sidekiq-unique-jobs` UI by default (#29199) --- config/routes.rb | 2 +- lib/tasks/sidekiq_unique_jobs.rake | 11 +++++++++++ 2 files changed, 12 insertions(+), 1 deletion(-) create mode 100644 lib/tasks/sidekiq_unique_jobs.rake diff --git a/config/routes.rb b/config/routes.rb index bb088821f..51c10a14f 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -1,6 +1,6 @@ # frozen_string_literal: true -require 'sidekiq_unique_jobs/web' +require 'sidekiq_unique_jobs/web' if ENV['ENABLE_SIDEKIQ_UNIQUE_JOBS_UI'] == true require 'sidekiq-scheduler/web' class RedirectWithVary < ActionDispatch::Routing::PathRedirect diff --git a/lib/tasks/sidekiq_unique_jobs.rake b/lib/tasks/sidekiq_unique_jobs.rake new file mode 100644 index 000000000..bedc8fe4c --- /dev/null +++ b/lib/tasks/sidekiq_unique_jobs.rake @@ -0,0 +1,11 @@ +# frozen_string_literal: true + +namespace :sidekiq_unique_jobs do + task delete_all_locks: :environment do + digests = SidekiqUniqueJobs::Digests.new + digests.delete_by_pattern('*', count: digests.count) + + expiring_digests = SidekiqUniqueJobs::ExpiringDigests.new + expiring_digests.delete_by_pattern('*', count: expiring_digests.count) + end +end From 68eaa804c9bafdc5f798e114e9ba00161425dd71 Mon Sep 17 00:00:00 2001 From: Emelia Smith Date: Wed, 14 Feb 2024 15:15:34 +0100 Subject: [PATCH 13/37] Merge pull request from GHSA-7w3c-p9j8-mq3x * Ensure destruction of OAuth Applications notifies streaming Due to doorkeeper using a dependent: delete_all relationship, the destroy of an OAuth Application bypassed the existing AccessTokenExtension callbacks for announcing destructing of access tokens. * Ensure password resets revoke access to Streaming API * Improve performance of deleting OAuth tokens --------- Co-authored-by: Claire --- app/lib/application_extension.rb | 20 ++++++++++++++++++++ app/models/user.rb | 10 ++++++++++ spec/models/user_spec.rb | 7 +++++++ 3 files changed, 37 insertions(+) diff --git a/app/lib/application_extension.rb b/app/lib/application_extension.rb index fb442e2c2..400c51a02 100644 --- a/app/lib/application_extension.rb +++ b/app/lib/application_extension.rb @@ -4,14 +4,34 @@ module ApplicationExtension extend ActiveSupport::Concern included do + include Redisable + has_many :created_users, class_name: 'User', foreign_key: 'created_by_application_id', inverse_of: :created_by_application validates :name, length: { maximum: 60 } validates :website, url: true, length: { maximum: 2_000 }, if: :website? validates :redirect_uri, length: { maximum: 2_000 } + + # The relationship used between Applications and AccessTokens is using + # dependent: delete_all, which means the ActiveRecord callback in + # AccessTokenExtension is not run, so instead we manually announce to + # streaming that these tokens are being deleted. + before_destroy :push_to_streaming_api, prepend: true end def confirmation_redirect_uri redirect_uri.lines.first.strip end + + def push_to_streaming_api + # TODO: #28793 Combine into a single topic + payload = Oj.dump(event: :kill) + access_tokens.in_batches do |tokens| + redis.pipelined do |pipeline| + tokens.ids.each do |id| + pipeline.publish("timeline:access_token:#{id}", payload) + end + end + end + end end diff --git a/app/models/user.rb b/app/models/user.rb index 95fdc431a..f706c91ef 100644 --- a/app/models/user.rb +++ b/app/models/user.rb @@ -344,6 +344,16 @@ class User < ApplicationRecord Doorkeeper::AccessToken.by_resource_owner(self).in_batches do |batch| batch.update_all(revoked_at: Time.now.utc) Web::PushSubscription.where(access_token_id: batch).delete_all + + # Revoke each access token for the Streaming API, since `update_all`` + # doesn't trigger ActiveRecord Callbacks: + # TODO: #28793 Combine into a single topic + payload = Oj.dump(event: :kill) + redis.pipelined do |pipeline| + batch.ids.each do |id| + pipeline.publish("timeline:access_token:#{id}", payload) + end + end end end diff --git a/spec/models/user_spec.rb b/spec/models/user_spec.rb index 5ac41c0ff..845335e87 100644 --- a/spec/models/user_spec.rb +++ b/spec/models/user_spec.rb @@ -420,7 +420,10 @@ RSpec.describe User do let!(:access_token) { Fabricate(:access_token, resource_owner_id: user.id) } let!(:web_push_subscription) { Fabricate(:web_push_subscription, access_token: access_token) } + let(:redis_pipeline_stub) { instance_double(Redis::Namespace, publish: nil) } + before do + allow(redis).to receive(:pipelined).and_yield(redis_pipeline_stub) user.reset_password! end @@ -437,6 +440,10 @@ RSpec.describe User do expect(Doorkeeper::AccessToken.active_for(user).count).to eq 0 end + it 'revokes streaming access for all access tokens' do + expect(redis_pipeline_stub).to have_received(:publish).with("timeline:access_token:#{access_token.id}", Oj.dump(event: :kill)).once + 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) From b31af34c9716338e4a32a62cc812d1ca59e88d15 Mon Sep 17 00:00:00 2001 From: Claire Date: Wed, 14 Feb 2024 15:16:07 +0100 Subject: [PATCH 14/37] Merge pull request from GHSA-vm39-j3vx-pch3 * Prevent different identities from a same SSO provider from accessing a same account * Lock auth provider changes behind `ALLOW_UNSAFE_AUTH_PROVIDER_REATTACH=true` * Rename methods to avoid confusion between OAuth and OmniAuth --- .../auth/omniauth_callbacks_controller.rb | 2 +- app/models/concerns/user/omniauthable.rb | 52 ++++++++++++++----- app/models/identity.rb | 2 +- spec/models/identity_spec.rb | 6 +-- spec/requests/omniauth_callbacks_spec.rb | 2 +- 5 files changed, 44 insertions(+), 20 deletions(-) diff --git a/app/controllers/auth/omniauth_callbacks_controller.rb b/app/controllers/auth/omniauth_callbacks_controller.rb index 707b50ef9..9b83de945 100644 --- a/app/controllers/auth/omniauth_callbacks_controller.rb +++ b/app/controllers/auth/omniauth_callbacks_controller.rb @@ -7,7 +7,7 @@ class Auth::OmniauthCallbacksController < Devise::OmniauthCallbacksController def self.provides_callback_for(provider) define_method provider do @provider = provider - @user = User.find_for_oauth(request.env['omniauth.auth'], current_user) + @user = User.find_for_omniauth(request.env['omniauth.auth'], current_user) if @user.persisted? record_login_activity diff --git a/app/models/concerns/user/omniauthable.rb b/app/models/concerns/user/omniauthable.rb index 113bfda23..396a0598f 100644 --- a/app/models/concerns/user/omniauthable.rb +++ b/app/models/concerns/user/omniauthable.rb @@ -19,17 +19,18 @@ module User::Omniauthable end class_methods do - def find_for_oauth(auth, signed_in_resource = nil) + def find_for_omniauth(auth, signed_in_resource = nil) # EOLE-SSO Patch auth.uid = (auth.uid[0][:uid] || auth.uid[0][:user]) if auth.uid.is_a? Hashie::Array - identity = Identity.find_for_oauth(auth) + identity = Identity.find_for_omniauth(auth) # If a signed_in_resource is provided it always overrides the existing user # to prevent the identity being locked with accidentally created accounts. # Note that this may leave zombie accounts (with no associated identity) which # can be cleaned up at a later date. user = signed_in_resource || identity.user - user ||= create_for_oauth(auth) + user ||= reattach_for_auth(auth) + user ||= create_for_auth(auth) if identity.user.nil? identity.user = user @@ -39,19 +40,35 @@ module User::Omniauthable user end - def create_for_oauth(auth) - # Check if the user exists with provided email. If no email was provided, + private + + def reattach_for_auth(auth) + # If allowed, check if a user exists with the provided email address, + # and return it if they does not have an associated identity with the + # current authentication provider. + + # This can be used to provide a choice of alternative auth providers + # or provide smooth gradual transition between multiple auth providers, + # but this is discouraged because any insecure provider will put *all* + # local users at risk, regardless of which provider they registered with. + + return unless ENV['ALLOW_UNSAFE_AUTH_PROVIDER_REATTACH'] == 'true' + + email, email_is_verified = email_from_auth(auth) + return unless email_is_verified + + user = User.find_by(email: email) + return if user.nil? || Identity.exists?(provider: auth.provider, user_id: user.id) + + user + end + + def create_for_auth(auth) + # Create a user for the given auth params. If no email was provided, # we assign a temporary email and ask the user to verify it on # the next step via Auth::SetupController.show - strategy = Devise.omniauth_configs[auth.provider.to_sym].strategy - assume_verified = strategy&.security&.assume_email_is_verified - email_is_verified = auth.info.verified || auth.info.verified_email || auth.info.email_verified || assume_verified - email = auth.info.verified_email || auth.info.email - - user = User.find_by(email: email) if email_is_verified - - return user unless user.nil? + email, email_is_verified = email_from_auth(auth) user = User.new(user_params_from_auth(email, auth)) @@ -66,7 +83,14 @@ module User::Omniauthable user end - private + def email_from_auth(auth) + strategy = Devise.omniauth_configs[auth.provider.to_sym].strategy + assume_verified = strategy&.security&.assume_email_is_verified + email_is_verified = auth.info.verified || auth.info.verified_email || auth.info.email_verified || assume_verified + email = auth.info.verified_email || auth.info.email + + [email, email_is_verified] + end def user_params_from_auth(email, auth) { diff --git a/app/models/identity.rb b/app/models/identity.rb index c95a68a6f..77821b78f 100644 --- a/app/models/identity.rb +++ b/app/models/identity.rb @@ -17,7 +17,7 @@ class Identity < ApplicationRecord validates :uid, presence: true, uniqueness: { scope: :provider } validates :provider, presence: true - def self.find_for_oauth(auth) + def self.find_for_omniauth(auth) find_or_create_by(uid: auth.uid, provider: auth.provider) end end diff --git a/spec/models/identity_spec.rb b/spec/models/identity_spec.rb index 702245444..d5a2ffbc8 100644 --- a/spec/models/identity_spec.rb +++ b/spec/models/identity_spec.rb @@ -3,19 +3,19 @@ require 'rails_helper' RSpec.describe Identity do - describe '.find_for_oauth' do + describe '.find_for_omniauth' do let(:auth) { Fabricate(:identity, user: Fabricate(:user)) } it 'calls .find_or_create_by' do allow(described_class).to receive(:find_or_create_by) - described_class.find_for_oauth(auth) + described_class.find_for_omniauth(auth) expect(described_class).to have_received(:find_or_create_by).with(uid: auth.uid, provider: auth.provider) end it 'returns an instance of Identity' do - expect(described_class.find_for_oauth(auth)).to be_instance_of described_class + expect(described_class.find_for_omniauth(auth)).to be_instance_of described_class end end end diff --git a/spec/requests/omniauth_callbacks_spec.rb b/spec/requests/omniauth_callbacks_spec.rb index 0d37c4114..b478ca1ce 100644 --- a/spec/requests/omniauth_callbacks_spec.rb +++ b/spec/requests/omniauth_callbacks_spec.rb @@ -96,7 +96,7 @@ describe 'OmniAuth callbacks' do context 'when a user cannot be built' do before do - allow(User).to receive(:find_for_oauth).and_return(User.new) + allow(User).to receive(:find_for_omniauth).and_return(User.new) end it 'redirects to the new user signup page' do From 8e8e0f104fc3a64c9f862eca588a63ddbb8b6865 Mon Sep 17 00:00:00 2001 From: Claire Date: Wed, 14 Feb 2024 15:20:02 +0100 Subject: [PATCH 15/37] Bump version to v4.3.0-alpha.2 (#29200) --- lib/mastodon/version.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/mastodon/version.rb b/lib/mastodon/version.rb index dd7c84207..c2f26aee6 100644 --- a/lib/mastodon/version.rb +++ b/lib/mastodon/version.rb @@ -17,7 +17,7 @@ module Mastodon end def default_prerelease - 'alpha.1' + 'alpha.2' end def prerelease From bbbbf000849a3eb38f2a1fb58370f7e81ef71f11 Mon Sep 17 00:00:00 2001 From: Claire Date: Wed, 14 Feb 2024 15:57:49 +0100 Subject: [PATCH 16/37] Fix OmniAuth tests (#29201) --- spec/requests/omniauth_callbacks_spec.rb | 35 ++++++++++++++++++------ 1 file changed, 26 insertions(+), 9 deletions(-) diff --git a/spec/requests/omniauth_callbacks_spec.rb b/spec/requests/omniauth_callbacks_spec.rb index b478ca1ce..1e488b3f4 100644 --- a/spec/requests/omniauth_callbacks_spec.rb +++ b/spec/requests/omniauth_callbacks_spec.rb @@ -39,16 +39,33 @@ describe 'OmniAuth callbacks' do Fabricate(:user, email: 'user@host.example') end - it 'matches the existing user, creates an identity, and redirects to root path' do - expect { subject } - .to not_change(User, :count) - .and change(Identity, :count) - .by(1) - .and change(LoginActivity, :count) - .by(1) + context 'when ALLOW_UNSAFE_AUTH_PROVIDER_REATTACH is set to true' do + around do |example| + ClimateControl.modify ALLOW_UNSAFE_AUTH_PROVIDER_REATTACH: 'true' do + example.run + end + end - expect(Identity.find_by(user: User.last).uid).to eq('123') - expect(response).to redirect_to(root_path) + it 'matches the existing user, creates an identity, and redirects to root path' do + expect { subject } + .to not_change(User, :count) + .and change(Identity, :count) + .by(1) + .and change(LoginActivity, :count) + .by(1) + + expect(Identity.find_by(user: User.last).uid).to eq('123') + expect(response).to redirect_to(root_path) + end + end + + context 'when ALLOW_UNSAFE_AUTH_PROVIDER_REATTACH is not set to true' do + it 'does not match the existing user or create an identity' do + expect { subject } + .to not_change(User, :count) + .and not_change(Identity, :count) + .and not_change(LoginActivity, :count) + end end end From 844aa59bdfe76d8db2253c1a25d2f9b6caead690 Mon Sep 17 00:00:00 2001 From: Matt Jankowski Date: Wed, 14 Feb 2024 11:44:27 -0500 Subject: [PATCH 17/37] Doc update about ruby version 3.0+ (#29202) --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 267f0ed29..6cf722b35 100644 --- a/README.md +++ b/README.md @@ -69,7 +69,7 @@ Mastodon acts as an OAuth2 provider, so 3rd party apps can use the REST and Stre - **PostgreSQL** 12+ - **Redis** 4+ -- **Ruby** 2.7+ +- **Ruby** 3.0+ - **Node.js** 16+ The repository includes deployment configurations for **Docker and docker-compose** as well as specific platforms like **Heroku**, **Scalingo**, and **Nanobox**. For Helm charts, reference the [mastodon/chart repository](https://github.com/mastodon/chart). The [**standalone** installation guide](https://docs.joinmastodon.org/admin/install/) is available in the documentation. From d4d0565b0fd86ca80d2dbf0c7d09a9af5ea4a293 Mon Sep 17 00:00:00 2001 From: Claire Date: Wed, 14 Feb 2024 22:49:45 +0100 Subject: [PATCH 18/37] Fix user creation failure handling in OAuth paths (#29207) --- app/controllers/auth/omniauth_callbacks_controller.rb | 3 +++ config/locales/devise.en.yml | 1 + spec/requests/omniauth_callbacks_spec.rb | 4 +++- 3 files changed, 7 insertions(+), 1 deletion(-) diff --git a/app/controllers/auth/omniauth_callbacks_controller.rb b/app/controllers/auth/omniauth_callbacks_controller.rb index 9b83de945..9d496220a 100644 --- a/app/controllers/auth/omniauth_callbacks_controller.rb +++ b/app/controllers/auth/omniauth_callbacks_controller.rb @@ -17,6 +17,9 @@ class Auth::OmniauthCallbacksController < Devise::OmniauthCallbacksController session["devise.#{provider}_data"] = request.env['omniauth.auth'] redirect_to new_user_registration_url end + rescue ActiveRecord::RecordInvalid + flash[:alert] = I18n.t('devise.failure.omniauth_user_creation_failure') if is_navigational_format? + redirect_to new_user_session_url end end diff --git a/config/locales/devise.en.yml b/config/locales/devise.en.yml index 4439397c8..61bd33851 100644 --- a/config/locales/devise.en.yml +++ b/config/locales/devise.en.yml @@ -12,6 +12,7 @@ en: last_attempt: You have one more attempt before your account is locked. locked: Your account is locked. not_found_in_database: Invalid %{authentication_keys} or password. + omniauth_user_creation_failure: Error creating an account for this identity. pending: Your account is still under review. timeout: Your session expired. Please login again to continue. unauthenticated: You need to login or sign up before continuing. diff --git a/spec/requests/omniauth_callbacks_spec.rb b/spec/requests/omniauth_callbacks_spec.rb index 1e488b3f4..095535e48 100644 --- a/spec/requests/omniauth_callbacks_spec.rb +++ b/spec/requests/omniauth_callbacks_spec.rb @@ -60,11 +60,13 @@ describe 'OmniAuth callbacks' do end context 'when ALLOW_UNSAFE_AUTH_PROVIDER_REATTACH is not set to true' do - it 'does not match the existing user or create an identity' do + it 'does not match the existing user or create an identity, and redirects to login page' do expect { subject } .to not_change(User, :count) .and not_change(Identity, :count) .and not_change(LoginActivity, :count) + + expect(response).to redirect_to(new_user_session_url) end end end From fc4f82346440573898c60fcd4af1f033ec724aae Mon Sep 17 00:00:00 2001 From: Matt Jankowski Date: Fri, 16 Feb 2024 02:41:25 -0500 Subject: [PATCH 19/37] Avoid local block var assignment in ap/process_status_update_service spec (#29210) --- .../services/activitypub/process_status_update_service_spec.rb | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/spec/services/activitypub/process_status_update_service_spec.rb b/spec/services/activitypub/process_status_update_service_spec.rb index 53cbaf4cc..67f2f2727 100644 --- a/spec/services/activitypub/process_status_update_service_spec.rb +++ b/spec/services/activitypub/process_status_update_service_spec.rb @@ -218,7 +218,8 @@ RSpec.describe ActivityPub::ProcessStatusUpdateService, type: :service do end it 'does not update the text, spoiler_text or edited_at' do - expect { subject.call(status, json, json) }.to_not(change { s = status.reload; [s.text, s.spoiler_text, s.edited_at] }) + expect { subject.call(status, json, json) } + .to_not(change { status.reload.attributes.slice('text', 'spoiler_text', 'edited_at').values }) end end From 1df2ffc3eee80ab53de00d076658dd546515a9bd Mon Sep 17 00:00:00 2001 From: Matt Jankowski Date: Fri, 16 Feb 2024 02:42:03 -0500 Subject: [PATCH 20/37] Use `subject` in blacklist email validator spec (#29211) --- spec/validators/blacklisted_email_validator_spec.rb | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/spec/validators/blacklisted_email_validator_spec.rb b/spec/validators/blacklisted_email_validator_spec.rb index 6292f0737..86760df2e 100644 --- a/spec/validators/blacklisted_email_validator_spec.rb +++ b/spec/validators/blacklisted_email_validator_spec.rb @@ -4,7 +4,7 @@ require 'rails_helper' RSpec.describe BlacklistedEmailValidator do describe '#validate' do - subject { described_class.new.validate(user); errors } + subject { described_class.new.validate(user) } let(:user) { instance_double(User, email: 'info@mail.com', sign_up_ip: '1.2.3.4', errors: errors) } let(:errors) { instance_double(ActiveModel::Errors, add: nil) } @@ -18,7 +18,8 @@ RSpec.describe BlacklistedEmailValidator do let(:blocked_email) { true } it 'adds error' do - described_class.new.validate(user) + subject + expect(errors).to have_received(:add).with(:email, :blocked).once end end @@ -27,7 +28,8 @@ RSpec.describe BlacklistedEmailValidator do let(:blocked_email) { false } it 'does not add errors' do - described_class.new.validate(user) + subject + expect(errors).to_not have_received(:add) end @@ -39,7 +41,8 @@ RSpec.describe BlacklistedEmailValidator do end it 'adds error' do - described_class.new.validate(user) + subject + expect(errors).to have_received(:add).with(:email, :taken).once end end From ed4939296a2f0ecf5d072c4f04c2733170038fa4 Mon Sep 17 00:00:00 2001 From: Matt Jankowski Date: Fri, 16 Feb 2024 02:43:00 -0500 Subject: [PATCH 21/37] Reduce `RSpec/MultipleExpectations` in ap/activity/create spec (#29224) --- spec/lib/activitypub/activity/create_spec.rb | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/spec/lib/activitypub/activity/create_spec.rb b/spec/lib/activitypub/activity/create_spec.rb index e4966cffa..dec17b916 100644 --- a/spec/lib/activitypub/activity/create_spec.rb +++ b/spec/lib/activitypub/activity/create_spec.rb @@ -970,12 +970,15 @@ RSpec.describe ActivityPub::Activity::Create do it 'creates an encrypted message' do encrypted_message = target_device.encrypted_messages.reload.first - expect(encrypted_message).to_not be_nil - expect(encrypted_message.from_device_id).to eq '1234' - expect(encrypted_message.from_account).to eq sender - expect(encrypted_message.type).to eq 1 - expect(encrypted_message.body).to eq 'Foo' - expect(encrypted_message.digest).to eq 'Foo123' + expect(encrypted_message) + .to be_present + .and have_attributes( + from_device_id: eq('1234'), + from_account: eq(sender), + type: eq(1), + body: eq('Foo'), + digest: eq('Foo123') + ) end it 'creates a message franking' do From 1c93d625c6392374ebf014c190166ce98652f539 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Fri, 16 Feb 2024 08:51:13 +0100 Subject: [PATCH 22/37] New Crowdin Translations (automated) (#29195) Co-authored-by: GitHub Actions --- app/javascript/mastodon/locales/bg.json | 12 +- app/javascript/mastodon/locales/ie.json | 13 +++ app/javascript/mastodon/locales/kab.json | 61 ++++++---- app/javascript/mastodon/locales/sk.json | 1 + app/javascript/mastodon/locales/th.json | 4 +- app/javascript/mastodon/locales/tok.json | 10 ++ config/locales/de.yml | 4 +- config/locales/devise.be.yml | 1 + config/locales/devise.ca.yml | 1 + config/locales/devise.da.yml | 1 + config/locales/devise.de.yml | 1 + config/locales/devise.es-AR.yml | 1 + config/locales/devise.eu.yml | 1 + config/locales/devise.fi.yml | 1 + config/locales/devise.fo.yml | 1 + config/locales/devise.fy.yml | 1 + config/locales/devise.gl.yml | 1 + config/locales/devise.he.yml | 1 + config/locales/devise.hu.yml | 1 + config/locales/devise.ie.yml | 1 + config/locales/devise.is.yml | 1 + config/locales/devise.it.yml | 1 + config/locales/devise.kab.yml | 8 +- config/locales/devise.ko.yml | 1 + config/locales/devise.lad.yml | 1 + config/locales/devise.nl.yml | 1 + config/locales/devise.pl.yml | 1 + config/locales/devise.pt-PT.yml | 1 + config/locales/devise.sk.yml | 1 + config/locales/devise.sl.yml | 1 + config/locales/devise.sq.yml | 1 + config/locales/devise.sr-Latn.yml | 1 + config/locales/devise.sr.yml | 1 + config/locales/devise.tr.yml | 1 + config/locales/devise.uk.yml | 1 + config/locales/devise.zh-CN.yml | 1 + config/locales/devise.zh-HK.yml | 1 + config/locales/devise.zh-TW.yml | 1 + config/locales/doorkeeper.kab.yml | 10 +- config/locales/ie.yml | 6 + config/locales/kab.yml | 136 +++++++++++++++-------- config/locales/simple_form.kab.yml | 8 +- config/locales/sq.yml | 4 +- config/locales/th.yml | 2 +- 44 files changed, 211 insertions(+), 98 deletions(-) diff --git a/app/javascript/mastodon/locales/bg.json b/app/javascript/mastodon/locales/bg.json index 5a6fa175e..3e7f6e51b 100644 --- a/app/javascript/mastodon/locales/bg.json +++ b/app/javascript/mastodon/locales/bg.json @@ -201,7 +201,7 @@ "disabled_account_banner.text": "Вашият акаунт {disabledAccount} сега е изключен.", "dismissable_banner.community_timeline": "Ето най-скорошните публични публикации от хора, чиито акаунти са разположени в {domain}.", "dismissable_banner.dismiss": "Отхвърляне", - "dismissable_banner.explore_links": "Тези новини се разказват от хората в този и други сървъри на децентрализираната мрежа точно сега.", + "dismissable_banner.explore_links": "Това са най-споделяните новини в социалната мрежа днес. По-нови истории, споделени от повече хора се показват по-напред.", "dismissable_banner.explore_statuses": "Има публикации през социалната мрежа, които днес набират популярност. По-новите публикации с повече подсилвания и любими са класирани по-високо.", "dismissable_banner.explore_tags": "Тези хаштагове сега набират популярност сред хората в този и други сървъри на децентрализирата мрежа.", "dismissable_banner.public_timeline": "Ето най-новите обществени публикации от хора в социална мрежа, която хората в {domain} следват.", @@ -231,7 +231,7 @@ "empty_column.community": "Локалният инфопоток е празен. Публикувайте нещо, за да започнете!", "empty_column.direct": "Още нямате никакви частни споменавания. Тук ще се показват, изпращайки или получавайки едно.", "empty_column.domain_blocks": "Още няма блокирани домейни.", - "empty_column.explore_statuses": "Няма нищо налагащо се в момента. Проверете пак по-късно!", + "empty_column.explore_statuses": "Няма тенденции в момента. Проверете пак по-късно!", "empty_column.favourited_statuses": "Още нямате никакви любими публикации. Правейки любима, то тя ще се покаже тук.", "empty_column.favourites": "Още никого не е слагал публикацията в любими. Когато някой го направи, този човек ще се покаже тук.", "empty_column.follow_requests": "Още нямате заявки за последване. Получавайки такава, то тя ще се покаже тук.", @@ -407,7 +407,7 @@ "navigation_bar.direct": "Частни споменавания", "navigation_bar.discover": "Откриване", "navigation_bar.domain_blocks": "Блокирани домейни", - "navigation_bar.explore": "Изследване", + "navigation_bar.explore": "Разглеждане", "navigation_bar.favourites": "Любими", "navigation_bar.filters": "Заглушени думи", "navigation_bar.follow_requests": "Заявки за последване", @@ -474,10 +474,10 @@ "notifications_permission_banner.title": "Никога не пропускате нещо", "onboarding.action.back": "Върнете ме обратно", "onboarding.actions.back": "Върнете ме обратно", - "onboarding.actions.go_to_explore": "Вижте какво изгрява", + "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": "Популярно в Mastodon", "onboarding.profile.discoverable": "Правене на моя профил откриваем", @@ -530,7 +530,7 @@ "privacy.private.short": "Последователи", "privacy.public.long": "Всеки във и извън Mastodon", "privacy.public.short": "Публично", - "privacy.unlisted.additional": "Това поведение е точно като публичното, с изключение на това, че публикацията няма да се появява в каналите на живо, хаштаговете, проучването или търсенето в Mastodon, дори ако сте се включили в целия акаунт.", + "privacy.unlisted.additional": "Това действие е точно като публичното, с изключение на това, че публикацията няма да се появява в каналите на живо, хаштаговете, разглеждането или търсенето в Mastodon, дори ако сте избрали да се публично видими на ниво акаунт.", "privacy.unlisted.long": "По-малко алгоритмични фанфари", "privacy.unlisted.short": "Тиха публика", "privacy_policy.last_updated": "Последно осъвременяване на {date}", diff --git a/app/javascript/mastodon/locales/ie.json b/app/javascript/mastodon/locales/ie.json index d39aa6cf6..0c21832ed 100644 --- a/app/javascript/mastodon/locales/ie.json +++ b/app/javascript/mastodon/locales/ie.json @@ -158,6 +158,7 @@ "compose_form.save_changes": "Actualisar", "compose_form.spoiler.marked": "Remover avise pri li contenete", "compose_form.spoiler.unmarked": "Adjunter avise pri li contenete", + "compose_form.spoiler_placeholder": "Advertiment de contenete (optional)", "confirmation_modal.cancel": "Anullar", "confirmations.block.block_and_report": "Bloccar & Raportar", "confirmations.block.confirm": "Bloccar", @@ -276,6 +277,12 @@ "follow_request.authorize": "Autorisar", "follow_request.reject": "Rejecter", "follow_requests.unlocked_explanation": "Benque tu conto ne es cludet, li administratores de {domain} pensat que tu fórsan vell voler tractar seque-petitiones de tis-ci contos manualmen.", + "follow_suggestions.curated_suggestion": "Selection del Servitor", + "follow_suggestions.dismiss": "Ne monstrar plu", + "follow_suggestions.personalized_suggestion": "Personalisat suggestion", + "follow_suggestions.popular_suggestion": "Populari suggestion", + "follow_suggestions.view_all": "Vider omnicos", + "follow_suggestions.who_to_follow": "Persones a sequer", "followed_tags": "Sequet hashtags", "footer.about": "Information", "footer.directory": "Profilarium", @@ -517,11 +524,15 @@ "poll_button.add_poll": "Adjunter un balotation", "poll_button.remove_poll": "Remover balotation", "privacy.change": "Changear li privatie del posta", + "privacy.direct.long": "Omnes mentionat in li posta", "privacy.direct.short": "Specific persones", "privacy.private.long": "Solmen tui sequitores", "privacy.private.short": "Sequitores", "privacy.public.long": "Quicunc in e ex Mastodon", "privacy.public.short": "Public", + "privacy.unlisted.additional": "It acte just quam public, except que li posta ne va aparir in tendentie o hashtags, explorar, o sercha de Mastodon, mem si tu ha optet por les sur tui tot conto.", + "privacy.unlisted.long": "Minu fanfare algoritmic", + "privacy.unlisted.short": "Quiet public", "privacy_policy.last_updated": "Ultimmen actualisat ye {date}", "privacy_policy.title": "Politica pri Privatie", "recommended": "Recomandat", @@ -539,7 +550,9 @@ "relative_time.minutes": "{number}m", "relative_time.seconds": "{number}s", "relative_time.today": "hodie", + "reply_indicator.attachments": "{count, plural, one {# atachament} other {# atachamentes}}", "reply_indicator.cancel": "Anullar", + "reply_indicator.poll": "Balotar", "report.block": "Bloccar", "report.block_explanation": "Tu ne va vider su postas. Li usator ni va posser vider tui postas, ni sequer te, ni va posser saver pri li statu de esser bloccat.", "report.categories.legal": "Legal", diff --git a/app/javascript/mastodon/locales/kab.json b/app/javascript/mastodon/locales/kab.json index 7fb617518..b69e93952 100644 --- a/app/javascript/mastodon/locales/kab.json +++ b/app/javascript/mastodon/locales/kab.json @@ -11,11 +11,13 @@ "account.blocked": "Yettusewḥel", "account.browse_more_on_origin_server": "Snirem ugar deg umeɣnu aneẓli", "account.cancel_follow_request": "Withdraw follow request", + "account.copy": "Nɣel assaɣ ɣer umaɣnu", "account.disable_notifications": "Ḥbes ur iyi-d-ttazen ara ilɣa mi ara d-isuffeɣ @{name}", "account.domain_blocked": "Taɣult yeffren", "account.edit_profile": "Ẓreg amaɣnu", "account.enable_notifications": "Azen-iyi-d ilɣa mi ara d-isuffeɣ @{name}", "account.endorse": "Welleh fell-as deg umaɣnu-inek", + "account.featured_tags.last_status_never": "Ulac tisuffaɣ", "account.follow": "Ḍfer", "account.followers": "Imeḍfaren", "account.followers.empty": "Ar tura, ulac yiwen i yeṭṭafaṛen amseqdac-agi.", @@ -65,7 +67,7 @@ "bundle_modal_error.message": "Tella-d kra n tuccḍa mi d-yettali ugbur-agi.", "bundle_modal_error.retry": "Ɛreḍ tikelt-nniḍen", "closed_registrations_modal.find_another_server": "Aff-d aqeddac nniḍen", - "column.about": "Γef", + "column.about": "Ɣef", "column.blocks": "Imiḍanen yettusḥebsen", "column.bookmarks": "Ticraḍ", "column.community": "Tasuddemt tadigant", @@ -77,7 +79,7 @@ "column.lists": "Tibdarin", "column.mutes": "Imiḍanen yettwasgugmen", "column.notifications": "Tilɣa", - "column.pins": "Tijewwaqin yettwasenṭḍen", + "column.pins": "Tisuffaɣ yettwasenṭḍen", "column.public": "Tasuddemt tamatut", "column_back_button.label": "Tuɣalin", "column_header.hide_settings": "Ffer iɣewwaṛen", @@ -88,32 +90,36 @@ "column_header.unpin": "Kkes asenteḍ", "column_subheading.settings": "Iɣewwaṛen", "community.column_settings.local_only": "Adigan kan", - "community.column_settings.media_only": "Allal n teywalt kan", + "community.column_settings.media_only": "Imidyaten kan", "community.column_settings.remote_only": "Anmeggag kan", "compose.language.change": "Beddel tutlayt", "compose.language.search": "Nadi tutlayin …", "compose.published.open": "Ldi", "compose_form.direct_message_warning_learn_more": "Issin ugar", - "compose_form.encryption_warning": "Posts on Mastodon are not end-to-end encrypted. Do not share any dangerous information over Mastodon.", - "compose_form.hashtag_warning": "This post won't be listed under any hashtag as it is unlisted. Only public posts can be searched by hashtag.", + "compose_form.encryption_warning": "", + "compose_form.hashtag_warning": "", "compose_form.lock_disclaimer": "Amiḍan-ik·im ur yelli ara {locked}. Menwala yezmer ad k·kem-yeḍfeṛ akken ad iẓer acu tbeṭṭuḍ akked yimeḍfaṛen-ik·im.", "compose_form.lock_disclaimer.lock": "yettwacekkel", "compose_form.placeholder": "D acu i itezzin deg wallaɣ?", "compose_form.poll.duration": "Tanzagt n tefrant", + "compose_form.poll.option_placeholder": "Taxtiṛt {number}", "compose_form.poll.single": "Fren yiwen", - "compose_form.publish_form": "Suffeɣ", + "compose_form.publish_form": "Tasuffeɣt tamaynut", + "compose_form.reply": "Err", + "compose_form.save_changes": "Leqqem", "compose_form.spoiler.marked": "Kkes aḍris yettwaffren deffir n walɣu", "compose_form.spoiler.unmarked": "Rnu aḍris yettwaffren deffir n walɣu", "confirmation_modal.cancel": "Sefsex", "confirmations.block.block_and_report": "Sewḥel & sewɛed", "confirmations.block.confirm": "Sewḥel", - "confirmations.block.message": "Tebγiḍ s tidet ad tesḥebseḍ {name}?", + "confirmations.block.message": "Tebɣiḍ s tidet ad tesḥebseḍ {name}?", "confirmations.delete.confirm": "Kkes", "confirmations.delete.message": "Tebɣiḍ s tidet ad tekkseḍ tasuffeɣt-agi?", "confirmations.delete_list.confirm": "Kkes", "confirmations.delete_list.message": "Tebɣiḍ s tidet ad tekkseḍ umuɣ-agi i lebda?", "confirmations.discard_edit_media.confirm": "Sefsex", "confirmations.domain_block.confirm": "Ffer taɣult meṛṛa", + "confirmations.edit.confirm": "Ẓreg", "confirmations.logout.confirm": "Ffeɣ", "confirmations.logout.message": "D tidet tebɣiḍ ad teffɣeḍ?", "confirmations.mute.confirm": "Sgugem", @@ -133,12 +139,13 @@ "directory.local": "Seg {domain} kan", "directory.new_arrivals": "Imaynuten id yewḍen", "directory.recently_active": "Yermed xas melmi kan", - "disabled_account_banner.account_settings": "Iγewwaṛen n umiḍan", + "disabled_account_banner.account_settings": "Iɣewwaṛen n umiḍan", "dismissable_banner.explore_links": "These news stories are being talked about by people on this and other servers of the decentralized network right now.", "dismissable_banner.explore_tags": "These hashtags are gaining traction among people on this and other servers of the decentralized network right now.", "embed.instructions": "Ẓẓu addad-agi deg usmel-inek s wenγal n tangalt yellan sdaw-agi.", "embed.preview": "Akka ara d-iban:", "emoji_button.activity": "Aqeddic", + "emoji_button.clear": "Sfeḍ", "emoji_button.custom": "Udmawan", "emoji_button.flags": "Innayen", "emoji_button.food": "Tegwella & Tissit", @@ -153,7 +160,7 @@ "emoji_button.symbols": "Izamulen", "emoji_button.travel": "Imeḍqan d Yinigen", "empty_column.account_suspended": "Amiḍan yettwaḥbas", - "empty_column.account_timeline": "Ulac tijewwaqin dagi!", + "empty_column.account_timeline": "Ulac tisuffaɣ da !", "empty_column.account_unavailable": "Ur nufi ara amaɣnu-ayi", "empty_column.blocks": "Ur tesḥebseḍ ula yiwen n umseqdac ar tura.", "empty_column.bookmarked_statuses": "Ulac tijewwaqin i terniḍ ɣer yismenyifen-ik ar tura. Ticki terniḍ yiwet, ad d-tettwasken da.", @@ -174,7 +181,7 @@ "explore.suggested_follows": "Imdanen", "explore.title": "Snirem", "explore.trending_links": "Isallen", - "explore.trending_statuses": "Tisuffiɣin", + "explore.trending_statuses": "Tisuffaɣ", "explore.trending_tags": "Ihacṭagen", "filter_modal.added.settings_link": "asebter n yiɣewwaṛen", "filter_modal.select_filter.prompt_new": "Taggayt tamaynutt : {name}", @@ -183,8 +190,9 @@ "firehose.local": "Deg uqeddac-ayi", "follow_request.authorize": "Ssireg", "follow_request.reject": "Agi", - "footer.about": "Γef", - "footer.directory": "Akaram n imaγnuten", + "followed_tags": "Ihacṭagen yettwaḍfaren", + "footer.about": "Ɣef", + "footer.directory": "Akaram n imaɣnuten", "footer.get_app": "Awi-d asnas", "footer.invite": "Ɛreḍ-d kra n yimdanen", "footer.keyboard_shortcuts": "Inegzumen n unasiw", @@ -207,6 +215,7 @@ "home.column_settings.show_replies": "Ssken-d tiririyin", "home.hide_announcements": "Ffer ulɣuyen", "home.show_announcements": "Ssken-d ulɣuyen", + "interaction_modal.no_account_yet": "Ulac-ik·ikem deg Maṣṭudun?", "interaction_modal.on_this_server": "Deg uqeddac-ayi", "interaction_modal.title.follow": "Ḍfer {name}", "intervals.full.days": "{number, plural, one {# n wass} other {# n wussan}}", @@ -247,8 +256,8 @@ "lightbox.close": "Mdel", "lightbox.compress": "Ḥemmeẓ tamnaḍt n uskan n tugna", "lightbox.expand": "Simeɣer tamnaḍt n uskan n tugna", - "lightbox.next": "Γer zdat", - "lightbox.previous": "Γer deffir", + "lightbox.next": "Ɣer zdat", + "lightbox.previous": "Ɣer deffir", "link_preview.author": "S-ɣur {name}", "lists.account.add": "Rnu ɣer tebdart", "lists.account.remove": "Kkes seg tebdart", @@ -264,11 +273,12 @@ "lists.search": "Nadi gar yemdanen i teṭṭafaṛeḍ", "lists.subheading": "Tibdarin-ik·im", "load_pending": "{count, plural, one {# n uferdis amaynut} other {# n yiferdisen imaynuten}}", - "media_gallery.toggle_visible": "Ffer {number, plural, one {tugna} other {tugniwin}}", + "loading_indicator.label": "Yessalay-d …", + "media_gallery.toggle_visible": "{number, plural, one {Ffer tugna} other {Ffer tugniwin}}", "mute_modal.duration": "Tanzagt", "mute_modal.hide_notifications": "Tebɣiḍ ad teffreḍ talɣutin n umseqdac-a?", "mute_modal.indefinite": "Ur yettwasbadu ara", - "navigation_bar.about": "Γef", + "navigation_bar.about": "Ɣef", "navigation_bar.blocks": "Imseqdacen yettusḥebsen", "navigation_bar.bookmarks": "Ticraḍ", "navigation_bar.community_timeline": "Tasuddemt tadigant", @@ -284,7 +294,7 @@ "navigation_bar.logout": "Ffeɣ", "navigation_bar.mutes": "Iseqdacen yettwasusmen", "navigation_bar.personal": "Udmawan", - "navigation_bar.pins": "Tijewwiqin yettwasentḍen", + "navigation_bar.pins": "Tisuffaɣ yettwasenṭḍen", "navigation_bar.preferences": "Imenyafen", "navigation_bar.public_timeline": "Tasuddemt tazayezt tamatut", "navigation_bar.search": "Nadi", @@ -311,7 +321,7 @@ "notifications.column_settings.reblog": "Seǧhed:", "notifications.column_settings.show": "Ssken-d tilɣa deg ujgu", "notifications.column_settings.sound": "Rmed imesli", - "notifications.column_settings.status": "Tiẓenẓunin timaynutin:", + "notifications.column_settings.status": "Tisuffaɣ timaynutin :", "notifications.filter.all": "Akk", "notifications.filter.boosts": "Seǧhed", "notifications.filter.favourites": "Imenyafen", @@ -325,11 +335,15 @@ "notifications.permission_denied": "D awezɣi ad yili wermad n yilɣa n tnarit axateṛ turagt tettwagdel.", "notifications_permission_banner.enable": "Rmed talɣutin n tnarit", "notifications_permission_banner.title": "Ur zeggel acemma", + "onboarding.action.back": "Tuɣalin ɣer deffir", + "onboarding.actions.back": "Tuɣalin ɣer deffir", "onboarding.actions.go_to_explore": "See what's trending", "onboarding.actions.go_to_home": "Go to your home feed", "onboarding.compose.template": "Azul a #Mastodon!", "onboarding.follows.lead": "You curate your own home feed. The more people you follow, the more active and interesting it will be. These profiles may be a good starting point—you can always unfollow them later!", "onboarding.follows.title": "Popular on Mastodon", + "onboarding.profile.display_name": "Isem ara d-yettwaskanen", + "onboarding.share.title": "Bḍu amaɣnu-inek·inem", "onboarding.start.lead": "Your new Mastodon account is ready to go. Here's how you can make the most of it:", "onboarding.start.skip": "Want to skip right ahead?", "onboarding.steps.follow_people.body": "You curate your own feed. Lets fill it with interesting people.", @@ -365,7 +379,7 @@ "report.block": "Sewḥel", "report.categories.other": "Tiyyaḍ", "report.categories.spam": "Aspam", - "report.category.title_account": "ameγnu", + "report.category.title_account": "ameɣnu", "report.category.title_status": "tasuffeɣt", "report.close": "Immed", "report.forward": "Bren-it ɣeṛ {target}", @@ -383,6 +397,7 @@ "report_notification.open": "Ldi aneqqis", "search.placeholder": "Nadi", "search.search_or_paste": "Nadi neɣ senṭeḍ URL", + "search_popout.user": "amseqdac", "search_results.all": "Akk", "search_results.hashtags": "Ihacṭagen", "search_results.statuses": "Tisuffaɣ", @@ -405,7 +420,7 @@ "status.embed": "Seddu", "status.filtered": "Yettwasizdeg", "status.load_more": "Sali ugar", - "status.media_hidden": "Taɣwalt tettwaffer", + "status.media_hidden": "Amidya yettwaffer", "status.mention": "Bder-d @{name}", "status.more": "Ugar", "status.mute": "Sussem @{name}", @@ -425,7 +440,7 @@ "status.sensitive_warning": "Agbur amḥulfu", "status.share": "Bḍu", "status.show_less": "Ssken-d drus", - "status.show_less_all": "Semẓi akk tisuffγin", + "status.show_less_all": "Semẓi akk tisuffɣin", "status.show_more": "Ssken-d ugar", "status.show_more_all": "Ẓerr ugar lebda", "status.title.with_attachments": "{user} posted {attachmentCount, plural, one {an attachment} other {# attachments}}", @@ -444,7 +459,7 @@ "timeline_hint.remote_resource_not_displayed": "{resource} seg yiqeddacen-nniḍen ur d-ttwaskanent ara.", "timeline_hint.resources.followers": "Imeḍfaṛen", "timeline_hint.resources.follows": "T·Yeṭafaṛ", - "timeline_hint.resources.statuses": "Tijewwaqin tiqdimin", + "timeline_hint.resources.statuses": "Tisuffaɣ tiqdimin", "trends.counter_by_accounts": "{count, plural, one {{counter} person} other {{counter} people}} in the past {days, plural, one {day} other {# days}}", "trends.trending_now": "Ayen mucaɛen tura", "ui.beforeunload": "Arewway-ik·im ad iruḥ ma yella tefeɣ-d deg Maṣṭudun.", @@ -465,7 +480,7 @@ "upload_modal.choose_image": "Fren tugna", "upload_modal.description_placeholder": "Aberraɣ arurad ineggez nnig n uqjun amuṭṭis", "upload_modal.detect_text": "Sefru-d aḍris seg tugna", - "upload_modal.edit_media": "Ẓreg taɣwalt", + "upload_modal.edit_media": "Ẓreg amidya", "upload_modal.preparing_ocr": "Aheyyi n OCR…", "upload_modal.preview_label": "Taskant ({ratio})", "upload_progress.label": "Asali iteddu...", diff --git a/app/javascript/mastodon/locales/sk.json b/app/javascript/mastodon/locales/sk.json index ad7837cab..da76e9868 100644 --- a/app/javascript/mastodon/locales/sk.json +++ b/app/javascript/mastodon/locales/sk.json @@ -523,6 +523,7 @@ "poll_button.add_poll": "Pridaj anketu", "poll_button.remove_poll": "Odstráň anketu", "privacy.change": "Uprav súkromie príspevku", + "privacy.direct.long": "Všetci spomenutí v príspevku", "privacy.direct.short": "Konkrétni ľudia", "privacy.private.long": "Iba tvoji nasledovatelia", "privacy.private.short": "Sledovatelia", diff --git a/app/javascript/mastodon/locales/th.json b/app/javascript/mastodon/locales/th.json index 72ecb11ed..e0aa072a7 100644 --- a/app/javascript/mastodon/locales/th.json +++ b/app/javascript/mastodon/locales/th.json @@ -279,8 +279,8 @@ "follow_requests.unlocked_explanation": "แม้ว่าไม่มีการล็อคบัญชีของคุณ พนักงานของ {domain} คิดว่าคุณอาจต้องการตรวจทานคำขอติดตามจากบัญชีเหล่านี้ด้วยตนเอง", "follow_suggestions.curated_suggestion": "คัดสรรโดยบรรณาธิการ", "follow_suggestions.dismiss": "ไม่ต้องแสดงอีก", - "follow_suggestions.personalized_suggestion": "คำแนะนำเฉพาะบุคคล", - "follow_suggestions.popular_suggestion": "คำแนะนำยอดนิยม", + "follow_suggestions.personalized_suggestion": "ข้อเสนอแนะเฉพาะบุคคล", + "follow_suggestions.popular_suggestion": "ข้อเสนอแนะยอดนิยม", "follow_suggestions.view_all": "ดูทั้งหมด", "follow_suggestions.who_to_follow": "ติดตามใครดี", "followed_tags": "แฮชแท็กที่ติดตาม", diff --git a/app/javascript/mastodon/locales/tok.json b/app/javascript/mastodon/locales/tok.json index 85f62f404..4d2cc3d1d 100644 --- a/app/javascript/mastodon/locales/tok.json +++ b/app/javascript/mastodon/locales/tok.json @@ -2,6 +2,9 @@ "about.blocks": "ma lawa", "about.contact": "toki:", "about.domain_blocks.no_reason_available": "mi sona ala e tan", + "about.domain_blocks.preamble": "ilo Masoton li ken e ni: sina lukin e toki jan pi ma ilo mute. sina ken toki tawa ona lon kulupu ma. taso, ma ni li ken ala e ni tawa ma ni:", + "about.domain_blocks.silenced.explanation": "sina lukin ala e toki e jan tan ma ni. taso, sina wile la, sina ken ni.", + "about.domain_blocks.silenced.title": "ken lili lukin", "about.domain_blocks.suspended.title": "weka", "about.not_available": "lon kulupu ni la sina ken alasa ala e sona ni.", "about.rules": "lawa kulupu", @@ -32,6 +35,7 @@ "account.follows.empty": "jan ni li kute e jan ala", "account.go_to_profile": "o tawa lipu jan", "account.hide_reblogs": "o lukin ala e pana toki tan @{name}", + "account.in_memoriam": "jan ni li moli. pona o tawa ona.", "account.languages": "sina wile lukin e sitelen pi toki seme", "account.locked_info": "sina wile kute e jan ni la ona o toki e ken", "account.media": "sitelen", @@ -53,6 +57,7 @@ "account.unblock": "o weka ala e jan {name}", "account.unblock_domain": "o weka ala e ma {domain}", "account.unblock_short": "o pini weka", + "account.unendorse": "lipu jan la o suli ala e ni", "account.unfollow": "o pini kute", "account.unmute": "o len ala e @{name}", "account.unmute_notifications_short": "o kute e mu tan jan ni", @@ -65,6 +70,9 @@ "alert.unexpected.title": "pakala a!", "announcement.announcement": "toki suli", "audio.hide": "o len e kalama", + "boost_modal.combo": "sina ken luka e nena {combo} tawa ni: sina wile ala luka e nena lon tenpo kama", + "bundle_column_error.copy_stacktrace": "o awen e sona pakala lon ilo sina", + "bundle_column_error.error.body": "ilo li ken ala pana e lipu ni. ni li ken tan pakala ilo.", "bundle_column_error.error.title": "ike a!", "bundle_column_error.network.title": "pakala la ilo sina li toki ala tawa ilo ante", "bundle_column_error.retry": "o ni sin", @@ -75,7 +83,9 @@ "bundle_modal_error.message": "ilo li wile kama e ijo ni, taso pakala li lon.", "bundle_modal_error.retry": "o ni sin", "closed_registrations_modal.find_another_server": "o alasa e ma ante", + "column.about": "sona", "column.blocks": "kulupu pi jan weka", + "column.bookmarks": "awen toki", "column.home": "lipu open", "column.lists": "kulupu lipu", "column.mutes": "jan len", diff --git a/config/locales/de.yml b/config/locales/de.yml index b77f41519..57ce5268a 100644 --- a/config/locales/de.yml +++ b/config/locales/de.yml @@ -979,7 +979,7 @@ de: next_steps: Du kannst dem Einspruch zustimmen, um die Moderationsentscheidung rückgängig zu machen, oder ihn ignorieren. subject: "%{username} hat Einspruch gegen eine Moderationsentscheidung auf %{instance} erhoben" new_critical_software_updates: - body: Kritische Updates wurden für Mastodon veröffentlicht – du solltest so schnell wie möglich aktualisieren! + body: ein neues Sicherheitsupdate wurde veröffentlicht. Du solltest Mastodon so schnell wie möglich aktualisieren! subject: Kritische Mastodon-Updates sind für %{instance} verfügbar! new_pending_account: body: Die Details von diesem neuem Konto sind unten. Du kannst die Anfrage akzeptieren oder ablehnen. @@ -1023,7 +1023,7 @@ de: salutation: "%{name}," settings: 'E-Mail-Einstellungen ändern: %{link}' unsubscribe: Abbestellen - view: 'Hier überprüfen:' + view: 'Siehe:' view_profile: Profil anzeigen view_status: Beitrag anschauen applications: diff --git a/config/locales/devise.be.yml b/config/locales/devise.be.yml index 18785d16a..81f3120a8 100644 --- a/config/locales/devise.be.yml +++ b/config/locales/devise.be.yml @@ -12,6 +12,7 @@ be: last_attempt: У вас ёсць яшчэ адна спроба, перш чым ваш рахунак будзе заблакаваны locked: Ваш уліковы запіс заблакіраваны. not_found_in_database: Няправільны %{authentication_keys} або пароль. + omniauth_user_creation_failure: Памылка пры стварэнні ўліковага запісу для гэтай асобы. pending: Ваш уліковы запіс яшчэ разглядаецца. timeout: Ваш сеанс скончыўся. Каб працягнуць, увайдзіце яшчэ раз. unauthenticated: Вам патрэбна зайсьці альбо зарэгістравацца, каб працягнуць diff --git a/config/locales/devise.ca.yml b/config/locales/devise.ca.yml index 3720d3c5f..9b4ccccff 100644 --- a/config/locales/devise.ca.yml +++ b/config/locales/devise.ca.yml @@ -14,6 +14,7 @@ ca: last_attempt: Tens un intent més abans no es bloqui el teu compte. locked: El teu compte s'ha blocat. not_found_in_database: "%{authentication_keys} o contrasenya no són vàlids." + omniauth_user_creation_failure: S'ha produït un error en crear un compte per a aquesta identitat. pending: El teu compte encara està en revisió. timeout: La teva sessió ha expirat. Torna a iniciar-la per a continuar. unauthenticated: Necessites iniciar sessió o registrar-te abans de continuar. diff --git a/config/locales/devise.da.yml b/config/locales/devise.da.yml index daf802cdb..c472242ba 100644 --- a/config/locales/devise.da.yml +++ b/config/locales/devise.da.yml @@ -12,6 +12,7 @@ da: last_attempt: Du har ét forsøg mere, før din konto bliver låst. locked: Din konto er låst. not_found_in_database: Ugyldig %{authentication_keys} eller adgangskode. + omniauth_user_creation_failure: Fejl under oprettelse af konto for denne identitet. pending: Din konto er stadig under revision. timeout: Session udløbet. Log ind igen for at fortsætte. unauthenticated: Log ind eller tilmeld dig for at fortsætte. diff --git a/config/locales/devise.de.yml b/config/locales/devise.de.yml index cf05ddc16..7982f8a74 100644 --- a/config/locales/devise.de.yml +++ b/config/locales/devise.de.yml @@ -12,6 +12,7 @@ de: last_attempt: Du hast nur noch einen Versuch, bevor dein Zugang gesperrt wird. locked: Dein Konto ist gesperrt. not_found_in_database: "%{authentication_keys} oder Passwort ungültig." + omniauth_user_creation_failure: Fehler beim Erstellen eines Kontos für diese Identität. pending: Dein Konto wird weiterhin überprüft. timeout: Deine Sitzung ist abgelaufen. Bitte melde dich erneut an, um fortzufahren. unauthenticated: Du musst dich anmelden oder registrieren, bevor du fortfahren kannst. diff --git a/config/locales/devise.es-AR.yml b/config/locales/devise.es-AR.yml index ca60ee5de..624929459 100644 --- a/config/locales/devise.es-AR.yml +++ b/config/locales/devise.es-AR.yml @@ -12,6 +12,7 @@ es-AR: last_attempt: Tenés un intento más antes de que se bloquee tu cuenta. locked: Se bloqueó tu cuenta. not_found_in_database: "%{authentication_keys} o contraseña no válidas." + omniauth_user_creation_failure: Error al crear una cuenta para esta identidad. pending: Tu cuenta todavía está bajo revisión. timeout: Venció tu sesión. Por favor, volvé a iniciar sesión para continuar. unauthenticated: Necesitás iniciar sesión o registrarte antes de continuar. diff --git a/config/locales/devise.eu.yml b/config/locales/devise.eu.yml index 624f9ee93..3e675659f 100644 --- a/config/locales/devise.eu.yml +++ b/config/locales/devise.eu.yml @@ -12,6 +12,7 @@ eu: last_attempt: Saiakera bat geratzen zaizu zure kontua giltzapetu aurretik. locked: Zure kontua giltzapetuta dago. not_found_in_database: Baliogabeko %{authentication_keys} edo pasahitza. + omniauth_user_creation_failure: Errorea identitate honen kontu bat sortzean. pending: Zure kontua oraindik berrikusteke dago. timeout: Zure saioa iraungitu da. Hasi saioa berriro jarraitzeko. unauthenticated: Saioa hasi edo izena eman behar duzu jarraitu aurretik. diff --git a/config/locales/devise.fi.yml b/config/locales/devise.fi.yml index 66616d16b..003d48417 100644 --- a/config/locales/devise.fi.yml +++ b/config/locales/devise.fi.yml @@ -12,6 +12,7 @@ fi: last_attempt: Sinulla on vielä yksi yritys ennen kuin tilisi lukitaan. locked: Tilisi on lukittu. not_found_in_database: Virheellinen %{authentication_keys} tai salasana. + omniauth_user_creation_failure: Virhe luotaessa tiliä tälle henkilöllisyydelle. pending: Tilisi on vielä tarkistamatta. timeout: Istuntosi on vanhentunut. Jatkaaksesi käyttöä, kirjaudu uudelleen. unauthenticated: Sinun on kirjauduttava tai rekisteröidyttävä ennen kuin voit jatkaa. diff --git a/config/locales/devise.fo.yml b/config/locales/devise.fo.yml index 1f7708bb4..30f83ba0d 100644 --- a/config/locales/devise.fo.yml +++ b/config/locales/devise.fo.yml @@ -12,6 +12,7 @@ fo: last_attempt: Tú kanst royna einaferð afturat áðrenn kontan verður stongd. locked: Kontan hjá tær er læst. not_found_in_database: Ogyldigur %{authentication_keys} ella loyniorð. + omniauth_user_creation_failure: Feilur í sambandi við, at ein konta fyri hendan samleikan bleiv stovnað. pending: Kontan hjá tær verður kannað enn. timeout: Tín innritan er útgingin. Innrita av nýggjum, fyri at hada fram. unauthenticated: Tú mást skriva teg inn aftur fyri at halda fram. diff --git a/config/locales/devise.fy.yml b/config/locales/devise.fy.yml index 05fd7b807..c8a04a740 100644 --- a/config/locales/devise.fy.yml +++ b/config/locales/devise.fy.yml @@ -12,6 +12,7 @@ fy: last_attempt: Jo hawwe noch ien besykjen oer eardat jo account blokkearre wurdt. locked: Jo account is blokkearre. not_found_in_database: "%{authentication_keys} of wachtwurd ûnjildich." + omniauth_user_creation_failure: Flater by it oanmeitsjen fan in account foar dizze identiteit. pending: Jo account moat noch hieltyd beoardiele wurde. timeout: Jo sesje is ferrûn. Meld jo opnij oan om troch te gean. unauthenticated: Jo moatte oanmelde of registrearje. diff --git a/config/locales/devise.gl.yml b/config/locales/devise.gl.yml index b9f4a0a00..00b182480 100644 --- a/config/locales/devise.gl.yml +++ b/config/locales/devise.gl.yml @@ -12,6 +12,7 @@ gl: last_attempt: Tes un intento máis antes de que a túa conta fique bloqueada. locked: A túa conta está bloqueada. not_found_in_database: "%{authentication_keys} ou contrasinal non válidos." + omniauth_user_creation_failure: Erro ao crear unha conta para esta identidade. pending: A túa conta aínda está baixo revisión. timeout: A túa sesión caducou. Accede outra vez para continuar. unauthenticated: Precisas iniciar sesión ou rexistrarte antes de continuar. diff --git a/config/locales/devise.he.yml b/config/locales/devise.he.yml index f2ec3a671..02e307ae1 100644 --- a/config/locales/devise.he.yml +++ b/config/locales/devise.he.yml @@ -12,6 +12,7 @@ he: last_attempt: יש לך עוד ניסיון אחד לפני נעילת החשבון. locked: חשבון זה נעול. not_found_in_database: "%{authentication_keys} או סיסמה לא נכונים." + omniauth_user_creation_failure: שגיאה ביצירת חשבון לזהות הזו. pending: חשבונך נמצא עדיין בבדיקה. timeout: פג תוקף השהיה בחשבון. נא להכנס מחדש על מנת להמשיך. unauthenticated: יש להרשם או להכנס לחשבון על מנת להמשיך. diff --git a/config/locales/devise.hu.yml b/config/locales/devise.hu.yml index fea56ab24..8c9fdf6a5 100644 --- a/config/locales/devise.hu.yml +++ b/config/locales/devise.hu.yml @@ -12,6 +12,7 @@ hu: last_attempt: Már csak egy próbálkozásod maradt, mielőtt a fiókodat zároljuk. locked: A fiókodat zároltuk. not_found_in_database: Helytelen %{authentication_keys} vagy jelszó. + omniauth_user_creation_failure: Hiba történt a fiók létrehozása során ehhez az identitáshoz. pending: A fiókod még engedélyezésre vár. timeout: A munkameneted lejárt. A folytatáshoz jelentkezz be újra. unauthenticated: A folytatás előtt be kell jelentkezned vagy regisztrálnod kell. diff --git a/config/locales/devise.ie.yml b/config/locales/devise.ie.yml index 332c9da45..9c82bd452 100644 --- a/config/locales/devise.ie.yml +++ b/config/locales/devise.ie.yml @@ -12,6 +12,7 @@ ie: last_attempt: Hay solmen un prova ante que tui conto deveni serrat. locked: Tui conto es serrat. not_found_in_database: Ínvalid %{authentication_keys} o passa-parol. + omniauth_user_creation_failure: Errore in li creation de un conto por ti-ci identitá. pending: Tui conto es ancor sub revision. timeout: Tui session ha expirat. Ples reintrar denov por continuar. unauthenticated: Tu deve intrar o registrar te ante continuar. diff --git a/config/locales/devise.is.yml b/config/locales/devise.is.yml index 12015fa29..a045bdd80 100644 --- a/config/locales/devise.is.yml +++ b/config/locales/devise.is.yml @@ -12,6 +12,7 @@ is: last_attempt: Þú getur reynt einu sinni í viðbót áður en aðgangnum þínum verður læst. locked: Notandaaðgangurinn þinn er læstur. not_found_in_database: Ógilt %{authentication_keys} eða lykilorð. + omniauth_user_creation_failure: Villa við að útbúa aðgang fyrir þetta auðkenni. pending: Notandaaðgangurinn þinn er enn til yfirferðar. timeout: Setan þín er útrunnin. Skráðu þig aftur inn til að halda áfram. unauthenticated: Þú þarft að skrá þig inn eða nýskrá þig áður en lengra er haldið. diff --git a/config/locales/devise.it.yml b/config/locales/devise.it.yml index 19bd999aa..8aaea3c15 100644 --- a/config/locales/devise.it.yml +++ b/config/locales/devise.it.yml @@ -12,6 +12,7 @@ it: last_attempt: Hai un altro tentativo, prima che il tuo profilo venga bloccato. locked: Il tuo profilo è bloccato. not_found_in_database: "%{authentication_keys} o password non valida." + omniauth_user_creation_failure: Errore nella creazione di un account per questa identità. pending: Il tuo profilo è ancora in revisione. timeout: La tua sessione è scaduta. Sei pregato di accedere nuovamente per continuare. unauthenticated: Devi accedere o registrarti, per continuare. diff --git a/config/locales/devise.kab.yml b/config/locales/devise.kab.yml index 2f60629fd..f878a5b50 100644 --- a/config/locales/devise.kab.yml +++ b/config/locales/devise.kab.yml @@ -13,13 +13,13 @@ kab: locked: Amiḍan-ik yettwargel. not_found_in_database: Tella tuccḍa deg %{authentication_keys} neγ deg wawal uffir. pending: Amiḍan-inek mazal-it deg ɛiwed n tmuγli. - timeout: Tiγimit n tuqqna tezri. Ma ulac aγilif ɛiwed tuqqna akken ad tkemmleḍ. - unauthenticated: Ilaq ad teqqneḍ neγ ad tjerrḍeḍ akken ad tkemmelḍ. + timeout: Tiɣimit n tuqqna tezri. Ma ulac aɣilif ɛiwed tuqqna akken ad tkemmleḍ. + unauthenticated: Ilaq ad teqqneḍ neɣ ad tjerrḍeḍ akken ad tkemmelḍ. unconfirmed: Ilaq ad wekdeḍ tansa-inek imayl akken ad tkemmelḍ. mailer: confirmation_instructions: action: Senqed tansa-inek imayl - action_with_app: Wekked sakkin uγal γer %{app} + action_with_app: Sentem sakkin uɣal ɣer %{app} explanation: Aqla-k terniḍ amiḍan deg %{host} s tansa imayl-agi. Mazal-ak yiwen utekki akken ad t-tremdeḍ. Ma mačči d kečč i yessutren ay-agi, ttxil-k ssinef izen-a. explanation_when_pending: Tsutreḍ-d ajerred deg %{host} s tansa-agi imayl. Ad nγeṛ asuter-ik ticki tsentmeḍ tansa-ik imayl. Send asentem, ur tezmireḍ ara ad teqqneḍ γer umiḍan-ik. Ma yella nugi asuter-ik, isefka-ik ad ttwakksen seg uqeddac, ihi ulac tigawt-nniḍen ara k-d-yettuqeblen. Ma mačči d kečč i yellan deffir n usuter-agi, ttxil-k ssinef izen-agi. extra_html: Ttxil-k ẓer daγen ilugan n uqeddac akked twetlin n useqdec-nneγ. @@ -87,7 +87,7 @@ kab: unlocks: send_instructions: Deg kra n tesdatin, ad teṭṭfeḍ imayl deg-s iwellihen i yilaqen i userreḥ n umiḍan-ik·im. Ma yella ur tufiḍ ara izen-agi, ttxil-k·m ẓer deg ukaram spam. send_paranoid_instructions: Ma yella umiḍan-ik·im yella, ad teṭṭfeḍ imayl deg tesdatin i d-iteddun, deg-s iwellihen i yilaqen i userreḥ n umiḍan-ik·im. Ma yella ur tufiḍ ara izen-agi, ttxil-k·m ẓer deg ukaram spam. - unlocked: Iserreḥ umiḍan-ik·im akken iwata. ttxil qqen akken ad tkemleḍ. + unlocked: Iserreḥ umiḍan-ik·im akken iwata. Ttxil qqen akken ad tkemleḍ. errors: messages: already_confirmed: ittwasentem yakan, ttxil εreḍ ad teqneḍ diff --git a/config/locales/devise.ko.yml b/config/locales/devise.ko.yml index 0c848e4ba..198d44a4f 100644 --- a/config/locales/devise.ko.yml +++ b/config/locales/devise.ko.yml @@ -12,6 +12,7 @@ ko: last_attempt: 계정이 잠기기까지 한 번의 시도가 남았습니다. locked: 계정이 잠겼습니다. not_found_in_database: 올바르지 않은 %{authentication_keys} 혹은 암호입니다. + omniauth_user_creation_failure: 이 신원으로 계정을 만드는데 실패했습니다. pending: 이 계정은 아직 검토 중입니다. timeout: 세션이 만료되었습니다. 다시 로그인 하세요. unauthenticated: 계속 하려면 로그인을 해야 합니다. diff --git a/config/locales/devise.lad.yml b/config/locales/devise.lad.yml index d2ce53760..7d447140f 100644 --- a/config/locales/devise.lad.yml +++ b/config/locales/devise.lad.yml @@ -12,6 +12,7 @@ lad: last_attempt: Aprova una vez mas antes de ke tu kuento sea blokado. locked: Tu kuento esta blokado. not_found_in_database: Inkorekto %{authentication_keys} o kod. + omniauth_user_creation_failure: Ay un error en kriyar un kuento para esta identita. pending: Tu kuento ainda esta basho revizyon. timeout: Tu sesyon tiene kadukado. Por favor konektate kon tu kuento de muevo para kontinuar. unauthenticated: Kale konektarte kon tu kuento o enregistrarte antes de kontinuar. diff --git a/config/locales/devise.nl.yml b/config/locales/devise.nl.yml index 0aaf376f7..ab6ae84db 100644 --- a/config/locales/devise.nl.yml +++ b/config/locales/devise.nl.yml @@ -12,6 +12,7 @@ nl: last_attempt: Je hebt nog één poging over voordat jouw account wordt opgeschort. locked: Jouw account is opgeschort. not_found_in_database: "%{authentication_keys} of wachtwoord ongeldig." + omniauth_user_creation_failure: Fout bij het aanmaken van een account voor deze identiteit. pending: Jouw account moet nog steeds worden beoordeeld. timeout: Jouw sessie is verlopen, log opnieuw in. unauthenticated: Je dient in te loggen of te registreren. diff --git a/config/locales/devise.pl.yml b/config/locales/devise.pl.yml index a6d48f11e..f34fd0463 100644 --- a/config/locales/devise.pl.yml +++ b/config/locales/devise.pl.yml @@ -12,6 +12,7 @@ pl: last_attempt: Masz jeszcze jedną próbę; Twoje konto zostanie zablokowane jeśli się nie powiedzie. locked: Twoje konto zostało zablokowane. not_found_in_database: Nieprawidłowy %{authentication_keys} lub hasło. + omniauth_user_creation_failure: Błąd przy tworzeniu konta dla tej tożsamości. pending: Twoje konto oczekuje na przegląd. timeout: Twoja sesja wygasła. Zaloguj się ponownie, aby kontynuować.. unauthenticated: Zapisz się lub zaloguj, aby kontynuować. diff --git a/config/locales/devise.pt-PT.yml b/config/locales/devise.pt-PT.yml index c169ddeb9..c66181fc5 100644 --- a/config/locales/devise.pt-PT.yml +++ b/config/locales/devise.pt-PT.yml @@ -12,6 +12,7 @@ pt-PT: last_attempt: Tem só mais uma tentativa antes da sua conta ser bloqueada. locked: A tua conta está bloqueada. not_found_in_database: "%{authentication_keys} ou palavra-passe inválida." + omniauth_user_creation_failure: Erro ao criar uma conta para esta identidade. pending: A sua conta está ainda a aguardar revisão. timeout: A tua sessão expirou. Por favor, entra de novo para continuares. unauthenticated: Precisas de entrar na tua conta ou de te registares antes de continuar. diff --git a/config/locales/devise.sk.yml b/config/locales/devise.sk.yml index 3eb4b5304..bc01b73cc 100644 --- a/config/locales/devise.sk.yml +++ b/config/locales/devise.sk.yml @@ -12,6 +12,7 @@ sk: last_attempt: Máš posledný pokus pred zamknutím tvojho účtu. locked: Tvoj účet je zamknutý. not_found_in_database: Nesprávny %{authentication_keys}, alebo heslo. + omniauth_user_creation_failure: Chyba pri vytváraní účtu pre túto identitu. pending: Tvoj účet je stále prehodnocovaný. timeout: Tvoja aktívna sezóna vypršala. Pre pokračovanie sa prosím prihlás znovu. unauthenticated: K pokračovaniu sa musíš zaregistrovať alebo prihlásiť. diff --git a/config/locales/devise.sl.yml b/config/locales/devise.sl.yml index 2d567e63f..0eb9b6330 100644 --- a/config/locales/devise.sl.yml +++ b/config/locales/devise.sl.yml @@ -12,6 +12,7 @@ sl: last_attempt: Pred zaklepom računa imate še en poskus. locked: Vaš račun je zaklenjen. not_found_in_database: Neveljavno %{authentication_keys} ali geslo. + omniauth_user_creation_failure: Napaka pri ustvarjanju računa za to identiteto. pending: Vaš račun je še vedno pod drobnogledom. timeout: Vaša seja je potekla. Če želite nadaljevati, se znova prijavite. unauthenticated: Pred nadaljevanjem se morate prijaviti ali vpisati. diff --git a/config/locales/devise.sq.yml b/config/locales/devise.sq.yml index 32136a0ba..76dd49324 100644 --- a/config/locales/devise.sq.yml +++ b/config/locales/devise.sq.yml @@ -12,6 +12,7 @@ sq: last_attempt: Mund të provoni edhe një herë, përpara se llogaria juaj të kyçet. locked: Llogaria juaj është e kyçur. not_found_in_database: "%{authentication_keys} ose fjalëkalim i pavlefshëm." + omniauth_user_creation_failure: Gabim në krijim llogarie për këtë identitet. pending: Llogaria juaj është ende nën shqyrtim. timeout: Sesioni juaj ka skaduar. Ju lutemi, që të vazhdohet, ribëni hyrjen. unauthenticated: Përpara se të vazhdohet më tej, lypset të bëni hyrjen ose të regjistroheni. diff --git a/config/locales/devise.sr-Latn.yml b/config/locales/devise.sr-Latn.yml index c48ed87dc..3947b2d84 100644 --- a/config/locales/devise.sr-Latn.yml +++ b/config/locales/devise.sr-Latn.yml @@ -12,6 +12,7 @@ sr-Latn: last_attempt: Imate još jedan pokušaj pre nego što Vaš nalog bude zaključan. locked: Vaš nalog je zaključan. not_found_in_database: Neispravna %{authentication_keys} ili lozinka. + omniauth_user_creation_failure: Greška pri kreiranju naloga za ovaj identitet. pending: Vaš račun je još uvek u pregledu. timeout: Vreme trajanja Vaše sesije je isteklo. Za nastavak prijavite se ponovo. unauthenticated: Za nastavak se morate prijaviti ili registrovati. diff --git a/config/locales/devise.sr.yml b/config/locales/devise.sr.yml index 3e49cf97e..a4c08dfaf 100644 --- a/config/locales/devise.sr.yml +++ b/config/locales/devise.sr.yml @@ -12,6 +12,7 @@ sr: last_attempt: Имате још један покушај пре него што Ваш налог буде закључан. locked: Ваш налог је закључан. not_found_in_database: Неисправна %{authentication_keys} или лозинка. + omniauth_user_creation_failure: Грешка при креирању налога за овај идентитет. pending: Ваш налог се још увек прегледа. timeout: Ваша сесија је истекла. Пријавите се поново да бисте наставили. unauthenticated: Морате да се пријавите или региструјете пре него што наставите. diff --git a/config/locales/devise.tr.yml b/config/locales/devise.tr.yml index 66ca9b281..e709d3fff 100644 --- a/config/locales/devise.tr.yml +++ b/config/locales/devise.tr.yml @@ -12,6 +12,7 @@ tr: last_attempt: Hesabınız kilitlenmeden önce bir kez daha denemeniz gerekir. locked: Hesabınız kilitlendi. not_found_in_database: Geçersiz %{authentication_keys} ya da parola. + omniauth_user_creation_failure: Bu kimlik için hesap oluşturmada hata. pending: Hesabınız hala inceleniyor. timeout: Oturum süreniz sona erdi. Lütfen devam etmek için tekrar giriş yapınız. unauthenticated: Devam etmeden önce oturum açmanız veya kayıt olmanız gerek. diff --git a/config/locales/devise.uk.yml b/config/locales/devise.uk.yml index 3b3883fa9..65e89a274 100644 --- a/config/locales/devise.uk.yml +++ b/config/locales/devise.uk.yml @@ -12,6 +12,7 @@ uk: last_attempt: У вас залишилась ще одна спроба, після якої ваш обліковий запис буде заблоковано. locked: Ваш обліковий запис заблоковано. not_found_in_database: Неправильний %{authentication_keys} або пароль. + omniauth_user_creation_failure: Помилка створення облікового запису для цієї особи. pending: Ваш обліковий запис ще перебуває на розгляді. timeout: Час сеансу минув. Будь ласка, увійдіть знову, щоб продовжити. unauthenticated: Щоб продовжити, увійдіть або зареєструйтеся. diff --git a/config/locales/devise.zh-CN.yml b/config/locales/devise.zh-CN.yml index 9b4b3ae20..3eb722b96 100644 --- a/config/locales/devise.zh-CN.yml +++ b/config/locales/devise.zh-CN.yml @@ -12,6 +12,7 @@ zh-CN: last_attempt: 你只有最后一次尝试机会,若未通过,帐号将被锁定。 locked: 你的账户已被锁定。 not_found_in_database: "%{authentication_keys}或密码错误。" + omniauth_user_creation_failure: 为此身份创建账户时出错。 pending: 你的账号仍在审核中。 timeout: 你的会话已过期。请重新登录再继续操作。 unauthenticated: 继续操作前请注册或者登录。 diff --git a/config/locales/devise.zh-HK.yml b/config/locales/devise.zh-HK.yml index 7f728bf0a..a2620a8e4 100644 --- a/config/locales/devise.zh-HK.yml +++ b/config/locales/devise.zh-HK.yml @@ -12,6 +12,7 @@ zh-HK: last_attempt: 若你再一次嘗試失敗,我們將鎖定你的帳號,以策安全。 locked: 你的帳號已被鎖定。 not_found_in_database: 不正確的%{authentication_keys}或密碼。 + omniauth_user_creation_failure: 為此身份建立帳號時出錯。 pending: 你的帳號仍在審核中 timeout: 你的登入階段已經過期,請重新登入以繼續使用。 unauthenticated: 你必須先登入或登記,以繼續使用。 diff --git a/config/locales/devise.zh-TW.yml b/config/locales/devise.zh-TW.yml index 06438971a..7ead831e4 100644 --- a/config/locales/devise.zh-TW.yml +++ b/config/locales/devise.zh-TW.yml @@ -12,6 +12,7 @@ zh-TW: last_attempt: 帳號鎖定前,您還有最後一次嘗試機會。 locked: 已鎖定您的帳號。 not_found_in_database: 無效的 %{authentication_keys} 或密碼。 + omniauth_user_creation_failure: 以此身分新增帳號時發生錯誤。 pending: 您的帳號仍在審核中。 timeout: 登入階段逾時。請重新登入以繼續。 unauthenticated: 您必須先登入或註冊才能繼續使用。 diff --git a/config/locales/doorkeeper.kab.yml b/config/locales/doorkeeper.kab.yml index fe1a8d9c5..d7f8904a3 100644 --- a/config/locales/doorkeeper.kab.yml +++ b/config/locales/doorkeeper.kab.yml @@ -36,7 +36,7 @@ kab: application: Asnas callback_url: URL n tririt n wawal delete: Kkes - empty: Ulac γur-ek·em isnasen. + empty: Ulac ɣur-k·m isnasen. name: Isem new: Asnas amaynut show: Ẓer @@ -57,7 +57,7 @@ kab: new: title: Tlaq tsiregt show: - title: Nγel tangalt n wurag sakkin senteḍ-itt deg usnas. + title: Nɣel tangalt n wurag sakkin senteḍ-itt deg usnas. authorized_applications: buttons: revoke: Ḥwi @@ -113,13 +113,13 @@ kab: read:notifications: ẓer tilγa-ik read:reports: ẓer ineqqisen-ik·im read:search: anadi deg umkan-ik·im - read:statuses: ẓer meṛṛa tisuffaγ + read:statuses: ẓer meṛṛa tisuffaɣ write: beddel meṛṛa isefka n umiḍan-ik write:accounts: ẓreg amaγnu-ik write:blocks: seḥbes imiḍanen d tγula - write:bookmarks: ad yernu tisuffγin γer ticraḍ + write:bookmarks: ad yernu tisuffaɣ ɣer ticraḍ write:filters: rnu-d imsizedgen write:follows: ḍfeṛ imdanen write:lists: ad yesnulfu tibdarin - write:media: ad yessali ifayluyen n teγwalt + write:media: ad yessali ifuyla n umidya write:notifications: sfeḍ tilɣa-k·m diff --git a/config/locales/ie.yml b/config/locales/ie.yml index a8287da53..7ab7f953b 100644 --- a/config/locales/ie.yml +++ b/config/locales/ie.yml @@ -1793,6 +1793,12 @@ ie: extra: It es ja pret a descargar! subject: Tui archive es pret por descargar title: Descargar archive + failed_2fa: + details: 'Vi li detallies del prova de intrar:' + explanation: Alqui provat accesser tui conto ma usat un ínvalid duesim factor de autentication. + further_actions_html: Si it ne esset tu, noi recomanda que tu strax %{action} nam li conto posse esser compromisset. + subject: Falliment de autentication de duesim factor + title: Fallit autentication de duesim factor suspicious_sign_in: change_password: changear tui passa-parol details: 'Vi li detallies del apertion de session:' diff --git a/config/locales/kab.yml b/config/locales/kab.yml index 66aeafde6..bf574fc01 100644 --- a/config/locales/kab.yml +++ b/config/locales/kab.yml @@ -5,7 +5,7 @@ kab: contact_missing: Ur yettusbadu ara contact_unavailable: Wlac hosted_on: Maṣṭudun yersen deg %{domain} - title: Γef + title: Ɣef accounts: follow: Ḍfeṛ followers: @@ -15,9 +15,9 @@ kab: last_active: armud aneggaru nothing_here: Ulac kra da! posts: - one: Tajewwiqt - other: Tijewwiqin - posts_tab_heading: Tijewwiqin + one: Tasuffeɣt + other: Tisuffaɣ + posts_tab_heading: Tisuffaɣ admin: account_actions: action: Eg tigawt @@ -47,7 +47,7 @@ kab: disable_two_factor_authentication: Gdel 2FA disabled: Yensa display_name: Isem ara d-yettwaskanen - domain: Taγult + domain: Taɣult edit: Ẓreg email: Imayl email_status: Addad n imayl @@ -111,7 +111,7 @@ kab: targeted_reports: Yettwazen uneqqis sɣur wiyaḍ silence: Sgugem silenced: Yettwasgugem - statuses: Tisuffɣin + statuses: Tisuffaɣ subscribe: Jerred suspended: Yeḥbes title: Imiḍanen @@ -203,22 +203,22 @@ kab: announcements: destroyed_msg: Tamselɣut tettwakkes akken iwata! edit: - title: Ẓreg ulγu - empty: Ulac kra n ulγuyen. + title: Ẓreg ulɣu + empty: Ulac kra n yilɣa yettwafen. live: Srid new: - create: Rnu-d ulγu - title: Ulγu amaynut + create: Snlufu-d ulɣu + title: Ulɣu amaynut publish: Sufeɣ published_msg: Tamselɣut tettwasufeɣ-d akken iwata! scheduled_for: Yettusɣiwsen i %{time} scheduled_msg: Tamselɣut tettusɣiwes i usufeɣ! - title: Ulγuyen + title: Ilɣa custom_emojis: assign_category: Efk taggayt - by_domain: Taγult + by_domain: Taɣult copied_msg: Takna tadigant n imuji yettwarna-d mebla ugur - copy: Nγel + copy: Nɣel create_new_category: Rnu-d taggayt tamaynut created_msg: Imuji yettwarna-d mebla ugur! delete: Kkes @@ -229,7 +229,7 @@ kab: enable: Rmed enabled: Yermed enabled_msg: Imuji yermed mebla ugur - list: Umuγ + list: Tabdart new: title: Timerna n imuji udmawan amaynut overwrite: Semselsi @@ -256,7 +256,7 @@ kab: add_new: Rni iḥder amaynut n taɣult confirm_suspension: cancel: Sefsex - domain: Taγult + domain: Taɣult export: Sifeḍ import: Kter new: @@ -274,9 +274,9 @@ kab: email_domain_blocks: add_new: Rnu amaynut delete: Kkes - domain: Taγult + domain: Taɣult new: - create: Rnu taγult + create: Rnu taɣult title: Timerna n taɣult tamaynut n imayl ɣer tebdart taberkant title: Tabdart taberkant n imayl follow_recommendations: @@ -286,8 +286,8 @@ kab: instances: back_to_all: Akk back_to_limited: Ɣur-s talast - back_to_warning: Γur-wat - by_domain: Taγult + back_to_warning: Ɣur-wat + by_domain: Taɣult content_policies: policy: Tasertit delivery: @@ -306,7 +306,7 @@ kab: private_comment: Awennit uslig public_comment: Awennit azayez title: Tamatut - total_blocked_by_us: Ttwasḥebsen sγur-neγ + total_blocked_by_us: Ttwasḥebsen sɣur-neɣ total_followed_by_them: Ṭtafaṛen-t total_followed_by_us: Neṭṭafaṛ-it total_reported: Ineqqisen fell-asen @@ -354,12 +354,15 @@ kab: other: "%{count} n timawin" action_taken_by: Tigawt yettwaṭṭfen sɣur are_you_sure: Tetḥaq-eḍ? + cancel: Sefsex category: Taggayt comment: none: Ula yiwen confirm: Sentem + delete_and_resolve: Kkes tisuffaɣ mark_as_resolved: Creḍ-it yefra mark_as_unresolved: Creḍ-it ur yefra ara + no_one_assigned: Ula yiwen notes: create: Rnu tazmilt create_and_resolve: Fru s tamawt @@ -390,16 +393,16 @@ kab: title: Ilugan n uqeddac settings: about: - title: Γef + title: Ɣef appearance: title: Udem discovery: - profile_directory: Akaram n imaγnuten + profile_directory: Akaram n imaɣnuten trends: Ayen mucaɛen domain_blocks: all: I medden akk - disabled: Γef ula yiwen - users: Γef yimseqdacen idiganen i yeqqnen + disabled: Ɣef ula yiwen + users: Ɣef yimseqdacen idiganen i yeqqnen registrations: title: Ajerred registrations_mode: @@ -408,19 +411,26 @@ kab: open: Zemren akk ad jerden site_uploads: delete: Kkes afaylu yulin + software_updates: + documentation_link: Issin ugar statuses: application: Asnas - back_to_account: Tuγalin γer usebter n umiḍan + back_to_account: Tuɣalin ɣer usebter n umiḍan deleted: Yettwakkes favourites: Imenyafen language: Tutlayt media: - title: Taγwalt - title: Tisuffiγin n umiḍan - with_media: S taγwalt + title: Amidya + title: Tisuffaɣ n umiḍan + trending: Ayen mucaɛen + visibility: Abani + with_media: S umidya title: Tadbelt trends: allow: Sireg + statuses: + title: Tisuffaɣ mucaɛen + trending: Ayen mucaɛen warning_presets: add_new: Rnu amaynut delete: Kkes @@ -431,7 +441,11 @@ kab: new_report: body: "%{reporter} yettwazen ɣef %{target}" subject: Aneqqis amaynut i %{instance} (#%{id}) + new_trends: + new_trending_statuses: + title: Tisuffaɣ mucaɛen appearance: + advanced_web_interface: Agrudem n web leqqayen discovery: Asnirem localization: guide_link: https://crowdin.com/project/mastodon @@ -448,6 +462,8 @@ kab: your_token: Ajiṭun-ik·im n unekcum auth: apply_for_account: Suter amiḍan + confirmations: + welcome_title: Ansuf yessek·em, %{name}! delete_account: Kkes amiḍan description: prefix_invited_by_user: "@%{name} inced-ik·ikem ad ternuḍ ɣer uqeddac-a n Mastodon!" @@ -455,9 +471,11 @@ kab: forgot_password: Tettud awal-ik uffir? log_in_with: Qqen s login: Qqen - logout: Ffeγ - migrate_account: Gujj γer umiḍan nniḍen - or_log_in_with: Neγ eqqen s + logout: Ffeɣ + migrate_account: Gujj ɣer umiḍan nniḍen + or_log_in_with: Neɣ eqqen s + progress: + confirm: Sentem imayl providers: cas: CAS saml: SAML @@ -466,8 +484,11 @@ kab: reset_password: Wennez awal uffir rules: back: Tuɣalin - security: Taγellist + security: Taɣellist set_new_password: Egr-d awal uffir amaynut + sign_in: + preamble_html: Kcem ar %{domain} s inekcam-inek n tuqqna. Ma yella yezga-d umiḍan-ik deg uqeddac-nniḍen, ur tezmireḍ ara ad tkecmeḍ sya. + title: Akeččum ɣer %{domain} status: account_status: Addad n umiḍan use_security_key: Seqdec tasarut n teɣlist @@ -498,16 +519,21 @@ kab: warning: username_available: Isem-ik·im n useqdac ad yuɣal yella i tikkelt-nniḍen username_unavailable: Isem-ik·im n useqdac ad yeqqim ulac-it + disputes: + strikes: + status: 'Tasuffeɣt #%{id}' + title_actions: + none: Ɣur-wat errors: '500': - title: Asebter-ayi d arameγtu + title: Asebter-ayi d arameɣtu existing_username_validator: not_found_multiple: ur yezmir ara ad yaf %{usernames} exports: archive_takeout: date: Azemz download: Sider-d aḥraz-ik·im - size: Teγzi + size: Teɣzi bookmarks: Ticraḍ csv: CSV lists: Tibdarin @@ -516,8 +542,8 @@ kab: add_new: Rnu amaynut filters: contexts: - account: Imuγna - notifications: Tilγa + account: Imuɣna + notifications: Ilɣa thread: Idiwenniyen edit: title: Ẓreg amzizdig @@ -534,8 +560,10 @@ kab: remove: Kkes seg umsizdeg generic: all: Akk + cancel: Sefsex changes_saved_msg: Ttwaskelsen ibelliden-ik·im akken ilaq! - copy: Nγel + confirm: Sentem + copy: Nɣel delete: Kkes order_by: Sizwer s save_changes: Sekles ibeddilen @@ -575,7 +603,7 @@ kab: sign_in_token: tangalt n tɣellist n tansa imayl webauthn: tisura n tɣellist migrations: - acct: Ibeddel γer + acct: Ibeddel ɣer incoming_migrations: Tusiḍ-d seg umiḍan nniḍen proceed_with_move: Awid imeḍfaṛen-ik moderation: @@ -597,7 +625,7 @@ kab: reblog: subject: "%{name} yesselha addad-ik·im" notifications: - other_settings: Iγewwaṛen nniḍen n tilγa + other_settings: Iɣewwaṛen nniḍen n yilɣa number: human: decimal_units: @@ -611,11 +639,13 @@ kab: setup: Sbadu pagination: newer: Amaynut - next: Γer zdat + next: Ɣer zdat older: Aqbuṛ prev: Win iɛeddan preferences: other: Wiyaḍ + privacy: + privacy: Tabaḍnit privacy_policy: title: Tasertit tabaḍnit relationships: @@ -634,6 +664,7 @@ kab: browser: Iminig browsers: alipay: Alipay + blackberry: BlackBerry chrome: Chrome edge: Microsoft Edge electron: Electron @@ -648,37 +679,41 @@ kab: qq: Iminig QQ safari: Safari weibo: Weibo - current_session: Tiγimit tamirant + current_session: Tiɣimit tamirant + date: Azemz description: "%{browser} s %{platform}" ip: IP platforms: adobe_air: Adobe Air android: Android + blackberry: BlackBerry + chrome_os: ChromeOS firefox_os: Firefox OS ios: iOS + kai_os: KaiOS linux: Linux mac: macOS windows: Windows windows_mobile: Windows Mobile - windows_phone: Tiliγri Windows Phone + windows_phone: Tiliɣri Windows Phone revoke: Ḥwi title: Tiɣimiyin settings: account: Amiḍan - account_settings: Iγewwaṛen n umiḍan + account_settings: Iɣewwaṛen n umiḍan appearance: Udem authorized_apps: Isnasen yettussirgen - back: Uγal γer Maṣṭudun + back: Uɣal ɣer Maṣṭudun delete: Tukksa n umiḍan development: Taneflit - edit_profile: Ẓreg amaγnu + edit_profile: Ẓreg amaɣnu export: Taktert n yisefka import: Kter import_and_export: Taktert d usifeḍ migrate: Tunigin n umiḍan - notifications: Tilγa + notifications: Ilɣa preferences: Imenyafen - profile: Ameγnu + profile: Ameɣnu relationships: Imeḍfaṛen akked wid i teṭṭafaṛeḍ statuses_cleanup: Tukksa tawurmant n tsuffaɣ two_factor_authentication: Asesteb s snat n tarrayin @@ -745,22 +780,25 @@ kab: otp: Asnas n usesteb webauthn: Tisura n teɣlist user_mailer: + appeal_approved: + action: Iɣewwaṛen n umiḍan warning: categories: spam: Aspam title: disable: Amiḍan i igersen - none: Γur-wat + none: Ɣur-wat silence: Amiḍan yesɛa talast suspend: Amiḍan yettwaḥbas welcome: final_action: Bdu asuffeɣ full_handle: Tansa umiḍan-ik takemmalit - subject: Ansuf γer Maṣṭudun + subject: Ansuf ɣer Maṣṭudun title: Ansuf yessek·em, %{name}! users: signed_in_as: 'Teqqneḍ amzun d:' verification: + here_is_how: Ha-t-a amek verification: Asenqed webauthn_credentials: add: Rnu tasarut n teɣlist tamaynut diff --git a/config/locales/simple_form.kab.yml b/config/locales/simple_form.kab.yml index 1e1c52da2..546336660 100644 --- a/config/locales/simple_form.kab.yml +++ b/config/locales/simple_form.kab.yml @@ -12,7 +12,7 @@ kab: defaults: autofollow: Imdanen ara ijerrden s usnebgi-inek, ad k-ḍefṛen s wudem awurman email: Ad n-teṭṭfeḍ imayl i usentem - irreversible: Tijewwaqin i tessazedgeḍ ad ttwakksent i lebda, ula ma tekkseḍ imsizdeg-nni ar zdat + irreversible: Tisuffaɣ i tessazedgeḍ ad ttwakksent i lebda, ula ma tekkseḍ imsizdeg-nni ar zdat locale: Tutlayt n ugrudem, imaylen d tilγa password: Seqdec ma drus 8 n yisekkilen setting_display_media_default: Ffer teywalt yettwacreḍ d tanafrit @@ -69,12 +69,12 @@ kab: setting_display_media_show_all: Ssken kullec setting_hide_network: Ffer azetta-k·m setting_theme: Asental n wesmel - setting_use_pending_items: Askar aleγwayan + setting_use_pending_items: Askar aleɣwayan sign_in_token_attempt: Tangalt n tɣellist title: Azwel type: Anaw n uktar username: Isem n useqdac - username_or_email: Isem n useqdac neγ imal + username_or_email: Isem n useqdac neɣ imal whole_word: Awal akk featured_tag: name: Ahacṭag @@ -84,7 +84,7 @@ kab: invite: comment: Awennit invite_request: - text: Acimi tebγiḍ ad ternuḍ iman-ik? + text: Acimi tebɣiḍ ad ternuḍ iman-ik? ip_block: comment: Awennit ip: IP diff --git a/config/locales/sq.yml b/config/locales/sq.yml index 3dd473120..460fd82dc 100644 --- a/config/locales/sq.yml +++ b/config/locales/sq.yml @@ -188,7 +188,7 @@ sq: create_user_role: Krijoni Rol demote_user: Zhgradoje Përdoruesin destroy_announcement: Fshije Lajmërimin - destroy_canonical_email_block: Fshi Bllokim El-esh + destroy_canonical_email_block: Fshi Bllokim Email-esh destroy_custom_emoji: Fshi Emotikon Vetjak destroy_domain_allow: Fshi Lejim Përkatësie destroy_domain_block: Fshi Bllokim Përkatësie @@ -283,7 +283,7 @@ sq: unsuspend_account_html: "%{name} hoqi pezullimin për llogarinë e %{target}" update_announcement_html: "%{name} përditësoi lajmërimin %{target}" update_custom_emoji_html: "%{name} përditësoi emoxhin %{target}" - update_domain_block_html: "%{name} përditësoi bllokimin e përkatësish për %{target}" + update_domain_block_html: "%{name} përditësoi bllokim përkatësish për %{target}" update_ip_block_html: "%{name} ndryshoi rregull për IP-në %{target}" update_status_html: "%{name} përditësoi gjendjen me %{target}" update_user_role_html: "%{name} ndryshoi rolin për %{target}" diff --git a/config/locales/th.yml b/config/locales/th.yml index 74fc1b26b..b76f6992a 100644 --- a/config/locales/th.yml +++ b/config/locales/th.yml @@ -452,7 +452,7 @@ th: title: นำเข้าการปิดกั้นโดเมน no_file: ไม่ได้เลือกไฟล์ follow_recommendations: - description_html: "คำแนะนำการติดตามช่วยให้ผู้ใช้ใหม่ค้นหาเนื้อหาที่น่าสนใจได้อย่างรวดเร็ว เมื่อผู้ใช้ไม่ได้โต้ตอบกับผู้อื่นมากพอที่จะสร้างคำแนะนำการติดตามส่วนบุคคล จะแนะนำบัญชีเหล่านี้แทน จะคำนวณคำแนะนำใหม่เป็นประจำทุกวันจากบัญชีต่าง ๆ ที่มีการมีส่วนร่วมล่าสุดสูงสุดและจำนวนผู้ติดตามในเซิร์ฟเวอร์สูงสุดสำหรับภาษาที่กำหนด" + description_html: "คำแนะนำการติดตามช่วยให้ผู้ใช้ใหม่ค้นหาเนื้อหาที่น่าสนใจได้อย่างรวดเร็ว เมื่อผู้ใช้ไม่ได้โต้ตอบกับผู้อื่นมากพอที่จะสร้างคำแนะนำการติดตามเฉพาะบุคคล จะแนะนำบัญชีเหล่านี้แทน จะคำนวณคำแนะนำใหม่เป็นประจำทุกวันจากบัญชีต่าง ๆ ที่มีการมีส่วนร่วมล่าสุดสูงสุดและจำนวนผู้ติดตามในเซิร์ฟเวอร์สูงสุดสำหรับภาษาที่กำหนด" language: สำหรับภาษา status: สถานะ suppress: ระงับคำแนะนำการติดตาม From 4b7f04e3eab274e574289a554f004c4a58e7ef9b Mon Sep 17 00:00:00 2001 From: Matt Jankowski Date: Fri, 16 Feb 2024 02:52:29 -0500 Subject: [PATCH 23/37] Reduce `RSpec/MultipleExpectations` in post_status_service spec (#29225) --- spec/services/post_status_service_spec.rb | 28 +++++++++++------------ 1 file changed, 14 insertions(+), 14 deletions(-) diff --git a/spec/services/post_status_service_spec.rb b/spec/services/post_status_service_spec.rb index d10a82607..acbebc505 100644 --- a/spec/services/post_status_service_spec.rb +++ b/spec/services/post_status_service_spec.rb @@ -32,27 +32,27 @@ RSpec.describe PostStatusService, type: :service do let!(:future) { Time.now.utc + 2.hours } let!(:previous_status) { Fabricate(:status, account: account) } - it 'schedules a status' do - status = subject.call(account, text: 'Hi future!', scheduled_at: future) - expect(status).to be_a ScheduledStatus - expect(status.scheduled_at).to eq future - expect(status.params['text']).to eq 'Hi future!' - end - - it 'does not immediately create a status' do + it 'schedules a status for future creation and does not create one immediately' do media = Fabricate(:media_attachment, account: account) status = subject.call(account, text: 'Hi future!', media_ids: [media.id], scheduled_at: future) - expect(status).to be_a ScheduledStatus - expect(status.scheduled_at).to eq future - expect(status.params['text']).to eq 'Hi future!' - expect(status.params['media_ids']).to eq [media.id] + expect(status) + .to be_a(ScheduledStatus) + .and have_attributes( + scheduled_at: eq(future), + params: include( + 'text' => eq('Hi future!'), + 'media_ids' => contain_exactly(media.id) + ) + ) expect(media.reload.status).to be_nil expect(Status.where(text: 'Hi future!')).to_not exist end - it 'does not change statuses count' do - expect { subject.call(account, text: 'Hi future!', scheduled_at: future, thread: previous_status) }.to_not(change { [account.statuses_count, previous_status.replies_count] }) + it 'does not change statuses_count of account or replies_count of thread previous status' do + expect { subject.call(account, text: 'Hi future!', scheduled_at: future, thread: previous_status) } + .to not_change { account.statuses_count } + .and(not_change { previous_status.replies_count }) end end From a9f9b0097bc18b87c7fe6636a74ea135bab61dc0 Mon Sep 17 00:00:00 2001 From: Matt Jankowski Date: Fri, 16 Feb 2024 02:52:57 -0500 Subject: [PATCH 24/37] Reduce `RSpec/MultipleExpectations` in captcha feature spec (#29226) --- spec/features/captcha_spec.rb | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) diff --git a/spec/features/captcha_spec.rb b/spec/features/captcha_spec.rb index 15c37eb46..06c823adf 100644 --- a/spec/features/captcha_spec.rb +++ b/spec/features/captcha_spec.rb @@ -19,12 +19,10 @@ describe 'email confirmation flow when captcha is enabled' do # It presents the user with a captcha form expect(page).to have_title(I18n.t('auth.captcha_confirmation.title')) - # It does not confirm the user just yet - expect(user.reload.confirmed?).to be false - # It redirects to app and confirms user - click_on I18n.t('challenge.confirm') - expect(user.reload.confirmed?).to be true + expect { click_on I18n.t('challenge.confirm') } + .to change { user.reload.confirmed? }.from(false).to(true) + expect(page).to have_current_path(/\A#{client_app.confirmation_redirect_uri}/, url: true) # Browsers will generally reload the original page upon redirection @@ -32,8 +30,9 @@ describe 'email confirmation flow when captcha is enabled' do visit "/auth/confirmation?confirmation_token=#{user.confirmation_token}&redirect_to_app=true" # It presents a page with a link to the app callback - expect(page).to have_content(I18n.t('auth.confirmations.registration_complete', domain: 'cb6e6126.ngrok.io')) - expect(page).to have_link(I18n.t('auth.confirmations.clicking_this_link'), href: client_app.confirmation_redirect_uri) + expect(page) + .to have_content(I18n.t('auth.confirmations.registration_complete', domain: 'cb6e6126.ngrok.io')) + .and have_link(I18n.t('auth.confirmations.clicking_this_link'), href: client_app.confirmation_redirect_uri) end end From a8ee6fdd62a85cc8ad20007783000682110a8f0d Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Fri, 16 Feb 2024 09:12:10 +0100 Subject: [PATCH 25/37] Update dependency pg to v1.5.5 (#29230) 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 00ca4663a..0b53df82e 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -505,7 +505,7 @@ GEM parslet (2.0.0) pastel (0.8.0) tty-color (~> 0.5) - pg (1.5.4) + pg (1.5.5) pghero (3.4.1) activerecord (>= 6) posix-spawn (0.3.15) From 9fee5e852669e26f970e278021302e1a203fc022 Mon Sep 17 00:00:00 2001 From: Claire Date: Fri, 16 Feb 2024 11:56:12 +0100 Subject: [PATCH 26/37] Merge pull request from GHSA-jhrq-qvrm-qr36 * Fix insufficient Content-Type checking of fetched ActivityStreams objects * Allow JSON-LD documents with multiple profiles --- app/helpers/jsonld_helper.rb | 14 +++++++++++++- app/services/fetch_resource_service.rb | 2 +- spec/helpers/json_ld_helper_spec.rb | 14 +++++++------- spec/lib/activitypub/activity/announce_spec.rb | 4 ++-- .../fetch_featured_collection_service_spec.rb | 18 +++++++++--------- ...ch_featured_tags_collection_service_spec.rb | 8 ++++---- .../fetch_remote_account_service_spec.rb | 10 +++++----- .../fetch_remote_actor_service_spec.rb | 10 +++++----- .../fetch_remote_key_service_spec.rb | 8 ++++---- .../activitypub/fetch_replies_service_spec.rb | 6 +++--- .../synchronize_followers_service_spec.rb | 6 +++--- .../activitypub/fetch_replies_worker_spec.rb | 2 +- 12 files changed, 57 insertions(+), 45 deletions(-) diff --git a/app/helpers/jsonld_helper.rb b/app/helpers/jsonld_helper.rb index cc05b7a40..b0f2077db 100644 --- a/app/helpers/jsonld_helper.rb +++ b/app/helpers/jsonld_helper.rb @@ -174,7 +174,19 @@ module JsonLdHelper build_request(uri, on_behalf_of, options: request_options).perform do |response| raise Mastodon::UnexpectedResponseError, response unless response_successful?(response) || response_error_unsalvageable?(response) || !raise_on_temporary_error - body_to_json(response.body_with_limit) if response.code == 200 + body_to_json(response.body_with_limit) if response.code == 200 && valid_activitypub_content_type?(response) + end + end + + def valid_activitypub_content_type?(response) + return true if response.mime_type == 'application/activity+json' + + # When the mime type is `application/ld+json`, we need to check the profile, + # but `http.rb` does not parse it for us. + return false unless response.mime_type == 'application/ld+json' + + response.headers[HTTP::Headers::CONTENT_TYPE]&.split(';')&.map(&:strip)&.any? do |str| + str.start_with?('profile="') && str[9...-1].split.include?('https://www.w3.org/ns/activitystreams') end end diff --git a/app/services/fetch_resource_service.rb b/app/services/fetch_resource_service.rb index 71c6cca79..84c36f6a1 100644 --- a/app/services/fetch_resource_service.rb +++ b/app/services/fetch_resource_service.rb @@ -44,7 +44,7 @@ class FetchResourceService < BaseService @response_code = response.code return nil if response.code != 200 - if ['application/activity+json', 'application/ld+json'].include?(response.mime_type) + if valid_activitypub_content_type?(response) body = response.body_with_limit json = body_to_json(body) diff --git a/spec/helpers/json_ld_helper_spec.rb b/spec/helpers/json_ld_helper_spec.rb index 99857278a..485508502 100644 --- a/spec/helpers/json_ld_helper_spec.rb +++ b/spec/helpers/json_ld_helper_spec.rb @@ -56,15 +56,15 @@ describe JsonLdHelper do describe '#fetch_resource' do context 'when the second argument is false' do it 'returns resource even if the retrieved ID and the given URI does not match' do - stub_request(:get, 'https://bob.test/').to_return body: '{"id": "https://alice.test/"}' - stub_request(:get, 'https://alice.test/').to_return body: '{"id": "https://alice.test/"}' + stub_request(:get, 'https://bob.test/').to_return(body: '{"id": "https://alice.test/"}', headers: { 'Content-Type': 'application/activity+json' }) + stub_request(:get, 'https://alice.test/').to_return(body: '{"id": "https://alice.test/"}', headers: { 'Content-Type': 'application/activity+json' }) expect(fetch_resource('https://bob.test/', false)).to eq({ 'id' => 'https://alice.test/' }) end it 'returns nil if the object identified by the given URI and the object identified by the retrieved ID does not match' do - stub_request(:get, 'https://mallory.test/').to_return body: '{"id": "https://marvin.test/"}' - stub_request(:get, 'https://marvin.test/').to_return body: '{"id": "https://alice.test/"}' + stub_request(:get, 'https://mallory.test/').to_return(body: '{"id": "https://marvin.test/"}', headers: { 'Content-Type': 'application/activity+json' }) + stub_request(:get, 'https://marvin.test/').to_return(body: '{"id": "https://alice.test/"}', headers: { 'Content-Type': 'application/activity+json' }) expect(fetch_resource('https://mallory.test/', false)).to be_nil end @@ -72,7 +72,7 @@ describe JsonLdHelper do context 'when the second argument is true' do it 'returns nil if the retrieved ID and the given URI does not match' do - stub_request(:get, 'https://mallory.test/').to_return body: '{"id": "https://alice.test/"}' + stub_request(:get, 'https://mallory.test/').to_return(body: '{"id": "https://alice.test/"}', headers: { 'Content-Type': 'application/activity+json' }) expect(fetch_resource('https://mallory.test/', true)).to be_nil end end @@ -80,12 +80,12 @@ describe JsonLdHelper do describe '#fetch_resource_without_id_validation' do it 'returns nil if the status code is not 200' do - stub_request(:get, 'https://host.test/').to_return status: 400, body: '{}' + stub_request(:get, 'https://host.test/').to_return(status: 400, body: '{}', headers: { 'Content-Type': 'application/activity+json' }) expect(fetch_resource_without_id_validation('https://host.test/')).to be_nil end it 'returns hash' do - stub_request(:get, 'https://host.test/').to_return status: 200, body: '{}' + stub_request(:get, 'https://host.test/').to_return(status: 200, body: '{}', headers: { 'Content-Type': 'application/activity+json' }) expect(fetch_resource_without_id_validation('https://host.test/')).to eq({}) end end diff --git a/spec/lib/activitypub/activity/announce_spec.rb b/spec/lib/activitypub/activity/announce_spec.rb index 8ad892975..b556bfd6c 100644 --- a/spec/lib/activitypub/activity/announce_spec.rb +++ b/spec/lib/activitypub/activity/announce_spec.rb @@ -35,7 +35,7 @@ RSpec.describe ActivityPub::Activity::Announce do context 'when sender is followed by a local account' do before do Fabricate(:account).follow!(sender) - stub_request(:get, 'https://example.com/actor/hello-world').to_return(body: Oj.dump(unknown_object_json)) + stub_request(:get, 'https://example.com/actor/hello-world').to_return(body: Oj.dump(unknown_object_json), headers: { 'Content-Type': 'application/activity+json' }) subject.perform end @@ -120,7 +120,7 @@ RSpec.describe ActivityPub::Activity::Announce do let(:object_json) { 'https://example.com/actor/hello-world' } before do - stub_request(:get, 'https://example.com/actor/hello-world').to_return(body: Oj.dump(unknown_object_json)) + stub_request(:get, 'https://example.com/actor/hello-world').to_return(body: Oj.dump(unknown_object_json), headers: { 'Content-Type': 'application/activity+json' }) end context 'when the relay is enabled' do diff --git a/spec/services/activitypub/fetch_featured_collection_service_spec.rb b/spec/services/activitypub/fetch_featured_collection_service_spec.rb index b9e95b825..dab204406 100644 --- a/spec/services/activitypub/fetch_featured_collection_service_spec.rb +++ b/spec/services/activitypub/fetch_featured_collection_service_spec.rb @@ -72,11 +72,11 @@ RSpec.describe ActivityPub::FetchFeaturedCollectionService, type: :service do shared_examples 'sets pinned posts' do before do - stub_request(:get, 'https://example.com/account/pinned/known').to_return(status: 200, body: Oj.dump(status_json_pinned_known)) - stub_request(:get, 'https://example.com/account/pinned/unknown-inlined').to_return(status: 200, body: Oj.dump(status_json_pinned_unknown_inlined)) + stub_request(:get, 'https://example.com/account/pinned/known').to_return(status: 200, body: Oj.dump(status_json_pinned_known), headers: { 'Content-Type': 'application/activity+json' }) + stub_request(:get, 'https://example.com/account/pinned/unknown-inlined').to_return(status: 200, body: Oj.dump(status_json_pinned_unknown_inlined), headers: { 'Content-Type': 'application/activity+json' }) stub_request(:get, 'https://example.com/account/pinned/unknown-unreachable').to_return(status: 404) - stub_request(:get, 'https://example.com/account/pinned/unknown-reachable').to_return(status: 200, body: Oj.dump(status_json_pinned_unknown_reachable)) - stub_request(:get, 'https://example.com/account/collections/featured').to_return(status: 200, body: Oj.dump(featured_with_null)) + stub_request(:get, 'https://example.com/account/pinned/unknown-reachable').to_return(status: 200, body: Oj.dump(status_json_pinned_unknown_reachable), headers: { 'Content-Type': 'application/activity+json' }) + stub_request(:get, 'https://example.com/account/collections/featured').to_return(status: 200, body: Oj.dump(featured_with_null), headers: { 'Content-Type': 'application/activity+json' }) subject.call(actor, note: true, hashtag: false) end @@ -94,7 +94,7 @@ RSpec.describe ActivityPub::FetchFeaturedCollectionService, type: :service do describe '#call' do context 'when the endpoint is a Collection' do before do - stub_request(:get, actor.featured_collection_url).to_return(status: 200, body: Oj.dump(payload)) + stub_request(:get, actor.featured_collection_url).to_return(status: 200, body: Oj.dump(payload), headers: { 'Content-Type': 'application/activity+json' }) end it_behaves_like 'sets pinned posts' @@ -111,7 +111,7 @@ RSpec.describe ActivityPub::FetchFeaturedCollectionService, type: :service do end before do - stub_request(:get, actor.featured_collection_url).to_return(status: 200, body: Oj.dump(payload)) + stub_request(:get, actor.featured_collection_url).to_return(status: 200, body: Oj.dump(payload), headers: { 'Content-Type': 'application/activity+json' }) end it_behaves_like 'sets pinned posts' @@ -120,7 +120,7 @@ RSpec.describe ActivityPub::FetchFeaturedCollectionService, type: :service do let(:items) { 'https://example.com/account/pinned/unknown-reachable' } before do - stub_request(:get, 'https://example.com/account/pinned/unknown-reachable').to_return(status: 200, body: Oj.dump(status_json_pinned_unknown_reachable)) + stub_request(:get, 'https://example.com/account/pinned/unknown-reachable').to_return(status: 200, body: Oj.dump(status_json_pinned_unknown_reachable), headers: { 'Content-Type': 'application/activity+json' }) subject.call(actor, note: true, hashtag: false) end @@ -147,7 +147,7 @@ RSpec.describe ActivityPub::FetchFeaturedCollectionService, type: :service do end before do - stub_request(:get, actor.featured_collection_url).to_return(status: 200, body: Oj.dump(payload)) + stub_request(:get, actor.featured_collection_url).to_return(status: 200, body: Oj.dump(payload), headers: { 'Content-Type': 'application/activity+json' }) end it_behaves_like 'sets pinned posts' @@ -156,7 +156,7 @@ RSpec.describe ActivityPub::FetchFeaturedCollectionService, type: :service do let(:items) { 'https://example.com/account/pinned/unknown-reachable' } before do - stub_request(:get, 'https://example.com/account/pinned/unknown-reachable').to_return(status: 200, body: Oj.dump(status_json_pinned_unknown_reachable)) + stub_request(:get, 'https://example.com/account/pinned/unknown-reachable').to_return(status: 200, body: Oj.dump(status_json_pinned_unknown_reachable), headers: { 'Content-Type': 'application/activity+json' }) subject.call(actor, note: true, hashtag: false) end diff --git a/spec/services/activitypub/fetch_featured_tags_collection_service_spec.rb b/spec/services/activitypub/fetch_featured_tags_collection_service_spec.rb index 071e4d92d..638278a10 100644 --- a/spec/services/activitypub/fetch_featured_tags_collection_service_spec.rb +++ b/spec/services/activitypub/fetch_featured_tags_collection_service_spec.rb @@ -38,7 +38,7 @@ RSpec.describe ActivityPub::FetchFeaturedTagsCollectionService, type: :service d describe '#call' do context 'when the endpoint is a Collection' do before do - stub_request(:get, collection_url).to_return(status: 200, body: Oj.dump(payload)) + stub_request(:get, collection_url).to_return(status: 200, body: Oj.dump(payload), headers: { 'Content-Type': 'application/activity+json' }) end it_behaves_like 'sets featured tags' @@ -46,7 +46,7 @@ RSpec.describe ActivityPub::FetchFeaturedTagsCollectionService, type: :service d context 'when the account already has featured tags' do before do - stub_request(:get, collection_url).to_return(status: 200, body: Oj.dump(payload)) + stub_request(:get, collection_url).to_return(status: 200, body: Oj.dump(payload), headers: { 'Content-Type': 'application/activity+json' }) actor.featured_tags.create!(name: 'FoO') actor.featured_tags.create!(name: 'baz') @@ -67,7 +67,7 @@ RSpec.describe ActivityPub::FetchFeaturedTagsCollectionService, type: :service d end before do - stub_request(:get, collection_url).to_return(status: 200, body: Oj.dump(payload)) + stub_request(:get, collection_url).to_return(status: 200, body: Oj.dump(payload), headers: { 'Content-Type': 'application/activity+json' }) end it_behaves_like 'sets featured tags' @@ -88,7 +88,7 @@ RSpec.describe ActivityPub::FetchFeaturedTagsCollectionService, type: :service d end before do - stub_request(:get, collection_url).to_return(status: 200, body: Oj.dump(payload)) + stub_request(:get, collection_url).to_return(status: 200, body: Oj.dump(payload), headers: { 'Content-Type': 'application/activity+json' }) end it_behaves_like 'sets featured tags' diff --git a/spec/services/activitypub/fetch_remote_account_service_spec.rb b/spec/services/activitypub/fetch_remote_account_service_spec.rb index e7f6bb8dd..799a70d09 100644 --- a/spec/services/activitypub/fetch_remote_account_service_spec.rb +++ b/spec/services/activitypub/fetch_remote_account_service_spec.rb @@ -38,7 +38,7 @@ RSpec.describe ActivityPub::FetchRemoteAccountService, type: :service do before do actor[:inbox] = nil - stub_request(:get, 'https://example.com/alice').to_return(body: Oj.dump(actor)) + stub_request(:get, 'https://example.com/alice').to_return(body: Oj.dump(actor), headers: { 'Content-Type': 'application/activity+json' }) stub_request(:get, 'https://example.com/.well-known/webfinger?resource=acct:alice@example.com').to_return(body: Oj.dump(webfinger), headers: { 'Content-Type': 'application/jrd+json' }) end @@ -54,7 +54,7 @@ RSpec.describe ActivityPub::FetchRemoteAccountService, type: :service do let!(:webfinger) { { subject: 'acct:alice@example.com', links: [{ rel: 'self', href: 'https://example.com/alice' }] } } before do - stub_request(:get, 'https://example.com/alice').to_return(body: Oj.dump(actor)) + stub_request(:get, 'https://example.com/alice').to_return(body: Oj.dump(actor), headers: { 'Content-Type': 'application/activity+json' }) stub_request(:get, 'https://example.com/.well-known/webfinger?resource=acct:alice@example.com').to_return(body: Oj.dump(webfinger), headers: { 'Content-Type': 'application/jrd+json' }) end @@ -75,7 +75,7 @@ RSpec.describe ActivityPub::FetchRemoteAccountService, type: :service do let!(:webfinger) { { subject: 'acct:alice@iscool.af', links: [{ rel: 'self', href: 'https://example.com/alice' }] } } before do - stub_request(:get, 'https://example.com/alice').to_return(body: Oj.dump(actor)) + stub_request(:get, 'https://example.com/alice').to_return(body: Oj.dump(actor), headers: { 'Content-Type': 'application/activity+json' }) stub_request(:get, 'https://example.com/.well-known/webfinger?resource=acct:alice@example.com').to_return(body: Oj.dump(webfinger), headers: { 'Content-Type': 'application/jrd+json' }) stub_request(:get, 'https://iscool.af/.well-known/webfinger?resource=acct:alice@iscool.af').to_return(body: Oj.dump(webfinger), headers: { 'Content-Type': 'application/jrd+json' }) end @@ -98,7 +98,7 @@ RSpec.describe ActivityPub::FetchRemoteAccountService, type: :service do let!(:webfinger) { { subject: 'acct:alice@example.com', links: [{ rel: 'self', href: 'https://example.com/bob' }] } } before do - stub_request(:get, 'https://example.com/alice').to_return(body: Oj.dump(actor)) + stub_request(:get, 'https://example.com/alice').to_return(body: Oj.dump(actor), headers: { 'Content-Type': 'application/activity+json' }) stub_request(:get, 'https://example.com/.well-known/webfinger?resource=acct:alice@example.com').to_return(body: Oj.dump(webfinger), headers: { 'Content-Type': 'application/jrd+json' }) end @@ -114,7 +114,7 @@ RSpec.describe ActivityPub::FetchRemoteAccountService, type: :service do let!(:webfinger) { { subject: 'acct:alice@iscool.af', links: [{ rel: 'self', href: 'https://example.com/bob' }] } } before do - stub_request(:get, 'https://example.com/alice').to_return(body: Oj.dump(actor)) + stub_request(:get, 'https://example.com/alice').to_return(body: Oj.dump(actor), headers: { 'Content-Type': 'application/activity+json' }) stub_request(:get, 'https://example.com/.well-known/webfinger?resource=acct:alice@example.com').to_return(body: Oj.dump(webfinger), headers: { 'Content-Type': 'application/jrd+json' }) stub_request(:get, 'https://iscool.af/.well-known/webfinger?resource=acct:alice@iscool.af').to_return(body: Oj.dump(webfinger), headers: { 'Content-Type': 'application/jrd+json' }) end diff --git a/spec/services/activitypub/fetch_remote_actor_service_spec.rb b/spec/services/activitypub/fetch_remote_actor_service_spec.rb index e622c7d4c..4ce42ea56 100644 --- a/spec/services/activitypub/fetch_remote_actor_service_spec.rb +++ b/spec/services/activitypub/fetch_remote_actor_service_spec.rb @@ -38,7 +38,7 @@ RSpec.describe ActivityPub::FetchRemoteActorService, type: :service do before do actor[:inbox] = nil - stub_request(:get, 'https://example.com/alice').to_return(body: Oj.dump(actor)) + stub_request(:get, 'https://example.com/alice').to_return(body: Oj.dump(actor), headers: { 'Content-Type': 'application/activity+json' }) stub_request(:get, 'https://example.com/.well-known/webfinger?resource=acct:alice@example.com').to_return(body: Oj.dump(webfinger), headers: { 'Content-Type': 'application/jrd+json' }) end @@ -54,7 +54,7 @@ RSpec.describe ActivityPub::FetchRemoteActorService, type: :service do let!(:webfinger) { { subject: 'acct:alice@example.com', links: [{ rel: 'self', href: 'https://example.com/alice' }] } } before do - stub_request(:get, 'https://example.com/alice').to_return(body: Oj.dump(actor)) + stub_request(:get, 'https://example.com/alice').to_return(body: Oj.dump(actor), headers: { 'Content-Type': 'application/activity+json' }) stub_request(:get, 'https://example.com/.well-known/webfinger?resource=acct:alice@example.com').to_return(body: Oj.dump(webfinger), headers: { 'Content-Type': 'application/jrd+json' }) end @@ -75,7 +75,7 @@ RSpec.describe ActivityPub::FetchRemoteActorService, type: :service do let!(:webfinger) { { subject: 'acct:alice@iscool.af', links: [{ rel: 'self', href: 'https://example.com/alice' }] } } before do - stub_request(:get, 'https://example.com/alice').to_return(body: Oj.dump(actor)) + stub_request(:get, 'https://example.com/alice').to_return(body: Oj.dump(actor), headers: { 'Content-Type': 'application/activity+json' }) stub_request(:get, 'https://example.com/.well-known/webfinger?resource=acct:alice@example.com').to_return(body: Oj.dump(webfinger), headers: { 'Content-Type': 'application/jrd+json' }) stub_request(:get, 'https://iscool.af/.well-known/webfinger?resource=acct:alice@iscool.af').to_return(body: Oj.dump(webfinger), headers: { 'Content-Type': 'application/jrd+json' }) end @@ -98,7 +98,7 @@ RSpec.describe ActivityPub::FetchRemoteActorService, type: :service do let!(:webfinger) { { subject: 'acct:alice@example.com', links: [{ rel: 'self', href: 'https://example.com/bob' }] } } before do - stub_request(:get, 'https://example.com/alice').to_return(body: Oj.dump(actor)) + stub_request(:get, 'https://example.com/alice').to_return(body: Oj.dump(actor), headers: { 'Content-Type': 'application/activity+json' }) stub_request(:get, 'https://example.com/.well-known/webfinger?resource=acct:alice@example.com').to_return(body: Oj.dump(webfinger), headers: { 'Content-Type': 'application/jrd+json' }) end @@ -114,7 +114,7 @@ RSpec.describe ActivityPub::FetchRemoteActorService, type: :service do let!(:webfinger) { { subject: 'acct:alice@iscool.af', links: [{ rel: 'self', href: 'https://example.com/bob' }] } } before do - stub_request(:get, 'https://example.com/alice').to_return(body: Oj.dump(actor)) + stub_request(:get, 'https://example.com/alice').to_return(body: Oj.dump(actor), headers: { 'Content-Type': 'application/activity+json' }) stub_request(:get, 'https://example.com/.well-known/webfinger?resource=acct:alice@example.com').to_return(body: Oj.dump(webfinger), headers: { 'Content-Type': 'application/jrd+json' }) stub_request(:get, 'https://iscool.af/.well-known/webfinger?resource=acct:alice@iscool.af').to_return(body: Oj.dump(webfinger), headers: { 'Content-Type': 'application/jrd+json' }) end diff --git a/spec/services/activitypub/fetch_remote_key_service_spec.rb b/spec/services/activitypub/fetch_remote_key_service_spec.rb index 0b14da4f4..478778cc9 100644 --- a/spec/services/activitypub/fetch_remote_key_service_spec.rb +++ b/spec/services/activitypub/fetch_remote_key_service_spec.rb @@ -50,7 +50,7 @@ RSpec.describe ActivityPub::FetchRemoteKeyService, type: :service do end before do - stub_request(:get, 'https://example.com/alice').to_return(body: Oj.dump(actor)) + stub_request(:get, 'https://example.com/alice').to_return(body: Oj.dump(actor), headers: { 'Content-Type': 'application/activity+json' }) stub_request(:get, 'https://example.com/.well-known/webfinger?resource=acct:alice@example.com').to_return(body: Oj.dump(webfinger), headers: { 'Content-Type': 'application/jrd+json' }) end @@ -59,7 +59,7 @@ RSpec.describe ActivityPub::FetchRemoteKeyService, type: :service do context 'when the key is a sub-object from the actor' do before do - stub_request(:get, public_key_id).to_return(body: Oj.dump(actor)) + stub_request(:get, public_key_id).to_return(body: Oj.dump(actor), headers: { 'Content-Type': 'application/activity+json' }) end it 'returns the expected account' do @@ -71,7 +71,7 @@ RSpec.describe ActivityPub::FetchRemoteKeyService, type: :service do let(:public_key_id) { 'https://example.com/alice-public-key.json' } before do - stub_request(:get, public_key_id).to_return(body: Oj.dump(key_json.merge({ '@context': ['https://www.w3.org/ns/activitystreams', 'https://w3id.org/security/v1'] }))) + stub_request(:get, public_key_id).to_return(body: Oj.dump(key_json.merge({ '@context': ['https://www.w3.org/ns/activitystreams', 'https://w3id.org/security/v1'] })), headers: { 'Content-Type': 'application/activity+json' }) end it 'returns the expected account' do @@ -84,7 +84,7 @@ RSpec.describe ActivityPub::FetchRemoteKeyService, type: :service do let(:actor_public_key) { 'https://example.com/alice-public-key.json' } before do - stub_request(:get, public_key_id).to_return(body: Oj.dump(key_json.merge({ '@context': ['https://www.w3.org/ns/activitystreams', 'https://w3id.org/security/v1'] }))) + stub_request(:get, public_key_id).to_return(body: Oj.dump(key_json.merge({ '@context': ['https://www.w3.org/ns/activitystreams', 'https://w3id.org/security/v1'] })), headers: { 'Content-Type': 'application/activity+json' }) end it 'returns the nil' do diff --git a/spec/services/activitypub/fetch_replies_service_spec.rb b/spec/services/activitypub/fetch_replies_service_spec.rb index a76b996c2..8e1f606e2 100644 --- a/spec/services/activitypub/fetch_replies_service_spec.rb +++ b/spec/services/activitypub/fetch_replies_service_spec.rb @@ -58,7 +58,7 @@ RSpec.describe ActivityPub::FetchRepliesService, type: :service do context 'when passing the URL to the collection' do before do - stub_request(:get, collection_uri).to_return(status: 200, body: Oj.dump(payload)) + stub_request(:get, collection_uri).to_return(status: 200, body: Oj.dump(payload), headers: { 'Content-Type': 'application/activity+json' }) end it 'spawns workers for up to 5 replies on the same server' do @@ -93,7 +93,7 @@ RSpec.describe ActivityPub::FetchRepliesService, type: :service do context 'when passing the URL to the collection' do before do - stub_request(:get, collection_uri).to_return(status: 200, body: Oj.dump(payload)) + stub_request(:get, collection_uri).to_return(status: 200, body: Oj.dump(payload), headers: { 'Content-Type': 'application/activity+json' }) end it 'spawns workers for up to 5 replies on the same server' do @@ -132,7 +132,7 @@ RSpec.describe ActivityPub::FetchRepliesService, type: :service do context 'when passing the URL to the collection' do before do - stub_request(:get, collection_uri).to_return(status: 200, body: Oj.dump(payload)) + stub_request(:get, collection_uri).to_return(status: 200, body: Oj.dump(payload), headers: { 'Content-Type': 'application/activity+json' }) end it 'spawns workers for up to 5 replies on the same server' do diff --git a/spec/services/activitypub/synchronize_followers_service_spec.rb b/spec/services/activitypub/synchronize_followers_service_spec.rb index c9a513e24..f62376ab9 100644 --- a/spec/services/activitypub/synchronize_followers_service_spec.rb +++ b/spec/services/activitypub/synchronize_followers_service_spec.rb @@ -60,7 +60,7 @@ RSpec.describe ActivityPub::SynchronizeFollowersService, type: :service do describe '#call' do context 'when the endpoint is a Collection of actor URIs' do before do - stub_request(:get, collection_uri).to_return(status: 200, body: Oj.dump(payload)) + stub_request(:get, collection_uri).to_return(status: 200, body: Oj.dump(payload), headers: { 'Content-Type': 'application/activity+json' }) end it_behaves_like 'synchronizes followers' @@ -77,7 +77,7 @@ RSpec.describe ActivityPub::SynchronizeFollowersService, type: :service do end before do - stub_request(:get, collection_uri).to_return(status: 200, body: Oj.dump(payload)) + stub_request(:get, collection_uri).to_return(status: 200, body: Oj.dump(payload), headers: { 'Content-Type': 'application/activity+json' }) end it_behaves_like 'synchronizes followers' @@ -98,7 +98,7 @@ RSpec.describe ActivityPub::SynchronizeFollowersService, type: :service do end before do - stub_request(:get, collection_uri).to_return(status: 200, body: Oj.dump(payload)) + stub_request(:get, collection_uri).to_return(status: 200, body: Oj.dump(payload), headers: { 'Content-Type': 'application/activity+json' }) end it_behaves_like 'synchronizes followers' diff --git a/spec/workers/activitypub/fetch_replies_worker_spec.rb b/spec/workers/activitypub/fetch_replies_worker_spec.rb index ff4d049a2..2d080e286 100644 --- a/spec/workers/activitypub/fetch_replies_worker_spec.rb +++ b/spec/workers/activitypub/fetch_replies_worker_spec.rb @@ -21,7 +21,7 @@ describe ActivityPub::FetchRepliesWorker do describe 'perform' do it 'performs a request if the collection URI is from the same host' do - stub_request(:get, 'https://example.com/statuses_replies/1').to_return(status: 200, body: json) + stub_request(:get, 'https://example.com/statuses_replies/1').to_return(status: 200, body: json, headers: { 'Content-Type': 'application/activity+json' }) subject.perform(status.id, 'https://example.com/statuses_replies/1') expect(a_request(:get, 'https://example.com/statuses_replies/1')).to have_been_made.once end From 5f21a1f5a3492a212a25235086e620799d47f1c9 Mon Sep 17 00:00:00 2001 From: Claire Date: Fri, 16 Feb 2024 12:06:47 +0100 Subject: [PATCH 27/37] Bump version to v4.3.0-alpha.3 (#29241) --- CHANGELOG.md | 95 +++++++++++++++++++++++++++++++++++++++++ docker-compose.yml | 6 +-- lib/mastodon/version.rb | 2 +- 3 files changed, 99 insertions(+), 4 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 6f775fcfa..a53790afa 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,101 @@ All notable changes to this project will be documented in this file. +## [4.2.7] - 2024-02-16 + +### Fixed + +- Fix OmniAuth tests and edge cases in error handling ([ClearlyClaire](https://github.com/mastodon/mastodon/pull/29201), [ClearlyClaire](https://github.com/mastodon/mastodon/pull/29207)) +- Fix new installs by upgrading to the latest release of the `nsa` gem, instead of a no longer existing commit ([mjankowski](https://github.com/mastodon/mastodon/pull/29065)) + +### Security + +- Fix insufficient checking of remote posts ([GHSA-jhrq-qvrm-qr36](https://github.com/mastodon/mastodon/security/advisories/GHSA-jhrq-qvrm-qr36)) + +## [4.2.6] - 2024-02-14 + +### Security + +- Update the `sidekiq-unique-jobs` dependency (see [GHSA-cmh9-rx85-xj38](https://github.com/mhenrixon/sidekiq-unique-jobs/security/advisories/GHSA-cmh9-rx85-xj38)) + In addition, we have disabled the web interface for `sidekiq-unique-jobs` out of caution. + If you need it, you can re-enable it by setting `ENABLE_SIDEKIQ_UNIQUE_JOBS_UI=true`. + If you only need to clear all locks, you can now use `bundle exec rake sidekiq_unique_jobs:delete_all_locks`. +- Update the `nokogiri` dependency (see [GHSA-xc9x-jj77-9p9j](https://github.com/sparklemotion/nokogiri/security/advisories/GHSA-xc9x-jj77-9p9j)) +- Disable administrative Doorkeeper routes ([ThisIsMissEm](https://github.com/mastodon/mastodon/pull/29187)) +- Fix ongoing streaming sessions not being invalidated when applications get deleted in some cases ([GHSA-7w3c-p9j8-mq3x](https://github.com/mastodon/mastodon/security/advisories/GHSA-7w3c-p9j8-mq3x)) + In some rare cases, the streaming server was not notified of access tokens revocation on application deletion. +- Change external authentication behavior to never reattach a new identity to an existing user by default ([GHSA-vm39-j3vx-pch3](https://github.com/mastodon/mastodon/security/advisories/GHSA-vm39-j3vx-pch3)) + Up until now, Mastodon has allowed new identities from external authentication providers to attach to an existing local user based on their verified e-mail address. + This allowed upgrading users from a database-stored password to an external authentication provider, or move from one authentication provider to another. + However, this behavior may be unexpected, and means that when multiple authentication providers are configured, the overall security would be that of the least secure authentication provider. + For these reasons, this behavior is now locked under the `ALLOW_UNSAFE_AUTH_PROVIDER_REATTACH` environment variable. + In addition, regardless of this environment variable, Mastodon will refuse to attach two identities from the same authentication provider to the same account. + +## [4.2.5] - 2024-02-01 + +### Security + +- Fix insufficient origin validation (CVE-2024-23832, [GHSA-3fjr-858r-92rw](https://github.com/mastodon/mastodon/security/advisories/GHSA-3fjr-858r-92rw)) + +## [4.2.4] - 2024-01-24 + +### Fixed + +- Fix error when processing remote files with unusually long names ([ClearlyClaire](https://github.com/mastodon/mastodon/pull/28823)) +- Fix processing of compacted single-item JSON-LD collections ([ClearlyClaire](https://github.com/mastodon/mastodon/pull/28816)) +- Retry 401 errors on replies fetching ([ShadowJonathan](https://github.com/mastodon/mastodon/pull/28788)) +- Fix `RecordNotUnique` errors in LinkCrawlWorker ([tribela](https://github.com/mastodon/mastodon/pull/28748)) +- Fix Mastodon not correctly processing HTTP Signatures with query strings ([ClearlyClaire](https://github.com/mastodon/mastodon/pull/28443), [ClearlyClaire](https://github.com/mastodon/mastodon/pull/28476)) +- Fix potential redirection loop of streaming endpoint ([ClearlyClaire](https://github.com/mastodon/mastodon/pull/28665)) +- Fix streaming API redirection ignoring the port of `streaming_api_base_url` ([ClearlyClaire](https://github.com/mastodon/mastodon/pull/28558)) +- Fix error when processing link preview with an array as `inLanguage` ([ClearlyClaire](https://github.com/mastodon/mastodon/pull/28252)) +- Fix unsupported time zone or locale preventing sign-up ([Gargron](https://github.com/mastodon/mastodon/pull/28035)) +- Fix "Hide these posts from home" list setting not refreshing when switching lists ([brianholley](https://github.com/mastodon/mastodon/pull/27763)) +- Fix missing background behind dismissable banner in web UI ([Gargron](https://github.com/mastodon/mastodon/pull/27479)) +- Fix line wrapping of language selection button with long locale codes ([gunchleoc](https://github.com/mastodon/mastodon/pull/27100), [ClearlyClaire](https://github.com/mastodon/mastodon/pull/27127)) +- Fix `Undo Announce` activity not being sent to non-follower authors ([MitarashiDango](https://github.com/mastodon/mastodon/pull/18482)) +- Fix N+1s because of association preloaders not actually getting called ([ClearlyClaire](https://github.com/mastodon/mastodon/pull/28339)) +- Fix empty column explainer getting cropped under certain conditions ([ClearlyClaire](https://github.com/mastodon/mastodon/pull/28337)) +- Fix `LinkCrawlWorker` error when encountering empty OEmbed response ([ClearlyClaire](https://github.com/mastodon/mastodon/pull/28268)) +- Fix call to inefficient `delete_matched` cache method in domain blocks ([ClearlyClaire](https://github.com/mastodon/mastodon/pull/28367)) + +### Security + +- Add rate-limit of TOTP authentication attempts at controller level ([ClearlyClaire](https://github.com/mastodon/mastodon/pull/28801)) + +## [4.2.3] - 2023-12-05 + +### Fixed + +- Fix dependency on `json-canonicalization` version that has been made unavailable since last release + +## [4.2.2] - 2023-12-04 + +### Changed + +- Change dismissed banners to be stored server-side ([ClearlyClaire](https://github.com/mastodon/mastodon/pull/27055)) +- Change GIF max matrix size error to explicitly mention GIF files ([ClearlyClaire](https://github.com/mastodon/mastodon/pull/27927)) +- Change `Follow` activities delivery to bypass availability check ([ShadowJonathan](https://github.com/mastodon/mastodon/pull/27586)) +- Change single-column navigation notice to be displayed outside of the logo container ([renchap](https://github.com/mastodon/mastodon/pull/27462), [renchap](https://github.com/mastodon/mastodon/pull/27476)) +- Change Content-Security-Policy to be tighter on media paths ([ClearlyClaire](https://github.com/mastodon/mastodon/pull/26889)) +- Change post language code to include country code when relevant ([gunchleoc](https://github.com/mastodon/mastodon/pull/27099), [ClearlyClaire](https://github.com/mastodon/mastodon/pull/27207)) + +### Fixed + +- Fix upper border radius of onboarding columns ([ClearlyClaire](https://github.com/mastodon/mastodon/pull/27890)) +- Fix incoming status creation date not being restricted to standard ISO8601 ([ClearlyClaire](https://github.com/mastodon/mastodon/pull/27655), [ClearlyClaire](https://github.com/mastodon/mastodon/pull/28081)) +- Fix some posts from threads received out-of-order sometimes not being inserted into timelines ([ClearlyClaire](https://github.com/mastodon/mastodon/pull/27653)) +- Fix posts from force-sensitized accounts being able to trend ([ClearlyClaire](https://github.com/mastodon/mastodon/pull/27620)) +- Fix error when trying to delete already-deleted file with OpenStack Swift ([ClearlyClaire](https://github.com/mastodon/mastodon/pull/27569)) +- Fix batch attachment deletion when using OpenStack Swift ([ClearlyClaire](https://github.com/mastodon/mastodon/pull/27554)) +- Fix processing LDSigned activities from actors with unknown public keys ([ClearlyClaire](https://github.com/mastodon/mastodon/pull/27474)) +- Fix error and incorrect URLs in `/api/v1/accounts/:id/featured_tags` for remote accounts ([ClearlyClaire](https://github.com/mastodon/mastodon/pull/27459)) +- Fix report processing notice not mentioning the report number when performing a custom action ([ClearlyClaire](https://github.com/mastodon/mastodon/pull/27442)) +- Fix handling of `inLanguage` attribute in preview card processing ([ClearlyClaire](https://github.com/mastodon/mastodon/pull/27423)) +- Fix own posts being removed from home timeline when unfollowing a used hashtag ([kmycode](https://github.com/mastodon/mastodon/pull/27391)) +- Fix some link anchors being recognized as hashtags ([ClearlyClaire](https://github.com/mastodon/mastodon/pull/27271), [ClearlyClaire](https://github.com/mastodon/mastodon/pull/27584)) +- Fix format-dependent redirects being cached regardless of requested format ([ClearlyClaire](https://github.com/mastodon/mastodon/pull/27634)) + ## [4.2.1] - 2023-10-10 ### Added diff --git a/docker-compose.yml b/docker-compose.yml index 93451d961..154754d45 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -56,7 +56,7 @@ services: web: build: . - image: ghcr.io/mastodon/mastodon:v4.2.0 + image: ghcr.io/mastodon/mastodon:v4.2.7 restart: always env_file: .env.production command: bundle exec puma -C config/puma.rb @@ -77,7 +77,7 @@ services: streaming: build: . - image: ghcr.io/mastodon/mastodon:v4.2.0 + image: ghcr.io/mastodon/mastodon:v4.2.7 restart: always env_file: .env.production command: node ./streaming @@ -95,7 +95,7 @@ services: sidekiq: build: . - image: ghcr.io/mastodon/mastodon:v4.2.0 + image: ghcr.io/mastodon/mastodon:v4.2.7 restart: always env_file: .env.production command: bundle exec sidekiq diff --git a/lib/mastodon/version.rb b/lib/mastodon/version.rb index c2f26aee6..1135ba0a1 100644 --- a/lib/mastodon/version.rb +++ b/lib/mastodon/version.rb @@ -17,7 +17,7 @@ module Mastodon end def default_prerelease - 'alpha.2' + 'alpha.3' end def prerelease From e140d05a6a6d679153fe02ac38588aaa4656e464 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Fri, 16 Feb 2024 13:59:51 +0100 Subject: [PATCH 28/37] Update dependency doorkeeper to v5.6.9 (#29196) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- Gemfile.lock | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Gemfile.lock b/Gemfile.lock index 0b53df82e..79d3b1e63 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -219,7 +219,7 @@ GEM docile (1.4.0) domain_name (0.5.20190701) unf (>= 0.0.5, < 1.0.0) - doorkeeper (5.6.8) + doorkeeper (5.6.9) railties (>= 5) dotenv (2.8.1) dotenv-rails (2.8.1) @@ -811,7 +811,7 @@ GEM xorcist (1.1.3) xpath (3.2.0) nokogiri (~> 1.8) - zeitwerk (2.6.12) + zeitwerk (2.6.13) PLATFORMS ruby From bba488c189084d8499173c3e65dcce8e40a5606a Mon Sep 17 00:00:00 2001 From: Matt Jankowski Date: Fri, 16 Feb 2024 08:00:09 -0500 Subject: [PATCH 29/37] Reduce `RSpec/MultipleExpectations` in media_attachment spec (#29228) --- spec/models/media_attachment_spec.rb | 49 ++++++++++++++-------------- 1 file changed, 25 insertions(+), 24 deletions(-) diff --git a/spec/models/media_attachment_spec.rb b/spec/models/media_attachment_spec.rb index 89916f9f5..1b9a13c38 100644 --- a/spec/models/media_attachment_spec.rb +++ b/spec/models/media_attachment_spec.rb @@ -91,20 +91,15 @@ RSpec.describe MediaAttachment, :paperclip_processing do end it 'saves media attachment with correct file metadata' do - expect(media.persisted?).to be true - expect(media.file).to_not be_nil - - # completes processing - expect(media.processing_complete?).to be true - - # sets type - expect(media.type).to eq 'image' - - # sets content type - expect(media.file_content_type).to eq content_type - - # sets file extension - expect(media.file_file_name).to end_with extension + expect(media) + .to be_persisted + .and be_processing_complete + .and have_attributes( + file: be_present, + type: eq('image'), + file_content_type: eq(content_type), + file_file_name: end_with(extension) + ) # Rack::Mime (used by PublicFileServerMiddleware) recognizes file extension expect(Rack::Mime.mime_type(extension, nil)).to eq content_type @@ -112,17 +107,23 @@ RSpec.describe MediaAttachment, :paperclip_processing do it 'saves media attachment with correct size metadata' do # strips original file name - expect(media.file_file_name).to_not start_with '600x400' + expect(media.file_file_name) + .to_not start_with '600x400' - # sets meta for original - expect(media.file.meta['original']['width']).to eq 600 - expect(media.file.meta['original']['height']).to eq 400 - expect(media.file.meta['original']['aspect']).to eq 1.5 - - # sets meta for thumbnail - expect(media.file.meta['small']['width']).to eq 588 - expect(media.file.meta['small']['height']).to eq 392 - expect(media.file.meta['small']['aspect']).to eq 1.5 + # sets meta for original and thumbnail + expect(media.file.meta.deep_symbolize_keys) + .to include( + original: include( + width: eq(600), + height: eq(400), + aspect: eq(1.5) + ), + small: include( + width: eq(588), + height: eq(392), + aspect: eq(1.5) + ) + ) end end From 1690fb39e6e4a26cc5f708626920d3491d7dd95b Mon Sep 17 00:00:00 2001 From: Matt Jankowski Date: Fri, 16 Feb 2024 08:00:11 -0500 Subject: [PATCH 30/37] Reduce `RSpec/MultipleExpectations` in instance_actors_controller spec (#29229) --- .../instance_actors_controller_spec.rb | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) diff --git a/spec/controllers/instance_actors_controller_spec.rb b/spec/controllers/instance_actors_controller_spec.rb index 36b9049fb..be1eefa7b 100644 --- a/spec/controllers/instance_actors_controller_spec.rb +++ b/spec/controllers/instance_actors_controller_spec.rb @@ -13,17 +13,19 @@ RSpec.describe InstanceActorsController do end it 'returns http success with correct media type, headers, and session values' do - expect(response).to have_http_status(200) + expect(response) + .to have_http_status(200) + .and have_attributes( + media_type: eq('application/activity+json'), + cookies: be_empty + ) - expect(response.media_type).to eq 'application/activity+json' - - expect(response.cookies).to be_empty - expect(response.headers['Set-Cookies']).to be_nil + expect(response.headers) + .to include('Cache-Control' => include('public')) + .and not_include('Set-Cookies') expect(session).to be_empty - expect(response.headers['Cache-Control']).to include 'public' - expect(body_as_json) .to include(:id, :type, :preferredUsername, :inbox, :publicKey, :inbox, :outbox, :url) end From 117b507df59b2f302c278797a0ea312aee68d570 Mon Sep 17 00:00:00 2001 From: Matt Jankowski Date: Fri, 16 Feb 2024 08:01:04 -0500 Subject: [PATCH 31/37] Extract `subject` from `User#mark_email_as_confirmed!` spec (#29231) --- spec/models/user_spec.rb | 25 +++++++++++-------------- 1 file changed, 11 insertions(+), 14 deletions(-) diff --git a/spec/models/user_spec.rb b/spec/models/user_spec.rb index 845335e87..1baa3ccbf 100644 --- a/spec/models/user_spec.rb +++ b/spec/models/user_spec.rb @@ -451,35 +451,32 @@ RSpec.describe User do end describe '#mark_email_as_confirmed!' do - subject(:user) { Fabricate(:user, confirmed_at: confirmed_at) } + subject { user.mark_email_as_confirmed! } - before do - ActionMailer::Base.deliveries.clear - user.mark_email_as_confirmed! - end + let!(:user) { Fabricate(:user, confirmed_at: confirmed_at) } + + before { ActionMailer::Base.deliveries.clear } after { ActionMailer::Base.deliveries.clear } context 'when user is new' do let(:confirmed_at) { nil } - it 'confirms user' do - expect(user.confirmed_at).to be_present - end + it 'confirms user and delivers welcome email', :sidekiq_inline do + subject - it 'delivers mails', :sidekiq_inline do - expect(ActionMailer::Base.deliveries.count).to eq 2 + expect(user.confirmed_at).to be_present + expect(ActionMailer::Base.deliveries.count).to eq 1 end end context 'when user is not new' do let(:confirmed_at) { Time.zone.now } - it 'confirms user' do - expect(user.confirmed_at).to be_present - end + it 'confirms user but does not deliver welcome email' do + subject - it 'does not deliver mail' do + expect(user.confirmed_at).to be_present expect(ActionMailer::Base.deliveries.count).to eq 0 end end From a316c0e38de9e0dd5853c1c7a1f8d8b7188fb253 Mon Sep 17 00:00:00 2001 From: Matt Jankowski Date: Fri, 16 Feb 2024 08:01:15 -0500 Subject: [PATCH 32/37] Reduce round trips in disputes/appeals spec (#29232) --- .../disputes/appeals_controller_spec.rb | 22 +++++++------------ 1 file changed, 8 insertions(+), 14 deletions(-) diff --git a/spec/controllers/disputes/appeals_controller_spec.rb b/spec/controllers/disputes/appeals_controller_spec.rb index da2f86ade..d763068eb 100644 --- a/spec/controllers/disputes/appeals_controller_spec.rb +++ b/spec/controllers/disputes/appeals_controller_spec.rb @@ -10,19 +10,17 @@ RSpec.describe Disputes::AppealsController do let!(:admin) { Fabricate(:user, role: UserRole.find_by(name: 'Admin')) } describe '#create' do + subject { post :create, params: params } + context 'with valid params' do let(:current_user) { Fabricate(:user) } let(:strike) { Fabricate(:account_warning, target_account: current_user.account) } + let(:params) { { strike_id: strike.id, appeal: { text: 'Foo' } } } - before do - post :create, params: { strike_id: strike.id, appeal: { text: 'Foo' } } - end + it 'notifies staff about new appeal and redirects back to strike page', :sidekiq_inline do + subject - it 'notifies staff about new appeal', :sidekiq_inline do expect(ActionMailer::Base.deliveries.first.to).to eq([admin.email]) - end - - it 'redirects back to the strike page' do expect(response).to redirect_to(disputes_strike_path(strike.id)) end end @@ -30,16 +28,12 @@ RSpec.describe Disputes::AppealsController do context 'with invalid params' do let(:current_user) { Fabricate(:user) } let(:strike) { Fabricate(:account_warning, target_account: current_user.account) } + let(:params) { { strike_id: strike.id, appeal: { text: '' } } } - before do - post :create, params: { strike_id: strike.id, appeal: { text: '' } } - end + it 'does not send email and renders strike show page', :sidekiq_inline do + subject - it 'does not send email', :sidekiq_inline do expect(ActionMailer::Base.deliveries.size).to eq(0) - end - - it 'renders the strike show page' do expect(response).to render_template('disputes/strikes/show') end end From 3454fcbd719f3f28b1466fd65c42c14d394212c0 Mon Sep 17 00:00:00 2001 From: Matt Jankowski Date: Fri, 16 Feb 2024 08:38:49 -0500 Subject: [PATCH 33/37] Reduce round trips in auth/sessions spec (#29233) --- .../auth/sessions_controller_spec.rb | 80 ++++++------------- 1 file changed, 25 insertions(+), 55 deletions(-) diff --git a/spec/controllers/auth/sessions_controller_spec.rb b/spec/controllers/auth/sessions_controller_spec.rb index b663f55af..dcbaf1fcb 100644 --- a/spec/controllers/auth/sessions_controller_spec.rb +++ b/spec/controllers/auth/sessions_controller_spec.rb @@ -57,11 +57,9 @@ RSpec.describe Auth::SessionsController do post :create, params: { user: { email: 'pam_user1', password: '123456' } } end - it 'redirects to home' do + it 'redirects to home and logs the user in' do expect(response).to redirect_to(root_path) - end - it 'logs the user in' do expect(controller.current_user).to be_instance_of(User) end end @@ -71,11 +69,9 @@ RSpec.describe Auth::SessionsController do post :create, params: { user: { email: 'pam_user1', password: 'WRONGPW' } } end - it 'shows a login error' do + it 'shows a login error and does not log the user in' do expect(flash[:alert]).to match I18n.t('devise.failure.invalid', authentication_keys: I18n.t('activerecord.attributes.user.email')) - end - it "doesn't log the user in" do expect(controller.current_user).to be_nil end end @@ -92,11 +88,9 @@ RSpec.describe Auth::SessionsController do post :create, params: { user: { email: user.email, password: '123456' } } end - it 'redirects to home' do + it 'redirects to home and logs the user in' do expect(response).to redirect_to(root_path) - end - it 'logs the user in' do expect(controller.current_user).to eq user end end @@ -110,16 +104,16 @@ RSpec.describe Auth::SessionsController do post :create, params: { user: { email: user.email, password: user.password } } end - it 'redirects to home' do + it 'redirects to home and logs the user in' do expect(response).to redirect_to(root_path) - end - it 'logs the user in' do expect(controller.current_user).to eq user end end context 'when using a valid password on a previously-used account with a new IP address' do + subject { post :create, params: { user: { email: user.email, password: user.password } } } + let(:previous_ip) { '1.2.3.4' } let(:current_ip) { '4.3.2.1' } @@ -127,18 +121,17 @@ RSpec.describe Auth::SessionsController do Fabricate(:login_activity, user: user, ip: previous_ip) allow(controller.request).to receive(:remote_ip).and_return(current_ip) user.update(current_sign_in_at: 1.month.ago) - post :create, params: { user: { email: user.email, password: user.password } } end - it 'redirects to home' do - expect(response).to redirect_to(root_path) - end + it 'logs the user in and sends suspicious email and redirects home', :sidekiq_inline do + subject - it 'logs the user in' do - expect(controller.current_user).to eq user - end + expect(response) + .to redirect_to(root_path) + + expect(controller.current_user) + .to eq user - it 'sends a suspicious sign-in mail', :sidekiq_inline do expect(UserMailer.deliveries.size).to eq(1) expect(UserMailer.deliveries.first.to.first).to eq(user.email) expect(UserMailer.deliveries.first.subject).to eq(I18n.t('user_mailer.suspicious_sign_in.subject')) @@ -150,11 +143,9 @@ RSpec.describe Auth::SessionsController do post :create, params: { user: { email: user.email.upcase, password: user.password } } end - it 'redirects to home' do + it 'redirects to home and logs the user in' do expect(response).to redirect_to(root_path) - end - it 'logs the user in' do expect(controller.current_user).to eq user end end @@ -164,11 +155,9 @@ RSpec.describe Auth::SessionsController do post :create, params: { user: { email: user.email, password: 'wrongpw' } } end - it 'shows a login error' do + it 'shows a login error and does not log the user in' do expect(flash[:alert]).to match I18n.t('devise.failure.invalid', authentication_keys: I18n.t('activerecord.attributes.user.email')) - end - it "doesn't log the user in" do expect(controller.current_user).to be_nil end end @@ -270,7 +259,7 @@ RSpec.describe Auth::SessionsController do travel_to '2023-12-20T10:00:00Z' end - it 'does not log the user in' do + it 'does not log the user in, sets a flash message, and sends a suspicious sign in email', :sidekiq_inline do Auth::SessionsController::MAX_2FA_ATTEMPTS_PER_HOUR.times do post :create, params: { user: { otp_attempt: '1234' } }, session: { attempt_user_id: user.id, attempt_user_updated_at: user.updated_at.to_s } expect(controller.current_user).to be_nil @@ -278,17 +267,10 @@ RSpec.describe Auth::SessionsController do post :create, params: { user: { otp_attempt: user.current_otp } }, session: { attempt_user_id: user.id, attempt_user_updated_at: user.updated_at.to_s } - expect(controller.current_user).to be_nil - expect(flash[:alert]).to match I18n.t('users.rate_limited') - end - - it 'sends a suspicious sign-in mail', :sidekiq_inline do - Auth::SessionsController::MAX_2FA_ATTEMPTS_PER_HOUR.times do - post :create, params: { user: { otp_attempt: '1234' } }, session: { attempt_user_id: user.id, attempt_user_updated_at: user.updated_at.to_s } - expect(controller.current_user).to be_nil - end - - post :create, params: { user: { otp_attempt: user.current_otp } }, session: { attempt_user_id: user.id, attempt_user_updated_at: user.updated_at.to_s } + expect(controller.current_user) + .to be_nil + expect(flash[:alert]) + .to match I18n.t('users.rate_limited') expect(UserMailer.deliveries.size).to eq(1) expect(UserMailer.deliveries.first.to.first).to eq(user.email) @@ -301,11 +283,9 @@ RSpec.describe Auth::SessionsController do post :create, params: { user: { otp_attempt: user.current_otp } }, session: { attempt_user_id: user.id, attempt_user_updated_at: user.updated_at.to_s } end - it 'redirects to home' do + it 'redirects to home and logs the user in' do expect(response).to redirect_to(root_path) - end - it 'logs the user in' do expect(controller.current_user).to eq user end end @@ -318,11 +298,9 @@ RSpec.describe Auth::SessionsController do post :create, params: { user: { otp_attempt: user.current_otp } }, session: { attempt_user_id: user.id, attempt_user_updated_at: user.updated_at.to_s } end - it 'shows a login error' do + it 'shows a login error and does not log the user in' do expect(flash[:alert]).to match I18n.t('users.invalid_otp_token') - end - it "doesn't log the user in" do expect(controller.current_user).to be_nil end end @@ -332,11 +310,9 @@ RSpec.describe Auth::SessionsController do post :create, params: { user: { otp_attempt: recovery_codes.first } }, session: { attempt_user_id: user.id, attempt_user_updated_at: user.updated_at.to_s } end - it 'redirects to home' do + it 'redirects to home and logs the user in' do expect(response).to redirect_to(root_path) - end - it 'logs the user in' do expect(controller.current_user).to eq user end end @@ -346,11 +322,9 @@ RSpec.describe Auth::SessionsController do post :create, params: { user: { otp_attempt: 'wrongotp' } }, session: { attempt_user_id: user.id, attempt_user_updated_at: user.updated_at.to_s } end - it 'shows a login error' do + it 'shows a login error and does not log the user in' do expect(flash[:alert]).to match I18n.t('users.invalid_otp_token') - end - it "doesn't log the user in" do expect(controller.current_user).to be_nil end end @@ -417,15 +391,11 @@ RSpec.describe Auth::SessionsController do post :create, params: { user: { credential: fake_credential } }, session: { attempt_user_id: user.id, attempt_user_updated_at: user.updated_at.to_s } end - it 'instructs the browser to redirect to home' do + it 'instructs the browser to redirect to home, logs the user in, and updates the sign count' do expect(body_as_json[:redirect_path]).to eq(root_path) - end - it 'logs the user in' do expect(controller.current_user).to eq user - end - it 'updates the sign count' do expect(webauthn_credential.reload.sign_count).to eq(sign_count) end end From 1946e171e6d150cecedf3949c3c4630d5bce1066 Mon Sep 17 00:00:00 2001 From: Matt Jankowski Date: Fri, 16 Feb 2024 08:46:28 -0500 Subject: [PATCH 34/37] Reduce round trips in admin/disputes/appeals spec (#29234) --- .../admin/disputes/appeals_controller_spec.rb | 31 +++++++++---------- 1 file changed, 14 insertions(+), 17 deletions(-) diff --git a/spec/controllers/admin/disputes/appeals_controller_spec.rb b/spec/controllers/admin/disputes/appeals_controller_spec.rb index f830c3b95..d36523316 100644 --- a/spec/controllers/admin/disputes/appeals_controller_spec.rb +++ b/spec/controllers/admin/disputes/appeals_controller_spec.rb @@ -30,21 +30,19 @@ RSpec.describe Admin::Disputes::AppealsController do end describe 'POST #approve' do + subject { post :approve, params: { id: appeal.id } } + let(:current_user) { Fabricate(:user, role: UserRole.find_by(name: 'Admin')) } - before do - post :approve, params: { id: appeal.id } - end + it 'redirects back to the strike page and notifies target account about approved appeal', :sidekiq_inline do + subject - it 'unsuspends a suspended account' do - expect(target_account.reload.suspended?).to be false - end + expect(response) + .to redirect_to(disputes_strike_path(appeal.strike)) - it 'redirects back to the strike page' do - expect(response).to redirect_to(disputes_strike_path(appeal.strike)) - end + expect(target_account.reload) + .to_not be_suspended - it 'notifies target account about approved appeal', :sidekiq_inline do expect(UserMailer.deliveries.size).to eq(1) expect(UserMailer.deliveries.first.to.first).to eq(target_account.user.email) expect(UserMailer.deliveries.first.subject).to eq(I18n.t('user_mailer.appeal_approved.subject', date: I18n.l(appeal.created_at))) @@ -52,17 +50,16 @@ RSpec.describe Admin::Disputes::AppealsController do end describe 'POST #reject' do + subject { post :reject, params: { id: appeal.id } } + let(:current_user) { Fabricate(:user, role: UserRole.find_by(name: 'Admin')) } - before do - post :reject, params: { id: appeal.id } - end + it 'redirects back to the strike page and notifies target account about rejected appeal', :sidekiq_inline do + subject - it 'redirects back to the strike page' do - expect(response).to redirect_to(disputes_strike_path(appeal.strike)) - end + expect(response) + .to redirect_to(disputes_strike_path(appeal.strike)) - it 'notifies target account about rejected appeal', :sidekiq_inline do expect(UserMailer.deliveries.size).to eq(1) expect(UserMailer.deliveries.first.to.first).to eq(target_account.user.email) expect(UserMailer.deliveries.first.subject).to eq(I18n.t('user_mailer.appeal_rejected.subject', date: I18n.l(appeal.created_at))) From 1d9d14b8de67daab169d10293e1f09901734c445 Mon Sep 17 00:00:00 2001 From: Matt Jankowski Date: Fri, 16 Feb 2024 09:29:24 -0500 Subject: [PATCH 35/37] Use `abort` instead of `warn(); exit` in boot.rb env check (#29209) --- .rubocop.yml | 6 ------ config/boot.rb | 11 +++++++++-- 2 files changed, 9 insertions(+), 8 deletions(-) diff --git a/.rubocop.yml b/.rubocop.yml index a8310489e..dce33eab3 100644 --- a/.rubocop.yml +++ b/.rubocop.yml @@ -96,12 +96,6 @@ Rails/FilePath: Rails/HttpStatus: EnforcedStyle: numeric -# Reason: Allowed in boot ENV checker -# https://docs.rubocop.org/rubocop-rails/cops_rails.html#railsexit -Rails/Exit: - Exclude: - - 'config/boot.rb' - # Reason: Conflicts with `Lint/UselessMethodDefinition` for inherited controller actions # https://docs.rubocop.org/rubocop-rails/cops_rails.html#railslexicallyscopedactionfilter Rails/LexicallyScopedActionFilter: diff --git a/config/boot.rb b/config/boot.rb index 717de85f2..70ffe22c0 100644 --- a/config/boot.rb +++ b/config/boot.rb @@ -1,8 +1,15 @@ # frozen_string_literal: true unless ENV.key?('RAILS_ENV') - warn 'ERROR: Missing RAILS_ENV environment variable, please set it to "production", "development", or "test".' - exit 1 + abort <<~ERROR + The RAILS_ENV environment variable is not set. + + Please set it correctly depending on context: + + - Use "production" for a live deployment of the application + - Use "development" for local feature work + - Use "test" when running the automated spec suite + ERROR end ENV['BUNDLE_GEMFILE'] ||= File.expand_path('../Gemfile', __dir__) From cfadb8707737ff679b1b08fa9dcab627a632f6ab Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Wolfgang=20Fourn=C3=A8s?= Date: Fri, 16 Feb 2024 15:54:23 +0100 Subject: [PATCH 36/37] Update enum syntax to use the new Rails 7.0 style (#29217) --- app/models/account.rb | 4 ++-- app/models/account_warning.rb | 4 ++-- app/models/bulk_import.rb | 4 ++-- app/models/custom_filter.rb | 2 +- app/models/domain_block.rb | 2 +- app/models/import.rb | 2 +- app/models/ip_block.rb | 2 +- app/models/list.rb | 2 +- app/models/login_activity.rb | 2 +- app/models/media_attachment.rb | 4 ++-- app/models/preview_card.rb | 4 ++-- app/models/relay.rb | 2 +- app/models/report.rb | 2 +- app/models/software_update.rb | 2 +- app/models/status.rb | 2 +- 15 files changed, 20 insertions(+), 20 deletions(-) diff --git a/app/models/account.rb b/app/models/account.rb index 05e1f943c..442d4a431 100644 --- a/app/models/account.rb +++ b/app/models/account.rb @@ -85,8 +85,8 @@ class Account < ApplicationRecord include DomainNormalizable include Paginable - enum protocol: { ostatus: 0, activitypub: 1 } - enum suspension_origin: { local: 0, remote: 1 }, _prefix: true + enum :protocol, { ostatus: 0, activitypub: 1 } + enum :suspension_origin, { local: 0, remote: 1 }, prefix: true validates :username, presence: true validates_with UniqueUsernameValidator, if: -> { will_save_change_to_username? } diff --git a/app/models/account_warning.rb b/app/models/account_warning.rb index 9286577f5..a54387a56 100644 --- a/app/models/account_warning.rb +++ b/app/models/account_warning.rb @@ -17,7 +17,7 @@ # class AccountWarning < ApplicationRecord - enum action: { + enum :action, { none: 0, disable: 1_000, mark_statuses_as_sensitive: 1_250, @@ -25,7 +25,7 @@ class AccountWarning < ApplicationRecord sensitive: 2_000, silence: 3_000, suspend: 4_000, - }, _suffix: :action + }, suffix: :action normalizes :text, with: ->(text) { text.to_s }, apply_to_nil: true diff --git a/app/models/bulk_import.rb b/app/models/bulk_import.rb index 406fb2aba..4cd228705 100644 --- a/app/models/bulk_import.rb +++ b/app/models/bulk_import.rb @@ -24,7 +24,7 @@ class BulkImport < ApplicationRecord belongs_to :account has_many :rows, class_name: 'BulkImportRow', inverse_of: :bulk_import, dependent: :delete_all - enum type: { + enum :type, { following: 0, blocking: 1, muting: 2, @@ -33,7 +33,7 @@ class BulkImport < ApplicationRecord lists: 5, } - enum state: { + enum :state, { unconfirmed: 0, scheduled: 1, in_progress: 2, diff --git a/app/models/custom_filter.rb b/app/models/custom_filter.rb index c8120c239..5e2d152e3 100644 --- a/app/models/custom_filter.rb +++ b/app/models/custom_filter.rb @@ -31,7 +31,7 @@ class CustomFilter < ApplicationRecord include Expireable include Redisable - enum action: { warn: 0, hide: 1 }, _suffix: :action + enum :action, { warn: 0, hide: 1 }, suffix: :action belongs_to :account has_many :keywords, class_name: 'CustomFilterKeyword', inverse_of: :custom_filter, dependent: :destroy diff --git a/app/models/domain_block.rb b/app/models/domain_block.rb index a05db099a..e310918e9 100644 --- a/app/models/domain_block.rb +++ b/app/models/domain_block.rb @@ -21,7 +21,7 @@ class DomainBlock < ApplicationRecord include DomainNormalizable include DomainMaterializable - enum severity: { silence: 0, suspend: 1, noop: 2 } + enum :severity, { silence: 0, suspend: 1, noop: 2 } validates :domain, presence: true, uniqueness: true, domain: true diff --git a/app/models/import.rb b/app/models/import.rb index 7cd6cccf7..4bdb39201 100644 --- a/app/models/import.rb +++ b/app/models/import.rb @@ -28,7 +28,7 @@ class Import < ApplicationRecord belongs_to :account - enum type: { following: 0, blocking: 1, muting: 2, domain_blocking: 3, bookmarks: 4 } + enum :type, { following: 0, blocking: 1, muting: 2, domain_blocking: 3, bookmarks: 4 } validates :type, presence: true diff --git a/app/models/ip_block.rb b/app/models/ip_block.rb index 99783050b..9def5b0cd 100644 --- a/app/models/ip_block.rb +++ b/app/models/ip_block.rb @@ -19,7 +19,7 @@ class IpBlock < ApplicationRecord include Expireable include Paginable - enum severity: { + enum :severity, { sign_up_requires_approval: 5000, sign_up_block: 5500, no_access: 9999, diff --git a/app/models/list.rb b/app/models/list.rb index fcef49e6e..b45bd057b 100644 --- a/app/models/list.rb +++ b/app/models/list.rb @@ -18,7 +18,7 @@ class List < ApplicationRecord PER_ACCOUNT_LIMIT = 50 - enum replies_policy: { list: 0, followed: 1, none: 2 }, _prefix: :show + enum :replies_policy, { list: 0, followed: 1, none: 2 }, prefix: :show belongs_to :account, optional: true diff --git a/app/models/login_activity.rb b/app/models/login_activity.rb index 2b7b37f8e..654dd623a 100644 --- a/app/models/login_activity.rb +++ b/app/models/login_activity.rb @@ -16,7 +16,7 @@ # class LoginActivity < ApplicationRecord - enum authentication_method: { password: 'password', otp: 'otp', webauthn: 'webauthn', sign_in_token: 'sign_in_token', omniauth: 'omniauth' } + enum :authentication_method, { password: 'password', otp: 'otp', webauthn: 'webauthn', sign_in_token: 'sign_in_token', omniauth: 'omniauth' } belongs_to :user diff --git a/app/models/media_attachment.rb b/app/models/media_attachment.rb index 7ff6a15f5..f53da04a9 100644 --- a/app/models/media_attachment.rb +++ b/app/models/media_attachment.rb @@ -34,8 +34,8 @@ class MediaAttachment < ApplicationRecord include Attachmentable - enum type: { image: 0, gifv: 1, video: 2, unknown: 3, audio: 4 } - enum processing: { queued: 0, in_progress: 1, complete: 2, failed: 3 }, _prefix: true + enum :type, { image: 0, gifv: 1, video: 2, unknown: 3, audio: 4 } + enum :processing, { queued: 0, in_progress: 1, complete: 2, failed: 3 }, prefix: true MAX_DESCRIPTION_LENGTH = 1_500 diff --git a/app/models/preview_card.rb b/app/models/preview_card.rb index 837592743..9fe02bd16 100644 --- a/app/models/preview_card.rb +++ b/app/models/preview_card.rb @@ -47,8 +47,8 @@ class PreviewCard < ApplicationRecord self.inheritance_column = false - enum type: { link: 0, photo: 1, video: 2, rich: 3 } - enum link_type: { unknown: 0, article: 1 } + enum :type, { link: 0, photo: 1, video: 2, rich: 3 } + enum :link_type, { unknown: 0, article: 1 } has_many :preview_cards_statuses, dependent: :delete_all, inverse_of: :preview_card has_many :statuses, through: :preview_cards_statuses diff --git a/app/models/relay.rb b/app/models/relay.rb index 8d697b891..f652b4864 100644 --- a/app/models/relay.rb +++ b/app/models/relay.rb @@ -15,7 +15,7 @@ class Relay < ApplicationRecord validates :inbox_url, presence: true, uniqueness: true, url: true, if: :will_save_change_to_inbox_url? - enum state: { idle: 0, pending: 1, accepted: 2, rejected: 3 } + enum :state, { idle: 0, pending: 1, accepted: 2, rejected: 3 } scope :enabled, -> { accepted } diff --git a/app/models/report.rb b/app/models/report.rb index 1b132753b..df7e3d2ef 100644 --- a/app/models/report.rb +++ b/app/models/report.rb @@ -55,7 +55,7 @@ class Report < ApplicationRecord # - app/javascript/mastodon/features/notifications/components/report.jsx # - app/javascript/mastodon/features/report/category.jsx # - app/javascript/mastodon/components/admin/ReportReasonSelector.jsx - enum category: { + enum :category, { other: 0, spam: 1_000, legal: 1_500, diff --git a/app/models/software_update.rb b/app/models/software_update.rb index cb3a6df2a..51a73c273 100644 --- a/app/models/software_update.rb +++ b/app/models/software_update.rb @@ -16,7 +16,7 @@ class SoftwareUpdate < ApplicationRecord self.inheritance_column = nil - enum type: { patch: 0, minor: 1, major: 2 }, _suffix: :type + enum :type, { patch: 0, minor: 1, major: 2 }, suffix: :type def gem_version Gem::Version.new(version) diff --git a/app/models/status.rb b/app/models/status.rb index e3d41cced..0ec69c8dd 100644 --- a/app/models/status.rb +++ b/app/models/status.rb @@ -50,7 +50,7 @@ class Status < ApplicationRecord update_index('statuses', :proper) update_index('public_statuses', :proper) - enum visibility: { public: 0, unlisted: 1, private: 2, direct: 3, limited: 4 }, _suffix: :visibility + enum :visibility, { public: 0, unlisted: 1, private: 2, direct: 3, limited: 4 }, suffix: :visibility belongs_to :application, class_name: 'Doorkeeper::Application', optional: true From 96ddf1d4820419a6b5367af022be5cf17526109e Mon Sep 17 00:00:00 2001 From: Claire Date: Fri, 16 Feb 2024 17:57:23 +0100 Subject: [PATCH 37/37] Fix flaky end-to-end OCR test (#29244) --- spec/system/ocr_spec.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/spec/system/ocr_spec.rb b/spec/system/ocr_spec.rb index 3ab815c04..254efa713 100644 --- a/spec/system/ocr_spec.rb +++ b/spec/system/ocr_spec.rb @@ -28,6 +28,6 @@ describe 'OCR', :paperclip_processing, :sidekiq_inline do click_on('Detect text from picture') - expect(page).to have_css('#upload-modal__description', text: 'Hello Mastodon') + expect(page).to have_css('#upload-modal__description', text: /Hello Mastodon\s*/, wait: 10) end end