diff --git a/Gemfile b/Gemfile index 0c3484a7aa..22a8d86c3c 100644 --- a/Gemfile +++ b/Gemfile @@ -25,7 +25,7 @@ gem 'ruby-vips', '~> 2.2', require: false gem 'active_model_serializers', '~> 0.10' gem 'addressable', '~> 2.8' gem 'bootsnap', '~> 1.18.0', require: false -gem 'browser', '< 6' # https://github.com/fnando/browser/issues/543 +gem 'browser' gem 'charlock_holmes', '~> 0.7.7' gem 'chewy', '~> 7.3' gem 'devise', '~> 4.9' diff --git a/Gemfile.lock b/Gemfile.lock index c714838170..392acf36bb 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -133,7 +133,7 @@ GEM msgpack (~> 1.2) brakeman (6.2.2) racc - browser (5.3.1) + browser (6.0.0) brpoplpush-redis_script (0.1.3) concurrent-ruby (~> 1.0, >= 1.0.5) redis (>= 1.0, < 6) @@ -448,7 +448,7 @@ GEM nokogiri (1.16.7) mini_portile2 (~> 2.8.2) racc (~> 1.4) - oj (3.16.6) + oj (3.16.7) bigdecimal (>= 3.0) ostruct (>= 0.2) omniauth (2.1.2) @@ -908,7 +908,7 @@ DEPENDENCIES blurhash (~> 0.1) bootsnap (~> 1.18.0) brakeman (~> 6.0) - browser (< 6) + browser bundler-audit (~> 0.9) capybara (~> 3.39) charlock_holmes (~> 0.7.7) diff --git a/app/javascript/mastodon/components/media_gallery.jsx b/app/javascript/mastodon/components/media_gallery.jsx index e059978442..59963a0a9f 100644 --- a/app/javascript/mastodon/components/media_gallery.jsx +++ b/app/javascript/mastodon/components/media_gallery.jsx @@ -97,12 +97,12 @@ class Item extends PureComponent { height = 50; } - if (attachment.get('description')?.length > 0) { - badges.push(); - } - const description = attachment.getIn(['translation', 'description']) || attachment.get('description'); + if (description?.length > 0) { + badges.push(); + } + if (attachment.get('type') === 'unknown') { return (
diff --git a/app/javascript/mastodon/locales/eo.json b/app/javascript/mastodon/locales/eo.json index 7abe0783c3..ee4d733ab8 100644 --- a/app/javascript/mastodon/locales/eo.json +++ b/app/javascript/mastodon/locales/eo.json @@ -45,7 +45,7 @@ "account.languages": "Ŝanĝi la abonitajn lingvojn", "account.link_verified_on": "Propreco de tiu ligilo estis konfirmita je {date}", "account.locked_info": "Tiu konto estas privatigita. La posedanto mane akceptas tiun, kiu povas sekvi rin.", - "account.media": "Plurmedioj", + "account.media": "Plurmedio", "account.mention": "Mencii @{name}", "account.moved_to": "{name} indikis, ke ria nova konto estas nun:", "account.mute": "Silentigi @{name}", @@ -142,7 +142,7 @@ "column_header.unpin": "Malfiksi", "column_subheading.settings": "Agordoj", "community.column_settings.local_only": "Nur loka", - "community.column_settings.media_only": "Nur plurmedioj", + "community.column_settings.media_only": "Nur plurmedio", "community.column_settings.remote_only": "Nur fora", "compose.language.change": "Ŝanĝi lingvon", "compose.language.search": "Serĉi lingvojn...", diff --git a/app/javascript/mastodon/locales/fi.json b/app/javascript/mastodon/locales/fi.json index 2222e6038c..f06566df75 100644 --- a/app/javascript/mastodon/locales/fi.json +++ b/app/javascript/mastodon/locales/fi.json @@ -158,7 +158,7 @@ "compose_form.poll.duration": "Äänestyksen kesto", "compose_form.poll.multiple": "Monivalinta", "compose_form.poll.option_placeholder": "Vaihtoehto {number}", - "compose_form.poll.single": "Yksi vaihtoehto", + "compose_form.poll.single": "Yksittäisvalinta", "compose_form.poll.switch_to_multiple": "Muuta äänestys monivalinnaksi", "compose_form.poll.switch_to_single": "Muuta äänestys yksittäisvalinnaksi", "compose_form.poll.type": "Tyyli", @@ -386,7 +386,7 @@ "interaction_modal.description.follow": "Mastodon-tilillä voit seurata käyttäjää {name} saadaksesi hänen julkaisunsa kotisyötteeseesi.", "interaction_modal.description.reblog": "Mastodon-tilillä voit tehostaa tätä julkaisua jakaaksesi sen seuraajiesi kanssa.", "interaction_modal.description.reply": "Mastodon-tilillä voit vastata tähän julkaisuun.", - "interaction_modal.description.vote": "Osallistuminen äänestykseen onnistuu Mastodon-tilillä.", + "interaction_modal.description.vote": "Mastodon-tilillä voit osallistua tähän äänestykseen.", "interaction_modal.login.action": "Siirry kotiin", "interaction_modal.login.prompt": "Kotipalvelimesi verkkotunnus, kuten mastodon.social", "interaction_modal.no_account_yet": "Etkö ole vielä Mastodonissa?", diff --git a/app/javascript/mastodon/locales/fy.json b/app/javascript/mastodon/locales/fy.json index e1c090cb0c..3f4d942b61 100644 --- a/app/javascript/mastodon/locales/fy.json +++ b/app/javascript/mastodon/locales/fy.json @@ -158,6 +158,7 @@ "compose_form.poll.duration": "Doer fan de enkête", "compose_form.poll.multiple": "Mearkar", "compose_form.poll.option_placeholder": "Opsje {number}", + "compose_form.poll.single": "Inkelde kar", "compose_form.poll.switch_to_multiple": "Enkête wizigje om meardere karren ta te stean", "compose_form.poll.switch_to_single": "Enkête wizigje om in inkelde kar ta te stean", "compose_form.poll.type": "Styl", @@ -196,6 +197,7 @@ "confirmations.unfollow.title": "Brûker net mear folgje?", "content_warning.hide": "Berjocht ferstopje", "content_warning.show": "Dochs toane", + "content_warning.show_more": "Mear toane", "conversation.delete": "Petear fuortsmite", "conversation.mark_as_read": "As lêzen markearje", "conversation.open": "Petear toane", @@ -304,6 +306,7 @@ "filter_modal.select_filter.subtitle": "In besteande kategory brûke of in nije oanmeitsje", "filter_modal.select_filter.title": "Dit berjocht filterje", "filter_modal.title.status": "In berjocht filterje", + "filter_warning.matches_filter": "Komt oerien mei filter ‘{title}’", "filtered_notifications_banner.pending_requests": "Fan {count, plural, =0 {net ien} one {ien persoan} other {# persoanen}} dy’t jo mooglik kinne", "filtered_notifications_banner.title": "Filtere meldingen", "firehose.all": "Alles", @@ -383,6 +386,7 @@ "interaction_modal.description.follow": "Jo kinne mei in Mastodon-account {name} folgje, om sa harren berjochten op jo starttiidline te ûntfangen.", "interaction_modal.description.reblog": "Jo kinne mei in Mastodon-account dit berjocht booste, om it sa mei jo folgers te dielen.", "interaction_modal.description.reply": "Jo kinne mei in Mastodon-account op dit berjocht reagearje.", + "interaction_modal.description.vote": "Mei in Mastodon-account kinne jo yn dizze enkête stimme.", "interaction_modal.login.action": "Gean nei start", "interaction_modal.login.prompt": "Domein fan jo server, byg. mastodon.social", "interaction_modal.no_account_yet": "Net op Mastodon?", @@ -394,6 +398,7 @@ "interaction_modal.title.follow": "{name} folgje", "interaction_modal.title.reblog": "Berjocht fan {name} booste", "interaction_modal.title.reply": "Op it berjocht fan {name} reagearje", + "interaction_modal.title.vote": "Stimme yn {name}’s peiling", "intervals.full.days": "{number, plural, one {# dei} other {# dagen}} lyn", "intervals.full.hours": "{number, plural, one {# oere} other {# oeren}} lyn", "intervals.full.minutes": "{number, plural, one {# minút} other {# minuten}} lyn", @@ -506,6 +511,7 @@ "notification.favourite": "{name} hat jo berjocht as favoryt markearre", "notification.favourite.name_and_others_with_link": "{name} en {count, plural, one {# oar} other {# oaren}} hawwe jo berjocht as favoryt markearre", "notification.follow": "{name} folget dy", + "notification.follow.name_and_others": "{name} en {count, plural, one {# oar persoan} other {# oare persoanen}} folgje jo no", "notification.follow_request": "{name} hat dy in folchfersyk stjoerd", "notification.follow_request.name_and_others": "{name} en {count, plural, one {# oar} other {# oaren}} hawwe frege om jo te folgjen", "notification.label.mention": "Fermelding", @@ -564,6 +570,7 @@ "notifications.column_settings.filter_bar.category": "Flugge filterbalke", "notifications.column_settings.follow": "Nije folgers:", "notifications.column_settings.follow_request": "Nij folchfersyk:", + "notifications.column_settings.group": "Groepearje", "notifications.column_settings.mention": "Fermeldingen:", "notifications.column_settings.poll": "Enkêteresultaten:", "notifications.column_settings.push": "Pushmeldingen", diff --git a/app/javascript/mastodon/locales/ko.json b/app/javascript/mastodon/locales/ko.json index 3462675e3e..dbdb5062cf 100644 --- a/app/javascript/mastodon/locales/ko.json +++ b/app/javascript/mastodon/locales/ko.json @@ -113,7 +113,7 @@ "bundle_modal_error.message": "컴포넌트를 불러오는 중 문제가 발생했습니다.", "bundle_modal_error.retry": "다시 시도", "closed_registrations.other_server_instructions": "마스토돈은 분산화 되어 있기 때문에, 다른 서버에서 계정을 만들더라도 이 서버와 상호작용 할 수 있습니다.", - "closed_registrations_modal.description": "{domain}은 현재 가입이 막혀있는 상태입니다, 마스토돈을 이용하기 위해 꼭 {domain}을 사용할 필요는 없다는 사실을 인지해 두세요.", + "closed_registrations_modal.description": "{domain}은 현재 가입이 불가능합니다. 하지만 마스토돈을 이용하기 위해 꼭 {domain}을 사용할 필요는 없다는 사실을 인지해 두세요.", "closed_registrations_modal.find_another_server": "다른 서버 찾기", "closed_registrations_modal.preamble": "마스토돈은 분산화 되어 있습니다, 그렇기 때문에 어디에서 계정을 생성하든, 이 서버에 있는 누구와도 팔로우와 상호작용을 할 수 있습니다. 심지어는 스스로 서버를 만드는 것도 가능합니다!", "closed_registrations_modal.title": "마스토돈에서 가입", @@ -386,6 +386,7 @@ "interaction_modal.description.follow": "마스토돈 계정을 통해, {name} 님을 팔로우 하고 그의 게시물을 홈 피드에서 받아 볼 수 있습니다.", "interaction_modal.description.reblog": "마스토돈 계정을 통해, 이 게시물을 부스트 하고 자신의 팔로워들에게 공유할 수 있습니다.", "interaction_modal.description.reply": "마스토돈 계정을 통해, 이 게시물에 응답할 수 있습니다.", + "interaction_modal.description.vote": "마스토돈 계정을 통해, 이 투표에 참여할 수 있습니다.", "interaction_modal.login.action": "홈 서버로 가기", "interaction_modal.login.prompt": "내 홈 서버의 도메인. 예시: mastodon.social", "interaction_modal.no_account_yet": "Mastodon 계정이 없나요?", @@ -397,6 +398,7 @@ "interaction_modal.title.follow": "{name} 님을 팔로우", "interaction_modal.title.reblog": "{name} 님의 게시물을 부스트", "interaction_modal.title.reply": "{name} 님의 게시물에 답글", + "interaction_modal.title.vote": "{name} 님의 투표에 참여", "intervals.full.days": "{number} 일", "intervals.full.hours": "{number} 시간", "intervals.full.minutes": "{number} 분", diff --git a/app/javascript/mastodon/locales/lv.json b/app/javascript/mastodon/locales/lv.json index d7507ee884..30fc0ea348 100644 --- a/app/javascript/mastodon/locales/lv.json +++ b/app/javascript/mastodon/locales/lv.json @@ -36,6 +36,7 @@ "account.followers.empty": "Šim lietotājam vēl nav sekotāju.", "account.followers_counter": "{count, plural, zero {{count} sekotāju} one {{count} sekotājs} other {{count} sekotāji}}", "account.following": "Seko", + "account.following_counter": "{count, plural, one {seko {counter}} other {seko {counter}}}", "account.follows.empty": "Šis lietotājs pagaidām nevienam neseko.", "account.go_to_profile": "Doties uz profilu", "account.hide_reblogs": "Paslēpt @{name} pastiprinātos ierakstus", @@ -61,6 +62,7 @@ "account.requested_follow": "{name} nosūtīja Tev sekošanas pieprasījumu", "account.share": "Dalīties ar @{name} profilu", "account.show_reblogs": "Parādīt @{name} pastiprinātos ierakstus", + "account.statuses_counter": "{count, plural, zero {{counter} ierakstu} one {{counter} ieraksts} other {{counter} ieraksti}}", "account.unblock": "Atbloķēt @{name}", "account.unblock_domain": "Atbloķēt domēnu {domain}", "account.unblock_short": "Atbloķēt", @@ -191,6 +193,7 @@ "confirmations.unfollow.title": "Pārtraukt sekošanu lietotājam?", "content_warning.hide": "Paslēpt ierakstu", "content_warning.show": "Tomēr rādīt", + "content_warning.show_more": "Rādīt vairāk", "conversation.delete": "Dzēst sarunu", "conversation.mark_as_read": "Atzīmēt kā izlasītu", "conversation.open": "Skatīt sarunu", @@ -211,6 +214,7 @@ "dismissable_banner.explore_tags": "Šie ir tēmturi, kas šodien gūst uzmanību sabiedriskajā tīmeklī. Tēmturi, kurus izmanto vairāk dažādu cilvēku, tiek vērtēti augstāk.", "dismissable_banner.public_timeline": "Šie ir jaunākie publiskie ieraksti no lietotājiem sociālajā tīmeklī, kuriem {domain} seko cilvēki.", "domain_block_modal.block": "Bloķēt serveri", + "domain_block_modal.block_account_instead": "Tā vietā liegt @{name}", "domain_block_modal.they_cant_follow": "Neviens šajā serverī nevar Tev sekot.", "domain_block_modal.they_wont_know": "Viņi nezinās, ka tikuši bloķēti.", "domain_block_modal.title": "Bloķēt domēnu?", @@ -329,6 +333,7 @@ "home.pending_critical_update.link": "Skatīt jauninājumus", "home.pending_critical_update.title": "Ir pieejams būtisks drošības atjauninājums.", "home.show_announcements": "Rādīt paziņojumus", + "ignore_notifications_modal.ignore": "Neņemt vērā paziņojumus", "interaction_modal.description.favourite": "Ar Mastodon kontu tu vari pievienot šo ziņu izlasei, lai informētu autoru, ka to novērtē, un saglabātu to vēlākai lasīšanai.", "interaction_modal.description.follow": "Ar Mastodon kontu Tu vari sekot {name}, lai saņemtu lietotāja ierakstus savā mājas plūsmā.", "interaction_modal.description.reblog": "Ar Mastodon kontu Tu vari izvirzīt šo ierakstu, lai kopīgotu to ar saviem sekotājiem.", @@ -505,10 +510,10 @@ "onboarding.action.back": "Aizved mani atpakaļ", "onboarding.actions.back": "Aizved mani atpakaļ", "onboarding.actions.go_to_explore": "Skatīt tendences", - "onboarding.actions.go_to_home": "Dodieties uz manu mājas plūsmu", + "onboarding.actions.go_to_home": "Doties uz manu sākuma plūsmu", "onboarding.compose.template": "Sveiki, #Mastodon!", "onboarding.follows.empty": "Diemžēl pašlaik nevar parādīt rezultātus. Vari mēģināt izmantot meklēšanu vai pārlūkot izpētes lapu, lai atrastu cilvēkus, kuriem sekot, vai vēlāk mēģināt vēlreiz.", - "onboarding.follows.lead": "Tava mājas plūsma ir galvenais veids, kā pieredzēt Mastodon. Jo vairāk cilvēkiem sekosi, jo dzīvīgāka un aizraujošāka tā būs. Lai sāktu, šeit ir daži ieteikumi:", + "onboarding.follows.lead": "Tava sākuma plūsma ir galvenais veids, kā pieredzēt Mastodon. Jo vairāk cilvēkiem sekosi, jo dzīvīgāka un aizraujošāka tā būs. Lai sāktu, šeit ir daži ieteikumi:", "onboarding.follows.title": "Pielāgo savu mājas barotni", "onboarding.profile.discoverable": "Padarīt manu profilu atklājamu", "onboarding.profile.display_name": "Attēlojamais vārds", @@ -526,7 +531,7 @@ "onboarding.start.lead": "Tagad Tu esi daļa no Mastodon — vienreizējas, decentralizētas sociālās mediju platformas, kurā Tu, nevis algoritms, veido Tavu pieredzi. Sāksim darbu šajā jaunajā sociālajā jomā:", "onboarding.start.skip": "Nav nepieciešama palīdzība darba sākšanai?", "onboarding.start.title": "Tev tas izdevās!", - "onboarding.steps.follow_people.body": "Tu pats veido savu plūsmu. Piepildīsim to ar interesantiem cilvēkiem.", + "onboarding.steps.follow_people.body": "Sekošana aizraujošiem cilvēkiem ir tas, par ko ir Mastodon.", "onboarding.steps.follow_people.title": "Pielāgo savu mājas barotni", "onboarding.steps.publish_status.body": "Pasveicini pasauli ar tekstu, attēliem, video vai aptaujām {emoji}", "onboarding.steps.publish_status.title": "Izveido savu pirmo ziņu", diff --git a/app/javascript/mastodon/locales/ru.json b/app/javascript/mastodon/locales/ru.json index 2a985a1f84..d75b5fab26 100644 --- a/app/javascript/mastodon/locales/ru.json +++ b/app/javascript/mastodon/locales/ru.json @@ -84,7 +84,7 @@ "alert.rate_limited.message": "Пожалуйста, повторите после {retry_time, time, medium}.", "alert.rate_limited.title": "Ограничение количества запросов", "alert.unexpected.message": "Произошла непредвиденная ошибка.", - "alert.unexpected.title": "Упс!", + "alert.unexpected.title": "Ой!", "alt_text_badge.title": "Альтернативный текст", "announcement.announcement": "Объявление", "attachments_list.unprocessed": "(не обработан)", @@ -95,11 +95,11 @@ "block_modal.they_cant_mention": "Он не может упоминать или подписываться на вас.", "block_modal.they_cant_see_posts": "Он не может видеть ваши сообщения, и вы не увидите его.", "block_modal.they_will_know": "Он может видеть, что он заблокирован.", - "block_modal.title": "Заблокировать пользователя?", + "block_modal.title": "Заблокируем пользователя?", "block_modal.you_wont_see_mentions": "Вы не увидите записи, которые упоминают его.", "boost_modal.combo": "{combo}, чтобы пропустить это в следующий раз", - "boost_modal.reblog": "Повысить пост?", - "boost_modal.undo_reblog": "Разгрузить пост?", + "boost_modal.reblog": "Репостнуть?", + "boost_modal.undo_reblog": "Убрать репост?", "bundle_column_error.copy_stacktrace": "Скопировать отчет об ошибке", "bundle_column_error.error.body": "Запрошенная страница не может быть отображена. Это может быть вызвано ошибкой в нашем коде или проблемой совместимости браузера.", "bundle_column_error.error.title": "О нет!", @@ -144,7 +144,7 @@ "community.column_settings.local_only": "Только локальные", "community.column_settings.media_only": "Только с медиафайлами", "community.column_settings.remote_only": "Только удалённые", - "compose.language.change": "Изменить язык", + "compose.language.change": "Сменить язык", "compose.language.search": "Поиск языков...", "compose.published.body": "Запись опубликована.", "compose.published.open": "Открыть", @@ -180,7 +180,7 @@ "confirmations.discard_edit_media.message": "У вас есть несохранённые изменения описания мультимедиа или предпросмотра, отменить их?", "confirmations.edit.confirm": "Редактировать", "confirmations.edit.message": "В данный момент, редактирование перезапишет составляемое вами сообщение. Вы уверены, что хотите продолжить?", - "confirmations.edit.title": "Переписать сообщение?", + "confirmations.edit.title": "Перепишем сообщение?", "confirmations.logout.confirm": "Выйти", "confirmations.logout.message": "Вы уверены, что хотите выйти?", "confirmations.logout.title": "Выйти?", @@ -196,6 +196,7 @@ "confirmations.unfollow.title": "Отписаться?", "content_warning.hide": "Скрыть пост", "content_warning.show": "Всё равно показать", + "content_warning.show_more": "Покажи ещё", "conversation.delete": "Удалить беседу", "conversation.mark_as_read": "Отметить как прочитанное", "conversation.open": "Просмотр беседы", @@ -303,6 +304,7 @@ "filter_modal.select_filter.subtitle": "Используйте существующую категорию или создайте новую", "filter_modal.select_filter.title": "Фильтровать этот пост", "filter_modal.title.status": "Фильтровать пост", + "filter_warning.matches_filter": "Соответствует фильтру \"{title}\"", "filtered_notifications_banner.pending_requests": "Вы можете знать {count, plural, =0 {ни одного человека} one {одного человека} other {# человек}}", "filtered_notifications_banner.title": "Отфильтрованные уведомления", "firehose.all": "Все", @@ -382,6 +384,7 @@ "interaction_modal.description.follow": "С учётной записью Mastodon вы можете подписаться на {name}, чтобы получать их посты в своей домашней ленте.", "interaction_modal.description.reblog": "С учётной записью Mastodon, вы можете продвинуть этот пост, чтобы поделиться им со своими подписчиками.", "interaction_modal.description.reply": "Вы можете ответить на этот пост с учётной записью Mastodon.", + "interaction_modal.description.vote": "Вы сможете проголосовать тут имея аккаунт Mastodon.", "interaction_modal.login.action": "Перейти на домашнюю страницу", "interaction_modal.login.prompt": "Домен вашего домашнего сервера, например, mastodon.social", "interaction_modal.no_account_yet": "Еще не на Mastodon?", @@ -393,12 +396,13 @@ "interaction_modal.title.follow": "Подписаться на {name}", "interaction_modal.title.reblog": "Продвинуть публикацию {name}", "interaction_modal.title.reply": "Ответить на пост {name}", + "interaction_modal.title.vote": "Голосовать в опросе {name}", "intervals.full.days": "{number, plural, one {# день} few {# дня} other {# дней}}", "intervals.full.hours": "{number, plural, one {# час} few {# часа} other {# часов}}", "intervals.full.minutes": "{number, plural, one {# минута} few {# минуты} other {# минут}}", "keyboard_shortcuts.back": "перейти назад", "keyboard_shortcuts.blocked": "чтобы открыть список заблокированных", - "keyboard_shortcuts.boost": "продвинуть пост", + "keyboard_shortcuts.boost": "Репостнуть", "keyboard_shortcuts.column": "фокус на одном из столбцов", "keyboard_shortcuts.compose": "фокус на поле ввода", "keyboard_shortcuts.description": "Описание", @@ -464,7 +468,7 @@ "mute_modal.show_options": "Показать опции", "mute_modal.they_can_mention_and_follow": "Они могут упоминать и следить за вами, но вы не будете их видеть.", "mute_modal.they_wont_know": "Они не будут знать, что их заглушили.", - "mute_modal.title": "Заглушить пользователя?", + "mute_modal.title": "Заткнуть пользователя?", "mute_modal.you_wont_see_mentions": "Вы не увидите постов, которые их упоминают.", "mute_modal.you_wont_see_posts": "Они по-прежнему смогут видеть ваши посты, но вы не сможете видеть их посты.", "navigation_bar.about": "О проекте", @@ -505,6 +509,7 @@ "notification.favourite": "{name} добавил(а) ваш пост в избранное", "notification.favourite.name_and_others_with_link": "{name} и {count, plural, one {# другие} other {# другие}} отдали предпочтение вашему посту", "notification.follow": "{name} подписался (-лась) на вас", + "notification.follow.name_and_others": "{name} и {count, plural, one {# other} few {# others} many {# others} other {# others}} подписались на вас", "notification.follow_request": "{name} отправил запрос на подписку", "notification.follow_request.name_and_others": "{name} и ещё {count, plural, one {#} other {# других}} подписались на вас", "notification.label.mention": "Упоминание", @@ -512,7 +517,7 @@ "notification.label.private_reply": "Частный ответ", "notification.label.reply": "Ответить", "notification.mention": "Упоминание", - "notification.mentioned_you": "{name} упомянул(а) вас", + "notification.mentioned_you": "{name} упоминает вас", "notification.moderation-warning.learn_more": "Узнать больше", "notification.moderation_warning": "Вы получили предупреждение от модерации", "notification.moderation_warning.action_delete_statuses": "Некоторые из ваших публикаций были удалены.", @@ -558,6 +563,7 @@ "notifications.column_settings.filter_bar.category": "Панель сортировки", "notifications.column_settings.follow": "У вас новый подписчик:", "notifications.column_settings.follow_request": "Новые запросы на подписку:", + "notifications.column_settings.group": "Группа", "notifications.column_settings.mention": "Вас упомянули в посте:", "notifications.column_settings.poll": "Опрос, в котором вы приняли участие, завершился:", "notifications.column_settings.push": "Пуш-уведомления", @@ -600,8 +606,8 @@ "notifications_permission_banner.enable": "Включить уведомления", "notifications_permission_banner.how_to_control": "Получайте уведомления даже когда Mastodon закрыт, включив уведомления на рабочем столе. А чтобы лишний шум не отвлекал, вы можете настроить какие уведомления вы хотите получать, нажав на кнопку {icon} выше.", "notifications_permission_banner.title": "Будьте в курсе происходящего", - "onboarding.action.back": "Вернуть меня", - "onboarding.actions.back": "Вернуть меня", + "onboarding.action.back": "Верните меня", + "onboarding.actions.back": "Верните меня", "onboarding.actions.go_to_explore": "Посмотреть, что актуально", "onboarding.actions.go_to_home": "Перейти к домашней ленте новостей", "onboarding.compose.template": "Привет, #Mastodon!", @@ -619,7 +625,7 @@ "onboarding.profile.title": "Настройка профиля", "onboarding.profile.upload_avatar": "Загрузить фотографию профиля", "onboarding.profile.upload_header": "Загрузить заголовок профиля", - "onboarding.share.lead": "Расскажите людям, как они могут найти вас на Mastodon!", + "onboarding.share.lead": "Расскажите людям, как найти вас на Mastodon!", "onboarding.share.message": "Я {username} на #Mastodon! Следуйте за мной по адресу {url}", "onboarding.share.next_steps": "Возможные дальнейшие шаги:", "onboarding.share.title": "Поделиться вашим профилем", @@ -634,7 +640,7 @@ "onboarding.steps.setup_profile.title": "Настройте свой профиль", "onboarding.steps.share_profile.body": "Расскажите своим друзьям как найти вас на Mastodon!", "onboarding.steps.share_profile.title": "Поделитесь вашим профилем", - "onboarding.tips.2fa": "Знаете ли вы? Вы можете защитить свой аккаунт, настроив двухфакторную аутентификацию в настройках аккаунта. Она работает с любым приложением TOTP по вашему выбору, номер телефона не требуется!", + "onboarding.tips.2fa": "А вы знали? Можно защитить свой аккаунт, настроив двухфакторную аутентификацию в настройках аккаунта. Она работает с любым приложением TOTP по вашему выбору, номер телефона не нужен!", "onboarding.tips.accounts_from_other_servers": "Знали ли вы? Поскольку Mastodon децентрализован, некоторые профили, с которыми вы столкнетесь, будут размещены на серверах, отличных от вашего. И все же вы можете взаимодействовать с ними без проблем! Их сервер находится во второй половине имени пользователя!", "onboarding.tips.migration": "Знаете ли вы? Если вы чувствуете, что {domain} не подходит вам в качестве сервера в будущем, вы можете переехать на другой сервер Mastodon без потери своих подписчиков. Вы даже можете разместить свой собственный сервер!", "onboarding.tips.verification": "Знали ли вы? Вы можете подтвердить свою учетную запись, разместив ссылку на свой профиль Mastodon на собственном сайте и добавив сайт в свой профиль. Никаких сборов или документов не требуется!", @@ -665,7 +671,7 @@ "privacy_policy.title": "Политика конфиденциальности", "recommended": "Рекомендуется", "refresh": "Обновить", - "regeneration_indicator.label": "Загрузка…", + "regeneration_indicator.label": "Грузим…", "regeneration_indicator.sublabel": "Один момент, мы подготавливаем вашу ленту!", "relative_time.days": "{number} д", "relative_time.full.days": "{number, plural, one {# день} many {# дней} other {# дня}} назад", @@ -800,6 +806,7 @@ "status.reblog": "Продвинуть", "status.reblog_private": "Продвинуть для своей аудитории", "status.reblogged_by": "{name} продвинул(а)", + "status.reblogs": "{count, plural, one {boost} few {boosts} many {boosts} other {boosts}}", "status.reblogs.empty": "Никто ещё не продвинул этот пост. Как только кто-то это сделает, они появятся здесь.", "status.redraft": "Создать заново", "status.remove_bookmark": "Убрать из закладок", @@ -856,11 +863,11 @@ "upload_modal.detect_text": "Найти текст на картинке", "upload_modal.edit_media": "Изменить файл", "upload_modal.hint": "Нажмите и перетащите круг в предпросмотре в точку фокуса, которая всегда будет видна на эскизах.", - "upload_modal.preparing_ocr": "Подготовка распознования…", + "upload_modal.preparing_ocr": "Подготовка распознавания…", "upload_modal.preview_label": "Предпросмотр ({ratio})", "upload_progress.label": "Загрузка...", "upload_progress.processing": "Обработка…", - "username.taken": "Данное имя пользователя уже занято. Выберите другое.", + "username.taken": "Это имя пользователя уже занято. Выберите другое", "video.close": "Закрыть видео", "video.download": "Загрузить файл", "video.exit_fullscreen": "Покинуть полноэкранный режим", diff --git a/app/javascript/mastodon/locales/sk.json b/app/javascript/mastodon/locales/sk.json index a1bcdb9ff9..dc31f6100f 100644 --- a/app/javascript/mastodon/locales/sk.json +++ b/app/javascript/mastodon/locales/sk.json @@ -194,6 +194,7 @@ "confirmations.unfollow.title": "Prestať sledovať užívateľa?", "content_warning.hide": "Skryť príspevok", "content_warning.show": "Aj tak zobraziť", + "content_warning.show_more": "Ukázať viac", "conversation.delete": "Vymazať konverzáciu", "conversation.mark_as_read": "Označiť ako prečítanú", "conversation.open": "Zobraziť konverzáciu", @@ -484,7 +485,7 @@ "notification_requests.edit_selection": "Uprav", "notification_requests.exit_selection": "Hotovo", "notification_requests.notifications_from": "Oboznámenia od {name}", - "notification_requests.title": "Filtrované oboznámenia", + "notification_requests.title": "Filtrované oznámenia", "notification_requests.view": "Zobraz upozornenia", "notifications.clear": "Vyčistiť upozornenia", "notifications.clear_confirmation": "Určite chcete nenávratne odstrániť všetky svoje upozornenia?", diff --git a/app/javascript/mastodon/locales/sv.json b/app/javascript/mastodon/locales/sv.json index 7824d07629..e404c2244b 100644 --- a/app/javascript/mastodon/locales/sv.json +++ b/app/javascript/mastodon/locales/sv.json @@ -82,7 +82,7 @@ "admin.impact_report.instance_follows": "Följare som deras användare skulle förlora", "admin.impact_report.title": "Sammanfattning av påverkan", "alert.rate_limited.message": "Vänligen försök igen efter {retry_time, time, medium}.", - "alert.rate_limited.title": "Mängd begränsad", + "alert.rate_limited.title": "Hastighetsbegränsad", "alert.unexpected.message": "Ett oväntat fel uppstod.", "alert.unexpected.title": "Hoppsan!", "alt_text_badge.title": "Alt-Text", @@ -271,7 +271,7 @@ "empty_column.follow_requests": "Du har inga följarförfrågningar än. När du får en kommer den visas här.", "empty_column.followed_tags": "Du följer inga hashtaggar ännu. När du gör det kommer de att dyka upp här.", "empty_column.hashtag": "Det finns inget i denna hashtag ännu.", - "empty_column.home": "Din hemma-tidslinje är tom! Följ fler användare för att fylla den. {suggestions}", + "empty_column.home": "Din hemma-tidslinje är tom! Följ fler användare för att fylla den.", "empty_column.list": "Det finns inget i denna lista än. När listmedlemmar publicerar nya inlägg kommer de synas här.", "empty_column.lists": "Du har inga listor än. När skapar en kommer den dyka upp här.", "empty_column.mutes": "Du har ännu inte tystat några användare.", @@ -383,7 +383,7 @@ "ignore_notifications_modal.not_following_title": "Vill du blockera aviseringar från personer som du inte följer dig?", "ignore_notifications_modal.private_mentions_title": "Vill du ignorera aviseringar från oönskade privata omnämningar?", "interaction_modal.description.favourite": "Med ett Mastodon-konto kan du favoritmarkera detta inlägg för att visa författaren att du gillar det och för att spara det till senare.", - "interaction_modal.description.follow": "Med ett Mastodon-konto kan du följa {name} för att se hens inlägg i ditt hemflöde.", + "interaction_modal.description.follow": "Med ett Mastodon-konto kan du följa {name} för att se deras inlägg i ditt hemflöde.", "interaction_modal.description.reblog": "Med ett Mastodon-konto kan du boosta detta inlägg för att dela den med dina egna följare.", "interaction_modal.description.reply": "Med ett Mastodon-konto kan du svara på detta inlägg.", "interaction_modal.description.vote": "Med ett konto på Mastodon kan du delta i denna omröstning.", @@ -405,11 +405,11 @@ "keyboard_shortcuts.back": "Gå bakåt", "keyboard_shortcuts.blocked": "Öppna listan över blockerade användare", "keyboard_shortcuts.boost": "Boosta inlägg", - "keyboard_shortcuts.column": "för att fokusera en status i en av kolumnerna", + "keyboard_shortcuts.column": "Fokusera kolumn", "keyboard_shortcuts.compose": "för att fokusera skrivfältet", "keyboard_shortcuts.description": "Beskrivning", "keyboard_shortcuts.direct": "för att öppna privata nämningskolumnen", - "keyboard_shortcuts.down": "för att flytta nedåt i listan", + "keyboard_shortcuts.down": "Flytta ner i listan", "keyboard_shortcuts.enter": "Öppna inlägg", "keyboard_shortcuts.favourite": "Favoritmarkera inlägg", "keyboard_shortcuts.favourites": "Öppna favoritlistan", @@ -429,13 +429,13 @@ "keyboard_shortcuts.reply": "Svara på inlägg", "keyboard_shortcuts.requests": "för att öppna Följförfrågningar", "keyboard_shortcuts.search": "för att fokusera sökfältet", - "keyboard_shortcuts.spoilers": "visa/dölja CW-fält", - "keyboard_shortcuts.start": "för att öppna \"Kom igång\"-kolumnen", - "keyboard_shortcuts.toggle_hidden": "för att visa/gömma text bakom CW", - "keyboard_shortcuts.toggle_sensitivity": "för att visa/gömma media", + "keyboard_shortcuts.spoilers": "Visa/dölja CW-fält", + "keyboard_shortcuts.start": "Öppna \"Kom igång\"-kolumnen", + "keyboard_shortcuts.toggle_hidden": "Visa/gömma text bakom CW", + "keyboard_shortcuts.toggle_sensitivity": "Visa/gömma media", "keyboard_shortcuts.toot": "Starta nytt inlägg", - "keyboard_shortcuts.unfocus": "för att avfokusera skrivfält/sökfält", - "keyboard_shortcuts.up": "för att flytta uppåt i listan", + "keyboard_shortcuts.unfocus": "Avfokusera skrivfält/sökfält", + "keyboard_shortcuts.up": "Flytta uppåt i listan", "lightbox.close": "Stäng", "lightbox.next": "Nästa", "lightbox.previous": "Tidigare", @@ -617,11 +617,11 @@ "onboarding.action.back": "Ta mig tillbaka", "onboarding.actions.back": "Ta mig tillbaka", "onboarding.actions.go_to_explore": "See what's trending", - "onboarding.actions.go_to_home": "Go to your home feed", + "onboarding.actions.go_to_home": "Ta mig till mitt hemflöde", "onboarding.compose.template": "Hallå #Mastodon!", "onboarding.follows.empty": "Tyvärr kan inga resultat visas just nu. Du kan prova att använda sökfunktionen eller utforska sidan för att hitta personer att följa, eller försök igen senare.", - "onboarding.follows.lead": "You curate your own home feed. The more people you follow, the more active and interesting it will be. These profiles may be a good starting point—you can always unfollow them later!", - "onboarding.follows.title": "Popular on Mastodon", + "onboarding.follows.lead": "Ditt hemflöde är det primära sättet att uppleva Mastodon. Ju fler människor du följer, desto mer aktiv och intressant blir det. För att komma igång, är här några förslag:", + "onboarding.follows.title": "Anpassa ditt hemflöde", "onboarding.profile.discoverable": "Gör min profil upptäckbar", "onboarding.profile.discoverable_hint": "När du väljer att vara upptäckbar på Mastodon kan dina inlägg visas i sök- och trendresultat, och din profil kan föreslås för personer med liknande intressen som du.", "onboarding.profile.display_name": "Visningsnamn", @@ -642,7 +642,7 @@ "onboarding.start.title": "Du klarade det!", "onboarding.steps.follow_people.body": "You curate your own feed. Lets fill it with interesting people.", "onboarding.steps.follow_people.title": "Follow {count, plural, one {one person} other {# people}}", - "onboarding.steps.publish_status.body": "Say hello to the world.", + "onboarding.steps.publish_status.body": "Säg hej till världen med text, foton, videor eller omröstningar {emoji}", "onboarding.steps.publish_status.title": "Gör ditt första inlägg", "onboarding.steps.setup_profile.body": "Others are more likely to interact with you with a filled out profile.", "onboarding.steps.setup_profile.title": "Customize your profile", @@ -733,8 +733,8 @@ "report.thanks.take_action_actionable": "Medan vi granskar detta kan du vidta åtgärder mot {name}:", "report.thanks.title": "Vill du inte se det här?", "report.thanks.title_actionable": "Tack för att du rapporterar, vi kommer att titta på detta.", - "report.unfollow": "Sluta följ @{username}", - "report.unfollow_explanation": "Du följer detta konto. Avfölj hen för att inte se hens inlägg i ditt hemflöde.", + "report.unfollow": "Sluta följ @{name}", + "report.unfollow_explanation": "Du följer detta konto. Avfölj det för att inte se dess inlägg i ditt hemflöde.", "report_notification.attached_statuses": "bifogade {count, plural, one {{count} inlägg} other {{count} inlägg}}", "report_notification.categories.legal": "Rättsligt", "report_notification.categories.legal_sentence": "olagligt innehåll", @@ -829,7 +829,7 @@ "status.show_less_all": "Visa mindre för alla", "status.show_more_all": "Visa mer för alla", "status.show_original": "Visa original", - "status.title.with_attachments": "{user} posted {attachmentCount, plural, one {an attachment} other {# attachments}}", + "status.title.with_attachments": "{user} lade upp {attachmentCount, plural, one {en bilaga} other {{attachmentCount} bilagor}}", "status.translate": "Översätt", "status.translated_from_with": "Översatt från {lang} med {provider}", "status.uncached_media_warning": "Förhandsvisning inte tillgänglig", diff --git a/app/javascript/mastodon/locales/th.json b/app/javascript/mastodon/locales/th.json index b0ad6e1c66..5cf95554bc 100644 --- a/app/javascript/mastodon/locales/th.json +++ b/app/javascript/mastodon/locales/th.json @@ -44,7 +44,7 @@ "account.joined_short": "เข้าร่วมเมื่อ", "account.languages": "เปลี่ยนภาษาที่บอกรับ", "account.link_verified_on": "ตรวจสอบความเป็นเจ้าของของลิงก์นี้เมื่อ {date}", - "account.locked_info": "สถานะความเป็นส่วนตัวของบัญชีนี้ถูกตั้งค่าเป็นล็อค เจ้าของตรวจสอบด้วยตนเองว่าใครสามารถติดตามพวกเขาได้", + "account.locked_info": "มีการตั้งสถานะความเป็นส่วนตัวของบัญชีนี้เป็นล็อคอยู่ เจ้าของตรวจทานผู้ที่สามารถติดตามเขาด้วยตนเอง", "account.media": "สื่อ", "account.mention": "กล่าวถึง @{name}", "account.moved_to": "{name} ได้ระบุว่าบัญชีใหม่ของเขาในตอนนี้คือ:", @@ -97,7 +97,7 @@ "block_modal.they_will_know": "เขาสามารถเห็นว่ามีการปิดกั้นเขา", "block_modal.title": "ปิดกั้นผู้ใช้?", "block_modal.you_wont_see_mentions": "คุณจะไม่เห็นโพสต์ที่กล่าวถึงเขา", - "boost_modal.combo": "คุณสามารถกด {combo} เพื่อข้ามสิ่งนี้ในครั้งถัดไป", + "boost_modal.combo": "คุณสามารถกดปุ่ม {combo} เพื่อข้ามสิ่งนี้ในครั้งถัดไป", "boost_modal.reblog": "ดันโพสต์?", "boost_modal.undo_reblog": "เลิกดันโพสต์?", "bundle_column_error.copy_stacktrace": "คัดลอกรายงานข้อผิดพลาด", @@ -386,6 +386,7 @@ "interaction_modal.description.follow": "ด้วยบัญชีใน Mastodon คุณสามารถติดตาม {name} เพื่อรับโพสต์ของเขาในฟีดหน้าแรกของคุณ", "interaction_modal.description.reblog": "ด้วยบัญชีใน Mastodon คุณสามารถดันโพสต์นี้เพื่อแชร์โพสต์กับผู้ติดตามของคุณเอง", "interaction_modal.description.reply": "ด้วยบัญชีใน Mastodon คุณสามารถตอบกลับโพสต์นี้", + "interaction_modal.description.vote": "ด้วยบัญชีใน Mastodon คุณสามารถลงคะแนนในการสำรวจความคิดเห็นนี้", "interaction_modal.login.action": "นำฉันกลับบ้าน", "interaction_modal.login.prompt": "โดเมนของเซิร์ฟเวอร์บ้านของคุณ เช่น mastodon.social", "interaction_modal.no_account_yet": "ไม่ได้อยู่ใน Mastodon?", @@ -397,6 +398,7 @@ "interaction_modal.title.follow": "ติดตาม {name}", "interaction_modal.title.reblog": "ดันโพสต์ของ {name}", "interaction_modal.title.reply": "ตอบกลับโพสต์ของ {name}", + "interaction_modal.title.vote": "ลงคะแนนในการสำรวจความคิดเห็นของ {name}", "intervals.full.days": "{number, plural, other {# วัน}}", "intervals.full.hours": "{number, plural, other {# ชั่วโมง}}", "intervals.full.minutes": "{number, plural, other {# นาที}}", @@ -855,11 +857,11 @@ "upload_error.poll": "ไม่อนุญาตการอัปโหลดไฟล์โดยมีการสำรวจความคิดเห็น", "upload_form.audio_description": "อธิบายสำหรับผู้ที่สูญเสียการได้ยิน", "upload_form.description": "อธิบายสำหรับผู้คนที่พิการทางการมองเห็นหรือมีสายตาเลือนราง", - "upload_form.drag_and_drop.instructions": "หากต้องการเลือกไฟล์สื่อ ให้กดปุ่มที Space หรือ Enter บนแป้นพิมพ์ เมื่อเลือกไฟล์ได้แล้ว ก็สามารถใช้ปุ่มลูกศรเพื่อเลื่อนไฟล์ไปในทิศทางที่ต้องการได้ เมื่อต้องการวางไฟล์ในตำแหน่งใหม่ ให้กดปุ่ม Space หรือ Enter ดูอีกครั้ง หรือหากต้องการยกเลิกการเลือก ให้กดปุ่ม Esc ได้", - "upload_form.drag_and_drop.on_drag_cancel": "การลากไฟล์นั้นหยุดชะงัก ไฟล์ที่กำลังแนบมาถูกยกเลิก {item} ได้ถูกลบทิ้งแล้ว", - "upload_form.drag_and_drop.on_drag_end": "ไฟล์แนบ {item} ได้ถูกยกเลิกแล้ว", - "upload_form.drag_and_drop.on_drag_over": "ไฟล์แนบ {item} ได้ถูกย้ายไปแล้ว", - "upload_form.drag_and_drop.on_drag_start": "ได้รับไฟล์แนบเรียบร้อยแล้ว {item}.", + "upload_form.drag_and_drop.instructions": "เพื่อหยิบไฟล์แนบสื่อ กดปุ่มเว้นวรรคหรือขึ้นบรรทัดใหม่ ขณะลาก ใช้ปุ่มลูกศรเพื่อย้ายไฟล์แนบสื่อในทิศทางใดก็ตามที่กำหนด กดปุ่มเว้นวรรคหรือขึ้นบรรทัดใหม่อีกครั้งเพื่อปล่อยไฟล์แนบสื่อในตำแหน่งใหม่ หรือกดปุ่ม Escape เพื่อยกเลิก", + "upload_form.drag_and_drop.on_drag_cancel": "ยกเลิกการลากแล้ว ปล่อยไฟล์แนบสื่อ {item} แล้ว", + "upload_form.drag_and_drop.on_drag_end": "ปล่อยไฟล์แนบสื่อ {item} แล้ว", + "upload_form.drag_and_drop.on_drag_over": "ย้ายไฟล์แนบสื่อ {item} แล้ว", + "upload_form.drag_and_drop.on_drag_start": "หยิบไฟล์แนบสื่อ {item} แล้ว", "upload_form.edit": "แก้ไข", "upload_form.thumbnail": "เปลี่ยนภาพขนาดย่อ", "upload_form.video_description": "อธิบายสำหรับผู้คนที่พิการทางการได้ยิน ได้ยินไม่ชัด พิการทางการมองเห็น หรือมีสายตาเลือนราง", diff --git a/app/lib/annual_report.rb b/app/lib/annual_report.rb index cf4297f2a4..275cc4b87d 100644 --- a/app/lib/annual_report.rb +++ b/app/lib/annual_report.rb @@ -17,11 +17,21 @@ class AnnualReport SCHEMA = 1 + def self.table_name_prefix + 'annual_report_' + end + def initialize(account, year) @account = account @year = year end + def self.prepare(year) + SOURCES.each do |klass| + klass.prepare(year) + end + end + def generate return if GeneratedAnnualReport.exists?(account: @account, year: @year) diff --git a/app/lib/annual_report/percentiles.rb b/app/lib/annual_report/percentiles.rb index 0251cb66ad..2b0305c415 100644 --- a/app/lib/annual_report/percentiles.rb +++ b/app/lib/annual_report/percentiles.rb @@ -1,62 +1,37 @@ # frozen_string_literal: true class AnnualReport::Percentiles < AnnualReport::Source + def self.prepare(year) + AnnualReport::StatusesPerAccountCount.connection.exec_query(<<~SQL.squish, nil, [year, Mastodon::Snowflake.id_at(DateTime.new(year).beginning_of_year), Mastodon::Snowflake.id_at(DateTime.new(year).end_of_year)]) + INSERT INTO annual_report_statuses_per_account_counts (year, account_id, statuses_count) + SELECT $1, account_id, count(*) + FROM statuses + WHERE id BETWEEN $2 AND $3 + AND (local OR uri IS NULL) + GROUP BY account_id + ON CONFLICT (year, account_id) DO NOTHING + SQL + end + def generate { percentiles: { - followers: (total_with_fewer_followers / (total_with_any_followers + 1.0)) * 100, - statuses: (total_with_fewer_statuses / (total_with_any_statuses + 1.0)) * 100, + statuses: 100.0 - ((total_with_fewer_statuses / (total_with_any_statuses + 1.0)) * 100), }, } end private - def followers_gained - @followers_gained ||= @account.passive_relationships.where("date_part('year', follows.created_at) = ?", @year).count - end - def statuses_created @statuses_created ||= report_statuses.count end - def total_with_fewer_followers - @total_with_fewer_followers ||= Follow.find_by_sql([<<~SQL.squish, { year: @year, comparison: followers_gained }]).first.total - WITH tmp0 AS ( - SELECT follows.target_account_id - FROM follows - INNER JOIN accounts ON accounts.id = follows.target_account_id - WHERE date_part('year', follows.created_at) = :year - AND accounts.domain IS NULL - GROUP BY follows.target_account_id - HAVING COUNT(*) < :comparison - ) - SELECT count(*) AS total - FROM tmp0 - SQL - end - def total_with_fewer_statuses - @total_with_fewer_statuses ||= Status.find_by_sql([<<~SQL.squish, { comparison: statuses_created, min_id: year_as_snowflake_range.first, max_id: year_as_snowflake_range.last }]).first.total - WITH tmp0 AS ( - SELECT statuses.account_id - FROM statuses - INNER JOIN accounts ON accounts.id = statuses.account_id - WHERE statuses.id BETWEEN :min_id AND :max_id - AND accounts.domain IS NULL - GROUP BY statuses.account_id - HAVING count(*) < :comparison - ) - SELECT count(*) AS total - FROM tmp0 - SQL - end - - def total_with_any_followers - @total_with_any_followers ||= Follow.where("date_part('year', follows.created_at) = ?", @year).joins(:target_account).merge(Account.local).count('distinct follows.target_account_id') + @total_with_fewer_statuses ||= AnnualReport::StatusesPerAccountCount.where(year: year).where(statuses_count: ...statuses_created).count end def total_with_any_statuses - @total_with_any_statuses ||= Status.where(id: year_as_snowflake_range).joins(:account).merge(Account.local).count('distinct statuses.account_id') + @total_with_any_statuses ||= AnnualReport::StatusesPerAccountCount.where(year: year).count end end diff --git a/app/lib/annual_report/source.rb b/app/lib/annual_report/source.rb index cb9f7b16e3..86528731f5 100644 --- a/app/lib/annual_report/source.rb +++ b/app/lib/annual_report/source.rb @@ -8,6 +8,14 @@ class AnnualReport::Source @year = year end + def self.prepare(_year) + # Use this method if any pre-calculations must be made before individual annual reports are generated + end + + def generate + raise NotImplementedError + end + protected def report_statuses diff --git a/app/models/annual_report/statuses_per_account_count.rb b/app/models/annual_report/statuses_per_account_count.rb new file mode 100644 index 0000000000..05a2f53c9d --- /dev/null +++ b/app/models/annual_report/statuses_per_account_count.rb @@ -0,0 +1,15 @@ +# frozen_string_literal: true + +# == Schema Information +# +# Table name: annual_report_statuses_per_account_counts +# +# id :bigint(8) not null, primary key +# year :integer not null +# account_id :bigint(8) not null +# statuses_count :bigint(8) not null +# + +class AnnualReport::StatusesPerAccountCount < ApplicationRecord + # This table facilitates percentile calculations +end diff --git a/config/initializers/cookie_rotator.rb b/config/initializers/cookie_rotator.rb deleted file mode 100644 index ccc2c6b21f..0000000000 --- a/config/initializers/cookie_rotator.rb +++ /dev/null @@ -1,23 +0,0 @@ -# frozen_string_literal: true - -# TODO: remove this file some time after 4.3.0 - -Rails.application.config.after_initialize do - Rails.application.config.action_dispatch.cookies_rotations.tap do |cookies| - authenticated_encrypted_cookie_salt = Rails.application.config.action_dispatch.authenticated_encrypted_cookie_salt - signed_cookie_salt = Rails.application.config.action_dispatch.signed_cookie_salt - - secret_key_base = Rails.application.secret_key_base - - key_generator = ActiveSupport::KeyGenerator.new( - secret_key_base, iterations: 1000, hash_digest_class: OpenSSL::Digest::SHA1 - ) - key_len = ActiveSupport::MessageEncryptor.key_len - - old_encrypted_secret = key_generator.generate_key(authenticated_encrypted_cookie_salt, key_len) - old_signed_secret = key_generator.generate_key(signed_cookie_salt) - - cookies.rotate :encrypted, old_encrypted_secret - cookies.rotate :signed, old_signed_secret - end -end diff --git a/config/locales/doorkeeper.th.yml b/config/locales/doorkeeper.th.yml index 2dfc72cd6c..3b52e170ea 100644 --- a/config/locales/doorkeeper.th.yml +++ b/config/locales/doorkeeper.th.yml @@ -60,7 +60,7 @@ th: error: title: เกิดข้อผิดพลาด new: - prompt_html: "%{client_name} ร้องขอสิทธิ์ในการเข้าถึงข้อมูลในบัญชีของคุณ อนุมัติคำขอนี้ได้ก็ต่อเมื่อคุณมั่นใจและเชื่อถือในแหล่งที่มาของข้อมูลนี้" + prompt_html: "%{client_name} ต้องการสิทธิอนุญาตเพื่อเข้าถึงบัญชีของคุณ อนุมัติคำขอนี้เฉพาะหากคุณรู้จักและเชื่อถือแหล่งที่มานี้เท่านั้น" review_permissions: ตรวจทานสิทธิอนุญาต title: ต้องการการอนุญาต show: diff --git a/config/locales/fy.yml b/config/locales/fy.yml index 8ccedd2be1..a6656f91b8 100644 --- a/config/locales/fy.yml +++ b/config/locales/fy.yml @@ -21,6 +21,7 @@ fy: one: Toot other: Berjochten posts_tab_heading: Berjochten + self_follow_error: It folgjen fan dyn eigen account is net tastien admin: account_actions: action: Aksje útfiere @@ -1165,8 +1166,11 @@ fy: use_security_key: Befeiligingskaai brûke author_attribution: example_title: Faorbyldtekst + hint_html: Skriuwe jo nijs- of blogartikelen bûten Mastodon? Bepaal hoe’t jo oahelle wurde as dizze dield wurde op Mastodon. + instructions: 'Soargj derfoar dat dizze koade yn de HTML fan jo artikel sit:' more_from_html: Mear fan %{name} s_blog: Weblog fan %{name} + then_instructions: Foegje dernei de domeinnamme fan de publikaasje yn it ûndersteande fjild ta. title: Auteur-attribúsje challenge: confirm: Trochgean diff --git a/config/locales/gd.yml b/config/locales/gd.yml index a05ce6ed3c..c804f42523 100644 --- a/config/locales/gd.yml +++ b/config/locales/gd.yml @@ -262,7 +262,7 @@ gd: destroy_domain_allow_html: Dì-cheadaich %{name} co-nasgadh leis an àrainn %{target} destroy_domain_block_html: Dì-bhac %{name} an àrainn %{target} destroy_email_domain_block_html: Dì-bhac %{name} an àrainn puist-d %{target} - destroy_instance_html: Purgaidich %{name} an àrainn %{target} + destroy_instance_html: Phurgaidich %{name} an àrainn %{target} destroy_ip_block_html: Sguab %{name} às riaghailt dhan IP %{target} destroy_status_html: Thug %{name} post aig %{target} air falbh destroy_unavailable_domain_html: Lean %{name} air adhart leis an lìbhrigeadh dhan àrainn %{target} diff --git a/config/locales/simple_form.fy.yml b/config/locales/simple_form.fy.yml index 8a753dcc89..c840342db5 100644 --- a/config/locales/simple_form.fy.yml +++ b/config/locales/simple_form.fy.yml @@ -3,6 +3,7 @@ fy: simple_form: hints: account: + attribution_domains_as_text: Ien per rigel. Beskermet tsjin falske attribúsjes. discoverable: Jo iepenbiere berjochten kinne útljochte wurde op ferskate plakken binnen Mastodon en jo account kin oanrekommandearre wurde oan oare brûkers. display_name: Jo folsleine namme of in aardige bynamme. fields: Jo website, persoanlike foarnammewurden, leeftiid, alles wat jo mar kwyt wolle. @@ -143,6 +144,7 @@ fy: url: Wêr’t eveneminten nei ta stjoerd wurde labels: account: + attribution_domains_as_text: Websites dy’t jo wurdearring jaan meie discoverable: Profyl en bydragen yn sykalgoritmen opnimme litte fields: name: Label diff --git a/config/locales/simple_form.lv.yml b/config/locales/simple_form.lv.yml index 30f2d2bba4..50fc347fc7 100644 --- a/config/locales/simple_form.lv.yml +++ b/config/locales/simple_form.lv.yml @@ -61,7 +61,7 @@ lv: setting_display_media_hide_all: Vienmēr slēpt multividi setting_display_media_show_all: Vienmēr rādīt multividi setting_use_blurhash: Pāreju pamatā ir paslēpto uzskatāmo līdzekļu krāsas, bet saturs tiek padarīts neskaidrs - setting_use_pending_items: Paslēpt laika skalas atjauninājumus aiz klikšķa, nevis automātiski ritini plūsmu + setting_use_pending_items: Paslēpt laika skalas atjauninājumus aiz klikšķa, nevis ar automātisku plūsmas ritināšanu username: Tu vari lietot burtus, ciparus un zemsvītras whole_word: Ja atslēgvārds vai frāze ir tikai burtciparu, tas tiks lietots tikai tad, ja tas atbilst visam vārdam domain_allow: diff --git a/config/locales/simple_form.nl.yml b/config/locales/simple_form.nl.yml index d2242a4921..d9e9c8bfe5 100644 --- a/config/locales/simple_form.nl.yml +++ b/config/locales/simple_form.nl.yml @@ -3,7 +3,7 @@ nl: simple_form: hints: account: - attribution_domains: Eén per regel. Beschermt tegen valse attribueringen. + attribution_domains: Eén per regel. Beschermt tegen valse toeschrijvingen. discoverable: Jouw openbare berichten kunnen worden uitgelicht op verschillende plekken binnen Mastodon en jouw account kan worden aanbevolen aan andere gebruikers. display_name: Jouw volledige naam of een leuke bijnaam. fields: Jouw website, persoonlijke voornaamwoorden, leeftijd, alles wat je maar kwijt wilt. diff --git a/config/locales/simple_form.sv.yml b/config/locales/simple_form.sv.yml index 1ac2209089..96687f51d2 100644 --- a/config/locales/simple_form.sv.yml +++ b/config/locales/simple_form.sv.yml @@ -74,7 +74,7 @@ sv: filters: action: Välj vilken åtgärd som ska utföras när ett inlägg matchar filtret actions: - hide: Dölj det filtrerade innehållet helt (beter sig som om det inte fanns) + hide: Dölj det filtrerade innehållet helt, beter sig som om det inte fanns warn: Dölj det filtrerade innehållet bakom en varning som visar filtrets rubrik form_admin_settings: activity_api_enabled: Antalet lokalt publicerade inlägg, aktiva användare och nya registrerade konton per vecka diff --git a/config/locales/sv.yml b/config/locales/sv.yml index f3ce6443f6..bd33e837bd 100644 --- a/config/locales/sv.yml +++ b/config/locales/sv.yml @@ -59,7 +59,7 @@ sv: delete: Radera data deleted: Raderad demote: Degradera - destroyed_msg: "%{username}'s data har nu lagts till kön för att raderas omedelbart" + destroyed_msg: "%{username}s data har nu lagts till kön för att raderas omedelbart" disable: inaktivera disable_sign_in_token_auth: Inaktivera autentisering med pollett via e-post disable_two_factor_authentication: Inaktivera 2FA @@ -72,7 +72,7 @@ sv: enable: Aktivera enable_sign_in_token_auth: Aktivera autentisering med pollett via e-post enabled: Aktiverad - enabled_msg: Uppfrysningen av %{username}'s konto lyckades + enabled_msg: Uppfrysningen av %{username}s konto lyckades followers: Följare follows: Följs header: Rubrik @@ -268,21 +268,21 @@ sv: enable_custom_emoji_html: "%{name} aktiverade emoji %{target}" enable_sign_in_token_auth_user_html: "%{name} aktiverade e-posttokenautentisering för %{target}" enable_user_html: "%{name} aktiverade inloggning för användaren %{target}" - memorialize_account_html: "%{name} gjorde %{target}'s konto till en minnessida" + memorialize_account_html: "%{name} gjorde %{target}s konto till en minnessida" promote_user_html: "%{name} befordrade användaren %{target}" reject_appeal_html: "%{name} avvisade överklagande av modereringsbeslut från %{target}" reject_user_html: "%{name} avvisade registrering från %{target}" - remove_avatar_user_html: "%{name} tog bort %{target}'s avatar" + remove_avatar_user_html: "%{name} tog bort %{target}s avatar" reopen_report_html: "%{name} öppnade rapporten igen %{target}" resend_user_html: "%{name} skickade bekräftelsemail för %{target} på nytt" reset_password_user_html: "%{name} återställ användarens lösenord %{target}" resolve_report_html: "%{name} löste rapporten %{target}" - sensitive_account_html: "%{name} markerade %{target}'s media som känsligt" - silence_account_html: "%{name} begränsade %{target}'s konto" + sensitive_account_html: "%{name} markerade %{target}s media som känsligt" + silence_account_html: "%{name} begränsade %{target}s konto" suspend_account_html: "%{name} stängde av %{target}s konto" unassigned_report_html: "%{name} tog bort tilldelning av rapporten %{target}" unblock_email_account_html: "%{name} avblockerade %{target}s e-postadress" - unsensitive_account_html: "%{name} avmarkerade %{target}'s media som känsligt" + unsensitive_account_html: "%{name} avmarkerade %{target}s media som känsligt" unsilence_account_html: "%{name} tog bort begränsning av %{target}s konto" unsuspend_account_html: "%{name} ångrade avstängningen av %{target}s konto" update_announcement_html: "%{name} uppdaterade kungörelsen %{target}" @@ -569,7 +569,7 @@ sv: no_ip_block_selected: Inga IP-regler ändrades då inga var valda title: IP-regler relationships: - title: "%{acct}'s relationer" + title: "%{acct}s relationer" relays: add_new: Lägg till nytt relä delete: Radera @@ -899,7 +899,7 @@ sv: review_requested: Granskning begärd reviewed: Granskat title: Status - trendable: + trendable: Kan trenda unreviewed: Ogranskad usable: Användbar name: Namn @@ -1826,8 +1826,8 @@ sv: tags: does_not_match_previous_name: matchar inte det föregående namnet themes: - contrast: Hög kontrast - default: Mastodon + contrast: Mastodon (Hög kontrast) + default: Mastodon (Mörk) mastodon-light: Mastodon (ljust) system: Automatisk (använd systemtema) time: diff --git a/config/locales/th.yml b/config/locales/th.yml index cdc56d98ce..ea039a2b99 100644 --- a/config/locales/th.yml +++ b/config/locales/th.yml @@ -1148,11 +1148,11 @@ th: use_security_key: ใช้กุญแจความปลอดภัย author_attribution: example_title: ข้อความตัวอย่าง - hint_html: คุณเขียนข่าวหรือลงบทความที่อื่นๆที่นอกจาก Mastodon บ้างไหม? ถ้าหากคุณเขียนอยู่ล่ะก็ คุณสามารถบอกได้นะว่าอยากให้คนอื่นให้เครดิตคุณยังไงเวลาแชร์ไปที่ Mastodon นะ - instructions: 'โปรดตรวจสอบให้แน่ใจว่าโค้ดนี้ได้มีอยู่ในบทความของคุณแล้ว HTML:' + hint_html: คุณกำลังเขียนข่าวหรือบทความบล็อกภายนอก Mastodon หรือไม่? ควบคุมวิธีที่คุณได้รับเครดิตเมื่อมีการแบ่งปันข่าวหรือบทความบล็อกใน Mastodon + instructions: 'ตรวจสอบให้แน่ใจว่าโค้ดนี้อยู่ใน HTML ของบทความของคุณ:' more_from_html: เพิ่มเติมจาก %{name} s_blog: บล็อกของ %{name} - then_instructions: จากนั้น ให้เพิ่มใส่ชื่อเว็บไซต์ของสิ่งพิมพ์ลงไปในช่องว่างข้างล่าง + then_instructions: จากนั้น เพิ่มชื่อโดเมนของการเผยแพร่ในช่องด้านล่าง title: การระบุแหล่งที่มาผู้สร้าง challenge: confirm: ดำเนินการต่อ diff --git a/db/migrate/20241104082851_create_annual_report_statuses_per_account_counts.rb b/db/migrate/20241104082851_create_annual_report_statuses_per_account_counts.rb new file mode 100644 index 0000000000..c8ec30ad57 --- /dev/null +++ b/db/migrate/20241104082851_create_annual_report_statuses_per_account_counts.rb @@ -0,0 +1,13 @@ +# frozen_string_literal: true + +class CreateAnnualReportStatusesPerAccountCounts < ActiveRecord::Migration[7.1] + def change + create_table :annual_report_statuses_per_account_counts do |t| # rubocop:disable Rails/CreateTableWithTimestamps + t.integer :year, null: false + t.bigint :account_id, null: false + t.bigint :statuses_count, null: false + end + + add_index :annual_report_statuses_per_account_counts, [:year, :account_id], unique: true + end +end diff --git a/db/schema.rb b/db/schema.rb index bea9ad46be..ec029366a5 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_10_22_214312) do +ActiveRecord::Schema[7.1].define(version: 2024_11_04_082851) do # These are extensions that must be enabled in order to support this database enable_extension "plpgsql" @@ -260,6 +260,13 @@ ActiveRecord::Schema[7.1].define(version: 2024_10_22_214312) do t.bigint "status_ids", array: true end + create_table "annual_report_statuses_per_account_counts", force: :cascade do |t| + t.integer "year", null: false + t.bigint "account_id", null: false + t.bigint "statuses_count", null: false + t.index ["year", "account_id"], name: "idx_on_year_account_id_ff3e167cef", unique: true + end + create_table "appeals", force: :cascade do |t| t.bigint "account_id", null: false t.bigint "account_warning_id", null: false diff --git a/lib/mastodon/cli/media.rb b/lib/mastodon/cli/media.rb index 996b7fd92c..68420fb15d 100644 --- a/lib/mastodon/cli/media.rb +++ b/lib/mastodon/cli/media.rb @@ -6,6 +6,8 @@ module Mastodon::CLI class Media < Base include ActionView::Helpers::NumberHelper + class UnrecognizedOrphanType < StandardError; end + VALID_PATH_SEGMENTS_SIZE = [7, 10].freeze option :days, type: :numeric, default: 7, aliases: [:d] @@ -120,23 +122,10 @@ module Mastodon::CLI object.acl.put(acl: s3_permissions) if options[:fix_permissions] && !dry_run? path_segments = object.key.split('/') - path_segments.delete('cache') - - unless VALID_PATH_SEGMENTS_SIZE.include?(path_segments.size) - progress.log(pastel.yellow("Unrecognized file found: #{object.key}")) - next - end - - model_name = path_segments.first.classify - attachment_name = path_segments[1].singularize - record_id = path_segments[2...-2].join.to_i - file_name = path_segments.last - record = record_map.dig(model_name, record_id) - attachment = record&.public_send(attachment_name) progress.increment - next unless attachment.blank? || !attachment.variant?(file_name) + next unless orphaned_file?(path_segments, record_map) begin object.delete unless dry_run? @@ -148,6 +137,8 @@ module Mastodon::CLI rescue => e progress.log(pastel.red("Error processing #{object.key}: #{e}")) end + rescue UnrecognizedOrphanType + progress.log(pastel.yellow("Unrecognized file found: #{object.key}")) end end when :fog @@ -165,26 +156,10 @@ module Mastodon::CLI key = path.gsub("#{root_path}#{File::SEPARATOR}", '') path_segments = key.split(File::SEPARATOR) - path_segments.delete('cache') - - unless VALID_PATH_SEGMENTS_SIZE.include?(path_segments.size) - progress.log(pastel.yellow("Unrecognized file found: #{key}")) - next - end - - model_name = path_segments.first.classify - record_id = path_segments[2...-2].join.to_i - attachment_name = path_segments[1].singularize - file_name = path_segments.last - - next unless PRELOADED_MODELS.include?(model_name) - - record = model_name.constantize.find_by(id: record_id) - attachment = record&.public_send(attachment_name) progress.increment - next unless attachment.blank? || !attachment.variant?(file_name) + next unless orphaned_file?(path_segments) begin size = File.size(path) @@ -205,6 +180,8 @@ module Mastodon::CLI rescue => e progress.log(pastel.red("Error processing #{key}: #{e}")) end + rescue UnrecognizedOrphanType + progress.log(pastel.yellow("Unrecognized file found: #{path}")) end end @@ -364,5 +341,23 @@ module Mastodon::CLI model_map[model_name] = model_name.constantize.where(id: record_ids).index_by(&:id) end end + + def orphaned_file?(path_segments, record_map = nil) + path_segments.delete('cache') + + raise UnrecognizedOrphanType unless VALID_PATH_SEGMENTS_SIZE.include?(path_segments.size) + + model_name = path_segments.first.classify + record_id = path_segments[2...-2].join.to_i + attachment_name = path_segments[1].singularize + file_name = path_segments.last + + raise UnrecognizedOrphanType unless PRELOADED_MODELS.include?(model_name) + + record = record_map.present? ? record_map.dig(model_name, record_id) : model_name.constantize.find_by(id: record_id) + attachment = record&.public_send(attachment_name) + + attachment.blank? || !attachment.variant?(file_name) + end end end diff --git a/spec/lib/account_statuses_filter_spec.rb b/spec/lib/account_statuses_filter_spec.rb index 7774585124..351d3dae57 100644 --- a/spec/lib/account_statuses_filter_spec.rb +++ b/spec/lib/account_statuses_filter_spec.rb @@ -52,36 +52,24 @@ RSpec.describe AccountStatusesFilter do end shared_examples 'filter params' do - context 'with only_media param' do - let(:params) { { only_media: true } } + it 'respects param options in results' do + expect(results_for(only_media: true)) + .to all(satisfy(&:with_media?)) - it 'returns only statuses with media' do - expect(subject.all?(&:with_media?)).to be true - end + expect(results_for(tagged: tag.name)) + .to all(satisfy { |status| status.tags.include?(tag) }) + + expect(results_for(exclude_replies: true)) + .to all(satisfy { |status| !status.reply? }) + + expect(results_for(exclude_reblogs: true)) + .to all(satisfy { |status| !status.reblog? }) end - context 'with tagged param' do - let(:params) { { tagged: tag.name } } - - it 'returns only statuses with tag' do - expect(subject.all? { |s| s.tags.include?(tag) }).to be true - end - end - - context 'with exclude_replies param' do - let(:params) { { exclude_replies: true } } - - it 'returns only statuses that are not replies' do - expect(subject.none?(&:reply?)).to be true - end - end - - context 'with exclude_reblogs param' do - let(:params) { { exclude_reblogs: true } } - - it 'returns only statuses that are not reblogs' do - expect(subject.none?(&:reblog?)).to be true - end + def results_for(params) + described_class + .new(account, current_account, params) + .results end end diff --git a/spec/lib/annual_report/percentiles_spec.rb b/spec/lib/annual_report/percentiles_spec.rb index 1d1df3166b..11df81cfb6 100644 --- a/spec/lib/annual_report/percentiles_spec.rb +++ b/spec/lib/annual_report/percentiles_spec.rb @@ -4,17 +4,20 @@ require 'rails_helper' RSpec.describe AnnualReport::Percentiles do describe '#generate' do - subject { described_class.new(account, Time.zone.now.year) } + subject { described_class.new(account, year) } + + let(:year) { Time.zone.now.year } context 'with an inactive account' do let(:account) { Fabricate :account } it 'builds a report for an account' do + described_class.prepare(year) + expect(subject.generate) .to include( percentiles: include( - followers: 0, - statuses: 0 + statuses: 100 ) ) end @@ -25,16 +28,15 @@ RSpec.describe AnnualReport::Percentiles do before do Fabricate.times 2, :status # Others as `account` - Fabricate.times 2, :follow # Others as `target_account` Fabricate.times 2, :status, account: account - Fabricate.times 2, :follow, target_account: account end it 'builds a report for an account' do + described_class.prepare(year) + expect(subject.generate) .to include( percentiles: include( - followers: 50, statuses: 50 ) ) diff --git a/yarn.lock b/yarn.lock index 0b24803e6c..e9bdcb459b 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2206,8 +2206,8 @@ __metadata: linkType: hard "@formatjs/cli@npm:^6.1.1": - version: 6.3.5 - resolution: "@formatjs/cli@npm:6.3.5" + version: 6.3.6 + resolution: "@formatjs/cli@npm:6.3.6" peerDependencies: "@glimmer/env": ^0.1.7 "@glimmer/reference": ^0.91.1 || ^0.92.0 @@ -2236,7 +2236,7 @@ __metadata: optional: true bin: formatjs: bin/formatjs - checksum: 10c0/f3fd57de6df3ef0cfa668813c49acd7dcbecbf52444f30e8edec4ee7bc2d8c47c2e6fb4b7ce3c9c5b4595bdf8416c37953ebb05b400f99874a7f810943f6265b + checksum: 10c0/55f10699644c8b879d7fcf38660e7d9b0642c5f40ca59076c25ba190f350b48d7edb7f3d8481cc6139d3a708ee73f877c2c0a7d1865f15e80a73667270c9b7e3 languageName: node linkType: hard @@ -2251,14 +2251,14 @@ __metadata: languageName: node linkType: hard -"@formatjs/ecma402-abstract@npm:2.2.1": - version: 2.2.1 - resolution: "@formatjs/ecma402-abstract@npm:2.2.1" +"@formatjs/ecma402-abstract@npm:2.2.3": + version: 2.2.3 + resolution: "@formatjs/ecma402-abstract@npm:2.2.3" dependencies: - "@formatjs/fast-memoize": "npm:2.2.2" - "@formatjs/intl-localematcher": "npm:0.5.6" + "@formatjs/fast-memoize": "npm:2.2.3" + "@formatjs/intl-localematcher": "npm:0.5.7" tslib: "npm:2" - checksum: 10c0/bb0b01282368d201d9bcfb3232963af90069f6048da5824d38a674118fd49a0cb92b05d19d2526fe6d035428b2e47e1abd671bb59a673317f1418e67974253fa + checksum: 10c0/611d12bf320fc5c5b85cb2b57e3dcebe8490a51c6a0459c857c7a3560656cd2bdba5b117e9dd7cf174f5aa120c11eaad7a65a6783637b816caa59a1bc5c727f6 languageName: node linkType: hard @@ -2271,12 +2271,12 @@ __metadata: languageName: node linkType: hard -"@formatjs/fast-memoize@npm:2.2.2": - version: 2.2.2 - resolution: "@formatjs/fast-memoize@npm:2.2.2" +"@formatjs/fast-memoize@npm:2.2.3": + version: 2.2.3 + resolution: "@formatjs/fast-memoize@npm:2.2.3" dependencies: tslib: "npm:2" - checksum: 10c0/cebbf632a6ed8798ed67dba59d05be8bbe81c9ada7bcbc8ce69798fbaa5e0117c35792f212097d28b8b06fb99cf73bdbc7754702c06cda34f847e5082814643b + checksum: 10c0/f1004c3b280de7e362bd37c5f48ff34c2ba1d6271d4a7b695fed561d1201a3379397824d8bffbf15fecee344d1e70398393bbb04297f242692310a305f12e75b languageName: node linkType: hard @@ -2291,14 +2291,14 @@ __metadata: languageName: node linkType: hard -"@formatjs/icu-messageformat-parser@npm:2.9.1": - version: 2.9.1 - resolution: "@formatjs/icu-messageformat-parser@npm:2.9.1" +"@formatjs/icu-messageformat-parser@npm:2.9.3": + version: 2.9.3 + resolution: "@formatjs/icu-messageformat-parser@npm:2.9.3" dependencies: - "@formatjs/ecma402-abstract": "npm:2.2.1" - "@formatjs/icu-skeleton-parser": "npm:1.8.5" + "@formatjs/ecma402-abstract": "npm:2.2.3" + "@formatjs/icu-skeleton-parser": "npm:1.8.7" tslib: "npm:2" - checksum: 10c0/53554edc7d41f6bd737dc3bb3e03dcd4b4081b4fc9a70383612b87993c1639747d1d3827d8ebb13f8bf3566c60442549a0a42df4959699eef76633d4c7b49b25 + checksum: 10c0/519b59f7b4cf90681315c5382f7fcd105eb1974486f0d62d9227b6d0498895114ccc818792c208baae1ef79571d93b0edb9914c676e5ab76924dddb7fd6c28a0 languageName: node linkType: hard @@ -2312,35 +2312,35 @@ __metadata: languageName: node linkType: hard -"@formatjs/icu-skeleton-parser@npm:1.8.5": - version: 1.8.5 - resolution: "@formatjs/icu-skeleton-parser@npm:1.8.5" +"@formatjs/icu-skeleton-parser@npm:1.8.7": + version: 1.8.7 + resolution: "@formatjs/icu-skeleton-parser@npm:1.8.7" dependencies: - "@formatjs/ecma402-abstract": "npm:2.2.1" + "@formatjs/ecma402-abstract": "npm:2.2.3" tslib: "npm:2" - checksum: 10c0/3e5ddd26e5dc983547320ca09b4a5daa692a00c15382e85474a9a539c223b581dba2290708d71aae12589c3ddd053b3bfd0dab0a07a11c44033fb313605566bc + checksum: 10c0/e29eb4151580f2d324e6591509dc4543e2326266fc209a08580c94d502acab14acc3560d98b3aaf9ffbd5ff8e2683601ff08c65b32886f22da015c31ca35c5d0 languageName: node linkType: hard -"@formatjs/intl-displaynames@npm:6.8.1": - version: 6.8.1 - resolution: "@formatjs/intl-displaynames@npm:6.8.1" +"@formatjs/intl-displaynames@npm:6.8.3": + version: 6.8.3 + resolution: "@formatjs/intl-displaynames@npm:6.8.3" dependencies: - "@formatjs/ecma402-abstract": "npm:2.2.1" - "@formatjs/intl-localematcher": "npm:0.5.6" + "@formatjs/ecma402-abstract": "npm:2.2.3" + "@formatjs/intl-localematcher": "npm:0.5.7" tslib: "npm:2" - checksum: 10c0/6d39c7bbc3cf0b1398463d662662e5c7c8b873fe977e93b7d702a337f1ed639246492b71b7138c1f193df9e1045add5609edb3fd3efc76c6174ce134c02a186f + checksum: 10c0/54d3ecaabc45dc8494be4cd9633bbf5eb0bc40c5f62ed5e5073aa5b214c4a9a9620d61d1c8a6f0074618474fd9c2ccc42904605078d2f6341c242bf43627bb3a languageName: node linkType: hard -"@formatjs/intl-listformat@npm:7.7.1": - version: 7.7.1 - resolution: "@formatjs/intl-listformat@npm:7.7.1" +"@formatjs/intl-listformat@npm:7.7.3": + version: 7.7.3 + resolution: "@formatjs/intl-listformat@npm:7.7.3" dependencies: - "@formatjs/ecma402-abstract": "npm:2.2.1" - "@formatjs/intl-localematcher": "npm:0.5.6" + "@formatjs/ecma402-abstract": "npm:2.2.3" + "@formatjs/intl-localematcher": "npm:0.5.7" tslib: "npm:2" - checksum: 10c0/9ac38d34956ee8018c000bbd594c84f1de283d18441f1376b072658844735a4ebee61ac4711f824dd0a89f4a855acfc7a24159e4cd8a4747609b1d2153316a61 + checksum: 10c0/2683513e86cc7885528f23237079e3ab9e3a8bc7111aa10d4c685dcbe368ef07039573115df240112fb20f2ec0b70c8ea189ea3b79cbfed7e3dc46024a4667ff languageName: node linkType: hard @@ -2353,43 +2353,43 @@ __metadata: languageName: node linkType: hard -"@formatjs/intl-localematcher@npm:0.5.6": - version: 0.5.6 - resolution: "@formatjs/intl-localematcher@npm:0.5.6" +"@formatjs/intl-localematcher@npm:0.5.7": + version: 0.5.7 + resolution: "@formatjs/intl-localematcher@npm:0.5.7" dependencies: tslib: "npm:2" - checksum: 10c0/39fc454641b7871f4b37416a01c7851624db6f1bf6cdcd5c854dfe06b95c0ca7540ec7c803a654140fc3f1c758596a684de8054bc95c4d6c7962091c251f5671 + checksum: 10c0/1ae374ca146a0d7457794926eed808c99971628e594f704a42ae2540b1f38928b26cbf942a7bbcc2796cc9fe8d9d7a603ac422bd9b89b714d2f91b506da40792 languageName: node linkType: hard "@formatjs/intl-pluralrules@npm:^5.2.2": - version: 5.3.1 - resolution: "@formatjs/intl-pluralrules@npm:5.3.1" + version: 5.3.3 + resolution: "@formatjs/intl-pluralrules@npm:5.3.3" dependencies: - "@formatjs/ecma402-abstract": "npm:2.2.1" - "@formatjs/intl-localematcher": "npm:0.5.6" + "@formatjs/ecma402-abstract": "npm:2.2.3" + "@formatjs/intl-localematcher": "npm:0.5.7" tslib: "npm:2" - checksum: 10c0/71a87aa81d5d69d56dca0636144f8f9714176b95fe3bc92ae1e455322c09b5b09ba0018315d81def00e89fc95e4fbffe41110104c86eb189ba6d58ac09efa48c + checksum: 10c0/003d33af6f5d902517f230b7038e39b8336da3a84500fe5f4278fa5cac0c9a1b746de484f1c2bb2315026fd771491eafdc0aa59a809bb25189b63093efb8400d languageName: node linkType: hard -"@formatjs/intl@npm:2.10.11": - version: 2.10.11 - resolution: "@formatjs/intl@npm:2.10.11" +"@formatjs/intl@npm:2.10.13": + version: 2.10.13 + resolution: "@formatjs/intl@npm:2.10.13" dependencies: - "@formatjs/ecma402-abstract": "npm:2.2.1" - "@formatjs/fast-memoize": "npm:2.2.2" - "@formatjs/icu-messageformat-parser": "npm:2.9.1" - "@formatjs/intl-displaynames": "npm:6.8.1" - "@formatjs/intl-listformat": "npm:7.7.1" - intl-messageformat: "npm:10.7.3" + "@formatjs/ecma402-abstract": "npm:2.2.3" + "@formatjs/fast-memoize": "npm:2.2.3" + "@formatjs/icu-messageformat-parser": "npm:2.9.3" + "@formatjs/intl-displaynames": "npm:6.8.3" + "@formatjs/intl-listformat": "npm:7.7.3" + intl-messageformat: "npm:10.7.5" tslib: "npm:2" peerDependencies: typescript: ^4.7 || 5 peerDependenciesMeta: typescript: optional: true - checksum: 10c0/83baa76d1194dbaae38c21d28cdc4e1ce024f8c49a37e2c02629a9f6afe18912f640435e346fae11af7d8128dac6355b36b93cff37685542ab3095edf3ec6d19 + checksum: 10c0/14edcc45addc181c7a45845bc34cec5c73bb5544dcf8ed455eca916bbd3a5023c7204a8e8e289060545b85006933c6f297c33c4f04a8a4cb3890aa7baae5bfbf languageName: node linkType: hard @@ -2413,13 +2413,13 @@ __metadata: languageName: node linkType: hard -"@formatjs/ts-transformer@npm:3.13.20": - version: 3.13.20 - resolution: "@formatjs/ts-transformer@npm:3.13.20" +"@formatjs/ts-transformer@npm:3.13.22": + version: 3.13.22 + resolution: "@formatjs/ts-transformer@npm:3.13.22" dependencies: - "@formatjs/icu-messageformat-parser": "npm:2.9.1" + "@formatjs/icu-messageformat-parser": "npm:2.9.3" "@types/json-stable-stringify": "npm:1" - "@types/node": "npm:14 || 16 || 17 || 18 || 20" + "@types/node": "npm:14 || 16 || 17 || 18 || 20 || 22" chalk: "npm:4" json-stable-stringify: "npm:1" tslib: "npm:2" @@ -2429,7 +2429,7 @@ __metadata: peerDependenciesMeta: ts-jest: optional: true - checksum: 10c0/0c1a203ce2e0efc24b9c1fc087771330f9630ebb4220e34dd2fffe64d5ee94816554df8ed8402a54dd588c186617765efb6c200a3373cf1d5dfb093ba8d70416 + checksum: 10c0/42503292248bcae728181fdf68e79eac4169c18064953beb9245097d2c58e5434ae7a7978e6ce2829dfd6eb4b4155f78fecef70ac6820626a338f231c66f60cb languageName: node linkType: hard @@ -3445,8 +3445,8 @@ __metadata: linkType: hard "@testing-library/jest-dom@npm:^6.0.0": - version: 6.6.2 - resolution: "@testing-library/jest-dom@npm:6.6.2" + version: 6.6.3 + resolution: "@testing-library/jest-dom@npm:6.6.3" dependencies: "@adobe/css-tools": "npm:^4.4.0" aria-query: "npm:^5.0.0" @@ -3455,7 +3455,7 @@ __metadata: dom-accessibility-api: "npm:^0.6.3" lodash: "npm:^4.17.21" redent: "npm:^3.0.0" - checksum: 10c0/1c51390f97063ce8b06a7267534aac0d6ac9b1f27042a0ae43ca52d886b32c9d2b0ff85e62e7cfeb7e1f089ef03c4d75fda4f2b7b1f08afb4bdb09a5d56566d9 + checksum: 10c0/5566b6c0b7b0709bc244aec3aa3dc9e5f4663e8fb2b99d8cd456fc07279e59db6076cbf798f9d3099a98fca7ef4cd50e4e1f4c4dec5a60a8fad8d24a638a5bf6 languageName: node linkType: hard @@ -3776,9 +3776,9 @@ __metadata: linkType: hard "@types/lodash@npm:^4.14.195": - version: 4.17.12 - resolution: "@types/lodash@npm:4.17.12" - checksum: 10c0/106008f628ea3c74ed7ee7842dee79e230c84e3721ac38c293700031adb5bd130113048c22f476dbde0d0c119506b0fc447d4bd62eca922682d11e00e1377967 + version: 4.17.13 + resolution: "@types/lodash@npm:4.17.13" + checksum: 10c0/c3d0b7efe7933ac0369b99f2f7bff9240d960680fdb74b41ed4bd1b3ca60cca1e31fe4046d9abbde778f941a41bc2a75eb629abf8659fa6c27b66efbbb0802a9 languageName: node linkType: hard @@ -3803,12 +3803,12 @@ __metadata: languageName: node linkType: hard -"@types/node@npm:*, @types/node@npm:14 || 16 || 17 || 18 || 20": - version: 20.16.13 - resolution: "@types/node@npm:20.16.13" +"@types/node@npm:*, @types/node@npm:14 || 16 || 17 || 18 || 20 || 22": + version: 22.8.6 + resolution: "@types/node@npm:22.8.6" dependencies: - undici-types: "npm:~6.19.2" - checksum: 10c0/7f4fd7176db0802c62e11ebbf7a66d0248e2dc8ec9153d9fc8bcb164d9aed581d91c407046c823c522e60d0babfdc24a1618dba7f2c6920ef1a24e1d416c9550 + undici-types: "npm:~6.19.8" + checksum: 10c0/d3a11f2549234a91a4c5d0ff35ab4bdcb7ba34db4d3f1d189be39b8bd41c19aac98d117150a95a9c5a9d45b1014135477ea240b2b8317c86ae3d3cf1c3b3f8f4 languageName: node linkType: hard @@ -3998,7 +3998,7 @@ __metadata: languageName: node linkType: hard -"@types/react@npm:*, @types/react@npm:>=16.9.11, @types/react@npm:^18.2.7, @types/react@npm:^18.3.11": +"@types/react@npm:*, @types/react@npm:16 || 17 || 18, @types/react@npm:>=16.9.11, @types/react@npm:^18.2.7": version: 18.3.12 resolution: "@types/react@npm:18.3.12" dependencies: @@ -4151,11 +4151,11 @@ __metadata: linkType: hard "@types/ws@npm:^8.5.9": - version: 8.5.12 - resolution: "@types/ws@npm:8.5.12" + version: 8.5.13 + resolution: "@types/ws@npm:8.5.13" dependencies: "@types/node": "npm:*" - checksum: 10c0/3fd77c9e4e05c24ce42bfc7647f7506b08c40a40fe2aea236ef6d4e96fc7cb4006a81ed1b28ec9c457e177a74a72924f4768b7b4652680b42dfd52bc380e15f9 + checksum: 10c0/a5430aa479bde588e69cb9175518d72f9338b6999e3b2ae16fc03d3bdcff8347e486dc031e4ed14601260463c07e1f9a0d7511dfc653712b047c439c680b0b34 languageName: node linkType: hard @@ -5180,21 +5180,21 @@ __metadata: linkType: hard "babel-plugin-formatjs@npm:^10.5.1": - version: 10.5.22 - resolution: "babel-plugin-formatjs@npm:10.5.22" + version: 10.5.24 + resolution: "babel-plugin-formatjs@npm:10.5.24" dependencies: "@babel/core": "npm:^7.25.0" "@babel/helper-plugin-utils": "npm:^7.25.0" "@babel/plugin-syntax-jsx": "npm:^7.25.0" "@babel/traverse": "npm:^7.25.0" "@babel/types": "npm:^7.25.0" - "@formatjs/icu-messageformat-parser": "npm:2.9.1" - "@formatjs/ts-transformer": "npm:3.13.20" + "@formatjs/icu-messageformat-parser": "npm:2.9.3" + "@formatjs/ts-transformer": "npm:3.13.22" "@types/babel__core": "npm:^7.20.5" "@types/babel__helper-plugin-utils": "npm:^7.10.3" "@types/babel__traverse": "npm:^7.20.6" tslib: "npm:2" - checksum: 10c0/c35ec81d89eb228d23d3d62e7e4d0e5d7216f0d09f91b1dc3c46e049c5515a201fcfe77c1079924c6bfb9883b2941af91431f479a0f5a24a0574b695f18b64bc + checksum: 10c0/a99c92e62edb30e0b6a5bf1115811eb18336b851109f8c096b5a9aa2be3eb72299eea3a8cb706e03705eb79edfa5a62d69bb52d80a375c1d5a1c963e3d00c40e languageName: node linkType: hard @@ -9741,15 +9741,15 @@ __metadata: languageName: node linkType: hard -"intl-messageformat@npm:10.7.3, intl-messageformat@npm:^10.3.5": - version: 10.7.3 - resolution: "intl-messageformat@npm:10.7.3" +"intl-messageformat@npm:10.7.5, intl-messageformat@npm:^10.3.5": + version: 10.7.5 + resolution: "intl-messageformat@npm:10.7.5" dependencies: - "@formatjs/ecma402-abstract": "npm:2.2.1" - "@formatjs/fast-memoize": "npm:2.2.2" - "@formatjs/icu-messageformat-parser": "npm:2.9.1" + "@formatjs/ecma402-abstract": "npm:2.2.3" + "@formatjs/fast-memoize": "npm:2.2.3" + "@formatjs/icu-messageformat-parser": "npm:2.9.3" tslib: "npm:2" - checksum: 10c0/7ddd118c04023c9ecdf9a2270753abd876e90a428d5106ce8373622ddefe72ff1daa33993b12065a3339b7f838e9266c3db9048aa7dd20012c8703c6ebe26fd4 + checksum: 10c0/1aa173a8c16ace50520af3de7d3f0ce9bafda90d47b6d674eb88cc47c12c3460d4d53c97ca412fae1141b00abb8ff2ba313250997a040837f01a25379165c949 languageName: node linkType: hard @@ -14474,18 +14474,18 @@ __metadata: linkType: hard "react-intl@npm:^6.4.2": - version: 6.8.4 - resolution: "react-intl@npm:6.8.4" + version: 6.8.6 + resolution: "react-intl@npm:6.8.6" dependencies: - "@formatjs/ecma402-abstract": "npm:2.2.1" - "@formatjs/icu-messageformat-parser": "npm:2.9.1" - "@formatjs/intl": "npm:2.10.11" - "@formatjs/intl-displaynames": "npm:6.8.1" - "@formatjs/intl-listformat": "npm:7.7.1" + "@formatjs/ecma402-abstract": "npm:2.2.3" + "@formatjs/icu-messageformat-parser": "npm:2.9.3" + "@formatjs/intl": "npm:2.10.13" + "@formatjs/intl-displaynames": "npm:6.8.3" + "@formatjs/intl-listformat": "npm:7.7.3" "@types/hoist-non-react-statics": "npm:3" - "@types/react": "npm:^18.3.11" + "@types/react": "npm:16 || 17 || 18" hoist-non-react-statics: "npm:3" - intl-messageformat: "npm:10.7.3" + intl-messageformat: "npm:10.7.5" tslib: "npm:2" peerDependencies: react: ^16.6.0 || 17 || 18 @@ -14493,7 +14493,7 @@ __metadata: peerDependenciesMeta: typescript: optional: true - checksum: 10c0/a6b417c1cfb36ffe38645fe9daaaf3e1a25660468b8dbd4ccf386be063cc7c0fdeecc3c0490c671721408696b6578262b8db5882d00b76d4ec48d94601b14eab + checksum: 10c0/ec88cc2b1d0edf089f04c8061ffda730840fb3317177d0dc1a6df208245ec278f52b4ca8546ff9511b0b28ff2d89863c5837a274d33731d4c8f75a3b3baafbe2 languageName: node linkType: hard @@ -17339,7 +17339,7 @@ __metadata: languageName: node linkType: hard -"undici-types@npm:~6.19.2": +"undici-types@npm:~6.19.8": version: 6.19.8 resolution: "undici-types@npm:6.19.8" checksum: 10c0/078afa5990fba110f6824823ace86073b4638f1d5112ee26e790155f481f2a868cc3e0615505b6f4282bdf74a3d8caad715fd809e870c2bb0704e3ea6082f344 @@ -17599,12 +17599,12 @@ __metadata: linkType: hard "utf-8-validate@npm:^6.0.3": - version: 6.0.4 - resolution: "utf-8-validate@npm:6.0.4" + version: 6.0.5 + resolution: "utf-8-validate@npm:6.0.5" dependencies: node-gyp: "npm:latest" node-gyp-build: "npm:^4.3.0" - checksum: 10c0/f7042d94aec6ca02461b64e725bdc7262266610dbb787331e5bbd49374ef6f75fe9900600df3fc63d97906c23614a965c8989b4bf95d70bf35dc617da99215e7 + checksum: 10c0/6dc63c513adb001e47a51819072cdd414158430091c49c21d4947ea99f16df5167b671f680df8fb2b6f2ae6a7f30264b4ec111bd3e573720dfe371da1ab99a81 languageName: node linkType: hard