From c07028b2fae4dc692570df84227023ca90443288 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Fri, 9 Feb 2024 10:55:30 +0100 Subject: [PATCH 01/28] New Crowdin Translations (automated) (#29152) Co-authored-by: GitHub Actions --- app/javascript/mastodon/locales/ia.json | 22 +++ app/javascript/mastodon/locales/sk.json | 9 +- app/javascript/mastodon/locales/tok.json | 177 ++++++++++++++++++----- config/locales/activerecord.tok.yml | 8 + config/locales/doorkeeper.tok.yml | 50 +++++++ config/locales/simple_form.tok.yml | 4 +- config/locales/sk.yml | 2 +- config/locales/tok.yml | 4 + 8 files changed, 230 insertions(+), 46 deletions(-) diff --git a/app/javascript/mastodon/locales/ia.json b/app/javascript/mastodon/locales/ia.json index 7b9ab3742b6746..10328efd0e0de2 100644 --- a/app/javascript/mastodon/locales/ia.json +++ b/app/javascript/mastodon/locales/ia.json @@ -2,6 +2,8 @@ "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.silenced.title": "Limitate", + "about.domain_blocks.suspended.title": "Suspendite", "about.rules": "Regulas del servitor", "account.account_note_header": "Nota", "account.add_or_remove_from_list": "Adder o remover ab listas", @@ -12,6 +14,7 @@ "account.blocked": "Blocate", "account.browse_more_on_origin_server": "Navigar plus sur le profilo original", "account.copy": "Copiar ligamine a profilo", + "account.direct": "Mentionar privatemente a @{name}", "account.disable_notifications": "Stoppar le notificationes quando @{name} publica", "account.domain_blocked": "Dominio blocate", "account.edit_profile": "Modificar profilo", @@ -33,6 +36,7 @@ "account.languages": "Cambiar le linguas subscribite", "account.link_verified_on": "Le proprietate de iste ligamine esseva verificate le {date}", "account.locked_info": "Le stato de confidentialitate de iste conto es definite a blocate. Le proprietario revisa manualmente qui pote sequer lo.", + "account.media": "Multimedia", "account.mention": "Mentionar @{name}", "account.moved_to": "{name} indicava que lor nove conto ora es:", "account.mute": "Silentiar @{name}", @@ -57,6 +61,7 @@ "account.unmute_notifications_short": "Non plus silentiar le notificationes", "account.unmute_short": "Non plus silentiar", "account_note.placeholder": "Clicca pro adder un nota", + "admin.dashboard.retention.average": "Median", "admin.dashboard.retention.cohort_size": "Nove usatores", "admin.impact_report.instance_followers": "Sequitores que nostre usatores poterea perder", "admin.impact_report.instance_follows": "Sequitores que lor usatores poterea perder", @@ -69,6 +74,7 @@ "bundle_column_error.return": "Retornar al initio", "bundle_modal_error.close": "Clauder", "bundle_modal_error.retry": "Tentar novemente", + "closed_registrations_modal.description": "Crear un conto in {domain} actualmente non es possibile, ma considera que tu non besonia un conto specific in {domain} pro usar Mastodon.", "closed_registrations_modal.find_another_server": "Trovar altere servitor", "column.about": "A proposito de", "column.blocks": "Usatores blocate", @@ -105,6 +111,7 @@ "compose_form.poll.option_placeholder": "Option {number}", "compose_form.poll.single": "Seliger un", "compose_form.poll.switch_to_multiple": "Cambiar inquesta pro permitter selectiones multiple", + "compose_form.poll.switch_to_single": "Cambiar inquesta pro permitter selection singule", "compose_form.poll.type": "Stylo", "compose_form.publish": "Publicar", "compose_form.publish_form": "Nove message", @@ -117,6 +124,8 @@ "confirmations.block.block_and_report": "Blocar e signalar", "confirmations.block.confirm": "Blocar", "confirmations.block.message": "Es tu secur que tu vole blocar {name}?", + "confirmations.cancel_follow_request.confirm": "Retirar requesta", + "confirmations.cancel_follow_request.message": "Es tu secur que tu vole retirar tu requesta a sequer a {name}?", "confirmations.delete.confirm": "Deler", "confirmations.delete.message": "Es tu secur que tu vole deler iste message?", "confirmations.delete_list.confirm": "Deler", @@ -320,6 +329,8 @@ "report.placeholder": "Commentos additional", "report.reasons.dislike": "Non me place", "report_notification.categories.other": "Alteres", + "report_notification.open": "Aperir reporto", + "search.no_recent_searches": "Nulle recercas recente", "search.quick_action.go_to_account": "Vader al profilo {x}", "search.quick_action.go_to_hashtag": "Vader al hashtag {x}", "search.quick_action.open_url": "Aperir URL in Mastodon", @@ -333,14 +344,20 @@ "search_results.hashtags": "Hashtags", "search_results.see_all": "Vider toto", "search_results.statuses": "Messages", + "server_banner.active_users": "usatores active", "server_banner.learn_more": "Apprender plus", + "server_banner.server_stats": "Statos del servitor:", "sign_in_banner.create_account": "Crear un conto", "sign_in_banner.sign_in": "Initiar le session", "status.block": "Blocar @{name}", "status.copy": "Copiar ligamine a message", "status.delete": "Deler", + "status.direct": "Mentionar privatemente a @{name}", "status.direct_indicator": "Mention private", "status.edit": "Modificar", + "status.edited": "Modificate le {date}", + "status.edited_x_times": "Modificate {count, plural, one {{count} tempore} other {{count} tempores}}", + "status.favourite": "Adder al favoritos", "status.filter": "Filtrar iste message", "status.hide": "Celar le message", "status.history.created": "create per {name} le {date}", @@ -351,12 +368,17 @@ "status.mute_conversation": "Silentiar conversation", "status.read_more": "Leger plus", "status.share": "Compartir", + "status.show_less": "Monstrar minus", + "status.show_more": "Monstrar plus", "status.translate": "Traducer", "status.translated_from_with": "Traducite ab {lang} usante {provider}", + "status.uncached_media_warning": "Previsualisation non disponibile", + "subscribed_languages.save": "Salveguardar le cambiamentos", "tabs_bar.home": "Initio", "tabs_bar.notifications": "Notificationes", "timeline_hint.resources.statuses": "Messages ancian", "trends.trending_now": "Ora in tendentias", + "upload_button.label": "Adde imagines, un video o un file de audio", "upload_modal.choose_image": "Seliger un imagine", "upload_modal.detect_text": "Deteger texto ab un pictura", "video.close": "Clauder le video", diff --git a/app/javascript/mastodon/locales/sk.json b/app/javascript/mastodon/locales/sk.json index 7a05eb4f7e5d04..ad7837cab28e76 100644 --- a/app/javascript/mastodon/locales/sk.json +++ b/app/javascript/mastodon/locales/sk.json @@ -280,6 +280,7 @@ "follow_suggestions.curated_suggestion": "Výber zo servera", "follow_suggestions.dismiss": "Znovu nezobrazuj", "follow_suggestions.personalized_suggestion": "Prispôsobené odporúčania", + "follow_suggestions.popular_suggestion": "Populárne návrhy", "follow_suggestions.view_all": "Zobraz všetky", "follow_suggestions.who_to_follow": "Koho nasledovať", "followed_tags": "Nasledované haštagy", @@ -355,7 +356,7 @@ "keyboard_shortcuts.muted": "otvor zoznam stíšených užívateľov", "keyboard_shortcuts.my_profile": "otvor svoj profil", "keyboard_shortcuts.notifications": "Otvor panel oznámení", - "keyboard_shortcuts.open_media": "na otvorenie médií", + "keyboard_shortcuts.open_media": "Otvorenie médií", "keyboard_shortcuts.pinned": "otvor zoznam pripnutých príspevkov", "keyboard_shortcuts.profile": "otvor autorov profil", "keyboard_shortcuts.reply": "odpovedať", @@ -364,7 +365,7 @@ "keyboard_shortcuts.spoilers": "to show/hide CW field", "keyboard_shortcuts.start": "otvor panel ''začíname''", "keyboard_shortcuts.toggle_hidden": "ukáž/skry text za CW", - "keyboard_shortcuts.toggle_sensitivity": "pre zobrazenie/skrytie médií", + "keyboard_shortcuts.toggle_sensitivity": "Ukáž/skry médiá", "keyboard_shortcuts.toot": "začni úplne nový príspevok", "keyboard_shortcuts.unfocus": "nesústreď sa na písaciu plochu, alebo hľadanie", "keyboard_shortcuts.up": "posuň sa vyššie v zozname", @@ -493,7 +494,7 @@ "onboarding.share.message": "Na Mastodone som {username}. Príď ma nasledovať na {url}", "onboarding.share.next_steps": "Ďalšie možné kroky:", "onboarding.share.title": "Zdieľaj svoj profil", - "onboarding.start.lead": "Your new Mastodon account is ready to go. Here's how you can make the most of it:", + "onboarding.start.lead": "Teraz si súčasťou Mastodonu, unikátnej, decentralizovanej sociálnej platformy, kde ty, nie algoritmus, spravuješ svoj vlastný zážitok. Poďme ťa naštartovať na tomto novom sociálnom pomedzí:", "onboarding.start.skip": "Want to skip right ahead?", "onboarding.start.title": "Zvládli ste to!", "onboarding.steps.follow_people.body": "You curate your own feed. Lets fill it with interesting people.", @@ -705,7 +706,7 @@ "units.short.million": "{count}mil.", "units.short.thousand": "{count}tis.", "upload_area.title": "Pretiahni a pusť pre nahratie", - "upload_button.label": "Pridaj médiálny súbor (JPEG, PNG, GIF, WebM, MP4, MOV)", + "upload_button.label": "Pridaj obrázky, video, alebo zvukový súbor", "upload_error.limit": "Limit pre nahrávanie súborov bol prekročený.", "upload_error.poll": "Nahrávanie súborov pri anketách nieje možné.", "upload_form.audio_description": "Popíš, pre ľudí so stratou sluchu", diff --git a/app/javascript/mastodon/locales/tok.json b/app/javascript/mastodon/locales/tok.json index 1c8435623855d1..7270d520672a55 100644 --- a/app/javascript/mastodon/locales/tok.json +++ b/app/javascript/mastodon/locales/tok.json @@ -2,16 +2,18 @@ "about.blocks": "ma lawa", "about.contact": "toki:", "about.domain_blocks.no_reason_available": "mi sona ala e tan", + "about.domain_blocks.suspended.title": "weka", "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.badges.bot": "ilo nanpa li lawa e ni", "account.badges.group": "kulupu", "account.block": "o weka e @{name}", "account.block_domain": "o weka e ma {domain}", - "account.block_short": "o weka e jan", - "account.blocked": "jan ni li weka", + "account.block_short": "o weka e jan tawa mi", + "account.blocked": "jan ni 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 wile kute", + "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", @@ -34,15 +36,15 @@ "account.media": "sitelen", "account.mention": "o toki e jan @{name}", "account.moved_to": "lipu jan sin pi jan {name} li ni:", - "account.mute": "o kute ala e @{name}", + "account.mute": "o len e @{name}", "account.mute_notifications_short": "o kute ala e mu tan jan ni", "account.mute_short": "o kute ala", - "account.muted": "sina kute ala e jan ni", + "account.muted": "sina len e jan ni", "account.no_bio": "lipu li weka", "account.open_original_page": "o open e lipu open", "account.posts": "toki suli", "account.posts_with_replies": "toki ale", - "account.report": "jan @{name} la o toki e lawa", + "account.report": "jan @{name} la o toki tawa lawa", "account.requested": "jan ni o ken e kute sina. sina pini wile kute la o luka e ni", "account.requested_follow": "{name} li wile kute e sina", "account.share": "o pana e lipu jan @{name}", @@ -51,20 +53,21 @@ "account.unblock_domain": "o weka ala e ma {domain}", "account.unblock_short": "o pini weka", "account.unfollow": "o pini kute", - "account.unmute": "o kute e @{name}", + "account.unmute": "o len ala e @{name}", "account.unmute_notifications_short": "o kute e mu tan jan ni", - "account.unmute_short": "o ken kute e jan ni", + "account.unmute_short": "o len ala", "admin.dashboard.retention.average": "sama", "admin.dashboard.retention.cohort": "tenpo mun open", "admin.dashboard.retention.cohort_size": "jan sin", "alert.rate_limited.message": "tenpo {retry_time, time, medium} la o pali awen", "alert.unexpected.message": "pakala li lon", - "alert.unexpected.title": "pakala", + "alert.unexpected.title": "pakala a!", "announcement.announcement": "toki suli", "audio.hide": "o len e kalama", - "bundle_column_error.error.title": "pakala!", + "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", + "bundle_column_error.return": "o tawa tomo", "bundle_column_error.routing.body": "ilo li sona ala e lipu wile. sina pana ala pana e nasin pona tawa lipu?", "bundle_column_error.routing.title": "pakala nanpa 404", "bundle_modal_error.close": "o pini", @@ -72,64 +75,92 @@ "bundle_modal_error.retry": "o ni sin", "closed_registrations_modal.find_another_server": "o alasa e ma ante", "column.blocks": "kulupu pi jan weka", - "column.lists": "lipu pi lipu mute", - "column.mutes": "sina wile ala kute e jan ni", - "community.column_settings.local_only": "toki lon ni taso", + "column.home": "lipu open", + "column.lists": "kulupu lipu", + "column.mutes": "jan len", + "column.pins": "toki sewi", + "column_header.hide_settings": "o len e lawa", + "column_header.pin": "o sewi", + "column_header.show_settings": "o lukin e lawa", + "column_header.unpin": "o sewi ala", + "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", "compose.language.change": "o ante e nasin toki", "compose.language.search": "o alasa e nasin toki...", + "compose.published.body": "toki li pana.", "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.placeholder": "sina toki insa e seme", + "compose_form.placeholder": "sina wile toki e seme?", + "compose_form.poll.duration": "tenpo pana", + "compose_form.poll.multiple": "pana mute", "compose_form.poll.option_placeholder": "ken nanpa {number}", + "compose_form.poll.single": "pana pi wan taso", "compose_form.poll.switch_to_multiple": "o ante e nasin pana. pana mute o ken", "compose_form.poll.switch_to_single": "o ante e nasin pana. pana wan taso o lon", + "compose_form.poll.type": "nasin", "compose_form.publish": "o toki", "compose_form.publish_form": "o open toki sin", "compose_form.reply": "o toki lon ijo ni", "compose_form.save_changes": "o sin e ni", "compose_form.spoiler.marked": "o weka e toki pi ijo ike ken", - "confirmations.block.confirm": "o weka.", + "confirmation_modal.cancel": "o pini", + "confirmations.block.confirm": "o weka", "confirmations.block.message": "sina o wile ala wile weka e jan {name}?", "confirmations.cancel_follow_request.confirm": "o weka e wile sina", "confirmations.cancel_follow_request.message": "sina awen ala awen wile weka e wile kute sina lon {name}?", - "confirmations.delete.confirm": "o pakala", - "confirmations.delete.message": "sina wile ala wile pakala e toki ni", - "confirmations.delete_list.confirm": "o pakala", - "confirmations.delete_list.message": "sina wile ala wile pakala e lipu ni", + "confirmations.delete.confirm": "o weka", + "confirmations.delete.message": "sina wile ala wile weka e toki ni?", + "confirmations.delete_list.confirm": "o weka", + "confirmations.delete_list.message": "sina wile ala wile weka e lipu ni?", "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.edit.confirm": "o ante", "confirmations.logout.confirm": "o weka", "confirmations.logout.message": "sina wile ala wile weka", - "confirmations.mute.confirm": "sina wile ala kute e jan ni", + "confirmations.mute.confirm": "o len", "confirmations.mute.message": "sina awen ala awen wile kute ala e {name}?", - "confirmations.redraft.confirm": "o pakala o pali sin e toki", + "confirmations.redraft.confirm": "o weka o pali sin e toki", + "confirmations.redraft.message": "pali sin e toki ni la sina wile ala wile weka e ona? sina ni la suli pi toki ni en wawa pi toki ni li weka. kin la toki lon toki ni li jo e mama ala.", + "confirmations.reply.confirm": "toki lon toki ni", + "confirmations.reply.message": "toki tawa ona li weka e toki pali sina ꞏ sina wile ala wile ni", "confirmations.unfollow.confirm": "o pini kute", "confirmations.unfollow.message": "sina o wile ala wile pini kute e jan {name}?", "conversation.delete": "o weka e toki ni", "conversation.mark_as_read": "ni o sin ala", "conversation.open": "o lukin e toki", "conversation.with": "lon {names}", + "directory.local": "tan {domain} taso", "directory.new_arrivals": "jan pi kama sin", + "directory.recently_active": "jan lon tenpo poka", + "disabled_account_banner.account_settings": "wile pi lipu jan", + "disabled_account_banner.text": "sina ken ala kepeken e lipu jan sina pi nimi {disabledAccount}.", + "dismissable_banner.community_timeline": "ni li toki pi tenpo poka tawa ale tan jan lon ma lawa pi nimi {domain}.", "dismissable_banner.dismiss": "o weka", + "dismissable_banner.explore_links": "ni li toki pi ijo sin ꞏ jan mute li pana e ni lon tenpo suno ni ꞏ sin la jan mute li pana la ni li kama suli", + "embed.preview": "ni li jo e sitelen ni:", + "emoji_button.activity": "musi", "emoji_button.flags": "len ma", "emoji_button.food": "moku", - "emoji_button.label": "o pana e Emosi", + "emoji_button.label": "o pana e sitelen pilin", "emoji_button.nature": "soweli en kasi", - "emoji_button.not_found": "sitelen Emosi ala li lon", + "emoji_button.not_found": "sitelen pilin ala li lon", "emoji_button.objects": "ijo", "emoji_button.people": "jan", - "emoji_button.search": "o alasa", + "emoji_button.search": "o alasa...", "emoji_button.search_results": "ijo pi alasa ni", "emoji_button.symbols": "sitelen", "emoji_button.travel": "ma en tawa", + "empty_column.account_hides_collections": "jan ni li wile len e sona ni", "empty_column.account_timeline": "toki ala li lon!", "empty_column.account_unavailable": "ken ala lukin e lipu jan", + "empty_column.blocks": "jan ala li weka tawa sina.", "empty_column.followed_tags": "sina alasa ala e toki ꞏ sina alasa e toki la toki li lon ni", "empty_column.hashtag": "ala li lon toki ni", - "empty_column.mutes": "jan ala la sina wile ala kute.", + "empty_column.mutes": "jan ala li len tawa sina.", + "errors.unexpected_crash.report_issue": "o toki e pakala tawa lawa", "explore.search_results": "ijo pi alasa ni", "explore.suggested_follows": "jan", "explore.title": "o alasa", @@ -138,52 +169,102 @@ "filter_modal.select_filter.expired": "tenpo pini", "filter_modal.select_filter.search": "o alasa anu pali", "firehose.all": "ale", - "firehose.local": "ilo ni", - "firehose.remote": "ilo ante", - "follow_request.authorize": "o sina kama", - "follow_request.reject": "o weka", + "firehose.local": "kulupu ni", + "firehose.remote": "kulupu ante", + "follow_request.authorize": "o ken", + "follow_request.reject": "o ala", "follow_suggestions.view_all": "o lukin e ale", + "follow_suggestions.who_to_follow": "sina o kute e ni", + "footer.get_app": "o jo e ilo", "footer.privacy_policy": "lawa len", "footer.source_code": "o lukin e toki ilo", "footer.status": "lon", + "generic.saved": "ni li awen", "hashtag.column_header.tag_mode.all": "en {additional}", "hashtag.column_header.tag_mode.any": "anu {additional}", + "hashtag.column_header.tag_mode.none": "en {additional} ala", "hashtag.column_settings.tag_mode.all": "ale ni", "hashtag.column_settings.tag_mode.any": "wan ni", "hashtag.column_settings.tag_mode.none": "ala ni", "home.pending_critical_update.link": "o lukin e ijo ilo sin", "interaction_modal.on_another_server": "lon ma ante", "interaction_modal.on_this_server": "lon ma ni", + "interaction_modal.title.favourite": "o suli e toki {name}", "interaction_modal.title.follow": "o kute e {name}", - "keyboard_shortcuts.muted": "sina wile ala kute e jan la o lukin e ona ale", - "keyboard_shortcuts.open_media": "o open e sitelen", - "keyboard_shortcuts.toggle_sensitivity": "sitelen la o len anu lukin", + "interaction_modal.title.reblog": "o wawa e toki {name}", + "keyboard_shortcuts.blocked": "o lukin e lipu sina pi jan weka", + "keyboard_shortcuts.down": "o tawa anpa lon lipu", + "keyboard_shortcuts.enter": "o lukin e toki", + "keyboard_shortcuts.favourite": "o suli e toki", + "keyboard_shortcuts.favourites": "o lukin e lipu sina pi toki suli", + "keyboard_shortcuts.muted": "o lukin e lipu sina pi jan len", + "keyboard_shortcuts.my_profile": "o lukin e lipu sina", + "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.up": "o tawa sewi lon lipu", "lightbox.close": "o pini", - "link_preview.author": "{name} li pali e ni", + "lightbox.compress": "o lili e sitelen", + "lightbox.expand": "o suli e sitelen", + "lightbox.next": "sinpin", + "lightbox.previous": "monsi", + "link_preview.author": "tan {name}", + "lists.account.add": "o pana tawa kulupu lipu", + "lists.account.remove": "o weka tan kulupu lipu", + "lists.delete": "o weka e kulupu lipu", + "lists.edit": "o ante e kulupu lipu", "lists.edit.submit": "o ante e nimi", + "lists.exclusive": "o len e toki lon lipu open", + "lists.new.create": "o sin e kulupu lipu", + "lists.replies_policy.followed": "jan kute ale", + "lists.replies_policy.list": "jan pi kulupu ni taso", "lists.replies_policy.none": "jan ala", + "lists.subheading": "kulupu lipu sina", + "load_pending": "{count, plural, other {ijo sin #}}", + "loading_indicator.label": "ni li kama…", + "media_gallery.toggle_visible": "{number, plural, other {o len e sitelen}}", "mute_modal.duration": "tenpo", "mute_modal.indefinite": "tenpo ale", - "navigation_bar.filters": "sina wile ala kute e nimi ni", + "navigation_bar.blocks": "jan weka", + "navigation_bar.compose": "o pali e toki sin", + "navigation_bar.favourites": "toki suli", + "navigation_bar.filters": "nimi len", + "navigation_bar.lists": "kulupu lipu", "navigation_bar.mutes": "sina wile ala kute e jan ni", - "notification.follow": "jan {name} li kama kute e sina", + "navigation_bar.pins": "toki sewi", + "navigation_bar.preferences": "wile sina", + "navigation_bar.search": "o alasa", + "notification.admin.sign_up": "{name} li kama", + "notification.favourite": "{name} li suli e toki sina", + "notification.follow": " {name} li kute e sina", "notification.follow_request": "{name} li wile kute e sina", "notification.mention": "jan {name} li toki e sina", + "notification.reblog": "{name} li wawa e toki sina", + "notification.status": "{name} li toki", + "notification.update": "{name} li ante e toki", "notifications.column_settings.follow": "jan kute sin", "notifications.filter.all": "ale", + "onboarding.compose.template": "toki a, #Mastodon o!", "onboarding.start.title": "sina o kama pona a!", - "privacy.public.short": "jan ale", + "poll.total_people": "{count, plural, other {jan #}}", + "privacy.public.short": "tawa ale", "relative_time.full.just_now": "tenpo ni", "relative_time.just_now": "tenpo ni", "relative_time.today": "tenpo suno ni", "report.block": "o weka e jan", "report.block_explanation": "sina kama lukin ala e toki ona. ona li kama ala ken lukin e toki sina li kama ala ken kute e sina. ona li ken sona e kama ni.", "report.category.title": "ike seme li lon {type} ni", + "report.category.title_account": "lipu", + "report.category.title_status": "toki", "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.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}", "search.placeholder": "o alasa", "search.quick_action.go_to_account": "o tawa lipu jan {x}", "search_popout.language_code": "nimi toki kepeken nasin ISO", @@ -196,27 +277,40 @@ "status.edit": "o ante", "status.edited": "ni li ante lon {date}", "status.embed": "ni o lon insa pi lipu ante", + "status.favourite": "o suli", + "status.hide": "o len", "status.history.created": "{name} li pali e ni lon {date}", "status.history.edited": "{name} li ante lon {date}", "status.load_more": "o kama e ijo ante", "status.media.open": "o open", "status.media.show": "o lukin", "status.media_hidden": "sitelen li len", - "status.mute": "o kute ala e @{name}", + "status.mute": "o len e @{name}", "status.mute_conversation": "o kute ala e ijo pi toki ni", + "status.pin": "o sewi lon lipu sina", + "status.pinned": "toki sewi", + "status.reblog": "o wawa", + "status.share": "o pana tawa ante", "status.show_less": "o lili e ni", "status.show_less_all": "o lili e ale", "status.show_more": "o suli e ni", "status.show_more_all": "o suli e ale", - "status.show_original": "ijo mama pi ijo ni li seme", + "status.show_original": "o lukin e mama", + "status.translate": "o ante pi nasin toki", + "status.translated_from_with": "toki li ante tan {lang} kepeken {provider}", "status.uncached_media_warning": "lukin lili li weka", "status.unmute_conversation": "o ken kute e ijo pi toki ni", + "status.unpin": "o sewi ala lon lipu sina", + "subscribed_languages.save": "o awen e ante", + "tabs_bar.home": "lipu open", "timeline_hint.resources.statuses": "ijo pi tenpo suli", "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.", "upload_form.audio_description": "o toki e ijo kute tawa jan pi kute ala, tawa jan pi kute lili", "upload_form.description": "o toki e ijo lukin tawa jan pi lukin ala, tawa jan pi lukin lili", "upload_form.edit": "o ante", + "upload_form.thumbnail": "o ante e sitelen lili", "upload_form.video_description": "o toki e ijo kute tawa jan pi kute ala, tawa jan pi kute lili, e ijo lukin tawa jan pi lukin ala, tawa jan pi lukin lili", "upload_modal.choose_image": "o wile e sitelen", "upload_modal.description_placeholder": "mi pu jaki tan soweli", @@ -225,7 +319,12 @@ "upload_modal.preparing_ocr": "ilo li open e alasa nimi lon sitelen…", "upload_progress.label": "ilo li kama jo e ijo sina...", "upload_progress.processing": "ilo li pali…", - "username.taken": "jan ante li jo e nimi ni. sina o pali e nimi sin.", + "username.taken": "jan ante li kepeken e nimi ni. sina o kepeken e nimi sin", + "video.close": "o weka e ni", + "video.download": "o jo e ni", + "video.exit_fullscreen": "o weka tan sitelen suli", + "video.expand": "o suli e ni", + "video.hide": "o len e sitelen", "video.mute": "o kalama ala", "video.pause": "o lape e ni", "video.unmute": "o kalama" diff --git a/config/locales/activerecord.tok.yml b/config/locales/activerecord.tok.yml index 5623538ba96cec..9862a7f9532dba 100644 --- a/config/locales/activerecord.tok.yml +++ b/config/locales/activerecord.tok.yml @@ -4,3 +4,11 @@ tok: attributes: poll: expires_at: pini tenpo + user/account: + username: nimi jan + errors: + models: + account: + attributes: + username: + reserved: jan ante li jo e nimi ni diff --git a/config/locales/doorkeeper.tok.yml b/config/locales/doorkeeper.tok.yml index d15ecd21b277d6..6aef4fb34bb58d 100644 --- a/config/locales/doorkeeper.tok.yml +++ b/config/locales/doorkeeper.tok.yml @@ -1 +1,51 @@ +--- tok: + doorkeeper: + applications: + buttons: + cancel: o pini + destroy: o weka + edit: o ante + submit: o awen + confirmations: + destroy: ni li pona ala pona? + edit: + title: o ante e ilo nanpa + form: + error: 'pakala a! o lukin e ni: lipu sina li jo ala jo e pakala.' + index: + delete: o weka + empty: sina li jo e ilo nanpa ala. + name: nimi + new: o pali e ilo nanpa sin + title: ilo nanpa sina + new: + title: o pali e ilo nanpa sin + show: + title: ilo nanpa pi nimi %{name} + authorizations: + error: + title: pakala li lon. + authorized_applications: + confirmations: + revoke: ni li pona ala pona? + index: + scopes: ken + errors: + messages: + invalid_request: + missing_param: o pana e sona "%{value}". + flash: + applications: + create: + notice: sina pali e ilo nanpa. + destroy: + notice: sina weka e ilo nanpa. + update: + notice: sina ante e ilo nanpa. + authorized_applications: + destroy: + notice: sina weka e ilo nanpa tawa sina. + grouped_scopes: + access: + read: lukin taso diff --git a/config/locales/simple_form.tok.yml b/config/locales/simple_form.tok.yml index 1eb7d5be87c29f..37b0ee765a6be5 100644 --- a/config/locales/simple_form.tok.yml +++ b/config/locales/simple_form.tok.yml @@ -5,8 +5,8 @@ tok: account: display_name: nimi sina ale anu nimi sina musi. defaults: - setting_display_media_hide_all: tenpo ale la, o weka e sitelen - setting_display_media_show_all: tenpo ale la, o awen e sitelen + setting_display_media_hide_all: sitelen ale li len + setting_display_media_show_all: sitelen ale li len ala labels: defaults: expires_in: ona o moli lon diff --git a/config/locales/sk.yml b/config/locales/sk.yml index f13a15d795a981..88617967ff9918 100644 --- a/config/locales/sk.yml +++ b/config/locales/sk.yml @@ -88,7 +88,7 @@ sk: remote: Federované title: Umiestnenie login_status: Stav prihlásenia - media_attachments: Prílohy + media_attachments: Mediálne prílohy memorialize: Zmeň na "Navždy budeme spomínať" memorialized: Spomienka na memorialized_msg: Úspešne zmenené %{username} na spomienkové konto diff --git a/config/locales/tok.yml b/config/locales/tok.yml index d15ecd21b277d6..9f962d2b5344b0 100644 --- a/config/locales/tok.yml +++ b/config/locales/tok.yml @@ -1 +1,5 @@ +--- tok: + admin: + accounts: + are_you_sure: ni li pona ala pona? From 8125dae5a84e3115be6f487b337ac942c70a81f0 Mon Sep 17 00:00:00 2001 From: Claire Date: Mon, 12 Feb 2024 10:54:06 +0100 Subject: [PATCH 02/28] 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 0fb311dbb37bc8..0d9fc75e9948b2 100644 --- a/config/initializers/chewy.rb +++ b/config/initializers/chewy.rb @@ -7,7 +7,7 @@ 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 03/28] 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 daff6563e87bf0..7e21703b4a8d21 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 99c0f8b1022f01..95572a79328209 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 0ae471e02370be..42de594cdc2ea9 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 cb90252c7f73e3..f29d016b07438f 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 10328efd0e0de2..07966628514746 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 f9356fd279cc21..4a15c60ed82826 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 7270d520672a55..ba45f844532b75 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 58f6e26374ba9b..f79d63a4593d82 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 c07e75fefff0e5..4b4d1f441b3a85 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 1a6a3ecd778de6..868bb4b3a19401 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 e7e6f03cdbfbe3..443342b404760c 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 bf7da9a314070a..a85af012f3be7a 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 68e45ef47bd4bf..a4637a68109e89 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 552abb255098e1..af198d932a38f3 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 a31ad5eb1190d8..696fd5fed98f9e 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 88617967ff9918..520b64f886ec3b 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 04/28] 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 d3988d2f1a3ae1..a676ff12fcdc7e 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 05/28] 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 fb3472904855ea..351fd31ab4b249 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 06/28] 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 351fd31ab4b249..d76af5d9ef86d0 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 07/28] 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 152436b47a421c..00ca4663a848ca 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 08/28] 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 d76af5d9ef86d0..6088034d9bd88a 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 09/28] 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 95572a79328209..5a6fa175e8abe5 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 d5e8f4239eeb4c..3e4f36ba5a416b 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 d236ba49698158..547493af18d598 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 ba45f844532b75..85f62f404ae718 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 10/28] 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 427144ed8e053a..af9fc88e7bbe1d 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 11/28] 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 d84ff084b2f10f..180df9d3101ebb 100644 --- a/app/models/concerns/user/ldap_authenticable.rb +++ b/app/models/concerns/user/ldap_authenticable.rb @@ -25,7 +25,15 @@ def ldap_get_user(attributes = {}) 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 a682058ccacd99..30dc7d8aef20f6 100644 --- a/app/models/concerns/user/pam_authenticable.rb +++ b/app/models/concerns/user/pam_authenticable.rb @@ -32,7 +32,6 @@ def pam_setup(_attributes) 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 70c24336f35cfa..95fdc431ac43ea 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 12/28] 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 fe3871d2e72fbb..f9d47a205ccd9c 100644 --- a/config/initializers/doorkeeper.rb +++ b/config/initializers/doorkeeper.rb @@ -21,9 +21,14 @@ 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 00000000000000..7c2c09f3804bf3 --- /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 f8b32facb42080a9017d120e64a52c1aab8abd77 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?KMY=EF=BC=88=E9=9B=AA=E3=81=82=E3=81=99=E3=81=8B=EF=BC=89?= Date: Wed, 14 Feb 2024 09:58:45 +0900 Subject: [PATCH 13/28] =?UTF-8?q?Fix:=20#540=20emoji=5Freactions=E3=83=86?= =?UTF-8?q?=E3=83=BC=E3=83=96=E3=83=AB=E3=81=AEuri=E3=82=AB=E3=83=A9?= =?UTF-8?q?=E3=83=A0=E3=81=B8=E3=81=AE=E3=82=A4=E3=83=B3=E3=83=87=E3=83=83?= =?UTF-8?q?=E3=82=AF=E3=82=B9=E8=A8=AD=E5=AE=9A=E6=99=82=E3=80=81=E9=87=8D?= =?UTF-8?q?=E8=A4=87=E3=82=92=E5=89=8A=E9=99=A4=E3=81=99=E3=82=8B=E5=87=A6?= =?UTF-8?q?=E7=90=86=20(#543)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- ...230358_fix_uri_index_to_emoji_reactions.rb | 9 ------ ...230358_fix_uri_index_to_emoji_reactions.rb | 28 +++++++++++++++++++ 2 files changed, 28 insertions(+), 9 deletions(-) delete mode 100644 db/migrate/20240212230358_fix_uri_index_to_emoji_reactions.rb create mode 100644 db/post_migrate/20240212230358_fix_uri_index_to_emoji_reactions.rb diff --git a/db/migrate/20240212230358_fix_uri_index_to_emoji_reactions.rb b/db/migrate/20240212230358_fix_uri_index_to_emoji_reactions.rb deleted file mode 100644 index 1523f8adbb6ae2..00000000000000 --- a/db/migrate/20240212230358_fix_uri_index_to_emoji_reactions.rb +++ /dev/null @@ -1,9 +0,0 @@ -# frozen_string_literal: true - -class FixUriIndexToEmojiReactions < ActiveRecord::Migration[7.1] - disable_ddl_transaction! - - def change - add_index :emoji_reactions, :uri, unique: true, algorithm: :concurrently - end -end diff --git a/db/post_migrate/20240212230358_fix_uri_index_to_emoji_reactions.rb b/db/post_migrate/20240212230358_fix_uri_index_to_emoji_reactions.rb new file mode 100644 index 00000000000000..2a5721d814360b --- /dev/null +++ b/db/post_migrate/20240212230358_fix_uri_index_to_emoji_reactions.rb @@ -0,0 +1,28 @@ +# frozen_string_literal: true + +class FixUriIndexToEmojiReactions < ActiveRecord::Migration[7.1] + disable_ddl_transaction! + + class EmojiReaction < ApplicationRecord + end + + def up + # Remove duplications (very old kmyblue code [2023/03-04] maybe made some duplications) + duplications = EmojiReaction.where('uri IN (SELECT uri FROM emoji_reactions GROUP BY uri HAVING COUNT(*) > 1)') + .to_a.group_by(&:uri).to_h + + if duplications.any? + EmojiReaction.transaction do + duplications.each do |h| + h[1].drop(1).each(&:destroy) + end + end + end + + add_index :emoji_reactions, :uri, unique: true, algorithm: :concurrently + end + + def down + remove_index :emoji_reactions, :uri + end +end From 554e2a019e40755fbe6ae02fbf5cfc1862550e20 Mon Sep 17 00:00:00 2001 From: Claire Date: Wed, 14 Feb 2024 13:12:13 +0100 Subject: [PATCH 14/28] 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 bb088821fd7356..51c10a14f6e6a6 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 00000000000000..bedc8fe4c650c4 --- /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 15/28] 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 fb442e2c2d2fca..400c51a023d09b 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 95fdc431ac43ea..f706c91eff55c4 100644 --- a/app/models/user.rb +++ b/app/models/user.rb @@ -344,6 +344,16 @@ def revoke_access! 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 5ac41c0ff1dd94..845335e87341e9 100644 --- a/spec/models/user_spec.rb +++ b/spec/models/user_spec.rb @@ -420,7 +420,10 @@ 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 @@ 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 16/28] 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 707b50ef9e1c03..9b83de945bee2a 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 113bfda23043eb..396a0598f87b82 100644 --- a/app/models/concerns/user/omniauthable.rb +++ b/app/models/concerns/user/omniauthable.rb @@ -19,17 +19,18 @@ def email_present? 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 @@ def find_for_oauth(auth, signed_in_resource = nil) user end - def create_for_oauth(auth) - # Check if the user exists with provided email. 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 + private - 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 + 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' - user = User.find_by(email: email) if email_is_verified + email, email_is_verified = email_from_auth(auth) + return unless email_is_verified - return user unless user.nil? + 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 + + email, email_is_verified = email_from_auth(auth) user = User.new(user_params_from_auth(email, auth)) @@ -66,7 +83,14 @@ def create_for_oauth(auth) 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 c95a68a6f63abb..77821b78fa2550 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 70224544433c8d..d5a2ffbc869fad 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 0d37c411403bdc..b478ca1ce614f6 100644 --- a/spec/requests/omniauth_callbacks_spec.rb +++ b/spec/requests/omniauth_callbacks_spec.rb @@ -96,7 +96,7 @@ 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 17/28] 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 dd7c84207e0b1e..c2f26aee63551e 100644 --- a/lib/mastodon/version.rb +++ b/lib/mastodon/version.rb @@ -17,7 +17,7 @@ def patch 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 18/28] 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 b478ca1ce614f6..1e488b3f43fc3a 100644 --- a/spec/requests/omniauth_callbacks_spec.rb +++ b/spec/requests/omniauth_callbacks_spec.rb @@ -39,16 +39,33 @@ 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 + + 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 - expect(Identity.find_by(user: User.last).uid).to eq('123') - expect(response).to redirect_to(root_path) + 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 19/28] 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 267f0ed29578ab..6cf722b355af8b 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 20/28] 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 9b83de945bee2a..9d496220a3d277 100644 --- a/app/controllers/auth/omniauth_callbacks_controller.rb +++ b/app/controllers/auth/omniauth_callbacks_controller.rb @@ -17,6 +17,9 @@ def self.provides_callback_for(provider) 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 4439397c8eead1..61bd33851b6fca 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 1e488b3f43fc3a..095535e48598e0 100644 --- a/spec/requests/omniauth_callbacks_spec.rb +++ b/spec/requests/omniauth_callbacks_spec.rb @@ -60,11 +60,13 @@ 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 0508671f4eec4fa3aa35cc864201e7c56fd666e1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?KMY=EF=BC=88=E9=9B=AA=E3=81=82=E3=81=99=E3=81=8B=EF=BC=89?= Date: Thu, 15 Feb 2024 12:34:25 +0900 Subject: [PATCH 21/28] =?UTF-8?q?Change:=20#475=20=E7=B5=B5=E6=96=87?= =?UTF-8?q?=E5=AD=97=E3=83=AA=E3=82=A2=E3=82=AF=E3=82=B7=E3=83=A7=E3=83=B3?= =?UTF-8?q?=E3=81=AE=E7=B5=B5=E6=96=87=E5=AD=97=E3=82=B5=E3=82=A4=E3=82=BA?= =?UTF-8?q?=E3=82=92=E3=82=82=E3=81=86=E5=B0=91=E3=81=97=E5=A4=A7=E3=81=8D?= =?UTF-8?q?=E3=81=8F=20(#550)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/javascript/styles/mastodon/components.scss | 18 +++++++++--------- app/javascript/styles/mastodon/tables.scss | 2 +- app/javascript/styles/mastodon/widgets.scss | 2 +- 3 files changed, 11 insertions(+), 11 deletions(-) diff --git a/app/javascript/styles/mastodon/components.scss b/app/javascript/styles/mastodon/components.scss index a0f3dbfa8007d8..98b0cf369699a7 100644 --- a/app/javascript/styles/mastodon/components.scss +++ b/app/javascript/styles/mastodon/components.scss @@ -940,7 +940,7 @@ body > [data-popper-placement] { object-fit: contain; margin: -0.2ex 0.15em 0.2ex; min-width: 20px; - max-width: min(8em, 100%); + max-width: min(10em, 100%); height: 20px; img { @@ -983,7 +983,7 @@ body > [data-popper-placement] { .emojione { min-width: 20px; - max-width: min(8em, 100%); + max-width: min(10em, 100%); height: 20px; margin: -3px 0 0; } @@ -1225,7 +1225,7 @@ body > [data-popper-placement] { .emojione { min-width: 20px; - max-width: min(8em, 100%); + max-width: min(10em, 100%); height: 20px; margin: -3px 0 0; } @@ -1628,7 +1628,7 @@ body > [data-popper-placement] { display: flex; justify-items: center; align-items: center; - height: 24px; + height: 28px; &.toggled { background: $emoji-reaction-selected-color; @@ -1636,7 +1636,7 @@ body > [data-popper-placement] { > .emoji { display: block; - height: 20px; + height: 24px; transition: transform 0.2s ease; &:hover { @@ -1646,7 +1646,7 @@ body > [data-popper-placement] { img { margin-top: 0; margin-bottom: 0; - height: 20px; + height: 24px; } } @@ -1701,7 +1701,7 @@ body > [data-popper-placement] { .emojione { min-width: 24px; - max-width: min(8em, 100%); + max-width: min(10em, 100%); height: 24px; margin: -1px 0 0; } @@ -6538,7 +6538,7 @@ a.status-card { .emojione { min-width: 24px; - max-width: min(8em, 100%); + max-width: min(10em, 100%); height: 24px; margin: -1px 0 0; } @@ -7944,7 +7944,7 @@ noscript { .emojione { min-width: 22px; - max-width: min(8em, 100%); + max-width: min(10em, 100%); height: 22px; } diff --git a/app/javascript/styles/mastodon/tables.scss b/app/javascript/styles/mastodon/tables.scss index 572d66229bbeec..25206f9a5de70e 100644 --- a/app/javascript/styles/mastodon/tables.scss +++ b/app/javascript/styles/mastodon/tables.scss @@ -305,7 +305,7 @@ a.table-action-link { .emojione { min-width: 32px; - max-width: min(8em, 100%); + max-width: min(10em, 100%); height: 32px; } } diff --git a/app/javascript/styles/mastodon/widgets.scss b/app/javascript/styles/mastodon/widgets.scss index 75d0c7ee3dfc11..d35b36f28bbc60 100644 --- a/app/javascript/styles/mastodon/widgets.scss +++ b/app/javascript/styles/mastodon/widgets.scss @@ -37,7 +37,7 @@ .emojione { min-width: 20px; - max-width: min(8em, 100%); + max-width: min(10em, 100%); height: 20px; margin: -3px 0 0; margin-inline-start: 0.075em; From dae8985e418ddd40fd11e0b841bb5fc20820e5ef Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?KMY=EF=BC=88=E9=9B=AA=E3=81=82=E3=81=99=E3=81=8B=EF=BC=89?= Date: Thu, 15 Feb 2024 12:34:38 +0900 Subject: [PATCH 22/28] =?UTF-8?q?Fix:=20#531=20=E6=8A=95=E7=A8=BF=E3=83=95?= =?UTF-8?q?=E3=82=A9=E3=83=BC=E3=83=A0=E3=81=AE=E5=85=AC=E9=96=8B=E7=AF=84?= =?UTF-8?q?=E5=9B=B2=E3=81=AE=E9=81=B8=E6=8A=9E=E8=82=A2=E3=81=A7=E3=80=81?= =?UTF-8?q?=E3=82=B9=E3=83=9E=E3=83=9B=E3=81=8B=E3=82=89=E8=A6=8B=E3=82=8B?= =?UTF-8?q?=E3=81=A8=E5=B8=B8=E3=81=AB=E3=80=8C=E3=83=AD=E3=82=B0=E3=82=A4?= =?UTF-8?q?=E3=83=B3=E3=83=A6=E3=83=BC=E3=82=B6=E3=83=BC=E3=81=AE=E3=81=BF?= =?UTF-8?q?=E3=80=8D=E3=81=8C=E8=A1=A8=E7=A4=BA=E3=81=95=E3=82=8C=E3=82=8B?= =?UTF-8?q?=20(#549)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../features/compose/components/privacy_dropdown.jsx | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/app/javascript/mastodon/features/compose/components/privacy_dropdown.jsx b/app/javascript/mastodon/features/compose/components/privacy_dropdown.jsx index ebfe62051770d7..97e1e921edf88d 100644 --- a/app/javascript/mastodon/features/compose/components/privacy_dropdown.jsx +++ b/app/javascript/mastodon/features/compose/components/privacy_dropdown.jsx @@ -271,15 +271,15 @@ class PrivacyDropdown extends PureComponent { this.options = this.options.filter((opt) => !['mutual', 'circle'].includes(opt.value)); } - this.selectableOptions = [...this.options]; - if (!enableLoginPrivacy) { - this.selectableOptions = this.selectableOptions.filter((opt) => opt.value !== 'login'); + this.options = this.options.filter((opt) => opt.value !== 'login'); } if (!enableLocalPrivacy) { - this.selectableOptions = this.selectableOptions.filter((opt) => opt.value !== 'public_unlisted'); + this.options = this.options.filter((opt) => opt.value !== 'public_unlisted'); } + + this.selectableOptions = [...this.options]; } setTargetRef = c => { From a51da9243ee3d85593d22127a0d2e6d2017f4222 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?KMY=EF=BC=88=E9=9B=AA=E3=81=82=E3=81=99=E3=81=8B=EF=BC=89?= Date: Thu, 15 Feb 2024 12:42:04 +0900 Subject: [PATCH 23/28] =?UTF-8?q?Change:=20=E3=82=A4=E3=83=B3=E3=82=B9?= =?UTF-8?q?=E3=82=BF=E3=83=B3=E3=82=B9=E6=83=85=E5=A0=B1=E5=8F=96=E5=BE=97?= =?UTF-8?q?Worker=E3=81=AE=E3=82=AD=E3=83=A5=E3=83=BC=E3=82=92`pull`?= =?UTF-8?q?=E3=81=AB=E5=A4=89=E6=9B=B4=20(#552)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/workers/activitypub/fetch_instance_info_worker.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/workers/activitypub/fetch_instance_info_worker.rb b/app/workers/activitypub/fetch_instance_info_worker.rb index bc9a1a48157e13..1b25c2a5512392 100644 --- a/app/workers/activitypub/fetch_instance_info_worker.rb +++ b/app/workers/activitypub/fetch_instance_info_worker.rb @@ -6,7 +6,7 @@ class ActivityPub::FetchInstanceInfoWorker include Redisable include Lockable - sidekiq_options queue: 'push', retry: 2 + sidekiq_options queue: 'pull', retry: 2 SUPPORTED_NOTEINFO_RELS = ['http://nodeinfo.diaspora.software/ns/schema/2.0', 'http://nodeinfo.diaspora.software/ns/schema/2.1'].freeze From 8a29aef8428e863a79edb9123375e722dabf091f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?KMY=EF=BC=88=E9=9B=AA=E3=81=82=E3=81=99=E3=81=8B=EF=BC=89?= Date: Thu, 15 Feb 2024 12:53:11 +0900 Subject: [PATCH 24/28] =?UTF-8?q?Add:=20#446=20=E3=82=B9=E3=82=BF=E3=83=B3?= =?UTF-8?q?=E3=83=97=E4=B8=8A=E9=99=90=E3=81=AE=E8=A8=AD=E5=AE=9A=E3=82=92?= =?UTF-8?q?=E3=80=81=E3=83=AD=E3=83=BC=E3=82=AB=E3=83=AB=E3=83=A6=E3=83=BC?= =?UTF-8?q?=E3=82=B6=E3=83=BC=E5=90=91=E3=81=91=E3=81=A8=E5=A4=96=E9=83=A8?= =?UTF-8?q?=E3=82=B5=E3=83=BC=E3=83=90=E3=83=BC=E3=83=A6=E3=83=BC=E3=82=B6?= =?UTF-8?q?=E3=83=BC=E5=90=91=E3=81=91=E3=81=AE=E3=82=82=E3=81=AE=E3=81=AB?= =?UTF-8?q?=E5=88=86=E3=81=91=E3=82=8B=20(#553)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/lib/activitypub/activity/like.rb | 2 +- app/models/emoji_reaction.rb | 1 + app/serializers/rest/instance_serializer.rb | 1 + app/serializers/rest/v1/instance_serializer.rb | 1 + 4 files changed, 4 insertions(+), 1 deletion(-) diff --git a/app/lib/activitypub/activity/like.rb b/app/lib/activitypub/activity/like.rb index 065a2a7d9aa7e5..dd02e9ffcf7812 100644 --- a/app/lib/activitypub/activity/like.rb +++ b/app/lib/activitypub/activity/like.rb @@ -46,7 +46,7 @@ def process_emoji_reaction reaction = nil with_redis_lock("emoji_reaction:#{@original_status.id}") do - return if EmojiReaction.where(account: @account, status: @original_status).count >= EmojiReaction::EMOJI_REACTION_PER_ACCOUNT_LIMIT + return if EmojiReaction.where(account: @account, status: @original_status).count >= EmojiReaction::EMOJI_REACTION_PER_REMOTE_ACCOUNT_LIMIT return if EmojiReaction.find_by(account: @account, status: @original_status, name: shortcode) reaction = @original_status.emoji_reactions.create!(account: @account, name: shortcode, custom_emoji: emoji, uri: @json['id']) diff --git a/app/models/emoji_reaction.rb b/app/models/emoji_reaction.rb index 7eebe81cb1f8d5..2534cfebe2f111 100644 --- a/app/models/emoji_reaction.rb +++ b/app/models/emoji_reaction.rb @@ -19,6 +19,7 @@ class EmojiReaction < ApplicationRecord EMOJI_REACTION_LIMIT = 32_767 EMOJI_REACTION_PER_ACCOUNT_LIMIT = ENV.fetch('EMOJI_REACTION_PER_ACCOUNT_LIMIT', 3).to_i + EMOJI_REACTION_PER_REMOTE_ACCOUNT_LIMIT = ENV.fetch('EMOJI_REACTION_PER_REMOTE_ACCOUNT_LIMIT', 3).to_i update_index('statuses', :status) diff --git a/app/serializers/rest/instance_serializer.rb b/app/serializers/rest/instance_serializer.rb index 38010e49493e4f..c3070b6852f4fc 100644 --- a/app/serializers/rest/instance_serializer.rb +++ b/app/serializers/rest/instance_serializer.rb @@ -90,6 +90,7 @@ def configuration emoji_reactions: { max_reactions: EmojiReaction::EMOJI_REACTION_LIMIT, max_reactions_per_account: EmojiReaction::EMOJI_REACTION_PER_ACCOUNT_LIMIT, + max_reactions_per_remote_account: EmojiReaction::EMOJI_REACTION_PER_REMOTE_ACCOUNT_LIMIT, }, reaction_deck: { diff --git a/app/serializers/rest/v1/instance_serializer.rb b/app/serializers/rest/v1/instance_serializer.rb index 74ceec385b5a3e..57a1e807137158 100644 --- a/app/serializers/rest/v1/instance_serializer.rb +++ b/app/serializers/rest/v1/instance_serializer.rb @@ -92,6 +92,7 @@ def configuration emoji_reactions: { max_reactions: EmojiReaction::EMOJI_REACTION_LIMIT, max_reactions_per_account: EmojiReaction::EMOJI_REACTION_PER_ACCOUNT_LIMIT, + max_reactions_per_remote_account: EmojiReaction::EMOJI_REACTION_PER_REMOTE_ACCOUNT_LIMIT, }, reaction_deck: { From 91cb329e1888fe24466f5331452d0a31682a82f5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?KMY=EF=BC=88=E9=9B=AA=E3=81=82=E3=81=99=E3=81=8B=EF=BC=89?= Date: Thu, 15 Feb 2024 12:59:27 +0900 Subject: [PATCH 25/28] =?UTF-8?q?Change:=20#420=20=E7=B5=B5=E6=96=87?= =?UTF-8?q?=E5=AD=97=E3=83=AA=E3=82=A2=E3=82=AF=E3=82=B7=E3=83=A7=E3=83=B3?= =?UTF-8?q?=E3=82=B9=E3=83=88=E3=83=AA=E3=83=BC=E3=83=9F=E3=83=B3=E3=82=B0?= =?UTF-8?q?Worker=E3=81=AE=E3=82=AD=E3=83=A5=E3=83=BC=E3=81=AE=E7=A8=AE?= =?UTF-8?q?=E9=A1=9E=E3=82=92=E6=96=B0=E8=A6=8F=E4=BD=9C=E6=88=90=20(#551)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Change: #420 絵文字リアクションストリーミングWorkerのキューの種類を`push`に変更 * `perishable`キュー新規作成に変更 * 優先順位を`ingress`と一緒に --- app/lib/admin/system_check/sidekiq_process_check.rb | 1 + app/workers/delivery_emoji_reaction_worker.rb | 2 ++ config/sidekiq.yml | 1 + spec/lib/admin/system_check/sidekiq_process_check_spec.rb | 4 ++-- 4 files changed, 6 insertions(+), 2 deletions(-) diff --git a/app/lib/admin/system_check/sidekiq_process_check.rb b/app/lib/admin/system_check/sidekiq_process_check.rb index d577b3bf3c51c7..4c7447e4da04f2 100644 --- a/app/lib/admin/system_check/sidekiq_process_check.rb +++ b/app/lib/admin/system_check/sidekiq_process_check.rb @@ -8,6 +8,7 @@ class Admin::SystemCheck::SidekiqProcessCheck < Admin::SystemCheck::BaseCheck pull scheduler ingress + perishable ).freeze def skip? diff --git a/app/workers/delivery_emoji_reaction_worker.rb b/app/workers/delivery_emoji_reaction_worker.rb index e38b61d9acd548..6720d4623caecf 100644 --- a/app/workers/delivery_emoji_reaction_worker.rb +++ b/app/workers/delivery_emoji_reaction_worker.rb @@ -6,6 +6,8 @@ class DeliveryEmojiReactionWorker include Lockable include AccountScope + sidekiq_options queue: 'perishable' + def perform(payload_json, status_id, reacted_account_id) return unless Setting.enable_emoji_reaction diff --git a/config/sidekiq.yml b/config/sidekiq.yml index 3f9cbd9a7a5bef..f083e372c18406 100644 --- a/config/sidekiq.yml +++ b/config/sidekiq.yml @@ -4,6 +4,7 @@ - [default, 8] - [push, 6] - [ingress, 4] + - [perishable, 4] - [mailers, 2] - [pull] - [scheduler] diff --git a/spec/lib/admin/system_check/sidekiq_process_check_spec.rb b/spec/lib/admin/system_check/sidekiq_process_check_spec.rb index 9bd9daddf6722f..42a2922355bec0 100644 --- a/spec/lib/admin/system_check/sidekiq_process_check_spec.rb +++ b/spec/lib/admin/system_check/sidekiq_process_check_spec.rb @@ -35,11 +35,11 @@ describe 'message' do it 'sends values to message instance' do - allow(Admin::SystemCheck::Message).to receive(:new).with(:sidekiq_process_check, 'default, push, mailers, pull, scheduler, ingress') + allow(Admin::SystemCheck::Message).to receive(:new).with(:sidekiq_process_check, 'default, push, mailers, pull, scheduler, ingress, perishable') check.message - expect(Admin::SystemCheck::Message).to have_received(:new).with(:sidekiq_process_check, 'default, push, mailers, pull, scheduler, ingress') + expect(Admin::SystemCheck::Message).to have_received(:new).with(:sidekiq_process_check, 'default, push, mailers, pull, scheduler, ingress, perishable') end end end From 0ca2a73fd26534fda8ffdfbb52ba81cee9324edd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?KMY=EF=BC=88=E9=9B=AA=E3=81=82=E3=81=99=E3=81=8B=EF=BC=89?= Date: Fri, 16 Feb 2024 11:44:11 +0900 Subject: [PATCH 26/28] =?UTF-8?q?Fix:=20=E6=96=B0=E8=A6=8F=E7=99=BB?= =?UTF-8?q?=E9=8C=B2=E5=88=B6=E9=99=90=E3=82=92=E3=81=8B=E3=81=91=E3=81=A6?= =?UTF-8?q?=E3=81=84=E3=82=8B=E5=A0=B4=E5=90=88=E3=80=81=E6=8B=9B=E5=BE=85?= =?UTF-8?q?=E3=81=95=E3=82=8C=E3=81=A6=E3=82=82=E7=99=BB=E9=8C=B2=E3=81=A7?= =?UTF-8?q?=E3=81=8D=E3=81=AA=E3=81=84=E5=95=8F=E9=A1=8C=20(#558)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/controllers/auth/confirmations_controller.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/controllers/auth/confirmations_controller.rb b/app/controllers/auth/confirmations_controller.rb index fdbde5d730b029..a99dceeb25b3ee 100644 --- a/app/controllers/auth/confirmations_controller.rb +++ b/app/controllers/auth/confirmations_controller.rb @@ -17,7 +17,7 @@ class Auth::ConfirmationsController < Devise::ConfirmationsController skip_before_action :require_functional! def show - if reach_registrations_limit? + if reach_registrations_limit? && !current_user&.valid_invitation? render :limitation_error return end From 7421c89431beaff6356913bb0debc2d5a8641915 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?KMY=EF=BC=88=E9=9B=AA=E3=81=82=E3=81=99=E3=81=8B=EF=BC=89?= Date: Fri, 16 Feb 2024 17:52:59 +0900 Subject: [PATCH 27/28] =?UTF-8?q?Add:=20#545=20NG=E3=83=AF=E3=83=BC?= =?UTF-8?q?=E3=83=89=E6=8C=87=E5=AE=9A=E3=81=A7=E5=AE=9F=E9=9A=9B=E3=81=AB?= =?UTF-8?q?=E9=99=A4=E5=A4=96=E3=81=95=E3=82=8C=E3=81=9F=E6=8A=95=E7=A8=BF?= =?UTF-8?q?=E3=81=AE=E3=83=AD=E3=82=B0=20(#561)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../admin/ngword_histories_controller.rb | 19 +++++ app/lib/activitypub/activity/create.rb | 4 +- app/lib/activitypub/parser/status_parser.rb | 4 + app/models/admin/ng_word.rb | 29 +++++-- app/models/ngword_history.rb | 21 ++++++ app/models/user.rb | 2 - .../activitypub/process_account_service.rb | 3 +- .../process_status_update_service.rb | 4 +- app/views/admin/ng_words/show.html.haml | 8 +- .../admin/ngword_histories/_history.html.haml | 30 ++++++++ .../admin/ngword_histories/index.html.haml | 22 ++++++ config/locales/en.yml | 8 ++ config/locales/ja.yml | 8 ++ config/navigation.rb | 2 +- config/routes/admin.rb | 1 + .../20240216042730_create_ngword_histories.rb | 17 +++++ db/schema.rb | 13 +++- spec/lib/activitypub/activity/create_spec.rb | 75 +++++++++++++++++++ .../process_account_service_spec.rb | 9 +++ 19 files changed, 262 insertions(+), 17 deletions(-) create mode 100644 app/controllers/admin/ngword_histories_controller.rb create mode 100644 app/models/ngword_history.rb create mode 100644 app/views/admin/ngword_histories/_history.html.haml create mode 100644 app/views/admin/ngword_histories/index.html.haml create mode 100644 db/migrate/20240216042730_create_ngword_histories.rb diff --git a/app/controllers/admin/ngword_histories_controller.rb b/app/controllers/admin/ngword_histories_controller.rb new file mode 100644 index 00000000000000..90f13db2fe7927 --- /dev/null +++ b/app/controllers/admin/ngword_histories_controller.rb @@ -0,0 +1,19 @@ +# frozen_string_literal: true + +module Admin + class NgwordHistoriesController < BaseController + before_action :set_histories + + PER_PAGE = 20 + + def index + authorize :ng_words, :show? + end + + private + + def set_histories + @histories = NgwordHistory.order(id: :desc).page(params[:page]).per(PER_PAGE) + end + end +end diff --git a/app/lib/activitypub/activity/create.rb b/app/lib/activitypub/activity/create.rb index 1ef7bd29bc450f..d3f9fea0be0015 100644 --- a/app/lib/activitypub/activity/create.rb +++ b/app/lib/activitypub/activity/create.rb @@ -143,9 +143,9 @@ def process_status_params end def valid_status? - valid = !Admin::NgWord.reject?("#{@params[:spoiler_text]}\n#{@params[:text]}") && !Admin::NgWord.hashtag_reject?(@tags.size) + valid = !Admin::NgWord.reject?("#{@params[:spoiler_text]}\n#{@params[:text]}", uri: @params[:uri], target_type: :status, public: @status_parser.distributable_visibility?) && !Admin::NgWord.hashtag_reject?(@tags.size) - valid = !Admin::NgWord.stranger_mention_reject?("#{@params[:spoiler_text]}\n#{@params[:text]}") if valid && mention_to_local_but_not_followed? + valid = !Admin::NgWord.stranger_mention_reject?("#{@params[:spoiler_text]}\n#{@params[:text]}", uri: @params[:uri], target_type: :status, public: @status_parser.distributable_visibility?) if valid && mention_to_local_but_not_followed? valid end diff --git a/app/lib/activitypub/parser/status_parser.rb b/app/lib/activitypub/parser/status_parser.rb index 1d5b2f48c67c28..a77686dcb3a2a2 100644 --- a/app/lib/activitypub/parser/status_parser.rb +++ b/app/lib/activitypub/parser/status_parser.rb @@ -92,6 +92,10 @@ def visibility end end + def distributable_visibility? + %i(public public_unlisted unlisted login).include?(visibility) + end + def searchability from_audience = searchability_from_audience return from_audience if from_audience diff --git a/app/models/admin/ng_word.rb b/app/models/admin/ng_word.rb index 801c12094ee18b..5be03409d6d9a8 100644 --- a/app/models/admin/ng_word.rb +++ b/app/models/admin/ng_word.rb @@ -2,8 +2,16 @@ class Admin::NgWord class << self - def reject?(text) - ng_words.any? { |word| include?(text, word) } + def reject?(text, **options) + hit_word = ng_words.detect { |word| include?(text, word) ? word : nil } + record!(:ng_words, text, hit_word, options) if hit_word.present? + hit_word.present? + end + + def stranger_mention_reject?(text, **options) + hit_word = ng_words_for_stranger_mention.detect { |word| include?(text, word) ? word : nil } + record!(:ng_words_for_stranger_mention, text, hit_word, options) if hit_word.present? + hit_word.present? end def reject_with_custom_words?(text, custom_ng_words) @@ -18,10 +26,6 @@ def hashtag_reject_with_extractor?(text) hashtag_reject?(Extractor.extract_hashtags(text)&.size || 0) end - def stranger_mention_reject?(text) - ng_words_for_stranger_mention.any? { |word| include?(text, word) } - end - private def include?(text, word) @@ -44,5 +48,18 @@ def post_hash_tags_max value = Setting.post_hash_tags_max value.is_a?(Integer) && value.positive? ? value : 0 end + + def record!(type, text, keyword, options) + return unless options[:uri] && options[:target_type] + return if options.key?(:public) && !options.delete(:public) + + return if NgwordHistory.where('created_at > ?', 1.day.ago).exists?(uri: options[:uri], keyword: options[:keyword]) + + NgwordHistory.create(options.merge({ + reason: type, + text: text, + keyword: keyword, + })) + end end end diff --git a/app/models/ngword_history.rb b/app/models/ngword_history.rb new file mode 100644 index 00000000000000..992d3c16fb7833 --- /dev/null +++ b/app/models/ngword_history.rb @@ -0,0 +1,21 @@ +# frozen_string_literal: true + +# == Schema Information +# +# Table name: ngword_histories +# +# id :bigint(8) not null, primary key +# uri :string not null +# target_type :integer not null +# reason :integer not null +# text :string not null +# keyword :string not null +# created_at :datetime not null +# updated_at :datetime not null +# +class NgwordHistory < ApplicationRecord + include Paginable + + enum target_type: { status: 0, account_note: 1, account_name: 2 }, _suffix: :blocked + enum reason: { ng_words: 0, ng_words_for_stranger_mention: 1 }, _prefix: :within +end diff --git a/app/models/user.rb b/app/models/user.rb index 3ed618ac5ee8c0..2d20ca040137ab 100644 --- a/app/models/user.rb +++ b/app/models/user.rb @@ -14,7 +14,6 @@ # sign_in_count :integer default(0), not null # current_sign_in_at :datetime # last_sign_in_at :datetime -# admin :boolean default(FALSE), not null # confirmation_token :string # confirmed_at :datetime # confirmation_sent_at :datetime @@ -29,7 +28,6 @@ # otp_backup_codes :string is an Array # account_id :bigint(8) not null # disabled :boolean default(FALSE), not null -# moderator :boolean default(FALSE), not null # invite_id :bigint(8) # chosen_languages :string is an Array # created_by_application_id :bigint(8) diff --git a/app/services/activitypub/process_account_service.rb b/app/services/activitypub/process_account_service.rb index 697bca05432b20..5b1cfe2f59383c 100644 --- a/app/services/activitypub/process_account_service.rb +++ b/app/services/activitypub/process_account_service.rb @@ -133,7 +133,8 @@ def set_immediate_attributes! def valid_account? display_name = @json['name'] || '' note = @json['summary'] || '' - !Admin::NgWord.reject?(display_name) && !Admin::NgWord.reject?(note) + !Admin::NgWord.reject?(display_name, uri: @uri, target_type: :account_name) && + !Admin::NgWord.reject?(note, uri: @uri, target_type: :account_note) end def set_fetchable_key! diff --git a/app/services/activitypub/process_status_update_service.rb b/app/services/activitypub/process_status_update_service.rb index 358a51f6c3231a..296f87b9cfa370 100644 --- a/app/services/activitypub/process_status_update_service.rb +++ b/app/services/activitypub/process_status_update_service.rb @@ -161,11 +161,11 @@ def update_poll!(allow_significant_changes: true) end def valid_status? - !Admin::NgWord.reject?("#{@status_parser.spoiler_text}\n#{@status_parser.text}") && !Admin::NgWord.hashtag_reject?(@raw_tags.size) + !Admin::NgWord.reject?("#{@status_parser.spoiler_text}\n#{@status_parser.text}", uri: @status.uri, target_type: :status) && !Admin::NgWord.hashtag_reject?(@raw_tags.size) end def validate_status_mentions! - raise AbortError if mention_to_stranger? && Admin::NgWord.stranger_mention_reject?("#{@status.spoiler_text}\n#{@status.text}") + raise AbortError if mention_to_stranger? && Admin::NgWord.stranger_mention_reject?("#{@status.spoiler_text}\n#{@status.text}", uri: @status.uri, target_type: :status) end def mention_to_stranger? diff --git a/app/views/admin/ng_words/show.html.haml b/app/views/admin/ng_words/show.html.haml index 2a81eec057b1e5..8b7c943f64dd94 100644 --- a/app/views/admin/ng_words/show.html.haml +++ b/app/views/admin/ng_words/show.html.haml @@ -7,14 +7,18 @@ = simple_form_for @admin_settings, url: admin_ng_words_path, html: { method: :post } do |f| = render 'shared/error_messages', object: @admin_settings + %p.hint + = t 'admin.ng_words.history_hint' + = link_to t('admin.ngword_histories.title'), admin_ngword_histories_path + .fields-group - = f.input :ng_words_for_stranger_mention, wrapper: :with_label, as: :text, input_html: { rows: 12 }, label: t('admin.ng_words.keywords_for_stranger_mention'), hint: t('admin.ng_words.keywords_for_stranger_mention_hint') + = f.input :ng_words_for_stranger_mention, wrapper: :with_label, as: :text, input_html: { rows: 10 }, label: t('admin.ng_words.keywords_for_stranger_mention'), hint: t('admin.ng_words.keywords_for_stranger_mention_hint') .fields-group = f.input :stranger_mention_from_local_ng, wrapper: :with_label, as: :boolean, label: t('admin.ng_words.stranger_mention_from_local_ng'), hint: t('admin.ng_words.stranger_mention_from_local_ng_hint') .fields-group - = f.input :ng_words, wrapper: :with_label, as: :text, input_html: { rows: 12 }, label: t('admin.ng_words.keywords'), hint: t('admin.ng_words.keywords_hint') + = f.input :ng_words, wrapper: :with_label, as: :text, input_html: { rows: 10 }, label: t('admin.ng_words.keywords'), hint: t('admin.ng_words.keywords_hint') .fields-group = f.input :post_hash_tags_max, wrapper: :with_label, as: :integer, label: t('admin.ng_words.post_hash_tags_max') diff --git a/app/views/admin/ngword_histories/_history.html.haml b/app/views/admin/ngword_histories/_history.html.haml new file mode 100644 index 00000000000000..f781924683b880 --- /dev/null +++ b/app/views/admin/ngword_histories/_history.html.haml @@ -0,0 +1,30 @@ +.batch-table__row + %label.batch-table__row__select.batch-checkbox + -# = f.check_box :history_ids, { multiple: true, include_hidden: false }, history.id + .batch-table__row__content + .status__content>< + = html_aware_format(history.text, false) + + .detailed-status__meta + %span.negative-hint= history.keyword + · + - if history.within_ng_words? + = t('admin.ng_words.keywords') + - elsif history.within_ng_words_for_stranger_mention? + = t('admin.ng_words.keywords_for_stranger_mention') + + %br/ + + %time.formatted{ datetime: history.created_at.iso8601, title: l(history.created_at) }= l(history.created_at) + · + - if history.account_note_blocked? + = t('admin.ngword_history.target_types.account_note') + - elsif history.account_name_blocked? + = t('admin.ngword_history.target_types.account_name') + - elsif history.status_blocked? + = t('admin.ngword_history.target_types.status') + · + = history.uri + -# if history.application + = history.application.name + · diff --git a/app/views/admin/ngword_histories/index.html.haml b/app/views/admin/ngword_histories/index.html.haml new file mode 100644 index 00000000000000..27442441f4d4f1 --- /dev/null +++ b/app/views/admin/ngword_histories/index.html.haml @@ -0,0 +1,22 @@ +- content_for :page_title do + = t('admin.ngword_histories.title') + +.filters + .back-link + = link_to admin_ng_words_path do + = fa_icon 'chevron-left fw' + = t('admin.ngword_histories.back_to_ng_words') + +%hr.spacer/ + +.batch-table + .batch-table__toolbar + %label.batch-table__toolbar__select.batch-checkbox-all + = check_box_tag :batch_checkbox_all, nil, false + .batch-table__body + - if @histories.empty? + = nothing_here 'nothing-here--under-tabs' + - else + = render partial: 'admin/ngword_histories/history', collection: @histories + += paginate @histories diff --git a/config/locales/en.yml b/config/locales/en.yml index dde3e35fa08285..a8b0c0ff06ded0 100644 --- a/config/locales/en.yml +++ b/config/locales/en.yml @@ -642,6 +642,7 @@ en: title: Media attachments ng_words: hide_local_users_for_anonymous: Hide timeline local user posts from anonymous + history_hint: We recommend that you regularly check your NG words to make sure that you have not specified the NG words incorrectly. keywords: Reject keywords keywords_for_stranger_mention: Reject keywords when mention/reply from strangers keywords_for_stranger_mention_hint: Currently this words are checked posts from other servers only. @@ -651,6 +652,13 @@ en: stranger_mention_from_local_ng_hint: サーバーの登録が承認制でない場合、あなたのサーバーにもスパムが入り込む可能性があります test_error: Testing is returned any errors title: NG words and against spams + ngword_histories: + back_to_ng_words: NG words and against spams + target_types: + account_name: Account name + account_note: Account note + status: Post + title: NG words history relationships: title: "%{acct}'s relationships" relays: diff --git a/config/locales/ja.yml b/config/locales/ja.yml index 901bacac9300f0..34d8a56300563b 100644 --- a/config/locales/ja.yml +++ b/config/locales/ja.yml @@ -635,6 +635,7 @@ ja: title: 投稿された画像 ng_words: hide_local_users_for_anonymous: ログインしていない状態でローカルユーザーの投稿をタイムラインから取得できないようにする + history_hint: 設定されたNGワードによって実際に拒否された投稿などは、履歴より確認できます。NGワードの指定に誤りがないか定期的に確認することをおすすめします。 keywords: 投稿できないキーワード keywords_for_stranger_mention: フォローしていないアカウントへのメンションで利用できないキーワード keywords_for_stranger_mention_hint: フォローしていないアカウントへのメンションにのみ適用されます。現状は外部サーバーから来た投稿のみに適用されます @@ -644,6 +645,13 @@ ja: stranger_mention_from_local_ng_hint: サーバーの登録が承認制でない場合、あなたのサーバーにもスパムが入り込む可能性があります test_error: NGワードのテストに失敗しました。正規表現のミスが含まれているかもしれません title: NGワードとスパム + ngword_histories: + back_to_ng_words: NGワードとスパム + target_types: + account_name: アカウントの名前 + account_note: アカウントの説明文 + status: 投稿 + title: NGワード検出履歴 relationships: title: "%{acct} さんのフォロー・フォロワー" relays: diff --git a/config/navigation.rb b/config/navigation.rb index 2fa9a6b4f9edbe..00d048d0392725 100644 --- a/config/navigation.rb +++ b/config/navigation.rb @@ -49,7 +49,7 @@ n.item :moderation, safe_join([fa_icon('gavel fw'), t('moderation.title')]), nil, if: -> { current_user.can?(:manage_reports, :view_audit_log, :manage_users, :manage_invites, :manage_taxonomies, :manage_federation, :manage_blocks, :manage_ng_words, :manage_sensitive_words) && !self_destruct } do |s| s.item :reports, safe_join([fa_icon('flag fw'), t('admin.reports.title')]), admin_reports_path, highlights_on: %r{/admin/reports}, if: -> { current_user.can?(:manage_reports) } s.item :accounts, safe_join([fa_icon('users fw'), t('admin.accounts.title')]), admin_accounts_path(origin: 'local'), highlights_on: %r{/admin/accounts|/admin/pending_accounts|/admin/disputes|/admin/users}, if: -> { current_user.can?(:manage_users) } - s.item :ng_words, safe_join([fa_icon('list fw'), t('admin.ng_words.title')]), admin_ng_words_path, highlights_on: %r{/admin/ng_words}, if: -> { current_user.can?(:manage_ng_words) } + s.item :ng_words, safe_join([fa_icon('list fw'), t('admin.ng_words.title')]), admin_ng_words_path, highlights_on: %r{/admin/(ng_words|ngword_histories)}, if: -> { current_user.can?(:manage_ng_words) } s.item :sensitive_words, safe_join([fa_icon('list fw'), t('admin.sensitive_words.title')]), admin_sensitive_words_path, highlights_on: %r{/admin/sensitive_words}, if: -> { current_user.can?(:manage_sensitive_words) } s.item :invites, safe_join([fa_icon('user-plus fw'), t('admin.invites.title')]), admin_invites_path, if: -> { current_user.can?(:manage_invites) } s.item :follow_recommendations, safe_join([fa_icon('user-plus fw'), t('admin.follow_recommendations.title')]), admin_follow_recommendations_path, highlights_on: %r{/admin/follow_recommendations}, if: -> { current_user.can?(:manage_taxonomies) } diff --git a/config/routes/admin.rb b/config/routes/admin.rb index 48dd4395e54d26..6c53ca79e620a6 100644 --- a/config/routes/admin.rb +++ b/config/routes/admin.rb @@ -33,6 +33,7 @@ resources :action_logs, only: [:index] resources :warning_presets, except: [:new, :show] resource :ng_words, only: [:show, :create] + resources :ngword_histories, only: [:index] resource :sensitive_words, only: [:show, :create] resource :special_instances, only: [:show, :create] diff --git a/db/migrate/20240216042730_create_ngword_histories.rb b/db/migrate/20240216042730_create_ngword_histories.rb new file mode 100644 index 00000000000000..46cedbed7356fe --- /dev/null +++ b/db/migrate/20240216042730_create_ngword_histories.rb @@ -0,0 +1,17 @@ +# frozen_string_literal: true + +class CreateNgwordHistories < ActiveRecord::Migration[7.1] + def change + create_table :ngword_histories do |t| + t.string :uri, null: false + t.integer :target_type, null: false + t.integer :reason, null: false + t.string :text, null: false + t.string :keyword, null: false + + t.timestamps + end + + add_index :ngword_histories, [:uri, :keyword, :created_at], unique: false + end +end diff --git a/db/schema.rb b/db/schema.rb index bbe9102c05f2e4..271b1f24be4128 100644 --- a/db/schema.rb +++ b/db/schema.rb @@ -10,7 +10,7 @@ # # It's strongly recommended that you check this file into your version control system. -ActiveRecord::Schema[7.1].define(version: 2024_02_12_230358) do +ActiveRecord::Schema[7.1].define(version: 2024_02_16_042730) do # These are extensions that must be enabled in order to support this database enable_extension "plpgsql" @@ -868,6 +868,17 @@ t.index ["target_account_id"], name: "index_mutes_on_target_account_id" end + create_table "ngword_histories", force: :cascade do |t| + t.string "uri", null: false + t.integer "target_type", null: false + t.integer "reason", null: false + t.string "text", null: false + t.string "keyword", null: false + t.datetime "created_at", null: false + t.datetime "updated_at", null: false + t.index ["uri", "keyword", "created_at"], name: "index_ngword_histories_on_uri_and_keyword_and_created_at" + end + create_table "notifications", force: :cascade do |t| t.bigint "activity_id", null: false t.string "activity_type", null: false diff --git a/spec/lib/activitypub/activity/create_spec.rb b/spec/lib/activitypub/activity/create_spec.rb index 971c512be2b3de..2966ae82b6b089 100644 --- a/spec/lib/activitypub/activity/create_spec.rb +++ b/spec/lib/activitypub/activity/create_spec.rb @@ -1781,6 +1781,11 @@ def activity_for_object(json) it 'creates status' do expect(sender.statuses.first).to_not be_nil end + + it 'does not record history' do + history = NgwordHistory.find_by(uri: object_json[:id]) + expect(history).to be_nil + end end context 'when hit ng words' do @@ -1789,6 +1794,34 @@ def activity_for_object(json) it 'creates status' do expect(sender.statuses.first).to be_nil end + + it 'records history' do + history = NgwordHistory.find_by(uri: object_json[:id]) + expect(history).to_not be_nil + expect(history.status_blocked?).to be true + expect(history.within_ng_words?).to be true + expect(history.keyword).to eq ng_words + end + end + + context 'when hit ng words but does not public visibility' do + let(:content) { 'hello, world!' } + let(:object_json) do + { + id: [ActivityPub::TagManager.instance.uri_for(sender), '#bar'].join, + type: 'Note', + content: content, + } + end + + it 'creates status' do + expect(sender.statuses.first).to be_nil + end + + it 'records history' do + history = NgwordHistory.find_by(uri: object_json[:id]) + expect(history).to be_nil + end end context 'when mention from tags' do @@ -1799,6 +1832,7 @@ def activity_for_object(json) id: [ActivityPub::TagManager.instance.uri_for(sender), '#bar'].join, type: 'Note', content: content, + to: 'https://www.w3.org/ns/activitystreams#Public', tag: [ { type: 'Mention', @@ -1814,6 +1848,11 @@ def activity_for_object(json) it 'creates status' do expect(sender.statuses.first).to_not be_nil end + + it 'does not record history' do + history = NgwordHistory.find_by(uri: object_json[:id]) + expect(history).to be_nil + end end context 'with using ng words for stranger' do @@ -1822,6 +1861,14 @@ def activity_for_object(json) it 'creates status' do expect(sender.statuses.first).to be_nil end + + it 'records history' do + history = NgwordHistory.find_by(uri: object_json[:id]) + expect(history).to_not be_nil + expect(history.status_blocked?).to be true + expect(history.within_ng_words_for_stranger_mention?).to be true + expect(history.keyword).to eq ng_words_for_stranger_mention + end end context 'with using ng words for stranger but receiver is following him' do @@ -1836,6 +1883,11 @@ def activity_for_object(json) it 'creates status' do expect(sender.statuses.first).to_not be_nil end + + it 'does not record history' do + history = NgwordHistory.find_by(uri: object_json[:id]) + expect(history).to be_nil + end end context 'with using ng words for stranger but multiple receivers are partically following him' do @@ -1847,6 +1899,7 @@ def activity_for_object(json) id: [ActivityPub::TagManager.instance.uri_for(sender), '#bar'].join, type: 'Note', content: content, + to: 'https://www.w3.org/ns/activitystreams#Public', tag: [ { type: 'Mention', @@ -1868,6 +1921,14 @@ def activity_for_object(json) it 'creates status' do expect(sender.statuses.first).to be_nil end + + it 'records history' do + history = NgwordHistory.find_by(uri: object_json[:id]) + expect(history).to_not be_nil + expect(history.status_blocked?).to be true + expect(history.within_ng_words_for_stranger_mention?).to be true + expect(history.keyword).to eq ng_words_for_stranger_mention + end end end @@ -1880,6 +1941,7 @@ def activity_for_object(json) id: [ActivityPub::TagManager.instance.uri_for(sender), '#bar'].join, type: 'Note', content: 'ohagi peers', + to: 'https://www.w3.org/ns/activitystreams#Public', inReplyTo: ActivityPub::TagManager.instance.uri_for(original_status), } end @@ -1888,6 +1950,14 @@ def activity_for_object(json) it 'creates status' do expect(sender.statuses.first).to be_nil end + + it 'records history' do + history = NgwordHistory.find_by(uri: object_json[:id]) + expect(history).to_not be_nil + expect(history.status_blocked?).to be true + expect(history.within_ng_words_for_stranger_mention?).to be true + expect(history.keyword).to eq ng_words_for_stranger_mention + end end context 'with following' do @@ -1901,6 +1971,11 @@ def activity_for_object(json) it 'creates status' do expect(sender.statuses.first).to_not be_nil end + + it 'does not record history' do + history = NgwordHistory.find_by(uri: object_json[:id]) + expect(history).to be_nil + end end end end diff --git a/spec/services/activitypub/process_account_service_spec.rb b/spec/services/activitypub/process_account_service_spec.rb index 5ff3e6813766f6..2763805f6dc1c6 100644 --- a/spec/services/activitypub/process_account_service_spec.rb +++ b/spec/services/activitypub/process_account_service_spec.rb @@ -308,12 +308,21 @@ Setting.ng_words = ['Amazon'] subject expect(account.reload.display_name).to eq 'Ohagi' + + history = NgwordHistory.find_by(uri: payload[:id]) + expect(history).to be_nil end it 'does not create account when ng word is set' do Setting.ng_words = ['Ohagi'] subject expect(account.reload.display_name).to_not eq 'Ohagi' + + history = NgwordHistory.find_by(uri: payload[:id]) + expect(history).to_not be_nil + expect(history.account_name_blocked?).to be true + expect(history.within_ng_words?).to be true + expect(history.keyword).to eq 'Ohagi' end end From 5c543c602b9351db0dd53da1d4807ffa8686f039 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?KMY=EF=BC=88=E9=9B=AA=E3=81=82=E3=81=99=E3=81=8B=EF=BC=89?= Date: Fri, 16 Feb 2024 17:53:09 +0900 Subject: [PATCH 28/28] =?UTF-8?q?Fix:=20#554=20=E6=A6=82=E8=A6=81=E7=94=BB?= =?UTF-8?q?=E9=9D=A2=E3=81=AE=E9=80=A3=E7=B5=A1=E5=85=88=E3=81=8C=E3=83=A1?= =?UTF-8?q?=E3=83=BC=E3=83=AB=E3=82=A2=E3=83=89=E3=83=AC=E3=82=B9=E3=81=A7?= =?UTF-8?q?=E3=81=AA=E3=81=8B=E3=81=A3=E3=81=9F=E5=A0=B4=E5=90=88=E3=81=AB?= =?UTF-8?q?=E3=80=81=E3=83=AA=E3=83=B3=E3=82=AF=E3=81=ABmailto=E3=82=92?= =?UTF-8?q?=E5=BC=B7=E5=88=B6=E7=9A=84=E3=81=AB=E3=81=A4=E3=81=91=E3=81=AA?= =?UTF-8?q?=E3=81=84=20(#562)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/javascript/mastodon/features/about/index.jsx | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/app/javascript/mastodon/features/about/index.jsx b/app/javascript/mastodon/features/about/index.jsx index 0ae76e46131b5d..ffc693e7ecb14e 100644 --- a/app/javascript/mastodon/features/about/index.jsx +++ b/app/javascript/mastodon/features/about/index.jsx @@ -162,6 +162,9 @@ class About extends PureComponent { const isFullTextSearch = server.getIn(['configuration', 'search', 'enabled']); + const email = server.getIn(['contact', 'email']) || ''; + const emailLink = email.startsWith('https://') ? email : `mailto:${email}`; + return (
@@ -183,7 +186,7 @@ class About extends PureComponent {