Merge pull request #713 from kmycode/upstream-20240417

Upstream 20240417
This commit is contained in:
KMY(雪あすか) 2024-04-17 19:57:09 +09:00 committed by GitHub
commit a97eb2433b
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
76 changed files with 835 additions and 307 deletions

View file

@ -112,7 +112,6 @@ jobs:
fail-fast: false fail-fast: false
matrix: matrix:
ruby-version: ruby-version:
- '3.0'
- '3.1' - '3.1'
- '.ruby-version' - '.ruby-version'
- '3.3' - '3.3'
@ -189,7 +188,6 @@ jobs:
fail-fast: false fail-fast: false
matrix: matrix:
ruby-version: ruby-version:
- '3.0'
- '3.1' - '3.1'
- '.ruby-version' - '.ruby-version'
- '3.3' - '3.3'
@ -276,7 +274,6 @@ jobs:
fail-fast: false fail-fast: false
matrix: matrix:
ruby-version: ruby-version:
- '3.0'
- '3.1' - '3.1'
- '.ruby-version' - '.ruby-version'
- '3.3' - '3.3'

View file

@ -14,7 +14,7 @@ require:
- ./lib/linter/rubocop_middle_dot - ./lib/linter/rubocop_middle_dot
AllCops: AllCops:
TargetRubyVersion: 3.0 # Set to minimum supported version of CI TargetRubyVersion: 3.1 # Set to minimum supported version of CI
DisplayCopNames: true DisplayCopNames: true
DisplayStyleGuide: true DisplayStyleGuide: true
ExtraDetails: true ExtraDetails: true
@ -92,6 +92,11 @@ Metrics/PerceivedComplexity:
- 'app/services/delivery_antenna_service.rb' - 'app/services/delivery_antenna_service.rb'
- 'app/services/post_status_service.rb' - 'app/services/post_status_service.rb'
# Reason: Prefer seeing a variable name
# https://docs.rubocop.org/rubocop/cops_naming.html#namingblockforwarding
Naming/BlockForwarding:
EnforcedStyle: explicit
# Reason: Prevailing style is argument file paths # Reason: Prevailing style is argument file paths
# https://docs.rubocop.org/rubocop-rails/cops_rails.html#railsfilepath # https://docs.rubocop.org/rubocop-rails/cops_rails.html#railsfilepath
Rails/FilePath: Rails/FilePath:
@ -192,6 +197,7 @@ Style/FormatStringToken:
# https://docs.rubocop.org/rubocop/cops_style.html#stylehashsyntax # https://docs.rubocop.org/rubocop/cops_style.html#stylehashsyntax
Style/HashSyntax: Style/HashSyntax:
EnforcedStyle: ruby19_no_mixed_keys EnforcedStyle: ruby19_no_mixed_keys
EnforcedShorthandSyntax: either
# Reason: # Reason:
# https://docs.rubocop.org/rubocop/cops_style.html#stylenumericliterals # https://docs.rubocop.org/rubocop/cops_style.html#stylenumericliterals

View file

@ -100,7 +100,6 @@ Style/FetchEnvVar:
- 'config/initializers/paperclip.rb' - 'config/initializers/paperclip.rb'
- 'config/initializers/vapid.rb' - 'config/initializers/vapid.rb'
- 'lib/mastodon/redis_config.rb' - 'lib/mastodon/redis_config.rb'
- 'lib/premailer_webpack_strategy.rb'
- 'lib/tasks/repo.rake' - 'lib/tasks/repo.rake'
- 'spec/features/profile_spec.rb' - 'spec/features/profile_spec.rb'
@ -253,11 +252,6 @@ Style/SignalException:
- 'lib/devise/strategies/two_factor_ldap_authenticatable.rb' - 'lib/devise/strategies/two_factor_ldap_authenticatable.rb'
- 'lib/devise/strategies/two_factor_pam_authenticatable.rb' - 'lib/devise/strategies/two_factor_pam_authenticatable.rb'
# This cop supports unsafe autocorrection (--autocorrect-all).
Style/SingleArgumentDig:
Exclude:
- 'lib/webpacker/manifest_extensions.rb'
# This cop supports unsafe autocorrection (--autocorrect-all). # This cop supports unsafe autocorrection (--autocorrect-all).
# Configuration parameters: Mode. # Configuration parameters: Mode.
Style/StringConcatenation: Style/StringConcatenation:

View file

@ -1,7 +1,7 @@
# frozen_string_literal: true # frozen_string_literal: true
source 'https://rubygems.org' source 'https://rubygems.org'
ruby '>= 3.0.0' ruby '>= 3.1.0'
gem 'puma', '~> 6.3' gem 'puma', '~> 6.3'
gem 'rails', '~> 7.1.1' gem 'rails', '~> 7.1.1'

View file

@ -648,7 +648,7 @@ GEM
rspec-mocks (~> 3.0) rspec-mocks (~> 3.0)
sidekiq (>= 5, < 8) sidekiq (>= 5, < 8)
rspec-support (3.13.1) rspec-support (3.13.1)
rubocop (1.62.1) rubocop (1.63.2)
json (~> 2.3) json (~> 2.3)
language_server-protocol (>= 3.17.0) language_server-protocol (>= 3.17.0)
parallel (~> 1.10) parallel (~> 1.10)

View file

@ -46,9 +46,11 @@ class AccountsController < ApplicationController
end end
def default_statuses def default_statuses
visibilities = [:public, :unlisted, :public_unlisted] if current_account.present?
visibilities << :login unless current_account.nil? @account.statuses.distributable_visibility
@account.statuses.where(visibility: visibilities) else
@account.statuses.distributable_visibility_for_anonymous
end
end end
def only_media_scope def only_media_scope

View file

@ -31,7 +31,7 @@ class ActivityPub::RepliesController < ActivityPub::BaseController
def set_replies def set_replies
@replies = only_other_accounts? ? Status.where.not(account_id: @account.id).joins(:account).merge(Account.without_suspended) : @account.statuses @replies = only_other_accounts? ? Status.where.not(account_id: @account.id).joins(:account).merge(Account.without_suspended) : @account.statuses
@replies = @replies.where(in_reply_to_id: @status.id, visibility: [:public, :unlisted, :public_unlisted, :login]) @replies = @replies.distributable_visibility.where(in_reply_to_id: @status.id)
@replies = @replies.paginate_by_min_id(DESCENDANTS_LIMIT, params[:min_id]) @replies = @replies.paginate_by_min_id(DESCENDANTS_LIMIT, params[:min_id])
end end

View file

@ -23,7 +23,7 @@ class Api::V1::Statuses::RebloggedByAccountsController < Api::V1::Statuses::Base
end end
def paginated_statuses def paginated_statuses
Status.where(reblog_of_id: @status.id).where(visibility: [:public, :unlisted, :public_unlisted, :login]).paginate_by_max_id( Status.where(reblog_of_id: @status.id).distributable_visibility.paginate_by_max_id(
limit_param(DEFAULT_ACCOUNTS_LIMIT), limit_param(DEFAULT_ACCOUNTS_LIMIT),
params[:max_id], params[:max_id],
params[:since_id] params[:since_id]

View file

@ -19,6 +19,6 @@ module BrandingHelper
end end
def render_logo def render_logo
image_pack_tag('logo.svg', alt: 'Mastodon', class: 'logo logo--icon') image_tag(frontend_asset_path('images/logo.svg'), alt: 'Mastodon', class: 'logo logo--icon')
end end
end end

View file

@ -3,8 +3,8 @@
module ThemeHelper module ThemeHelper
def theme_style_tags(theme) def theme_style_tags(theme)
if theme == 'system' if theme == 'system'
concat stylesheet_pack_tag('mastodon-light', media: 'not all and (prefers-color-scheme: dark)', crossorigin: 'anonymous') stylesheet_pack_tag('mastodon-light', media: 'not all and (prefers-color-scheme: dark)', crossorigin: 'anonymous') +
concat stylesheet_pack_tag('default', media: '(prefers-color-scheme: dark)', crossorigin: 'anonymous') stylesheet_pack_tag('default', media: '(prefers-color-scheme: dark)', crossorigin: 'anonymous')
else else
stylesheet_pack_tag theme, media: 'all', crossorigin: 'anonymous' stylesheet_pack_tag theme, media: 'all', crossorigin: 'anonymous'
end end
@ -12,8 +12,8 @@ module ThemeHelper
def theme_color_tags(theme) def theme_color_tags(theme)
if theme == 'system' if theme == 'system'
concat tag.meta(name: 'theme-color', content: Themes::THEME_COLORS[:dark], media: '(prefers-color-scheme: dark)') tag.meta(name: 'theme-color', content: Themes::THEME_COLORS[:dark], media: '(prefers-color-scheme: dark)') +
concat tag.meta(name: 'theme-color', content: Themes::THEME_COLORS[:light], media: '(prefers-color-scheme: light)') tag.meta(name: 'theme-color', content: Themes::THEME_COLORS[:light], media: '(prefers-color-scheme: light)')
else else
tag.meta name: 'theme-color', content: theme_color_for(theme) tag.meta name: 'theme-color', content: theme_color_for(theme)
end end

View file

@ -107,7 +107,7 @@ class KeyboardShortcuts extends ImmutablePureComponent {
<td><FormattedMessage id='keyboard_shortcuts.back' defaultMessage='to navigate back' /></td> <td><FormattedMessage id='keyboard_shortcuts.back' defaultMessage='to navigate back' /></td>
</tr> </tr>
<tr> <tr>
<td><kbd>s</kbd></td> <td><kbd>s</kbd>, <kbd>/</kbd></td>
<td><FormattedMessage id='keyboard_shortcuts.search' defaultMessage='to focus search' /></td> <td><FormattedMessage id='keyboard_shortcuts.search' defaultMessage='to focus search' /></td>
</tr> </tr>
<tr> <tr>

View file

@ -42,7 +42,7 @@ export const FilteredNotificationsBanner = () => {
<div className='filtered-notifications-banner__badge'> <div className='filtered-notifications-banner__badge'>
<div className='filtered-notifications-banner__badge__badge'>{toCappedNumber(policy.getIn(['summary', 'pending_notifications_count']))}</div> <div className='filtered-notifications-banner__badge__badge'>{toCappedNumber(policy.getIn(['summary', 'pending_notifications_count']))}</div>
<FormattedMessage id='filtered_notifications_banner.private_mentions' defaultMessage='{count, plural, one {private mention} other {private mentions}}' values={{ count: policy.getIn(['summary', 'pending_notifications_count']) }} /> <FormattedMessage id='filtered_notifications_banner.mentions' defaultMessage='{count, plural, one {mention} other {mentions}}' values={{ count: policy.getIn(['summary', 'pending_notifications_count']) }} />
</div> </div>
</Link> </Link>
); );

View file

@ -102,7 +102,7 @@ const mapStateToProps = state => ({
const keyMap = { const keyMap = {
help: '?', help: '?',
new: 'n', new: 'n',
search: 's', search: ['s', '/'],
forceNew: 'option+n', forceNew: 'option+n',
toggleComposeSpoilers: 'option+x', toggleComposeSpoilers: 'option+x',
focusColumn: ['1', '2', '3', '4', '5', '6', '7', '8', '9'], focusColumn: ['1', '2', '3', '4', '5', '6', '7', '8', '9'],

View file

@ -89,6 +89,14 @@
"announcement.announcement": "Announcement", "announcement.announcement": "Announcement",
"attachments_list.unprocessed": "(unprocessed)", "attachments_list.unprocessed": "(unprocessed)",
"audio.hide": "Hide audio", "audio.hide": "Hide audio",
"block_modal.remote_users_caveat": "We will ask the server {domain} to respect your decision. However, compliance is not guaranteed since some servers may handle blocks differently. Public posts may still be visible to non-logged-in users.",
"block_modal.show_less": "Show less",
"block_modal.show_more": "Show more",
"block_modal.they_cant_mention": "They can't mention or follow you.",
"block_modal.they_cant_see_posts": "They can't see your posts and you won't see theirs.",
"block_modal.they_will_know": "They can see that they're blocked.",
"block_modal.title": "Block user?",
"block_modal.you_wont_see_mentions": "You won't see posts that mention them.",
"boost_modal.combo": "You can press {combo} to skip this next time", "boost_modal.combo": "You can press {combo} to skip this next time",
"bundle_column_error.copy_stacktrace": "Copy error report", "bundle_column_error.copy_stacktrace": "Copy error report",
"bundle_column_error.error.body": "The requested page could not be rendered. It could be due to a bug in our code, or a browser compatibility issue.", "bundle_column_error.error.body": "The requested page could not be rendered. It could be due to a bug in our code, or a browser compatibility issue.",
@ -169,6 +177,7 @@
"confirmations.delete_list.message": "Are you sure you want to permanently delete this list?", "confirmations.delete_list.message": "Are you sure you want to permanently delete this list?",
"confirmations.discard_edit_media.confirm": "Discard", "confirmations.discard_edit_media.confirm": "Discard",
"confirmations.discard_edit_media.message": "You have unsaved changes to the media description or preview, discard them anyway?", "confirmations.discard_edit_media.message": "You have unsaved changes to the media description or preview, discard them anyway?",
"confirmations.domain_block.confirm": "Block server",
"confirmations.domain_block.message": "Are you really, really sure you want to block the entire {domain}? In most cases a few targeted blocks or mutes are sufficient and preferable. You will not see content from that domain in any public timelines or your notifications. Your followers from that domain will be removed.", "confirmations.domain_block.message": "Are you really, really sure you want to block the entire {domain}? In most cases a few targeted blocks or mutes are sufficient and preferable. You will not see content from that domain in any public timelines or your notifications. Your followers from that domain will be removed.",
"confirmations.edit.confirm": "Edit", "confirmations.edit.confirm": "Edit",
"confirmations.edit.message": "Editing now will overwrite the message you are currently composing. Are you sure you want to proceed?", "confirmations.edit.message": "Editing now will overwrite the message you are currently composing. Are you sure you want to proceed?",
@ -431,6 +440,7 @@
"notifications.column_settings.admin.sign_up": "New sign-ups:", "notifications.column_settings.admin.sign_up": "New sign-ups:",
"notifications.column_settings.alert": "Desktop notifications", "notifications.column_settings.alert": "Desktop notifications",
"notifications.column_settings.favourite": "Favourites:", "notifications.column_settings.favourite": "Favourites:",
"notifications.column_settings.filter_bar.category": "Quick filter bar",
"notifications.column_settings.follow": "New followers:", "notifications.column_settings.follow": "New followers:",
"notifications.column_settings.follow_request": "New follow requests:", "notifications.column_settings.follow_request": "New follow requests:",
"notifications.column_settings.mention": "Mentions:", "notifications.column_settings.mention": "Mentions:",
@ -456,6 +466,15 @@
"notifications.permission_denied": "Desktop notifications are unavailable due to previously denied browser permissions request", "notifications.permission_denied": "Desktop notifications are unavailable due to previously denied browser permissions request",
"notifications.permission_denied_alert": "Desktop notifications can't be enabled, as browser permission has been denied before", "notifications.permission_denied_alert": "Desktop notifications can't be enabled, as browser permission has been denied before",
"notifications.permission_required": "Desktop notifications are unavailable because the required permission has not been granted.", "notifications.permission_required": "Desktop notifications are unavailable because the required permission has not been granted.",
"notifications.policy.filter_new_accounts.hint": "Created within the past {days, plural, one {one day} other {# days}}",
"notifications.policy.filter_new_accounts_title": "New accounts",
"notifications.policy.filter_not_followers_hint": "Including people who have been following you fewer than {days, plural, one {one day} other {# days}}",
"notifications.policy.filter_not_followers_title": "People not following you",
"notifications.policy.filter_not_following_hint": "Until you manually approve them",
"notifications.policy.filter_not_following_title": "People you don't follow",
"notifications.policy.filter_private_mentions_hint": "Filtered unless it's in reply to your own mention or if you follow the sender",
"notifications.policy.filter_private_mentions_title": "Unsolicited private mentions",
"notifications.policy.title": "Filter out notifications from…",
"notifications_permission_banner.enable": "Enable desktop notifications", "notifications_permission_banner.enable": "Enable desktop notifications",
"notifications_permission_banner.how_to_control": "To receive notifications when Mastodon isn't open, enable desktop notifications. You can control precisely which types of interactions generate desktop notifications through the {icon} button above once they're enabled.", "notifications_permission_banner.how_to_control": "To receive notifications when Mastodon isn't open, enable desktop notifications. You can control precisely which types of interactions generate desktop notifications through the {icon} button above once they're enabled.",
"notifications_permission_banner.title": "Never miss a thing", "notifications_permission_banner.title": "Never miss a thing",
@ -632,9 +651,11 @@
"status.direct": "Privately mention @{name}", "status.direct": "Privately mention @{name}",
"status.direct_indicator": "Private mention", "status.direct_indicator": "Private mention",
"status.edit": "Edit", "status.edit": "Edit",
"status.edited": "Last edited {date}",
"status.edited_x_times": "Edited {count, plural, one {{count} time} other {{count} times}}", "status.edited_x_times": "Edited {count, plural, one {{count} time} other {{count} times}}",
"status.embed": "Embed", "status.embed": "Embed",
"status.favourite": "Favourite", "status.favourite": "Favourite",
"status.favourites": "{count, plural, one {favorite} other {favorites}}",
"status.filter": "Filter this post", "status.filter": "Filter this post",
"status.filtered": "Filtered", "status.filtered": "Filtered",
"status.hide": "Hide post", "status.hide": "Hide post",
@ -655,6 +676,7 @@
"status.reblog": "Boost", "status.reblog": "Boost",
"status.reblog_private": "Boost with original visibility", "status.reblog_private": "Boost with original visibility",
"status.reblogged_by": "{name} boosted", "status.reblogged_by": "{name} boosted",
"status.reblogs": "{count, plural, one {boost} other {boosts}}",
"status.reblogs.empty": "No one has boosted this post yet. When someone does, they will show up here.", "status.reblogs.empty": "No one has boosted this post yet. When someone does, they will show up here.",
"status.redraft": "Delete & re-draft", "status.redraft": "Delete & re-draft",
"status.remove_bookmark": "Remove bookmark", "status.remove_bookmark": "Remove bookmark",

View file

@ -400,8 +400,8 @@
"filter_modal.select_filter.subtitle": "Use an existing category or create a new one", "filter_modal.select_filter.subtitle": "Use an existing category or create a new one",
"filter_modal.select_filter.title": "Filter this post", "filter_modal.select_filter.title": "Filter this post",
"filter_modal.title.status": "Filter a post", "filter_modal.title.status": "Filter a post",
"filtered_notifications_banner.mentions": "{count, plural, one {mention} other {mentions}}",
"filtered_notifications_banner.pending_requests": "Notifications from {count, plural, =0 {no one} one {one person} other {# people}} you may know", "filtered_notifications_banner.pending_requests": "Notifications from {count, plural, =0 {no one} one {one person} other {# people}} you may know",
"filtered_notifications_banner.private_mentions": "{count, plural, one {private mention} other {private mentions}}",
"filtered_notifications_banner.title": "Filtered notifications", "filtered_notifications_banner.title": "Filtered notifications",
"firehose.all": "All", "firehose.all": "All",
"firehose.local": "This server", "firehose.local": "This server",

View file

@ -148,7 +148,7 @@
"compose.published.open": "Ireki", "compose.published.open": "Ireki",
"compose.saved.body": "Argitalpena gorde da.", "compose.saved.body": "Argitalpena gorde da.",
"compose_form.direct_message_warning_learn_more": "Ikasi gehiago", "compose_form.direct_message_warning_learn_more": "Ikasi gehiago",
"compose_form.encryption_warning": "Mastodoneko bidalketak ez daude muturretik muturrera enkriptatuta. Ez partekatu informazio sentikorrik Mastodonen.", "compose_form.encryption_warning": "Mastodon-go bidalketak ez daude muturretik muturrera enkriptatuta. Ez partekatu informazio sentikorrik Mastodonen.",
"compose_form.hashtag_warning": "Tut hau ez da inolako traolatan zerrendatuko, ez baita publikoa. Tut publikoak soilik traolen bitartez bila daitezke.", "compose_form.hashtag_warning": "Tut hau ez da inolako traolatan zerrendatuko, ez baita publikoa. Tut publikoak soilik traolen bitartez bila daitezke.",
"compose_form.lock_disclaimer": "Zure kontua ez dago {locked}. Edonork jarraitu zaitzake zure jarraitzaileentzako soilik diren bidalketak ikusteko.", "compose_form.lock_disclaimer": "Zure kontua ez dago {locked}. Edonork jarraitu zaitzake zure jarraitzaileentzako soilik diren bidalketak ikusteko.",
"compose_form.lock_disclaimer.lock": "giltzapetuta", "compose_form.lock_disclaimer.lock": "giltzapetuta",
@ -345,7 +345,7 @@
"home.column_settings.show_reblogs": "Erakutsi bultzadak", "home.column_settings.show_reblogs": "Erakutsi bultzadak",
"home.column_settings.show_replies": "Erakutsi erantzunak", "home.column_settings.show_replies": "Erakutsi erantzunak",
"home.hide_announcements": "Ezkutatu iragarpenak", "home.hide_announcements": "Ezkutatu iragarpenak",
"home.pending_critical_update.body": "Eguneratu zure Mastodoneko zerbitzaria leheinbailehen!", "home.pending_critical_update.body": "Eguneratu zure Mastodon-go zerbitzaria leheinbailehen!",
"home.pending_critical_update.link": "Ikusi eguneraketak", "home.pending_critical_update.link": "Ikusi eguneraketak",
"home.pending_critical_update.title": "Segurtasun eguneraketa kritikoa eskuragarri!", "home.pending_critical_update.title": "Segurtasun eguneraketa kritikoa eskuragarri!",
"home.show_announcements": "Erakutsi iragarpenak", "home.show_announcements": "Erakutsi iragarpenak",
@ -408,7 +408,7 @@
"lightbox.previous": "Aurrekoa", "lightbox.previous": "Aurrekoa",
"limited_account_hint.action": "Erakutsi profila hala ere", "limited_account_hint.action": "Erakutsi profila hala ere",
"limited_account_hint.title": "Profil hau ezkutatu egin dute {domain} zerbitzariko moderatzaileek.", "limited_account_hint.title": "Profil hau ezkutatu egin dute {domain} zerbitzariko moderatzaileek.",
"link_preview.author": "{name}(r)en eskutik", "link_preview.author": "Egilea: {name}",
"lists.account.add": "Gehitu zerrendara", "lists.account.add": "Gehitu zerrendara",
"lists.account.remove": "Kendu zerrendatik", "lists.account.remove": "Kendu zerrendatik",
"lists.delete": "Ezabatu zerrenda", "lists.delete": "Ezabatu zerrenda",
@ -548,7 +548,7 @@
"onboarding.share.message": "{username} naiz #Mastodon-en! Jarrai nazazu hemen: {url}", "onboarding.share.message": "{username} naiz #Mastodon-en! Jarrai nazazu hemen: {url}",
"onboarding.share.next_steps": "Hurrengo urrats posibleak:", "onboarding.share.next_steps": "Hurrengo urrats posibleak:",
"onboarding.share.title": "Partekatu zure profila", "onboarding.share.title": "Partekatu zure profila",
"onboarding.start.lead": "Mastodonen parte zara orain, bakarra eta deszentralizatua den sare-sozialaren plataforma, non zuk, eta ez algoritmo batek, zeure esperientzia pertsonaliza dezakezun. Igaro ezazu muga soziala:", "onboarding.start.lead": "Mastodon-en parte zara orain, bakarra eta deszentralizatua den sare sozialaren plataforma, non zuk, eta ez algoritmo batek, zeure esperientzia pertsonaliza dezakezun. Igaro ezazu muga soziala:",
"onboarding.start.skip": "Urrats guztiak saltatu nahi dituzu?", "onboarding.start.skip": "Urrats guztiak saltatu nahi dituzu?",
"onboarding.start.title": "Lortu duzu!", "onboarding.start.title": "Lortu duzu!",
"onboarding.steps.follow_people.body": "Zure jarioa zuk pertsonalizatzen duzu. Bete dezagun jende interesgarriaz.", "onboarding.steps.follow_people.body": "Zure jarioa zuk pertsonalizatzen duzu. Bete dezagun jende interesgarriaz.",
@ -562,7 +562,7 @@
"onboarding.tips.2fa": "<strong>Bazenekien?</strong> Zure kontua babes dezakezu, bi faktoreko autentifikazioa zure kontuko ezarpenetan ezarriaz. Edozein TOTP aplikaziorekin dabil, ez da telefono-zenbakirik behar!", "onboarding.tips.2fa": "<strong>Bazenekien?</strong> Zure kontua babes dezakezu, bi faktoreko autentifikazioa zure kontuko ezarpenetan ezarriaz. Edozein TOTP aplikaziorekin dabil, ez da telefono-zenbakirik behar!",
"onboarding.tips.accounts_from_other_servers": "<strong>Badakizu?</strong> Mastodon deszentralizatua denez, beste zerbitzarietako profilak topatuko dituzu. Eta, hala ere, arazorik gabe jardun dezakezu haiekin! Haien zerbitzaria erabiltzaile-izenaren bigarren erdian dago!", "onboarding.tips.accounts_from_other_servers": "<strong>Badakizu?</strong> Mastodon deszentralizatua denez, beste zerbitzarietako profilak topatuko dituzu. Eta, hala ere, arazorik gabe jardun dezakezu haiekin! Haien zerbitzaria erabiltzaile-izenaren bigarren erdian dago!",
"onboarding.tips.migration": "<strong>Bazenekien?</strong> Uste baduzu {domain} ez dela aukera on bat zuretzako etorkizunari begira, beste Mastodon zerbitzari batera alda zaitezke, zure jarraitzaileak galdu gabe. Zure zerbitzaria propioa ere ostata dezakezu!", "onboarding.tips.migration": "<strong>Bazenekien?</strong> Uste baduzu {domain} ez dela aukera on bat zuretzako etorkizunari begira, beste Mastodon zerbitzari batera alda zaitezke, zure jarraitzaileak galdu gabe. Zure zerbitzaria propioa ere ostata dezakezu!",
"onboarding.tips.verification": "<strong>Bazenekien?</strong> Zure kontua egiazta dezakezu zure webgunean zure Mastodoneko profilaren esteka jarriz, eta profilean webgunea gehituz. Ordainketa edo dokumenturik gabe!", "onboarding.tips.verification": "<strong>Bazenekien?</strong> Zure kontua egiazta dezakezu zure webgunean zure Mastodon-go profilaren esteka jarriz, eta profilean webgunea gehituz. Ordainketa edo dokumenturik gabe!",
"password_confirmation.exceeds_maxlength": "Pasahitzaren berrespenak pasahitzaren gehienezko luzera gainditzen du", "password_confirmation.exceeds_maxlength": "Pasahitzaren berrespenak pasahitzaren gehienezko luzera gainditzen du",
"password_confirmation.mismatching": "Pasahitzaren berrespena ez dator bat", "password_confirmation.mismatching": "Pasahitzaren berrespena ez dator bat",
"picture_in_picture.restore": "Leheneratu", "picture_in_picture.restore": "Leheneratu",

View file

@ -534,7 +534,7 @@
"onboarding.actions.go_to_home": "Allers vers mon flux principal", "onboarding.actions.go_to_home": "Allers vers mon flux principal",
"onboarding.compose.template": "Bonjour #Mastodon!", "onboarding.compose.template": "Bonjour #Mastodon!",
"onboarding.follows.empty": "Malheureusement, aucun résultat ne peut être affiché pour le moment. Vous pouvez essayer d'utiliser la recherche ou parcourir la page de découverte pour trouver des personnes à suivre, ou réessayez plus tard.", "onboarding.follows.empty": "Malheureusement, aucun résultat ne peut être affiché pour le moment. Vous pouvez essayer d'utiliser la recherche ou parcourir la page de découverte pour trouver des personnes à suivre, ou réessayez plus tard.",
"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.lead": "Votre flux principal est le principal moyen de découvrir Mastodon. Plus vous suivez de personnes, plus il sera actif et intéressant. Pour commencer, voici quelques suggestions :",
"onboarding.follows.title": "Personnaliser votre flux principal", "onboarding.follows.title": "Personnaliser votre flux principal",
"onboarding.profile.discoverable": "Rendre mon profil découvrable", "onboarding.profile.discoverable": "Rendre mon profil découvrable",
"onboarding.profile.discoverable_hint": "Lorsque vous acceptez d'être découvert sur Mastodon, vos messages peuvent apparaître dans les résultats de recherche et les tendances, et votre profil peut être suggéré à des personnes ayant des intérêts similaires aux vôtres.", "onboarding.profile.discoverable_hint": "Lorsque vous acceptez d'être découvert sur Mastodon, vos messages peuvent apparaître dans les résultats de recherche et les tendances, et votre profil peut être suggéré à des personnes ayant des intérêts similaires aux vôtres.",

View file

@ -13,7 +13,7 @@
"about.rules": "Serverrigels", "about.rules": "Serverrigels",
"account.account_note_header": "Opmerking", "account.account_note_header": "Opmerking",
"account.add_or_remove_from_list": "Tafoegje oan of fuortsmite út listen", "account.add_or_remove_from_list": "Tafoegje oan of fuortsmite út listen",
"account.badges.bot": "Bot", "account.badges.bot": "Automatisearre",
"account.badges.group": "Groep", "account.badges.group": "Groep",
"account.block": "@{name} blokkearje", "account.block": "@{name} blokkearje",
"account.block_domain": "Domein {domain} blokkearje", "account.block_domain": "Domein {domain} blokkearje",
@ -89,6 +89,11 @@
"announcement.announcement": "Oankundiging", "announcement.announcement": "Oankundiging",
"attachments_list.unprocessed": "(net ferwurke)", "attachments_list.unprocessed": "(net ferwurke)",
"audio.hide": "Audio ferstopje", "audio.hide": "Audio ferstopje",
"block_modal.show_less": "Minder toane",
"block_modal.show_more": "Mear toane",
"block_modal.they_cant_mention": "Sy kinne jo net fermelde of folgje.",
"block_modal.title": "Brûker blokkearje?",
"block_modal.you_wont_see_mentions": "Jo sjogge gjin berjochten mear dyt dizze account fermelde.",
"boost_modal.combo": "Jo kinne op {combo} drukke om dit de folgjende kear oer te slaan", "boost_modal.combo": "Jo kinne op {combo} drukke om dit de folgjende kear oer te slaan",
"bundle_column_error.copy_stacktrace": "Flaterrapport kopiearje", "bundle_column_error.copy_stacktrace": "Flaterrapport kopiearje",
"bundle_column_error.error.body": "De opfrege side koe net werjûn wurde. It kin wêze troch in flater yn ús koade, of in probleem mei browserkompatibiliteit.", "bundle_column_error.error.body": "De opfrege side koe net werjûn wurde. It kin wêze troch in flater yn ús koade, of in probleem mei browserkompatibiliteit.",
@ -169,6 +174,7 @@
"confirmations.delete_list.message": "Binne jo wis dat jo dizze list foar permanint fuortsmite wolle?", "confirmations.delete_list.message": "Binne jo wis dat jo dizze list foar permanint fuortsmite wolle?",
"confirmations.discard_edit_media.confirm": "Fuortsmite", "confirmations.discard_edit_media.confirm": "Fuortsmite",
"confirmations.discard_edit_media.message": "Jo hawwe net-bewarre wizigingen yn de mediabeskriuwing of foarfertoaning, wolle jo dizze dochs fuortsmite?", "confirmations.discard_edit_media.message": "Jo hawwe net-bewarre wizigingen yn de mediabeskriuwing of foarfertoaning, wolle jo dizze dochs fuortsmite?",
"confirmations.domain_block.confirm": "Server blokkearje",
"confirmations.domain_block.message": "Binne jo echt wis dat jo alles fan {domain} negearje wolle? Yn de measte gefallen is it blokkearjen of negearjen fan in pear spesifike persoanen genôch en better. Jo sille gjin berjochten fan dizze server op iepenbiere tiidlinen sjen of yn jo meldingen. Jo folgers fan dizze server wurde fuortsmiten.", "confirmations.domain_block.message": "Binne jo echt wis dat jo alles fan {domain} negearje wolle? Yn de measte gefallen is it blokkearjen of negearjen fan in pear spesifike persoanen genôch en better. Jo sille gjin berjochten fan dizze server op iepenbiere tiidlinen sjen of yn jo meldingen. Jo folgers fan dizze server wurde fuortsmiten.",
"confirmations.edit.confirm": "Bewurkje", "confirmations.edit.confirm": "Bewurkje",
"confirmations.edit.message": "Troch no te bewurkjen sil it berjocht dat jo no oan it skriuwen binne oerskreaun wurde. Wolle jo trochgean?", "confirmations.edit.message": "Troch no te bewurkjen sil it berjocht dat jo no oan it skriuwen binne oerskreaun wurde. Wolle jo trochgean?",
@ -200,6 +206,20 @@
"dismissable_banner.explore_statuses": "Dizze berjochten winne oan populariteit op dizze en oare servers binnen it desintrale netwurk. Nijere berjochten mei mear boosts en favoriten stean heger.", "dismissable_banner.explore_statuses": "Dizze berjochten winne oan populariteit op dizze en oare servers binnen it desintrale netwurk. Nijere berjochten mei mear boosts en favoriten stean heger.",
"dismissable_banner.explore_tags": "Dizze hashtags winne oan populariteit op dizze en oare servers binnen it desintrale netwurk.", "dismissable_banner.explore_tags": "Dizze hashtags winne oan populariteit op dizze en oare servers binnen it desintrale netwurk.",
"dismissable_banner.public_timeline": "Dit binne de meast resinte iepenbiere berjochten fan accounts op it sosjale web dyt troch minsken op {domain} folge wurde.", "dismissable_banner.public_timeline": "Dit binne de meast resinte iepenbiere berjochten fan accounts op it sosjale web dyt troch minsken op {domain} folge wurde.",
"domain_block_modal.block": "Server blokkearje",
"domain_block_modal.block_account_instead": "Yn stee hjirfan {name} blokkearje",
"domain_block_modal.they_can_interact_with_old_posts": "Minsken op dizze server kinne ynteraksje hawwe mei jo âlde berjochten.",
"domain_block_modal.they_cant_follow": "Net ien op dizze server kin jo folgje.",
"domain_block_modal.they_wont_know": "Se krije net te witten dat se blokkearre wurde.",
"domain_block_modal.title": "Domein blokkearje?",
"domain_block_modal.you_will_lose_followers": "Al jo folgers fan dizze server wurde ûntfolge.",
"domain_block_modal.you_wont_see_posts": "Jo sjogge gjin berjochten of meldingen mear fan brûkers op dizze server.",
"domain_pill.server": "Server",
"domain_pill.their_handle": "Harren fediverse-adres:",
"domain_pill.their_server": "Harren digitale thús, wert al harren berjochten binne.",
"domain_pill.username": "Brûkersnamme",
"domain_pill.whats_in_a_handle": "Wat is in fediverse-adres?",
"domain_pill.your_handle": "Jo fediverse-adres:",
"embed.instructions": "Embed this status on your website by copying the code below.", "embed.instructions": "Embed this status on your website by copying the code below.",
"embed.preview": "Sa komt it der út te sjen:", "embed.preview": "Sa komt it der út te sjen:",
"emoji_button.activity": "Aktiviteiten", "emoji_button.activity": "Aktiviteiten",
@ -266,6 +286,7 @@
"filter_modal.select_filter.subtitle": "In besteande kategory brûke of in nije oanmeitsje", "filter_modal.select_filter.subtitle": "In besteande kategory brûke of in nije oanmeitsje",
"filter_modal.select_filter.title": "Dit berjocht filterje", "filter_modal.select_filter.title": "Dit berjocht filterje",
"filter_modal.title.status": "In berjocht filterje", "filter_modal.title.status": "In berjocht filterje",
"filtered_notifications_banner.title": "Filtere meldingen",
"firehose.all": "Alles", "firehose.all": "Alles",
"firehose.local": "Dizze server", "firehose.local": "Dizze server",
"firehose.remote": "Oare servers", "firehose.remote": "Oare servers",
@ -394,6 +415,9 @@
"loading_indicator.label": "Lade…", "loading_indicator.label": "Lade…",
"media_gallery.toggle_visible": "{number, plural, one {ôfbylding ferstopje} other {ôfbyldingen ferstopje}}", "media_gallery.toggle_visible": "{number, plural, one {ôfbylding ferstopje} other {ôfbyldingen ferstopje}}",
"moved_to_account_banner.text": "Omdat jo nei {movedToAccount} ferhuze binne is jo account {disabledAccount} op dit stuit útskeakele.", "moved_to_account_banner.text": "Omdat jo nei {movedToAccount} ferhuze binne is jo account {disabledAccount} op dit stuit útskeakele.",
"mute_modal.hide_options": "Opsjes ferstopje",
"mute_modal.indefinite": "Oant ik se net mear negearje",
"mute_modal.show_options": "Opsjes toane",
"navigation_bar.about": "Oer", "navigation_bar.about": "Oer",
"navigation_bar.advanced_interface": "Yn avansearre webomjouwing iepenje", "navigation_bar.advanced_interface": "Yn avansearre webomjouwing iepenje",
"navigation_bar.blocks": "Blokkearre brûkers", "navigation_bar.blocks": "Blokkearre brûkers",
@ -429,14 +453,20 @@
"notification.own_poll": "Jo poll is beëinige", "notification.own_poll": "Jo poll is beëinige",
"notification.poll": "In enkête dêrt jo yn stimd hawwe is beëinige", "notification.poll": "In enkête dêrt jo yn stimd hawwe is beëinige",
"notification.reblog": "{name} hat jo berjocht boost", "notification.reblog": "{name} hat jo berjocht boost",
"notification.relationships_severance_event.learn_more": "Mear ynfo",
"notification.status": "{name} hat in berjocht pleatst", "notification.status": "{name} hat in berjocht pleatst",
"notification.update": "{name} hat in berjocht bewurke", "notification.update": "{name} hat in berjocht bewurke",
"notification_requests.accept": "Akseptearje",
"notification_requests.dismiss": "Ofwize",
"notification_requests.notifications_from": "Meldingen fan {name}",
"notification_requests.title": "Filtere meldingen",
"notifications.clear": "Meldingen wiskje", "notifications.clear": "Meldingen wiskje",
"notifications.clear_confirmation": "Binne jo wis dat jo al jo meldingen permanint fuortsmite wolle?", "notifications.clear_confirmation": "Binne jo wis dat jo al jo meldingen permanint fuortsmite wolle?",
"notifications.column_settings.admin.report": "Nije rapportaazjes:", "notifications.column_settings.admin.report": "Nije rapportaazjes:",
"notifications.column_settings.admin.sign_up": "Nije registraasjes:", "notifications.column_settings.admin.sign_up": "Nije registraasjes:",
"notifications.column_settings.alert": "Desktopmeldingen", "notifications.column_settings.alert": "Desktopmeldingen",
"notifications.column_settings.favourite": "Favoriten:", "notifications.column_settings.favourite": "Favoriten:",
"notifications.column_settings.filter_bar.advanced": "Alle kategoryen toane",
"notifications.column_settings.follow": "Nije folgers:", "notifications.column_settings.follow": "Nije folgers:",
"notifications.column_settings.follow_request": "Nij folchfersyk:", "notifications.column_settings.follow_request": "Nij folchfersyk:",
"notifications.column_settings.mention": "Fermeldingen:", "notifications.column_settings.mention": "Fermeldingen:",

View file

@ -9,15 +9,18 @@
"about.domain_blocks.suspended.explanation": "Nulle datos de iste servitor essera processate, immagazinate o excambiate, rendente omne interaction o communication con usatores de iste servitor impossibile.", "about.domain_blocks.suspended.explanation": "Nulle datos de iste servitor essera processate, immagazinate o excambiate, rendente omne interaction o communication con usatores de iste servitor impossibile.",
"about.domain_blocks.suspended.title": "Suspendite", "about.domain_blocks.suspended.title": "Suspendite",
"about.not_available": "Iste information non ha essite rendite disponibile sur iste servitor.", "about.not_available": "Iste information non ha essite rendite disponibile sur iste servitor.",
"about.powered_by": "Rete social decentralisate, actionate per {mastodon}",
"about.rules": "Regulas del servitor", "about.rules": "Regulas del servitor",
"account.account_note_header": "Nota", "account.account_note_header": "Nota",
"account.add_or_remove_from_list": "Adder a, o remover de listas", "account.add_or_remove_from_list": "Adder a, o remover de listas",
"account.badges.bot": "Automatisate",
"account.badges.group": "Gruppo", "account.badges.group": "Gruppo",
"account.block": "Blocar @{name}", "account.block": "Blocar @{name}",
"account.block_domain": "Blocar dominio {domain}", "account.block_domain": "Blocar dominio {domain}",
"account.block_short": "Blocar", "account.block_short": "Blocar",
"account.blocked": "Blocate", "account.blocked": "Blocate",
"account.browse_more_on_origin_server": "Navigar plus sur le profilo original", "account.browse_more_on_origin_server": "Navigar plus sur le profilo original",
"account.cancel_follow_request": "Cancellar sequimento",
"account.copy": "Copiar ligamine a profilo", "account.copy": "Copiar ligamine a profilo",
"account.direct": "Mentionar privatemente @{name}", "account.direct": "Mentionar privatemente @{name}",
"account.disable_notifications": "Non plus notificar me quando @{name} publica", "account.disable_notifications": "Non plus notificar me quando @{name} publica",
@ -26,7 +29,7 @@
"account.enable_notifications": "Notificar me quando @{name} publica", "account.enable_notifications": "Notificar me quando @{name} publica",
"account.endorse": "Evidentiar sur le profilo", "account.endorse": "Evidentiar sur le profilo",
"account.featured_tags.last_status_at": "Ultime message publicate le {date}", "account.featured_tags.last_status_at": "Ultime message publicate le {date}",
"account.featured_tags.last_status_never": "Necun messages", "account.featured_tags.last_status_never": "Necun message",
"account.featured_tags.title": "Hashtags eminente de {name}", "account.featured_tags.title": "Hashtags eminente de {name}",
"account.follow": "Sequer", "account.follow": "Sequer",
"account.follow_back": "Sequer in retorno", "account.follow_back": "Sequer in retorno",
@ -34,9 +37,10 @@
"account.followers.empty": "Necuno seque ancora iste usator.", "account.followers.empty": "Necuno seque ancora iste usator.",
"account.followers_counter": "{count, plural, one {{counter} sequitor} other {{counter} sequitores}}", "account.followers_counter": "{count, plural, one {{counter} sequitor} other {{counter} sequitores}}",
"account.following": "Sequente", "account.following": "Sequente",
"account.following_counter": "{count, plural, one {{counter} sequite} other {{counter} sequites}}",
"account.follows.empty": "Iste usator non seque ancora alcuno.", "account.follows.empty": "Iste usator non seque ancora alcuno.",
"account.go_to_profile": "Vader al profilo", "account.go_to_profile": "Vader al profilo",
"account.hide_reblogs": "Celar boosts de @{name}", "account.hide_reblogs": "Celar impulsos de @{name}",
"account.in_memoriam": "In memoriam.", "account.in_memoriam": "In memoriam.",
"account.languages": "Cambiar le linguas subscribite", "account.languages": "Cambiar le linguas subscribite",
"account.link_verified_on": "Le proprietate de iste ligamine ha essite verificate le {date}", "account.link_verified_on": "Le proprietate de iste ligamine ha essite verificate le {date}",
@ -74,9 +78,13 @@
"alert.unexpected.message": "Un error inexpectate ha occurrite.", "alert.unexpected.message": "Un error inexpectate ha occurrite.",
"announcement.announcement": "Annuncio", "announcement.announcement": "Annuncio",
"audio.hide": "Celar audio", "audio.hide": "Celar audio",
"block_modal.remote_users_caveat": "Nos demandera al servitor {domain} de respectar tu decision. Nonobstante, le conformitate non es garantite perque alcun servitores pote tractar le blocadas de maniera differente. Le messages public pote esser totevia visibile pro le usatores non authenticate.",
"block_modal.show_less": "Monstrar minus", "block_modal.show_less": "Monstrar minus",
"block_modal.show_more": "Monstrar plus", "block_modal.show_more": "Monstrar plus",
"block_modal.they_cant_see_posts": "Iste persona non potera vider tu messages e tu non videra le sues.",
"block_modal.title": "Blocar usator?", "block_modal.title": "Blocar usator?",
"block_modal.you_wont_see_mentions": "Tu non videra le messages que mentiona iste persona.",
"boost_modal.combo": "Tu pote premer {combo} pro saltar isto le proxime vice",
"bundle_column_error.error.title": "Oh, no!", "bundle_column_error.error.title": "Oh, no!",
"bundle_column_error.network.title": "Error de rete", "bundle_column_error.network.title": "Error de rete",
"bundle_column_error.retry": "Tentar novemente", "bundle_column_error.retry": "Tentar novemente",
@ -98,6 +106,7 @@
"column.lists": "Listas", "column.lists": "Listas",
"column.mutes": "Usatores silentiate", "column.mutes": "Usatores silentiate",
"column.notifications": "Notificationes", "column.notifications": "Notificationes",
"column.pins": "Messages fixate",
"column.public": "Chronologia federate", "column.public": "Chronologia federate",
"column_back_button.label": "Retro", "column_back_button.label": "Retro",
"column_header.hide_settings": "Celar le parametros", "column_header.hide_settings": "Celar le parametros",
@ -113,6 +122,8 @@
"compose.published.open": "Aperir", "compose.published.open": "Aperir",
"compose.saved.body": "Message salvate.", "compose.saved.body": "Message salvate.",
"compose_form.direct_message_warning_learn_more": "Apprender plus", "compose_form.direct_message_warning_learn_more": "Apprender plus",
"compose_form.encryption_warning": "Le messages sur Mastodon non es cryptate de puncta a puncta. Non condivide alcun information sensibile usante Mastodon.",
"compose_form.hashtag_warning": "Iste message non essera listate sub alcun hashtag perque illo non es public. Solmente le messages public pote esser cercate per hashtag.",
"compose_form.lock_disclaimer": "Tu conto non es {locked}. Quicunque pote sequer te pro vider tu messages solo pro sequitores.", "compose_form.lock_disclaimer": "Tu conto non es {locked}. Quicunque pote sequer te pro vider tu messages solo pro sequitores.",
"compose_form.lock_disclaimer.lock": "serrate", "compose_form.lock_disclaimer.lock": "serrate",
"compose_form.poll.duration": "Durata del sondage", "compose_form.poll.duration": "Durata del sondage",
@ -142,6 +153,7 @@
"confirmations.logout.confirm": "Clauder session", "confirmations.logout.confirm": "Clauder session",
"confirmations.logout.message": "Es tu secur que tu vole clauder le session?", "confirmations.logout.message": "Es tu secur que tu vole clauder le session?",
"confirmations.mute.confirm": "Silentiar", "confirmations.mute.confirm": "Silentiar",
"confirmations.redraft.message": "Es tu secur de voler deler iste message e rescriber lo? Le favorites e le impulsos essera perdite, e le responsas al message original essera orphanate.",
"confirmations.reply.confirm": "Responder", "confirmations.reply.confirm": "Responder",
"confirmations.unfollow.confirm": "Non plus sequer", "confirmations.unfollow.confirm": "Non plus sequer",
"confirmations.unfollow.message": "Es tu secur que tu vole cessar de sequer {name}?", "confirmations.unfollow.message": "Es tu secur que tu vole cessar de sequer {name}?",
@ -158,16 +170,24 @@
"directory.recently_active": "Recentemente active", "directory.recently_active": "Recentemente active",
"disabled_account_banner.account_settings": "Parametros de conto", "disabled_account_banner.account_settings": "Parametros de conto",
"disabled_account_banner.text": "Tu conto {disabledAccount} es actualmente disactivate.", "disabled_account_banner.text": "Tu conto {disabledAccount} es actualmente disactivate.",
"dismissable_banner.community_timeline": "Ecce le messages public le plus recente del personas con contos sur {domain}.",
"dismissable_banner.dismiss": "Dimitter", "dismissable_banner.dismiss": "Dimitter",
"dismissable_banner.explore_links": "Istes es le articulos de novas que se condivide le plus sur le rete social hodie. Le articulos de novas le plus recente, publicate per plus personas differente, se classifica plus in alto.",
"dismissable_banner.explore_statuses": "Ecce le messages de tote le rete social que gania popularitate hodie. Le messages plus nove con plus impulsos e favorites se classifica plus in alto.",
"dismissable_banner.public_timeline": "Istes es le messages public le plus recente del personas sur le rete social que le gente sur {domain} seque.",
"domain_block_modal.block": "Blocar le servitor", "domain_block_modal.block": "Blocar le servitor",
"domain_block_modal.block_account_instead": "Blocar @{name} in su loco", "domain_block_modal.block_account_instead": "Blocar @{name} in su loco",
"domain_block_modal.they_can_interact_with_old_posts": "Le personas de iste servitor pote interager con tu messages ancian.",
"domain_block_modal.they_cant_follow": "Nulle persona ab iste servitor pote sequer te.", "domain_block_modal.they_cant_follow": "Nulle persona ab iste servitor pote sequer te.",
"domain_block_modal.they_wont_know": "Illes non sapera que illes ha essite blocate.", "domain_block_modal.they_wont_know": "Illes non sapera que illes ha essite blocate.",
"domain_block_modal.title": "Blocar dominio?", "domain_block_modal.title": "Blocar dominio?",
"domain_block_modal.you_will_lose_followers": "Omne sequitores ab iste servitor essera removite.", "domain_block_modal.you_will_lose_followers": "Omne sequitores ab iste servitor essera removite.",
"domain_block_modal.you_wont_see_posts": "Tu non videra messages e notificationes ab usatores sur iste servitor.", "domain_block_modal.you_wont_see_posts": "Tu non videra messages e notificationes ab usatores sur iste servitor.",
"domain_pill.server": "Servitor", "domain_pill.server": "Servitor",
"domain_pill.their_server": "Su casa digital, ubi vive tote su messages.",
"domain_pill.username": "Nomine de usator", "domain_pill.username": "Nomine de usator",
"domain_pill.your_server": "Tu casa digital, ubi vive tote tu messages. Non te place? Cambia de servitor a omne momento e porta tu sequitores con te.",
"embed.instructions": "Incorpora iste message sur tu sito web con le codice sequente.",
"embed.preview": "Ecce como illlo parera:", "embed.preview": "Ecce como illlo parera:",
"emoji_button.activity": "Activitate", "emoji_button.activity": "Activitate",
"emoji_button.clear": "Rader", "emoji_button.clear": "Rader",
@ -187,11 +207,15 @@
"empty_column.account_timeline": "Nulle messages hic!", "empty_column.account_timeline": "Nulle messages hic!",
"empty_column.account_unavailable": "Profilo non disponibile", "empty_column.account_unavailable": "Profilo non disponibile",
"empty_column.blocks": "Tu non ha blocate alcun usator ancora.", "empty_column.blocks": "Tu non ha blocate alcun usator ancora.",
"empty_column.bookmarked_statuses": "Tu non ha ancora messages in marcapaginas. Quando tu adde un message al marcapaginas, illo apparera hic.",
"empty_column.domain_blocks": "Il non ha dominios blocate ancora.", "empty_column.domain_blocks": "Il non ha dominios blocate ancora.",
"empty_column.explore_statuses": "Il non ha tendentias in iste momento. Reveni plus tarde!", "empty_column.explore_statuses": "Il non ha tendentias in iste momento. Reveni plus tarde!",
"empty_column.favourited_statuses": "Tu non ha alcun message favorite ancora. Quando tu marca un message como favorite, illo apparera hic.", "empty_column.favourited_statuses": "Tu non ha alcun message favorite ancora. Quando tu marca un message como favorite, illo apparera hic.",
"empty_column.favourites": "Necuno ha ancora marcate iste message como favorite. Quando alcuno lo face, ille apparera hic.",
"empty_column.followed_tags": "Tu non ha ancora sequite alcun hashtags. Quando tu lo face, illos apparera hic.", "empty_column.followed_tags": "Tu non ha ancora sequite alcun hashtags. Quando tu lo face, illos apparera hic.",
"empty_column.hashtag": "Il non ha ancora alcun cosa in iste hashtag.", "empty_column.hashtag": "Il non ha ancora alcun cosa in iste hashtag.",
"empty_column.home": "Tu chronologia de initio es vacue! Seque plus personas pro plenar lo.",
"empty_column.list": "Iste lista es ancora vacue. Quando le membros de iste lista publica nove messages, illos apparera hic.",
"errors.unexpected_crash.report_issue": "Signalar un defecto", "errors.unexpected_crash.report_issue": "Signalar un defecto",
"explore.search_results": "Resultatos de recerca", "explore.search_results": "Resultatos de recerca",
"explore.suggested_follows": "Personas", "explore.suggested_follows": "Personas",
@ -199,6 +223,7 @@
"explore.trending_links": "Novas", "explore.trending_links": "Novas",
"explore.trending_statuses": "Messages", "explore.trending_statuses": "Messages",
"explore.trending_tags": "Hashtags", "explore.trending_tags": "Hashtags",
"filter_modal.added.context_mismatch_explanation": "Iste categoria de filtros non se applica al contexto in le qual tu ha accedite a iste message. Pro filtrar le message in iste contexto tamben, modifica le filtro.",
"filter_modal.added.review_and_configure_title": "Parametros de filtro", "filter_modal.added.review_and_configure_title": "Parametros de filtro",
"filter_modal.added.settings_link": "pagina de parametros", "filter_modal.added.settings_link": "pagina de parametros",
"filter_modal.added.short_explanation": "Iste message ha essite addite al sequente categoria de filtros: {title}.", "filter_modal.added.short_explanation": "Iste message ha essite addite al sequente categoria de filtros: {title}.",
@ -231,6 +256,8 @@
"hashtag.column_header.tag_mode.none": "sin {additional}", "hashtag.column_header.tag_mode.none": "sin {additional}",
"hashtag.column_settings.select.no_options_message": "Nulle suggestiones trovate", "hashtag.column_settings.select.no_options_message": "Nulle suggestiones trovate",
"hashtag.column_settings.select.placeholder": "Insere hashtags…", "hashtag.column_settings.select.placeholder": "Insere hashtags…",
"hashtag.counter_by_uses": "{count, plural, one {{counter} message} other {{counter} messages}}",
"hashtag.counter_by_uses_today": "{count, plural, one {{counter} message} other {{counter} messages}} hodie",
"hashtag.follow": "Sequer hashtag", "hashtag.follow": "Sequer hashtag",
"hashtag.unfollow": "Non sequer plus le hashtag", "hashtag.unfollow": "Non sequer plus le hashtag",
"hashtags.and_other": "…e {count, plural, one {}other {# plus}}", "hashtags.and_other": "…e {count, plural, one {}other {# plus}}",
@ -241,10 +268,16 @@
"home.pending_critical_update.link": "Vider actualisationes", "home.pending_critical_update.link": "Vider actualisationes",
"home.pending_critical_update.title": "Actualisation de securitate critic disponibile!", "home.pending_critical_update.title": "Actualisation de securitate critic disponibile!",
"home.show_announcements": "Monstrar annuncios", "home.show_announcements": "Monstrar annuncios",
"interaction_modal.description.favourite": "Con un conto sur Mastodon, tu pote marcar iste message como favorite pro informar le autor que tu lo apprecia e salveguarda pro plus tarde.",
"interaction_modal.description.follow": "Con un conto sur Mastodon, tu pote sequer {name} e reciper su messages in tu fluxo de initio.",
"interaction_modal.description.reblog": "Con un conto sur Mastodon, tu pote impulsar iste message pro condivider lo con tu proprie sequitores.",
"interaction_modal.description.reply": "Con un conto sur Mastodon, tu pote responder a iste message.",
"interaction_modal.login.action": "Porta me a casa",
"interaction_modal.login.prompt": "Dominio de tu servitor, p.ex. mastodon.social", "interaction_modal.login.prompt": "Dominio de tu servitor, p.ex. mastodon.social",
"interaction_modal.no_account_yet": "Non sur Mstodon?", "interaction_modal.no_account_yet": "Non sur Mstodon?",
"interaction_modal.on_another_server": "Sur un altere servitor", "interaction_modal.on_another_server": "Sur un altere servitor",
"interaction_modal.on_this_server": "Sur iste servitor", "interaction_modal.on_this_server": "Sur iste servitor",
"interaction_modal.title.favourite": "Marcar le message de {name} como favorite",
"interaction_modal.title.follow": "Sequer {name}", "interaction_modal.title.follow": "Sequer {name}",
"interaction_modal.title.reblog": "Impulsar le message de {name}", "interaction_modal.title.reblog": "Impulsar le message de {name}",
"interaction_modal.title.reply": "Responder al message de {name}", "interaction_modal.title.reply": "Responder al message de {name}",
@ -264,6 +297,7 @@
"keyboard_shortcuts.my_profile": "Aperir tu profilo", "keyboard_shortcuts.my_profile": "Aperir tu profilo",
"keyboard_shortcuts.notifications": "Aperir columna de notificationes", "keyboard_shortcuts.notifications": "Aperir columna de notificationes",
"keyboard_shortcuts.open_media": "Aperir multimedia", "keyboard_shortcuts.open_media": "Aperir multimedia",
"keyboard_shortcuts.pinned": "Aperir le lista de messages fixate",
"keyboard_shortcuts.profile": "Aperir le profilo del autor", "keyboard_shortcuts.profile": "Aperir le profilo del autor",
"keyboard_shortcuts.reply": "Responder al message", "keyboard_shortcuts.reply": "Responder al message",
"keyboard_shortcuts.spoilers": "Monstrar/celar le campo CW", "keyboard_shortcuts.spoilers": "Monstrar/celar le campo CW",
@ -294,7 +328,8 @@
"mute_modal.they_can_mention_and_follow": "Illes pote mentionar te e sequer te, ma tu non potera vider los.", "mute_modal.they_can_mention_and_follow": "Illes pote mentionar te e sequer te, ma tu non potera vider los.",
"mute_modal.they_wont_know": "Illes non sapera que illes ha essite silentiate.", "mute_modal.they_wont_know": "Illes non sapera que illes ha essite silentiate.",
"mute_modal.title": "Silentiar le usator?", "mute_modal.title": "Silentiar le usator?",
"mute_modal.you_wont_see_mentions": "Tu non videra messages que los mentiona.", "mute_modal.you_wont_see_mentions": "Tu non videra le messages que mentiona iste persona.",
"mute_modal.you_wont_see_posts": "Iste persona pote totevia vider tu messages, ma tu non videra le sues.",
"navigation_bar.about": "A proposito", "navigation_bar.about": "A proposito",
"navigation_bar.advanced_interface": "Aperir in le interfacie web avantiate", "navigation_bar.advanced_interface": "Aperir in le interfacie web avantiate",
"navigation_bar.blocks": "Usatores blocate", "navigation_bar.blocks": "Usatores blocate",
@ -312,12 +347,16 @@
"navigation_bar.mutes": "Usatores silentiate", "navigation_bar.mutes": "Usatores silentiate",
"navigation_bar.opened_in_classic_interface": "Messages, contos e altere paginas specific es aperite per predefinition in le interfacie web classic.", "navigation_bar.opened_in_classic_interface": "Messages, contos e altere paginas specific es aperite per predefinition in le interfacie web classic.",
"navigation_bar.personal": "Personal", "navigation_bar.personal": "Personal",
"navigation_bar.pins": "Messages fixate",
"navigation_bar.preferences": "Preferentias", "navigation_bar.preferences": "Preferentias",
"navigation_bar.public_timeline": "Chronologia federate", "navigation_bar.public_timeline": "Chronologia federate",
"navigation_bar.search": "Cercar", "navigation_bar.search": "Cercar",
"navigation_bar.security": "Securitate", "navigation_bar.security": "Securitate",
"notification.favourite": "{name} ha marcate tu message como favorite",
"notification.own_poll": "Tu sondage ha finite", "notification.own_poll": "Tu sondage ha finite",
"notification.reblog": "{name} ha impulsate tu message",
"notification.relationships_severance_event.learn_more": "Apprender plus", "notification.relationships_severance_event.learn_more": "Apprender plus",
"notification.status": "{name} ha justo ora publicate",
"notification.update": "{name} ha modificate un message", "notification.update": "{name} ha modificate un message",
"notification_requests.accept": "Acceptar", "notification_requests.accept": "Acceptar",
"notification_requests.dismiss": "Dimitter", "notification_requests.dismiss": "Dimitter",
@ -332,11 +371,13 @@
"notifications.column_settings.mention": "Mentiones:", "notifications.column_settings.mention": "Mentiones:",
"notifications.column_settings.poll": "Resultatos del sondage:", "notifications.column_settings.poll": "Resultatos del sondage:",
"notifications.column_settings.push": "Notificationes push", "notifications.column_settings.push": "Notificationes push",
"notifications.column_settings.reblog": "Impulsos:",
"notifications.column_settings.show": "Monstrar in columna", "notifications.column_settings.show": "Monstrar in columna",
"notifications.column_settings.sound": "Reproducer sono", "notifications.column_settings.sound": "Reproducer sono",
"notifications.column_settings.status": "Nove messages:", "notifications.column_settings.status": "Nove messages:",
"notifications.column_settings.unread_notifications.category": "Notificationes non legite", "notifications.column_settings.unread_notifications.category": "Notificationes non legite",
"notifications.filter.all": "Toto", "notifications.filter.all": "Toto",
"notifications.filter.boosts": "Impulsos",
"notifications.filter.favourites": "Favoritos", "notifications.filter.favourites": "Favoritos",
"notifications.filter.mentions": "Mentiones", "notifications.filter.mentions": "Mentiones",
"notifications.filter.polls": "Resultatos del sondage", "notifications.filter.polls": "Resultatos del sondage",
@ -346,38 +387,52 @@
"notifications.mark_as_read": "Marcar cata notification como legite", "notifications.mark_as_read": "Marcar cata notification como legite",
"notifications.policy.filter_new_accounts_title": "Nove contos", "notifications.policy.filter_new_accounts_title": "Nove contos",
"notifications_permission_banner.enable": "Activar notificationes de scriptorio", "notifications_permission_banner.enable": "Activar notificationes de scriptorio",
"onboarding.actions.go_to_home": "Porta me a mi fluxo de initio",
"onboarding.compose.template": "Salute #Mastodon!", "onboarding.compose.template": "Salute #Mastodon!",
"onboarding.follows.lead": "Le fluxo de initio es le maniera principal de discoperir Mastodon. Quanto plus personas tu seque, tanto plus active e interessante illo essera. Pro comenciar, ecce alcun suggestiones:",
"onboarding.follows.title": "Personalisar tu fluxo de initio",
"onboarding.profile.discoverable_hint": "Quando tu opta pro devenir discoperibile sur Mastodon, tu messages pote apparer in resultatos de recerca e in tendentias, e tu profilo pote esser suggerite al personas con interesses simile al tues.",
"onboarding.profile.save_and_continue": "Salvar e continuar", "onboarding.profile.save_and_continue": "Salvar e continuar",
"onboarding.share.next_steps": "Sequente passos possibile:", "onboarding.share.next_steps": "Sequente passos possibile:",
"onboarding.share.title": "Compartir tu profilo", "onboarding.share.title": "Compartir tu profilo",
"onboarding.steps.follow_people.title": "Personalisa tu fluxo de initio", "onboarding.steps.follow_people.title": "Personalisar tu fluxo de initio",
"onboarding.steps.publish_status.title": "Face tu prime message", "onboarding.steps.publish_status.title": "Face tu prime message",
"onboarding.steps.setup_profile.body": "Impulsa tu interactiones con un profilo comprehensive.",
"onboarding.steps.setup_profile.title": "Personalisa tu profilo", "onboarding.steps.setup_profile.title": "Personalisa tu profilo",
"onboarding.steps.share_profile.title": "Compartir tu profilo de Mastodon", "onboarding.steps.share_profile.title": "Compartir tu profilo de Mastodon",
"poll.closed": "Claudite", "poll.closed": "Claudite",
"poll.reveal": "Vider le resultatos", "poll.reveal": "Vider le resultatos",
"privacy.change": "Cambiar le confidentialitate del message", "privacy.change": "Cambiar le confidentialitate del message",
"privacy.direct.long": "Tote le personas mentionate in le message",
"privacy.public.short": "Public", "privacy.public.short": "Public",
"privacy.unlisted.additional": "Isto es exactemente como public, excepte que le message non apparera in fluxos in directo, in hashtags, in Explorar, o in le recerca de Mastodon, mesmo si tu ha optate pro render tote le conto discoperibile.",
"privacy_policy.last_updated": "Ultime actualisation {date}", "privacy_policy.last_updated": "Ultime actualisation {date}",
"privacy_policy.title": "Politica de confidentialitate", "privacy_policy.title": "Politica de confidentialitate",
"regeneration_indicator.sublabel": "Tu fluxo de initio es in preparation!",
"relative_time.just_now": "ora", "relative_time.just_now": "ora",
"relative_time.today": "hodie", "relative_time.today": "hodie",
"reply_indicator.cancel": "Cancellar", "reply_indicator.cancel": "Cancellar",
"report.block": "Blocar", "report.block": "Blocar",
"report.block_explanation": "Tu non videra le messages de iste persona. Ille non potera vider tu messages o sequer te. Ille potera saper de esser blocate.",
"report.categories.other": "Alteres", "report.categories.other": "Alteres",
"report.category.title_account": "profilo", "report.category.title_account": "profilo",
"report.category.title_status": "message", "report.category.title_status": "message",
"report.close": "Facite", "report.close": "Facite",
"report.mute": "Silentiar", "report.mute": "Silentiar",
"report.mute_explanation": "Tu non videra le messages de iste persona. Ille pote totevia sequer te e vider tu messages e non sapera de esser silentiate.",
"report.next": "Sequente", "report.next": "Sequente",
"report.placeholder": "Commentos additional", "report.placeholder": "Commentos additional",
"report.reasons.dislike": "Non me place", "report.reasons.dislike": "Non me place",
"report.statuses.title": "Existe alcun messages que appoia iste reporto?",
"report.unfollow_explanation": "Tu seque iste conto. Pro non plus vider su messages in tu fluxo de initio, cessa de sequer lo.",
"report_notification.attached_statuses": "{count, plural, one {{count} message} other {{count} messages}} annexate",
"report_notification.categories.other": "Alteres", "report_notification.categories.other": "Alteres",
"report_notification.open": "Aperir reporto", "report_notification.open": "Aperir reporto",
"search.no_recent_searches": "Nulle recercas recente", "search.no_recent_searches": "Nulle recercas recente",
"search.quick_action.go_to_account": "Vader al profilo {x}", "search.quick_action.go_to_account": "Vader al profilo {x}",
"search.quick_action.go_to_hashtag": "Vader al hashtag {x}", "search.quick_action.go_to_hashtag": "Vader al hashtag {x}",
"search.quick_action.open_url": "Aperir URL in Mastodon", "search.quick_action.open_url": "Aperir URL in Mastodon",
"search.quick_action.status_search": "Messages correspondente a {x}",
"search_popout.full_text_search_disabled_message": "Non disponibile sur {domain}.", "search_popout.full_text_search_disabled_message": "Non disponibile sur {domain}.",
"search_popout.language_code": "Codice de lingua ISO", "search_popout.language_code": "Codice de lingua ISO",
"search_popout.options": "Optiones de recerca", "search_popout.options": "Optiones de recerca",
@ -393,7 +448,11 @@
"server_banner.server_stats": "Statos del servitor:", "server_banner.server_stats": "Statos del servitor:",
"sign_in_banner.create_account": "Crear un conto", "sign_in_banner.create_account": "Crear un conto",
"sign_in_banner.sign_in": "Aperir session", "sign_in_banner.sign_in": "Aperir session",
"sign_in_banner.text": "Aperi session pro sequer profilos o hashtags, marcar messages como favorite, e condivider e responder a messages. Tu pote etiam interager desde tu conto sur un altere servitor.",
"status.admin_status": "Aperir iste message in le interfacie de moderation",
"status.block": "Blocar @{name}", "status.block": "Blocar @{name}",
"status.cancel_reblog_private": "Disfacer impulso",
"status.cannot_reblog": "Iste message non pote esser impulsate",
"status.copy": "Copiar ligamine a message", "status.copy": "Copiar ligamine a message",
"status.delete": "Deler", "status.delete": "Deler",
"status.direct": "Mentionar privatemente @{name}", "status.direct": "Mentionar privatemente @{name}",
@ -409,7 +468,13 @@
"status.media.show": "Clicca pro monstrar", "status.media.show": "Clicca pro monstrar",
"status.more": "Plus", "status.more": "Plus",
"status.mute_conversation": "Silentiar conversation", "status.mute_conversation": "Silentiar conversation",
"status.open": "Expander iste message",
"status.pinned": "Message fixate",
"status.read_more": "Leger plus", "status.read_more": "Leger plus",
"status.reblog": "Impulsar",
"status.reblog_private": "Impulsar con visibilitate original",
"status.reblogged_by": "Impulsate per {name}",
"status.reblogs": "{count, plural, one {impulso} other {impulsos}}",
"status.reblogs.empty": "Necuno ha ancora impulsate iste message. Quando alcuno lo face, le impulsos apparera hic.", "status.reblogs.empty": "Necuno ha ancora impulsate iste message. Quando alcuno lo face, le impulsos apparera hic.",
"status.redraft": "Deler e reconciper", "status.redraft": "Deler e reconciper",
"status.remove_bookmark": "Remover marcapagina", "status.remove_bookmark": "Remover marcapagina",

View file

@ -701,7 +701,7 @@
"status.direct": "@{name} 님에게 개인적으로 멘션", "status.direct": "@{name} 님에게 개인적으로 멘션",
"status.direct_indicator": "개인적인 멘션", "status.direct_indicator": "개인적인 멘션",
"status.edit": "수정", "status.edit": "수정",
"status.edited": "%{date}에 마지막으로 편집됨", "status.edited": "{date}에 마지막으로 편집됨",
"status.edited_x_times": "{count}번 수정됨", "status.edited_x_times": "{count}번 수정됨",
"status.embed": "임베드", "status.embed": "임베드",
"status.favourite": "좋아요", "status.favourite": "좋아요",

View file

@ -83,12 +83,15 @@
"admin.impact_report.instance_follows": "Sekėjai, kuriuos prarastų jų naudotojai", "admin.impact_report.instance_follows": "Sekėjai, kuriuos prarastų jų naudotojai",
"admin.impact_report.title": "Poveikio apibendrinimas", "admin.impact_report.title": "Poveikio apibendrinimas",
"alert.rate_limited.message": "Pabandyk vėliau po {retry_time, time, medium}.", "alert.rate_limited.message": "Pabandyk vėliau po {retry_time, time, medium}.",
"alert.rate_limited.title": "Sparta ribota", "alert.rate_limited.title": "Sparta ribota.",
"alert.unexpected.message": "Įvyko netikėta klaida.", "alert.unexpected.message": "Įvyko netikėta klaida.",
"alert.unexpected.title": "Ups!", "alert.unexpected.title": "Ups!",
"announcement.announcement": "Skelbimas", "announcement.announcement": "Skelbimas",
"attachments_list.unprocessed": "(neapdorotas)", "attachments_list.unprocessed": "(neapdorotas)",
"audio.hide": "Slėpti garsą", "audio.hide": "Slėpti garsą",
"block_modal.remote_users_caveat": "Paprašysime serverio {domain} gerbti tavo sprendimą. Tačiau atitiktis negarantuojama, nes kai kurie serveriai gali skirtingai tvarkyti blokavimus. Vieši įrašai vis tiek gali būti matomi neprisijungusiems naudotojams.",
"block_modal.show_less": "Rodyti mažiau",
"block_modal.show_more": "Rodyti daugiau",
"boost_modal.combo": "Galima paspausti {combo}, kad praleisti kitą kartą.", "boost_modal.combo": "Galima paspausti {combo}, kad praleisti kitą kartą.",
"bundle_column_error.copy_stacktrace": "Kopijuoti klaidos ataskaitą", "bundle_column_error.copy_stacktrace": "Kopijuoti klaidos ataskaitą",
"bundle_column_error.error.body": "Paprašytos puslapio nepavyko atvaizduoti. Tai gali būti dėl mūsų kodo klaidos arba naršyklės suderinamumo problemos.", "bundle_column_error.error.body": "Paprašytos puslapio nepavyko atvaizduoti. Tai gali būti dėl mūsų kodo klaidos arba naršyklės suderinamumo problemos.",

View file

@ -225,8 +225,8 @@
"domain_pill.their_username": "Hun unieke identificatie-adres op hun server. Het is mogelijk dat er gebruikers met dezelfde gebruikersnaam op verschillende servers te vinden zijn.", "domain_pill.their_username": "Hun unieke identificatie-adres op hun server. Het is mogelijk dat er gebruikers met dezelfde gebruikersnaam op verschillende servers te vinden zijn.",
"domain_pill.username": "Gebruikersnaam", "domain_pill.username": "Gebruikersnaam",
"domain_pill.whats_in_a_handle": "Wat is een fediverse-adres?", "domain_pill.whats_in_a_handle": "Wat is een fediverse-adres?",
"domain_pill.who_they_are": "Omdat je aan een fediverse-adres kunt zien wie iemand is en waar die zich bevindt, kun je met mensen op het door <button>ActivityPub aangedreven</button> sociale web (fediverse) communiceren.", "domain_pill.who_they_are": "Omdat je aan een fediverse-adres kunt zien hoe iemand heet en op welke server die zich bevindt, kun je met mensen op het door <button>ActivityPub aangedreven</button> sociale web (fediverse) communiceren.",
"domain_pill.who_you_are": "Omdat je aan jouw fediverse-adres kunt zien wie jij bent is en waar je je bevindt, kunnen mensen op het door <button>ActivityPub aangedreven</button> sociale web (fediverse) met jou communiceren.", "domain_pill.who_you_are": "Omdat je aan jouw fediverse-adres kunt zien hoe je heet en op welke server je je bevindt, kunnen mensen op het door <button>ActivityPub aangedreven</button> sociale web (fediverse) met jou communiceren.",
"domain_pill.your_handle": "Jouw fediverse-adres:", "domain_pill.your_handle": "Jouw fediverse-adres:",
"domain_pill.your_server": "Jouw digitale thuis, waar al jouw berichten zich bevinden. Is deze server toch niet naar jouw wens? Dan kun je op elk moment naar een andere server verhuizen en ook jouw volgers overbrengen.", "domain_pill.your_server": "Jouw digitale thuis, waar al jouw berichten zich bevinden. Is deze server toch niet naar jouw wens? Dan kun je op elk moment naar een andere server verhuizen en ook jouw volgers overbrengen.",
"domain_pill.your_username": "Jouw unieke identificatie-adres op deze server. Het is mogelijk dat er gebruikers met dezelfde gebruikersnaam op verschillende servers te vinden zijn.", "domain_pill.your_username": "Jouw unieke identificatie-adres op deze server. Het is mogelijk dat er gebruikers met dezelfde gebruikersnaam op verschillende servers te vinden zijn.",

View file

@ -15,21 +15,32 @@
"account.cancel_follow_request": "ਫ਼ਾਲੋ ਕਰਨ ਨੂੰ ਰੱਦ ਕਰੋ", "account.cancel_follow_request": "ਫ਼ਾਲੋ ਕਰਨ ਨੂੰ ਰੱਦ ਕਰੋ",
"account.copy": "ਪਰੋਫਾਇਲ ਲਈ ਲਿੰਕ ਕਾਪੀ ਕਰੋ", "account.copy": "ਪਰੋਫਾਇਲ ਲਈ ਲਿੰਕ ਕਾਪੀ ਕਰੋ",
"account.direct": "ਨਿੱਜੀ ਜ਼ਿਕਰ @{name}", "account.direct": "ਨਿੱਜੀ ਜ਼ਿਕਰ @{name}",
"account.domain_blocked": "ਡੋਮੇਨ ਉੱਤੇ ਪਾਬੰਦੀ",
"account.edit_profile": "ਪਰੋਫਾਈਲ ਨੂੰ ਸੋਧੋ", "account.edit_profile": "ਪਰੋਫਾਈਲ ਨੂੰ ਸੋਧੋ",
"account.enable_notifications": "ਜਦੋਂ {name} ਪੋਸਟ ਕਰੇ ਤਾਂ ਮੈਨੂੰ ਸੂਚਨਾ ਦਿਓ",
"account.endorse": "ਪਰੋਫਾਇਲ ਉੱਤੇ ਫ਼ੀਚਰ",
"account.featured_tags.last_status_at": "{date} ਨੂੰ ਆਖਰੀ ਪੋਸਟ", "account.featured_tags.last_status_at": "{date} ਨੂੰ ਆਖਰੀ ਪੋਸਟ",
"account.featured_tags.last_status_never": "ਕੋਈ ਪੋਸਟ ਨਹੀਂ", "account.featured_tags.last_status_never": "ਕੋਈ ਪੋਸਟ ਨਹੀਂ",
"account.follow": "ਫ਼ਾਲੋ", "account.follow": "ਫ਼ਾਲੋ",
"account.follow_back": "ਵਾਪਸ ਫਾਲ਼ੋ ਕਰੋ",
"account.followers": "ਫ਼ਾਲੋਅਰ", "account.followers": "ਫ਼ਾਲੋਅਰ",
"account.followers.empty": "ਇਸ ਵਰਤੋਂਕਾਰ ਨੂੰ ਹਾਲੇ ਕੋਈ ਫ਼ਾਲੋ ਨਹੀਂ ਕਰਦਾ ਹੈ।", "account.followers.empty": "ਇਸ ਵਰਤੋਂਕਾਰ ਨੂੰ ਹਾਲੇ ਕੋਈ ਫ਼ਾਲੋ ਨਹੀਂ ਕਰਦਾ ਹੈ।",
"account.followers_counter": "{count, plural, one {{counter} ਫ਼ਾਲੋਅਰ} other {{counter} ਫ਼ਾਲੋਅਰ}}",
"account.following": "ਫ਼ਾਲੋ ਕੀਤਾ", "account.following": "ਫ਼ਾਲੋ ਕੀਤਾ",
"account.following_counter": "{count, plural, one {{counter} ਨੂੰ ਫ਼ਾਲੋ} other {{counter} ਨੂੰ ਫ਼ਾਲੋ}}",
"account.follows.empty": "ਇਹ ਵਰਤੋਂਕਾਰ ਹਾਲੇ ਕਿਸੇ ਨੂੰ ਫ਼ਾਲੋ ਨਹੀਂ ਕਰਦਾ ਹੈ।", "account.follows.empty": "ਇਹ ਵਰਤੋਂਕਾਰ ਹਾਲੇ ਕਿਸੇ ਨੂੰ ਫ਼ਾਲੋ ਨਹੀਂ ਕਰਦਾ ਹੈ।",
"account.go_to_profile": "ਪਰੋਫਾਇਲ ਉੱਤੇ ਜਾਓ", "account.go_to_profile": "ਪਰੋਫਾਇਲ ਉੱਤੇ ਜਾਓ",
"account.media": "ਮੀਡੀਆ", "account.media": "ਮੀਡੀਆ",
"account.muted": "ਮੌਨ ਕੀਤੀਆਂ", "account.muted": "ਮੌਨ ਕੀਤੀਆਂ",
"account.mutual": "ਸਾਂਝੇ",
"account.no_bio": "ਕੋਈ ਵਰਣਨ ਨਹੀਂ ਦਿੱਤਾ।",
"account.open_original_page": "ਅਸਲ ਸਫ਼ੇ ਨੂੰ ਖੋਲ੍ਹੋ",
"account.posts": "ਪੋਸਟਾਂ", "account.posts": "ਪੋਸਟਾਂ",
"account.posts_with_replies": "ਪੋਸਤਾਂ ਅਤੇ ਜਵਾਬ", "account.posts_with_replies": "ਪੋਸਤਾਂ ਅਤੇ ਜਵਾਬ",
"account.report": "{name} ਬਾਰੇ ਰਿਪੋਰਟ ਕਰੋ",
"account.requested": "ਮਨਜ਼ੂਰੀ ਕੀਤੀ ਜਾ ਰਹੀ ਹੈ। ਫ਼ਾਲੋ ਬੇਨਤੀਆਂ ਨੂੰ ਰੱਦ ਕਰਨ ਲਈ ਕਲਿੱਕ ਕਰੋ", "account.requested": "ਮਨਜ਼ੂਰੀ ਕੀਤੀ ਜਾ ਰਹੀ ਹੈ। ਫ਼ਾਲੋ ਬੇਨਤੀਆਂ ਨੂੰ ਰੱਦ ਕਰਨ ਲਈ ਕਲਿੱਕ ਕਰੋ",
"account.requested_follow": "{name} ਨੇ ਤੁਹਾਨੂੰ ਫ਼ਾਲੋ ਕਰਨ ਦੀ ਬੇਨਤੀ ਕੀਤੀ ਹੈ", "account.requested_follow": "{name} ਨੇ ਤੁਹਾਨੂੰ ਫ਼ਾਲੋ ਕਰਨ ਦੀ ਬੇਨਤੀ ਕੀਤੀ ਹੈ",
"account.share": "{name} ਦਾ ਪਰੋਫ਼ਾਇਲ ਸਾਂਝਾ ਕਰੋ",
"account.statuses_counter": "{count, plural, one {{counter} Toot} other {{counter} Toots}}", "account.statuses_counter": "{count, plural, one {{counter} Toot} other {{counter} Toots}}",
"account.unblock": "@{name} ਤੋਂ ਪਾਬੰਦੀ ਹਟਾਓ", "account.unblock": "@{name} ਤੋਂ ਪਾਬੰਦੀ ਹਟਾਓ",
"account.unblock_domain": "{domain} ਡੋਮੇਨ ਤੋਂ ਪਾਬੰਦੀ ਹਟਾਓ", "account.unblock_domain": "{domain} ਡੋਮੇਨ ਤੋਂ ਪਾਬੰਦੀ ਹਟਾਓ",
@ -41,6 +52,9 @@
"admin.dashboard.retention.cohort_size": "ਨਵੇਂ ਵਰਤੋਂਕਾਰ", "admin.dashboard.retention.cohort_size": "ਨਵੇਂ ਵਰਤੋਂਕਾਰ",
"alert.unexpected.title": "ਓਹੋ!", "alert.unexpected.title": "ਓਹੋ!",
"announcement.announcement": "ਹੋਕਾ", "announcement.announcement": "ਹੋਕਾ",
"block_modal.show_less": "ਘੱਟ ਦਿਖਾਓ",
"block_modal.show_more": "ਵੱਧ ਦਿਖਾਓ",
"block_modal.title": "ਵਰਤੋਂਕਾਰ ਉੱਤੇ ਪਾਬੰਦੀ ਲਾਉਣੀ ਹੈ?",
"bundle_column_error.error.title": "ਓਹ ਹੋ!", "bundle_column_error.error.title": "ਓਹ ਹੋ!",
"bundle_column_error.network.title": "ਨੈੱਟਵਰਕ ਦੀ ਸਮੱਸਿਆ", "bundle_column_error.network.title": "ਨੈੱਟਵਰਕ ਦੀ ਸਮੱਸਿਆ",
"bundle_column_error.retry": "ਮੁੜ-ਕੋਸ਼ਿਸ਼ ਕਰੋ", "bundle_column_error.retry": "ਮੁੜ-ਕੋਸ਼ਿਸ਼ ਕਰੋ",

View file

@ -514,6 +514,7 @@
"notifications.permission_denied": "Уведомления на рабочем столе недоступны, так как вы запретили их отправку в браузере. Проверьте настройки для сайта, чтобы включить их обратно.", "notifications.permission_denied": "Уведомления на рабочем столе недоступны, так как вы запретили их отправку в браузере. Проверьте настройки для сайта, чтобы включить их обратно.",
"notifications.permission_denied_alert": "Уведомления на рабочем столе недоступны, так как вы ранее отклонили запрос на их отправку.", "notifications.permission_denied_alert": "Уведомления на рабочем столе недоступны, так как вы ранее отклонили запрос на их отправку.",
"notifications.permission_required": "Чтобы включить уведомления на рабочем столе, необходимо разрешить их в браузере.", "notifications.permission_required": "Чтобы включить уведомления на рабочем столе, необходимо разрешить их в браузере.",
"notifications.policy.filter_new_accounts_title": "Новые учётные записи",
"notifications_permission_banner.enable": "Включить уведомления", "notifications_permission_banner.enable": "Включить уведомления",
"notifications_permission_banner.how_to_control": "Получайте уведомления даже когда Mastodon закрыт, включив уведомления на рабочем столе. А чтобы лишний шум не отвлекал, вы можете настроить какие уведомления вы хотите получать, нажав на кнопку {icon} выше.", "notifications_permission_banner.how_to_control": "Получайте уведомления даже когда Mastodon закрыт, включив уведомления на рабочем столе. А чтобы лишний шум не отвлекал, вы можете настроить какие уведомления вы хотите получать, нажав на кнопку {icon} выше.",
"notifications_permission_banner.title": "Будьте в курсе происходящего", "notifications_permission_banner.title": "Будьте в курсе происходящего",

View file

@ -36,6 +36,7 @@
"account.go_to_profile": "o tawa lipu jan", "account.go_to_profile": "o tawa lipu jan",
"account.hide_reblogs": "o lukin ala e pana toki tan @{name}", "account.hide_reblogs": "o lukin ala e pana toki tan @{name}",
"account.in_memoriam": "jan ni li moli. pona o tawa ona.", "account.in_memoriam": "jan ni li moli. pona o tawa ona.",
"account.joined_short": "li kama",
"account.languages": "sina wile lukin e sitelen pi toki seme", "account.languages": "sina wile lukin e sitelen pi toki seme",
"account.locked_info": "sina wile kute e jan ni la ona o toki e ken", "account.locked_info": "sina wile kute e jan ni la ona o toki e ken",
"account.media": "sitelen", "account.media": "sitelen",
@ -70,6 +71,10 @@
"alert.unexpected.title": "pakala a!", "alert.unexpected.title": "pakala a!",
"announcement.announcement": "toki suli", "announcement.announcement": "toki suli",
"audio.hide": "o len e kalama", "audio.hide": "o len e kalama",
"block_modal.show_less": "o lili e lukin",
"block_modal.show_more": "o mute e lukin",
"block_modal.they_cant_mention": "ona li ken ala toki e sina li ken ala alasa e sina",
"block_modal.title": "o weka ala weka e jan",
"boost_modal.combo": "sina ken luka e nena {combo} tawa ni: sina wile ala luka e nena lon tenpo kama", "boost_modal.combo": "sina ken luka e nena {combo} tawa ni: sina wile ala luka e nena lon tenpo kama",
"bundle_column_error.copy_stacktrace": "o awen e sona pakala lon ilo sina", "bundle_column_error.copy_stacktrace": "o awen e sona pakala lon ilo sina",
"bundle_column_error.error.body": "ilo li ken ala pana e lipu ni. ni li ken tan pakala ilo.", "bundle_column_error.error.body": "ilo li ken ala pana e lipu ni. ni li ken tan pakala ilo.",
@ -86,10 +91,15 @@
"column.about": "sona", "column.about": "sona",
"column.blocks": "kulupu pi jan weka", "column.blocks": "kulupu pi jan weka",
"column.bookmarks": "awen toki", "column.bookmarks": "awen toki",
"column.community": "linja tenpo pi ma ni",
"column.favourites": "ijo pona",
"column.firehose": "toki pi tenpo ni",
"column.follow_requests": "wile alasa pi jan ante",
"column.home": "lipu open", "column.home": "lipu open",
"column.lists": "kulupu lipu", "column.lists": "kulupu lipu",
"column.mutes": "jan len", "column.mutes": "jan len",
"column.pins": "toki sewi", "column.pins": "toki sewi",
"column_back_button.label": "o tawa monsi",
"column_header.hide_settings": "o len e lawa", "column_header.hide_settings": "o len e lawa",
"column_header.pin": "o sewi", "column_header.pin": "o sewi",
"column_header.show_settings": "o lukin e lawa", "column_header.show_settings": "o lukin e lawa",
@ -157,6 +167,9 @@
"dismissable_banner.explore_statuses": "suni ni la jan mute li lukin e toki ni. jan mute li wawa e toki li suli e toki la toki ni li lon sewi. toki li sin la toki ni li lon sewi.", "dismissable_banner.explore_statuses": "suni ni la jan mute li lukin e toki ni. jan mute li wawa e toki li suli e toki la toki ni li lon sewi. toki li sin la toki ni li lon sewi.",
"dismissable_banner.explore_tags": "suni ni la jan mute li lukin e toki pi toki ni. jan mute li kepeken toki la toki ni li lon sewi.", "dismissable_banner.explore_tags": "suni ni la jan mute li lukin e toki pi toki ni. jan mute li kepeken toki la toki ni li lon sewi.",
"dismissable_banner.public_timeline": "toki ni li sin. jan li pali e toki ni la jan ante mute pi ma {domain} li kute e jan ni.", "dismissable_banner.public_timeline": "toki ni li sin. jan li pali e toki ni la jan ante mute pi ma {domain} li kute e jan ni.",
"domain_block_modal.block": "o weka e ma",
"domain_block_modal.you_will_lose_followers": "ma ni la jan alasa ale sina li weka",
"domain_block_modal.you_wont_see_posts": "sina ken ala lukin e toki tan jan pi ma ni",
"embed.preview": "ni li jo e sitelen ni:", "embed.preview": "ni li jo e sitelen ni:",
"emoji_button.activity": "musi", "emoji_button.activity": "musi",
"emoji_button.flags": "len ma", "emoji_button.flags": "len ma",
@ -232,7 +245,7 @@
"keyboard_shortcuts.boost": "o pana sin e toki", "keyboard_shortcuts.boost": "o pana sin e toki",
"keyboard_shortcuts.down": "o tawa anpa lon lipu", "keyboard_shortcuts.down": "o tawa anpa lon lipu",
"keyboard_shortcuts.enter": "o lukin e toki", "keyboard_shortcuts.enter": "o lukin e toki",
"keyboard_shortcuts.favourite": "o suli e toki", "keyboard_shortcuts.favourite": "o sitelen pona e toki",
"keyboard_shortcuts.favourites": "o lukin e lipu sina pi toki suli", "keyboard_shortcuts.favourites": "o lukin e lipu sina pi toki suli",
"keyboard_shortcuts.muted": "o lukin e lipu sina pi jan len", "keyboard_shortcuts.muted": "o lukin e lipu sina pi jan len",
"keyboard_shortcuts.my_profile": "o lukin e lipu sina", "keyboard_shortcuts.my_profile": "o lukin e lipu sina",
@ -264,7 +277,7 @@
"navigation_bar.about": "sona", "navigation_bar.about": "sona",
"navigation_bar.blocks": "jan weka", "navigation_bar.blocks": "jan weka",
"navigation_bar.compose": "o pali e toki sin", "navigation_bar.compose": "o pali e toki sin",
"navigation_bar.favourites": "toki suli", "navigation_bar.favourites": "ijo pona",
"navigation_bar.filters": "nimi len", "navigation_bar.filters": "nimi len",
"navigation_bar.lists": "kulupu lipu", "navigation_bar.lists": "kulupu lipu",
"navigation_bar.mutes": "sina wile ala kute e jan ni", "navigation_bar.mutes": "sina wile ala kute e jan ni",
@ -273,7 +286,7 @@
"navigation_bar.search": "o alasa", "navigation_bar.search": "o alasa",
"notification.admin.report": "jan {name} li toki e jan {target} tawa lawa", "notification.admin.report": "jan {name} li toki e jan {target} tawa lawa",
"notification.admin.sign_up": "{name} li kama", "notification.admin.sign_up": "{name} li kama",
"notification.favourite": "{name} li suli e toki sina", "notification.favourite": "toki sina li pona tawa {name}",
"notification.follow": " {name} li kute e sina", "notification.follow": " {name} li kute e sina",
"notification.follow_request": "{name} li wile kute e sina", "notification.follow_request": "{name} li wile kute e sina",
"notification.mention": "jan {name} li toki e sina", "notification.mention": "jan {name} li toki e sina",
@ -281,11 +294,13 @@
"notification.reblog": "{name} li wawa e toki sina", "notification.reblog": "{name} li wawa e toki sina",
"notification.status": "{name} li toki", "notification.status": "{name} li toki",
"notification.update": "{name} li ante e toki", "notification.update": "{name} li ante e toki",
"notifications.column_settings.favourite": "ijo pona:",
"notifications.column_settings.follow": "jan kute sin", "notifications.column_settings.follow": "jan kute sin",
"notifications.column_settings.poll": "pana lon pana ni:", "notifications.column_settings.poll": "pana lon pana ni:",
"notifications.column_settings.reblog": "wawa:", "notifications.column_settings.reblog": "wawa:",
"notifications.column_settings.update": "ante toki:", "notifications.column_settings.update": "ante toki:",
"notifications.filter.all": "ale", "notifications.filter.all": "ale",
"notifications.filter.favourites": "ijo pona",
"notifications.filter.polls": "pana lon pana ni", "notifications.filter.polls": "pana lon pana ni",
"onboarding.compose.template": "toki a, #Mastodon o!", "onboarding.compose.template": "toki a, #Mastodon o!",
"onboarding.profile.display_name": "nimi tawa jan ante", "onboarding.profile.display_name": "nimi tawa jan ante",
@ -333,7 +348,7 @@
"status.delete": "o weka", "status.delete": "o weka",
"status.edit": "o ante", "status.edit": "o ante",
"status.embed": "ni o lon insa pi lipu ante", "status.embed": "ni o lon insa pi lipu ante",
"status.favourite": "o suli", "status.favourite": "o sitelen pona",
"status.hide": "o len", "status.hide": "o len",
"status.history.created": "{name} li pali e ni lon {date}", "status.history.created": "{name} li pali e ni lon {date}",
"status.history.edited": "{name} li ante lon {date}", "status.history.edited": "{name} li ante lon {date}",

View file

@ -8291,8 +8291,13 @@ noscript {
} }
} }
@container account-header (max-width: 372px) { .optional {
.optional { @container account-header (max-width: 372px) {
display: none;
}
// Fallback for older browsers with no container queries support
@media screen and (max-width: 372px + 55px) {
display: none; display: none;
} }
} }

View file

@ -49,7 +49,7 @@ class AccountStatusesFilter
if blocked? if blocked?
Status.none Status.none
elsif anonymous? elsif anonymous?
account.statuses.where(visibility: %i(public unlisted public_unlisted)) account.statuses.distributable_visibility_for_anonymous
elsif author? elsif author?
account.statuses.all # NOTE: #merge! does not work without the #all account.statuses.all # NOTE: #merge! does not work without the #all
else else

View file

@ -124,7 +124,7 @@ class FeedManager
def merge_into_home(from_account, into_account) def merge_into_home(from_account, into_account)
timeline_key = key(:home, into_account.id) timeline_key = key(:home, into_account.id)
aggregate = into_account.user&.aggregates_reblogs? aggregate = into_account.user&.aggregates_reblogs?
query = from_account.statuses.where(visibility: [:public, :unlisted, :public_unlisted, :login, :private]).includes(:preloadable_poll, :media_attachments, reblog: :account).limit(FeedManager::MAX_ITEMS / 4) query = from_account.statuses.list_eligible_visibility.includes(:preloadable_poll, :media_attachments, reblog: :account).limit(FeedManager::MAX_ITEMS / 4)
if redis.zcard(timeline_key) >= FeedManager::MAX_ITEMS / 4 if redis.zcard(timeline_key) >= FeedManager::MAX_ITEMS / 4
oldest_home_score = redis.zrange(timeline_key, 0, 0, with_scores: true).first.last.to_i oldest_home_score = redis.zrange(timeline_key, 0, 0, with_scores: true).first.last.to_i
@ -150,7 +150,7 @@ class FeedManager
def merge_into_list(from_account, list) def merge_into_list(from_account, list)
timeline_key = key(:list, list.id) timeline_key = key(:list, list.id)
aggregate = list.account.user&.aggregates_reblogs? aggregate = list.account.user&.aggregates_reblogs?
query = from_account.statuses.where(visibility: [:public, :unlisted, :public_unlisted, :login, :private]).includes(:preloadable_poll, :media_attachments, reblog: :account).limit(FeedManager::MAX_ITEMS / 4) query = from_account.statuses.list_eligible_visibility.includes(:preloadable_poll, :media_attachments, reblog: :account).limit(FeedManager::MAX_ITEMS / 4)
if redis.zcard(timeline_key) >= FeedManager::MAX_ITEMS / 4 if redis.zcard(timeline_key) >= FeedManager::MAX_ITEMS / 4
oldest_home_score = redis.zrange(timeline_key, 0, 0, with_scores: true).first.last.to_i oldest_home_score = redis.zrange(timeline_key, 0, 0, with_scores: true).first.last.to_i
@ -311,7 +311,7 @@ class FeedManager
next if last_status_score < oldest_home_score next if last_status_score < oldest_home_score
end end
statuses = target_account.statuses.where(visibility: [:public, :unlisted, :public_unlisted, :login, :private]).includes(:preloadable_poll, :media_attachments, :account, reblog: :account).limit(limit) statuses = target_account.statuses.list_eligible_visibility.includes(:preloadable_poll, :media_attachments, :account, reblog: :account).limit(limit)
crutches = build_crutches(account.id, statuses) crutches = build_crutches(account.id, statuses)
statuses.each do |status| statuses.each do |status|

View file

@ -68,6 +68,7 @@ class Account < ApplicationRecord
) )
BACKGROUND_REFRESH_INTERVAL = 1.week.freeze BACKGROUND_REFRESH_INTERVAL = 1.week.freeze
DEFAULT_FIELDS_SIZE = 6
INSTANCE_ACTOR_ID = -99 INSTANCE_ACTOR_ID = -99
USERNAME_RE = /[a-z0-9_]+([a-z0-9_.-]+[a-z0-9_]+)?/i USERNAME_RE = /[a-z0-9_]+([a-z0-9_.-]+[a-z0-9_]+)?/i
@ -110,7 +111,7 @@ class Account < ApplicationRecord
validates_with UnreservedUsernameValidator, if: -> { local? && will_save_change_to_username? && actor_type != 'Application' } validates_with UnreservedUsernameValidator, if: -> { local? && will_save_change_to_username? && actor_type != 'Application' }
validates :display_name, length: { maximum: 30 }, if: -> { local? && will_save_change_to_display_name? } validates :display_name, length: { maximum: 30 }, if: -> { local? && will_save_change_to_display_name? }
validates :note, note_length: { maximum: 500 }, if: -> { local? && will_save_change_to_note? } validates :note, note_length: { maximum: 500 }, if: -> { local? && will_save_change_to_note? }
validates :fields, length: { maximum: 6 }, if: -> { local? && will_save_change_to_fields? } validates :fields, length: { maximum: DEFAULT_FIELDS_SIZE }, if: -> { local? && will_save_change_to_fields? }
validates :uri, absence: true, if: :local?, on: :create validates :uri, absence: true, if: :local?, on: :create
validates :inbox_url, absence: true, if: :local?, on: :create validates :inbox_url, absence: true, if: :local?, on: :create
validates :shared_inbox_url, absence: true, if: :local?, on: :create validates :shared_inbox_url, absence: true, if: :local?, on: :create
@ -410,8 +411,6 @@ class Account < ApplicationRecord
self[:fields] = fields self[:fields] = fields
end end
DEFAULT_FIELDS_SIZE = 6
def build_fields def build_fields
return if fields.size >= DEFAULT_FIELDS_SIZE return if fields.size >= DEFAULT_FIELDS_SIZE

View file

@ -16,7 +16,7 @@ class Admin::StatusFilter
end end
def results def results
scope = @account.statuses.where(visibility: [:public, :unlisted, :public_unlisted, :login]) scope = @account.statuses.distributable_visibility
params.each do |key, value| params.each do |key, value|
next if IGNORED_PARAMS.include?(key.to_s) next if IGNORED_PARAMS.include?(key.to_s)

View file

@ -62,7 +62,7 @@ class Announcement < ApplicationRecord
@statuses ||= if status_ids.nil? @statuses ||= if status_ids.nil?
[] []
else else
Status.where(id: status_ids, visibility: [:public, :unlisted, :public_unlisted]) Status.where(id: status_ids).distributable_visibility_for_anonymous
end end
end end

View file

@ -21,7 +21,7 @@ module Status::ThreadingConcern
end end
def self_replies(limit) def self_replies(limit)
account.statuses.where(in_reply_to_id: id, visibility: [:public, :unlisted, :public_unlisted, :login]).reorder(id: :asc).limit(limit) account.statuses.distributable_visibility.where(in_reply_to_id: id).reorder(id: :asc).limit(limit)
end end
private private

View file

@ -46,6 +46,7 @@ class CustomFilter < ApplicationRecord
validate :context_must_be_valid validate :context_must_be_valid
normalizes :context, with: ->(context) { context.map(&:strip).filter_map(&:presence) } normalizes :context, with: ->(context) { context.map(&:strip).filter_map(&:presence) }
scope :unexpired, -> { where(expires_at: nil).or where.not(expires_at: ..Time.zone.now) }
before_save :prepare_cache_invalidation! before_save :prepare_cache_invalidation!
before_destroy :prepare_cache_invalidation! before_destroy :prepare_cache_invalidation!
@ -78,14 +79,16 @@ class CustomFilter < ApplicationRecord
active_filters = Rails.cache.fetch("filters:v3:#{account_id}") do active_filters = Rails.cache.fetch("filters:v3:#{account_id}") do
filters_hash = {} filters_hash = {}
scope = CustomFilterKeyword.includes(:custom_filter).where(custom_filter: { account_id: account_id }).where(Arel.sql('expires_at IS NULL OR expires_at > NOW()')) scope = CustomFilterKeyword.left_outer_joins(:custom_filter).merge(unexpired.where(account_id: account_id))
scope.to_a.group_by(&:custom_filter).each do |filter, keywords| scope.to_a.group_by(&:custom_filter).each do |filter, keywords|
keywords.map!(&:to_regex) keywords.map!(&:to_regex)
filters_hash[filter.id] = { keywords: Regexp.union(keywords), filter: filter } filters_hash[filter.id] = { keywords: Regexp.union(keywords), filter: filter }
end.to_h end.to_h
scope = CustomFilterStatus.includes(:custom_filter).where(custom_filter: { account_id: account_id }).where(Arel.sql('expires_at IS NULL OR expires_at > NOW()')) scope = CustomFilterStatus.left_outer_joins(:custom_filter).merge(unexpired.where(account_id: account_id))
scope.to_a.group_by(&:custom_filter).each do |filter, statuses| scope.to_a.group_by(&:custom_filter).each do |filter, statuses|
filters_hash[filter.id] ||= { filter: filter } filters_hash[filter.id] ||= { filter: filter }
filters_hash[filter.id].merge!(status_ids: statuses.map(&:status_id)) filters_hash[filter.id].merge!(status_ids: statuses.map(&:status_id))

View file

@ -74,6 +74,6 @@ class FeaturedTag < ApplicationRecord
end end
def visible_tagged_account_statuses def visible_tagged_account_statuses
account.statuses.where(visibility: %i(public unlisted public_unlisted login)).tagged_with(tag) account.statuses.distributable_visibility.tagged_with(tag)
end end
end end

View file

@ -154,6 +154,9 @@ class Status < ApplicationRecord
where('NOT EXISTS (SELECT * FROM statuses_tags forbidden WHERE forbidden.status_id = statuses.id AND forbidden.tag_id IN (?))', tag_ids) where('NOT EXISTS (SELECT * FROM statuses_tags forbidden WHERE forbidden.status_id = statuses.id AND forbidden.tag_id IN (?))', tag_ids)
} }
scope :unset_searchability, -> { where(searchability: nil, reblog_of_id: nil) } scope :unset_searchability, -> { where(searchability: nil, reblog_of_id: nil) }
scope :distributable_visibility, -> { where(visibility: %i(public public_unlisted login unlisted)) }
scope :distributable_visibility_for_anonymous, -> { where(visibility: %i(public public_unlisted unlisted)) }
scope :list_eligible_visibility, -> { where(visibility: %i(public public_unlisted login unlisted private)) }
after_create_commit :trigger_create_webhooks after_create_commit :trigger_create_webhooks
after_update_commit :trigger_update_webhooks after_update_commit :trigger_update_webhooks

View file

@ -12,7 +12,7 @@
.notranslate.app-holder#mastodon{ data: { props: Oj.dump(default_props) } } .notranslate.app-holder#mastodon{ data: { props: Oj.dump(default_props) } }
%noscript %noscript
= image_pack_tag 'logo.svg', alt: 'Mastodon' = image_tag frontend_asset_path('images/logo.svg'), alt: 'Mastodon'
%div %div
= t('errors.noscript_html', apps_path: 'https://joinmastodon.org/apps') = t('errors.noscript_html', apps_path: 'https://joinmastodon.org/apps')

View file

@ -1,9 +1,9 @@
# frozen_string_literal: true # frozen_string_literal: true
require_relative '../../lib/premailer_webpack_strategy' require_relative '../../lib/premailer_bundled_asset_strategy'
Premailer::Rails.config.merge!(remove_ids: true, Premailer::Rails.config.merge!(remove_ids: true,
adapter: :nokogiri, adapter: :nokogiri,
generate_text_part: false, generate_text_part: false,
css_to_attributes: false, css_to_attributes: false,
strategies: [PremailerWebpackStrategy]) strategies: [PremailerBundledAssetStrategy])

View file

@ -615,7 +615,7 @@ de:
created_at: Gemeldet created_at: Gemeldet
delete_and_resolve: Beiträge löschen delete_and_resolve: Beiträge löschen
forwarded: Weitergeleitet forwarded: Weitergeleitet
forwarded_replies_explanation: Diese Meldung stammt von einem externen Profil und betrifft einen externen Inhalt. Der Inhalt wurde an Dich weitergeleitet, weil er eine Antwort auf ein bei Dir registriertes Profil ist. forwarded_replies_explanation: Diese Meldung stammt von einem externen Profil und betrifft einen externen Inhalt. Der Inhalt wurde an dich weitergeleitet, weil er eine Antwort auf ein bei dir registriertes Profil ist.
forwarded_to: Weitergeleitet an %{domain} forwarded_to: Weitergeleitet an %{domain}
mark_as_resolved: Als geklärt markieren mark_as_resolved: Als geklärt markieren
mark_as_sensitive: Mit einer Inhaltswarnung versehen mark_as_sensitive: Mit einer Inhaltswarnung versehen

View file

@ -12,6 +12,7 @@ en-GB:
last_attempt: You have one more attempt before your account is locked. last_attempt: You have one more attempt before your account is locked.
locked: Your account is locked. locked: Your account is locked.
not_found_in_database: Invalid %{authentication_keys} or password. 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. pending: Your account is still under review.
timeout: Your session expired. Please log in again to continue. timeout: Your session expired. Please log in again to continue.
unauthenticated: You need to log in or sign up before continuing. unauthenticated: You need to log in or sign up before continuing.

View file

@ -597,6 +597,9 @@ en-GB:
actions_description_html: Decide which action to take to resolve this report. If you take a punitive action against the reported account, an e-mail notification will be sent to them, except when the <strong>Spam</strong> category is selected. actions_description_html: Decide which action to take to resolve this report. If you take a punitive action against the reported account, an e-mail notification will be sent to them, except when the <strong>Spam</strong> category is selected.
actions_description_remote_html: Decide which action to take to resolve this report. This will only affect how <strong>your</strong> server communicates with this remote account and handle its content. actions_description_remote_html: Decide which action to take to resolve this report. This will only affect how <strong>your</strong> server communicates with this remote account and handle its content.
add_to_report: Add more to report add_to_report: Add more to report
already_suspended_badges:
local: Already suspended on this server
remote: Already suspended on their server
are_you_sure: Are you sure? are_you_sure: Are you sure?
assign_to_self: Assign to me assign_to_self: Assign to me
assigned: Assigned moderator assigned: Assigned moderator
@ -767,6 +770,7 @@ en-GB:
disabled: To no one disabled: To no one
users: To logged-in local users users: To logged-in local users
registrations: registrations:
moderation_recommandation: Please make sure you have an adequate and reactive moderation team before you open registrations to everyone!
preamble: Control who can create an account on your server. preamble: Control who can create an account on your server.
title: Registrations title: Registrations
registrations_mode: registrations_mode:
@ -774,6 +778,7 @@ en-GB:
approved: Approval required for sign up approved: Approval required for sign up
none: Nobody can sign up none: Nobody can sign up
open: Anyone can sign up open: Anyone can sign up
warning_hint: We recommend using “Approval required for sign up” unless you are confident your moderation team can handle spam and malicious registrations in a timely fashion.
security: security:
authorized_fetch: Require authentication from federated servers authorized_fetch: Require authentication from federated servers
authorized_fetch_hint: Requiring authentication from federated servers enables stricter enforcement of both user-level and server-level blocks. However, this comes at the cost of a performance penalty, reduces the reach of your replies, and may introduce compatibility issues with some federated services. In addition, this will not prevent dedicated actors from fetching your public posts and accounts. authorized_fetch_hint: Requiring authentication from federated servers enables stricter enforcement of both user-level and server-level blocks. However, this comes at the cost of a performance penalty, reduces the reach of your replies, and may introduce compatibility issues with some federated services. In addition, this will not prevent dedicated actors from fetching your public posts and accounts.
@ -966,6 +971,9 @@ en-GB:
title: Webhooks title: Webhooks
webhook: Webhook webhook: Webhook
admin_mailer: admin_mailer:
auto_close_registrations:
body: Due to a lack of recent moderator activity, registrations on %{instance} have been automatically switched to requiring manual review, to prevent %{instance} from being used as a platform for potential bad actors. You can switch it back to open registrations at any time.
subject: Registrations for %{instance} have been automatically switched to requiring approval
new_appeal: new_appeal:
actions: actions:
delete_statuses: to delete their posts delete_statuses: to delete their posts
@ -1647,13 +1655,26 @@ en-GB:
import: Import import: Import
import_and_export: Import and export import_and_export: Import and export
migrate: Account migration migrate: Account migration
notifications: E-mail notifications
preferences: Preferences preferences: Preferences
profile: Profile profile: Profile
relationships: Follows and followers relationships: Follows and followers
severed_relationships: Severed relationships
statuses_cleanup: Automated post deletion statuses_cleanup: Automated post deletion
strikes: Moderation strikes strikes: Moderation strikes
two_factor_authentication: Two-factor Auth two_factor_authentication: Two-factor Auth
webauthn_authentication: Security keys webauthn_authentication: Security keys
severed_relationships:
download: Download (%{count})
event_type:
account_suspension: Account suspension (%{target_name})
domain_block: Server suspension (%{target_name})
user_domain_block: You blocked %{target_name}
lost_followers: Lost followers
lost_follows: Lost follows
preamble: You may lose follows and followers when you block a domain or when your moderators decide to suspend a remote server. When that happens, you will be able to download lists of severed relationships, to be inspected and possibly imported on another server.
purged: Information about this server has been purged by your server's administrators.
type: Event
statuses: statuses:
attached: attached:
audio: audio:
@ -1747,6 +1768,7 @@ en-GB:
contrast: Mastodon (High contrast) contrast: Mastodon (High contrast)
default: Mastodon (Dark) default: Mastodon (Dark)
mastodon-light: Mastodon (Light) mastodon-light: Mastodon (Light)
system: Automatic (use system theme)
time: time:
formats: formats:
default: "%b %d, %Y, %H:%M" default: "%b %d, %Y, %H:%M"
@ -1834,7 +1856,44 @@ en-GB:
silence: Account limited silence: Account limited
suspend: Account suspended suspend: Account suspended
welcome: welcome:
apps_android_action: Get it on Google Play
apps_ios_action: Download on the App Store
apps_step: Download our official apps.
apps_title: Mastodon apps
checklist_subtitle: 'Let''s get you started on this new social frontier:'
checklist_title: Welcome Checklist
edit_profile_action: Personalise
edit_profile_step: Boost your interactions by having a comprehensive profile.
edit_profile_title: Personalise your profile
explanation: Here are some tips to get you started explanation: Here are some tips to get you started
feature_action: Learn more
feature_audience: Mastodon provides you with a unique possibility of managing your audience without middlemen. Mastodon deployed on your own infrastructure allows you to follow and be followed from any other Mastodon server online and is under no one's control but yours.
feature_audience_title: Build your audience in confidence
feature_control: You know best what you want to see on your home feed. No algorithms or ads to waste your time. Follow anyone across any Mastodon server from a single account and receive their posts in chronological order, and make your corner of the Internet a little more like you.
feature_control_title: Stay in control of your own timeline
feature_creativity: Mastodon supports audio, video and picture posts, accessibility descriptions, polls, content warnings, animated avatars, custom emojis, thumbnail crop control, and more, to help you express yourself online. Whether you're publishing your art, your music, or your podcast, Mastodon is there for you.
feature_creativity_title: Unparalleled creativity
feature_moderation: Mastodon puts decision making back in your hands. Each server creates their own rules and regulations, which are enforced locally and not top-down like corporate social media, making it the most flexible in responding to the needs of different groups of people. Join a server with the rules you agree with, or host your own.
feature_moderation_title: Moderating the way it should be
follow_action: Follow
follow_step: Following interesting people is what Mastodon is all about.
follow_title: Personalise your home feed
follows_subtitle: Follow well-known accounts
follows_title: Who to follow
follows_view_more: View more people to follow
hashtags_recent_count:
one: "%{people} person in the past 2 days"
other: "%{people} people in the past 2 days"
hashtags_subtitle: Explore whats trending since past 2 days
hashtags_title: Trending hashtags
hashtags_view_more: View more trending hashtags
post_action: Compose
post_step: Say hello to the world with text, photos, videos, or polls.
post_title: Make your first post
share_action: Share
share_step: Let your friends know how to find you on Mastodon.
share_title: Share your Mastodon profile
sign_in_action: Sign in
subject: Welcome to Mastodon subject: Welcome to Mastodon
title: Welcome aboard, %{name}! title: Welcome aboard, %{name}!
users: users:

View file

@ -1988,13 +1988,26 @@ ja:
import: データのインポート import: データのインポート
import_and_export: インポート・エクスポート import_and_export: インポート・エクスポート
migrate: アカウントの引っ越し migrate: アカウントの引っ越し
notifications: メール通知
preferences: ユーザー設定 preferences: ユーザー設定
profile: プロフィール profile: プロフィール
relationships: フォロー・フォロワー relationships: フォロー・フォロワー
severed_relationships: 途切れたフォロー関係
statuses_cleanup: 投稿の自動削除 statuses_cleanup: 投稿の自動削除
strikes: モデレーションストライク strikes: モデレーションストライク
two_factor_authentication: 二要素認証 two_factor_authentication: 二要素認証
webauthn_authentication: セキュリティキー webauthn_authentication: セキュリティキー
severed_relationships:
download: 取り出す (%{count}件)
event_type:
account_suspension: アカウントの停止 (%{target_name})
domain_block: 管理者によるサーバーの停止 (%{target_name})
user_domain_block: ユーザーによるドメインブロック (%{target_name})
lost_followers: 解除されたフォロワー
lost_follows: 解除されたフォロー
preamble: ドメインをブロックしたりモデレーターによってリモートのサーバーが停止された場合、巻き込みでフォロー・フォロワー関係が失われることがあります。このようにして解除されたフォロー・フォロワーはリスト形式で取り出して内容を確認したり、対応している場合は他のサーバーでインポートできます。
purged: 管理者がサーバーの情報を削除したため表示できません。
type: 理由
statuses: statuses:
attached: attached:
audio: audio:

View file

@ -1669,6 +1669,9 @@ pt-BR:
event_type: event_type:
account_suspension: Suspensão da conta (%{target_name}) account_suspension: Suspensão da conta (%{target_name})
domain_block: Suspensão do servidor (%{target_name}) domain_block: Suspensão do servidor (%{target_name})
user_domain_block: Você bloqueou %{target_name}
lost_followers: Seguidores perdidos
type: Evento
statuses: statuses:
attached: attached:
audio: audio:
@ -1874,6 +1877,9 @@ pt-BR:
follows_subtitle: Siga contas conhecidas follows_subtitle: Siga contas conhecidas
follows_title: Quem seguir follows_title: Quem seguir
follows_view_more: Veja mais pessoas para seguir follows_view_more: Veja mais pessoas para seguir
hashtags_recent_count:
one: "%{people} Pessoas nos últimos 2 dias"
other: "%{people} pessoas nos últimos 2 dias"
hashtags_subtitle: Explorar o que está em alta nos últimos 2 dias hashtags_subtitle: Explorar o que está em alta nos últimos 2 dias
hashtags_title: Hashtags em alta hashtags_title: Hashtags em alta
hashtags_view_more: Ver mais hashtags em alta hashtags_view_more: Ver mais hashtags em alta

View file

@ -39,12 +39,14 @@ en-GB:
text: You can only appeal a strike once text: You can only appeal a strike once
defaults: defaults:
autofollow: People who sign up through the invite will automatically follow you autofollow: People who sign up through the invite will automatically follow you
avatar: WEBP, PNG, GIF or JPG. At most %{size}. Will be downscaled to %{dimensions}px
bot: Signal to others that the account mainly performs automated actions and might not be monitored bot: Signal to others that the account mainly performs automated actions and might not be monitored
context: One or multiple contexts where the filter should apply context: One or multiple contexts where the filter should apply
current_password: For security purposes please enter the password of the current account current_password: For security purposes please enter the password of the current account
current_username: To confirm, please enter the username of the current account current_username: To confirm, please enter the username of the current account
digest: Only sent after a long period of inactivity and only if you have received any personal messages in your absence digest: Only sent after a long period of inactivity and only if you have received any personal messages in your absence
email: You will be sent a confirmation e-mail email: You will be sent a confirmation e-mail
header: WEBP, PNG, GIF or JPG. At most %{size}. Will be downscaled to %{dimensions}px
inbox_url: Copy the URL from the frontpage of the relay you want to use inbox_url: Copy the URL from the frontpage of the relay you want to use
irreversible: Filtered posts will disappear irreversibly, even if filter is later removed irreversible: Filtered posts will disappear irreversibly, even if filter is later removed
locale: The language of the user interface, e-mails and push notifications locale: The language of the user interface, e-mails and push notifications
@ -114,6 +116,7 @@ en-GB:
sign_up_requires_approval: New sign-ups will require your approval sign_up_requires_approval: New sign-ups will require your approval
severity: Choose what will happen with requests from this IP severity: Choose what will happen with requests from this IP
rule: rule:
hint: Optional. Provide more details about the rule
text: Describe a rule or requirement for users on this server. Try to keep it short and simple text: Describe a rule or requirement for users on this server. Try to keep it short and simple
sessions: sessions:
otp: 'Enter the two-factor code generated by your phone app or use one of your recovery codes:' otp: 'Enter the two-factor code generated by your phone app or use one of your recovery codes:'
@ -297,6 +300,7 @@ en-GB:
patch: Notify on bugfix updates patch: Notify on bugfix updates
trending_tag: New trend requires review trending_tag: New trend requires review
rule: rule:
hint: Additional information
text: Rule text: Rule
settings: settings:
indexable: Include profile page in search engines indexable: Include profile page in search engines

View file

@ -3,7 +3,7 @@ eu:
simple_form: simple_form:
hints: hints:
account: account:
discoverable: Zure bidalketa publikoak eta profila nabarmendu edo gomendatu egin daitezke Mastodoneko hainbat eremutan eta zure profila beste erabiltzaile batzuei iradoki dakieke. discoverable: Zure bidalketa publikoak eta profila nabarmendu edo gomendatu egin daitezke Mastodon-go hainbat eremutan eta zure profila beste erabiltzaile batzuei iradoki dakieke.
display_name: Zure izena edo ezizena. display_name: Zure izena edo ezizena.
fields: Zure webgunea, izenordainak, adina, nahi duzun guztia. fields: Zure webgunea, izenordainak, adina, nahi duzun guztia.
indexable: Zure argitalpen publikoak bilaketa-emaitzetan ager daitezke Mastodonen. Zure argitalpenekin elkarregin duten jendeak ikusi ahal izango dituzte, hala ere. indexable: Zure argitalpen publikoak bilaketa-emaitzetan ager daitezke Mastodonen. Zure argitalpenekin elkarregin duten jendeak ikusi ahal izango dituzte, hala ere.

View file

@ -228,7 +228,7 @@ tr:
title: Başlık title: Başlık
type: İçeri aktarma türü type: İçeri aktarma türü
username: Kullanıcı adı username: Kullanıcı adı
username_or_email: Kullanıcı adı ya da e-posta username_or_email: Kullanıcı adı veya e-posta
whole_word: Tam sözcük whole_word: Tam sözcük
email_domain_block: email_domain_block:
with_dns_records: Alan adının MX kayıtlarını ve IP'lerini ekleyin with_dns_records: Alan adının MX kayıtlarını ve IP'lerini ekleyin
@ -269,7 +269,7 @@ tr:
interactions: interactions:
must_be_follower: Takipçim olmayan kişilerden gelen bildirimleri engelle must_be_follower: Takipçim olmayan kişilerden gelen bildirimleri engelle
must_be_following: Takip etmediğim kişilerden gelen bildirimleri engelle must_be_following: Takip etmediğim kişilerden gelen bildirimleri engelle
must_be_following_dm: Takip etmediğiniz kişilerden gelen direkt mesajları engelle must_be_following_dm: Takip etmediğiniz kişilerden gelen doğrudan iletileri engelle
invite: invite:
comment: Yorum comment: Yorum
invite_request: invite_request:

View file

@ -1835,6 +1835,7 @@ th:
edit_profile_title: ปรับแต่งโปรไฟล์ของคุณ edit_profile_title: ปรับแต่งโปรไฟล์ของคุณ
explanation: นี่คือเคล็ดลับบางส่วนที่จะช่วยให้คุณเริ่มต้นใช้งาน explanation: นี่คือเคล็ดลับบางส่วนที่จะช่วยให้คุณเริ่มต้นใช้งาน
feature_action: เรียนรู้เพิ่มเติม feature_action: เรียนรู้เพิ่มเติม
feature_audience: Mastodon มีความพิเศษที่ให้คุณจัดการผู้รับสารของคุณได้โดยไม่มีตัวกลาง นอกจากนี้ การติดตั้ง Mastodon บนโครงสร้างพื้นฐานของคุณจะทำให้คุณสามารถติดตาม (และติดตามโดย) เซิร์ฟเวอร์ Mastodon แห่งไหนก็ได้ที่ทำงานอยู่ โดยไม่มีใครสามารถควบคุมได้นอกจากคุณ
follow_action: ติดตาม follow_action: ติดตาม
follow_step: การติดตามผู้คนที่น่าสนใจคือสิ่งที่ Mastodon ให้ความสำคัญ follow_step: การติดตามผู้คนที่น่าสนใจคือสิ่งที่ Mastodon ให้ความสำคัญ
follow_title: ปรับแต่งฟีดหน้าแรกของคุณ follow_title: ปรับแต่งฟีดหน้าแรกของคุณ

View file

@ -7,5 +7,7 @@ if Rails.env.development?
admin = Account.where(username: 'admin').first_or_initialize(username: 'admin') admin = Account.where(username: 'admin').first_or_initialize(username: 'admin')
admin.save(validate: false) admin.save(validate: false)
User.where(email: "admin@#{domain}").first_or_initialize(email: "admin@#{domain}", password: 'mastodonadmin', password_confirmation: 'mastodonadmin', confirmed_at: Time.now.utc, role: UserRole.find_by(name: 'Owner'), account: admin, agreement: true, approved: true).save! user = User.where(email: "admin@#{domain}").first_or_initialize(email: "admin@#{domain}", password: 'mastodonadmin', password_confirmation: 'mastodonadmin', confirmed_at: Time.now.utc, role: UserRole.find_by(name: 'Owner'), account: admin, agreement: true, approved: true)
user.save!
user.approve!
end end

View file

@ -1,8 +1,8 @@
# frozen_string_literal: true # frozen_string_literal: true
module PremailerWebpackStrategy module PremailerBundledAssetStrategy
def load(url) def load(url)
asset_host = ENV['CDN_HOST'] || ENV['WEB_DOMAIN'] || ENV['LOCAL_DOMAIN'] asset_host = ENV['CDN_HOST'] || ENV['WEB_DOMAIN'] || ENV.fetch('LOCAL_DOMAIN', nil)
if Webpacker.dev_server.running? if Webpacker.dev_server.running?
asset_host = "#{Webpacker.dev_server.protocol}://#{Webpacker.dev_server.host_with_port}" asset_host = "#{Webpacker.dev_server.protocol}://#{Webpacker.dev_server.host_with_port}"

View file

@ -5,9 +5,9 @@ module Webpacker::ManifestExtensions
asset = super asset = super
if pack_type[:with_integrity] && asset.respond_to?(:dig) if pack_type[:with_integrity] && asset.respond_to?(:dig)
[asset.dig('src'), asset.dig('integrity')] [asset['src'], asset['integrity']]
elsif asset.respond_to?(:dig) elsif asset.respond_to?(:dig)
asset.dig('src') asset['src']
else else
asset asset
end end

View file

@ -144,7 +144,7 @@
"devDependencies": { "devDependencies": {
"@formatjs/cli": "^6.1.1", "@formatjs/cli": "^6.1.1",
"@testing-library/jest-dom": "^6.0.0", "@testing-library/jest-dom": "^6.0.0",
"@testing-library/react": "^14.0.0", "@testing-library/react": "^15.0.0",
"@types/babel__core": "^7.20.1", "@types/babel__core": "^7.20.1",
"@types/emoji-mart": "^3.0.9", "@types/emoji-mart": "^3.0.9",
"@types/escape-html": "^1.0.2", "@types/escape-html": "^1.0.2",

View file

@ -1,7 +1,10 @@
module.exports = ({ env }) => ({ /** @type {import('postcss-load-config').Config} */
const config = ({ env }) => ({
plugins: [ plugins: [
'postcss-preset-env', require('postcss-preset-env'),
'autoprefixer', require('autoprefixer'),
env === 'production' ? 'cssnano' : '', env === 'production' ? require('cssnano') : '',
], ],
}); });
module.exports = config;

View file

@ -3,16 +3,32 @@
require 'rails_helper' require 'rails_helper'
describe Admin::Metrics::Dimension::InstanceAccountsDimension do describe Admin::Metrics::Dimension::InstanceAccountsDimension do
subject(:dimension) { described_class.new(start_at, end_at, limit, params) } subject { described_class.new(start_at, end_at, limit, params) }
let(:start_at) { 2.days.ago } let(:start_at) { 2.days.ago }
let(:end_at) { Time.now.utc } let(:end_at) { Time.now.utc }
let(:limit) { 10 } let(:limit) { 10 }
let(:params) { ActionController::Parameters.new } let(:params) { ActionController::Parameters.new(domain: domain) }
describe '#data' do describe '#data' do
it 'runs data query without error' do let(:domain) { 'host.example' }
expect { dimension.data }.to_not raise_error let(:alice) { Fabricate(:account, domain: domain) }
let(:bob) { Fabricate(:account) }
before do
Fabricate :follow, target_account: alice
Fabricate :follow, target_account: bob
Fabricate :status, account: alice
Fabricate :status, account: bob
end
it 'returns instances with follow counts' do
expect(subject.data.size)
.to eq(1)
expect(subject.data.map(&:symbolize_keys))
.to contain_exactly(
include(key: alice.username, value: '1')
)
end end
end end
end end

View file

@ -3,16 +3,30 @@
require 'rails_helper' require 'rails_helper'
describe Admin::Metrics::Dimension::InstanceLanguagesDimension do describe Admin::Metrics::Dimension::InstanceLanguagesDimension do
subject(:dimension) { described_class.new(start_at, end_at, limit, params) } subject { described_class.new(start_at, end_at, limit, params) }
let(:start_at) { 2.days.ago } let(:start_at) { 2.days.ago }
let(:end_at) { Time.now.utc } let(:end_at) { Time.now.utc }
let(:limit) { 10 } let(:limit) { 10 }
let(:params) { ActionController::Parameters.new } let(:params) { ActionController::Parameters.new(domain: domain) }
describe '#data' do describe '#data' do
it 'runs data query without error' do let(:domain) { 'host.example' }
expect { dimension.data }.to_not raise_error let(:alice) { Fabricate(:account, domain: domain) }
let(:bob) { Fabricate(:account) }
before do
Fabricate :status, account: alice, language: 'en'
Fabricate :status, account: bob, language: 'es'
end
it 'returns locales with status counts' do
expect(subject.data.size)
.to eq(1)
expect(subject.data.map(&:symbolize_keys))
.to contain_exactly(
include(key: 'en', value: '1')
)
end end
end end
end end

View file

@ -3,7 +3,7 @@
require 'rails_helper' require 'rails_helper'
describe Admin::Metrics::Dimension::ServersDimension do describe Admin::Metrics::Dimension::ServersDimension do
subject(:dimension) { described_class.new(start_at, end_at, limit, params) } subject { described_class.new(start_at, end_at, limit, params) }
let(:start_at) { 2.days.ago } let(:start_at) { 2.days.ago }
let(:end_at) { Time.now.utc } let(:end_at) { Time.now.utc }
@ -11,8 +11,24 @@ describe Admin::Metrics::Dimension::ServersDimension do
let(:params) { ActionController::Parameters.new } let(:params) { ActionController::Parameters.new }
describe '#data' do describe '#data' do
it 'runs data query without error' do let(:domain) { 'host.example' }
expect { dimension.data }.to_not raise_error let(:alice) { Fabricate(:account, domain: domain) }
let(:bob) { Fabricate(:account) }
before do
Fabricate :status, account: alice, created_at: 1.day.ago
Fabricate :status, account: alice, created_at: 30.days.ago
Fabricate :status, account: bob, created_at: 1.day.ago
end
it 'returns domains with status counts' do
expect(subject.data.size)
.to eq(2)
expect(subject.data.map(&:symbolize_keys))
.to contain_exactly(
include(key: domain, value: '1'),
include(key: Rails.configuration.x.local_domain, value: '1')
)
end end
end end
end end

View file

@ -3,7 +3,7 @@
require 'rails_helper' require 'rails_helper'
describe Admin::Metrics::Dimension::SoftwareVersionsDimension do describe Admin::Metrics::Dimension::SoftwareVersionsDimension do
subject(:dimension) { described_class.new(start_at, end_at, limit, params) } subject { described_class.new(start_at, end_at, limit, params) }
let(:start_at) { 2.days.ago } let(:start_at) { 2.days.ago }
let(:end_at) { Time.now.utc } let(:end_at) { Time.now.utc }
@ -11,8 +11,12 @@ describe Admin::Metrics::Dimension::SoftwareVersionsDimension do
let(:params) { ActionController::Parameters.new } let(:params) { ActionController::Parameters.new }
describe '#data' do describe '#data' do
it 'runs data query without error' do it 'reports on the running software' do
expect { dimension.data }.to_not raise_error expect(subject.data.map(&:symbolize_keys))
.to include(
include(key: 'mastodon', value: Mastodon::Version.to_s),
include(key: 'ruby', value: include(RUBY_VERSION))
)
end end
end end
end end

View file

@ -3,7 +3,7 @@
require 'rails_helper' require 'rails_helper'
describe Admin::Metrics::Dimension::SourcesDimension do describe Admin::Metrics::Dimension::SourcesDimension do
subject(:dimension) { described_class.new(start_at, end_at, limit, params) } subject { described_class.new(start_at, end_at, limit, params) }
let(:start_at) { 2.days.ago } let(:start_at) { 2.days.ago }
let(:end_at) { Time.now.utc } let(:end_at) { Time.now.utc }
@ -11,8 +11,21 @@ describe Admin::Metrics::Dimension::SourcesDimension do
let(:params) { ActionController::Parameters.new } let(:params) { ActionController::Parameters.new }
describe '#data' do describe '#data' do
it 'runs data query without error' do let(:app) { Fabricate(:application) }
expect { dimension.data }.to_not raise_error let(:alice) { Fabricate(:user) }
let(:bob) { Fabricate(:user) }
before do
alice.update(created_by_application: app)
end
it 'returns OAuth applications with user counts' do
expect(subject.data.size)
.to eq(1)
expect(subject.data.map(&:symbolize_keys))
.to contain_exactly(
include(key: app.name, value: '1')
)
end end
end end
end end

View file

@ -3,7 +3,7 @@
require 'rails_helper' require 'rails_helper'
describe Admin::Metrics::Dimension::SpaceUsageDimension do describe Admin::Metrics::Dimension::SpaceUsageDimension do
subject(:dimension) { described_class.new(start_at, end_at, limit, params) } subject { described_class.new(start_at, end_at, limit, params) }
let(:start_at) { 2.days.ago } let(:start_at) { 2.days.ago }
let(:end_at) { Time.now.utc } let(:end_at) { Time.now.utc }
@ -11,8 +11,13 @@ describe Admin::Metrics::Dimension::SpaceUsageDimension do
let(:params) { ActionController::Parameters.new } let(:params) { ActionController::Parameters.new }
describe '#data' do describe '#data' do
it 'runs data query without error' do it 'reports on used storage space' do
expect { dimension.data }.to_not raise_error expect(subject.data.map(&:symbolize_keys))
.to include(
include(key: 'media', value: /\d/),
include(key: 'postgresql', value: /\d/),
include(key: 'redis', value: /\d/)
)
end end
end end
end end

View file

@ -3,16 +3,36 @@
require 'rails_helper' require 'rails_helper'
describe Admin::Metrics::Dimension::TagLanguagesDimension do describe Admin::Metrics::Dimension::TagLanguagesDimension do
subject(:dimension) { described_class.new(start_at, end_at, limit, params) } subject { described_class.new(start_at, end_at, limit, params) }
let(:start_at) { 2.days.ago } let(:start_at) { 2.days.ago }
let(:end_at) { Time.now.utc } let(:end_at) { Time.now.utc }
let(:limit) { 10 } let(:limit) { 10 }
let(:params) { ActionController::Parameters.new } let(:params) { ActionController::Parameters.new(id: tag.id) }
describe '#data' do describe '#data' do
it 'runs data query without error' do let(:alice) { Fabricate(:account) }
expect { dimension.data }.to_not raise_error let(:bob) { Fabricate(:account) }
let(:tag) { Fabricate(:tag) }
before do
alice_status_recent = Fabricate :status, account: alice, created_at: 1.day.ago, language: 'en'
alice_status_older = Fabricate :status, account: alice, created_at: 30.days.ago, language: 'en'
bob_status_recent = Fabricate :status, account: bob, created_at: 1.day.ago, language: 'es'
alice_status_older.tags << tag
alice_status_recent.tags << tag
bob_status_recent.tags << tag
end
it 'returns languages with tag usage counts' do
expect(subject.data.size)
.to eq(2)
expect(subject.data.map(&:symbolize_keys))
.to contain_exactly(
include(key: 'en', value: '1'),
include(key: 'es', value: '1')
)
end end
end end
end end

View file

@ -3,16 +3,37 @@
require 'rails_helper' require 'rails_helper'
describe Admin::Metrics::Dimension::TagServersDimension do describe Admin::Metrics::Dimension::TagServersDimension do
subject(:dimension) { described_class.new(start_at, end_at, limit, params) } subject { described_class.new(start_at, end_at, limit, params) }
let(:start_at) { 2.days.ago } let(:start_at) { 2.days.ago }
let(:end_at) { Time.now.utc } let(:end_at) { Time.now.utc }
let(:limit) { 10 } let(:limit) { 10 }
let(:params) { ActionController::Parameters.new } let(:params) { ActionController::Parameters.new(id: tag.id) }
describe '#data' do describe '#data' do
it 'runs data query without error' do let(:alice) { Fabricate(:account, domain: domain) }
expect { dimension.data }.to_not raise_error let(:bob) { Fabricate(:account) }
let(:domain) { 'host.example' }
let(:tag) { Fabricate(:tag) }
before do
alice_status_recent = Fabricate :status, account: alice, created_at: 1.day.ago
alice_status_older = Fabricate :status, account: alice, created_at: 30.days.ago
bob_status_recent = Fabricate :status, account: bob, created_at: 1.day.ago
alice_status_older.tags << tag
alice_status_recent.tags << tag
bob_status_recent.tags << tag
end
it 'returns servers with tag usage counts' do
expect(subject.data.size)
.to eq(2)
expect(subject.data.map(&:symbolize_keys))
.to contain_exactly(
include(key: domain, value: '1'),
include(key: Rails.configuration.x.local_domain, value: '1')
)
end end
end end
end end

View file

@ -3,15 +3,38 @@
require 'rails_helper' require 'rails_helper'
describe Admin::Metrics::Measure::ActiveUsersMeasure do describe Admin::Metrics::Measure::ActiveUsersMeasure do
subject(:measure) { described_class.new(start_at, end_at, params) } subject { described_class.new(start_at, end_at, params) }
let(:start_at) { 2.days.ago } let(:start_at) { 2.days.ago }
let(:end_at) { Time.now.utc } let(:end_at) { Time.now.utc }
let(:params) { ActionController::Parameters.new } let(:params) { ActionController::Parameters.new }
describe '#data' do describe '#data' do
it 'runs data query without error' do context 'with activity tracking records' do
expect { measure.data }.to_not raise_error before do
3.times do
travel_to(2.days.ago) { record_login_activity }
end
2.times do
travel_to(1.day.ago) { record_login_activity }
end
travel_to(0.days.ago) { record_login_activity }
end
it 'returns correct activity tracker counts' do
expect(subject.data.size)
.to eq(3)
expect(subject.data.map(&:symbolize_keys))
.to contain_exactly(
include(date: 2.days.ago.midnight.to_time, value: '3'),
include(date: 1.day.ago.midnight.to_time, value: '2'),
include(date: 0.days.ago.midnight.to_time, value: '1')
)
end
def record_login_activity
ActivityTracker.record('activity:logins', Fabricate(:user).id)
end
end end
end end
end end

View file

@ -3,7 +3,7 @@
require 'rails_helper' require 'rails_helper'
describe Admin::Metrics::Measure::InstanceAccountsMeasure do describe Admin::Metrics::Measure::InstanceAccountsMeasure do
subject(:measure) { described_class.new(start_at, end_at, params) } subject { described_class.new(start_at, end_at, params) }
let(:domain) { 'example.com' } let(:domain) { 'example.com' }
@ -20,12 +20,13 @@ describe Admin::Metrics::Measure::InstanceAccountsMeasure do
Fabricate(:account, domain: "foo.#{domain}", created_at: 1.year.ago) Fabricate(:account, domain: "foo.#{domain}", created_at: 1.year.ago)
Fabricate(:account, domain: "foo.#{domain}") Fabricate(:account, domain: "foo.#{domain}")
Fabricate(:account, domain: "bar.#{domain}") Fabricate(:account, domain: "bar.#{domain}")
Fabricate(:account, domain: 'other-host.example')
end end
describe 'total' do describe '#total' do
context 'without include_subdomains' do context 'without include_subdomains' do
it 'returns the expected number of accounts' do it 'returns the expected number of accounts' do
expect(measure.total).to eq 3 expect(subject.total).to eq 3
end end
end end
@ -33,14 +34,21 @@ describe Admin::Metrics::Measure::InstanceAccountsMeasure do
let(:params) { ActionController::Parameters.new(domain: domain, include_subdomains: 'true') } let(:params) { ActionController::Parameters.new(domain: domain, include_subdomains: 'true') }
it 'returns the expected number of accounts' do it 'returns the expected number of accounts' do
expect(measure.total).to eq 6 expect(subject.total).to eq 6
end end
end end
end end
describe '#data' do describe '#data' do
it 'runs data query without error' do it 'returns correct instance_accounts counts' do
expect { measure.data }.to_not raise_error expect(subject.data.size)
.to eq(3)
expect(subject.data.map(&:symbolize_keys))
.to contain_exactly(
include(date: 2.days.ago.midnight.to_time, value: '0'),
include(date: 1.day.ago.midnight.to_time, value: '0'),
include(date: 0.days.ago.midnight.to_time, value: '1')
)
end end
end end
end end

View file

@ -3,7 +3,7 @@
require 'rails_helper' require 'rails_helper'
describe Admin::Metrics::Measure::InstanceFollowersMeasure do describe Admin::Metrics::Measure::InstanceFollowersMeasure do
subject(:measure) { described_class.new(start_at, end_at, params) } subject { described_class.new(start_at, end_at, params) }
let(:domain) { 'example.com' } let(:domain) { 'example.com' }
@ -22,12 +22,14 @@ describe Admin::Metrics::Measure::InstanceFollowersMeasure do
Fabricate(:account, domain: "foo.#{domain}").follow!(local_account) Fabricate(:account, domain: "foo.#{domain}").follow!(local_account)
Fabricate(:account, domain: "foo.#{domain}").follow!(local_account) Fabricate(:account, domain: "foo.#{domain}").follow!(local_account)
Fabricate(:account, domain: "bar.#{domain}") Fabricate(:account, domain: "bar.#{domain}")
Fabricate(:account, domain: 'other.example').follow!(local_account)
end end
describe 'total' do describe '#total' do
context 'without include_subdomains' do context 'without include_subdomains' do
it 'returns the expected number of accounts' do it 'returns the expected number of accounts' do
expect(measure.total).to eq 2 expect(subject.total).to eq 2
end end
end end
@ -35,14 +37,21 @@ describe Admin::Metrics::Measure::InstanceFollowersMeasure do
let(:params) { ActionController::Parameters.new(domain: domain, include_subdomains: 'true') } let(:params) { ActionController::Parameters.new(domain: domain, include_subdomains: 'true') }
it 'returns the expected number of accounts' do it 'returns the expected number of accounts' do
expect(measure.total).to eq 4 expect(subject.total).to eq 4
end end
end end
end end
describe '#data' do describe '#data' do
it 'runs data query without error' do it 'returns correct instance_followers counts' do
expect { measure.data }.to_not raise_error expect(subject.data.size)
.to eq(3)
expect(subject.data.map(&:symbolize_keys))
.to contain_exactly(
include(date: 2.days.ago.midnight.to_time, value: '0'),
include(date: 1.day.ago.midnight.to_time, value: '0'),
include(date: 0.days.ago.midnight.to_time, value: '2')
)
end end
end end
end end

View file

@ -3,7 +3,7 @@
require 'rails_helper' require 'rails_helper'
describe Admin::Metrics::Measure::InstanceFollowsMeasure do describe Admin::Metrics::Measure::InstanceFollowsMeasure do
subject(:measure) { described_class.new(start_at, end_at, params) } subject { described_class.new(start_at, end_at, params) }
let(:domain) { 'example.com' } let(:domain) { 'example.com' }
@ -24,10 +24,10 @@ describe Admin::Metrics::Measure::InstanceFollowsMeasure do
Fabricate(:account, domain: "bar.#{domain}") Fabricate(:account, domain: "bar.#{domain}")
end end
describe 'total' do describe '#total' do
context 'without include_subdomains' do context 'without include_subdomains' do
it 'returns the expected number of accounts' do it 'returns the expected number of accounts' do
expect(measure.total).to eq 2 expect(subject.total).to eq 2
end end
end end
@ -35,14 +35,21 @@ describe Admin::Metrics::Measure::InstanceFollowsMeasure do
let(:params) { ActionController::Parameters.new(domain: domain, include_subdomains: 'true') } let(:params) { ActionController::Parameters.new(domain: domain, include_subdomains: 'true') }
it 'returns the expected number of accounts' do it 'returns the expected number of accounts' do
expect(measure.total).to eq 4 expect(subject.total).to eq 4
end end
end end
end end
describe '#data' do describe '#data' do
it 'runs data query without error' do it 'returns correct instance_followers counts' do
expect { measure.data }.to_not raise_error expect(subject.data.size)
.to eq(3)
expect(subject.data.map(&:symbolize_keys))
.to contain_exactly(
include(date: 2.days.ago.midnight.to_time, value: '0'),
include(date: 1.day.ago.midnight.to_time, value: '0'),
include(date: 0.days.ago.midnight.to_time, value: '2')
)
end end
end end
end end

View file

@ -3,7 +3,7 @@
require 'rails_helper' require 'rails_helper'
describe Admin::Metrics::Measure::InstanceMediaAttachmentsMeasure do describe Admin::Metrics::Measure::InstanceMediaAttachmentsMeasure do
subject(:measure) { described_class.new(start_at, end_at, params) } subject { described_class.new(start_at, end_at, params) }
let(:domain) { 'example.com' } let(:domain) { 'example.com' }
@ -20,11 +20,11 @@ describe Admin::Metrics::Measure::InstanceMediaAttachmentsMeasure do
remote_account_on_subdomain.media_attachments.create!(file: attachment_fixture('attachment.jpg')) remote_account_on_subdomain.media_attachments.create!(file: attachment_fixture('attachment.jpg'))
end end
describe 'total' do describe '#total' do
context 'without include_subdomains' do context 'without include_subdomains' do
it 'returns the expected number of accounts' do it 'returns the expected number of accounts' do
expected_total = remote_account.media_attachments.sum(:file_file_size) + remote_account.media_attachments.sum(:thumbnail_file_size) expected_total = remote_account.media_attachments.sum(:file_file_size) + remote_account.media_attachments.sum(:thumbnail_file_size)
expect(measure.total).to eq expected_total expect(subject.total).to eq expected_total
end end
end end
@ -36,14 +36,25 @@ describe Admin::Metrics::Measure::InstanceMediaAttachmentsMeasure do
account.media_attachments.sum(:file_file_size) + account.media_attachments.sum(:thumbnail_file_size) account.media_attachments.sum(:file_file_size) + account.media_attachments.sum(:thumbnail_file_size)
end end
expect(measure.total).to eq expected_total expect(subject.total).to eq expected_total
end end
end end
end end
describe '#data' do describe '#data' do
it 'runs data query without error' do it 'returns correct media_attachments counts' do
expect { measure.data }.to_not raise_error expect(subject.data.size)
.to eq(3)
expect(subject.data.map(&:symbolize_keys))
.to contain_exactly(
include(date: 2.days.ago.midnight.to_time, value: '0'),
include(date: 1.day.ago.midnight.to_time, value: '0'),
include(date: 0.days.ago.midnight.to_time, value: expected_domain_only_total.to_s)
)
end
def expected_domain_only_total
remote_account.media_attachments.sum(:file_file_size) + remote_account.media_attachments.sum(:thumbnail_file_size)
end end
end end
end end

View file

@ -3,7 +3,7 @@
require 'rails_helper' require 'rails_helper'
describe Admin::Metrics::Measure::InstanceReportsMeasure do describe Admin::Metrics::Measure::InstanceReportsMeasure do
subject(:measure) { described_class.new(start_at, end_at, params) } subject { described_class.new(start_at, end_at, params) }
let(:domain) { 'example.com' } let(:domain) { 'example.com' }
@ -21,10 +21,10 @@ describe Admin::Metrics::Measure::InstanceReportsMeasure do
Fabricate(:report, target_account: Fabricate(:account, domain: "bar.#{domain}")) Fabricate(:report, target_account: Fabricate(:account, domain: "bar.#{domain}"))
end end
describe 'total' do describe '#total' do
context 'without include_subdomains' do context 'without include_subdomains' do
it 'returns the expected number of accounts' do it 'returns the expected number of accounts' do
expect(measure.total).to eq 2 expect(subject.total).to eq 2
end end
end end
@ -32,14 +32,21 @@ describe Admin::Metrics::Measure::InstanceReportsMeasure do
let(:params) { ActionController::Parameters.new(domain: domain, include_subdomains: 'true') } let(:params) { ActionController::Parameters.new(domain: domain, include_subdomains: 'true') }
it 'returns the expected number of accounts' do it 'returns the expected number of accounts' do
expect(measure.total).to eq 5 expect(subject.total).to eq 5
end end
end end
end end
describe '#data' do describe '#data' do
it 'runs data query without error' do it 'returns correct instance_reports counts' do
expect { measure.data }.to_not raise_error expect(subject.data.size)
.to eq(3)
expect(subject.data.map(&:symbolize_keys))
.to contain_exactly(
include(date: 2.days.ago.midnight.to_time, value: '0'),
include(date: 1.day.ago.midnight.to_time, value: '0'),
include(date: 0.days.ago.midnight.to_time, value: '2')
)
end end
end end
end end

View file

@ -3,7 +3,7 @@
require 'rails_helper' require 'rails_helper'
describe Admin::Metrics::Measure::InstanceStatusesMeasure do describe Admin::Metrics::Measure::InstanceStatusesMeasure do
subject(:measure) { described_class.new(start_at, end_at, params) } subject { described_class.new(start_at, end_at, params) }
let(:domain) { 'example.com' } let(:domain) { 'example.com' }
@ -21,10 +21,10 @@ describe Admin::Metrics::Measure::InstanceStatusesMeasure do
Fabricate(:status, account: Fabricate(:account, domain: "bar.#{domain}")) Fabricate(:status, account: Fabricate(:account, domain: "bar.#{domain}"))
end end
describe 'total' do describe '#total' do
context 'without include_subdomains' do context 'without include_subdomains' do
it 'returns the expected number of accounts' do it 'returns the expected number of accounts' do
expect(measure.total).to eq 2 expect(subject.total).to eq 2
end end
end end
@ -32,14 +32,21 @@ describe Admin::Metrics::Measure::InstanceStatusesMeasure do
let(:params) { ActionController::Parameters.new(domain: domain, include_subdomains: 'true') } let(:params) { ActionController::Parameters.new(domain: domain, include_subdomains: 'true') }
it 'returns the expected number of accounts' do it 'returns the expected number of accounts' do
expect(measure.total).to eq 5 expect(subject.total).to eq 5
end end
end end
end end
describe '#data' do describe '#data' do
it 'runs data query without error' do it 'returns correct instance_statuses counts' do
expect { measure.data }.to_not raise_error expect(subject.data.size)
.to eq(3)
expect(subject.data.map(&:symbolize_keys))
.to contain_exactly(
include(date: 2.days.ago.midnight.to_time, value: '0'),
include(date: 1.day.ago.midnight.to_time, value: '0'),
include(date: 0.days.ago.midnight.to_time, value: '2')
)
end end
end end
end end

View file

@ -3,15 +3,38 @@
require 'rails_helper' require 'rails_helper'
describe Admin::Metrics::Measure::InteractionsMeasure do describe Admin::Metrics::Measure::InteractionsMeasure do
subject(:measure) { described_class.new(start_at, end_at, params) } subject { described_class.new(start_at, end_at, params) }
let(:start_at) { 2.days.ago } let(:start_at) { 2.days.ago }
let(:end_at) { Time.now.utc } let(:end_at) { Time.now.utc }
let(:params) { ActionController::Parameters.new } let(:params) { ActionController::Parameters.new }
describe '#data' do describe '#data' do
it 'runs data query without error' do context 'with activity tracking records' do
expect { measure.data }.to_not raise_error before do
3.times do
travel_to(2.days.ago) { record_interaction_activity }
end
2.times do
travel_to(1.day.ago) { record_interaction_activity }
end
travel_to(0.days.ago) { record_interaction_activity }
end
it 'returns correct activity tracker counts' do
expect(subject.data.size)
.to eq(3)
expect(subject.data.map(&:symbolize_keys))
.to contain_exactly(
include(date: 2.days.ago.midnight.to_time, value: '3'),
include(date: 1.day.ago.midnight.to_time, value: '2'),
include(date: 0.days.ago.midnight.to_time, value: '1')
)
end
def record_interaction_activity
ActivityTracker.increment('activity:interactions')
end
end end
end end
end end

View file

@ -3,15 +3,30 @@
require 'rails_helper' require 'rails_helper'
describe Admin::Metrics::Measure::NewUsersMeasure do describe Admin::Metrics::Measure::NewUsersMeasure do
subject(:measure) { described_class.new(start_at, end_at, params) } subject { described_class.new(start_at, end_at, params) }
let(:start_at) { 2.days.ago } let(:start_at) { 2.days.ago }
let(:end_at) { Time.now.utc } let(:end_at) { Time.now.utc }
let(:params) { ActionController::Parameters.new } let(:params) { ActionController::Parameters.new }
describe '#data' do describe '#data' do
it 'runs data query without error' do context 'with user records' do
expect { measure.data }.to_not raise_error before do
3.times { Fabricate :user, created_at: 2.days.ago }
2.times { Fabricate :user, created_at: 1.day.ago }
Fabricate :user, created_at: 0.days.ago
end
it 'returns correct user counts' do
expect(subject.data.size)
.to eq(3)
expect(subject.data.map(&:symbolize_keys))
.to contain_exactly(
include(date: 2.days.ago.midnight.to_time, value: '3'),
include(date: 1.day.ago.midnight.to_time, value: '2'),
include(date: 0.days.ago.midnight.to_time, value: '1')
)
end
end end
end end
end end

View file

@ -3,15 +3,30 @@
require 'rails_helper' require 'rails_helper'
describe Admin::Metrics::Measure::OpenedReportsMeasure do describe Admin::Metrics::Measure::OpenedReportsMeasure do
subject(:measure) { described_class.new(start_at, end_at, params) } subject { described_class.new(start_at, end_at, params) }
let(:start_at) { 2.days.ago } let(:start_at) { 2.days.ago }
let(:end_at) { Time.now.utc } let(:end_at) { Time.now.utc }
let(:params) { ActionController::Parameters.new } let(:params) { ActionController::Parameters.new }
describe '#data' do describe '#data' do
it 'runs data query without error' do context 'with report records' do
expect { measure.data }.to_not raise_error before do
3.times { Fabricate :report, created_at: 2.days.ago }
2.times { Fabricate :report, created_at: 1.day.ago }
Fabricate :report, created_at: 0.days.ago
end
it 'returns correct report counts' do
expect(subject.data.size)
.to eq(3)
expect(subject.data.map(&:symbolize_keys))
.to contain_exactly(
include(date: 2.days.ago.midnight.to_time, value: '3'),
include(date: 1.day.ago.midnight.to_time, value: '2'),
include(date: 0.days.ago.midnight.to_time, value: '1')
)
end
end end
end end
end end

View file

@ -3,15 +3,30 @@
require 'rails_helper' require 'rails_helper'
describe Admin::Metrics::Measure::ResolvedReportsMeasure do describe Admin::Metrics::Measure::ResolvedReportsMeasure do
subject(:measure) { described_class.new(start_at, end_at, params) } subject { described_class.new(start_at, end_at, params) }
let(:start_at) { 2.days.ago } let(:start_at) { 2.days.ago }
let(:end_at) { Time.now.utc } let(:end_at) { Time.now.utc }
let(:params) { ActionController::Parameters.new } let(:params) { ActionController::Parameters.new }
describe '#data' do describe '#data' do
it 'runs data query without error' do context 'with report records' do
expect { measure.data }.to_not raise_error before do
3.times { Fabricate :report, action_taken_at: 2.days.ago }
2.times { Fabricate :report, action_taken_at: 1.day.ago }
Fabricate :report, action_taken_at: 0.days.ago
end
it 'returns correct report counts' do
expect(subject.data.size)
.to eq(3)
expect(subject.data.map(&:symbolize_keys))
.to contain_exactly(
include(date: 2.days.ago.midnight.to_time, value: '3'),
include(date: 1.day.ago.midnight.to_time, value: '2'),
include(date: 0.days.ago.midnight.to_time, value: '1')
)
end
end end
end end
end end

View file

@ -3,7 +3,7 @@
require 'rails_helper' require 'rails_helper'
describe Admin::Metrics::Measure::TagAccountsMeasure do describe Admin::Metrics::Measure::TagAccountsMeasure do
subject(:measure) { described_class.new(start_at, end_at, params) } subject { described_class.new(start_at, end_at, params) }
let!(:tag) { Fabricate(:tag) } let!(:tag) { Fabricate(:tag) }
@ -12,8 +12,39 @@ describe Admin::Metrics::Measure::TagAccountsMeasure do
let(:params) { ActionController::Parameters.new(id: tag.id) } let(:params) { ActionController::Parameters.new(id: tag.id) }
describe '#data' do describe '#data' do
it 'runs data query without error' do context 'with tagged accounts' do
expect { measure.data }.to_not raise_error let(:alice) { Fabricate(:account, domain: 'alice.example') }
let(:bob) { Fabricate(:account, domain: 'bob.example') }
before do
3.times do
travel_to(2.days.ago) { add_tag_history(alice) }
end
2.times do
travel_to(1.day.ago) do
add_tag_history(alice)
add_tag_history(bob)
end
end
add_tag_history(bob)
end
it 'returns correct tag_accounts counts' do
expect(subject.data.size)
.to eq(3)
expect(subject.data.map(&:symbolize_keys))
.to contain_exactly(
include(date: 2.days.ago.midnight.to_time, value: '1'),
include(date: 1.day.ago.midnight.to_time, value: '2'),
include(date: 0.days.ago.midnight.to_time, value: '1')
)
end
def add_tag_history(account)
tag.history.add(account.id)
end
end end
end end
end end

View file

@ -3,7 +3,7 @@
require 'rails_helper' require 'rails_helper'
describe Admin::Metrics::Measure::TagServersMeasure do describe Admin::Metrics::Measure::TagServersMeasure do
subject(:measure) { described_class.new(start_at, end_at, params) } subject { described_class.new(start_at, end_at, params) }
let!(:tag) { Fabricate(:tag) } let!(:tag) { Fabricate(:tag) }
@ -12,8 +12,38 @@ describe Admin::Metrics::Measure::TagServersMeasure do
let(:params) { ActionController::Parameters.new(id: tag.id) } let(:params) { ActionController::Parameters.new(id: tag.id) }
describe '#data' do describe '#data' do
it 'runs data query without error' do context 'with tagged statuses' do
expect { measure.data }.to_not raise_error let(:alice) { Fabricate(:account, domain: 'alice.example') }
let(:bob) { Fabricate(:account, domain: 'bob.example') }
before do
3.times do
status_alice = Fabricate(:status, account: alice, created_at: 2.days.ago)
status_alice.tags << tag
end
2.times do
status_alice = Fabricate(:status, account: alice, created_at: 1.day.ago)
status_alice.tags << tag
status_bob = Fabricate(:status, account: bob, created_at: 1.day.ago)
status_bob.tags << tag
end
status_bob = Fabricate(:status, account: bob, created_at: 0.days.ago)
status_bob.tags << tag
end
it 'returns correct tag counts' do
expect(subject.data.size)
.to eq(3)
expect(subject.data.map(&:symbolize_keys))
.to contain_exactly(
include(date: 2.days.ago.midnight.to_time, value: '1'),
include(date: 1.day.ago.midnight.to_time, value: '2'),
include(date: 0.days.ago.midnight.to_time, value: '1')
)
end
end end
end end
end end

View file

@ -3,7 +3,7 @@
require 'rails_helper' require 'rails_helper'
describe Admin::Metrics::Measure::TagUsesMeasure do describe Admin::Metrics::Measure::TagUsesMeasure do
subject(:measure) { described_class.new(start_at, end_at, params) } subject { described_class.new(start_at, end_at, params) }
let!(:tag) { Fabricate(:tag) } let!(:tag) { Fabricate(:tag) }
@ -12,8 +12,39 @@ describe Admin::Metrics::Measure::TagUsesMeasure do
let(:params) { ActionController::Parameters.new(id: tag.id) } let(:params) { ActionController::Parameters.new(id: tag.id) }
describe '#data' do describe '#data' do
it 'runs data query without error' do context 'with tagged accounts' do
expect { measure.data }.to_not raise_error let(:alice) { Fabricate(:account, domain: 'alice.example') }
let(:bob) { Fabricate(:account, domain: 'bob.example') }
before do
3.times do
travel_to(2.days.ago) { add_tag_history(alice) }
end
2.times do
travel_to(1.day.ago) do
add_tag_history(alice)
add_tag_history(bob)
end
end
add_tag_history(bob)
end
it 'returns correct tag_uses counts' do
expect(subject.data.size)
.to eq(3)
expect(subject.data.map(&:symbolize_keys))
.to contain_exactly(
include(date: 2.days.ago.midnight.to_time, value: '3'),
include(date: 1.day.ago.midnight.to_time, value: '4'),
include(date: 0.days.ago.midnight.to_time, value: '1')
)
end
def add_tag_history(account)
tag.history.add(account.id)
end
end end
end end
end end

View file

@ -9,12 +9,18 @@ describe 'The account show page' do
get '/@alice' get '/@alice'
expect(head_link_icons.size).to eq(4) # One general favicon and three with sizes
expect(head_meta_content('og:title')).to match alice.display_name expect(head_meta_content('og:title')).to match alice.display_name
expect(head_meta_content('og:type')).to eq 'profile' expect(head_meta_content('og:type')).to eq 'profile'
expect(head_meta_content('og:image')).to match '.+' expect(head_meta_content('og:image')).to match '.+'
expect(head_meta_content('og:url')).to match 'http://.+' expect(head_meta_content('og:url')).to match 'http://.+'
end end
def head_link_icons
head_section.css('link[rel=icon]')
end
def head_meta_content(property) def head_meta_content(property)
head_section.meta("[@property='#{property}']")[:content] head_section.meta("[@property='#{property}']")[:content]
end end

View file

@ -3,46 +3,41 @@
require 'rails_helper' require 'rails_helper'
describe 'statuses/show.html.haml', :without_verify_partial_doubles do describe 'statuses/show.html.haml', :without_verify_partial_doubles do
let(:alice) { Fabricate(:account, username: 'alice', display_name: 'Alice') }
let(:status) { Fabricate(:status, account: alice, text: 'Hello World') }
before do before do
allow(view).to receive_messages(api_oembed_url: '', site_title: 'example site', site_hostname: 'example.com', full_asset_url: '//asset.host/image.svg', current_account: nil, single_user_mode?: false) allow(view).to receive_messages(api_oembed_url: '', site_title: 'example site', site_hostname: 'example.com', full_asset_url: '//asset.host/image.svg', current_account: nil, single_user_mode?: false)
allow(view).to receive(:local_time) allow(view).to receive(:local_time)
allow(view).to receive(:local_time_ago) allow(view).to receive(:local_time_ago)
assign(:instance_presenter, InstancePresenter.new) assign(:instance_presenter, InstancePresenter.new)
Fabricate(:media_attachment, account: alice, status: status, type: :video)
assign(:status, status)
assign(:account, alice)
assign(:descendant_threads, [])
end end
it 'has valid opengraph tags' do it 'has valid opengraph tags' do
alice = Fabricate(:account, username: 'alice', display_name: 'Alice')
status = Fabricate(:status, account: alice, text: 'Hello World')
Fabricate(:media_attachment, account: alice, status: status, type: :video)
assign(:status, status)
assign(:account, alice)
assign(:descendant_threads, [])
render render
header_tags = view.content_for(:header_tags) expect(header_tags)
.to match(/<meta content=".+" property="og:title">/)
expect(header_tags).to match(/<meta content=".+" property="og:title">/) .and match(/<meta content="article" property="og:type">/)
expect(header_tags).to match(/<meta content="article" property="og:type">/) .and match(/<meta content=".+" property="og:image">/)
expect(header_tags).to match(/<meta content=".+" property="og:image">/) .and match(%r{<meta content="http://.+" property="og:url">})
expect(header_tags).to match(%r{<meta content="http://.+" property="og:url">})
end end
it 'has twitter player tag' do it 'has twitter player tag' do
alice = Fabricate(:account, username: 'alice', display_name: 'Alice')
status = Fabricate(:status, account: alice, text: 'Hello World')
Fabricate(:media_attachment, account: alice, status: status, type: :video)
assign(:status, status)
assign(:account, alice)
assign(:descendant_threads, [])
render render
header_tags = view.content_for(:header_tags) expect(header_tags)
.to match(%r{<meta content="http://.+/media/.+/player" property="twitter:player">})
.and match(/<meta content="player" property="twitter:card">/)
end
expect(header_tags).to match(%r{<meta content="http://.+/media/.+/player" property="twitter:player">}) def header_tags
expect(header_tags).to match(/<meta content="player" property="twitter:card">/) view.content_for(:header_tags)
end end
end end

172
yarn.lock
View file

@ -2757,7 +2757,7 @@ __metadata:
"@reduxjs/toolkit": "npm:^2.0.1" "@reduxjs/toolkit": "npm:^2.0.1"
"@svgr/webpack": "npm:^5.5.0" "@svgr/webpack": "npm:^5.5.0"
"@testing-library/jest-dom": "npm:^6.0.0" "@testing-library/jest-dom": "npm:^6.0.0"
"@testing-library/react": "npm:^14.0.0" "@testing-library/react": "npm:^15.0.0"
"@types/babel__core": "npm:^7.20.1" "@types/babel__core": "npm:^7.20.1"
"@types/emoji-mart": "npm:^3.0.9" "@types/emoji-mart": "npm:^3.0.9"
"@types/escape-html": "npm:^1.0.2" "@types/escape-html": "npm:^1.0.2"
@ -3300,19 +3300,19 @@ __metadata:
languageName: node languageName: node
linkType: hard linkType: hard
"@testing-library/dom@npm:^9.0.0": "@testing-library/dom@npm:^10.0.0":
version: 9.3.1 version: 10.0.0
resolution: "@testing-library/dom@npm:9.3.1" resolution: "@testing-library/dom@npm:10.0.0"
dependencies: dependencies:
"@babel/code-frame": "npm:^7.10.4" "@babel/code-frame": "npm:^7.10.4"
"@babel/runtime": "npm:^7.12.5" "@babel/runtime": "npm:^7.12.5"
"@types/aria-query": "npm:^5.0.1" "@types/aria-query": "npm:^5.0.1"
aria-query: "npm:5.1.3" aria-query: "npm:5.3.0"
chalk: "npm:^4.1.0" chalk: "npm:^4.1.0"
dom-accessibility-api: "npm:^0.5.9" dom-accessibility-api: "npm:^0.5.9"
lz-string: "npm:^1.5.0" lz-string: "npm:^1.5.0"
pretty-format: "npm:^27.0.2" pretty-format: "npm:^27.0.2"
checksum: 10c0/25d1deddba014c107fd9703181fbb7063ed376d3ad42d7918ee752e7e677edfb5abaf672b22afc5257ffe760c9c7e5cc981656297c328bc61578d23c6b65b4dc checksum: 10c0/2d12d2a6018a6f1d15e91834180bc068932c699ff1fcbfb80aa21aba519a4f5329c861dfa852e06ee5615bcb92ef2a0f0e755e32684ea3dada63bc34248382ab
languageName: node languageName: node
linkType: hard linkType: hard
@ -3349,17 +3349,17 @@ __metadata:
languageName: node languageName: node
linkType: hard linkType: hard
"@testing-library/react@npm:^14.0.0": "@testing-library/react@npm:^15.0.0":
version: 14.2.2 version: 15.0.2
resolution: "@testing-library/react@npm:14.2.2" resolution: "@testing-library/react@npm:15.0.2"
dependencies: dependencies:
"@babel/runtime": "npm:^7.12.5" "@babel/runtime": "npm:^7.12.5"
"@testing-library/dom": "npm:^9.0.0" "@testing-library/dom": "npm:^10.0.0"
"@types/react-dom": "npm:^18.0.0" "@types/react-dom": "npm:^18.0.0"
peerDependencies: peerDependencies:
react: ^18.0.0 react: ^18.0.0
react-dom: ^18.0.0 react-dom: ^18.0.0
checksum: 10c0/ab36707f6701a4a56dd217e16e00d6326e0f760bb2e716245422c7500a0b94efcd351d0aa89c4fab2916e6ebc68c983cec6b3ae0804de813cafc913a612668f6 checksum: 10c0/8d75e4850f8f749244bf4f30b0f99a5d4aa1156ee5a59eea0772f47971c38535d1fb31d021c4f0f0b816346ae664870dc223d5d997ab399dfb1b6211f0e2acf1
languageName: node languageName: node
linkType: hard linkType: hard
@ -3718,13 +3718,13 @@ __metadata:
linkType: hard linkType: hard
"@types/pg@npm:^8.6.6": "@types/pg@npm:^8.6.6":
version: 8.11.4 version: 8.11.5
resolution: "@types/pg@npm:8.11.4" resolution: "@types/pg@npm:8.11.5"
dependencies: dependencies:
"@types/node": "npm:*" "@types/node": "npm:*"
pg-protocol: "npm:*" pg-protocol: "npm:*"
pg-types: "npm:^4.0.1" pg-types: "npm:^4.0.1"
checksum: 10c0/81158ffa9d2f9b2b299a1650756b90fc418e0040e654d7d9ee46734a3c874d07b638af86d765e22e9c8246054c30a0274ee4dea58a0a7ed5c0c4aa01964a09ef checksum: 10c0/d64d183bee2df96cd0558231190ff629558e8c0fd3203b880f48a7d34b1eaea528d20c09b57b19c0939f369136e6c6941533592eadd71174be78d1ec0ca5e60e
languageName: node languageName: node
linkType: hard linkType: hard
@ -3778,11 +3778,11 @@ __metadata:
linkType: hard linkType: hard
"@types/react-dom@npm:^18.0.0, @types/react-dom@npm:^18.2.4": "@types/react-dom@npm:^18.0.0, @types/react-dom@npm:^18.2.4":
version: 18.2.24 version: 18.2.25
resolution: "@types/react-dom@npm:18.2.24" resolution: "@types/react-dom@npm:18.2.25"
dependencies: dependencies:
"@types/react": "npm:*" "@types/react": "npm:*"
checksum: 10c0/9ec38e5ab4727c56ef17bd8e938ead88748ba19db314b8d9807714a5cae430f5b799514667b221b4f2dc8d9b4ca17dd1c3da8c41c083c2de9eddcc31bec6b8ff checksum: 10c0/87604407eca6884c5b4d4657cb511dc5ba28ea1cfa5d0ce1fc2d659a7ad1b64ae85dcda60e3f010641f9a52a6a60dfcaa6be3b0d0de9d624475052a13dae01f4
languageName: node languageName: node
linkType: hard linkType: hard
@ -3881,12 +3881,12 @@ __metadata:
linkType: hard linkType: hard
"@types/react@npm:*, @types/react@npm:16 || 17 || 18, @types/react@npm:>=16.9.11, @types/react@npm:^18.2.7": "@types/react@npm:*, @types/react@npm:16 || 17 || 18, @types/react@npm:>=16.9.11, @types/react@npm:^18.2.7":
version: 18.2.74 version: 18.2.78
resolution: "@types/react@npm:18.2.74" resolution: "@types/react@npm:18.2.78"
dependencies: dependencies:
"@types/prop-types": "npm:*" "@types/prop-types": "npm:*"
csstype: "npm:^3.0.2" csstype: "npm:^3.0.2"
checksum: 10c0/347e38b4c5dc20d50ff71bf04b7caaef490e5ff695e74a0088a13fbb2a0c5d125a5ecfd142adfa30f0176da0e2734942c91ba61d95ce269c43b3265bd7379361 checksum: 10c0/5eb8e1dd98c29aeddf40b90f466d1a9ce83b113d42a096633d632b834e7ae9821f24ba7999928de9d98cca37764532a7ea35355a8103a377d8baa750f1841b5c
languageName: node languageName: node
linkType: hard linkType: hard
@ -4731,16 +4731,7 @@ __metadata:
languageName: node languageName: node
linkType: hard linkType: hard
"aria-query@npm:5.1.3": "aria-query@npm:5.3.0, aria-query@npm:^5.0.0, aria-query@npm:^5.3.0":
version: 5.1.3
resolution: "aria-query@npm:5.1.3"
dependencies:
deep-equal: "npm:^2.0.5"
checksum: 10c0/edcbc8044c4663d6f88f785e983e6784f98cb62b4ba1e9dd8d61b725d0203e4cfca38d676aee984c31f354103461102a3d583aa4fbe4fd0a89b679744f4e5faf
languageName: node
linkType: hard
"aria-query@npm:^5.0.0, aria-query@npm:^5.3.0":
version: 5.3.0 version: 5.3.0
resolution: "aria-query@npm:5.3.0" resolution: "aria-query@npm:5.3.0"
dependencies: dependencies:
@ -4770,7 +4761,7 @@ __metadata:
languageName: node languageName: node
linkType: hard linkType: hard
"array-buffer-byte-length@npm:^1.0.0, array-buffer-byte-length@npm:^1.0.1": "array-buffer-byte-length@npm:^1.0.1":
version: 1.0.1 version: 1.0.1
resolution: "array-buffer-byte-length@npm:1.0.1" resolution: "array-buffer-byte-length@npm:1.0.1"
dependencies: dependencies:
@ -6933,32 +6924,6 @@ __metadata:
languageName: node languageName: node
linkType: hard linkType: hard
"deep-equal@npm:^2.0.5":
version: 2.2.1
resolution: "deep-equal@npm:2.2.1"
dependencies:
array-buffer-byte-length: "npm:^1.0.0"
call-bind: "npm:^1.0.2"
es-get-iterator: "npm:^1.1.3"
get-intrinsic: "npm:^1.2.0"
is-arguments: "npm:^1.1.1"
is-array-buffer: "npm:^3.0.2"
is-date-object: "npm:^1.0.5"
is-regex: "npm:^1.1.4"
is-shared-array-buffer: "npm:^1.0.2"
isarray: "npm:^2.0.5"
object-is: "npm:^1.1.5"
object-keys: "npm:^1.1.1"
object.assign: "npm:^4.1.4"
regexp.prototype.flags: "npm:^1.5.0"
side-channel: "npm:^1.0.4"
which-boxed-primitive: "npm:^1.0.2"
which-collection: "npm:^1.0.1"
which-typed-array: "npm:^1.1.9"
checksum: 10c0/9e32606f0e24ef4d6b100c68cadae81495c3638944e933afc4b8389b042e95c5fe1381492cf7a6d385bcbae564c9cfb7086f37f277e37521a632b008a6b208dc
languageName: node
linkType: hard
"deep-is@npm:^0.1.3": "deep-is@npm:^0.1.3":
version: 0.1.4 version: 0.1.4
resolution: "deep-is@npm:0.1.4" resolution: "deep-is@npm:0.1.4"
@ -7613,23 +7578,6 @@ __metadata:
languageName: node languageName: node
linkType: hard linkType: hard
"es-get-iterator@npm:^1.1.3":
version: 1.1.3
resolution: "es-get-iterator@npm:1.1.3"
dependencies:
call-bind: "npm:^1.0.2"
get-intrinsic: "npm:^1.1.3"
has-symbols: "npm:^1.0.3"
is-arguments: "npm:^1.1.1"
is-map: "npm:^2.0.2"
is-set: "npm:^2.0.2"
is-string: "npm:^1.0.7"
isarray: "npm:^2.0.5"
stop-iteration-iterator: "npm:^1.0.0"
checksum: 10c0/ebd11effa79851ea75d7f079405f9d0dc185559fd65d986c6afea59a0ff2d46c2ed8675f19f03dce7429d7f6c14ff9aede8d121fbab78d75cfda6a263030bac0
languageName: node
linkType: hard
"es-iterator-helpers@npm:^1.0.15, es-iterator-helpers@npm:^1.0.17": "es-iterator-helpers@npm:^1.0.15, es-iterator-helpers@npm:^1.0.17":
version: 1.0.17 version: 1.0.17
resolution: "es-iterator-helpers@npm:1.0.17" resolution: "es-iterator-helpers@npm:1.0.17"
@ -8783,7 +8731,7 @@ __metadata:
languageName: node languageName: node
linkType: hard linkType: hard
"get-intrinsic@npm:^1.0.2, get-intrinsic@npm:^1.1.1, get-intrinsic@npm:^1.1.3, get-intrinsic@npm:^1.2.0, get-intrinsic@npm:^1.2.1, get-intrinsic@npm:^1.2.2, get-intrinsic@npm:^1.2.3, get-intrinsic@npm:^1.2.4": "get-intrinsic@npm:^1.0.2, get-intrinsic@npm:^1.1.1, get-intrinsic@npm:^1.1.3, get-intrinsic@npm:^1.2.1, get-intrinsic@npm:^1.2.2, get-intrinsic@npm:^1.2.3, get-intrinsic@npm:^1.2.4":
version: 1.2.4 version: 1.2.4
resolution: "get-intrinsic@npm:1.2.4" resolution: "get-intrinsic@npm:1.2.4"
dependencies: dependencies:
@ -9622,7 +9570,7 @@ __metadata:
languageName: node languageName: node
linkType: hard linkType: hard
"internal-slot@npm:^1.0.4, internal-slot@npm:^1.0.5, internal-slot@npm:^1.0.7": "internal-slot@npm:^1.0.5, internal-slot@npm:^1.0.7":
version: 1.0.7 version: 1.0.7
resolution: "internal-slot@npm:1.0.7" resolution: "internal-slot@npm:1.0.7"
dependencies: dependencies:
@ -9738,7 +9686,7 @@ __metadata:
languageName: node languageName: node
linkType: hard linkType: hard
"is-arguments@npm:^1.0.4, is-arguments@npm:^1.1.1": "is-arguments@npm:^1.0.4":
version: 1.1.1 version: 1.1.1
resolution: "is-arguments@npm:1.1.1" resolution: "is-arguments@npm:1.1.1"
dependencies: dependencies:
@ -9748,7 +9696,7 @@ __metadata:
languageName: node languageName: node
linkType: hard linkType: hard
"is-array-buffer@npm:^3.0.2, is-array-buffer@npm:^3.0.4": "is-array-buffer@npm:^3.0.4":
version: 3.0.4 version: 3.0.4
resolution: "is-array-buffer@npm:3.0.4" resolution: "is-array-buffer@npm:3.0.4"
dependencies: dependencies:
@ -9995,7 +9943,7 @@ __metadata:
languageName: node languageName: node
linkType: hard linkType: hard
"is-map@npm:^2.0.1, is-map@npm:^2.0.2": "is-map@npm:^2.0.1":
version: 2.0.2 version: 2.0.2
resolution: "is-map@npm:2.0.2" resolution: "is-map@npm:2.0.2"
checksum: 10c0/119ff9137a37fd131a72fab3f4ab8c9d6a24b0a1ee26b4eff14dc625900d8675a97785eea5f4174265e2006ed076cc24e89f6e57ebd080a48338d914ec9168a5 checksum: 10c0/119ff9137a37fd131a72fab3f4ab8c9d6a24b0a1ee26b4eff14dc625900d8675a97785eea5f4174265e2006ed076cc24e89f6e57ebd080a48338d914ec9168a5
@ -10120,7 +10068,7 @@ __metadata:
languageName: node languageName: node
linkType: hard linkType: hard
"is-set@npm:^2.0.1, is-set@npm:^2.0.2": "is-set@npm:^2.0.1":
version: 2.0.2 version: 2.0.2
resolution: "is-set@npm:2.0.2" resolution: "is-set@npm:2.0.2"
checksum: 10c0/5f8bd1880df8c0004ce694e315e6e1e47a3452014be792880bb274a3b2cdb952fdb60789636ca6e084c7947ca8b7ae03ccaf54c93a7fcfed228af810559e5432 checksum: 10c0/5f8bd1880df8c0004ce694e315e6e1e47a3452014be792880bb274a3b2cdb952fdb60789636ca6e084c7947ca8b7ae03ccaf54c93a7fcfed228af810559e5432
@ -12316,7 +12264,7 @@ __metadata:
languageName: node languageName: node
linkType: hard linkType: hard
"object-is@npm:^1.0.1, object-is@npm:^1.1.5": "object-is@npm:^1.0.1":
version: 1.1.5 version: 1.1.5
resolution: "object-is@npm:1.1.5" resolution: "object-is@npm:1.1.5"
dependencies: dependencies:
@ -13228,9 +13176,9 @@ __metadata:
languageName: node languageName: node
linkType: hard linkType: hard
"postcss-custom-properties@npm:^13.3.6": "postcss-custom-properties@npm:^13.3.7":
version: 13.3.6 version: 13.3.7
resolution: "postcss-custom-properties@npm:13.3.6" resolution: "postcss-custom-properties@npm:13.3.7"
dependencies: dependencies:
"@csstools/cascade-layer-name-parser": "npm:^1.0.9" "@csstools/cascade-layer-name-parser": "npm:^1.0.9"
"@csstools/css-parser-algorithms": "npm:^2.6.1" "@csstools/css-parser-algorithms": "npm:^2.6.1"
@ -13239,7 +13187,7 @@ __metadata:
postcss-value-parser: "npm:^4.2.0" postcss-value-parser: "npm:^4.2.0"
peerDependencies: peerDependencies:
postcss: ^8.4 postcss: ^8.4
checksum: 10c0/faa3b692966314a6dfcba93e74d91f20f2484ea328f88c809b1d0daa8ecc0d8d5125e06d1d7c18b5455ac30cb3501c7069b6e56e5efac61523a6ed75c3d73a30 checksum: 10c0/5d8767efae956f98d9a62a8f54d913c9ea95eaab1c906679ddeee64d87f0fb37d99c8ac1d16ec199794ed7c13a42d39ca2ea0a98df1056d400d4cbc9f31d6b94
languageName: node languageName: node
linkType: hard linkType: hard
@ -13700,8 +13648,8 @@ __metadata:
linkType: hard linkType: hard
"postcss-preset-env@npm:^9.5.2": "postcss-preset-env@npm:^9.5.2":
version: 9.5.4 version: 9.5.5
resolution: "postcss-preset-env@npm:9.5.4" resolution: "postcss-preset-env@npm:9.5.5"
dependencies: dependencies:
"@csstools/postcss-cascade-layers": "npm:^4.0.4" "@csstools/postcss-cascade-layers": "npm:^4.0.4"
"@csstools/postcss-color-function": "npm:^3.0.13" "@csstools/postcss-color-function": "npm:^3.0.13"
@ -13744,7 +13692,7 @@ __metadata:
postcss-color-hex-alpha: "npm:^9.0.4" postcss-color-hex-alpha: "npm:^9.0.4"
postcss-color-rebeccapurple: "npm:^9.0.3" postcss-color-rebeccapurple: "npm:^9.0.3"
postcss-custom-media: "npm:^10.0.4" postcss-custom-media: "npm:^10.0.4"
postcss-custom-properties: "npm:^13.3.6" postcss-custom-properties: "npm:^13.3.7"
postcss-custom-selectors: "npm:^7.1.8" postcss-custom-selectors: "npm:^7.1.8"
postcss-dir-pseudo-class: "npm:^8.0.1" postcss-dir-pseudo-class: "npm:^8.0.1"
postcss-double-position-gradients: "npm:^5.0.6" postcss-double-position-gradients: "npm:^5.0.6"
@ -13765,7 +13713,7 @@ __metadata:
postcss-selector-not: "npm:^7.0.2" postcss-selector-not: "npm:^7.0.2"
peerDependencies: peerDependencies:
postcss: ^8.4 postcss: ^8.4
checksum: 10c0/6af900ad2f46b640339b626317288543ebb7c47b739f4776e4006513b32eceabe0be78109aa58446fa0f50284a433b3e3a9bd48aa5730fd0ac59ef51153e8f7b checksum: 10c0/afc31fb75bc5e8e223d38fd34b81da08ee340818f5e392df1781728f2ff2a9dbc75e458673ce9f52deafefa90bbc99e0bd1453271498f5e02746c785180bad07
languageName: node languageName: node
linkType: hard linkType: hard
@ -14040,12 +13988,12 @@ __metadata:
linkType: hard linkType: hard
"prom-client@npm:^15.0.0": "prom-client@npm:^15.0.0":
version: 15.1.1 version: 15.1.2
resolution: "prom-client@npm:15.1.1" resolution: "prom-client@npm:15.1.2"
dependencies: dependencies:
"@opentelemetry/api": "npm:^1.4.0" "@opentelemetry/api": "npm:^1.4.0"
tdigest: "npm:^0.1.1" tdigest: "npm:^0.1.1"
checksum: 10c0/b3e6a58fc0ef87cf5b0badf06d7d79c24ac93ba47cccfaad95faeba79824c6a7724d74a257e7268d691245c847173818c16c8153054cccf16b8f033c37c74129 checksum: 10c0/a221db148fa64e29dfd4c6cdcaaae14635495a4272b68917e2b44fcfd988bc57027d275b04489ceeea4d0c4d64d058af842c1300966d2c1ffa255f1fa6af1277
languageName: node languageName: node
linkType: hard linkType: hard
@ -14497,8 +14445,8 @@ __metadata:
linkType: hard linkType: hard
"react-redux@npm:^9.0.4": "react-redux@npm:^9.0.4":
version: 9.1.0 version: 9.1.1
resolution: "react-redux@npm:9.1.0" resolution: "react-redux@npm:9.1.1"
dependencies: dependencies:
"@types/use-sync-external-store": "npm:^0.0.3" "@types/use-sync-external-store": "npm:^0.0.3"
use-sync-external-store: "npm:^1.0.0" use-sync-external-store: "npm:^1.0.0"
@ -14514,7 +14462,7 @@ __metadata:
optional: true optional: true
redux: redux:
optional: true optional: true
checksum: 10c0/53161b5dc4d109020fbc42d26906ace92fed9ba1d7ab6274af60e9c0684583d20d1c8ec6d58601ac7b833c6468a652bbf3d4a102149d1793cb8a28b05b042f73 checksum: 10c0/40ccdc8d48aefeed02c025f46e4a2e6641a2996fe985feb70d25feaaf8f101f6ef937cd1420909cad4c8869a8c79323ee071f5b090b011b950e5ae09100f5767
languageName: node languageName: node
linkType: hard linkType: hard
@ -15367,15 +15315,15 @@ __metadata:
linkType: hard linkType: hard
"sass@npm:^1.62.1": "sass@npm:^1.62.1":
version: 1.74.1 version: 1.75.0
resolution: "sass@npm:1.74.1" resolution: "sass@npm:1.75.0"
dependencies: dependencies:
chokidar: "npm:>=3.0.0 <4.0.0" chokidar: "npm:>=3.0.0 <4.0.0"
immutable: "npm:^4.0.0" immutable: "npm:^4.0.0"
source-map-js: "npm:>=0.6.2 <2.0.0" source-map-js: "npm:>=0.6.2 <2.0.0"
bin: bin:
sass: sass.js sass: sass.js
checksum: 10c0/4610257ee27823276ce4998a534b4ee9f313e5a0b3d3899e70e0f87096feeae4cd8dd3c2f765b52f57dd87f5dab22370ef63f95a837a189fbb9401396d5ce717 checksum: 10c0/1564ab2c8041c99a330cec93127fe8abcf65ac63eecb471610ed7f3126a2599a58b788a3a98eb8719f7f40b9b04e00c92bc9e11a9c2180ad582b8cba9fb030b0
languageName: node languageName: node
linkType: hard linkType: hard
@ -16142,15 +16090,6 @@ __metadata:
languageName: node languageName: node
linkType: hard linkType: hard
"stop-iteration-iterator@npm:^1.0.0":
version: 1.0.0
resolution: "stop-iteration-iterator@npm:1.0.0"
dependencies:
internal-slot: "npm:^1.0.4"
checksum: 10c0/c4158d6188aac510d9e92925b58709207bd94699e9c31186a040c80932a687f84a51356b5895e6dc72710aad83addb9411c22171832c9ae0e6e11b7d61b0dfb9
languageName: node
linkType: hard
"stream-browserify@npm:^2.0.1": "stream-browserify@npm:^2.0.1":
version: 2.0.2 version: 2.0.2
resolution: "stream-browserify@npm:2.0.2" resolution: "stream-browserify@npm:2.0.2"
@ -17157,22 +17096,22 @@ __metadata:
linkType: hard linkType: hard
"typescript@npm:5, typescript@npm:^5.0.4": "typescript@npm:5, typescript@npm:^5.0.4":
version: 5.4.4 version: 5.4.5
resolution: "typescript@npm:5.4.4" resolution: "typescript@npm:5.4.5"
bin: bin:
tsc: bin/tsc tsc: bin/tsc
tsserver: bin/tsserver tsserver: bin/tsserver
checksum: 10c0/4d8de0291204ed61ca97ad0cba2ce064e09c4988ca1c451c787e4653ba76296ba35177a52694e8a00cf4ef899d0ee83338663b926d8b7d55167ff0ba81549999 checksum: 10c0/2954022ada340fd3d6a9e2b8e534f65d57c92d5f3989a263754a78aba549f7e6529acc1921913560a4b816c46dce7df4a4d29f9f11a3dc0d4213bb76d043251e
languageName: node languageName: node
linkType: hard linkType: hard
"typescript@patch:typescript@npm%3A5#optional!builtin<compat/typescript>, typescript@patch:typescript@npm%3A^5.0.4#optional!builtin<compat/typescript>": "typescript@patch:typescript@npm%3A5#optional!builtin<compat/typescript>, typescript@patch:typescript@npm%3A^5.0.4#optional!builtin<compat/typescript>":
version: 5.4.4 version: 5.4.5
resolution: "typescript@patch:typescript@npm%3A5.4.4#optional!builtin<compat/typescript>::version=5.4.4&hash=5adc0c" resolution: "typescript@patch:typescript@npm%3A5.4.5#optional!builtin<compat/typescript>::version=5.4.5&hash=5adc0c"
bin: bin:
tsc: bin/tsc tsc: bin/tsc
tsserver: bin/tsserver tsserver: bin/tsserver
checksum: 10c0/1fa41b9964a9ff0ed913b339c90b46031b2d2da3cb1a192af516610733f7f1d5f7f9754a8e22b9ac7076d3d8aedd2c4f84db3f113bad060eac3a95962443a1bf checksum: 10c0/db2ad2a16ca829f50427eeb1da155e7a45e598eec7b086d8b4e8ba44e5a235f758e606d681c66992230d3fc3b8995865e5fd0b22a2c95486d0b3200f83072ec9
languageName: node languageName: node
linkType: hard linkType: hard
@ -17702,8 +17641,8 @@ __metadata:
linkType: hard linkType: hard
"webpack-bundle-analyzer@npm:^4.8.0": "webpack-bundle-analyzer@npm:^4.8.0":
version: 4.10.1 version: 4.10.2
resolution: "webpack-bundle-analyzer@npm:4.10.1" resolution: "webpack-bundle-analyzer@npm:4.10.2"
dependencies: dependencies:
"@discoveryjs/json-ext": "npm:0.5.7" "@discoveryjs/json-ext": "npm:0.5.7"
acorn: "npm:^8.0.4" acorn: "npm:^8.0.4"
@ -17713,14 +17652,13 @@ __metadata:
escape-string-regexp: "npm:^4.0.0" escape-string-regexp: "npm:^4.0.0"
gzip-size: "npm:^6.0.0" gzip-size: "npm:^6.0.0"
html-escaper: "npm:^2.0.2" html-escaper: "npm:^2.0.2"
is-plain-object: "npm:^5.0.0"
opener: "npm:^1.5.2" opener: "npm:^1.5.2"
picocolors: "npm:^1.0.0" picocolors: "npm:^1.0.0"
sirv: "npm:^2.0.3" sirv: "npm:^2.0.3"
ws: "npm:^7.3.1" ws: "npm:^7.3.1"
bin: bin:
webpack-bundle-analyzer: lib/bin/analyzer.js webpack-bundle-analyzer: lib/bin/analyzer.js
checksum: 10c0/6a94c8f6aa03296fb2eb00d6ad3b27bd5c551590fd253772bc61debf3177414d42701014079d4f85c74ba1ca685ae9f0cb4063812b58c21f294d108e9908e5cd checksum: 10c0/00603040e244ead15b2d92981f0559fa14216381349412a30070a7358eb3994cd61a8221d34a3b3fb8202dc3d1c5ee1fbbe94c5c52da536e5b410aa1cf279a48
languageName: node languageName: node
linkType: hard linkType: hard