diff --git a/Gemfile b/Gemfile index ef52d50cac128d..135b94c7739b37 100644 --- a/Gemfile +++ b/Gemfile @@ -88,7 +88,7 @@ gem 'sidekiq-unique-jobs', '~> 7.1' gem 'simple_form', '~> 5.2' gem 'simple-navigation', '~> 4.4' gem 'stoplight', '~> 4.1' -gem 'strong_migrations', '1.8.0' +gem 'strong_migrations' gem 'tty-prompt', '~> 0.23', require: false gem 'twitter-text', '~> 3.1.0' gem 'tzinfo-data', '~> 1.2023' diff --git a/Gemfile.lock b/Gemfile.lock index 98a3571731fedd..fa09e99cb0f464 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -222,16 +222,16 @@ GEM elasticsearch-transport (7.17.10) faraday (>= 1, < 3) multi_json - email_spec (2.2.2) + email_spec (2.3.0) htmlentities (~> 4.3.3) - launchy (~> 2.1) + launchy (>= 2.1, < 4.0) mail (~> 2.7) erubi (1.13.0) et-orbi (1.2.11) tzinfo excon (0.110.0) fabrication (2.31.0) - faker (3.4.1) + faker (3.4.2) i18n (>= 1.8.11, < 2) faraday (1.10.3) faraday-em_http (~> 1.0) @@ -367,7 +367,7 @@ GEM json-ld-preloaded (3.3.0) json-ld (~> 3.3) rdf (~> 3.3) - json-schema (4.3.0) + json-schema (4.3.1) addressable (>= 2.8) jsonapi-renderer (0.2.2) jwt (2.7.1) @@ -440,7 +440,7 @@ GEM uri net-http-persistent (4.0.2) connection_pool (~> 2.2) - net-imap (0.4.12) + net-imap (0.4.14) date net-protocol net-ldap (0.19.0) @@ -512,14 +512,14 @@ GEM opentelemetry-api (~> 1.0) opentelemetry-instrumentation-base (~> 0.22.1) opentelemetry-instrumentation-rack (~> 0.21) - opentelemetry-instrumentation-action_view (0.7.0) + opentelemetry-instrumentation-action_view (0.7.1) opentelemetry-api (~> 1.0) opentelemetry-instrumentation-active_support (~> 0.1) opentelemetry-instrumentation-base (~> 0.22.1) - opentelemetry-instrumentation-active_job (0.7.2) + opentelemetry-instrumentation-active_job (0.7.3) opentelemetry-api (~> 1.0) opentelemetry-instrumentation-base (~> 0.22.1) - opentelemetry-instrumentation-active_model_serializers (0.20.1) + opentelemetry-instrumentation-active_model_serializers (0.20.2) opentelemetry-api (~> 1.0) opentelemetry-instrumentation-base (~> 0.22.1) opentelemetry-instrumentation-active_record (0.7.2) @@ -531,32 +531,32 @@ GEM opentelemetry-instrumentation-base (0.22.3) opentelemetry-api (~> 1.0) opentelemetry-registry (~> 0.1) - opentelemetry-instrumentation-concurrent_ruby (0.21.3) + opentelemetry-instrumentation-concurrent_ruby (0.21.4) opentelemetry-api (~> 1.0) opentelemetry-instrumentation-base (~> 0.22.1) - opentelemetry-instrumentation-excon (0.22.3) + opentelemetry-instrumentation-excon (0.22.4) opentelemetry-api (~> 1.0) opentelemetry-instrumentation-base (~> 0.22.1) - opentelemetry-instrumentation-faraday (0.24.5) + opentelemetry-instrumentation-faraday (0.24.6) opentelemetry-api (~> 1.0) opentelemetry-instrumentation-base (~> 0.22.1) - opentelemetry-instrumentation-http (0.23.3) + opentelemetry-instrumentation-http (0.23.4) opentelemetry-api (~> 1.0) opentelemetry-instrumentation-base (~> 0.22.1) - opentelemetry-instrumentation-http_client (0.22.6) + opentelemetry-instrumentation-http_client (0.22.7) opentelemetry-api (~> 1.0) opentelemetry-instrumentation-base (~> 0.22.1) - opentelemetry-instrumentation-net_http (0.22.6) + opentelemetry-instrumentation-net_http (0.22.7) opentelemetry-api (~> 1.0) opentelemetry-instrumentation-base (~> 0.22.1) - opentelemetry-instrumentation-pg (0.27.3) + opentelemetry-instrumentation-pg (0.27.4) opentelemetry-api (~> 1.0) opentelemetry-helpers-sql-obfuscation opentelemetry-instrumentation-base (~> 0.22.1) - opentelemetry-instrumentation-rack (0.24.5) + opentelemetry-instrumentation-rack (0.24.6) opentelemetry-api (~> 1.0) opentelemetry-instrumentation-base (~> 0.22.1) - opentelemetry-instrumentation-rails (0.31.0) + opentelemetry-instrumentation-rails (0.31.1) opentelemetry-api (~> 1.0) opentelemetry-instrumentation-action_mailer (~> 0.1.0) opentelemetry-instrumentation-action_pack (~> 0.9.0) @@ -565,10 +565,10 @@ GEM opentelemetry-instrumentation-active_record (~> 0.7.0) opentelemetry-instrumentation-active_support (~> 0.6.0) opentelemetry-instrumentation-base (~> 0.22.1) - opentelemetry-instrumentation-redis (0.25.6) + opentelemetry-instrumentation-redis (0.25.7) opentelemetry-api (~> 1.0) opentelemetry-instrumentation-base (~> 0.22.1) - opentelemetry-instrumentation-sidekiq (0.25.6) + opentelemetry-instrumentation-sidekiq (0.25.7) opentelemetry-api (~> 1.0) opentelemetry-instrumentation-base (~> 0.22.1) opentelemetry-registry (0.3.1) @@ -607,7 +607,7 @@ GEM railties (>= 7.0.0) psych (5.1.2) stringio - public_suffix (6.0.0) + public_suffix (6.0.1) puma (6.4.2) nio4r (~> 2.0) pundit (2.3.2) @@ -696,7 +696,7 @@ GEM responders (3.1.1) actionpack (>= 5.2) railties (>= 5.2) - rexml (3.3.1) + rexml (3.3.2) strscan rotp (6.3.0) rouge (4.2.1) @@ -766,8 +766,9 @@ GEM ruby-saml (1.16.0) nokogiri (>= 1.13.10) rexml - ruby-vips (2.2.1) + ruby-vips (2.2.2) ffi (~> 1.12) + logger ruby2_keywords (0.0.5) rubyzip (2.3.2) rufus-scheduler (3.9.1) @@ -780,7 +781,7 @@ GEM scenic (1.8.0) activerecord (>= 4.0.0) railties (>= 4.0.0) - selenium-webdriver (4.22.0) + selenium-webdriver (4.23.0) base64 (~> 0.2) logger (~> 1.4) rexml (~> 3.2, >= 3.2.5) @@ -820,8 +821,8 @@ GEM stoplight (4.1.0) redlock (~> 1.0) stringio (3.1.1) - strong_migrations (1.8.0) - activerecord (>= 5.2) + strong_migrations (2.0.0) + activerecord (>= 6.1) strscan (3.1.0) swd (1.3.0) activesupport (>= 3) @@ -893,7 +894,7 @@ GEM railties (>= 5.2) semantic_range (>= 2.3.0) webrick (1.8.1) - websocket (1.2.10) + websocket (1.2.11) websocket-driver (0.7.6) websocket-extensions (>= 0.1.0) websocket-extensions (0.1.5) @@ -1045,7 +1046,7 @@ DEPENDENCIES simplecov-lcov (~> 0.8) stackprof stoplight (~> 4.1) - strong_migrations (= 1.8.0) + strong_migrations test-prof thor (~> 1.2) tty-prompt (~> 0.23) diff --git a/app/controllers/admin/instances_controller.rb b/app/controllers/admin/instances_controller.rb index a6997b62f7db6b..d7f88a71f3698f 100644 --- a/app/controllers/admin/instances_controller.rb +++ b/app/controllers/admin/instances_controller.rb @@ -13,6 +13,7 @@ def index def show authorize :instance, :show? @time_period = (6.days.ago.to_date...Time.now.utc.to_date) + @action_logs = Admin::ActionLogFilter.new(target_domain: @instance.domain).results.limit(5) end def destroy diff --git a/app/controllers/api/v1/admin/domain_allows_controller.rb b/app/controllers/api/v1/admin/domain_allows_controller.rb index 9801d832b8ba84..0cd5aebd53ad8b 100644 --- a/app/controllers/api/v1/admin/domain_allows_controller.rb +++ b/app/controllers/api/v1/admin/domain_allows_controller.rb @@ -47,18 +47,13 @@ def destroy private def set_domain_allows - @domain_allows = filtered_domain_allows.order(id: :desc).to_a_paginated_by_id(limit_param(LIMIT), params_slice(:max_id, :since_id, :min_id)) + @domain_allows = DomainAllow.order(id: :desc).to_a_paginated_by_id(limit_param(LIMIT), params_slice(:max_id, :since_id, :min_id)) end def set_domain_allow @domain_allow = DomainAllow.find(params[:id]) end - def filtered_domain_allows - # TODO: no filtering yet - DomainAllow.all - end - def next_path api_v1_admin_domain_allows_url(pagination_params(max_id: pagination_max_id)) if records_continue? end diff --git a/app/controllers/api/v1/admin/domain_blocks_controller.rb b/app/controllers/api/v1/admin/domain_blocks_controller.rb index 61a923eccb30f8..ca762cc3311a13 100644 --- a/app/controllers/api/v1/admin/domain_blocks_controller.rb +++ b/app/controllers/api/v1/admin/domain_blocks_controller.rb @@ -59,18 +59,13 @@ def conflicts_with_existing_block?(domain_block, existing_domain_block) end def set_domain_blocks - @domain_blocks = filtered_domain_blocks.order(id: :desc).to_a_paginated_by_id(limit_param(LIMIT), params_slice(:max_id, :since_id, :min_id)) + @domain_blocks = DomainBlock.order(id: :desc).to_a_paginated_by_id(limit_param(LIMIT), params_slice(:max_id, :since_id, :min_id)) end def set_domain_block @domain_block = DomainBlock.find(params[:id]) end - def filtered_domain_blocks - # TODO: no filtering yet - DomainBlock.all - end - def domain_block_params params.permit(:severity, :reject_media, :reject_favourite, :reject_reply_exclude_followers, :reject_reports, :reject_send_sensitive, :reject_hashtag, :reject_straight_follow, :reject_new_follow, :reject_friend, :block_trends, :detect_invalid_subscription, :private_comment, :public_comment, :obfuscate, :hidden) diff --git a/app/controllers/api/v1/reports_controller.rb b/app/controllers/api/v1/reports_controller.rb index 300c9faa3f0ee9..72f358bb5bcd95 100644 --- a/app/controllers/api/v1/reports_controller.rb +++ b/app/controllers/api/v1/reports_controller.rb @@ -10,7 +10,7 @@ def create @report = ReportService.new.call( current_account, reported_account, - report_params + report_params.merge(application: doorkeeper_token.application) ) render json: @report, serializer: REST::ReportSerializer diff --git a/app/controllers/api/v2_alpha/notifications_controller.rb b/app/controllers/api/v2_alpha/notifications_controller.rb index edba23ab4a823c..83d40a0886f52f 100644 --- a/app/controllers/api/v2_alpha/notifications_controller.rb +++ b/app/controllers/api/v2_alpha/notifications_controller.rb @@ -12,10 +12,27 @@ def index with_read_replica do @notifications = load_notifications @group_metadata = load_group_metadata + @grouped_notifications = load_grouped_notifications @relationships = StatusRelationshipsPresenter.new(target_statuses_from_notifications, current_user&.account_id) + @sample_accounts = @grouped_notifications.flat_map(&:sample_accounts) + + # Preload associations to avoid N+1s + ActiveRecord::Associations::Preloader.new(records: @sample_accounts, associations: [:account_stat, { user: :role }]).call end - render json: @notifications.map { |notification| NotificationGroup.from_notification(notification, max_id: @group_metadata.dig(notification.group_key, :max_id)) }, each_serializer: REST::NotificationGroupSerializer, relationships: @relationships, group_metadata: @group_metadata + MastodonOTELTracer.in_span('Api::V2Alpha::NotificationsController#index rendering') do |span| + statuses = @grouped_notifications.filter_map { |group| group.target_status&.id } + + span.add_attributes( + 'app.notification_grouping.count' => @grouped_notifications.size, + 'app.notification_grouping.sample_account.count' => @sample_accounts.size, + 'app.notification_grouping.sample_account.unique_count' => @sample_accounts.pluck(:id).uniq.size, + 'app.notification_grouping.status.count' => statuses.size, + 'app.notification_grouping.status.unique_count' => statuses.uniq.size + ) + + render json: @grouped_notifications, each_serializer: REST::NotificationGroupSerializer, relationships: @relationships, group_metadata: @group_metadata + end end def show @@ -36,25 +53,35 @@ def dismiss private def load_notifications - notifications = browserable_account_notifications.includes(from_account: [:account_stat, :user]).to_a_grouped_paginated_by_id( - limit_param(DEFAULT_NOTIFICATIONS_LIMIT), - params_slice(:max_id, :since_id, :min_id) - ) - - Notification.preload_cache_collection_target_statuses(notifications) do |target_statuses| - preload_collection(target_statuses, Status) + MastodonOTELTracer.in_span('Api::V2Alpha::NotificationsController#load_notifications') do + notifications = browserable_account_notifications.includes(from_account: [:account_stat, :user]).to_a_grouped_paginated_by_id( + limit_param(DEFAULT_NOTIFICATIONS_LIMIT), + params_slice(:max_id, :since_id, :min_id) + ) + + Notification.preload_cache_collection_target_statuses(notifications) do |target_statuses| + preload_collection(target_statuses, Status) + end end end def load_group_metadata return {} if @notifications.empty? - browserable_account_notifications - .where(group_key: @notifications.filter_map(&:group_key)) - .where(id: (@notifications.last.id)..(@notifications.first.id)) - .group(:group_key) - .pluck(:group_key, 'min(notifications.id) as min_id', 'max(notifications.id) as max_id', 'max(notifications.created_at) as latest_notification_at') - .to_h { |group_key, min_id, max_id, latest_notification_at| [group_key, { min_id: min_id, max_id: max_id, latest_notification_at: latest_notification_at }] } + MastodonOTELTracer.in_span('Api::V2Alpha::NotificationsController#load_group_metadata') do + browserable_account_notifications + .where(group_key: @notifications.filter_map(&:group_key)) + .where(id: (@notifications.last.id)..(@notifications.first.id)) + .group(:group_key) + .pluck(:group_key, 'min(notifications.id) as min_id', 'max(notifications.id) as max_id', 'max(notifications.created_at) as latest_notification_at') + .to_h { |group_key, min_id, max_id, latest_notification_at| [group_key, { min_id: min_id, max_id: max_id, latest_notification_at: latest_notification_at }] } + end + end + + def load_grouped_notifications + MastodonOTELTracer.in_span('Api::V2Alpha::NotificationsController#load_grouped_notifications') do + @notifications.map { |notification| NotificationGroup.from_notification(notification, max_id: @group_metadata.dig(notification.group_key, :max_id)) } + end end def browserable_account_notifications diff --git a/app/javascript/entrypoints/public.tsx b/app/javascript/entrypoints/public.tsx index 40a9b7c0ca6470..149c1d28d09495 100644 --- a/app/javascript/entrypoints/public.tsx +++ b/app/javascript/entrypoints/public.tsx @@ -316,8 +316,8 @@ function loaded() { const message = statusEl.dataset.spoiler === 'expanded' - ? localeData['status.show_less'] ?? 'Show less' - : localeData['status.show_more'] ?? 'Show more'; + ? (localeData['status.show_less'] ?? 'Show less') + : (localeData['status.show_more'] ?? 'Show more'); spoilerLink.textContent = new IntlMessageFormat( message, locale, diff --git a/app/javascript/mastodon/actions/accounts.js b/app/javascript/mastodon/actions/accounts.js index cea915e5f17fd0..9144235195e3f5 100644 --- a/app/javascript/mastodon/actions/accounts.js +++ b/app/javascript/mastodon/actions/accounts.js @@ -1,3 +1,5 @@ +import { browserHistory } from 'mastodon/components/router'; + import api, { getLinks } from '../api'; import { @@ -676,3 +678,13 @@ export const updateAccount = ({ displayName, note, avatar, header, discoverable, dispatch(importFetchedAccount(response.data)); }); }; + +export const navigateToProfile = (accountId) => { + return (_dispatch, getState) => { + const acct = getState().accounts.getIn([accountId, 'acct']); + + if (acct) { + browserHistory.push(`/@${acct}`); + } + }; +}; diff --git a/app/javascript/mastodon/actions/compose.js b/app/javascript/mastodon/actions/compose.js index 218cf3977c2e42..459847e37bbbec 100644 --- a/app/javascript/mastodon/actions/compose.js +++ b/app/javascript/mastodon/actions/compose.js @@ -4,6 +4,7 @@ import axios from 'axios'; import { throttle } from 'lodash'; import api from 'mastodon/api'; +import { browserHistory } from 'mastodon/components/router'; import { search as emojiSearch } from 'mastodon/features/emoji/emoji_mart_search_light'; import { tagHistory } from 'mastodon/settings'; @@ -97,9 +98,9 @@ const messages = defineMessages({ saved: { id: 'compose.saved.body', defaultMessage: 'Post saved.' }, }); -export const ensureComposeIsVisible = (getState, routerHistory) => { +export const ensureComposeIsVisible = (getState) => { if (!getState().getIn(['compose', 'mounted'])) { - routerHistory.push('/publish'); + browserHistory.push('/publish'); } }; @@ -119,14 +120,26 @@ export function changeCompose(text) { }; } -export function replyCompose(status, routerHistory) { +export function replyCompose(status) { return (dispatch, getState) => { dispatch({ type: COMPOSE_REPLY, status: status, }); - ensureComposeIsVisible(getState, routerHistory); + ensureComposeIsVisible(getState); + }; +} + +export function replyComposeById(statusId) { + return (dispatch, getState) => { + const state = getState(); + const status = state.statuses.get(statusId); + + if (status) { + const account = state.accounts.get(status.get('account')); + dispatch(replyCompose(status.set('account', account))); + } }; } @@ -142,38 +155,44 @@ export function resetCompose() { }; } -export const focusCompose = (routerHistory, defaultText) => (dispatch, getState) => { +export const focusCompose = (defaultText) => (dispatch, getState) => { dispatch({ type: COMPOSE_FOCUS, defaultText, }); - ensureComposeIsVisible(getState, routerHistory); + ensureComposeIsVisible(getState); }; -export function mentionCompose(account, routerHistory) { +export function mentionCompose(account) { return (dispatch, getState) => { dispatch({ type: COMPOSE_MENTION, account: account, }); - ensureComposeIsVisible(getState, routerHistory); + ensureComposeIsVisible(getState); }; } -export function directCompose(account, routerHistory) { +export function mentionComposeById(accountId) { + return (dispatch, getState) => { + dispatch(mentionCompose(getState().accounts.get(accountId))); + }; +} + +export function directCompose(account) { return (dispatch, getState) => { dispatch({ type: COMPOSE_DIRECT, account: account, }); - ensureComposeIsVisible(getState, routerHistory); + ensureComposeIsVisible(getState); }; } -export function submitCompose(routerHistory) { +export function submitCompose() { return function (dispatch, getState) { const status = getState().getIn(['compose', 'text'], ''); const media = getState().getIn(['compose', 'media_attachments']); @@ -228,8 +247,8 @@ export function submitCompose(routerHistory) { 'Idempotency-Key': getState().getIn(['compose', 'idempotencyKey']), }, }).then(function (response) { - if (routerHistory && (routerHistory.location.pathname === '/publish' || routerHistory.location.pathname === '/statuses/new') && window.history.state) { - routerHistory.goBack(); + if ((browserHistory.location.pathname === '/publish' || browserHistory.location.pathname === '/statuses/new') && window.history.state) { + browserHistory.goBack(); } dispatch(insertIntoTagHistory(response.data.tags, status)); @@ -267,7 +286,7 @@ export function submitCompose(routerHistory) { message: statusId === null ? messages.published : messages.saved, action: messages.open, dismissAfter: 10000, - onClick: () => routerHistory.push(`/@${response.data.account.username}/${response.data.id}`), + onClick: () => browserHistory.push(`/@${response.data.account.username}/${response.data.id}`), })); }).catch(function (error) { dispatch(submitComposeFail(error)); diff --git a/app/javascript/mastodon/actions/interactions.js b/app/javascript/mastodon/actions/interactions.js index 6c60a704654914..e443ceb32522fa 100644 --- a/app/javascript/mastodon/actions/interactions.js +++ b/app/javascript/mastodon/actions/interactions.js @@ -1,7 +1,11 @@ +import { boostModal } from 'mastodon/initial_state'; + import api, { getLinks } from '../api'; import { fetchRelationships } from './accounts'; import { importFetchedAccounts, importFetchedStatus, importFetchedStatuses } from './importer'; +import { unreblog, reblog } from './interactions_typed'; +import { openModal } from './modal'; export const REBLOGS_EXPAND_REQUEST = 'REBLOGS_EXPAND_REQUEST'; export const REBLOGS_EXPAND_SUCCESS = 'REBLOGS_EXPAND_SUCCESS'; @@ -741,3 +745,49 @@ export function expandMentionedUsersFail(id, error) { error, }; } + +function toggleReblogWithoutConfirmation(status, privacy) { + return (dispatch) => { + if (status.get('reblogged')) { + dispatch(unreblog({ statusId: status.get('id') })); + } else { + dispatch(reblog({ statusId: status.get('id'), privacy })); + } + }; +} + +export function toggleReblog(statusId, skipModal = false, forceModal = false) { + return (dispatch, getState) => { + const state = getState(); + let status = state.statuses.get(statusId); + + if (!status) + return; + + // The reblog modal expects a pre-filled account in status + // TODO: fix this by having the reblog modal get a statusId and do the work itself + status = status.set('account', state.accounts.get(status.get('account'))); + + if ((boostModal && !skipModal) || (forceModal && !status.get('reblogged'))) { + dispatch(openModal({ modalType: 'BOOST', modalProps: { status, onReblog: (status, privacy) => dispatch(toggleReblogWithoutConfirmation(status, privacy)) } })); + } else { + dispatch(toggleReblogWithoutConfirmation(status)); + } + }; +} + +export function toggleFavourite(statusId) { + return (dispatch, getState) => { + const state = getState(); + const status = state.statuses.get(statusId); + + if (!status) + return; + + if (status.get('favourited')) { + dispatch(unfavourite(status)); + } else { + dispatch(favourite(status)); + } + }; +} diff --git a/app/javascript/mastodon/actions/markers.ts b/app/javascript/mastodon/actions/markers.ts index 03f577c540fc5d..77d91d9b9c3411 100644 --- a/app/javascript/mastodon/actions/markers.ts +++ b/app/javascript/mastodon/actions/markers.ts @@ -75,9 +75,17 @@ interface MarkerParam { } function getLastNotificationId(state: RootState): string | undefined { - // @ts-expect-error state.notifications is not yet typed - // eslint-disable-next-line @typescript-eslint/no-unsafe-return, @typescript-eslint/no-unsafe-call - return state.getIn(['notifications', 'lastReadId']); + // eslint-disable-next-line @typescript-eslint/no-unsafe-call, @typescript-eslint/no-unsafe-member-access + const enableBeta = state.settings.getIn( + ['notifications', 'groupingBeta'], + false, + ) as boolean; + // eslint-disable-next-line @typescript-eslint/no-unsafe-return + return enableBeta + ? state.notificationGroups.lastReadId + : // @ts-expect-error state.notifications is not yet typed + // eslint-disable-next-line @typescript-eslint/no-unsafe-call + state.getIn(['notifications', 'lastReadId']); } const buildPostMarkersParams = (state: RootState) => { diff --git a/app/javascript/mastodon/actions/notification_groups.ts b/app/javascript/mastodon/actions/notification_groups.ts new file mode 100644 index 00000000000000..06c5341207e055 --- /dev/null +++ b/app/javascript/mastodon/actions/notification_groups.ts @@ -0,0 +1,147 @@ +import { createAction } from '@reduxjs/toolkit'; + +import { + apiClearNotifications, + apiFetchNotifications, +} from 'mastodon/api/notifications'; +import type { ApiAccountJSON } from 'mastodon/api_types/accounts'; +import type { + ApiNotificationGroupJSON, + ApiNotificationJSON, +} from 'mastodon/api_types/notifications'; +import { allNotificationTypes } from 'mastodon/api_types/notifications'; +import type { ApiStatusJSON } from 'mastodon/api_types/statuses'; +import type { NotificationGap } from 'mastodon/reducers/notification_groups'; +import { + selectSettingsNotificationsExcludedTypes, + selectSettingsNotificationsQuickFilterActive, +} from 'mastodon/selectors/settings'; +import type { AppDispatch } from 'mastodon/store'; +import { + createAppAsyncThunk, + createDataLoadingThunk, +} from 'mastodon/store/typed_functions'; + +import { importFetchedAccounts, importFetchedStatuses } from './importer'; +import { NOTIFICATIONS_FILTER_SET } from './notifications'; +import { saveSettings } from './settings'; + +function excludeAllTypesExcept(filter: string) { + return allNotificationTypes.filter((item) => item !== filter); +} + +function dispatchAssociatedRecords( + dispatch: AppDispatch, + notifications: ApiNotificationGroupJSON[] | ApiNotificationJSON[], +) { + const fetchedAccounts: ApiAccountJSON[] = []; + const fetchedStatuses: ApiStatusJSON[] = []; + + notifications.forEach((notification) => { + if ('sample_accounts' in notification) { + fetchedAccounts.push(...notification.sample_accounts); + } + + if (notification.type === 'admin.report') { + fetchedAccounts.push(notification.report.target_account); + } + + if (notification.type === 'moderation_warning') { + fetchedAccounts.push(notification.moderation_warning.target_account); + } + + if ( + 'status' in notification && + (notification.status as ApiStatusJSON | null) !== null + ) { + fetchedStatuses.push(notification.status); + } + }); + + if (fetchedAccounts.length > 0) + dispatch(importFetchedAccounts(fetchedAccounts)); + + if (fetchedStatuses.length > 0) + dispatch(importFetchedStatuses(fetchedStatuses)); +} + +export const fetchNotifications = createDataLoadingThunk( + 'notificationGroups/fetch', + async (_params, { getState }) => { + const activeFilter = + selectSettingsNotificationsQuickFilterActive(getState()); + + return apiFetchNotifications({ + exclude_types: + activeFilter === 'all' + ? selectSettingsNotificationsExcludedTypes(getState()) + : excludeAllTypesExcept(activeFilter), + }); + }, + ({ notifications }, { dispatch }) => { + dispatchAssociatedRecords(dispatch, notifications); + const payload: (ApiNotificationGroupJSON | NotificationGap)[] = + notifications; + + // TODO: might be worth not using gaps for that… + // if (nextLink) payload.push({ type: 'gap', loadUrl: nextLink.uri }); + if (notifications.length > 1) + payload.push({ type: 'gap', maxId: notifications.at(-1)?.page_min_id }); + + return payload; + // dispatch(submitMarkers()); + }, +); + +export const fetchNotificationsGap = createDataLoadingThunk( + 'notificationGroups/fetchGap', + async (params: { gap: NotificationGap }) => + apiFetchNotifications({ max_id: params.gap.maxId }), + + ({ notifications }, { dispatch }) => { + dispatchAssociatedRecords(dispatch, notifications); + + return { notifications }; + }, +); + +export const processNewNotificationForGroups = createAppAsyncThunk( + 'notificationGroups/processNew', + (notification: ApiNotificationJSON, { dispatch }) => { + dispatchAssociatedRecords(dispatch, [notification]); + + return notification; + }, +); + +export const loadPending = createAction('notificationGroups/loadPending'); + +export const updateScrollPosition = createAction<{ top: boolean }>( + 'notificationGroups/updateScrollPosition', +); + +export const setNotificationsFilter = createAppAsyncThunk( + 'notifications/filter/set', + ({ filterType }: { filterType: string }, { dispatch }) => { + dispatch({ + type: NOTIFICATIONS_FILTER_SET, + path: ['notifications', 'quickFilter', 'active'], + value: filterType, + }); + // dispatch(expandNotifications({ forceLoad: true })); + void dispatch(fetchNotifications()); + dispatch(saveSettings()); + }, +); + +export const clearNotifications = createDataLoadingThunk( + 'notifications/clear', + () => apiClearNotifications(), +); + +export const markNotificationsAsRead = createAction( + 'notificationGroups/markAsRead', +); + +export const mountNotifications = createAction('notificationGroups/mount'); +export const unmountNotifications = createAction('notificationGroups/unmount'); diff --git a/app/javascript/mastodon/actions/notifications.js b/app/javascript/mastodon/actions/notifications.js index 08f85475da6645..cc71323ab9c2af 100644 --- a/app/javascript/mastodon/actions/notifications.js +++ b/app/javascript/mastodon/actions/notifications.js @@ -33,7 +33,6 @@ export const NOTIFICATIONS_EXPAND_FAIL = 'NOTIFICATIONS_EXPAND_FAIL'; export const NOTIFICATIONS_FILTER_SET = 'NOTIFICATIONS_FILTER_SET'; -export const NOTIFICATIONS_CLEAR = 'NOTIFICATIONS_CLEAR'; export const NOTIFICATIONS_SCROLL_TOP = 'NOTIFICATIONS_SCROLL_TOP'; export const NOTIFICATIONS_LOAD_PENDING = 'NOTIFICATIONS_LOAD_PENDING'; @@ -186,7 +185,7 @@ const noOp = () => {}; let expandNotificationsController = new AbortController(); -export function expandNotifications({ maxId, forceLoad } = {}, done = noOp) { +export function expandNotifications({ maxId, forceLoad = false } = {}, done = noOp) { return (dispatch, getState) => { const activeFilter = getState().getIn(['settings', 'notifications', 'quickFilter', 'active']); const notifications = getState().get('notifications'); @@ -274,16 +273,6 @@ export function expandNotificationsFail(error, isLoadingMore) { }; } -export function clearNotifications() { - return (dispatch) => { - dispatch({ - type: NOTIFICATIONS_CLEAR, - }); - - api().post('/api/v1/notifications/clear'); - }; -} - export function scrollTopNotifications(top) { return { type: NOTIFICATIONS_SCROLL_TOP, diff --git a/app/javascript/mastodon/actions/notifications_migration.tsx b/app/javascript/mastodon/actions/notifications_migration.tsx new file mode 100644 index 00000000000000..f856e56828f11f --- /dev/null +++ b/app/javascript/mastodon/actions/notifications_migration.tsx @@ -0,0 +1,18 @@ +import { createAppAsyncThunk } from 'mastodon/store'; + +import { fetchNotifications } from './notification_groups'; +import { expandNotifications } from './notifications'; + +export const initializeNotifications = createAppAsyncThunk( + 'notifications/initialize', + (_, { dispatch, getState }) => { + // eslint-disable-next-line @typescript-eslint/no-unsafe-call, @typescript-eslint/no-unsafe-member-access + const enableBeta = getState().settings.getIn( + ['notifications', 'groupingBeta'], + false, + ) as boolean; + + if (enableBeta) void dispatch(fetchNotifications()); + else dispatch(expandNotifications()); + }, +); diff --git a/app/javascript/mastodon/actions/notifications_typed.ts b/app/javascript/mastodon/actions/notifications_typed.ts index 176362f4b1edd4..88d942d45e54b5 100644 --- a/app/javascript/mastodon/actions/notifications_typed.ts +++ b/app/javascript/mastodon/actions/notifications_typed.ts @@ -1,11 +1,6 @@ import { createAction } from '@reduxjs/toolkit'; -import type { ApiAccountJSON } from '../api_types/accounts'; -// To be replaced once ApiNotificationJSON type exists -interface FakeApiNotificationJSON { - type: string; - account: ApiAccountJSON; -} +import type { ApiNotificationJSON } from 'mastodon/api_types/notifications'; export const notificationsUpdate = createAction( 'notifications/update', @@ -13,7 +8,7 @@ export const notificationsUpdate = createAction( playSound, ...args }: { - notification: FakeApiNotificationJSON; + notification: ApiNotificationJSON; usePendingItems: boolean; playSound: boolean; }) => ({ diff --git a/app/javascript/mastodon/actions/statuses.js b/app/javascript/mastodon/actions/statuses.js index ec07f2295784ad..54b2e02b2a0348 100644 --- a/app/javascript/mastodon/actions/statuses.js +++ b/app/javascript/mastodon/actions/statuses.js @@ -1,3 +1,5 @@ +import { browserHistory } from 'mastodon/components/router'; + import api from '../api'; import { ensureComposeIsVisible, setComposeToStatus } from './compose'; @@ -95,7 +97,7 @@ export function redraft(status, raw_text) { }; } -export const editStatus = (id, routerHistory) => (dispatch, getState) => { +export const editStatus = (id) => (dispatch, getState) => { let status = getState().getIn(['statuses', id]); if (status.get('poll')) { @@ -106,7 +108,7 @@ export const editStatus = (id, routerHistory) => (dispatch, getState) => { api().get(`/api/v1/statuses/${id}/source`).then(response => { dispatch(fetchStatusSourceSuccess()); - ensureComposeIsVisible(getState, routerHistory); + ensureComposeIsVisible(getState); dispatch(setComposeToStatus(status, response.data.text, response.data.spoiler_text)); }).catch(error => { dispatch(fetchStatusSourceFail(error)); @@ -126,7 +128,7 @@ export const fetchStatusSourceFail = error => ({ error, }); -export function deleteStatus(id, routerHistory, withRedraft = false) { +export function deleteStatus(id, withRedraft = false) { return (dispatch, getState) => { let status = getState().getIn(['statuses', id]); @@ -143,7 +145,7 @@ export function deleteStatus(id, routerHistory, withRedraft = false) { if (withRedraft) { dispatch(redraft(status, response.data.text)); - ensureComposeIsVisible(getState, routerHistory); + ensureComposeIsVisible(getState); } }).catch(error => { dispatch(deleteStatusFail(id, error)); @@ -311,6 +313,21 @@ export function revealStatus(ids) { }; } +export function toggleStatusSpoilers(statusId) { + return (dispatch, getState) => { + const status = getState().statuses.get(statusId); + + if (!status) + return; + + if (status.get('hidden')) { + dispatch(revealStatus(statusId)); + } else { + dispatch(hideStatus(statusId)); + } + }; +} + export function toggleStatusCollapse(id, isCollapsed) { return { type: STATUS_COLLAPSE, @@ -356,3 +373,15 @@ export const updateEmojiReaction = (emoji_reaction) => ({ type: STATUS_EMOJI_REACTION_UPDATE, emoji_reaction, }); + +export const navigateToStatus = (statusId) => { + return (_dispatch, getState) => { + const state = getState(); + const accountId = state.statuses.getIn([statusId, 'account']); + const acct = state.accounts.getIn([accountId, 'acct']); + + if (acct) { + browserHistory.push(`/@${acct}/${statusId}`); + } + }; +}; diff --git a/app/javascript/mastodon/actions/streaming.js b/app/javascript/mastodon/actions/streaming.js index 9d87bb32865536..6ee9ac687b7fd6 100644 --- a/app/javascript/mastodon/actions/streaming.js +++ b/app/javascript/mastodon/actions/streaming.js @@ -10,6 +10,7 @@ import { deleteAnnouncement, } from './announcements'; import { updateConversations } from './conversations'; +import { processNewNotificationForGroups } from './notification_groups'; import { updateNotifications, expandNotifications, updateEmojiReactions } from './notifications'; import { updateStatus } from './statuses'; import { @@ -99,10 +100,16 @@ export const connectTimelineStream = (timelineId, channelName, params = {}, opti case 'delete': dispatch(deleteFromTimelines(data.payload)); break; - case 'notification': + case 'notification': { // @ts-expect-error - dispatch(updateNotifications(JSON.parse(data.payload), messages, locale)); + const notificationJSON = JSON.parse(data.payload); + dispatch(updateNotifications(notificationJSON, messages, locale)); + // TODO: remove this once the groups feature replaces the previous one + if(getState().notificationGroups.groups.length > 0) { + dispatch(processNewNotificationForGroups(notificationJSON)); + } break; + } case 'emoji_reaction': // @ts-expect-error dispatch(updateEmojiReactions(JSON.parse(data.payload))); diff --git a/app/javascript/mastodon/api/notifications.ts b/app/javascript/mastodon/api/notifications.ts new file mode 100644 index 00000000000000..82ee05ab5bab3e --- /dev/null +++ b/app/javascript/mastodon/api/notifications.ts @@ -0,0 +1,33 @@ +import api, { apiRequest, getLinks } from 'mastodon/api'; +import type { ApiNotificationGroupJSON } from 'mastodon/api_types/notifications'; +import type { ApiStatusJSON } from 'mastodon/api_types/statuses'; + +const exceptInvalidNotifications = ( + notifications: ApiNotificationGroupJSON[], +) => { + return notifications.filter((n) => { + if ('status' in n) { + return (n.status as ApiStatusJSON | null) !== null; + } + return true; + }); +}; + +export const apiFetchNotifications = async (params?: { + exclude_types?: string[]; + max_id?: string; +}) => { + const response = await api().request({ + method: 'GET', + url: '/api/v2_alpha/notifications', + params, + }); + + return { + notifications: exceptInvalidNotifications(response.data), + links: getLinks(response), + }; +}; + +export const apiClearNotifications = () => + apiRequest('POST', 'v1/notifications/clear'); diff --git a/app/javascript/mastodon/api_types/notifications.ts b/app/javascript/mastodon/api_types/notifications.ts new file mode 100644 index 00000000000000..c510d6bba52796 --- /dev/null +++ b/app/javascript/mastodon/api_types/notifications.ts @@ -0,0 +1,149 @@ +// See app/serializers/rest/notification_group_serializer.rb + +import type { AccountWarningAction } from 'mastodon/models/notification_group'; + +import type { ApiAccountJSON } from './accounts'; +import type { ApiReportJSON } from './reports'; +import type { ApiStatusJSON } from './statuses'; + +// See app/model/notification.rb +export const allNotificationTypes = [ + 'follow', + 'follow_request', + 'favourite', + 'emoji_reaction', + 'reblog', + 'mention', + 'status_reference', + 'poll', + 'status', + 'update', + 'admin.sign_up', + 'admin.report', + 'moderation_warning', + 'severed_relationships', +]; + +export type NotificationWithStatusType = + | 'favourite' + | 'emoji_reaction' + | 'reblog' + | 'status' + | 'mention' + | 'status_reference' + | 'poll' + | 'update'; + +export type NotificationType = + | NotificationWithStatusType + | 'follow' + | 'follow_request' + | 'moderation_warning' + | 'severed_relationships' + | 'admin.sign_up' + | 'admin.report'; + +export interface BaseNotificationJSON { + id: string; + type: NotificationType; + created_at: string; + group_key: string; + account: ApiAccountJSON; +} + +export interface BaseNotificationGroupJSON { + group_key: string; + notifications_count: number; + type: NotificationType; + sample_accounts: ApiAccountJSON[]; + latest_page_notification_at: string; // FIXME: This will only be present if the notification group is returned in a paginated list, not requested directly + most_recent_notification_id: string; + page_min_id?: string; + page_max_id?: string; +} + +interface NotificationGroupWithStatusJSON extends BaseNotificationGroupJSON { + type: NotificationWithStatusType; + status: ApiStatusJSON; +} + +interface NotificationWithStatusJSON extends BaseNotificationJSON { + type: NotificationWithStatusType; + status: ApiStatusJSON; +} + +interface ReportNotificationGroupJSON extends BaseNotificationGroupJSON { + type: 'admin.report'; + report: ApiReportJSON; +} + +interface ReportNotificationJSON extends BaseNotificationJSON { + type: 'admin.report'; + report: ApiReportJSON; +} + +type SimpleNotificationTypes = 'follow' | 'follow_request' | 'admin.sign_up'; +interface SimpleNotificationGroupJSON extends BaseNotificationGroupJSON { + type: SimpleNotificationTypes; +} + +interface SimpleNotificationJSON extends BaseNotificationJSON { + type: SimpleNotificationTypes; +} + +export interface ApiAccountWarningJSON { + id: string; + action: AccountWarningAction; + text: string; + status_ids: string[]; + created_at: string; + target_account: ApiAccountJSON; + appeal: unknown; +} + +interface ModerationWarningNotificationGroupJSON + extends BaseNotificationGroupJSON { + type: 'moderation_warning'; + moderation_warning: ApiAccountWarningJSON; +} + +interface ModerationWarningNotificationJSON extends BaseNotificationJSON { + type: 'moderation_warning'; + moderation_warning: ApiAccountWarningJSON; +} + +export interface ApiAccountRelationshipSeveranceEventJSON { + id: string; + type: 'account_suspension' | 'domain_block' | 'user_domain_block'; + purged: boolean; + target_name: string; + followers_count: number; + following_count: number; + created_at: string; +} + +interface AccountRelationshipSeveranceNotificationGroupJSON + extends BaseNotificationGroupJSON { + type: 'severed_relationships'; + event: ApiAccountRelationshipSeveranceEventJSON; +} + +interface AccountRelationshipSeveranceNotificationJSON + extends BaseNotificationJSON { + type: 'severed_relationships'; + event: ApiAccountRelationshipSeveranceEventJSON; +} + +export type ApiNotificationJSON = + | SimpleNotificationJSON + | ReportNotificationJSON + | AccountRelationshipSeveranceNotificationJSON + | NotificationWithStatusJSON + | ModerationWarningNotificationJSON; + +export type ApiNotificationGroupJSON = + | SimpleNotificationGroupJSON + | ReportNotificationGroupJSON + | AccountRelationshipSeveranceNotificationGroupJSON + | NotificationGroupWithStatusJSON + | ModerationWarningNotificationGroupJSON; diff --git a/app/javascript/mastodon/api_types/reports.ts b/app/javascript/mastodon/api_types/reports.ts new file mode 100644 index 00000000000000..b11cfdd2eb59c8 --- /dev/null +++ b/app/javascript/mastodon/api_types/reports.ts @@ -0,0 +1,16 @@ +import type { ApiAccountJSON } from './accounts'; + +export type ReportCategory = 'other' | 'spam' | 'legal' | 'violation'; + +export interface ApiReportJSON { + id: string; + action_taken: unknown; + action_taken_at: unknown; + category: ReportCategory; + comment: string; + forwarded: boolean; + created_at: string; + status_ids: string[]; + rule_ids: string[]; + target_account: ApiAccountJSON; +} diff --git a/app/javascript/mastodon/components/__tests__/hashtag_bar.tsx b/app/javascript/mastodon/components/__tests__/hashtag_bar.tsx index b7225fc92e01e4..f86c1a2a6bc5b5 100644 --- a/app/javascript/mastodon/components/__tests__/hashtag_bar.tsx +++ b/app/javascript/mastodon/components/__tests__/hashtag_bar.tsx @@ -165,7 +165,7 @@ describe('computeHashtagBarForStatus', () => { ); }); - it('puts the hashtags in the bar if a status content has hashtags in the only line and has a media', () => { + it('does not put the hashtags in the bar if a status content has hashtags in the only line and has a media', () => { const status = createStatus( '

This is my content! #hashtag

', ['hashtag'], diff --git a/app/javascript/mastodon/components/load_gap.tsx b/app/javascript/mastodon/components/load_gap.tsx index 1d4193a35951ab..544b5e1461b17f 100644 --- a/app/javascript/mastodon/components/load_gap.tsx +++ b/app/javascript/mastodon/components/load_gap.tsx @@ -9,18 +9,18 @@ const messages = defineMessages({ load_more: { id: 'status.load_more', defaultMessage: 'Load more' }, }); -interface Props { +interface Props { disabled: boolean; - maxId: string; - onClick: (maxId: string) => void; + param: T; + onClick: (params: T) => void; } -export const LoadGap: React.FC = ({ disabled, maxId, onClick }) => { +export const LoadGap = ({ disabled, param, onClick }: Props) => { const intl = useIntl(); const handleClick = useCallback(() => { - onClick(maxId); - }, [maxId, onClick]); + onClick(param); + }, [param, onClick]); return ( + + + ); + } + if (featured) { prepend = (
@@ -454,7 +476,7 @@ class Status extends ImmutablePureComponent { } if (this.state.forceFilter === undefined ? matchedFilters : this.state.forceFilter) { - const minHandlers = muted ? {} : { + const minHandlers = this.props.muted ? {} : { moveUp: this.handleHotkeyMoveUp, moveDown: this.handleHotkeyMoveDown, }; @@ -511,7 +533,7 @@ class Status extends ImmutablePureComponent { } else if (status.get('media_attachments').size > 0) { const language = status.getIn(['translation', 'language']) || status.get('language'); - if (muted) { + if (this.props.muted) { media = ( ); } - } else if (status.get('card') && !muted) { + } else if (status.get('card') && !this.props.muted) { media = ( ; + } else { + statusAvatar = ; + } + const {statusContentProps, hashtagBar} = getHashtagBarForStatus(status); const expanded = !status.get('hidden') || status.get('spoiler_text').length === 0; @@ -620,14 +649,14 @@ class Status extends ImmutablePureComponent { const withReference = (!withQuote && status.get('status_references_count') > 0) ? : null; const withExpiration = status.get('expires_at') ? : null; - const quote = !muted && !withoutQuote && status.get('quote_id') && (['public', 'community'].includes(contextType) ? isShowItem('quote_in_public') : isShowItem('quote_in_home')) && ; + const quote = !this.props.muted && !withoutQuote && status.get('quote_id') && (['public', 'community'].includes(contextType) ? isShowItem('quote_in_public') : isShowItem('quote_in_home')) && ; return ( - -
- {prepend} + +
+ {!skipPrepend && prepend} -
+
{(connectReply || connectUp || connectToRoot) &&
} {/* eslint-disable-next-line jsx-a11y/no-static-element-interactions */} diff --git a/app/javascript/mastodon/components/status_action_bar.jsx b/app/javascript/mastodon/components/status_action_bar.jsx index 1a38189e109c7b..b7e47c7dcb1f12 100644 --- a/app/javascript/mastodon/components/status_action_bar.jsx +++ b/app/javascript/mastodon/components/status_action_bar.jsx @@ -134,7 +134,7 @@ class StatusActionBar extends ImmutablePureComponent { const { signedIn } = this.props.identity; if (signedIn) { - this.props.onReply(this.props.status, this.props.history); + this.props.onReply(this.props.status); } else { this.props.onInteractionModal('reply', this.props.status); } @@ -201,15 +201,15 @@ class StatusActionBar extends ImmutablePureComponent { }; handleDeleteClick = () => { - this.props.onDelete(this.props.status, this.props.history); + this.props.onDelete(this.props.status); }; handleRedraftClick = () => { - this.props.onDelete(this.props.status, this.props.history, true); + this.props.onDelete(this.props.status, true); }; handleEditClick = () => { - this.props.onEdit(this.props.status, this.props.history); + this.props.onEdit(this.props.status); }; handlePinClick = () => { @@ -217,11 +217,11 @@ class StatusActionBar extends ImmutablePureComponent { }; handleMentionClick = () => { - this.props.onMention(this.props.status.get('account'), this.props.history); + this.props.onMention(this.props.status.get('account')); }; handleDirectClick = () => { - this.props.onDirect(this.props.status.get('account'), this.props.history); + this.props.onDirect(this.props.status.get('account')); }; handleMuteClick = () => { diff --git a/app/javascript/mastodon/components/status_list.jsx b/app/javascript/mastodon/components/status_list.jsx index fee6675faa2906..c6cacbd2b27285 100644 --- a/app/javascript/mastodon/components/status_list.jsx +++ b/app/javascript/mastodon/components/status_list.jsx @@ -107,7 +107,7 @@ export default class StatusList extends ImmutablePureComponent { 0 ? statusIds.get(index - 1) : null} + param={index > 0 ? statusIds.get(index - 1) : null} onClick={onLoadMore} /> ); diff --git a/app/javascript/mastodon/containers/status_container.jsx b/app/javascript/mastodon/containers/status_container.jsx index 74490a252dae83..c2d1f6c28d42da 100644 --- a/app/javascript/mastodon/containers/status_container.jsx +++ b/app/javascript/mastodon/containers/status_container.jsx @@ -22,13 +22,11 @@ import { initAddFilter, } from '../actions/filters'; import { - reblog, - favourite, emojiReact, - bookmark, - unreblog, - unfavourite, unEmojiReact, + toggleReblog, + toggleFavourite, + bookmark, unbookmark, pin, unpin, @@ -41,15 +39,14 @@ import { muteStatus, unmuteStatus, deleteStatus, - hideStatus, - revealStatus, + toggleStatusSpoilers, toggleStatusCollapse, editStatus, translateStatus, undoStatusTranslation, } from '../actions/statuses'; import Status from '../components/status'; -import { boostModal, deleteModal } from '../initial_state'; +import { deleteModal } from '../initial_state'; import { makeGetStatus, makeGetPictureInPicture } from '../selectors'; const messages = defineMessages({ @@ -81,7 +78,7 @@ const mapDispatchToProps = (dispatch, { intl, contextType }) => ({ contextType, - onReply (status, router) { + onReply (status) { dispatch((_, getState) => { let state = getState(); @@ -91,28 +88,16 @@ const mapDispatchToProps = (dispatch, { intl, contextType }) => ({ modalProps: { message: intl.formatMessage(messages.replyMessage), confirm: intl.formatMessage(messages.replyConfirm), - onConfirm: () => dispatch(replyCompose(status, router)) }, + onConfirm: () => dispatch(replyCompose(status)) }, })); } else { - dispatch(replyCompose(status, router)); + dispatch(replyCompose(status)); } }); }, - onModalReblog (status, privacy) { - if (status.get('reblogged')) { - dispatch(unreblog({ statusId: status.get('id') })); - } else { - dispatch(reblog({ statusId: status.get('id'), visibility: privacy })); - } - }, - onReblog (status, e) { - if ((e && e.shiftKey) || !boostModal) { - this.onModalReblog(status); - } else { - dispatch(openModal({ modalType: 'BOOST', modalProps: { status, onReblog: this.onModalReblog } })); - } + dispatch(toggleReblog(status.get('id'), e.shiftKey)); }, onReblogForceModal (status) { @@ -120,11 +105,7 @@ const mapDispatchToProps = (dispatch, { intl, contextType }) => ({ }, onFavourite (status) { - if (status.get('favourited')) { - dispatch(unfavourite(status)); - } else { - dispatch(favourite(status)); - } + dispatch(toggleFavourite(status.get('id'))); }, onEmojiReact (status, emoji) { @@ -170,22 +151,22 @@ const mapDispatchToProps = (dispatch, { intl, contextType }) => ({ })); }, - onDelete (status, history, withRedraft = false) { + onDelete (status, withRedraft = false) { if (!deleteModal) { - dispatch(deleteStatus(status.get('id'), history, withRedraft)); + dispatch(deleteStatus(status.get('id'), withRedraft)); } else { dispatch(openModal({ modalType: 'CONFIRM', modalProps: { message: intl.formatMessage(withRedraft ? messages.redraftMessage : messages.deleteMessage), confirm: intl.formatMessage(withRedraft ? messages.redraftConfirm : messages.deleteConfirm), - onConfirm: () => dispatch(deleteStatus(status.get('id'), history, withRedraft)), + onConfirm: () => dispatch(deleteStatus(status.get('id'), withRedraft)), }, })); } }, - onEdit (status, history) { + onEdit (status) { dispatch((_, getState) => { let state = getState(); if (state.getIn(['compose', 'text']).trim().length !== 0) { @@ -194,11 +175,11 @@ const mapDispatchToProps = (dispatch, { intl, contextType }) => ({ modalProps: { message: intl.formatMessage(messages.editMessage), confirm: intl.formatMessage(messages.editConfirm), - onConfirm: () => dispatch(editStatus(status.get('id'), history)), + onConfirm: () => dispatch(editStatus(status.get('id'))), }, })); } else { - dispatch(editStatus(status.get('id'), history)); + dispatch(editStatus(status.get('id'))); } }); }, @@ -219,12 +200,12 @@ const mapDispatchToProps = (dispatch, { intl, contextType }) => ({ } }, - onDirect (account, router) { - dispatch(directCompose(account, router)); + onDirect (account) { + dispatch(directCompose(account)); }, - onMention (account, router) { - dispatch(mentionCompose(account, router)); + onMention (account) { + dispatch(mentionCompose(account)); }, onOpenMedia (statusId, media, index, lang) { @@ -275,11 +256,7 @@ const mapDispatchToProps = (dispatch, { intl, contextType }) => ({ }, onToggleHidden (status) { - if (status.get('hidden')) { - dispatch(revealStatus(status.get('id'))); - } else { - dispatch(hideStatus(status.get('id'))); - } + dispatch(toggleStatusSpoilers(status.get('id'))); }, onToggleCollapsed (status, isCollapsed) { diff --git a/app/javascript/mastodon/features/account_timeline/components/header.jsx b/app/javascript/mastodon/features/account_timeline/components/header.jsx index 8a99a3991f429f..d49655878804dd 100644 --- a/app/javascript/mastodon/features/account_timeline/components/header.jsx +++ b/app/javascript/mastodon/features/account_timeline/components/header.jsx @@ -2,13 +2,11 @@ import PropTypes from 'prop-types'; import { FormattedMessage } from 'react-intl'; -import { NavLink, withRouter } from 'react-router-dom'; +import { NavLink } from 'react-router-dom'; import ImmutablePropTypes from 'react-immutable-proptypes'; import ImmutablePureComponent from 'react-immutable-pure-component'; -import { WithRouterPropTypes } from 'mastodon/utils/react_router'; - import InnerHeader from '../../account/components/header'; import MemorialNote from './memorial_note'; @@ -40,7 +38,6 @@ class Header extends ImmutablePureComponent { hideTabs: PropTypes.bool, domain: PropTypes.string.isRequired, hidden: PropTypes.bool, - ...WithRouterPropTypes, }; handleFollow = () => { @@ -52,11 +49,11 @@ class Header extends ImmutablePureComponent { }; handleMention = () => { - this.props.onMention(this.props.account, this.props.history); + this.props.onMention(this.props.account); }; handleDirect = () => { - this.props.onDirect(this.props.account, this.props.history); + this.props.onDirect(this.props.account); }; handleReport = () => { @@ -175,4 +172,4 @@ class Header extends ImmutablePureComponent { } -export default withRouter(Header); +export default Header; diff --git a/app/javascript/mastodon/features/account_timeline/containers/header_container.jsx b/app/javascript/mastodon/features/account_timeline/containers/header_container.jsx index 1b1c1b3db914a3..8b05d42edc71e5 100644 --- a/app/javascript/mastodon/features/account_timeline/containers/header_container.jsx +++ b/app/javascript/mastodon/features/account_timeline/containers/header_container.jsx @@ -78,12 +78,12 @@ const mapDispatchToProps = (dispatch, { intl }) => ({ } }, - onMention (account, router) { - dispatch(mentionCompose(account, router)); + onMention (account) { + dispatch(mentionCompose(account)); }, - onDirect (account, router) { - dispatch(directCompose(account, router)); + onDirect (account) { + dispatch(directCompose(account)); }, onReblogToggle (account) { diff --git a/app/javascript/mastodon/features/compose/components/compose_form.jsx b/app/javascript/mastodon/features/compose/components/compose_form.jsx index 43dcb3d2c1feb7..4776e3e20c82ab 100644 --- a/app/javascript/mastodon/features/compose/components/compose_form.jsx +++ b/app/javascript/mastodon/features/compose/components/compose_form.jsx @@ -10,9 +10,6 @@ import ImmutablePureComponent from 'react-immutable-pure-component'; import { length } from 'stringz'; -import { WithOptionalRouterPropTypes, withOptionalRouter } from 'mastodon/utils/react_router'; - - import AutosuggestInput from '../../../components/autosuggest_input'; import AutosuggestTextarea from '../../../components/autosuggest_textarea'; import { Button } from '../../../components/button'; @@ -81,7 +78,6 @@ class ComposeForm extends ImmutablePureComponent { lang: PropTypes.string, circleId: PropTypes.string, maxChars: PropTypes.number, - ...WithOptionalRouterPropTypes }; static defaultProps = { @@ -130,7 +126,7 @@ class ComposeForm extends ImmutablePureComponent { return; } - this.props.onSubmit(this.props.history || null); + this.props.onSubmit(); if (e) { e.preventDefault(); @@ -349,4 +345,4 @@ class ComposeForm extends ImmutablePureComponent { } -export default withOptionalRouter(injectIntl(ComposeForm)); +export default injectIntl(ComposeForm); diff --git a/app/javascript/mastodon/features/compose/components/edit_indicator.jsx b/app/javascript/mastodon/features/compose/components/edit_indicator.jsx index cc37d2d7d8127b..106ff7bdaa41f6 100644 --- a/app/javascript/mastodon/features/compose/components/edit_indicator.jsx +++ b/app/javascript/mastodon/features/compose/components/edit_indicator.jsx @@ -13,6 +13,7 @@ import { cancelReplyCompose } from 'mastodon/actions/compose'; import { Icon } from 'mastodon/components/icon'; import { IconButton } from 'mastodon/components/icon_button'; import { RelativeTimestamp } from 'mastodon/components/relative_timestamp'; +import { EmbeddedStatusContent } from 'mastodon/features/notifications_v2/components/embedded_status_content'; const messages = defineMessages({ cancel: { id: 'reply_indicator.cancel', defaultMessage: 'Cancel' }, @@ -33,8 +34,6 @@ export const EditIndicator = () => { return null; } - const content = { __html: status.get('contentHtml') }; - return (
@@ -49,7 +48,12 @@ export const EditIndicator = () => {
-
+ {(status.get('poll') || status.get('media_attachments').size > 0) && (
diff --git a/app/javascript/mastodon/features/compose/components/reply_indicator.jsx b/app/javascript/mastodon/features/compose/components/reply_indicator.jsx index b7959e211d6e45..cf5bae2e07415f 100644 --- a/app/javascript/mastodon/features/compose/components/reply_indicator.jsx +++ b/app/javascript/mastodon/features/compose/components/reply_indicator.jsx @@ -9,6 +9,7 @@ import PhotoLibraryIcon from '@/material-icons/400-24px/photo_library.svg?react' import { Avatar } from 'mastodon/components/avatar'; import { DisplayName } from 'mastodon/components/display_name'; import { Icon } from 'mastodon/components/icon'; +import { EmbeddedStatusContent } from 'mastodon/features/notifications_v2/components/embedded_status_content'; export const ReplyIndicator = () => { const inReplyToId = useSelector(state => state.getIn(['compose', 'in_reply_to'])); @@ -19,8 +20,6 @@ export const ReplyIndicator = () => { return null; } - const content = { __html: status.get('contentHtml') }; - return (
@@ -34,7 +33,12 @@ export const ReplyIndicator = () => { -
+ {(status.get('poll') || status.get('media_attachments').size > 0) && (
diff --git a/app/javascript/mastodon/features/compose/containers/compose_form_container.js b/app/javascript/mastodon/features/compose/containers/compose_form_container.js index ae2759a93d7aee..4672ae5f681f02 100644 --- a/app/javascript/mastodon/features/compose/containers/compose_form_container.js +++ b/app/javascript/mastodon/features/compose/containers/compose_form_container.js @@ -41,8 +41,8 @@ const mapDispatchToProps = (dispatch) => ({ dispatch(changeCompose(text)); }, - onSubmit (router) { - dispatch(submitCompose(router)); + onSubmit () { + dispatch(submitCompose()); }, onClearSuggestions () { diff --git a/app/javascript/mastodon/features/direct_timeline/components/conversation.jsx b/app/javascript/mastodon/features/direct_timeline/components/conversation.jsx index a2b72f7162af04..326ea3e5ac4502 100644 --- a/app/javascript/mastodon/features/direct_timeline/components/conversation.jsx +++ b/app/javascript/mastodon/features/direct_timeline/components/conversation.jsx @@ -18,7 +18,7 @@ import ReplyIcon from '@/material-icons/400-24px/reply.svg?react'; import { replyCompose } from 'mastodon/actions/compose'; import { markConversationRead, deleteConversation } from 'mastodon/actions/conversations'; import { openModal } from 'mastodon/actions/modal'; -import { muteStatus, unmuteStatus, revealStatus, hideStatus } from 'mastodon/actions/statuses'; +import { muteStatus, unmuteStatus, toggleStatusSpoilers } from 'mastodon/actions/statuses'; import AttachmentList from 'mastodon/components/attachment_list'; import AvatarComposite from 'mastodon/components/avatar_composite'; import { IconButton } from 'mastodon/components/icon_button'; @@ -108,14 +108,14 @@ export const Conversation = ({ conversation, scrollKey, onMoveUp, onMoveDown }) modalProps: { message: intl.formatMessage(messages.replyMessage), confirm: intl.formatMessage(messages.replyConfirm), - onConfirm: () => dispatch(replyCompose(lastStatus, history)), + onConfirm: () => dispatch(replyCompose(lastStatus)), }, })); } else { - dispatch(replyCompose(lastStatus, history)); + dispatch(replyCompose(lastStatus)); } }); - }, [dispatch, lastStatus, history, intl]); + }, [dispatch, lastStatus, intl]); const handleDelete = useCallback(() => { dispatch(deleteConversation(id)); @@ -138,11 +138,7 @@ export const Conversation = ({ conversation, scrollKey, onMoveUp, onMoveDown }) }, [dispatch, lastStatus]); const handleShowMore = useCallback(() => { - if (lastStatus.get('hidden')) { - dispatch(revealStatus(lastStatus.get('id'))); - } else { - dispatch(hideStatus(lastStatus.get('id'))); - } + dispatch(toggleStatusSpoilers(lastStatus.get('id'))); }, [dispatch, lastStatus]); if (!lastStatus) { diff --git a/app/javascript/mastodon/features/notifications/components/column_settings.jsx b/app/javascript/mastodon/features/notifications/components/column_settings.jsx index c5f404f0796d44..891845b2044e02 100644 --- a/app/javascript/mastodon/features/notifications/components/column_settings.jsx +++ b/app/javascript/mastodon/features/notifications/components/column_settings.jsx @@ -59,6 +59,7 @@ class ColumnSettings extends PureComponent { const filterAdvancedStr = ; const unreadMarkersShowStr = ; + const groupingShowStr = ; const alertStr = ; const showStr = ; const soundStr = ; @@ -110,6 +111,16 @@ class ColumnSettings extends PureComponent {
+
+

+ +

+ +
+ +
+
+

diff --git a/app/javascript/mastodon/features/notifications/components/filtered_notifications_banner.tsx b/app/javascript/mastodon/features/notifications/components/filtered_notifications_banner.tsx index 2c4b3b971752d9..be1ea2c556e1d2 100644 --- a/app/javascript/mastodon/features/notifications/components/filtered_notifications_banner.tsx +++ b/app/javascript/mastodon/features/notifications/components/filtered_notifications_banner.tsx @@ -35,7 +35,9 @@ export const FilteredNotificationsBanner: React.FC = () => { className='filtered-notifications-banner' to='/notifications/requests' > - +
+ +
diff --git a/app/javascript/mastodon/features/notifications/components/moderation_warning.tsx b/app/javascript/mastodon/features/notifications/components/moderation_warning.tsx index 2129f0d8ae75e0..e34c70488cf8ea 100644 --- a/app/javascript/mastodon/features/notifications/components/moderation_warning.tsx +++ b/app/javascript/mastodon/features/notifications/components/moderation_warning.tsx @@ -1,7 +1,10 @@ import { defineMessages, FormattedMessage, useIntl } from 'react-intl'; +import classNames from 'classnames'; + import GavelIcon from '@/material-icons/400-24px/gavel.svg?react'; import { Icon } from 'mastodon/components/icon'; +import type { AccountWarningAction } from 'mastodon/models/notification_group'; // This needs to be kept in sync with app/models/account_warning.rb const messages = defineMessages({ @@ -40,20 +43,18 @@ const messages = defineMessages({ }); interface Props { - action: - | 'none' - | 'disable' - | 'force_cw' - | 'mark_statuses_as_sensitive' - | 'delete_statuses' - | 'sensitive' - | 'silence' - | 'suspend'; + action: AccountWarningAction; id: string; - hidden: boolean; + hidden?: boolean; + unread?: boolean; } -export const ModerationWarning: React.FC = ({ action, id, hidden }) => { +export const ModerationWarning: React.FC = ({ + action, + id, + hidden, + unread, +}) => { const intl = useIntl(); if (hidden) { @@ -61,23 +62,32 @@ export const ModerationWarning: React.FC = ({ action, id, hidden }) => { } return ( - - +
+ +
-
); }; diff --git a/app/javascript/mastodon/features/notifications/components/notification.jsx b/app/javascript/mastodon/features/notifications/components/notification.jsx index 13d4a859744e73..a4bb98331c5b53 100644 --- a/app/javascript/mastodon/features/notifications/components/notification.jsx +++ b/app/javascript/mastodon/features/notifications/components/notification.jsx @@ -38,7 +38,7 @@ const messages = defineMessages({ emojiReaction: { id: 'notification.emoji_reaction', defaultMessage: '{name} reacted your status with emoji' }, follow: { id: 'notification.follow', defaultMessage: '{name} followed you' }, ownPoll: { id: 'notification.own_poll', defaultMessage: 'Your poll has ended' }, - poll: { id: 'notification.poll', defaultMessage: 'A poll you have voted in has ended' }, + poll: { id: 'notification.poll', defaultMessage: 'A poll you voted in has ended' }, reblog: { id: 'notification.reblog', defaultMessage: '{name} boosted your status' }, status: { id: 'notification.status', defaultMessage: '{name} just posted' }, listStatus: { id: 'notification.list_status', defaultMessage: '{name} post is added to {listName}' }, @@ -107,7 +107,7 @@ class Notification extends ImmutablePureComponent { e.preventDefault(); const { notification, onMention } = this.props; - onMention(notification.get('account'), this.props.history); + onMention(notification.get('account')); }; handleHotkeyFavourite = () => { @@ -452,7 +452,7 @@ class Notification extends ImmutablePureComponent { {ownPoll ? ( ) : ( - + )}
diff --git a/app/javascript/mastodon/features/notifications/components/relationships_severance_event.jsx b/app/javascript/mastodon/features/notifications/components/relationships_severance_event.jsx index 738159fc5a2ba8..3075aff31bad1b 100644 --- a/app/javascript/mastodon/features/notifications/components/relationships_severance_event.jsx +++ b/app/javascript/mastodon/features/notifications/components/relationships_severance_event.jsx @@ -2,6 +2,8 @@ import PropTypes from 'prop-types'; import { defineMessages, FormattedMessage, useIntl } from 'react-intl'; +import classNames from 'classnames'; + import HeartBrokenIcon from '@/material-icons/400-24px/heart_broken-fill.svg?react'; import { Icon } from 'mastodon/components/icon'; import { domain } from 'mastodon/initial_state'; @@ -13,7 +15,7 @@ const messages = defineMessages({ user_domain_block: { id: 'notification.relationships_severance_event.user_domain_block', defaultMessage: 'You have blocked {target}, removing {followersCount} of your followers and {followingCount, plural, one {# account} other {# accounts}} you follow.' }, }); -export const RelationshipsSeveranceEvent = ({ type, target, followingCount, followersCount, hidden }) => { +export const RelationshipsSeveranceEvent = ({ type, target, followingCount, followersCount, hidden, unread }) => { const intl = useIntl(); if (hidden) { @@ -21,14 +23,14 @@ export const RelationshipsSeveranceEvent = ({ type, target, followingCount, foll } return ( - - +
+
-
); }; @@ -42,4 +44,5 @@ RelationshipsSeveranceEvent.propTypes = { followersCount: PropTypes.number.isRequired, followingCount: PropTypes.number.isRequired, hidden: PropTypes.bool, + unread: PropTypes.bool, }; diff --git a/app/javascript/mastodon/features/notifications/containers/column_settings_container.js b/app/javascript/mastodon/features/notifications/containers/column_settings_container.js index 94383d0bb57ce2..2434c3982d582b 100644 --- a/app/javascript/mastodon/features/notifications/containers/column_settings_container.js +++ b/app/javascript/mastodon/features/notifications/containers/column_settings_container.js @@ -2,10 +2,13 @@ import { defineMessages, injectIntl } from 'react-intl'; import { connect } from 'react-redux'; +import { initializeNotifications } from 'mastodon/actions/notifications_migration'; + import { showAlert } from '../../../actions/alerts'; import { openModal } from '../../../actions/modal'; +import { clearNotifications } from '../../../actions/notification_groups'; import { updateNotificationsPolicy } from '../../../actions/notification_policies'; -import { setFilter, clearNotifications, requestBrowserPermission } from '../../../actions/notifications'; +import { setFilter, requestBrowserPermission } from '../../../actions/notifications'; import { changeAlerts as changePushNotifications } from '../../../actions/push_notifications'; import { changeSetting } from '../../../actions/settings'; import ColumnSettings from '../components/column_settings'; @@ -58,6 +61,9 @@ const mapDispatchToProps = (dispatch, { intl }) => ({ } else { dispatch(changeSetting(['notifications', ...path], checked)); } + } else if(path[0] === 'groupingBeta') { + dispatch(changeSetting(['notifications', ...path], checked)); + dispatch(initializeNotifications()); } else { dispatch(changeSetting(['notifications', ...path], checked)); } diff --git a/app/javascript/mastodon/features/notifications/containers/notification_container.js b/app/javascript/mastodon/features/notifications/containers/notification_container.js index 9cb25785134c16..54e0488dc25bc2 100644 --- a/app/javascript/mastodon/features/notifications/containers/notification_container.js +++ b/app/javascript/mastodon/features/notifications/containers/notification_container.js @@ -2,18 +2,13 @@ import { connect } from 'react-redux'; import { mentionCompose } from '../../../actions/compose'; import { - reblog, - favourite, - unreblog, - unfavourite, emojiReact, + toggleFavourite, + toggleReblog, } from '../../../actions/interactions'; -import { openModal } from '../../../actions/modal'; import { - hideStatus, - revealStatus, + toggleStatusSpoilers, } from '../../../actions/statuses'; -import { boostModal } from '../../../initial_state'; import { makeGetNotification, makeGetStatus, makeGetReport } from '../../../selectors'; import Notification from '../components/notification'; @@ -35,40 +30,20 @@ const makeMapStateToProps = () => { }; const mapDispatchToProps = dispatch => ({ - onMention: (account, router) => { - dispatch(mentionCompose(account, router)); - }, - - onModalReblog (status, privacy) { - dispatch(reblog({ statusId: status.get('id'), visibility: privacy })); + onMention: (account) => { + dispatch(mentionCompose(account)); }, onReblog (status, e) { - if (status.get('reblogged')) { - dispatch(unreblog({ statusId: status.get('id') })); - } else { - if (e.shiftKey || !boostModal) { - this.onModalReblog(status); - } else { - dispatch(openModal({ modalType: 'BOOST', modalProps: { status, onReblog: this.onModalReblog } })); - } - } + dispatch(toggleReblog(status.get('id'), e.shiftKey)); }, onReblogForceModal (status) { - if (status.get('reblogged')) { - dispatch(unreblog(status)); - } else { - dispatch(openModal({ modalType: 'BOOST', modalProps: { status, onReblog: this.onModalReblog } })); - } + dispatch(toggleReblog(status.get('id'), true, true)); }, onFavourite (status) { - if (status.get('favourited')) { - dispatch(unfavourite(status)); - } else { - dispatch(favourite(status)); - } + dispatch(toggleFavourite(status.get('id'))); }, onEmojiReact (status, emoji) { @@ -76,11 +51,7 @@ const mapDispatchToProps = dispatch => ({ }, onToggleHidden (status) { - if (status.get('hidden')) { - dispatch(revealStatus(status.get('id'))); - } else { - dispatch(hideStatus(status.get('id'))); - } + dispatch(toggleStatusSpoilers(status.get('id'))); }, }); diff --git a/app/javascript/mastodon/features/notifications/index.jsx b/app/javascript/mastodon/features/notifications/index.jsx index 54883096ef50af..f5ebe6fe91c0e5 100644 --- a/app/javascript/mastodon/features/notifications/index.jsx +++ b/app/javascript/mastodon/features/notifications/index.jsx @@ -202,7 +202,7 @@ class Notifications extends PureComponent { 0 ? notifications.getIn([index - 1, 'id']) : null} + param={index > 0 ? notifications.getIn([index - 1, 'id']) : null} onClick={this.handleLoadGap} /> ) : ( diff --git a/app/javascript/mastodon/features/notifications_v2/components/avatar_group.tsx b/app/javascript/mastodon/features/notifications_v2/components/avatar_group.tsx new file mode 100644 index 00000000000000..b5da8914a1da08 --- /dev/null +++ b/app/javascript/mastodon/features/notifications_v2/components/avatar_group.tsx @@ -0,0 +1,31 @@ +import { Link } from 'react-router-dom'; + +import { Avatar } from 'mastodon/components/avatar'; +import { NOTIFICATIONS_GROUP_MAX_AVATARS } from 'mastodon/models/notification_group'; +import { useAppSelector } from 'mastodon/store'; + +const AvatarWrapper: React.FC<{ accountId: string }> = ({ accountId }) => { + const account = useAppSelector((state) => state.accounts.get(accountId)); + + if (!account) return null; + + return ( + + + + ); +}; + +export const AvatarGroup: React.FC<{ accountIds: string[] }> = ({ + accountIds, +}) => ( +
+ {accountIds.slice(0, NOTIFICATIONS_GROUP_MAX_AVATARS).map((accountId) => ( + + ))} +
+); diff --git a/app/javascript/mastodon/features/notifications_v2/components/embedded_status.tsx b/app/javascript/mastodon/features/notifications_v2/components/embedded_status.tsx new file mode 100644 index 00000000000000..baec0161173ff3 --- /dev/null +++ b/app/javascript/mastodon/features/notifications_v2/components/embedded_status.tsx @@ -0,0 +1,159 @@ +import { useCallback, useRef } from 'react'; + +import { FormattedMessage } from 'react-intl'; + +import { useHistory } from 'react-router-dom'; + +import type { List as ImmutableList, RecordOf } from 'immutable'; + +import BarChart4BarsIcon from '@/material-icons/400-24px/bar_chart_4_bars.svg?react'; +import PhotoLibraryIcon from '@/material-icons/400-24px/photo_library.svg?react'; +import { Avatar } from 'mastodon/components/avatar'; +import { DisplayName } from 'mastodon/components/display_name'; +import { Icon } from 'mastodon/components/icon'; +import type { Status } from 'mastodon/models/status'; +import { useAppSelector } from 'mastodon/store'; + +import { EmbeddedStatusContent } from './embedded_status_content'; + +export type Mention = RecordOf<{ url: string; acct: string }>; + +export const EmbeddedStatus: React.FC<{ statusId: string }> = ({ + statusId, +}) => { + const history = useHistory(); + const clickCoordinatesRef = useRef<[number, number] | null>(); + + const status = useAppSelector( + (state) => state.statuses.get(statusId) as Status | undefined, + ); + + const account = useAppSelector((state) => + state.accounts.get(status?.get('account') as string), + ); + + const handleMouseDown = useCallback>( + ({ clientX, clientY }) => { + clickCoordinatesRef.current = [clientX, clientY]; + }, + [clickCoordinatesRef], + ); + + const handleMouseUp = useCallback>( + ({ clientX, clientY, target, button }) => { + const [startX, startY] = clickCoordinatesRef.current ?? [0, 0]; + const [deltaX, deltaY] = [ + Math.abs(clientX - startX), + Math.abs(clientY - startY), + ]; + + let element: HTMLDivElement | null = target as HTMLDivElement; + + while (element) { + if ( + element.localName === 'button' || + element.localName === 'a' || + element.localName === 'label' + ) { + return; + } + + element = element.parentNode as HTMLDivElement | null; + } + + if (deltaX + deltaY < 5 && button === 0 && account) { + history.push(`/@${account.acct}/${statusId}`); + } + + clickCoordinatesRef.current = null; + }, + [clickCoordinatesRef, statusId, account, history], + ); + + const handleMouseEnter = useCallback>( + ({ currentTarget }) => { + const emojis = + currentTarget.querySelectorAll('.custom-emoji'); + + for (const emoji of emojis) { + const newSrc = emoji.getAttribute('data-original'); + if (newSrc) emoji.src = newSrc; + } + }, + [], + ); + + const handleMouseLeave = useCallback>( + ({ currentTarget }) => { + const emojis = + currentTarget.querySelectorAll('.custom-emoji'); + + for (const emoji of emojis) { + const newSrc = emoji.getAttribute('data-static'); + if (newSrc) emoji.src = newSrc; + } + }, + [], + ); + + if (!status) { + return null; + } + + // Assign status attributes to variables with a forced type, as status is not yet properly typed + const contentHtml = status.get('contentHtml') as string; + const poll = status.get('poll'); + const language = status.get('language') as string; + const mentions = status.get('mentions') as ImmutableList; + const mediaAttachmentsSize = ( + status.get('media_attachments') as ImmutableList + ).size; + + return ( +
+
+ + +
+ + + + {(poll || mediaAttachmentsSize > 0) && ( +
+ {!!poll && ( + <> + + + + )} + {mediaAttachmentsSize > 0 && ( + <> + + + + )} +
+ )} +
+ ); +}; diff --git a/app/javascript/mastodon/features/notifications_v2/components/embedded_status_content.tsx b/app/javascript/mastodon/features/notifications_v2/components/embedded_status_content.tsx new file mode 100644 index 00000000000000..1a38be536ba6a8 --- /dev/null +++ b/app/javascript/mastodon/features/notifications_v2/components/embedded_status_content.tsx @@ -0,0 +1,93 @@ +import { useCallback } from 'react'; + +import { useHistory } from 'react-router-dom'; + +import type { List } from 'immutable'; + +import type { History } from 'history'; + +import type { Mention } from './embedded_status'; + +const handleMentionClick = ( + history: History, + mention: Mention, + e: MouseEvent, +) => { + if (e.button === 0 && !(e.ctrlKey || e.metaKey)) { + e.preventDefault(); + history.push(`/@${mention.get('acct')}`); + } +}; + +const handleHashtagClick = ( + history: History, + hashtag: string, + e: MouseEvent, +) => { + if (e.button === 0 && !(e.ctrlKey || e.metaKey)) { + e.preventDefault(); + history.push(`/tags/${hashtag.replace(/^#/, '')}`); + } +}; + +export const EmbeddedStatusContent: React.FC<{ + content: string; + mentions: List; + language: string; + className?: string; +}> = ({ content, mentions, language, className }) => { + const history = useHistory(); + + const handleContentRef = useCallback( + (node: HTMLDivElement | null) => { + if (!node) { + return; + } + + const links = node.querySelectorAll('a'); + + for (const link of links) { + if (link.classList.contains('status-link')) { + continue; + } + + link.classList.add('status-link'); + + const mention = mentions.find((item) => link.href === item.get('url')); + + if (mention) { + link.addEventListener( + 'click', + handleMentionClick.bind(null, history, mention), + false, + ); + link.setAttribute('title', `@${mention.get('acct')}`); + link.setAttribute('href', `/@${mention.get('acct')}`); + } else if ( + link.textContent?.[0] === '#' || + link.previousSibling?.textContent?.endsWith('#') + ) { + link.addEventListener( + 'click', + handleHashtagClick.bind(null, history, link.text), + false, + ); + link.setAttribute('href', `/tags/${link.text.replace(/^#/, '')}`); + } else { + link.setAttribute('title', link.href); + link.classList.add('unhandled-link'); + } + } + }, + [mentions, history], + ); + + return ( +
+ ); +}; diff --git a/app/javascript/mastodon/features/notifications_v2/components/names_list.tsx b/app/javascript/mastodon/features/notifications_v2/components/names_list.tsx new file mode 100644 index 00000000000000..3d70cc0b623260 --- /dev/null +++ b/app/javascript/mastodon/features/notifications_v2/components/names_list.tsx @@ -0,0 +1,51 @@ +import { FormattedMessage } from 'react-intl'; + +import { Link } from 'react-router-dom'; + +import { useAppSelector } from 'mastodon/store'; + +export const NamesList: React.FC<{ + accountIds: string[]; + total: number; + seeMoreHref?: string; +}> = ({ accountIds, total, seeMoreHref }) => { + const lastAccountId = accountIds[0] ?? '0'; + const account = useAppSelector((state) => state.accounts.get(lastAccountId)); + + if (!account) return null; + + const displayedName = ( + + + + ); + + if (total === 1) { + return displayedName; + } + + if (seeMoreHref) + return ( + {chunks}, + }} + /> + ); + + return ( + + ); +}; diff --git a/app/javascript/mastodon/features/notifications_v2/components/notification_admin_report.tsx b/app/javascript/mastodon/features/notifications_v2/components/notification_admin_report.tsx new file mode 100644 index 00000000000000..fda5798ae98b49 --- /dev/null +++ b/app/javascript/mastodon/features/notifications_v2/components/notification_admin_report.tsx @@ -0,0 +1,132 @@ +import { FormattedMessage, useIntl, defineMessages } from 'react-intl'; + +import classNames from 'classnames'; + +import FlagIcon from '@/material-icons/400-24px/flag-fill.svg?react'; +import { Icon } from 'mastodon/components/icon'; +import { RelativeTimestamp } from 'mastodon/components/relative_timestamp'; +import type { NotificationGroupAdminReport } from 'mastodon/models/notification_group'; +import { useAppSelector } from 'mastodon/store'; + +// This needs to be kept in sync with app/models/report.rb +const messages = defineMessages({ + other: { + id: 'report_notification.categories.other_sentence', + defaultMessage: 'other', + }, + spam: { + id: 'report_notification.categories.spam_sentence', + defaultMessage: 'spam', + }, + legal: { + id: 'report_notification.categories.legal_sentence', + defaultMessage: 'illegal content', + }, + violation: { + id: 'report_notification.categories.violation_sentence', + defaultMessage: 'rule violation', + }, +}); + +export const NotificationAdminReport: React.FC<{ + notification: NotificationGroupAdminReport; + unread?: boolean; +}> = ({ notification, notification: { report }, unread }) => { + const intl = useIntl(); + const targetAccount = useAppSelector((state) => + state.accounts.get(report.targetAccountId), + ); + const account = useAppSelector((state) => + state.accounts.get(notification.sampleAccountIds[0] ?? '0'), + ); + + if (!account || !targetAccount) return null; + + const values = { + name: ( + + ), + target: ( + + ), + category: intl.formatMessage(messages[report.category]), + count: report.status_ids.length, + }; + + let message; + + if (report.status_ids.length > 0) { + if (report.category === 'other') { + message = ( + + ); + } else { + message = ( + + ); + } + } else { + if (report.category === 'other') { + message = ( + + ); + } else { + message = ( + + ); + } + } + + return ( + +
+ +
+ +
+
+
+ {message} + +
+
+ + {report.comment.length > 0 && ( +
+ “{report.comment}” +
+ )} +
+
+ ); +}; diff --git a/app/javascript/mastodon/features/notifications_v2/components/notification_admin_sign_up.tsx b/app/javascript/mastodon/features/notifications_v2/components/notification_admin_sign_up.tsx new file mode 100644 index 00000000000000..9f7afc63f5b073 --- /dev/null +++ b/app/javascript/mastodon/features/notifications_v2/components/notification_admin_sign_up.tsx @@ -0,0 +1,31 @@ +import { FormattedMessage } from 'react-intl'; + +import PersonAddIcon from '@/material-icons/400-24px/person_add-fill.svg?react'; +import type { NotificationGroupAdminSignUp } from 'mastodon/models/notification_group'; + +import type { LabelRenderer } from './notification_group_with_status'; +import { NotificationGroupWithStatus } from './notification_group_with_status'; + +const labelRenderer: LabelRenderer = (values) => ( + +); + +export const NotificationAdminSignUp: React.FC<{ + notification: NotificationGroupAdminSignUp; + unread: boolean; +}> = ({ notification, unread }) => ( + +); diff --git a/app/javascript/mastodon/features/notifications_v2/components/notification_emoji_reaction.tsx b/app/javascript/mastodon/features/notifications_v2/components/notification_emoji_reaction.tsx new file mode 100644 index 00000000000000..61540d8cae21cf --- /dev/null +++ b/app/javascript/mastodon/features/notifications_v2/components/notification_emoji_reaction.tsx @@ -0,0 +1,47 @@ +import { FormattedMessage } from 'react-intl'; + +import EmojiReactionIcon from '@/material-icons/400-24px/mood.svg?react'; +import type { NotificationGroupEmojiReaction } from 'mastodon/models/notification_group'; +import { useAppSelector } from 'mastodon/store'; + +import type { LabelRenderer } from './notification_group_with_status'; +import { NotificationGroupWithStatus } from './notification_group_with_status'; + +const labelRenderer: LabelRenderer = (values) => ( + +); + +export const NotificationEmojiReaction: React.FC<{ + notification: NotificationGroupEmojiReaction; + unread: boolean; +}> = ({ notification, unread }) => { + const { statusId } = notification; + const statusAccount = useAppSelector( + (state) => + state.accounts.get(state.statuses.getIn([statusId, 'account']) as string) + ?.acct, + ); + + return ( + + ); +}; diff --git a/app/javascript/mastodon/features/notifications_v2/components/notification_favourite.tsx b/app/javascript/mastodon/features/notifications_v2/components/notification_favourite.tsx new file mode 100644 index 00000000000000..22838fe69bc0be --- /dev/null +++ b/app/javascript/mastodon/features/notifications_v2/components/notification_favourite.tsx @@ -0,0 +1,45 @@ +import { FormattedMessage } from 'react-intl'; + +import StarIcon from '@/material-icons/400-24px/star-fill.svg?react'; +import type { NotificationGroupFavourite } from 'mastodon/models/notification_group'; +import { useAppSelector } from 'mastodon/store'; + +import type { LabelRenderer } from './notification_group_with_status'; +import { NotificationGroupWithStatus } from './notification_group_with_status'; + +const labelRenderer: LabelRenderer = (values) => ( + +); + +export const NotificationFavourite: React.FC<{ + notification: NotificationGroupFavourite; + unread: boolean; +}> = ({ notification, unread }) => { + const { statusId } = notification; + const statusAccount = useAppSelector( + (state) => + state.accounts.get(state.statuses.getIn([statusId, 'account']) as string) + ?.acct, + ); + + return ( + + ); +}; diff --git a/app/javascript/mastodon/features/notifications_v2/components/notification_follow.tsx b/app/javascript/mastodon/features/notifications_v2/components/notification_follow.tsx new file mode 100644 index 00000000000000..0ed96ae636c662 --- /dev/null +++ b/app/javascript/mastodon/features/notifications_v2/components/notification_follow.tsx @@ -0,0 +1,31 @@ +import { FormattedMessage } from 'react-intl'; + +import PersonAddIcon from '@/material-icons/400-24px/person_add-fill.svg?react'; +import type { NotificationGroupFollow } from 'mastodon/models/notification_group'; + +import type { LabelRenderer } from './notification_group_with_status'; +import { NotificationGroupWithStatus } from './notification_group_with_status'; + +const labelRenderer: LabelRenderer = (values) => ( + +); + +export const NotificationFollow: React.FC<{ + notification: NotificationGroupFollow; + unread: boolean; +}> = ({ notification, unread }) => ( + +); diff --git a/app/javascript/mastodon/features/notifications_v2/components/notification_follow_request.tsx b/app/javascript/mastodon/features/notifications_v2/components/notification_follow_request.tsx new file mode 100644 index 00000000000000..8c9837efa34da8 --- /dev/null +++ b/app/javascript/mastodon/features/notifications_v2/components/notification_follow_request.tsx @@ -0,0 +1,78 @@ +import { useCallback } from 'react'; + +import { FormattedMessage, useIntl, defineMessages } from 'react-intl'; + +import CheckIcon from '@/material-icons/400-24px/check.svg?react'; +import CloseIcon from '@/material-icons/400-24px/close.svg?react'; +import PersonAddIcon from '@/material-icons/400-24px/person_add-fill.svg?react'; +import { + authorizeFollowRequest, + rejectFollowRequest, +} from 'mastodon/actions/accounts'; +import { IconButton } from 'mastodon/components/icon_button'; +import type { NotificationGroupFollowRequest } from 'mastodon/models/notification_group'; +import { useAppDispatch } from 'mastodon/store'; + +import type { LabelRenderer } from './notification_group_with_status'; +import { NotificationGroupWithStatus } from './notification_group_with_status'; + +const messages = defineMessages({ + authorize: { id: 'follow_request.authorize', defaultMessage: 'Authorize' }, + reject: { id: 'follow_request.reject', defaultMessage: 'Reject' }, +}); + +const labelRenderer: LabelRenderer = (values) => ( + +); + +export const NotificationFollowRequest: React.FC<{ + notification: NotificationGroupFollowRequest; + unread: boolean; +}> = ({ notification, unread }) => { + const intl = useIntl(); + + const dispatch = useAppDispatch(); + + const onAuthorize = useCallback(() => { + dispatch(authorizeFollowRequest(notification.sampleAccountIds[0])); + }, [dispatch, notification.sampleAccountIds]); + + const onReject = useCallback(() => { + dispatch(rejectFollowRequest(notification.sampleAccountIds[0])); + }, [dispatch, notification.sampleAccountIds]); + + const actions = ( +
+ + +
+ ); + + return ( + + ); +}; diff --git a/app/javascript/mastodon/features/notifications_v2/components/notification_group.tsx b/app/javascript/mastodon/features/notifications_v2/components/notification_group.tsx new file mode 100644 index 00000000000000..a21c73e96138be --- /dev/null +++ b/app/javascript/mastodon/features/notifications_v2/components/notification_group.tsx @@ -0,0 +1,169 @@ +import { useMemo } from 'react'; + +import { HotKeys } from 'react-hotkeys'; + +import { navigateToProfile } from 'mastodon/actions/accounts'; +import { mentionComposeById } from 'mastodon/actions/compose'; +import type { NotificationGroup as NotificationGroupModel } from 'mastodon/models/notification_group'; +import { useAppSelector, useAppDispatch } from 'mastodon/store'; + +import { NotificationAdminReport } from './notification_admin_report'; +import { NotificationAdminSignUp } from './notification_admin_sign_up'; +import { NotificationEmojiReaction } from './notification_emoji_reaction'; +import { NotificationFavourite } from './notification_favourite'; +import { NotificationFollow } from './notification_follow'; +import { NotificationFollowRequest } from './notification_follow_request'; +import { NotificationMention } from './notification_mention'; +import { NotificationModerationWarning } from './notification_moderation_warning'; +import { NotificationPoll } from './notification_poll'; +import { NotificationReblog } from './notification_reblog'; +import { NotificationSeveredRelationships } from './notification_severed_relationships'; +import { NotificationStatus } from './notification_status'; +import { NotificationStatusReference } from './notification_status_reference'; +import { NotificationUpdate } from './notification_update'; + +export const NotificationGroup: React.FC<{ + notificationGroupId: NotificationGroupModel['group_key']; + unread: boolean; + onMoveUp: (groupId: string) => void; + onMoveDown: (groupId: string) => void; +}> = ({ notificationGroupId, unread, onMoveUp, onMoveDown }) => { + const notificationGroup = useAppSelector((state) => + state.notificationGroups.groups.find( + (item) => item.type !== 'gap' && item.group_key === notificationGroupId, + ), + ); + + const dispatch = useAppDispatch(); + + const accountId = + notificationGroup?.type === 'gap' + ? undefined + : notificationGroup?.sampleAccountIds[0]; + + const handlers = useMemo( + () => ({ + moveUp: () => { + onMoveUp(notificationGroupId); + }, + + moveDown: () => { + onMoveDown(notificationGroupId); + }, + + openProfile: () => { + if (accountId) dispatch(navigateToProfile(accountId)); + }, + + mention: () => { + if (accountId) dispatch(mentionComposeById(accountId)); + }, + }), + [dispatch, notificationGroupId, accountId, onMoveUp, onMoveDown], + ); + + if (!notificationGroup || notificationGroup.type === 'gap') return null; + + let content; + + switch (notificationGroup.type) { + case 'reblog': + content = ( + + ); + break; + case 'favourite': + content = ( + + ); + break; + case 'emoji_reaction': + content = ( + + ); + break; + case 'severed_relationships': + content = ( + + ); + break; + case 'mention': + content = ( + + ); + break; + case 'status_reference': + content = ( + + ); + break; + case 'follow': + content = ( + + ); + break; + case 'follow_request': + content = ( + + ); + break; + case 'poll': + content = ( + + ); + break; + case 'status': + content = ( + + ); + break; + case 'update': + content = ( + + ); + break; + case 'admin.sign_up': + content = ( + + ); + break; + case 'admin.report': + content = ( + + ); + break; + case 'moderation_warning': + content = ( + + ); + break; + default: + return null; + } + + return {content}; +}; diff --git a/app/javascript/mastodon/features/notifications_v2/components/notification_group_with_status.tsx b/app/javascript/mastodon/features/notifications_v2/components/notification_group_with_status.tsx new file mode 100644 index 00000000000000..2af73c8362a7b7 --- /dev/null +++ b/app/javascript/mastodon/features/notifications_v2/components/notification_group_with_status.tsx @@ -0,0 +1,113 @@ +import { useMemo } from 'react'; + +import classNames from 'classnames'; + +import { HotKeys } from 'react-hotkeys'; + +import { replyComposeById } from 'mastodon/actions/compose'; +import { navigateToStatus } from 'mastodon/actions/statuses'; +import type { IconProp } from 'mastodon/components/icon'; +import { Icon } from 'mastodon/components/icon'; +import { RelativeTimestamp } from 'mastodon/components/relative_timestamp'; +import { useAppDispatch } from 'mastodon/store'; + +import { AvatarGroup } from './avatar_group'; +import { EmbeddedStatus } from './embedded_status'; +import { NamesList } from './names_list'; + +export type LabelRenderer = ( + values: Record, +) => JSX.Element; + +export const NotificationGroupWithStatus: React.FC<{ + icon: IconProp; + iconId: string; + statusId?: string; + actions?: JSX.Element; + count: number; + accountIds: string[]; + timestamp: string; + labelRenderer: LabelRenderer; + labelSeeMoreHref?: string; + type: string; + unread: boolean; +}> = ({ + icon, + iconId, + timestamp, + accountIds, + actions, + count, + statusId, + labelRenderer, + labelSeeMoreHref, + type, + unread, +}) => { + const dispatch = useAppDispatch(); + + const label = useMemo( + () => + labelRenderer({ + name: ( + + ), + }), + [labelRenderer, accountIds, count, labelSeeMoreHref], + ); + + const handlers = useMemo( + () => ({ + open: () => { + dispatch(navigateToStatus(statusId)); + }, + + reply: () => { + dispatch(replyComposeById(statusId)); + }, + }), + [dispatch, statusId], + ); + + return ( + +
+
+ +
+ +
+
+
+ + + {actions} +
+ +
+ {label} + {timestamp && } +
+
+ + {statusId && ( +
+ +
+ )} +
+
+
+ ); +}; diff --git a/app/javascript/mastodon/features/notifications_v2/components/notification_mention.tsx b/app/javascript/mastodon/features/notifications_v2/components/notification_mention.tsx new file mode 100644 index 00000000000000..8c584f0ce1dde2 --- /dev/null +++ b/app/javascript/mastodon/features/notifications_v2/components/notification_mention.tsx @@ -0,0 +1,55 @@ +import { FormattedMessage } from 'react-intl'; + +import ReplyIcon from '@/material-icons/400-24px/reply-fill.svg?react'; +import type { StatusVisibility } from 'mastodon/api_types/statuses'; +import type { NotificationGroupMention } from 'mastodon/models/notification_group'; +import { useAppSelector } from 'mastodon/store'; + +import type { LabelRenderer } from './notification_group_with_status'; +import { NotificationWithStatus } from './notification_with_status'; + +const labelRenderer: LabelRenderer = (values) => ( + +); + +const privateMentionLabelRenderer: LabelRenderer = (values) => ( + +); + +export const NotificationMention: React.FC<{ + notification: NotificationGroupMention; + unread: boolean; +}> = ({ notification, unread }) => { + const statusVisibility = useAppSelector( + (state) => + state.statuses.getIn([ + notification.statusId, + 'visibility', + ]) as StatusVisibility, + ); + + return ( + + ); +}; diff --git a/app/javascript/mastodon/features/notifications_v2/components/notification_moderation_warning.tsx b/app/javascript/mastodon/features/notifications_v2/components/notification_moderation_warning.tsx new file mode 100644 index 00000000000000..d653385fda83c4 --- /dev/null +++ b/app/javascript/mastodon/features/notifications_v2/components/notification_moderation_warning.tsx @@ -0,0 +1,13 @@ +import { ModerationWarning } from 'mastodon/features/notifications/components/moderation_warning'; +import type { NotificationGroupModerationWarning } from 'mastodon/models/notification_group'; + +export const NotificationModerationWarning: React.FC<{ + notification: NotificationGroupModerationWarning; + unread: boolean; +}> = ({ notification: { moderationWarning }, unread }) => ( + +); diff --git a/app/javascript/mastodon/features/notifications_v2/components/notification_poll.tsx b/app/javascript/mastodon/features/notifications_v2/components/notification_poll.tsx new file mode 100644 index 00000000000000..a7748c2c7c372b --- /dev/null +++ b/app/javascript/mastodon/features/notifications_v2/components/notification_poll.tsx @@ -0,0 +1,41 @@ +import { FormattedMessage } from 'react-intl'; + +import BarChart4BarsIcon from '@/material-icons/400-20px/bar_chart_4_bars.svg?react'; +import { me } from 'mastodon/initial_state'; +import type { NotificationGroupPoll } from 'mastodon/models/notification_group'; + +import { NotificationWithStatus } from './notification_with_status'; + +const labelRendererOther = () => ( + +); + +const labelRendererOwn = () => ( + +); + +export const NotificationPoll: React.FC<{ + notification: NotificationGroupPoll; + unread: boolean; +}> = ({ notification, unread }) => ( + +); diff --git a/app/javascript/mastodon/features/notifications_v2/components/notification_reblog.tsx b/app/javascript/mastodon/features/notifications_v2/components/notification_reblog.tsx new file mode 100644 index 00000000000000..06255686884142 --- /dev/null +++ b/app/javascript/mastodon/features/notifications_v2/components/notification_reblog.tsx @@ -0,0 +1,45 @@ +import { FormattedMessage } from 'react-intl'; + +import RepeatIcon from '@/material-icons/400-24px/repeat.svg?react'; +import type { NotificationGroupReblog } from 'mastodon/models/notification_group'; +import { useAppSelector } from 'mastodon/store'; + +import type { LabelRenderer } from './notification_group_with_status'; +import { NotificationGroupWithStatus } from './notification_group_with_status'; + +const labelRenderer: LabelRenderer = (values) => ( + +); + +export const NotificationReblog: React.FC<{ + notification: NotificationGroupReblog; + unread: boolean; +}> = ({ notification, unread }) => { + const { statusId } = notification; + const statusAccount = useAppSelector( + (state) => + state.accounts.get(state.statuses.getIn([statusId, 'account']) as string) + ?.acct, + ); + + return ( + + ); +}; diff --git a/app/javascript/mastodon/features/notifications_v2/components/notification_severed_relationships.tsx b/app/javascript/mastodon/features/notifications_v2/components/notification_severed_relationships.tsx new file mode 100644 index 00000000000000..fd92498ea3dfc2 --- /dev/null +++ b/app/javascript/mastodon/features/notifications_v2/components/notification_severed_relationships.tsx @@ -0,0 +1,15 @@ +import { RelationshipsSeveranceEvent } from 'mastodon/features/notifications/components/relationships_severance_event'; +import type { NotificationGroupSeveredRelationships } from 'mastodon/models/notification_group'; + +export const NotificationSeveredRelationships: React.FC<{ + notification: NotificationGroupSeveredRelationships; + unread: boolean; +}> = ({ notification: { event }, unread }) => ( + +); diff --git a/app/javascript/mastodon/features/notifications_v2/components/notification_status.tsx b/app/javascript/mastodon/features/notifications_v2/components/notification_status.tsx new file mode 100644 index 00000000000000..9ade355a71494b --- /dev/null +++ b/app/javascript/mastodon/features/notifications_v2/components/notification_status.tsx @@ -0,0 +1,31 @@ +import { FormattedMessage } from 'react-intl'; + +import NotificationsActiveIcon from '@/material-icons/400-24px/notifications_active-fill.svg?react'; +import type { NotificationGroupStatus } from 'mastodon/models/notification_group'; + +import type { LabelRenderer } from './notification_group_with_status'; +import { NotificationWithStatus } from './notification_with_status'; + +const labelRenderer: LabelRenderer = (values) => ( + +); + +export const NotificationStatus: React.FC<{ + notification: NotificationGroupStatus; + unread: boolean; +}> = ({ notification, unread }) => ( + +); diff --git a/app/javascript/mastodon/features/notifications_v2/components/notification_status_reference.tsx b/app/javascript/mastodon/features/notifications_v2/components/notification_status_reference.tsx new file mode 100644 index 00000000000000..683d3bcc447a19 --- /dev/null +++ b/app/javascript/mastodon/features/notifications_v2/components/notification_status_reference.tsx @@ -0,0 +1,34 @@ +import { FormattedMessage } from 'react-intl'; + +import ReferenceIcon from '@/material-icons/400-24px/link.svg?react'; +import type { NotificationGroupStatusReference } from 'mastodon/models/notification_group'; + +import type { LabelRenderer } from './notification_group_with_status'; +import { NotificationWithStatus } from './notification_with_status'; + +const labelRenderer: LabelRenderer = (values) => ( + +); + +export const NotificationStatusReference: React.FC<{ + notification: NotificationGroupStatusReference; + unread: boolean; +}> = ({ notification, unread }) => { + return ( + + ); +}; diff --git a/app/javascript/mastodon/features/notifications_v2/components/notification_update.tsx b/app/javascript/mastodon/features/notifications_v2/components/notification_update.tsx new file mode 100644 index 00000000000000..c518367bf5a24f --- /dev/null +++ b/app/javascript/mastodon/features/notifications_v2/components/notification_update.tsx @@ -0,0 +1,31 @@ +import { FormattedMessage } from 'react-intl'; + +import EditIcon from '@/material-icons/400-24px/edit.svg?react'; +import type { NotificationGroupUpdate } from 'mastodon/models/notification_group'; + +import type { LabelRenderer } from './notification_group_with_status'; +import { NotificationWithStatus } from './notification_with_status'; + +const labelRenderer: LabelRenderer = (values) => ( + +); + +export const NotificationUpdate: React.FC<{ + notification: NotificationGroupUpdate; + unread: boolean; +}> = ({ notification, unread }) => ( + +); diff --git a/app/javascript/mastodon/features/notifications_v2/components/notification_with_status.tsx b/app/javascript/mastodon/features/notifications_v2/components/notification_with_status.tsx new file mode 100644 index 00000000000000..2275f25e0c8ce7 --- /dev/null +++ b/app/javascript/mastodon/features/notifications_v2/components/notification_with_status.tsx @@ -0,0 +1,115 @@ +import { useMemo } from 'react'; + +import classNames from 'classnames'; + +import { HotKeys } from 'react-hotkeys'; + +import { replyComposeById } from 'mastodon/actions/compose'; +import { toggleReblog, toggleFavourite } from 'mastodon/actions/interactions'; +import { + navigateToStatus, + toggleStatusSpoilers, +} from 'mastodon/actions/statuses'; +import type { IconProp } from 'mastodon/components/icon'; +import { Icon } from 'mastodon/components/icon'; +import Status from 'mastodon/containers/status_container'; +import { useAppSelector, useAppDispatch } from 'mastodon/store'; + +import { NamesList } from './names_list'; +import type { LabelRenderer } from './notification_group_with_status'; + +export const NotificationWithStatus: React.FC<{ + type: string; + icon: IconProp; + iconId: string; + accountIds: string[]; + statusId: string; + count: number; + labelRenderer: LabelRenderer; + unread: boolean; + muted?: boolean; +}> = ({ + icon, + iconId, + accountIds, + statusId, + count, + labelRenderer, + type, + unread, + muted, +}) => { + const dispatch = useAppDispatch(); + + const label = useMemo( + () => + labelRenderer({ + name: , + }), + [labelRenderer, accountIds, count], + ); + + const isPrivateMention = useAppSelector( + (state) => state.statuses.getIn([statusId, 'visibility']) === 'direct', + ); + + const handlers = useMemo( + () => ({ + open: () => { + dispatch(navigateToStatus(statusId)); + }, + + reply: () => { + dispatch(replyComposeById(statusId)); + }, + + boost: () => { + dispatch(toggleReblog(statusId)); + }, + + favourite: () => { + dispatch(toggleFavourite(statusId)); + }, + + toggleHidden: () => { + dispatch(toggleStatusSpoilers(statusId)); + }, + }), + [dispatch, statusId], + ); + + return ( + +
+
+
+ +
+ {label} +
+ + is not yet typed + id={statusId} + contextType='notifications' + withDismiss + skipPrepend + avatarSize={40} + unfocusable + muted={muted} + withoutEmojiReactions + /> +
+
+ ); +}; diff --git a/app/javascript/mastodon/features/notifications_v2/filter_bar.tsx b/app/javascript/mastodon/features/notifications_v2/filter_bar.tsx new file mode 100644 index 00000000000000..78b97231b23e2d --- /dev/null +++ b/app/javascript/mastodon/features/notifications_v2/filter_bar.tsx @@ -0,0 +1,171 @@ +import type { PropsWithChildren } from 'react'; +import { useCallback } from 'react'; + +import { defineMessages, FormattedMessage, useIntl } from 'react-intl'; + +import HomeIcon from '@/material-icons/400-24px/home-fill.svg?react'; +import InsertChartIcon from '@/material-icons/400-24px/insert_chart.svg?react'; +import ReferenceIcon from '@/material-icons/400-24px/link.svg?react'; +import EmojiReactionIcon from '@/material-icons/400-24px/mood.svg?react'; +import PersonAddIcon from '@/material-icons/400-24px/person_add.svg?react'; +import RepeatIcon from '@/material-icons/400-24px/repeat.svg?react'; +import ReplyAllIcon from '@/material-icons/400-24px/reply_all.svg?react'; +import StarIcon from '@/material-icons/400-24px/star.svg?react'; +import { setNotificationsFilter } from 'mastodon/actions/notification_groups'; +import { Icon } from 'mastodon/components/icon'; +import { + selectSettingsNotificationsQuickFilterActive, + selectSettingsNotificationsQuickFilterAdvanced, +} from 'mastodon/selectors/settings'; +import { useAppDispatch, useAppSelector } from 'mastodon/store'; + +const tooltips = defineMessages({ + mentions: { id: 'notifications.filter.mentions', defaultMessage: 'Mentions' }, + favourites: { + id: 'notifications.filter.favourites', + defaultMessage: 'Favorites', + }, + emojiReactions: { + id: 'notifications.filter.emoji_reactions', + defaultMessage: 'Stamps', + }, + boosts: { id: 'notifications.filter.boosts', defaultMessage: 'Boosts' }, + status_references: { + id: 'notifications.filter.status_references', + defaultMessage: 'Status references', + }, + polls: { id: 'notifications.filter.polls', defaultMessage: 'Poll results' }, + follows: { id: 'notifications.filter.follows', defaultMessage: 'Follows' }, + statuses: { + id: 'notifications.filter.statuses', + defaultMessage: 'Updates from people you follow', + }, +}); + +const BarButton: React.FC< + PropsWithChildren<{ + selectedFilter: string; + type: string; + title?: string; + }> +> = ({ selectedFilter, type, title, children }) => { + const dispatch = useAppDispatch(); + + const onClick = useCallback(() => { + void dispatch(setNotificationsFilter({ filterType: type })); + }, [dispatch, type]); + + return ( + + ); +}; + +export const FilterBar: React.FC = () => { + const intl = useIntl(); + + const selectedFilter = useAppSelector( + selectSettingsNotificationsQuickFilterActive, + ); + const advancedMode = useAppSelector( + selectSettingsNotificationsQuickFilterAdvanced, + ); + + if (advancedMode) + return ( +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ ); + else + return ( +
+ + + + + + +
+ ); +}; diff --git a/app/javascript/mastodon/features/notifications_v2/index.tsx b/app/javascript/mastodon/features/notifications_v2/index.tsx new file mode 100644 index 00000000000000..fc20f0583631ed --- /dev/null +++ b/app/javascript/mastodon/features/notifications_v2/index.tsx @@ -0,0 +1,354 @@ +import { useCallback, useEffect, useMemo, useRef } from 'react'; + +import { defineMessages, FormattedMessage, useIntl } from 'react-intl'; + +import { Helmet } from 'react-helmet'; + +import { createSelector } from '@reduxjs/toolkit'; + +import { useDebouncedCallback } from 'use-debounce'; + +import DoneAllIcon from '@/material-icons/400-24px/done_all.svg?react'; +import NotificationsIcon from '@/material-icons/400-24px/notifications-fill.svg?react'; +import { + fetchNotificationsGap, + updateScrollPosition, + loadPending, + markNotificationsAsRead, + mountNotifications, + unmountNotifications, +} from 'mastodon/actions/notification_groups'; +import { compareId } from 'mastodon/compare_id'; +import { Icon } from 'mastodon/components/icon'; +import { NotSignedInIndicator } from 'mastodon/components/not_signed_in_indicator'; +import { useIdentity } from 'mastodon/identity_context'; +import type { NotificationGap } from 'mastodon/reducers/notification_groups'; +import { + selectUnreadNotificationGroupsCount, + selectPendingNotificationGroupsCount, +} from 'mastodon/selectors/notifications'; +import { + selectNeedsNotificationPermission, + selectSettingsNotificationsExcludedTypes, + selectSettingsNotificationsQuickFilterActive, + selectSettingsNotificationsQuickFilterShow, + selectSettingsNotificationsShowUnread, +} from 'mastodon/selectors/settings'; +import { useAppDispatch, useAppSelector } from 'mastodon/store'; +import type { RootState } from 'mastodon/store'; + +import { addColumn, removeColumn, moveColumn } from '../../actions/columns'; +import { submitMarkers } from '../../actions/markers'; +import Column from '../../components/column'; +import { ColumnHeader } from '../../components/column_header'; +import { LoadGap } from '../../components/load_gap'; +import ScrollableList from '../../components/scrollable_list'; +import { FilteredNotificationsBanner } from '../notifications/components/filtered_notifications_banner'; +import NotificationsPermissionBanner from '../notifications/components/notifications_permission_banner'; +import ColumnSettingsContainer from '../notifications/containers/column_settings_container'; + +import { NotificationGroup } from './components/notification_group'; +import { FilterBar } from './filter_bar'; + +const messages = defineMessages({ + title: { id: 'column.notifications', defaultMessage: 'Notifications' }, + markAsRead: { + id: 'notifications.mark_as_read', + defaultMessage: 'Mark every notification as read', + }, +}); + +const getNotifications = createSelector( + [ + selectSettingsNotificationsQuickFilterShow, + selectSettingsNotificationsQuickFilterActive, + selectSettingsNotificationsExcludedTypes, + (state: RootState) => state.notificationGroups.groups, + ], + (showFilterBar, allowedType, excludedTypes, notifications) => { + if (!showFilterBar || allowedType === 'all') { + // used if user changed the notification settings after loading the notifications from the server + // otherwise a list of notifications will come pre-filtered from the backend + // we need to turn it off for FilterBar in order not to block ourselves from seeing a specific category + return notifications.filter( + (item) => item.type === 'gap' || !excludedTypes.includes(item.type), + ); + } + return notifications.filter( + (item) => item.type === 'gap' || allowedType === item.type, + ); + }, +); + +export const Notifications: React.FC<{ + columnId?: string; + multiColumn?: boolean; +}> = ({ columnId, multiColumn }) => { + const intl = useIntl(); + const notifications = useAppSelector(getNotifications); + const dispatch = useAppDispatch(); + const isLoading = useAppSelector((s) => s.notificationGroups.isLoading); + const hasMore = notifications.at(-1)?.type === 'gap'; + + const lastReadId = useAppSelector((s) => + selectSettingsNotificationsShowUnread(s) + ? s.notificationGroups.lastReadId + : '0', + ); + + const numPending = useAppSelector(selectPendingNotificationGroupsCount); + + const unreadNotificationsCount = useAppSelector( + selectUnreadNotificationGroupsCount, + ); + + const isUnread = unreadNotificationsCount > 0; + + const canMarkAsRead = + useAppSelector(selectSettingsNotificationsShowUnread) && + unreadNotificationsCount > 0; + + const needsNotificationPermission = useAppSelector( + selectNeedsNotificationPermission, + ); + + const columnRef = useRef(null); + + const selectChild = useCallback((index: number, alignTop: boolean) => { + const container = columnRef.current?.node as HTMLElement | undefined; + + if (!container) return; + + const element = container.querySelector( + `article:nth-of-type(${index + 1}) .focusable`, + ); + + if (element) { + if (alignTop && container.scrollTop > element.offsetTop) { + element.scrollIntoView(true); + } else if ( + !alignTop && + container.scrollTop + container.clientHeight < + element.offsetTop + element.offsetHeight + ) { + element.scrollIntoView(false); + } + element.focus(); + } + }, []); + + // Keep track of mounted components for unread notification handling + useEffect(() => { + dispatch(mountNotifications()); + + return () => { + dispatch(unmountNotifications()); + dispatch(updateScrollPosition({ top: false })); + }; + }, [dispatch]); + + const handleLoadGap = useCallback( + (gap: NotificationGap) => { + void dispatch(fetchNotificationsGap({ gap })); + }, + [dispatch], + ); + + const handleLoadOlder = useDebouncedCallback( + () => { + const gap = notifications.at(-1); + if (gap?.type === 'gap') void dispatch(fetchNotificationsGap({ gap })); + }, + 300, + { leading: true }, + ); + + const handleLoadPending = useCallback(() => { + dispatch(loadPending()); + }, [dispatch]); + + const handleScrollToTop = useDebouncedCallback(() => { + dispatch(updateScrollPosition({ top: true })); + }, 100); + + const handleScroll = useDebouncedCallback(() => { + dispatch(updateScrollPosition({ top: false })); + }, 100); + + useEffect(() => { + return () => { + handleLoadOlder.cancel(); + handleScrollToTop.cancel(); + handleScroll.cancel(); + }; + }, [handleLoadOlder, handleScrollToTop, handleScroll]); + + const handlePin = useCallback(() => { + if (columnId) { + dispatch(removeColumn(columnId)); + } else { + dispatch(addColumn('NOTIFICATIONS', {})); + } + }, [columnId, dispatch]); + + const handleMove = useCallback( + (dir: unknown) => { + dispatch(moveColumn(columnId, dir)); + }, + [dispatch, columnId], + ); + + const handleHeaderClick = useCallback(() => { + columnRef.current?.scrollTop(); + }, []); + + const handleMoveUp = useCallback( + (id: string) => { + const elementIndex = + notifications.findIndex( + (item) => item.type !== 'gap' && item.group_key === id, + ) - 1; + selectChild(elementIndex, true); + }, + [notifications, selectChild], + ); + + const handleMoveDown = useCallback( + (id: string) => { + const elementIndex = + notifications.findIndex( + (item) => item.type !== 'gap' && item.group_key === id, + ) + 1; + selectChild(elementIndex, false); + }, + [notifications, selectChild], + ); + + const handleMarkAsRead = useCallback(() => { + dispatch(markNotificationsAsRead()); + void dispatch(submitMarkers({ immediate: true })); + }, [dispatch]); + + const pinned = !!columnId; + const emptyMessage = ( + + ); + + const { signedIn } = useIdentity(); + + const filterBar = signedIn ? : null; + + const scrollableContent = useMemo(() => { + if (notifications.length === 0 && !hasMore) return null; + + return notifications.map((item) => + item.type === 'gap' ? ( + + ) : ( + 0 + } + /> + ), + ); + }, [ + notifications, + isLoading, + hasMore, + lastReadId, + handleLoadGap, + handleMoveUp, + handleMoveDown, + ]); + + const prepend = ( + <> + {needsNotificationPermission && } + + + ); + + const scrollContainer = signedIn ? ( + + {scrollableContent} + + ) : ( + + ); + + const extraButton = canMarkAsRead ? ( + + ) : null; + + return ( + + + + + + {filterBar} + + {scrollContainer} + + + {intl.formatMessage(messages.title)} + + + + ); +}; + +// eslint-disable-next-line import/no-default-export +export default Notifications; diff --git a/app/javascript/mastodon/features/notifications_wrapper.jsx b/app/javascript/mastodon/features/notifications_wrapper.jsx new file mode 100644 index 00000000000000..057ed1b395f8ec --- /dev/null +++ b/app/javascript/mastodon/features/notifications_wrapper.jsx @@ -0,0 +1,13 @@ +import Notifications from 'mastodon/features/notifications'; +import Notifications_v2 from 'mastodon/features/notifications_v2'; +import { useAppSelector } from 'mastodon/store'; + +export const NotificationsWrapper = (props) => { + const optedInGroupedNotifications = useAppSelector((state) => state.getIn(['settings', 'notifications', 'groupingBeta'], false)); + + return ( + optedInGroupedNotifications ? : + ); +}; + +export default NotificationsWrapper; \ No newline at end of file diff --git a/app/javascript/mastodon/features/onboarding/index.jsx b/app/javascript/mastodon/features/onboarding/index.jsx index 125584b418acb0..1d4649f90bf0ae 100644 --- a/app/javascript/mastodon/features/onboarding/index.jsx +++ b/app/javascript/mastodon/features/onboarding/index.jsx @@ -3,7 +3,7 @@ import { useCallback } from 'react'; import { FormattedMessage, useIntl, defineMessages } from 'react-intl'; import { Helmet } from 'react-helmet'; -import { Link, Switch, Route, useHistory } from 'react-router-dom'; +import { Link, Switch, Route } from 'react-router-dom'; import { useDispatch } from 'react-redux'; @@ -35,11 +35,10 @@ const Onboarding = () => { const account = useAppSelector(state => state.getIn(['accounts', me])); const dispatch = useDispatch(); const intl = useIntl(); - const history = useHistory(); const handleComposeClick = useCallback(() => { - dispatch(focusCompose(history, intl.formatMessage(messages.template))); - }, [dispatch, intl, history]); + dispatch(focusCompose(intl.formatMessage(messages.template))); + }, [dispatch, intl]); return ( diff --git a/app/javascript/mastodon/features/picture_in_picture/components/footer.jsx b/app/javascript/mastodon/features/picture_in_picture/components/footer.jsx index 86aa28aa41e4b5..d82ce091e11ad3 100644 --- a/app/javascript/mastodon/features/picture_in_picture/components/footer.jsx +++ b/app/javascript/mastodon/features/picture_in_picture/components/footer.jsx @@ -15,11 +15,11 @@ import ReplyIcon from '@/material-icons/400-24px/reply.svg?react'; import ReplyAllIcon from '@/material-icons/400-24px/reply_all.svg?react'; import StarIcon from '@/material-icons/400-24px/star.svg?react'; import { replyCompose } from 'mastodon/actions/compose'; -import { reblog, favourite, unreblog, unfavourite } from 'mastodon/actions/interactions'; +import { toggleReblog, toggleFavourite } from 'mastodon/actions/interactions'; import { openModal } from 'mastodon/actions/modal'; import { IconButton } from 'mastodon/components/icon_button'; import { identityContextPropShape, withIdentity } from 'mastodon/identity_context'; -import { me, boostModal } from 'mastodon/initial_state'; +import { me } from 'mastodon/initial_state'; import { makeGetStatus } from 'mastodon/selectors'; import { WithRouterPropTypes } from 'mastodon/utils/react_router'; @@ -61,13 +61,13 @@ class Footer extends ImmutablePureComponent { }; _performReply = () => { - const { dispatch, status, onClose, history } = this.props; + const { dispatch, status, onClose } = this.props; if (onClose) { onClose(true); } - dispatch(replyCompose(status, history)); + dispatch(replyCompose(status)); }; handleReplyClick = () => { @@ -104,11 +104,7 @@ class Footer extends ImmutablePureComponent { const { signedIn } = this.props.identity; if (signedIn) { - if (status.get('favourited')) { - dispatch(unfavourite(status)); - } else { - dispatch(favourite(status)); - } + dispatch(toggleFavourite(status.get('id'))); } else { dispatch(openModal({ modalType: 'INTERACTION', @@ -121,23 +117,12 @@ class Footer extends ImmutablePureComponent { } }; - _performReblog = (status, privacy) => { - const { dispatch } = this.props; - dispatch(reblog({ statusId: status.get('id'), visibility: privacy })); - }; - handleReblogClick = e => { const { dispatch, status } = this.props; const { signedIn } = this.props.identity; if (signedIn) { - if (status.get('reblogged')) { - dispatch(unreblog({ statusId: status.get('id') })); - } else if ((e && e.shiftKey) || !boostModal) { - this._performReblog(status); - } else { - dispatch(openModal({ modalType: 'BOOST', modalProps: { status, onReblog: this._performReblog } })); - } + dispatch(toggleReblog(status.get('id'), e && e.shiftKey)); } else { dispatch(openModal({ modalType: 'INTERACTION', diff --git a/app/javascript/mastodon/features/status/components/action_bar.jsx b/app/javascript/mastodon/features/status/components/action_bar.jsx index 0f35e38cae80cb..c555a8c8db695f 100644 --- a/app/javascript/mastodon/features/status/components/action_bar.jsx +++ b/app/javascript/mastodon/features/status/components/action_bar.jsx @@ -4,7 +4,7 @@ import { PureComponent } from 'react'; import { defineMessages, injectIntl } from 'react-intl'; import classNames from 'classnames'; -import { withRouter } from 'react-router-dom'; + import ImmutablePropTypes from 'react-immutable-proptypes'; import { connect } from 'react-redux'; @@ -109,10 +109,6 @@ class ActionBar extends PureComponent { ...WithRouterPropTypes, }; - handleOpenMentions = () => { - this.props.history.push(`/@${this.props.status.getIn(['account', 'acct'])}/${this.props.status.get('id')}/mentioned_users`); - }; - handleReplyClick = () => { this.props.onReply(this.props.status); }; @@ -142,23 +138,23 @@ class ActionBar extends PureComponent { }; handleDeleteClick = () => { - this.props.onDelete(this.props.status, this.props.history); + this.props.onDelete(this.props.status); }; handleRedraftClick = () => { - this.props.onDelete(this.props.status, this.props.history, true); + this.props.onDelete(this.props.status, true); }; handleEditClick = () => { - this.props.onEdit(this.props.status, this.props.history); + this.props.onEdit(this.props.status); }; handleDirectClick = () => { - this.props.onDirect(this.props.status.get('account'), this.props.history); + this.props.onDirect(this.props.status.get('account')); }; handleMentionClick = () => { - this.props.onMention(this.props.status.get('account'), this.props.history); + this.props.onMention(this.props.status.get('account')); }; handleMuteClick = () => { @@ -293,7 +289,7 @@ class ActionBar extends PureComponent { } if (status.get('limited_scope') !== 'reply') { - menu.push({ text: intl.formatMessage(messages.mentions), action: this.handleOpenMentions }); + menu.push({ text: intl.formatMessage(messages.mentions), href: `/@${this.props.status.getIn(['account', 'acct'])}/${this.props.status.get('id')}/mentioned_users` }); } menu.push({ text: intl.formatMessage(mutingConversation ? messages.unmuteConversation : messages.muteConversation), action: this.handleConversationMuteClick }); @@ -446,4 +442,4 @@ class ActionBar extends PureComponent { } -export default withRouter(connect(mapStateToProps)(withIdentity(injectIntl(ActionBar)))); +export default connect(mapStateToProps)(withIdentity(injectIntl(ActionBar))); diff --git a/app/javascript/mastodon/features/status/containers/detailed_status_container.js b/app/javascript/mastodon/features/status/containers/detailed_status_container.js index c6215c706dc0b8..388341daa12c98 100644 --- a/app/javascript/mastodon/features/status/containers/detailed_status_container.js +++ b/app/javascript/mastodon/features/status/containers/detailed_status_container.js @@ -10,10 +10,8 @@ import { directCompose, } from '../../../actions/compose'; import { - reblog, - favourite, - unreblog, - unfavourite, + toggleReblog, + toggleFavourite, pin, unpin, emojiReact, @@ -26,10 +24,9 @@ import { muteStatus, unmuteStatus, deleteStatus, - hideStatus, - revealStatus, + toggleStatusSpoilers, } from '../../../actions/statuses'; -import { boostModal, deleteModal } from '../../../initial_state'; +import { deleteModal } from '../../../initial_state'; import { makeGetStatus, makeGetPictureInPicture } from '../../../selectors'; import DetailedStatus from '../components/detailed_status'; @@ -57,7 +54,7 @@ const makeMapStateToProps = () => { const mapDispatchToProps = (dispatch, { intl }) => ({ - onReply (status, router) { + onReply (status) { dispatch((_, getState) => { let state = getState(); if (state.getIn(['compose', 'text']).trim().length !== 0) { @@ -66,45 +63,25 @@ const mapDispatchToProps = (dispatch, { intl }) => ({ modalProps: { message: intl.formatMessage(messages.replyMessage), confirm: intl.formatMessage(messages.replyConfirm), - onConfirm: () => dispatch(replyCompose(status, router)), + onConfirm: () => dispatch(replyCompose(status)), }, })); } else { - dispatch(replyCompose(status, router)); + dispatch(replyCompose(status)); } }); }, - onModalReblog (status, privacy) { - dispatch(reblog({ statusId: status.get('id'), visibility: privacy })); - }, - onReblog (status, e) { - if (status.get('reblogged')) { - dispatch(unreblog({ statusId: status.get('id') })); - } else { - if (e.shiftKey || !boostModal) { - this.onModalReblog(status); - } else { - dispatch(openModal({ modalType: 'BOOST', modalProps: { status, onReblog: this.onModalReblog } })); - } - } + dispatch(toggleReblog(status.get('id'), e.shiftKey)); }, onReblogForceModal (status) { - if (status.get('reblogged')) { - dispatch(unreblog(status)); - } else { - dispatch(openModal({ modalType: 'BOOST', modalProps: { status, onReblog: this.onModalReblog } })); - } + dispatch(toggleReblog(status.get('id'), true, true)); }, onFavourite (status) { - if (status.get('favourited')) { - dispatch(unfavourite(status)); - } else { - dispatch(favourite(status)); - } + dispatch(toggleFavourite(status.get('id'))); }, onEmojiReact (status, emoji) { @@ -133,27 +110,27 @@ const mapDispatchToProps = (dispatch, { intl }) => ({ })); }, - onDelete (status, history, withRedraft = false) { + onDelete (status, withRedraft = false) { if (!deleteModal) { - dispatch(deleteStatus(status.get('id'), history, withRedraft)); + dispatch(deleteStatus(status.get('id'), withRedraft)); } else { dispatch(openModal({ modalType: 'CONFIRM', modalProps: { message: intl.formatMessage(withRedraft ? messages.redraftMessage : messages.deleteMessage), confirm: intl.formatMessage(withRedraft ? messages.redraftConfirm : messages.deleteConfirm), - onConfirm: () => dispatch(deleteStatus(status.get('id'), history, withRedraft)), + onConfirm: () => dispatch(deleteStatus(status.get('id'), withRedraft)), }, })); } }, - onDirect (account, router) { - dispatch(directCompose(account, router)); + onDirect (account) { + dispatch(directCompose(account)); }, - onMention (account, router) { - dispatch(mentionCompose(account, router)); + onMention (account) { + dispatch(mentionCompose(account)); }, onOpenMedia (media, index, lang) { @@ -192,11 +169,7 @@ const mapDispatchToProps = (dispatch, { intl }) => ({ }, onToggleHidden (status) { - if (status.get('hidden')) { - dispatch(revealStatus(status.get('id'))); - } else { - dispatch(hideStatus(status.get('id'))); - } + dispatch(toggleStatusSpoilers(status.get('id'))); }, }); diff --git a/app/javascript/mastodon/features/status/index.jsx b/app/javascript/mastodon/features/status/index.jsx index 1c0b1ab13df1ef..06f7da0dc9f811 100644 --- a/app/javascript/mastodon/features/status/index.jsx +++ b/app/javascript/mastodon/features/status/index.jsx @@ -39,14 +39,12 @@ import { unblockDomain, } from '../../actions/domain_blocks'; import { - favourite, - unfavourite, emojiReact, unEmojiReact, + toggleFavourite, bookmark, unbookmark, - reblog, - unreblog, + toggleReblog, pin, unpin, } from '../../actions/interactions'; @@ -67,7 +65,7 @@ import { import ColumnHeader from '../../components/column_header'; import { textForScreenReader, defaultMediaVisibility } from '../../components/status'; import StatusContainer from '../../containers/status_container'; -import { bookmarkCategoryNeeded, boostModal, deleteModal } from '../../initial_state'; +import { bookmarkCategoryNeeded, deleteModal } from '../../initial_state'; import { makeGetStatus, makeGetPictureInPicture } from '../../selectors'; import Column from '../ui/components/column'; import { attachFullscreenListener, detachFullscreenListener, isFullscreen } from '../ui/util/fullscreen'; @@ -257,11 +255,7 @@ class Status extends ImmutablePureComponent { const { signedIn } = this.props.identity; if (signedIn) { - if (status.get('favourited')) { - dispatch(unfavourite(status)); - } else { - dispatch(favourite(status)); - } + dispatch(toggleFavourite(status.get('id'))); } else { dispatch(openModal({ modalType: 'INTERACTION', @@ -316,11 +310,11 @@ class Status extends ImmutablePureComponent { modalProps: { message: intl.formatMessage(messages.replyMessage), confirm: intl.formatMessage(messages.replyConfirm), - onConfirm: () => dispatch(replyCompose(status, this.props.history)), + onConfirm: () => dispatch(replyCompose(status)), }, })); } else { - dispatch(replyCompose(status, this.props.history)); + dispatch(replyCompose(status)); } } else { dispatch(openModal({ @@ -334,24 +328,12 @@ class Status extends ImmutablePureComponent { } }; - handleModalReblog = (status, privacy) => { - this.props.dispatch(reblog({ statusId: status.get('id'), visibility: privacy })); - }; - handleReblogClick = (status, e, force = false) => { const { dispatch } = this.props; const { signedIn } = this.props.identity; if (signedIn) { - if (status.get('reblogged')) { - dispatch(unreblog({ statusId: status.get('id') })); - } else { - if (!force && ((e && e.shiftKey) || !boostModal)) { - this.handleModalReblog(status); - } else { - dispatch(openModal({ modalType: 'BOOST', modalProps: { status, onReblog: this.handleModalReblog } })); - } - } + dispatch(toggleReblog(status.get('id'), e && e.shiftKey, force)); } else { dispatch(openModal({ modalType: 'INTERACTION', @@ -398,33 +380,33 @@ class Status extends ImmutablePureComponent { })); }; - handleDeleteClick = (status, history, withRedraft = false) => { + handleDeleteClick = (status, withRedraft = false) => { const { dispatch, intl } = this.props; if (!deleteModal) { - dispatch(deleteStatus(status.get('id'), history, withRedraft)); + dispatch(deleteStatus(status.get('id'), withRedraft)); } else { dispatch(openModal({ modalType: 'CONFIRM', modalProps: { message: intl.formatMessage(withRedraft ? messages.redraftMessage : messages.deleteMessage), confirm: intl.formatMessage(withRedraft ? messages.redraftConfirm : messages.deleteConfirm), - onConfirm: () => dispatch(deleteStatus(status.get('id'), history, withRedraft)), + onConfirm: () => dispatch(deleteStatus(status.get('id'), withRedraft)), }, })); } }; - handleEditClick = (status, history) => { - this.props.dispatch(editStatus(status.get('id'), history)); + handleEditClick = (status) => { + this.props.dispatch(editStatus(status.get('id'))); }; - handleDirectClick = (account, router) => { - this.props.dispatch(directCompose(account, router)); + handleDirectClick = (account) => { + this.props.dispatch(directCompose(account)); }; - handleMentionClick = (account, router) => { - this.props.dispatch(mentionCompose(account, router)); + handleMentionClick = (account) => { + this.props.dispatch(mentionCompose(account)); }; handleOpenMedia = (media, index, lang) => { diff --git a/app/javascript/mastodon/features/ui/components/columns_area.jsx b/app/javascript/mastodon/features/ui/components/columns_area.jsx index 2e6c4a63edc5b0..0a35a3998313af 100644 --- a/app/javascript/mastodon/features/ui/components/columns_area.jsx +++ b/app/javascript/mastodon/features/ui/components/columns_area.jsx @@ -10,7 +10,7 @@ import { scrollRight } from '../../../scroll'; import BundleContainer from '../containers/bundle_container'; import { Compose, - Notifications, + NotificationsWrapper, HomeTimeline, CommunityTimeline, PublicTimeline, @@ -37,7 +37,7 @@ import NavigationPanel from './navigation_panel'; const componentMap = { 'COMPOSE': Compose, 'HOME': HomeTimeline, - 'NOTIFICATIONS': Notifications, + 'NOTIFICATIONS': NotificationsWrapper, 'PUBLIC': PublicTimeline, 'REMOTE': PublicTimeline, 'COMMUNITY': CommunityTimeline, diff --git a/app/javascript/mastodon/features/ui/components/navigation_panel.jsx b/app/javascript/mastodon/features/ui/components/navigation_panel.jsx index e9d6077646e055..2c222088461378 100644 --- a/app/javascript/mastodon/features/ui/components/navigation_panel.jsx +++ b/app/javascript/mastodon/features/ui/components/navigation_panel.jsx @@ -36,6 +36,7 @@ import { NavigationPortal } from 'mastodon/components/navigation_portal'; import { identityContextPropShape, withIdentity } from 'mastodon/identity_context'; import { enableDtlMenu, timelinePreview, trendsEnabled, dtlTag, enableLocalTimeline, isHideItem } from 'mastodon/initial_state'; import { transientSingleColumn } from 'mastodon/is_mobile'; +import { selectUnreadNotificationGroupsCount } from 'mastodon/selectors/notifications'; import ColumnLink from './column_link'; import DisabledAccountBanner from './disabled_account_banner'; @@ -65,15 +66,19 @@ const messages = defineMessages({ }); const NotificationsLink = () => { + const optedInGroupedNotifications = useSelector((state) => state.getIn(['settings', 'notifications', 'groupingBeta'], false)); const count = useSelector(state => state.getIn(['notifications', 'unread'])); const intl = useIntl(); + const newCount = useSelector(selectUnreadNotificationGroupsCount); + return ( } - activeIcon={} + icon={} + activeIcon={} text={intl.formatMessage(messages.notifications)} /> ); diff --git a/app/javascript/mastodon/features/ui/index.jsx b/app/javascript/mastodon/features/ui/index.jsx index 6da280ac67b0d3..75d9888c61f95e 100644 --- a/app/javascript/mastodon/features/ui/index.jsx +++ b/app/javascript/mastodon/features/ui/index.jsx @@ -13,6 +13,7 @@ import { HotKeys } from 'react-hotkeys'; import { focusApp, unfocusApp, changeLayout } from 'mastodon/actions/app'; import { synchronouslySubmitMarkers, submitMarkers, fetchMarkers } from 'mastodon/actions/markers'; +import { initializeNotifications } from 'mastodon/actions/notifications_migration'; import { INTRODUCTION_VERSION } from 'mastodon/actions/onboarding'; import { HoverCardController } from 'mastodon/components/hover_card_controller'; import { PictureInPicture } from 'mastodon/features/picture_in_picture'; @@ -22,7 +23,6 @@ import { WithRouterPropTypes } from 'mastodon/utils/react_router'; import { uploadCompose, resetCompose, changeComposeSpoilerness } from '../../actions/compose'; import { clearHeight } from '../../actions/height_cache'; -import { expandNotifications } from '../../actions/notifications'; import { fetchServer, fetchServerTranslationLanguages } from '../../actions/server'; import { expandHomeTimeline } from '../../actions/timelines'; import initialState, { me, owner, singleUserMode, trendsEnabled, trendsAsLanding, disableHoverCards } from '../../initial_state'; @@ -53,7 +53,7 @@ import { DirectTimeline, HashtagTimeline, AntennaTimeline, - Notifications, + NotificationsWrapper, NotificationRequests, NotificationRequest, FollowRequests, @@ -84,6 +84,7 @@ import { } from './util/async-components'; import { ColumnsContextProvider } from './util/columns_context'; import { WrappedSwitch, WrappedRoute } from './util/react_router_helpers'; + // Dummy import, to make sure that ends up in the application bundle. // Without this it ends up in ~8 very commonly used bundles. import '../../components/status'; @@ -222,7 +223,7 @@ class SwitchingColumnsArea extends PureComponent { - + @@ -435,7 +436,7 @@ class UI extends PureComponent { if (signedIn) { this.props.dispatch(fetchMarkers()); this.props.dispatch(expandHomeTimeline()); - this.props.dispatch(expandNotifications()); + this.props.dispatch(initializeNotifications()); this.props.dispatch(fetchServerTranslationLanguages()); setTimeout(() => this.props.dispatch(fetchServer()), 3000); diff --git a/app/javascript/mastodon/features/ui/util/async-components.js b/app/javascript/mastodon/features/ui/util/async-components.js index 19a4c5fc95eb0d..58461a9339f60e 100644 --- a/app/javascript/mastodon/features/ui/util/async-components.js +++ b/app/javascript/mastodon/features/ui/util/async-components.js @@ -7,7 +7,15 @@ export function Compose () { } export function Notifications () { - return import(/* webpackChunkName: "features/notifications" */'../../notifications'); + return import(/* webpackChunkName: "features/notifications_v1" */'../../notifications'); +} + +export function Notifications_v2 () { + return import(/* webpackChunkName: "features/notifications_v2" */'../../notifications_v2'); +} + +export function NotificationsWrapper () { + return import(/* webpackChunkName: "features/notifications" */'../../notifications_wrapper'); } export function HomeTimeline () { diff --git a/app/javascript/mastodon/locales/an.json b/app/javascript/mastodon/locales/an.json index 752b6c3564f6ec..d8f41b29bd153e 100644 --- a/app/javascript/mastodon/locales/an.json +++ b/app/javascript/mastodon/locales/an.json @@ -342,7 +342,6 @@ "notification.follow_request": "{name} ha solicitau seguir-te", "notification.mention": "{name} t'ha mencionau", "notification.own_poll": "La tuya enqüesta ha rematau", - "notification.poll": "Una enqüesta en a quala has votau ha rematau", "notification.reblog": "{name} ha retutau la tuya publicación", "notification.status": "{name} acaba de publicar", "notification.update": "{name} editó una publicación", diff --git a/app/javascript/mastodon/locales/ar.json b/app/javascript/mastodon/locales/ar.json index 5509769e04085b..9cfda3cbc2f2ef 100644 --- a/app/javascript/mastodon/locales/ar.json +++ b/app/javascript/mastodon/locales/ar.json @@ -482,7 +482,6 @@ "notification.moderation_warning.action_silence": "لقد تم تقييد حسابك.", "notification.moderation_warning.action_suspend": "لقد تم تعليق حسابك.", "notification.own_poll": "انتهى استطلاعك للرأي", - "notification.poll": "لقد انتهى استطلاع رأي شاركتَ فيه", "notification.reblog": "قام {name} بمشاركة منشورك", "notification.relationships_severance_event": "فقدت الاتصالات مع {name}", "notification.relationships_severance_event.account_suspension": "قام مشرف من {from} بتعليق {target}، مما يعني أنك لم يعد بإمكانك تلقي التحديثات منهم أو التفاعل معهم.", diff --git a/app/javascript/mastodon/locales/ast.json b/app/javascript/mastodon/locales/ast.json index 3f32a8bf158e04..883737eb4aa96c 100644 --- a/app/javascript/mastodon/locales/ast.json +++ b/app/javascript/mastodon/locales/ast.json @@ -1,7 +1,7 @@ { "about.blocks": "Sirvidores moderaos", "about.contact": "Contautu:", - "about.disclaimer": "Mastodon ye software gratuito ya de códigu llibre, ya una marca rexistrada de Mastodon gGmbH.", + "about.disclaimer": "Mastodon ye software gratuito y de códigu llibre, y una marca rexistrada de Mastodon gGmbH.", "about.domain_blocks.no_reason_available": "El motivu nun ta disponible", "about.domain_blocks.preamble": "Polo xeneral, Mastodon permítete ver el conteníu ya interactuar colos perfiles d'otros sirvidores nel fediversu. Estes son les esceiciones que se ficieron nesti sirvidor.", "about.domain_blocks.silenced.explanation": "Polo xeneral, nun ves los perfiles ya'l conteníu d'esti sirvidor sacante que los busques o decidas siguilos.", @@ -37,15 +37,15 @@ "account.hide_reblogs": "Anubrir los artículos compartíos de @{name}", "account.in_memoriam": "N'alcordanza.", "account.joined_short": "Data de xunión", - "account.link_verified_on": "La propiedá d'esti enllaz foi comprobada'l {date}", + "account.link_verified_on": "La propiedá d'esti enllaz comprobóse'l {date}", "account.media": "Multimedia", "account.mention": "Mentar a @{name}", "account.moved_to": "{name} indicó qu'agora la so cuenta nueva ye:", "account.mute": "Desactivar los avisos de @{name}", "account.open_original_page": "Abrir la páxina orixinal", "account.posts": "Artículos", - "account.posts_with_replies": "Artículos ya rempuestes", - "account.report": "Informar de: @{name}", + "account.posts_with_replies": "Artículos y rempuestes", + "account.report": "Informar de @{name}", "account.requested_follow": "{name} solicitó siguite", "account.show_reblogs": "Amosar los artículos compartíos de @{name}", "account.unblock": "Desbloquiar a @{name}", @@ -71,7 +71,7 @@ "bundle_column_error.routing.body": "Nun se pudo atopar la páxina solicitada. ¿De xuru que la URL de la barra de direiciones ta bien escrita?", "bundle_column_error.routing.title": "404", "bundle_modal_error.message": "Asocedió daqué malo mentanto se cargaba esti componente.", - "closed_registrations.other_server_instructions": "Darréu que Mastodon ye una rede social descentralizada, pues crear una cuenta n'otru sirvidor ya siguir interactuando con esti.", + "closed_registrations.other_server_instructions": "Darréu que Mastodon ye una rede social descentralizada, pues crear una cuenta n'otru sirvidor y siguir interactuando con esti.", "closed_registrations_modal.description": "Anguaño nun ye posible crear cuentes en {domain}, mas ten en cuenta que nun precises una cuenta nesti sirvidor pa usar Mastodon.", "closed_registrations_modal.find_another_server": "Atopar otru sirvidor", "closed_registrations_modal.preamble": "Mastodon ye una rede social descentralizada polo que nun importa ónde crees la cuenta, vas ser a siguir ya interactuar con persones d'esti sirvidor. ¡Ya tamién pues tener el to propiu sirvidor!", @@ -107,7 +107,7 @@ "compose_form.lock_disclaimer.lock": "privada", "compose_form.placeholder": "¿En qué pienses?", "compose_form.poll.option_placeholder": "Opción {number}", - "compose_form.poll.type": "Estilu", + "compose_form.poll.type": "Tipu", "compose_form.publish_form": "Artículu nuevu", "confirmation_modal.cancel": "Encaboxar", "confirmations.block.confirm": "Bloquiar", @@ -120,7 +120,7 @@ "confirmations.edit.message": "La edición va sobrescribir el mensaxe que tas escribiendo. ¿De xuru que quies siguir?", "confirmations.logout.confirm": "Zarrar la sesión", "confirmations.logout.message": "¿De xuru que quies zarrar la sesión?", - "confirmations.redraft.confirm": "Desaniciar ya reeditar", + "confirmations.redraft.confirm": "Desaniciar y reeditar", "confirmations.reply.confirm": "Responder", "confirmations.unfollow.confirm": "Dexar de siguir", "confirmations.unfollow.message": "¿De xuru que quies dexar de siguir a {name}?", @@ -140,7 +140,7 @@ "embed.preview": "Va apaecer asina:", "emoji_button.activity": "Actividá", "emoji_button.flags": "Banderes", - "emoji_button.food": "Comida ya bébora", + "emoji_button.food": "Comida y bébora", "emoji_button.nature": "Natura", "emoji_button.not_found": "Nun s'atoparon fustaxes que concasen", "emoji_button.objects": "Oxetos", @@ -149,7 +149,7 @@ "emoji_button.search": "Buscar…", "emoji_button.search_results": "Resultaos de la busca", "emoji_button.symbols": "Símbolos", - "emoji_button.travel": "Viaxes ya llugares", + "emoji_button.travel": "Viaxes y llugares", "empty_column.account_timeline": "¡Equí nun hai nengún artículu!", "empty_column.blocks": "Nun bloquiesti a nengún perfil.", "empty_column.bookmarked_statuses": "Nun tienes nengún artículu en Marcadores. Cuando amiestes dalgún, apaez equí.", @@ -168,7 +168,7 @@ "error.unexpected_crash.explanation": "Pola mor d'un fallu nel códigu o un problema de compatibilidá del restolador, esta páxina nun se pudo amosar correutamente.", "error.unexpected_crash.explanation_addons": "Esta páxina nun se pudo amosar correutamente. Ye probable que dalgún complementu del restolador o dalguna ferramienta de traducción automática produxere esti error.", "error.unexpected_crash.next_steps": "Prueba a anovar la páxina. Si nun sirve, ye posible que tovía seyas a usar Mastodon pente otru restolador o una aplicación nativa.", - "error.unexpected_crash.next_steps_addons": "Prueba a desactivalos ya a anovar la páxina. Si nun sirve, ye posible que tovía seyas a usar Mastodon pente otru restolador o una aplicación nativa.", + "error.unexpected_crash.next_steps_addons": "Prueba a desactivalos y a anovar la páxina. Si nun sirve, ye posible que tovía seyas a usar Mastodon pente otru restolador o una aplicación nativa.", "explore.search_results": "Resultaos de la busca", "explore.suggested_follows": "Perfiles", "explore.title": "Esploración", @@ -179,7 +179,7 @@ "filter_modal.added.context_mismatch_title": "¡El contestu nun coincide!", "filter_modal.added.expired_explanation": "Esta categoría de peñera caducó, tienes de camudar la so data de caducidá p'aplicala.", "filter_modal.added.expired_title": "¡La peñera caducó!", - "filter_modal.added.review_and_configure": "Pa revisar ya configurar a fondu esta categoría de peñera, vete a la {settings_link}.", + "filter_modal.added.review_and_configure": "Pa revisar y configurar a fondu esta categoría de peñera, vete a la {settings_link}.", "filter_modal.added.review_and_configure_title": "Configuración de la peñera", "filter_modal.added.settings_link": "páxina de configuración", "filter_modal.added.short_explanation": "Esti artículu amestóse a la categoría de peñera siguiente: {title}.", @@ -195,8 +195,10 @@ "follow_request.reject": "Refugar", "follow_requests.unlocked_explanation": "Magar que la to cuenta nun seya privada, el personal del dominiu «{domain}» pensó qu'a lo meyor quies revisar manualmente les solicitúes de siguimientu d'estes cuentes.", "follow_suggestions.dismiss": "Nun volver amosar", + "follow_suggestions.friends_of_friends_longer": "Ye popular ente los perfiles que sigues", "follow_suggestions.personalized_suggestion": "Suxerencia personalizada", "follow_suggestions.popular_suggestion": "Suxerencia popular", + "follow_suggestions.similar_to_recently_followed_longer": "Aseméyase a los perfiles que siguiesti apocayá", "follow_suggestions.view_all": "Ver too", "follow_suggestions.who_to_follow": "A quién siguir", "footer.about": "Tocante a", @@ -272,6 +274,8 @@ "lists.subheading": "Les tos llistes", "load_pending": "{count, plural, one {# elementu nuevu} other {# elementos nuevos}}", "media_gallery.toggle_visible": "{number, plural, one {Anubrir la imaxe} other {Anubrir les imáxenes}}", + "name_and_others": "{name} y {count, plural, one {# más} other {# más}}", + "name_and_others_with_link": "{name} y {count, plural, one {# más} other {# más}}", "navigation_bar.about": "Tocante a", "navigation_bar.blocks": "Perfiles bloquiaos", "navigation_bar.bookmarks": "Marcadores", @@ -281,11 +285,11 @@ "navigation_bar.explore": "Esploración", "navigation_bar.filters": "Pallabres desactivaes", "navigation_bar.follow_requests": "Solicitúes de siguimientu", - "navigation_bar.follows_and_followers": "Perfiles que sigues ya te siguen", + "navigation_bar.follows_and_followers": "Perfiles que sigues y te siguen", "navigation_bar.lists": "Llistes", "navigation_bar.logout": "Zarrar la sesión", "navigation_bar.mutes": "Perfiles colos avisos desactivaos", - "navigation_bar.opened_in_classic_interface": "Los artículos, les cuentes ya otres páxines específiques ábrense por defeutu na interfaz web clásica.", + "navigation_bar.opened_in_classic_interface": "Los artículos, les cuentes y otres páxines específiques ábrense por defeutu na interfaz web clásica.", "navigation_bar.pins": "Artículos fixaos", "navigation_bar.preferences": "Preferencies", "navigation_bar.public_timeline": "Llinia de tiempu federada", @@ -296,13 +300,13 @@ "notification.follow": "{name} siguióte", "notification.follow_request": "{name} solicitó siguite", "notification.mention": "{name} mentóte", - "notification.poll": "Finó una encuesta na que votesti", "notification.reblog": "{name} compartió'l to artículu", "notification.status": "{name} ta acabante d'espublizar", "notification.update": "{name} editó un artículu", "notifications.clear": "Borrar los avisos", "notifications.column_settings.admin.report": "Informes nuevos:", "notifications.column_settings.admin.sign_up": "Rexistros nuevos:", + "notifications.column_settings.beta.category": "Funciones esperimentales", "notifications.column_settings.follow": "Siguidores nuevos:", "notifications.column_settings.follow_request": "Solicitúes de siguimientu nueves:", "notifications.column_settings.mention": "Menciones:", @@ -319,7 +323,7 @@ "notifications.mark_as_read": "Marcar tolos avisos como lleíos", "notifications.permission_required": "Los avisos d'escritoriu nun tán disponibles porque nun se concedió'l permisu riquíu.", "onboarding.profile.note_hint": "Pues @mentar a otros perfiles o poner #etiquetes…", - "onboarding.start.lead": "Xá yes parte de Mastodon, una plataforma social multimedia descentralizada onde tu ya non un algoritmu, personalices la to esperiencia. Vamos presentate esti llugar social nuevu:", + "onboarding.start.lead": "Yá yes parte de Mastodon, una plataforma social multimedia descentralizada onde tu y non un algoritmu, personalices la to esperiencia. Vamos presentate esti llugar social nuevu:", "onboarding.start.skip": "¿Nun precises ayuda pa comenzar?", "onboarding.steps.follow_people.body": "Mastodon trata namás de siguir a cuentes interesantes.", "onboarding.steps.publish_status.body": "Saluda al mundu con semeyes, vídeos, testu o encuestes {emoji}", @@ -334,6 +338,8 @@ "poll_button.add_poll": "Amestar una encuesta", "poll_button.remove_poll": "Quitar la encuesta", "privacy.change": "Configurar la privacidá del artículu", + "privacy.direct.short": "Perfiles específicos", + "privacy.private.short": "Siguidores", "privacy.public.short": "Artículu públicu", "privacy_policy.last_updated": "Data del últimu anovamientu: {date}", "privacy_policy.title": "Política de privacidá", @@ -383,10 +389,11 @@ "report.thanks.take_action": "Equí tienes les opciones pa controlar qué ves en Mastodon:", "report.thanks.take_action_actionable": "Mentanto revisamos esti informe, pues tomar midíes contra @{name}:", "report.thanks.title": "¿Nun quies ver esti conteníu?", - "report.thanks.title_actionable": "Gracies pol informe, el casu xá ta n'investigación.", + "report.thanks.title_actionable": "Gracies pol informe, el casu yá ta n'investigación.", "report.unfollow": "Dexar de siguir a @{name}", "report.unfollow_explanation": "Sigues a esta cuenta. Pa dexar de ver los sos artículos nel to feed d'aniciu, dexa de siguila.", "report_notification.attached_statuses": "{count, plural, one {Axuntóse {count} artículu} other {Axuntáronse {count} artículos}}", + "report_notification.categories.legal_sentence": "conteníu illegal", "report_notification.open": "Abrir l'informe", "search.no_recent_searches": "Nun hai nenguna busca recién", "search.placeholder": "Buscar", @@ -396,6 +403,7 @@ "search.quick_action.status_search": "Artículos que concasen con {x}", "search.search_or_paste": "Busca o apiega una URL", "search_popout.language_code": "códigu de llingua ISO", + "search_popout.options": "Opciones de busca", "search_popout.quick_actions": "Aiciones rápides", "search_popout.recent": "Busques de recién", "search_popout.specific_date": "data específica", @@ -440,12 +448,13 @@ "status.reblog": "Compartir", "status.reblogged_by": "{name} compartió", "status.reblogs.empty": "Naide nun compartió esti artículu. Cuando daquién lo faiga, apaez equí.", - "status.redraft": "Desaniciar ya reeditar", + "status.redraft": "Desaniciar y reeditar", "status.replied_to": "En rempuesta a {name}", "status.reply": "Responder", "status.replyAll": "Responder al filu", "status.report": "Informar de @{name}", "status.sensitive_warning": "Conteníu sensible", + "status.share": "Compartir", "status.show_filter_reason": "Amosar de toes toes", "status.show_less": "Amosar menos", "status.show_more": "Amosar más", @@ -472,7 +481,7 @@ "units.short.thousand": "{count} mil", "upload_button.label": "Amestar ficheros multimedia", "upload_error.poll": "La xuba de ficheros nun ta permitida coles encuestes.", - "upload_form.audio_description": "Describi'l conteníu pa persones sordes ya/o ciegues", + "upload_form.audio_description": "Describi'l conteníu pa persones sordes y/o ciegues", "upload_form.edit": "Editar", "upload_modal.analyzing_picture": "Analizando la semeya…", "upload_modal.apply": "Aplicar", diff --git a/app/javascript/mastodon/locales/be.json b/app/javascript/mastodon/locales/be.json index df29fbd4184fdf..e2120d80d9fcb7 100644 --- a/app/javascript/mastodon/locales/be.json +++ b/app/javascript/mastodon/locales/be.json @@ -485,7 +485,6 @@ "notification.moderation_warning.action_silence": "Ваш уліковы запіс быў абмежаваны.", "notification.moderation_warning.action_suspend": "Ваш уліковы запіс быў прыпынены.", "notification.own_poll": "Ваша апытанне скончылася", - "notification.poll": "Апытанне, дзе вы прынялі ўдзел, скончылася", "notification.reblog": "{name} пашырыў ваш допіс", "notification.relationships_severance_event": "Страціў сувязь з {name}", "notification.relationships_severance_event.account_suspension": "Адміністратар з {from} прыпыніў працу {target}, што азначае, што вы больш не можаце атрымліваць ад іх абнаўлення ці ўзаемадзейнічаць з імі.", diff --git a/app/javascript/mastodon/locales/bg.json b/app/javascript/mastodon/locales/bg.json index 98e84c45d75351..b2dff17407f4b0 100644 --- a/app/javascript/mastodon/locales/bg.json +++ b/app/javascript/mastodon/locales/bg.json @@ -443,6 +443,8 @@ "mute_modal.title": "Заглушавате ли потребител?", "mute_modal.you_wont_see_mentions": "Няма да виждате споменаващите ги публикации.", "mute_modal.you_wont_see_posts": "Още могат да виждат публикациите ви, но вие техните не.", + "name_and_others": "{name} и {count, plural, one {# друг} other {# други}}", + "name_and_others_with_link": "{name} и {count, plural, one {# друг} other {# други}}", "navigation_bar.about": "Относно", "navigation_bar.advanced_interface": "Отваряне в разширен уебинтерфейс", "navigation_bar.blocks": "Блокирани потребители", @@ -470,6 +472,10 @@ "navigation_bar.security": "Сигурност", "not_signed_in_indicator.not_signed_in": "Трябва ви вход за достъп до ресурса.", "notification.admin.report": "{name} докладва {target}", + "notification.admin.report_account": "{name} докладва {count, plural, one {публикация} other {# публикации}} от {target} за {category}", + "notification.admin.report_account_other": "{name} докладва {count, plural, one {публикация} other {# публикации}} от {target}", + "notification.admin.report_statuses": "{name} докладва {target} за {category}", + "notification.admin.report_statuses_other": "{name} докладва {target}", "notification.admin.sign_up": "{name} се регистрира", "notification.favourite": "{name} направи любима публикацията ви", "notification.follow": "{name} ви последва", @@ -486,6 +492,7 @@ "notification.moderation_warning.action_suspend": "Вашият акаунт е спрян.", "notification.own_poll": "Анкетата ви приключи", "notification.poll": "Анкета, в която гласувахте, приключи", + "notification.private_mention": "{name} лично ви спомена", "notification.reblog": "{name} подсили ваша публикация", "notification.relationships_severance_event": "Изгуби се връзката с {name}", "notification.relationships_severance_event.account_suspension": "Администратор от {from} спря {target}, което значи че повече не може да получавате новости от тях или да взаимодействате с тях.", @@ -503,6 +510,8 @@ "notifications.column_settings.admin.report": "Нови доклади:", "notifications.column_settings.admin.sign_up": "Нови регистрации:", "notifications.column_settings.alert": "Известия на работния плот", + "notifications.column_settings.beta.category": "Експериментални функции", + "notifications.column_settings.beta.grouping": "Групови известия", "notifications.column_settings.favourite": "Любими:", "notifications.column_settings.filter_bar.advanced": "Показване на всички категории", "notifications.column_settings.filter_bar.category": "Лента за бърз филтър", @@ -666,9 +675,13 @@ "report.unfollow_explanation": "Последвали сте този акаунт. За да не виждате повече публикациите му в началния си инфопоток, спрете да го следвате.", "report_notification.attached_statuses": "{count, plural, one {прикаченa {count} публикация} other {прикачени {count} публикации}}", "report_notification.categories.legal": "Правни въпроси", + "report_notification.categories.legal_sentence": "незаконно съдържание", "report_notification.categories.other": "Друго", + "report_notification.categories.other_sentence": "друго", "report_notification.categories.spam": "Спам", + "report_notification.categories.spam_sentence": "спам", "report_notification.categories.violation": "Нарушение на правилото", + "report_notification.categories.violation_sentence": "нарушение на правило", "report_notification.open": "Отваряне на доклада", "search.no_recent_searches": "Няма скорошни търсения", "search.placeholder": "Търсене", diff --git a/app/javascript/mastodon/locales/bn.json b/app/javascript/mastodon/locales/bn.json index a203c43f034e24..6d64c00a2f57a4 100644 --- a/app/javascript/mastodon/locales/bn.json +++ b/app/javascript/mastodon/locales/bn.json @@ -320,7 +320,6 @@ "notification.follow_request": "{name} আপনাকে অনুসরণ করার জন্য অনুরধ করেছে", "notification.mention": "{name} আপনাকে উল্লেখ করেছেন", "notification.own_poll": "আপনার পোল শেষ হয়েছে", - "notification.poll": "আপনি ভোট দিয়েছিলেন এমন এক নির্বাচনের ভোটের সময় শেষ হয়েছে", "notification.reblog": "{name} আপনার কার্যক্রমে সমর্থন দেখিয়েছেন", "notifications.clear": "প্রজ্ঞাপনগুলো মুছে ফেলতে", "notifications.clear_confirmation": "আপনি কি নির্চিত প্রজ্ঞাপনগুলো মুছে ফেলতে চান ?", diff --git a/app/javascript/mastodon/locales/br.json b/app/javascript/mastodon/locales/br.json index a150fb4902be39..76cd9d45743458 100644 --- a/app/javascript/mastodon/locales/br.json +++ b/app/javascript/mastodon/locales/br.json @@ -398,7 +398,6 @@ "notification.mention": "Gant {name} oc'h bet meneget", "notification.moderation-warning.learn_more": "Gouzout hiroc'h", "notification.own_poll": "Echu eo ho sontadeg", - "notification.poll": "Ur sontadeg ho deus mouezhet warnañ a zo echuet", "notification.reblog": "Gant {name} eo bet skignet ho toud", "notification.status": "Emañ {name} o paouez toudañ", "notification.update": "Gant {name} ez eus bet kemmet un toud", diff --git a/app/javascript/mastodon/locales/ca.json b/app/javascript/mastodon/locales/ca.json index 3123e29d8d26e1..80c85ce178eb67 100644 --- a/app/javascript/mastodon/locales/ca.json +++ b/app/javascript/mastodon/locales/ca.json @@ -443,6 +443,8 @@ "mute_modal.title": "Silenciem l'usuari?", "mute_modal.you_wont_see_mentions": "No veureu publicacions que els esmentin.", "mute_modal.you_wont_see_posts": "Encara poden veure les vostres publicacions, però no veureu les seves.", + "name_and_others": "{name} i {count, plural, one {# altre} other {# altres}}", + "name_and_others_with_link": "{name} i {count, plural, one {# altre} other {# altres}}", "navigation_bar.about": "Quant a", "navigation_bar.advanced_interface": "Obre en la interfície web avançada", "navigation_bar.blocks": "Usuaris blocats", @@ -470,6 +472,10 @@ "navigation_bar.security": "Seguretat", "not_signed_in_indicator.not_signed_in": "Cal que iniciïs la sessió per a accedir a aquest recurs.", "notification.admin.report": "{name} ha reportat {target}", + "notification.admin.report_account": "{name} ha reportat {count, plural, one {una publicació} other {# publicacions}} de {target} per {category}", + "notification.admin.report_account_other": "{name} ha reportat {count, plural, one {una publicació} other {# publicacions}} de {target}", + "notification.admin.report_statuses": "{name} ha reportat {target} per {category}", + "notification.admin.report_statuses_other": "{name} ha reportat {target}", "notification.admin.sign_up": "{name} s'ha registrat", "notification.favourite": "{name} ha afavorit el teu tut", "notification.follow": "{name} et segueix", @@ -485,7 +491,8 @@ "notification.moderation_warning.action_silence": "S'ha limitat el vostre compte.", "notification.moderation_warning.action_suspend": "S'ha suspès el vostre compte.", "notification.own_poll": "La teva enquesta ha finalitzat", - "notification.poll": "Ha finalitzat una enquesta en què has votat", + "notification.poll": "Ha finalitzat una enquesta que heu respost", + "notification.private_mention": "{name} us ha esmentat en privat", "notification.reblog": "{name} t'ha impulsat", "notification.relationships_severance_event": "S'han perdut les connexions amb {name}", "notification.relationships_severance_event.account_suspension": "Un administrador de {from} ha suspès {target}; això vol dir que ja no en podreu rebre actualitzacions o interactuar-hi.", @@ -503,6 +510,8 @@ "notifications.column_settings.admin.report": "Nous informes:", "notifications.column_settings.admin.sign_up": "Registres nous:", "notifications.column_settings.alert": "Notificacions d'escriptori", + "notifications.column_settings.beta.category": "Característiques experimentals", + "notifications.column_settings.beta.grouping": "Notificacions de grup", "notifications.column_settings.favourite": "Favorits:", "notifications.column_settings.filter_bar.advanced": "Mostra totes les categories", "notifications.column_settings.filter_bar.category": "Barra ràpida de filtres", @@ -666,9 +675,13 @@ "report.unfollow_explanation": "Estàs seguint aquest compte. Per no veure els seus tuts a la teva línia de temps d'Inici, deixa de seguir-lo.", "report_notification.attached_statuses": "{count, plural, one {{count} tut} other {{count} tuts}} adjunts", "report_notification.categories.legal": "Legal", + "report_notification.categories.legal_sentence": "contingut no permès", "report_notification.categories.other": "Altres", + "report_notification.categories.other_sentence": "altres", "report_notification.categories.spam": "Brossa", + "report_notification.categories.spam_sentence": "brossa", "report_notification.categories.violation": "Violació de norma", + "report_notification.categories.violation_sentence": "violació de normes", "report_notification.open": "Obre l'informe", "search.no_recent_searches": "No hi ha cerques recents", "search.placeholder": "Cerca", diff --git a/app/javascript/mastodon/locales/ckb.json b/app/javascript/mastodon/locales/ckb.json index 3ebf9391d2e9aa..379706a3e08c7b 100644 --- a/app/javascript/mastodon/locales/ckb.json +++ b/app/javascript/mastodon/locales/ckb.json @@ -391,7 +391,6 @@ "notification.follow_request": "{name} داوای کردووە کە شوێنت بکەوێت", "notification.mention": "{name} باسی ئێوەی کرد", "notification.own_poll": "ڕاپرسیەکەت کۆتایی هات", - "notification.poll": "ڕاپرسییەک کە دەنگی پێداویت کۆتایی هات", "notification.reblog": "{name} نووسراوەکەتی دووبارە توتاند", "notification.status": "{name} تازە بڵاوکرایەوە", "notification.update": "{name} پۆستێکی دەستکاریکرد", diff --git a/app/javascript/mastodon/locales/co.json b/app/javascript/mastodon/locales/co.json index 78f8e6fd786eb3..4520663b52b022 100644 --- a/app/javascript/mastodon/locales/co.json +++ b/app/javascript/mastodon/locales/co.json @@ -240,7 +240,6 @@ "notification.follow_request": "{name} vole abbunassi à u vostru contu", "notification.mention": "{name} v'hà mintuvatu", "notification.own_poll": "U vostru scandagliu hè compiu", - "notification.poll": "Un scandagliu induve avete vutatu hè finitu", "notification.reblog": "{name} hà spartutu u vostru statutu", "notification.status": "{name} hà appena pubblicatu", "notifications.clear": "Purgà e nutificazione", diff --git a/app/javascript/mastodon/locales/cs.json b/app/javascript/mastodon/locales/cs.json index 12de5d5ecd4794..213fe5e530e392 100644 --- a/app/javascript/mastodon/locales/cs.json +++ b/app/javascript/mastodon/locales/cs.json @@ -485,7 +485,6 @@ "notification.moderation_warning.action_silence": "Váš účet byl omezen.", "notification.moderation_warning.action_suspend": "Váš účet byl pozastaven.", "notification.own_poll": "Vaše anketa skončila", - "notification.poll": "Anketa, ve které jste hlasovali, skončila", "notification.reblog": "Uživatel {name} boostnul váš příspěvek", "notification.relationships_severance_event": "Kontakt ztracen s {name}", "notification.relationships_severance_event.account_suspension": "Administrátor z {from} pozastavil {target}, což znamená, že již od nich nemůžete přijímat aktualizace nebo s nimi interagovat.", diff --git a/app/javascript/mastodon/locales/cy.json b/app/javascript/mastodon/locales/cy.json index 1c7e61832c1f29..e4c10cc14269e6 100644 --- a/app/javascript/mastodon/locales/cy.json +++ b/app/javascript/mastodon/locales/cy.json @@ -48,8 +48,8 @@ "account.mention": "Crybwyll @{name}", "account.moved_to": "Mae {name} wedi nodi fod eu cyfrif newydd yn:", "account.mute": "Tewi @{name}", - "account.mute_notifications_short": "Distewi hysbysiadau", - "account.mute_short": "Tewi", + "account.mute_notifications_short": "Diffodd hysbysiadau", + "account.mute_short": "Anwybyddu", "account.muted": "Wedi anwybyddu", "account.mutual": "Cydgydnabod", "account.no_bio": "Dim disgrifiad wedi'i gynnig.", @@ -92,7 +92,7 @@ "block_modal.they_cant_mention": "Nid ydynt yn gallu eich crybwyll na'ch dilyn.", "block_modal.they_cant_see_posts": "Nid ydynt yn gallu gweld eich postiadau ac ni fyddwch yn gweld eu rhai hwy.", "block_modal.they_will_know": "Gallant weld eu bod wedi'u rhwystro.", - "block_modal.title": "Rhwystro defnyddiwr?", + "block_modal.title": "Blocio defnyddiwr?", "block_modal.you_wont_see_mentions": "Ni welwch bostiadau sy'n sôn amdanynt.", "boost_modal.combo": "Mae modd pwyso {combo} er mwyn hepgor hyn tro nesa", "bundle_column_error.copy_stacktrace": "Copïo'r adroddiad gwall", @@ -164,7 +164,7 @@ "compose_form.spoiler.marked": "Dileu rhybudd cynnwys", "compose_form.spoiler.unmarked": "Ychwanegu rhybudd cynnwys", "compose_form.spoiler_placeholder": "Rhybudd cynnwys (dewisol)", - "confirmation_modal.cancel": "Diddymu", + "confirmation_modal.cancel": "Canslo", "confirmations.block.confirm": "Blocio", "confirmations.cancel_follow_request.confirm": "Tynnu'r cais yn ôl", "confirmations.cancel_follow_request.message": "Ydych chi'n siŵr eich bod am dynnu'ch cais i ddilyn {name} yn ôl?", @@ -174,7 +174,7 @@ "confirmations.delete_list.message": "Ydych chi'n siŵr eich bod eisiau dileu'r rhestr hwn am byth?", "confirmations.discard_edit_media.confirm": "Dileu", "confirmations.discard_edit_media.message": "Mae gennych newidiadau heb eu cadw i'r disgrifiad cyfryngau neu'r rhagolwg - eu dileu beth bynnag?", - "confirmations.domain_block.confirm": "Rhwystro gweinydd", + "confirmations.domain_block.confirm": "Blocio gweinydd", "confirmations.domain_block.message": "Ydych chi wir, wir eisiau blocio'r holl {domain}? Fel arfer, mae blocio neu dewi pobl penodol yn broses mwy effeithiol. Fyddwch chi ddim yn gweld cynnwys o'r parth hwnnw mewn ffrydiau cyhoeddus neu yn eich hysbysiadau. Bydd eich dilynwyr o'r parth hwnnw yn cael eu ddileu.", "confirmations.edit.confirm": "Golygu", "confirmations.edit.message": "Bydd golygu nawr yn trosysgrifennu'r neges rydych yn ei ysgrifennu ar hyn o bryd. Ydych chi'n siŵr eich bod eisiau gwneud hyn?", @@ -201,17 +201,17 @@ "disabled_account_banner.account_settings": "Gosodiadau'r cyfrif", "disabled_account_banner.text": "Mae eich cyfrif {disabledAccount} wedi ei analluogi ar hyn o bryd.", "dismissable_banner.community_timeline": "Dyma'r postiadau cyhoeddus diweddaraf gan bobl sydd â chyfrifon ar {domain}.", - "dismissable_banner.dismiss": "Diddymu", + "dismissable_banner.dismiss": "Cau", "dismissable_banner.explore_links": "Dyma straeon newyddion sy’n cael eu rhannu fwyaf ar y we gymdeithasol heddiw. Mae'r straeon newyddion diweddaraf sy'n cael eu postio gan fwy o unigolion gwahanol yn cael eu graddio'n uwch.", "dismissable_banner.explore_statuses": "Mae'r rhain yn bostiadau o bob rhan o'r we gymdeithasol sydd ar gynnydd heddiw. Mae postiadau mwy diweddar sydd â mwy o hybiau a ffefrynu'n cael eu graddio'n uwch.", "dismissable_banner.explore_tags": "Mae'r rhain yn hashnodau sydd ar gynnydd ar y we gymdeithasol heddiw. Mae hashnodau sy'n cael eu defnyddio gan fwy o unigolion gwahanol yn cael eu graddio'n uwch.", "dismissable_banner.public_timeline": "Dyma'r postiadau cyhoeddus diweddaraf gan bobl ar y we gymdeithasol y mae pobl ar {domain} yn eu dilyn.", - "domain_block_modal.block": "Rhwystro gweinydd", - "domain_block_modal.block_account_instead": "Rhwystro @{name} yn lle hynny", + "domain_block_modal.block": "Blocio gweinydd", + "domain_block_modal.block_account_instead": "Blocio @{name} yn ei le", "domain_block_modal.they_can_interact_with_old_posts": "Gall pobl o'r gweinydd hwn ryngweithio â'ch hen bostiadau.", "domain_block_modal.they_cant_follow": "Ni all neb o'r gweinydd hwn eich dilyn.", - "domain_block_modal.they_wont_know": "Fyddan nhw ddim yn gwybod eu bod wedi cael eu rhwystro.", - "domain_block_modal.title": "Rhwystro parth?", + "domain_block_modal.they_wont_know": "Fyddan nhw ddim yn gwybod eu bod wedi cael eu blocio.", + "domain_block_modal.title": "Blocio parth?", "domain_block_modal.you_will_lose_followers": "Bydd eich holl ddilynwyr o'r gweinydd hwn yn cael eu tynnu.", "domain_block_modal.you_wont_see_posts": "Fyddwch chi ddim yn gweld postiadau na hysbysiadau gan ddefnyddwyr ar y gweinydd hwn.", "domain_pill.activitypub_lets_connect": "Mae'n caniatáu ichi gysylltu a rhyngweithio â phobl nid yn unig ar Mastodon, ond ar draws gwahanol apiau cymdeithasol hefyd.", @@ -252,7 +252,7 @@ "empty_column.bookmarked_statuses": "Nid oes gennych unrhyw bostiad wedi'u cadw fel llyfrnodau eto. Pan fyddwch yn gosod nod tudalen i un, mi fydd yn ymddangos yma.", "empty_column.community": "Mae'r ffrwd lleol yn wag. Beth am ysgrifennu rhywbeth cyhoeddus!", "empty_column.direct": "Nid oes gennych unrhyw grybwylliadau preifat eto. Pan fyddwch chi'n anfon neu'n derbyn un, bydd yn ymddangos yma.", - "empty_column.domain_blocks": "Nid oes yna unrhyw barthau cuddiedig eto.", + "empty_column.domain_blocks": "Nid oes unrhyw barthau wedi'u blocio eto.", "empty_column.explore_statuses": "Does dim yn trendio ar hyn o bryd. Dewch nôl nes ymlaen!", "empty_column.favourited_statuses": "Nid oes gennych unrhyw hoff bostiadau eto. Pan byddwch yn hoffi un, bydd yn ymddangos yma.", "empty_column.favourites": "Nid oes unrhyw un wedi hoffi'r postiad hwn eto. Pan fydd rhywun yn gwneud hynny, byddan nhw'n ymddangos yma.", @@ -411,6 +411,7 @@ "limited_account_hint.action": "Dangos y proffil beth bynnag", "limited_account_hint.title": "Mae'r proffil hwn wedi cael ei guddio gan gymedrolwyr {domain}.", "link_preview.author": "Gan {name}", + "link_preview.more_from_author": "Mwy gan {name}", "lists.account.add": "Ychwanegu at restr", "lists.account.remove": "Tynnu o'r rhestr", "lists.delete": "Dileu rhestr", @@ -480,13 +481,12 @@ "notification.moderation_warning.action_silence": "Mae eich cyfrif wedi'i gyfyngu.", "notification.moderation_warning.action_suspend": "Mae eich cyfrif wedi'i hatal.", "notification.own_poll": "Mae eich pleidlais wedi dod i ben", - "notification.poll": "Mae pleidlais rydych wedi pleidleisio ynddi wedi dod i ben", "notification.reblog": "Hybodd {name} eich post", "notification.relationships_severance_event": "Wedi colli cysylltiad â {name}", "notification.relationships_severance_event.account_suspension": "Mae gweinyddwr o {from} wedi atal {target}, sy'n golygu na allwch dderbyn diweddariadau ganddynt mwyach na rhyngweithio â nhw.", - "notification.relationships_severance_event.domain_block": "Mae gweinyddwr o {from} wedi rhwystro {target}, gan gynnwys {followersCount} o'ch dilynwyr a {followingCount, plural, one {# cyfrif} other {# cyfrif}} arall rydych chi'n ei ddilyn.", + "notification.relationships_severance_event.domain_block": "Mae gweinyddwr o {from} wedi blocio {target}, gan gynnwys {followersCount} o'ch dilynwyr a {followingCount, plural, one {# cyfrif} other {# cyfrif}} arall rydych chi'n ei ddilyn.", "notification.relationships_severance_event.learn_more": "Dysgu mwy", - "notification.relationships_severance_event.user_domain_block": "Rydych wedi rhwystro {target}, gan ddileu {followersCount} o'ch dilynwyr a {followingCount, plural, one {# cyfrif} other {#cyfrifon}} arall rydych yn ei ddilyn.", + "notification.relationships_severance_event.user_domain_block": "Rydych wedi blocio {target}, gan ddileu {followersCount} o'ch dilynwyr a {followingCount, plural, one {# cyfrif} other {#cyfrifon}} arall rydych yn ei ddilyn.", "notification.status": "{name} newydd ei bostio", "notification.update": "Golygodd {name} bostiad", "notification_requests.accept": "Derbyn", @@ -803,7 +803,7 @@ "video.expand": "Ymestyn fideo", "video.fullscreen": "Sgrin llawn", "video.hide": "Cuddio fideo", - "video.mute": "Tewi sain", + "video.mute": "Diffodd sain", "video.pause": "Oedi", "video.play": "Chwarae", "video.unmute": "Dad-dewi sain" diff --git a/app/javascript/mastodon/locales/da.json b/app/javascript/mastodon/locales/da.json index d8c178d295ea4f..9316884d7184f6 100644 --- a/app/javascript/mastodon/locales/da.json +++ b/app/javascript/mastodon/locales/da.json @@ -37,6 +37,7 @@ "account.followers.empty": "Ingen følger denne bruger endnu.", "account.followers_counter": "{count, plural, one {{counter} følger} other {{counter} følgere}}", "account.following": "Følger", + "account.following_counter": "{count, plural, one {{counter} følger} other {{counter} følger}}", "account.follows.empty": "Denne bruger følger ikke nogen endnu.", "account.go_to_profile": "Gå til profil", "account.hide_reblogs": "Skjul boosts fra @{name}", @@ -62,6 +63,7 @@ "account.requested_follow": "{name} har anmodet om at følge dig", "account.share": "Del @{name}s profil", "account.show_reblogs": "Vis fremhævelser fra @{name}", + "account.statuses_counter": "{count, plural, one {{counter} indlæg} other {{counter} indlæg}}", "account.unblock": "Afblokér @{name}", "account.unblock_domain": "Afblokér domænet {domain}", "account.unblock_short": "Afblokér", @@ -441,6 +443,8 @@ "mute_modal.title": "Tavsgør bruger?", "mute_modal.you_wont_see_mentions": "Indlæg, som nævner vedkommende, vises ikke.", "mute_modal.you_wont_see_posts": "Vedkommende kan stadig se dine indlæg, med vedkommendes vise ikke.", + "name_and_others": "{name} og {count, plural, one {# anden} other {# andre}}", + "name_and_others_with_link": "{name} og {count, plural, one {# anden} other {# andre}}", "navigation_bar.about": "Om", "navigation_bar.advanced_interface": "Åbn i avanceret webgrænseflade", "navigation_bar.blocks": "Blokerede brugere", @@ -468,6 +472,10 @@ "navigation_bar.security": "Sikkerhed", "not_signed_in_indicator.not_signed_in": "Log ind for at tilgå denne ressource.", "notification.admin.report": "{name} anmeldte {target}", + "notification.admin.report_account": "{name} anmeldte {count, plural, one {et indlæg} other {# indlæg}} fra {target} angående {category}", + "notification.admin.report_account_other": "{name} anmeldte {count, plural, one {et indlæg} other {# indlæg}} fra {target}", + "notification.admin.report_statuses": "{name} anmeldte {target} angående {category}", + "notification.admin.report_statuses_other": "{name} anmeldte {target}", "notification.admin.sign_up": "{name} tilmeldte sig", "notification.favourite": "{name} favoritmarkerede dit indlæg", "notification.follow": "{name} begyndte at følge dig", @@ -483,7 +491,8 @@ "notification.moderation_warning.action_silence": "Din konto er blevet begrænset.", "notification.moderation_warning.action_suspend": "Din konto er suspenderet.", "notification.own_poll": "Din afstemning er afsluttet", - "notification.poll": "En afstemning, hvori du stemte, er slut", + "notification.poll": "En afstemning, hvori du har stemt, er slut", + "notification.private_mention": "{name} nævnte dig privat", "notification.reblog": "{name} boostede dit indlæg", "notification.relationships_severance_event": "Mistede forbindelser med {name}", "notification.relationships_severance_event.account_suspension": "En admin fra {from} har suspenderet {target}, hvofor opdateringer herfra eller interaktion hermed ikke længer er mulig.", @@ -501,6 +510,8 @@ "notifications.column_settings.admin.report": "Nye anmeldelser:", "notifications.column_settings.admin.sign_up": "Nye tilmeldinger:", "notifications.column_settings.alert": "Computernotifikationer", + "notifications.column_settings.beta.category": "Eksperimentelle funktioner", + "notifications.column_settings.beta.grouping": "Gruppér notifikationer", "notifications.column_settings.favourite": "Favoritter:", "notifications.column_settings.filter_bar.advanced": "Vis alle kategorier", "notifications.column_settings.filter_bar.category": "Hurtigfiltreringsbjælke", @@ -664,9 +675,13 @@ "report.unfollow_explanation": "Du følger denne konto. For ikke længere at se vedkommendes indlæg i dit hjemmefeed, kan du stoppe med at følge dem.", "report_notification.attached_statuses": "{count, plural, one {{count} post} other {{count} poster}} vedhæftet", "report_notification.categories.legal": "Juridisk", + "report_notification.categories.legal_sentence": "ikke-tilladt indhold", "report_notification.categories.other": "Andre", + "report_notification.categories.other_sentence": "andet", "report_notification.categories.spam": "Spam", + "report_notification.categories.spam_sentence": "spam", "report_notification.categories.violation": "Regelovertrædelse", + "report_notification.categories.violation_sentence": "regelovertrædelse", "report_notification.open": "Åbn anmeldelse", "search.no_recent_searches": "Ingen seneste søgninger", "search.placeholder": "Søg", @@ -694,8 +709,11 @@ "server_banner.about_active_users": "Folk, som brugte denne server de seneste 30 dage (månedlige aktive brugere)", "server_banner.active_users": "aktive brugere", "server_banner.administered_by": "Håndteres af:", + "server_banner.is_one_of_many": "{domain} er en af de mange uafhængige Mastodon-servere, man kan bruge for at deltage i fediverset.", "server_banner.server_stats": "Serverstatstik:", "sign_in_banner.create_account": "Opret konto", + "sign_in_banner.follow_anyone": "Følg alle på tværs af fediverset og se alt i kronologisk rækkefølge. Ingen algoritmer, annoncer eller clickbait i syne.", + "sign_in_banner.mastodon_is": "Mastodon er den bedste måde at holde sig ajour med, hvad der sker.", "sign_in_banner.sign_in": "Log ind", "sign_in_banner.sso_redirect": "Log ind eller Tilmeld", "status.admin_account": "Åbn modereringsbrugerflade for @{name}", diff --git a/app/javascript/mastodon/locales/de.json b/app/javascript/mastodon/locales/de.json index 0f3b3c91a9bfd0..3ba058b9a74618 100644 --- a/app/javascript/mastodon/locales/de.json +++ b/app/javascript/mastodon/locales/de.json @@ -443,6 +443,8 @@ "mute_modal.title": "Profil stummschalten?", "mute_modal.you_wont_see_mentions": "Du wirst keine Beiträge sehen, die dieses Profil erwähnen.", "mute_modal.you_wont_see_posts": "Deine Beiträge können weiterhin angesehen werden, aber du wirst deren Beiträge nicht mehr sehen.", + "name_and_others": "{name} und {count, plural, one {# weitere Person} other {# weitere Personen}}", + "name_and_others_with_link": "{name} und {count, plural, one {# weitere Person} other {# weitere Personen}}", "navigation_bar.about": "Über", "navigation_bar.advanced_interface": "Im erweiterten Webinterface öffnen", "navigation_bar.blocks": "Blockierte Profile", @@ -470,6 +472,10 @@ "navigation_bar.security": "Sicherheit", "not_signed_in_indicator.not_signed_in": "Du musst dich anmelden, um auf diesen Inhalt zugreifen zu können.", "notification.admin.report": "{name} meldete {target}", + "notification.admin.report_account": "{name} meldete {count, plural, one {einen Beitrag} other {# Beiträge}} von {target} wegen {category}", + "notification.admin.report_account_other": "{name} meldete {count, plural, one {einen Beitrag} other {# Beiträge}} von {target}", + "notification.admin.report_statuses": "{name} meldete {target} wegen {category}", + "notification.admin.report_statuses_other": "{name} meldete {target}", "notification.admin.sign_up": "{name} registrierte sich", "notification.favourite": "{name} favorisierte deinen Beitrag", "notification.follow": "{name} folgt dir", @@ -486,6 +492,7 @@ "notification.moderation_warning.action_suspend": "Dein Konto wurde gesperrt.", "notification.own_poll": "Deine Umfrage ist beendet", "notification.poll": "Eine Umfrage, an der du teilgenommen hast, ist beendet", + "notification.private_mention": "{name} hat dich privat erwähnt", "notification.reblog": "{name} teilte deinen Beitrag", "notification.relationships_severance_event": "Verbindungen mit {name} verloren", "notification.relationships_severance_event.account_suspension": "Ein Admin von {from} hat {target} gesperrt. Du wirst von diesem Profil keine Updates mehr erhalten und auch nicht mit ihm interagieren können.", @@ -503,6 +510,8 @@ "notifications.column_settings.admin.report": "Neue Meldungen:", "notifications.column_settings.admin.sign_up": "Neue Registrierungen:", "notifications.column_settings.alert": "Desktop-Benachrichtigungen", + "notifications.column_settings.beta.category": "Experimentelle Funktionen", + "notifications.column_settings.beta.grouping": "Benachrichtigungen gruppieren", "notifications.column_settings.favourite": "Favoriten:", "notifications.column_settings.filter_bar.advanced": "Alle Filterkategorien anzeigen", "notifications.column_settings.filter_bar.category": "Filterleiste", @@ -644,7 +653,7 @@ "report.placeholder": "Ergänzende Hinweise", "report.reasons.dislike": "Das gefällt mir nicht", "report.reasons.dislike_description": "Das ist etwas, das du nicht sehen möchtest", - "report.reasons.legal": "Das ist illegal", + "report.reasons.legal": "Das ist rechtswidrig", "report.reasons.legal_description": "Du glaubst, dass es gegen die Gesetze deines Landes oder des Landes des Servers verstößt", "report.reasons.other": "Es ist etwas anderes", "report.reasons.other_description": "Der Vorfall passt zu keiner dieser Kategorien", @@ -666,9 +675,13 @@ "report.unfollow_explanation": "Du folgst diesem Konto. Um die Beiträge nicht mehr auf deiner Startseite zu sehen, entfolge dem Konto.", "report_notification.attached_statuses": "{count, plural, one {{count} angehangener Beitrag} other {{count} angehängte Beiträge}}", "report_notification.categories.legal": "Rechtliches", + "report_notification.categories.legal_sentence": "rechtswidrigem Inhalt", "report_notification.categories.other": "Nicht aufgeführt", + "report_notification.categories.other_sentence": "etwas anderem", "report_notification.categories.spam": "Spam", + "report_notification.categories.spam_sentence": "Spam", "report_notification.categories.violation": "Regelverstoß", + "report_notification.categories.violation_sentence": "Regelverletzung", "report_notification.open": "Meldung öffnen", "search.no_recent_searches": "Keine früheren Suchanfragen", "search.placeholder": "Suche", diff --git a/app/javascript/mastodon/locales/el.json b/app/javascript/mastodon/locales/el.json index 5442624b36881a..cba2525f37763e 100644 --- a/app/javascript/mastodon/locales/el.json +++ b/app/javascript/mastodon/locales/el.json @@ -35,7 +35,9 @@ "account.follow_back": "Ακολούθησε και εσύ", "account.followers": "Ακόλουθοι", "account.followers.empty": "Κανείς δεν ακολουθεί αυτόν τον χρήστη ακόμα.", + "account.followers_counter": "{count, plural, one {{counter} ακόλουθος} other {{counter} ακόλουθοι}}", "account.following": "Ακολουθείτε", + "account.following_counter": "{count, plural, one {{counter} ακολουθεί} other {{counter} ακολουθούν}}", "account.follows.empty": "Αυτός ο χρήστης δεν ακολουθεί κανέναν ακόμα.", "account.go_to_profile": "Μετάβαση στο προφίλ", "account.hide_reblogs": "Απόκρυψη ενισχύσεων από @{name}", @@ -61,6 +63,7 @@ "account.requested_follow": "Ο/Η {name} αιτήθηκε να σε ακολουθήσει", "account.share": "Κοινοποίηση του προφίλ @{name}", "account.show_reblogs": "Εμφάνιση ενισχύσεων από @{name}", + "account.statuses_counter": "{count, plural, one {{counter} ανάρτηση} other {{counter} αναρτήσεις}}", "account.unblock": "Άρση αποκλεισμού @{name}", "account.unblock_domain": "Άρση αποκλεισμού του τομέα {domain}", "account.unblock_short": "Άρση αποκλεισμού", @@ -75,6 +78,10 @@ "admin.dashboard.retention.average": "Μέσος όρος", "admin.dashboard.retention.cohort": "Μήνας εγγραφής", "admin.dashboard.retention.cohort_size": "Νέοι χρήστες", + "admin.impact_report.instance_accounts": "Προφίλ λογαριασμών που θα διαγράψει", + "admin.impact_report.instance_followers": "Ακόλουθοι που θα χάσουν οι χρήστες μας", + "admin.impact_report.instance_follows": "Ακόλουθοι που θα χάσουν οι χρήστες τους", + "admin.impact_report.title": "Περίληψη επιπτώσεων", "alert.rate_limited.message": "Παρακαλούμε δοκίμασε ξανά μετά τις {retry_time, time, medium}", "alert.rate_limited.title": "Περιορισμός συχνότητας", "alert.unexpected.message": "Προέκυψε απροσδόκητο σφάλμα.", @@ -82,6 +89,14 @@ "announcement.announcement": "Ανακοίνωση", "attachments_list.unprocessed": "(μη επεξεργασμένο)", "audio.hide": "Απόκρυψη αρχείου ήχου", + "block_modal.remote_users_caveat": "Θα ζητήσουμε από τον διακομιστή {domain} να σεβαστεί την απόφασή σου. Ωστόσο, η συμμόρφωση δεν είναι εγγυημένη δεδομένου ότι ορισμένοι διακομιστές ενδέχεται να χειρίζονται τους αποκλεισμούς διαφορετικά. Οι δημόσιες αναρτήσεις ενδέχεται να είναι ορατές σε μη συνδεδεμένους χρήστες.", + "block_modal.show_less": "Εμφάνιση λιγότερων", + "block_modal.show_more": "Εμφάνιση περισσότερων", + "block_modal.they_cant_mention": "Δεν μπορεί να σε επισημάνει ή να σε ακολουθήσει.", + "block_modal.they_cant_see_posts": "Δεν μπορεί να δει τις αναρτήσεις σου και δε θα δεις τις δικές του.", + "block_modal.they_will_know": "Μπορούν να δει ότι έχει αποκλειστεί.", + "block_modal.title": "Αποκλεισμός χρήστη;", + "block_modal.you_wont_see_mentions": "Δε θα βλέπεις τις αναρτήσεις που τον αναφέρουν.", "boost_modal.combo": "Μπορείς να πατήσεις {combo} για να το προσπεράσεις την επόμενη φορά", "bundle_column_error.copy_stacktrace": "Αντιγραφή αναφοράς σφάλματος", "bundle_column_error.error.body": "Δεν ήταν δυνατή η απόδοση της σελίδας που ζήτησες. Μπορεί να οφείλεται σε σφάλμα στον κώδικά μας ή σε πρόβλημα συμβατότητας του προγράμματος περιήγησης.", @@ -108,6 +123,7 @@ "column.directory": "Περιήγηση στα προφίλ", "column.domain_blocks": "Αποκλεισμένοι τομείς", "column.favourites": "Αγαπημένα", + "column.firehose": "Ζωντανές ροές", "column.follow_requests": "Αιτήματα ακολούθησης", "column.home": "Αρχική", "column.lists": "Λίστες", @@ -140,6 +156,7 @@ "compose_form.poll.duration": "Διάρκεια δημοσκόπησης", "compose_form.poll.multiple": "Πολλαπλή επιλογή", "compose_form.poll.option_placeholder": "Επιλογή {number}", + "compose_form.poll.single": "Διάλεξε ένα", "compose_form.poll.switch_to_multiple": "Ενημέρωση δημοσκόπησης με πολλαπλές επιλογές", "compose_form.poll.switch_to_single": "Ενημέρωση δημοσκόπησης με μοναδική επιλογή", "compose_form.poll.type": "Στυλ", @@ -160,6 +177,7 @@ "confirmations.delete_list.message": "Σίγουρα θες να διαγράψεις οριστικά αυτή τη λίστα;", "confirmations.discard_edit_media.confirm": "Απόρριψη", "confirmations.discard_edit_media.message": "Έχεις μη αποθηκευμένες αλλαγές στην περιγραφή πολυμέσων ή στην προεπισκόπηση, απόρριψη ούτως ή άλλως;", + "confirmations.domain_block.confirm": "Αποκλεισμός διακομιστή", "confirmations.domain_block.message": "Σίγουρα θες να αποκλείσεις ολόκληρο τον {domain}; Συνήθως μερικοί συγκεκρίμένοι αποκλεισμοί ή σιγάσεις επαρκούν και προτιμούνται. Δεν θα βλέπεις περιεχόμενο από αυτό τον τομέα σε καμία δημόσια ροή ή στις ειδοποιήσεις σου. Όσους ακόλουθους έχεις αυτό αυτό τον τομέα θα αφαιρεθούν.", "confirmations.edit.confirm": "Επεξεργασία", "confirmations.edit.message": "Αν το επεξεργαστείς τώρα θα αντικατασταθεί το μήνυμα που συνθέτεις. Είσαι σίγουρος ότι θέλεις να συνεχίσεις;", @@ -190,6 +208,28 @@ "dismissable_banner.explore_links": "Αυτές οι ειδήσεις συζητούνται σε αυτόν και άλλους διακομιστές του αποκεντρωμένου δικτύου αυτή τη στιγμή.", "dismissable_banner.explore_statuses": "Αυτές είναι οι αναρτήσεις που έχουν απήχηση στο κοινωνικό δίκτυο σήμερα. Οι νεώτερες αναρτήσεις με περισσότερες προωθήσεις και προτιμήσεις κατατάσσονται ψηλότερα.", "dismissable_banner.explore_tags": "Αυτές οι ετικέτες αποκτούν απήχηση σε αυτόν και άλλους διακομιστές του αποκεντρωμένου δικτύου αυτή τη στιγμή.", + "dismissable_banner.public_timeline": "Αυτές είναι οι πιο πρόσφατες δημόσιες αναρτήσεις από άτομα στον κοινωνικό ιστό που ακολουθούν άτομα από το {domain}.", + "domain_block_modal.block": "Αποκλεισμός διακομιστή", + "domain_block_modal.block_account_instead": "Αποκλεισμός @{name} αντ' αυτού", + "domain_block_modal.they_can_interact_with_old_posts": "Άτομα από αυτόν τον διακομιστή μπορούν να αλληλεπιδράσουν με τις παλιές αναρτήσεις σου.", + "domain_block_modal.they_cant_follow": "Κανείς από αυτόν τον διακομιστή δεν μπορεί να σε ακολουθήσει.", + "domain_block_modal.they_wont_know": "Δεν θα ξέρουν ότι έχουν αποκλειστεί.", + "domain_block_modal.title": "Αποκλεισμός τομέα;", + "domain_block_modal.you_will_lose_followers": "Οι ακόλουθοί σου από αυτόν τον διακομιστή θα αφαιρεθούν.", + "domain_block_modal.you_wont_see_posts": "Δεν θα βλέπεις αναρτήσεις ή ειδοποιήσεις από χρήστες σε αυτόν το διακομιστή.", + "domain_pill.activitypub_lets_connect": "Σού επιτρέπει να συνδεθείς και να αλληλεπιδράσεις με τους ανθρώπους όχι μόνο στο Mastodon, αλλά και σε διαφορετικές κοινωνικές εφαρμογές.", + "domain_pill.activitypub_like_language": "Το ActivityPub είναι σαν τη γλώσσα Mastodon μιλάει με άλλα κοινωνικά δίκτυα.", + "domain_pill.server": "Διακομιστής", + "domain_pill.their_handle": "Το πλήρες όνομα χρήστη:", + "domain_pill.their_server": "Το ψηφιακό του σπίτι, όπου ζουν όλες οι αναρτήσεις του.", + "domain_pill.their_username": "Το μοναδικό του αναγνωριστικό στο διακομιστή του. Είναι πιθανό να βρεις χρήστες με το ίδιο όνομα χρήστη σε διαφορετικούς διακομιστές.", + "domain_pill.username": "Όνομα χρήστη", + "domain_pill.whats_in_a_handle": "Τί υπάρχει σε ένα πλήρες όνομα χρήστη;", + "domain_pill.who_they_are": "Από τη στιγμή που τα πλήρη ονόματα λένε ποιος είναι κάποιος και πού είναι, μπορείς να αλληλεπιδράσεις με άτομα απ' όλο τον κοινωνικό ιστό των .", + "domain_pill.who_you_are": "Επειδή το πλήρες όνομα χρήστη σου λέει ποιος είσαι και πού βρίσκεσαι, άτομα μπορούν να αλληλεπιδράσουν μαζί σου στον κοινωνικό ιστό των .", + "domain_pill.your_handle": "Το πλήρες όνομα χρήστη σου:", + "domain_pill.your_server": "Το ψηφιακό σου σπίτι, όπου ζουν όλες σου οι αναρτήσεις. Δε σ' αρέσει αυτός; Μετακινήσου σε διακομιστές ανά πάσα στιγμή και πάρε και τους ακόλουθούς σου.", + "domain_pill.your_username": "Το μοναδικό σου αναγνωριστικό σε τούτο τον διακομιστή. Είναι πιθανό να βρεις χρήστες με το ίδιο όνομα χρήστη σε διαφορετικούς διακομιστές.", "embed.instructions": "Ενσωμάτωσε αυτή την ανάρτηση στην ιστοσελίδα σου αντιγράφοντας τον παρακάτω κώδικα.", "embed.preview": "Ορίστε πως θα φαίνεται:", "emoji_button.activity": "Δραστηριότητα", @@ -207,6 +247,7 @@ "emoji_button.search_results": "Αποτελέσματα αναζήτησης", "emoji_button.symbols": "Σύμβολα", "emoji_button.travel": "Ταξίδια & Τοποθεσίες", + "empty_column.account_hides_collections": "Αυτός ο χρήστης έχει επιλέξει να μην καταστήσει αυτές τις πληροφορίες διαθέσιμες", "empty_column.account_suspended": "Λογαριασμός σε αναστολή", "empty_column.account_timeline": "Δεν έχει αναρτήσεις εδώ!", "empty_column.account_unavailable": "Μη διαθέσιμο προφίλ", @@ -216,6 +257,8 @@ "empty_column.direct": "Δεν έχεις καμία προσωπική επισήμανση ακόμα. Όταν στείλεις ή λάβεις μία, θα εμφανιστεί εδώ.", "empty_column.domain_blocks": "Δεν υπάρχουν αποκλεισμένοι τομείς ακόμα.", "empty_column.explore_statuses": "Τίποτα δεν βρίσκεται στις τάσεις αυτή τη στιγμή. Έλεγξε αργότερα!", + "empty_column.favourited_statuses": "Δεν έχεις καμία αγαπημένη ανάρτηση ακόμα. Μόλις αγαπήσεις κάποια, θα εμφανιστεί εδώ.", + "empty_column.favourites": "Κανείς δεν έχει αγαπήσει αυτή την ανάρτηση ακόμα. Μόλις το κάνει κάποιος, θα εμφανιστεί εδώ.", "empty_column.follow_requests": "Δεν έχεις κανένα αίτημα παρακολούθησης ακόμα. Μόλις λάβεις κάποιο, θα εμφανιστεί εδώ.", "empty_column.followed_tags": "Δεν έχετε παρακολουθήσει ακόμα καμία ετικέτα. Όταν το κάνετε, θα εμφανιστούν εδώ.", "empty_column.hashtag": "Δεν υπάρχει ακόμα κάτι για αυτή την ετικέτα.", @@ -223,6 +266,7 @@ "empty_column.list": "Δεν υπάρχει τίποτα σε αυτή τη λίστα ακόμα. Όταν τα μέλη της δημοσιεύσουν νέες καταστάσεις, θα εμφανιστούν εδώ.", "empty_column.lists": "Δεν έχεις καμία λίστα ακόμα. Μόλις φτιάξεις μια, θα εμφανιστεί εδώ.", "empty_column.mutes": "Δεν έχεις κανένα χρήστη σε σίγαση ακόμα.", + "empty_column.notification_requests": "Όλα καθαρά! Δεν υπάρχει τίποτα εδώ. Όταν λαμβάνεις νέες ειδοποιήσεις, αυτές θα εμφανίζονται εδώ σύμφωνα με τις ρυθμίσεις σου.", "empty_column.notifications": "Δεν έχεις ειδοποιήσεις ακόμα. Όταν άλλα άτομα αλληλεπιδράσουν μαζί σου, θα το δεις εδώ.", "empty_column.public": "Δεν υπάρχει τίποτα εδώ! Γράψε κάτι δημόσιο ή ακολούθησε χειροκίνητα χρήστες από άλλους διακομιστές για να τη γεμίσεις", "error.unexpected_crash.explanation": "Είτε λόγω σφάλματος στον κώδικά μας ή λόγω ασυμβατότητας με τον περιηγητή, η σελίδα δε μπόρεσε να εμφανιστεί σωστά.", @@ -253,12 +297,30 @@ "filter_modal.select_filter.subtitle": "Χρησιμοποιήστε μια υπάρχουσα κατηγορία ή δημιουργήστε μια νέα", "filter_modal.select_filter.title": "Φιλτράρισμα αυτής της ανάρτησης", "filter_modal.title.status": "Φιλτράρισμα μιας ανάρτησης", + "filtered_notifications_banner.mentions": "{count, plural, one {επισήμανση} other {επισημάνσεις}}", + "filtered_notifications_banner.pending_requests": "Ειδοποιήσεις από {count, plural, =0 {κανένα} one {ένα άτομο} other {# άτομα}} που μπορεί να ξέρεις", + "filtered_notifications_banner.title": "Φιλτραρισμένες ειδοποιήσεις", "firehose.all": "Όλα", "firehose.local": "Αυτός ο διακομιστής", "firehose.remote": "Άλλοι διακομιστές", "follow_request.authorize": "Εξουσιοδότησε", "follow_request.reject": "Απέρριψε", "follow_requests.unlocked_explanation": "Παρόλο που ο λογαριασμός σου δεν είναι κλειδωμένος, το προσωπικό του {domain} θεώρησαν πως ίσως να θέλεις να ελέγξεις χειροκίνητα αυτά τα αιτήματα ακολούθησης.", + "follow_suggestions.curated_suggestion": "Επιλογή προσωπικού", + "follow_suggestions.dismiss": "Να μην εμφανιστεί ξανά", + "follow_suggestions.featured_longer": "Προσεκτικά επιλεγμένα απ' την ομάδα του {domain}", + "follow_suggestions.friends_of_friends_longer": "Δημοφιλή μεταξύ των ατόμων που ακολουθείς", + "follow_suggestions.hints.featured": "Αυτό το προφίλ έχει επιλεγεί προσεκτικά από την ομάδα του {domain}.", + "follow_suggestions.hints.friends_of_friends": "Αυτό το προφίλ είναι δημοφιλές μεταξύ των ατόμων που ακολουθείς.", + "follow_suggestions.hints.most_followed": "Αυτό το προφίλ είναι ένα από τα πιο ακολουθούμενα στο {domain}.", + "follow_suggestions.hints.most_interactions": "Αυτό το προφίλ έχει πάρει πρόσφατα μεγάλη προσοχή στο {domain}.", + "follow_suggestions.hints.similar_to_recently_followed": "Αυτό το προφίλ είναι παρόμοιο με τα προφίλ που έχεις ακολουθήσει πρόσφατα.", + "follow_suggestions.personalized_suggestion": "Εξατομικευμένη πρόταση", + "follow_suggestions.popular_suggestion": "Δημοφιλής πρόταση", + "follow_suggestions.popular_suggestion_longer": "Δημοφιλή στο {domain}", + "follow_suggestions.similar_to_recently_followed_longer": "Παρόμοια με προφίλ που ακολούθησες πρόσφατα", + "follow_suggestions.view_all": "Εμφάνιση όλων", + "follow_suggestions.who_to_follow": "Ποιον να ακολουθήσεις", "followed_tags": "Ετικέτες που ακολουθούνται", "footer.about": "Σχετικά με", "footer.directory": "Κατάλογος προφίλ", @@ -279,21 +341,30 @@ "hashtag.column_settings.tag_mode.any": "Οποιοδήποτε από αυτά", "hashtag.column_settings.tag_mode.none": "Κανένα από αυτά", "hashtag.column_settings.tag_toggle": "Προσθήκη επιπλέον ταμπελών για την κολώνα", + "hashtag.counter_by_accounts": "{count, plural, one {{counter} συμμετέχων} other {{counter} συμμετέχοντες}}", + "hashtag.counter_by_uses": "{count, plural, one {{counter} ανάρτηση} other {{counter} αναρτήσεις}}", + "hashtag.counter_by_uses_today": "{count, plural, one {{counter} ανάρτηση} other {{counter} αναρτήσεις}} σήμερα", "hashtag.follow": "Παρακολούθηση ετικέτας", "hashtag.unfollow": "Διακοπή παρακολούθησης ετικέτας", + "hashtags.and_other": "…και {count, plural, one {}other {# ακόμη}}", "home.column_settings.show_reblogs": "Εμφάνιση προωθήσεων", "home.column_settings.show_replies": "Εμφάνιση απαντήσεων", "home.hide_announcements": "Απόκρυψη ανακοινώσεων", + "home.pending_critical_update.body": "Παρακαλούμε ενημέρωσε τον διακομιστή Mastodon σου το συντομότερο δυνατόν!", "home.pending_critical_update.link": "Δείτε ενημερώσεις", "home.pending_critical_update.title": "Κρίσιμη ενημέρωση ασφαλείας διαθέσιμη!", "home.show_announcements": "Εμφάνιση ανακοινώσεων", + "interaction_modal.description.favourite": "Με ένα συντάκτη στο Mastodon μπορείς να αγαπήσεις αυτή την ανάρτηση, για να ενημερώσεις τον συγγραφέα ότι την εκτιμάς και να την αποθηκεύσεις για αργότερα.", "interaction_modal.description.follow": "Με έναν λογαριασμό Mastodon, μπορείς να ακολουθήσεις τον/την {name} ώστε να λαμβάνεις τις αναρτήσεις του/της στη δική σου ροή.", "interaction_modal.description.reblog": "Με ένα λογαριασμό Mastodon, μπορείς να ενισχύσεις αυτή την ανάρτηση για να τη μοιραστείς με τους δικούς σου ακολούθους.", "interaction_modal.description.reply": "Με ένα λογαριασμό Mastodon, μπορείς να απαντήσεις σε αυτή την ανάρτηση.", "interaction_modal.login.action": "Take me home\nΠήγαινέ με στην αρχική σελίδα", + "interaction_modal.login.prompt": "Τομέας του οικιακού σου διακομιστή, πχ. mastodon.social", "interaction_modal.no_account_yet": "Not on Mastodon?\nΔεν είστε στο Mastodon;", "interaction_modal.on_another_server": "Σε διαφορετικό διακομιστή", "interaction_modal.on_this_server": "Σε αυτόν τον διακομιστή", + "interaction_modal.sign_in": "Δεν είσαι συνδεδεμένος σε αυτόν το διακομιστή. Πού φιλοξενείται ο λογαριασμός σου;", + "interaction_modal.sign_in_hint": "Συμβουλή: Αυτή είναι η ιστοσελίδα όπου έχεις εγγραφεί. Αν δεν θυμάσαι, αναζήτησε το καλώς ήρθες e-mail στα εισερχόμενά σου. Μπορείς επίσης να εισάγεις το πλήρες όνομα χρήστη! (πχ. @Mastodon@mastodon.social)", "interaction_modal.title.favourite": "Favorite {name}'s post\nΠροτίμησε την ανάρτηση της/του {name}", "interaction_modal.title.follow": "Ακολούθησε {name}", "interaction_modal.title.reblog": "Ενίσχυσε την ανάρτηση του {name}", @@ -311,6 +382,7 @@ "keyboard_shortcuts.down": "κίνηση προς τα κάτω στη λίστα", "keyboard_shortcuts.enter": "Εμφάνιση ανάρτησης", "keyboard_shortcuts.favourite": "Αγαπημένη δημοσίευση", + "keyboard_shortcuts.favourites": "Άνοιγμα λίστας αγαπημένων", "keyboard_shortcuts.federated": "Άνοιγμα ροής συναλλαγών", "keyboard_shortcuts.heading": "Συντομεύσεις πληκτρολογίου", "keyboard_shortcuts.home": "Άνοιγμα ροής αρχικής σελίδας", @@ -341,11 +413,15 @@ "lightbox.previous": "Προηγούμενο", "limited_account_hint.action": "Εμφάνιση προφίλ ούτως ή άλλως", "limited_account_hint.title": "Αυτό το προφίλ έχει αποκρυφτεί από τους διαχειριστές του διακομιστή {domain}.", + "link_preview.author": "Από {name}", + "link_preview.more_from_author": "Περισσότερα από {name}", + "link_preview.shares": "{count, plural, one {{counter} ανάρτηση} other {{counter} αναρτήσεις}}", "lists.account.add": "Πρόσθεσε στη λίστα", "lists.account.remove": "Βγάλε από τη λίστα", "lists.delete": "Διαγραφή λίστας", "lists.edit": "Επεξεργασία λίστας", "lists.edit.submit": "Αλλαγή τίτλου", + "lists.exclusive": "Απόκρυψη αυτών των αναρτήσεων από την αρχική", "lists.new.create": "Προσθήκη λίστας", "lists.new.title_placeholder": "Τίτλος νέας λίστα", "lists.replies_policy.followed": "Οποιοσδήποτε χρήστης που ακολουθείς", @@ -358,7 +434,19 @@ "loading_indicator.label": "Φόρτωση…", "media_gallery.toggle_visible": "{number, plural, one {Απόκρυψη εικόνας} other {Απόκρυψη εικόνων}}", "moved_to_account_banner.text": "Ο λογαριασμός σου {disabledAccount} είναι προσωρινά απενεργοποιημένος επειδή μεταφέρθηκες στον {movedToAccount}.", + "mute_modal.hide_from_notifications": "Απόκρυψη από ειδοποιήσεις", + "mute_modal.hide_options": "Απόκρυψη επιλογών", + "mute_modal.indefinite": "Μέχρι να κάνω άρση σίγασης", + "mute_modal.show_options": "Εμφάνιση επιλογών", + "mute_modal.they_can_mention_and_follow": "Μπορεί να σε αναφέρει και να σε ακολουθήσει, αλλά δε θα τον βλέπεις.", + "mute_modal.they_wont_know": "Δε θα ξέρει ότι είναι σε σίγαση.", + "mute_modal.title": "Σίγαση χρήστη;", + "mute_modal.you_wont_see_mentions": "Δε θα βλέπεις τις αναρτήσεις που τον αναφέρουν.", + "mute_modal.you_wont_see_posts": "Μπορεί ακόμα να δει τις αναρτήσεις σου, αλλά δε θα βλέπεις τις δικές του.", + "name_and_others": "{name} και {count, plural, one {# ακόμη} other {# ακόμη}}", + "name_and_others_with_link": "{name} και {count, plural, one {# ακόμη} other {# ακόμη}}", "navigation_bar.about": "Σχετικά με", + "navigation_bar.advanced_interface": "Άνοιγμα σε προηγμένη διεπαφή ιστού", "navigation_bar.blocks": "Αποκλεισμένοι χρήστες", "navigation_bar.bookmarks": "Σελιδοδείκτες", "navigation_bar.community_timeline": "Τοπική ροή", @@ -367,6 +455,7 @@ "navigation_bar.discover": "Ανακάλυψη", "navigation_bar.domain_blocks": "Αποκλεισμένοι τομείς", "navigation_bar.explore": "Εξερεύνηση", + "navigation_bar.favourites": "Αγαπημένα", "navigation_bar.filters": "Αποσιωπημένες λέξεις", "navigation_bar.follow_requests": "Αιτήματα ακολούθησης", "navigation_bar.followed_tags": "Ετικέτες που ακολουθούνται", @@ -383,22 +472,49 @@ "navigation_bar.security": "Ασφάλεια", "not_signed_in_indicator.not_signed_in": "Πρέπει να συνδεθείς για να αποκτήσεις πρόσβαση σε αυτόν τον πόρο.", "notification.admin.report": "Ο/Η {name} ανέφερε τον {target}", + "notification.admin.report_account": "Ο χρήστης {name} ανέφερε {count, plural, one {μία ανάρτηση} other {# αναρτήσεις}} από {target} για {category}", + "notification.admin.report_account_other": "Ο χρήστης {name} ανέφερε {count, plural, one {μία ανάρτηση} other {# αναρτήσεις}} από {target}", + "notification.admin.report_statuses": "Ο χρήστης {name} ανέφερε τον χρήστη {target} για {category}", + "notification.admin.report_statuses_other": "Ο χρήστης {name} ανέφερε τον χρήστη {target}", "notification.admin.sign_up": "{name} έχει εγγραφεί", "notification.favourite": "{name} favorited your post\n{name} προτίμησε την ανάρτηση σου", "notification.follow": "Ο/Η {name} σε ακολούθησε", "notification.follow_request": "Ο/H {name} ζήτησε να σε ακολουθήσει", "notification.mention": "Ο/Η {name} σε επισήμανε", + "notification.moderation-warning.learn_more": "Μάθε περισσότερα", + "notification.moderation_warning": "Έχετε λάβει μία προειδοποίηση συντονισμού", + "notification.moderation_warning.action_delete_statuses": "Ορισμένες από τις αναρτήσεις σου έχουν αφαιρεθεί.", + "notification.moderation_warning.action_disable": "Ο λογαριασμός σου έχει απενεργοποιηθεί.", + "notification.moderation_warning.action_mark_statuses_as_sensitive": "Μερικές από τις αναρτήσεις σου έχουν επισημανθεί ως ευαίσθητες.", + "notification.moderation_warning.action_none": "Ο λογαριασμός σου έχει λάβει προειδοποίηση συντονισμού.", + "notification.moderation_warning.action_sensitive": "Οι αναρτήσεις σου θα επισημαίνονται, από εδώ και στο εξής, ως ευαίσθητες.", + "notification.moderation_warning.action_silence": "Ο λογαριασμός σου έχει περιοριστεί.", + "notification.moderation_warning.action_suspend": "Ο λογαριασμός σου έχει ανασταλεί.", "notification.own_poll": "Η δημοσκόπησή σου έληξε", - "notification.poll": "Τελείωσε μια από τις δημοσκοπήσεις που συμμετείχες", + "notification.poll": "Μία ψηφοφορία στην οποία συμμετείχες έχει τελειώσει", + "notification.private_mention": "{name} σέ επισήμανε ιδιωτικά", "notification.reblog": "Ο/Η {name} ενίσχυσε τη δημοσίευσή σου", + "notification.relationships_severance_event": "Χάθηκε η σύνδεση με το {name}", + "notification.relationships_severance_event.account_suspension": "Ένας διαχειριστής από το {from} ανέστειλε το {target}, πράγμα που σημαίνει ότι δεν μπορείς πλέον να λαμβάνεις ενημερώσεις από αυτούς ή να αλληλεπιδράς μαζί τους.", + "notification.relationships_severance_event.domain_block": "Ένας διαχειριστής από {from} έχει μπλοκάρει το {target}, συμπεριλαμβανομένων {followersCount} από τους ακόλουθούς σου και {followingCount, plural, one {# λογαριασμό} other {# λογαριασμοί}} που ακολουθείς.", + "notification.relationships_severance_event.learn_more": "Μάθε περισσότερα", + "notification.relationships_severance_event.user_domain_block": "Έχεις αποκλείσει τον λογαριασμό {target}, αφαιρώντας {followersCount} από τους ακόλουθούς σου και {followingCount, plural, one {# λογαριασμό} other {# λογαριασμοί}} που ακολουθείς.", "notification.status": "Ο/Η {name} μόλις ανέρτησε κάτι", "notification.update": "ο/η {name} επεξεργάστηκε μια ανάρτηση", + "notification_requests.accept": "Αποδοχή", + "notification_requests.dismiss": "Απόρριψη", + "notification_requests.notifications_from": "Ειδοποιήσεις από {name}", + "notification_requests.title": "Φιλτραρισμένες ειδοποιήσεις", "notifications.clear": "Καθαρισμός ειδοποιήσεων", "notifications.clear_confirmation": "Σίγουρα θέλεις να καθαρίσεις μόνιμα όλες τις ειδοποιήσεις σου;", "notifications.column_settings.admin.report": "Νέες αναφορές:", "notifications.column_settings.admin.sign_up": "Νέες εγγραφές:", "notifications.column_settings.alert": "Ειδοποιήσεις επιφάνειας εργασίας", + "notifications.column_settings.beta.category": "Πειραματικές λειτουργίες", + "notifications.column_settings.beta.grouping": "Ομαδοποίηση ειδοποιήσεων", "notifications.column_settings.favourite": "Αγαπημένα:", + "notifications.column_settings.filter_bar.advanced": "Εμφάνιση όλων των κατηγοριών", + "notifications.column_settings.filter_bar.category": "Μπάρα γρήγορου φίλτρου", "notifications.column_settings.follow": "Νέοι ακόλουθοι:", "notifications.column_settings.follow_request": "Νέο αίτημα ακολούθησης:", "notifications.column_settings.mention": "Επισημάνσεις:", @@ -413,6 +529,7 @@ "notifications.column_settings.update": "Επεξεργασίες:", "notifications.filter.all": "Όλες", "notifications.filter.boosts": "Προωθήσεις", + "notifications.filter.favourites": "Αγαπημένα", "notifications.filter.follows": "Ακολουθείς", "notifications.filter.mentions": "Επισημάνσεις", "notifications.filter.polls": "Αποτελέσματα δημοσκόπησης", @@ -423,6 +540,15 @@ "notifications.permission_denied": "Οι ειδοποιήσεις στην επιφάνεια εργασίας δεν είναι διαθέσιμες διότι έχει απορριφθεί κάποιο προηγούμενο αίτημα άδειας", "notifications.permission_denied_alert": "Δεν είναι δυνατή η ενεργοποίηση των ειδοποιήσεων της επιφάνειας εργασίας, καθώς η άδεια του προγράμματος περιήγησης έχει απορριφθεί νωρίτερα", "notifications.permission_required": "Οι ειδοποιήσεις δεν είναι διαθέσιμες επειδή δεν έχει δοθεί η απαιτούμενη άδεια.", + "notifications.policy.filter_new_accounts.hint": "Δημιουργήθηκε εντός {days, plural, one {της τελευταίας ημέρας} other {των τελευταίων # ημερών}}", + "notifications.policy.filter_new_accounts_title": "Νέοι λογαριασμοί", + "notifications.policy.filter_not_followers_hint": "Συμπεριλαμβανομένων των ατόμων που σας έχουν ακολουθήσει λιγότερο από {days, plural, one {μια ημέρα} other {# ημέρες}} πριν", + "notifications.policy.filter_not_followers_title": "Άτομα που δε σε ακολουθούν", + "notifications.policy.filter_not_following_hint": "Μέχρι να τους εγκρίνεις χειροκίνητα", + "notifications.policy.filter_not_following_title": "Άτομα που δεν ακολουθείς", + "notifications.policy.filter_private_mentions_hint": "Φιλτραρισμένο εκτός αν είναι απάντηση σε δική σου αναφορά ή αν ακολουθείς τον αποστολέα", + "notifications.policy.filter_private_mentions_title": "Μη συναινετικές ιδιωτικές αναφορές", + "notifications.policy.title": "Φιλτράρισμα ειδοποιήσεων από…", "notifications_permission_banner.enable": "Ενεργοποίηση ειδοποιήσεων επιφάνειας εργασίας", "notifications_permission_banner.how_to_control": "Για να λαμβάνεις ειδοποιήσεις όταν το Mastodon δεν είναι ανοιχτό, ενεργοποίησε τις ειδοποιήσεις επιφάνειας εργασίας. Μπορείς να ελέγξεις με ακρίβεια ποιοι τύποι αλληλεπιδράσεων δημιουργούν ειδοποιήσεις επιφάνειας εργασίας μέσω του κουμπιού {icon} μόλις ενεργοποιηθούν.", "notifications_permission_banner.title": "Μη χάσεις στιγμή", @@ -430,8 +556,15 @@ "onboarding.actions.back": "Επιστροφή", "onboarding.actions.go_to_explore": "See what's trending", "onboarding.actions.go_to_home": "Πηγαίνετε στην αρχική σας ροή", + "onboarding.compose.template": "Γειά σου #Mastodon!", + "onboarding.follows.empty": "Δυστυχώς, δεν μπορούν να εμφανιστούν αποτελέσματα αυτή τη στιγμή. Μπορείς να προσπαθήσεις να χρησιμοποιήσεις την αναζήτηση ή να περιηγηθείς στη σελίδα εξερεύνησης για να βρεις άτομα να ακολουθήσεις ή να δοκιμάσεις ξανά αργότερα.", "onboarding.follows.lead": "You curate your own home feed. The more people you follow, the more active and interesting it will be. These profiles may be a good starting point—you can always unfollow them later!", "onboarding.follows.title": "Δημοφιλή στο Mastodon", + "onboarding.profile.discoverable": "Κάνε το προφίλ μου ανακαλύψιμο", + "onboarding.profile.discoverable_hint": "Όταν επιλέγεις την δυνατότητα ανακάλυψης στο Mastodon, οι αναρτήσεις σου μπορεί να εμφανιστούν στα αποτελέσματα αναζήτησης και τις τάσεις, και το προφίλ σου μπορεί να προτείνεται σε άτομα με παρόμοια ενδιαφέροντα με εσένα.", + "onboarding.profile.display_name": "Εμφανιζόμενο όνομα", + "onboarding.profile.display_name_hint": "Το πλήρες ή το διασκεδαστικό σου όνομα…", + "onboarding.profile.lead": "Μπορείς πάντα να το ολοκληρώσεις αργότερα στις ρυθμίσεις, όπου είναι διαθέσιμες ακόμα περισσότερες επιλογές προσαρμογής.", "onboarding.profile.note": "Βιογραφικό", "onboarding.profile.note_hint": "Μπορείτε να @αναφέρετε άλλα άτομα ή #hashtags…", "onboarding.profile.save_and_continue": "Αποθήκευση και συνέχεια", @@ -439,7 +572,9 @@ "onboarding.profile.upload_avatar": "Μεταφόρτωση εικόνας προφίλ", "onboarding.profile.upload_header": "Μεταφόρτωση κεφαλίδας προφίλ", "onboarding.share.lead": "Let people know how they can find you on Mastodon!\nΕνημερώστε άλλα άτομα πώς μπορούν να σας βρουν στο Mastodon!", + "onboarding.share.message": "Με λένε {username} στο #Mastodon! Έλα να με ακολουθήσεις στο {url}", "onboarding.share.next_steps": "Πιθανά επόμενα βήματα:", + "onboarding.share.title": "Κοινοποίηση του προφίλ σου", "onboarding.start.lead": "Your new Mastodon account is ready to go. Here's how you can make the most of it:", "onboarding.start.skip": "Want to skip right ahead?", "onboarding.start.title": "You've made it!\nΤα καταφέρατε!", @@ -451,6 +586,10 @@ "onboarding.steps.setup_profile.title": "Customize your profile", "onboarding.steps.share_profile.body": "Let your friends know how to find you on Mastodon!", "onboarding.steps.share_profile.title": "Share your profile", + "onboarding.tips.2fa": "Το ήξερες; Μπορείς να ασφαλίσεις το λογαριασμό σου ρυθμίζοντας ταυτότητα δύο παραγόντων στις ρυθμίσεις του λογαριασμού σου. Λειτουργεί με οποιαδήποτε εφαρμογή TOTP της επιλογής σας, δεν απαιτείται αριθμός τηλεφώνου!", + "onboarding.tips.accounts_from_other_servers": "Το ήξερες; Από τη στιγμή που το Mastodon είναι αποκεντρωμένο, κάποια προφίλ που συναντάς θα φιλοξενούνται σε διακομιστές διαφορετικούς από τον δικό σου. Και παρόλα αυτά μπορείς να αλληλεπιδράσεις μαζί τους απρόσκοπτα! Ο διακομιστής τους είναι στο δεύτερο μισό του ονόματος χρήστη!", + "onboarding.tips.migration": "Το ήξερες; Αν αισθάνεσαι ότι το {domain} δεν είναι η κατάλληλη επιλογή διακομιστή για σένα στο μέλλον, μπορείς να μετακινηθείς σε άλλο διακομιστή Mastodon χωρίς να χάσεις τους ακόλουθούς σου. Μπορείς να κάνεις ακόμα και τον δικό σου διακομιστή!", + "onboarding.tips.verification": "Το ήξερες; Μπορείς να επαληθεύσεις τον λογαριασμό σου βάζοντας έναν σύνδεσμο του προφίλ σου στο Mastodon στην ιστοσελίδα σου και να προσθέσεις την ιστοσελίδα στο προφίλ σου. Χωρίς έξοδα ή έγγραφα!", "password_confirmation.exceeds_maxlength": "Η επιβεβαίωση κωδικού πρόσβασης υπερβαίνει το μέγιστο μήκος κωδικού πρόσβασης", "password_confirmation.mismatching": "Η επιβεβαίωση του κωδικού πρόσβασης δε συμπίπτει", "picture_in_picture.restore": "Βάλε το πίσω", @@ -469,7 +608,11 @@ "privacy.direct.short": "Συγκεκριμένα άτομα", "privacy.private.long": "Μόνο οι ακόλουθοί σας", "privacy.private.short": "Ακόλουθοι", + "privacy.public.long": "Όλοι εντός και εκτός του Mastodon", "privacy.public.short": "Δημόσιο", + "privacy.unlisted.additional": "Αυτό συμπεριφέρεται ακριβώς όπως το δημόσιο, εκτός από το ότι η ανάρτηση δεν θα εμφανιστεί σε ζωντανές ροές ή ετικέτες, εξερεύνηση ή αναζήτηση στο Mastodon, ακόμη και αν το έχεις επιλέξει για τον λογαριασμό σου.", + "privacy.unlisted.long": "Λιγότερα αλγοριθμικά κόλπα", + "privacy.unlisted.short": "Ήσυχα δημόσια", "privacy_policy.last_updated": "Τελευταία ενημέρωση {date}", "privacy_policy.title": "Πολιτική Απορρήτου", "recommended": "Προτεινόμενα", @@ -487,6 +630,7 @@ "relative_time.minutes": "{number}λ", "relative_time.seconds": "{number}δ", "relative_time.today": "σήμερα", + "reply_indicator.attachments": "{count, plural, one {# συνημμένο} other {# συνημμένα}}", "reply_indicator.cancel": "Άκυρο", "reply_indicator.poll": "Δημοσκόπηση", "report.block": "Αποκλεισμός", @@ -530,9 +674,14 @@ "report.unfollow": "Κατάργηση ακολούθησης του @{name}", "report.unfollow_explanation": "Ακολουθείς αυτό τον λογαριασμό. Για να μη βλέπεις τις αναρτήσεις τους στη δική σου ροή, πάψε να τον ακολουθείς.", "report_notification.attached_statuses": "{count, plural, one {{count} ανάρτηση} other {{count} αναρτήσεις}} επισυνάπτονται", + "report_notification.categories.legal": "Νομικά", + "report_notification.categories.legal_sentence": "παράνομο περιεχόμενο", "report_notification.categories.other": "Άλλες", + "report_notification.categories.other_sentence": "άλλο", "report_notification.categories.spam": "Ανεπιθύμητα", + "report_notification.categories.spam_sentence": "ανεπιθύμητα", "report_notification.categories.violation": "Παραβίαση κανόνα", + "report_notification.categories.violation_sentence": "παραβίαση κανόνα", "report_notification.open": "Ανοιχτή αναφορά", "search.no_recent_searches": "Καμία πρόσφατη αναζήτηση", "search.placeholder": "Αναζήτηση", @@ -542,8 +691,13 @@ "search.quick_action.open_url": "Άνοιγμα διεύθυνσης URL στο Mastodon", "search.quick_action.status_search": "Αναρτήσεις που ταιριάζουν με {x}", "search.search_or_paste": "Αναζήτηση ή εισαγωγή URL", + "search_popout.full_text_search_disabled_message": "Μη διαθέσιμο στο {domain}.", + "search_popout.full_text_search_logged_out_message": "Διαθέσιμο μόνο όταν συνδεθείς.", + "search_popout.language_code": "Κωδικός γλώσσας ISO", + "search_popout.options": "Επιλογές αναζήτησης", "search_popout.quick_actions": "Γρήγορες ενέργειες", "search_popout.recent": "Πρόσφατες αναζητήσεις", + "search_popout.specific_date": "συγκεκριμένη ημερομηνία", "search_popout.user": "χρήστης", "search_results.accounts": "Προφίλ", "search_results.all": "Όλα", @@ -555,8 +709,11 @@ "server_banner.about_active_users": "Άτομα που χρησιμοποιούν αυτόν τον διακομιστή κατά τις τελευταίες 30 ημέρες (Μηνιαία Ενεργοί Χρήστες)", "server_banner.active_users": "ενεργοί χρήστες", "server_banner.administered_by": "Διαχειριστής:", + "server_banner.is_one_of_many": "Το {domain} είναι ένας από τους πολλούς ανεξάρτητους διακομιστές Mastodon που μπορείς να χρησιμοποιήσεις για να συμμετάσχεις στο fediverse.", "server_banner.server_stats": "Στατιστικά διακομιστή:", "sign_in_banner.create_account": "Δημιουργία λογαριασμού", + "sign_in_banner.follow_anyone": "Ακολούθησε οποιονδήποτε κατά μήκος του fediverse και δες τα όλα με χρονολογική σειρά. Δεν υπάρχουν αλγόριθμοι, διαφημίσεις ή clickbait ούτε για δείγμα.", + "sign_in_banner.mastodon_is": "Το Mastodon είναι ο καλύτερος τρόπος για να συμβαδίσεις με τα γεγονότα.", "sign_in_banner.sign_in": "Σύνδεση", "sign_in_banner.sso_redirect": "Συνδεθείτε ή Εγγραφείτε", "status.admin_account": "Άνοιγμα διεπαφής συντονισμού για τον/την @{name}", @@ -572,15 +729,19 @@ "status.direct": "Ιδιωτική επισήμανση @{name}", "status.direct_indicator": "Ιδιωτική επισήμανση", "status.edit": "Επεξεργασία", + "status.edited": "Τελευταία επεξεργασία {date}", "status.edited_x_times": "Επεξεργάστηκε {count, plural, one {{count} φορά} other {{count} φορές}}", "status.embed": "Ενσωμάτωσε", "status.favourite": "Αγαπημένα", + "status.favourites": "{count, plural, one {# αγαπημένο} other {# αγαπημένα}}", "status.filter": "Φιλτράρισμα αυτής της ανάρτησης", "status.filtered": "Φιλτραρισμένα", "status.hide": "Απόκρυψη ανάρτησης", "status.history.created": "{name} δημιούργησε στις {date}", "status.history.edited": "{name} επεξεργάστηκε στις {date}", "status.load_more": "Φόρτωσε περισσότερα", + "status.media.open": "Κάνε κλικ για άνοιγμα", + "status.media.show": "Κάνε κλικ για εμφάνιση", "status.media_hidden": "Κρυμμένο πολυμέσο", "status.mention": "Επισήμανε @{name}", "status.more": "Περισσότερα", @@ -593,6 +754,7 @@ "status.reblog": "Ενίσχυση", "status.reblog_private": "Ενίσχυση με αρχική ορατότητα", "status.reblogged_by": "{name} προώθησε", + "status.reblogs": "{count, plural, one {# ενίσχυση} other {# ενισχύσεις}}", "status.reblogs.empty": "Κανείς δεν ενίσχυσε αυτή την ανάρτηση ακόμα. Μόλις το κάνει κάποιος, θα εμφανιστεί εδώ.", "status.redraft": "Σβήσε & ξαναγράψε", "status.remove_bookmark": "Αφαίρεση σελιδοδείκτη", @@ -611,6 +773,7 @@ "status.title.with_attachments": "{user} δημοσίευσε {attachmentCount, plural, one {ένα συνημμένο} other {{attachmentCount} συνημμένα}}", "status.translate": "Μετάφραση", "status.translated_from_with": "Μεταφράστηκε από {lang} χρησιμοποιώντας {provider}", + "status.uncached_media_warning": "Μη διαθέσιμη προεπισκόπηση", "status.unmute_conversation": "Αναίρεση σίγασης συνομιλίας", "status.unpin": "Ξεκαρφίτσωσε από το προφίλ", "subscribed_languages.lead": "Μόνο αναρτήσεις σε επιλεγμένες γλώσσες θα εμφανίζονται στην αρχική σου και θα παραθέτονται χρονοδιαγράμματα μετά την αλλαγή. Επέλεξε καμία για να λαμβάνεις αναρτήσεις σε όλες τις γλώσσες.", diff --git a/app/javascript/mastodon/locales/en-GB.json b/app/javascript/mastodon/locales/en-GB.json index 94d7defc7ee456..6143c6e1ca09a2 100644 --- a/app/javascript/mastodon/locales/en-GB.json +++ b/app/javascript/mastodon/locales/en-GB.json @@ -485,7 +485,6 @@ "notification.moderation_warning.action_silence": "Your account has been limited.", "notification.moderation_warning.action_suspend": "Your account has been suspended.", "notification.own_poll": "Your poll has ended", - "notification.poll": "A poll you have voted in has ended", "notification.reblog": "{name} boosted your status", "notification.relationships_severance_event": "Lost connections with {name}", "notification.relationships_severance_event.account_suspension": "An admin from {from} has suspended {target}, which means you can no longer receive updates from them or interact with them.", diff --git a/app/javascript/mastodon/locales/en.json b/app/javascript/mastodon/locales/en.json index 7faac14223b580..a3f49bb8cec508 100644 --- a/app/javascript/mastodon/locales/en.json +++ b/app/javascript/mastodon/locales/en.json @@ -552,6 +552,8 @@ "mute_modal.title": "Mute user?", "mute_modal.you_wont_see_mentions": "You won't see posts that mention them.", "mute_modal.you_wont_see_posts": "They can still see your posts, but you won't see theirs.", + "name_and_others": "{name} and {count, plural, one {# other} other {# others}}", + "name_and_others_with_link": "{name} and {count, plural, one {# other} other {# others}}", "navigation_bar.about": "About", "navigation_bar.advanced_interface": "Open in advanced web interface", "navigation_bar.antennas": "Antenna", @@ -585,8 +587,12 @@ "navigation_bar.security": "Security", "not_signed_in_indicator.not_signed_in": "You need to login to access this resource.", "notification.admin.report": "{name} reported {target}", + "notification.admin.report_account": "{name} reported {count, plural, one {one post} other {# posts}} from {target} for {category}", + "notification.admin.report_account_other": "{name} reported {count, plural, one {one post} other {# posts}} from {target}", + "notification.admin.report_statuses": "{name} reported {target} for {category}", + "notification.admin.report_statuses_other": "{name} reported {target}", "notification.admin.sign_up": "{name} signed up", - "notification.emoji_reaction": "{name} reacted your post with emoji", + "notification.emoji_reaction": "{name} reacted your status with emoji", "notification.favourite": "{name} favorited your post", "notification.follow": "{name} followed you", "notification.follow_request": "{name} has requested to follow you", @@ -603,7 +609,8 @@ "notification.moderation_warning.action_silence": "Your account has been limited.", "notification.moderation_warning.action_suspend": "Your account has been suspended.", "notification.own_poll": "Your poll has ended", - "notification.poll": "A poll you have voted in has ended", + "notification.poll": "A poll you voted in has ended", + "notification.private_mention": "{name} privately mentioned you", "notification.reblog": "{name} boosted your post", "notification.relationships_severance_event": "Lost connections with {name}", "notification.relationships_severance_event.account_suspension": "An admin from {from} has suspended {target}, which means you can no longer receive updates from them or interact with them.", @@ -622,7 +629,9 @@ "notifications.column_settings.admin.report": "New reports:", "notifications.column_settings.admin.sign_up": "New sign-ups:", "notifications.column_settings.alert": "Desktop notifications", - "notifications.column_settings.emoji_reaction": "Stamps:", + "notifications.column_settings.beta.category": "Experimental features", + "notifications.column_settings.beta.grouping": "Group notifications", + "notifications.column_settings.emoji_reaction": "Emoji reactions:", "notifications.column_settings.favourite": "Favorites:", "notifications.column_settings.filter_bar.advanced": "Display all categories", "notifications.column_settings.filter_bar.category": "Quick filter bar", @@ -807,9 +816,13 @@ "report.unfollow_explanation": "You are following this account. To not see their posts in your home feed anymore, unfollow them.", "report_notification.attached_statuses": "{count, plural, one {{count} post} other {{count} posts}} attached", "report_notification.categories.legal": "Legal", + "report_notification.categories.legal_sentence": "illegal content", "report_notification.categories.other": "Other", + "report_notification.categories.other_sentence": "other", "report_notification.categories.spam": "Spam", + "report_notification.categories.spam_sentence": "spam", "report_notification.categories.violation": "Rule violation", + "report_notification.categories.violation_sentence": "rule violation", "report_notification.open": "Open report", "search.no_recent_searches": "No recent searches", "search.placeholder": "Search", diff --git a/app/javascript/mastodon/locales/eo.json b/app/javascript/mastodon/locales/eo.json index e7cfc03468140e..211f4ad8d91677 100644 --- a/app/javascript/mastodon/locales/eo.json +++ b/app/javascript/mastodon/locales/eo.json @@ -405,7 +405,6 @@ "notification.follow_request": "{name} petis sekvi vin", "notification.mention": "{name} menciis vin", "notification.own_poll": "Via enketo finiĝis", - "notification.poll": "Partoprenita balotenketo finiĝis", "notification.reblog": "{name} diskonigis vian afiŝon", "notification.status": "{name} ĵus afiŝis", "notification.update": "{name} redaktis afiŝon", diff --git a/app/javascript/mastodon/locales/es-AR.json b/app/javascript/mastodon/locales/es-AR.json index 28e8de92374547..2e22865493f08a 100644 --- a/app/javascript/mastodon/locales/es-AR.json +++ b/app/javascript/mastodon/locales/es-AR.json @@ -443,6 +443,8 @@ "mute_modal.title": "¿Silenciar usuario?", "mute_modal.you_wont_see_mentions": "No verás mensajes que los mencionen.", "mute_modal.you_wont_see_posts": "Todavía pueden ver tus mensajes, pero vos no verás los suyos.", + "name_and_others": "{name} y {count, plural, one {# cuenta más} other {# cuentas más}}", + "name_and_others_with_link": "{name} y {count, plural, one {# cuenta más} other {# cuentas más}}", "navigation_bar.about": "Información", "navigation_bar.advanced_interface": "Abrir en interface web avanzada", "navigation_bar.blocks": "Usuarios bloqueados", @@ -470,6 +472,10 @@ "navigation_bar.security": "Seguridad", "not_signed_in_indicator.not_signed_in": "Necesitás iniciar sesión para acceder a este recurso.", "notification.admin.report": "{name} denunció a {target}", + "notification.admin.report_account": "{name} denunció {count, plural, one {un mensaje} other {# mensajes}} de {target} por {category}", + "notification.admin.report_account_other": "{name} denunció {count, plural, one {un mensaje} other {# mensajes}} de {target}", + "notification.admin.report_statuses": "{name} denunció a {target} por {category}", + "notification.admin.report_statuses_other": "{name} denunció a {target}", "notification.admin.sign_up": "Se registró {name}", "notification.favourite": "{name} marcó tu mensaje como favorito", "notification.follow": "{name} te empezó a seguir", @@ -486,6 +492,7 @@ "notification.moderation_warning.action_suspend": "Tu cuenta fue suspendida.", "notification.own_poll": "Tu encuesta finalizó", "notification.poll": "Finalizó una encuesta en la que votaste", + "notification.private_mention": "{name} te mencionó en privado", "notification.reblog": "{name} adhirió a tu mensaje", "notification.relationships_severance_event": "Conexiones perdidas con {name}", "notification.relationships_severance_event.account_suspension": "Un administrador de {from} suspendió a {target}, lo que significa que ya no podés recibir actualizaciones de esa cuenta o interactuar con la misma.", @@ -503,6 +510,8 @@ "notifications.column_settings.admin.report": "Nuevas denuncias:", "notifications.column_settings.admin.sign_up": "Nuevos registros:", "notifications.column_settings.alert": "Notificaciones de escritorio", + "notifications.column_settings.beta.category": "Funciones experimentales", + "notifications.column_settings.beta.grouping": "Agrupar notificaciones", "notifications.column_settings.favourite": "Favoritos:", "notifications.column_settings.filter_bar.advanced": "Mostrar todas las categorías", "notifications.column_settings.filter_bar.category": "Barra de filtrado rápido", @@ -666,9 +675,13 @@ "report.unfollow_explanation": "Estás siguiendo a esta cuenta. Para no ver sus mensajes en tu línea temporal principal, dejá de seguirla.", "report_notification.attached_statuses": "{count, plural, one {{count} mensaje adjunto} other {{count} mensajes adjuntos}}", "report_notification.categories.legal": "Legal", + "report_notification.categories.legal_sentence": "contenido ilegal", "report_notification.categories.other": "Otros", + "report_notification.categories.other_sentence": "[otras categorías]", "report_notification.categories.spam": "Spam", + "report_notification.categories.spam_sentence": "spam", "report_notification.categories.violation": "Violación de regla", + "report_notification.categories.violation_sentence": "violación de regla", "report_notification.open": "Abrir denuncia", "search.no_recent_searches": "Sin búsquedas recientes", "search.placeholder": "Buscar", diff --git a/app/javascript/mastodon/locales/es-MX.json b/app/javascript/mastodon/locales/es-MX.json index c10a1610155fa3..837bbbc2cea639 100644 --- a/app/javascript/mastodon/locales/es-MX.json +++ b/app/javascript/mastodon/locales/es-MX.json @@ -443,6 +443,8 @@ "mute_modal.title": "¿Silenciar usuario?", "mute_modal.you_wont_see_mentions": "No verás publicaciones que los mencionen.", "mute_modal.you_wont_see_posts": "Todavía pueden ver tus publicaciones, pero tú no verás las de ellos.", + "name_and_others": "{name} y {count, plural, one {# más} other {# más}}", + "name_and_others_with_link": "{name} y {count, plural, one {# más} other {# más}}", "navigation_bar.about": "Acerca de", "navigation_bar.advanced_interface": "Abrir en interfaz web avanzada", "navigation_bar.blocks": "Usuarios bloqueados", @@ -470,6 +472,10 @@ "navigation_bar.security": "Seguridad", "not_signed_in_indicator.not_signed_in": "Necesitas iniciar sesión para acceder a este recurso.", "notification.admin.report": "{name} denunció a {target}", + "notification.admin.report_account": "{name} informó de {count, plural, one {una publicación} other {# publicaciones}} de {target} por {category}", + "notification.admin.report_account_other": "{name} informó de {count, plural, one {una publicación} other {# publicaciones}} de {target}", + "notification.admin.report_statuses": "{name} informó de {target} por {category}", + "notification.admin.report_statuses_other": "{name} informó de {target}", "notification.admin.sign_up": "{name} se unio", "notification.favourite": "{name} marcó como favorita tu publicación", "notification.follow": "{name} te empezó a seguir", @@ -485,7 +491,8 @@ "notification.moderation_warning.action_silence": "Tu cuenta ha sido limitada.", "notification.moderation_warning.action_suspend": "Tu cuenta ha sido suspendida.", "notification.own_poll": "Tu encuesta ha terminado", - "notification.poll": "Una encuesta en la que has votado ha terminado", + "notification.poll": "Una encuesta ha terminado", + "notification.private_mention": "{name} te mencionó en privado", "notification.reblog": "{name} ha retooteado tu estado", "notification.relationships_severance_event": "Conexiones perdidas con {name}", "notification.relationships_severance_event.account_suspension": "Un administrador de {from} ha suspendido {target}, lo que significa que ya no puedes recibir actualizaciones de sus cuentas o interactuar con ellas.", @@ -503,6 +510,8 @@ "notifications.column_settings.admin.report": "Nuevas denuncias:", "notifications.column_settings.admin.sign_up": "Registros nuevos:", "notifications.column_settings.alert": "Notificaciones de escritorio", + "notifications.column_settings.beta.category": "Características experimentales", + "notifications.column_settings.beta.grouping": "Agrupar notificaciones", "notifications.column_settings.favourite": "Favoritos:", "notifications.column_settings.filter_bar.advanced": "Mostrar todas las categorías", "notifications.column_settings.filter_bar.category": "Barra de filtrado rápido", @@ -666,9 +675,13 @@ "report.unfollow_explanation": "Estás siguiendo esta cuenta. Para no ver sus publicaciones en tu inicio, deja de seguirla.", "report_notification.attached_statuses": "{count, plural, one {{count} publicación} other {{count} publicaciones}} adjunta(s)", "report_notification.categories.legal": "Legal", + "report_notification.categories.legal_sentence": "contenido ilegal", "report_notification.categories.other": "Otro", + "report_notification.categories.other_sentence": "otra", "report_notification.categories.spam": "Spam", + "report_notification.categories.spam_sentence": "spam", "report_notification.categories.violation": "Infracción de regla", + "report_notification.categories.violation_sentence": "infracción de regla", "report_notification.open": "Abrir denuncia", "search.no_recent_searches": "Sin búsquedas recientes", "search.placeholder": "Buscar", diff --git a/app/javascript/mastodon/locales/es.json b/app/javascript/mastodon/locales/es.json index 259fc1795b373a..a6cecf160567a3 100644 --- a/app/javascript/mastodon/locales/es.json +++ b/app/javascript/mastodon/locales/es.json @@ -443,6 +443,8 @@ "mute_modal.title": "¿Silenciar usuario?", "mute_modal.you_wont_see_mentions": "No verás mensajes que los mencionen.", "mute_modal.you_wont_see_posts": "Todavía pueden ver tus publicaciones, pero tú no verás las suyas.", + "name_and_others": "{name} y {count, plural, one {# más} other {# más}}", + "name_and_others_with_link": "{name} y {count, plural, one {# más} other {# más}}", "navigation_bar.about": "Acerca de", "navigation_bar.advanced_interface": "Abrir en la interfaz web avanzada", "navigation_bar.blocks": "Usuarios bloqueados", @@ -470,6 +472,10 @@ "navigation_bar.security": "Seguridad", "not_signed_in_indicator.not_signed_in": "Necesitas iniciar sesión para acceder a este recurso.", "notification.admin.report": "{name} informó {target}", + "notification.admin.report_account": "{name} informó de {count, plural, one {una publicación} other {# publicaciones}} de {target} por {category}", + "notification.admin.report_account_other": "{name} informó de {count, plural, one {una publicación} other {# publicaciones}} de {target}", + "notification.admin.report_statuses": "{name} informó de {target} por {category}", + "notification.admin.report_statuses_other": "{name} informó de {target}", "notification.admin.sign_up": "{name} se registró", "notification.favourite": "{name} marcó como favorita tu publicación", "notification.follow": "{name} te empezó a seguir", @@ -485,7 +491,8 @@ "notification.moderation_warning.action_silence": "Tu cuenta ha sido limitada.", "notification.moderation_warning.action_suspend": "Tu cuenta ha sido suspendida.", "notification.own_poll": "Tu encuesta ha terminado", - "notification.poll": "Una encuesta en la que has votado ha terminado", + "notification.poll": "Una encuesta ha terminado", + "notification.private_mention": "{name} te mencionó en privado", "notification.reblog": "{name} ha impulsado tu publicación", "notification.relationships_severance_event": "Conexiones perdidas con {name}", "notification.relationships_severance_event.account_suspension": "Un administrador de {from} ha suspendido {target}, lo que significa que ya no puedes recibir actualizaciones de sus cuentas o interactuar con ellas.", @@ -503,6 +510,8 @@ "notifications.column_settings.admin.report": "Nuevos informes:", "notifications.column_settings.admin.sign_up": "Nuevos registros:", "notifications.column_settings.alert": "Notificaciones de escritorio", + "notifications.column_settings.beta.category": "Características experimentales", + "notifications.column_settings.beta.grouping": "Agrupar notificaciones", "notifications.column_settings.favourite": "Favoritos:", "notifications.column_settings.filter_bar.advanced": "Mostrar todas las categorías", "notifications.column_settings.filter_bar.category": "Barra de filtrado rápido", @@ -666,9 +675,13 @@ "report.unfollow_explanation": "Estás siguiendo esta cuenta. Para no ver sus publicaciones en tu muro de inicio, deja de seguirla.", "report_notification.attached_statuses": "{count, plural, one {{count} publicación} other {{count} publicaciones}} adjunta(s)", "report_notification.categories.legal": "Legal", + "report_notification.categories.legal_sentence": "contenido ilegal", "report_notification.categories.other": "Otros", + "report_notification.categories.other_sentence": "otra", "report_notification.categories.spam": "Spam", + "report_notification.categories.spam_sentence": "spam", "report_notification.categories.violation": "Infracción de regla", + "report_notification.categories.violation_sentence": "infracción de regla", "report_notification.open": "Abrir informe", "search.no_recent_searches": "No hay búsquedas recientes", "search.placeholder": "Buscar", diff --git a/app/javascript/mastodon/locales/et.json b/app/javascript/mastodon/locales/et.json index 94f5ef5d9eef52..b07229adece46c 100644 --- a/app/javascript/mastodon/locales/et.json +++ b/app/javascript/mastodon/locales/et.json @@ -482,7 +482,6 @@ "notification.moderation_warning.action_silence": "Su kontole pandi piirang.", "notification.moderation_warning.action_suspend": "Su konto on peatatud.", "notification.own_poll": "Su küsitlus on lõppenud", - "notification.poll": "Küsitlus, milles osalesid, on lõppenud", "notification.reblog": "{name} jagas edasi postitust", "notification.relationships_severance_event": "Kadunud ühendus kasutajaga {name}", "notification.relationships_severance_event.account_suspension": "{from} admin on kustutanud {target}, mis tähendab, et sa ei saa enam neilt uuendusi või suhelda nendega.", diff --git a/app/javascript/mastodon/locales/eu.json b/app/javascript/mastodon/locales/eu.json index 97c4250d225b23..bd1b51ba3e5f1d 100644 --- a/app/javascript/mastodon/locales/eu.json +++ b/app/javascript/mastodon/locales/eu.json @@ -480,7 +480,6 @@ "notification.moderation_warning.action_silence": "Kontua murriztu egin da.", "notification.moderation_warning.action_suspend": "Kontua itxi da.", "notification.own_poll": "Zure inkesta amaitu da", - "notification.poll": "Zuk erantzun duzun inkesta bat bukatu da", "notification.reblog": "{name}(e)k bultzada eman dio zure bidalketari", "notification.relationships_severance_event": "{name} erabiltzailearekin galdutako konexioak", "notification.relationships_severance_event.account_suspension": "{from} zerbitzariko administratzaile batek {target} bertan behera utzi du, hau da, ezin izango dituzu jaso hango eguneratzerik edo hangoekin elkarreragin.", diff --git a/app/javascript/mastodon/locales/fa.json b/app/javascript/mastodon/locales/fa.json index 18f6466d4873fc..9dc429f7de861f 100644 --- a/app/javascript/mastodon/locales/fa.json +++ b/app/javascript/mastodon/locales/fa.json @@ -424,7 +424,6 @@ "notification.follow_request": "{name} درخواست پی‌گیریتان را داد", "notification.mention": "‫{name}‬ به شما اشاره کرد", "notification.own_poll": "نظرسنجیتان پایان یافت", - "notification.poll": "نظرسنجی‌ای که در آن رأی دادید به پایان رسیده است", "notification.reblog": "‫{name}‬ فرسته‌تان را تقویت کرد", "notification.status": "{name} چیزی فرستاد", "notification.update": "{name} فرسته‌ای را ویرایش کرد", diff --git a/app/javascript/mastodon/locales/fi.json b/app/javascript/mastodon/locales/fi.json index 0767dd5e37cf63..5ba77dd72e0813 100644 --- a/app/javascript/mastodon/locales/fi.json +++ b/app/javascript/mastodon/locales/fi.json @@ -157,8 +157,8 @@ "compose_form.poll.multiple": "Monivalinta", "compose_form.poll.option_placeholder": "Vaihtoehto {number}", "compose_form.poll.single": "Valitse yksi", - "compose_form.poll.switch_to_multiple": "Muuta kysely monivalinnaksi", - "compose_form.poll.switch_to_single": "Muuta kysely sallimaan vain yksi valinta", + "compose_form.poll.switch_to_multiple": "Muuta äänestys monivalinnaksi", + "compose_form.poll.switch_to_single": "Muuta äänestys yksittäisvalinnaksi", "compose_form.poll.type": "Tyyli", "compose_form.publish": "Julkaise", "compose_form.publish_form": "Uusi julkaisu", @@ -443,6 +443,8 @@ "mute_modal.title": "Mykistetäänkö käyttäjä?", "mute_modal.you_wont_see_mentions": "Et tule enää näkemään julkaisuja, joissa hänet mainitaan.", "mute_modal.you_wont_see_posts": "Hän voi yhä nähdä julkaisusi, mutta sinä et näe hänen.", + "name_and_others": "{name} ja {count, plural, one {# muu} other {# muuta}}", + "name_and_others_with_link": "{name} ja {count, plural, one {# muu} other {# muuta}}", "navigation_bar.about": "Tietoja", "navigation_bar.advanced_interface": "Avaa edistyneessä selainkäyttöliittymässä", "navigation_bar.blocks": "Estetyt käyttäjät", @@ -469,7 +471,11 @@ "navigation_bar.search": "Hae", "navigation_bar.security": "Turvallisuus", "not_signed_in_indicator.not_signed_in": "Sinun on kirjauduttava sisään käyttääksesi resurssia.", - "notification.admin.report": "{name} teki ilmoituksen käytäjästä {target}", + "notification.admin.report": "{name} raportoi käyttäjän {target}", + "notification.admin.report_account": "{name} raportoi {count, plural, one {julkaisun} other {# julkaisua}} käyttäjältä {target}, syynä {category}", + "notification.admin.report_account_other": "{name} raportoi {count, plural, one {julkaisun} other {# julkaisua}} käyttäjältä {target}", + "notification.admin.report_statuses": "{name} raportoi käyttäjän {target}, syynä {category}", + "notification.admin.report_statuses_other": "{name} raportoi käyttäjän {target}", "notification.admin.sign_up": "{name} rekisteröityi", "notification.favourite": "{name} lisäsi julkaisusi suosikkeihinsa", "notification.follow": "{name} seurasi sinua", @@ -485,7 +491,8 @@ "notification.moderation_warning.action_silence": "Tiliäsi on rajoitettu.", "notification.moderation_warning.action_suspend": "Tilisi on jäädytetty.", "notification.own_poll": "Äänestyksesi on päättynyt", - "notification.poll": "Kysely, johon osallistuit, on päättynyt", + "notification.poll": "Äänestys, johon osallistuit, on päättynyt", + "notification.private_mention": "{name} mainitsi sinut yksityisesti", "notification.reblog": "{name} tehosti julkaisuasi", "notification.relationships_severance_event": "Menetettiin yhteydet palvelimeen {name}", "notification.relationships_severance_event.account_suspension": "Palvelimen {from} ylläpitäjä on jäädyttänyt palvelimen {target} vuorovaikutuksen. Enää et voi siis vastaanottaa päivityksiä heiltä tai olla yhteyksissä heidän kanssaan.", @@ -503,6 +510,8 @@ "notifications.column_settings.admin.report": "Uudet ilmoitukset:", "notifications.column_settings.admin.sign_up": "Uudet rekisteröitymiset:", "notifications.column_settings.alert": "Työpöytäilmoitukset", + "notifications.column_settings.beta.category": "Kokeelliset ominaisuudet", + "notifications.column_settings.beta.grouping": "Ryhmittele ilmoitukset", "notifications.column_settings.favourite": "Suosikit:", "notifications.column_settings.filter_bar.advanced": "Näytä kaikki luokat", "notifications.column_settings.filter_bar.category": "Pikasuodatuspalkki", @@ -592,8 +601,8 @@ "poll.vote": "Äänestä", "poll.voted": "Äänestit tätä vastausta", "poll.votes": "{votes, plural, one {# ääni} other {# ääntä}}", - "poll_button.add_poll": "Lisää kysely", - "poll_button.remove_poll": "Poista kysely", + "poll_button.add_poll": "Lisää äänestys", + "poll_button.remove_poll": "Poista äänestys", "privacy.change": "Muuta julkaisun näkyvyyttä", "privacy.direct.long": "Kaikki tässä julkaisussa mainitut", "privacy.direct.short": "Tietyt henkilöt", @@ -623,7 +632,7 @@ "relative_time.today": "tänään", "reply_indicator.attachments": "{count, plural, one {# liite} other {# liitettä}}", "reply_indicator.cancel": "Peruuta", - "reply_indicator.poll": "Kysely", + "reply_indicator.poll": "Äänestys", "report.block": "Estä", "report.block_explanation": "Et näe hänen viestejään, eikä hän voi nähdä viestejäsi tai seurata sinua. Hän näkee, että olet estänyt hänet.", "report.categories.legal": "Juridiset tiedot", @@ -666,9 +675,13 @@ "report.unfollow_explanation": "Seuraat tätä tiliä. Estääksesi tilin viestejä näykymästä kotisyötteessäsi, lopeta sen seuraaminen.", "report_notification.attached_statuses": "{count, plural, one {{count} julkaisu} other {{count} julkaisua}} liitteenä", "report_notification.categories.legal": "Laillinen", + "report_notification.categories.legal_sentence": "laiton sisältö", "report_notification.categories.other": "Muu", + "report_notification.categories.other_sentence": "jokin muu", "report_notification.categories.spam": "Roskaposti", + "report_notification.categories.spam_sentence": "roskaposti", "report_notification.categories.violation": "Sääntörikkomus", + "report_notification.categories.violation_sentence": "sääntörikkomus", "report_notification.open": "Avaa raportti", "search.no_recent_searches": "Ei viimeaikaisia hakuja", "search.placeholder": "Hae", diff --git a/app/javascript/mastodon/locales/fo.json b/app/javascript/mastodon/locales/fo.json index c27ffe0aa7d1ff..dd3d448834e06a 100644 --- a/app/javascript/mastodon/locales/fo.json +++ b/app/javascript/mastodon/locales/fo.json @@ -443,6 +443,8 @@ "mute_modal.title": "Sløkk brúkara?", "mute_modal.you_wont_see_mentions": "Tú sært ikki postar, sum nevna tey.", "mute_modal.you_wont_see_posts": "Tey síggja framvegis tínar postar, men tú sært ikki teirra.", + "name_and_others": "{name} og {count, plural, one {# annar} other {# onnur}}", + "name_and_others_with_link": "{name} og {count, plural, one {# annar} other {# onnur}}", "navigation_bar.about": "Um", "navigation_bar.advanced_interface": "Lat upp í framkomnum vevmarkamóti", "navigation_bar.blocks": "Bannaðir brúkarar", @@ -470,6 +472,10 @@ "navigation_bar.security": "Trygd", "not_signed_in_indicator.not_signed_in": "Tú mást rita inn fyri at fáa atgongd til hetta tilfarið.", "notification.admin.report": "{name} hevur meldað {target}", + "notification.admin.report_account": "{name} meldaði {count, plural, one {ein post} other {# postar}} frá {target} fyri {category}", + "notification.admin.report_account_other": "{name} meldaði {count, plural, one {ein post} other {# postar}} frá {target}", + "notification.admin.report_statuses": "{name} melaði {target} fyri {category}", + "notification.admin.report_statuses_other": "{name} meldaði {target}", "notification.admin.sign_up": "{name} meldaði seg til", "notification.favourite": "{name} dámdi postin hjá tær", "notification.follow": "{name} fylgdi tær", @@ -485,7 +491,8 @@ "notification.moderation_warning.action_silence": "Konta tín er avmarkað.", "notification.moderation_warning.action_suspend": "Konta tín er ógildað.", "notification.own_poll": "Tín atkvøðugreiðsla er endað", - "notification.poll": "Ein atkvøðugreiðsla, har tú hevur atkvøtt, er endað", + "notification.poll": "Ein atkvøðugreiðsla, har tú atkvøddi, er endað", + "notification.private_mention": "{name} nevndi teg í privatum boðum", "notification.reblog": "{name} lyfti tín post", "notification.relationships_severance_event": "Mist sambond við {name}", "notification.relationships_severance_event.account_suspension": "Ein umsitari frá {from} hevur gjørt {target} óvirkna, sum merkir, at tú ikki kanst móttaka dagføringar ella virka saman við teimum longur.", @@ -503,6 +510,8 @@ "notifications.column_settings.admin.report": "Nýggjar fráboðanir:", "notifications.column_settings.admin.sign_up": "Nýggjar tilmeldingar:", "notifications.column_settings.alert": "Skriviborðsfráboðanir", + "notifications.column_settings.beta.category": "Royndarhentleikar", + "notifications.column_settings.beta.grouping": "Bólkafráboðanir", "notifications.column_settings.favourite": "Dámdir postar:", "notifications.column_settings.filter_bar.advanced": "Vís allar bólkar", "notifications.column_settings.filter_bar.category": "Skjótfilturbjálki", @@ -666,9 +675,13 @@ "report.unfollow_explanation": "Tú fylgir hesi kontuni. Gevst at fylgja henni, um tú ikki longur ynskir at síggja postarnar á heimarásini hjá tær.", "report_notification.attached_statuses": "{count, plural, one {{count} postur atknýttur} other {{count} postar atknýttir}}", "report_notification.categories.legal": "Løgfrøðisligt", + "report_notification.categories.legal_sentence": "ólógligt innihald", "report_notification.categories.other": "Aðrir", + "report_notification.categories.other_sentence": "aðrir", "report_notification.categories.spam": "Ruskpostur", + "report_notification.categories.spam_sentence": "ruskpostur", "report_notification.categories.violation": "Brotin regla", + "report_notification.categories.violation_sentence": "brot á reglu", "report_notification.open": "Opna melding", "search.no_recent_searches": "Ongar nýggjar leitingar", "search.placeholder": "Leita", diff --git a/app/javascript/mastodon/locales/fr-CA.json b/app/javascript/mastodon/locales/fr-CA.json index 4324855003fda2..94b73bbf18235d 100644 --- a/app/javascript/mastodon/locales/fr-CA.json +++ b/app/javascript/mastodon/locales/fr-CA.json @@ -466,7 +466,6 @@ "notification.follow_request": "{name} a demandé à vous suivre", "notification.mention": "{name} vous a mentionné·e", "notification.own_poll": "Votre sondage est terminé", - "notification.poll": "Un sondage auquel vous avez participé est terminé", "notification.reblog": "{name} a boosté votre message", "notification.relationships_severance_event": "Connexions perdues avec {name}", "notification.relationships_severance_event.account_suspension": "Un·e administrateur·rice de {from} a suspendu {target}, ce qui signifie que vous ne pourrez plus recevoir de mises à jour ou interagir avec lui.", diff --git a/app/javascript/mastodon/locales/fr.json b/app/javascript/mastodon/locales/fr.json index cd67cda539a06a..fd256fe7168688 100644 --- a/app/javascript/mastodon/locales/fr.json +++ b/app/javascript/mastodon/locales/fr.json @@ -466,7 +466,6 @@ "notification.follow_request": "{name} a demandé à vous suivre", "notification.mention": "{name} vous a mentionné·e :", "notification.own_poll": "Votre sondage est terminé", - "notification.poll": "Un sondage auquel vous avez participé vient de se terminer", "notification.reblog": "{name} a partagé votre message", "notification.relationships_severance_event": "Connexions perdues avec {name}", "notification.relationships_severance_event.account_suspension": "Un·e administrateur·rice de {from} a suspendu {target}, ce qui signifie que vous ne pourrez plus recevoir de mises à jour ou interagir avec lui.", diff --git a/app/javascript/mastodon/locales/fy.json b/app/javascript/mastodon/locales/fy.json index d787c16bf3b729..e3b3a965681583 100644 --- a/app/javascript/mastodon/locales/fy.json +++ b/app/javascript/mastodon/locales/fy.json @@ -422,6 +422,7 @@ "mute_modal.hide_options": "Opsjes ferstopje", "mute_modal.indefinite": "Oant ik se net mear negearje", "mute_modal.show_options": "Opsjes toane", + "mute_modal.title": "Brûker negearje?", "navigation_bar.about": "Oer", "navigation_bar.advanced_interface": "Yn avansearre webomjouwing iepenje", "navigation_bar.blocks": "Blokkearre brûkers", @@ -455,7 +456,6 @@ "notification.follow_request": "{name} hat dy in folchfersyk stjoerd", "notification.mention": "{name} hat dy fermeld", "notification.own_poll": "Jo poll is beëinige", - "notification.poll": "In enkête dêr’t jo yn stimd hawwe is beëinige", "notification.reblog": "{name} hat jo berjocht boost", "notification.relationships_severance_event.learn_more": "Mear ynfo", "notification.status": "{name} hat in berjocht pleatst", diff --git a/app/javascript/mastodon/locales/ga.json b/app/javascript/mastodon/locales/ga.json index edf7618148ecff..711c97f66c7e1a 100644 --- a/app/javascript/mastodon/locales/ga.json +++ b/app/javascript/mastodon/locales/ga.json @@ -17,22 +17,28 @@ "account.badges.group": "Grúpa", "account.block": "Déan cosc ar @{name}", "account.block_domain": "Bac ainm fearainn {domain}", + "account.block_short": "Bloc", "account.blocked": "Bactha", "account.browse_more_on_origin_server": "Brabhsáil níos mó ar an phróifíl bhunaidh", "account.cancel_follow_request": "Éirigh as iarratas leanta", + "account.copy": "Cóipeáil nasc chuig an bpróifíl", + "account.direct": "Luaigh @{name} go príobháideach", "account.disable_notifications": "Éirigh as ag cuir mé in eol nuair bpostálann @{name}", "account.domain_blocked": "Ainm fearainn bactha", "account.edit_profile": "Cuir an phróifíl in eagar", "account.enable_notifications": "Cuir mé in eol nuair bpostálann @{name}", "account.endorse": "Cuir ar an phróifíl mar ghné", "account.featured_tags.last_status_at": "Postáil is déanaí ar {date}", - "account.featured_tags.last_status_never": "Níl postáil ar bith ann", - "account.featured_tags.title": "Haischlib {name}", + "account.featured_tags.last_status_never": "Gan aon phoist", + "account.featured_tags.title": "Haischlib faoi thrácht {name}", "account.follow": "Lean", + "account.follow_back": "Leanúint ar ais", "account.followers": "Leantóirí", "account.followers.empty": "Ní leanann éinne an t-úsáideoir seo fós.", + "account.followers_counter": "{count, plural, one {{counter} leantóir} other {{counter} leantóirí}}", "account.following": "Ag leanúint", - "account.follows.empty": "Ní leanann an t-úsáideoir seo duine ar bith fós.", + "account.following_counter": "{count, plural, one {{counter} ag leanúint} other {{counter} ag leanúint}}", + "account.follows.empty": "Ní leanann an t-úsáideoir seo aon duine go fóill.", "account.go_to_profile": "Téigh go dtí próifíl", "account.hide_reblogs": "Folaigh moltaí ó @{name}", "account.in_memoriam": "Cuimhneachán.", @@ -40,11 +46,15 @@ "account.languages": "Athraigh teangacha foscríofa", "account.link_verified_on": "Seiceáladh úinéireacht an naisc seo ar {date}", "account.locked_info": "Tá an socrú príobháideachais don cuntas seo curtha go 'faoi ghlas'. Déanann an t-úinéir léirmheas ar cén daoine atá ceadaithe an cuntas leanúint.", - "account.media": "Ábhair", + "account.media": "Meáin", "account.mention": "Luaigh @{name}", "account.moved_to": "Tá tugtha le fios ag {name} gurb é an cuntas nua atá acu ná:", "account.mute": "Balbhaigh @{name}", + "account.mute_notifications_short": "Balbhaigh fógraí", + "account.mute_short": "Balbhaigh", "account.muted": "Balbhaithe", + "account.mutual": "Frithpháirteach", + "account.no_bio": "Níor tugadh tuairisc.", "account.open_original_page": "Oscail an leathanach bunaidh", "account.posts": "Postálacha", "account.posts_with_replies": "Postálacha agus freagraí", @@ -53,12 +63,14 @@ "account.requested_follow": "D'iarr {name} ort do chuntas a leanúint", "account.share": "Roinn próifíl @{name}", "account.show_reblogs": "Taispeáin moltaí ó @{name}", + "account.statuses_counter": "{count, plural, one {{counter} post} other {{counter} poist}}", "account.unblock": "Bain bac de @{name}", "account.unblock_domain": "Bain bac den ainm fearainn {domain}", - "account.unblock_short": "Bain bac de", + "account.unblock_short": "Díbhlocáil", "account.unendorse": "Ná chuir ar an phróifíl mar ghné", "account.unfollow": "Ná lean a thuilleadh", "account.unmute": "Díbhalbhaigh @{name}", + "account.unmute_notifications_short": "Díbhalbhaigh fógraí", "account.unmute_short": "Díbhalbhaigh", "account_note.placeholder": "Cliceáil chun nóta a chuir leis", "admin.dashboard.daily_retention": "Ráta coinneála an úsáideora de réir an lae tar éis clárú", @@ -66,6 +78,10 @@ "admin.dashboard.retention.average": "Meán", "admin.dashboard.retention.cohort": "Mí cláraraithe", "admin.dashboard.retention.cohort_size": "Úsáideoirí nua", + "admin.impact_report.instance_accounts": "Próifílí cuntais a scriosfadh sé seo", + "admin.impact_report.instance_followers": "Leanúna a chaillfeadh ár n-úsáideoirí", + "admin.impact_report.instance_follows": "Leanúna a bheadh ​​​​a n-úsáideoirí chailleadh", + "admin.impact_report.title": "Achoimre ar an tionchar", "alert.rate_limited.message": "Atriail aris tar éis {retry_time, time, medium}.", "alert.rate_limited.title": "Rátatheoranta", "alert.unexpected.message": "Tharla earráid gan choinne.", @@ -73,10 +89,18 @@ "announcement.announcement": "Fógra", "attachments_list.unprocessed": "(neamhphróiseáilte)", "audio.hide": "Cuir fuaim i bhfolach", + "block_modal.remote_users_caveat": "Iarrfaimid ar an bhfreastalaí {domain} meas a bheith agat ar do chinneadh. Mar sin féin, ní ráthaítear comhlíonadh toisc go bhféadfadh roinnt freastalaithe bloic a láimhseáil ar bhealach difriúil. Seans go mbeidh postálacha poiblí fós le feiceáil ag úsáideoirí nach bhfuil logáilte isteach.", + "block_modal.show_less": "Taispeáin níos lú", + "block_modal.show_more": "Taispeáin níos mó", + "block_modal.they_cant_mention": "Ní féidir leo tú a lua ná a leanúint.", + "block_modal.they_cant_see_posts": "Ní féidir leo do chuid postálacha a fheiceáil agus ní fheicfidh tú a gcuid postanna.", + "block_modal.they_will_know": "Is féidir leo a fheiceáil go bhfuil bac orthu.", + "block_modal.title": "An bhfuil fonn ort an t-úsáideoir a bhlocáil?", + "block_modal.you_wont_see_mentions": "Ní fheicfidh tú postálacha a luann iad.", "boost_modal.combo": "Is féidir leat {combo} a bhrú chun é seo a scipeáil an chéad uair eile", "bundle_column_error.copy_stacktrace": "Cóipeáil tuairisc earráide", "bundle_column_error.error.body": "Ní féidir an leathanach a iarradh a sholáthar. Seans gurb amhlaidh mar gheall ar fhabht sa chód, nó mar gheall ar mhíréireacht leis an mbrabhsálaí.", - "bundle_column_error.error.title": "Ná habair!", + "bundle_column_error.error.title": "Ó, níl sé sin go maith!", "bundle_column_error.network.body": "Tharla earráid agus an leathanach á lódáil. Seans gur mar gheall ar fhadhb shealadach le do nasc idirlín nó i ndáil leis an bhfreastalaí seo atá sé.", "bundle_column_error.network.title": "Earráid líonra", "bundle_column_error.retry": "Bain triail as arís", @@ -95,8 +119,11 @@ "column.blocks": "Cuntais choiscthe", "column.bookmarks": "Leabharmharcanna", "column.community": "Amlíne áitiúil", + "column.direct": "Luann príobháideach", "column.directory": "Brabhsáil próifílí", "column.domain_blocks": "Fearainn bhactha", + "column.favourites": "Ceanáin", + "column.firehose": "Fothaí beo", "column.follow_requests": "Iarratais leanúnaí", "column.home": "Baile", "column.lists": "Liostaí", @@ -108,15 +135,18 @@ "column_header.hide_settings": "Folaigh socruithe", "column_header.moveLeft_settings": "Bog an colún ar chlé", "column_header.moveRight_settings": "Bog an colún ar dheis", - "column_header.pin": "Greamaigh", + "column_header.pin": "Pionna", "column_header.show_settings": "Taispeáin socruithe", - "column_header.unpin": "Díghreamaigh", + "column_header.unpin": "Bain pionna", "column_subheading.settings": "Socruithe", "community.column_settings.local_only": "Áitiúil amháin", "community.column_settings.media_only": "Meáin Amháin", "community.column_settings.remote_only": "Cian amháin", "compose.language.change": "Athraigh teanga", "compose.language.search": "Cuardaigh teangacha...", + "compose.published.body": "Post foilsithe.", + "compose.published.open": "Oscail", + "compose.saved.body": "Postáil sábháilte.", "compose_form.direct_message_warning_learn_more": "Tuilleadh eolais", "compose_form.encryption_warning": "Ní criptiú taobh-go-taobh déanta ar theachtaireachtaí ar Mhastodon. Ná roinn eolas íogair ar Mhastodon.", "compose_form.hashtag_warning": "Ní áireofar an teachtaireacht seo faoi haischlib ar bith mar níl sí ar fáil don phobal. Ní féidir ach teachtaireachtaí poiblí a chuardach de réir haischlib.", @@ -124,11 +154,19 @@ "compose_form.lock_disclaimer.lock": "faoi ghlas", "compose_form.placeholder": "Cad atá ag tarlú?", "compose_form.poll.duration": "Achar suirbhéanna", + "compose_form.poll.multiple": "Ilrogha", + "compose_form.poll.option_placeholder": "Rogha {number}", + "compose_form.poll.single": "Roghnaigh ceann amháin", "compose_form.poll.switch_to_multiple": "Athraigh suirbhé chun cead a thabhairt do ilrogha", "compose_form.poll.switch_to_single": "Athraigh suirbhé chun cead a thabhairt do rogha amháin", - "compose_form.publish_form": "Foilsigh\n", + "compose_form.poll.type": "Stíl", + "compose_form.publish": "Postáil", + "compose_form.publish_form": "Post nua", + "compose_form.reply": "Freagra", + "compose_form.save_changes": "Nuashonrú", "compose_form.spoiler.marked": "Bain rabhadh ábhair", "compose_form.spoiler.unmarked": "Cuir rabhadh ábhair", + "compose_form.spoiler_placeholder": "Rabhadh ábhair (roghnach)", "confirmation_modal.cancel": "Cealaigh", "confirmations.block.confirm": "Bac", "confirmations.cancel_follow_request.confirm": "Éirigh as iarratas", @@ -139,11 +177,15 @@ "confirmations.delete_list.message": "An bhfuil tú cinnte gur mhaith leat an liosta seo a scriosadh go buan?", "confirmations.discard_edit_media.confirm": "Faigh réidh de", "confirmations.discard_edit_media.message": "Tá athruithe neamhshlánaithe don tuarascáil gné nó réamhamharc agat, faigh réidh dóibh ar aon nós?", + "confirmations.domain_block.confirm": "Bloc freastalaí", "confirmations.domain_block.message": "An bhfuil tú iontach cinnte gur mhaith leat bac an t-ainm fearainn {domain} in iomlán? I bhformhór na gcásanna, is leor agus is fearr cúpla baic a cur i bhfeidhm nó cúpla úsáideoirí a balbhú. Ní fheicfidh tú ábhair ón t-ainm fearainn sin in amlíne ar bith, nó i d'fhógraí. Scaoilfear do leantóirí ón ainm fearainn sin.", + "confirmations.edit.confirm": "Eagar", + "confirmations.edit.message": "Má dhéanann tú eagarthóireacht anois, déanfar an teachtaireacht atá á cumadh agat faoi láthair a fhorscríobh. An bhfuil tú cinnte gur mhaith leat leanúint ar aghaidh?", "confirmations.logout.confirm": "Logáil amach", "confirmations.logout.message": "An bhfuil tú cinnte gur mhaith leat logáil amach?", "confirmations.mute.confirm": "Balbhaigh", "confirmations.redraft.confirm": "Scrios ⁊ athdhréachtaigh", + "confirmations.redraft.message": "An bhfuil tú cinnte gur mhaith leat an postáil seo a scriosadh agus é a athdhréachtú? Caillfear ceanáin agus treisithe, agus dílleachtaí freagraí ar an mbunphostála.", "confirmations.reply.confirm": "Freagair", "confirmations.reply.message": "Scriosfaidh freagra láithreach an teachtaireacht atá a chumadh anois agat. An bhfuil tú cinnte gur mhaith leat leanúint leat?", "confirmations.unfollow.confirm": "Ná lean", @@ -152,7 +194,9 @@ "conversation.mark_as_read": "Marcáil mar léite", "conversation.open": "Féach ar comhrá", "conversation.with": "Le {names}", + "copy_icon_button.copied": "Cóipeáladh chuig an ngearrthaisce", "copypaste.copied": "Cóipeáilte", + "copypaste.copy_to_clipboard": "Cóipeáil chuig an ngearrthaisce", "directory.federated": "Ó chomhchruinne aitheanta", "directory.local": "Ó {domain} amháin", "directory.new_arrivals": "Daoine atá tar éis teacht", @@ -162,7 +206,30 @@ "dismissable_banner.community_timeline": "Seo iad na postála is déanaí ó dhaoine le cuntais ar {domain}.", "dismissable_banner.dismiss": "Diúltaigh", "dismissable_banner.explore_links": "Tá na scéalta nuachta seo á phlé anseo agus ar fhreastalaithe eile ar an líonra díláraithe faoi láthair.", - "dismissable_banner.explore_tags": "These hashtags are gaining traction among people on this and other servers of the decentralized network right now.", + "dismissable_banner.explore_statuses": "Is postálacha iad seo ó ar fud an ghréasáin shóisialta atá ag éirí níos tarraingtí inniu. Rangaítear poist níos nuaí le níos mó teanntáin agus ceanáin níos airde.", + "dismissable_banner.explore_tags": "Is hashtags iad seo atá ag tarraingt ar an ngréasán sóisialta inniu. Tá na hashtags a úsáideann níos mó daoine difriúla rangaithe níos airde.", + "dismissable_banner.public_timeline": "Seo iad na postálacha poiblí is déanaí ó dhaoine ar an ngréasán sóisialta a leanann daoine ar {domain}.", + "domain_block_modal.block": "Bloc freastalaí", + "domain_block_modal.block_account_instead": "Cuir bac ar @{name} ina ionad sin", + "domain_block_modal.they_can_interact_with_old_posts": "Is féidir le daoine ón bhfreastalaí seo idirghníomhú le do sheanphoist.", + "domain_block_modal.they_cant_follow": "Ní féidir le duine ar bith ón bhfreastalaí seo tú a leanúint.", + "domain_block_modal.they_wont_know": "Ní bheidh a fhios acu go bhfuil bac orthu.", + "domain_block_modal.title": "Blocáil fearann?", + "domain_block_modal.you_will_lose_followers": "Bainfear do leantóirí go léir ón bhfreastalaí seo.", + "domain_block_modal.you_wont_see_posts": "Ní fheicfidh tú postálacha nó fógraí ó úsáideoirí ar an bhfreastalaí seo.", + "domain_pill.activitypub_lets_connect": "Ligeann sé duit ceangal agus idirghníomhú le daoine, ní hamháin ar Mastodon, ach thar aipeanna sóisialta éagsúla freisin.", + "domain_pill.activitypub_like_language": "Tá GníomhaíochtPub cosúil leis an teanga a labhraíonn Mastodon le líonraí sóisialta eile.", + "domain_pill.server": "Freastalaí", + "domain_pill.their_handle": "A láimhseáil:", + "domain_pill.their_server": "A dteach digiteach, áit a bhfuil a gcuid post go léir ina gcónaí.", + "domain_pill.their_username": "Aitheantóir uathúil ar a bhfreastalaí. Is féidir teacht ar úsáideoirí leis an ainm úsáideora céanna ar fhreastalaithe éagsúla.", + "domain_pill.username": "Ainm úsáideora", + "domain_pill.whats_in_a_handle": "Cad atá i láimhseáil?", + "domain_pill.who_they_are": "Ós rud é go ndeir láimhseálaithe cé hé duine agus cá bhfuil siad, is féidir leat idirghníomhú le daoine ar fud an ghréasáin shóisialta de .", + "domain_pill.who_you_are": "Toisc go ndeir do láimhseáil cé tú féin agus cén áit a bhfuil tú, is féidir le daoine idirghníomhú leat ar fud an ghréasáin shóisialta de .", + "domain_pill.your_handle": "Do láimhseáil:", + "domain_pill.your_server": "Do theach digiteach, áit a bhfuil do phoist go léir ina gcónaí. Nach maith leat an ceann seo? Aistrigh freastalaithe am ar bith agus tabhair leat do leantóirí freisin.", + "domain_pill.your_username": "D'aitheantóir uathúil ar an bhfreastalaí seo. Is féidir teacht ar úsáideoirí leis an ainm úsáideora céanna ar fhreastalaithe éagsúla.", "embed.instructions": "Embed this status on your website by copying the code below.", "embed.preview": "Seo an chuma a bheidh air:", "emoji_button.activity": "Gníomhaíocht", @@ -180,49 +247,81 @@ "emoji_button.search_results": "Torthaí cuardaigh", "emoji_button.symbols": "Comharthaí", "emoji_button.travel": "Taisteal ⁊ Áiteanna", + "empty_column.account_hides_collections": "Roghnaigh an t-úsáideoir seo gan an fhaisnéis seo a chur ar fáil", "empty_column.account_suspended": "Cuntas ar fionraí", "empty_column.account_timeline": "Níl postálacha ar bith anseo!", "empty_column.account_unavailable": "Níl an phróifíl ar fáil", "empty_column.blocks": "Níl aon úsáideoir bactha agat fós.", "empty_column.bookmarked_statuses": "Níl aon phostáil leabharmharcaithe agat fós. Nuair a dhéanann tú leabharmharc, beidh sé le feiceáil anseo.", "empty_column.community": "Tá an amlíne áitiúil folamh. Foilsigh rud éigin go poiblí le tús a chur le cúrsaí!", + "empty_column.direct": "Níl aon tagairtí príobháideacha agat fós. Nuair a sheolann tú nó a gheobhaidh tú ceann, beidh sé le feiceáil anseo.", "empty_column.domain_blocks": "Níl aon fearainn bhactha ann go fóill.", "empty_column.explore_statuses": "Níl rud ar bith ag treochtáil faoi láthair. Tar ar ais ar ball!", + "empty_column.favourited_statuses": "Níl aon postálacha is fearr leat fós. Nuair is fearr leat ceann, beidh sé le feiceáil anseo.", + "empty_column.favourites": "Níor thaitin an post seo le haon duine go fóill. Nuair a dhéanann duine, taispeánfaidh siad suas anseo.", "empty_column.follow_requests": "Níl aon phostáil leabharmharcaithe agat fós. Nuair a dhéanann tú leabharmharc, feicfear anseo é.", + "empty_column.followed_tags": "Níor lean tú aon hashtags fós. Nuair a dhéanann tú, beidh siad a thaispeáint suas anseo.", "empty_column.hashtag": "Níl rud ar bith faoin haischlib seo go fóill.", "empty_column.home": "Tá d'amlíne baile folamh! B'fhiú duit cúpla duine eile a leanúint lena líonadh! {suggestions}", - "empty_column.list": "There is nothing in this list yet. When members of this list post new statuses, they will appear here.", + "empty_column.list": "Níl aon rud ar an liosta seo fós. Nuair a fhoilseoidh baill an liosta seo postálacha nua, beidh siad le feiceáil anseo.", "empty_column.lists": "Níl aon liostaí fós agat. Nuair a chruthaíonn tú ceann, feicfear anseo é.", "empty_column.mutes": "Níl aon úsáideoir balbhaithe agat fós.", + "empty_column.notification_requests": "Gach soiléir! Níl aon rud anseo. Nuair a gheobhaidh tú fógraí nua, beidh siad le feiceáil anseo de réir do shocruithe.", "empty_column.notifications": "Níl aon fógraí agat fós. Nuair a dhéanann daoine eile idirghníomhú leat, feicfear anseo é.", "empty_column.public": "Faic anseo! Scríobh rud éigin go poiblí, nó lean úsáideoirí ar fhreastalaithe eile chun é a líonadh", "error.unexpected_crash.explanation": "De bharr fabht inár gcód, nó fadhb le chomhoiriúnacht brabhsálaí, níorbh fhéadfadh an leathanach seo a léiriú i gceart.", "error.unexpected_crash.explanation_addons": "Ní taispeántar an leathanach seo mar is ceart. Is dócha go gcruthaíonn breiseán brabhsálaí nó uirlisí uathaistriúcháin an fhadhb seo.", + "error.unexpected_crash.next_steps": "Bain triail as an leathanach a athnuachan. Mura gcabhraíonn sé sin, seans go mbeidh tú fós in ann Mastodon a úsáid trí bhrabhsálaí nó aip dhúchais eile.", + "error.unexpected_crash.next_steps_addons": "Déan iarracht iad a dhíchumasú agus an leathanach a athnuachan. Mura gcabhraíonn sé sin, seans go mbeidh tú fós in ann Mastodon a úsáid trí bhrabhsálaí nó aip dhúchais eile.", + "errors.unexpected_crash.copy_stacktrace": "Cóipeáil rian cruachta go dtí an ghearrthaisce", "errors.unexpected_crash.report_issue": "Tuairiscigh deacracht", "explore.search_results": "Torthaí cuardaigh", + "explore.suggested_follows": "Daoine", "explore.title": "Féach thart", "explore.trending_links": "Nuacht", "explore.trending_statuses": "Postálacha", "explore.trending_tags": "Haischlibeanna", + "filter_modal.added.context_mismatch_explanation": "Ní bhaineann an chatagóir scagaire seo leis an gcomhthéacs ina bhfuair tú rochtain ar an bpostáil seo. Más mian leat an postáil a scagadh sa chomhthéacs seo freisin, beidh ort an scagaire a chur in eagar.", + "filter_modal.added.context_mismatch_title": "Neamhréir comhthéacs!", + "filter_modal.added.expired_explanation": "Tá an chatagóir scagaire seo imithe in éag, beidh ort an dáta éaga a athrú chun é a chur i bhfeidhm.", "filter_modal.added.expired_title": "Scagaire as feidhm!", + "filter_modal.added.review_and_configure": "Chun an chatagóir scagaire seo a athbhreithniú agus a chumrú tuilleadh, téigh chuig {settings_link}.", "filter_modal.added.review_and_configure_title": "Socruithe scagtha", "filter_modal.added.settings_link": "leathan socruithe", + "filter_modal.added.short_explanation": "Cuireadh an postáil seo leis an gcatagóir scagaire seo a leanas: {title}.", "filter_modal.added.title": "Scagaire curtha leis!", "filter_modal.select_filter.context_mismatch": "ní bhaineann sé leis an gcomhthéacs seo", - "filter_modal.select_filter.expired": "as feidhm", + "filter_modal.select_filter.expired": "imithe in éag", "filter_modal.select_filter.prompt_new": "Catagóir nua: {name}", "filter_modal.select_filter.search": "Cuardaigh nó cruthaigh", "filter_modal.select_filter.subtitle": "Bain úsáid as catagóir reatha nó cruthaigh ceann nua", "filter_modal.select_filter.title": "Déan scagadh ar an bpostáil seo", "filter_modal.title.status": "Déan scagadh ar phostáil", + "filtered_notifications_banner.mentions": "{count, plural, one {tagairt} other {tagairtí}}", + "filtered_notifications_banner.pending_requests": "Fógraí ó {count, plural, =0 {duine ar bith} one {duine amháin} two {# daoine} few {# daoine} many {# daoine} other {# daoine}} b'fhéidir go mbeadh a fhios agat", + "filtered_notifications_banner.title": "Fógraí scagtha", + "firehose.all": "Gach", + "firehose.local": "An freastalaí seo", + "firehose.remote": "Freastalaithe eile", "follow_request.authorize": "Ceadaigh", "follow_request.reject": "Diúltaigh", "follow_requests.unlocked_explanation": "Cé nach bhfuil do chuntas faoi ghlas, cheap foireann {domain} gur mhaith leat súil siar ar iarratais leanúnaí as na cuntais seo.", + "follow_suggestions.curated_suggestion": "Pioc foirne", "follow_suggestions.dismiss": "Ná taispeáin arís", + "follow_suggestions.featured_longer": "Lámh-roghnaithe ag an bhfoireann {domain}", + "follow_suggestions.friends_of_friends_longer": "Coitianta i measc na ndaoine a leanann tú", + "follow_suggestions.hints.featured": "Tá an phróifíl seo roghnaithe de láimh ag foireann {domain}.", + "follow_suggestions.hints.friends_of_friends": "Tá an-tóir ar an bpróifíl seo i measc na ndaoine a leanann tú.", + "follow_suggestions.hints.most_followed": "Tá an phróifíl seo ar cheann de na cinn is mó a leantar ar {domain}.", + "follow_suggestions.hints.most_interactions": "Tá an phróifíl seo ag tarraingt go leor airde ar {domain} le déanaí.", + "follow_suggestions.hints.similar_to_recently_followed": "Tá an phróifíl seo cosúil leis na próifílí a lean tú le déanaí.", "follow_suggestions.personalized_suggestion": "Nod pearsantaithe", "follow_suggestions.popular_suggestion": "Nod coiteann", + "follow_suggestions.popular_suggestion_longer": "Tá an-tóir ar {domain}", + "follow_suggestions.similar_to_recently_followed_longer": "Cosúil le próifílí a lean tú le déanaí", "follow_suggestions.view_all": "Féach uile", "follow_suggestions.who_to_follow": "Cé le leanúint", + "followed_tags": "Hashtags le leanúint", "footer.about": "Maidir le", "footer.directory": "Eolaire próifílí", "footer.get_app": "Faigh an aip", @@ -230,6 +329,7 @@ "footer.keyboard_shortcuts": "Aicearraí méarchláir", "footer.privacy_policy": "Polasaí príobháideachais", "footer.source_code": "Féach ar an gcód foinseach", + "footer.status": "Stádas", "generic.saved": "Sábháilte", "getting_started.heading": "Ag tosú amach", "hashtag.column_header.tag_mode.all": "agus {additional}", @@ -238,15 +338,34 @@ "hashtag.column_settings.select.no_options_message": "Moltaí ar bith faighte", "hashtag.column_settings.select.placeholder": "Iontráil haischlibeanna…", "hashtag.column_settings.tag_mode.all": "Iad seo go léir", - "hashtag.column_settings.tag_toggle": "Include additional tags in this column", + "hashtag.column_settings.tag_mode.any": "Aon cheann díobh seo", + "hashtag.column_settings.tag_mode.none": "Níl aon cheann díobh seo", + "hashtag.column_settings.tag_toggle": "Cuir clibeanna breise san áireamh don cholún seo", + "hashtag.counter_by_accounts": "{count, plural, one {{counter} rannpháirtí} two {{counter} rannpháirtí} few {{counter} rannpháirtí} many {{counter} rannpháirtí} other {{counter} rannpháirtí}}", + "hashtag.counter_by_uses": "{count, plural, one {{counter} post} two {{counter} post} few {{counter} post} many {{counter} post} other {{counter} poist}}", + "hashtag.counter_by_uses_today": "{count, plural, one {{counter} post inniu} other {{counter} poist inniu}} inniu", "hashtag.follow": "Lean haischlib", "hashtag.unfollow": "Ná lean haischlib", + "hashtags.and_other": "agus {count, plural, one {} two {# níos} few {# níos} many {# níos} other {# níos}}", "home.column_settings.show_reblogs": "Taispeáin moltaí", "home.column_settings.show_replies": "Taispeán freagraí", "home.hide_announcements": "Cuir fógraí i bhfolach", + "home.pending_critical_update.body": "Nuashonraigh do fhreastalaí Mastodon chomh luath agus is féidir!", + "home.pending_critical_update.link": "Féach nuashonruithe", + "home.pending_critical_update.title": "Nuashonrú slándála ríthábhachtach ar fáil!", "home.show_announcements": "Taispeáin fógraí", + "interaction_modal.description.favourite": "Le cuntas ar Mastodon, is fearr leat an postáil seo chun a chur in iúl don údar go bhfuil meas agat air agus é a shábháil ar feadh níos déanaí.", + "interaction_modal.description.follow": "Le cuntas ar Mastodon, is féidir leat {name} a leanúint chun a gcuid postálacha a fháil i do fhotha baile.", + "interaction_modal.description.reblog": "Le cuntas ar Mastodon, is féidir leat an postáil seo a threisiú chun é a roinnt le do leantóirí féin.", + "interaction_modal.description.reply": "Le cuntas ar Mastodon, is féidir leat freagra a thabhairt ar an bpostáil seo.", + "interaction_modal.login.action": "Thabhairt dom abhaile", + "interaction_modal.login.prompt": "Fearann ​​do fhreastalaí baile, e.g. mastodon.sóisialta", + "interaction_modal.no_account_yet": "Ní ar Mastodon?", "interaction_modal.on_another_server": "Ar freastalaí eile", "interaction_modal.on_this_server": "Ar an freastalaí seo", + "interaction_modal.sign_in": "Níl tú logáilte isteach ar an bhfreastalaí seo. Cá bhfuil do chuntas á óstáil?", + "interaction_modal.sign_in_hint": "Leid: Sin é an suíomh Gréasáin inar chláraigh tú. Mura cuimhin leat, lorg an ríomhphost fáilte i do bhosca isteach. Is féidir leat d'ainm úsáideora iomlán a chur isteach freisin! (m.sh. @Mastodon@mastodon.social)", + "interaction_modal.title.favourite": "An postáil {name} is fearr leat", "interaction_modal.title.follow": "Lean {name}", "interaction_modal.title.reblog": "Mol postáil de chuid {name}", "interaction_modal.title.reply": "Freagair postáil {name}", @@ -256,45 +375,53 @@ "keyboard_shortcuts.back": "Nasclean siar", "keyboard_shortcuts.blocked": "Oscail liosta na n-úsáideoirí bactha", "keyboard_shortcuts.boost": "Treisigh postáil", - "keyboard_shortcuts.column": "to focus a status in one of the columns", - "keyboard_shortcuts.compose": "to focus the compose textarea", - "keyboard_shortcuts.description": "Cuntas", - "keyboard_shortcuts.direct": "to open direct messages column", + "keyboard_shortcuts.column": "Colún fócas", + "keyboard_shortcuts.compose": "Fócas a chumadh textarea", + "keyboard_shortcuts.description": "Cur síos", + "keyboard_shortcuts.direct": "chun colún lua príobháideach a oscailt", "keyboard_shortcuts.down": "Bog síos ar an liosta", "keyboard_shortcuts.enter": "Oscail postáil", + "keyboard_shortcuts.favourite": "Postáil is fearr leat", + "keyboard_shortcuts.favourites": "Oscail liosta ceanáin", "keyboard_shortcuts.federated": "Oscail amlíne cónaidhmithe", "keyboard_shortcuts.heading": "Aicearraí méarchláir", "keyboard_shortcuts.home": "Oscail amlíne bhaile", "keyboard_shortcuts.hotkey": "Eochair aicearra", - "keyboard_shortcuts.legend": "to display this legend", + "keyboard_shortcuts.legend": "Taispeáin an finscéal seo", "keyboard_shortcuts.local": "Oscail an amlíne áitiúil", "keyboard_shortcuts.mention": "Luaigh údar", "keyboard_shortcuts.muted": "Oscail liosta na n-úsáideoirí balbhaithe", "keyboard_shortcuts.my_profile": "Oscail do phróifíl", - "keyboard_shortcuts.notifications": "to open notifications column", + "keyboard_shortcuts.notifications": "Oscail colún fógraí", "keyboard_shortcuts.open_media": "Oscail meáin", - "keyboard_shortcuts.pinned": "to open pinned posts list", + "keyboard_shortcuts.pinned": "Oscail liosta postálacha pinn", "keyboard_shortcuts.profile": "Oscail próifíl an t-údar", "keyboard_shortcuts.reply": "Freagair ar phostáil", "keyboard_shortcuts.requests": "Oscail liosta iarratas leanúnaí", - "keyboard_shortcuts.search": "to focus search", - "keyboard_shortcuts.spoilers": "to show/hide CW field", - "keyboard_shortcuts.start": "to open \"get started\" column", - "keyboard_shortcuts.toggle_hidden": "to show/hide text behind CW", + "keyboard_shortcuts.search": "Díriú ar an mbosca cuardaigh", + "keyboard_shortcuts.spoilers": "Taispeáin / folaigh réimse CW", + "keyboard_shortcuts.start": "Oscail an colún “tosaigh”", + "keyboard_shortcuts.toggle_hidden": "Taispeáin/folaigh an téacs taobh thiar de CW", "keyboard_shortcuts.toggle_sensitivity": "Taispeáin / cuir i bhfolach meáin", "keyboard_shortcuts.toot": "Cuir tús le postáil nua", - "keyboard_shortcuts.unfocus": "to un-focus compose textarea/search", + "keyboard_shortcuts.unfocus": "Unfocus cum textarea/search", "keyboard_shortcuts.up": "Bog suas ar an liosta", "lightbox.close": "Dún", + "lightbox.compress": "Comhbhrúigh an bosca amhairc íomhá", + "lightbox.expand": "Leathnaigh an bosca amhairc íomhá", "lightbox.next": "An céad eile", "lightbox.previous": "Roimhe seo", "limited_account_hint.action": "Taispeáin an phróifíl ar aon nós", "limited_account_hint.title": "Tá an phróifíl seo curtha i bhfolach ag na modhnóra {domain}.", + "link_preview.author": "Le {name}", + "link_preview.more_from_author": "Tuilleadh ó {name}", + "link_preview.shares": "{count, plural, one {{counter} post} other {{counter} poist}}", "lists.account.add": "Cuir leis an liosta", "lists.account.remove": "Scrios as an liosta", "lists.delete": "Scrios liosta", "lists.edit": "Cuir an liosta in eagar", "lists.edit.submit": "Athraigh teideal", + "lists.exclusive": "Folaigh na poist seo ón mbaile", "lists.new.create": "Cruthaigh liosta", "lists.new.title_placeholder": "Teideal liosta nua", "lists.replies_policy.followed": "Úsáideoir ar bith atá á leanúint", @@ -303,40 +430,91 @@ "lists.replies_policy.title": "Taispeáin freagraí:", "lists.search": "Cuardaigh i measc daoine atá á leanúint agat", "lists.subheading": "Do liostaí", + "load_pending": "{count, plural, one {# mír nua} two {# mír nua} few {# mír nua} many {# mír nua} other {# mír nua}}", + "loading_indicator.label": "Á lódáil…", + "media_gallery.toggle_visible": "{number, plural, one {Folaigh íomhá} two {Folaigh íomhánna} few {Folaigh íomhánna} many {Folaigh íomhánna} other {Folaigh íomhánna}}", + "moved_to_account_banner.text": "Tá do chuntas {disabledAccount} díchumasaithe faoi láthair toisc gur bhog tú go {movedToAccount}.", + "mute_modal.hide_from_notifications": "Folaigh ó fhógraí", + "mute_modal.hide_options": "Folaigh roghanna", + "mute_modal.indefinite": "Go dtí go ndíbhalfaidh mé iad", + "mute_modal.show_options": "Taispeáin roghanna", + "mute_modal.they_can_mention_and_follow": "Is féidir leo tú a lua agus a leanúint, ach ní fheicfidh tú iad.", + "mute_modal.they_wont_know": "Ní bheidh a fhios acu go bhfuil balbhú orthu.", + "mute_modal.title": "An bhfuil fonn ort úsáideoir a bhalbhú?", + "mute_modal.you_wont_see_mentions": "Ní fheicfidh tú postálacha a luann iad.", + "mute_modal.you_wont_see_posts": "Is féidir leo do phoist a fheiceáil go fóill, ach ní fheicfidh tú a gcuid postanna.", + "name_and_others": "{name} and {count, plural, one {# eile} two {# eile} few {# eile} many {# eile} other {# eile}}", + "name_and_others_with_link": "{name} agus {count, plural, one {# eile} two {# eile} few {# eile} many {# eile} other {# eile}}", "navigation_bar.about": "Maidir le", + "navigation_bar.advanced_interface": "Oscail i gcomhéadan gréasáin chun cinn", "navigation_bar.blocks": "Cuntais bhactha", "navigation_bar.bookmarks": "Leabharmharcanna", "navigation_bar.community_timeline": "Amlíne áitiúil", "navigation_bar.compose": "Cum postáil nua", + "navigation_bar.direct": "Luann príobháideach", "navigation_bar.discover": "Faigh amach", "navigation_bar.domain_blocks": "Fearainn bhactha", "navigation_bar.explore": "Féach thart", + "navigation_bar.favourites": "Ceanáin", "navigation_bar.filters": "Focail bhalbhaithe", "navigation_bar.follow_requests": "Iarratais leanúnaí", + "navigation_bar.followed_tags": "Haischlibeanna ina dhiaidh", "navigation_bar.follows_and_followers": "Ag leanúint agus do do leanúint", "navigation_bar.lists": "Liostaí", "navigation_bar.logout": "Logáil Amach", "navigation_bar.mutes": "Úsáideoirí balbhaithe", + "navigation_bar.opened_in_classic_interface": "Osclaítear poist, cuntais agus leathanaigh shonracha eile de réir réamhshocraithe sa chomhéadan gréasáin clasaiceach.", "navigation_bar.personal": "Pearsanta", "navigation_bar.pins": "Postálacha pionnáilte", "navigation_bar.preferences": "Sainroghanna pearsanta", "navigation_bar.public_timeline": "Amlíne cónaidhmithe", "navigation_bar.search": "Cuardaigh", "navigation_bar.security": "Slándáil", - "not_signed_in_indicator.not_signed_in": "You need to sign in to access this resource.", + "not_signed_in_indicator.not_signed_in": "Ní mór duit logáil isteach chun rochtain a fháil ar an acmhainn seo.", "notification.admin.report": "Tuairiscigh {name} {target}", + "notification.admin.report_account": "{name} thuairiscigh {count, plural, one {aon phost} two {# phost} few {# phost} many {# bpost} other {# bpost}} ó {target} do {category}", + "notification.admin.report_account_other": "{name} thuairiscigh {count, plural, one {aon phost} two {# phost} few {# phost} many {# bpost} other {# bpost}} ó {target}", + "notification.admin.report_statuses": "Thuairiscigh {name} {target} le haghaidh {category}", + "notification.admin.report_statuses_other": "{name} tuairiscithe {target}", "notification.admin.sign_up": "Chláraigh {name}", + "notification.favourite": "Is fearr le {name} do phostáil", "notification.follow": "Lean {name} thú", "notification.follow_request": "D'iarr {name} ort do chuntas a leanúint", "notification.mention": "Luaigh {name} tú", + "notification.moderation-warning.learn_more": "Foghlaim níos mó", + "notification.moderation_warning": "Tá rabhadh modhnóireachta faighte agat", + "notification.moderation_warning.action_delete_statuses": "Baineadh cuid de do phostálacha.", + "notification.moderation_warning.action_disable": "Díchumasaíodh do chuntas.", + "notification.moderation_warning.action_mark_statuses_as_sensitive": "Tá cuid de do phostálacha marcáilte mar íogair.", + "notification.moderation_warning.action_none": "Tá rabhadh modhnóireachta faighte ag do chuntas.", + "notification.moderation_warning.action_sensitive": "Déanfar do phostálacha a mharcáil mar íogair as seo amach.", + "notification.moderation_warning.action_silence": "Tá do chuntas teoranta.", + "notification.moderation_warning.action_suspend": "Cuireadh do chuntas ar fionraí.", "notification.own_poll": "Tá do suirbhé críochnaithe", - "notification.poll": "Tá suirbhé inar vótáil tú tar éis críochnú", + "notification.poll": "Tá deireadh le vótaíocht inar vótáil tú", + "notification.private_mention": "luaigh {name} tú go príobháideach", "notification.reblog": "Mhol {name} do phostáil", + "notification.relationships_severance_event": "Cailleadh naisc le {name}", + "notification.relationships_severance_event.account_suspension": "Chuir riarthóir ó {from} {target} ar fionraí, rud a chiallaíonn nach féidir leat nuashonruithe a fháil uathu a thuilleadh ná idirghníomhú leo.", + "notification.relationships_severance_event.domain_block": "Chuir riarthóir ó {from} bac ar {target}, lena n-áirítear {followersCount} de do leantóirí agus {followingCount, plural, one {#cuntas} other {#cuntas}} leanann tú.", + "notification.relationships_severance_event.learn_more": "Foghlaim níos mó", + "notification.relationships_severance_event.user_domain_block": "Chuir tú bac ar {target}, bhain tú {followersCount} de do leantóirí agus {followingCount, plural, one {# cuntas} other {# cuntais}} a leanann tú.", "notification.status": "Phostáil {name} díreach", "notification.update": "Chuir {name} postáil in eagar", + "notification_requests.accept": "Glac", + "notification_requests.dismiss": "Díbhe", + "notification_requests.notifications_from": "Fógraí ó {name}", + "notification_requests.title": "Fógraí scagtha", "notifications.clear": "Glan fógraí", + "notifications.clear_confirmation": "An bhfuil tú cinnte gur mhaith leat d'fhógraí go léir a ghlanadh go buan?", "notifications.column_settings.admin.report": "Tuairiscí nua:", + "notifications.column_settings.admin.sign_up": "Clárúcháin nua:", "notifications.column_settings.alert": "Fógraí deisce", + "notifications.column_settings.beta.category": "Gnéithe turgnamhacha", + "notifications.column_settings.beta.grouping": "Fógraí grúpa", + "notifications.column_settings.favourite": "Ceanáin:", + "notifications.column_settings.filter_bar.advanced": "Taispeáin gach catagóir", + "notifications.column_settings.filter_bar.category": "Barra scagairí tapa", "notifications.column_settings.follow": "Leantóirí nua:", "notifications.column_settings.follow_request": "Iarratais leanúnaí nua:", "notifications.column_settings.mention": "Tráchtanna:", @@ -347,33 +525,77 @@ "notifications.column_settings.sound": "Seinn an fhuaim", "notifications.column_settings.status": "Postálacha nua:", "notifications.column_settings.unread_notifications.category": "Brúfhógraí neamhléite", + "notifications.column_settings.unread_notifications.highlight": "Aibhsigh fógraí neamhléite", "notifications.column_settings.update": "Eagair:", "notifications.filter.all": "Uile", "notifications.filter.boosts": "Treisithe", + "notifications.filter.favourites": "Ceanáin", "notifications.filter.follows": "Ag leanúint", "notifications.filter.mentions": "Tráchtanna", "notifications.filter.polls": "Torthaí suirbhéanna", "notifications.filter.statuses": "Nuashonruithe ó dhaoine a leanann tú", "notifications.grant_permission": "Tabhair cead.", "notifications.group": "{count} fógraí", + "notifications.mark_as_read": "Marcáil gach fógra mar atá léite", + "notifications.permission_denied": "Níl fógraí deisce ar fáil mar gheall ar iarratas ar chead brabhsálaí a diúltaíodh roimhe seo", + "notifications.permission_denied_alert": "Ní féidir fógraí deisce a chumasú, mar gur diúltaíodh cead brabhsálaí roimhe seo", + "notifications.permission_required": "Níl fógraí deisce ar fáil toisc nár tugadh an cead riachtanach.", + "notifications.policy.filter_new_accounts.hint": "Cruthaithe laistigh den {days, plural, one {lae amháin} two {# lá} few {# lá} many {# lá} other {# lá}}", + "notifications.policy.filter_new_accounts_title": "Cuntais nua", + "notifications.policy.filter_not_followers_hint": "Agus daoine a bhfuil siad ag leanúint ort le níos lú ná {days, plural, one {lae amháin} two {# lá} few {# lá} many {# lá} other {# lá}}", + "notifications.policy.filter_not_followers_title": "Daoine nach leanann tú", + "notifications.policy.filter_not_following_hint": "Go dtí go gceadaíonn tú iad de láimh", + "notifications.policy.filter_not_following_title": "Daoine nach leanann tú", + "notifications.policy.filter_private_mentions_hint": "Scagtha mura bhfuil sé mar fhreagra ar do lua féin nó má leanann tú an seoltóir", + "notifications.policy.filter_private_mentions_title": "Tagairtí príobháideacha gan iarraidh", + "notifications.policy.title": "Scag fógraí ó…", "notifications_permission_banner.enable": "Ceadaigh fógraí ar an deasc", + "notifications_permission_banner.how_to_control": "Chun fógraí a fháil nuair nach bhfuil Mastodon oscailte, cumasaigh fógraí deisce. Is féidir leat a rialú go beacht cé na cineálacha idirghníomhaíochtaí a ghineann fógraí deisce tríd an gcnaipe {icon} thuas nuair a bhíonn siad cumasaithe.", "notifications_permission_banner.title": "Ná caill aon rud go deo", - "onboarding.actions.go_to_explore": "See what's trending", - "onboarding.actions.go_to_home": "Go to your home feed", - "onboarding.follows.lead": "You curate your own home feed. The more people you follow, the more active and interesting it will be. These profiles may be a good starting point—you can always unfollow them later!", - "onboarding.follows.title": "Popular on Mastodon", - "onboarding.start.lead": "Your new Mastodon account is ready to go. Here's how you can make the most of it:", - "onboarding.start.skip": "Want to skip right ahead?", - "onboarding.steps.follow_people.body": "You curate your own feed. Lets fill it with interesting people.", - "onboarding.steps.follow_people.title": "Follow {count, plural, one {one person} other {# people}}", - "onboarding.steps.publish_status.body": "Say hello to the world.", - "onboarding.steps.setup_profile.body": "Others are more likely to interact with you with a filled out profile.", - "onboarding.steps.setup_profile.title": "Customize your profile", - "onboarding.steps.share_profile.body": "Let your friends know how to find you on Mastodon!", - "onboarding.steps.share_profile.title": "Share your profile", + "onboarding.action.back": "Tóg ar ais mé", + "onboarding.actions.back": "Tóg ar ais mé", + "onboarding.actions.go_to_explore": "Tóg mé chun trending", + "onboarding.actions.go_to_home": "Tóg go dtí mo bheathú baile mé", + "onboarding.compose.template": "Dia duit #Mastodon!", + "onboarding.follows.empty": "Ar an drochuair, ní féidir aon torthaí a thaispeáint faoi láthair. Is féidir leat triail a bhaint as cuardach nó brabhsáil ar an leathanach taiscéalaíochta chun teacht ar dhaoine le leanúint, nó bain triail eile as níos déanaí.", + "onboarding.follows.lead": "Is é do bheathú baile an príomhbhealach chun taithí a fháil ar Mastodon. Dá mhéad daoine a leanann tú, is ea is gníomhaí agus is suimiúla a bheidh sé. Chun tú a chur ar bun, seo roinnt moltaí:", + "onboarding.follows.title": "Cuir do chuid fotha baile in oiriúint duit féin", + "onboarding.profile.discoverable": "Déan mo phróifíl a fháil amach", + "onboarding.profile.discoverable_hint": "Nuair a roghnaíonn tú infhionnachtana ar Mastodon, d’fhéadfadh do phoist a bheith le feiceáil i dtorthaí cuardaigh agus treochtaí, agus d’fhéadfaí do phróifíl a mholadh do dhaoine a bhfuil na leasanna céanna acu leat.", + "onboarding.profile.display_name": "Ainm taispeána", + "onboarding.profile.display_name_hint": "D’ainm iomlán nó d’ainm spraíúil…", + "onboarding.profile.lead": "Is féidir leat é seo a chomhlánú i gcónaí níos déanaí sna socruithe, áit a bhfuil níos mó roghanna saincheaptha ar fáil.", + "onboarding.profile.note": "Bith", + "onboarding.profile.note_hint": "Is féidir leat @ daoine eile a lua nó #hashtags…", + "onboarding.profile.save_and_continue": "Sábháil agus lean ar aghaidh", + "onboarding.profile.title": "Socrú próifíle", + "onboarding.profile.upload_avatar": "Íosluchtaigh pictiúr próifíl", + "onboarding.profile.upload_header": "Íoslódáil an ceanntásca próifíl", + "onboarding.share.lead": "Cuir in iúl do dhaoine conas is féidir leo tú a aimsiú ar Mastodon!", + "onboarding.share.message": "Is {username} mé ar #Mastodon! Tar lean mé ag {url}", + "onboarding.share.next_steps": "Na chéad chéimeanna eile is féidir:", + "onboarding.share.title": "Roinn do phróifíl", + "onboarding.start.lead": "Tá tú mar chuid de Mastodon anois, ardán meán sóisialta díláraithe uathúil ina ndéanann tú - ní algartam - do thaithí féin a choimeád. Cuirimis tús leat ar an teorainn shóisialta nua seo:", + "onboarding.start.skip": "Nach bhfuil cabhair uait le tosú?", + "onboarding.start.title": "Tá sé déanta agat!", + "onboarding.steps.follow_people.body": "Is éard atá i gceist le daoine suimiúla a leanúint ná Mastodon.", + "onboarding.steps.follow_people.title": "Cuir do chuid fotha baile in oiriúint duit féin", + "onboarding.steps.publish_status.body": "Abair heileo leis an domhan le téacs, grianghraif, físeáin nó pobalbhreith {emoji}", + "onboarding.steps.publish_status.title": "Déan do chéad phostáil", + "onboarding.steps.setup_profile.body": "Cuir le d'idirghníomhaíochtaí trí phróifíl chuimsitheach a bheith agat.", + "onboarding.steps.setup_profile.title": "Déan do phróifíl a phearsantú", + "onboarding.steps.share_profile.body": "Cuir in iúl do do chairde conas tú a aimsiú ar Mastodon", + "onboarding.steps.share_profile.title": "Roinn do phróifíl Mastodon", + "onboarding.tips.2fa": "An raibh a fhios agat? Is féidir leat do chuntas a dhéanamh slán trí fhíordheimhniú dhá fhachtóir a shocrú i socruithe do chuntais. Oibríonn sé le haon aip TOTP de do rogha féin, níl aon uimhir theileafóin riachtanach!", + "onboarding.tips.accounts_from_other_servers": "An raibh a fhios agat? Ós rud é go bhfuil Mastodon díláraithe, déanfar roinnt próifílí a dtagann tú trasna orthu a óstáil ar fhreastalaithe seachas do fhreastalaithe. Agus fós is féidir leat idirghníomhú leo gan uaim! Tá an freastalaí acu sa dara leath dá n-ainm úsáideora!", + "onboarding.tips.migration": "An raibh a fhios agat? Más dóigh leat nach rogha freastalaí iontach é {domain} amach anseo, is féidir leat bogadh go freastalaí Mastodon eile gan do leantóirí a chailliúint. Is féidir leat do fhreastalaí féin a óstáil fiú!", + "onboarding.tips.verification": "An raibh a fhios agat? Is féidir leat do chuntas a fhíorú trí nasc a chur le do phróifíl Mastodon ar do shuíomh Gréasáin féin agus an suíomh Gréasáin a chur le do phróifíl. Níl aon táillí nó doiciméid riachtanach!", + "password_confirmation.exceeds_maxlength": "Sáraíonn dearbhú pasfhocail uasfhad an phasfhocail", + "password_confirmation.mismatching": "Ní hionann dearbhú pasfhocail", "picture_in_picture.restore": "Cuir é ar ais", "poll.closed": "Dúnta", "poll.refresh": "Athnuaigh", + "poll.reveal": "Féach torthaí", "poll.total_people": "{count, plural, one {# duine} other {# duine}}", "poll.total_votes": "{count, plural, one {# vóta} other {# vóta}}", "poll.vote": "Vótáil", @@ -381,11 +603,22 @@ "poll.votes": "{votes, plural, one {# vóta} other {# vóta}}", "poll_button.add_poll": "Cruthaigh suirbhé", "poll_button.remove_poll": "Bain suirbhé", - "privacy.change": "Adjust status privacy", + "privacy.change": "Athraigh príobháideacht postála", + "privacy.direct.long": "Luaigh gach duine sa phost", + "privacy.direct.short": "Daoine ar leith", + "privacy.private.long": "Do leanúna amháin", + "privacy.private.short": "Leantóirí", + "privacy.public.long": "Duine ar bith ar agus amach Mastodon", "privacy.public.short": "Poiblí", + "privacy.unlisted.additional": "Iompraíonn sé seo díreach mar a bheadh ​​poiblí, ach amháin ní bheidh an postáil le feiceáil i bhfothaí beo nó i hashtags, in iniúchadh nó i gcuardach Mastodon, fiú má tá tú liostáilte ar fud an chuntais.", + "privacy.unlisted.long": "Níos lú fanfarraí algarthacha", + "privacy.unlisted.short": "Poiblí ciúin", + "privacy_policy.last_updated": "Nuashonraithe {date}", "privacy_policy.title": "Polasaí príobháideachais", + "recommended": "Molta", "refresh": "Athnuaigh", "regeneration_indicator.label": "Ag lódáil…", + "regeneration_indicator.sublabel": "Tá do bheathú baile á ullmhú!", "relative_time.days": "{number}l", "relative_time.full.days": "{number, plural, one {# lá} other {# lá}} ó shin", "relative_time.full.hours": "{number, plural, one {# uair} other {# uair}} ó shin", @@ -397,77 +630,135 @@ "relative_time.minutes": "{number}n", "relative_time.seconds": "{number}s", "relative_time.today": "inniu", + "reply_indicator.attachments": "{count, plural, one {# alán} two {# aláin} few {# aláin} many {# aláin} other {# aláin}}", "reply_indicator.cancel": "Cealaigh", + "reply_indicator.poll": "Vótaíocht", "report.block": "Bac", "report.block_explanation": "Ní fheicfidh tú a c(h)úid postálacha. Ní bheidh sé/sí in ann do chuid postálacha a fheiceáil ná tú féin a leanúint. Beidh sé/sí in ann a dhéanamh amach go bhfuil sé/sí bactha.", + "report.categories.legal": "Dlíthiúil", "report.categories.other": "Eile", "report.categories.spam": "Turscar", "report.categories.violation": "Sáraíonn ábhar riail freastalaí amháin nó níos mó", "report.category.subtitle": "Roghnaigh an toradh is fearr", + "report.category.title": "Inis dúinn cad atá ar siúl leis an {type} seo", "report.category.title_account": "próifíl", "report.category.title_status": "postáil", "report.close": "Déanta", + "report.comment.title": "An bhfuil aon rud eile ba chóir dúinn a fhios agat, dar leat?", "report.forward": "Seol ar aghaidh chun {target}", + "report.forward_hint": "Is ó fhreastalaí eile an cuntas. Cuir cóip gan ainm den tuarascáil ansin freisin?", "report.mute": "Balbhaigh", "report.mute_explanation": "Ní fheicfidh tú a postálacha. Is féidir an té seo tú a leanúint agus do phostálacha a fheiceáil, agus ní fhios go bhfuil iad balbhaithe.", "report.next": "An céad eile", "report.placeholder": "Ráitis bhreise", "report.reasons.dislike": "Ní maith liom é", + "report.reasons.dislike_description": "Ní rud é ba mhaith leat a fheiceáil", + "report.reasons.legal": "Tá sé mídhleathach", + "report.reasons.legal_description": "Creideann tú go sáraíonn sé dlí do thíre nó do thír an fhreastalaí", "report.reasons.other": "Is rud eile é", + "report.reasons.other_description": "Ní luíonn an cheist le catagóirí eile", "report.reasons.spam": "Is turscar é", + "report.reasons.spam_description": "Naisc mhailíseacha, rannpháirtíocht bhréige, nó freagraí athchleachtach", "report.reasons.violation": "Sáraíonn sé rialacha an fhreastalaí", "report.reasons.violation_description": "Tá a fhios agat go sáraíonn sé rialacha ar leith", "report.rules.subtitle": "Roghnaigh gach atá i bhfeidhm", "report.rules.title": "Cén rialacha atá á sárú?", "report.statuses.subtitle": "Roghnaigh gach atá i bhfeidhm", + "report.statuses.title": "An bhfuil aon phoist a thacaíonn leis an tuarascáil seo?", "report.submit": "Cuir isteach", "report.target": "Ag tuairisciú {target}", + "report.thanks.take_action": "Seo do roghanna chun an méid a fheiceann tú ar Mastodon a rialú:", + "report.thanks.take_action_actionable": "Agus é seo á athbhreithniú againn, is féidir leat caingean a dhéanamh in aghaidh @{name}:", + "report.thanks.title": "Ná bí ag iarraidh é seo a fheiceáil?", + "report.thanks.title_actionable": "Go raibh maith agat as tuairisc a thabhairt, scrúdóimid é seo.", "report.unfollow": "Ná lean @{name}", + "report.unfollow_explanation": "Tá tú ag leanúint an chuntais seo. Chun nach bhfeicfidh tú a bpoist i do fhotha baile a thuilleadh, dílean ​​iad.", "report_notification.attached_statuses": "{count, plural, one {# post} other {# posts}} attached", + "report_notification.categories.legal": "Dlíthiúil", + "report_notification.categories.legal_sentence": "ábhar mídhleathach", "report_notification.categories.other": "Eile", + "report_notification.categories.other_sentence": "eile", "report_notification.categories.spam": "Turscar", + "report_notification.categories.spam_sentence": "turscar", "report_notification.categories.violation": "Sárú rialach", + "report_notification.categories.violation_sentence": "sárú riail", "report_notification.open": "Oscail tuairisc", + "search.no_recent_searches": "Níl aon chuardach le déanaí", "search.placeholder": "Cuardaigh", + "search.quick_action.account_search": "Próifílí a mheaitseálann {x}", + "search.quick_action.go_to_account": "Téigh go próifíl {x}", + "search.quick_action.go_to_hashtag": "Téigh chuig hashtag {x}", + "search.quick_action.open_url": "Oscail URL i Mastodon", + "search.quick_action.status_search": "Postálacha a mheaitseálann {x}", "search.search_or_paste": "Cuardaigh nó cuir URL isteach", - "search_results.all": "Uile", - "search_results.hashtags": "Haischlibeanna", + "search_popout.full_text_search_disabled_message": "Níl sé ar fáil ar {domain}.", + "search_popout.full_text_search_logged_out_message": "Ar fáil ach amháin nuair atá tú logáilte isteach.", + "search_popout.language_code": "Cód teanga ISO", + "search_popout.options": "Roghanna cuardaigh", + "search_popout.quick_actions": "Gníomhartha tapa", + "search_popout.recent": "Cuardach le déanaí", + "search_popout.specific_date": "dáta ar leith", + "search_popout.user": "úsáideoir", + "search_results.accounts": "Próifílí", + "search_results.all": "Gach", + "search_results.hashtags": "Haischlib", + "search_results.nothing_found": "Níorbh fhéidir aon rud a aimsiú do na téarmaí cuardaigh seo", + "search_results.see_all": "Gach rud a fheicáil", "search_results.statuses": "Postálacha", "search_results.title": "Cuardaigh ar thóir {q}", + "server_banner.about_active_users": "Daoine a úsáideann an freastalaí seo le 30 lá anuas (Úsáideoirí Gníomhacha Míosúla)", "server_banner.active_users": "úsáideoirí gníomhacha", + "server_banner.administered_by": "Arna riar ag:", + "server_banner.is_one_of_many": "Tá {domain} ar cheann de na freastalaithe Mastodon neamhspleácha go leor is féidir leat a úsáid chun páirt a ghlacadh sa feiliúnach.", "server_banner.server_stats": "Staitisticí freastalaí:", "sign_in_banner.create_account": "Cruthaigh cuntas", + "sign_in_banner.follow_anyone": "Lean aon duine ar fud an fhealsúnachta agus féach ar fad in ord croineolaíoch. Gan algartam, fógraí, nó clickbait i radharc.", + "sign_in_banner.mastodon_is": "Is é Mastodon an bealach is fearr le coinneáil suas lena bhfuil ag tarlú.", "sign_in_banner.sign_in": "Sinigh isteach", - "status.admin_status": "Open this status in the moderation interface", + "sign_in_banner.sso_redirect": "Logáil isteach nó Cláraigh", + "status.admin_account": "Oscail comhéadan modhnóireachta do @{name}", + "status.admin_domain": "Oscail comhéadan modhnóireachta le haghaidh {domain}", + "status.admin_status": "Oscail an postáil seo sa chomhéadan modhnóireachta", "status.block": "Bac @{name}", "status.bookmark": "Leabharmharcanna", "status.cancel_reblog_private": "Dímhol", "status.cannot_reblog": "Ní féidir an phostáil seo a mholadh", - "status.copy": "Copy link to status", + "status.copy": "Cóipeáil an nasc chuig an bpostáil", "status.delete": "Scrios", + "status.detailed_status": "Amharc comhrá mionsonraithe", + "status.direct": "Luaigh @{name} go príobháideach", + "status.direct_indicator": "Lua príobháideach", "status.edit": "Cuir in eagar", + "status.edited": "Arna chuir in eagar anuas {date}", "status.edited_x_times": "Curtha in eagar {count, plural, one {{count} uair amháin} two {{count} uair} few {{count} uair} many {{count} uair} other {{count} uair}}", "status.embed": "Leabaigh", + "status.favourite": "Is fearr leat", + "status.favourites": "{count, plural, one {a bhfuil grá agat do} two {gráite} few {gráite} many {gráite} other {gráite}}", "status.filter": "Déan scagadh ar an bpostáil seo", "status.filtered": "Scagtha", "status.hide": "Cuir postáil i bhfolach", "status.history.created": "Chruthaigh {name} {date}", "status.history.edited": "Curtha in eagar ag {name} in {date}", "status.load_more": "Lódáil a thuilleadh", + "status.media.open": "Cliceáil chun oscailt", + "status.media.show": "Cliceáil chun a thaispeáint", "status.media_hidden": "Cuirtear meáin i bhfolach", "status.mention": "Luaigh @{name}", "status.more": "Tuilleadh", "status.mute": "Balbhaigh @{name}", "status.mute_conversation": "Balbhaigh comhrá", - "status.open": "Expand this status", + "status.open": "Leathnaigh an post seo", "status.pin": "Pionnáil ar do phróifíl", "status.pinned": "Postáil pionnáilte", "status.read_more": "Léan a thuilleadh", - "status.reblog": "Mol", + "status.reblog": "Treisiú", "status.reblog_private": "Mol le léargas bunúsach", "status.reblogged_by": "Mhol {name}", + "status.reblogs": "{count, plural, one {buaic} other {buaic}}", "status.reblogs.empty": "Níor mhol éinne an phostáil seo fós. Nuair a mholfaidh duine éigin í, taispeánfar anseo é sin.", "status.redraft": "Scrios ⁊ athdhréachtaigh", + "status.remove_bookmark": "Bain leabharmharc", + "status.replied_to": "D'fhreagair {name}", "status.reply": "Freagair", "status.replyAll": "Freagair le snáithe", "status.report": "Tuairiscigh @{name}", @@ -479,41 +770,57 @@ "status.show_more": "Taispeáin níos mó", "status.show_more_all": "Taispeáin níos mó d'uile", "status.show_original": "Taispeáin bunchóip", - "status.title.with_attachments": "{user} posted {attachmentCount, plural, one {an attachment} other {# attachments}}", + "status.title.with_attachments": "{user} a sheol {attachmentCount, plural, one {ceangal} two {{attachmentCount} ceangal} few {{attachmentCount} ceangail} many {{attachmentCount} ceangal} other {{attachmentCount} ceangal}}", "status.translate": "Aistrigh", "status.translated_from_with": "D'Aistrigh ón {lang} ag úsáid {provider}", + "status.uncached_media_warning": "Níl an réamhamharc ar fáil", "status.unmute_conversation": "Díbhalbhaigh comhrá", "status.unpin": "Díphionnáil de do phróifíl", + "subscribed_languages.lead": "Ní bheidh ach postálacha i dteangacha roghnaithe le feiceáil ar do bhaile agus liostaí amlínte tar éis an athraithe. Roghnaigh ceann ar bith chun postálacha a fháil i ngach teanga.", "subscribed_languages.save": "Sábháil athruithe", + "subscribed_languages.target": "Athraigh teangacha suibscríofa le haghaidh {target}", "tabs_bar.home": "Baile", "tabs_bar.notifications": "Fógraí", "time_remaining.days": "{number, plural, one {# lá} other {# lá}} fágtha", "time_remaining.hours": "{number, plural, one {# uair} other {# uair}} fágtha", "time_remaining.minutes": "{number, plural, one {# nóiméad} other {# nóiméad}} fágtha", + "time_remaining.moments": "Chuimhneacháin fágtha", "time_remaining.seconds": "{number, plural, one {# soicind} other {# soicind}} fágtha", + "timeline_hint.remote_resource_not_displayed": "Níl {resource} ó fhreastalaithe eile ar taispeáint.", "timeline_hint.resources.followers": "Leantóirí", "timeline_hint.resources.follows": "Cuntais leanta", "timeline_hint.resources.statuses": "Postáilí níos sine", "trends.counter_by_accounts": "{count, plural, one {{counter} duine} other {{counter} duine}} le {days, plural, one {lá} other {{days} lá}} anuas", "trends.trending_now": "Ag treochtáil anois", + "ui.beforeunload": "Caillfear do dhréacht má fhágann tú Mastodon.", "units.short.billion": "{count}B", "units.short.million": "{count}M", "units.short.thousand": "{count}k", "upload_area.title": "Tarraing ⁊ scaoil chun uaslódáil", - "upload_form.audio_description": "Describe for people with hearing loss", + "upload_button.label": "Cuir íomhánna, físeán nó comhad fuaime leis", + "upload_error.limit": "Sáraíodh an teorainn uaslódála comhaid.", + "upload_error.poll": "Ní cheadaítear uaslódáil comhad le pobalbhreith.", + "upload_form.audio_description": "Déan cur síos ar dhaoine bodhra nó lagéisteachta", "upload_form.description": "Describe for the visually impaired", "upload_form.edit": "Cuir in eagar", - "upload_form.video_description": "Describe for people with hearing loss or visual impairment", + "upload_form.thumbnail": "Athraigh mionsamhail", + "upload_form.video_description": "Déan cur síos ar dhaoine atá bodhar, lagéisteachta, dall nó lagamhairc", "upload_modal.analyzing_picture": "Ag anailísiú íomhá…", "upload_modal.apply": "Cuir i bhFeidhm", "upload_modal.applying": "Á gcur i bhfeidhm…", "upload_modal.choose_image": "Roghnaigh íomhá", "upload_modal.description_placeholder": "Chuaigh bé mhórsách le dlúthspád fíorfhinn trí hata mo dhea-phorcáin bhig", + "upload_modal.detect_text": "Braith téacs ó phictiúr", "upload_modal.edit_media": "Cuir gné in eagar", + "upload_modal.hint": "Cliceáil nó tarraing an ciorcal ar an réamhamharc chun an pointe fócasach a roghnú a bheidh le feiceáil i gcónaí ar na mionsamhlacha go léir.", + "upload_modal.preparing_ocr": "OCR á ullmhú…", + "upload_modal.preview_label": "Réamhamharc ({ratio})", "upload_progress.label": "Ag uaslódáil...", "upload_progress.processing": "Ag próiseáil…", + "username.taken": "Glactar leis an ainm úsáideora sin. Bain triail eile as", "video.close": "Dún físeán", "video.download": "Íoslódáil comhad", + "video.exit_fullscreen": "Scoir scáileán iomlán", "video.expand": "Leath físeán", "video.fullscreen": "Lánscáileán", "video.hide": "Cuir físeán i bhfolach", diff --git a/app/javascript/mastodon/locales/gd.json b/app/javascript/mastodon/locales/gd.json index fec025045c9f78..93268c2715df0b 100644 --- a/app/javascript/mastodon/locales/gd.json +++ b/app/javascript/mastodon/locales/gd.json @@ -470,7 +470,6 @@ "notification.mention": "Thug {name} iomradh ort", "notification.moderation-warning.learn_more": "Barrachd fiosrachaidh", "notification.own_poll": "Thàinig an cunntas-bheachd agad gu crìoch", - "notification.poll": "Thàinig cunntas-bheachd sa bhòt thu gu crìoch", "notification.reblog": "Bhrosnaich {name} am post agad", "notification.relationships_severance_event": "Chaill thu dàimhean le {name}", "notification.relationships_severance_event.account_suspension": "Chuir rianaire aig {from} {target} à rèim agus is ciall dha sin nach fhaigh thu naidheachdan uapa ’s nach urrainn dhut conaltradh leotha.", diff --git a/app/javascript/mastodon/locales/gl.json b/app/javascript/mastodon/locales/gl.json index 03287c7e5224bc..d64789b86cb120 100644 --- a/app/javascript/mastodon/locales/gl.json +++ b/app/javascript/mastodon/locales/gl.json @@ -92,7 +92,7 @@ "block_modal.remote_users_caveat": "Ímoslle pedir ao servidor {domain} que respecte a túa decisión. Emporiso, non hai garantía de que atenda a petición xa que os servidores xestionan os bloqueos de formas diferentes. As publicacións públicas poderían aínda ser visibles para usuarias que non iniciaron sesión.", "block_modal.show_less": "Mostrar menos", "block_modal.show_more": "Mostrar máis", - "block_modal.they_cant_mention": "Non te poden seguir nin mencionar.", + "block_modal.they_cant_mention": "Non te pode seguir nin mencionar.", "block_modal.they_cant_see_posts": "Non pode ver as túas publicacións nin ti as de ela.", "block_modal.they_will_know": "Pode ver que a bloqueaches.", "block_modal.title": "Bloquear usuaria?", @@ -216,7 +216,7 @@ "domain_block_modal.they_wont_know": "Non saberá que a bloqueaches.", "domain_block_modal.title": "Bloquear dominio?", "domain_block_modal.you_will_lose_followers": "Vanse eliminar todas as túas seguidoras deste servidor.", - "domain_block_modal.you_wont_see_posts": "Non verás publicacións ou notificación das usuarias neste servidor.", + "domain_block_modal.you_wont_see_posts": "Non verás publicacións ou notificacións das usuarias deste servidor.", "domain_pill.activitypub_lets_connect": "Permíteche conectar e interactuar con persoas non só de Mastodon, se non tamén con outras apps sociais.", "domain_pill.activitypub_like_language": "ActivityPub é algo así como o idioma que Mastodon fala con outras redes sociais.", "domain_pill.server": "Servidor", @@ -443,6 +443,8 @@ "mute_modal.title": "Acalar usuaria?", "mute_modal.you_wont_see_mentions": "Non verás as publicacións que a mencionen.", "mute_modal.you_wont_see_posts": "Seguirá podendo ler as túas publicacións, pero non verás as súas.", + "name_and_others": "{name} e {count, plural, one {outra máis} other {# máis}}", + "name_and_others_with_link": "{name} e {count, plural, one {outra máis} other {# máis}}", "navigation_bar.about": "Sobre", "navigation_bar.advanced_interface": "Abrir coa interface web avanzada", "navigation_bar.blocks": "Usuarias bloqueadas", @@ -470,6 +472,10 @@ "navigation_bar.security": "Seguranza", "not_signed_in_indicator.not_signed_in": "Debes acceder para ver este recurso.", "notification.admin.report": "{name} denunciou a {target}", + "notification.admin.report_account": "{name} denunciou {count, plural, one {unha publicación} other {# publicacións}} de {target} por {category}", + "notification.admin.report_account_other": "{name} denunciou {count, plural, one {unha publicación} other {# publicacións}} de {target}", + "notification.admin.report_statuses": "{name} deununciou a {target} por {category}", + "notification.admin.report_statuses_other": "{name} denunciou a {target}", "notification.admin.sign_up": "{name} rexistrouse", "notification.favourite": "{name} marcou como favorita a túa publicación", "notification.follow": "{name} comezou a seguirte", @@ -486,6 +492,7 @@ "notification.moderation_warning.action_suspend": "A túa conta foi suspendida.", "notification.own_poll": "A túa enquisa rematou", "notification.poll": "Rematou a enquisa na que votaches", + "notification.private_mention": "{name} mencionoute de xeito privado", "notification.reblog": "{name} compartiu a túa publicación", "notification.relationships_severance_event": "Perdeuse a conexión con {name}", "notification.relationships_severance_event.account_suspension": "A administración de {from} suspendeu a {target}, o que significa que xa non vas recibir actualizacións de esa conta ou interactuar con ela.", @@ -503,6 +510,8 @@ "notifications.column_settings.admin.report": "Novas denuncias:", "notifications.column_settings.admin.sign_up": "Novas usuarias:", "notifications.column_settings.alert": "Notificacións de escritorio", + "notifications.column_settings.beta.category": "Características experimentais", + "notifications.column_settings.beta.grouping": "Notificacións de grupo", "notifications.column_settings.favourite": "Favoritas:", "notifications.column_settings.filter_bar.advanced": "Mostrar todas as categorías", "notifications.column_settings.filter_bar.category": "Barra de filtrado rápido", @@ -666,9 +675,13 @@ "report.unfollow_explanation": "Estás a seguir esta conta. Deixar de ver as súas publicacións na túa cronoloxía, non seguila.", "report_notification.attached_statuses": "Achegou {count, plural, one {{count} publicación} other {{count} publicacións}}", "report_notification.categories.legal": "Legal", + "report_notification.categories.legal_sentence": "contido ilegal", "report_notification.categories.other": "Outro", + "report_notification.categories.other_sentence": "outra", "report_notification.categories.spam": "Spam", + "report_notification.categories.spam_sentence": "spam", "report_notification.categories.violation": "Faltou ás regras", + "report_notification.categories.violation_sentence": "violación das regras", "report_notification.open": "Abrir a denuncia", "search.no_recent_searches": "Non hai buscas recentes", "search.placeholder": "Procurar", diff --git a/app/javascript/mastodon/locales/he.json b/app/javascript/mastodon/locales/he.json index 8111a56e895f8c..3687df7b87b2b6 100644 --- a/app/javascript/mastodon/locales/he.json +++ b/app/javascript/mastodon/locales/he.json @@ -443,6 +443,8 @@ "mute_modal.title": "להשתיק משתמש?", "mute_modal.you_wont_see_mentions": "לא תראה הודעות שמאזכרות אותם.", "mute_modal.you_wont_see_posts": "הם יכולים לראות את הודעותכם, אבל אתם לא תוכלו לראות את שלהם.", + "name_and_others": "{name} ועוד {count, plural,one {אחד נוסף}other {# נוספים}}", + "name_and_others_with_link": "{name} ועוד {count, plural,one {אחד נוסף}other {# נוספים}}", "navigation_bar.about": "אודות", "navigation_bar.advanced_interface": "פתח במנשק ווב מתקדם", "navigation_bar.blocks": "משתמשים חסומים", @@ -470,6 +472,10 @@ "navigation_bar.security": "אבטחה", "not_signed_in_indicator.not_signed_in": "יש להיות מאומת כדי לגשת למשאב זה.", "notification.admin.report": "{name} דיווח.ה על {target}", + "notification.admin.report_account": "{name} דווחו על {count, plural, one {הודעה אחת} two {הודעותיים} many {# הודעות} other {# הודעות}} מאת {target} בגין {category}", + "notification.admin.report_account_other": "{name} דווחו על {count, plural, one {הודעה אחת} two {הודעותיים} many {# הודעות} other {# הודעות}} מאת {target}", + "notification.admin.report_statuses": "{name} דווחו על {target} בגין {category}", + "notification.admin.report_statuses_other": "{name} דיווח.ה על {target}", "notification.admin.sign_up": "{name} נרשמו", "notification.favourite": "הודעתך חובבה על ידי {name}", "notification.follow": "{name} במעקב אחרייך", @@ -486,6 +492,7 @@ "notification.moderation_warning.action_suspend": "חשבונך הושעה.", "notification.own_poll": "הסקר שלך הסתיים", "notification.poll": "סקר שהצבעת בו הסתיים", + "notification.private_mention": "{name} פנה/פנתה אליך בפרטיות", "notification.reblog": "הודעתך הודהדה על ידי {name}", "notification.relationships_severance_event": "אבד הקשר עם {name}", "notification.relationships_severance_event.account_suspension": "מנהל.ת משרת {from} השע(ת)ה את {target}, ולפיכך לא תעודכנו יותר על ידם ולא תוכלו להיות איתם בקשר.", @@ -503,6 +510,8 @@ "notifications.column_settings.admin.report": "דו\"חות חדשים", "notifications.column_settings.admin.sign_up": "הרשמות חדשות:", "notifications.column_settings.alert": "התראות לשולחן העבודה", + "notifications.column_settings.beta.category": "יכולות ניסיוניות", + "notifications.column_settings.beta.grouping": "התראות קבוצה", "notifications.column_settings.favourite": "חיבובים:", "notifications.column_settings.filter_bar.advanced": "להציג את כל הקטגוריות", "notifications.column_settings.filter_bar.category": "שורת סינון מהיר", @@ -666,9 +675,13 @@ "report.unfollow_explanation": "אתם עוקבים אחרי החשבון הזה. כדי להפסיק לראות את הפרסומים שלו בפיד הבית שלכם, הפסיקו לעקוב אחריו.", "report_notification.attached_statuses": "{count, plural, one {הודעה מצורפת} two {הודעותיים מצורפות} many {{count} הודעות מצורפות} other {{count} הודעות מצורפות}}", "report_notification.categories.legal": "חוקי", + "report_notification.categories.legal_sentence": "תוכן בלתי חוקי", "report_notification.categories.other": "שונות", + "report_notification.categories.other_sentence": "אחר", "report_notification.categories.spam": "ספאם (דואר זבל)", + "report_notification.categories.spam_sentence": "ספאם (דואר זבל)", "report_notification.categories.violation": "הפרת כלל", + "report_notification.categories.violation_sentence": "הפרת כלל", "report_notification.open": "פתח דו\"ח", "search.no_recent_searches": "לא נמצאו חיפושים אחרונים", "search.placeholder": "חיפוש", diff --git a/app/javascript/mastodon/locales/hr.json b/app/javascript/mastodon/locales/hr.json index c8f6f018623394..5d087dae948b7b 100644 --- a/app/javascript/mastodon/locales/hr.json +++ b/app/javascript/mastodon/locales/hr.json @@ -342,7 +342,6 @@ "notification.follow_request": "{name} zatražio/la je da Vas prati", "notification.mention": "{name} Vas je spomenuo", "notification.own_poll": "Vaša anketa je završila", - "notification.poll": "Anketa u kojoj ste glasali je završila", "notification.reblog": "{name} je boostao/la Vaš status", "notifications.clear": "Očisti obavijesti", "notifications.clear_confirmation": "Želite li zaista trajno očistiti sve Vaše obavijesti?", diff --git a/app/javascript/mastodon/locales/hu.json b/app/javascript/mastodon/locales/hu.json index 1fcadc8f9c4730..fd9ce38eb120ac 100644 --- a/app/javascript/mastodon/locales/hu.json +++ b/app/javascript/mastodon/locales/hu.json @@ -443,6 +443,8 @@ "mute_modal.title": "Elnémítsuk a felhasználót?", "mute_modal.you_wont_see_mentions": "Nem látsz majd őt említő bejegyzéseket.", "mute_modal.you_wont_see_posts": "Továbbra is látni fogja a bejegyzéseidet, de te nem fogod látni az övéit.", + "name_and_others": "{name} és {count, plural, one {# másik} other {# másik}}", + "name_and_others_with_link": "{name} és {count, plural, one {# másik} other {# másik}}", "navigation_bar.about": "Névjegy", "navigation_bar.advanced_interface": "Megnyitás a speciális webes felületben", "navigation_bar.blocks": "Letiltott felhasználók", @@ -470,6 +472,10 @@ "navigation_bar.security": "Biztonság", "not_signed_in_indicator.not_signed_in": "Az erőforrás eléréséhez be kell jelentkezned.", "notification.admin.report": "{name} jelentette: {target}", + "notification.admin.report_account": "{name} jelentett {count, plural, one {egy bejegyzést} other {# bejegyzést}} itt: {target}, ezért: {category}", + "notification.admin.report_account_other": "{name} jelentett {count, plural, one {egy bejegyzést} other {# bejegyzést}} itt: {target}", + "notification.admin.report_statuses": "{name} jelentette: {target}, ezért: {category}", + "notification.admin.report_statuses_other": "{name} jelentette: {target}", "notification.admin.sign_up": "{name} regisztrált", "notification.favourite": "{name} kedvencnek jelölte a bejegyzésedet", "notification.follow": "{name} követ téged", @@ -485,7 +491,8 @@ "notification.moderation_warning.action_silence": "A fiókod korlátozásra került.", "notification.moderation_warning.action_suspend": "A fiókod felfüggesztésre került.", "notification.own_poll": "A szavazásod véget ért", - "notification.poll": "Egy szavazás, melyben részt vettél, véget ért", + "notification.poll": "Véget ért egy szavazás, melyben részt vettél", + "notification.private_mention": "{name} privátban megemlített", "notification.reblog": "{name} megtolta a bejegyzésedet", "notification.relationships_severance_event": "Elvesztek a kapcsolatok vele: {name}", "notification.relationships_severance_event.account_suspension": "Egy admin a(z) {from} kiszolgálóról felfüggesztette {target} fiókját, ami azt jelenti, hogy mostantól nem fogsz róla értesítést kapni, és nem fogsz tudni vele kapcsolatba lépni.", @@ -503,6 +510,8 @@ "notifications.column_settings.admin.report": "Új jelentések:", "notifications.column_settings.admin.sign_up": "Új regisztrálók:", "notifications.column_settings.alert": "Asztali értesítések", + "notifications.column_settings.beta.category": "Kísérleti funkciók", + "notifications.column_settings.beta.grouping": "Csoportértesítések", "notifications.column_settings.favourite": "Kedvencek:", "notifications.column_settings.filter_bar.advanced": "Minden kategória megjelenítése", "notifications.column_settings.filter_bar.category": "Gyorsszűrő sáv", @@ -666,9 +675,13 @@ "report.unfollow_explanation": "Követed ezt a fiókot. Hogy ne lásd a bejegyzéseit a saját idővonaladon, szüntesd meg a követését.", "report_notification.attached_statuses": "{count} bejegyzés mellékelve", "report_notification.categories.legal": "Jogi", + "report_notification.categories.legal_sentence": "illegális tartalom", "report_notification.categories.other": "Egyéb", + "report_notification.categories.other_sentence": "egyéb", "report_notification.categories.spam": "Kéretlen üzenet", + "report_notification.categories.spam_sentence": "kéretlen üzenet", "report_notification.categories.violation": "Szabálysértés", + "report_notification.categories.violation_sentence": "szabálysértés", "report_notification.open": "Bejelentés megnyitása", "search.no_recent_searches": "Nincsenek keresési előzmények", "search.placeholder": "Keresés", diff --git a/app/javascript/mastodon/locales/hy.json b/app/javascript/mastodon/locales/hy.json index b4abe9bf09b3d7..4a197185e30c22 100644 --- a/app/javascript/mastodon/locales/hy.json +++ b/app/javascript/mastodon/locales/hy.json @@ -324,7 +324,6 @@ "notification.follow_request": "{name} քեզ հետեւելու հայց է ուղարկել", "notification.mention": "{name} նշեց քեզ", "notification.own_poll": "Հարցումդ աւարտուեց", - "notification.poll": "Հարցումը, ուր դու քուէարկել ես, աւարտուեց։", "notification.reblog": "{name} տարածեց գրառումդ", "notification.status": "{name} հենց նոր գրառում արեց", "notification.update": "{name}-ը փոխել է գրառումը", diff --git a/app/javascript/mastodon/locales/ia.json b/app/javascript/mastodon/locales/ia.json index ace6402ee145de..db1ead30c82216 100644 --- a/app/javascript/mastodon/locales/ia.json +++ b/app/javascript/mastodon/locales/ia.json @@ -485,7 +485,6 @@ "notification.moderation_warning.action_silence": "Tu conto ha essite limitate.", "notification.moderation_warning.action_suspend": "Tu conto ha essite suspendite.", "notification.own_poll": "Tu sondage ha finite", - "notification.poll": "Un sondage in le qual tu ha votate ha finite", "notification.reblog": "{name} ha impulsate tu message", "notification.relationships_severance_event": "Connexiones perdite con {name}", "notification.relationships_severance_event.account_suspension": "Un administrator de {from} ha suspendiute {target}. Isto significa que tu non pote plus reciper actualisationes de iste persona o interager con ille.", diff --git a/app/javascript/mastodon/locales/id.json b/app/javascript/mastodon/locales/id.json index f4e5e1baea4723..e139796bf1f290 100644 --- a/app/javascript/mastodon/locales/id.json +++ b/app/javascript/mastodon/locales/id.json @@ -426,7 +426,6 @@ "notification.follow_request": "{name} ingin mengikuti Anda", "notification.mention": "{name} menyebut Anda", "notification.own_poll": "Japat Anda telah berakhir", - "notification.poll": "Japat yang Anda ikuti telah berakhir", "notification.reblog": "{name} mem-boost kiriman Anda", "notification.status": "{name} baru saja mengirim", "notification.update": "{name} mengedit kiriman", diff --git a/app/javascript/mastodon/locales/ie.json b/app/javascript/mastodon/locales/ie.json index c75788c430129e..3ece43918b19af 100644 --- a/app/javascript/mastodon/locales/ie.json +++ b/app/javascript/mastodon/locales/ie.json @@ -480,7 +480,6 @@ "notification.moderation_warning.action_silence": "Tui conto ha esset limitat.", "notification.moderation_warning.action_suspend": "Tui conto ha esset suspendet.", "notification.own_poll": "Tui balotation ha finit", - "notification.poll": "Un balotation in quel tu votat ha finit", "notification.reblog": "{name} boostat tui posta", "notification.relationships_severance_event": "Perdit conexiones con {name}", "notification.relationships_severance_event.account_suspension": "Un admin de {from} ha suspendet {target}, dunc con ti person tu ne plu posse reciver actualisationes ni far interactiones.", diff --git a/app/javascript/mastodon/locales/io.json b/app/javascript/mastodon/locales/io.json index 6aa954ae573048..839939687d219f 100644 --- a/app/javascript/mastodon/locales/io.json +++ b/app/javascript/mastodon/locales/io.json @@ -402,7 +402,6 @@ "notification.follow_request": "{name} demandas sequar vu", "notification.mention": "{name} mencionis tu", "notification.own_poll": "Vua votposto finigis", - "notification.poll": "Votposto quo havas vua voto finigis", "notification.reblog": "{name} repetis tua mesajo", "notification.status": "{name} nove postigis", "notification.update": "{name} modifikis posto", diff --git a/app/javascript/mastodon/locales/is.json b/app/javascript/mastodon/locales/is.json index 1a38591b853b35..27d23aafd0e5c8 100644 --- a/app/javascript/mastodon/locales/is.json +++ b/app/javascript/mastodon/locales/is.json @@ -443,6 +443,8 @@ "mute_modal.title": "Þagga niður í notanda?", "mute_modal.you_wont_see_mentions": "Þú munt ekki sjá færslur sem minnast á viðkomandi aðila.", "mute_modal.you_wont_see_posts": "Viðkomandi geta áfram séð færslurnar þínar en þú munt ekki sjá færslurnar þeirra.", + "name_and_others": "{name} og {count, plural, one {# annar} other {# aðrir}}", + "name_and_others_with_link": "{name} og {count, plural, one {# annar} other {# aðrir}}", "navigation_bar.about": "Um hugbúnaðinn", "navigation_bar.advanced_interface": "Opna í ítarlegu vefviðmóti", "navigation_bar.blocks": "Útilokaðir notendur", @@ -470,6 +472,10 @@ "navigation_bar.security": "Öryggi", "not_signed_in_indicator.not_signed_in": "Þú þarft að skrá þig inn til að nota þetta tilfang.", "notification.admin.report": "{name} kærði {target}", + "notification.admin.report_account": "{name} kærði {count, plural, one {eina færslu} other {# færslur}} frá {target} fyrir {category}", + "notification.admin.report_account_other": "{name} kærði {count, plural, one {eina færslu} other {# færslur}} frá {target}", + "notification.admin.report_statuses": "{name} kærði {target} fyrir {category}", + "notification.admin.report_statuses_other": "{name} kærði {target}", "notification.admin.sign_up": "{name} skráði sig", "notification.favourite": "{name} setti færsluna þína í eftirlæti", "notification.follow": "{name} fylgist með þér", @@ -485,7 +491,8 @@ "notification.moderation_warning.action_silence": "Notandaaðgangurinn þinn hefur verið takmarkaður.", "notification.moderation_warning.action_suspend": "Notandaaðgangurinn þinn hefur verið settur í frysti.", "notification.own_poll": "Könnuninni þinni er lokið", - "notification.poll": "Könnun sem þú tókst þátt í er lokið", + "notification.poll": "Könnun sem þú greiddir atkvæði í er lokið", + "notification.private_mention": "{name} minntist á þig í einrúmi", "notification.reblog": "{name} endurbirti færsluna þína", "notification.relationships_severance_event": "Missti tengingar við {name}", "notification.relationships_severance_event.account_suspension": "Stjórnandi á {from} hefur fryst {target}, sem þýðir að þú færð ekki lengur skilaboð frá viðkomandi né átt í samskiptum við viðkomandi.", @@ -503,6 +510,8 @@ "notifications.column_settings.admin.report": "Nýjar kærur:", "notifications.column_settings.admin.sign_up": "Nýjar skráningar:", "notifications.column_settings.alert": "Tilkynningar á skjáborði", + "notifications.column_settings.beta.category": "Eiginleikar á tilraunastigi", + "notifications.column_settings.beta.grouping": "Tilkynningar hópa", "notifications.column_settings.favourite": "Eftirlæti:", "notifications.column_settings.filter_bar.advanced": "Birta alla flokka", "notifications.column_settings.filter_bar.category": "Skyndisíustika", @@ -666,9 +675,13 @@ "report.unfollow_explanation": "Þú ert að fylgjast með þessum aðgangi. Til að hætta að sjá viðkomandi færslur á streyminu þínu, skaltu hætta að fylgjast með viðkomandi.", "report_notification.attached_statuses": "{count, plural, one {{count} færsla} other {{count} færslur}} viðhengdar", "report_notification.categories.legal": "Löglegt", + "report_notification.categories.legal_sentence": "ólöglegt efni", "report_notification.categories.other": "Annað", + "report_notification.categories.other_sentence": "annað", "report_notification.categories.spam": "Ruslpóstur", + "report_notification.categories.spam_sentence": "ruslpóstur", "report_notification.categories.violation": "Brot á reglum", + "report_notification.categories.violation_sentence": "brot á reglum", "report_notification.open": "Opin kæra", "search.no_recent_searches": "Engar nýlegar leitir", "search.placeholder": "Leita", diff --git a/app/javascript/mastodon/locales/it.json b/app/javascript/mastodon/locales/it.json index 73c4f9ba60827b..419b6bcd9f2312 100644 --- a/app/javascript/mastodon/locales/it.json +++ b/app/javascript/mastodon/locales/it.json @@ -443,6 +443,8 @@ "mute_modal.title": "Silenziare l'utente?", "mute_modal.you_wont_see_mentions": "Non vedrai i post che li menzionano.", "mute_modal.you_wont_see_posts": "Possono ancora vedere i tuoi post, ma tu non vedrai i loro.", + "name_and_others": "{name} e {count, plural, one {# un altro} other {# altri}}", + "name_and_others_with_link": "{name} e {count, plural, one {# un altro} other {# altri}}", "navigation_bar.about": "Info", "navigation_bar.advanced_interface": "Apri nell'interfaccia web avanzata", "navigation_bar.blocks": "Utenti bloccati", @@ -470,6 +472,10 @@ "navigation_bar.security": "Sicurezza", "not_signed_in_indicator.not_signed_in": "Devi accedere per consultare questa risorsa.", "notification.admin.report": "{name} ha segnalato {target}", + "notification.admin.report_account": "{name} ha segnalato {count, plural, one {un post} other {# post}} da {target} per {category}", + "notification.admin.report_account_other": "{name} ha segnalato {count, plural, one {un post} other {# post}} da {target}", + "notification.admin.report_statuses": "{name} ha segnalato {target} per {category}", + "notification.admin.report_statuses_other": "{name} ha segnalato {target}", "notification.admin.sign_up": "{name} si è iscritto", "notification.favourite": "{name} ha aggiunto il tuo post ai preferiti", "notification.follow": "{name} ha iniziato a seguirti", @@ -486,6 +492,7 @@ "notification.moderation_warning.action_suspend": "Il tuo account è stato sospeso.", "notification.own_poll": "Il tuo sondaggio è terminato", "notification.poll": "Un sondaggio in cui hai votato è terminato", + "notification.private_mention": "{name} ti ha citato privatamente", "notification.reblog": "{name} ha rebloggato il tuo post", "notification.relationships_severance_event": "Connessioni perse con {name}", "notification.relationships_severance_event.account_suspension": "Un amministratore da {from} ha sospeso {target}, il che significa che non puoi più ricevere aggiornamenti da loro o interagire con loro.", @@ -503,6 +510,8 @@ "notifications.column_settings.admin.report": "Nuove segnalazioni:", "notifications.column_settings.admin.sign_up": "Nuove iscrizioni:", "notifications.column_settings.alert": "Notifiche desktop", + "notifications.column_settings.beta.category": "Funzioni sperimentali", + "notifications.column_settings.beta.grouping": "Notifiche di gruppo", "notifications.column_settings.favourite": "Preferiti:", "notifications.column_settings.filter_bar.advanced": "Mostra tutte le categorie", "notifications.column_settings.filter_bar.category": "Barra del filtro veloce", @@ -666,9 +675,13 @@ "report.unfollow_explanation": "Segui questo profilo. Per non visualizzare più i suoi post nel feed della tua home, smetti di seguirlo.", "report_notification.attached_statuses": "{count, plural, one {{count} post allegato} other {{count} post allegati}}", "report_notification.categories.legal": "Legale", + "report_notification.categories.legal_sentence": "contenuti illegali", "report_notification.categories.other": "Altro", + "report_notification.categories.other_sentence": "altri", "report_notification.categories.spam": "Spam", + "report_notification.categories.spam_sentence": "spam", "report_notification.categories.violation": "Violazione delle regole", + "report_notification.categories.violation_sentence": "violazione delle regole", "report_notification.open": "Apri segnalazione", "search.no_recent_searches": "Nessuna ricerca recente", "search.placeholder": "Cerca", diff --git a/app/javascript/mastodon/locales/ja.json b/app/javascript/mastodon/locales/ja.json index 794360fc64a1c0..f10b1be0ad8582 100644 --- a/app/javascript/mastodon/locales/ja.json +++ b/app/javascript/mastodon/locales/ja.json @@ -590,7 +590,6 @@ "notification.moderation_warning.action_silence": "あなたのアカウントは制限されています。", "notification.moderation_warning.action_suspend": "あなたのアカウントは停止されました。", "notification.own_poll": "アンケートが終了しました", - "notification.poll": "アンケートが終了しました", "notification.reblog": "{name}さんがあなたの投稿をブーストしました", "notification.relationships_severance_event": "{name} との関係が失われました", "notification.relationships_severance_event.account_suspension": "{from} の管理者が {target} さんを停止したため、今後このユーザーとの交流や新しい投稿の受け取りができなくなりました。", @@ -609,6 +608,8 @@ "notifications.column_settings.admin.report": "新しい通報:", "notifications.column_settings.admin.sign_up": "新規登録:", "notifications.column_settings.alert": "デスクトップ通知", + "notifications.column_settings.beta.category": "実験段階の機能", + "notifications.column_settings.beta.grouping": "通知をグループにまとめる", "notifications.column_settings.emoji_reaction": "絵文字リアクション", "notifications.column_settings.favourite": "お気に入り:", "notifications.column_settings.filter_bar.advanced": "すべてのカテゴリを表示", diff --git a/app/javascript/mastodon/locales/kab.json b/app/javascript/mastodon/locales/kab.json index 868edbc8c0fe4c..776b3446a2e4c2 100644 --- a/app/javascript/mastodon/locales/kab.json +++ b/app/javascript/mastodon/locales/kab.json @@ -20,15 +20,15 @@ "account.cancel_follow_request": "Sefsex taḍfart", "account.copy": "Nɣel assaɣ ɣer umaɣnu", "account.direct": "Bder-d @{name} weḥd-s", - "account.disable_notifications": "Ḥbes ur iyi-d-ttazen ara ilɣa mi ara d-isuffeɣ @{name}", + "account.disable_notifications": "Ḥbes ur iyi-d-ttazen ara alɣuten mi ara d-isuffeɣ @{name}", "account.domain_blocked": "Taɣult yeffren", "account.edit_profile": "Ẓreg amaɣnu", - "account.enable_notifications": "Azen-iyi-d ilɣa mi ara d-isuffeɣ @{name}", + "account.enable_notifications": "Azen-iyi-d alɣuten mi ara d-isuffeɣ @{name}", "account.endorse": "Welleh fell-as deg umaɣnu-inek", "account.featured_tags.last_status_at": "Tasuffeɣt taneggarut ass n {date}", "account.featured_tags.last_status_never": "Ulac tisuffaɣ", "account.follow": "Ḍfer", - "account.follow_back": "Ḍfer-it ula d kečč·m", + "account.follow_back": "Ḍfer-it ula d kečč·mm", "account.followers": "Imeḍfaren", "account.followers.empty": "Ar tura, ulac yiwen i yeṭṭafaṛen amseqdac-agi.", "account.followers_counter": "{count, plural, one {{counter} n umḍfar} other {{counter} n yimeḍfaren}}", @@ -38,13 +38,14 @@ "account.go_to_profile": "Ddu ɣer umaɣnu", "account.hide_reblogs": "Ffer ayen i ibeṭṭu @{name}", "account.joined_short": "Izeddi da seg ass n", + "account.languages": "Beddel tutlayin yettwajerden", "account.link_verified_on": "Taɣara n useɣwen-a tettwasenqed ass n {date}", "account.locked_info": "Amiḍan-agi uslig isekweṛ. D bab-is kan i izemren ad yeǧǧ, s ufus-is, win ara t-iḍefṛen.", "account.media": "Timidyatin", "account.mention": "Bder-d @{name}", "account.moved_to": "{name} yenna-d dakken amiḍan-is amaynut yuɣal :", "account.mute": "Sgugem @{name}", - "account.mute_notifications_short": "Susem ilɣa", + "account.mute_notifications_short": "Susem alɣuten", "account.mute_short": "Sgugem", "account.muted": "Yettwasgugem", "account.no_bio": "Ulac aglam i d-yettunefken.", @@ -102,7 +103,7 @@ "column.home": "Agejdan", "column.lists": "Tibdarin", "column.mutes": "Imiḍanen yettwasgugmen", - "column.notifications": "Tilɣa", + "column.notifications": "Alɣuten", "column.pins": "Tisuffaɣ yettwasenṭḍen", "column.public": "Tasuddemt tamatut", "column_back_button.label": "Tuɣalin", @@ -209,7 +210,7 @@ "empty_column.list": "Ar tura ur yelli kra deg umuɣ-a. Ad d-yettwasken da ticki iɛeggalen n wumuɣ-a suffɣen-d kra.", "empty_column.lists": "Ulac ɣur-k·m kra n wumuɣ yakan. Ad d-tettwasken da ticki tesluleḍ-d yiwet.", "empty_column.mutes": "Ulac ɣur-k·m imseqdacen i yettwasgugmen.", - "empty_column.notifications": "Ulac ɣur-k·m tilɣa. Sedmer akked yemdanen-nniḍen akken ad tebduḍ adiwenni.", + "empty_column.notifications": "Ulac ɣur-k·m alɣuten. Sedmer akked yemdanen-nniḍen akken ad tebduḍ adiwenni.", "empty_column.public": "Ulac kra da! Aru kra, neɣ ḍfeṛ imdanen i yellan deg yiqeddacen-nniḍen akken ad d-teččar tsuddemt tazayezt", "error.unexpected_crash.next_steps": "Smiren asebter-a, ma ur yekkis ara wugur, ẓer d akken tzemreḍ ad tesqedceḍ Maṣṭudun deg yiminig-nniḍen neɣ deg usnas anaṣli.", "errors.unexpected_crash.copy_stacktrace": "Nɣel stacktrace ɣef wafus", @@ -235,6 +236,7 @@ "follow_request.authorize": "Ssireg", "follow_request.reject": "Agi", "follow_suggestions.dismiss": "Dayen ur t-id-skan ara", + "follow_suggestions.popular_suggestion_longer": "Yettwassen deg {domain}", "follow_suggestions.view_all": "Wali-ten akk", "follow_suggestions.who_to_follow": "Ad tḍefreḍ?", "followed_tags": "Ihacṭagen yettwaḍfaren", @@ -245,7 +247,7 @@ "footer.keyboard_shortcuts": "Inegzumen n unasiw", "footer.privacy_policy": "Tasertit tabaḍnit", "footer.source_code": "Wali tangalt taɣbalut", - "footer.status": "N tsuffeɣt", + "footer.status": "Addad", "generic.saved": "Yettwasekles", "getting_started.heading": "Bdu", "hashtag.column_header.tag_mode.all": "d {additional}", @@ -303,7 +305,7 @@ "keyboard_shortcuts.mention": "akken ad d-bedreḍ ameskar", "keyboard_shortcuts.muted": "akken ad teldiḍ tabdart n yimseqdacen yettwasgugmen", "keyboard_shortcuts.my_profile": "akken ad d-teldiḍ amaɣnu-ik", - "keyboard_shortcuts.notifications": "akken ad d-teldiḍ ajgu n tilɣa", + "keyboard_shortcuts.notifications": "akken ad d-teldiḍ ajgu n walɣuten", "keyboard_shortcuts.open_media": "i tiɣwalin yeldin", "keyboard_shortcuts.pinned": "akken ad teldiḍ tabdart n tjewwiqin yettwasentḍen", "keyboard_shortcuts.profile": "akken ad d-teldiḍ amaɣnu n umeskar", @@ -325,7 +327,7 @@ "limited_account_hint.action": "Wali amaɣnu akken yebɣu yili", "link_preview.author": "S-ɣur {name}", "link_preview.more_from_author": "Ugar sɣur {name}", - "link_preview.shares": "{count, plural, one {{counter} post} other {{counter} posts}}", + "link_preview.shares": "{count, plural, one {{counter} n tsuffeɣt} other {{counter} n tsuffaɣ}}", "lists.account.add": "Rnu ɣer tebdart", "lists.account.remove": "Kkes seg tebdart", "lists.delete": "Kkes tabdart", @@ -381,17 +383,17 @@ "notification.moderation-warning.learn_more": "Issin ugar", "notification.moderation_warning.action_suspend": "Yettwaseḥbes umiḍan-ik.", "notification.own_poll": "Tafrant-ik·im tfuk", - "notification.poll": "Tfukk tefrant ideg tettekkaḍ", "notification.reblog": "{name} yebḍa tajewwiqt-ik i tikelt-nniḍen", "notification.relationships_severance_event.learn_more": "Issin ugar", "notification.status": "{name} akken i d-yessufeɣ", "notification_requests.accept": "Qbel", "notification_requests.dismiss": "Agi", - "notification_requests.notifications_from": "Ilɣa sɣur {name}", - "notifications.clear": "Sfeḍ tilɣa", - "notifications.clear_confirmation": "Tebɣiḍ s tidet ad tekkseḍ akk tilɣa-inek·em i lebda?", + "notification_requests.notifications_from": "Alɣuten sɣur {name}", + "notifications.clear": "Sfeḍ alɣuten", + "notifications.clear_confirmation": "Tebɣiḍ s tidet ad tekkseḍ akk alɣuten-inek·em i lebda?", "notifications.column_settings.admin.report": "Ineqqisen imaynuten:", - "notifications.column_settings.alert": "Tilɣa n tnarit", + "notifications.column_settings.alert": "Alɣuten n tnarit", + "notifications.column_settings.beta.grouping": "Segrew alɣuten", "notifications.column_settings.favourite": "Imenyafen:", "notifications.column_settings.filter_bar.advanced": "Sken-d akk taggayin", "notifications.column_settings.filter_bar.category": "Iri n usizdeg uzrib", @@ -399,12 +401,12 @@ "notifications.column_settings.follow_request": "Isuturen imaynuten n teḍfeṛt:", "notifications.column_settings.mention": "Abdar:", "notifications.column_settings.poll": "Igemmaḍ n usenqed:", - "notifications.column_settings.push": "Tilɣa yettudemmren", + "notifications.column_settings.push": "Alɣuten yettudemmren", "notifications.column_settings.reblog": "Seǧhed:", "notifications.column_settings.show": "Ssken-d tilɣa deg ujgu", "notifications.column_settings.sound": "Rmed imesli", "notifications.column_settings.status": "Tisuffaɣ timaynutin :", - "notifications.column_settings.unread_notifications.category": "Ilɣa ur nettwaɣra", + "notifications.column_settings.unread_notifications.category": "Alɣuten ur nettwaɣra", "notifications.column_settings.update": "Iẓreg:", "notifications.filter.all": "Akk", "notifications.filter.boosts": "Seǧhed", @@ -414,9 +416,9 @@ "notifications.filter.polls": "Igemmaḍ n usenqed", "notifications.filter.statuses": "Ileqman n yimdanen i teṭṭafareḍ", "notifications.grant_permission": "Mudd tasiregt.", - "notifications.group": "{count} n tilɣa", - "notifications.mark_as_read": "Creḍ meṛṛa iilɣa am wakken ttwaɣran", - "notifications.permission_denied": "D awezɣi ad yili wermad n yilɣa n tnarit axateṛ turagt tettwagdel.", + "notifications.group": "{count} n walɣuten", + "notifications.mark_as_read": "Creḍ meṛṛa alɣuten am wakken ttwaɣran", + "notifications.permission_denied": "D awezɣi ad yili wermad n walɣuten n tnarit axateṛ turagt tettwagdel", "notifications.policy.filter_new_accounts.hint": "Imiḍanen imaynuten i d-yennulfan deg {days, plural, one {yiwen n wass} other {# n wussan}} yezrin", "notifications.policy.filter_new_accounts_title": "Imiḍan imaynuten", "notifications.policy.filter_not_followers_hint": "Ula d wid akked tid i k·m-id-iḍefren, ur wwiḍen ara {days, plural, one {yiwen n wass} other {# n wussan}}", @@ -424,8 +426,8 @@ "notifications.policy.filter_not_following_hint": "Alamma tqebleḍ-ten s ufus", "notifications.policy.filter_not_following_title": "Wid akked tid ur tettḍafareḍ ara", "notifications.policy.filter_private_mentions_title": "Abdar uslig ur yettwasferken ara", - "notifications.policy.title": "Sizdeg ilɣa sɣur …", - "notifications_permission_banner.enable": "Rmed talɣutin n tnarit", + "notifications.policy.title": "Sizdeg alɣuten sɣur …", + "notifications_permission_banner.enable": "Rmed alɣuten n tnarit", "notifications_permission_banner.title": "Ur zeggel acemma", "onboarding.action.back": "Tuɣalin ɣer deffir", "onboarding.actions.back": "Tuɣalin ɣer deffir", @@ -520,7 +522,7 @@ "report.thanks.title": "Ur tebɣiḍ ara ad twaliḍ aya?", "report.thanks.title_actionable": "Tanemmirt ɣef uneqqis, ad nwali deg waya.", "report.unfollow": "Seḥbes aḍfar n @{name}", - "report_notification.attached_statuses": "{count, plural, one {# post} other {# posts}} attached", + "report_notification.attached_statuses": "{count, plural, one {{count} n tsuffeɣt} other {{count} n tsuffiɣin}} ttwaqnent", "report_notification.categories.legal": "Azerfan", "report_notification.categories.other": "Ayen nniḍen", "report_notification.categories.spam": "Aspam", @@ -580,7 +582,7 @@ "status.mute_conversation": "Sgugem adiwenni", "status.open": "Semɣeṛ tasuffeɣt-ayi", "status.pin": "Senteḍ-itt deg umaɣnu", - "status.pinned": "Tijewwiqin yettwasentḍen", + "status.pinned": "Tisuffaɣ yettwasentḍen", "status.read_more": "Issin ugar", "status.reblog": "Bḍu", "status.reblogged_by": "Yebḍa-tt {name}", @@ -607,7 +609,7 @@ "status.unpin": "Kkes asenteḍ seg umaɣnu", "subscribed_languages.save": "Sekles ibeddilen", "tabs_bar.home": "Agejdan", - "tabs_bar.notifications": "Tilɣa", + "tabs_bar.notifications": "Alɣuten", "time_remaining.days": "Mazal {number, plural, one {# n wass} other {# n wussan}}", "time_remaining.hours": "Mazal {number, plural, one {# n usrag} other {# n yesragen}}", "time_remaining.minutes": "Mazal {number, plural, one {# n tesdat} other {# n tesdatin}}", diff --git a/app/javascript/mastodon/locales/kk.json b/app/javascript/mastodon/locales/kk.json index efeee16c6514a7..74fb33a91ab42f 100644 --- a/app/javascript/mastodon/locales/kk.json +++ b/app/javascript/mastodon/locales/kk.json @@ -248,7 +248,6 @@ "notification.follow_request": "{name} сізге жазылғысы келеді", "notification.mention": "{name} сізді атап өтті", "notification.own_poll": "Сауалнама аяқталды", - "notification.poll": "Бұл сауалнаманың мерзімі аяқталыпты", "notification.reblog": "{name} жазбаңызды бөлісті", "notifications.clear": "Ескертпелерді тазарт", "notifications.clear_confirmation": "Шынымен барлық ескертпелерді өшіресіз бе?", diff --git a/app/javascript/mastodon/locales/ko.json b/app/javascript/mastodon/locales/ko.json index fe3582c1d89ac7..6619cdb2d6014a 100644 --- a/app/javascript/mastodon/locales/ko.json +++ b/app/javascript/mastodon/locales/ko.json @@ -485,7 +485,6 @@ "notification.moderation_warning.action_silence": "계정이 제한되었습니다.", "notification.moderation_warning.action_suspend": "계정이 정지되었습니다.", "notification.own_poll": "설문을 마침", - "notification.poll": "참여한 설문이 종료됨", "notification.reblog": "{name} 님이 부스트했습니다", "notification.relationships_severance_event": "{name} 님과의 연결이 끊어졌습니다", "notification.relationships_severance_event.account_suspension": "{from}의 관리자가 {target}를 정지시켰기 때문에 그들과 더이상 상호작용 할 수 없고 정보를 받아볼 수 없습니다.", diff --git a/app/javascript/mastodon/locales/ku.json b/app/javascript/mastodon/locales/ku.json index 5248cdfa51b772..3821216a9a9d35 100644 --- a/app/javascript/mastodon/locales/ku.json +++ b/app/javascript/mastodon/locales/ku.json @@ -349,7 +349,6 @@ "notification.follow_request": "{name} dixwazê te bişopîne", "notification.mention": "{name} qale te kir", "notification.own_poll": "Rapirsîya te qediya", - "notification.poll": "Rapirsiyeke ku te deng daye qediya", "notification.reblog": "{name} şandiya te bilind kir", "notification.status": "{name} niha şand", "notification.update": "{name} şandiyek serrast kir", diff --git a/app/javascript/mastodon/locales/kw.json b/app/javascript/mastodon/locales/kw.json index 1afcf645cf8914..f59f342cbe051a 100644 --- a/app/javascript/mastodon/locales/kw.json +++ b/app/javascript/mastodon/locales/kw.json @@ -239,7 +239,6 @@ "notification.follow_request": "{name} a bysis agas holya", "notification.mention": "{name} a wrug agas meneges", "notification.own_poll": "Agas sondyans a worfennas", - "notification.poll": "An sondyans may hwrussowgh ragleva a worfennas", "notification.reblog": "{name} a generthas agas post", "notification.status": "{name} a wrug nowydh postya", "notifications.clear": "Dilea gwarnyansow", diff --git a/app/javascript/mastodon/locales/la.json b/app/javascript/mastodon/locales/la.json index aa209fcc00db3d..e35e7112bea950 100644 --- a/app/javascript/mastodon/locales/la.json +++ b/app/javascript/mastodon/locales/la.json @@ -150,7 +150,6 @@ "notification.moderation_warning.action_silence": "Ratio tua est limitata.", "notification.moderation_warning.action_suspend": "Ratio tua suspensus est.", "notification.own_poll": "Suffragium tuum terminatum est.", - "notification.poll": "Electione in quam suffragium dedisti finita est.", "notification.reblog": "{name} tuum nuntium amplificavit.", "notification.relationships_severance_event.account_suspension": "Admin ab {from} {target} suspendit, quod significat nōn iam posse tē novitātēs ab eīs accipere aut cum eīs interagere.", "notification.relationships_severance_event.domain_block": "Admin ab {from} {target} obsēcāvit, includēns {followersCount} ex tuīs sectātōribus et {followingCount, plural, one {# ratione} other {# rationibus}} quās sequeris.", diff --git a/app/javascript/mastodon/locales/lad.json b/app/javascript/mastodon/locales/lad.json index 292f00818c16c4..2dc360f9eda102 100644 --- a/app/javascript/mastodon/locales/lad.json +++ b/app/javascript/mastodon/locales/lad.json @@ -300,6 +300,7 @@ "follow_suggestions.hints.similar_to_recently_followed": "Este profil es similar a otros ke tienes segido resientemente.", "follow_suggestions.personalized_suggestion": "Sujestion personalizada", "follow_suggestions.popular_suggestion": "Sujestion populara", + "follow_suggestions.popular_suggestion_longer": "Popular en {domain}", "follow_suggestions.view_all": "Ve todos", "follow_suggestions.who_to_follow": "A ken segir", "followed_tags": "Etiketas segidas", @@ -396,6 +397,7 @@ "limited_account_hint.title": "Este profil fue eskondido por los moderadores de {domain}.", "link_preview.author": "Publikasyon de {name}", "link_preview.more_from_author": "Mas de {name}", + "link_preview.shares": "{count, plural, one {{counter} publikasyon} other {{counter} publikasyones}}", "lists.account.add": "Adjusta a lista", "lists.account.remove": "Kita de lista", "lists.delete": "Efasa lista", @@ -448,12 +450,16 @@ "navigation_bar.security": "Segurita", "not_signed_in_indicator.not_signed_in": "Nesesitas konektarse kon tu kuento para akseder este rekurso.", "notification.admin.report": "{name} raporto {target}", + "notification.admin.report_statuses_other": "{name} raporto {target}", "notification.admin.sign_up": "{name} kriyo un konto", "notification.favourite": "A {name} le plaze tu publikasyon", "notification.follow": "{name} te ampeso a segir", "notification.follow_request": "{name} tiene solisitado segirte", "notification.mention": "{name} te enmento", "notification.moderation-warning.learn_more": "Ambezate mas", + "notification.moderation_warning.action_disable": "Tu kuento tiene sido inkapasitado.", + "notification.moderation_warning.action_mark_statuses_as_sensitive": "Algunas de tus publikasyones tienen sido markadas komo sensivles.", + "notification.moderation_warning.action_sensitive": "Tus publikasyones seran markadas komo sensivles dizde agora.", "notification.moderation_warning.action_silence": "Tu kuento tiene sido limitado.", "notification.moderation_warning.action_suspend": "Tu kuento tiene sido suspendido.", "notification.own_poll": "Tu anketa eskapo", @@ -634,8 +640,11 @@ "report_notification.attached_statuses": "{count, plural, one {{count} publikasyon} other {{count} publikasyones}} atadas", "report_notification.categories.legal": "Legal", "report_notification.categories.other": "Otros", + "report_notification.categories.other_sentence": "otros", "report_notification.categories.spam": "Spam", + "report_notification.categories.spam_sentence": "spam", "report_notification.categories.violation": "Violasyon de reglas", + "report_notification.categories.violation_sentence": "violasyon de reglas", "report_notification.open": "Avre raporto", "search.no_recent_searches": "No ay bushkedas resientes", "search.placeholder": "Bushka", diff --git a/app/javascript/mastodon/locales/lt.json b/app/javascript/mastodon/locales/lt.json index bb69b733997bd1..f8a2995c57aafc 100644 --- a/app/javascript/mastodon/locales/lt.json +++ b/app/javascript/mastodon/locales/lt.json @@ -1,6 +1,6 @@ { "about.blocks": "Prižiūrimi serveriai", - "about.contact": "Kontaktai:", + "about.contact": "Kontaktuoti:", "about.disclaimer": "„Mastodon“ – tai nemokama atvirojo kodo programinė įranga ir „Mastodon“ gGmbH prekės ženklas.", "about.domain_blocks.no_reason_available": "Priežastis nepateikta", "about.domain_blocks.preamble": "„Mastodon“ paprastai leidžia peržiūrėti turinį ir bendrauti su naudotojais iš bet kurio kito fediverse esančio serverio. Šios yra išimtys, kurios buvo padarytos šiame konkrečiame serveryje.", @@ -230,7 +230,7 @@ "domain_pill.your_handle": "Tavo socialinis medijos vardas:", "domain_pill.your_server": "Tavo skaitmeniniai namai, kuriuose saugomi visi tavo įrašai. Nepatinka šis? Bet kada perkelk serverius ir atsivesk ir savo sekėjus.", "domain_pill.your_username": "Tavo unikalus identifikatorius šiame serveryje. Skirtinguose serveriuose galima rasti naudotojų su tuo pačiu naudotojo vardu.", - "embed.instructions": "Įterpk šį įrašą į savo svetainę nukopijavus (-usi) toliau pateiktą kodą.", + "embed.instructions": "Įterpk šį įrašą į savo svetainę nukopijuojant toliau pateiktą kodą.", "embed.preview": "Štai kaip tai atrodys:", "emoji_button.activity": "Veikla", "emoji_button.clear": "Išvalyti", @@ -485,7 +485,6 @@ "notification.moderation_warning.action_silence": "Tavo paskyra buvo apribota.", "notification.moderation_warning.action_suspend": "Tavo paskyra buvo sustabdyta.", "notification.own_poll": "Tavo apklausa baigėsi", - "notification.poll": "Apklausa, kurioje balsavai, pasibaigė", "notification.reblog": "{name} pakėlė tavo įrašą", "notification.relationships_severance_event": "Prarasti sąryšiai su {name}", "notification.relationships_severance_event.learn_more": "Sužinoti daugiau", diff --git a/app/javascript/mastodon/locales/lv.json b/app/javascript/mastodon/locales/lv.json index 701569fa05ce1c..d4623a8b31a344 100644 --- a/app/javascript/mastodon/locales/lv.json +++ b/app/javascript/mastodon/locales/lv.json @@ -440,7 +440,6 @@ "notification.moderation_warning.action_silence": "Tavs konts tika ierobežots.", "notification.moderation_warning.action_suspend": "Tava konta darbība tika apturēta.", "notification.own_poll": "Tava aptauja ir noslēgusies", - "notification.poll": "Aptauja, kurā tu piedalījies, ir noslēgusies", "notification.reblog": "{name} pastiprināja Tavu ierakstu", "notification.relationships_severance_event": "Zaudēti savienojumi ar {name}", "notification.relationships_severance_event.learn_more": "Uzzināt vairāk", diff --git a/app/javascript/mastodon/locales/ms.json b/app/javascript/mastodon/locales/ms.json index 88c093bdee2ab1..dc34867106d497 100644 --- a/app/javascript/mastodon/locales/ms.json +++ b/app/javascript/mastodon/locales/ms.json @@ -421,7 +421,6 @@ "notification.follow_request": "{name} meminta untuk mengikuti anda", "notification.mention": "{name} menyebut anda", "notification.own_poll": "Undian anda telah tamat", - "notification.poll": "Sebuah undian yang anda undi telah tamat", "notification.reblog": "{name} menggalak hantaran anda", "notification.status": "{name} baru sahaja mengirim hantaran", "notification.update": "{name} menyunting hantaran", diff --git a/app/javascript/mastodon/locales/my.json b/app/javascript/mastodon/locales/my.json index 46c8d180690c59..cb3ea9723bd5be 100644 --- a/app/javascript/mastodon/locales/my.json +++ b/app/javascript/mastodon/locales/my.json @@ -402,7 +402,6 @@ "notification.follow_request": "{name} က သင့်ကို စောင့်ကြည့်ရန် တောင်းဆိုထားသည်", "notification.mention": "{name} က သင့်ကို ဖော်ပြခဲ့သည်", "notification.own_poll": "စစ်တမ်းကောက်မှု ပြီးဆုံးပါပြီ", - "notification.poll": "သင်ပါဝင်ခဲ့သော စစ်တမ်းပြီးပါပြီ", "notification.reblog": "{name} boosted your status", "notification.status": "{name} က အခုလေးတင် ပို့စ်တင်လိုက်ပါပြီ", "notification.update": "{name} က ပို့စ်တစ်ခုကို ပြင်ဆင်ခဲ့သည်", diff --git a/app/javascript/mastodon/locales/nl.json b/app/javascript/mastodon/locales/nl.json index 8246d8dfd2d0fe..027c09280c85a2 100644 --- a/app/javascript/mastodon/locales/nl.json +++ b/app/javascript/mastodon/locales/nl.json @@ -443,6 +443,8 @@ "mute_modal.title": "Gebruiker negeren?", "mute_modal.you_wont_see_mentions": "Je ziet geen berichten meer die dit account vermelden.", "mute_modal.you_wont_see_posts": "De persoon kan nog steeds jouw berichten zien, maar diens berichten zie je niet meer.", + "name_and_others": "{name} en {count, plural, one {# ander} other {# anderen}}", + "name_and_others_with_link": "{name} en {count, plural, one {# ander} other {# anderen}}", "navigation_bar.about": "Over", "navigation_bar.advanced_interface": "In geavanceerde webinterface openen", "navigation_bar.blocks": "Geblokkeerde gebruikers", @@ -470,6 +472,10 @@ "navigation_bar.security": "Beveiliging", "not_signed_in_indicator.not_signed_in": "Je moet inloggen om toegang tot deze informatie te krijgen.", "notification.admin.report": "{name} heeft {target} geapporteerd", + "notification.admin.report_account": "{name} rapporteerde {count, plural, one {een bericht} other {# berichten}} van {target} voor {category}", + "notification.admin.report_account_other": "{name} rapporteerde {count, plural, one {een bericht} other {# berichten}} van {target}", + "notification.admin.report_statuses": "{name} rapporteerde {target} voor {category}", + "notification.admin.report_statuses_other": "{name} rapporteerde {target}", "notification.admin.sign_up": "{name} heeft zich geregistreerd", "notification.favourite": "{name} markeerde jouw bericht als favoriet", "notification.follow": "{name} volgt jou nu", @@ -486,6 +492,7 @@ "notification.moderation_warning.action_suspend": "Jouw account is opgeschort.", "notification.own_poll": "Jouw peiling is beëindigd", "notification.poll": "Een peiling waaraan jij hebt meegedaan is beëindigd", + "notification.private_mention": "{name} heeft je een privébericht gestuurd", "notification.reblog": "{name} boostte jouw bericht", "notification.relationships_severance_event": "Verloren verbindingen met {name}", "notification.relationships_severance_event.account_suspension": "Een beheerder van {from} heeft {target} geschorst, wat betekent dat je geen updates meer van hen kunt ontvangen of met hen kunt communiceren.", @@ -503,6 +510,8 @@ "notifications.column_settings.admin.report": "Nieuwe rapportages:", "notifications.column_settings.admin.sign_up": "Nieuwe registraties:", "notifications.column_settings.alert": "Desktopmeldingen", + "notifications.column_settings.beta.category": "Experimentele functies", + "notifications.column_settings.beta.grouping": "Gegroepeerde meldingen", "notifications.column_settings.favourite": "Favorieten:", "notifications.column_settings.filter_bar.advanced": "Alle categorieën tonen", "notifications.column_settings.filter_bar.category": "Snelle filterbalk", @@ -666,9 +675,13 @@ "report.unfollow_explanation": "Je volgt dit account. Om diens berichten niet meer op jouw starttijdlijn te zien, kun je diegene ontvolgen.", "report_notification.attached_statuses": "{count, plural, one {{count} bericht} other {{count} berichten}} toegevoegd", "report_notification.categories.legal": "Juridisch", + "report_notification.categories.legal_sentence": "illegale inhoud", "report_notification.categories.other": "Overig", + "report_notification.categories.other_sentence": "overig", "report_notification.categories.spam": "Spam", + "report_notification.categories.spam_sentence": "spam", "report_notification.categories.violation": "Overtreden regel(s)", + "report_notification.categories.violation_sentence": "serverregel overtreden", "report_notification.open": "Rapportage openen", "search.no_recent_searches": "Geen recente zoekopdrachten", "search.placeholder": "Zoeken", diff --git a/app/javascript/mastodon/locales/nn.json b/app/javascript/mastodon/locales/nn.json index 0fb0edf0a04b15..f5efedb1aeefe0 100644 --- a/app/javascript/mastodon/locales/nn.json +++ b/app/javascript/mastodon/locales/nn.json @@ -485,7 +485,6 @@ "notification.moderation_warning.action_silence": "Kontoen din har blitt avgrensa.", "notification.moderation_warning.action_suspend": "Kontoen din har blitt suspendert.", "notification.own_poll": "Rundspørjinga di er ferdig", - "notification.poll": "Ei rundspørjing du har røysta i er ferdig", "notification.reblog": "{name} framheva innlegget ditt", "notification.relationships_severance_event": "Tapte samband med {name}", "notification.relationships_severance_event.account_suspension": "Ein administrator på {from} har utvist {target}, som tyder at du ikkje lenger får oppdateringar frå dei eller kan samhandla med dei.", diff --git a/app/javascript/mastodon/locales/no.json b/app/javascript/mastodon/locales/no.json index 2bda3734044d33..f2476bf14cde9d 100644 --- a/app/javascript/mastodon/locales/no.json +++ b/app/javascript/mastodon/locales/no.json @@ -414,7 +414,6 @@ "notification.follow_request": "{name} har bedt om å få følge deg", "notification.mention": "{name} nevnte deg", "notification.own_poll": "Avstemningen din er ferdig", - "notification.poll": "En avstemning du stemte på har avsluttet", "notification.reblog": "{name} fremhevet ditt innlegg", "notification.status": "{name} la nettopp ut", "notification.update": "{name} redigerte et innlegg", diff --git a/app/javascript/mastodon/locales/oc.json b/app/javascript/mastodon/locales/oc.json index d977eed4af63a2..c02c821afcec06 100644 --- a/app/javascript/mastodon/locales/oc.json +++ b/app/javascript/mastodon/locales/oc.json @@ -357,7 +357,6 @@ "notification.follow_request": "{name} a demandat a vos sègre", "notification.mention": "{name} vos a mencionat", "notification.own_poll": "Vòstre sondatge es acabat", - "notification.poll": "Avètz participat a un sondatge que ven de s’acabar", "notification.reblog": "{name} a partejat vòstre estatut", "notification.status": "{name} ven de publicar", "notification.update": "{name} modiquè sa publicacion", diff --git a/app/javascript/mastodon/locales/pl.json b/app/javascript/mastodon/locales/pl.json index ddfe1d4fbcd804..75987f5d29c67f 100644 --- a/app/javascript/mastodon/locales/pl.json +++ b/app/javascript/mastodon/locales/pl.json @@ -443,6 +443,8 @@ "mute_modal.title": "Wyciszyć użytkownika?", "mute_modal.you_wont_see_mentions": "Nie zobaczysz wpisów, które wspominają tego użytkownika.", "mute_modal.you_wont_see_posts": "Użytkownik dalej będzie widzieć Twoje posty, ale Ty nie będziesz widzieć jego.", + "name_and_others": "{name} i {count, plural, one {# inny} few {# inne} many {# innych} other {# innych}}", + "name_and_others_with_link": "{name} i {count, plural, one {# inny} few {# inne} many {# innych} other {# innych}}", "navigation_bar.about": "O serwerze", "navigation_bar.advanced_interface": "Otwórz w zaawansowanym interfejsie użytkownika", "navigation_bar.blocks": "Zablokowani użytkownicy", @@ -470,6 +472,10 @@ "navigation_bar.security": "Bezpieczeństwo", "not_signed_in_indicator.not_signed_in": "Musisz się zalogować, aby uzyskać dostęp do tego zasobu.", "notification.admin.report": "{name} zgłosił {target}", + "notification.admin.report_account": "{name} zgłosił(a) {count, plural, one {1 wpis} few {# wpisy} other {# wpisów}} z {target} w kategorii {category}", + "notification.admin.report_account_other": "{name} zgłosił(a) {count, plural, one {1 wpis} few {# wpisy} other {# wpisów}} z {target}", + "notification.admin.report_statuses": "{name} zgłosił(a) {target} w kategorii {category}", + "notification.admin.report_statuses_other": "{name} zgłosił(a) {target}", "notification.admin.sign_up": "Użytkownik {name} zarejestrował się", "notification.favourite": "{name} dodaje Twój wpis do ulubionych", "notification.follow": "{name} obserwuje Cię", @@ -485,7 +491,8 @@ "notification.moderation_warning.action_silence": "Twoje konto zostało ograniczone.", "notification.moderation_warning.action_suspend": "Twoje konto zostało zawieszone.", "notification.own_poll": "Twoje głosowanie zakończyło się", - "notification.poll": "Głosowanie w którym brałeś(-aś) udział zakończyło się", + "notification.poll": "Głosowanie, w którym brałeś(-aś) udział, zostało zakończone", + "notification.private_mention": "{name} prywatnie o tobie wspomniał(a)", "notification.reblog": "Twój post został podbity przez {name}", "notification.relationships_severance_event": "Utracone związki z {name}", "notification.relationships_severance_event.account_suspension": "Administrator z {from} zawiesił {target}, więc nie dostaniesz wieści ani nie wejdziesz w interakcje z użytkownikami z tego serwera.", @@ -502,6 +509,8 @@ "notifications.column_settings.admin.report": "Nowe zgłoszenia:", "notifications.column_settings.admin.sign_up": "Nowe rejestracje:", "notifications.column_settings.alert": "Powiadomienia na pulpicie", + "notifications.column_settings.beta.category": "Funkcje eksperymentalne", + "notifications.column_settings.beta.grouping": "Powiadomienia grupowe", "notifications.column_settings.favourite": "Ulubione:", "notifications.column_settings.filter_bar.advanced": "Wyświetl wszystkie kategorie", "notifications.column_settings.filter_bar.category": "Szybkie filtrowanie", @@ -665,9 +674,13 @@ "report.unfollow_explanation": "Obserwujesz to konto. Jeśli nie chcesz już widzieć postów z tego konta w swojej głównej osi czasu, przestań je obserwować.", "report_notification.attached_statuses": "{count, plural, one {{count} wpis} few {{count} wpisy} many {{counter} wpisów} other {{counter} wpisów}}", "report_notification.categories.legal": "Prawne", + "report_notification.categories.legal_sentence": "treść nielegalna", "report_notification.categories.other": "Inne", + "report_notification.categories.other_sentence": "inne", "report_notification.categories.spam": "Spam", + "report_notification.categories.spam_sentence": "spam", "report_notification.categories.violation": "Naruszenie zasad", + "report_notification.categories.violation_sentence": "naruszenie zasad", "report_notification.open": "Otwórz zgłoszenie", "search.no_recent_searches": "Brak ostatnich wyszukiwań", "search.placeholder": "Szukaj", diff --git a/app/javascript/mastodon/locales/pt-BR.json b/app/javascript/mastodon/locales/pt-BR.json index 34d0ba36e6f817..9ebde4e6a48dfc 100644 --- a/app/javascript/mastodon/locales/pt-BR.json +++ b/app/javascript/mastodon/locales/pt-BR.json @@ -482,7 +482,6 @@ "notification.moderation_warning.action_silence": "Sua conta foi limitada.", "notification.moderation_warning.action_suspend": "Sua conta foi suspensa.", "notification.own_poll": "Sua enquete terminou", - "notification.poll": "Uma enquete que você votou terminou", "notification.reblog": "{name} deu boost no teu toot", "notification.relationships_severance_event": "Conexões perdidas com {name}", "notification.relationships_severance_event.account_suspension": "Um administrador de {from} suspendeu {target}, o que significa que você não pode mais receber atualizações deles ou interagir com eles.", diff --git a/app/javascript/mastodon/locales/pt-PT.json b/app/javascript/mastodon/locales/pt-PT.json index 6a6feca309f2bf..a0359fd8684589 100644 --- a/app/javascript/mastodon/locales/pt-PT.json +++ b/app/javascript/mastodon/locales/pt-PT.json @@ -485,7 +485,6 @@ "notification.moderation_warning.action_silence": "A sua conta foi limitada.", "notification.moderation_warning.action_suspend": "A sua conta foi suspensa.", "notification.own_poll": "A sua votação terminou", - "notification.poll": "Uma votação em que participaste chegou ao fim", "notification.reblog": "{name} reforçou a tua publicação", "notification.relationships_severance_event": "Perdeu as ligações com {name}", "notification.relationships_severance_event.account_suspension": "Um administrador de {from} suspendeu {target}, o que significa que já não pode receber atualizações dele ou interagir com ele.", diff --git a/app/javascript/mastodon/locales/ro.json b/app/javascript/mastodon/locales/ro.json index 35abf1b021f5d0..bbae7112696534 100644 --- a/app/javascript/mastodon/locales/ro.json +++ b/app/javascript/mastodon/locales/ro.json @@ -393,7 +393,6 @@ "notification.follow_request": "{name} a trimis o cerere de abonare", "notification.mention": "{name} te-a menționat", "notification.own_poll": "Sondajul tău s-a încheiat", - "notification.poll": "Un sondaj pentru care ai votat s-a încheiat", "notification.reblog": "{name} ți-a distribuit postarea", "notification.status": "{name} tocmai a postat", "notification.update": "{name} și-a modificat o postare", diff --git a/app/javascript/mastodon/locales/ru.json b/app/javascript/mastodon/locales/ru.json index 97a1f0b09c3a05..971d6c77cadd8e 100644 --- a/app/javascript/mastodon/locales/ru.json +++ b/app/javascript/mastodon/locales/ru.json @@ -482,7 +482,6 @@ "notification.moderation_warning.action_silence": "Ваша учётная запись была ограничена.", "notification.moderation_warning.action_suspend": "Действие вашей учётной записи приостановлено.", "notification.own_poll": "Ваш опрос закончился", - "notification.poll": "Опрос, в котором вы приняли участие, завершился", "notification.reblog": "{name} продвинул(а) ваш пост", "notification.relationships_severance_event": "Потеряно соединение с {name}", "notification.relationships_severance_event.account_suspension": "Администратор {from} заблокировал {target}, что означает, что вы больше не сможете получать обновления от них или взаймодествовать с ними.", diff --git a/app/javascript/mastodon/locales/sa.json b/app/javascript/mastodon/locales/sa.json index c3880a6b037504..7f8dae326ef972 100644 --- a/app/javascript/mastodon/locales/sa.json +++ b/app/javascript/mastodon/locales/sa.json @@ -355,7 +355,6 @@ "notification.follow_request": "{name} त्वामनुसर्तुमयाचीत्", "notification.mention": "{name} त्वामुल्लिलेख", "notification.own_poll": "तव निर्वाचनं समाप्तम्", - "notification.poll": "यस्मिन्निर्वाचने मतमदास्तन्निर्वाचनं समाप्तम्", "notification.reblog": "{name} तव पत्रं बुस्तिमिति अकार्षीत्", "notification.status": "{name} अधुना अस्थापयिष्ट", "notification.update": "{name} पत्रमेकं समपादयिष्ट", diff --git a/app/javascript/mastodon/locales/sc.json b/app/javascript/mastodon/locales/sc.json index 8955573737836c..f13514fd0232d9 100644 --- a/app/javascript/mastodon/locales/sc.json +++ b/app/javascript/mastodon/locales/sc.json @@ -282,7 +282,6 @@ "notification.follow_request": "{name} at dimandadu de ti sighire", "notification.mention": "{name} t'at mentovadu", "notification.own_poll": "Sondàgiu acabbadu", - "notification.poll": "Unu sondàgiu in su chi as votadu est acabbadu", "notification.reblog": "{name} at cumpartzidu sa publicatzione tua", "notification.status": "{name} at publicadu cosa", "notifications.clear": "Lìmpia notìficas", diff --git a/app/javascript/mastodon/locales/sco.json b/app/javascript/mastodon/locales/sco.json index 397f63fed41f92..7c4d1db60ebd9f 100644 --- a/app/javascript/mastodon/locales/sco.json +++ b/app/javascript/mastodon/locales/sco.json @@ -338,7 +338,6 @@ "notification.follow_request": "{name} is wantin tae follae ye", "notification.mention": "{name} menshied ye", "notification.own_poll": "Yer poll is duin", - "notification.poll": "A poll thit ye votit in is duin", "notification.reblog": "{name} heezed yer post", "notification.status": "{name} juist postit", "notification.update": "{name} editit a post", diff --git a/app/javascript/mastodon/locales/si.json b/app/javascript/mastodon/locales/si.json index 3a67beed527a59..c4f82c41336c80 100644 --- a/app/javascript/mastodon/locales/si.json +++ b/app/javascript/mastodon/locales/si.json @@ -289,7 +289,6 @@ "notification.follow": "{name} ඔබව අනුගමනය කළා", "notification.mention": "{name} ඔබව සඳහන් කර ඇත", "notification.own_poll": "ඔබගේ මත විමසුම නිමයි", - "notification.poll": "ඔබ ඡන්දය දුන් මත විමසුමක් නිමයි", "notification.status": "{name} දැන් පළ කළා", "notification.update": "{name} ලිපියක් සංස්කරණය කළා", "notifications.clear": "දැනුම්දීම් මකන්න", diff --git a/app/javascript/mastodon/locales/sk.json b/app/javascript/mastodon/locales/sk.json index ed877f7667c9b0..cff79c6b9bb379 100644 --- a/app/javascript/mastodon/locales/sk.json +++ b/app/javascript/mastodon/locales/sk.json @@ -452,7 +452,6 @@ "notification.moderation_warning.action_silence": "Tvoj účet bol obmedzený.", "notification.moderation_warning.action_suspend": "Tvoj účet bol pozastavený.", "notification.own_poll": "Vaša anketa sa skončila", - "notification.poll": "Anketa, v ktorej ste hlasovali, sa skončila", "notification.reblog": "{name} zdieľa váš príspevok", "notification.relationships_severance_event": "Stratené prepojenia s {name}", "notification.relationships_severance_event.account_suspension": "Správca z {from} pozastavil/a {target}, čo znamená, že od nich viac nemôžeš dostávať aktualizácie, alebo s nimi interaktovať.", diff --git a/app/javascript/mastodon/locales/sl.json b/app/javascript/mastodon/locales/sl.json index 2a3d74a80f2b63..b8c995b8d1c209 100644 --- a/app/javascript/mastodon/locales/sl.json +++ b/app/javascript/mastodon/locales/sl.json @@ -443,6 +443,8 @@ "mute_modal.title": "Utišaj uporabnika?", "mute_modal.you_wont_see_mentions": "Objav, ki jih omenjajo, ne boste videli.", "mute_modal.you_wont_see_posts": "Še vedno vidijo vaše objave, vi pa ne njihovih.", + "name_and_others": "{name} in {count, plural, one {# drug} two {# druga} few {# drugi} other {# drugih}}", + "name_and_others_with_link": "{name} in {count, plural, one {# drug} two {# druga} few {# drugi} other {# drugih}}", "navigation_bar.about": "O Mastodonu", "navigation_bar.advanced_interface": "Odpri v naprednem spletnem vmesniku", "navigation_bar.blocks": "Blokirani uporabniki", @@ -470,6 +472,10 @@ "navigation_bar.security": "Varnost", "not_signed_in_indicator.not_signed_in": "Za dostop do tega vira se morate prijaviti.", "notification.admin.report": "{name} je prijavil/a {target}", + "notification.admin.report_account": "{name} je prijavil/a {count, plural, one {# objavo} two {# objavi} few {# objave} other {# objav}} od {target} zaradi {category}", + "notification.admin.report_account_other": "{name} je prijavil/a {count, plural, one {# objavo} two {# objavi} few {# objave} other {# objav}} od {target}", + "notification.admin.report_statuses": "{name} je prijavil/a {target} zaradi {category}", + "notification.admin.report_statuses_other": "{name} je prijavil/a {target}", "notification.admin.sign_up": "{name} se je vpisal/a", "notification.favourite": "{name} je vzljubil/a vašo objavo", "notification.follow": "{name} vam sledi", @@ -486,6 +492,7 @@ "notification.moderation_warning.action_suspend": "Vaš račun je bil suspendiran.", "notification.own_poll": "Vaša anketa je zaključena", "notification.poll": "Anketa, v kateri ste sodelovali, je zaključena", + "notification.private_mention": "{name} vas je zasebno omenil/a", "notification.reblog": "{name} je izpostavila/a vašo objavo", "notification.relationships_severance_event": "Povezave z {name} prekinjene", "notification.relationships_severance_event.account_suspension": "Skrbnik na {from} je suspendiral račun {target}, kar pomeni, da od računa ne morete več prejemati posodobitev ali imeti z njim interakcij.", @@ -503,6 +510,8 @@ "notifications.column_settings.admin.report": "Nove prijave:", "notifications.column_settings.admin.sign_up": "Novi vpisi:", "notifications.column_settings.alert": "Namizna obvestila", + "notifications.column_settings.beta.category": "Poskusne funkcionalnosti", + "notifications.column_settings.beta.grouping": "Skupine obvestil", "notifications.column_settings.favourite": "Priljubljeni:", "notifications.column_settings.filter_bar.advanced": "Prikaži vse kategorije", "notifications.column_settings.filter_bar.category": "Vrstica za hitro filtriranje", @@ -666,9 +675,13 @@ "report.unfollow_explanation": "Temu računu sledite. Da ne boste več videli njegovih objav v svojem domačem viru, mu prenehajte slediti.", "report_notification.attached_statuses": "{count, plural, one {{count} objava pripeta} two {{count} objavi pripeti} few {{count} objave pripete} other {{count} objav pripetih}}", "report_notification.categories.legal": "Legalno", + "report_notification.categories.legal_sentence": "nedovoljena vsebina", "report_notification.categories.other": "Drugo", + "report_notification.categories.other_sentence": "drugo", "report_notification.categories.spam": "Neželeno", + "report_notification.categories.spam_sentence": "neželeno", "report_notification.categories.violation": "Kršitev pravila", + "report_notification.categories.violation_sentence": "kršitev pravila", "report_notification.open": "Odpri prijavo", "search.no_recent_searches": "Ni nedavnih iskanj", "search.placeholder": "Iskanje", diff --git a/app/javascript/mastodon/locales/sq.json b/app/javascript/mastodon/locales/sq.json index 96b7b3fefc715a..6f378b145eaf40 100644 --- a/app/javascript/mastodon/locales/sq.json +++ b/app/javascript/mastodon/locales/sq.json @@ -443,6 +443,8 @@ "mute_modal.title": "Të heshtohet përdoruesi?", "mute_modal.you_wont_see_mentions": "S’do të shihni postime ku përmenden.", "mute_modal.you_wont_see_posts": "Ata munden ende të shohin postimet tuaja, por ju s’do të shihni të tyret.", + "name_and_others": "{name} dhe {count, plural, one {# tjetër} other {# të tjerë}}", + "name_and_others_with_link": "{name} dhe {count, plural, one {# tjetër} other {# të tjerë}}", "navigation_bar.about": "Mbi", "navigation_bar.advanced_interface": "Hape në ndërfaqe web të thelluar", "navigation_bar.blocks": "Përdorues të bllokuar", @@ -470,6 +472,10 @@ "navigation_bar.security": "Siguri", "not_signed_in_indicator.not_signed_in": "Që të përdorni këtë burim, lypset të bëni hyrjen.", "notification.admin.report": "{name} raportoi {target}", + "notification.admin.report_account": "{name} raportoi për {count, plural, one {një postim} other {# postime}} nga {target} për {category}", + "notification.admin.report_account_other": "{name} raportoi për {count, plural, one {një postim} other {# postime}} nga {target}", + "notification.admin.report_statuses": "{name} raportoi {target} për {category}", + "notification.admin.report_statuses_other": "{name} raportoi {target}", "notification.admin.sign_up": "{name} u regjistrua", "notification.favourite": "{name} i vuri shenjë postimit tuaj si të parapëlqyer", "notification.follow": "{name} zuri t’ju ndjekë", @@ -485,7 +491,8 @@ "notification.moderation_warning.action_silence": "Llogaria juaj është kufizuar.", "notification.moderation_warning.action_suspend": "Llogaria juaj është pezulluar.", "notification.own_poll": "Pyetësori juaj ka përfunduar", - "notification.poll": "Ka përfunduar një pyetësor ku keni votuar", + "notification.poll": "Ka përfunduar një pyetësor në të cilin keni marrë pjesë", + "notification.private_mention": "{name} ju përmendi privatisht", "notification.reblog": "{name} përforcoi mesazhin tuaj", "notification.relationships_severance_event": "Lidhje të humbura me {name}", "notification.relationships_severance_event.account_suspension": "Një përgjegjës nga {from} ka pezulluar {target}, që do të thotë se s’mund të merrni më përditësime prej tij, apo të ndërveproni me të.", @@ -503,6 +510,8 @@ "notifications.column_settings.admin.report": "Raportime të reja:", "notifications.column_settings.admin.sign_up": "Regjistrime të reja:", "notifications.column_settings.alert": "Njoftime desktopi", + "notifications.column_settings.beta.category": "Veçori eksperimentale", + "notifications.column_settings.beta.grouping": "Njoftime grupi", "notifications.column_settings.favourite": "Të parapëlqyer:", "notifications.column_settings.filter_bar.advanced": "Shfaq krejt kategoritë", "notifications.column_settings.filter_bar.category": "Shtyllë filtrimesh të shpejta", @@ -666,9 +675,13 @@ "report.unfollow_explanation": "Po e ndiqni këtë llogari. Për të mos parë më postimet e tyre te prurja juaj e kreut, ndalni ndjekjen e tyre.", "report_notification.attached_statuses": "{count, plural, one {{count} postim} other {{count} postime}} bashkëngjitur", "report_notification.categories.legal": "Ligjore", + "report_notification.categories.legal_sentence": "lëndë e paligjshme", "report_notification.categories.other": "Tjetër", + "report_notification.categories.other_sentence": "tjetër", "report_notification.categories.spam": "I padëshiruar", + "report_notification.categories.spam_sentence": "mesazh i padëshiruar", "report_notification.categories.violation": "Cenim rregullash", + "report_notification.categories.violation_sentence": "cenim rregullash", "report_notification.open": "Hape raportimin", "search.no_recent_searches": "Pa kërkime së fundi", "search.placeholder": "Kërkoni", diff --git a/app/javascript/mastodon/locales/sr-Latn.json b/app/javascript/mastodon/locales/sr-Latn.json index 71b69d428af7ab..38ff12bdcf6021 100644 --- a/app/javascript/mastodon/locales/sr-Latn.json +++ b/app/javascript/mastodon/locales/sr-Latn.json @@ -485,7 +485,6 @@ "notification.moderation_warning.action_silence": "Vaš nalog je ograničen.", "notification.moderation_warning.action_suspend": "Vaš nalog je suspendovan.", "notification.own_poll": "Vaša anketa je završena", - "notification.poll": "Završena je anketa u kojoj ste glasali", "notification.reblog": "{name} je podržao vašu objavu", "notification.relationships_severance_event": "Izgubljena veza sa {name}", "notification.relationships_severance_event.account_suspension": "Administrator sa {from} je suspendovao {target}, što znači da više ne možete da primate ažuriranja od njih niti da komunicirate sa njima.", diff --git a/app/javascript/mastodon/locales/sr.json b/app/javascript/mastodon/locales/sr.json index 2c4649f9d03941..047e8cf3a8d41c 100644 --- a/app/javascript/mastodon/locales/sr.json +++ b/app/javascript/mastodon/locales/sr.json @@ -485,7 +485,6 @@ "notification.moderation_warning.action_silence": "Ваш налог је ограничен.", "notification.moderation_warning.action_suspend": "Ваш налог је суспендован.", "notification.own_poll": "Ваша анкета је завршена", - "notification.poll": "Завршена је анкета у којој сте гласали", "notification.reblog": "{name} је подржао вашу објаву", "notification.relationships_severance_event": "Изгубљена веза са {name}", "notification.relationships_severance_event.account_suspension": "Администратор са {from} је суспендовао {target}, што значи да више не можете да примате ажурирања од њих нити да комуницирате са њима.", diff --git a/app/javascript/mastodon/locales/sv.json b/app/javascript/mastodon/locales/sv.json index 1833a2cfdefa4b..53e2dde42ea416 100644 --- a/app/javascript/mastodon/locales/sv.json +++ b/app/javascript/mastodon/locales/sv.json @@ -442,6 +442,8 @@ "mute_modal.title": "Tysta användare?", "mute_modal.you_wont_see_mentions": "Du kommer inte att se inlägg som nämner dem.", "mute_modal.you_wont_see_posts": "De kan fortfarande se dina inlägg, men du kan inte se deras.", + "name_and_others": "{name} och {count, plural, one {# annan} other {# andra}}", + "name_and_others_with_link": "{name} och {count, plural, one {# annan} other {# andra}}", "navigation_bar.about": "Om", "navigation_bar.advanced_interface": "Öppna i avancerat webbgränssnitt", "navigation_bar.blocks": "Blockerade användare", @@ -469,6 +471,7 @@ "navigation_bar.security": "Säkerhet", "not_signed_in_indicator.not_signed_in": "Du behöver logga in för att få åtkomst till denna resurs.", "notification.admin.report": "{name} rapporterade {target}", + "notification.admin.report_statuses_other": "{name} rapporterade {target}", "notification.admin.sign_up": "{name} registrerade sig", "notification.favourite": "{name} favoritmarkerade ditt inlägg", "notification.follow": "{name} följer dig", @@ -484,7 +487,7 @@ "notification.moderation_warning.action_silence": "Ditt konto har begränsats.", "notification.moderation_warning.action_suspend": "Ditt konto har stängts av.", "notification.own_poll": "Din röstning har avslutats", - "notification.poll": "En omröstning du röstat i har avslutats", + "notification.private_mention": "{name} nämnde dig privat", "notification.reblog": "{name} boostade ditt inlägg", "notification.relationships_severance_event": "Förlorade kontakter med {name}", "notification.relationships_severance_event.account_suspension": "En administratör från {from} har stängt av {target}, vilket innebär att du inte längre kan ta emot uppdateringar från dem eller interagera med dem.", @@ -502,6 +505,7 @@ "notifications.column_settings.admin.report": "Nya rapporter:", "notifications.column_settings.admin.sign_up": "Nya registreringar:", "notifications.column_settings.alert": "Skrivbordsaviseringar", + "notifications.column_settings.beta.category": "Experimentella funktioner", "notifications.column_settings.favourite": "Favoriter:", "notifications.column_settings.filter_bar.advanced": "Visa alla kategorier", "notifications.column_settings.filter_bar.category": "Snabbfilter", @@ -666,8 +670,11 @@ "report_notification.attached_statuses": "bifogade {count, plural, one {{count} inlägg} other {{count} inlägg}}", "report_notification.categories.legal": "Rättsligt", "report_notification.categories.other": "Övrigt", + "report_notification.categories.other_sentence": "övrigt", "report_notification.categories.spam": "Skräppost", + "report_notification.categories.spam_sentence": "skräppost", "report_notification.categories.violation": "Regelöverträdelse", + "report_notification.categories.violation_sentence": "regelöverträdelse", "report_notification.open": "Öppna rapport", "search.no_recent_searches": "Inga sökningar nyligen", "search.placeholder": "Sök", diff --git a/app/javascript/mastodon/locales/ta.json b/app/javascript/mastodon/locales/ta.json index d44ac424f4f715..bb26986b818206 100644 --- a/app/javascript/mastodon/locales/ta.json +++ b/app/javascript/mastodon/locales/ta.json @@ -278,7 +278,6 @@ "notification.follow_request": "{name} உங்களைப் பின்தொடரக் கோருகிறார்", "notification.mention": "{name} நீங்கள் குறிப்பிட்டுள்ளீர்கள்", "notification.own_poll": "கருத்துக்கணிப்பு நிறைவடைந்தது", - "notification.poll": "நீங்கள் வாக்களித்த வாக்கெடுப்பு முடிவடைந்தது", "notification.reblog": "{name} உங்கள் நிலை அதிகரித்தது", "notifications.clear": "அறிவிப்புகளை அழிக்கவும்", "notifications.clear_confirmation": "உங்கள் எல்லா அறிவிப்புகளையும் நிரந்தரமாக அழிக்க விரும்புகிறீர்களா?", diff --git a/app/javascript/mastodon/locales/te.json b/app/javascript/mastodon/locales/te.json index c06472561f9915..471890b9a36646 100644 --- a/app/javascript/mastodon/locales/te.json +++ b/app/javascript/mastodon/locales/te.json @@ -187,7 +187,6 @@ "not_signed_in_indicator.not_signed_in": "You need to sign in to access this resource.", "notification.follow": "{name} మిమ్మల్ని అనుసరిస్తున్నారు", "notification.mention": "{name} మిమ్మల్ని ప్రస్తావించారు", - "notification.poll": "మీరు పాల్గొనిన ఎన్సిక ముగిసినది", "notification.reblog": "{name} మీ స్టేటస్ ను బూస్ట్ చేసారు", "notifications.clear": "ప్రకటనలను తుడిచివేయు", "notifications.clear_confirmation": "మీరు మీ అన్ని నోటిఫికేషన్లను శాశ్వతంగా తొలగించాలనుకుంటున్నారా?", diff --git a/app/javascript/mastodon/locales/th.json b/app/javascript/mastodon/locales/th.json index 64abb394bfce4b..ab8179863c1d3d 100644 --- a/app/javascript/mastodon/locales/th.json +++ b/app/javascript/mastodon/locales/th.json @@ -443,6 +443,7 @@ "mute_modal.title": "ซ่อนผู้ใช้?", "mute_modal.you_wont_see_mentions": "คุณจะไม่เห็นโพสต์ที่กล่าวถึงเขา", "mute_modal.you_wont_see_posts": "เขายังคงสามารถเห็นโพสต์ของคุณ แต่คุณจะไม่เห็นโพสต์ของเขา", + "name_and_others": "{name} และ {count, plural, one {# อื่น ๆ } other {# อื่น ๆ}}", "navigation_bar.about": "เกี่ยวกับ", "navigation_bar.advanced_interface": "เปิดในส่วนติดต่อเว็บขั้นสูง", "navigation_bar.blocks": "ผู้ใช้ที่ปิดกั้นอยู่", @@ -470,6 +471,7 @@ "navigation_bar.security": "ความปลอดภัย", "not_signed_in_indicator.not_signed_in": "คุณจำเป็นต้องเข้าสู่ระบบเพื่อเข้าถึงทรัพยากรนี้", "notification.admin.report": "{name} ได้รายงาน {target}", + "notification.admin.report_statuses_other": "{name} รายงาน {target}", "notification.admin.sign_up": "{name} ได้ลงทะเบียน", "notification.favourite": "{name} ได้ชื่นชอบโพสต์ของคุณ", "notification.follow": "{name} ได้ติดตามคุณ", @@ -485,7 +487,7 @@ "notification.moderation_warning.action_silence": "จำกัดบัญชีของคุณแล้ว", "notification.moderation_warning.action_suspend": "ระงับบัญชีของคุณแล้ว", "notification.own_poll": "การสำรวจความคิดเห็นของคุณได้สิ้นสุดแล้ว", - "notification.poll": "การสำรวจความคิดเห็นที่คุณได้ลงคะแนนได้สิ้นสุดแล้ว", + "notification.poll": "โพลที่คุณโหวตได้จบลงแล้ว", "notification.reblog": "{name} ได้ดันโพสต์ของคุณ", "notification.relationships_severance_event": "สูญเสียการเชื่อมต่อกับ {name}", "notification.relationships_severance_event.account_suspension": "ผู้ดูแลจาก {from} ได้ระงับ {target} ซึ่งหมายความว่าคุณจะไม่สามารถรับการอัปเดตจากเขาหรือโต้ตอบกับเขาได้อีกต่อไป", @@ -667,8 +669,11 @@ "report_notification.attached_statuses": "{count, plural, other {{count} โพสต์}}ที่แนบมา", "report_notification.categories.legal": "กฎหมาย", "report_notification.categories.other": "อื่น ๆ", + "report_notification.categories.other_sentence": "อื่น ๆ", "report_notification.categories.spam": "สแปม", + "report_notification.categories.spam_sentence": "สแปม", "report_notification.categories.violation": "การละเมิดกฎ", + "report_notification.categories.violation_sentence": "ละเมิดกฎ", "report_notification.open": "รายงานที่เปิด", "search.no_recent_searches": "ไม่มีการค้นหาล่าสุด", "search.placeholder": "ค้นหา", diff --git a/app/javascript/mastodon/locales/tok.json b/app/javascript/mastodon/locales/tok.json index fcdef5f32ce744..e581978f2419a4 100644 --- a/app/javascript/mastodon/locales/tok.json +++ b/app/javascript/mastodon/locales/tok.json @@ -294,7 +294,6 @@ "notification.follow_request": "{name} li wile kute e sina", "notification.mention": "jan {name} li toki e sina", "notification.moderation-warning.learn_more": "o kama sona e ijo ante", - "notification.poll": "sina pana lon pana la pana ni li pini", "notification.reblog": "{name} li wawa e toki sina", "notification.status": "{name} li toki", "notification.update": "{name} li ante e toki", diff --git a/app/javascript/mastodon/locales/tr.json b/app/javascript/mastodon/locales/tr.json index ac39a3fd7b6e39..ae7b5ba25dc314 100644 --- a/app/javascript/mastodon/locales/tr.json +++ b/app/javascript/mastodon/locales/tr.json @@ -443,6 +443,8 @@ "mute_modal.title": "Kullanıcıyı sustur?", "mute_modal.you_wont_see_mentions": "Onlardan bahseden gönderiler göremezsiniz.", "mute_modal.you_wont_see_posts": "Onlar sizin gönderilerinizi görmeye devam edebilir, ancak siz onlarınkini göremezsiniz.", + "name_and_others": "{name} ve {count, plural, one {# diğer} other {# diğerleri}}", + "name_and_others_with_link": "{name} ve {count, plural, one {# diğer} other {# diğerleri}}", "navigation_bar.about": "Hakkında", "navigation_bar.advanced_interface": "Gelişmiş web arayüzünde aç", "navigation_bar.blocks": "Engellenen kullanıcılar", @@ -470,6 +472,10 @@ "navigation_bar.security": "Güvenlik", "not_signed_in_indicator.not_signed_in": "Bu kaynağa erişmek için oturum açmanız gerekir.", "notification.admin.report": "{name}, {target} kişisini bildirdi", + "notification.admin.report_account": "{name}, {category} kategorisi için {target} kişisini {count, plural, one {bir gönderi} other {# gönderi}} bildirdi", + "notification.admin.report_account_other": "{name}, {target} kişisinden {count, plural, one {bir gönderi} other {# gönderi}} bildirdi", + "notification.admin.report_statuses": "{name}, {category} kategorisi için {target} kişisini bildirdi", + "notification.admin.report_statuses_other": "{name}, {target} kişisini bildirdi", "notification.admin.sign_up": "{name} kaydoldu", "notification.favourite": "{name} gönderinizi beğendi", "notification.follow": "{name} seni takip etti", @@ -486,6 +492,7 @@ "notification.moderation_warning.action_suspend": "Hesabınız askıya alındı.", "notification.own_poll": "Anketiniz sona erdi", "notification.poll": "Oy verdiğiniz bir anket sona erdi", + "notification.private_mention": "{name} gizlice sizden bahsetti", "notification.reblog": "{name} gönderini yeniden paylaştı", "notification.relationships_severance_event": "{name} ile bağlantılar koptu", "notification.relationships_severance_event.account_suspension": "{from} yöneticisi, {target} askıya aldı, bunun anlamı onlardan artık güncelleme alamayacak veya etkileşemeyeceksiniz demektir.", @@ -503,6 +510,8 @@ "notifications.column_settings.admin.report": "Yeni bildirimler:", "notifications.column_settings.admin.sign_up": "Yeni kayıtlar:", "notifications.column_settings.alert": "Masaüstü bildirimleri", + "notifications.column_settings.beta.category": "Deneysel özellikler", + "notifications.column_settings.beta.grouping": "Grup bildirimleri", "notifications.column_settings.favourite": "Favorilerin:", "notifications.column_settings.filter_bar.advanced": "Tüm kategorileri görüntüle", "notifications.column_settings.filter_bar.category": "Hızlı filtre çubuğu", @@ -666,9 +675,13 @@ "report.unfollow_explanation": "Bu hesabı takip ediyorsunuz. Ana akışınızda gönderilerini görmek istemiyorsanız, onu takip etmeyi bırakın.", "report_notification.attached_statuses": "{count, plural, one {{count} gönderi} other {{count} gönderi}} eklendi", "report_notification.categories.legal": "Yasal", + "report_notification.categories.legal_sentence": "yasadışı içerik", "report_notification.categories.other": "Diğer", + "report_notification.categories.other_sentence": "diğer", "report_notification.categories.spam": "İstenmeyen", + "report_notification.categories.spam_sentence": "i̇stenmeyen", "report_notification.categories.violation": "Kural ihlali", + "report_notification.categories.violation_sentence": "kural ihlali", "report_notification.open": "Bildirim aç", "search.no_recent_searches": "Son arama yok", "search.placeholder": "Ara", diff --git a/app/javascript/mastodon/locales/uk.json b/app/javascript/mastodon/locales/uk.json index 67ebb031aefcd0..b5cd1f7b283f6d 100644 --- a/app/javascript/mastodon/locales/uk.json +++ b/app/javascript/mastodon/locales/uk.json @@ -443,6 +443,8 @@ "mute_modal.title": "Ігнорувати користувача?", "mute_modal.you_wont_see_mentions": "Ви не бачитимете дописів, де їх згадано.", "mute_modal.you_wont_see_posts": "Вони все ще можуть бачити ваші дописи, але ви не бачитимете їхніх.", + "name_and_others": "{name} і {count, plural, one {# інший} few {# інших} many {# інших} other {# інший}}", + "name_and_others_with_link": "{name} і {count, plural, one {# інший} few {# інших} many {# інших} other {# інший}}", "navigation_bar.about": "Про застосунок", "navigation_bar.advanced_interface": "Відкрити в розширеному вебінтерфейсі", "navigation_bar.blocks": "Заблоковані користувачі", @@ -470,6 +472,10 @@ "navigation_bar.security": "Безпека", "not_signed_in_indicator.not_signed_in": "Ви повинні увійти, щоб отримати доступ до цього ресурсу.", "notification.admin.report": "Скарга від {name} на {target}", + "notification.admin.report_account": "{name} повідомив(ла) про {count, plural, one {один допис} few {# дописи} many {# дописів} other {# дописів}} від {target} в категорії {category}", + "notification.admin.report_account_other": "{name} повідомив(ла) про {count, plural, one {один допис} few {# дописи} many {# дописів} other {# дописів}} від {target}", + "notification.admin.report_statuses": "{name} повідомив(ла) про {target} в категорії {category}", + "notification.admin.report_statuses_other": "{name} повідомив(ла) про {target}", "notification.admin.sign_up": "{name} приєдналися", "notification.favourite": "Ваш допис сподобався {name}", "notification.follow": "{name} підписалися на вас", @@ -485,7 +491,8 @@ "notification.moderation_warning.action_silence": "Ваш обліковий запис було обмежено.", "notification.moderation_warning.action_suspend": "Ваш обліковий запис було заблоковано.", "notification.own_poll": "Ваше опитування завершилося", - "notification.poll": "Опитування, у якому ви голосували, скінчилося", + "notification.poll": "Опитування, в якому ви проголосували, завершено", + "notification.private_mention": "{name} приватно згадав(ла) вас", "notification.reblog": "{name} поширює ваш допис", "notification.relationships_severance_event": "Втрачено з'єднання з {name}", "notification.relationships_severance_event.account_suspension": "Адміністратор з {from} призупинив {target}, що означає, що ви більше не можете отримувати оновлення від них або взаємодіяти з ними.", @@ -503,6 +510,8 @@ "notifications.column_settings.admin.report": "Нові скарги:", "notifications.column_settings.admin.sign_up": "Нові реєстрації:", "notifications.column_settings.alert": "Сповіщення стільниці", + "notifications.column_settings.beta.category": "Експериментальні функції", + "notifications.column_settings.beta.grouping": "Групові сповіщення", "notifications.column_settings.favourite": "Уподобане:", "notifications.column_settings.filter_bar.advanced": "Показати всі категорії", "notifications.column_settings.filter_bar.category": "Панель швидкого фільтра", @@ -666,9 +675,13 @@ "report.unfollow_explanation": "Ви підписані на цього користувача. Щоб більше не бачити їхні дописи у вашій стрічці, відпишіться від них.", "report_notification.attached_statuses": "{count, plural, one {{count} допис} few {{count} дописи} many {{count} дописів} other {{count} дописи}} прикріплено", "report_notification.categories.legal": "Правові", + "report_notification.categories.legal_sentence": "незаконний контент", "report_notification.categories.other": "Інше", + "report_notification.categories.other_sentence": "інше", "report_notification.categories.spam": "Спам", + "report_notification.categories.spam_sentence": "спам", "report_notification.categories.violation": "Порушення правил", + "report_notification.categories.violation_sentence": "порушення правил", "report_notification.open": "Відкрити скаргу", "search.no_recent_searches": "Немає останніх пошуків", "search.placeholder": "Пошук", diff --git a/app/javascript/mastodon/locales/ur.json b/app/javascript/mastodon/locales/ur.json index cf53eb6fe8a7d8..3c61846e9c63a7 100644 --- a/app/javascript/mastodon/locales/ur.json +++ b/app/javascript/mastodon/locales/ur.json @@ -240,7 +240,6 @@ "notification.follow_request": "{name} نے آپ کی پیروی کی درخواست کی", "notification.mention": "{name} نے آپ کا تذکرہ کیا", "notification.own_poll": "آپ کا پول ختم ہو گیا ہے", - "notification.poll": "آپ کا ووٹ دیا گیا ایک پول ختم ہو گیا ہے", "notification.reblog": "{name} boosted your status", "notification.status": "{name} نے ابھی ابھی پوسٹ کیا", "notifications.clear": "اطلاعات ہٹائیں", diff --git a/app/javascript/mastodon/locales/uz.json b/app/javascript/mastodon/locales/uz.json index 4824b1d3320fa7..90ad67d2879903 100644 --- a/app/javascript/mastodon/locales/uz.json +++ b/app/javascript/mastodon/locales/uz.json @@ -328,7 +328,6 @@ "navigation_bar.security": "Xavfsizlik", "not_signed_in_indicator.not_signed_in": "Ushbu manbaga kirish uchun tizimga kirishingiz kerak.", "notification.own_poll": "So‘rovingiz tugadi", - "notification.poll": "Siz ovoz bergan soʻrovnoma yakunlandi", "notification.reblog": "{name} boosted your status", "onboarding.actions.go_to_explore": "See what's trending", "onboarding.actions.go_to_home": "Go to your home feed", diff --git a/app/javascript/mastodon/locales/vi.json b/app/javascript/mastodon/locales/vi.json index 70932d10bee96e..0f2cc996a2e4e1 100644 --- a/app/javascript/mastodon/locales/vi.json +++ b/app/javascript/mastodon/locales/vi.json @@ -443,6 +443,8 @@ "mute_modal.title": "Ẩn người này?", "mute_modal.you_wont_see_mentions": "Bạn sẽ không nhìn thấy tút có nhắc đến họ.", "mute_modal.you_wont_see_posts": "Bạn sẽ không nhìn thấy tút của họ.", + "name_and_others": "{name} và {count, plural, other {# người khác}}", + "name_and_others_with_link": "{name} và {count, plural, other {# người khác}}", "navigation_bar.about": "Giới thiệu", "navigation_bar.advanced_interface": "Dùng bố cục nhiều cột", "navigation_bar.blocks": "Người đã chặn", @@ -470,6 +472,10 @@ "navigation_bar.security": "Bảo mật", "not_signed_in_indicator.not_signed_in": "Bạn cần đăng nhập để truy cập mục này.", "notification.admin.report": "{name} báo cáo {target}", + "notification.admin.report_account": "{name} báo cáo {count, plural, other {# tút}} của {target} vì {category}", + "notification.admin.report_account_other": "{name} báo cáo {count, plural, other {# tút}} của {target}", + "notification.admin.report_statuses": "{name} báo cáo {target} vì {category}", + "notification.admin.report_statuses_other": "{name} báo cáo {target}", "notification.admin.sign_up": "{name} tham gia máy chủ của bạn", "notification.favourite": "{name} thích tút của bạn", "notification.follow": "{name} theo dõi bạn", @@ -485,7 +491,8 @@ "notification.moderation_warning.action_silence": "Tài khoản của bạn đã bị hạn chế.", "notification.moderation_warning.action_suspend": "Tài khoản của bạn đã bị vô hiệu hóa.", "notification.own_poll": "Cuộc bình chọn của bạn đã kết thúc", - "notification.poll": "Cuộc bình chọn đã kết thúc", + "notification.poll": "Cuộc bình chọn có bạn tham gia đã kết thúc", + "notification.private_mention": "{name} nhắn riêng đến bạn", "notification.reblog": "{name} đăng lại tút của bạn", "notification.relationships_severance_event": "Mất kết nối với {name}", "notification.relationships_severance_event.account_suspension": "Quản trị viên {from} đã vô hiệu hóa {target}, điều này có nghĩa là bạn không còn có thể nhận được cập nhật từ họ hoặc tương tác với họ nữa.", @@ -503,6 +510,8 @@ "notifications.column_settings.admin.report": "Báo cáo mới:", "notifications.column_settings.admin.sign_up": "Người mới tham gia:", "notifications.column_settings.alert": "Báo trên máy tính", + "notifications.column_settings.beta.category": "Tính năng thử nghiệm", + "notifications.column_settings.beta.grouping": "Gộp thông báo theo loại", "notifications.column_settings.favourite": "Lượt thích:", "notifications.column_settings.filter_bar.advanced": "Toàn bộ", "notifications.column_settings.filter_bar.category": "Thanh lọc nhanh", @@ -666,9 +675,13 @@ "report.unfollow_explanation": "Bạn đang theo dõi người này. Để không thấy tút của họ trên trang chủ nữa, hãy bỏ theo dõi.", "report_notification.attached_statuses": "{count, plural, other {{count} tút}} đính kèm", "report_notification.categories.legal": "Pháp lý", + "report_notification.categories.legal_sentence": "nội dung bất hợp pháp", "report_notification.categories.other": "Khác", + "report_notification.categories.other_sentence": "khác", "report_notification.categories.spam": "Spam", + "report_notification.categories.spam_sentence": "spam", "report_notification.categories.violation": "Vi phạm nội quy", + "report_notification.categories.violation_sentence": "vi phạm nội quy", "report_notification.open": "Mở báo cáo", "search.no_recent_searches": "Không có tìm kiếm gần đây", "search.placeholder": "Tìm kiếm", diff --git a/app/javascript/mastodon/locales/zh-CN.json b/app/javascript/mastodon/locales/zh-CN.json index f2accae0d066cb..f6c0feecfdb160 100644 --- a/app/javascript/mastodon/locales/zh-CN.json +++ b/app/javascript/mastodon/locales/zh-CN.json @@ -443,6 +443,8 @@ "mute_modal.title": "隐藏用户?", "mute_modal.you_wont_see_mentions": "你看不到提及他们的嘟文。", "mute_modal.you_wont_see_posts": "他们可以看到你的嘟文,但是你看不到他们的。", + "name_and_others": "{name} 和其它 {count, plural, other {# 人}}", + "name_and_others_with_link": "{name} 和其它 {count, plural, other {# 人}}", "navigation_bar.about": "关于", "navigation_bar.advanced_interface": "在高级网页界面中打开", "navigation_bar.blocks": "已屏蔽的用户", @@ -470,6 +472,10 @@ "navigation_bar.security": "安全", "not_signed_in_indicator.not_signed_in": "您需要登录才能访问此资源。", "notification.admin.report": "{name} 举报了 {target}", + "notification.admin.report_account": "{name} 举报了来自 {target} 的 {count, plural, other {# 条嘟文}},原因为 {category}", + "notification.admin.report_account_other": "{name} 举报了来自 {target} 的 {count, plural, other {# 条嘟文}}", + "notification.admin.report_statuses": "{name} 举报了 {target},原因为 {category}", + "notification.admin.report_statuses_other": "{name} 举报了 {target}", "notification.admin.sign_up": "{name} 注册了", "notification.favourite": "{name} 喜欢了你的嘟文", "notification.follow": "{name} 开始关注你", @@ -485,7 +491,8 @@ "notification.moderation_warning.action_silence": "你的账号已被限制。", "notification.moderation_warning.action_suspend": "你的账号已被封禁.", "notification.own_poll": "你的投票已经结束", - "notification.poll": "你参与的一个投票已经结束", + "notification.poll": "你参与的一项投票已结束", + "notification.private_mention": "{name} 私下提及了你", "notification.reblog": "{name} 转发了你的嘟文", "notification.relationships_severance_event": "与 {name} 的联系已断开", "notification.relationships_severance_event.account_suspension": "一名来自 {from} 的管理员已经封禁了{target},这意味着你将无法再收到他们的更新或与他们互动。", @@ -503,6 +510,8 @@ "notifications.column_settings.admin.report": "新举报:", "notifications.column_settings.admin.sign_up": "新注册:", "notifications.column_settings.alert": "桌面通知", + "notifications.column_settings.beta.category": "实验性功能", + "notifications.column_settings.beta.grouping": "通知分组", "notifications.column_settings.favourite": "喜欢:", "notifications.column_settings.filter_bar.advanced": "显示所有类别", "notifications.column_settings.filter_bar.category": "快速筛选栏", @@ -666,9 +675,13 @@ "report.unfollow_explanation": "你正在关注此账户。如果不想继续在主页看到他们的嘟文,取消对他们的关注即可。", "report_notification.attached_statuses": "附上 {count} 条嘟文", "report_notification.categories.legal": "法律义务", + "report_notification.categories.legal_sentence": "非法内容", "report_notification.categories.other": "其他", + "report_notification.categories.other_sentence": "其它", "report_notification.categories.spam": "骚扰", + "report_notification.categories.spam_sentence": "骚扰", "report_notification.categories.violation": "违反规则", + "report_notification.categories.violation_sentence": "违反规则", "report_notification.open": "打开举报", "search.no_recent_searches": "无最近搜索", "search.placeholder": "搜索", diff --git a/app/javascript/mastodon/locales/zh-HK.json b/app/javascript/mastodon/locales/zh-HK.json index 09a497e889d40c..4b717a77dab751 100644 --- a/app/javascript/mastodon/locales/zh-HK.json +++ b/app/javascript/mastodon/locales/zh-HK.json @@ -479,7 +479,6 @@ "notification.moderation_warning.action_silence": "你的帳號已受到限制。", "notification.moderation_warning.action_suspend": "你的帳號已被停權。", "notification.own_poll": "你的投票已結束", - "notification.poll": "你參與過的一個投票已經結束", "notification.reblog": "{name} 轉推你的文章", "notification.relationships_severance_event": "失去與 {name} 的連結", "notification.relationships_severance_event.account_suspension": "{from} 的管理員已將 {target} 停權,這表示你無法再收到他們的更新或與他們互動。", diff --git a/app/javascript/mastodon/locales/zh-TW.json b/app/javascript/mastodon/locales/zh-TW.json index 04469a971d5cbf..dca4cd134a2ab2 100644 --- a/app/javascript/mastodon/locales/zh-TW.json +++ b/app/javascript/mastodon/locales/zh-TW.json @@ -113,7 +113,7 @@ "closed_registrations.other_server_instructions": "因為 Mastodon 是去中心化的,所以您也能於其他伺服器上建立帳號,並仍然與這個伺服器互動。", "closed_registrations_modal.description": "目前無法於 {domain} 建立新帳號,但也請別忘了,您並不一定需要有 {domain} 伺服器的帳號,也能使用 Mastodon。", "closed_registrations_modal.find_another_server": "尋找另一個伺服器", - "closed_registrations_modal.preamble": "Mastodon 是去中心化的,所以無論您於哪個伺服器新增帳號,都可以與此伺服器上的任何人跟隨及互動。您甚至能自行架設一個自己的伺服器!", + "closed_registrations_modal.preamble": "Mastodon 是去中心化的,所以無論您於哪個伺服器新增帳號,都可以與此伺服器上的任何人跟隨及互動。您甚至能自行架設自己的伺服器!", "closed_registrations_modal.title": "註冊 Mastodon", "column.about": "關於", "column.blocks": "已封鎖的使用者", @@ -271,7 +271,7 @@ "empty_column.public": "這裡什麼都沒有!嘗試寫些公開的嘟文,或者跟隨其他伺服器的使用者後,就會有嘟文出現了", "error.unexpected_crash.explanation": "由於發生系統故障或瀏覽器相容性問題,無法正常顯示此頁面。", "error.unexpected_crash.explanation_addons": "此頁面無法被正常顯示,這可能是由瀏覽器附加元件或網頁自動翻譯工具造成的。", - "error.unexpected_crash.next_steps": "請嘗試重新整理頁面。如果狀況沒有改善,您可以使用不同的瀏覽器或應用程式來檢視來使用 Mastodon。", + "error.unexpected_crash.next_steps": "請嘗試重新整理頁面。如果狀況沒有改善,您可以使用不同的瀏覽器或應用程式以檢視來使用 Mastodon。", "error.unexpected_crash.next_steps_addons": "請嘗試關閉它們然後重新整理頁面。如果狀況沒有改善,您可以使用不同的瀏覽器或應用程式來檢視來使用 Mastodon。", "errors.unexpected_crash.copy_stacktrace": "複製 stacktrace 到剪貼簿", "errors.unexpected_crash.report_issue": "回報問題", @@ -356,7 +356,7 @@ "home.show_announcements": "顯示公告", "interaction_modal.description.favourite": "若於 Mastodon 上有個帳號,您可以將此嘟文加入最愛使作者知道您欣賞它且將它儲存下來。", "interaction_modal.description.follow": "若於 Mastodon 上有個帳號,您可以跟隨 {name} 以於首頁時間軸接收他們的嘟文。", - "interaction_modal.description.reblog": "若於 Mastodon 上有個帳號,您可以轉嘟此嘟文以分享給您的跟隨者們。", + "interaction_modal.description.reblog": "若於 Mastodon 上有個帳號,您可以轉嘟此嘟文以向您的跟隨者們分享。", "interaction_modal.description.reply": "若於 Mastodon 上有個帳號,您可以回覆此嘟文。", "interaction_modal.login.action": "返回首頁", "interaction_modal.login.prompt": "您帳號所屬伺服器之網域,例如:mastodon.social", @@ -443,6 +443,8 @@ "mute_modal.title": "是否靜音該使用者?", "mute_modal.you_wont_see_mentions": "您不會見到提及他們的嘟文。", "mute_modal.you_wont_see_posts": "他們仍可讀取您的嘟文,但您不會見到他們的。", + "name_and_others": "{name} 與 {count, plural, other {# 個人}}", + "name_and_others_with_link": "{name} 與 {count, plural, other {# 個人}}", "navigation_bar.about": "關於", "navigation_bar.advanced_interface": "以進階網頁介面開啟", "navigation_bar.blocks": "已封鎖的使用者", @@ -470,6 +472,10 @@ "navigation_bar.security": "安全性", "not_signed_in_indicator.not_signed_in": "您需要登入才能存取此資源。", "notification.admin.report": "{name} 已檢舉 {target}", + "notification.admin.report_account": "{name} 已檢舉來自 {target} 關於 {category} 之 {count, plural, other {# 則嘟文}} ", + "notification.admin.report_account_other": "{name} 已檢舉來自 {target} 之 {count, plural, other {# 則嘟文}} ", + "notification.admin.report_statuses": "{name} 已檢舉 {target} 關於 {category}", + "notification.admin.report_statuses_other": "{name} 已檢舉 {target}", "notification.admin.sign_up": "{name} 已經註冊", "notification.favourite": "{name} 已將您的嘟文加入最愛", "notification.follow": "{name} 已跟隨您", @@ -486,6 +492,7 @@ "notification.moderation_warning.action_suspend": "您的帳號已被停權。", "notification.own_poll": "您的投票已結束", "notification.poll": "您曾投過的投票已經結束", + "notification.private_mention": "{name} 私訊您", "notification.reblog": "{name} 已轉嘟您的嘟文", "notification.relationships_severance_event": "與 {name} 失去連結", "notification.relationships_severance_event.account_suspension": "{from} 之管理員已將 {target} 停權,意味著您將不再收到來自他們的更新或與之互動。", @@ -503,6 +510,8 @@ "notifications.column_settings.admin.report": "新檢舉報告:", "notifications.column_settings.admin.sign_up": "新註冊帳號:", "notifications.column_settings.alert": "桌面通知", + "notifications.column_settings.beta.category": "實驗性功能", + "notifications.column_settings.beta.grouping": "分組通知", "notifications.column_settings.favourite": "最愛:", "notifications.column_settings.filter_bar.advanced": "顯示所有分類", "notifications.column_settings.filter_bar.category": "快速過濾器", @@ -552,7 +561,7 @@ "onboarding.follows.lead": "您的首頁時間軸是 Mastodon 的核心體驗。若您跟隨更多人,它將會變得更活躍有趣。這些個人檔案也許是個好起點,您可以隨時取消跟隨他們!", "onboarding.follows.title": "客製化您的首頁時間軸", "onboarding.profile.discoverable": "使我的個人檔案可以被找到", - "onboarding.profile.discoverable_hint": "當您於 Mastodon 上選擇加入可發現性時,您的嘟文可能會顯示於搜尋結果與趨勢中。您的個人檔案可能會被推薦給與您志趣相投的人。", + "onboarding.profile.discoverable_hint": "當您於 Mastodon 上選擇加入可發現性時,您的嘟文可能會顯示於搜尋結果與趨勢中。您的個人檔案可能會被推薦至與您志趣相投的人。", "onboarding.profile.display_name": "顯示名稱", "onboarding.profile.display_name_hint": "完整名稱或暱稱...", "onboarding.profile.lead": "您隨時可以稍候於設定中完成此操作,將有更多自訂選項可使用。", @@ -666,9 +675,13 @@ "report.unfollow_explanation": "您正在跟隨此帳號。如不欲於首頁時間軸再見到他們的嘟文,請取消跟隨。", "report_notification.attached_statuses": "{count, plural, one {{count} 則} other {{count} 則}} 嘟文", "report_notification.categories.legal": "合法性", + "report_notification.categories.legal_sentence": "違法內容", "report_notification.categories.other": "其他", + "report_notification.categories.other_sentence": "其他", "report_notification.categories.spam": "垃圾訊息", + "report_notification.categories.spam_sentence": "垃圾訊息", "report_notification.categories.violation": "違反規則", + "report_notification.categories.violation_sentence": "違反規則", "report_notification.open": "開啟檢舉報告", "search.no_recent_searches": "尚無最近的搜尋紀錄", "search.placeholder": "搜尋", @@ -797,7 +810,7 @@ "upload_modal.applying": "正在套用...", "upload_modal.choose_image": "選擇圖片", "upload_modal.description_placeholder": "我能吞下玻璃而不傷身體", - "upload_modal.detect_text": "從圖片中偵測文字", + "upload_modal.detect_text": "自圖片中偵測文字", "upload_modal.edit_media": "編輯媒體", "upload_modal.hint": "於預覽中點擊或拖曳圓圈以選擇將於所有縮圖中顯示的焦點。", "upload_modal.preparing_ocr": "準備 OCR 中……", diff --git a/app/javascript/mastodon/models/notification_group.ts b/app/javascript/mastodon/models/notification_group.ts new file mode 100644 index 00000000000000..d9a0504fa11f68 --- /dev/null +++ b/app/javascript/mastodon/models/notification_group.ts @@ -0,0 +1,218 @@ +import type { + ApiAccountRelationshipSeveranceEventJSON, + ApiAccountWarningJSON, + BaseNotificationGroupJSON, + ApiNotificationGroupJSON, + ApiNotificationJSON, + NotificationType, + NotificationWithStatusType, +} from 'mastodon/api_types/notifications'; +import type { ApiReportJSON } from 'mastodon/api_types/reports'; + +// Maximum number of avatars displayed in a notification group +// This corresponds to the max lenght of `group.sampleAccountIds` +export const NOTIFICATIONS_GROUP_MAX_AVATARS = 8; + +interface BaseNotificationGroup + extends Omit { + sampleAccountIds: string[]; +} + +interface BaseNotificationWithStatus + extends BaseNotificationGroup { + type: Type; + statusId: string; +} + +interface BaseNotification + extends BaseNotificationGroup { + type: Type; +} + +export type NotificationGroupFavourite = + BaseNotificationWithStatus<'favourite'>; +export type NotificationGroupEmojiReaction = + BaseNotificationWithStatus<'emoji_reaction'>; +export type NotificationGroupReblog = BaseNotificationWithStatus<'reblog'>; +export type NotificationGroupStatus = BaseNotificationWithStatus<'status'>; +export type NotificationGroupMention = BaseNotificationWithStatus<'mention'>; +export type NotificationGroupStatusReference = + BaseNotificationWithStatus<'status_reference'>; +export type NotificationGroupPoll = BaseNotificationWithStatus<'poll'>; +export type NotificationGroupUpdate = BaseNotificationWithStatus<'update'>; +export type NotificationGroupFollow = BaseNotification<'follow'>; +export type NotificationGroupFollowRequest = BaseNotification<'follow_request'>; +export type NotificationGroupAdminSignUp = BaseNotification<'admin.sign_up'>; + +export type AccountWarningAction = + | 'none' + | 'disable' + | 'force_cw' + | 'mark_statuses_as_sensitive' + | 'delete_statuses' + | 'sensitive' + | 'silence' + | 'suspend'; +export interface AccountWarning + extends Omit { + targetAccountId: string; +} + +export interface NotificationGroupModerationWarning + extends BaseNotification<'moderation_warning'> { + moderationWarning: AccountWarning; +} + +type AccountRelationshipSeveranceEvent = + ApiAccountRelationshipSeveranceEventJSON; +export interface NotificationGroupSeveredRelationships + extends BaseNotification<'severed_relationships'> { + event: AccountRelationshipSeveranceEvent; +} + +interface Report extends Omit { + targetAccountId: string; +} + +export interface NotificationGroupAdminReport + extends BaseNotification<'admin.report'> { + report: Report; +} + +export type NotificationGroup = + | NotificationGroupFavourite + | NotificationGroupEmojiReaction + | NotificationGroupReblog + | NotificationGroupStatus + | NotificationGroupMention + | NotificationGroupStatusReference + | NotificationGroupPoll + | NotificationGroupUpdate + | NotificationGroupFollow + | NotificationGroupFollowRequest + | NotificationGroupModerationWarning + | NotificationGroupSeveredRelationships + | NotificationGroupAdminSignUp + | NotificationGroupAdminReport; + +function createReportFromJSON(reportJSON: ApiReportJSON): Report { + const { target_account, ...report } = reportJSON; + return { + targetAccountId: target_account.id, + ...report, + }; +} + +function createAccountWarningFromJSON( + warningJSON: ApiAccountWarningJSON, +): AccountWarning { + const { target_account, ...warning } = warningJSON; + return { + targetAccountId: target_account.id, + ...warning, + }; +} + +function createAccountRelationshipSeveranceEventFromJSON( + eventJson: ApiAccountRelationshipSeveranceEventJSON, +): AccountRelationshipSeveranceEvent { + return eventJson; +} + +export function createNotificationGroupFromJSON( + groupJson: ApiNotificationGroupJSON, +): NotificationGroup { + const { sample_accounts, ...group } = groupJson; + const sampleAccountIds = sample_accounts.map((account) => account.id); + + switch (group.type) { + case 'favourite': + case 'emoji_reaction': + case 'reblog': + case 'status': + case 'mention': + case 'status_reference': + case 'poll': + case 'update': { + const { status, ...groupWithoutStatus } = group; + return { + statusId: status.id, + sampleAccountIds, + ...groupWithoutStatus, + }; + } + case 'admin.report': { + const { report, ...groupWithoutTargetAccount } = group; + return { + report: createReportFromJSON(report), + sampleAccountIds, + ...groupWithoutTargetAccount, + }; + } + case 'severed_relationships': + return { + ...group, + event: createAccountRelationshipSeveranceEventFromJSON(group.event), + sampleAccountIds, + }; + + case 'moderation_warning': { + const { moderation_warning, ...groupWithoutModerationWarning } = group; + return { + ...groupWithoutModerationWarning, + moderationWarning: createAccountWarningFromJSON(moderation_warning), + sampleAccountIds, + }; + } + default: + return { + sampleAccountIds, + ...group, + }; + } +} + +export function createNotificationGroupFromNotificationJSON( + notification: ApiNotificationJSON, +) { + const group = { + sampleAccountIds: [notification.account.id], + group_key: notification.group_key, + notifications_count: 1, + type: notification.type, + most_recent_notification_id: notification.id, + page_min_id: notification.id, + page_max_id: notification.id, + latest_page_notification_at: notification.created_at, + } as NotificationGroup; + + switch (notification.type) { + case 'favourite': + case 'emoji_reaction': + case 'reblog': + case 'status': + case 'mention': + case 'status_reference': + case 'poll': + case 'update': + return { ...group, statusId: notification.status.id }; + case 'admin.report': + return { ...group, report: createReportFromJSON(notification.report) }; + case 'severed_relationships': + return { + ...group, + event: createAccountRelationshipSeveranceEventFromJSON( + notification.event, + ), + }; + case 'moderation_warning': + return { + ...group, + moderationWarning: createAccountWarningFromJSON( + notification.moderation_warning, + ), + }; + default: + return group; + } +} diff --git a/app/javascript/mastodon/reducers/index.ts b/app/javascript/mastodon/reducers/index.ts index 003ab99ab4f5f5..46cbb4830628ac 100644 --- a/app/javascript/mastodon/reducers/index.ts +++ b/app/javascript/mastodon/reducers/index.ts @@ -33,6 +33,7 @@ import { markersReducer } from './markers'; import media_attachments from './media_attachments'; import meta from './meta'; import { modalReducer } from './modal'; +import { notificationGroupsReducer } from './notification_groups'; import { notificationPolicyReducer } from './notification_policy'; import { notificationRequestsReducer } from './notification_requests'; import notifications from './notifications'; @@ -75,6 +76,7 @@ const reducers = { search, media_attachments, notifications, + notificationGroups: notificationGroupsReducer, height_cache, custom_emojis, lists, diff --git a/app/javascript/mastodon/reducers/markers.ts b/app/javascript/mastodon/reducers/markers.ts index ec85d0f17328cb..b1f10b5fa23a92 100644 --- a/app/javascript/mastodon/reducers/markers.ts +++ b/app/javascript/mastodon/reducers/markers.ts @@ -1,6 +1,7 @@ import { createReducer } from '@reduxjs/toolkit'; -import { submitMarkersAction } from 'mastodon/actions/markers'; +import { submitMarkersAction, fetchMarkers } from 'mastodon/actions/markers'; +import { compareId } from 'mastodon/compare_id'; const initialState = { home: '0', @@ -15,4 +16,23 @@ export const markersReducer = createReducer(initialState, (builder) => { if (notifications) state.notifications = notifications; }, ); + builder.addCase( + fetchMarkers.fulfilled, + ( + state, + { + payload: { + markers: { home, notifications }, + }, + }, + ) => { + if (home && compareId(home.last_read_id, state.home) > 0) + state.home = home.last_read_id; + if ( + notifications && + compareId(notifications.last_read_id, state.notifications) > 0 + ) + state.notifications = notifications.last_read_id; + }, + ); }); diff --git a/app/javascript/mastodon/reducers/notification_groups.ts b/app/javascript/mastodon/reducers/notification_groups.ts new file mode 100644 index 00000000000000..e59f3e7ca11b57 --- /dev/null +++ b/app/javascript/mastodon/reducers/notification_groups.ts @@ -0,0 +1,508 @@ +import { createReducer, isAnyOf } from '@reduxjs/toolkit'; + +import { + authorizeFollowRequestSuccess, + blockAccountSuccess, + muteAccountSuccess, + rejectFollowRequestSuccess, +} from 'mastodon/actions/accounts_typed'; +import { focusApp, unfocusApp } from 'mastodon/actions/app'; +import { blockDomainSuccess } from 'mastodon/actions/domain_blocks_typed'; +import { fetchMarkers } from 'mastodon/actions/markers'; +import { + clearNotifications, + fetchNotifications, + fetchNotificationsGap, + processNewNotificationForGroups, + loadPending, + updateScrollPosition, + markNotificationsAsRead, + mountNotifications, + unmountNotifications, +} from 'mastodon/actions/notification_groups'; +import { + disconnectTimeline, + timelineDelete, +} from 'mastodon/actions/timelines_typed'; +import type { ApiNotificationJSON } from 'mastodon/api_types/notifications'; +import { compareId } from 'mastodon/compare_id'; +import { usePendingItems } from 'mastodon/initial_state'; +import { + NOTIFICATIONS_GROUP_MAX_AVATARS, + createNotificationGroupFromJSON, + createNotificationGroupFromNotificationJSON, +} from 'mastodon/models/notification_group'; +import type { NotificationGroup } from 'mastodon/models/notification_group'; + +const NOTIFICATIONS_TRIM_LIMIT = 50; + +export interface NotificationGap { + type: 'gap'; + maxId?: string; + sinceId?: string; +} + +interface NotificationGroupsState { + groups: (NotificationGroup | NotificationGap)[]; + pendingGroups: (NotificationGroup | NotificationGap)[]; + scrolledToTop: boolean; + isLoading: boolean; + lastReadId: string; + mounted: number; + isTabVisible: boolean; +} + +const initialState: NotificationGroupsState = { + groups: [], + pendingGroups: [], // holds pending groups in slow mode + scrolledToTop: false, + isLoading: false, + // The following properties are used to track unread notifications + lastReadId: '0', // used for unread notifications + mounted: 0, // number of mounted notification list components, usually 0 or 1 + isTabVisible: true, +}; + +function filterNotificationsForAccounts( + groups: NotificationGroupsState['groups'], + accountIds: string[], + onlyForType?: string, +) { + groups = groups + .map((group) => { + if ( + group.type !== 'gap' && + (!onlyForType || group.type === onlyForType) + ) { + const previousLength = group.sampleAccountIds.length; + + group.sampleAccountIds = group.sampleAccountIds.filter( + (id) => !accountIds.includes(id), + ); + + const newLength = group.sampleAccountIds.length; + const removed = previousLength - newLength; + + group.notifications_count -= removed; + } + + return group; + }) + .filter( + (group) => group.type === 'gap' || group.sampleAccountIds.length > 0, + ); + mergeGaps(groups); + return groups; +} + +function filterNotificationsForStatus( + groups: NotificationGroupsState['groups'], + statusId: string, +) { + groups = groups.filter( + (group) => + group.type === 'gap' || + !('statusId' in group) || + group.statusId !== statusId, + ); + mergeGaps(groups); + return groups; +} + +function removeNotificationsForAccounts( + state: NotificationGroupsState, + accountIds: string[], + onlyForType?: string, +) { + state.groups = filterNotificationsForAccounts( + state.groups, + accountIds, + onlyForType, + ); + state.pendingGroups = filterNotificationsForAccounts( + state.pendingGroups, + accountIds, + onlyForType, + ); +} + +function removeNotificationsForStatus( + state: NotificationGroupsState, + statusId: string, +) { + state.groups = filterNotificationsForStatus(state.groups, statusId); + state.pendingGroups = filterNotificationsForStatus( + state.pendingGroups, + statusId, + ); +} + +function isNotificationGroup( + groupOrGap: NotificationGroup | NotificationGap, +): groupOrGap is NotificationGroup { + return groupOrGap.type !== 'gap'; +} + +// Merge adjacent gaps in `groups` in-place +function mergeGaps(groups: NotificationGroupsState['groups']) { + for (let i = 0; i < groups.length; i++) { + const firstGroupOrGap = groups[i]; + + if (firstGroupOrGap?.type === 'gap') { + let lastGap = firstGroupOrGap; + let j = i + 1; + + for (; j < groups.length; j++) { + const groupOrGap = groups[j]; + if (groupOrGap?.type === 'gap') lastGap = groupOrGap; + else break; + } + + if (j - i > 1) { + groups.splice(i, j - i, { + type: 'gap', + maxId: firstGroupOrGap.maxId, + sinceId: lastGap.sinceId, + }); + } + } + } +} + +// Checks if `groups[index-1]` and `groups[index]` are gaps, and merge them in-place if they are +function mergeGapsAround( + groups: NotificationGroupsState['groups'], + index: number, +) { + if (index > 0) { + const potentialFirstGap = groups[index - 1]; + const potentialSecondGap = groups[index]; + + if ( + potentialFirstGap?.type === 'gap' && + potentialSecondGap?.type === 'gap' + ) { + groups.splice(index - 1, 2, { + type: 'gap', + maxId: potentialFirstGap.maxId, + sinceId: potentialSecondGap.sinceId, + }); + } + } +} + +function processNewNotification( + groups: NotificationGroupsState['groups'], + notification: ApiNotificationJSON, +) { + const existingGroupIndex = groups.findIndex( + (group) => + group.type !== 'gap' && group.group_key === notification.group_key, + ); + + // In any case, we are going to add a group at the top + // If there is currently a gap at the top, now is the time to update it + if (groups.length > 0 && groups[0]?.type === 'gap') { + groups[0].maxId = notification.id; + } + + if (existingGroupIndex > -1) { + const existingGroup = groups[existingGroupIndex]; + + if ( + existingGroup && + existingGroup.type !== 'gap' && + !existingGroup.sampleAccountIds.includes(notification.account.id) // This can happen for example if you like, then unlike, then like again the same post + ) { + // Update the existing group + if ( + existingGroup.sampleAccountIds.unshift(notification.account.id) > + NOTIFICATIONS_GROUP_MAX_AVATARS + ) + existingGroup.sampleAccountIds.pop(); + + existingGroup.most_recent_notification_id = notification.id; + existingGroup.page_max_id = notification.id; + existingGroup.latest_page_notification_at = notification.created_at; + existingGroup.notifications_count += 1; + + groups.splice(existingGroupIndex, 1); + mergeGapsAround(groups, existingGroupIndex); + + groups.unshift(existingGroup); + } + } else { + // Create a new group + groups.unshift(createNotificationGroupFromNotificationJSON(notification)); + } +} + +function trimNotifications(state: NotificationGroupsState) { + if (state.scrolledToTop) { + state.groups.splice(NOTIFICATIONS_TRIM_LIMIT); + } +} + +function shouldMarkNewNotificationsAsRead( + { + isTabVisible, + scrolledToTop, + mounted, + lastReadId, + groups, + }: NotificationGroupsState, + ignoreScroll = false, +) { + const isMounted = mounted > 0; + const oldestGroup = groups.findLast(isNotificationGroup); + const hasMore = groups.at(-1)?.type === 'gap'; + const oldestGroupReached = + !hasMore || + lastReadId === '0' || + (oldestGroup?.page_min_id && + compareId(oldestGroup.page_min_id, lastReadId) <= 0); + + return ( + isTabVisible && + (ignoreScroll || scrolledToTop) && + isMounted && + oldestGroupReached + ); +} + +function updateLastReadId( + state: NotificationGroupsState, + group: NotificationGroup | undefined = undefined, +) { + if (shouldMarkNewNotificationsAsRead(state)) { + group = group ?? state.groups.find(isNotificationGroup); + if ( + group?.page_max_id && + compareId(state.lastReadId, group.page_max_id) < 0 + ) + state.lastReadId = group.page_max_id; + } +} + +export const notificationGroupsReducer = createReducer( + initialState, + (builder) => { + builder + .addCase(fetchNotifications.fulfilled, (state, action) => { + state.groups = action.payload.map((json) => + json.type === 'gap' ? json : createNotificationGroupFromJSON(json), + ); + state.isLoading = false; + updateLastReadId(state); + }) + .addCase(fetchNotificationsGap.fulfilled, (state, action) => { + const { notifications } = action.payload; + + // find the gap in the existing notifications + const gapIndex = state.groups.findIndex( + (groupOrGap) => + groupOrGap.type === 'gap' && + groupOrGap.sinceId === action.meta.arg.gap.sinceId && + groupOrGap.maxId === action.meta.arg.gap.maxId, + ); + + if (gapIndex < 0) + // We do not know where to insert, let's return + return; + + // Filling a disconnection gap means we're getting historical data + // about groups we may know or may not know about. + + // The notifications timeline is split in two by the gap, with + // group information newer than the gap, and group information older + // than the gap. + + // Filling a gap should not touch anything before the gap, so any + // information on groups already appearing before the gap should be + // discarded, while any information on groups appearing after the gap + // can be updated and re-ordered. + + const oldestPageNotification = notifications.at(-1)?.page_min_id; + + // replace the gap with the notifications + a new gap + + const newerGroupKeys = state.groups + .slice(0, gapIndex) + .filter(isNotificationGroup) + .map((group) => group.group_key); + + const toInsert: NotificationGroupsState['groups'] = notifications + .map((json) => createNotificationGroupFromJSON(json)) + .filter( + (notification) => !newerGroupKeys.includes(notification.group_key), + ); + + const apiGroupKeys = (toInsert as NotificationGroup[]).map( + (group) => group.group_key, + ); + + const sinceId = action.meta.arg.gap.sinceId; + if ( + notifications.length > 0 && + !( + oldestPageNotification && + sinceId && + compareId(oldestPageNotification, sinceId) <= 0 + ) + ) { + // If we get an empty page, it means we reached the bottom, so we do not need to insert a new gap + // Similarly, if we've fetched more than the gap's, this means we have completely filled it + toInsert.push({ + type: 'gap', + maxId: notifications.at(-1)?.page_max_id, + sinceId, + } as NotificationGap); + } + + // Remove older groups covered by the API + state.groups = state.groups.filter( + (groupOrGap) => + groupOrGap.type !== 'gap' && + !apiGroupKeys.includes(groupOrGap.group_key), + ); + + // Replace the gap with API results (+ the new gap if needed) + state.groups.splice(gapIndex, 1, ...toInsert); + + // Finally, merge any adjacent gaps that could have been created by filtering + // groups earlier + mergeGaps(state.groups); + + state.isLoading = false; + + updateLastReadId(state); + }) + .addCase(processNewNotificationForGroups.fulfilled, (state, action) => { + const notification = action.payload; + processNewNotification( + usePendingItems ? state.pendingGroups : state.groups, + notification, + ); + updateLastReadId(state); + trimNotifications(state); + }) + .addCase(disconnectTimeline, (state, action) => { + if (action.payload.timeline === 'home') { + if (state.groups.length > 0 && state.groups[0]?.type !== 'gap') { + state.groups.unshift({ + type: 'gap', + sinceId: state.groups[0]?.page_min_id, + }); + } + } + }) + .addCase(timelineDelete, (state, action) => { + removeNotificationsForStatus(state, action.payload.statusId); + }) + .addCase(clearNotifications.pending, (state) => { + state.groups = []; + state.pendingGroups = []; + }) + .addCase(blockAccountSuccess, (state, action) => { + removeNotificationsForAccounts(state, [action.payload.relationship.id]); + }) + .addCase(muteAccountSuccess, (state, action) => { + if (action.payload.relationship.muting_notifications) + removeNotificationsForAccounts(state, [ + action.payload.relationship.id, + ]); + }) + .addCase(blockDomainSuccess, (state, action) => { + removeNotificationsForAccounts( + state, + action.payload.accounts.map((account) => account.id), + ); + }) + .addCase(loadPending, (state) => { + // First, remove any existing group and merge data + state.pendingGroups.forEach((group) => { + if (group.type !== 'gap') { + const existingGroupIndex = state.groups.findIndex( + (groupOrGap) => + isNotificationGroup(groupOrGap) && + groupOrGap.group_key === group.group_key, + ); + if (existingGroupIndex > -1) { + const existingGroup = state.groups[existingGroupIndex]; + if (existingGroup && existingGroup.type !== 'gap') { + group.notifications_count += existingGroup.notifications_count; + group.sampleAccountIds = group.sampleAccountIds + .concat(existingGroup.sampleAccountIds) + .slice(0, NOTIFICATIONS_GROUP_MAX_AVATARS); + state.groups.splice(existingGroupIndex, 1); + } + } + } + trimNotifications(state); + }); + + // Then build the consolidated list and clear pending groups + state.groups = state.pendingGroups.concat(state.groups); + state.pendingGroups = []; + }) + .addCase(updateScrollPosition, (state, action) => { + state.scrolledToTop = action.payload.top; + updateLastReadId(state); + trimNotifications(state); + }) + .addCase(markNotificationsAsRead, (state) => { + const mostRecentGroup = state.groups.find(isNotificationGroup); + if ( + mostRecentGroup?.page_max_id && + compareId(state.lastReadId, mostRecentGroup.page_max_id) < 0 + ) + state.lastReadId = mostRecentGroup.page_max_id; + }) + .addCase(fetchMarkers.fulfilled, (state, action) => { + if ( + action.payload.markers.notifications && + compareId( + state.lastReadId, + action.payload.markers.notifications.last_read_id, + ) < 0 + ) + state.lastReadId = action.payload.markers.notifications.last_read_id; + }) + .addCase(mountNotifications, (state) => { + state.mounted += 1; + updateLastReadId(state); + }) + .addCase(unmountNotifications, (state) => { + state.mounted -= 1; + }) + .addCase(focusApp, (state) => { + state.isTabVisible = true; + updateLastReadId(state); + }) + .addCase(unfocusApp, (state) => { + state.isTabVisible = false; + }) + .addMatcher( + isAnyOf(authorizeFollowRequestSuccess, rejectFollowRequestSuccess), + (state, action) => { + removeNotificationsForAccounts( + state, + [action.payload.id], + 'follow_request', + ); + }, + ) + .addMatcher( + isAnyOf(fetchNotifications.pending, fetchNotificationsGap.pending), + (state) => { + state.isLoading = true; + }, + ) + .addMatcher( + isAnyOf(fetchNotifications.rejected, fetchNotificationsGap.rejected), + (state) => { + state.isLoading = false; + }, + ); + }, +); diff --git a/app/javascript/mastodon/reducers/notifications.js b/app/javascript/mastodon/reducers/notifications.js index d6dac2fc2a903f..8bed97024c4e4c 100644 --- a/app/javascript/mastodon/reducers/notifications.js +++ b/app/javascript/mastodon/reducers/notifications.js @@ -16,13 +16,13 @@ import { import { fetchMarkers, } from '../actions/markers'; +import { clearNotifications } from '../actions/notification_groups'; import { notificationsUpdate, NOTIFICATIONS_EXPAND_SUCCESS, NOTIFICATIONS_EXPAND_REQUEST, NOTIFICATIONS_EXPAND_FAIL, NOTIFICATIONS_FILTER_SET, - NOTIFICATIONS_CLEAR, NOTIFICATIONS_SCROLL_TOP, NOTIFICATIONS_LOAD_PENDING, NOTIFICATIONS_MOUNT, @@ -292,7 +292,7 @@ export default function notifications(state = initialState, action) { case authorizeFollowRequestSuccess.type: case rejectFollowRequestSuccess.type: return filterNotifications(state, [action.payload.id], 'follow_request'); - case NOTIFICATIONS_CLEAR: + case clearNotifications.pending.type: return state.set('items', ImmutableList()).set('pendingItems', ImmutableList()).set('hasMore', false); case timelineDelete.type: return deleteByStatus(state, action.payload.statusId); diff --git a/app/javascript/mastodon/selectors/notifications.ts b/app/javascript/mastodon/selectors/notifications.ts new file mode 100644 index 00000000000000..1b1ed2154cdaa7 --- /dev/null +++ b/app/javascript/mastodon/selectors/notifications.ts @@ -0,0 +1,34 @@ +import { createSelector } from '@reduxjs/toolkit'; + +import { compareId } from 'mastodon/compare_id'; +import type { RootState } from 'mastodon/store'; + +export const selectUnreadNotificationGroupsCount = createSelector( + [ + (s: RootState) => s.notificationGroups.lastReadId, + (s: RootState) => s.notificationGroups.pendingGroups, + (s: RootState) => s.notificationGroups.groups, + ], + (notificationMarker, pendingGroups, groups) => { + return ( + groups.filter( + (group) => + group.type !== 'gap' && + group.page_max_id && + compareId(group.page_max_id, notificationMarker) > 0, + ).length + + pendingGroups.filter( + (group) => + group.type !== 'gap' && + group.page_max_id && + compareId(group.page_max_id, notificationMarker) > 0, + ).length + ); + }, +); + +export const selectPendingNotificationGroupsCount = createSelector( + [(s: RootState) => s.notificationGroups.pendingGroups], + (pendingGroups) => + pendingGroups.filter((group) => group.type !== 'gap').length, +); diff --git a/app/javascript/mastodon/selectors/settings.ts b/app/javascript/mastodon/selectors/settings.ts new file mode 100644 index 00000000000000..64d9440bc8d3b0 --- /dev/null +++ b/app/javascript/mastodon/selectors/settings.ts @@ -0,0 +1,40 @@ +import type { RootState } from 'mastodon/store'; + +/* eslint-disable @typescript-eslint/no-unsafe-call, @typescript-eslint/no-unsafe-member-access */ +// state.settings is not yet typed, so we disable some ESLint checks for those selectors +export const selectSettingsNotificationsShows = (state: RootState) => + state.settings.getIn(['notifications', 'shows']).toJS() as Record< + string, + boolean + >; + +export const selectSettingsNotificationsExcludedTypes = (state: RootState) => + Object.entries(selectSettingsNotificationsShows(state)) + .filter(([_type, enabled]) => !enabled) + .map(([type, _enabled]) => type); + +export const selectSettingsNotificationsQuickFilterShow = (state: RootState) => + state.settings.getIn(['notifications', 'quickFilter', 'show']) as boolean; + +export const selectSettingsNotificationsQuickFilterActive = ( + state: RootState, +) => state.settings.getIn(['notifications', 'quickFilter', 'active']) as string; + +export const selectSettingsNotificationsQuickFilterAdvanced = ( + state: RootState, +) => + state.settings.getIn(['notifications', 'quickFilter', 'advanced']) as boolean; + +export const selectSettingsNotificationsShowUnread = (state: RootState) => + state.settings.getIn(['notifications', 'showUnread']) as boolean; + +export const selectNeedsNotificationPermission = (state: RootState) => + (state.settings.getIn(['notifications', 'alerts']).includes(true) && + state.notifications.get('browserSupport') && + state.notifications.get('browserPermission') === 'default' && + !state.settings.getIn([ + 'notifications', + 'dismissPermissionBanner', + ])) as boolean; + +/* eslint-enable @typescript-eslint/no-unsafe-call, @typescript-eslint/no-unsafe-member-access */ diff --git a/app/javascript/styles/mastodon-light/diff.scss b/app/javascript/styles/mastodon-light/diff.scss index a41272364a3106..635bab546018b2 100644 --- a/app/javascript/styles/mastodon-light/diff.scss +++ b/app/javascript/styles/mastodon-light/diff.scss @@ -23,7 +23,7 @@ html { // Change default background colors of columns .interaction-modal { background: $white; - border: 1px solid lighten($ui-base-color, 8%); + border: 1px solid var(--background-border-color); } .rules-list li::before { @@ -75,8 +75,8 @@ html { } .getting-started .navigation-bar { - border-top: 1px solid lighten($ui-base-color, 8%); - border-bottom: 1px solid lighten($ui-base-color, 8%); + border-top: 1px solid var(--background-border-color); + border-bottom: 1px solid var(--background-border-color); @media screen and (max-width: $no-gap-breakpoint) { border-top: 0; @@ -88,7 +88,7 @@ html { .setting-text, .report-dialog-modal__textarea, .audio-player { - border: 1px solid lighten($ui-base-color, 8%); + border: 1px solid var(--background-border-color); } .report-dialog-modal .dialog-option .poll__input { @@ -140,7 +140,6 @@ html { .actions-modal ul li:not(:empty) a:focus button, .actions-modal ul li:not(:empty) a:hover, .actions-modal ul li:not(:empty) a:hover button, -.admin-wrapper .sidebar ul .simple-navigation-active-leaf a, .simple_form .block-button, .simple_form .button, .simple_form button { @@ -175,7 +174,7 @@ html { .picture-in-picture__footer, .reactions-bar__item { background: $white; - border: 1px solid lighten($ui-base-color, 8%); + border: 1px solid var(--background-border-color); } .reactions-bar__item:hover, @@ -217,7 +216,7 @@ html { .column-header__collapsible-inner { background: darken($ui-base-color, 4%); - border: 1px solid lighten($ui-base-color, 8%); + border: 1px solid var(--background-border-color); border-bottom: 0; } @@ -259,7 +258,7 @@ html { .embed-modal .embed-modal__container .embed-modal__html { background: $white; - border: 1px solid lighten($ui-base-color, 8%); + border: 1px solid var(--background-border-color); &:focus { border-color: lighten($ui-base-color, 12%); @@ -298,7 +297,7 @@ html { .directory__tag > a, .directory__tag > div { background: $white; - border: 1px solid lighten($ui-base-color, 8%); + border: 1px solid var(--background-border-color); @media screen and (max-width: $no-gap-breakpoint) { border-left: 0; @@ -307,18 +306,6 @@ html { } } -.simple_form { - input[type='text'], - input[type='number'], - input[type='email'], - input[type='password'], - textarea { - &:hover { - border-color: lighten($ui-base-color, 12%); - } - } -} - .picture-in-picture-placeholder { background: $white; border-color: lighten($ui-base-color, 8%); @@ -346,7 +333,7 @@ html { } .activity-stream { - border: 1px solid lighten($ui-base-color, 8%); + border: 1px solid var(--background-border-color); &--under-tabs { border-top: 0; @@ -411,6 +398,22 @@ html { color: $ui-highlight-color; background-color: rgba($ui-highlight-color, 0.1); } + + input[type='text'], + input[type='number'], + input[type='email'], + input[type='password'], + input[type='url'], + input[type='datetime-local'], + textarea { + background: darken($ui-base-color, 10%); + } + + select { + background: darken($ui-base-color, 10%) + url("data:image/svg+xml;utf8,") + no-repeat right 8px center / auto 14px; + } } .compose-form .compose-form__warning { @@ -449,8 +452,24 @@ html { box-shadow: none; } +.card { + &__img { + background: darken($ui-base-color, 10%); + } + + & > a { + &:hover, + &:active, + &:focus { + .card__bar { + background: darken($ui-base-color, 10%); + } + } + } +} + .mute-modal select { - border: 1px solid lighten($ui-base-color, 8%); + border: 1px solid var(--background-border-color); background: $simple-background-color url("data:image/svg+xml;utf8,") no-repeat right 8px center / auto 16px; @@ -491,6 +510,7 @@ html { .search__popout, .emoji-mart-search input, .language-dropdown__dropdown .emoji-mart-search input, +// .strike-card, .poll__option input[type='text'] { background: darken($ui-base-color, 10%); } @@ -507,3 +527,43 @@ html { .inline-follow-suggestions__body__scroll-button__icon { color: $white; } + +a.sparkline { + &:hover, + &:focus, + &:active { + background: darken($ui-base-color, 10%); + } +} + +.dashboard__counters { + & > div { + & > a { + &:hover, + &:focus, + &:active { + background: darken($ui-base-color, 10%); + } + } + } +} + +.directory { + &__tag { + & > a { + &:hover, + &:focus, + &:active { + background: darken($ui-base-color, 10%); + } + } + } +} + +.strike-entry { + &:hover, + &:focus, + &:active { + background: darken($ui-base-color, 10%); + } +} diff --git a/app/javascript/styles/mastodon/accounts.scss b/app/javascript/styles/mastodon/accounts.scss index 0ed434939f4199..a86b86ac21e9c0 100644 --- a/app/javascript/styles/mastodon/accounts.scss +++ b/app/javascript/styles/mastodon/accounts.scss @@ -10,7 +10,7 @@ &:active, &:focus { .card__bar { - background: lighten($ui-base-color, 8%); + background: $ui-base-color; } } } @@ -18,7 +18,9 @@ &__img { height: 130px; position: relative; - background: darken($ui-base-color, 12%); + background: $ui-base-color; + border: 1px solid var(--background-border-color); + border-bottom: none; img { display: block; @@ -39,7 +41,9 @@ display: flex; justify-content: flex-start; align-items: center; - background: lighten($ui-base-color, 4%); + background: var(--background-color); + border: 1px solid var(--background-border-color); + border-top: none; .avatar { flex: 0 0 auto; diff --git a/app/javascript/styles/mastodon/admin.scss b/app/javascript/styles/mastodon/admin.scss index ddb601c399b29b..58f1b9ca453cef 100644 --- a/app/javascript/styles/mastodon/admin.scss +++ b/app/javascript/styles/mastodon/admin.scss @@ -1,7 +1,7 @@ @use 'sass:math'; $no-columns-breakpoint: 600px; -$sidebar-width: 240px; +$sidebar-width: 300px; $content-width: 840px; .admin-wrapper { @@ -26,7 +26,7 @@ $content-width: 840px; &__inner { display: flex; justify-content: flex-end; - background: $ui-base-color; + background: var(--background-color); height: 100%; } } @@ -38,7 +38,7 @@ $content-width: 840px; &__toggle { display: none; - background: darken($ui-base-color, 4%); + background: var(--background-color); border-bottom: 1px solid lighten($ui-base-color, 4%); align-items: center; @@ -103,7 +103,6 @@ $content-width: 840px; ul { list-style: none; - border-radius: 4px 0 0 4px; overflow: hidden; margin-bottom: 20px; @@ -112,13 +111,13 @@ $content-width: 840px; } a { + font-size: 14px; display: block; padding: 15px; color: $darker-text-color; text-decoration: none; transition: all 200ms linear; transition-property: color, background-color; - border-radius: 4px 0 0 4px; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; @@ -129,19 +128,13 @@ $content-width: 840px; &:hover { color: $primary-text-color; - background-color: darken($ui-base-color, 5%); transition: all 100ms linear; transition-property: color, background-color; } - - &.selected { - border-radius: 4px 0 0; - } } ul { - background: darken($ui-base-color, 4%); - border-radius: 0 0 0 4px; + background: var(--background-color); margin: 0; a { @@ -156,16 +149,10 @@ $content-width: 840px; } .simple-navigation-active-leaf a { - color: $primary-text-color; - background-color: $ui-highlight-color; + color: $highlight-text-color; border-bottom: 0; - border-radius: 0; } } - - & > ul > .simple-navigation-active-leaf a { - border-radius: 4px 0 0 4px; - } } .content-wrapper { @@ -299,7 +286,7 @@ $content-width: 840px; color: $darker-text-color; padding-bottom: 8px; margin-bottom: 8px; - border-bottom: 1px solid lighten($ui-base-color, 8%); + border-bottom: 1px solid var(--background-border-color); } h6 { @@ -372,7 +359,7 @@ $content-width: 840px; width: 100%; height: 0; border: 0; - border-bottom: 1px solid rgba($ui-base-lighter-color, 0.6); + border-bottom: 1px solid var(--background-border-color); margin: 20px 0; &.spacer { @@ -410,14 +397,14 @@ $content-width: 840px; inset-inline-start: 0; bottom: 0; overflow-y: auto; - background: $ui-base-color; + background: var(--background-color); } } ul a, ul ul a { + font-size: 16px; border-radius: 0; - border-bottom: 1px solid lighten($ui-base-color, 4%); transition: none; &:hover { @@ -683,8 +670,10 @@ body, line-height: 20px; padding: 15px; padding-inline-start: 15px * 2 + 40px; - background: $ui-base-color; - border-bottom: 1px solid darken($ui-base-color, 8%); + background: var(--background-color); + border-right: 1px solid var(--background-border-color); + border-left: 1px solid var(--background-border-color); + border-bottom: 1px solid var(--background-border-color); position: relative; text-decoration: none; color: $darker-text-color; @@ -693,18 +682,13 @@ body, &:first-child { border-top-left-radius: 4px; border-top-right-radius: 4px; + border-top: 1px solid var(--background-border-color); } &:last-child { border-bottom-left-radius: 4px; border-bottom-right-radius: 4px; - border-bottom: 0; - } - - &:hover, - &:focus, - &:active { - background: lighten($ui-base-color, 4%); + border-bottom: 1px solid var(--background-border-color); } &__avatar { @@ -744,6 +728,47 @@ body, } } +.strike-entry { + display: block; + line-height: 20px; + padding: 15px; + padding-inline-start: 15px * 2 + 40px; + background: var(--background-color); + border: 1px solid var(--background-border-color); + border-radius: 4px; + position: relative; + text-decoration: none; + color: $darker-text-color; + font-size: 14px; + margin-bottom: 15px; + + &__avatar { + position: absolute; + inset-inline-start: 15px; + top: 15px; + + .avatar { + border-radius: 4px; + width: 40px; + height: 40px; + } + } + + &__title { + word-wrap: break-word; + } + + &__timestamp { + color: $dark-text-color; + } + + &:hover, + &:focus, + &:active { + background: $ui-base-color; + } +} + a.name-tag, .name-tag, a.inline-name-tag, @@ -751,6 +776,10 @@ a.inline-name-tag, text-decoration: none; color: $secondary-text-color; + &:hover { + color: $highlight-text-color; + } + .username { font-weight: 500; } @@ -830,7 +859,8 @@ a.name-tag, } .report-card { - background: $ui-base-color; + background: var(--background-color); + border: 1px solid var(--background-border-color); border-radius: 4px; margin-bottom: 20px; @@ -842,7 +872,6 @@ a.name-tag, .account { padding: 0; - border: 0; &__avatar-wrapper { margin-inline-start: 0; @@ -863,7 +892,7 @@ a.name-tag, &:focus, &:hover, &:active { - color: lighten($darker-text-color, 8%); + color: $highlight-text-color; } } @@ -877,11 +906,7 @@ a.name-tag, &__item { display: flex; justify-content: flex-start; - border-top: 1px solid darken($ui-base-color, 4%); - - &:hover { - background: lighten($ui-base-color, 2%); - } + border-top: 1px solid var(--background-border-color); &__reported-by, &__assigned { @@ -904,7 +929,6 @@ a.name-tag, max-width: calc(100% - 300px); &__icon { - color: $dark-text-color; margin-inline-end: 4px; font-weight: 500; } @@ -917,6 +941,10 @@ a.name-tag, padding: 15px; text-decoration: none; color: $darker-text-color; + + &:hover { + color: $highlight-text-color; + } } } } @@ -952,14 +980,15 @@ a.name-tag, .account__header__fields, .account__header__content { - background: lighten($ui-base-color, 8%); + background: var(--background-color); + border: 1px solid var(--background-border-color); border-radius: 4px; height: 100%; } .account__header__fields { margin: 0; - border: 0; + border: 1px solid var(--background-border-color); a { color: $highlight-text-color; @@ -988,8 +1017,8 @@ a.name-tag, .applications-list__item, .filters-list__item { padding: 15px 0; - background: $ui-base-color; - border: 1px solid lighten($ui-base-color, 4%); + background: var(--background-color); + border: 1px solid var(--background-border-color); border-radius: 4px; margin-top: 15px; } @@ -1000,13 +1029,13 @@ a.name-tag, .announcements-list, .filters-list { - border: 1px solid lighten($ui-base-color, 4%); + border: 1px solid var(--background-border-color); border-radius: 4px; + border-bottom: none; &__item { padding: 15px 0; - background: $ui-base-color; - border-bottom: 1px solid lighten($ui-base-color, 4%); + border-bottom: 1px solid var(--background-border-color); &__title { padding: 0 15px; @@ -1018,6 +1047,10 @@ a.name-tag, text-decoration: none; margin-bottom: 10px; + &:hover { + color: $highlight-text-color; + } + .account-role { vertical-align: middle; } @@ -1056,10 +1089,6 @@ a.name-tag, &__permissions { margin-top: 10px; } - - &:last-child { - border-bottom: 0; - } } } @@ -1116,7 +1145,7 @@ a.name-tag, &__table { &__number { - color: $secondary-text-color; + color: var(--background-color); padding: 10px; } @@ -1143,7 +1172,7 @@ a.name-tag, &__box { box-sizing: border-box; - background: $ui-highlight-color; + background: var(--background-color); padding: 10px; font-weight: 500; color: $primary-text-color; @@ -1165,8 +1194,9 @@ a.name-tag, .sparkline { display: block; text-decoration: none; - background: lighten($ui-base-color, 4%); + background: var(--background-color); border-radius: 4px; + border: 1px solid var(--background-border-color); padding: 0; position: relative; padding-bottom: 55px + 20px; @@ -1238,12 +1268,12 @@ a.sparkline { &:hover, &:focus, &:active { - background: lighten($ui-base-color, 6%); + background: $ui-base-color; } } .skeleton { - background-color: lighten($ui-base-color, 8%); + background-color: var(--background-color); background-image: linear-gradient( 90deg, lighten($ui-base-color, 8%), @@ -1323,17 +1353,13 @@ a.sparkline { .report-reason-selector { border-radius: 4px; - background: $ui-base-color; + background: var(--background-color); margin-bottom: 20px; &__category { cursor: pointer; border-bottom: 1px solid darken($ui-base-color, 8%); - &:last-child { - border-bottom: 0; - } - &__label { padding: 15px; display: flex; @@ -1362,7 +1388,7 @@ a.sparkline { &__details { &__item { - border-bottom: 1px solid lighten($ui-base-color, 8%); + border-bottom: 1px solid var(--background-border-color); padding: 15px 0; &:last-child { @@ -1393,7 +1419,7 @@ a.sparkline { .account-card { border-radius: 4px; - border: 1px solid lighten($ui-base-color, 8%); + border: 1px solid var(--background-border-color); position: relative; &__warning-badge { @@ -1481,7 +1507,6 @@ a.sparkline { position: absolute; bottom: 0; inset-inline-end: 15px; - background: linear-gradient(to left, $ui-base-color, transparent); pointer-events: none; } @@ -1557,11 +1582,11 @@ a.sparkline { margin-bottom: 20px; &__item { - background: $ui-base-color; + background: var(--background-color); position: relative; padding: 15px; padding-inline-start: 15px * 2 + 40px; - border-bottom: 1px solid darken($ui-base-color, 8%); + border: 1px solid var(--background-border-color); &:first-child { border-top-left-radius: 4px; @@ -1571,11 +1596,6 @@ a.sparkline { &:last-child { border-bottom-left-radius: 4px; border-bottom-right-radius: 4px; - border-bottom: 0; - } - - &:hover { - background-color: lighten($ui-base-color, 4%); } &__avatar { @@ -1653,13 +1673,10 @@ a.sparkline { } .report-actions { - border: 1px solid darken($ui-base-color, 8%); - &__item { display: flex; align-items: center; line-height: 18px; - border-bottom: 1px solid darken($ui-base-color, 8%); &:last-child { border-bottom: 0; @@ -1722,8 +1739,6 @@ a.sparkline { .strike-card { padding: 15px; - border-radius: 4px; - background: $ui-base-color; font-size: 15px; line-height: 20px; word-wrap: break-word; @@ -1731,6 +1746,8 @@ a.sparkline { color: $primary-text-color; box-sizing: border-box; min-height: 100%; + border: 1px solid var(--background-border-color); + border-radius: 4px; a { color: $highlight-text-color; @@ -1771,15 +1788,14 @@ a.sparkline { &__statuses-list { border-radius: 4px; - border: 1px solid darken($ui-base-color, 8%); + border: 1px solid var(--background-border-color); font-size: 13px; line-height: 18px; overflow: hidden; &__item { padding: 16px; - background: lighten($ui-base-color, 2%); - border-bottom: 1px solid darken($ui-base-color, 8%); + border-bottom: 1px solid var(--background-border-color); &:last-child { border-bottom: 0; diff --git a/app/javascript/styles/mastodon/basics.scss b/app/javascript/styles/mastodon/basics.scss index 2e7d5e5e9c5287..456e042c535357 100644 --- a/app/javascript/styles/mastodon/basics.scss +++ b/app/javascript/styles/mastodon/basics.scss @@ -122,7 +122,7 @@ body { } &.admin { - background: darken($ui-base-color, 4%); + background: var(--background-color); padding: 0; } diff --git a/app/javascript/styles/mastodon/components.scss b/app/javascript/styles/mastodon/components.scss index c1b42cd398e415..314940e607e2f6 100644 --- a/app/javascript/styles/mastodon/components.scss +++ b/app/javascript/styles/mastodon/components.scss @@ -521,7 +521,7 @@ body > [data-popper-placement] { gap: 16px; flex: 0 1 auto; border-radius: 4px; - border: 1px solid lighten($ui-base-color, 8%); + border: 1px solid var(--background-border-color); transition: border-color 300ms linear; min-height: 0; position: relative; @@ -591,7 +591,7 @@ body > [data-popper-placement] { .autosuggest-input { flex: 1 1 auto; - border-bottom: 1px solid lighten($ui-base-color, 8%); + border-bottom: 1px solid var(--background-border-color); } } @@ -1468,7 +1468,7 @@ body > [data-popper-placement] { } &--first-in-thread { - border-top: 1px solid lighten($ui-base-color, 8%); + border-top: 1px solid var(--background-border-color); } &__line { @@ -1627,14 +1627,19 @@ body > [data-popper-placement] { } } -.status__wrapper-direct { +.status__wrapper-direct, +.notification-ungrouped--direct { background: rgba($ui-highlight-color, 0.05); &:focus { - background: rgba($ui-highlight-color, 0.05); + background: rgba($ui-highlight-color, 0.1); } +} - .status__prepend { +.status__wrapper-direct, +.notification-ungrouped--direct { + .status__prepend, + .notification-ungrouped__header { color: $highlight-text-color; } } @@ -1859,7 +1864,6 @@ body > [data-popper-placement] { .account { padding: 16px; - border-bottom: 1px solid var(--background-border-color); .account__display-name { flex: 1 1 auto; @@ -2284,41 +2288,28 @@ a.account__display-name { } } -.notification__relationships-severance-event, -.notification__moderation-warning { - display: flex; - gap: 16px; +.notification-group--link { color: $secondary-text-color; text-decoration: none; - align-items: flex-start; - padding: 16px 32px; - border-bottom: 1px solid var(--background-border-color); - - &:hover { - color: $primary-text-color; - } - .icon { - padding: 2px; - color: $highlight-text-color; - } - - &__content { + .notification-group__main { display: flex; flex-direction: column; align-items: flex-start; gap: 8px; flex-grow: 1; - font-size: 16px; - line-height: 24px; + font-size: 15px; + line-height: 22px; - strong { + strong, + bdi { font-weight: 700; } .link-button { font-size: inherit; line-height: inherit; + font-weight: inherit; } } } @@ -3427,7 +3418,7 @@ $ui-header-logo-wordmark-width: 99px; .copy-paste-text { background: lighten($ui-base-color, 4%); border-radius: 8px; - border: 1px solid lighten($ui-base-color, 8%); + border: 1px solid var(--background-border-color); padding: 16px; color: $primary-text-color; font-size: 15px; @@ -4889,7 +4880,7 @@ a.status-card { section { padding: 16px; - border-bottom: 1px solid lighten($ui-base-color, 8%); + border-bottom: 1px solid var(--background-border-color); &:last-child { border-bottom: 0; @@ -5604,7 +5595,7 @@ a.status-card { input { padding: 8px 12px; background: $ui-base-color; - border: 1px solid lighten($ui-base-color, 8%); + border: 1px solid var(--background-border-color); color: $darker-text-color; @media screen and (width <= 600px) { @@ -5690,7 +5681,7 @@ a.status-card { margin-top: -2px; width: 100%; background: $ui-base-color; - border: 1px solid lighten($ui-base-color, 8%); + border: 1px solid var(--background-border-color); border-radius: 0 0 4px 4px; box-shadow: var(--dropdown-shadow); z-index: 99; @@ -7690,6 +7681,11 @@ a.status-card { display: flex; flex-shrink: 0; + @media screen and (max-width: $no-gap-breakpoint) { + border-right: 0; + border-left: 0; + } + button { background: transparent; border: 0; @@ -9229,13 +9225,13 @@ noscript { } .search__input { - border: 1px solid lighten($ui-base-color, 8%); + border: 1px solid var(--background-border-color); padding: 10px; padding-inline-end: 30px; } .search__popout { - border: 1px solid lighten($ui-base-color, 8%); + border: 1px solid var(--background-border-color); } .search .icon { @@ -9554,7 +9550,7 @@ noscript { &__input { @include search-input; - border: 1px solid lighten($ui-base-color, 8%); + border: 1px solid var(--background-border-color); padding: 4px 6px; color: $primary-text-color; font-size: 16px; @@ -9589,7 +9585,7 @@ noscript { margin-top: -1px; padding-top: 5px; padding-bottom: 5px; - border: 1px solid lighten($ui-base-color, 8%); + border: 1px solid var(--background-border-color); } &.focused &__input { @@ -10624,8 +10620,8 @@ noscript { display: flex; align-items: center; border-bottom: 1px solid var(--background-border-color); - padding: 24px 32px; - gap: 16px; + padding: 16px 24px; + gap: 8px; color: $darker-text-color; text-decoration: none; @@ -10635,10 +10631,8 @@ noscript { color: $secondary-text-color; } - .icon { - width: 24px; - height: 24px; - padding: 2px; + .notification-group__icon { + color: inherit; } &__text { @@ -10776,6 +10770,252 @@ noscript { } } +.notification-group { + display: flex; + align-items: flex-start; + gap: 8px; + padding: 16px 24px; + border-bottom: 1px solid var(--background-border-color); + + &__icon { + width: 40px; + display: flex; + align-items: center; + justify-content: center; + flex: 0 0 auto; + color: $dark-text-color; + + .icon { + width: 28px; + height: 28px; + } + } + + &--follow &__icon, + &--follow-request &__icon { + color: $highlight-text-color; + } + + &--favourite &__icon { + color: $gold-star; + } + + &--reblog &__icon { + color: $valid-value-color; + } + + &--relationships-severance-event &__icon, + &--admin-report &__icon, + &--admin-sign-up &__icon { + color: $dark-text-color; + } + + &--moderation-warning &__icon { + color: $red-bookmark; + } + + &--follow-request &__actions { + align-items: center; + display: flex; + gap: 8px; + + .icon-button { + border: 1px solid var(--background-border-color); + border-radius: 50%; + padding: 1px; + } + } + + &__main { + display: flex; + flex-direction: column; + gap: 8px; + flex: 1 1 auto; + overflow: hidden; + + &__header { + display: flex; + flex-direction: column; + gap: 8px; + + &__wrapper { + display: flex; + justify-content: space-between; + } + + &__label { + display: flex; + gap: 8px; + font-size: 15px; + line-height: 22px; + color: $darker-text-color; + + a { + color: inherit; + text-decoration: none; + } + + bdi { + font-weight: 700; + color: $primary-text-color; + } + + time { + color: $dark-text-color; + } + } + } + + &__status { + border: 1px solid var(--background-border-color); + border-radius: 8px; + padding: 8px; + } + } + + &__avatar-group { + display: flex; + gap: 8px; + height: 28px; + overflow-y: hidden; + flex-wrap: wrap; + } + + .status { + padding: 0; + border: 0; + } + + &__embedded-status { + cursor: pointer; + + &__account { + display: flex; + align-items: center; + gap: 4px; + margin-bottom: 8px; + color: $dark-text-color; + + bdi { + color: inherit; + } + } + + .account__avatar { + opacity: 0.5; + } + + &__content { + display: -webkit-box; + font-size: 15px; + line-height: 22px; + color: $dark-text-color; + -webkit-line-clamp: 4; + -webkit-box-orient: vertical; + max-height: 4 * 22px; + overflow: hidden; + + p, + a { + color: inherit; + } + } + } +} + +.notification-ungrouped { + padding: 16px 24px; + border-bottom: 1px solid var(--background-border-color); + + &__header { + display: flex; + align-items: center; + gap: 8px; + color: $dark-text-color; + font-size: 15px; + line-height: 22px; + font-weight: 500; + padding-inline-start: 24px; + margin-bottom: 16px; + + &__icon { + display: flex; + align-items: center; + justify-content: center; + flex: 0 0 auto; + + .icon { + width: 16px; + height: 16px; + } + } + + a { + color: inherit; + text-decoration: none; + } + } + + .status { + border: 0; + padding: 0; + + &__avatar { + width: 40px; + height: 40px; + } + } + + .status__wrapper-direct { + background: transparent; + } + + $icon-margin: 48px; // 40px avatar + 8px gap + + .status__content, + .status__action-bar, + .media-gallery, + .video-player, + .audio-player, + .attachment-list, + .picture-in-picture-placeholder, + .more-from-author, + .status-card, + .hashtag-bar { + margin-inline-start: $icon-margin; + width: calc(100% - $icon-margin); + } + + .more-from-author { + width: calc(100% - $icon-margin + 2px); + } + + .status__content__read-more-button { + margin-inline-start: $icon-margin; + } + + .notification__report { + border: 0; + padding: 0; + } +} + +.notification-group--unread, +.notification-ungrouped--unread { + position: relative; + + &::before { + content: ''; + position: absolute; + top: 0; + inset-inline-start: 0; + width: 100%; + height: 100%; + border-inline-start: 4px solid $highlight-text-color; + pointer-events: none; + } +} + .hover-card-controller[data-popper-reference-hidden='true'] { opacity: 0; pointer-events: none; diff --git a/app/javascript/styles/mastodon/containers.scss b/app/javascript/styles/mastodon/containers.scss index 8a472d75b13cf6..9363e428b3809b 100644 --- a/app/javascript/styles/mastodon/containers.scss +++ b/app/javascript/styles/mastodon/containers.scss @@ -63,7 +63,7 @@ padding: 20px 0; margin-top: 40px; margin-bottom: 10px; - border-bottom: 1px solid lighten($ui-base-color, 8%); + border-bottom: 1px solid var(--background-border-color); @media screen and (width <= 440px) { width: 100%; diff --git a/app/javascript/styles/mastodon/dashboard.scss b/app/javascript/styles/mastodon/dashboard.scss index 36a7f44253f423..12d0a6b92f9b90 100644 --- a/app/javascript/styles/mastodon/dashboard.scss +++ b/app/javascript/styles/mastodon/dashboard.scss @@ -13,8 +13,9 @@ & > div, & > a { padding: 20px; - background: lighten($ui-base-color, 4%); + background: var(--background-color); border-radius: 4px; + border: 1px solid var(--background-border-color); box-sizing: border-box; height: 100%; } @@ -27,7 +28,7 @@ &:hover, &:focus, &:active { - background: lighten($ui-base-color, 8%); + background: $ui-base-color; } } } diff --git a/app/javascript/styles/mastodon/emoji_picker.scss b/app/javascript/styles/mastodon/emoji_picker.scss index dd371feb150b68..f327cab3208abc 100644 --- a/app/javascript/styles/mastodon/emoji_picker.scss +++ b/app/javascript/styles/mastodon/emoji_picker.scss @@ -105,7 +105,7 @@ width: 100%; background: $ui-base-color; color: $darker-text-color; - border: 1px solid lighten($ui-base-color, 8%); + border: 1px solid var(--background-border-color); border-radius: 4px; &::-moz-focus-inner { diff --git a/app/javascript/styles/mastodon/forms.scss b/app/javascript/styles/mastodon/forms.scss index 2adfa917954492..9dbdac2b904cba 100644 --- a/app/javascript/styles/mastodon/forms.scss +++ b/app/javascript/styles/mastodon/forms.scss @@ -426,7 +426,7 @@ code { } .input.static .label_input__wrapper { - font-size: 16px; + font-size: 14px; padding: 10px; border: 1px solid $dark-text-color; border-radius: 4px; @@ -448,13 +448,14 @@ code { outline: 0; font-family: inherit; resize: vertical; - background: darken($ui-base-color, 10%); - border: 1px solid darken($ui-base-color, 10%); - border-radius: 8px; + background: $ui-base-color; + border: 1px solid var(--background-border-color); + border-radius: 4px; padding: 10px 16px; &::placeholder { - color: lighten($darker-text-color, 4%); + color: $dark-text-color; + opacity: 1; } &:invalid { @@ -465,11 +466,6 @@ code { border-color: $valid-value-color; } - &:active, - &:focus { - border-color: $highlight-text-color; - } - @media screen and (width <= 600px) { font-size: 16px; } @@ -588,21 +584,25 @@ code { select { appearance: none; box-sizing: border-box; - font-size: 16px; + font-size: 14px; color: $primary-text-color; display: block; width: 100%; outline: 0; font-family: inherit; resize: vertical; - background: darken($ui-base-color, 10%) + background: $ui-base-color url("data:image/svg+xml;utf8,") - no-repeat right 8px center / auto 16px; - border: 1px solid darken($ui-base-color, 14%); + no-repeat right 8px center / auto 14px; + border: 1px solid var(--background-border-color); border-radius: 4px; padding-inline-start: 10px; padding-inline-end: 30px; height: 41px; + + @media screen and (width <= 600px) { + font-size: 16px; + } } h4 { @@ -656,8 +656,9 @@ code { } .flash-message { - background: lighten($ui-base-color, 8%); - color: $darker-text-color; + background: var(--background-color); + color: $highlight-text-color; + border: 1px solid $highlight-text-color; border-radius: 4px; padding: 15px 10px; margin-bottom: 30px; @@ -1351,7 +1352,7 @@ code { &__toggle > div { display: flex; - border-inline-start: 1px solid lighten($ui-base-color, 8%); + border-inline-start: 1px solid var(--background-border-color); padding-inline-start: 16px; } } diff --git a/app/javascript/styles/mastodon/rtl.scss b/app/javascript/styles/mastodon/rtl.scss index b5c4836bcd7726..8d3efcb5726197 100644 --- a/app/javascript/styles/mastodon/rtl.scss +++ b/app/javascript/styles/mastodon/rtl.scss @@ -46,7 +46,7 @@ body.rtl { } .simple_form select { - background: darken($ui-base-color, 10%) + background: $ui-base-color url("data:image/svg+xml;utf8,") no-repeat left 8px center / auto 16px; } diff --git a/app/javascript/styles/mastodon/tables.scss b/app/javascript/styles/mastodon/tables.scss index 25206f9a5de70e..09a1c626c85ee9 100644 --- a/app/javascript/styles/mastodon/tables.scss +++ b/app/javascript/styles/mastodon/tables.scss @@ -9,9 +9,9 @@ padding: 8px; line-height: 18px; vertical-align: top; - border-top: 1px solid $ui-base-color; + border-bottom: 1px solid var(--background-border-color); text-align: start; - background: darken($ui-base-color, 4%); + background: var(--background-color); &.critical { font-weight: 700; @@ -21,8 +21,6 @@ & > thead > tr > th { vertical-align: bottom; - border-bottom: 2px solid $ui-base-color; - border-top: 0; font-weight: 500; } @@ -32,15 +30,20 @@ & > tbody > tr:nth-child(odd) > td, & > tbody > tr:nth-child(odd) > th { - background: $ui-base-color; + background: var(--background-color); + } + + & > tbody > tr:last-child > td, + & > tbody > tr:last-child > th { + border-bottom: 0; } a { - color: $highlight-text-color; - text-decoration: underline; + color: $darker-text-color; + text-decoration: none; &:hover { - text-decoration: none; + color: $highlight-text-color; } } @@ -78,7 +81,7 @@ & > tbody > tr > td { padding: 11px 10px; background: transparent; - border: 1px solid lighten($ui-base-color, 8%); + border: 1px solid var(--background-border-color); color: $secondary-text-color; } @@ -90,18 +93,18 @@ &.batch-table { & > thead > tr > th { - background: $ui-base-color; - border-top: 1px solid darken($ui-base-color, 8%); - border-bottom: 1px solid darken($ui-base-color, 8%); + background: var(--background-color); + border-top: 1px solid var(--background-border-color); + border-bottom: 1px solid var(--background-border-color); &:first-child { border-radius: 4px 0 0; - border-inline-start: 1px solid darken($ui-base-color, 8%); + border-inline-start: 1px solid var(--background-border-color); } &:last-child { border-radius: 0 4px 0 0; - border-inline-end: 1px solid darken($ui-base-color, 8%); + border-inline-end: 1px solid var(--background-border-color); } } } @@ -136,7 +139,7 @@ a.table-action-link { font-weight: 500; &:hover { - color: $primary-text-color; + color: $highlight-text-color; } i.fa { @@ -186,9 +189,9 @@ a.table-action-link { position: sticky; top: 0; z-index: 1; - border: 1px solid darken($ui-base-color, 8%); - background: $ui-base-color; - border-radius: 4px 0 0; + border: 1px solid var(--background-border-color); + background: var(--background-color); + border-radius: 4px 4px 0 0; height: 47px; align-items: center; @@ -199,11 +202,11 @@ a.table-action-link { } &__select-all { - background: $ui-base-color; + background: var(--background-color); height: 47px; align-items: center; justify-content: center; - border: 1px solid darken($ui-base-color, 8%); + border: 1px solid var(--background-border-color); border-top: 0; color: $secondary-text-color; display: none; @@ -249,9 +252,9 @@ a.table-action-link { &__form { padding: 16px; - border: 1px solid darken($ui-base-color, 8%); + border: 1px solid var(--background-border-color); border-top: 0; - background: $ui-base-color; + background: var(--background-color); .fields-row { padding-top: 0; @@ -260,26 +263,18 @@ a.table-action-link { } &__row { - border: 1px solid darken($ui-base-color, 8%); + border: 1px solid var(--background-border-color); border-top: 0; - background: darken($ui-base-color, 4%); + background: var(--background-color); @media screen and (max-width: $no-gap-breakpoint) { .optional &:first-child { - border-top: 1px solid darken($ui-base-color, 8%); + border-top: 1px solid var(--background-border-color); } } - &:hover { - background: darken($ui-base-color, 2%); - } - &:nth-child(even) { - background: $ui-base-color; - - &:hover { - background: lighten($ui-base-color, 2%); - } + background: var(--background-color); } &__content { @@ -358,12 +353,13 @@ a.table-action-link { } .nothing-here { - border: 1px solid darken($ui-base-color, 8%); + border: 1px solid var(--background-border-color); border-top: 0; box-shadow: none; + background: var(--background-color); @media screen and (max-width: $no-gap-breakpoint) { - border-top: 1px solid darken($ui-base-color, 8%); + border-top: 1px solid var(--background-border-color); } } diff --git a/app/javascript/styles/mastodon/widgets.scss b/app/javascript/styles/mastodon/widgets.scss index d35b36f28bbc60..130314f73352ec 100644 --- a/app/javascript/styles/mastodon/widgets.scss +++ b/app/javascript/styles/mastodon/widgets.scss @@ -205,7 +205,7 @@ } .directory { - background: $ui-base-color; + background: var(--background-color); border-radius: 4px; box-shadow: 0 0 15px rgba($base-shadow-color, 0.2); @@ -218,7 +218,7 @@ display: flex; align-items: center; justify-content: space-between; - background: $ui-base-color; + border: 1px solid lighten($ui-base-color, 8%); border-radius: 4px; padding: 15px; text-decoration: none; @@ -230,7 +230,7 @@ &:hover, &:active, &:focus { - background: lighten($ui-base-color, 8%); + background: $ui-base-color; } } @@ -352,7 +352,7 @@ &:focus, &:hover, &:active { - text-decoration: underline; + color: $highlight-text-color; } } } diff --git a/app/lib/activitypub/adapter.rb b/app/lib/activitypub/adapter.rb index 098b6296fb053e..5b9437eb8dad40 100644 --- a/app/lib/activitypub/adapter.rb +++ b/app/lib/activitypub/adapter.rb @@ -20,6 +20,6 @@ def serializable_hash(options = nil) serialized_hash = serialized_hash.select { |k, _| options[:fields].include?(k) } if options[:fields] serialized_hash = self.class.transform_key_casing!(serialized_hash, instance_options) - { '@context' => serialized_context(named_contexts, context_extensions) }.merge(serialized_hash) + { '@context': serialized_context(named_contexts, context_extensions) }.merge(serialized_hash) end end diff --git a/app/lib/webfinger.rb b/app/lib/webfinger.rb index ae8a3b1eae0264..01a5dbc21d914b 100644 --- a/app/lib/webfinger.rb +++ b/app/lib/webfinger.rb @@ -6,6 +6,8 @@ class GoneError < Error; end class RedirectError < Error; end class Response + ACTIVITYPUB_READY_TYPE = ['application/activity+json', 'application/ld+json; profile="https://www.w3.org/ns/activitystreams"'].freeze + attr_reader :uri def initialize(uri, body) @@ -20,17 +22,28 @@ def subject end def link(rel, attribute) - links.dig(rel, attribute) + links.dig(rel, 0, attribute) + end + + def self_link_href + self_link.fetch('href') end private def links - @links ||= @json['links'].index_by { |link| link['rel'] } + @links ||= @json.fetch('links', []).group_by { |link| link['rel'] } + end + + def self_link + links.fetch('self', []).find do |link| + ACTIVITYPUB_READY_TYPE.include?(link['type']) + end end def validate_response! raise Webfinger::Error, "Missing subject in response for #{@uri}" if subject.blank? + raise Webfinger::Error, "Missing self link in response for #{@uri}" if self_link.blank? end end diff --git a/app/models/admin/action_log_filter.rb b/app/models/admin/action_log_filter.rb index 17af35fbc8baea..b156cd49fe276e 100644 --- a/app/models/admin/action_log_filter.rb +++ b/app/models/admin/action_log_filter.rb @@ -5,6 +5,14 @@ class Admin::ActionLogFilter action_type account_id target_account_id + target_domain + ).freeze + + INSTANCE_TARGET_TYPES = %w( + DomainBlock + DomainAllow + Instance + UnavailableDomain ).freeze ACTION_TYPE_MAP = { @@ -99,6 +107,9 @@ def scope_for(key, value) when 'target_account_id' account = Account.find_or_initialize_by(id: value) latest_action_logs.where(target: [account, account.user].compact) + when 'target_domain' + normalized_domain = TagManager.instance.normalize_domain(value) + latest_action_logs.where(human_identifier: normalized_domain, target_type: INSTANCE_TARGET_TYPES) else raise Mastodon::InvalidParameterError, "Unknown filter: #{key}" end diff --git a/app/models/notification.rb b/app/models/notification.rb index 60070b8c07fd46..4f537b43c28bc1 100644 --- a/app/models/notification.rb +++ b/app/models/notification.rb @@ -34,6 +34,7 @@ class Notification < ApplicationRecord 'AccountWarning' => :moderation_warning, }.freeze + # Please update app/javascript/api_types/notification.ts if you change this PROPERTIES = { mention: { filterable: true, @@ -166,33 +167,53 @@ def browserable(types: [], exclude_types: [], from_account_id: nil, include_filt end end - # This returns notifications from the request page, but with at most one notification per group. - # Notifications that have no `group_key` each count as a separate group. - def paginate_groups_by_max_id(limit, max_id: nil, since_id: nil) - query = reorder(id: :desc) - query = query.where(id: ...max_id) if max_id.present? - query = query.where(id: (since_id + 1)...) if since_id.present? + def paginate_groups(limit, pagination_order) + raise ArgumentError unless %i(asc desc).include?(pagination_order) + + query = reorder(id: pagination_order) unscoped .with_recursive( grouped_notifications: [ + # Base case: fetching one notification and annotating it with visited groups query - .select('notifications.*', "ARRAY[COALESCE(notifications.group_key, 'ungrouped-' || notifications.id)] groups") - .limit(1), - query - .joins('CROSS JOIN grouped_notifications') - .where('array_length(grouped_notifications.groups, 1) < :limit', limit: limit) - .where('notifications.id < grouped_notifications.id') - .where.not("COALESCE(notifications.group_key, 'ungrouped-' || notifications.id) = ANY(grouped_notifications.groups)") - .select('notifications.*', "array_append(grouped_notifications.groups, COALESCE(notifications.group_key, 'ungrouped-' || notifications.id))") + .select('notifications.*', "ARRAY[COALESCE(notifications.group_key, 'ungrouped-' || notifications.id)] AS groups") .limit(1), + # Recursive case, always yielding at most one annotated notification + unscoped + .from( + [ + # Expose the working table as `wt`, but quit early if we've reached the limit + unscoped + .select('id', 'groups') + .from('grouped_notifications') + .where('array_length(grouped_notifications.groups, 1) < :limit', limit: limit) + .arel.as('wt'), + # Recursive query, using `LATERAL` so we can refer to `wt` + query + .where(pagination_order == :desc ? 'notifications.id < wt.id' : 'notifications.id > wt.id') + .where.not("COALESCE(notifications.group_key, 'ungrouped-' || notifications.id) = ANY(wt.groups)") + .limit(1) + .arel.lateral('notifications'), + ] + ) + .select('notifications.*', "array_append(wt.groups, COALESCE(notifications.group_key, 'ungrouped-' || notifications.id))"), ] ) .from('grouped_notifications AS notifications') - .order(id: :desc) + .order(id: pagination_order) .limit(limit) end + # This returns notifications from the request page, but with at most one notification per group. + # Notifications that have no `group_key` each count as a separate group. + def paginate_groups_by_max_id(limit, max_id: nil, since_id: nil) + query = reorder(id: :desc) + query = query.where(id: ...max_id) if max_id.present? + query = query.where(id: (since_id + 1)...) if since_id.present? + query.paginate_groups(limit, :desc) + end + # Differs from :paginate_groups_by_max_id in that it gives the results immediately following min_id, # whereas since_id gives the items with largest id, but with since_id as a cutoff. # Results will be in ascending order by id. @@ -200,25 +221,7 @@ def paginate_groups_by_min_id(limit, max_id: nil, min_id: nil) query = reorder(id: :asc) query = query.where(id: (min_id + 1)...) if min_id.present? query = query.where(id: ...max_id) if max_id.present? - - unscoped - .with_recursive( - grouped_notifications: [ - query - .select('notifications.*', "ARRAY[COALESCE(notifications.group_key, 'ungrouped-' || notifications.id)] groups") - .limit(1), - query - .joins('CROSS JOIN grouped_notifications') - .where('array_length(grouped_notifications.groups, 1) < :limit', limit: limit) - .where('notifications.id > grouped_notifications.id') - .where.not("COALESCE(notifications.group_key, 'ungrouped-' || notifications.id) = ANY(grouped_notifications.groups)") - .select('notifications.*', "array_append(grouped_notifications.groups, COALESCE(notifications.group_key, 'ungrouped-' || notifications.id))") - .limit(1), - ] - ) - .from('grouped_notifications AS notifications') - .order(id: :asc) - .limit(limit) + query.paginate_groups(limit, :asc) end def to_a_grouped_paginated_by_id(limit, options = {}) diff --git a/app/models/notification_group.rb b/app/models/notification_group.rb index b1cbd7c19abf9f..223945f07bf681 100644 --- a/app/models/notification_group.rb +++ b/app/models/notification_group.rb @@ -3,13 +3,17 @@ class NotificationGroup < ActiveModelSerializers::Model attributes :group_key, :sample_accounts, :notifications_count, :notification, :most_recent_notification_id + # Try to keep this consistent with `app/javascript/mastodon/models/notification_group.ts` + SAMPLE_ACCOUNTS_SIZE = 8 + def self.from_notification(notification, max_id: nil) if notification.group_key.present? - # TODO: caching and preloading + # TODO: caching, and, if caching, preloading scope = notification.account.notifications.where(group_key: notification.group_key) scope = scope.where(id: ..max_id) if max_id.present? - most_recent_notifications = scope.order(id: :desc).take(3) + # Ideally, we would not load accounts for each notification group + most_recent_notifications = scope.order(id: :desc).includes(:from_account).take(SAMPLE_ACCOUNTS_SIZE) most_recent_id = most_recent_notifications.first.id sample_accounts = most_recent_notifications.map(&:from_account) notifications_count = scope.count diff --git a/app/models/report.rb b/app/models/report.rb index 3df5a20e1819c1..17c1503436f0ff 100644 --- a/app/models/report.rb +++ b/app/models/report.rb @@ -18,6 +18,7 @@ # category :integer default("other"), not null # action_taken_at :datetime # rule_ids :bigint(8) is an Array +# application_id :bigint(8) # class Report < ApplicationRecord @@ -31,6 +32,7 @@ class Report < ApplicationRecord rate_limit by: :account, family: :reports belongs_to :account + belongs_to :application, class_name: 'Doorkeeper::Application', optional: true with_options class_name: 'Account' do belongs_to :target_account diff --git a/app/serializers/rest/notification_group_serializer.rb b/app/serializers/rest/notification_group_serializer.rb index 9aa5663f4e040c..111239843f516b 100644 --- a/app/serializers/rest/notification_group_serializer.rb +++ b/app/serializers/rest/notification_group_serializer.rb @@ -1,6 +1,7 @@ # frozen_string_literal: true class REST::NotificationGroupSerializer < ActiveModel::Serializer + # Please update app/javascript/api_types/notification.ts when making changes to the attributes attributes :group_key, :notifications_count, :type, :most_recent_notification_id attribute :page_min_id, if: :paginated? @@ -14,7 +15,7 @@ class REST::NotificationGroupSerializer < ActiveModel::Serializer belongs_to :account_warning, key: :moderation_warning, if: :moderation_warning_event?, serializer: REST::AccountWarningSerializer def status_type? - [:favourite, :reblog, :status, :mention, :poll, :update].include?(object.type) + [:favourite, :emoji_reaction, :reblog, :status, :mention, :status_reference, :poll, :update].include?(object.type) end def report_type? diff --git a/app/serializers/rest/notification_serializer.rb b/app/serializers/rest/notification_serializer.rb index 70aebc34d29f8e..644da0c87e6b03 100644 --- a/app/serializers/rest/notification_serializer.rb +++ b/app/serializers/rest/notification_serializer.rb @@ -1,6 +1,7 @@ # frozen_string_literal: true class REST::NotificationSerializer < ActiveModel::Serializer + # Please update app/javascript/api_types/notification.ts when making changes to the attributes attributes :id, :type, :created_at, :group_key attribute :filtered, if: :filtered? diff --git a/app/services/activitypub/fetch_remote_actor_service.rb b/app/services/activitypub/fetch_remote_actor_service.rb index 86a134bb4ed911..2c372c2ec3fd84 100644 --- a/app/services/activitypub/fetch_remote_actor_service.rb +++ b/app/services/activitypub/fetch_remote_actor_service.rb @@ -49,7 +49,7 @@ def check_webfinger! confirmed_username, confirmed_domain = split_acct(webfinger.subject) if @username.casecmp(confirmed_username).zero? && @domain.casecmp(confirmed_domain).zero? - raise Error, "Webfinger response for #{@username}@#{@domain} does not loop back to #{@uri}" if webfinger.link('self', 'href') != @uri + raise Error, "Webfinger response for #{@username}@#{@domain} does not loop back to #{@uri}" if webfinger.self_link_href != @uri return end @@ -58,8 +58,7 @@ def check_webfinger! @username, @domain = split_acct(webfinger.subject) raise Webfinger::RedirectError, "Too many webfinger redirects for URI #{@uri} (stopped at #{@username}@#{@domain})" unless confirmed_username.casecmp(@username).zero? && confirmed_domain.casecmp(@domain).zero? - - raise Error, "Webfinger response for #{@username}@#{@domain} does not loop back to #{@uri}" if webfinger.link('self', 'href') != @uri + raise Error, "Webfinger response for #{@username}@#{@domain} does not loop back to #{@uri}" if webfinger.self_link_href != @uri rescue Webfinger::RedirectError => e raise Error, e.message rescue Webfinger::Error => e diff --git a/app/services/backup_service.rb b/app/services/backup_service.rb index 2cf8302e55b0aa..8bc90968b7e4c7 100644 --- a/app/services/backup_service.rb +++ b/app/services/backup_service.rb @@ -19,8 +19,8 @@ def call(backup) def build_outbox_json!(file) skeleton = serialize(collection_presenter, ActivityPub::CollectionSerializer) - skeleton['@context'] = full_context - skeleton['orderedItems'] = ['!PLACEHOLDER!'] + skeleton[:@context] = full_context + skeleton[:orderedItems] = ['!PLACEHOLDER!'] skeleton = Oj.dump(skeleton) prepend, append = skeleton.split('"!PLACEHOLDER!"') add_comma = false @@ -33,7 +33,7 @@ def build_outbox_json!(file) file.write(statuses.map do |status| item = serialize_payload(ActivityPub::ActivityPresenter.from_status(status, use_bearcap: false), ActivityPub::ActivitySerializer) - item.delete('@context') + item.delete(:@context) unless item[:type] == 'Announce' || item[:object][:attachment].blank? item[:object][:attachment].each do |attachment| diff --git a/app/services/notify_service.rb b/app/services/notify_service.rb index 533355a2af5195..4e3e4e188ec81b 100644 --- a/app/services/notify_service.rb +++ b/app/services/notify_service.rb @@ -4,7 +4,6 @@ class NotifyService < BaseService include Redisable MAXIMUM_GROUP_SPAN_HOURS = 12 - MAXIMUM_GROUP_GAP_TIME = 4.hours.to_i NON_EMAIL_TYPES = %i( admin.report @@ -210,7 +209,7 @@ def call(recipient, type, activity) private def notification_group_key - return nil if @notification.filtered || %i(favourite reblog).exclude?(@notification.type) + return nil if @notification.filtered || %i(favourite emoji_reaction reblog).exclude?(@notification.type) type_prefix = "#{@notification.type}-#{@notification.target_status.id}" redis_key = "notif-group/#{@recipient.id}/#{type_prefix}" @@ -220,9 +219,8 @@ def notification_group_key previous_bucket = redis.get(redis_key).to_i hour_bucket = previous_bucket if hour_bucket < previous_bucket + MAXIMUM_GROUP_SPAN_HOURS - # Do not track groups past a given inactivity time # We do not concern ourselves with race conditions since we use hour buckets - redis.set(redis_key, hour_bucket, ex: MAXIMUM_GROUP_GAP_TIME) + redis.set(redis_key, hour_bucket, ex: MAXIMUM_GROUP_SPAN_HOURS.hours.to_i) "#{type_prefix}-#{hour_bucket}" end diff --git a/app/services/report_service.rb b/app/services/report_service.rb index e8d236bf828f30..cd52fdc34c4a7c 100644 --- a/app/services/report_service.rb +++ b/app/services/report_service.rb @@ -10,6 +10,7 @@ def call(source_account, target_account, options = {}) @comment = options.delete(:comment).presence || '' @category = options[:rule_ids].present? ? 'violation' : (options.delete(:category).presence || 'other') @rule_ids = options.delete(:rule_ids).presence + @application = options.delete(:application).presence @options = options raise ActiveRecord::RecordNotFound if @target_account.unavailable? @@ -35,7 +36,8 @@ def create_report! uri: @options[:uri], forwarded: forward_to_origin?, category: @category, - rule_ids: @rule_ids + rule_ids: @rule_ids, + application: @application ) end diff --git a/app/services/resolve_account_service.rb b/app/services/resolve_account_service.rb index 078a0423f287ce..8a5863baba6c7f 100644 --- a/app/services/resolve_account_service.rb +++ b/app/services/resolve_account_service.rb @@ -106,8 +106,6 @@ def split_acct(acct) end def fetch_account! - return unless activitypub_ready? - with_redis_lock("resolve:#{@username}@#{@domain}") do @account = ActivityPub::FetchRemoteAccountService.new.call(actor_url, suppress_errors: @options[:suppress_errors]) end @@ -122,12 +120,8 @@ def webfinger_update_due? @options[:skip_cache] || @account.nil? || @account.possibly_stale? end - def activitypub_ready? - ['application/activity+json', 'application/ld+json; profile="https://www.w3.org/ns/activitystreams"'].include?(@webfinger.link('self', 'type')) - end - def actor_url - @actor_url ||= @webfinger.link('self', 'href') + @actor_url ||= @webfinger.self_link_href end def gone_from_origin? diff --git a/app/views/admin/instances/show.html.haml b/app/views/admin/instances/show.html.haml index a357eaf4b4cfc3..606d00e27c9d9c 100644 --- a/app/views/admin/instances/show.html.haml +++ b/app/views/admin/instances/show.html.haml @@ -118,6 +118,16 @@ - if @instance.persisted? %hr.spacer/ + %h3= t('admin.instances.audit_log.title') + - if @action_logs.empty? + %p= t('accounts.nothing_here') + - else + .report-notes + = render partial: 'admin/action_logs/action_log', collection: @action_logs + = link_to t('admin.instances.audit_log.view_all'), admin_action_logs_path(target_domain: @instance.domain), class: 'button' + + %hr.spacer/ + %h3= t('admin.instances.availability.title') %p diff --git a/app/views/admin/reports/_header_details.html.haml b/app/views/admin/reports/_header_details.html.haml index 45790b9cd50d75..434231f7333626 100644 --- a/app/views/admin/reports/_header_details.html.haml +++ b/app/views/admin/reports/_header_details.html.haml @@ -14,6 +14,12 @@ = admin_account_link_to report.account - else = report.account.domain + - if report.application.present? + .report-header__details__item + .report-header__details__item__header + %strong= t('admin.reports.reported_with_application') + .report-header__details__item__content + = report.application.name .report-header__details__item .report-header__details__item__header %strong= t('admin.reports.status') diff --git a/app/views/admin/roles/index.html.haml b/app/views/admin/roles/index.html.haml index 4f6c511b4fae08..90a647cc8a8187 100644 --- a/app/views/admin/roles/index.html.haml +++ b/app/views/admin/roles/index.html.haml @@ -8,10 +8,10 @@ %hr.spacer/ -.applications-list +.announcements-list = render partial: 'role', collection: @roles.select(&:everyone?) %hr.spacer/ -.applications-list +.announcements-list = render partial: 'role', collection: @roles.reject(&:everyone?) diff --git a/app/views/auth/registrations/_account_warning.html.haml b/app/views/auth/registrations/_account_warning.html.haml index 19e5746ff63c08..c51179b49dad8e 100644 --- a/app/views/auth/registrations/_account_warning.html.haml +++ b/app/views/auth/registrations/_account_warning.html.haml @@ -1,14 +1,14 @@ -= link_to disputes_strike_path(account_warning), class: 'log-entry' do - .log-entry__header - .log-entry__avatar += link_to disputes_strike_path(account_warning), class: 'strike-entry' do + .strike-entry__header + .strike-entry__avatar .indicator-icon{ class: account_warning.overruled? ? 'success' : 'failure' } = fa_icon 'warning' - .log-entry__content - .log-entry__title + .strike-entry__content + .strike-entry__title = t 'disputes.strikes.title', action: t(account_warning.action, scope: 'disputes.strikes.title_actions'), date: l(account_warning.created_at.to_date) - .log-entry__timestamp + .strike-entry__timestamp %time.formatted{ datetime: account_warning.created_at.iso8601 }= l(account_warning.created_at) - if account_warning.overruled? diff --git a/babel.config.js b/babel.config.js index 9ced748a9615f7..4c2fe5682bb53d 100644 --- a/babel.config.js +++ b/babel.config.js @@ -68,7 +68,7 @@ module.exports = (api) => { plugins, overrides: [ { - test: /tesseract\.js/, + test: [/tesseract\.js/, /fuzzysort\.js/], presets: [ ['@babel/env', { ...envOptions, modules: 'commonjs' }], ], diff --git a/config/locales/activerecord.ast.yml b/config/locales/activerecord.ast.yml index 2d532071a9b420..d139a3257049cd 100644 --- a/config/locales/activerecord.ast.yml +++ b/config/locales/activerecord.ast.yml @@ -18,7 +18,7 @@ ast: account: attributes: username: - invalid: ha contener namás lletres, númberos ya guiones baxos + invalid: ha contener namás lletres, númberos y guiones baxos reserved: ta acutáu admin/webhook: attributes: diff --git a/config/locales/activerecord.el.yml b/config/locales/activerecord.el.yml index 01e9a75f98e4ab..1c3bcc6ebf58be 100644 --- a/config/locales/activerecord.el.yml +++ b/config/locales/activerecord.el.yml @@ -36,14 +36,14 @@ el: status: attributes: reblog: - taken: της κατάστασης ήδη υπάρχει + taken: της ανάρτησης υπάρχει ήδη user: attributes: email: blocked: χρησιμοποιεί μη επιτρεπόμενο πάροχο e-mail unreachable: δεν φαίνεται να υπάρχει role_id: - elevated: δεν μπορεί να είναι μεγαλύτερο από τον τρέχοντα ρόλο σας + elevated: δεν μπορεί να είναι υψηλότερο από τον τρέχοντα ρόλο σου user_role: attributes: permissions_as_keys: diff --git a/config/locales/activerecord.ga.yml b/config/locales/activerecord.ga.yml index 236cc479e17e1b..1b61edb2e2fe00 100644 --- a/config/locales/activerecord.ga.yml +++ b/config/locales/activerecord.ga.yml @@ -19,8 +19,41 @@ ga: account: attributes: username: + invalid: ní mór go mbeadh litreacha, uimhreacha agus pointí béime amháin reserved: in áirithe + admin/webhook: + attributes: + url: + invalid: nach URL bailí é + doorkeeper/application: + attributes: + website: + invalid: nach URL bailí é import: attributes: data: malformed: míchumtha + status: + attributes: + reblog: + taken: den phost cheana féin + user: + attributes: + email: + blocked: úsáideann soláthraí ríomhphoist dícheadaithe + unreachable: ní cosúil go bhfuil sé ann + role_id: + elevated: ní féidir leat a bheith níos airde ná do ról reatha + user_role: + attributes: + permissions_as_keys: + dangerous: cuir san áireamh ceadanna nach bhfuil sábháilte don ról bunúsach + elevated: ní féidir ceadanna nach bhfuil ag do ról reatha a áireamh + own_role: ní féidir é a athrú le do ról reatha + position: + elevated: ní féidir leat a bheith níos airde ná do ról reatha + own_role: ní féidir é a athrú le do ról reatha + webhook: + attributes: + events: + invalid_permissions: ní féidir imeachtaí nach bhfuil na cearta agat ina leith a chur san áireamh diff --git a/config/locales/ast.yml b/config/locales/ast.yml index 9e6ec6d2330cb9..567e5357ebcfb7 100644 --- a/config/locales/ast.yml +++ b/config/locales/ast.yml @@ -1,7 +1,7 @@ --- ast: about: - about_mastodon_html: 'La rede social del futuru: ¡ensin anuncios nin vixilancia, con un diseñu éticu ya descentralizáu! Controla los tos datos con Mastodon.' + about_mastodon_html: 'La rede social del futuru: ¡ensin anuncios nin vixilancia, con un diseñu éticu y descentralizáu! Controla los tos datos con Mastodon.' contact_unavailable: N/D hosted_on: 'Mastodon ta agospiáu en: %{domain}' title: Tocante a @@ -45,11 +45,12 @@ ast: title: Moderación most_recent_activity: L'actividá más recién most_recent_ip: La IP más recién + no_limits_imposed: S'impunxo nenguna llende perform_full_suspension: Suspender protocol: Protocolu rejected_msg: Refugóse correutamente la solicitú de rexistru de «%{username}» resend_confirmation: - already_confirmed: Esti perfil xá ta confirmáu + already_confirmed: Esti perfil yá ta confirmáu role: Rol search: Buscar search_same_email_domain: Otros perfiles col mesmu dominiu de corréu electrónicu @@ -125,7 +126,7 @@ ast: no_emoji_selected: Nun camudó nengún fustaxe darréu que nun se seleicionó nengún not_permitted: Nun tienes permisu pa facer esta aición shortcode: Códigu curtiu - shortcode_hint: De 2 caráuteres como muncho, namás caráuteres alfanumbéricos ya guiones baxos + shortcode_hint: De 2 caráuteres como muncho, namás caráuteres alfanumbéricos y guiones baxos title: Fustaxes personalizaos uncategorized: Ensin categoría update_failed_msg: Nun se pudo anovar esi fustaxe @@ -176,7 +177,7 @@ ast: export_domain_allows: no_file: Nun se seleicionó nengún ficheru follow_recommendations: - description_html: "La recomendación de cuentes ayuda a que los perfiles nuevos atopen aína conteníu interesante. Cuando una cuenta nun interactuó abondo con otros perfiles como pa formar recomendaciones personalizaes, estes cuentes van ser les que se recomienden. Recalcúlense caldía a partir d'un mecíu de cuentes con más actividá recién ya mayor númberu de siguidores llocales pa una llingua determinada." + description_html: "La recomendación de cuentes ayuda a que los perfiles nuevos atopen aína conteníu interesante. Cuando una cuenta nun interactuó abondo con otros perfiles como pa formar recomendaciones personalizaes, estes cuentes van ser les que se recomienden. Recalcúlense caldía a partir d'un mecíu de cuentes con más actividá recién y mayor númberu de siguidores llocales pa una llingua determinada." language: Pa la llingua status: Estáu title: Recomendación de cuentes @@ -240,7 +241,7 @@ ast: one: "%{count} nota" other: "%{count} notes" actions: - silence_description_html: La cuenta va ser visible namás pa quien xá la siguiere o la buscare manualmente, lo que llenda'l so algame. Esta decisión pue desfacese en cualesquier momentu. Si escueyes esta opción, zárrense tolos informes escontra esta cuenta. + silence_description_html: La cuenta va ser visible namás pa quien yá la siguiere o la buscare manualmente, lo que llenda'l so algame. Esta decisión pue desfacese en cualesquier momentu. Si escueyes esta opción, zárrense tolos informes escontra esta cuenta. actions_description_html: Decidi qué aición tomar pa resolver esti informe. Si tomes una aición punitiva escontra la cuenta de la que s'informó, va unviase un avisu per corréu electrónicu a esa cuenta, esceuto cuando se seleiciona la categoría Puxarra. add_to_report: Amestar más al informe are_you_sure: "¿De xuru que quies facer esta aición?" @@ -314,7 +315,7 @@ ast: preamble: Personaliza la interfaz web de Mastodon. title: Aspeutu branding: - preamble: La marca del to sirvidor estrémalu d'otros sirvidores de la rede. Ye posible qu'esta información apaeza nuna variedá d'entornos, como la interfaz web de Mastodon, les aplicaciones natives, nes previsualizaciones de los enllaces d'otros sitios web, dientro de les aplicaciones de mensaxería, etc. Por esti motivu, lo meyor ye qu'esta información seya clara, curtia ya concisa. + preamble: La marca del to sirvidor estrémalu d'otros sirvidores de la rede. Ye posible qu'esta información apaeza nuna variedá d'entornos, como la interfaz web de Mastodon, les aplicaciones natives, nes previsualizaciones de los enllaces d'otros sitios web, dientro de les aplicaciones de mensaxería, etc. Por esti motivu, lo meyor ye qu'esta información seya clara, curtia y concisa. title: Marca content_retention: preamble: Controla cómo s'atroxa'l conteníu xeneráu polos perfiles en Mastodon. @@ -438,8 +439,8 @@ ast: empty: Nun tienes nengún nomatu. appearance: advanced_web_interface: Interfaz web avanzada - advanced_web_interface_hint: 'Si quies asegúrate de que s''use tol llargor de la pantalla, la interfaz web avanzada permítete configurar columnes estremaes pa ver muncha más información al empar: Aniciu, avisos, llinia de tiempu federada ya cualesquier cantidá de llistes ya etiquetes.' - animations_and_accessibility: Animaciones ya accesibilidá + advanced_web_interface_hint: 'Si quies asegúrate de que s''use tol llargor de la pantalla, la interfaz web avanzada permítete configurar columnes estremaes pa ver muncha más información al empar: Aniciu, avisos, llinia de tiempu federada y cualesquier cantidá de llistes y etiquetes.' + animations_and_accessibility: Animaciones y accesibilidá confirmation_dialogs: Diálogos de confirmación discovery: Descubrimientu localization: @@ -470,7 +471,7 @@ ast: logout: Zarrar la sesión migrate_account: Cambéu de cuenta migrate_account_html: Si quies redirixir esta cuenta a otra diferente, pues configurar esta opción equí. - privacy_policy_agreement_html: Lleí ya acepto la política de privacidá + privacy_policy_agreement_html: Lleí y acepto la política de privacidá providers: cas: CAS saml: SAML @@ -491,7 +492,7 @@ ast: status: account_status: Estáu de la cuenta functional: La cuenta ta completamente operativa. - pending: La to solicitú ta pendiente de que la revise'l nuesu personal ya ye posible que tarde tiempu. Vas recibir un mensaxe si s'aprueba. + pending: La to solicitú ta pendiente de que la revise'l nuesu personal y ye posible que tarde tiempu. Vas recibir un mensaxe si s'aprueba. too_fast: El formulariu xubióse mui rápido, volvi tentalo. challenge: confirm: Siguir @@ -536,7 +537,7 @@ ast: recipient: Dirixóse a reject_appeal: Refugar l'apellación status: 'Artículu #%{id}' - status_removed: L'artículu xá se quitó del sistema + status_removed: L'artículu yá se quitó del sistema your_appeal_approved: Aprobóse la to apellación your_appeal_pending: Unviesti una apellación your_appeal_rejected: Refugóse la to apellación @@ -548,7 +549,7 @@ ast: '403': Nun tienes permisu pa ver esta páxina. '404': La páxina que busques nun ta equí. '406': Esta páxina nun ta disponible nel formatu solicitáu. - '410': La páxina que busques xá nun esiste. + '410': La páxina que busques yá nun esiste. '422': content: La verificación de seguranza falló. ¿Tas bloquiando les cookies? title: La verificación de seguranza falló @@ -561,7 +562,7 @@ ast: exports: archive_takeout: date: Data - hint_html: Pues solicitar un archivu colos tos artículos ya ficheros xubíos. Los datos esportaos van tar nel formatu ActivityPub, llexible pa cualesquier software que seya compatible. Pues solicitar un archivu cada 7 díes. + hint_html: Pues solicitar un archivu colos tos artículos y ficheros xubíos. Los datos esportaos van tar nel formatu ActivityPub, llexible pa cualesquier software que seya compatible. Pues solicitar un archivu cada 7 díes. in_progress: Compilando l'archivu... request: Solicitar l'archivu size: Tamañu @@ -576,7 +577,7 @@ ast: filters: contexts: account: Perfiles - home: Aniciu ya llistes + home: Aniciu y llistes notifications: Avisos public: Llinies de tiempu públiques thread: Conversaciones @@ -617,7 +618,7 @@ ast: over_rows_processing_limit: contién más de %{count} fileres modes: merge: Mecíu - merge_long: Caltién los rexistros esistentes ya amiesta otros nuevos + merge_long: Caltién los rexistros esistentes y amiesta otros nuevos overwrite: Sobrescritura overwrite_long: Troca los rexistros actuales por otros nuevos preface: Pues importar los datos qu'esportares dende otru sirvidor, como la llista de perfiles bloquiaos o que sigas. @@ -645,7 +646,7 @@ ast: max_uses: one: 1 usu other: "%{count} usos" - prompt: Xenera ya comparti enllaces con otres persones pa conceder l'accesu a esti sirvidor + prompt: Xenera y comparti enllaces con otres persones pa conceder l'accesu a esti sirvidor table: expires_at: Data de caducidá uses: Usos @@ -657,7 +658,7 @@ ast: successful_sign_in_html: Anicióse correutamente la sesión col métodu «%{method}» dende %{ip} (%{browser}) media_attachments: validations: - images_and_video: Nun se pue axuntar nengún videu a un artículu que xá contién imáxenes + images_and_video: Nun se pue axuntar nengún videu a un artículu que yá contién imáxenes too_many: Nun se puen axuntar más de 4 ficheros migrations: errors: @@ -707,16 +708,16 @@ ast: description_html: Si actives l'autenticación en dos pasos con una aplicación autenticadora, al aniciar la sesión va ser obligatorio que tengas el teléfonu a mano, preséu que xenera los pases que tienes d'introducir. enable: Activar instructions_html: "Escania esti códigu QR con Google Authenticator o otra aplicación asemeyada nel móvil. Dende agora, esa aplicación va xenerar los pases que tienes d'introducir cuando anicies la sesión." - manual_instructions: 'Si nun pues escaniar el códigu QR ya tienes d''introducilu manualmente, equí tienes el secretu en testu ensin formatu:' + manual_instructions: 'Si nun pues escaniar el códigu QR y tienes d''introducilu manualmente, equí tienes el secretu en testu ensin formatu:' setup: Configurar - wrong_code: "¡El códigu introducíu nun yera válidu! ¿La hora del sirvidor ya la del preséu son correutes?" + wrong_code: "¡El códigu introducíu nun yera válidu! ¿La hora del sirvidor y la del preséu son correutes?" pagination: next: Siguiente truncate: "…" polls: errors: - already_voted: Xá votesti nesta encuesta - expired: La encuesta xá finó + already_voted: Yá votesti nesta encuesta + expired: La encuesta yá finó invalid_choice: La opción de votu escoyida nun esiste too_many_options: nun pue contener más de %{max} elementos preferences: @@ -724,13 +725,13 @@ ast: posting_defaults: Configuración predeterminada del espublizamientu d'artículos public_timelines: Llinies de tiempu públiques privacy: - hint_html: "Personaliza cómo quies s'atope esti perfil ya los sos artículos. Hai una variedá de funciones de Mastodon que puen ayudate a algamar audiencies más grandes cuando s'activen. Dedica un momentu pa revisar estes opciones y asegurate de que s'axusten al to casu." + hint_html: "Personaliza cómo quies que s'atope esti perfil y los sos artículos. Hai una variedá de funciones de Mastodon que puen ayudate a algamar audiencies más grandes cuando s'activen. Dedica un momentu pa revisar estes opciones y asegurate de que s'axusten al to casu." privacy: Privacidá reach: Algame - reach_hint_html: Controla si quies que te descubran ya te sigan perfiles nuevos. ¿Quies que los tos artículos apaezan na pantalla «Esploración»? ¿Quies qu'otres persones te vean na recomendación de cuentes? ¿Quies aceptar toles solicitúes de siguimientu automáticamente o tener un control minuciosu de caúna? + reach_hint_html: Controla si quies que te descubran y te sigan perfiles nuevos. ¿Quies que los tos artículos apaezan na pantalla «Esploración»? ¿Quies qu'otres persones te vean na recomendación de cuentes? ¿Quies aceptar toles solicitúes de siguimientu automáticamente o tener un control minuciosu de caúna? search: Busca search_hint_html: Controla cómo quies que t'atopen. ¿Quies que la xente t'atope polo qu'espublices públicamente? ¿Quies que la xente fuera de Mástodon atope esti perfil cuando busque na web? Ten en cuenta que nun se pue garantizar la esclusión total de tolos motores de busca. - title: Privacidá ya algame + title: Privacidá y algame privacy_policy: title: Política de privacidá relationships: @@ -797,11 +798,11 @@ ast: export: Esportación de datos featured_tags: Etiquetes destacaes import: Importación - import_and_export: Importación ya esportación + import_and_export: Importación y esportación migrate: Migración de la cuenta preferences: Preferencies profile: Perfil públicu - relationships: Perfiles que sigues ya te siguen + relationships: Perfiles que sigues y te siguen statuses_cleanup: Desaniciu automáticu d'artículos two_factor_authentication: Autenticación en dos pasos webauthn_authentication: Llaves de seguranza @@ -822,7 +823,7 @@ ast: open_in_web: Abrir na web pin_errors: direct: Nun se puen fixar los artículos que son visibles namás pa los usuarios mentaos - limit: Xá fixesti'l númberu máximu d'artículos + limit: Yá fixesti'l númberu máximu d'artículos ownership: Nun se pue fixar l'artículu d'otru perfil reblog: Nun se pue fixar un artículu compartíu poll: @@ -877,15 +878,15 @@ ast: webauthn: Llaves de seguranza user_mailer: suspicious_sign_in: - explanation: Detectemos un aniciu de sesión a la to cuenta dende una direición IP nueva. + explanation: Detectemos un aniciu de sesión na to cuenta dende una direición IP nueva. subject: Accedióse a la to cuenta dende una direición IP nueva warning: appeal: Unviar una apellación appeal_description: Si te paez que ye un error, pues unviar una apellación al personal de %{instance}. explanation: - disable: Xá nun pues usar la cuenta mas el perfil ya otros datos siguen intautos. Pues solicitar una copia de seguranza de los datos, camudar la configuración de la cuenta o desaniciar la cuenta. - silence: Pues siguir usando la cuenta mas namás vas ver los artículos de los perfiles que xá siguieres nesti sirvidor ya ye posible que se t'escluya de dalgunes funciones de descubrimientu. Por embargu, otros perfiles entá puen siguite manualmente. - suspend: Xá nun pues usar la cuenta nin se pue acceder a los datos del to perfil. Pues aniciar la sesión pa pidir una copia de seguranza de los tos datos hasta que se desanicien en 30 díes, mas vamos caltener dalgunos datos básicos pa evitar que te saltes la suspensión. + disable: Yá nun pues usar la cuenta mas el perfil y otros datos siguen intautos. Pues solicitar una copia de seguranza de los datos, camudar la configuración de la cuenta o desaniciar la cuenta. + silence: Pues siguir usando la cuenta mas namás vas ver los artículos de los perfiles que yá siguieres nesti sirvidor y ye posible que se t'escluya de dalgunes funciones de descubrimientu. Por embargu, otros perfiles entá puen siguite manualmente. + suspend: Yá nun pues usar la cuenta nin se pue acceder a los datos del to perfil. Pues aniciar la sesión pa pidir una copia de seguranza de los tos datos hasta que se desanicien en 30 díes, mas vamos caltener dalgunos datos básicos pa evitar que te saltes la suspensión. reason: 'Motivu:' statuses: 'Artículos citaos:' subject: @@ -896,14 +897,27 @@ ast: none: Alvertencia suspend: Cuenta suspendida welcome: + apps_title: Aplicaciones de Mastodon + edit_profile_title: Personalización del perfil explanation: Equí tienes dalgunos conseyos pa que comiences + feature_action: Saber más + follows_title: A quién siguir + follows_view_more: Ver más perfiles a los que siguir + hashtags_recent_count: + one: "%{people} persona nos últimos 2 díes" + other: "%{people} persones nos últimos 2 díes" + hashtags_subtitle: Esplora qué ta en tendencia dende hai 2 díes + hashtags_title: Etiquetes en tendencia + hashtags_view_more: Ver más etiquetes en tendencia + post_step: Saluda al mundu con semeyes, vídeos, testu o encuestes. + sign_in_action: Aniciar la sesión subject: Afáyate en Mastodon title: "¡Afáyate, %{name}!" users: follow_limit_reached: Nun pues siguir a más de %{limit} persones invalid_otp_token: El códigu de l'autenticación en dos pasos nun ye válidu rate_limited: Fixéronse milenta intentos d'autenticación. Volvi tentalo dempués. - seamless_external_login: Aniciesti la sesión pente un serviciu esternu, polo que la configuración de la contraseña ya de la direición de corréu electrónicu nun tán disponibles. + seamless_external_login: Aniciesti la sesión pente un serviciu esternu, polo que la configuración de la contraseña y de la direición de corréu electrónicu nun tán disponibles. signed_in_as: 'Aniciesti la sesión como:' verification: verification: Verificación diff --git a/config/locales/bg.yml b/config/locales/bg.yml index 602a26225c2d23..c0abc3c845579d 100644 --- a/config/locales/bg.yml +++ b/config/locales/bg.yml @@ -226,6 +226,7 @@ bg: update_custom_emoji: Обновяване на персонализираното емоджи update_domain_block: Обновяване на блокирането за домейна update_ip_block: Обновяване на правило за IP + update_report: Обновяване на доклада update_status: Обновяване на публикация update_user_role: Обновяване на ролята actions: @@ -638,6 +639,7 @@ bg: report: 'Докладване на #%{id}' reported_account: Докладван акаунт reported_by: Докладвано от + reported_with_application: Докладвано с приложението resolved: Разрешено resolved_msg: Успешно разрешен доклад! skip_to_actions: Прескок към действия diff --git a/config/locales/ca.yml b/config/locales/ca.yml index f892df02c1e689..4d0e2ab389d2a4 100644 --- a/config/locales/ca.yml +++ b/config/locales/ca.yml @@ -226,6 +226,7 @@ ca: update_custom_emoji: Actualitza l'emoji personalitzat update_domain_block: Actualitza el Bloqueig de Domini update_ip_block: Actualitza norma IP + update_report: Actualitza l'informe update_status: Actualitza l'estat update_user_role: Actualitza Rol actions: @@ -638,6 +639,7 @@ ca: report: 'Informe #%{id}' reported_account: Compte denunciat reported_by: Denunciat per + reported_with_application: Reportat amb l'aplicació resolved: Resolt resolved_msg: Informe resolt correctament! skip_to_actions: Salta a les accions diff --git a/config/locales/cy.yml b/config/locales/cy.yml index 35ed5ade8aa913..cd48b3e3b0ec2f 100644 --- a/config/locales/cy.yml +++ b/config/locales/cy.yml @@ -305,6 +305,7 @@ cy: filter_by_action: Hidlo yn ôl gweithred filter_by_user: Hidlo yn ôl defnyddiwr title: Cofnod archwilio + unavailable_instance: "(nid yw enw'r parth ar gael)" announcements: destroyed_msg: Cyhoeddiad wedi'i ddileu'n llwyddiannus! edit: @@ -1436,7 +1437,7 @@ cy: domain_blocking_html: Rydych ar fin rhwystro hyd at %{total_items} parth o %{filename} . following_html: Rydych ar fin dilyn hyd at %{total_items} cyfrif gan %{filename} . lists_html: Rydych ar fin ychwanegu hyd at %{total_items} o gyfrifon o %{filename} at eich rhestrau . Bydd rhestrau newydd yn cael eu creu os nad oes rhestr i ychwanegu ati. - muting_html: Rydych ar fin tewi hyd at %{total_items} cyfrif o %{filename} . + muting_html: Rydych ar fin anwybyddu hyd at %{total_items} cyfrif o %{filename}. preface: Gallwch fewnforio data rydych chi wedi'i allforio o weinydd arall, fel rhestr o'r bobl rydych chi'n eu dilyn neu'n eu blocio. recent_imports: Mewnforion diweddar states: @@ -1529,9 +1530,9 @@ cy: too_many: Methu atodi mwy na 4 ffeil migrations: acct: Symudwyd i - cancel: Diddymu ailgyfeirio - cancel_explanation: Bydd diddymu'r ailgyfeiriad yn ail agor eich cyfrif cyfredol, ond ni fydd yn dod â dilynwyr sydd wedi'u symud i'r cyfrif hwnnw yn ôl. - cancelled_msg: Wedi diddymu'r ailgyfeiriad yn llwyddiannus. + cancel: Canslo ailgyfeirio + cancel_explanation: Bydd canslo'r ailgyfeiriad yn ail agor eich cyfrif cyfredol, ond ni fydd yn dod â dilynwyr sydd wedi'u symud i'r cyfrif hwnnw yn ôl. + cancelled_msg: Wedi canslo'r ailgyfeiriad yn llwyddiannus. errors: already_moved: yw'r un cyfrif rydych chi wedi symud iddo eisoes missing_also_known_as: nid yw'n arallenw o'r cyfrif hwn diff --git a/config/locales/da.yml b/config/locales/da.yml index fc7373cc94c700..75da9a0b363fdf 100644 --- a/config/locales/da.yml +++ b/config/locales/da.yml @@ -226,6 +226,7 @@ da: update_custom_emoji: Opdatér tilpasset emoji update_domain_block: Opdatér domæneblokering update_ip_block: Opdatér IP-regel + update_report: Opdatér anmeldelse update_status: Opdatér indlæg update_user_role: Opdatér rolle actions: diff --git a/config/locales/de.yml b/config/locales/de.yml index 82ed9d8178c3d5..81b7cd172d64fb 100644 --- a/config/locales/de.yml +++ b/config/locales/de.yml @@ -226,6 +226,7 @@ de: update_custom_emoji: Eigenes Emoji aktualisieren update_domain_block: Domain-Sperre aktualisieren update_ip_block: IP-Regel aktualisieren + update_report: Meldung aktualisieren update_status: Beitrag aktualisieren update_user_role: Rolle bearbeiten actions: @@ -638,6 +639,7 @@ de: report: "%{id}. Meldung" reported_account: Gemeldetes Konto reported_by: Gemeldet von + reported_with_application: Per App gemeldet resolved: Geklärt resolved_msg: Meldung erfolgreich geklärt! skip_to_actions: Zur Maßnahme springen diff --git a/config/locales/devise.ast.yml b/config/locales/devise.ast.yml index 47372c2f07a68d..c3536070439b9c 100644 --- a/config/locales/devise.ast.yml +++ b/config/locales/devise.ast.yml @@ -6,7 +6,7 @@ ast: send_instructions: Nunos minutos vas recibir un mensaxe coles instrucciones pa saber cómo confirmar la direición de corréu electrónicu. Revisa la carpeta Puxarra si nun recibiesti esti mensaxe. send_paranoid_instructions: Si la direición de corréu electrónicu esiste na nuesa base de datos, nunos minutos vas recibir un mensaxe coles instrucciones pa saber cómo confirmala. Revisa la carpeta Puxarra si nun recibiesti esti mensaxe. failure: - already_authenticated: Xá aniciesti la sesión. + already_authenticated: Yá aniciesti la sesión. last_attempt: Quédate un intentu más enantes de bloquiar la cuenta. locked: La cuenta ta bloquiada. pending: La cuenta sigue en revisión. @@ -16,9 +16,9 @@ ast: mailer: confirmation_instructions: action: Verificar la direición de corréu electrónicu - explanation: Creesti una cuenta en %{host} con esta direición de corréu electrónicu ya tas a un calcu d'activala. Si nun fixesti esta aición, inora esti mensaxe. - explanation_when_pending: Solicitesti una invitación a %{host} con esta direición de corréu electrónicu. Namás que confirmes la direición de corréu electrónicu, vamos revisar la solicitú. Entrín ya non, pues aniciar la sesión pa camudar los detalles o desaniciar la cuenta, mas nun pues acceder a la mayoría de funciones hasta que la cuenta nun tea aprobada. Si se refuga la solicitú, nun ye necesario que faigas nada más o si, per otra parte, tu nun fixesti esta aición, inora esti mensaxe. - extra_html: Revisa tamién les normes del sirvidor ya los nuesos términos del serviciu. + explanation: Creesti una cuenta en %{host} con esta direición de corréu electrónicu y tas a un calcu d'activala. Si nun fixesti esta aición, inora esti mensaxe. + explanation_when_pending: Solicitesti una invitación a %{host} con esta direición de corréu electrónicu. Namás que confirmes la direición de corréu electrónicu, vamos revisar la solicitú. Entrín y non, pues aniciar la sesión pa camudar los detalles o desaniciar la cuenta, mas nun pues acceder a la mayoría de funciones hasta que la cuenta nun tea aprobada. Si se refuga la solicitú, nun ye necesario que faigas nada más o si, per otra parte, tu nun fixesti esta aición, inora esti mensaxe. + extra_html: Revisa tamién les normes del sirvidor y los nuesos términos del serviciu. subject: 'Mastodon: instrucciones de confirmación de «%{instance}»' title: Verificación de la direición de corréu electrónicu email_changed: @@ -38,7 +38,7 @@ ast: reset_password_instructions: action: Camudar la contraseña explanation: Solicitesti una contraseña nueva pa la to cuenta. - extra: Si nun solicitesti esta aición, inora esti mensaxe. La contraseña nun va camudar hasta que nun accedas al enllaz d'arriba ya crees una. + extra: Si nun solicitesti esta aición, inora esti mensaxe. La contraseña nun va camudar hasta que nun accedas al enllaz d'arriba y crees una. subject: 'Mastodon: instrucciones pa camudar la contraseña' title: Cambéu de la contaseña two_factor_disabled: @@ -48,7 +48,7 @@ ast: subject: 'Mastodon: activóse l''autenticación en dos pasos' title: Autenticación de dos pasos desactivada two_factor_recovery_codes_changed: - explanation: Invalidáronse los códigos de recuperación anteriores ya xeneráronse otros nuevos. + explanation: Invalidáronse los códigos de recuperación anteriores y xeneráronse otros nuevos. subject: 'Mastodon: volvieron xenerase los códigos de recuperación de l''autenticación en dos pasos' unlock_instructions: subject: 'Mastodon: instrucciones de desbloquéu' @@ -68,16 +68,16 @@ ast: passwords: send_instructions: Si la direición de corréu electrónicu esiste na nuesa base de datos, nunos minutos vas recibir un enllaz pa recuperar la contraseña. Revisa la carpeta Puxarra si nun recibiesti esti mensaxe. send_paranoid_instructions: Si la direición de corréu electrónicu esiste na nuesa base de datos, nunos minutos vas recibir un enllaz pa recuperar la contraseña. Revisa la carpeta Puxarra si nun recibiesti esti mensaxe. - updated: La contraseña camudó correutamente. Xá aniciesti la sesión. + updated: La contraseña camudó correutamente. yá aniciesti la sesión. updated_not_active: La contraseña camudó correutamente. registrations: destroyed: "¡Ta llueu! La cuenta anulóse correutamente. Esperamos volver vete pronto." signed_up: "¡Afáyate! Rexistréstite correutamente." signed_up_but_inactive: Rexistréstite correutamente. Por embargu, nun se pudo aniciar la sesión porque la cuenta entá nun s'activó. signed_up_but_locked: Rexistréstite correutamente. Por embargu, nun se pudo aniciar la sesión porque la cuenta ta bloquiada. - signed_up_but_pending: Unvióse un mensaxe a la direición de corréu electrónicu que contién un enllaz de confirmación. Darréu de calcar nel enllaz, vamos revisar la solicitú ya si s'aprueba, avisámoste. - signed_up_but_unconfirmed: Unvióse un mensaxe de confirmación a la to direición de corréu electrónicu. Sigui l'enllaz p'activar la cuenta ya revisa la carpeta Puxarra si nun recibiesti esti mensaxe. - update_needs_confirmation: Anovesti la cuenta correutamente, mas tenemos de verificar la direición de corréu electrónicu nueva. Revisa'l to corréu electrónicu ya sigui l'enllaz de confirmación pa confirmar esta direición. Si nun recibiesti'l mensaxe, revisa la carpeta Puxarra. + signed_up_but_pending: Unvióse un mensaxe a la direición de corréu electrónicu que contién un enllaz de confirmación. Darréu de calcar nel enllaz, vamos revisar la solicitú y si s'aprueba, avisámoste. + signed_up_but_unconfirmed: Unvióse un mensaxe de confirmación a la to direición de corréu electrónicu. Sigui l'enllaz p'activar la cuenta y revisa la carpeta Puxarra si nun recibiesti esti mensaxe. + update_needs_confirmation: Anovesti la cuenta correutamente, mas tenemos de verificar la direición de corréu electrónicu nueva. Revisa'l to corréu electrónicu y sigui l'enllaz de confirmación pa confirmar esta direición. Si nun recibiesti'l mensaxe, revisa la carpeta Puxarra. updated: La cuenta anovóse correutamente. sessions: already_signed_out: Zarresti la sesión correutamente. @@ -89,7 +89,7 @@ ast: unlocked: La cuenta desbloquióse correutamente. Anicia la sesión pa siguir. errors: messages: - already_confirmed: xá se confirmó, prueba a aniciar la sesión + already_confirmed: yá se confirmó, prueba a aniciar la sesión not_saved: one: '1 error torgó que «%{resource}» se guardare:' other: "%{count} errores torgaron que «%{resource}» se guardaren:" diff --git a/config/locales/devise.cy.yml b/config/locales/devise.cy.yml index 523ae70b049c4a..b41e12f85d69fd 100644 --- a/config/locales/devise.cy.yml +++ b/config/locales/devise.cy.yml @@ -93,7 +93,7 @@ cy: updated: Mae eich cyfrinair wedi'i newid yn llwyddiannus. Rydych chi bellach wedi mewngofnodi. updated_not_active: Mae eich cyfrinair wedi ei newid yn llwyddiannus. registrations: - destroyed: Hwyl fawr! Mae eich cyfrif wedi ei ddiddymu'n llwyddiannus. Gobeithiwn eich gweld chi eto'n fuan. + destroyed: Hwyl fawr! Mae eich cyfrif wedi ei chanslo'n llwyddiannus. Gobeithiwn eich gweld chi eto'n fuan. signed_up: Croeso! Rydych wedi cofrestru'n llwyddiannus. signed_up_but_inactive: Yr ydych wedi cofrestru'n llwyddiannus. Fodd bynnag, ni allwn eich mewngofnodi achos nid yw eich cyfrif wedi ei hagor eto. signed_up_but_locked: Rydych chi wedi cofrestru'n llwyddiannus. Fodd bynnag, ni allem eich mewngofnodi oherwydd bod eich cyfrif wedi'i gloi. diff --git a/config/locales/devise.ga.yml b/config/locales/devise.ga.yml index 6e6bd0a01360b3..ca51bb9467dbe6 100644 --- a/config/locales/devise.ga.yml +++ b/config/locales/devise.ga.yml @@ -11,19 +11,114 @@ ga: invalid: "%{authentication_keys} nó pasfhocal neamhbhailí." last_attempt: Tá iarracht amháin eile agat sula gcuirtear do chuntas faoi ghlas. locked: Tá do chuntas faoi ghlas. + not_found_in_database: "%{authentication_keys} nó pasfhocal neamhbhailí." + omniauth_user_creation_failure: Earráid agus cuntas á chruthú don aitheantas seo. pending: Tá do chuntas fós faoi athbhreithniú. + timeout: Chuaigh do sheisiún in éag. Logáil isteach arís chun leanúint ar aghaidh. unauthenticated: Ní mór duit lógáil isteach nó síniú suas roimh leanúint leat. unconfirmed: Caithfidh tú do r-phost a dheimhniú roimh leanúint leat. mailer: confirmation_instructions: action: Deimhnigh seoladh r-phost action_with_app: Deimhnigh agus fill ar %{app} + explanation: Tá cuntas cruthaithe agat ar %{host} leis an seoladh ríomhphoist seo. Tá tú ceann cliceáil ar shiúl ó é a ghníomhachtú. Mura tusa a bhí ann, déan neamhaird den ríomhphost seo le do thoil. + explanation_when_pending: Chuir tú isteach ar chuireadh chuig %{host} leis an seoladh ríomhphoist seo. Nuair a dheimhníonn tú do sheoladh r-phoist, déanfaimid athbhreithniú ar d’iarratas. Is féidir leat logáil isteach chun do shonraí a athrú nó chun do chuntas a scriosadh, ach ní féidir leat rochtain a fháil ar fhormhór na bhfeidhmeanna go dtí go mbeidh do chuntas faofa. Má dhiúltaítear do d’iarratas, bainfear do shonraí, mar sin ní bheidh aon ghníomh eile ag teastáil uait. Mura tusa a bhí ann, déan neamhaird den ríomhphost seo le do thoil. + extra_html: Seiceáil freisin rialacha an fhreastalaí agus ár dtéarmaí seirbhíse. + subject: 'Mastodon: Treoracha dearbhaithe do %{instance}' + title: Fíoraigh seoladh ríomhphoist email_changed: + explanation: 'Tá seoladh ríomhphoist do chuntais á athrú go:' + extra: Murar athraigh tú do ríomhphost, is dócha go bhfuil rochtain faighte ag duine éigin ar do chuntas. Athraigh do phasfhocal láithreach le do thoil nó déan teagmháil le riarthóir an fhreastalaí má tá tú glasáilte amach as do chuntas. + subject: 'Mastodon: Athraíodh an ríomhphost' title: Seoladh ríomhphoist nua password_change: + explanation: Athraíodh an pasfhocal do do chuntas. + extra: Murar athraigh tú do phasfhocal, is dócha go bhfuil rochtain faighte ag duine éigin ar do chuntas. Athraigh do phasfhocal láithreach le do thoil nó déan teagmháil le riarthóir an fhreastalaí má tá tú glasáilte amach as do chuntas. + subject: 'Mastodon: Athraíodh an pasfhocal' title: Pasfhocal athraithe + reconfirmation_instructions: + explanation: Deimhnigh an seoladh nua chun do ríomhphost a athrú. + extra: Murar tusa a thionscain an t-athrú seo, déan neamhaird den ríomhphost seo le do thoil. Ní athrófar seoladh ríomhphoist an chuntais Mastodon go dtí go bhfaighidh tú rochtain ar an nasc thuas. + subject: 'Mastodon: Deimhnigh ríomhphost le haghaidh %{instance}' + title: Fíoraigh seoladh ríomhphoist reset_password_instructions: action: Athraigh pasfhocal + explanation: D'iarr tú pasfhocal nua do do chuntas. + extra: Murar iarr tú é seo, déan neamhaird den ríomhphost seo le do thoil. Ní athrófar do phasfhocal go dtí go bhfaighidh tú rochtain ar an nasc thuas agus go gcruthóidh tú ceann nua. + subject: 'Mastodon: Athshocraigh treoracha pasfhocail' + title: Athshocrú pasfhocal + two_factor_disabled: + explanation: Is féidir logáil isteach anois ach úsáid a bhaint as seoladh ríomhphoist agus pasfhocal amháin. + subject: 'Mastodon: Díchumasaíodh fíordheimhniú dhá fhachtóir' + subtitle: Díchumasaíodh fíordheimhniú dhá-fhachtóir do do chuntas. + title: 2FA díchumasaithe + two_factor_enabled: + explanation: Beidh comhartha ginte ag an aip TOTP péireáilte ag teastáil chun logáil isteach. + subject: 'Mastodon: Fíordheimhniú dhá-fhachtóir cumasaithe' + subtitle: Cumasaíodh fíordheimhniú dhá fhachtóir do do chuntas. + title: 2FA cumasaithe + two_factor_recovery_codes_changed: + explanation: Tá na cóid athshlánaithe roimhe seo neamhbhailí agus gineadh cinn nua. + subject: 'Mastodon: Cóid aisghabhála dhá-fhachtóir athghinte' + subtitle: Tá na cóid athshlánaithe roimhe seo neamhbhailí agus gineadh cinn nua. + title: Athraíodh cóid aisghabhála 2FA + unlock_instructions: + subject: 'Mastodon: Díghlasáil treoracha' + webauthn_credential: + added: + explanation: Cuireadh an eochair shlándála seo a leanas le do chuntas + subject: 'Mastodon: Eochair shlándála nua' + title: Tá eochair shlándála nua curtha leis + deleted: + explanation: Scriosadh an eochair shlándála seo a leanas ó do chuntas + subject: 'Mastodon: Scriosadh an eochair shlándála' + title: Scriosadh ceann de d'eochracha slándála + webauthn_disabled: + explanation: Díchumasaíodh fíordheimhniú le heochracha slándála do do chuntas. + extra: Is féidir logáil isteach anois ag baint úsáide as an comhartha a ghineann an aip TOTP péireáilte amháin. + subject: 'Mastodon: Díchumasaíodh fíordheimhniú le heochracha slándála' + title: Eochracha slándála díchumasaithe + webauthn_enabled: + explanation: Cumasaíodh fíordheimhniú eochair shlándála do do chuntas. + extra: Is féidir d'eochair shlándála a úsáid le logáil isteach anois. + subject: 'Mastodon: Fíordheimhniú eochair shlándála cumasaithe' + title: Eochracha slándála cumasaithe + omniauth_callbacks: + failure: Níorbh fhéidir tú a fhíordheimhniú ó %{kind} toisc "%{reason}". + success: D'éirigh le fíordheimhniú ó chuntas %{kind}. + passwords: + no_token: Ní féidir leat rochtain a fháil ar an leathanach seo gan teacht ó ríomhphost athshocraithe pasfhocail. Má thagann tú ó ríomhphost athshocraithe pasfhocail, cinntigh le do thoil gur úsáid tú an URL iomlán a cuireadh ar fáil. + send_instructions: Má tá do sheoladh ríomhphoist inár mbunachar sonraí, gheobhaidh tú nasc athshlánaithe pasfhocail ag do sheoladh ríomhphoist i gceann cúpla nóiméad. Seiceáil d'fhillteán turscair mura bhfuair tú an ríomhphost seo. + send_paranoid_instructions: Má tá do sheoladh ríomhphoist inár mbunachar sonraí, gheobhaidh tú nasc athshlánaithe pasfhocail ag do sheoladh ríomhphoist i gceann cúpla nóiméad. Seiceáil d'fhillteán turscair mura bhfuair tú an ríomhphost seo. + updated: Athraíodh do phasfhocal go rathúil. Tá tú sínithe isteach anois. + updated_not_active: Athraíodh do phasfhocal go rathúil. + registrations: + destroyed: Slán! Cealaíodh do chuntas go rathúil. Tá súil againn tú a fheiceáil arís go luath. + signed_up: Fáilte romhat! D'éirigh leat síniú suas. + signed_up_but_inactive: D'éirigh leat síniú suas. Mar sin féin, níorbh fhéidir linn tú a shíniú isteach toisc nach bhfuil do chuntas gníomhachtaithe fós. + signed_up_but_locked: D'éirigh leat síniú suas. Mar sin féin, níorbh fhéidir linn tú a shíniú isteach toisc go bhfuil do chuntas glasáilte. + signed_up_but_pending: Tá teachtaireacht le nasc deimhnithe seolta chuig do sheoladh ríomhphoist. Tar éis duit an nasc a chliceáil, déanfaimid athbhreithniú ar d’iarratas. Cuirfear in iúl duit má cheadaítear é. + signed_up_but_unconfirmed: Tá teachtaireacht le nasc deimhnithe seolta chuig do sheoladh ríomhphoist. Lean an nasc chun do chuntas a ghníomhachtú. Seiceáil d'fhillteán turscair mura bhfuair tú an ríomhphost seo. + update_needs_confirmation: D'éirigh leat do chuntas a nuashonrú, ach caithfimid do sheoladh ríomhphoist nua a fhíorú. Seiceáil do ríomhphost agus lean an nasc dearbhaithe chun do sheoladh ríomhphoist nua a dhearbhú. Seiceáil d'fhillteán turscair mura bhfuair tú an ríomhphost seo. + updated: D'éirigh le do chuntas a nuashonrú. + sessions: + already_signed_out: D'éirigh le síniú amach. + signed_in: D'éirigh le síniú isteach. + signed_out: D'éirigh le síniú amach. + unlocks: + send_instructions: Gheobhaidh tú ríomhphost le treoracha maidir le conas do chuntas a dhíghlasáil i gceann cúpla nóiméad. Seiceáil d'fhillteán turscair mura bhfuair tú an ríomhphost seo. + send_paranoid_instructions: Má tá do chuntas ann, gheobhaidh tú ríomhphost le treoracha maidir le conas é a dhíghlasáil i gceann cúpla nóiméad. Seiceáil d'fhillteán turscair mura bhfuair tú an ríomhphost seo. + unlocked: Díghlasáladh do chuntas go rathúil. Logáil isteach le do thoil chun leanúint ar aghaidh. errors: messages: + already_confirmed: deimhníodh cheana féin, bain triail as síniú isteach + confirmation_period_expired: ní mór é a dhearbhú laistigh de %{period}, iarr ceann nua le do thoil + expired: imithe in éag, iarr ceann nua le do thoil not_found: níor aimsíodh é + not_locked: nach raibh faoi ghlas + not_saved: + few: 'Chuir %{count} earráid cosc ​​ar an %{resource} seo a shábháil:' + many: 'Chuir %{count} earráid cosc ​​ar an %{resource} seo a shábháil:' + one: 'Chuir earráid 1 cosc ​​ar an %{resource} seo a shábháil:' + other: 'Chuir %{count} earráid cosc ​​ar an %{resource} seo a shábháil:' + two: 'Chuir %{count} earráid cosc ​​ar an %{resource} seo a shábháil:' diff --git a/config/locales/devise.zh-TW.yml b/config/locales/devise.zh-TW.yml index 7ead831e4f75aa..3e3af9f323997c 100644 --- a/config/locales/devise.zh-TW.yml +++ b/config/locales/devise.zh-TW.yml @@ -75,7 +75,7 @@ zh-TW: title: 您的一支安全密鑰已經被移除 webauthn_disabled: explanation: 您的帳號已停用安全金鑰身份驗證。 - extra: 現在僅可使用配對的 TOTP 應用程式產生之 token 登入。 + extra: 目前僅可使用配對的 TOTP 應用程式產生之 token 登入。 subject: Mastodon:安全密鑰認證方式已停用 title: 已停用安全密鑰 webauthn_enabled: @@ -90,7 +90,7 @@ zh-TW: no_token: 您必須透過密碼重設信件才能存取此頁面。若確實如此,請確定輸入的網址是完整的。 send_instructions: 若電子郵件地址存在於我們的資料庫,幾分鐘後您將於信箱中收到密碼復原連結。若未收到請檢查垃圾郵件資料夾。 send_paranoid_instructions: 若電子郵件地址存在於我們的資料庫,幾分鐘後您將於信箱中收到密碼復原連結。若未收到請檢查垃圾郵件資料夾。 - updated: 您的密碼已成功變更,現在已經登入。 + updated: 您的密碼已成功變更,您現在已經成功登入。 updated_not_active: 您的密碼已成功變更。 registrations: destroyed: 再見!您的帳號已成功取消,期待再相逢。 diff --git a/config/locales/doorkeeper.ast.yml b/config/locales/doorkeeper.ast.yml index 0564e49dac18ff..0df15a07b62330 100644 --- a/config/locales/doorkeeper.ast.yml +++ b/config/locales/doorkeeper.ast.yml @@ -44,7 +44,7 @@ ast: prompt_html: "%{client_name}, que ye una aplicación de terceros, quier tener accesu a la cuenta. Si nun t'enfotes nella, nun habríes autorizala." review_permissions: Revisión de los permisos show: - title: Copia esti códigu d'autorización ya apiégalu na aplicación. + title: Copia esti códigu d'autorización y apiégalu na aplicación. authorized_applications: buttons: revoke: Revocar @@ -67,7 +67,7 @@ ast: grouped_scopes: access: read: Accesu de namás llectura - read/write: Accesu de llectura ya escritura + read/write: Accesu de llectura y escritura write: Accesu de namás escritura title: accounts: Cuentes @@ -111,14 +111,14 @@ ast: read:statuses: mira tolos artículos write: modifica los datos de les cuentes write:accounts: modifica los perfiles - write:blocks: bloquia cuentes ya dominios + write:blocks: bloquia cuentes y dominios write:bookmarks: meter artículos en Marcadores - write:conversations: desaniciar ya desactivar los avisos de conversaciones + write:conversations: desaniciar y desactivar los avisos de conversaciones write:filters: crea peñeres write:follows: sigue a perfiles write:lists: crea llistes write:media: xube ficheros multimedia - write:mutes: desactiva los avisos de perfiles ya de conversaciones + write:mutes: desactiva los avisos de perfiles y de conversaciones write:notifications: borra los avisos write:reports: informa d'otros perfiles write:statuses: espubliza artículos diff --git a/config/locales/doorkeeper.cy.yml b/config/locales/doorkeeper.cy.yml index e79aa0359f67b8..e023bc060312c8 100644 --- a/config/locales/doorkeeper.cy.yml +++ b/config/locales/doorkeeper.cy.yml @@ -20,7 +20,7 @@ cy: applications: buttons: authorize: Awdurdodi - cancel: Diddymu + cancel: Canslo destroy: Dinistrio edit: Golygu submit: Cyflwyno @@ -72,7 +72,7 @@ cy: revoke: Ydych chi'n siŵr? index: authorized_at: Wedi'i awdurdodi ar %{date} - description_html: Mae'r rhain yn raglenni sy'n gallu cael mynediad i'ch cyfrif gan ddefnyddio'r API. Os oes yna rhaglenni nad ydych chi'n eu hadnabod yma, neu os yw rhaglen yn camymddwyn, gallwch chi ddiddymu ei fynediad. + description_html: Mae'r rhain yn raglenni sy'n gallu cael mynediad i'ch cyfrif gan ddefnyddio'r API. Os oes yna rhaglenni nad ydych chi'n eu hadnabod yma, neu os yw rhaglen yn camymddwyn, gallwch chi ddirymu ei fynediad. last_used_at: Defnyddiwyd ddiwethaf ar %{date} never_used: Erioed wedi'i ddefnyddio scopes: Caniatâd @@ -83,7 +83,7 @@ cy: access_denied: Mae perchennog yr adnodd neu'r gweinydd awdurdodi wedi atal y cais. credential_flow_not_configured: Llif meini prawf cyfrinair perchennog yr adnodd wedi methu achos fod Doorkeeper.configure.resource_owner_from_credentials heb ei ffurfweddu. invalid_client: Methodd dilysu cleient oherwydd cleient anhysbys, dim dilysiad cleient wedi'i gynnwys, neu ddull dilysu heb ei gefnogi. - invalid_grant: Mae'r grant awdurdodi ar yr amod yn annilys, wedi dod i ben, wedi'i ddiddymu, nid yw'n cyfateb i'r URI ailgyfeirio a ddefnyddiwyd yn y cais am awdurdodiad, neu wedi'i roi i gleient arall. + invalid_grant: Mae'r grant awdurdodi ar yr amod yn annilys, wedi dod i ben, wedi'i ddirymu, nid yw'n cyfateb i'r URI ailgyfeirio a ddefnyddiwyd yn y cais am awdurdodiad, neu wedi'i roi i gleient arall. invalid_redirect_uri: Nid yw'r uri ailgyfeirio a gynhwysir yn ddilys. invalid_request: missing_param: 'Paramedr gofynnol ar goll: %{value}.' @@ -135,6 +135,7 @@ cy: media: Atodiadau cyfryngau mutes: Anwybyddiadau notifications: Hysbysiadau + profile: Eich proffil Mastodon push: Hysbysiadau gwthiadwy reports: Adroddiadau search: Chwilio @@ -165,6 +166,7 @@ cy: admin:write:reports: cyflawni camau cymedroli ar adroddiadau crypto: defnyddio amgryptio ben i ben follow: addasu perthnasau cyfrif + profile: darllen dim ond gwybodaeth proffil eich cyfrif push: derbyn eich hysbysiadau gwthiadwy read: darllen holl ddata eich cyfrif read:accounts: gweld gwybodaeth y cyfrif diff --git a/config/locales/doorkeeper.el.yml b/config/locales/doorkeeper.el.yml index 1cb9b3513bbda6..167cc6bd44e99b 100644 --- a/config/locales/doorkeeper.el.yml +++ b/config/locales/doorkeeper.el.yml @@ -4,7 +4,7 @@ el: attributes: doorkeeper/application: name: Όνομα εφαρμογής - redirect_uri: URI Ανακατεύθυνσης (Ενιαίο Αναγνωριστικό Πόρων) + redirect_uri: URI Ανακατεύθυνσης scopes: Εύρος εφαρμογής website: Ιστότοπος εφαρμογής errors: @@ -13,21 +13,21 @@ el: attributes: redirect_uri: fragment_present: δεν μπορεί να περιέχει τμήμα διεύθυνσης. - invalid_uri: πρέπει να είναι έγκυρο URI (Ενιαίο Αναγνωριστικό Πόρων). - relative_uri: πρέπει να είναι απόλυτο URI (Ενιαίο Αναγνωριστικό Πόρων). - secured_uri: πρέπει να είναι HTTPS/SSL URI (Ενιαίο Αναγνωριστικό Πόρων). + invalid_uri: πρέπει να είναι έγκυρο URI. + relative_uri: πρέπει να είναι απόλυτο URI. + secured_uri: πρέπει να είναι HTTPS/SSL URI. doorkeeper: applications: buttons: - authorize: Ενέκρινε + authorize: Έγκριση cancel: Άκυρο destroy: Καταστροφή - edit: Αλλαγή + edit: Επεξεργασία submit: Υποβολή confirmations: destroy: Σίγουρα; edit: - title: Αλλαγή εφαρμογής + title: Επεξεργασία εφαρμογής form: error: Ώπα! Έλεγξε τη φόρμα σου για πιθανά λάθη help: @@ -36,9 +36,9 @@ el: scopes: Διαχώρησε το κάθε εύρος εφαρμογής με κενά. Άστο κενό για χρήση των προεπιλεγμένων ευρών εφαρμογής. index: application: Εφαρμογή - callback_url: URL επιστροφής (Callback) + callback_url: Callback URL delete: Διαγραφή - empty: Δεν έχετε αιτήσεις. + empty: Δεν έχεις εφαρμογές. name: Όνομα new: Νέα εφαρμογή scopes: Εύρος εφαρμογής @@ -49,32 +49,32 @@ el: show: actions: Ενέργειες application_id: Κλειδί πελάτη - callback_urls: URL επιστροφής (Callback) + callback_urls: Callback URLs scopes: Εύρος εφαρμογής secret: Μυστικό πελάτη title: 'Εφαρμογή: %{name}' authorizations: buttons: - authorize: Ενέκρινε - deny: Απόρριψε + authorize: Έγκριση + deny: Απόρριψη error: title: Εμφανίστηκε σφάλμα new: - prompt_html: Ο/Η %{client_name} θα ήθελε άδεια πρόσβασης στο λογαριασμό σας. Είναι μια εφαρμογή από τρίτους. Αν δεν το εμπιστεύεστε, τότε δεν πρέπει να το εξουσιοδοτήσετε. - review_permissions: Αναθεώρηση δικαιωμάτων + prompt_html: Το %{client_name} θα ήθελε άδεια πρόσβασης στο λογαριασμό σου. Είναι μια εφαρμογή τρίτων. Αν δεν το εμπιστεύεσαι, τότε δεν πρέπει να το εγκρίνεις. + review_permissions: Ανασκόπηση δικαιωμάτων title: Απαιτείται έγκριση show: title: Αντέγραψε αυτό τον κωδικό έγκρισης στην εφαρμογή. authorized_applications: buttons: - revoke: Ανακάλεσε + revoke: Ανάκληση confirmations: revoke: Σίγουρα; index: authorized_at: Εξουσιοδοτήθηκε στις %{date} - description_html: Αυτές είναι εφαρμογές που μπορούν να έχουν πρόσβαση στο λογαριασμό σας χρησιμοποιώντας το API. Αν υπάρχουν εφαρμογές που δεν αναγνωρίζετε εδώ ή μια εφαρμογή δεν συμπεριφέρεται σωστά, μπορείτε να ανακαλέσετε την πρόσβασή της. + description_html: Αυτές είναι εφαρμογές που μπορούν να έχουν πρόσβαση στο λογαριασμό σου χρησιμοποιώντας το API. Αν υπάρχουν εφαρμογές που δεν αναγνωρίζεις εδώ ή μια εφαρμογή δεν συμπεριφέρεται σωστά, μπορείς να ανακαλέσεις την πρόσβασή της. last_used_at: Τελευταία χρήση στις %{date} - never_used: Ποτέ σε χρήση + never_used: Δεν έχει χρησιμοποιηθεί scopes: Δικαιώματα superapp: Εσωτερική title: Οι εφαρμογές που έχεις εγκρίνει @@ -84,23 +84,23 @@ el: credential_flow_not_configured: Η ροή Resource Owner Password Credentials απέτυχε επειδή το Doorkeeper.configure.resource_owner_from_credentials δεν έχει ρυθμιστεί. invalid_client: Η ταυτοποίηση του πελάτη απέτυχε είτε λόγω άγνωστου πελάτη, είτε λόγω έλλειψης ταυτοποιημένου πελάτη ή λόγω μη υποστηριζόμενης μεθόδου ταυτοποίησης. invalid_grant: Η άδεια πιστοποίησης που δόθηκε είναι άκυρη, ληγμένη, έχει ανακληθεί, δεν συμφωνεί με το URI ανακατεύθυνσης που δόθηκε στο αίτημα πιστοποίησης ή εκδόθηκε προς άλλο πελάτη. - invalid_redirect_uri: Το URI ανακατεύθυνσης που δόθηκε δεν είναι έγκυρο. + invalid_redirect_uri: Το uri ανακατεύθυνσης που δόθηκε δεν είναι έγκυρο. invalid_request: - missing_param: 'Λείπει η απαιτούμενη παράμετρος: %{value}.' + missing_param: 'Λείπει απαιτούμενη παράμετρος: %{value}.' request_not_authorized: Το αίτημα πρέπει να είναι εξουσιοδοτημένο. Η απαιτούμενη παράμετρος για την έγκριση της αίτησης λείπει ή είναι άκυρη. unknown: Από το αίτημα λείπει μία υποχρεωτική παράμετρος ή περιλαμβάνει μια μη υποστηριζόμενη τιμή ή έχει λανθασμένη μορφή με κάποιο άλλο τρόπο. - invalid_resource_owner: Τα διαπιστευτήρια που έδωσε ο ιδιοκτήτης του πόρου δεν είναι έγκυρα, ή δεν βρέθηκε ο ιδιοκτήτης του πόρου + invalid_resource_owner: Τα διαπιστευτήρια που έδωσε ο ιδιοκτήτης του πόρου δεν είναι έγκυρα ή δεν βρέθηκε ο ιδιοκτήτης του πόρου invalid_scope: Το αιτούμενο εύρος εφαρμογής είναι άκυρο, άγνωστο ή λάθος διατυπωμένο. invalid_token: expired: Το διακριτικό πρόσβασης έληξε revoked: Το διακριτικό πρόσβασης ανακλήθηκε unknown: Το διακριτικό πρόσβασης δεν είναι έγκυρο resource_owner_authenticator_not_configured: Η αναζήτηση του ιδιοκτήτη του πόρου απέτυχε επειδή το Doorkeeper.configure.resource_owner_authenticator δεν έχει ρυθμιστεί. - server_error: Ο εξυπηρετητής έγκρισης (authorization server) αντιμετώπισε μια απροσδόκητη συνθήκη που τον απέτρεψε να ικανοποιήσει το αίτημα. - temporarily_unavailable: Ο εξυπηρετητής έγκρισης (authorization server) προς το παρόν δεν είναι διαθέσιμος να αναλάβει το αίτημα λόγω προσωρινής υπερφόρτωσης ή συντήρησής του. + server_error: Ο εξυπηρετητής έγκρισης αντιμετώπισε μια απροσδόκητη συνθήκη που τον απέτρεψε να ικανοποιήσει το αίτημα. + temporarily_unavailable: Ο εξυπηρετητής έγκρισης προς το παρόν δεν είναι δυνατό να αναλάβει το αίτημα λόγω προσωρινής υπερφόρτωσης ή συντήρησής του. unauthorized_client: Ο πελάτης δεν έχει άδεια να εκτελέσει αυτό το αίτημα χρησιμοποιώντας αυτή τη μέθοδο. - unsupported_grant_type: Το είδος άδειας έγκρισης δεν υποστηρίζεται από τον εξυπηρετητή έγκρισης (authorization server). - unsupported_response_type: Ο εξυπηρετητής έγκρισης (authorization server) δεν υποστηρίζει αυτό το είδος απάντησης. + unsupported_grant_type: Το είδος άδειας έγκρισης δεν υποστηρίζεται από τον εξυπηρετητή έγκρισης. + unsupported_response_type: Ο εξυπηρετητής έγκρισης δεν υποστηρίζει αυτό το είδος απάντησης. flash: applications: create: @@ -122,19 +122,20 @@ el: admin/accounts: Διαχείριση λογαριασμών admin/all: Όλες οι λειτουργίες διαχείρησης admin/reports: Διαχείριση αναφορών - all: Πλήρης πρόσβαση στο λογαριασμό σας στο Mastodon + all: Πλήρης πρόσβαση στο λογαριασμό σου στο Mastodon blocks: Αποκλεισμοί bookmarks: Σελιδοδείκτες conversations: Συνομιλίες crypto: Κρυπτογράφηση από άκρο σε άκρο favourites: Αγαπημένα filters: Φίλτρα - follow: Ακολουθείτε, σε Σίγαση και Αποκλεισμοί - follows: Ακολουθείτε + follow: Ακολουθείς, σε Σίγαση και Αποκλεισμοί + follows: Ακολουθείς lists: Λίστες media: Συνημμένα πολυμέσα - mutes: Αποσιωπήσεις + mutes: Σιγάσεις notifications: Ειδοποιήσεις + profile: Το προφίλ σου στο Mastodon push: Άμεσες ειδοποιήσεις reports: Αναφορές search: Αναζήτηση @@ -147,43 +148,45 @@ el: application: title: Απαιτείται έγκριση OAuth scopes: - admin:read: ανάγνωση δεδομένων στον διακομιστή + admin:read: ανάγνωση όλων των δεδομένων στον διακομιστή admin:read:accounts: ανάγνωση ευαίσθητων πληροφοριών όλων των λογαριασμών admin:read:canonical_email_blocks: ανάγνωση ευαίσθητων πληροφοριών όλων των αποκλεισμένων email admin:read:domain_allows: ανάγνωση ευαίσθητων πληροφοριών όλων των επιτρεπόμενων τομέων admin:read:domain_blocks: ανάγνωση ευαίσθητων πληροφοριών όλων των αποκλεισμένων τομέων admin:read:email_domain_blocks: ανάγνωση ευαίσθητων πληροφοριών όλων των αποκλεισμένων τομέων email admin:read:ip_blocks: ανάγνωση ευαίσθητων πληροφοριών όλων των αποκλεισμένων IP - admin:read:reports: ανάγνωση ευαίσθητων πληροφοριών όλων των καταγγελιών και των καταγγελλομένων λογαριασμών - admin:write: αλλαγή δεδομένων στον διακομιστή - admin:write:accounts: εκτέλεση διαχειριστικών ενεργειών σε λογαριασμούς - admin:write:canonical_email_blocks: εκτέλεση ενεργειών διαχείρισης σε αποκλεισμένα email - admin:write:domain_allows: εκτέλεση ενεργειών διαχείρισης σε επιτρεπτούς τομείς - admin:write:domain_blocks: εκτέλεση ενεργειών διαχείρισης σε αποκλεισμένους τομείς - admin:write:email_domain_blocks: εκτελέστε ενέργειες διαχείρισης σε αποκλεισμένους τομείς email - admin:write:ip_blocks: εκτέλεση ενεργειών διαχείρισης σε αποκλεισμένες IP - admin:write:reports: εκτέλεση διαχειριστικών ενεργειών σε καταγγελίες + admin:read:reports: ανάγνωση ευαίσθητων πληροφοριών όλων των αναφορών και των αναφερομένων λογαριασμών + admin:write: τροποποίηση όλων των δεδομένων στον διακομιστή + admin:write:accounts: εκτέλεση συντονιστικών ενεργειών σε λογαριασμούς + admin:write:canonical_email_blocks: εκτέλεση ενεργειών συντονισμού σε αποκλεισμένα email + admin:write:domain_allows: εκτέλεση ενεργειών συντονισμού σε επιτρεπτούς τομείς + admin:write:domain_blocks: εκτέλεση ενεργειών συντονισμού σε αποκλεισμένους τομείς + admin:write:email_domain_blocks: εκτέλεση ενέργειες συντονισμού σε αποκλεισμένους τομείς email + admin:write:ip_blocks: εκτέλεση ενεργειών συντονισμού σε αποκλεισμένες IP + admin:write:reports: εκτέλεση ενεργειών συντονισμού σε αναφορές crypto: χρήση κρυπτογράφησης από άκρο σε άκρο - follow: να αλλάζει τις σχέσεις με λογαριασμούς - push: να λαμβάνει τις ειδοποιήσεις σου - read: να διαβάζει όλα τα στοιχεία του λογαριασμού σου - read:accounts: να βλέπει τα στοιχεία λογαριασμών - read:blocks: να βλέπει τους αποκλεισμένους σου - read:bookmarks: εμφάνιση των σελιδοδεικτών σας - read:favourites: δείτε τα αγαπημένα σας - read:filters: να βλέπει τα φίλτρα σου - read:follows: δές ποιους ακολουθείς - read:lists: δές τις λίστες σου - read:mutes: να βλέπει ποιους αποσιωπείς - read:notifications: να βλέπει τις ειδοποιήσεις σου - read:reports: να βλέπει τις καταγγελίες σου - read:search: να ψάχνει για εσένα + follow: τροποποίηση σχέσεων λογαριασμών + profile: ανάγνωση μόνο των πληροφοριών προφίλ του λογαριασμού σου + push: λήψη των ειδοποιήσεων σου + read: ανάγνωση όλων των στοιχείων του λογαριασμού σου + read:accounts: προβολή πληροφοριών λογαριασμών + read:blocks: προβολή των αποκλεισμών σου + read:bookmarks: προβολή των σελιδοδεικτών σου + read:favourites: προβολή των αγαπημένα σου + read:filters: προβολή των φίλτρων σου + read:follows: προβολή αυτών που ακολουθείς + read:lists: προβολή των λιστών σου + read:mutes: προβολή των σιγάσεων σου + read:notifications: προβολή των ειδοποιήσεων σου + read:reports: προβολή των αναφορών σου + read:search: αναζήτηση εκ μέρους σου read:statuses: να βλέπει όλες τις δημοσιεύσεις σου write: να αλλάζει όλα τα στοιχεία του λογαριασμού σου write:accounts: να αλλάζει το προφίλ σου write:blocks: να μπλοκάρει λογαριασμούς και τομείς write:bookmarks: προσθήκη σελιδοδεικτών write:conversations: σίγαση και διαγραφή συνομιλιών + write:favourites: αγαπημένες αναρτήσεις write:filters: να δημιουργεί φίλτρα write:follows: ακολουθήστε ανθρώπους write:lists: δημιουργία λιστών diff --git a/config/locales/doorkeeper.ga.yml b/config/locales/doorkeeper.ga.yml index a263a6b15dc529..09857768e39744 100644 --- a/config/locales/doorkeeper.ga.yml +++ b/config/locales/doorkeeper.ga.yml @@ -5,7 +5,17 @@ ga: doorkeeper/application: name: Ainm feidhmchláir redirect_uri: Atreoraigh URI + scopes: Scóip website: Suíomh gréasáin feidhmchláir + errors: + models: + doorkeeper/application: + attributes: + redirect_uri: + fragment_present: ní féidir blúire a bheith ann. + invalid_uri: caithfidh gur URI bailí é. + relative_uri: a bheith ina URI iomlán. + secured_uri: caithfidh gur URI HTTPS/SSL é. doorkeeper: applications: buttons: @@ -16,36 +26,172 @@ ga: submit: Cuir isteach confirmations: destroy: An bhfuil tú cinnte? + edit: + title: Cuir feidhmchlár in eagar + form: + error: Úps! Seiceáil d'fhoirm le haghaidh earráidí féideartha + help: + native_redirect_uri: Úsáid %{native_redirect_uri} le haghaidh tástálacha logánta + redirect_uri: Úsáid líne amháin in aghaidh an URI + scopes: Scóipeanna ar leith le spásanna. Fág bán chun na scóip réamhshocraithe a úsáid. index: application: Ainm feidhmchláir + callback_url: URL aisghlaoch delete: Scrios + empty: Níl aon iarratais agat. name: Ainm + new: Feidhmchlár nua + scopes: Scóip show: Taispeáin + title: D'iarratais + new: + title: Feidhmchlár nua show: + actions: Gníomhartha application_id: Eochair chliaint + callback_urls: URLanna aisghlaoch + scopes: Scóip secret: Rún cliaint title: 'Ainm feidhmchláir: %{name}' authorizations: buttons: authorize: Ceadaigh deny: Diúltaigh + error: + title: Tharla earráid + new: + prompt_html: Ba mhaith le %{client_name} cead rochtain a fháil ar do chuntas. Is iarratas tríú páirtí é. Mura bhfuil muinín agat as, níor cheart duit é a údarú. + review_permissions: Ceadanna a athbhreithniú + title: Tá údarú ag teastáil + show: + title: Cóipeáil an cód údaraithe seo agus greamaigh don fheidhmchlár é. authorized_applications: + buttons: + revoke: Cúlghair confirmations: revoke: An bhfuil tú cinnte? index: + authorized_at: Ceadaithe ar %{date} + description_html: Is feidhmchláir iad seo ar féidir rochtain a fháil ar do chuntas leis an API. Má tá feidhmchláir ann nach n-aithníonn tú anseo, nó má tá feidhmchlár mí-iompair, is féidir leat a rochtain a chúlghairm. + last_used_at: Úsáidte an uair dheireanach ar %{date} + never_used: Ná húsáideadh scopes: Ceadanna superapp: Inmheánach + title: D’iarratais údaraithe + errors: + messages: + access_denied: Shéan úinéir na hacmhainne nó an freastalaí údaraithe an t-iarratas. + credential_flow_not_configured: Theip ar shreabhadh Dintiúir Pasfhocal Úinéir Acmhainne toisc go raibh Doorkeeper.configure.resource_owner_from_credentials díchumraithe. + invalid_client: Theip ar fhíordheimhniú cliant de bharr cliant anaithnid, níl fíordheimhniú cliant san áireamh, nó modh fíordheimhnithe nach dtacaítear leis. + invalid_grant: Tá an deonú údaraithe ar choinníoll neamhbhailí, imithe in éag, cúlghairthe, nach ionann é agus an URI atreoraithe a úsáideadh san iarratas ar údarú, nó gur eisíodh é chuig cliant eile. + invalid_redirect_uri: Níl an uri atreoraithe atá san áireamh bailí. + invalid_request: + missing_param: 'Paraiméadar riachtanach in easnamh: %{value}.' + request_not_authorized: Ní mór an t-iarratas a údarú. Tá an paraiméadar riachtanach chun iarratas a údarú in easnamh nó neamhbhailí. + unknown: Tá paraiméadar riachtanach in easnamh ar an iarratas, folaíonn sé luach paraiméadar nach dtacaítear leis, nó tá sé míchumtha ar shlí eile. + invalid_resource_owner: Níl na dintiúir úinéara acmhainne a soláthraíodh bailí, nó ní féidir úinéir na hacmhainne a aimsiú + invalid_scope: Tá an scóip iarrtha neamhbhailí, anaithnid nó míchumtha. + invalid_token: + expired: Chuaigh an comhartha rochtana in éag + revoked: Cúlghairmeadh an comhartha rochtana + unknown: Tá an comhartha rochtana neamhbhailí + resource_owner_authenticator_not_configured: Theip ar aimsiú Úinéir Acmhainne toisc go bhfuil Doorkeeper.configure.resource_owner_authenticator díchumraithe. + server_error: Tháinig an freastalaí údaraithe ar riocht gan choinne a chuir cosc ​​air an t-iarratas a chomhlíonadh. + temporarily_unavailable: Ní féidir leis an bhfreastalaí údaraithe an t-iarratas a láimhseáil mar gheall ar ró-ualú sealadach nó cothabháil an fhreastalaí. + unauthorized_client: Níl an cliant údaraithe an t-iarratas seo a dhéanamh leis an modh seo. + unsupported_grant_type: Ní thacaíonn an freastalaí údaraithe leis an gcineál deontais údaraithe. + unsupported_response_type: Ní thacaíonn an freastalaí údaraithe leis an gcineál freagartha seo. + flash: + applications: + create: + notice: Cruthaíodh feidhmchlár. + destroy: + notice: Scriosadh an feidhmchlár. + update: + notice: Feidhmchlár nuashonraithe. + authorized_applications: + destroy: + notice: Cúlghairmeadh an t-iarratas. grouped_scopes: + access: + read: Rochtain inléite-amháin + read/write: Léigh agus scríobh rochtain + write: Rochtain scríofa-amháin title: accounts: Cuntais + admin/accounts: Cuntas a riar + admin/all: Feidhmeanna riaracháin go léir + admin/reports: Tuarascálacha a riar + all: Rochtain iomlán ar do chuntas Mastodon + blocks: Bloic bookmarks: Leabharmharcanna conversations: Comhráite + crypto: Criptiú ceann-go-deireadh + favourites: Ceanáin filters: Scagairí + follow: Leanann, Múchann agus Blocálann follows: Cuntais leanta lists: Liostaí + media: Ceangaltáin meán + mutes: Múchann notifications: Fógraí + profile: Do phróifíl Mastodon + push: Fógraí a bhrú + reports: Tuarascálacha search: Cuardaigh statuses: Postálacha + layouts: + admin: + nav: + applications: Feidhmchláir + oauth2_provider: Soláthraí OAuth2 + application: + title: Tá údarú OAuth riachtanach scopes: + admin:read: léigh na sonraí go léir ar an bhfreastalaí + admin:read:accounts: faisnéis íogair na gcuntas go léir a léamh + admin:read:canonical_email_blocks: léigh faisnéis íogair ar gach bloc ríomhphoist canónach + admin:read:domain_allows: léigh faisnéis íogair gach fearainn + admin:read:domain_blocks: léigh faisnéis íogair gach bloc fearainn + admin:read:email_domain_blocks: léigh faisnéis íogair gach bloc fearainn ríomhphoist + admin:read:ip_blocks: léigh faisnéis íogair gach bloic IP + admin:read:reports: faisnéis íogair na dtuarascálacha agus na gcuntas tuairiscithe go léir a léamh + admin:write: na sonraí go léir ar an bhfreastalaí a mhodhnú + admin:write:accounts: gníomhartha modhnóireachta a dhéanamh ar chuntais + admin:write:canonical_email_blocks: gníomhartha modhnóireachta a dhéanamh ar bhlocanna ríomhphoist chanónacha + admin:write:domain_allows: gníomhartha modhnóireachta a dhéanamh ar cheadaíonn fearainn + admin:write:domain_blocks: gníomhartha modhnóireachta a dhéanamh ar bhlocanna fearainn + admin:write:email_domain_blocks: gníomhartha modhnóireachta a dhéanamh ar bhlocanna fearainn ríomhphoist + admin:write:ip_blocks: gníomhartha modhnóireachta a dhéanamh ar bhlocanna IP + admin:write:reports: gníomhartha modhnóireachta a dhéanamh ar thuarascálacha + crypto: úsáid criptiú ceann-go-ceann + follow: caidrimh chuntais a mhodhnú + profile: léigh faisnéis phróifíle do chuntais amháin + push: faigh do bhrúfhógraí + read: léigh sonraí do chuntais go léir + read:accounts: féach eolas cuntais + read:blocks: féach ar do bloic + read:bookmarks: féach ar do leabharmharcanna + read:favourites: féach ar do cheanáin + read:filters: féach ar do chuid scagairí + read:follows: féach do chuid seo a leanas + read:lists: féach ar do liostaí + read:mutes: féach ar do bhalbh + read:notifications: féach ar do chuid fógraí + read:reports: féach ar do thuarascálacha + read:search: cuardach ar do shon + read:statuses: féach ar gach post + write: sonraí do chuntais go léir a mhodhnú + write:accounts: do phróifíl a mhodhnú + write:blocks: cuntais agus fearainn a bhlocáil + write:bookmarks: poist leabharmharcála + write:conversations: comhráite balbh agus scrios + write:favourites: poist is fearr leat write:filters: cruthaigh scagairí + write:follows: daoine a leanúint write:lists: cruthaigh liostaí + write:media: uaslódáil comhaid meáin + write:mutes: balbhaigh daoine agus comhráite + write:notifications: soiléir do chuid fógraí + write:reports: tuairisc a thabhairt do dhaoine eile + write:statuses: foilsigh poist diff --git a/config/locales/doorkeeper.kab.yml b/config/locales/doorkeeper.kab.yml index 33aecd8c6f03d7..d79c711e609f59 100644 --- a/config/locales/doorkeeper.kab.yml +++ b/config/locales/doorkeeper.kab.yml @@ -111,9 +111,9 @@ kab: lists: Tibdarin media: Imeddayen n umidya mutes: Yeggugem - notifications: Tilɣa + notifications: Alɣuten profile: Amaɣnu-k Mastodon - push: Tilɣa yettudemmren + push: Alɣuten yettudemmren reports: Ineqqisen search: Nadi statuses: Tisuffaɣ @@ -127,7 +127,7 @@ kab: admin:read: ad iɣeṛ akk isefka ɣef uqeddac admin:write: ẓreg akk isefka γef uqeddac follow: beddel assaγen n umiḍan - push: ṭṭef-d tilγa-ik yettwademren + push: ṭṭef-d alɣuten-ik·im yettwademren read: γeṛ akk isefka n umiḍan-ik read:accounts: ẓer isallen n yimiḍanen read:blocks: ẓer imiḍanen i tesḥebseḍ @@ -136,7 +136,7 @@ kab: read:follows: ẓer imeḍfaṛen-ik read:lists: ẓer tibdarin-ik·im read:mutes: ẓer wid i tesgugmeḍ - read:notifications: ad ẓer tilɣa-inek·inem + read:notifications: ad iẓer alɣuten-inek·inem read:reports: ẓer ineqqisen-ik·im read:search: anadi deg umkan-ik·im read:statuses: ẓer meṛṛa tisuffaɣ @@ -148,4 +148,4 @@ kab: write:follows: ḍfeṛ imdanen write:lists: ad yesnulfu tibdarin write:media: ad yessali ifuyla n umidya - write:notifications: sfeḍ tilɣa-k·m + write:notifications: sfeḍ alɣuten-ik·im diff --git a/config/locales/el.yml b/config/locales/el.yml index 47b2250f0e04e3..e177bf342afc75 100644 --- a/config/locales/el.yml +++ b/config/locales/el.yml @@ -5,14 +5,14 @@ el: contact_missing: Δεν έχει οριστεί contact_unavailable: Μη διαθέσιμο hosted_on: Το Mastodon φιλοξενείται στο %{domain} - title: Σχετικά με + title: Σχετικά accounts: follow: Ακολούθησε followers: one: Ακόλουθος other: Ακόλουθοι following: Ακολουθείτε - instance_actor_flash: Αυτός ο λογαριασμός είναι εικονικός και χρησιμοποιείται για να αντιπροσωπεύει τον ίδιο τον διακομιστή και όχι κάποιον μεμονωμένο χρήστη. Χρησιμοποιείται για σκοπούς συναλλαγών και δεν πρέπει να ανασταλεί. + instance_actor_flash: Αυτός ο λογαριασμός είναι εικονικός και χρησιμοποιείται για να αντιπροσωπεύει τον ίδιο τον διακομιστή και όχι κάποιον μεμονωμένο χρήστη. Χρησιμοποιείται για σκοπούς ομοσπονδίας και δεν πρέπει να ανασταλεί. last_active: τελευταία ενεργός/ή link_verified_on: Η ιδιοκτησία αυτού του συνδέσμου ελέγχθηκε στις %{date} nothing_here: Δεν υπάρχει τίποτα εδώ! @@ -159,7 +159,7 @@ el: unconfirmed_email: Ανεπιβεβαίωτο email undo_sensitized: Άρση ευαίσθητου undo_silenced: Άρση περιορισμού - undo_suspension: Αναίρεση παύσης + undo_suspension: Αναίρεση αναστολής unsilenced_msg: Επιτυχής άρση περιορισμών λογαριασμού του/της %{username} unsubscribe: Κατάργηση εγγραφής unsuspended_msg: Επιτυχής άρση αναστολής λογαριασμού του/της %{username} @@ -167,7 +167,7 @@ el: view_domain: Προβολή περίληψης τομέα warn: Προειδοποίηση web: Διαδίκτυο - whitelisted: Εγκεκριμένοι για συναλλαγές + whitelisted: Εγκεκριμένοι για ομοσπονδία action_logs: action_types: approve_appeal: Έγκριση Έφεσης @@ -185,7 +185,7 @@ el: create_email_domain_block: Δημουργία Αποκλεισμού Τομέα email create_ip_block: Δημιουργία κανόνα IP create_unavailable_domain: Δημιουργία Μη Διαθέσιμου Τομέα - create_user_role: Δημιουργία ρόλου + create_user_role: Δημιουργία Ρόλου demote_user: Υποβιβασμός Χρήστη destroy_announcement: Διαγραφή Ανακοίνωσης destroy_canonical_email_block: Διαγραφή Αποκλεισμού email @@ -226,6 +226,7 @@ el: update_custom_emoji: Ενημέρωση Προσαρμοσμένου Emoji update_domain_block: Ενημέρωση Αποκλεισμού Τομέα update_ip_block: Ενημέρωση κανόνα IP + update_report: Ενημέρωση Αναφοράς update_status: Ενημέρωση Ανάρτησης update_user_role: Ενημέρωση ρόλου actions: diff --git a/config/locales/en-GB.yml b/config/locales/en-GB.yml index 928823b995b674..fecdab4c7d7316 100644 --- a/config/locales/en-GB.yml +++ b/config/locales/en-GB.yml @@ -226,6 +226,7 @@ en-GB: update_custom_emoji: Update Custom Emoji update_domain_block: Update Domain Block update_ip_block: Update IP rule + update_report: Update Report update_status: Update Post update_user_role: Update Role actions: @@ -638,6 +639,7 @@ en-GB: report: 'Report #%{id}' reported_account: Reported account reported_by: Reported by + reported_with_application: Reported with application resolved: Resolved resolved_msg: Report successfully resolved! skip_to_actions: Skip to actions diff --git a/config/locales/en.yml b/config/locales/en.yml index ca569c6726248b..91fd33ec038120 100644 --- a/config/locales/en.yml +++ b/config/locales/en.yml @@ -235,6 +235,7 @@ en: update_custom_emoji: Update Custom Emoji update_domain_block: Update Domain Block update_ip_block: Update IP rule + update_report: Update Report update_status: Update Post update_user_role: Update Role actions: @@ -549,6 +550,9 @@ en: status: Status title: Friend server instances: + audit_log: + title: Recent Audit Logs + view_all: View full audit logs availability: description_html: one: If delivering to the domain fails %{count} day without succeeding, no further delivery attempts will be made unless a delivery from the domain is received. @@ -868,6 +872,7 @@ en: report: 'Report #%{id}' reported_account: Reported account reported_by: Reported by + reported_with_application: Reported with application resolved: Resolved resolved_msg: Report successfully resolved! skip_to_actions: Skip to actions diff --git a/config/locales/es-AR.yml b/config/locales/es-AR.yml index fda1566e22c478..5add90ae62c992 100644 --- a/config/locales/es-AR.yml +++ b/config/locales/es-AR.yml @@ -226,6 +226,7 @@ es-AR: update_custom_emoji: Actualizar emoji personalizado update_domain_block: Actualizar bloque de dominio update_ip_block: Actualizar regla de dirección IP + update_report: Actualizar denuncia update_status: Actualizar mensaje update_user_role: Actualizar rol actions: @@ -638,6 +639,7 @@ es-AR: report: 'Denuncia #%{id}' reported_account: Cuenta denunciada reported_by: Denunciada por + reported_with_application: Informado a través de la aplicación resolved: Resueltas resolved_msg: "¡Denuncia exitosamente resuelta!" skip_to_actions: Ir directamente a las acciones diff --git a/config/locales/es-MX.yml b/config/locales/es-MX.yml index 976b7a4f30cd00..22531d2403dfa1 100644 --- a/config/locales/es-MX.yml +++ b/config/locales/es-MX.yml @@ -226,6 +226,7 @@ es-MX: update_custom_emoji: Actualizar Emoji Personalizado update_domain_block: Actualizar el Bloqueo de Dominio update_ip_block: Actualizar regla IP + update_report: Actualizar informe update_status: Actualizar Estado update_user_role: Actualizar Rol actions: @@ -638,6 +639,7 @@ es-MX: report: 'Reportar #%{id}' reported_account: Cuenta reportada reported_by: Reportado por + reported_with_application: Informado a través de la aplicación resolved: Resuelto resolved_msg: "¡La denuncia se ha resuelto correctamente!" skip_to_actions: Ir directamente a las acciones diff --git a/config/locales/es.yml b/config/locales/es.yml index aef5100a6d1fea..567526fe8b7494 100644 --- a/config/locales/es.yml +++ b/config/locales/es.yml @@ -226,6 +226,7 @@ es: update_custom_emoji: Actualizar Emoji Personalizado update_domain_block: Actualizar el Bloqueo de Dominio update_ip_block: Actualizar regla IP + update_report: Actualizar informe update_status: Actualizar Publicación update_user_role: Actualizar Rol actions: @@ -638,6 +639,7 @@ es: report: 'Reportar #%{id}' reported_account: Cuenta reportada reported_by: Reportado por + reported_with_application: Informado a través de la aplicación resolved: Resuelto resolved_msg: "¡La denuncia se ha resuelto correctamente!" skip_to_actions: Ir directamente a las acciones diff --git a/config/locales/fi.yml b/config/locales/fi.yml index be87258daf22bb..c93c5edc0e664e 100644 --- a/config/locales/fi.yml +++ b/config/locales/fi.yml @@ -226,6 +226,7 @@ fi: update_custom_emoji: Päivitä mukautettu emoji update_domain_block: Päivitä verkkotunnuksen esto update_ip_block: Päivitä IP-sääntö + update_report: Päivitä raportti update_status: Päivitä julkaisu update_user_role: Päivitä rooli actions: @@ -605,7 +606,7 @@ fi: are_you_sure: Oletko varma? assign_to_self: Ota tehtäväksi assigned: Määritetty valvoja - by_target_domain: Ilmoitetun tilin verkkotunnus + by_target_domain: Raportoidun tilin verkkotunnus cancel: Peruuta category: Luokka category_description_html: Syy siihen, miksi tämä tili ja/tai sisältö raportoitiin, mainitaan ilmoitetun tilin kanssa viestiessä @@ -637,13 +638,13 @@ fi: reopen: Avaa raportti uudestaan report: Raportti nro %{id} reported_account: Raportoitu tili - reported_by: Raportoija + reported_by: Raportoinut resolved: Ratkaistut resolved_msg: Raportti onnistuneesti ratkaistu! skip_to_actions: Siirry toimintoihin status: Tila statuses: Raportoitu sisältö - statuses_description_html: Loukkaava sisältö mainitaan ilmoitetun tilin yhteydessä + statuses_description_html: Loukkaava sisältö mainitaan raportoidun tilin yhteydessä summary: action_preambles: delete_html: 'Olet aikeissa poistaa käyttäjän @%{acct} julkaisuja. Tästä seuraa:' diff --git a/config/locales/fo.yml b/config/locales/fo.yml index 945a2216a3d6ba..6a5401ced4882f 100644 --- a/config/locales/fo.yml +++ b/config/locales/fo.yml @@ -226,6 +226,7 @@ fo: update_custom_emoji: Dagfør Sergjørt Kenslutekn update_domain_block: Dagfør Domain forðing update_ip_block: Dagfør IP reglur + update_report: Dagfør frágreiðing update_status: Dagfør Uppslag update_user_role: Dagfør Leiklut actions: @@ -638,6 +639,7 @@ fo: report: 'Melding #%{id}' reported_account: Meldað konta reported_by: Meldað av + reported_with_application: Fráboðað við umsókn resolved: Loyst resolved_msg: Melding avgreidd! skip_to_actions: Leyp til atgerðir diff --git a/config/locales/ga.yml b/config/locales/ga.yml index a3ad293e5bd79d..647c46d7cf2726 100644 --- a/config/locales/ga.yml +++ b/config/locales/ga.yml @@ -3,13 +3,24 @@ ga: about: about_mastodon_html: 'Líonra sóisialta a sheasfaidh an aimsir: Gan fógraíocht, gan faire chorparáideach, le leagan amach eiticiúil agus dílárú. Bíodh do chuid sonraí agatsa féin le Mastodon!' contact_missing: Gan socrú - contact_unavailable: N/B + contact_unavailable: N/A hosted_on: Mastodon arna óstáil ar %{domain} title: Maidir le accounts: follow: Lean + followers: + few: Leantóirí + many: Leantóirí + one: Leantóir + other: LeantóiríLeantóirí + two: Leantóirí following: Ag leanúint + instance_actor_flash: Is gníomhaí fíorúil é an cuntas seo a úsáidtear chun an freastalaí féin agus ní aon úsáideoir aonair a léiriú. Úsáidtear é chun críocha cónaidhme agus níor cheart é a chur ar fionraí. + last_active: deireanach gníomhach + link_verified_on: Seiceáladh úinéireacht an naisc seo ar %{date} nothing_here: Níl rud ar bith anseo! + pin_errors: + following: Ní mór duit a bheith ag leanúint an duine is mian leat a fhormhuiniú cheana féin posts: few: Postálacha many: Postálacha @@ -23,12 +34,17 @@ ga: title: Dean gníomh modhnóireachta ar %{acct} account_moderation_notes: create: Fág nóta + created_msg: Cruthaíodh nóta modhnóireachta go rathúil! + destroyed_msg: Nóta measarthachta scriosta go rathúil! accounts: + add_email_domain_block: Cuir bac ar fhearann ​​​​ríomhphoist approve: Faomh + approved_msg: D'éirigh le feidhmchlár sínithe %{username} a cheadú are_you_sure: An bhfuil tú cinnte? avatar: Abhatár by_domain: Fearann change_email: + changed_msg: D'éirigh leis an ríomhphost a athrú! current_email: Ríomhphost reatha label: Athraigh ríomhphost new_email: Ríomhphost nua @@ -46,7 +62,9 @@ ga: delete: Scrios sonraí deleted: Scriosta demote: Ísligh + destroyed_msg: Tá sonraí %{username} ciúáilte anois le scriosadh gan mhoill disable: Reoigh + disable_sign_in_token_auth: Díchumasaigh fíordheimhniú comhartha r-phoist disable_two_factor_authentication: Díchumasaigh 2FA disabled: Reoite display_name: Ainm taispeána @@ -55,22 +73,31 @@ ga: email: Ríomhphost email_status: Stádas ríomhphoist enable: Dí-reoigh + enable_sign_in_token_auth: Cumasaigh fíordheimhniú comhartha ríomhphoist enabled: Ar chumas + enabled_msg: D'éirigh le dí-reoite cuntas %{username} followers: Leantóirí follows: Ag leanúint header: Ceanntásc + inbox_url: URL an Bhosca Isteach + invite_request_text: Cúiseanna le bheith páirteach + invited_by: Ar cuireadh ó ip: IP joined: Cláraithe location: all: Uile local: Áitiúil remote: Cian + title: Suíomh login_status: Stádas logála isteach + media_attachments: Ceangaltáin meán memorialize: Déan cuntas chuimhneacháin de memorialized: Cuntas chuimhneacháin + memorialized_msg: D'éirigh le %{username} a iompú ina chuntas cuimhneacháin moderation: active: Gníomhach all: Uile + disabled: Faoi mhíchumas pending: Ar feitheamh silenced: Teoranta suspended: Ar fionraí @@ -78,111 +105,389 @@ ga: moderation_notes: Nótaí modhnóireacht most_recent_activity: Gníomhaíocht is déanaí most_recent_ip: IP is déanaí + no_account_selected: Níor athraíodh aon chuntas mar níor roghnaíodh ceann ar bith + no_limits_imposed: Ní fhorchuirtear aon teorainneacha + no_role_assigned: Níl aon ról sannta + not_subscribed: Gan suibscríofa + pending: Athbhreithniú ar feitheamh perform_full_suspension: Fionraí previous_strikes: Cionta roimhe seo + previous_strikes_description_html: + few: Tá %{count} buailte ag an gcuntas seo. + many: Tá %{count} buailte ag an gcuntas seo. + one: Tá buail amháin ag an gcuntas seo. + other: Tá %{count} buailte ag an gcuntas seo. + two: Tá %{count} buailte ag an gcuntas seo. promote: Ardaigh protocol: Prótacal public: Poiblí + push_subscription_expires: Téann síntiús PuSH in éag redownload: Athnuaigh próifíl + redownloaded_msg: D'éirigh le hathnuachan próifíl %{username} ón mbunús reject: Diúltaigh + rejected_msg: D'éirigh le diúltú le feidhmchlár sínithe %{username} + remote_suspension_irreversible: Scriosadh sonraí an chuntais seo go do-aisiompaithe. + remote_suspension_reversible_hint_html: Cuireadh an cuntas ar fionraí ar a fhreastalaí, agus bainfear na sonraí go hiomlán ar %{date}. Go dtí sin, is féidir leis an gcianfhreastalaí an cuntas seo a chur ar ais gan aon drochéifeachtaí. Más mian leat sonraí uile an chuntais a bhaint láithreach, is féidir leat é sin a dhéanamh thíos. remove_avatar: Bain abhatár remove_header: Bain ceanntásc + removed_avatar_msg: D'éirigh leis an íomhá avatar %{username} a bhaint + removed_header_msg: D'éirigh le híomhá ceanntásc %{username} a bhaint + resend_confirmation: + already_confirmed: Tá an t-úsáideoir seo deimhnithe cheana féin + send: Seol an nasc deimhnithe arís + success: D'éirigh le nasc deimhnithe seolta! reset: Athshocraigh reset_password: Athshocraigh pasfhocal resubscribe: Athchláraigh role: Ról search: Cuardaigh + search_same_email_domain: Úsáideoirí eile a bhfuil an fearann ​​ríomhphoist céanna acu + search_same_ip: Úsáideoirí eile a bhfuil an IP céanna acu + security: Slándáil security_measures: only_password: Pasfhocal amháin password_and_2fa: Pasfhocal agus fíordheimhniú déshraithe + sensitive: Fórsa-íogair sensitized: Marcáladh mar íogair + shared_inbox_url: URL an bhosca isteach roinnte + show: + created_reports: Tuarascálacha déanta + targeted_reports: Thuairiscigh daoine eile silence: Teorannaigh silenced: Teoranta statuses: Postálacha + strikes: Stailceanna roimhe seo subscribe: Cláraigh suspend: Cuir ar fionraí suspended: Ar fionraí + suspension_irreversible: Scriosadh sonraí an chuntais seo go do-aisiompaithe. Is féidir leat an cuntas a chur ar fionraí chun é a dhéanamh inúsáidte ach ní dhéanfaidh sé aon sonraí a bhí aige roimhe seo a aisghabháil. + suspension_reversible_hint_html: Tá an cuntas curtha ar fionraí, agus bainfear na sonraí go hiomlán ar %{date}. Go dtí sin, is féidir an cuntas a chur ar ais gan aon drochthionchar. Más mian leat sonraí uile an chuntais a bhaint láithreach, is féidir leat é sin a dhéanamh thíos. title: Cuntais + unblock_email: Bain an bac den seoladh ríomhphoist + unblocked_email_msg: D'éirigh leis an mbac a bhain le seoladh ríomhphoist %{username} + unconfirmed_email: Ríomhphost neamhdheimhnithe + undo_sensitized: Cealaigh fórsa-íogair + undo_silenced: Cealaigh teorainn + undo_suspension: Cealaigh fionraí + unsilenced_msg: D'éirigh leis an teorainn chuntas %{username} a bhaint + unsubscribe: Díliostáil + unsuspended_msg: D'éirigh le dífhorlannú cuntas %{username} username: Ainm úsáideora + view_domain: Féach ar achoimre le haghaidh fearainn warn: Rabhadh a thabhairt web: Gréasán + whitelisted: Ceadaithe do chónaidhm action_logs: action_types: + approve_appeal: Achomharc a cheadú + approve_user: Úsáideoir a cheadú assigned_to_self_report: Sann Tuairisc + change_email_user: Athraigh Ríomhphost don Úsáideoir + change_role_user: Athrú Ról an Úsáideora + confirm_user: Deimhnigh Úsáideoir create_account_warning: Cruthaigh Rabhadh + create_announcement: Cruthaigh Fógra + create_canonical_email_block: Cruthaigh Bloc Ríomhphoist + create_custom_emoji: Cruthaigh Emoji Saincheaptha + create_domain_allow: Cruthaigh Ceadaigh Fearainn + create_domain_block: Cruthaigh Bloc Fearainn + create_email_domain_block: Cruthaigh Bloc Fearainn Ríomhphoist create_ip_block: Cruthaigh riail IP + create_unavailable_domain: Cruthaigh Fearann ​​Gan Fáil create_user_role: Cruthaigh Ról demote_user: Ísligh úsáideoir destroy_announcement: Scrios Fógra + destroy_canonical_email_block: Scrios Bloc Ríomhphoist + destroy_custom_emoji: Scrios Saincheaptha Emoji + destroy_domain_allow: Scrios Ceadaigh Fearainn + destroy_domain_block: Scrios Bloc Fearainn + destroy_email_domain_block: Scrios Bloc Fearainn R-phoist + destroy_instance: Fearann ​​Purge destroy_ip_block: Scrios riail IP destroy_status: Scrios Postáil + destroy_unavailable_domain: Scrios Fearann ​​Gan Fáil destroy_user_role: Scrios ról + disable_2fa_user: Díchumasaigh 2FA + disable_custom_emoji: Díchumasaigh Emoji Saincheaptha + disable_sign_in_token_auth_user: Díchumasaigh Fíordheimhniú Comhartha R-phoist don Úsáideoir + disable_user: Díchumasaigh Úsáideoir + enable_custom_emoji: Cumasaigh Emoji Saincheaptha + enable_sign_in_token_auth_user: Cumasaigh Fíordheimhniú Comhartha R-phoist don Úsáideoir + enable_user: Cumasaigh Úsáideoir + memorialize_account: Cuntas Cuimhneacháin + promote_user: Úsáideoir a chur chun cinn + reject_appeal: Diúltaigh Achomharc + reject_user: Diúltaigh Úsáideoir remove_avatar_user: Bain Abhatár reopen_report: Athoscail tuairisc + resend_user: Seol Ríomhphost Deimhnithe arís reset_password_user: Athshocraigh Pasfhocal resolve_report: Réitigh tuairisc + sensitive_account: Cuntas Íogair Fórsa + silence_account: Cuntas Teorainn + suspend_account: Cuntas a Fhionraí unassigned_report: Díshann Tuairisc + unblock_email_account: Bain an bac den seoladh ríomhphoist + unsensitive_account: Cealaigh Cuntas Íogair Fórsa + unsilence_account: Cealaigh an Cuntas Teorainn + unsuspend_account: Díghlasáil Cuntas update_announcement: Nuashonraigh Fógra + update_custom_emoji: Nuashonraigh Emoji Saincheaptha + update_domain_block: Nuashonraigh Emoji Saincheaptha + update_ip_block: Íoslódáil an riail IP + update_report: Tuairisc Nuashonraithe update_status: Nuashonraigh Postáil update_user_role: Nuashonraigh Ról actions: + approve_appeal_html: Cheadaigh %{name} achomharc ar chinneadh modhnóireachta ó %{target} + approve_user_html: Cheadaigh %{name} clárú ó %{target} + assigned_to_self_report_html: Shann %{name} tuairisc %{target} dóibh féin + change_email_user_html: D'athraigh %{name} seoladh ríomhphoist úsáideora %{target} + change_role_user_html: D'athraigh %{name} ról %{target} + confirm_user_html: Dhearbhaigh %{name} seoladh ríomhphoist úsáideora %{target} create_account_warning_html: Sheol %{name} rabhadh chuig %{target} + create_announcement_html: Chruthaigh %{name} fógra nua %{target} + create_canonical_email_block_html: Chuir %{name} bac ar ríomhphost leis an hash %{target} + create_custom_emoji_html: D'uaslódáil %{name} emoji nua %{target} + create_domain_allow_html: Cheadaigh %{name} cónaidhm le fearann ​​%{target} + create_domain_block_html: "%{name} fearann ​​bactha %{target}" + create_email_domain_block_html: Chuir %{name} bac ar fhearann ​​ríomhphoist %{target} + create_ip_block_html: Chruthaigh %{name} riail don IP %{target} + create_unavailable_domain_html: Chuir %{name} deireadh leis an seachadadh chuig fearann ​​%{target} + create_user_role_html: Chruthaigh %{name} %{target} ról + demote_user_html: "%{name} úsáideoir scriosta %{target}" + destroy_announcement_html: "%{name} fógra scriosta %{target}" + destroy_canonical_email_block_html: "%{name} ríomhphost díchoiscthe leis an hash %{target}" + destroy_custom_emoji_html: Scriosadh %{name} emoji %{target} + destroy_domain_allow_html: Dhiúltaigh %{name} cónaidhm le fearann ​​%{target} + destroy_domain_block_html: "%{name} fearann ​​%{target} bainte de" + destroy_email_domain_block_html: "%{name} bain an bac den fhearann ​​ríomhphoist %{target}" + destroy_instance_html: Glanadh %{name} fearann ​​%{target} + destroy_ip_block_html: "%{name} scriosta riail le haghaidh IP %{target}" + destroy_status_html: Bhain %{name} postáil le %{target} + destroy_unavailable_domain_html: D'athchrom %{name} ar an seachadadh chuig fearann ​​%{target} destroy_user_role_html: Scrios %{name} ról %{target} + disable_2fa_user_html: Dhíchumasaigh %{name} riachtanas dhá fhachtóir don úsáideoir %{target} + disable_custom_emoji_html: Dhíchumasaigh %{name} emoji %{target} + disable_sign_in_token_auth_user_html: Dhíchumasaigh %{name} fíordheimhniú comhartha ríomhphoist le haghaidh %{target} + disable_user_html: "%{name} logáil isteach díchumasaithe d'úsáideoir %{target}" + enable_custom_emoji_html: "%{name} emoji cumasaithe %{target}" + enable_sign_in_token_auth_user_html: Chuir %{name} fíordheimhniú comhartha ríomhphoist ar chumas %{target} + enable_user_html: "%{name} logáil isteach cumasaithe don úsáideoir %{target}" + memorialize_account_html: Rinne %{name} cuntas %{target} a iompú ina leathanach cuimhneacháin + promote_user_html: Chuir %{name} úsáideoir %{target} chun cinn + reject_appeal_html: Dhiúltaigh %{name} achomharc ar chinneadh modhnóireachta ó %{target} + reject_user_html: Dhiúltaigh %{name} síniú suas ó %{target} + remove_avatar_user_html: Bhain %{name} avatar %{target} + reopen_report_html: D'athoscail %{name} tuairisc %{target} + resend_user_html: "%{name} athsheoladh ríomhphost deimhnithe le haghaidh %{target}" + reset_password_user_html: Athshocraigh %{name} pasfhocal úsáideora %{target} + resolve_report_html: Réitigh %{name} tuairisc %{target} + sensitive_account_html: Mharcáil %{name} meán %{target} mar íogair + silence_account_html: Chuir %{name} teorainn le cuntas %{target} + suspend_account_html: Chuir %{name} cuntas %{target} ar fionraí + unassigned_report_html: "%{name} tuairisc neamhshannta %{target}" + unblock_email_account_html: Bhain %{name} seoladh ríomhphoist %{target} amach + unsensitive_account_html: "%{name} meán %{target} gan mharcáil mar íogair" + unsilence_account_html: Chealaigh %{name} teorainn chuntas %{target} + unsuspend_account_html: Níor chuir %{name} cuntas %{target} ar fionraí + update_announcement_html: "%{name} fógra nuashonraithe %{target}" + update_custom_emoji_html: "%{name} emoji nuashonraithe %{target}" + update_domain_block_html: "%{name} nuashonraithe bloc fearainn le haghaidh %{target}" + update_ip_block_html: D'athraigh %{name} riail an IP %{target} + update_report_html: "%{name} tuairisc nuashonraithe %{target}" + update_status_html: "%{name} postáil nuashonraithe faoi %{target}" update_user_role_html: D'athraigh %{name} ról %{target} deleted_account: cuntas scriosta + empty: Níor aimsíodh aon logaí. + filter_by_action: Scag de réir gnímh + filter_by_user: Scag de réir úsáideora + title: Loga iniúchta + unavailable_instance: "(ainm fearainn ar fáil)" announcements: + destroyed_msg: D'éirigh leis an bhfógra a scriosadh! edit: title: Cuir fógra in eagar + empty: Níor aimsíodh aon fhógraí. live: Beo new: create: Cruthaigh fógra title: Fógra nua publish: Foilsigh + published_msg: D’éirigh leis an bhfógra a fhoilsiú! + scheduled_for: Sceidealta le haghaidh %{time} + scheduled_msg: Tá an fógra le foilsiú! title: Fógraí + unpublish: Dífhoilsiú + unpublished_msg: D’éirigh leis an bhfógra neamhfhoilsithe! + updated_msg: D'éirigh leis an bhfógra a nuashonrú! + critical_update_pending: Nuashonrú criticiúil ar feitheamh custom_emojis: + assign_category: Sann catagóir by_domain: Fearann + copied_msg: Cruthaíodh cóip áitiúil den emoji go rathúil copy: Cóipeáil + copy_failed_msg: Níorbh fhéidir cóip áitiúil den emoji sin a dhéanamh create_new_category: Cruthaigh catagóir nua created_msg: Cruthaíodh emoji go rathúil! delete: Scrios destroyed_msg: Scriosadh emoji go rathúil! disable: Díchumasaigh disabled: Díchumasaithe + disabled_msg: D'éirigh leis an emoji sin a dhíchumasú emoji: Emoji enable: Cumasaigh enabled: Ar chumas + enabled_msg: D'éirigh leis an emoji sin a chumasú + image_hint: PNG nó GIF suas go %{size} list: Liosta listed: Liostaithe + new: + title: Cuir emoji saincheaptha nua leis + no_emoji_selected: Níor athraíodh emojis ar bith mar níor roghnaíodh ceann ar bith + not_permitted: Níl cead agat an gníomh seo a dhéanamh overwrite: Forscríobh + shortcode: Gearrchód + shortcode_hint: 2 charachtar ar a laghad, gan ach carachtair alfa-uimhriúla agus béim ar leith + title: Emojis saincheaptha uncategorized: Neamhchatagóirithe unlist: Neamhliostaigh unlisted: Neamhliostaithe + update_failed_msg: Níorbh fhéidir an emoji sin a nuashonrú + updated_msg: D'éirigh le Emoji a nuashonrú! upload: Uaslódáil dashboard: active_users: úsáideoirí gníomhacha + interactions: idirghníomhaíochtaí + media_storage: Stóráil meáin new_users: úsáideoirí nua opened_reports: tuairiscí oscailte + pending_appeals_html: + few: "%{count} achomharc ar feitheamh" + many: "%{count} achomharc ar feitheamh" + one: "%{count} ar feitheamh achomhairc" + other: "%{count} achomharc ar feitheamh" + two: "%{count} achomharc ar feitheamh" + pending_reports_html: + few: "%{count} tuairiscí ar feitheamh" + many: "%{count} tuairiscí ar feitheamh" + one: "%{count} tuairisc ar feitheamh" + other: "%{count} tuairiscí ar feitheamh" + two: "%{count} tuairiscí ar feitheamh" + pending_tags_html: + few: "%{count} hashtags ar feitheamh" + many: "%{count} hashtags ar feitheamh" + one: "%{count} hashtag ar feitheamh" + other: "%{count} hashtags ar feitheamh" + two: "%{count} hashtags ar feitheamh" + pending_users_html: + few: "%{count} úsáideoirí ar feitheamh" + many: "%{count} úsáideoirí ar feitheamh" + one: "%{count} úsáideoir ar feitheamh" + other: "%{count} úsáideoirí ar feitheamh" + two: "%{count} úsáideoirí ar feitheamh" + resolved_reports: tuarascálacha réitithe software: Bogearraí + sources: Foinsí sínithe + space: Úsáid spáis title: Deais + top_languages: Barr teangacha gníomhacha + top_servers: Barr freastalaithe gníomhacha website: Suíomh Gréasáin disputes: appeals: + empty: Níor aimsíodh aon achomharc. title: Achomhairc domain_allows: + add_new: Ceadaigh cónaidhm leis an bhfearann + created_msg: Ceadaíodh fearann ​​don chónaidhm go rathúil + destroyed_msg: Dícheadaíodh an fearann ​​ón gcónaidhm export: Easpórtáil import: Iompórtáil + undo: Dícheadaigh cónaidhm leis an bhfearann domain_blocks: + add_new: Cuir bloc fearainn nua leis + confirm_suspension: + cancel: Cealaigh + confirm: Fionraí + permanent_action: Má dhéantar an fionraí a chealú, ní dhéanfar aon sonraí nó gaol a athbhunú. + preamble_html: Tá tú ar tí %{domain} agus a fhofhearainn a chur ar fionraí. + remove_all_data: Bainfidh sé seo gach ábhar, meán agus sonraí próifíle do chuntais an fhearainn seo de do fhreastalaí. + stop_communication: Stopfaidh do fhreastalaí ag cumarsáid leis na freastalaithe seo. + title: Deimhnigh bloc fearainn le haghaidh %{domain} + undo_relationships: Déanfaidh sé seo aon ghaol leantach idir cuntais na bhfreastalaithe seo agus do chuid féin a chealú. + created_msg: Tá bloc fearainn á phróiseáil anois + destroyed_msg: Tá an bloc fearainn cealaithe domain: Fearann + edit: Cuir bloc fearainn in eagar + existing_domain_block: Chuir tú teorainneacha níos déine ar %{name} cheana féin. + existing_domain_block_html: Chuir tú teorainneacha níos déine ar %{name} cheana féin, ní mór duit an bac a bhaint as ar dtús. export: Easpórtáil import: Iompórtáil new: + create: Cruthaigh bloc + hint: Ní choiscfidh an bloc fearainn iontrálacha cuntais a chruthú sa bhunachar sonraí, ach cuirfidh sé modhanna modhnóireachta sonracha i bhfeidhm go haisghníomhach agus go huathoibríoch ar na cuntais sin. severity: + desc_html: Déanfaidh Teorainn postálacha ó chuntais ag an bhfearann ​​seo dofheicthe d'aon duine nach bhfuil á leanúint. Bainfidh Fionraí gach ábhar, meán agus sonraí próifíle do chuntais an fhearainn seo de do fhreastalaí. Úsáid Dada más mian leat comhaid meán a dhiúltú. + noop: Dada silence: Teorannaigh suspend: Cuir ar fionraí + title: Bloc fearainn nua + no_domain_block_selected: Níor athraíodh aon bhloc fearainn mar níor roghnaíodh ceann ar bith + not_permitted: Níl cead agat an gníomh seo a dhéanamh + obfuscate: Obfuscate ainm fearainn + obfuscate_hint: Cuir bac páirteach ar an ainm fearainn sa liosta má tá fógraíocht ar an liosta teorainneacha fearainn cumasaithe + private_comment: Trácht príobháideach + private_comment_hint: Déan trácht ar an teorannú fearainn seo le haghaidh úsáid inmheánach ag na modhnóirí. + public_comment: Trácht poiblí + public_comment_hint: Déan trácht ar an teorannú fearainn seo don phobal i gcoitinne, má tá fógraíocht ar an liosta teorainneacha fearainn cumasaithe. + reject_media: Diúltaigh comhaid meán + reject_media_hint: Baintear comhaid meán atá stóráilte go háitiúil agus diúltaíonn sé aon cheann a íoslódáil amach anseo. Ní bhaineann le fionraí + reject_reports: Diúltaigh tuarascálacha + reject_reports_hint: Déan neamhaird de gach tuairisc a thagann ón bhfearann ​​seo. Ní bhaineann le fionraí + undo: Cealaigh bloc fearainn + view: Féach ar bhloc fearainn email_domain_blocks: + add_new: Cuir nua leis + allow_registrations_with_approval: Ceadaigh clárúcháin le ceadú + attempts_over_week: + few: "%{count} iarracht chun síniú suas le seachtain anuas" + many: "%{count} iarracht chun síniú suas le seachtain anuas" + one: "%{count} iarracht le seachtain anuas" + other: "%{count} iarracht chun síniú suas le seachtain anuas" + two: "%{count} iarracht chun síniú suas le seachtain anuas" + created_msg: D'éirigh leis an bhfearann ​​ríomhphoist a bhlocáil delete: Scrios + dns: + types: + mx: Taifead MX domain: Fearann + new: + create: Cuir fearann ​​leis + resolve: Réitigh fearann + title: Cuir bac ar fhearann ​​​​r-phoist nua + no_email_domain_block_selected: Níor athraíodh aon bhloc fearainn ríomhphoist mar níor roghnaíodh ceann ar bith + not_permitted: Níl sé ceadaithe + resolved_dns_records_hint_html: Réitíonn an t-ainm fearainn chuig na fearainn MX seo a leanas, atá freagrach sa deireadh as glacadh le ríomhphost. Má dhéantar fearann ​​MX a bhlocáil, cuirfear bac ar chlárúcháin ó aon seoladh ríomhphoist a úsáideann an fearann ​​MX céanna, fiú má tá an t-ainm fearainn infheicthe difriúil. Bí cúramach gan bac a chur ar phríomhsholáthraithe ríomhphoist. + resolved_through_html: Réitithe trí %{domain} + title: Fearainn ríomhphoist bactha + export_domain_allows: + new: + title: Ceadaíonn fearann ​​​​iomportála + no_file: Níor roghnaíodh aon chomhad + export_domain_blocks: + import: + description_html: Tá tú ar tí liosta de bhlocanna fearainn a allmhairiú. Athbhreithnigh an liosta seo go han-chúramach, le do thoil, go háirithe murar scríobh tú féin an liosta seo. + existing_relationships_warning: Caidreamh leantach atá ann cheana féin + private_comment_description_html: 'Chun cabhrú leat teacht ar cad as a dtagann bloic iompórtáilte, cruthófar bloic iompórtáilte leis an nóta tráchta príobháideach seo a leanas: %{comment}' + private_comment_template: Iompórtáilte ó %{source} ar %{date} + title: Iompórtáil bloic fearainn + invalid_domain_block: 'Léiríodh bloc fearainn amháin nó níos mó mar gheall ar an earráid(í): %{error}' + new: + title: Iompórtáil bloic fearainn + no_file: Níor roghnaíodh aon chomhad follow_recommendations: + description_html: "Lean na moltaí cabhraíonn sé le húsáideoirí nua ábhar suimiúil a aimsiú go tapa. Nuair nach mbíonn go leor idirghníomhaithe ag úsáideoir le daoine eile chun moltaí pearsantaithe a leanúint, moltar na cuntais seo ina ionad sin. Déantar iad a athríomh ar bhonn laethúil ó mheascán de chuntais a bhfuil na rannpháirtíochtaí is airde acu le déanaí agus na háirimh áitiúla is airde leanúna do theanga ar leith." language: Don teanga status: Stádas suppress: Coisc moladh leanúna @@ -190,36 +495,94 @@ ga: title: Moltaí leanúna unsuppress: Aischuir moladh leanúna instances: + availability: + description_html: + few: Má theipeann ar sheachadadh chuig an bhfearann ​​ar %{count} laethanta éagsúla gan rath, ní dhéanfar aon iarrachtaí seachadta eile mura bhfaightear ó seachadadh ón bhfearann. + many: Má theipeann ar sheachadadh chuig an bhfearann ​​ar %{count} laethanta éagsúla gan rath, ní dhéanfar aon iarrachtaí seachadta eile mura bhfaightear ó seachadadh ón bhfearann. + one: Má theipeann ar sheachadadh chuig an bhfearann ​​%{count} day gan rath, ní dhéanfar aon iarrachtaí seachadta eile mura bhfaightear ó seachadadh ón bhfearann. + other: Má theipeann ar sheachadadh chuig an bhfearann ​​ar %{count} laethanta éagsúla gan rath, ní dhéanfar aon iarrachtaí seachadta eile mura bhfaightear ó seachadadh ón bhfearann. + two: Má theipeann ar sheachadadh chuig an bhfearann ​​ar %{count} laethanta éagsúla gan rath, ní dhéanfar aon iarrachtaí seachadta eile mura bhfaightear ó seachadadh ón bhfearann. + failure_threshold_reached: Baineadh an tairseach teipe amach ar %{date}. + failures_recorded: + few: Theip ar iarrachtaí ar %{count} lá difriúil. + many: Theip ar iarrachtaí ar %{count} lá difriúil. + one: Theip ar iarracht ar %{count} lá. + other: Theip ar iarrachtaí ar %{count} lá difriúil. + two: Theip ar iarrachtaí ar %{count} lá difriúil. + no_failures_recorded: Uimh teipeanna ar taifead. + title: Infhaighteacht + warning: Níor éirigh leis an iarracht dheireanach chun ceangal leis an bhfreastalaí seo back_to_all: Uile back_to_limited: Teoranta back_to_warning: Rabhadh by_domain: Fearann + confirm_purge: An bhfuil tú cinnte gur mian leat sonraí a scriosadh go buan ón bhfearann ​​seo? content_policies: comment: Nóta inmheánach + description_html: Is féidir leat beartais inneachair a shainiú a chuirfear i bhfeidhm ar gach cuntas ón bhfearann ​​seo agus aon cheann dá fhofhearainn. + limited_federation_mode_description_html: Is féidir leat an rogha a dhéanamh maidir le cónaidhm a cheadú leis an bhfearann ​​seo. policies: + reject_media: Na meáin a dhiúltú + reject_reports: Diúltaigh tuarascálacha silence: Teorannaigh suspend: Cuir ar fionraí policy: Polasaí + reason: Cúis phoiblí + title: Polasaithe ábhair dashboard: + instance_accounts_dimension: Cuntais a lean a bhformhór + instance_accounts_measure: cuntais stóráilte + instance_followers_measure: ár leantóirí ann + instance_follows_measure: a lucht leanta anseo instance_languages_dimension: Teangacha is airde + instance_media_attachments_measure: ceangaltáin meáin stóráilte + instance_reports_measure: tuairiscí mar gheall orthu + instance_statuses_measure: postanna stóráilte delivery: all: Uile + clear: Earráidí seachadta soiléir failing: Ag teip + restart: Seachadadh a atosú + stop: Stad seachadadh unavailable: Níl ar fáil + delivery_available: Tá seachadadh ar fáil + delivery_error_days: Laethanta earráide seachadta + delivery_error_hint: Mura féidir seachadadh a dhéanamh ar feadh %{count} lá, marcálfar go huathoibríoch é mar dosheachadta. + destroyed_msg: Tá sonraí ó %{domain} ciúáilte anois le haghaidh scriosadh gan mhoill. + empty: Níor aimsíodh aon fhearainn. + known_accounts: + few: "%{count} cuntas aitheanta" + many: "%{count} cuntas aitheanta" + one: "%{count} cuntas aitheanta" + other: "%{count} cuntas aitheanta" + two: "%{count} cuntas aitheanta" moderation: all: Uile limited: Teoranta + title: Measarthacht + private_comment: Trácht príobháideach + public_comment: Trácht poiblí purge: Glan + purge_description_html: Má chreideann tú go bhfuil an fearann ​​seo as líne ar feadh tamaill mhaith, is féidir leat gach taifead cuntais agus sonraí gaolmhara ón bhfearann ​​​​seo a scriosadh ó do stór. Seans go dtógfaidh sé seo tamall. title: Cónascadh + total_blocked_by_us: Blocáilte ag dúinn + total_followed_by_them: Ina dhiaidh sin iad total_followed_by_us: Á leanúint againn + total_reported: Tuarascálacha mar gheall orthu + total_storage: Ceangaltáin meán + totals_time_period_hint_html: Áiríonn na hiomláin a thaispeántar thíos sonraí don am ar fad. + unknown_instance: Níl aon taifead den fhearann ​​seo ar an bhfreastalaí seo faoi láthair. invites: + deactivate_all: Díghníomhachtaigh go léir filter: all: Uile available: Ar fáil + expired: Imithe in éag title: Scag title: Cuirí ip_blocks: add_new: Cruthaigh riail + created_msg: Cuireadh riail IP nua leis go rathúil delete: Scrios expires_in: '1209600': Coicís @@ -228,111 +591,609 @@ ga: '31556952': Bliain amháin '86400': Lá amháin '94670856': 3 bhliain + new: + title: Cruthaigh riail IP nua + no_ip_block_selected: Níor athraíodh aon rialacha IP mar níor roghnaíodh ceann ar bith title: Rialacha IP + relationships: + title: Caidrimh %{acct} relays: + add_new: Cuir sealaíochta nua leis delete: Scrios + description_html: Is freastalaí idirghabhálaí é athsheachadán cónaidhme a mhalartaíonn líon mór postálacha poiblí idir freastalaithe a shíníonn dó agus a fhoilsíonn é. Is féidir leis cabhrú le freastalaithe beaga agus meánmhéide inneachar a aimsiú ón bhfeideas, rud a d'éileodh ar úsáideoirí áitiúla daoine eile a leanúint de láimh ar fhreastalaithe cianda. disable: Díchumasaigh disabled: Díchumasaithe enable: Cumasaigh + enable_hint: Nuair a bheidh sé cumasaithe, liostóidh do fhreastalaí le gach postáil phoiblí ón athsheoladh seo, agus tosóidh sé ag seoladh postálacha poiblí an fhreastalaí seo chuige. enabled: Ar chumas + inbox_url: URL Athsheolta + pending: Ag fanacht le ceadú sealaíochta save_and_enable: Sábháil agus cumasaigh + setup: Socraigh nasc sealaíochta + signatures_not_enabled: Seans nach n-oibreoidh athsheachadáin i gceart agus mód slán nó modh cónaidhmthe teoranta cumasaithe status: Stádas + title: Athsheachadáin + report_notes: + created_msg: Cruthaíodh nóta tuairisce go rathúil! + destroyed_msg: D'éirigh leis an nóta tuairisce a scriosadh! reports: + account: + notes: + few: "%{count} nótaí" + many: "%{count} nótaí" + one: "%{count} nóta" + other: "%{count} nótaí" + two: "%{count} nótaí" + action_log: Loga iniúchta + action_taken_by: Gníomh arna ghlacadh ag + actions: + delete_description_html: Scriosfar na postálacha tuairiscithe agus déanfar stailc a thaifeadadh chun cabhrú leat dul in airde ar sháruithe sa todhchaí tríd an gcuntas céanna. + mark_as_sensitive_description_html: Déanfar na meáin sna poist tuairiscithe a mharcáil mar íogair agus déanfar stailc a thaifeadadh chun cabhrú leat sárú a dhéanamh ar sháruithe sa todhchaí tríd an gcuntas céanna. + other_description_html: Féach ar a thuilleadh roghanna chun iompar an chuntais a rialú agus cumarsáid a shaincheapadh chuig an gcuntas tuairiscithe. + resolve_description_html: Ní dhéanfar aon ghníomhaíocht i gcoinne an chuntais thuairiscithe, ní dhéanfar aon stailc a thaifeadadh, agus dúnfar an tuarascáil. + silence_description_html: Ní bheidh an cuntas le feiceáil ach amháin dóibh siúd a leanann é cheana féin nó a bhreathnaíonn suas de láimh air, rud a chuirfidh srian mór ar a rochtain. Is féidir é a chur ar ais i gcónaí. Dúnann sé gach tuairisc i gcoinne an chuntais seo. + suspend_description_html: Beidh an cuntas agus a bhfuil ann go léir dorochtana agus scriosfar iad ar deireadh, agus beidh sé dodhéanta idirghníomhú leis. Inchúlaithe laistigh de 30 lá. Dúnann sé gach tuairisc i gcoinne an chuntais seo. + actions_description_html: Déan cinneadh ar an ngníomh atá le déanamh chun an tuarascáil seo a réiteach. Má dhéanann tú beart pionósach in aghaidh an chuntais tuairiscithe, seolfar fógra ríomhphoist chucu, ach amháin nuair a roghnaítear an chatagóir Turscar. + actions_description_remote_html: Déan cinneadh ar an ngníomh atá le déanamh chun an tuarascáil seo a réiteach. Ní bheidh tionchar aige seo ach ar an gcaoi a ndéanann do fhreastalaí cumarsáid leis an gcianchuntas seo agus a láimhseálann sé a ábhar. + add_to_report: Cuir tuilleadh leis an tuairisc + already_suspended_badges: + local: Ar fionraí cheana féin ar an bhfreastalaí seo + remote: Ar fionraí cheana féin ar a bhfreastalaí are_you_sure: An bhfuil tú cinnte? + assign_to_self: Sann dom + assigned: Modhnóir sannta + by_target_domain: Fearann ​​an chuntais tuairiscithe cancel: Cealaigh category: Catagóir + category_description_html: Luafar an chúis ar tuairiscíodh an cuntas seo agus/nó an t-ábhar seo i gcumarsáid leis an gcuntas tuairiscithe + comment: + none: Dada + comment_description_html: 'Chun tuilleadh eolais a sholáthar, scríobh %{name}:' + confirm: Deimhnigh + confirm_action: Deimhnigh gníomh modhnóireachta i gcoinne @%{acct} created_at: Tuairiscithe delete_and_resolve: Scrios postálacha + forwarded: Ar aghaidh + forwarded_replies_explanation: Is ó chianúsáideoir an tuairisc seo agus faoi chianábhar. Tá sé curtha ar aghaidh chugat toisc go bhfuil an t-ábhar tuairiscithe mar fhreagra ar cheann de na húsáideoirí atá agat. + forwarded_to: Ar aghaidh chuig %{domain} mark_as_resolved: Marcáil mar réitithe mark_as_sensitive: Marcáil mar íogair + mark_as_unresolved: Marcáil mar gan réiteach no_one_assigned: Duine ar bith notes: create: Cruthaigh nóta create_and_resolve: Réitigh le nóta + create_and_unresolve: Oscail arís le nóta delete: Scrios + placeholder: Déan cur síos ar na bearta a rinneadh, nó ar aon nuashonruithe gaolmhara eile... title: Nótaí + notes_description_html: Féach ar agus fág nótaí do mhodhnóirí eile agus duit féin amach anseo + processed_msg: 'D''éirigh le próiseáil an tuairisc # %{id}' + quick_actions_description_html: 'Déan gníomh tapa nó scrollaigh síos chun ábhar tuairiscithe a fheiceáil:' + remote_user_placeholder: an cianúsáideoir ó %{instance} + reopen: Tuairisc a athoscailt + report: 'Tuairiscigh # %{id}' + reported_account: Cuntas tuairiscithe + reported_by: Tuairiscithe ag + reported_with_application: Tuairiscíodh leis an iarratas + resolved: Réitithe + resolved_msg: D'éirigh le réiteach an tuairisc! + skip_to_actions: Léim ar ghníomhartha status: Stádas + statuses: Ábhar tuairiscithe + statuses_description_html: Luafar ábhar ciontach i gcumarsáid leis an gcuntas tuairiscithe + summary: + action_preambles: + delete_html: 'Tá tú ar tí cuid de phostálacha @%{acct} a bhaint. Déanfaidh sé seo:' + mark_as_sensitive_html: 'Tá tú ar tí marcáil ar chuid de phostálacha @%{acct} mar íogair. Déanfaidh sé seo:' + silence_html: 'Tá tú ar tí teorannú a dhéanamh ar chuntas @%{acct}. Déanfaidh sé seo:' + suspend_html: 'Tá tú ar tí cuntas a chur ar fionraí @%{acct}. Déanfaidh sé seo:' + actions: + delete_html: Bain na postálacha ciontaithe + mark_as_sensitive_html: Marcáil meáin na bpost ciontaithe mar íogair + silence_html: Cuir teorainn mhór le rochtain @%{acct} trí a bpróifíl agus a n-inneachar a dhéanamh infheicthe ag daoine atá á leanúint cheana féin nó ag breathnú uirthi de láimh + suspend_html: Cuir @%{acct} ar fionraí, rud a fhágann go bhfuil a bpróifíl agus a bhfuil iontu dorochtana agus dodhéanta idirghníomhú leo + close_report: 'Marcáil an tuairisc #%{id} mar réitithe' + close_reports_html: Marcáil gach tuairisc in aghaidh @%{acct} mar réitithe + delete_data_html: Scrios próifíl agus inneachar @%{acct} 30 lá ó anois mura mbeidh siad curtha ar fionraí idir an dá linn + preview_preamble_html: 'Gheobhaidh @%{acct} rabhadh leis an ábhar seo a leanas:' + record_strike_html: Taifead stailc in aghaidh @%{acct} chun cabhrú leat dul i ngleic le sáruithe amach anseo ón gcuntas seo + send_email_html: Seol ríomhphost rabhaidh chuig @%{acct} + warning_placeholder: Réasúnaíocht bhreise roghnach don ghníomh modhnóireachta. + target_origin: Bunús an chuntais tuairiscithe title: Tuairiscí + unassign: Díshannadh + unknown_action_msg: 'Gníomh anaithnid: %{action}' + unresolved: Gan réiteach + updated_at: Nuashonraithe + view_profile: Féach ar phróifíl roles: add_new: Cruthaigh ról + assigned_users: + few: "%{count} úsáideoirí" + many: "%{count} úsáideoirí" + one: "%{count} úsáideoir" + other: "%{count} úsáideoirí" + two: "%{count} úsáideoirí" categories: administration: Riar + devops: DevOps invites: Cuirí + moderation: Measarthacht + special: Speisialta delete: Scrios + description_html: Le róil úsáideora, is féidir leat na feidhmeanna agus na réimsí de Mastodon ar féidir le d'úsáideoirí rochtain a fháil orthu a shaincheapadh. + edit: Cuir ról '%{name}' in eagar + everyone: Ceadanna réamhshocraithe + everyone_full_description_html: Seo é an bunról a théann i bhfeidhm ar gach úsáideoir, fiú iad siúd nach bhfuil ról sannta acu. Faigheann gach ról eile cead uaidh. + permissions_count: + few: "%{count} ceadanna" + many: "%{count} ceadanna" + one: "%{count} cead" + other: "%{count} ceadanna" + two: "%{count} ceadanna" privileges: administrator: Riarthóir + administrator_description: Seachnóidh úsáideoirí a bhfuil an cead seo acu gach cead delete_user_data: Scrios Sonraí Úsáideora + delete_user_data_description: Ligeann sé d'úsáideoirí sonraí úsáideoirí eile a scriosadh gan mhoill + invite_users: Tabhair cuireadh d'Úsáideoirí + invite_users_description: Ligeann sé d'úsáideoirí cuireadh a thabhairt do dhaoine nua chuig an bhfreastalaí + manage_announcements: Bainistigh Fógraí + manage_announcements_description: Ligeann sé d'úsáideoirí fógraí ar an bhfreastalaí a bhainistiú + manage_appeals: Achomharc a bhainistiú + manage_appeals_description: Ligeann sé d'úsáideoirí athbhreithniú a dhéanamh ar achomhairc i gcoinne gníomhartha modhnóireachta + manage_blocks: Bainistigh Bloic + manage_blocks_description: Ligeann sé d'úsáideoirí bac a chur ar sholáthraithe ríomhphoist agus seoltaí IP + manage_custom_emojis: Bainistigh Emojis Saincheaptha + manage_custom_emojis_description: Ligeann sé d'úsáideoirí emojis saincheaptha a bhainistiú ar an bhfreastalaí + manage_federation: Cónaidhm a bhainistiú + manage_federation_description: Ligeann sé d’úsáideoirí cónaidhm a bhlocáil nó a cheadú le fearainn eile, agus inseachadacht a rialú + manage_invites: Bainistigh Cuirí + manage_invites_description: Ligeann sé d'úsáideoirí naisc cuireadh a bhrabhsáil agus a dhíghníomhachtú + manage_reports: Tuarascálacha a bhainistiú + manage_reports_description: Ligeann sé d’úsáideoirí tuarascálacha a athbhreithniú agus gníomhartha modhnóireachta a dhéanamh ina gcoinne + manage_roles: Bainistigh Róil + manage_roles_description: Ligeann sé d'úsáideoirí róil faoina gcuid féin a bhainistiú agus a shannadh + manage_rules: Rialacha a bhainistiú + manage_rules_description: Ligeann sé d'úsáideoirí rialacha freastalaí a athrú + manage_settings: Bainistigh Socruithe + manage_settings_description: Ligeann sé d'úsáideoirí socruithe suímh a athrú + manage_taxonomies: Tacsanomaíochtaí a bhainistiú + manage_taxonomies_description: Ligeann sé d'úsáideoirí athbhreithniú a dhéanamh ar inneachar treochta agus socruithe hashtag a nuashonrú + manage_user_access: Bainistigh Rochtain Úsáideoir + manage_user_access_description: Ligeann sé d'úsáideoirí fíordheimhniú dhá fhachtóir úsáideoirí eile a dhíchumasú, a seoladh r-phoist a athrú, agus a bpasfhocal a athshocrú + manage_users: Bainistigh Úsáideoirí + manage_users_description: Ligeann sé d'úsáideoirí sonraí úsáideoirí eile a fheiceáil agus gníomhartha modhnóireachta a dhéanamh ina gcoinne + manage_webhooks: Bainistigh cuacha Gréasáin + manage_webhooks_description: Ligeann sé d'úsáideoirí cuacha gréasáin a shocrú le haghaidh imeachtaí riaracháin + view_audit_log: Féach ar Loga Iniúchta + view_audit_log_description: Ligeann sé d'úsáideoirí stair gníomhartha riaracháin a fheiceáil ar an bhfreastalaí + view_dashboard: Amharc ar an Deais + view_dashboard_description: Ligeann sé d’úsáideoirí rochtain a fháil ar an deais agus ar mhéadrachtaí éagsúla + view_devops: DevOps + view_devops_description: Ligeann sé d’úsáideoirí rochtain a fháil ar dheais Sidekiq agus pgHero title: Róil rules: add_new: Cruthaigh riail delete: Scrios + description_html: Cé go maíonn a bhformhór gur léigh siad agus go n-aontaíonn siad leis na téarmaí seirbhíse, de ghnáth ní léann daoine tríd go dtí go dtagann fadhb chun cinn. Déan rialacha do fhreastalaí a fheiceáil go sracfhéachaint trí iad a sholáthar i liosta comhréidh de phointe urchair. Déan iarracht rialacha aonair a choinneáil gearr simplí, ach déan iarracht gan iad a roinnt ina go leor míreanna ar leith ach an oiread. + edit: Cuir riail in eagar + empty: Níl aon rialacha freastalaí sainmhínithe fós. + title: Rialacha freastalaí settings: + about: + manage_rules: Bainistigh rialacha freastalaí + preamble: Cuir eolas domhain ar fáil faoin gcaoi a n-oibrítear, a ndéantar modhnóireacht agus maoiniú ar an bhfreastalaí. + rules_hint: Tá réimse tiomnaithe rialacha ann a bhfuiltear ag súil go gcloífidh d’úsáideoirí leis. + title: Faoi appearance: + preamble: Saincheap comhéadan gréasáin Mastodon. title: Cuma + branding: + preamble: Déanann brandáil do fhreastalaí é a idirdhealú ó fhreastalaithe eile sa líonra. Féadfar an fhaisnéis seo a thaispeáint ar fud timpeallachtaí éagsúla, mar shampla comhéadan gréasáin Mastodon, feidhmchláir dhúchasacha, i réamhamhairc naisc ar láithreáin ghréasáin eile agus laistigh d’aipeanna teachtaireachtaí, agus mar sin de. Ar an ábhar sin, is fearr an fhaisnéis seo a choinneáil soiléir, gearr agus gonta. + title: Brandáil + captcha_enabled: + desc_html: Braitheann sé seo ar scripteanna seachtracha ó hCaptcha, rud a d’fhéadfadh a bheith ina ábhar imní maidir le slándáil agus príobháideacht. Ina theannta sin, is féidir leis seo an próiseas clárúcháin a dhéanamh i bhfad níos lú inrochtana ag roinnt daoine (go háirithe faoi mhíchumas). Ar na cúiseanna seo, smaoinigh le do thoil ar bhearta eile amhail clárú bunaithe ar fhormheas nó ar chuireadh. + title: A cheangal ar úsáideoirí nua CAPTCHA a réiteach chun a gcuntas a dhearbhú + content_retention: + danger_zone: Crios contúirte + preamble: Rialú conas a stóráiltear ábhar a ghintear ag úsáideoirí i Mastodon. + title: Coinneáil ábhair default_noindex: desc_html: I bhfeidhm do ghach úsáideoir nár athraigh an socrú seo iad féin title: Diúltaigh d'innéacsú inneall cuardaigh mar réamhshocrú d'úsáideoirí + discovery: + follow_recommendations: Lean na moltaí + preamble: Tá sé ríthábhachtach dromchla a chur ar ábhar suimiúil chun úsáideoirí nua a chur ar bord nach bhfuil aithne acu ar dhuine ar bith Mastodon. Rialú conas a oibríonn gnéithe fionnachtana éagsúla ar do fhreastalaí. + profile_directory: Eolaire próifíle + public_timelines: Amlínte poiblí + publish_discovered_servers: Foilsigh freastalaithe aimsithe + publish_statistics: Staitisticí a fhoilsiú + title: Fionnachtain + trends: Treochtaí + domain_blocks: + all: Do chách + disabled: Do dhuine ar bith + users: Chun úsáideoirí áitiúla logáilte isteach registrations: + moderation_recommandation: Cinntigh le do thoil go bhfuil foireann mhodhnóireachta imoibríoch leordhóthanach agat sula n-osclaíonn tú clárúcháin do gach duine! + preamble: Rialú cé atá in ann cuntas a chruthú ar do fhreastalaí. title: Clárúcháin + registrations_mode: + modes: + approved: Teastaíonn ceadú le clárú + none: Ní féidir le duine ar bith clárú + open: Is féidir le duine ar bith clárú + warning_hint: Molaimid úsáid a bhaint as “Faomhadh riachtanach chun clárú” ach amháin má tá tú muiníneach gur féidir le d’fhoireann mhodhnóireachta clárú turscair agus mailíseach a láimhseáil go tráthúil. + security: + authorized_fetch: Teastaíonn fíordheimhniú ó fhreastalaithe cónasctha + authorized_fetch_hint: Toisc go n-éilítear fíordheimhniú ó fhreastalaithe cónasctha, is féidir bloic ar leibhéal an úsáideora agus ar leibhéal an fhreastalaí araon a fhorfheidhmiú níos déine. Mar sin féin, tagann sé seo ar chostas pionós feidhmíochta, laghdaítear an teacht ar do chuid freagraí, agus d'fhéadfadh saincheisteanna comhoiriúnachta a thabhairt isteach le roinnt seirbhísí cónasctha. Ina theannta sin, ní chuirfidh sé seo cosc ​​ar aisteoirí tiomnaithe do phoist phoiblí agus do chuntais phoiblí a fháil. + authorized_fetch_overridden_hint: Ní féidir leat an socrú seo a athrú faoi láthair toisc go bhfuil sé sáraithe ag athróg timpeallachta. + federation_authentication: Forghníomhú fíordheimhnithe Cónaidhm + title: Socruithe freastalaí site_uploads: delete: Scrios comhad uaslódáilte + destroyed_msg: D'éirigh le huaslódáil an tsuímh a scriosadh! + software_updates: + critical_update: Criticiúil - nuashonraigh go tapa le do thoil + description: Moltar do shuiteáil Mastodon a choinneáil cothrom le dáta chun leas a bhaint as na socruithe agus na gnéithe is déanaí. Ina theannta sin, tá sé ríthábhachtach uaireanta Mastodon a nuashonrú go tráthúil chun saincheisteanna slándála a sheachaint. Ar na cúiseanna seo, seiceálann Mastodon nuashonruithe gach 30 nóiméad, agus tabharfaidh sé fógra duit de réir do shainroghanna fógra ríomhphoist. + documentation_link: Foghlaim níos mó + release_notes: Nótaí scaoilte + title: Nuashonruithe ar fáil + type: Cineál + types: + major: Mórscaoileadh + minor: Mionscaoileadh + patch: Scaoileadh paiste - ceartúcháin agus athruithe atá éasca a chur i bhfeidhm + version: Leagan statuses: account: Údar + application: Iarratas back_to_account: Ar ais go leathanach cuntais + back_to_report: Ar ais go leathanach tuairisce + batch: + remove_from_report: Bain den tuairisc + report: Tuairisc deleted: Scriosta favourites: Toghanna + history: Stair leagan + in_reply_to: Ag freagairt do language: Teanga media: title: Meáin metadata: Meiteashonraí + no_status_selected: Níor athraíodh aon phostáil mar níor roghnaíodh ceann ar bith open: Oscail postáil original_status: Bunphostáil reblogs: Athbhlaganna status_changed: Athraíodh postáil + title: Poist chuntais trending: Ag treochtáil + visibility: Infheictheacht with_media: Le meáin strikes: actions: delete_statuses: Scrios %{name} postálacha de chuid %{target} + disable: Reoite %{name} cuntas %{target} + mark_statuses_as_sensitive: Mharcáil %{name} postálacha %{target} mar íogair + none: Sheol %{name} rabhadh chuig %{target} + sensitive: Mharcáil %{name} cuntas %{target} mar íogair + silence: Chuir %{name} teorainn le cuntas %{target} + suspend: Chuir %{name} cuntas %{target} ar fionraí + appeal_approved: Achomharc + appeal_pending: Achomharc ar feitheamh + appeal_rejected: Diúltaíodh don achomharc + system_checks: + database_schema_check: + message_html: Tá aistrithe bunachar sonraí ar feitheamh. Rith iad le do thoil chun a chinntiú go n-iompraíonn an t-iarratas mar a bhíothas ag súil leis + elasticsearch_health_red: + message_html: Tá braisle Elasticsearch míshláintiúil (stádas dearg), níl gnéithe cuardaigh ar fáil + elasticsearch_health_yellow: + message_html: Tá braisle Elasticsearch míshláintiúil (stádas buí), b'fhéidir gur mhaith leat an chúis a fhiosrú + elasticsearch_index_mismatch: + message_html: Tá mapálacha innéacs Elasticsearch as dáta. Rith tootctl search deploy --only=%{value} le do thoil + elasticsearch_preset: + action: Féach doiciméadú + message_html: Tá níos mó ná nód amháin ag do bhraisle Elasticsearch, ach níl Mastodon cumraithe chun iad a úsáid. + elasticsearch_preset_single_node: + action: Féach doiciméadú + message_html: Níl ach nód amháin ag do bhraisle Elasticsearch, ba cheart ES_PRESET a shocrú go single_node_cluster. + elasticsearch_reset_chewy: + message_html: Tá d'innéacs córais Elasticsearch as dáta mar gheall ar athrú socruithe. Rith tootctl search deploy --reset-chewy chun é a nuashonrú. + elasticsearch_running_check: + message_html: Níorbh fhéidir ceangal le Elasticsearch. Cinntigh go bhfuil sé ar siúl, nó díchumasaigh cuardach téacs iomlán + elasticsearch_version_check: + message_html: 'Leagan neamh-chomhoiriúnach le Elasticsearch: %{value}' + version_comparison: Tá Elasticsearch %{running_version} ag rith agus %{required_version} ag teastáil + rules_check: + action: Bainistigh rialacha freastalaí + message_html: Níl aon rialacha freastalaí sainmhínithe agat. + sidekiq_process_check: + message_html: Níl próiseas Sidekiq ag rith don scuaine/(scuainí) %{value}. Déan athbhreithniú ar do chumraíocht Sidekiq + software_version_critical_check: + action: Féach nuashonruithe atá ar fáil + message_html: Tá nuashonrú ríthábhachtach Mastodon ar fáil, nuashonraigh chomh tapa agus is féidir le do thoil. + software_version_patch_check: + action: Féach nuashonruithe atá ar fáil + message_html: Tá nuashonrú bugfix Mastodon ar fáil. + upload_check_privacy_error: + action: Seiceáil anseo le haghaidh tuilleadh eolais + message_html: "Tá do fhreastalaí gréasáin míchumraithe. Tá príobháideacht d'úsáideoirí i mbaol." + upload_check_privacy_error_object_storage: + action: Seiceáil anseo le haghaidh tuilleadh eolais + message_html: "Tá do stór oibiachtaí míchumraithe. Tá príobháideacht d'úsáideoirí i mbaol." tags: review: Stádas athbhreithnithe + updated_msg: D'éirigh le socruithe hashtag a nuashonrú title: Riar trends: allow: Ceadaigh + approved: Ceadaithe disallow: Dícheadaigh + links: + allow: Ceadaigh nasc + allow_provider: Ceadaigh foilsitheoir + description_html: Is naisc iad seo atá á roinnt go mór faoi láthair ag cuntais a bhfeiceann do fhreastalaí postálacha uathu. Is féidir leis cabhrú le d’úsáideoirí a fháil amach cad atá ar siúl ar fud an domhain. Ní thaispeánfar naisc ar bith go poiblí go dtí go gceadaíonn tú an foilsitheoir. Is féidir leat naisc aonair a cheadú nó a dhiúltú freisin. + disallow: Nasc a dhícheadú + disallow_provider: Dícheadaigh foilsitheoir + no_link_selected: Níor athraíodh aon nasc mar níor roghnaíodh ceann ar bith + publishers: + no_publisher_selected: Níor athraíodh aon fhoilsitheoir mar níor roghnaíodh ceann ar bith + shared_by_over_week: + few: Roinnte ag %{count} duine le seachtain anuas + many: Roinnte ag %{count} duine le seachtain anuas + one: Roinnte ag duine amháin le seachtain anuas + other: Roinnte ag %{count} duine le seachtain anuas + two: Roinnte ag %{count} duine le seachtain anuas + title: Naisc treochta + usage_comparison: Roinnte %{today} uair inniu, i gcomparáid le %{yesterday} inné + not_allowed_to_trend: Ní cheadaítear treocht + only_allowed: Ní cheadaítear ach + pending_review: Athbhreithniú ar feitheamh preview_card_providers: + allowed: Is féidir le naisc ón bhfoilsitheoir seo treocht + description_html: Is fearainn iad seo óna roinntear naisc go minic ar do fhreastalaí. Ní threochtóidh naisc go poiblí mura gceadaítear fearann ​​an naisc. Síneann do cheadú (nó diúltú) chuig fofhearainn. + rejected: Ní bheidh treocht ag naisc ón bhfoilsitheoir seo title: Foilsitheoirí rejected: Diúltaithe statuses: allow: Ceadaigh postáil allow_account: Ceadaigh údar + description_html: Is postálacha iad seo a bhfuil do fhreastalaí ar an eolas fúthu agus atá á roinnt faoi láthair agus is fearr leat go mór faoi láthair. Is féidir leis cabhrú le d’úsáideoirí nua agus úsáideoirí atá ag filleadh níos mó daoine a aimsiú le leanúint. Ní thaispeánfar postálacha ar bith go poiblí go dtí go gceadaíonn tú an t-údar, agus ceadaíonn an t-údar a gcuntas a mholadh do dhaoine eile. Is féidir leat postálacha aonair a cheadú nó a dhiúltú freisin. + disallow: Dícheadaigh postáil + disallow_account: Údar a dhícheadú + no_status_selected: Níor athraíodh aon phostáil treochta mar níor roghnaíodh ceann ar bith + not_discoverable: Níor roghnaigh an t-údar a bheith in-aimsithe + shared_by: + few: Roinnte agus ansa leat %{friendly_count} uair + many: Roinnte agus ansa leat %{friendly_count} uair + one: Roinnte nó is fearr leat am amháin + other: Roinnte agus ansa leat %{friendly_count} uair + two: Roinnte agus ansa leat %{friendly_count} uair + title: Poist trending + tags: + current_score: Scór reatha %{score} + dashboard: + tag_accounts_measure: úsáidí uathúla + tag_languages_dimension: Barrtheangacha + tag_servers_dimension: Barrtheangacha + tag_servers_measure: freastalaithe éagsúla + tag_uses_measure: úsáidí iomlána + description_html: Is hashtags iad seo atá le feiceáil faoi láthair i go leor postálacha a fheiceann do fhreastalaí. Is féidir leis cabhrú le d’úsáideoirí a fháil amach cad é is mó atá ag caint faoi dhaoine faoi láthair. Ní thaispeánfar aon hashtags go poiblí go dtí go gceadaíonn tú iad. + listable: Is féidir a mholadh + no_tag_selected: Níor athraíodh aon chlib mar níor roghnaíodh ceann ar bith + not_listable: Ní mholfar + not_trendable: Ní bheidh le feiceáil faoi threochtaí + not_usable: Ní féidir é a úsáid + peaked_on_and_decaying: Buaicphointe ar %{date}, ag lobhadh anois + title: Haischlib treochta + trendable: Is féidir le feiceáil faoi threochtaí + trending_rank: 'Ag treochtáil # %{rank}' + usable: Is féidir é a úsáid + usage_comparison: Úsáidte %{today} uair inniu, i gcomparáid le %{yesterday} inné + used_by_over_week: + few: Úsáidte ag %{count} duine le seachtain anuas + many: Úsáidte ag %{count} duine le seachtain anuas + one: Úsáidte ag duine amháin le seachtain anuas + other: Úsáidte ag %{count} duine le seachtain anuas + two: Úsáidte ag %{count} duine le seachtain anuas + title: Treochtaí + trending: Treocht warning_presets: + add_new: Cuir nua leis delete: Scrios + edit_preset: Cuir réamhshocrú rabhaidh in eagar + empty: Níl aon réamhshocruithe rabhaidh sainithe agat fós. + title: Réamhshocruithe rabhaidh webhooks: + add_new: Cuir críochphointe leis delete: Scrios + description_html: Cuireann cuadóg gréasáin ar chumas Mastodon fógraí fíor-ama faoi imeachtaí roghnaithe a bhrú le d'iarratas féin, ionas gur féidir le d'iarratas imoibrithe a spreagadh go huathoibríoch. disable: Díchumasaigh disabled: Díchumasaithe + edit: Cuir críochphointe in eagar + empty: Níl aon chríochphointí cuaille gréasáin agat fós. enable: Cumasaigh enabled: Gníomhach + enabled_events: + few: "%{count} imeacht cumasaithe" + many: "%{count} imeacht cumasaithe" + one: 1 imeacht cumasaithe + other: "%{count} imeacht cumasaithe" + two: "%{count} imeacht cumasaithe" events: Eachtraí + new: Cuaille gréasáin nua + rotate_secret: Rothlaigh an rún + secret: Rún a shíniú status: Stádas + title: Crúcaí gréasáin + webhook: Crúca gréasáin admin_mailer: + auto_close_registrations: + body: De bharr easpa gníomhaíochta modhnóra le déanaí, aistríodh clárúcháin ar %{instance} go huathoibríoch chuig athbhreithniú de láimh chun nach n-úsáidfear %{instance} mar ardán do dhrochghníomhaithe féideartha. Is féidir leat é a athrú ar ais chuig clárúcháin a oscailt am ar bith. + subject: Athraíodh clárúcháin le haghaidh %{instance} go huathoibríoch chuig a dteastaíonn ceadú uathu new_appeal: actions: delete_statuses: a gcuid postálacha a scrios + disable: a gcuntas a reo + mark_statuses_as_sensitive: a bpoist a mharcáil mar íogair none: rabhadh + sensitive: a gcuntas a mharcáil mar íogair + silence: a gcuntas a theorannú + suspend: a gcuntas a chur ar fionraí + body: 'Tá %{target} ag achomharc in aghaidh cinneadh modhnóireachta ó %{action_taken_by} ó %{date}, arbh é %{type} é. Scríobh siad:' + next_steps: Is féidir leat an t-achomharc a cheadú chun an cinneadh modhnóireachta a chealú, nó neamhaird a dhéanamh air. + subject: Tá %{username} ag achomharc in aghaidh cinneadh modhnóireachta ar %{instance} + new_critical_software_updates: + body: Tá leaganacha criticiúla nua de Mastodon eisithe, b'fhéidir gur mhaith leat a nuashonrú chomh luath agus is féidir! + subject: Tá nuashonruithe Critical Mastodon ar fáil do %{instance}! + new_pending_account: + body: Tá sonraí an chuntais nua thíos. Is féidir leat an t-iarratas seo a cheadú nó a dhiúltú. + subject: Cuntas nua le léirmheas ar %{instance} (%{username}) + new_report: + body: Thuairiscigh %{reporter} %{target} + body_remote: Thuairiscigh duine éigin ó %{domain} %{target} + subject: Tuairisc nua do %{instance} (#%{id}) + new_software_updates: + body: Tá leaganacha nua Mastodon eisithe, b'fhéidir gur mhaith leat a nuashonrú! + subject: Tá leaganacha nua Mastodon ar fáil do %{instance}! + new_trends: + body: 'Is gá na míreanna seo a leanas a athbhreithniú sular féidir iad a thaispeáint go poiblí:' + new_trending_links: + title: Naisc treochta + new_trending_statuses: + title: Poist trending + new_trending_tags: + title: Hashtags treochta + subject: Treochtaí nua le hathbhreithniú ar %{instance} + aliases: + add_new: Cruthaigh ailias + created_msg: D'éirigh le hailias nua a chruthú. Is féidir leat an t-aistriú ón seanchuntas a thionscnamh anois. + deleted_msg: D'éirigh leis an ailias a bhaint. Ní bheidh sé indéanta a thuilleadh bogadh ón gcuntas sin chuig an gceann seo. + empty: Níl aon ailiasanna agat. + hint_html: Más mian leat bogadh ó chuntas eile go dtí an ceann seo, anseo is féidir leat ailias a chruthú, a theastaíonn sular féidir leat leanúint ar aghaidh le leantóirí a bhogadh ón seanchuntas go dtí an ceann seo. Tá an gníomh seo ann féin neamhdhíobhálach agus inchúlaithe. Cuirtear tús leis an aistriú cuntais ón seanchuntas. + remove: Dícheangail ailias + appearance: + advanced_web_interface: Comhéadan gréasáin chun cinn + advanced_web_interface_hint: 'Más mian leat úsáid a bhaint as do leithead scáileáin ar fad, ceadaíonn an comhéadan gréasáin ardleibhéil duit go leor colúin éagsúla a chumrú chun an oiread faisnéise a fheiceáil ag an am céanna agus is mian leat: Baile, fógraí, amlíne chónaidhme, aon líon liostaí agus hashtags.' + animations_and_accessibility: Beochan agus inrochtaineacht + confirmation_dialogs: Dialóga deimhnithe + discovery: Fionnachtain + localization: + body: Aistríonn oibrithe deonacha Mastodon. + guide_link: https://crowdin.com/project/mastodon + guide_link_text: Is féidir le gach duine rannchuidiú. + sensitive_content: Ábhar íogair + application_mailer: + notification_preferences: Athraigh roghanna ríomhphoist + salutation: "%{name}," + settings: 'Athraigh sainroghanna ríomhphoist: %{link}' + unsubscribe: Díliostáil + view: 'Amharc:' + view_profile: Féach ar phróifíl + view_status: Féach ar phostáil + applications: + created: D'éirigh leis an bhfeidhmchlár a chruthú + destroyed: D'éirigh leis an bhfeidhmchlár a scriosadh + logout: Logáil Amach + regenerate_token: Athghin comhartha rochtana + token_regenerated: D'éirigh le hathghiniúint an comhartha rochtana + warning: Bí an-chúramach leis na sonraí seo. Ná roinn é le haon duine riamh! + your_token: Do chomhartha rochtana auth: + apply_for_account: Iarr cuntas + captcha_confirmation: + help_html: Má tá fadhbanna agat ag réiteach an CAPTCHA, is féidir leat dul i dteagmháil linn trí %{email} agus is féidir linn cabhrú leat. + hint_html: Ach rud amháin eile! Ní mór dúinn a dhearbhú gur duine daonna thú (tá sé seo ionas gur féidir linn an turscar a choinneáil amach!). Réitigh an CAPTCHA thíos agus cliceáil "Ar aghaidh". + title: Seiceáil slándála + confirmations: + awaiting_review: Tá do sheoladh r-phoist deimhnithe! Tá do chlárúchán á athbhreithniú ag foireann %{domain} anois. Gheobhaidh tú r-phost má fhaomhann siad do chuntas! + awaiting_review_title: Tá do chlárú á athbhreithniú + clicking_this_link: ag cliceáil ar an nasc seo + login_link: logáil isteach + proceed_to_login_html: Is féidir leat dul ar aghaidh chuig %{login_link} anois. + redirect_to_app_html: Ba cheart go ndearnadh tú a atreorú chuig an aip %{app_name}. Murar tharla sin, bain triail as %{clicking_this_link} nó fill ar an aip de láimh. + registration_complete: Tá do chlárú ar %{domain} críochnaithe anois! + welcome_title: Fáilte, %{name}! + wrong_email_hint: Mura bhfuil an seoladh ríomhphoist sin ceart, is féidir leat é a athrú i socruithe cuntais. delete_account: Scrios cuntas + delete_account_html: Más mian leat do chuntas a scriosadh, is féidir leat leanúint ar aghaidh anseo. Iarrfar ort deimhniú. + description: + prefix_invited_by_user: Tugann @%{name} cuireadh duit páirt a ghlacadh sa fhreastalaí seo de Mastodon! + prefix_sign_up: Cláraigh ar Mastodon inniu! + suffix: Le cuntas, beidh tú in ann daoine a leanúint, nuashonruithe a phostáil agus teachtaireachtaí a mhalartú le húsáideoirí ó aon fhreastalaí Mastodon agus níos mó! + didnt_get_confirmation: Nach bhfuair tú nasc deimhnithe? + dont_have_your_security_key: Nach bhfuil d'eochair shlándála agat? + forgot_password: Ar rinne tú dearmad ar do Phásfhocail? + invalid_reset_password_token: Tá comhartha athshocraithe pasfhocail neamhbhailí nó imithe in éag. Iarr ceann nua le do thoil. + link_to_otp: Cuir isteach cód dhá fhachtóir ó do ghuthán nó cód aisghabhála + link_to_webauth: Úsáid d'eochair shlándála gléas + log_in_with: Logáil isteach le login: Logáil isteach logout: Logáil Amach + migrate_account: Bog chuig cuntas eile + migrate_account_html: Más mian leat an cuntas seo a atreorú chuig ceann eile, is féidir leat é a chumrú anseo. or_log_in_with: Nó logáil isteach le + privacy_policy_agreement_html: Léigh mé agus aontaím leis an polasaí príobháideachais + progress: + confirm: Deimhnigh Ríomhphost + details: Do chuid sonraí + review: Ár léirmheas + rules: Glac le rialacha + providers: + cas: CAS + saml: SAML register: Clárú + registration_closed: Níl %{instance} ag glacadh le baill nua + resend_confirmation: Seol an nasc deimhnithe arís + reset_password: Athshocraigh pasfhocal + rules: + accept: Glac + back: Ar ais + invited_by: 'Is féidir leat páirt a ghlacadh i %{domain} a bhuíochas leis an gcuireadh a fuair tú ó:' + preamble: Socraíonn agus cuireann na modhnóirí %{domain} iad seo i bhfeidhm. + preamble_invited: Sula dtéann tú ar aghaidh, smaoinigh le do thoil ar na bunrialacha atá socraithe ag modhnóirí %{domain}. + title: Roinnt bunrialacha. + title_invited: Tá cuireadh faighte agat. security: Slándáil + set_new_password: Socraigh pasfhocal nua + setup: + email_below_hint_html: Seiceáil d'fhillteán turscair, nó iarr ceann eile. Is féidir leat do sheoladh r-phoist a cheartú má tá sé mícheart. + email_settings_hint_html: Cliceáil ar an nasc a sheol muid chugat chun %{email} a fhíorú. Beidh muid ag fanacht ar dheis anseo. + link_not_received: Nach bhfuair tú nasc? + new_confirmation_instructions_sent: Gheobhaidh tú r-phost nua leis an nasc deimhnithe i gceann cúpla bomaite! + title: Seiceáil do bhosca isteach + sign_in: + preamble_html: Logáil isteach le do dhintiúir %{domain}. Má tá do chuntas á óstáil ar fhreastalaí eile, ní bheidh tú in ann logáil isteach anseo. + title: Logáil isteach go %{domain} + sign_up: + manual_review: Téann clárúcháin ar %{domain} trí athbhreithniú láimhe ag ár modhnóirí. Chun cabhrú linn do chlárúchán a phróiseáil, scríobh beagán fút féin agus cén fáth a bhfuil cuntas uait ar %{domain}. + preamble: Le cuntas ar an bhfreastalaí Mastodon seo, beidh tú in ann aon duine eile ar an líonra a leanúint, beag beann ar an áit a bhfuil a gcuntas á óstáil. + title: Déanaimis tú a shocrú ar %{domain}. status: account_status: Stádas cuntais + confirming: Ag fanacht le deimhniú r-phoist a bheith críochnaithe. + functional: Tá do chuntas ag feidhmiú go hiomlán. + pending: Tá d’iarratas ar feitheamh athbhreithnithe ag ár bhfoireann. Seans go dtógfaidh sé seo roinnt ama. Gheobhaidh tú ríomhphost má cheadaítear d’iarratas. + redirecting_to: Tá do chuntas neamhghníomhach toisc go bhfuil sé á atreorú chuig %{acct} faoi láthair. + self_destruct: Toisc go bhfuil %{domain} ag dúnadh síos, ní bhfaighidh tú ach rochtain theoranta ar do chuntas. + view_strikes: Féach ar stailceanna san am atá caite i gcoinne do chuntais too_fast: Cuireadh an fhoirm isteach róthapa, triail arís. + use_security_key: Úsáid eochair shlándála challenge: confirm: Lean ar aghaidh + hint_html: "Leid: Ní iarrfaimid do phasfhocal ort arís go ceann uair an chloig eile." + invalid_password: Pasfhocal neamhbhailí + prompt: Deimhnigh an pasfhocal chun leanúint ar aghaidh + crypto: + errors: + invalid_key: nach eochair bhailí Ed25519 nó Curve25519 í + invalid_signature: nach síniú bailí Ed25519 é + date: + formats: + default: "%b %d, %Y" + with_month_name: "%B %d, %Y" datetime: distance_in_words: about_x_hours: "%{count}u" @@ -340,6 +1201,7 @@ ga: about_x_years: "%{count}b" almost_x_years: "%{count}b" half_a_minute: Díreach anois + less_than_x_minutes: "%{count}m" less_than_x_seconds: Díreach anois over_x_years: "%{count}b" x_days: "%{count}l" @@ -347,45 +1209,243 @@ ga: x_months: "%{count}m" x_seconds: "%{count}s" deletes: + challenge_not_passed: Ní raibh an fhaisnéis a d'iontráil tú ceart + confirm_password: Cuir isteach do phasfhocal reatha chun d'aitheantas a fhíorú + confirm_username: Cuir isteach d'ainm úsáideora chun an nós imeachta a dhearbhú proceed: Scrios cuntas + success_msg: Scriosadh do chuntas go rathúil + warning: + before: 'Sula dtéann tú ar aghaidh, léigh na nótaí seo go cúramach le do thoil:' + caches: Seans go seasfaidh inneachar atá i dtaisce ag freastalaithe eile + data_removal: Bainfear do phostálacha agus sonraí eile go buan + email_change_html: Is féidir leat do sheoladh ríomhphoist a athrú gan do chuntas a scriosadh + email_contact_html: Mura dtagann sé fós, is féidir leat ríomhphost a chur chuig %{email} chun cabhair a fháil + email_reconfirmation_html: Mura bhfuil an ríomhphost deimhnithe á fháil agat, is féidir é a iarraidh arís + irreversible: Ní bheidh tú in ann do chuntas a aischur nó a athghníomhachtú + more_details_html: Le haghaidh tuilleadh sonraí, féach an polasaí príobháideachais. + username_available: Cuirfear d'ainm úsáideora ar fáil arís + username_unavailable: Ní bheidh d'ainm úsáideora ar fáil fós disputes: strikes: + action_taken: Gníomh déanta + appeal: Achomharc + appeal_approved: D’éirigh le hachomharc a dhéanamh ar an stailc seo agus níl sé bailí a thuilleadh + appeal_rejected: Diúltaíodh don achomharc appeal_submitted_at: Achomharc curtha isteach appealed_msg: Cuireadh isteach d'achomharc. Má ceadófar é, cuirfear ar an eolas tú. appeals: submit: Cuir achomharc isteach + approve_appeal: Achomharc a cheadú + associated_report: Tuarascáil ghaolmhar + created_at: Dátaithe + description_html: Is gníomhartha iad seo a rinneadh i gcoinne do chuntais agus rabhaidh a sheol foireann %{instance} chugat. + recipient: Seolta chuig + reject_appeal: Diúltú achomharc + status: 'Postáil # %{id}' + status_removed: Baineadh an postáil den chóras cheana féin + title: "%{action} ó %{date}" title_actions: + delete_statuses: Post a bhaint + disable: Reo cuntais + mark_statuses_as_sensitive: Postálacha a mharcáil mar íogair none: Rabhadh + sensitive: An cuntas a mharcáil mar íogair + silence: Teorainn le cuntas + suspend: Cuntas a fhionraí + your_appeal_approved: Tá d’achomharc ceadaithe your_appeal_pending: Chuir tú achomharc isteach + your_appeal_rejected: Diúltaíodh do d'achomharc + domain_validator: + invalid_domain: nach ainm fearainn bailí é + edit_profile: + basic_information: Eolas bunúsach + hint_html: "Saincheap a bhfeiceann daoine ar do phróifíl phoiblí agus in aice le do phostálacha. Is dóichí go leanfaidh daoine eile ar ais tú agus go n-idirghníomhóidh siad leat nuair a bhíonn próifíl líonta agus pictiúr próifíle agat." + other: Eile + errors: + '400': Bhí an t-iarratas a chuir tú isteach neamhbhailí nó míchumtha. + '403': Níl cead agat an leathanach seo a fheiceáil. + '404': Níl an leathanach atá uait anseo. + '406': Níl an leathanach seo ar fáil san fhormáid iarrtha. + '410': Níl an leathanach a bhí á lorg agat ann a thuilleadh. + '422': + content: Theip ar fhíorú slándála. An bhfuil tú ag cur bac ar fhianáin? + title: Theip ar fhíorú slándála + '429': An iomarca iarratas + '500': + content: Tá brón orainn, ach chuaigh rud éigin mícheart ar ár deireadh. + title: Níl an leathanach seo ceart + '503': Níorbh fhéidir an leathanach a sheirbheáil mar gheall ar theip shealadach ar an bhfreastalaí. + noscript_html: Chun feidhmchlár gréasáin Mastodon a úsáid, cumasaigh JavaScript le do thoil. Nó, bain triail as ceann de na aipeanna dúchasacha do Mastodon do d'ardán. + existing_username_validator: + not_found: níorbh fhéidir úsáideoir áitiúil a aimsiú leis an ainm úsáideora sin + not_found_multiple: níorbh fhéidir %{usernames} a aimsiú exports: archive_takeout: date: Dáta + download: Íosluchtaigh cartlann do rang + hint_html: Is féidir leat cartlann de do postálacha agus meáin uaslódáilte a iarraidh. Beidh na sonraí easpórtáilte i bhformáid ActivityPub, inléite ag aon bhogearraí comhlíontacha. Is féidir leat cartlann a iarraidh gach 7 lá. + in_progress: Do chartlann á tiomsú... + request: Iarr do chartlann size: Méid + blocks: Bac leat + bookmarks: Leabharmharcanna + csv: CSV + domain_blocks: Bloic fearainn lists: Liostaí + mutes: Balbhaíonn tú + storage: Stóráil meáin + featured_tags: + add_new: Cuir nua leis + errors: + limit: Tá uaslíon na hashtags le feiceáil agat cheana féin + hint_html: "Áirigh na haischlibeanna is tábhachtaí ar do phróifíl. Uirlis iontach chun súil a choinneáil ar do shaothair chruthaitheacha agus do thionscadail fhadtéarmacha, taispeántar haischlibeanna faoi thrácht in áit fheiceálach ar do phróifíl agus ceadaíonn siad rochtain thapa ar do phostálacha féin." filters: contexts: + account: Próifílí home: Baile agus liostaí notifications: Fógraí + public: Amlínte poiblí thread: Comhráite edit: add_keyword: Cruthaigh eochairfhocal keywords: Eochairfhocal + statuses: Poist aonair + statuses_hint_html: Baineann an scagaire seo le postálacha aonair a roghnú is cuma má mheaitseálann siad leis na heochairfhocail thíos. Déan postálacha a athbhreithniú nó a bhaint den scagaire. + title: Cuir an scagaire in eagar + errors: + deprecated_api_multiple_keywords: Ní féidir na paraiméadair seo a athrú ón bhfeidhmchlár seo toisc go mbaineann siad le níos mó ná eochairfhocal scagaire amháin. Úsáid feidhmchlár níos déanaí nó an comhéadan gréasáin. + invalid_context: Níor soláthraíodh aon cheann nó comhthéacs neamhbhailí index: + contexts: Scagairí i %{contexts} delete: Scrios empty: Níl aon scagairí agat. + expires_in: In éag i %{distance} + expires_on: Rachaidh sé in éag ar %{date} + keywords: + few: "%{count} eochairfhocal" + many: "%{count} eochairfhocal" + one: "%{count} eochairfhocal" + other: "%{count} eochairfhocal" + two: "%{count} eochairfhocal" + statuses: + few: "%{count} postáil" + many: "%{count} postáil" + one: "%{count} postáil" + other: "%{count} postáil" + two: "%{count} postáil" + statuses_long: + few: "%{count} postáil aonair folaithe" + many: "%{count} postáil aonair folaithe" + one: "%{count} postáil aonair i bhfolach" + other: "%{count} postáil aonair folaithe" + two: "%{count} postáil aonair folaithe" title: Scagairí + new: + save: Sábháil scagaire nua + title: Cuir scagaire nua leis + statuses: + back_to_filter: Ar ais go dtí an scagaire + batch: + remove: Bain as an scagaire + index: + hint: Baineann an scagaire seo le poist aonair a roghnú beag beann ar chritéir eile. Is féidir leat tuilleadh postálacha a chur leis an scagaire seo ón gcomhéadan gréasáin. + title: Postálacha scagtha generic: + all: Gach + all_items_on_page_selected_html: + few: Tá gach %{count} mír ar an leathanach seo roghnaithe. + many: Tá gach %{count} mír ar an leathanach seo roghnaithe. + one: Tá %{count} mír ar an leathanach seo roghnaithe. + other: Tá gach %{count} mír ar an leathanach seo roghnaithe. + two: Tá gach %{count} mír ar an leathanach seo roghnaithe. + all_matching_items_selected_html: + few: Tá gach %{count} mír a thagann le do chuardach roghnaithe. + many: Tá gach %{count} mír a thagann le do chuardach roghnaithe. + one: Tá %{count} mír a thagann le do chuardach roghnaithe. + other: Tá gach %{count} mír a thagann le do chuardach roghnaithe. + two: Tá gach %{count} mír a thagann le do chuardach roghnaithe. + cancel: Cealaigh + changes_saved_msg: Sábháladh na hathruithe! + confirm: Deimhnigh copy: Cóipeáil delete: Scrios + deselect: Díroghnaigh go léir + none: Dada + order_by: Ordú le + save_changes: Sabháil na hathruithe + select_all_matching_items: + few: Roghnaigh gach %{count} mír a thagann le do chuardach. + many: Roghnaigh gach %{count} mír a thagann le do chuardach. + one: Roghnaigh %{count} mír a thagann le do chuardach. + other: Roghnaigh gach %{count} mír a thagann le do chuardach. + two: Roghnaigh gach %{count} mír a thagann le do chuardach. today: inniu + validation_errors: + few: Níl rud éigin ceart go leor fós! Déan athbhreithniú ar %{count} earráid thíos + many: Níl rud éigin ceart go leor fós! Déan athbhreithniú ar %{count} earráid thíos + one: Níl rud éigin ceart go leor fós! Déan athbhreithniú ar an earráid thíos + other: Níl rud éigin ceart go leor fós! Déan athbhreithniú ar %{count} earráid thíos + two: Níl rud éigin ceart go leor fós! Déan athbhreithniú ar %{count} earráid thíos imports: + errors: + empty: Comhad CSV folamh + incompatible_type: Neamh-chomhoiriúnach leis an gcineál iompórtála roghnaithe + invalid_csv_file: 'Comhad CSV neamhbhailí. Earráid: %{error}' + over_rows_processing_limit: níos mó ná %{count} sraitheanna + too_large: Tá an comhad ró-mhór + failures: Teipeanna + imported: Iompórtáilte + mismatched_types_warning: Is cosúil gur roghnaigh tú an cineál mícheart don iompórtáil seo, seiceáil arís le do thoil. modes: merge: Cumaisc + merge_long: Coinnigh taifid atá ann cheana féin agus cuir cinn nua leis overwrite: Forscríobh + overwrite_long: Cuir na cinn nua in ionad na dtaifead reatha + overwrite_preambles: + blocking_html: Tá tú ar tí do liosta bloc a chur in ionad suas le %{total_items} cuntas ó %{filename}. + bookmarks_html: Tá tú ar tí do leabharmharcanna a chur in ionad suas le %{total_items} postáil ó %{filename}. + domain_blocking_html: Tá tú ar tí do liosta bloc fearainn a chur in ionad suas le %{total_items} fearainn ó %{filename}. + following_html: Tá tú ar tí leanúint suas go dtí %{total_items} cuntas ó %{filename} agus stop a leanúint aon duine eile. + lists_html: Tá tú ar tí do liostaí a chur in ionad inneachair %{filename}. Cuirfear suas le %{total_items} cuntas le liostaí nua. + muting_html: Tá tú ar tí do liosta cuntas balbhaithe a chur in ionad suas le %{total_items} cuntas ó %{filename}. + preambles: + blocking_html: Tá tú ar tí bloc suas le %{total_items} cuntas ó %{filename}. + bookmarks_html: Tá tú ar tí %{total_items} postáil ó %{filename} a chur le do leabharmharcanna. + domain_blocking_html: Tá tú ar tí bloc suas le %{total_items} fearainn ó %{filename}. + following_html: Tá tú ar tí leanúint suas go dtí %{total_items} cuntas ó %{filename}. + lists_html: Tá tú ar tí %{total_items} cuntas ó %{filename} a chur le do liostaí. Cruthófar liostaí nua mura bhfuil aon liosta le cur leis. + muting_html: Tá tú ar tí balbhú suas le %{total_items} cuntas ó %{filename}. + preface: Is féidir leat sonraí a d’easpórtáil tú a allmhairiú ó fhreastalaí eile, mar shampla liosta de na daoine a bhfuil tú ag leanúint nó ag cur bac orthu. + recent_imports: Allmhairí le déanaí + states: + finished: Críochnaithe + in_progress: Ar siúl + scheduled: Sceidealta + unconfirmed: Neamhdhearbhaithe + status: Stádas + success: Uaslódáladh do shonraí go rathúil agus próiseálfar iad in am trátha + time_started: Thosaigh ag + titles: + blocking: Cuntais bhlocáilte á n-iompórtáil + bookmarks: Leabharmharcanna á n-iompórtáil + domain_blocking: Fearainn blocáilte á n-iompórtáil + following: Cuntais leanta á n-iompórtáil + lists: Liostaí á n-iompórtáil + muting: Cuntais bhalbhaithe á n-iompórtáil + type: Cineál iompórtála + type_groups: + constructive: Seo a leanas & Leabharmharcanna + destructive: Bloic agus balbhaigh types: + blocking: Liosta blocála bookmarks: Leabharmharcanna + domain_blocking: Liosta blocála fearainn + following: Liosta ina dhiaidh sin + lists: Liostaí + muting: Liosta muting upload: Uaslódáil invites: + delete: Díghníomhachtaigh expired: As feidhm expires_in: '1800': 30 nóiméid @@ -395,43 +1455,230 @@ ga: '604800': Seachtain amháin '86400': Lá amháin expires_in_prompt: In am ar bith + generate: Gin nasc cuireadh + invalid: Níl an cuireadh seo bailí + invited_by: 'Fuair ​​tú cuireadh ó:' + max_uses: + few: Úsáideann %{count} + many: Úsáideann %{count} + one: 1 úsáid + other: Úsáideann %{count} + two: Úsáideann %{count} + max_uses_prompt: Gan teorainn + prompt: Gin agus roinn naisc le daoine eile chun rochtain a dheonú ar an bhfreastalaí seo + table: + expires_at: In éag + uses: Úsáidí + title: Tabhair cuireadh do dhaoine + lists: + errors: + limit: Tá uaslíon na liostaí sroichte agat login_activities: authentication_methods: + otp: app fíordheimhnithe dhá-fachtóir password: pasfhocal + sign_in_token: cód slándála ríomhphoist webauthn: eochracha slándála + description_html: Má fheiceann tú gníomhaíocht nach n-aithníonn tú, smaoinigh ar do phasfhocal a athrú agus fíordheimhniú dhá fhachtóir a chumasú. + empty: Níl aon stair fíordheimhnithe ar fáil + failed_sign_in_html: Theip ar iarracht síniú isteach le %{method} ó %{ip} (%{browser}) + successful_sign_in_html: D'éirigh le síniú isteach le %{method} ó %{ip} (%{browser}) + title: Stair fíordheimhnithe + mail_subscriptions: + unsubscribe: + action: Sea, díliostáil + complete: Gan liostáil + confirmation_html: An bhfuil tú cinnte gur mhaith leat díliostáil ó %{type} a fháil do Mastodon ar %{domain} chuig do ríomhphost ag %{email}? Is féidir leat liostáil arís i gcónaí ó do socruithe fógra ríomhphoist. + emails: + notification_emails: + favourite: r-phoist fógra is fearr leat + follow: r-phoist fógra a leanúint + follow_request: r-phoist iarratais a leanúint + mention: trácht ar r-phoist fógra + reblog: r-phoist fógra a threisiú + resubscribe_html: Má dhíliostáil tú de dhearmad, is féidir leat liostáil arís ó do socruithe fógra ríomhphoist. + success_html: Ní bhfaighidh tú %{type} le haghaidh Mastodon ar %{domain} chuig do ríomhphost ag %{email} a thuilleadh. + title: Díliostáil + media_attachments: + validations: + images_and_video: Ní féidir físeán a cheangal le postáil a bhfuil íomhánna ann cheana féin + not_ready: Ní féidir comhaid nach bhfuil próiseáil críochnaithe acu a cheangal. Bain triail eile as i gceann nóiméad! + too_many: Ní féidir níos mó ná 4 chomhad a cheangal + migrations: + acct: Bogtha go + cancel: Cealaigh atreorú + cancel_explanation: Má chuirtear an t-atreorú ar ceal, déanfar do chuntas reatha a athghníomhú, ach ní thabharfaidh sé seo leantóirí a aistríodh chuig an gcuntas sin ar ais. + cancelled_msg: D'éirigh leis an atreorú a chealú. + errors: + already_moved: an cuntas céanna ar bhog tú chuige cheana + missing_also_known_as: nach ailias den chuntas seo é + move_to_self: ní féidir é a bheith ina chuntas reatha + not_found: níorbh fhéidir a fháil + on_cooldown: Tá tú ar fuarú + followers_count: Leantóirí ag am aistrithe + incoming_migrations: Ag bogadh ó chuntas eile + incoming_migrations_html: Chun bogadh ó chuntas eile go dtí an ceann seo, ní mór duit ailias cuntais a chruthú ar dtús. + moved_msg: Tá do chuntas á atreorú chuig %{acct} anois agus tá do leantóirí á bhogadh anonn. + not_redirecting: Níl do chuntas á atreorú chuig aon chuntas eile faoi láthair. + on_cooldown: D'aistrigh tú do chuntas le déanaí. Beidh an fheidhm seo ar fáil arís i gceann %{count} lá. + past_migrations: Imirce san am a chuaigh thart + proceed_with_move: Bog leantóirí + redirected_msg: Tá do chuntas á atreorú chuig %{acct} anois. + redirecting_to: Tá do chuntas á atreorú chuig %{acct}. + set_redirect: Socraigh atreorú + warning: + backreference_required: Ní mór an cuntas nua a chumrú ar dtús chun cúltagairt a dhéanamh don cheann seo + before: 'Sula dtéann tú ar aghaidh, léigh na nótaí seo go cúramach le do thoil:' + cooldown: Tar éis bogadh tá tréimhse feithimh ann nach mbeidh tú in ann bogadh arís + disabled_account: Ní bheidh do chuntas reatha inúsáidte go hiomlán ina dhiaidh sin. Mar sin féin, beidh rochtain agat ar onnmhairiú sonraí chomh maith le hathghníomhú. + followers: Bogfaidh an gníomh seo gach leantóir ón gcuntas reatha go dtí an cuntas nua + only_redirect_html: Nó, ní féidir leat ach atreorú a chur suas ar do phróifíl. + other_data: Ní bhogfar aon sonraí eile go huathoibríoch + redirect: Déanfar próifíl do chuntais reatha a nuashonrú le fógra atreoraithe agus fágfar as an áireamh é ó chuardaigh + moderation: + title: Measarthacht + move_handler: + carry_blocks_over_text: Bhog an t-úsáideoir seo ó %{acct}, rud a chuir tú bac air. + carry_mutes_over_text: Bhog an t-úsáideoir seo ó %{acct}, rud a bhalbhaigh tú. + copy_account_note_text: 'Bhog an úsáideoir seo ó %{acct}, seo do nótaí roimhe seo fúthu:' + navigation: + toggle_menu: Scoránaigh roghchlár notification_mailer: admin: report: subject: Chuir %{name} tuairisc isteach + sign_up: + subject: Chláraigh %{name} + favourite: + body: 'B''fhearr le %{name} do phostáil:' + subject: B'fhearr le %{name} do phostáil + title: Nua is fearr leat follow: body: Tá %{name} do do leanúint anois! subject: Tá %{name} do do leanúint anois title: Leantóirí nua + follow_request: + action: Bainistigh iarratais leantacha + body: D'iarr %{name} tú a leanúint + subject: 'Leantóir ar feitheamh: %{name}' + title: Iarratas leantach nua mention: action: Freagair + body: 'Luaigh %{name} thú i:' + subject: Luaigh %{name} thú + title: Lua nua + poll: + subject: Tháinig deireadh le vótaíocht le %{name} reblog: + body: 'Treisíodh do phostáil le %{name}:' subject: Mhol %{name} do phostáil title: Moladh nua + status: + subject: Tá %{name} díreach postáilte + update: + subject: Chuir %{name} postáil in eagar + notifications: + administration_emails: Fógraí r-phoist admin + email_events: Imeachtaí le haghaidh fógraí ríomhphoist + email_events_hint: 'Roghnaigh imeachtaí ar mhaith leat fógraí a fháil ina leith:' + number: + human: + decimal_units: + format: "%n%u" + units: + billion: B + million: M + quadrillion: Q + thousand: K + trillion: T otp_authentication: + code_hint: Cuir isteach an cód ginte ag d'aip fíordheimhnitheora le deimhniú + description_html: Má chumasaíonn tú fíordheimhniú dhá fhachtóir ag baint úsáide as aip fíordheimhneora, beidh ort do ghuthán a bheith i seilbh logáil isteach, rud a ghinfidh comharthaí chun tú a chur isteach. enable: Cumasaigh + instructions_html: "Scan an cód QR seo isteach i Google Authenticator nó aip eile TOTP ar do ghuthán. As seo amach, ginfidh an aip sin comharthaí a chaithfidh tú a chur isteach agus tú ag logáil isteach." + manual_instructions: 'Mura féidir leat an cód QR a scanadh agus más gá duit é a chur isteach de láimh, seo an rún gnáth-théacs:' + setup: Socraigh suas + wrong_code: Bhí an cód a iontráladh neamhbhailí! An bhfuil am freastalaí agus am gléis ceart? pagination: newer: Níos nuaí next: An céad eile older: Níos sine prev: Ceann roimhe seo + truncate: "…" + polls: + errors: + already_voted: Tá tú tar éis vótáil ar an vótaíocht seo cheana féin + duplicate_options: go bhfuil míreanna dúblacha + duration_too_long: rófhada amach anseo + duration_too_short: ró-luath + expired: Tá deireadh leis an vótaíocht cheana féin + invalid_choice: Níl an rogha vótála roghnaithe ann + over_character_limit: ní féidir leis a bheith níos faide ná %{max} carachtar an ceann + self_vote: Ní féidir leat vótáil i do phobalbhreith féin + too_few_options: caithfidh níos mó ná mír amháin a bheith ann + too_many_options: ní féidir níos mó ná %{max} mír a bheith ann preferences: other: Eile + posting_defaults: Réamhshocruithe á bpostáil + public_timelines: Amlínte poiblí + privacy: + hint_html: "Saincheap conas is mian leat do phróifíl agus do phostálacha a fháil. Is féidir le gnéithe éagsúla i Mastodon cabhrú leat teacht ar lucht féachana níos leithne nuair atá tú cumasaithe. Tóg nóiméad chun athbhreithniú a dhéanamh ar na socruithe seo chun a chinntiú go n-oireann siad do do chás úsáide." + privacy: Príobháideacht + privacy_hint_html: Rialú ar an méid is mian leat a nochtadh ar mhaithe le daoine eile. Aimsíonn daoine próifílí suimiúla agus aipeanna fionnuara trí na haipeanna seo a leanas a bhrabhsáil agus a fheiceáil cé na haipeanna a bpostálann siad, ach b’fhéidir gurbh fhearr leat é a choinneáil faoi cheilt. + reach: Shroich + reach_hint_html: Smacht a fháil ar cé acu is mian leat a fháil amach agus daoine nua a leanúint. Ar mhaith leat do phostálacha a thaispeáint ar an scáileán Explore? Ar mhaith leat go bhfeicfeadh daoine eile tú sna moltaí a leanann siad? Ar mhaith leat glacadh le gach leantóir nua go huathoibríoch, nó smacht gráinneach a bheith agat ar gach leantóir? + search: Cuardach + search_hint_html: Rialú conas ba mhaith leat a fháil. Ar mhaith leat go bhfaighidh daoine tú tríd an rud a chuir tú suas go poiblí faoi? Ar mhaith leat go bhfaighidh daoine lasmuigh de Mastodon do phróifíl agus iad ag cuardach an ghréasáin? Tabhair faoi deara le do thoil nach féidir eisiamh iomlán ó gach inneall cuardaigh a chinntiú mar fhaisnéis don phobal. + title: Príobháideacht agus teacht + privacy_policy: + title: Beartas Príobháideachais + reactions: + errors: + limit_reached: Teorainn frithghníomhartha éagsúla bainte amach + unrecognized_emoji: ní emoji aitheanta é + redirects: + prompt: Má tá muinín agat as an nasc seo, cliceáil air chun leanúint ar aghaidh. + title: Tá tú ag fágáil %{instance}. relationships: + activity: Gníomhaíocht chuntais + confirm_follow_selected_followers: An bhfuil tú cinnte gur mhaith leat na leantóirí roghnaithe a leanúint? + confirm_remove_selected_followers: An bhfuil tú cinnte gur mhaith leat na leantóirí roghnaithe a bhaint? + confirm_remove_selected_follows: An bhfuil tú cinnte gur mhaith leat na nithe seo a leanas roghnaithe a bhaint? + dormant: Díomhaoin + follow_failure: Níorbh fhéidir cuid de na cuntais roghnaithe a leanúint. follow_selected_followers: Lean leantóirí roghnaithe followers: Leantóirí following: Ag leanúint + invited: Cuireadh + last_active: Gníomhach seo caite + most_recent: Is déanaí + moved: Ar athraíodh a ionad + mutual: Frithpháirteach primary: Príomha + relationship: Gaol + remove_selected_domains: Bain gach leantóir ó na fearainn roghnaithe remove_selected_followers: Bain leantóirí roghnaithe remove_selected_follows: Dí-lean úsáideoirí roghnaithe status: Stádas cuntais + remote_follow: + missing_resource: Níorbh fhéidir an URL atreoraithe riachtanach do do chuntas a aimsiú + reports: + errors: + invalid_rules: ní thagraíonn sé do rialacha bailí rss: content_warning: 'Rabhadh ábhair:' + descriptions: + account: Postálacha poiblí ó @%{acct} + tag: 'Postálacha poiblí clibáilte # %{hashtag}' + scheduled_statuses: + over_daily_limit: Tá an teorainn de %{limit} postáil sceidealaithe sáraithe agat don lá atá inniu ann + over_total_limit: Tá an teorainn de %{limit} postáil sceidealaithe sáraithe agat + too_soon: Caithfidh an dáta sceidealta a bheith sa todhchaí + self_destruct: + lead_html: Ar an drochuair, tá %{domain} ag dúnadh síos go buan. Má bhí cuntas agat ann, ní bheidh tú in ann leanúint ar aghaidh á úsáid, ach is féidir leat cúltaca de do shonraí a iarraidh fós. + title: Tá an freastalaí seo ag dúnadh sessions: + activity: An ghníomhaíocht dheireanach browser: Brabhsálaí browsers: alipay: Alipay @@ -441,41 +1688,162 @@ ga: electron: Electron firefox: Firefox generic: Brabhsálaí anaithnid + huawei_browser: Brabhsálaí Huawei + ie: Internet Explorer + micro_messenger: Micreascannán + nokia: Nokia s40 Ovi Brabhsálaí + opera: Opera + otter: Dobharchú + phantom_js: PhantomJS + qq: Brabhsálaí QQ + safari: Safari + uc_browser: Brabhsálaí UC + unknown_browser: Brabhsálaí Anaithnid + weibo: Weibo + current_session: Seisiún reatha + date: Dáta + description: "%{browser} ar %{platform}" + explanation: Seo iad na brabhsálaithe gréasáin atá logáilte isteach i do chuntas Mastodon faoi láthair. + ip: IP platforms: + adobe_air: Adobe Air android: Android blackberry: BlackBerry chrome_os: ChromeOS firefox_os: Firefox OS ios: iOS + kai_os: KaiOS linux: Linux mac: macOS + unknown_platform: Ardán Anaithnid windows: Windows windows_mobile: Windows Mobile windows_phone: Windows Phone + revoke: Aisghair + revoke_success: Seisiún aisghairthe go rathúil title: Seisiúin + view_authentication_history: Féach ar stair fíordheimhnithe do chuntais settings: account: Cuntas account_settings: Socruithe cuntais + aliases: Ailiasanna cuntais appearance: Cuma + authorized_apps: Aipeanna údaraithe back: Ar ais go Mastodon + delete: Scriosadh cuntais development: Forbairt edit_profile: Cuir an phróifíl in eagar + export: Easpórtáil sonraí + featured_tags: Haischlib faoi thrácht import: Iompórtáil + import_and_export: Iompórtáil agus easpórtáil + migrate: Imirce cuntais + notifications: Fógraí ríomhphoist preferences: Sainroghanna pearsanta profile: Próifíl + relationships: Leantóirí agus leanúna + severed_relationships: Caidrimh dhearfa + statuses_cleanup: Uathscriosadh postála + strikes: Stailceanna measarthachta + two_factor_authentication: Údar dhá-fhachtóir webauthn_authentication: Eochracha slándála + severed_relationships: + download: Íoslódáil (%{count}) + event_type: + account_suspension: Fionraí cuntais (%{target_name}) + domain_block: Freastalaí ar fionraí (%{target_name}) + user_domain_block: Chuir tú bac ar %{target_name} + lost_followers: Leanúna caillte + lost_follows: Seo a leanas caillte + preamble: Seans go gcaillfidh tú seo a leanas agus a leantóirí nuair a bhacálann tú fearann ​​nó nuair a shocraíonn do mhodhnóirí cianfhreastalaí a chur ar fionraí. Nuair a tharlaíonn sé sin, beidh tú in ann liostaí de chaidreamh deighilte a íoslódáil, lena n-iniúchadh agus b'fhéidir iompórtáil ar fhreastalaí eile. + purged: Glanadh faisnéis faoin bhfreastalaí seo ag riarthóirí do fhreastalaí. + type: Imeacht statuses: + attached: + audio: + few: "%{count} fuaime" + many: "%{count} fuaime" + one: "%{count} fuaime" + other: "%{count} fuaime" + two: "%{count} fuaime" + description: 'Ceangailte: %{attached}' + image: + few: "%{count} híomhánna" + many: "%{count} híomhánna" + one: "%{count} íomhá" + other: "%{count} híomhánna" + two: "%{count} híomhánna" + video: + few: "%{count} físeáin" + many: "%{count} físeáin" + one: "%{count} físeán" + other: "%{count} físeáin" + two: "%{count} físeáin" boosted_from_html: Molta ó %{acct_link} content_warning: 'Rabhadh ábhair: %{warning}' + default_language: Mar an gcéanna le teanga an chomhéadain + disallowed_hashtags: + few: 'bhí na Haischlib dícheadaithe: %{tags}' + many: 'bhí na Haischlib dícheadaithe: %{tags}' + one: 'bhí haischlib dícheadaithe: %{tags}' + other: 'bhí na Haischlib dícheadaithe: %{tags}' + two: 'bhí na Haischlib dícheadaithe: %{tags}' + edited_at_html: "%{date} curtha in eagar" + errors: + in_reply_not_found: Is cosúil nach ann don phostáil a bhfuil tú ag iarraidh freagra a thabhairt air. + open_in_web: Oscail i ngréasán + over_character_limit: teorainn carachtar %{max} sáraithe + pin_errors: + direct: Ní féidir postálacha nach bhfuil le feiceáil ach ag úsáideoirí luaite a phinnáil + limit: Tá uaslíon na bpostálacha pinn agat cheana féin + ownership: Ní féidir postáil duine éigin eile a phionnáil + reblog: Ní féidir treisiú a phinnáil poll: + total_people: + few: "%{count} daoine" + many: "%{count} daoine" + one: "%{count} duine" + other: "%{count} daoine" + two: "%{count} daoine" + total_votes: + few: "%{count} vótaí" + many: "%{count} vótaí" + one: "%{count} vóta" + other: "%{count} vótaí" + two: "%{count} vótaí" vote: Vótáil show_more: Taispeáin níos mó show_thread: Taispeáin snáithe + title: '%{name}: "%{quote}"' visibilities: + direct: Díreach private: Leantóirí amháin private_long: Taispeáin do leantóirí amháin + public: Poiblí + public_long: Is féidir le gach duine a fheiceáil + unlisted: Neamhliostaithe + unlisted_long: Is féidir le gach duine a fheiceáil, ach nach bhfuil liostaithe ar amlínte poiblí statuses_cleanup: + enabled: Scrios seanphostálacha go huathoibríoch + enabled_hint: Scriostar do phostálacha go huathoibríoch nuair a shroicheann siad tairseach aoise sonraithe, ach amháin má thagann siad le ceann de na heisceachtaí thíos + exceptions: Eisceachtaí + explanation: Toisc gur oibríocht chostasach é postálacha a scriosadh, déantar é seo go mall le himeacht ama nuair nach mbíonn an freastalaí gnóthach ar bhealach eile. Ar an ábhar sin, d’fhéadfadh sé go scriosfar do phostálacha tamall tar éis dóibh an tairseach aoise a bhaint amach. ignore_favs: Tabhair neamhaird ar toghanna + ignore_reblogs: Déan neamhaird de boosts + interaction_exceptions: Eisceachtaí bunaithe ar idirghníomhaíochtaí + interaction_exceptions_explanation: Tabhair faoi deara nach bhfuil aon ráthaíocht go scriosfar postálacha má théann siad faoi bhun na tairsí is ansa leat nó an teanndáileog tar éis dóibh dul thar iad uair amháin. + keep_direct: Coinnigh teachtaireachtaí díreacha + keep_direct_hint: Ní scriosann sé aon cheann de do theachtaireachtaí díreacha + keep_media: Coinnigh postálacha le ceangaltáin meán + keep_media_hint: Ní scriosann sé aon cheann de do phostálacha a bhfuil ceangaltáin meán acu + keep_pinned: Coinnigh postálacha pinn + keep_pinned_hint: Ní scriosann sé aon cheann de do phostálacha pinn + keep_polls: Coinnigh pobalbhreith + keep_polls_hint: Ní scriosann sé aon cheann de do vótaíochtaí + keep_self_bookmark: Coinnigh postálacha leabharmharcáilte agat + keep_self_bookmark_hint: Ní scriosann sé do phostálacha féin má tá leabharmharcáilte agat + keep_self_fav: Coinnigh na poist a thaitin leat + keep_self_fav_hint: Ní scriosann sé do phostálacha féin más fearr leat iad min_age: '1209600': Coicís '15778476': 6 mhí @@ -485,20 +1853,182 @@ ga: '604800': Seachtain amháin '63113904': 2 bhliain '7889238': 3 mhí + min_age_label: Tairseach aoise + min_favs: Coinnigh na poist is fearr leat ar a laghad + min_favs_hint: Ní scriosann sé aon cheann de do phostálacha a fuair ar a laghad an líon ceanán seo. Fág bán chun postálacha a scriosadh beag beann ar líon na gceanán atá acu + min_reblogs: Coinnigh postálacha treisithe ar a laghad + min_reblogs_hint: Ní scriosann sé aon cheann de do phostálacha a cuireadh leis an líon seo uaireanta ar a laghad. Fág bán chun postálacha a scriosadh beag beann ar a líon teanndáileog stream_entries: sensitive_content: Ábhar íogair + strikes: + errors: + too_late: Tá sé ró-dhéanach achomharc a dhéanamh faoin stailc seo + tags: + does_not_match_previous_name: nach meaitseálann an t-ainm roimhe seo + themes: + contrast: Mastodon (Codarsnacht ard) + default: Mastodon (Dorcha) + mastodon-light: Mastodon (Solas) + system: Uathoibríoch (úsáid téama córais) + time: + formats: + default: "%b %d, %Y, %H:%M" + month: "%b %Y" + time: "%H:%M" + with_time_zone: "%b %d, %Y, %H:%M %Z" + translation: + errors: + quota_exceeded: Sáraíodh an cuóta úsáide uile-fhreastalaí don tseirbhís aistriúcháin. + too_many_requests: Tá an iomarca iarratas ar an tseirbhís aistriúcháin le déanaí. two_factor_authentication: + add: Cuir + disable: Díchumasaigh 2FA + disabled_success: D'éirigh le fíordheimhniú dhá-fhachtóir a dhíchumasú edit: Cuir in eagar + enabled: Tá fíordheimhniú dhá fhachtóir cumasaithe + enabled_success: D'éirigh le fíordheimhniú dhá fhachtóir a chumasú + generate_recovery_codes: Gin cóid athshlánaithe + lost_recovery_codes: Ligeann cóid athshlánaithe duit rochtain a fháil ar do chuntas arís má chailleann tú do ghuthán. Má tá do chóid athshlánaithe caillte agat, is féidir leat iad a athnuachan anseo. Déanfar do sheanchóid athshlánaithe a neamhbhailíochtú. + methods: Modhanna dhá-fhachtóir + otp: Aip fíordheimhnitheora + recovery_codes: Cóid aisghabhála cúltaca + recovery_codes_regenerated: D'éirigh le hathghiniúint cóid athshlánaithe + recovery_instructions_html: Má chailleann tú rochtain ar do ghuthán riamh, is féidir leat ceann de na cóid athshlánaithe thíos a úsáid chun rochtain a fháil ar do chuntas arís. Coinnigh na cóid athshlánaithe slán. Mar shampla, is féidir leat iad a phriontáil agus iad a stóráil le doiciméid thábhachtacha eile. webauthn: Eochracha slándála user_mailer: + appeal_approved: + action: Socruithe cuntas + explanation: Ceadaíodh achomharc na stailce i gcoinne do chuntais ar %{strike_date} a chuir tú isteach ar %{appeal_date}. Tá seasamh maith ag do chuntas arís. + subject: Ceadaíodh d'achomharc ó %{date} + subtitle: Tá seasamh maith ag do chuntas arís. + title: Achomharc ceadaithe + appeal_rejected: + explanation: Diúltaíodh d'achomharc na stailce in aghaidh do chuntais ar %{strike_date} a chuir tú isteach ar %{appeal_date}. + subject: Diúltaíodh do d'achomharc ó %{date} + subtitle: Diúltaíodh do d'achomharc. + title: Diúltaíodh don achomharc + backup_ready: + explanation: D'iarr tú cúltaca iomlán de do chuntas Mastodon. + extra: Tá sé réidh le híoslódáil anois! + subject: Tá do chartlann réidh le híoslódáil + title: Tógáil cartlainne + failed_2fa: + details: 'Seo sonraí na hiarrachta síniú isteach:' + explanation: Rinne duine éigin iarracht síniú isteach ar do chuntas ach sholáthair sé fachtóir fíordheimhnithe dara neamhbhailí. + further_actions_html: Mura tusa a bhí ann, molaimid duit %{action} a dhéanamh láithreach toisc go bhféadfadh sé a bheith i gcontúirt. + subject: Teip fíordheimhnithe dara fachtóir + title: Theip ar fhíordheimhniú an dara fachtóir + suspicious_sign_in: + change_password: do phasfhocal a athrú + details: 'Seo sonraí faoin síniú isteach:' + explanation: Bhraitheamar síniú isteach ar do chuntas ó sheoladh IP nua. + further_actions_html: Mura tusa a bhí ann, molaimid duit %{action} a dhéanamh láithreach agus fíordheimhniú dhá fhachtóir a chumasú chun do chuntas a choinneáil slán. + subject: Fuarthas rochtain ar do chuntas ó sheoladh IP nua + title: Síniú isteach nua warning: appeal: Cuir achomharc isteach + appeal_description: Má chreideann tú gur earráid é seo, is féidir leat achomharc a chur isteach chuig foireann %{instance}. categories: spam: Turscar + violation: Sáraíonn ábhar na treoirlínte pobail seo a leanas + explanation: + delete_statuses: Fuarthas amach gur sháraigh roinnt de do chuid postálacha treoirlínte pobail amháin nó níos mó agus bhain modhnóirí %{instance} iad ina dhiaidh sin. + disable: Ní féidir leat do chuntas a úsáid a thuilleadh, ach fanann do phróifíl agus sonraí eile slán. Is féidir leat cúltaca de do shonraí a iarraidh, socruithe cuntais a athrú nó do chuntas a scriosadh. + mark_statuses_as_sensitive: Tá cuid de do chuid postálacha marcáilte mar íogair ag modhnóirí %{instance}. Ciallaíonn sé seo go mbeidh ar dhaoine na meáin a thapáil sna poist sula dtaispeánfar réamhamharc. Is féidir leat na meáin a mharcáil mar íogair tú féin agus tú ag postáil amach anseo. + sensitive: As seo amach, beidh gach do chomhaid meán uaslódáilte a mharcáil mar íogair agus i bhfolach taobh thiar de rabhadh cliceáil-trí. + silence: Is féidir leat do chuntas a úsáid go fóill ach ní fheicfidh ach na daoine atá ag leanúint ort cheana féin do phostálacha ar an bhfreastalaí seo, agus seans go mbeidh tú eisiata ó ghnéithe éagsúla fionnachtana. Féadfaidh daoine eile tú a leanúint de láimh, áfach. + suspend: Ní féidir leat do chuntas a úsáid a thuilleadh, agus níl rochtain ar do phróifíl ná ar shonraí eile a thuilleadh. Is féidir leat logáil isteach fós chun cúltaca de do shonraí a iarraidh go dtí go mbaintear na sonraí go hiomlán i gceann thart ar 30 lá, ach coinneoimid roinnt sonraí bunúsacha chun cosc ​​a chur ort an fionraí a sheachaint. reason: 'Fáth:' + statuses: 'Postálacha a luadh:' subject: + delete_statuses: Baineadh do phostálacha ar %{acct} + disable: Tá do chuntas %{acct} reoite + mark_statuses_as_sensitive: Marcáladh do phostálacha ar %{acct} mar íogair none: Rabhadh do %{acct} + sensitive: Marcálfar do phostálacha ar %{acct} mar íogair as seo amach + silence: Tá do chuntas %{acct} teoranta + suspend: Tá do chuntas %{acct} curtha ar fionraí title: + delete_statuses: Baineadh postálacha + disable: Cuntas reoite + mark_statuses_as_sensitive: Postálacha marcáilte mar íogair none: Rabhadh + sensitive: Cuntas marcáilte mar íogair + silence: Cuntas teoranta + suspend: Cuntas ar fionraí + welcome: + apps_android_action: Faigh é ar Google Play + apps_ios_action: Íoslódáil ar an App Store + apps_step: Íoslódáil ár n-aipanna oifigiúla. + apps_title: Aipeanna Mastodon + checklist_subtitle: 'Cuirimis tús leat ar an teorainn shóisialta nua seo:' + checklist_title: Seicliosta Fáilte + edit_profile_action: Pearsanú + edit_profile_step: Cuir le d'idirghníomhaíochtaí trí phróifíl chuimsitheach a bheith agat. + edit_profile_title: Déan do phróifíl a phearsantú + explanation: Seo roinnt leideanna chun tú a chur ar bun + feature_action: Foghlaim níos mó + feature_audience: Soláthraíonn Mastodon deis uathúil duit do lucht féachana a bhainistiú gan fir lár. Ligeann Mastodon a imlonnaítear ar do bhonneagar féin duit leanúint agus leanúint ó aon fhreastalaí Mastodon eile ar líne agus níl sé faoi smacht aon duine ach mise. + feature_audience_title: Tóg do lucht féachana faoi rún + feature_control: Is fearr a fhios agat cad ba mhaith leat a fheiceáil ar do bheathú baile. Gan algartam nó fógraí chun do chuid ama a chur amú. Lean aon duine ar fud aon fhreastalaí Mastodon ó chuntas amháin agus faigh a gcuid post in ord croineolaíoch, agus déan do chúinne den idirlíon beagán níos mó cosúil leatsa. + feature_control_title: Coinnigh smacht ar d’amlíne féin + feature_creativity: Tacaíonn Mastodon le postálacha fuaime, físe agus pictiúr, tuairiscí inrochtaineachta, pobalbhreitheanna, rabhaidh inneachair, avatars beoite, emojis saincheaptha, rialú barr mionsamhlacha, agus níos mó, chun cabhrú leat tú féin a chur in iúl ar líne. Cibé an bhfuil do chuid ealaíne, do cheol nó do phodchraoladh á fhoilsiú agat, tá Mastodon ann duit. + feature_creativity_title: Cruthaitheacht gan sárú + feature_moderation: Cuireann Mastodon cinnteoireacht ar ais i do lámha. Cruthaíonn gach freastalaí a rialacha agus a rialacháin féin, a chuirtear i bhfeidhm go háitiúil agus nach bhfuil ó bharr anuas cosúil le meáin shóisialta chorparáideacha, rud a fhágann gurb é an ceann is solúbtha é chun freagairt do riachtanais grúpaí éagsúla daoine. Bí ar fhreastalaí leis na rialacha a n-aontaíonn tú leo, nó do chuid féin a óstáil. + feature_moderation_title: Ag maolú ar an mbealach ar cheart dó a bheith + follow_action: Lean + follow_step: Is éard atá i gceist le daoine suimiúla a leanúint ná Mastodon. + follow_title: Cuir do chuid fotha baile in oiriúint duit féin + follows_subtitle: Lean cuntais aitheanta + follows_title: Cé a leanúint + follows_view_more: Féach ar níos mó daoine a leanúint + hashtags_recent_count: + few: "%{people} daoine le 2 lá anuas" + many: "%{people} daoine le 2 lá anuas" + one: "%{people} duine le 2 lá anuas" + other: "%{people} daoine le 2 lá anuas" + two: "%{people} daoine le 2 lá anuas" + hashtags_subtitle: Déan iniúchadh ar a bhfuil ag dul chun cinn le 2 lá anuas + hashtags_title: Haischlib treochta + hashtags_view_more: Féach ar níos mó Haischlib treochta + post_action: Cum + post_step: Abair hello leis an domhan le téacs, grianghraif, físeáin, nó pobalbhreith. + post_title: Déan do chéad phostáil + share_action: Comhroinn + share_step: Cuir in iúl do do chairde conas tú a aimsiú ar Mastodon. + share_title: Roinn do phróifíl Mastodon + sign_in_action: Sínigh isteach + subject: Fáilte go Mastodon + title: Fáilte ar bord, %{name}! + users: + follow_limit_reached: Ní féidir leat níos mó ná %{limit} duine a leanúint + go_to_sso_account_settings: Téigh chuig socruithe cuntais do sholáthraí aitheantais + invalid_otp_token: Cód dhá-fhachtóir neamhbhailí + otp_lost_help_html: Má chaill tú rochtain ar an dá cheann, is féidir leat dul i dteagmháil le %{email} + rate_limited: An iomarca iarrachtaí fíordheimhnithe, bain triail eile as ar ball. + seamless_external_login: Tá tú logáilte isteach trí sheirbhís sheachtrach, mar sin níl socruithe pasfhocail agus ríomhphoist ar fáil. + signed_in_as: 'Sínithe isteach mar:' + verification: + extra_instructions_html: Leid: Is féidir an nasc ar do shuíomh Gréasáin a bheith dofheicthe. Is í an chuid thábhachtach ná rel="me" a chuireann cosc ​​ar phearsanú ar shuímh Ghréasáin a bhfuil inneachar a ghintear leis an úsáideoir. Is féidir leat fiú clib nasc a úsáid i gceanntásc an leathanaigh in ionad a, ach caithfidh an HTML a bheith inrochtana gan JavaScript a chur i gcrích. + here_is_how: Seo é an chaoi + hint_html: "Is do chách é d'aitheantas a fhíorú ar Mastodon. Bunaithe ar chaighdeáin oscailte gréasáin, saor in aisce anois agus go deo. Níl uait ach láithreán gréasáin pearsanta a aithníonn daoine thú. Nuair a nascann tú leis an suíomh Gréasáin seo ó do phróifíl, seiceóimid go bhfuil nasc idir an suíomh Gréasáin agus do phróifíl agus taispeánfaimid táscaire amhairc air." + instructions_html: Cóipeáil agus greamaigh an cód thíos isteach i HTML do shuíomh Gréasáin. Ansin cuir seoladh do shuíomh Gréasáin isteach i gceann de na réimsí breise ar do phróifíl ón gcluaisín "Cuir próifíl in eagar" agus sábháil athruithe. + verification: Fíorú + verified_links: Do naisc fhíoraithe webauthn_credentials: + add: Cuir eochair shlándála nua leis + create: + error: Bhí fadhb ann agus d'eochair shlándála á cur leis. Arís, le d'thoil. + success: Cuireadh d'eochair shlándála leis. delete: Scrios + delete_confirmation: An bhfuil tú cinnte gur mhaith leat an eochair shlándála seo a scriosadh? + description_html: Má chumasaíonn tú fíordheimhniú eochrach slándála, beidh ort ceann de na heochracha slándála a úsáid chun logáil isteach. + destroy: + error: Bhí fadhb ann agus d'eochair shlándála á scriosadh. Arís, le d'thoil. + success: Scriosadh d'eochair shlándála go rathúil. + invalid_credential: Eochair shlándála neamhbhailí + nickname_hint: Cuir isteach leasainm d'eochair shlándála nua + not_enabled: Níl WebAuthn cumasaithe agat fós + not_supported: Ní thacaíonn an brabhsálaí seo le heochracha slándála + otp_required: Chun eochracha slándála a úsáid cumasaigh fíordheimhniú dhá fhachtóir ar dtús. + registered_on: Cláraithe ar %{date} diff --git a/config/locales/gl.yml b/config/locales/gl.yml index c9f08dcad74d3a..d1c8633badd602 100644 --- a/config/locales/gl.yml +++ b/config/locales/gl.yml @@ -226,6 +226,7 @@ gl: update_custom_emoji: Actualizar emoticona personalizada update_domain_block: Actualizar bloqueo do dominio update_ip_block: Actualizar regra IP + update_report: Actualización da denuncia update_status: Actualizar publicación update_user_role: Actualizar Rol actions: @@ -638,6 +639,7 @@ gl: report: 'Denuncia #%{id}' reported_account: Conta denunciada reported_by: Denunciado por + reported_with_application: Denunciado coa aplicación resolved: Resolto resolved_msg: Resolveuse con éxito a denuncia! skip_to_actions: Ir a accións diff --git a/config/locales/he.yml b/config/locales/he.yml index 3ba823f99bc685..105bd059f23c87 100644 --- a/config/locales/he.yml +++ b/config/locales/he.yml @@ -232,6 +232,7 @@ he: update_custom_emoji: עדכון סמלון מותאם אישית update_domain_block: עדכון חסימת שם מתחם update_ip_block: עדכון כלל IP + update_report: עדכון דו"ח עבירה update_status: סטטוס עדכון update_user_role: עדכון תפקיד actions: @@ -662,6 +663,7 @@ he: report: 'דווח על #%{id}' reported_account: חשבון מדווח reported_by: דווח על ידי + reported_with_application: דיווחים באמצעות יישומון resolved: פתור resolved_msg: הדו"ח נפתר בהצלחה! skip_to_actions: דלג/י לפעולות diff --git a/config/locales/hi.yml b/config/locales/hi.yml index b67de192f2563e..0bfc30027abef7 100644 --- a/config/locales/hi.yml +++ b/config/locales/hi.yml @@ -32,6 +32,8 @@ hi: silence: सीमा silenced: सीमित title: खाते + reports: + reported_with_application: एप्लीकेशन से रिपोर्ट किया गया system_checks: upload_check_privacy_error: message_html: " आपके वेब सर्वर का कन्फिगरेशन सही नहीं है। उपयोगकर्ताओं की निजता खतरे में है। " diff --git a/config/locales/hu.yml b/config/locales/hu.yml index 19076910e2992c..df32bd39d116f7 100644 --- a/config/locales/hu.yml +++ b/config/locales/hu.yml @@ -226,6 +226,7 @@ hu: update_custom_emoji: Egyéni emodzsi frissítése update_domain_block: Domain tiltás frissítése update_ip_block: IP-szabály frissítése + update_report: Bejelentés frissítése update_status: Bejegyzés frissítése update_user_role: Szerepkör frissítése actions: @@ -638,6 +639,7 @@ hu: report: "#%{id} számú jelentés" reported_account: Bejelentett fiók reported_by: 'Jelentette:' + reported_with_application: Alkalmazással bejelentve resolved: Megoldott resolved_msg: A bejelentést sikeresen megoldottuk! skip_to_actions: Tovább az intézkedésekhez diff --git a/config/locales/is.yml b/config/locales/is.yml index 7ac50cd572dde4..a4cc282d1d770c 100644 --- a/config/locales/is.yml +++ b/config/locales/is.yml @@ -226,6 +226,7 @@ is: update_custom_emoji: Uppfæra sérsniðið tjáningartákn update_domain_block: Uppfæra útilokun léns update_ip_block: Uppfæra reglu IP-vistfangs + update_report: Uppfæra kæru update_status: Uppfæra færslu update_user_role: Uppfæra hlutverk actions: @@ -638,6 +639,7 @@ is: report: 'Kæra #%{id}' reported_account: Kærður notandaaðgangur reported_by: Kært af + reported_with_application: Kærði með forritinu resolved: Leyst resolved_msg: Það tókst að leysa kæruna! skip_to_actions: Sleppa og fara í aðgerðir diff --git a/config/locales/it.yml b/config/locales/it.yml index 1e17c5cbd0c721..68e1608d9c1990 100644 --- a/config/locales/it.yml +++ b/config/locales/it.yml @@ -226,6 +226,7 @@ it: update_custom_emoji: Aggiorna Emoji Personalizzata update_domain_block: Aggiorna Blocco del Dominio update_ip_block: Aggiorna regola IP + update_report: Aggiorna segnalazione update_status: Aggiorna Toot update_user_role: Aggiorna Ruolo actions: @@ -638,6 +639,7 @@ it: report: 'Rapporto #%{id}' reported_account: Account segnalato reported_by: Inviato da + reported_with_application: Segnalato con applicazione resolved: Risolto resolved_msg: Rapporto risolto! skip_to_actions: Passa alle azioni diff --git a/config/locales/kab.yml b/config/locales/kab.yml index b2fc9d847735f6..a094936aaf0b38 100644 --- a/config/locales/kab.yml +++ b/config/locales/kab.yml @@ -604,7 +604,7 @@ kab: filters: contexts: account: Imeɣna - notifications: Ilɣa + notifications: Alɣuten thread: Idiwenniyen edit: add_keyword: Rnu awal tasarut diff --git a/config/locales/ko.yml b/config/locales/ko.yml index f7feb73ba0b03d..632bd7c097647f 100644 --- a/config/locales/ko.yml +++ b/config/locales/ko.yml @@ -223,6 +223,7 @@ ko: update_custom_emoji: 커스텀 에모지 업데이트 update_domain_block: 도메인 차단 갱신 update_ip_block: IP 규칙 수정 + update_report: 신고 업데이트 update_status: 게시물 수정 update_user_role: 역할 수정 actions: diff --git a/config/locales/lt.yml b/config/locales/lt.yml index e731deedc8e64b..1e717b6c204292 100644 --- a/config/locales/lt.yml +++ b/config/locales/lt.yml @@ -232,6 +232,7 @@ lt: update_custom_emoji: Atnaujinti pasirinktinį jaustuką update_domain_block: Atnaujinti domeno bloką update_ip_block: Atnaujinti IP taisyklę + update_report: Atnaujinti ataskaitą update_status: Atnaujinti įrašą update_user_role: Atnaujinti vaidmenį actions: @@ -542,6 +543,8 @@ lt: manage_taxonomies_description: Leidžia naudotojams peržiūrėti tendencingą turinį ir atnaujinti saitažodžių nustatymus manage_user_access_description: Leidžia naudotojams išjungti kitų naudotojų dvigubo tapatybės nustatymą, pakeisti el. pašto adresą ir iš naujo nustatyti slaptažodį. settings: + branding: + title: Firminio ženklo kūrimas captcha_enabled: desc_html: Tai priklauso nuo hCaptcha išorinių skriptų, kurie gali kelti susirūpinimą dėl saugumo ir privatumo. Be to, dėl to registracijos procesas kai kuriems žmonėms (ypač neįgaliesiems) gali būti gerokai sunkiau prieinami. Dėl šių priežasčių apsvarstyk alternatyvias priemones, pavyzdžiui, patvirtinimu arba kvietimu grindžiamą registraciją. content_retention: @@ -663,7 +666,19 @@ lt: edit_preset: Keisti įspėjimo nustatymus title: Įspėjamieji numatytieji webhooks: + add_new: Pridėti galutinį tašką + delete: Ištrinti description_html: "Webhook leidžia Mastodon siųsti realaus laiko pranešimus apie pasirinktus įvykius į tavo programą, kad programa galėtų automatiškai paleisti reakcijas." + disable: Išjungti + disabled: Išjungta + edit: Redaguoti galutinį tašką + enable: Įjungti + enabled: Aktyvi + enabled_events: + few: "%{count} įjungti įvykiai" + many: "%{count} įjungto įvykio" + one: "%{count} įjungtas įvykis" + other: "%{count} įjungtų įvykių" events: Įvykiai admin_mailer: auto_close_registrations: @@ -909,6 +924,7 @@ lt: login_activities: authentication_methods: otp: dvigubas tapatybės nustatymo programėlė + webauthn: saugumo raktai description_html: Jei pastebėjei neatpažįstamą veiklą, apsvarstyk galimybę pakeisti slaptažodį ir įjungti dvigubą tapatybės nustatymą. empty: Tapatybės nustatymas istorijos nėra title: Tapatybės nustatymo istorija @@ -1049,6 +1065,7 @@ lt: relationships: Sekimai ir sekėjai severed_relationships: Nutrūkę sąryšiai two_factor_authentication: Dvigubas tapatybės nustatymas + webauthn_authentication: Saugumo raktai severed_relationships: download: Atsisiųsti (%{count}) preamble: Užblokavus domeną arba prižiūrėtojams nusprendus pristabdyti nuotolinio serverio veiklą, gali prarasti sekimus ir sekėjus. Kai taip atsitiks, galėsi atsisiųsti nutrauktų sąryšių sąrašus, kad juos patikrinti ir galbūt importuoti į kitą serverį. @@ -1110,6 +1127,7 @@ lt: recovery_codes: Atsarginio atkūrimo kodai recovery_codes_regenerated: Atkūrimo kodai sėkmingai sugeneruoti recovery_instructions_html: Jeigu prarandate prieiga prie telefono, jūs galite naudoti atkūrimo kodus esančius žemiau, kad atgautumėte priega prie savo paskyros.Laikykite atkūrimo kodus saugiai Pavyzdžiui, galite norėti juos išspausdinti, ir laikyti kartu su kitais svarbiais dokumentais. + webauthn: Saugumo raktai user_mailer: appeal_approved: action: Paskyros nustatymai @@ -1196,9 +1214,11 @@ lt: verification: Patvirtinimas verified_links: Tavo patikrintos nuorodos webauthn_credentials: + add: Pridėti naują saugumo raktą create: error: Kilo problema pridedant saugumo raktą. Bandyk dar kartą. success: Tavo saugumo raktas buvo sėkmingai pridėtas. + delete: Ištrinti delete_confirmation: Ar tikrai nori ištrinti šį saugumo raktą? description_html: Jei įjungsi saugumo rakto tapatybės nustatymą, prisijungiant reikės naudoti vieną iš savo saugumo raktų. destroy: diff --git a/config/locales/nl.yml b/config/locales/nl.yml index baab2cb587a0e7..91872754f5cd9b 100644 --- a/config/locales/nl.yml +++ b/config/locales/nl.yml @@ -226,6 +226,7 @@ nl: update_custom_emoji: Lokale emoji bijwerken update_domain_block: Domeinblokkade bijwerken update_ip_block: IP-regel bijwerken + update_report: Rapportage bijwerken update_status: Bericht bijwerken update_user_role: Rol bijwerken actions: @@ -638,6 +639,7 @@ nl: report: 'Rapportage #%{id}' reported_account: Gerapporteerde account reported_by: Gerapporteerd door + reported_with_application: Gerapporteerd met applicatie resolved: Opgelost resolved_msg: Rapportage succesvol opgelost! skip_to_actions: Ga direct naar de maatregelen diff --git a/config/locales/nn.yml b/config/locales/nn.yml index 2da30e6627184a..ec77a2edf8792d 100644 --- a/config/locales/nn.yml +++ b/config/locales/nn.yml @@ -226,6 +226,7 @@ nn: update_custom_emoji: Oppdater tilpassa emoji update_domain_block: Oppdater domene-sperring update_ip_block: Oppdater IP-regel + update_report: Oppdater rapport update_status: Oppdater tut update_user_role: Oppdater rolla actions: @@ -638,6 +639,7 @@ nn: report: 'Rapporter #%{id}' reported_account: Rapportert konto reported_by: Rapportert av + reported_with_application: Rapportert med app resolved: Oppløyst resolved_msg: Rapporten er løyst! skip_to_actions: Gå til handlingar diff --git a/config/locales/pl.yml b/config/locales/pl.yml index 7497f1784382db..b0c733102ea886 100644 --- a/config/locales/pl.yml +++ b/config/locales/pl.yml @@ -232,6 +232,7 @@ pl: update_custom_emoji: Aktualizuj niestandardowe emoji update_domain_block: Zaktualizuj blokadę domeny update_ip_block: Aktualizuj regułę IP + update_report: Wiadomości or raporcie update_status: Aktualizuj wpis update_user_role: Aktualizuj rolę actions: @@ -662,6 +663,7 @@ pl: report: 'Zgłoszenie #%{id}' reported_account: Zgłoszone konto reported_by: Zgłaszający + reported_with_application: Zareportowano przez aplikację resolved: Rozwiązane resolved_msg: Pomyślnie rozwiązano zgłoszenie. skip_to_actions: Przejdź do akcji diff --git a/config/locales/pt-PT.yml b/config/locales/pt-PT.yml index 839ae2184edfc2..1df423bb7de93f 100644 --- a/config/locales/pt-PT.yml +++ b/config/locales/pt-PT.yml @@ -226,6 +226,7 @@ pt-PT: update_custom_emoji: Atualizar Emoji Personalizado update_domain_block: Atualizar Bloqueio de Domínio update_ip_block: Atualizar regra de IP + update_report: Atualizar Relatório update_status: Atualizar Estado update_user_role: Atualizar Função actions: @@ -638,6 +639,7 @@ pt-PT: report: 'Denúncia #%{id}' reported_account: Conta denunciada reported_by: Denunciado por + reported_with_application: Reportado com a aplicação resolved: Resolvido resolved_msg: Denúncia correctamente resolvida! skip_to_actions: Passar para as ações diff --git a/config/locales/simple_form.ast.yml b/config/locales/simple_form.ast.yml index d1950ab15f87e2..c222c9aef5ba30 100644 --- a/config/locales/simple_form.ast.yml +++ b/config/locales/simple_form.ast.yml @@ -6,7 +6,7 @@ ast: note: 'Pues @mentar a otros perfiles o poner #etiquetes.' unlocked: Los perfiles van ser a siguite ensin solicitar la to aprobación. Desmarca esta opción si quies revisar les solicitúes de siguimientu y escoyer si aceptales o refugales. admin_account_action: - text_html: Opcional. Pues usar la sintaxis de los artículos ya amestar alvertencies preconfiguraes p'aforrar tiempu + text_html: Opcional. Pues usar la sintaxis de los artículos y amestar alvertencies preconfiguraes p'aforrar tiempu type_html: Escueyi qué facer con %{acct} types: none: Usa esta opción pa unviar una alvertencia al perfil, ensin aicionar nenguna otra aición. @@ -18,14 +18,14 @@ ast: text: Pues usar la sintaxis de los artículos. Ten en cuenta l'espaciu que l'anunciu va ocupar na pantalla del usuariu/a defaults: autofollow: Les persones que se rexistren pente la invitación van siguite automáticamente - bot: Avisa a otres persones de qu'esta cuenta fai principalmente aiciones automatizaes ya de que ye posible que nun tean supervisaes - digest: Namás s'unvia dempués d'un periodu llongu d'inactividá ya namás si recibiesti dalgún mensaxe personal demientres la to ausencia + bot: Avisa a otres persones de qu'esta cuenta fai principalmente aiciones automatizaes y de que ye posible que nun tean supervisaes + digest: Namás s'unvia dempués d'un periodu llongu d'inactividá y namás si recibiesti dalgún mensaxe personal demientres la to ausencia irreversible: Los artículos peñeraos desapaecen de forma irreversible, magar que la peñera se quite dempués - locale: La llingua de la interfaz, los mensaxes per corréu electrónicu ya los avisos push + locale: La llingua de la interfaz, los mensaxes per corréu electrónicu y los avisos push password: Usa polo menos 8 caráuteres - setting_aggregate_reblogs: Nun amuesa los artículos compartíos nuevos que xá se compartieren de recién (namás afeuta a los artículos compartíos d'agora) + setting_aggregate_reblogs: Nun amuesa los artículos compartíos nuevos que yá se compartieren de recién (namás afeuta a los artículos compartíos d'agora) setting_always_send_emails: Los avisos nun se suelen unviar per corréu electrónicu si uses activamente Mastodon - setting_default_sensitive: El conteníu multimedia sensible anúbrese por defeutu ya pue amosase al calcar nelli + setting_default_sensitive: El conteníu multimedia sensible anúbrese por defeutu y pue amosase al calcar nelli setting_display_media_default: Anubrilu cuando se marque como sensible setting_display_media_hide_all: Anubrilu siempres setting_display_media_show_all: Amosalu siempres @@ -37,10 +37,10 @@ ast: custom_css: Pues aplicar estilos personalizaos a la versión web de Mastodon. mascot: Anula la ilustración na interfaz web avanzada. require_invite_text: Cuando los rexistros riquen una aprobación manual, el campu «¿Por qué quies xunite?» vuélvese obligatoriu - site_extended_description: Cualesquier tipu d'información adicional que pueda ser útil pa visitantes ya pa perfiles rexistraos. El testu pue estructurase cola sintaxis de Mastodon. + site_extended_description: Cualesquier tipu d'información adicional que pueda ser útil pa visitantes y pa perfiles rexistraos. El testu pue estructurase cola sintaxis de Mastodon. site_short_description: Un descripción curtia qu'ayuda a identificar de forma única al sirvidor. ¿Quién lu lleva?, ¿pa quién ye? - theme: L'estilu que los visitantes ya los perfiles nuevos usen. - trends: Les tendencies amuesen artículos, etiquetes ya noticies que tean ganando popularidá nesti sirvidor. + theme: L'estilu que los visitantes y los perfiles nuevos usen. + trends: Les tendencies amuesen artículos, etiquetes y noticies que tean ganando popularidá nesti sirvidor. form_challenge: current_password: Tas entrando a una área segura imports: @@ -49,7 +49,7 @@ ast: text: Esto va ayudanos a revisar la to solicitú ip_block: comment: Opcional. Un recordatoriu de por qué amestesti esta norma. - expires_in: Les direiciones IP son un recursu finitu, suelen compartise ya cambiar de manes. Por esti motivu, nun s'aconseyen los bloqueos indefiníos de direiciones IP. + expires_in: Les direiciones IP son un recursu finitu, suelen compartise y cambiar de manes. Por esti motivu, nun s'aconseyen los bloqueos indefiníos de direiciones IP. severities: no_access: Bloquia l'accesu a tolos recursos sign_up_block: Fai que nun se puedan rexistrar cuentes nueves @@ -58,11 +58,12 @@ ast: chosen_languages: Namás los artículos de les llingües que marques son los que van apaecer nes llinies de tiempu públiques labels: account: - discoverable: Destacar el perfil ya los artículos nos algoritmos de descubrimientu + discoverable: Destacar el perfil y los artículos nos algoritmos de descubrimientu fields: name: Etiqueta value: Conteníu indexable: Incluyir los artículos públicos nos resultaos de busca + show_collections: Amosar los perfiles a los que sigues y los que te siguen account_warning_preset: title: Títulu admin_account_action: @@ -109,10 +110,11 @@ ast: setting_default_privacy: Privacidá de los artículos setting_default_sensitive: Marcar siempres tol conteníu como sensible setting_delete_modal: Amosar el diálogu de confirmación enantes de desaniciar un artículu + setting_disable_hover_cards: Desactivar la previsualización de perfiles al pasar el mur penriba setting_disable_swiping: Desactivar el movimientu de desplazamientu setting_display_media: Conteníu multimedia setting_expand_spoilers: Espander siempres los artículos marcaos con alvertencies de conteníu - setting_hide_network: Anubrir les cuentes que sigas ya te sigan + setting_hide_network: Anubrir les cuentes que sigas y te sigan setting_reduce_motion: Amenorgar el movimientu de les animaciones setting_system_font_ui: Usar la fonte predeterminada del sistema setting_theme: Estilu del sitiu @@ -173,8 +175,9 @@ ast: text: Norma settings: indexable: Incluyir la páxina del perfil nos motores de busca + show_application: Amosar l'aplicación dende la que s'unvien los artículos tag: - listable: Permitir qu'esta etiqueta apaeza nes busques ya nes suxerencies + listable: Permitir qu'esta etiqueta apaeza nes busques y nes suxerencies name: Etiqueta trendable: Permitir qu'esta etiqueta apaeza nes tendencies usable: Permitir que los artículos usen esta etiqueta diff --git a/config/locales/simple_form.bg.yml b/config/locales/simple_form.bg.yml index f14a21b0c70036..564f72e8c21231 100644 --- a/config/locales/simple_form.bg.yml +++ b/config/locales/simple_form.bg.yml @@ -211,6 +211,7 @@ bg: setting_default_privacy: Поверителност на публикуване setting_default_sensitive: Все да се бележи мултимедията като деликатна setting_delete_modal: Показване на прозорче за потвърждение преди изтриване на публикация + setting_disable_hover_cards: Изключване на прегледа на профила, премествайки показалеца отгоре setting_disable_swiping: Деактивиране на бързо плъзгащи движения setting_display_media: Показване на мултимедия setting_display_media_default: Стандартно @@ -242,11 +243,13 @@ bg: warn: Скриване зад предупреждение form_admin_settings: activity_api_enabled: Публикуване на агрегатна статистика относно потребителската дейност в API + app_icon: Икона на приложение backups_retention_period: Период за съхранение на потребителския архив bootstrap_timeline_accounts: Винаги да се препоръчват следните акаунти на нови потребители closed_registrations_message: Съобщение при неналична регистрация content_cache_retention_period: Период на запазване на отдалечено съдържание custom_css: Персонализиран CSS + favicon: Сайтоикона mascot: Плашило талисман по избор (остаряло) media_cache_retention_period: Период на запазване на мултимедийния кеш peers_api_enabled: Публикуване на списъка с открити сървъри в API diff --git a/config/locales/simple_form.ca.yml b/config/locales/simple_form.ca.yml index 4bb906abdbd897..2e0199d7fd5b06 100644 --- a/config/locales/simple_form.ca.yml +++ b/config/locales/simple_form.ca.yml @@ -243,11 +243,13 @@ ca: warn: Oculta amb un avís form_admin_settings: activity_api_enabled: Publica a l'API estadístiques agregades sobre l'activitat dels usuaris + app_icon: Icona de l'aplicació backups_retention_period: Període de retenció del arxiu d'usuari bootstrap_timeline_accounts: Recomana sempre aquests comptes als nous usuaris closed_registrations_message: Missatge personalitzat quan el registre no és accessible content_cache_retention_period: Període de retenció del contingut remot custom_css: CSS personalitzat + favicon: Icona de preferits mascot: Mascota personalitzada (llegat) media_cache_retention_period: Període de retenció del cau multimèdia peers_api_enabled: Publica a l'API la llista de servidors descoberts diff --git a/config/locales/simple_form.cy.yml b/config/locales/simple_form.cy.yml index 5e8fd85293f75a..cd5bc1add788b8 100644 --- a/config/locales/simple_form.cy.yml +++ b/config/locales/simple_form.cy.yml @@ -242,11 +242,13 @@ cy: warn: Cuddio â rhybudd form_admin_settings: activity_api_enabled: Cyhoeddi ystadegau cyfanredol am weithgarwch defnyddwyr yn yr API + app_icon: Eicon ap backups_retention_period: Cyfnod cadw archif defnyddwyr bootstrap_timeline_accounts: Argymhellwch y cyfrifon hyn i ddefnyddwyr newydd bob amser closed_registrations_message: Neges bersonol pan nad yw cofrestriadau ar gael content_cache_retention_period: Cyfnod cadw cynnwys o bell custom_css: CSS cyfaddas + favicon: Favicon mascot: Mascot cyfaddas (hen) media_cache_retention_period: Cyfnod cadw storfa cyfryngau peers_api_enabled: Cyhoeddi rhestr o weinyddion a ddarganfuwyd yn yr API diff --git a/config/locales/simple_form.da.yml b/config/locales/simple_form.da.yml index 73a32cf2fdee2d..9e949d16839f7d 100644 --- a/config/locales/simple_form.da.yml +++ b/config/locales/simple_form.da.yml @@ -243,11 +243,13 @@ da: warn: Skjul bag en advarsel form_admin_settings: activity_api_enabled: Offentliggør samlede statistikker vedr. brugeraktivitet i API'en + app_icon: App-ikon backups_retention_period: Brugerarkivs opbevaringsperiode bootstrap_timeline_accounts: Anbefal altid disse konti til nye brugere closed_registrations_message: Tilpasset besked, når tilmelding er utilgængelig content_cache_retention_period: Opbevaringsperiode for eksternt indhold custom_css: Tilpasset CSS + favicon: Favikon mascot: Tilpasset maskot (ældre funktion) media_cache_retention_period: Media-cache opbevaringsperiode peers_api_enabled: Udgiv liste over fundne server i API'en diff --git a/config/locales/simple_form.de.yml b/config/locales/simple_form.de.yml index 5711d2a12a4993..332d9513952126 100644 --- a/config/locales/simple_form.de.yml +++ b/config/locales/simple_form.de.yml @@ -243,11 +243,13 @@ de: warn: Mit einer Inhaltswarnung ausblenden form_admin_settings: activity_api_enabled: Aggregierte Nutzungsdaten über die API veröffentlichen + app_icon: App-Symbol backups_retention_period: Aufbewahrungsfrist für Archive bootstrap_timeline_accounts: Neuen Nutzern immer diese Konten empfehlen closed_registrations_message: Nachricht, falls Registrierungen deaktiviert sind content_cache_retention_period: Aufbewahrungsfrist für externe Inhalte custom_css: Eigenes CSS + favicon: Favicon mascot: Benutzerdefiniertes Maskottchen (Legacy) media_cache_retention_period: Aufbewahrungsfrist für Medien im Cache peers_api_enabled: Die entdeckten Server im Fediverse über die API veröffentlichen diff --git a/config/locales/simple_form.en-GB.yml b/config/locales/simple_form.en-GB.yml index eaf0501a27ba9e..c1f2a015e94b27 100644 --- a/config/locales/simple_form.en-GB.yml +++ b/config/locales/simple_form.en-GB.yml @@ -211,6 +211,7 @@ en-GB: setting_default_privacy: Posting privacy setting_default_sensitive: Always mark media as sensitive setting_delete_modal: Show confirmation dialogue before deleting a post + setting_disable_hover_cards: Disable profile preview on hover setting_disable_swiping: Disable swiping motions setting_display_media: Media display setting_display_media_default: Default @@ -242,11 +243,13 @@ en-GB: warn: Hide with a warning form_admin_settings: activity_api_enabled: Publish aggregate statistics about user activity in the API + app_icon: App icon backups_retention_period: User archive retention period bootstrap_timeline_accounts: Always recommend these accounts to new users closed_registrations_message: Custom message when sign-ups are not available content_cache_retention_period: Remote content retention period custom_css: Custom CSS + favicon: Favicon mascot: Custom mascot (legacy) media_cache_retention_period: Media cache retention period peers_api_enabled: Publish list of discovered servers in the API diff --git a/config/locales/simple_form.eo.yml b/config/locales/simple_form.eo.yml index 40535bf96bc12e..021be93b5d74cb 100644 --- a/config/locales/simple_form.eo.yml +++ b/config/locales/simple_form.eo.yml @@ -235,6 +235,7 @@ eo: warn: Kaŝi malantaŭ averto form_admin_settings: activity_api_enabled: Publikigi entutajn statistikojn pri uzantagado en la API + app_icon: Apbildo backups_retention_period: Uzantoarkivretendauro bootstrap_timeline_accounts: Ĉiam rekomendi ĉi tiujn kontojn al novaj uzantoj closed_registrations_message: Kutima mesaĝo kiam registroj ne estas disponeblaj diff --git a/config/locales/simple_form.es-AR.yml b/config/locales/simple_form.es-AR.yml index 1d1ac876894f94..71d9726b079423 100644 --- a/config/locales/simple_form.es-AR.yml +++ b/config/locales/simple_form.es-AR.yml @@ -243,11 +243,13 @@ es-AR: warn: Ocultar con una advertencia form_admin_settings: activity_api_enabled: Publicar estadísticas agregadas sobre la actividad de la cuenta en la API + app_icon: Ícono de la aplicación backups_retention_period: Período de retención del archivo historial del usuario bootstrap_timeline_accounts: Siempre recomendar estas cuentas a usuarios nuevos closed_registrations_message: Mensaje personalizado cuando los registros no están disponibles content_cache_retention_period: Período de retención de contenido remoto custom_css: CSS personalizado + favicon: Favicón mascot: Mascota personalizada (legado) media_cache_retention_period: Período de retención de la caché de medios peers_api_enabled: Publicar lista de servidores descubiertos en la API diff --git a/config/locales/simple_form.es-MX.yml b/config/locales/simple_form.es-MX.yml index 19a1c9d0c095f9..730e9b265b335a 100644 --- a/config/locales/simple_form.es-MX.yml +++ b/config/locales/simple_form.es-MX.yml @@ -243,11 +243,13 @@ es-MX: warn: Ocultar con una advertencia form_admin_settings: activity_api_enabled: Publicar estadísticas locales acerca de la actividad de usuario en la API + app_icon: Icono de la app backups_retention_period: Período de retención del archivo de usuario bootstrap_timeline_accounts: Recomendar siempre estas cuentas a nuevos usuarios closed_registrations_message: Mensaje personalizado cuando los registros no están disponibles content_cache_retention_period: Período de retención de contenido remoto custom_css: CSS personalizado + favicon: Favicon mascot: Mascota personalizada (legado) media_cache_retention_period: Período de retención de caché multimedia peers_api_enabled: Publicar lista de servidores descubiertos en la API diff --git a/config/locales/simple_form.es.yml b/config/locales/simple_form.es.yml index cc71e192665609..f2d91349adad6b 100644 --- a/config/locales/simple_form.es.yml +++ b/config/locales/simple_form.es.yml @@ -243,11 +243,13 @@ es: warn: Ocultar con una advertencia form_admin_settings: activity_api_enabled: Publicar estadísticas agregadas sobre la actividad del usuario con la API + app_icon: Icono de la app backups_retention_period: Período de retención del archivo de usuario bootstrap_timeline_accounts: Recomendar siempre estas cuentas a nuevos usuarios closed_registrations_message: Mensaje personalizado cuando los registros no están disponibles content_cache_retention_period: Período de retención de contenido remoto custom_css: CSS personalizado + favicon: Favicon mascot: Mascota personalizada (legado) media_cache_retention_period: Período de retención de caché multimedia peers_api_enabled: Publicar lista de servidores descubiertos en la API diff --git a/config/locales/simple_form.fi.yml b/config/locales/simple_form.fi.yml index 214308ba5cc6e6..de099a21be2e1a 100644 --- a/config/locales/simple_form.fi.yml +++ b/config/locales/simple_form.fi.yml @@ -243,11 +243,13 @@ fi: warn: Piilota varoittaen form_admin_settings: activity_api_enabled: Julkaise yhteenlasketut tilastot käyttäjätoiminnasta ohjelmointirajapinnassa + app_icon: Sovelluskuvake backups_retention_period: Käyttäjän arkiston säilytysaika bootstrap_timeline_accounts: Suosittele aina näitä tilejä uusille käyttäjille closed_registrations_message: Mukautettu viesti, kun rekisteröityminen ei ole saatavilla content_cache_retention_period: Etäsisällön säilytysaika custom_css: Mukautettu CSS + favicon: Suosikkikuvake mascot: Mukautettu maskotti (vanhentunut ominaisuus) media_cache_retention_period: Mediasisältövälimuistin säilytysaika peers_api_enabled: Julkaise löydettyjen palvelinten luettelo ohjelmointirajapinnassa diff --git a/config/locales/simple_form.fo.yml b/config/locales/simple_form.fo.yml index 8f0b51719fceed..b334d4f034ac5f 100644 --- a/config/locales/simple_form.fo.yml +++ b/config/locales/simple_form.fo.yml @@ -243,11 +243,13 @@ fo: warn: Fjal við eini ávaring form_admin_settings: activity_api_enabled: Útgev samantald hagtøl um brúkaravirksemi í API'num + app_icon: App ikon backups_retention_period: Hvussu leingi verða brúkarasøvn goymd bootstrap_timeline_accounts: Mæl altíð nýggjum brúkarum at fylgja hesar kontur closed_registrations_message: Serskild boð, tá tað ikki er møguligt at tilmelda seg content_cache_retention_period: Tíðarskeið fyri varðveiðslu av fjartilfari custom_css: Serskilt CSS + favicon: Favikon mascot: Serskildur maskottur (arvur) media_cache_retention_period: Tíðarskeið, har miðlagoymslur verða varðveittar peers_api_enabled: Kunnger lista við uppdagaðum ambætarum í API'num diff --git a/config/locales/simple_form.ga.yml b/config/locales/simple_form.ga.yml index 3597544ce3a623..2effe1a10cc7a0 100644 --- a/config/locales/simple_form.ga.yml +++ b/config/locales/simple_form.ga.yml @@ -2,47 +2,239 @@ ga: simple_form: hints: + account: + discoverable: Seans go mbeidh do phostálacha poiblí agus do phróifíl le feiceáil nó molta i réimsí éagsúla de Mastodon agus is féidir do phróifíl a mholadh d’úsáideoirí eile. + display_name: D'ainm iomlán nó d'ainm spraoi. + fields: Do leathanach baile, forainmneacha, aois, rud ar bith is mian leat. + indexable: Seans go mbeidh do phostálacha poiblí le feiceáil sna torthaí cuardaigh ar Mastodon. Seans go mbeidh daoine a d’idirghníomhaigh le do phostálacha in ann iad a chuardach beag beann ar. + note: 'Is féidir leat @trá a dhéanamh ar dhaoine eile nó #hashtags.' + show_collections: Beidh daoine in ann brabhsáil trí do seo a leanas agus do leanúna. Feicfidh na daoine a leanann tú go leanann tú iad beag beann ar. + unlocked: Beidh daoine in ann tú a leanúint gan cead a iarraidh. Díthiceáil an dteastaíonn uait athbhreithniú a dhéanamh ar iarratais leantacha agus roghnaigh cé acu an nglacfaidh nó an diúltóidh tú do leantóirí nua. account_alias: acct: Sonraigh ainm@fearann don chuntas ar mhaith leat aistriú uaidh account_migration: acct: Sonraigh ainm@fearann don chuntas ar mhaith leat aistriú chuige + account_warning_preset: + text: Is féidir leat comhréir na bpost a úsáid, mar URLanna, hashtags agus lua + title: Roghnach. Níl sé le feiceáil ag an bhfaighteoir admin_account_action: + include_statuses: Feicfidh an t-úsáideoir cé na poist ba chúis leis an ngníomh modhnóireachta nó leis an rabhadh + send_email_notification: Gheobhaidh an t-úsáideoir míniú ar an méid a tharla lena chuntas + text_html: Roghnach. Is féidir leat comhréir phoist a úsáid. Is féidir leat réamhshocruithe rabhaidh a chur leis chun am a shábháil + type_html: Roghnaigh cad atá le déanamh le %{acct} types: disable: Cuir cosc ar an úsáideoir a chuntas a úsáid, ach ná scrios ná folaigh a bhfuil ann. + none: Bain úsáid as seo chun rabhadh a sheoladh chuig an úsáideoir, gan aon ghníomh eile a spreagadh. + sensitive: Iallach a chur ar cheangaltáin meán an úsáideora seo go léir a bheith íogair. + silence: Cosc a chur ar an úsáideoir ó bheith in ann postáil le hinfheictheacht phoiblí, a gcuid postálacha agus fógraí a cheilt ar dhaoine nach leanann iad. Dúnann sé gach tuairisc i gcoinne an chuntais seo. + suspend: Cosc ar aon idirghníomhaíocht ón gcuntas seo nó chuig an gcuntas seo agus scrios a bhfuil ann. Inchúlaithe laistigh de 30 lá. Dúnann sé gach tuairisc i gcoinne an chuntais seo. + warning_preset_id: Roghnach. Is féidir leat téacs saincheaptha a chur le deireadh an réamhshocraithe fós + announcement: + all_day: Nuair a dhéantar iad a sheiceáil, ní thaispeánfar ach dátaí an raon ama + ends_at: Roghnach. Beidh an fógra neamhfhoilsithe go huathoibríoch ag an am seo + scheduled_at: Fág bán chun an fógra a fhoilsiú láithreach + starts_at: Roghnach. I gcás go bhfuil d'fhógra ceangailte le raon ama ar leith + text: Is féidir leat comhréir phoist a úsáid. Tabhair aird ar an spás a ghlacfaidh an fógra ar scáileán an úsáideora + appeal: + text: Ní féidir leat achomharc a dhéanamh ach uair amháin ar stailc defaults: + autofollow: Leanfaidh daoine a chláraíonn tríd an gcuireadh thú go huathoibríoch + avatar: WEBP, PNG, GIF nó JPG. %{size} ar a mhéad. Íoslaghdófar é go %{dimensions}px + bot: Cuir in iúl do dhaoine eile go ndéanann an cuntas gníomhartha uathoibrithe den chuid is mó agus go mb’fhéidir nach ndéanfar monatóireacht air + context: Comhthéacs amháin nó comhthéacsanna iolracha inar cheart go mbeadh feidhm ag an scagaire + current_password: Chun críocha slándála cuir isteach pasfhocal an chuntais reatha + current_username: Le deimhniú, cuir isteach ainm úsáideora an chuntais reatha + digest: Seoltar é tar éis tréimhse fhada neamhghníomhaíochta amháin agus sa chás sin amháin go bhfuil aon teachtaireachtaí pearsanta faighte agat agus tú as láthair + email: Seolfar ríomhphost deimhnithe chugat + header: WEBP, PNG, GIF nó JPG. %{size} ar a mhéad. Íoslaghdófar é go %{dimensions}px + inbox_url: Cóipeáil an URL ó leathanach tosaigh an athsheachadáin is mian leat a úsáid + irreversible: Imeoidh postálacha scagtha go dochúlaithe, fiú má bhaintear an scagaire níos déanaí + locale: Teanga an chomhéadain úsáideora, r-phoist agus fógraí brú + password: Úsáid ar a laghad 8 gcarachtar + phrase: Déanfar é a mheaitseáil beag beann ar chásáil an téacs nó ar an ábhar atá ag tabhairt foláireamh do phostáil + scopes: Cé na APIanna a mbeidh cead ag an bhfeidhmchlár rochtain a fháil orthu. Má roghnaíonn tú raon feidhme barrleibhéil, ní gá duit cinn aonair a roghnú. + setting_aggregate_reblogs: Ná taispeáin treisithe nua do phoist a treisíodh le déanaí (ní dhéanann difear ach do threisithe nuafhaighte) + setting_always_send_emails: Go hiondúil ní sheolfar fógraí ríomhphoist agus tú ag úsáid Mastodon go gníomhach + setting_default_sensitive: Tá meáin íogair i bhfolach de réir réamhshocraithe agus is féidir iad a nochtadh le cliceáil + setting_display_media_default: Folaigh meáin atá marcáilte mar íogair setting_display_media_hide_all: Folaigh meáin i gcónaí setting_display_media_show_all: Taispeáin meáin i gcónaí + setting_use_blurhash: Tá grádáin bunaithe ar dhathanna na n-amharcanna ceilte ach cuireann siad salach ar aon mhionsonraí + setting_use_pending_items: Folaigh nuashonruithe amlíne taobh thiar de chlic seachas an fotha a scrollú go huathoibríoch + username: Is féidir leat litreacha, uimhreacha, agus béim a úsáid + whole_word: Nuair a bhíonn an eochairfhocal nó frása alfa-uimhriúil amháin, ní chuirfear i bhfeidhm é ach amháin má mheaitseálann sé an focal iomlán + domain_allow: + domain: Beidh an fearann ​​seo in ann sonraí a fháil ón bhfreastalaí seo agus déanfar sonraí a thagann isteach uaidh a phróiseáil agus a stóráil + email_domain_block: + domain: Is féidir gurb é seo an t-ainm fearainn a thaispeánann sa seoladh ríomhphoist nó sa taifead MX a úsáideann sé. Déanfar iad a sheiceáil nuair a chláraítear iad. + with_dns_records: Déanfar iarracht taifid DNS an fhearainn tugtha a réiteach agus cuirfear bac ar na torthaí freisin + featured_tag: + name: 'Seo cuid de na hashtags a d’úsáid tú le déanaí:' + filters: + action: Roghnaigh an gníomh ba cheart a dhéanamh nuair a mheaitseálann postáil an scagaire + actions: + hide: Cuir an t-ábhar scagtha i bhfolach go hiomlán, ag iompar amhail is nach raibh sé ann + warn: Folaigh an t-ábhar scagtha taobh thiar de rabhadh a luann teideal an scagaire + form_admin_settings: + activity_api_enabled: Áireamh na bpost a foilsíodh go háitiúil, úsáideoirí gníomhacha, agus clárúcháin nua i buicéid seachtainiúla + app_icon: WEBP, PNG, GIF nó JPG. Sáraíonn sé an deilbhín réamhshocraithe aipe ar ghléasanna soghluaiste le deilbhín saincheaptha. + backups_retention_period: Tá an cumas ag úsáideoirí cartlanna dá gcuid post a ghiniúint le híoslódáil níos déanaí. Nuair a bheidh luach dearfach socraithe, scriosfar na cartlanna seo go huathoibríoch ó do stór tar éis an líon sonraithe laethanta. + bootstrap_timeline_accounts: Cuirfear na cuntais seo ar bharr na moltaí a leanann úsáideoirí nua. + closed_registrations_message: Ar taispeáint nuair a dhúntar clárúcháin + content_cache_retention_period: Scriosfar gach postáil ó fhreastalaithe eile (lena n-áirítear treisithe agus freagraí) tar éis an líon sonraithe laethanta, gan aird ar aon idirghníomhaíocht úsáideora áitiúil leis na postálacha sin. Áirítear leis seo postálacha ina bhfuil úsáideoir áitiúil tar éis é a mharcáil mar leabharmharcanna nó mar cheanáin. Caillfear tagairtí príobháideacha idir úsáideoirí ó chásanna éagsúla freisin agus ní féidir iad a athchóiriú. Tá úsáid an tsocraithe seo beartaithe le haghaidh cásanna sainchuspóra agus sáraítear go leor ionchais úsáideoirí nuair a chuirtear i bhfeidhm é le haghaidh úsáid ghinearálta. + custom_css: Is féidir leat stíleanna saincheaptha a chur i bhfeidhm ar an leagan gréasáin de Mastodon. + favicon: WEBP, PNG, GIF nó JPG. Sáraíonn sé an favicon Mastodon réamhshocraithe le deilbhín saincheaptha. + mascot: Sáraíonn sé an léaráid san ardchomhéadan gréasáin. + media_cache_retention_period: Déantar comhaid meán ó phoist a dhéanann cianúsáideoirí a thaisceadh ar do fhreastalaí. Nuair a bheidh luach dearfach socraithe, scriosfar na meáin tar éis an líon sonraithe laethanta. Má iarrtar na sonraí meán tar éis é a scriosadh, déanfar é a ath-íoslódáil, má tá an t-ábhar foinse fós ar fáil. Mar gheall ar shrianta ar cé chomh minic is atá cártaí réamhamhairc ag vótaíocht do shuíomhanna tríú páirtí, moltar an luach seo a shocrú go 14 lá ar a laghad, nó ní dhéanfar cártaí réamhamhairc naisc a nuashonrú ar éileamh roimh an am sin. + peers_api_enabled: Liosta de na hainmneacha fearainn ar tháinig an freastalaí seo orthu sa choinbhleacht. Níl aon sonraí san áireamh anseo faoi cé acu an ndéanann tú cónascadh le freastalaí ar leith, díreach go bhfuil a fhios ag do fhreastalaí faoi. Úsáideann seirbhísí a bhailíonn staitisticí ar chónaidhm go ginearálta é seo. + profile_directory: Liostaíonn an t-eolaire próifíle na húsáideoirí go léir a roghnaigh isteach le bheith in-aimsithe. + require_invite_text: Nuair a bhíonn faomhadh láimhe ag teastáil le haghaidh clárúcháin, déan an "Cén fáth ar mhaith leat a bheith páirteach?" ionchur téacs éigeantach seachas roghnach + site_contact_email: Conas is féidir le daoine dul i dteagmháil leat le haghaidh fiosrúchán dlíthiúil nó tacaíochta. + site_contact_username: Conas is féidir le daoine dul i dteagmháil leat ar Mastodon. + site_extended_description: Aon fhaisnéis bhreise a d’fhéadfadh a bheith úsáideach do chuairteoirí agus d’úsáideoirí. Is féidir é a struchtúrú le comhréir Markdown. + site_short_description: Cur síos gairid chun cabhrú le do fhreastalaí a aithint go uathúil. Cé atá á rith, cé dó a bhfuil sé? + site_terms: Bain úsáid as do pholasaí príobháideachta féin nó fág bán é chun an réamhshocrú a úsáid. Is féidir é a struchtúrú le comhréir Markdown. + site_title: Conas is féidir le daoine tagairt a dhéanamh do do fhreastalaí seachas a ainm fearainn. + status_page_url: URL leathanach inar féidir le daoine stádas an fhreastalaí seo a fheiceáil le linn briseadh amach + theme: Téama a fheiceann cuairteoirí logáilte amach agus úsáideoirí nua. + thumbnail: Íomhá thart ar 2:1 ar taispeáint taobh le faisnéis do fhreastalaí. + timeline_preview: Beidh cuairteoirí logáilte amach in ann na postálacha poiblí is déanaí atá ar fáil ar an bhfreastalaí a bhrabhsáil. + trendable_by_default: Léim ar athbhreithniú láimhe ar ábhar treochta. Is féidir míreanna aonair a bhaint as treochtaí fós tar éis an fhíric. + trends: Léiríonn treochtaí cé na postálacha, hashtags agus scéalta nuachta atá ag tarraingt ar do fhreastalaí. + trends_as_landing_page: Taispeáin inneachar treochta d'úsáideoirí agus do chuairteoirí atá logáilte amach in ionad cur síos ar an bhfreastalaí seo. Éilíonn treochtaí a chumasú. + form_challenge: + current_password: Tá tú ag dul isteach i limistéar slán + imports: + data: Comhad CSV easpórtáilte ó fhreastalaí Mastodon eile + invite_request: + text: Cabhróidh sé seo linn d’iarratas a athbhreithniú + ip_block: + comment: Roghnach. Cuimhnigh cén fáth ar chuir tú an riail seo leis. + expires_in: Is acmhainn chríochta iad seoltaí IP, uaireanta roinntear iad agus is minic a athraíonn lámha. Ar an gcúis seo, ní mholtar bloic IP éiginnte. + ip: Cuir isteach seoladh IPv4 nó IPv6. Is féidir leat raonta iomlána a bhlocáil ag baint úsáide as an chomhréir CIDR. Bí cúramach gan tú féin a ghlasáil amach! + severities: + no_access: Cuir bac ar rochtain ar na hacmhainní go léir + sign_up_block: Ní bheidh clárú nua indéanta + sign_up_requires_approval: Beidh do cheadú ag teastáil le haghaidh clárúcháin nua + severity: Roghnaigh cad a tharlóidh le hiarratais ón IP seo + rule: + hint: Roghnach. Tabhair tuilleadh sonraí faoin riail + text: Déan cur síos ar riail nó riachtanas d'úsáideoirí ar an bhfreastalaí seo. Déan iarracht é a choinneáil gearr agus simplí + sessions: + otp: 'Cuir isteach an cód dhá fhachtóir ginte ag d''aip ghutháin nó úsáid ceann de do chóid athshlánaithe:' + webauthn: Más eochair USB atá ann déan cinnte é a chur isteach agus, más gá, tapáil í. + settings: + indexable: Seans go mbeidh do leathanach próifíle le feiceáil i dtorthaí cuardaigh ar Google, Bing agus eile. + show_application: Beidh tú in ann a fheiceáil i gcónaí cén aip a d’fhoilsigh do phostáil beag beann ar. + tag: + name: Ní féidir leat ach cásáil na litreacha a athrú, mar shampla, chun é a dhéanamh níos inléite + user: + chosen_languages: Nuair a dhéantar iad a sheiceáil, ní thaispeánfar ach postálacha i dteangacha roghnaithe in amlínte poiblí + role: Rialaíonn an ról na ceadanna atá ag an úsáideoir + user_role: + color: Dath le húsáid don ról ar fud an Chomhéadain, mar RGB i bhformáid heicsidheachúlach + highlighted: Déanann sé seo an ról le feiceáil go poiblí + name: Ainm poiblí an róil, má tá an ról socraithe le taispeáint mar shuaitheantas + permissions_as_keys: Beidh rochtain ag úsáideoirí a bhfuil an ról seo acu ar... + position: Cinneann ról níos airde réiteach coinbhleachta i gcásanna áirithe. Ní féidir gníomhartha áirithe a dhéanamh ach amháin ar róil a bhfuil tosaíocht níos ísle acu + webhook: + events: Roghnaigh imeachtaí le seoladh + template: Cum do phálasta JSON féin ag baint úsáide as idirshuíomh athróg. Fág bán le haghaidh JSON réamhshocraithe. + url: An áit a seolfar imeachtaí chuig labels: account: + discoverable: Próifíl gné agus postálacha in halgartaim fionnachtana fields: name: Lipéad + value: Ábhar + indexable: Cuir postálacha poiblí san áireamh sna torthaí cuardaigh + show_collections: Taispeáin seo a leanas agus leanúna ar phróifíl + unlocked: Glac le leantóirí nua go huathoibríoch + account_alias: + acct: Láimhseáil an seanchuntais + account_migration: + acct: Láimhseáil an chuntais nua account_warning_preset: + text: Téacs réamhshocraithe title: Teideal admin_account_action: + include_statuses: Cuir postálacha tuairiscithe san áireamh sa ríomhphost + send_email_notification: Cuir an t-úsáideoir ar an eolas trí ríomhphost text: Rabhadh saincheaptha + type: Gníomh types: disable: Reoigh none: Seol rabhadh + sensitive: Íogair silence: Teorannaigh suspend: Cuir ar fionraí + warning_preset_id: Bain úsáid as réamhshocrú rabhaidh announcement: + all_day: Imeacht uile-lae + ends_at: Deireadh an imeachta + scheduled_at: Foilsiú sceideal + starts_at: Tús na hócáide text: Fógra + appeal: + text: Mínigh cén fáth ar cheart an cinneadh seo a fhreaschur defaults: + autofollow: Tabhair cuireadh do chuntas a leanúint avatar: Abhatár + bot: Is cuntas uathoibrithe é seo + chosen_languages: Scag teangacha + confirm_new_password: Deimhnigh pasfhocal nua + confirm_password: Deimhnigh Pasfhocal + context: Comhthéacsanna a scagadh + current_password: Pasfhocal reatha data: Sonraí display_name: Ainm taispeána email: Seoladh ríomhphoist + expires_in: In éag tar éis + fields: Réimsí breise header: Ceanntásc + honeypot: "%{label} (ná líon isteach)" + inbox_url: URL an bhosca isteach sealaíochta + irreversible: Droim ar aghaidh in ionad bheith ag folaigh + locale: Teanga comhéadan + max_uses: Uaslíon úsáidí new_password: Pasfhocal nua note: Beathaisnéis + otp_attempt: Cód dhá-fhachtóir password: Pasfhocal + phrase: Eochairfhocal nó frása + setting_advanced_layout: Cumasaigh ardchomhéadan gréasáin + setting_aggregate_reblogs: Treisithe grúpa i línte ama + setting_always_send_emails: Seol fógraí ríomhphoist i gcónaí + setting_auto_play_gif: Gifs beoite go huathoibríoch a imirt + setting_boost_modal: Taispeáin dialóg deimhnithe roimh threisiú + setting_default_language: Teanga postála + setting_default_privacy: Postáil príobháideachta + setting_default_sensitive: Marcáil na meáin mar íogair i gcónaí + setting_delete_modal: Taispeáin dialóg deimhnithe sula scriostar postáil + setting_disable_hover_cards: Díchumasaigh réamhamharc próifíle ar ainlíon + setting_disable_swiping: Díchumasaigh gluaiseachtaí swiping + setting_display_media: Taispeáint meáin setting_display_media_default: Réamhshocrú setting_display_media_hide_all: Cuir uile i bhfolach setting_display_media_show_all: Taispeáin uile + setting_expand_spoilers: Méadaigh postálacha atá marcáilte le rabhaidh inneachair i gcónaí + setting_hide_network: Folaigh do ghraf sóisialta + setting_reduce_motion: Laghdú ar an tairiscint i beochan + setting_system_font_ui: Úsáid cló réamhshocraithe an chórais setting_theme: Téama suímh setting_trends: Taispeáin treochtaí an lae inniu + setting_unfollow_modal: Taispeáin dialóg deimhnithe sula ndíleanfaidh tú duine éigin + setting_use_blurhash: Taispeáin grádáin ildaite do mheáin fholaithe + setting_use_pending_items: Modh mall + severity: Déine + sign_in_token_attempt: Cód slándála title: Teideal + type: Cineál iompórtála username: Ainm úsáideora + username_or_email: Ainm Úsáideora nó Ríomhphost + whole_word: Focal ar fad + email_domain_block: + with_dns_records: Cuir taifid MX agus IPanna an fhearainn san áireamh featured_tag: name: Haischlib filters: @@ -50,27 +242,100 @@ ga: hide: Cuir i bhfolach go hiomlán warn: Cuir i bhfolach le rabhadh form_admin_settings: + activity_api_enabled: Foilsigh staitisticí comhiomlána faoi ghníomhaíocht úsáideoirí san API + app_icon: Deilbhín aip + backups_retention_period: Tréimhse choinneála cartlainne úsáideora + bootstrap_timeline_accounts: Mol na cuntais seo d'úsáideoirí nua i gcónaí + closed_registrations_message: Teachtaireacht saincheaptha nuair nach bhfuil sínithe suas ar fáil + content_cache_retention_period: Tréimhse choinneála inneachair cianda + custom_css: CSS saincheaptha + favicon: Favicon + mascot: Mascóg saincheaptha (oidhreacht) + media_cache_retention_period: Tréimhse choinneála taisce meán + peers_api_enabled: Foilsigh liosta de na freastalaithe aimsithe san API + profile_directory: Cumasaigh eolaire próifíle + registrations_mode: Cé atá in ann clárú + require_invite_text: A cheangal ar chúis a bheith páirteach + show_domain_blocks: Taispeáin bloic fearainn + show_domain_blocks_rationale: Taispeáin cén fáth ar cuireadh bac ar fhearann + site_contact_email: R-phost teagmhála + site_contact_username: Ainm úsáideora teagmhála site_extended_description: Cur síos fada site_short_description: Cur síos freastalaí site_terms: Polasaí príobháideachais site_title: Ainm freastalaí + status_page_url: URL an leathanaigh stádais + theme: Téama réamhshocraithe + thumbnail: Mionsamhail freastalaí + timeline_preview: Ceadaigh rochtain neamhdheimhnithe ar amlínte poiblí + trendable_by_default: Ceadaigh treochtaí gan athbhreithniú roimh ré + trends: Cumasaigh treochtaí + trends_as_landing_page: Úsáid treochtaí mar an leathanach tuirlingthe + interactions: + must_be_follower: Cuir bac ar fhógraí ó dhaoine nach leantóirí iad + must_be_following: Cuir bac ar fhógraí ó dhaoine nach leanann tú + must_be_following_dm: Cuir bac ar theachtaireachtaí díreacha ó dhaoine nach leanann tú invite: comment: Ráiteas + invite_request: + text: Cén fáth ar mhaith leat a bheith páirteach? ip_block: comment: Ráiteas ip: IP + severities: + no_access: Rochtain a bhlocáil + sign_up_block: Cuir bac ar chlárúcháin + sign_up_requires_approval: Teorainn le clárú severity: Riail notification_emails: + appeal: Déanann duine éigin achomharc i gcoinne chinneadh modhnóra + digest: Seol r-phoist achoimre + favourite: Is fearr le duine éigin do phostáil follow: Lean duine éigin tú + follow_request: D'iarr duine éigin tú a leanúint + mention: Luaigh duine éigin tú + pending_account: Ní mór athbhreithniú a dhéanamh ar chuntas nua reblog: Mhol duine éigin do phostáil + report: Tá tuairisc nua curtha isteach + software_updates: + all: Fógra a thabhairt ar gach nuashonrú + critical: Fógra a thabhairt ar nuashonruithe ríthábhachtacha amháin + label: Tá leagan nua Mastodon ar fáil + none: Ná cuir nuashonruithe ar an eolas choíche (ní mholtar é) + patch: Fógra ar nuashonruithe bugfix + trending_tag: Teastaíonn athbhreithniú ar threocht nua rule: + hint: Eolas breise text: Riail + settings: + indexable: Cuir leathanach próifíle san innill chuardaigh + show_application: Taispeáin cén aip ónar sheol tú postáil tag: + listable: Lig don hashchlib seo a bheith le feiceáil i gcuardach agus i moltaí name: Haischlib + trendable: Lig don haischlib seo a bheith le feiceáil faoi threochtaí + usable: Lig do phostálacha an hashchlib seo a úsáid user: role: Ról + time_zone: Crios ama user_role: + color: Dath suaitheantas + highlighted: Taispeáin ról mar shuaitheantas ar phróifílí úsáideora name: Ainm + permissions_as_keys: Ceadanna + position: Tosaíocht + webhook: + events: Imeachtaí cumasaithe + template: Teimpléad pá-ualach + url: URL críochphointe + 'no': Níl + not_recommended: Ní mholtar + overridden: Sáraithe recommended: Molta required: mark: "*" + text: ag teastáil + title: + sessions: + webauthn: Úsáid ceann de d'eochracha slándála chun síniú isteach + 'yes': Tá diff --git a/config/locales/simple_form.gl.yml b/config/locales/simple_form.gl.yml index 0653d7620430ec..57bf31b42d2851 100644 --- a/config/locales/simple_form.gl.yml +++ b/config/locales/simple_form.gl.yml @@ -243,11 +243,13 @@ gl: warn: Agochar tras un aviso form_admin_settings: activity_api_enabled: Publicar na API estatísticas agregadas acerca da actividade das usuarias + app_icon: Icona da app backups_retention_period: Período de retención do arquivo da usuaria bootstrap_timeline_accounts: Recomendar sempre estas contas ás novas usuarias closed_registrations_message: Mensaxe personalizada para cando o rexistro está pechado content_cache_retention_period: Período de retención de contido remoto custom_css: CSS personalizado + favicon: Favicon mascot: Mascota propia (herdado) media_cache_retention_period: Período de retención da caché multimedia peers_api_enabled: Publicar na API unha lista dos servidores descubertos diff --git a/config/locales/simple_form.he.yml b/config/locales/simple_form.he.yml index 1331d2f62bc157..f79ddb9b34e832 100644 --- a/config/locales/simple_form.he.yml +++ b/config/locales/simple_form.he.yml @@ -243,11 +243,13 @@ he: warn: הסתרה עם אזהרה form_admin_settings: activity_api_enabled: פרסום סטטיסטיקות מקובצות עבור פעילות משתמשים באמצעות מנשק התוכנה + app_icon: אייקון יישומון backups_retention_period: תקופת השמירה של ארכיון המשתמש bootstrap_timeline_accounts: המלצה על חשבונות אלה למשתמשים חדשים closed_registrations_message: הודעה מיוחדת כשההרשמה לא מאופשרת content_cache_retention_period: תקופת השמירה על תוכן חיצוני custom_css: CSS בהתאמה אישית + favicon: סמל מועדפים (Favicon) mascot: סמל השרת (ישן) media_cache_retention_period: תקופת שמירת מטמון מדיה peers_api_enabled: פרסם רשימה של שרתים שנתגלו באמצעות ה-API diff --git a/config/locales/simple_form.hu.yml b/config/locales/simple_form.hu.yml index 6ccca2bc847928..518a82ec163a99 100644 --- a/config/locales/simple_form.hu.yml +++ b/config/locales/simple_form.hu.yml @@ -211,6 +211,7 @@ hu: setting_default_privacy: Bejegyzések láthatósága setting_default_sensitive: Minden médiafájl megjelölése kényesként setting_delete_modal: Megerősítés kérése bejegyzés törlése előtt + setting_disable_hover_cards: Profilelőnézet letiltása föléhúzás esetén setting_disable_swiping: Elhúzás művelet kikapcsolása setting_display_media: Média megjelenítése setting_display_media_default: Alapértelmezés @@ -242,11 +243,13 @@ hu: warn: Elrejtés figyelmeztetéssel form_admin_settings: activity_api_enabled: Összesített statisztikák közzététele az API-ban a felhasználók aktivitásáról + app_icon: Alkalmazásikon backups_retention_period: Felhasználói archívum megtartási időszaka bootstrap_timeline_accounts: Mindig javasoljuk ezeket a fiókokat az új felhasználók számára closed_registrations_message: A feliratkozáskor megjelenő egyéni üzenet nem érhető el content_cache_retention_period: Távoli tartalmak megtartási időszaka custom_css: Egyéni CSS + favicon: Könyvjelzőikon mascot: Egyéni kabala (örökölt) media_cache_retention_period: Média-gyorsítótár megtartási időszaka peers_api_enabled: Felfedezett kiszolgálók listájának közzététele az API-ban diff --git a/config/locales/simple_form.is.yml b/config/locales/simple_form.is.yml index cc267db8d5629e..9e28ef9be695b9 100644 --- a/config/locales/simple_form.is.yml +++ b/config/locales/simple_form.is.yml @@ -243,11 +243,13 @@ is: warn: Fela með aðvörun form_admin_settings: activity_api_enabled: Birta samantektartölfræði um virkni notanda í API-kerfisviðmótinu + app_icon: Táknmynd forrits backups_retention_period: Tímalengd sem safni notandans er haldið eftir bootstrap_timeline_accounts: Alltaf mæla með þessum notendaaðgöngum fyrir nýja notendur closed_registrations_message: Sérsniðin skilaboð þegar ekki er hægt að nýskrá content_cache_retention_period: Tímabil sem á að geyma fjartengt efni custom_css: Sérsniðið CSS + favicon: Auðkennismynd mascot: Sérsniðið gæludýr (eldra) media_cache_retention_period: Tímalengd sem myndefni haldið peers_api_enabled: Birta lista yfir uppgötvaða netþjóna í API-kerfisviðmótinu diff --git a/config/locales/simple_form.it.yml b/config/locales/simple_form.it.yml index 540812faa9958f..eddc86b4e11ad8 100644 --- a/config/locales/simple_form.it.yml +++ b/config/locales/simple_form.it.yml @@ -243,11 +243,13 @@ it: warn: Nascondi con avviso form_admin_settings: activity_api_enabled: Pubblica le statistiche aggregate sull'attività degli utenti nell'API + app_icon: Icona app backups_retention_period: Periodo di conservazione dell'archivio utente bootstrap_timeline_accounts: Consiglia sempre questi account ai nuovi utenti closed_registrations_message: Messaggio personalizzato quando le iscrizioni non sono disponibili content_cache_retention_period: Periodo di ritenzione del contenuto remoto custom_css: Personalizza CSS + favicon: Favicon mascot: Personalizza mascotte (legacy) media_cache_retention_period: Periodo di conservazione della cache multimediale peers_api_enabled: Pubblica l'elenco dei server scoperti nell'API diff --git a/config/locales/simple_form.ja.yml b/config/locales/simple_form.ja.yml index b23f381d3bdddf..7b54937a6b1a45 100644 --- a/config/locales/simple_form.ja.yml +++ b/config/locales/simple_form.ja.yml @@ -361,6 +361,7 @@ ja: exclude_quote: 引用の内容をフィルターの対象にしない form_admin_settings: activity_api_enabled: APIでユーザーアクティビティに関する集計統計を公開する + app_icon: アプリアイコン backups_retention_period: ユーザーアーカイブの保持期間 bootstrap_timeline_accounts: おすすめユーザーに常に表示するアカウント check_lts_version_only: 更新チェックの時、LTSバージョンのみ確認する @@ -372,6 +373,7 @@ ja: enable_local_timeline: ローカルタイムラインを有効にする enable_public_unlisted_visibility: 公開範囲「ローカル公開」と検索許可「ローカルとフォロワー」を有効にする enable_public_visibility: 公開範囲「公開」を有効にする + favicon: ブックマークアイコン mascot: カスタムマスコット(レガシー) media_cache_retention_period: メディアキャッシュの保持期間 peers_api_enabled: 発見したサーバーのリストをAPIで公開する diff --git a/config/locales/simple_form.kab.yml b/config/locales/simple_form.kab.yml index 63e2b9aacf1bf6..b4c0e0032bb3f5 100644 --- a/config/locales/simple_form.kab.yml +++ b/config/locales/simple_form.kab.yml @@ -11,14 +11,14 @@ kab: account_migration: acct: Sekcem isem n umseqdac@taγult n umiḍan anida itebγiḍ ad gujjeḍ admin_account_action: - send_email_notification: Amseqdac ad t-id-yewweḍ usefhem γef wayen yeḍran akked umiḍan-is + send_email_notification: Amseqdac ad t-id-yewweḍ usefhem ɣef wayen yeḍran akked umiḍan-is type_html: Fren d acu ara txedmeḍ s %{acct} defaults: autofollow: Imdanen ara ijerrden s usnebgi-inek, ad k-ḍefṛen s wudem awurman bot: Smekti-d wiyaḍ dakken amiḍan-a ixeddem s wudem amezwer tigawin tiwurmanin yernu ur yezmir ara ad yettwaɛass email: Ad n-teṭṭfeḍ imayl i usentem irreversible: Tisuffaɣ i tessazedgeḍ ad ttwakksent i lebda, ula ma tekkseḍ imsizdeg-nni ar zdat - locale: Tutlayt n ugrudem, imaylen d tilγa + locale: Tutlayt n ugrudem, imaylen d walɣuten yettudemren password: Seqdec ma drus 8 n yisekkilen setting_display_media_default: Ffer teywalt yettwacreḍ d tanafrit setting_display_media_hide_all: Ffer yal tikkelt akk taywalt @@ -29,7 +29,7 @@ kab: imports: data: Afaylu CSV id yusan seg uqeddac-nniḍen n Maṣṭudun invite_request: - text: Aya ad aɣ-iɛiwen ad nessenqed tuttra-k•m + text: Aya ad aɣ-iɛiwen ad nessenqed tuttra-k·m ip_block: comment: D afrayan. Cfu ɣef wayɣer i terniḍ alugen-a. severities: @@ -86,6 +86,7 @@ kab: setting_advanced_layout: Rmed agrudem n web leqqayen setting_default_language: Tutlayt n tira setting_default_privacy: Tabaḍnit n tira + setting_display_media: Askanay n imidyaten setting_display_media_default: Akk-a kan setting_display_media_hide_all: Ffer-iten akk setting_display_media_show_all: Sken-iten-id akk @@ -111,8 +112,8 @@ kab: theme: Asentel amezwer thumbnail: Tanfult n uqeddac interactions: - must_be_follower: Ssewḥel ilɣa sɣur wid akked tid ur yellin ara d imeḍfaren-ik·im - must_be_following: Ssewḥel ilɣa sɣur wid akked tid ur tettḍafareḍ ara + must_be_follower: Ssewḥel alɣuten sɣur wid akked tid ur yellin ara d imeḍfaren-ik·im + must_be_following: Ssewḥel alɣuten sɣur wid akked tid ur tettḍafareḍ ara must_be_following_dm: Sewḥel iznan usriden sɣur wid akked tid ur tettḍafareḍ ara invite: comment: Awennit diff --git a/config/locales/simple_form.ko.yml b/config/locales/simple_form.ko.yml index 1107e4cba5b736..b94b4b3d40425b 100644 --- a/config/locales/simple_form.ko.yml +++ b/config/locales/simple_form.ko.yml @@ -243,11 +243,13 @@ ko: warn: 경고와 함께 숨기기 form_admin_settings: activity_api_enabled: API에 유저 활동에 대한 통계 발행 + app_icon: 앱 아이콘 backups_retention_period: 사용자 아카이브 유지 기한 bootstrap_timeline_accounts: 새로운 사용자들에게 추천할 계정들 closed_registrations_message: 가입이 불가능 할 때의 사용자 지정 메시지 content_cache_retention_period: 리모트 콘텐츠 보유 기간 custom_css: 사용자 정의 CSS + favicon: 파비콘 mascot: 사용자 정의 마스코트 (legacy) media_cache_retention_period: 미디어 캐시 유지 기한 peers_api_enabled: API에 발견 된 서버들의 목록 발행 diff --git a/config/locales/simple_form.lad.yml b/config/locales/simple_form.lad.yml index cef58e46016011..65647a77dbb47e 100644 --- a/config/locales/simple_form.lad.yml +++ b/config/locales/simple_form.lad.yml @@ -241,6 +241,7 @@ lad: bootstrap_timeline_accounts: Rekomenda siempre estos kuentos a muevos utilizadores closed_registrations_message: Mesaj personalizado kuando las enrejistrasyones no estan desponivles custom_css: CSS personalizado + favicon: Ikona de favoritos mascot: Maskota personalizada (legado) media_cache_retention_period: Periodo de retensyon de kashe multimedia peers_api_enabled: Publika lista de sirvidores diskuviertos en la API diff --git a/config/locales/simple_form.lt.yml b/config/locales/simple_form.lt.yml index feec37ae003676..b31803409b3976 100644 --- a/config/locales/simple_form.lt.yml +++ b/config/locales/simple_form.lt.yml @@ -137,6 +137,7 @@ lt: setting_default_privacy: Skelbimo privatumas setting_default_sensitive: Visada žymėti mediją kaip jautrią setting_delete_modal: Rodyti patvirtinimo dialogą prieš ištrinant įrašą + setting_disable_hover_cards: Išjungti profilio peržiūrą užvedus setting_disable_swiping: Išjungti perbraukimo judėjimus setting_display_media: Medijos rodymas setting_display_media_hide_all: Slėpti viską @@ -164,9 +165,11 @@ lt: warn: Slėpti su įspėjimu form_admin_settings: activity_api_enabled: Skelbti suvestinį statistiką apie naudotojų veiklą per API + app_icon: Programėlės piktograma bootstrap_timeline_accounts: Visada rekomenduoti šias paskyras naujiems naudotojams content_cache_retention_period: Nuotolinio turinio saugojimo laikotarpis custom_css: Pasirinktinis CSS + favicon: Svetainės piktograma mascot: Pasirinktinis talismanas (pasenęs) registrations_mode: Kas gali užsiregistruoti require_invite_text: Reikalauti priežasties prisijungti diff --git a/config/locales/simple_form.nl.yml b/config/locales/simple_form.nl.yml index 5110e1e6d09b9a..56331934064401 100644 --- a/config/locales/simple_form.nl.yml +++ b/config/locales/simple_form.nl.yml @@ -243,11 +243,13 @@ nl: warn: Met een waarschuwing verbergen form_admin_settings: activity_api_enabled: Statistieken over gebruikersactiviteit via de API publiceren + app_icon: App-pictogram backups_retention_period: Bewaartermijn gebruikersarchief bootstrap_timeline_accounts: Accounts die altijd aan nieuwe gebruikers worden aanbevolen closed_registrations_message: Aangepast bericht wanneer registratie is uitgeschakeld content_cache_retention_period: Bewaartermijn voor externe inhoud custom_css: Aangepaste CSS + favicon: Favicon mascot: Aangepaste mascotte (legacy) media_cache_retention_period: Bewaartermijn mediacache peers_api_enabled: Lijst van bekende servers via de API publiceren diff --git a/config/locales/simple_form.nn.yml b/config/locales/simple_form.nn.yml index a200e1206e38e1..c9075a89c210e3 100644 --- a/config/locales/simple_form.nn.yml +++ b/config/locales/simple_form.nn.yml @@ -211,6 +211,7 @@ nn: setting_default_privacy: Privatliv setting_default_sensitive: Merk alltid media som nærtakande setting_delete_modal: Vis stadfesting før du slettar eit tut + setting_disable_hover_cards: Skru av profilvising når peikaren er over setting_disable_swiping: Skru av sveipebevegelser setting_display_media: Medievisning setting_display_media_default: Standard @@ -242,11 +243,13 @@ nn: warn: Gøym med ei åtvaring form_admin_settings: activity_api_enabled: Legg ut samla statistikk om brukaraktiviteten i APIet + app_icon: App-ikon backups_retention_period: Arkiveringsperiode for brukararkiv bootstrap_timeline_accounts: Tilrå alltid desse kontoane for nye brukarar closed_registrations_message: Eigendefinert melding når registrering ikkje er mogleg content_cache_retention_period: Oppbevaringstid for eksternt innhald custom_css: Egendefinert CSS + favicon: Favorittikon mascot: Eigendefinert maskot (eldre funksjon) media_cache_retention_period: Oppbevaringsperiode for mediebuffer peers_api_enabled: Legg ut ei liste over oppdaga tenarar i APIet diff --git a/config/locales/simple_form.pl.yml b/config/locales/simple_form.pl.yml index b8de10de26a336..39e1814195f877 100644 --- a/config/locales/simple_form.pl.yml +++ b/config/locales/simple_form.pl.yml @@ -243,11 +243,13 @@ pl: warn: Ukryj z ostrzeżeniem form_admin_settings: activity_api_enabled: Publikuj zagregowane statystyki dotyczące aktywności użytkownika w API + app_icon: Ikona aplikacji backups_retention_period: Okres przechowywania archiwum użytkownika bootstrap_timeline_accounts: Zawsze rekomenduj te konta nowym użytkownikom closed_registrations_message: Niestandardowa wiadomość, gdy rejestracje nie są dostępne content_cache_retention_period: Okres zachowywania zdalnych treści custom_css: Niestandardowy CSS + favicon: Favicon mascot: Własna ikona media_cache_retention_period: Okres przechowywania pamięci podręcznej peers_api_enabled: Opublikuj listę odkrytych serwerów w API diff --git a/config/locales/simple_form.pt-PT.yml b/config/locales/simple_form.pt-PT.yml index f993687b91bee4..ef7dfd00a80fa2 100644 --- a/config/locales/simple_form.pt-PT.yml +++ b/config/locales/simple_form.pt-PT.yml @@ -243,11 +243,13 @@ pt-PT: warn: Ocultar com um aviso form_admin_settings: activity_api_enabled: Publicar estatísticas agregadas sobre a atividade dos utilizadores na API + app_icon: Ícone da aplicação backups_retention_period: Período de retenção de arquivos de utilizador bootstrap_timeline_accounts: Recomendar sempre estas contas para novos utilizadores closed_registrations_message: Mensagem personalizada quando as inscrições não estiverem disponíveis content_cache_retention_period: Período de retenção de conteúdos remotos custom_css: CSS personalizado + favicon: Ícone de favoritos mascot: Mascote personalizada (legado) media_cache_retention_period: Período de retenção de ficheiros de media em cache peers_api_enabled: Publicar lista de servidores descobertos na API diff --git a/config/locales/simple_form.sl.yml b/config/locales/simple_form.sl.yml index 14551774fe0b29..a937f17206e465 100644 --- a/config/locales/simple_form.sl.yml +++ b/config/locales/simple_form.sl.yml @@ -243,11 +243,13 @@ sl: warn: Skrij z opozorilom form_admin_settings: activity_api_enabled: Objavi združeno statistiko o dejavnosti uporabnikov v API-ju + app_icon: Ikona programa backups_retention_period: Obdobje hrambe arhivov uporabnikov bootstrap_timeline_accounts: Vedno priporočaj te račune novim uporabnikom closed_registrations_message: Sporočilo po meri, ko registracije niso na voljo content_cache_retention_period: Obdobje hranjenja vsebine z ostalih strežnikov custom_css: CSS po meri + favicon: Ikona spletne strani mascot: Maskota po meri (opuščeno) media_cache_retention_period: Obdobje hrambe predpomnilnika predstavnosti peers_api_enabled: Objavi seznam odkritih strežnikov v API-ju diff --git a/config/locales/simple_form.sq.yml b/config/locales/simple_form.sq.yml index 6fedf315724746..4236d7dce2673b 100644 --- a/config/locales/simple_form.sq.yml +++ b/config/locales/simple_form.sq.yml @@ -243,11 +243,13 @@ sq: warn: Fshihe me një sinjalizim form_admin_settings: activity_api_enabled: Publikoni te API statistika përmbledhëse rreth veprimtarisë së përdoruesve + app_icon: Ikonë aplikacioni backups_retention_period: Periudhë mbajtjeje arkivash përdoruesish bootstrap_timeline_accounts: Rekomandoju përherë këto llogari përdoruesve të rinj closed_registrations_message: Mesazh vetjak për pamundësi regjistrimesh të reja content_cache_retention_period: Periudhë mbajtjeje lënde të largët custom_css: CSS Vetjake + favicon: Favikonë mascot: Simbol vetjak (e dikurshme) media_cache_retention_period: Periudhë mbajtjeje lënde media peers_api_enabled: Publiko te API listë shërbyesish të zbuluar diff --git a/config/locales/simple_form.sr-Latn.yml b/config/locales/simple_form.sr-Latn.yml index 22c07aa7c65938..40b710b078e690 100644 --- a/config/locales/simple_form.sr-Latn.yml +++ b/config/locales/simple_form.sr-Latn.yml @@ -243,11 +243,13 @@ sr-Latn: warn: Sakrij uz upozorenje form_admin_settings: activity_api_enabled: Objavi prikupljenu statistiku o korisničkoj aktivnosti u API + app_icon: Ikonica aplikacije backups_retention_period: Period čuvanja korisničke arhive bootstrap_timeline_accounts: Uvek preporuči ove naloge novim korisnicima closed_registrations_message: Prilagođena poruka kada prijave nisu moguće content_cache_retention_period: Period zadržavanja udaljenog sadržaja custom_css: Prilagođeni CSS + favicon: Favikon mascot: Prilagođena maskota (nasleđe) media_cache_retention_period: Period čuvanja keša medija peers_api_enabled: Objavite listu otkrivenih servera u API diff --git a/config/locales/simple_form.sr.yml b/config/locales/simple_form.sr.yml index 10c1796637e999..c0a9ac2d8963c6 100644 --- a/config/locales/simple_form.sr.yml +++ b/config/locales/simple_form.sr.yml @@ -243,11 +243,13 @@ sr: warn: Сакриј уз упозорење form_admin_settings: activity_api_enabled: Објави прикупљену статистику о корисничкој активности у API + app_icon: Иконица апликације backups_retention_period: Период чувања корисничке архиве bootstrap_timeline_accounts: Увек препоручи ове налоге новим корисницима closed_registrations_message: Прилагођена порука када пријаве нису могуће content_cache_retention_period: Период задржавања удаљеног садржаја custom_css: Прилагођени CSS + favicon: Фавикон mascot: Прилагођена маскота (наслеђе) media_cache_retention_period: Период чувања кеша медија peers_api_enabled: Објавите листу откривених сервера у API diff --git a/config/locales/simple_form.sv.yml b/config/locales/simple_form.sv.yml index 11d142a2bd6d73..2281e4b4abe109 100644 --- a/config/locales/simple_form.sv.yml +++ b/config/locales/simple_form.sv.yml @@ -242,11 +242,13 @@ sv: warn: Dölj med en varning form_admin_settings: activity_api_enabled: Publicera aggregerad statistik om användaraktivitet i API:et + app_icon: Appikon backups_retention_period: Lagringsperiod för användararkivet bootstrap_timeline_accounts: Rekommendera alltid dessa konton till nya användare closed_registrations_message: Anpassat meddelande när nyregistreringar inte är tillgängliga content_cache_retention_period: Förvaringsperiod för fjärrinnehåll custom_css: Anpassad CSS + favicon: Favicon mascot: Anpassad maskot (tekniskt arv) media_cache_retention_period: Tid för bibehållande av mediecache peers_api_enabled: Publicera lista över upptäckta servrar i API:et diff --git a/config/locales/simple_form.tr.yml b/config/locales/simple_form.tr.yml index b1e90122eca499..f098bfd3ca6d32 100644 --- a/config/locales/simple_form.tr.yml +++ b/config/locales/simple_form.tr.yml @@ -243,11 +243,13 @@ tr: warn: Uyarıyla gizle form_admin_settings: activity_api_enabled: API'deki kullanıcı etkinliği hakkında toplu istatistikler yayınlayın + app_icon: Uygulama simgesi backups_retention_period: Kullanıcı arşivi saklama süresi bootstrap_timeline_accounts: Bu hesapları yeni kullanıcılara her zaman öner closed_registrations_message: Kayıt olma mevcut değilken gösterilen özel ileti content_cache_retention_period: Uzak içerik saklama süresi custom_css: Özel CSS + favicon: Yer imi simgesi mascot: Özel maskot (eski) media_cache_retention_period: Medya önbelleği saklama süresi peers_api_enabled: API'de keşfedilen sunucuların listesini yayınla diff --git a/config/locales/simple_form.uk.yml b/config/locales/simple_form.uk.yml index 332f2c91dc9daf..2f494534ea63b9 100644 --- a/config/locales/simple_form.uk.yml +++ b/config/locales/simple_form.uk.yml @@ -243,11 +243,13 @@ uk: warn: Сховати за попередженням form_admin_settings: activity_api_enabled: Публікація агрегованої статистики про активність користувачів + app_icon: Значок застосунку backups_retention_period: Період утримання архіву користувача bootstrap_timeline_accounts: Завжди рекомендувати новим користувачам ці облікові записи closed_registrations_message: Показуване повідомлення, якщо реєстрація недоступна content_cache_retention_period: Період збереження віддаленого вмісту custom_css: Користувацький CSS + favicon: Значок сайту mascot: Користувацький символ (застарілий) media_cache_retention_period: Період збереження кешу медіа peers_api_enabled: Опублікувати список знайдених серверів у API diff --git a/config/locales/simple_form.vi.yml b/config/locales/simple_form.vi.yml index 9006156db1a4c7..c45da4713718ca 100644 --- a/config/locales/simple_form.vi.yml +++ b/config/locales/simple_form.vi.yml @@ -243,11 +243,13 @@ vi: warn: Ẩn kèm theo cảnh báo form_admin_settings: activity_api_enabled: Công khai số liệu thống kê tổng hợp về hoạt động của người dùng trong API + app_icon: Biểu tượng ứng dụng backups_retention_period: Thời hạn lưu trữ nội dung người dùng sao lưu bootstrap_timeline_accounts: Luôn đề xuất những người này đến người mới closed_registrations_message: Thông báo tùy chỉnh khi tắt đăng ký content_cache_retention_period: Khoảng thời gian lưu giữ nội dung máy chủ khác custom_css: Tùy chỉnh CSS + favicon: Favicon mascot: Tùy chỉnh linh vật (kế thừa) media_cache_retention_period: Thời hạn lưu trữ cache media peers_api_enabled: Công khai danh sách các máy chủ được phát hiện trong API diff --git a/config/locales/simple_form.zh-CN.yml b/config/locales/simple_form.zh-CN.yml index bbee8b6706297b..ab440e04f43c7f 100644 --- a/config/locales/simple_form.zh-CN.yml +++ b/config/locales/simple_form.zh-CN.yml @@ -243,11 +243,13 @@ zh-CN: warn: 隐藏时显示警告信息 form_admin_settings: activity_api_enabled: 在 API 中发布有关用户活动的汇总统计数据 + app_icon: 应用图标 backups_retention_period: 用户存档保留期 bootstrap_timeline_accounts: 推荐新用户关注以下账号 closed_registrations_message: 在关闭注册时显示的自定义消息 content_cache_retention_period: 外站内容保留期 custom_css: 自定义 CSS + favicon: Favicon mascot: 自定义吉祥物(旧) media_cache_retention_period: 媒体缓存保留期 peers_api_enabled: 在API中公开的已知实例的服务器的列表 diff --git a/config/locales/simple_form.zh-TW.yml b/config/locales/simple_form.zh-TW.yml index 7c460a25f58e24..15ccaf8a17782d 100644 --- a/config/locales/simple_form.zh-TW.yml +++ b/config/locales/simple_form.zh-TW.yml @@ -24,7 +24,7 @@ zh-TW: type_html: 設定要使用 %{acct} 做的事 types: disable: 禁止該使用者使用他們的帳號,但是不刪除或隱藏他們的內容。 - none: 使用這個寄送警告給該使用者,而不進行其他動作。 + none: 使用這個寄送警告至該使用者,而不進行其他動作。 sensitive: 強制標記此使用者所有多媒體附加檔案為敏感內容。 silence: 禁止該使用者發公開嘟文,從無跟隨他們的帳號中隱藏嘟文與通知。關閉所有對此帳號之檢舉報告。 suspend: 禁止所有對該帳號任何互動,並且刪除其內容。三十天內可以撤銷此動作。關閉所有對此帳號之檢舉報告。 @@ -34,7 +34,7 @@ zh-TW: ends_at: 可選的。公告會於該時間點自動取消發布 scheduled_at: 空白則立即發布公告 starts_at: 可選的。使公告於特定時間範圍內顯示 - text: 您可以使用嘟文語法,但請小心別讓公告太鴨霸而佔據使用者的整個版面。 + text: 您可以使用嘟文語法,但請小心別使公告太鴨霸而佔據使用者的整個版面。 appeal: text: 您只能對警示提出一次申訴 defaults: @@ -47,7 +47,7 @@ zh-TW: digest: 僅於您長時間未登入且於未登入期間收到私訊時傳送 email: 您將收到一封確認電子郵件 header: 支援 WEBP、PNG、GIF 或 JPG 圖片格式,檔案最大為 %{size}。將等比例縮減至 %{dimensions} 像素 - inbox_url: 從您想要使用的中繼首頁複製網址 + inbox_url: 自您想要使用的中繼首頁複製網址 irreversible: 已過濾的嘟文將會不可逆地消失,即便之後移除過濾器也一樣 locale: 使用者介面、電子郵件與推播通知的語言 password: 使用至少 8 個字元 @@ -92,7 +92,7 @@ zh-TW: site_contact_email: 其他人如何聯繫您關於法律或支援之諮詢。 site_contact_username: 其他人如何於 Mastodon 上聯繫您。 site_extended_description: 任何其他可能對訪客或使用者有用的額外資訊。可由 Markdown 語法撰寫。 - site_short_description: 一段有助於辨別您伺服器的簡短說明。例如:誰運行該伺服器、該伺服器是提供給哪些人群? + site_short_description: 一段有助於辨別您伺服器的簡短說明。例如:誰運行該伺服器、該伺服器是提供至哪些人群? site_terms: 使用您自己的隱私權政策,或者保留空白以使用預設值。可由 Markdown 語法撰寫。 site_title: 除了網域外,其他人該如何指稱您的伺服器。 status_page_url: 當服務中斷時,可以提供使用者了解伺服器資訊頁面之 URL @@ -101,11 +101,11 @@ zh-TW: timeline_preview: 未登入之訪客能夠瀏覽此伺服器上最新的公開嘟文。 trendable_by_default: 跳過手動審核熱門內容。仍能於登上熱門趨勢後移除個別內容。 trends: 熱門趨勢將顯示於您伺服器上正在吸引大量注意力的嘟文、主題標籤、或者新聞。 - trends_as_landing_page: 顯示熱門趨勢內容給未登入使用者及訪客而不是關於此伺服器之描述。需要啟用熱門趨勢。 + trends_as_landing_page: 顯示熱門趨勢內容至未登入使用者及訪客而不是關於此伺服器之描述。需要啟用熱門趨勢。 form_challenge: current_password: 您正要進入安全區域 imports: - data: 從其他 Mastodon 伺服器匯出的 CSV 檔案 + data: 自其他 Mastodon 伺服器匯出的 CSV 檔案 invite_request: text: 這會協助我們審核您的申請 ip_block: @@ -133,7 +133,7 @@ zh-TW: role: 角色控制使用者有哪些權限 user_role: color: 於整個使用者介面中用於角色的顏色,十六進位格式的 RGB - highlighted: 這會使角色公開可見 + highlighted: 這將使角色公開可見 name: 角色的公開名稱,如果角色設定為顯示為徽章 permissions_as_keys: 有此角色的使用者將有權存取... position: 某些情況下,衝突的解決方式由更高階的角色決定。某些動作只能由優先程度較低的角色執行 @@ -243,11 +243,13 @@ zh-TW: warn: 隱藏於警告之後 form_admin_settings: activity_api_enabled: 於 API 中公開使用者活躍度的統計數據 + app_icon: 應用程式圖示 backups_retention_period: 使用者封存資料保留期間 - bootstrap_timeline_accounts: 永遠推薦這些帳號給新使用者 + bootstrap_timeline_accounts: 永遠推薦這些帳號至新使用者 closed_registrations_message: 當註冊關閉時的客製化訊息 content_cache_retention_period: 遠端內容保留期限 custom_css: 自訂 CSS + favicon: 網站圖示 (Favicon) mascot: 自訂吉祥物 (legacy) media_cache_retention_period: 多媒體快取資料保留期間 peers_api_enabled: 於 API 中公開已知伺服器的列表 diff --git a/config/locales/sl.yml b/config/locales/sl.yml index 6087b1a1749642..f63aadd6c8f794 100644 --- a/config/locales/sl.yml +++ b/config/locales/sl.yml @@ -232,6 +232,7 @@ sl: update_custom_emoji: Posodobi emotikon po meri update_domain_block: Posodobi blokado domene update_ip_block: Posodobi pravilo IP + update_report: Posodobi poročilo update_status: Posodobi objavo update_user_role: Posodobi vlogo actions: @@ -662,6 +663,7 @@ sl: report: 'Prijavi #%{id}' reported_account: Prijavljeni račun reported_by: Prijavil/a + reported_with_application: Prijavljeno s programom resolved: Razrešeni resolved_msg: Prijava je uspešno razrešena! skip_to_actions: Preskoči na dejanja diff --git a/config/locales/sq.yml b/config/locales/sq.yml index 5439f08a04a8b2..c4bed80cc7cf47 100644 --- a/config/locales/sq.yml +++ b/config/locales/sq.yml @@ -226,6 +226,7 @@ sq: update_custom_emoji: Përditëso Emoxhi Vetjake update_domain_block: Përditëso Bllok Përkatësish update_ip_block: Përditësoni rregull IP + update_report: Përditësoni Raportimin update_status: Përditëso Gjendjen update_user_role: Përditësoni Rol actions: diff --git a/config/locales/sv.yml b/config/locales/sv.yml index 91b1720b553f2c..de2664f8b5f109 100644 --- a/config/locales/sv.yml +++ b/config/locales/sv.yml @@ -226,6 +226,7 @@ sv: update_custom_emoji: Uppdatera egna emojis update_domain_block: Uppdatera blockerad domän update_ip_block: Uppdatera IP-regel + update_report: Uppdatera rapport update_status: Uppdatera inlägg update_user_role: Uppdatera roll actions: diff --git a/config/locales/tr.yml b/config/locales/tr.yml index c690d22580cc20..9855b569241153 100644 --- a/config/locales/tr.yml +++ b/config/locales/tr.yml @@ -226,6 +226,7 @@ tr: update_custom_emoji: Özel İfadeyi Güncelle update_domain_block: Engellenen Alan Adını Güncelle update_ip_block: IP kuralını güncelle + update_report: Raporu Güncelle update_status: Durumu Güncelle update_user_role: Rolü Güncelle actions: @@ -638,6 +639,7 @@ tr: report: 'Şikayet #%{id}' reported_account: Şikayet edilen hesap reported_by: Şikayet eden + reported_with_application: Uygulamayla bildirildi resolved: Giderildi resolved_msg: Şikayet başarıyla çözümlendi! skip_to_actions: İşlemlere atla diff --git a/config/locales/uk.yml b/config/locales/uk.yml index 9994cd9d0dadc8..a5cdcfefb4cc0e 100644 --- a/config/locales/uk.yml +++ b/config/locales/uk.yml @@ -232,6 +232,7 @@ uk: update_custom_emoji: Оновити користувацькі емодзі update_domain_block: Оновити блокування домену update_ip_block: Оновити правило IP + update_report: Оновити звіт update_status: Оновити допис update_user_role: Оновити роль actions: @@ -662,6 +663,7 @@ uk: report: 'Скарга #%{id}' reported_account: Обліковий запис порушника reported_by: Відправник скарги + reported_with_application: Повідомлено через застосунок resolved: Вирішено resolved_msg: Скаргу успішно вирішено! skip_to_actions: Перейти до дій diff --git a/config/locales/vi.yml b/config/locales/vi.yml index 467356d65adfab..48e026d377ff87 100644 --- a/config/locales/vi.yml +++ b/config/locales/vi.yml @@ -223,6 +223,7 @@ vi: update_custom_emoji: Cập nhật emoji update_domain_block: Cập nhật máy chủ chặn update_ip_block: Cập nhật chặn IP + update_report: Cập nhật báo cáo update_status: Cập nhật tút update_user_role: Cập nhật vai trò actions: @@ -626,6 +627,7 @@ vi: report: 'Báo cáo #%{id}' reported_account: Tài khoản bị báo cáo reported_by: Báo cáo bởi + reported_with_application: Báo cáo bằng ứng dụng resolved: Đã xong resolved_msg: Đã xử lý báo cáo xong! skip_to_actions: Kiểm duyệt diff --git a/config/locales/zh-CN.yml b/config/locales/zh-CN.yml index 794b8344c10783..d2d64152fa7bcc 100644 --- a/config/locales/zh-CN.yml +++ b/config/locales/zh-CN.yml @@ -223,6 +223,7 @@ zh-CN: update_custom_emoji: 更新自定义表情符号 update_domain_block: 更新域名屏蔽 update_ip_block: 编辑 IP 封禁规则 + update_report: 更新举报 update_status: 更新嘟文 update_user_role: 更新角色 actions: @@ -626,6 +627,7 @@ zh-CN: report: '举报 #%{id}' reported_account: 举报用户 reported_by: 举报人 + reported_with_application: 举报人使用的应用 resolved: 已处理 resolved_msg: 举报处理成功! skip_to_actions: 跳转到操作 diff --git a/config/locales/zh-TW.yml b/config/locales/zh-TW.yml index 1317d5f70740a5..375c79048a4d71 100644 --- a/config/locales/zh-TW.yml +++ b/config/locales/zh-TW.yml @@ -223,11 +223,12 @@ zh-TW: update_custom_emoji: 更新自訂 emoji 表情符號 update_domain_block: 更新網域封鎖 update_ip_block: 更新 IP 規則 + update_report: 更新檢舉報告 update_status: 更新狀態 update_user_role: 更新角色 actions: approve_appeal_html: "%{name} 已批准來自 %{target} 的審核決定申訴" - approve_user_html: "%{name} 已批准從 %{target} 而來的註冊" + approve_user_html: "%{name} 已批准自 %{target} 而來的註冊" assigned_to_self_report_html: "%{name} 將報告 %{target} 指派給自己" change_email_user_html: "%{name} 已變更使用者 %{target} 的電子郵件地址" change_role_user_html: "%{name} 已變更 %{target} 的角色" @@ -264,10 +265,10 @@ zh-TW: memorialize_account_html: "%{name} 將 %{target} 設定為追悼帳號" promote_user_html: "%{name} 對使用者 %{target} 已進行晉級操作" reject_appeal_html: "%{name} 已回絕來自 %{target} 的審核決定申訴" - reject_user_html: "%{name} 已回絕從 %{target} 而來的註冊" + reject_user_html: "%{name} 已回絕自 %{target} 而來的註冊" remove_avatar_user_html: "%{name} 已移除 %{target} 的大頭貼" reopen_report_html: "%{name} 重新開啟 %{target} 的檢舉" - resend_user_html: "%{name} 已重新發送驗證信給 %{target}" + resend_user_html: "%{name} 已重新發送驗證信至 %{target}" reset_password_user_html: "%{name} 已重新設定使用者 %{target} 的密碼" resolve_report_html: "%{name} 已處理 %{target} 的檢舉" sensitive_account_html: "%{name} 將 %{target} 的媒體檔案標記為敏感內容" @@ -383,7 +384,7 @@ zh-TW: confirm: 停權 permanent_action: 撤銷停權將不會回復任何資料或跟隨關係 preamble_html: 您將要停權 %{domain} 及其子網域。 - remove_all_data: 此操作將從您伺服器移除所有來自此網域帳號之內容、媒體、個人檔案資料。 + remove_all_data: 此操作將自您伺服器移除所有來自此網域帳號之內容、媒體、個人檔案資料。 stop_communication: 您伺服器將停止與這些伺服器交流。 title: 確認對 %{domain} 網域之封鎖 undo_relationships: 此操作將撤銷任何您伺服器與此伺服器帳號間之跟隨關係。 @@ -555,11 +556,11 @@ zh-TW: relays: add_new: 新增中繼站 delete: 刪除 - description_html: "聯邦中繼站 是種中繼伺服器,會於訂閱並推送至此中繼站的伺服器之間交換大量的公開嘟文。中繼站也能協助小型或中型伺服器從聯邦宇宙中探索內容,而無須本地使用者手動跟隨遠端伺服器的其他使用者。" + description_html: "聯邦中繼站 是種中繼伺服器,會於訂閱並推送至此中繼站的伺服器之間交換大量的公開嘟文。中繼站也能協助小型或中型伺服器自聯邦宇宙中探索內容,而無須本地使用者手動跟隨遠端伺服器的其他使用者。" disable: 停用 disabled: 停用 enable: 啟用 - enable_hint: 啟用後,您的伺服器將訂閱該中繼的所有公開文章,並將會此伺服器的公開文章發送給它。 + enable_hint: 啟用後,您的伺服器將訂閱該中繼的所有公開文章,並將此伺服器的公開文章向它發送。 enabled: 已啟用 inbox_url: 中繼 URL pending: 等待中繼站審核 @@ -626,6 +627,7 @@ zh-TW: report: '檢舉 #%{id}' reported_account: 被檢舉使用者 reported_by: 檢舉人 + reported_with_application: 透過應用程式檢舉 resolved: 已解決 resolved_msg: 檢舉報告已處理完成! skip_to_actions: 跳過行動 @@ -648,7 +650,7 @@ zh-TW: delete_data_html: 於即日起 30 天後刪除 @%{acct}之個人檔案與內容,除非他們於期限前被解除停權 preview_preamble_html: "@%{acct} 將收到關於以下內容之警告:" record_strike_html: 紀錄關於 @%{acct}之警示有助於您升級對此帳號未來違規處理 - send_email_html: 寄一封警告 e-mail 給 @%{acct} + send_email_html: 寄一封警告 e-mail 至 @%{acct} warning_placeholder: 選填之其他站務動作理由。 target_origin: 檢舉帳號之來源 title: 檢舉 @@ -671,7 +673,7 @@ zh-TW: description_html: 透過使用者角色,您可以自訂您的使用者可以存取 Mastodon 的哪些功能與區域。 edit: 編輯「%{name}」角色 everyone: 預設權限 - everyone_full_description_html: 這是會影響所有使用者基本角色,即使是那些沒有被分配角色的使用者也一樣。其他所有的角色都從它繼承權限。 + everyone_full_description_html: 這是會影響所有使用者基本角色,即使是那些沒有被分配角色的使用者也一樣。其他所有的角色都自它繼承權限。 permissions_count: other: "%{count} 個權限" privileges: @@ -757,8 +759,8 @@ zh-TW: title: 探索 trends: 熱門趨勢 domain_blocks: - all: 給任何人 - disabled: 給沒有人 + all: 至任何人 + disabled: 至沒有人 users: 套用至所有登入的本站使用者 registrations: moderation_recommandation: 對所有人開放註冊之前,請確保您有人手充足且反應靈敏的管理員團隊! @@ -797,7 +799,7 @@ zh-TW: back_to_account: 返回帳號資訊頁面 back_to_report: 回到檢舉報告頁面 batch: - remove_from_report: 從檢舉報告中移除 + remove_from_report: 自檢舉報告中移除 report: 檢舉報告 deleted: 已刪除 favourites: 最愛 @@ -1055,7 +1057,7 @@ zh-TW: dont_have_your_security_key: 找不到您的安全金鑰? forgot_password: 忘記密碼? invalid_reset_password_token: 密碼重設 token 無效或已過期。請重新設定密碼。 - link_to_otp: 請從您手機輸入兩階段驗證 (2FA) 或備用驗證碼 + link_to_otp: 請自您手機輸入兩階段驗證 (2FA) 或備用驗證碼 link_to_webauth: 使用您的安全金鑰 log_in_with: 登入,使用 login: 登入 @@ -1138,7 +1140,7 @@ zh-TW: x_seconds: "%{count}秒" deletes: challenge_not_passed: 您所輸入的資料不正確 - confirm_password: 輸入您現在的密碼以驗證身份 + confirm_password: 輸入您目前的密碼以驗證身份 confirm_username: 請輸入您的使用者名稱以作確認 proceed: 刪除帳號 success_msg: 您的帳號已經成功刪除 @@ -1170,7 +1172,7 @@ zh-TW: recipient: 此致 reject_appeal: 駁回申訴 status: '嘟文編號 #%{id}' - status_removed: 嘟文已從系統中移除 + status_removed: 嘟文已自系統中移除 title: "%{action} 來自 %{date}" title_actions: delete_statuses: 嘟文移除 @@ -1238,10 +1240,10 @@ zh-TW: add_keyword: 新增關鍵字 keywords: 關鍵字 statuses: 各別嘟文 - statuses_hint_html: 此過濾器會套用至所選之各別嘟文,無論其是否符合下列關鍵字。審閱或從過濾條件移除嘟文。 + statuses_hint_html: 此過濾器會套用至所選之各別嘟文,無論其是否符合下列關鍵字。審閱或自過濾條件移除嘟文。 title: 編輯過濾條件 errors: - deprecated_api_multiple_keywords: 這些參數無法從此應用程式中更改,因為它們適用於一或多個過濾器關鍵字。請使用較新的應用程式或是網頁介面。 + deprecated_api_multiple_keywords: 這些參數無法自此應用程式中更改,因為它們適用於一或多個過濾器關鍵字。請使用較新的應用程式或是網頁介面。 invalid_context: 沒有提供內文或內文無效 index: contexts: "%{contexts} 中的過濾器" @@ -1262,7 +1264,7 @@ zh-TW: statuses: back_to_filter: 回到過濾器 batch: - remove: 從過濾器中移除 + remove: 自過濾器中移除 index: hint: 此過濾器會套用至所選之各別嘟文,不管它們有無符合其他條件。您可以從網頁介面中將更多嘟文加入至此過濾器。 title: 已過濾之嘟文 @@ -1419,7 +1421,7 @@ zh-TW: on_cooldown: 您最近已轉移過您的帳號。此功能將於 %{count} 天後可再度使用。 past_migrations: 以往的轉移紀錄 proceed_with_move: 移動跟隨者 - redirected_msg: 您的帳號現在指向 %{acct} + redirected_msg: 您的帳號目前重導向至 %{acct}。 redirecting_to: 您的帳號目前正被重新導向到 %{acct} set_redirect: 設定重新導向 warning: @@ -1552,7 +1554,7 @@ zh-TW: mutual: 跟隨彼此 primary: 主要 relationship: 關係 - remove_selected_domains: 從所選取網域中移除所有跟隨者 + remove_selected_domains: 自所選取網域中移除所有跟隨者 remove_selected_followers: 移除選取的跟隨者 remove_selected_follows: 取消跟隨選取的使用者 status: 帳號狀態 @@ -1599,7 +1601,7 @@ zh-TW: current_session: 目前的 session date: 日期 description: "%{platform} 上的 %{browser}" - explanation: 這些是現在正登入於您 Mastodon 帳號的瀏覽器。 + explanation: 這些是目前正登入於您 Mastodon 帳號的瀏覽器。 ip: IP 位址 platforms: adobe_air: Adobe Air diff --git a/config/routes.rb b/config/routes.rb index ac08a52b64a2bf..e102ed91642c43 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -33,6 +33,7 @@ def redirect_with_vary(path) /circles/(*any) /links/(*any) /notifications/(*any) + /notifications_v2/(*any) /favourites /emoji_reactions /bookmarks diff --git a/config/webpack/rules/babel.js b/config/webpack/rules/babel.js index c7bf886e795bf6..902b823e1f80aa 100644 --- a/config/webpack/rules/babel.js +++ b/config/webpack/rules/babel.js @@ -2,19 +2,19 @@ const { join, resolve } = require('path'); const { env, settings } = require('../configuration'); +// Those modules contain modern ES code that need to be transpiled for Webpack to process it +const nodeModulesToProcess = [ + '@reduxjs', 'fuzzysort' +]; + module.exports = { test: /\.(js|jsx|mjs|ts|tsx)$/, include: [ settings.source_path, ...settings.resolved_paths, - 'node_modules/@reduxjs' + ...nodeModulesToProcess.map(p => resolve(`node_modules/${p}`)), ].map(p => resolve(p)), - exclude: function(modulePath) { - return ( - /node_modules/.test(modulePath) && - !/@reduxjs/.test(modulePath) - ); - }, + exclude: new RegExp('node_modules\\/(?!(' + nodeModulesToProcess.join('|')+')\\/).*'), use: [ { loader: 'babel-loader', diff --git a/db/migrate/20240713171841_add_application_to_reports.rb b/db/migrate/20240713171841_add_application_to_reports.rb new file mode 100644 index 00000000000000..42ba14e9b260a0 --- /dev/null +++ b/db/migrate/20240713171841_add_application_to_reports.rb @@ -0,0 +1,8 @@ +# frozen_string_literal: true + +class AddApplicationToReports < ActiveRecord::Migration[7.1] + def change + add_column :reports, :application_id, :bigint, null: true + add_foreign_key :reports, :oauth_applications, column: :application_id, on_delete: :nullify, validate: false + end +end diff --git a/db/migrate/20240713171909_validate_add_application_to_reports.rb b/db/migrate/20240713171909_validate_add_application_to_reports.rb new file mode 100644 index 00000000000000..34ae690a3908e3 --- /dev/null +++ b/db/migrate/20240713171909_validate_add_application_to_reports.rb @@ -0,0 +1,7 @@ +# frozen_string_literal: true + +class ValidateAddApplicationToReports < ActiveRecord::Migration[7.1] + def change + validate_foreign_key :reports, :oauth_applications + end +end diff --git a/db/schema.rb b/db/schema.rb index 0673e3e252eb82..091e0d54522c15 100644 --- a/db/schema.rb +++ b/db/schema.rb @@ -10,7 +10,7 @@ # # It's strongly recommended that you check this file into your version control system. -ActiveRecord::Schema[7.1].define(version: 2024_07_12_064044) do +ActiveRecord::Schema[7.1].define(version: 2024_07_13_171909) do # These are extensions that must be enabled in order to support this database enable_extension "plpgsql" @@ -1229,6 +1229,7 @@ t.integer "category", default: 0, null: false t.datetime "action_taken_at", precision: nil t.bigint "rule_ids", array: true + t.bigint "application_id" t.index ["account_id"], name: "index_reports_on_account_id" t.index ["action_taken_by_account_id"], name: "index_reports_on_action_taken_by_account_id", where: "(action_taken_by_account_id IS NOT NULL)" t.index ["assigned_account_id"], name: "index_reports_on_assigned_account_id", where: "(assigned_account_id IS NOT NULL)" @@ -1749,6 +1750,7 @@ add_foreign_key "reports", "accounts", column: "assigned_account_id", on_delete: :nullify add_foreign_key "reports", "accounts", column: "target_account_id", name: "fk_eb37af34f0", on_delete: :cascade add_foreign_key "reports", "accounts", name: "fk_4b81f7522c", on_delete: :cascade + add_foreign_key "reports", "oauth_applications", column: "application_id", on_delete: :nullify add_foreign_key "scheduled_expiration_statuses", "accounts", on_delete: :cascade add_foreign_key "scheduled_expiration_statuses", "statuses", on_delete: :cascade add_foreign_key "scheduled_statuses", "accounts", on_delete: :cascade diff --git a/lib/tasks/statistics.rake b/lib/tasks/statistics.rake index dde7890f6b445d..82840f4fdc842e 100644 --- a/lib/tasks/statistics.rake +++ b/lib/tasks/statistics.rake @@ -9,11 +9,13 @@ namespace :mastodon do [ ['App Libraries', 'app/lib'], %w(Presenters app/presenters), + %w(Policies app/policies), + %w(Serializers app/serializers), %w(Services app/services), %w(Validators app/validators), %w(Workers app/workers), ].each do |name, dir| - STATS_DIRECTORIES << [name, Rails.root.join(dir)] + STATS_DIRECTORIES << [name, dir] end end end diff --git a/package.json b/package.json index 00014becbc9d4a..ee8b80091e142d 100644 --- a/package.json +++ b/package.json @@ -77,7 +77,7 @@ "escape-html": "^1.0.3", "file-loader": "^6.2.0", "font-awesome": "^4.7.0", - "fuzzysort": "^2.0.4", + "fuzzysort": "^3.0.0", "glob": "^10.2.6", "history": "^4.10.1", "hoist-non-react-statics": "^3.3.2", @@ -128,6 +128,7 @@ "tesseract.js": "^2.1.5", "tiny-queue": "^0.2.1", "twitter-text": "3.1.0", + "use-debounce": "^10.0.0", "webpack": "^4.47.0", "webpack-assets-manifest": "^4.0.6", "webpack-bundle-analyzer": "^4.8.0", @@ -191,7 +192,7 @@ "jest": "^29.5.0", "jest-environment-jsdom": "^29.5.0", "lint-staged": "^15.0.0", - "prettier": "^3.0.0", + "prettier": "^3.3.3", "react-test-renderer": "^18.2.0", "stylelint": "^16.0.2", "stylelint-config-standard-scss": "^13.0.0", diff --git a/spec/controllers/activitypub/collections_controller_spec.rb b/spec/controllers/activitypub/collections_controller_spec.rb index 11ef03c8425c1c..a5718fbd7d3c06 100644 --- a/spec/controllers/activitypub/collections_controller_spec.rb +++ b/spec/controllers/activitypub/collections_controller_spec.rb @@ -25,14 +25,12 @@ context 'without signature' do let(:remote_account) { nil } - it 'returns http success and correct media type' do + it_behaves_like 'cacheable response' + + it 'returns http success and correct media type and correct items' do expect(response).to have_http_status(200) expect(response.media_type).to eq 'application/activity+json' - end - it_behaves_like 'cacheable response' - - it 'returns orderedItems with correct items' do expect(body_as_json[:orderedItems]) .to be_an(Array) .and have_attributes(size: 3) @@ -66,14 +64,12 @@ let(:remote_account) { Fabricate(:account, domain: 'example.com') } context 'when getting a featured resource' do - it 'returns http success and correct media type' do + it_behaves_like 'cacheable response' + + it 'returns http success and correct media type and expected items' do expect(response).to have_http_status(200) expect(response.media_type).to eq 'application/activity+json' - end - - it_behaves_like 'cacheable response' - it 'returns orderedItems with expected items' do expect(body_as_json[:orderedItems]) .to be_an(Array) .and have_attributes(size: 3) @@ -92,16 +88,14 @@ account.block!(remote_account) end - it 'returns http success and correct media type and cache headers' do + it 'returns http success and correct media type and cache headers and empty items' do expect(response).to have_http_status(200) expect(response.media_type).to eq 'application/activity+json' expect(response.headers['Cache-Control']).to include 'private' - end - it 'returns empty orderedItems' do expect(body_as_json[:orderedItems]) .to be_an(Array) - .and have_attributes(size: 0) + .and be_empty end end @@ -110,16 +104,14 @@ account.block_domain!(remote_account.domain) end - it 'returns http success and correct media type and cache headers' do + it 'returns http success and correct media type and cache headers and empty items' do expect(response).to have_http_status(200) expect(response.media_type).to eq 'application/activity+json' expect(response.headers['Cache-Control']).to include 'private' - end - it 'returns empty orderedItems' do expect(body_as_json[:orderedItems]) .to be_an(Array) - .and have_attributes(size: 0) + .and be_empty end end end diff --git a/spec/controllers/activitypub/followers_synchronizations_controller_spec.rb b/spec/controllers/activitypub/followers_synchronizations_controller_spec.rb index b50c7b9cdcb1d7..c030078d43a643 100644 --- a/spec/controllers/activitypub/followers_synchronizations_controller_spec.rb +++ b/spec/controllers/activitypub/followers_synchronizations_controller_spec.rb @@ -37,25 +37,18 @@ let(:body) { body_as_json } let(:remote_account) { Fabricate(:account, domain: 'example.com', uri: 'https://example.com/instance') } - it 'returns http success' do + it 'returns http success and cache control and activity json types and correct items' do expect(response).to have_http_status(200) - end - - it 'returns application/activity+json' do + expect(response.headers['Cache-Control']).to eq 'max-age=0, private' expect(response.media_type).to eq 'application/activity+json' - end - it 'returns orderedItems with followers from example.com' do - expect(body[:orderedItems]).to be_an Array - expect(body[:orderedItems]).to contain_exactly( - follower_example_com_instance_actor.uri, - follower_example_com_user_a.uri, - follower_example_com_user_b.uri - ) - end - - it 'returns private Cache-Control header' do - expect(response.headers['Cache-Control']).to eq 'max-age=0, private' + expect(body[:orderedItems]) + .to be_an(Array) + .and contain_exactly( + follower_example_com_instance_actor.uri, + follower_example_com_user_a.uri, + follower_example_com_user_b.uri + ) end context 'when account is permanently suspended' do diff --git a/spec/controllers/activitypub/outboxes_controller_spec.rb b/spec/controllers/activitypub/outboxes_controller_spec.rb index ead231f29fbe43..3c8e8e399f6296 100644 --- a/spec/controllers/activitypub/outboxes_controller_spec.rb +++ b/spec/controllers/activitypub/outboxes_controller_spec.rb @@ -25,22 +25,13 @@ context 'with page not requested' do let(:page) { nil } - it 'returns http success' do - expect(response).to have_http_status(200) - end - - it 'returns application/activity+json' do - expect(response.media_type).to eq 'application/activity+json' - end - - it 'returns totalItems' do - expect(body[:totalItems]).to eq 4 - end - it_behaves_like 'cacheable response' - it 'does not have a Vary header' do + it 'returns http success and correct media type and headers and items count' do + expect(response).to have_http_status(200) + expect(response.media_type).to eq 'application/activity+json' expect(response.headers['Vary']).to be_nil + expect(body[:totalItems]).to eq 4 end context 'when account is permanently suspended' do @@ -68,26 +59,18 @@ context 'with page requested' do let(:page) { 'true' } - it 'returns http success' do - expect(response).to have_http_status(200) - end + it_behaves_like 'cacheable response' - it 'returns application/activity+json' do + it 'returns http success and correct media type and vary header and items' do + expect(response).to have_http_status(200) expect(response.media_type).to eq 'application/activity+json' - end + expect(response.headers['Vary']).to include 'Signature' - it 'returns orderedItems with public or unlisted statuses' do expect(body[:orderedItems]).to be_an Array expect(body[:orderedItems].size).to eq 2 expect(body[:orderedItems].all? { |item| targets_public_collection?(item) }).to be true end - it_behaves_like 'cacheable response' - - it 'returns Vary header with Signature' do - expect(response.headers['Vary']).to include 'Signature' - end - context 'when account is permanently suspended' do before do account.suspend! @@ -120,23 +103,14 @@ get :show, params: { account_username: account.username, page: page } end - it 'returns http success' do + it 'returns http success and correct media type and headers and items' do expect(response).to have_http_status(200) - end - - it 'returns application/activity+json' do expect(response.media_type).to eq 'application/activity+json' - end - - it 'returns orderedItems with public or unlisted statuses' do - json = body_as_json - expect(json[:orderedItems]).to be_an Array - expect(json[:orderedItems].size).to eq 2 - expect(json[:orderedItems].all? { |item| targets_public_collection?(item) }).to be true - end - - it 'returns private Cache-Control header' do expect(response.headers['Cache-Control']).to eq 'max-age=60, private' + + expect(body_as_json[:orderedItems]).to be_an Array + expect(body_as_json[:orderedItems].size).to eq 2 + expect(body_as_json[:orderedItems].all? { |item| targets_public_collection?(item) }).to be true end end @@ -146,23 +120,14 @@ get :show, params: { account_username: account.username, page: page } end - it 'returns http success' do + it 'returns http success and correct media type and headers and items' do expect(response).to have_http_status(200) - end - - it 'returns application/activity+json' do expect(response.media_type).to eq 'application/activity+json' - end - - it 'returns orderedItems with private statuses' do - json = body_as_json - expect(json[:orderedItems]).to be_an Array - expect(json[:orderedItems].size).to eq 3 - expect(json[:orderedItems].all? { |item| targets_public_collection?(item) || targets_followers_collection?(item, account) }).to be true - end - - it 'returns private Cache-Control header' do expect(response.headers['Cache-Control']).to eq 'max-age=60, private' + + expect(body_as_json[:orderedItems]).to be_an Array + expect(body_as_json[:orderedItems].size).to eq 3 + expect(body_as_json[:orderedItems].all? { |item| targets_public_collection?(item) || targets_followers_collection?(item, account) }).to be true end end @@ -172,22 +137,14 @@ get :show, params: { account_username: account.username, page: page } end - it 'returns http success' do + it 'returns http success and correct media type and headers and items' do expect(response).to have_http_status(200) - end - - it 'returns application/activity+json' do expect(response.media_type).to eq 'application/activity+json' - end - - it 'returns empty orderedItems' do - json = body_as_json - expect(json[:orderedItems]).to be_an Array - expect(json[:orderedItems].size).to eq 0 - end - - it 'returns private Cache-Control header' do expect(response.headers['Cache-Control']).to eq 'max-age=60, private' + + expect(body_as_json[:orderedItems]) + .to be_an(Array) + .and be_empty end end @@ -197,22 +154,14 @@ get :show, params: { account_username: account.username, page: page } end - it 'returns http success' do + it 'returns http success and correct media type and headers and items' do expect(response).to have_http_status(200) - end - - it 'returns application/activity+json' do expect(response.media_type).to eq 'application/activity+json' - end - - it 'returns empty orderedItems' do - json = body_as_json - expect(json[:orderedItems]).to be_an Array - expect(json[:orderedItems].size).to eq 0 - end - - it 'returns private Cache-Control header' do expect(response.headers['Cache-Control']).to eq 'max-age=60, private' + + expect(body_as_json[:orderedItems]) + .to be_an(Array) + .and be_empty end end end diff --git a/spec/controllers/activitypub/replies_controller_spec.rb b/spec/controllers/activitypub/replies_controller_spec.rb index db7f60d3f873dc..c556e0727047c4 100644 --- a/spec/controllers/activitypub/replies_controller_spec.rb +++ b/spec/controllers/activitypub/replies_controller_spec.rb @@ -66,19 +66,15 @@ context 'when status is public' do let(:parent_visibility) { :public } - let(:json) { body_as_json } - let(:page_json) { json[:first] } + let(:page_json) { body_as_json[:first] } - it 'returns http success' do - expect(response).to have_http_status(200) - end + it_behaves_like 'cacheable response' - it 'returns application/activity+json' do + it 'returns http success and correct media type' do + expect(response).to have_http_status(200) expect(response.media_type).to eq 'application/activity+json' end - it_behaves_like 'cacheable response' - context 'without only_other_accounts' do it "returns items with thread author's replies" do expect(page_json).to be_a Hash diff --git a/spec/controllers/admin/instances_controller_spec.rb b/spec/controllers/admin/instances_controller_spec.rb index e6fa0b9def2a1c..ca64dd90a04dd9 100644 --- a/spec/controllers/admin/instances_controller_spec.rb +++ b/spec/controllers/admin/instances_controller_spec.rb @@ -37,10 +37,32 @@ end describe 'GET #show' do + before do + allow(Admin::ActionLogFilter).to receive(:new).and_call_original + end + it 'shows an instance page' do get :show, params: { id: account_popular_main.domain } expect(response).to have_http_status(200) + + instance = assigns(:instance) + expect(instance).to_not be_new_record + + expect(Admin::ActionLogFilter).to have_received(:new).with(target_domain: account_popular_main.domain) + + action_logs = assigns(:action_logs).to_a + expect(action_logs.size).to eq 0 + end + + context 'with an unknown domain' do + it 'returns http success' do + get :show, params: { id: 'unknown.example' } + expect(response).to have_http_status(200) + + instance = assigns(:instance) + expect(instance).to be_new_record + end end end diff --git a/spec/controllers/admin/reports_controller_spec.rb b/spec/controllers/admin/reports_controller_spec.rb index 02760154fbe5ff..5849163b5fe06e 100644 --- a/spec/controllers/admin/reports_controller_spec.rb +++ b/spec/controllers/admin/reports_controller_spec.rb @@ -64,7 +64,7 @@ describe 'POST #reopen' do it 'reopens the report' do - report = Fabricate(:report) + report = Fabricate(:report, action_taken_at: 3.days.ago) put :reopen, params: { id: report } expect(response).to redirect_to(admin_report_path(report)) @@ -89,7 +89,7 @@ describe 'POST #unassign' do it 'reopens the report' do - report = Fabricate(:report) + report = Fabricate(:report, assigned_account_id: Account.last.id) put :unassign, params: { id: report } expect(response).to redirect_to(admin_report_path(report)) diff --git a/spec/fixtures/requests/activitypub-webfinger.txt b/spec/fixtures/requests/activitypub-webfinger.txt index 465066d84e1032..733b1693dc8807 100644 --- a/spec/fixtures/requests/activitypub-webfinger.txt +++ b/spec/fixtures/requests/activitypub-webfinger.txt @@ -4,4 +4,4 @@ Content-Type: application/jrd+json; charset=utf-8 X-Content-Type-Options: nosniff Date: Sun, 17 Sep 2017 06:22:50 GMT -{"subject":"acct:foo@ap.example.com","aliases":["https://ap.example.com/@foo","https://ap.example.com/users/foo"],"links":[{"rel":"http://webfinger.net/rel/profile-page","type":"text/html","href":"https://ap.example.com/@foo"},{"rel":"http://schemas.google.com/g/2010#updates-from","type":"application/atom+xml","href":"https://ap.example.com/users/foo.atom"},{"rel":"self","type":"application/activity+json","href":"https://ap.example.com/users/foo"},{"rel":"salmon","href":"https://ap.example.com/api/salmon/1"},{"rel":"magic-public-key","href":"data:application/magic-public-key,RSA.u3L4vnpNLzVH31MeWI394F0wKeJFsLDAsNXGeOu0QF2x-h1zLWZw_agqD2R3JPU9_kaDJGPIV2Sn5zLyUA9S6swCCMOtn7BBR9g9sucgXJmUFB0tACH2QSgHywMAybGfmSb3LsEMNKsGJ9VsvYoh8lDET6X4Pyw-ZJU0_OLo_41q9w-OrGtlsTm_PuPIeXnxa6BLqnDaxC-4IcjG_FiPahNCTINl_1F_TgSSDZ4Taf4U9XFEIFw8wmgploELozzIzKq-t8nhQYkgAkt64euWpva3qL5KD1mTIZQEP-LZvh3s2WHrLi3fhbdRuwQ2c0KkJA2oSTFPDpqqbPGZ3QvuHQ==.AQAB"},{"rel":"http://ostatus.org/schema/1.0/subscribe","template":"https://ap.example.com/authorize_follow?acct={uri}"}]} \ No newline at end of file +{"subject":"acct:foo@ap.example.com","aliases":["https://ap.example.com/@foo","https://ap.example.com/users/foo"],"links":[{"rel":"http://webfinger.net/rel/profile-page","type":"text/html","href":"https://ap.example.com/@foo"},{"rel":"http://schemas.google.com/g/2010#updates-from","type":"application/atom+xml","href":"https://ap.example.com/users/foo.atom"},{"rel":"self","type":"application/html","href":"https://ap.example.com/users/foo.html"},{"rel":"self","type":"application/activity+json","href":"https://ap.example.com/users/foo"},{"rel":"self","type":"application/json","href":"https://ap.example.com/users/foo.json"},{"rel":"salmon","href":"https://ap.example.com/api/salmon/1"},{"rel":"magic-public-key","href":"data:application/magic-public-key,RSA.u3L4vnpNLzVH31MeWI394F0wKeJFsLDAsNXGeOu0QF2x-h1zLWZw_agqD2R3JPU9_kaDJGPIV2Sn5zLyUA9S6swCCMOtn7BBR9g9sucgXJmUFB0tACH2QSgHywMAybGfmSb3LsEMNKsGJ9VsvYoh8lDET6X4Pyw-ZJU0_OLo_41q9w-OrGtlsTm_PuPIeXnxa6BLqnDaxC-4IcjG_FiPahNCTINl_1F_TgSSDZ4Taf4U9XFEIFw8wmgploELozzIzKq-t8nhQYkgAkt64euWpva3qL5KD1mTIZQEP-LZvh3s2WHrLi3fhbdRuwQ2c0KkJA2oSTFPDpqqbPGZ3QvuHQ==.AQAB"},{"rel":"http://ostatus.org/schema/1.0/subscribe","template":"https://ap.example.com/authorize_follow?acct={uri}"}]} \ No newline at end of file diff --git a/spec/fixtures/requests/webfinger.txt b/spec/fixtures/requests/webfinger.txt index f337ecae6f1501..fce821bddbf5c8 100644 --- a/spec/fixtures/requests/webfinger.txt +++ b/spec/fixtures/requests/webfinger.txt @@ -8,4 +8,4 @@ Access-Control-Allow-Origin: * Vary: Accept-Encoding,Cookie Strict-Transport-Security: max-age=31536000; includeSubdomains; -{"subject":"acct:gargron@quitter.no","aliases":["https:\/\/quitter.no\/user\/7477","https:\/\/quitter.no\/gargron","https:\/\/quitter.no\/index.php\/user\/7477","https:\/\/quitter.no\/index.php\/gargron"],"links":[{"rel":"http:\/\/webfinger.net\/rel\/profile-page","type":"text\/html","href":"https:\/\/quitter.no\/gargron"},{"rel":"http:\/\/gmpg.org\/xfn\/11","type":"text\/html","href":"https:\/\/quitter.no\/gargron"},{"rel":"describedby","type":"application\/rdf+xml","href":"https:\/\/quitter.no\/gargron\/foaf"},{"rel":"http:\/\/apinamespace.org\/atom","type":"application\/atomsvc+xml","href":"https:\/\/quitter.no\/api\/statusnet\/app\/service\/gargron.xml"},{"rel":"http:\/\/apinamespace.org\/twitter","href":"https:\/\/quitter.no\/api\/"},{"rel":"http:\/\/specs.openid.net\/auth\/2.0\/provider","href":"https:\/\/quitter.no\/gargron"},{"rel":"http:\/\/schemas.google.com\/g\/2010#updates-from","type":"application\/atom+xml","href":"https:\/\/quitter.no\/api\/statuses\/user_timeline\/7477.atom"},{"rel":"magic-public-key","href":"data:application\/magic-public-key,RSA.1ZBkHTavLvxH3FzlKv4O6WtlILKRFfNami3_Rcu8EuogtXSYiS-bB6hElZfUCSHbC4uLemOA34PEhz__CDMozax1iI_t8dzjDnh1x0iFSup7pSfW9iXk_WU3Dm74yWWW2jildY41vWgrEstuQ1dJ8vVFfSJ9T_tO4c-T9y8vDI8=.AQAB"},{"rel":"salmon","href":"https:\/\/quitter.no\/main\/salmon\/user\/7477"},{"rel":"http:\/\/salmon-protocol.org\/ns\/salmon-replies","href":"https:\/\/quitter.no\/main\/salmon\/user\/7477"},{"rel":"http:\/\/salmon-protocol.org\/ns\/salmon-mention","href":"https:\/\/quitter.no\/main\/salmon\/user\/7477"},{"rel":"http:\/\/ostatus.org\/schema\/1.0\/subscribe","template":"https:\/\/quitter.no\/main\/ostatussub?profile={uri}"}]} +{"subject":"acct:gargron@quitter.no","aliases":["https:\/\/quitter.no\/user\/7477","https:\/\/quitter.no\/gargron","https:\/\/quitter.no\/index.php\/user\/7477","https:\/\/quitter.no\/index.php\/gargron"],"links":[{"rel":"http:\/\/webfinger.net\/rel\/profile-page","type":"text\/html","href":"https:\/\/quitter.no\/gargron"},{"rel":"http:\/\/gmpg.org\/xfn\/11","type":"text\/html","href":"https:\/\/quitter.no\/gargron"},{"rel":"describedby","type":"application\/rdf+xml","href":"https:\/\/quitter.no\/gargron\/foaf"},{"rel":"self","type":"application/activity+json","href":"https://ap.example.com/users/foo"},{"rel":"http:\/\/apinamespace.org\/atom","type":"application\/atomsvc+xml","href":"https:\/\/quitter.no\/api\/statusnet\/app\/service\/gargron.xml"},{"rel":"http:\/\/apinamespace.org\/twitter","href":"https:\/\/quitter.no\/api\/"},{"rel":"http:\/\/specs.openid.net\/auth\/2.0\/provider","href":"https:\/\/quitter.no\/gargron"},{"rel":"http:\/\/schemas.google.com\/g\/2010#updates-from","type":"application\/atom+xml","href":"https:\/\/quitter.no\/api\/statuses\/user_timeline\/7477.atom"},{"rel":"magic-public-key","href":"data:application\/magic-public-key,RSA.1ZBkHTavLvxH3FzlKv4O6WtlILKRFfNami3_Rcu8EuogtXSYiS-bB6hElZfUCSHbC4uLemOA34PEhz__CDMozax1iI_t8dzjDnh1x0iFSup7pSfW9iXk_WU3Dm74yWWW2jildY41vWgrEstuQ1dJ8vVFfSJ9T_tO4c-T9y8vDI8=.AQAB"},{"rel":"salmon","href":"https:\/\/quitter.no\/main\/salmon\/user\/7477"},{"rel":"http:\/\/salmon-protocol.org\/ns\/salmon-replies","href":"https:\/\/quitter.no\/main\/salmon\/user\/7477"},{"rel":"http:\/\/salmon-protocol.org\/ns\/salmon-mention","href":"https:\/\/quitter.no\/main\/salmon\/user\/7477"},{"rel":"http:\/\/ostatus.org\/schema\/1.0\/subscribe","template":"https:\/\/quitter.no\/main\/ostatussub?profile={uri}"}]} diff --git a/spec/lib/activitypub/activity/create_spec.rb b/spec/lib/activitypub/activity/create_spec.rb index 03951d69990eed..33eb48a3634191 100644 --- a/spec/lib/activitypub/activity/create_spec.rb +++ b/spec/lib/activitypub/activity/create_spec.rb @@ -1109,7 +1109,7 @@ def activity_for_object(json) inbox: 'https://foo.test/inbox', }.with_indifferent_access end - let!(:webfinger) { { subject: 'acct:actor@foo.test', links: [{ rel: 'self', href: 'https://foo.test' }] } } + let!(:webfinger) { { subject: 'acct:actor@foo.test', links: [{ rel: 'self', href: 'https://foo.test', type: 'application/activity+json' }] } } let(:object_json) do { @@ -1129,13 +1129,13 @@ def activity_for_object(json) before do stub_request(:get, 'https://foo.test').to_return(status: 200, body: Oj.dump(actor_json), headers: { 'Content-Type': 'application/activity+json' }) - stub_request(:get, 'https://foo.test/.well-known/webfinger?resource=acct:actor@foo.test').to_return(status: 200, body: Oj.dump(webfinger), headers: { 'Content-Type': 'application/activity+json' }) + stub_request(:get, 'https://foo.test/.well-known/webfinger?resource=acct:actor@foo.test').to_return(status: 200, body: Oj.dump(webfinger), headers: { 'Content-Type': 'application/jrd+json' }) stub_request(:post, 'https://foo.test/inbox').to_return(status: 200) stub_request(:get, 'https://foo.test/.well-known/nodeinfo').to_return(status: 200, headers: { 'Content-Type': 'application/activity+json' }) subject.perform end - it 'creates status' do + it 'creates status', :inline_jobs do status = sender.statuses.first expect(status).to_not be_nil diff --git a/spec/lib/activitypub/activity/flag_spec.rb b/spec/lib/activitypub/activity/flag_spec.rb index 426cd97df9acf3..be1bd42a14a810 100644 --- a/spec/lib/activitypub/activity/flag_spec.rb +++ b/spec/lib/activitypub/activity/flag_spec.rb @@ -36,6 +36,7 @@ expect(report).to_not be_nil expect(report.comment).to eq 'Boo!!' expect(report.status_ids).to eq [status.id] + expect(report.application).to be_nil end end diff --git a/spec/lib/activitypub/activity/move_spec.rb b/spec/lib/activitypub/activity/move_spec.rb index d69ef215161210..02c3380ab3edd7 100644 --- a/spec/lib/activitypub/activity/move_spec.rb +++ b/spec/lib/activitypub/activity/move_spec.rb @@ -3,6 +3,9 @@ require 'rails_helper' RSpec.describe ActivityPub::Activity::Move do + RSpec::Matchers.define_negated_matcher :not_be_following, :be_following + RSpec::Matchers.define_negated_matcher :not_be_requested, :be_requested + let(:follower) { Fabricate(:account) } let(:old_account) { Fabricate(:account, uri: 'https://example.org/alice', domain: 'example.org', protocol: :activitypub, inbox_url: 'https://example.org/inbox') } let(:new_account) { Fabricate(:account, uri: 'https://example.com/alice', domain: 'example.com', protocol: :activitypub, inbox_url: 'https://example.com/inbox', also_known_as: also_known_as) } @@ -39,48 +42,36 @@ end context 'when all conditions are met', :inline_jobs do - it 'sets moved account on old account' do - expect(old_account.reload.moved_to_account_id).to eq new_account.id - end - - it 'makes followers unfollow old account' do - expect(follower.following?(old_account)).to be false - end - - it 'makes followers follow-request the new account' do - expect(follower.requested?(new_account)).to be true + it 'sets moved on old account, followers unfollow old account, followers request the new account' do + expect(old_account.reload.moved_to_account_id) + .to eq new_account.id + expect(follower) + .to not_be_following(old_account) + .and be_requested(new_account) end end context "when the new account can't be resolved" do let(:returned_account) { nil } - it 'does not set moved account on old account' do - expect(old_account.reload.moved_to_account_id).to be_nil - end - - it 'does not make followers unfollow old account' do - expect(follower.following?(old_account)).to be true - end - - it 'does not make followers follow-request the new account' do - expect(follower.requested?(new_account)).to be false + it 'does not set moved on old account, does not unfollow old, does not follow request new' do + expect(old_account.reload.moved_to_account_id) + .to be_nil + expect(follower) + .to be_following(old_account) + .and not_be_requested(new_account) end end context 'when the new account does not references the old account' do let(:also_known_as) { [] } - it 'does not set moved account on old account' do - expect(old_account.reload.moved_to_account_id).to be_nil - end - - it 'does not make followers unfollow old account' do - expect(follower.following?(old_account)).to be true - end - - it 'does not make followers follow-request the new account' do - expect(follower.requested?(new_account)).to be false + it 'does not set moved on old account, does not unfollow old, does not follow request new' do + expect(old_account.reload.moved_to_account_id) + .to be_nil + expect(follower) + .to be_following(old_account) + .and not_be_requested(new_account) end end @@ -91,16 +82,12 @@ redis.del("move_in_progress:#{old_account.id}") end - it 'does not set moved account on old account' do - expect(old_account.reload.moved_to_account_id).to be_nil - end - - it 'does not make followers unfollow old account' do - expect(follower.following?(old_account)).to be true - end - - it 'does not make followers follow-request the new account' do - expect(follower.requested?(new_account)).to be false + it 'does not set moved on old account, does not unfollow old, does not follow request new' do + expect(old_account.reload.moved_to_account_id) + .to be_nil + expect(follower) + .to be_following(old_account) + .and not_be_requested(new_account) end end end diff --git a/spec/lib/activitypub/adapter_spec.rb b/spec/lib/activitypub/adapter_spec.rb index 7d8d703ec2586b..5ecdfe812055fc 100644 --- a/spec/lib/activitypub/adapter_spec.rb +++ b/spec/lib/activitypub/adapter_spec.rb @@ -59,7 +59,7 @@ def virtual_object let(:serializer_class) { TestWithBasicContextSerializer } it 'renders a basic @context' do - expect(subject).to include({ '@context' => 'https://www.w3.org/ns/activitystreams' }) + expect(subject).to include({ '@context': 'https://www.w3.org/ns/activitystreams' }) end end @@ -67,7 +67,7 @@ def virtual_object let(:serializer_class) { TestWithNamedContextSerializer } it 'renders a @context with both items' do - expect(subject).to include({ '@context' => ['https://www.w3.org/ns/activitystreams', 'https://w3id.org/security/v1'] }) + expect(subject).to include({ '@context': ['https://www.w3.org/ns/activitystreams', 'https://w3id.org/security/v1'] }) end end @@ -75,7 +75,7 @@ def virtual_object let(:serializer_class) { TestWithNestedNamedContextSerializer } it 'renders a @context with both items' do - expect(subject).to include({ '@context' => ['https://www.w3.org/ns/activitystreams', 'https://w3id.org/security/v1'] }) + expect(subject).to include({ '@context': ['https://www.w3.org/ns/activitystreams', 'https://w3id.org/security/v1'] }) end end @@ -83,7 +83,7 @@ def virtual_object let(:serializer_class) { TestWithContextExtensionSerializer } it 'renders a @context with the extension' do - expect(subject).to include({ '@context' => ['https://www.w3.org/ns/activitystreams', { 'sensitive' => 'as:sensitive' }] }) + expect(subject).to include({ '@context': ['https://www.w3.org/ns/activitystreams', { 'sensitive' => 'as:sensitive' }] }) end end @@ -91,7 +91,7 @@ def virtual_object let(:serializer_class) { TestWithNestedContextExtensionSerializer } it 'renders a @context with both extensions' do - expect(subject).to include({ '@context' => ['https://www.w3.org/ns/activitystreams', { 'manuallyApprovesFollowers' => 'as:manuallyApprovesFollowers', 'sensitive' => 'as:sensitive' }] }) + expect(subject).to include({ '@context': ['https://www.w3.org/ns/activitystreams', { 'manuallyApprovesFollowers' => 'as:manuallyApprovesFollowers', 'sensitive' => 'as:sensitive' }] }) end end end diff --git a/spec/lib/webfinger_spec.rb b/spec/lib/webfinger_spec.rb new file mode 100644 index 00000000000000..5015deac7ffd87 --- /dev/null +++ b/spec/lib/webfinger_spec.rb @@ -0,0 +1,41 @@ +# frozen_string_literal: true + +require 'rails_helper' + +RSpec.describe Webfinger do + describe 'self link' do + context 'when self link is specified with type application/activity+json' do + let!(:webfinger) { { subject: 'acct:alice@example.com', links: [{ rel: 'self', href: 'https://example.com/alice', type: 'application/activity+json' }] } } + + it 'correctly parses the response' do + stub_request(:get, 'https://example.com/.well-known/webfinger?resource=acct:alice@example.com').to_return(body: Oj.dump(webfinger), headers: { 'Content-Type': 'application/jrd+json' }) + + response = described_class.new('acct:alice@example.com').perform + + expect(response.self_link_href).to eq 'https://example.com/alice' + end + end + + context 'when self link is specified with type application/ld+json' do + let!(:webfinger) { { subject: 'acct:alice@example.com', links: [{ rel: 'self', href: 'https://example.com/alice', type: 'application/ld+json; profile="https://www.w3.org/ns/activitystreams"' }] } } + + it 'correctly parses the response' do + stub_request(:get, 'https://example.com/.well-known/webfinger?resource=acct:alice@example.com').to_return(body: Oj.dump(webfinger), headers: { 'Content-Type': 'application/jrd+json' }) + + response = described_class.new('acct:alice@example.com').perform + + expect(response.self_link_href).to eq 'https://example.com/alice' + end + end + + context 'when self link is specified with incorrect type' do + let!(:webfinger) { { subject: 'acct:alice@example.com', links: [{ rel: 'self', href: 'https://example.com/alice', type: 'application/json"' }] } } + + it 'raises an error' do + stub_request(:get, 'https://example.com/.well-known/webfinger?resource=acct:alice@example.com').to_return(body: Oj.dump(webfinger), headers: { 'Content-Type': 'application/jrd+json' }) + + expect { described_class.new('acct:alice@example.com').perform }.to raise_error(Webfinger::Error) + end + end + end +end diff --git a/spec/models/account_spec.rb b/spec/models/account_spec.rb index c4e5b15baca366..0fd1a4d77df2a1 100644 --- a/spec/models/account_spec.rb +++ b/spec/models/account_spec.rb @@ -815,7 +815,7 @@ expect(results).to eq [match] end - it 'limits by 10 by default' do + it 'limits result count by default value' do stub_const('Account::Search::DEFAULT_LIMIT', 1) 2.times { Fabricate(:account, display_name: 'Display Name') } results = described_class.advanced_search_for('display', account) @@ -998,7 +998,7 @@ end it 'is invalid if the display name is longer than the character limit' do - account = Fabricate.build(:account, display_name: username_over_limit) + account = Fabricate.build(:account, display_name: display_name_over_limit) account.valid? expect(account).to model_have_error_on_field(:display_name) end @@ -1044,7 +1044,7 @@ end it 'is valid even if the display name is longer than the character limit' do - account = Fabricate.build(:account, domain: 'domain', display_name: username_over_limit) + account = Fabricate.build(:account, domain: 'domain', display_name: display_name_over_limit) account.valid? expect(account).to_not model_have_error_on_field(:display_name) end @@ -1060,6 +1060,10 @@ def username_over_limit 'a' * described_class::USERNAME_LENGTH_LIMIT * 2 end + def display_name_over_limit + 'a' * described_class::DISPLAY_NAME_LENGTH_LIMIT * 2 + end + def account_note_over_limit 'a' * described_class::NOTE_LENGTH_LIMIT * 2 end diff --git a/spec/models/media_attachment_spec.rb b/spec/models/media_attachment_spec.rb index 24e8ca39c11f0e..3142b291fb2b00 100644 --- a/spec/models/media_attachment_spec.rb +++ b/spec/models/media_attachment_spec.rb @@ -90,7 +90,7 @@ media.destroy end - it 'saves media attachment with correct file metadata' do + it 'saves media attachment with correct file and size metadata' do expect(media) .to be_persisted .and be_processing_complete @@ -103,14 +103,12 @@ # Rack::Mime (used by PublicFileServerMiddleware) recognizes file extension expect(Rack::Mime.mime_type(extension, nil)).to eq content_type - end - it 'saves media attachment with correct size metadata' do - # strips original file name + # Strip original file name expect(media.file_file_name) .to_not start_with '600x400' - # sets meta for original and thumbnail + # Set meta for original and thumbnail expect(media.file.meta.deep_symbolize_keys) .to include( original: include( @@ -174,10 +172,18 @@ let(:media) { Fabricate(:media_attachment, file: attachment_fixture('avatar.gif')) } it 'sets correct file metadata' do - expect(media.type).to eq 'gifv' - expect(media.file_content_type).to eq 'video/mp4' - expect(media.file.meta['original']['width']).to eq 128 - expect(media.file.meta['original']['height']).to eq 128 + expect(media) + .to have_attributes( + type: eq('gifv'), + file_content_type: eq('video/mp4') + ) + expect(media_metadata) + .to include( + original: include( + width: eq(128), + height: eq(128) + ) + ) end end @@ -192,11 +198,19 @@ let(:media) { Fabricate(:media_attachment, file: attachment_fixture(fixture[:filename])) } it 'sets correct file metadata' do - expect(media.type).to eq 'image' - expect(media.file_content_type).to eq 'image/gif' - expect(media.file.meta['original']['width']).to eq fixture[:width] - expect(media.file.meta['original']['height']).to eq fixture[:height] - expect(media.file.meta['original']['aspect']).to eq fixture[:aspect] + expect(media) + .to have_attributes( + type: eq('image'), + file_content_type: eq('image/gif') + ) + expect(media_metadata) + .to include( + original: include( + width: eq(fixture[:width]), + height: eq(fixture[:height]), + aspect: eq(fixture[:aspect]) + ) + ) end end end @@ -204,39 +218,42 @@ describe 'ogg with cover art' do let(:media) { Fabricate(:media_attachment, file: attachment_fixture('boop.ogg')) } + let(:expected_media_duration) { 0.235102 } - it 'sets correct file metadata' do - expect(media.type).to eq 'audio' - expect(media.file.meta['original']['duration']).to be_within(0.05).of(0.235102) - expect(media.thumbnail.present?).to be true + # The libvips and ImageMagick implementations produce different results + let(:expected_background_color) { Rails.configuration.x.use_vips ? '#268cd9' : '#3088d4' } - expect(media.file.meta['colors']['background']).to eq(expected_background_color) - expect(media.file_file_name).to_not eq 'boop.ogg' - end + it 'sets correct file metadata' do + expect(media) + .to have_attributes( + type: eq('audio'), + thumbnail: be_present, + file_file_name: not_eq('boop.ogg') + ) - def expected_background_color - # The libvips and ImageMagick implementations produce different results - Rails.configuration.x.use_vips ? '#268cd9' : '#3088d4' + expect(media_metadata) + .to include( + original: include(duration: be_within(0.05).of(expected_media_duration)), + colors: include(background: eq(expected_background_color)) + ) end end describe 'mp3 with large cover art' do let(:media) { Fabricate(:media_attachment, file: attachment_fixture('boop.mp3')) } + let(:expected_media_duration) { 0.235102 } - it 'detects it as an audio file' do - expect(media.type).to eq 'audio' - end - - it 'sets meta for the duration' do - expect(media.file.meta['original']['duration']).to be_within(0.05).of(0.235102) - end - - it 'extracts thumbnail' do - expect(media.thumbnail.present?).to be true - end - - it 'gives the file a random name' do - expect(media.file_file_name).to_not eq 'boop.mp3' + it 'detects file type and sets correct metadata' do + expect(media) + .to have_attributes( + type: eq('audio'), + thumbnail: be_present, + file_file_name: not_eq('boop.mp3') + ) + expect(media_metadata) + .to include( + original: include(duration: be_within(0.05).of(expected_media_duration)) + ) end end @@ -274,4 +291,10 @@ def expected_background_color expect(media.valid?).to be true end end + + private + + def media_metadata + media.file.meta.deep_symbolize_keys + end end diff --git a/spec/rails_helper.rb b/spec/rails_helper.rb index 79031f1a9430f7..d4b9bddf93f12a 100644 --- a/spec/rails_helper.rb +++ b/spec/rails_helper.rb @@ -161,6 +161,7 @@ def sign_in(resource, _deprecated = nil, scope: nil) end RSpec::Matchers.define_negated_matcher :not_change, :change +RSpec::Matchers.define_negated_matcher :not_eq, :eq RSpec::Matchers.define_negated_matcher :not_include, :include def request_fixture(name) diff --git a/spec/requests/api/v1/reports_spec.rb b/spec/requests/api/v1/reports_spec.rb index 491c6263d3397e..a72d9bbcd85bbb 100644 --- a/spec/requests/api/v1/reports_spec.rb +++ b/spec/requests/api/v1/reports_spec.rb @@ -47,6 +47,7 @@ expect(target_account.targeted_reports).to_not be_empty expect(target_account.targeted_reports.first.comment).to eq 'reasons' + expect(target_account.targeted_reports.first.application).to eq token.application expect(emails.size) .to eq(1) diff --git a/spec/services/activitypub/fetch_remote_account_service_spec.rb b/spec/services/activitypub/fetch_remote_account_service_spec.rb index 60ee879e4ecf3f..43d8148748b310 100644 --- a/spec/services/activitypub/fetch_remote_account_service_spec.rb +++ b/spec/services/activitypub/fetch_remote_account_service_spec.rb @@ -33,7 +33,7 @@ end context 'when the account does not have a inbox' do - let!(:webfinger) { { subject: 'acct:alice@example.com', links: [{ rel: 'self', href: 'https://example.com/alice' }] } } + let!(:webfinger) { { subject: 'acct:alice@example.com', links: [{ rel: 'self', href: 'https://example.com/alice', type: 'application/activity+json' }] } } before do actor[:inbox] = nil @@ -52,7 +52,7 @@ end context 'when URI and WebFinger share the same host' do - let!(:webfinger) { { subject: 'acct:alice@example.com', links: [{ rel: 'self', href: 'https://example.com/alice' }] } } + let!(:webfinger) { { subject: 'acct:alice@example.com', links: [{ rel: 'self', href: 'https://example.com/alice', type: 'application/activity+json' }] } } before do stub_request(:get, 'https://example.com/alice').to_return(body: Oj.dump(actor), headers: { 'Content-Type': 'application/activity+json' }) @@ -74,7 +74,7 @@ end context 'when WebFinger presents different domain than URI' do - let!(:webfinger) { { subject: 'acct:alice@iscool.af', links: [{ rel: 'self', href: 'https://example.com/alice' }] } } + let!(:webfinger) { { subject: 'acct:alice@iscool.af', links: [{ rel: 'self', href: 'https://example.com/alice', type: 'application/activity+json' }] } } before do stub_request(:get, 'https://example.com/alice').to_return(body: Oj.dump(actor), headers: { 'Content-Type': 'application/activity+json' }) @@ -98,7 +98,7 @@ end context 'when WebFinger returns a different URI' do - let!(:webfinger) { { subject: 'acct:alice@example.com', links: [{ rel: 'self', href: 'https://example.com/bob' }] } } + let!(:webfinger) { { subject: 'acct:alice@example.com', links: [{ rel: 'self', href: 'https://example.com/bob', type: 'application/activity+json' }] } } before do stub_request(:get, 'https://example.com/alice').to_return(body: Oj.dump(actor), headers: { 'Content-Type': 'application/activity+json' }) @@ -115,7 +115,7 @@ end context 'when WebFinger returns a different URI after a redirection' do - let!(:webfinger) { { subject: 'acct:alice@iscool.af', links: [{ rel: 'self', href: 'https://example.com/bob' }] } } + let!(:webfinger) { { subject: 'acct:alice@iscool.af', links: [{ rel: 'self', href: 'https://example.com/bob', type: 'application/activity+json' }] } } before do stub_request(:get, 'https://example.com/alice').to_return(body: Oj.dump(actor), headers: { 'Content-Type': 'application/activity+json' }) diff --git a/spec/services/activitypub/fetch_remote_actor_service_spec.rb b/spec/services/activitypub/fetch_remote_actor_service_spec.rb index ce0a8534f10ea2..9872c5cb4d4dd1 100644 --- a/spec/services/activitypub/fetch_remote_actor_service_spec.rb +++ b/spec/services/activitypub/fetch_remote_actor_service_spec.rb @@ -33,7 +33,7 @@ end context 'when the account does not have a inbox' do - let!(:webfinger) { { subject: 'acct:alice@example.com', links: [{ rel: 'self', href: 'https://example.com/alice' }] } } + let!(:webfinger) { { subject: 'acct:alice@example.com', links: [{ rel: 'self', href: 'https://example.com/alice', type: 'application/activity+json' }] } } before do actor[:inbox] = nil @@ -52,7 +52,7 @@ end context 'when URI and WebFinger share the same host' do - let!(:webfinger) { { subject: 'acct:alice@example.com', links: [{ rel: 'self', href: 'https://example.com/alice' }] } } + let!(:webfinger) { { subject: 'acct:alice@example.com', links: [{ rel: 'self', href: 'https://example.com/alice', type: 'application/activity+json' }] } } before do stub_request(:get, 'https://example.com/alice').to_return(body: Oj.dump(actor), headers: { 'Content-Type': 'application/activity+json' }) @@ -74,7 +74,7 @@ end context 'when WebFinger presents different domain than URI' do - let!(:webfinger) { { subject: 'acct:alice@iscool.af', links: [{ rel: 'self', href: 'https://example.com/alice' }] } } + let!(:webfinger) { { subject: 'acct:alice@iscool.af', links: [{ rel: 'self', href: 'https://example.com/alice', type: 'application/activity+json' }] } } before do stub_request(:get, 'https://example.com/alice').to_return(body: Oj.dump(actor), headers: { 'Content-Type': 'application/activity+json' }) @@ -98,7 +98,7 @@ end context 'when WebFinger returns a different URI' do - let!(:webfinger) { { subject: 'acct:alice@example.com', links: [{ rel: 'self', href: 'https://example.com/bob' }] } } + let!(:webfinger) { { subject: 'acct:alice@example.com', links: [{ rel: 'self', href: 'https://example.com/bob', type: 'application/activity+json' }] } } before do stub_request(:get, 'https://example.com/alice').to_return(body: Oj.dump(actor), headers: { 'Content-Type': 'application/activity+json' }) @@ -115,7 +115,7 @@ end context 'when WebFinger returns a different URI after a redirection' do - let!(:webfinger) { { subject: 'acct:alice@iscool.af', links: [{ rel: 'self', href: 'https://example.com/bob' }] } } + let!(:webfinger) { { subject: 'acct:alice@iscool.af', links: [{ rel: 'self', href: 'https://example.com/bob', type: 'application/activity+json' }] } } before do stub_request(:get, 'https://example.com/alice').to_return(body: Oj.dump(actor), headers: { 'Content-Type': 'application/activity+json' }) diff --git a/spec/services/activitypub/fetch_remote_key_service_spec.rb b/spec/services/activitypub/fetch_remote_key_service_spec.rb index ae12ee43d6ca24..563052c072721c 100644 --- a/spec/services/activitypub/fetch_remote_key_service_spec.rb +++ b/spec/services/activitypub/fetch_remote_key_service_spec.rb @@ -5,7 +5,7 @@ RSpec.describe ActivityPub::FetchRemoteKeyService do subject { described_class.new } - let(:webfinger) { { subject: 'acct:alice@example.com', links: [{ rel: 'self', href: 'https://example.com/alice' }] } } + let(:webfinger) { { subject: 'acct:alice@example.com', links: [{ rel: 'self', href: 'https://example.com/alice', type: 'application/activity+json' }] } } let(:public_key_pem) do <<~TEXT diff --git a/spec/services/activitypub/fetch_remote_status_service_spec.rb b/spec/services/activitypub/fetch_remote_status_service_spec.rb index c3adb9c470afd1..635fcb7976c954 100644 --- a/spec/services/activitypub/fetch_remote_status_service_spec.rb +++ b/spec/services/activitypub/fetch_remote_status_service_spec.rb @@ -227,7 +227,7 @@ context 'with statuses referencing other statuses', :inline_jobs do before do - stub_const 'ActivityPub::FetchRemoteStatusService::DISCOVERIES_PER_REQUEST', 5 + stub_const 'ActivityPub::FetchRemoteStatusService::DISCOVERIES_PER_REQUEST', 3 end context 'when using inReplyTo' do @@ -243,7 +243,7 @@ end before do - 8.times do |i| + 5.times do |i| status_json = { '@context': 'https://www.w3.org/ns/activitystreams', id: "https://foo.bar/@foo/#{i}", @@ -257,12 +257,10 @@ end end - it 'creates at least some statuses' do - expect { subject.call(object[:id], prefetched_body: Oj.dump(object)) }.to change { sender.statuses.count }.by_at_least(2) - end - - it 'creates no more account than the limit allows' do - expect { subject.call(object[:id], prefetched_body: Oj.dump(object)) }.to change { sender.statuses.count }.by_at_most(5) + it 'creates statuses but not more than limit allows' do + expect { subject.call(object[:id], prefetched_body: Oj.dump(object)) } + .to change { sender.statuses.count }.by_at_least(2) + .and change { sender.statuses.count }.by_at_most(3) end end @@ -287,7 +285,7 @@ end before do - 8.times do |i| + 5.times do |i| status_json = { '@context': 'https://www.w3.org/ns/activitystreams', id: "https://foo.bar/@foo/#{i}", @@ -309,12 +307,10 @@ end end - it 'creates at least some statuses' do - expect { subject.call(object[:id], prefetched_body: Oj.dump(object)) }.to change { sender.statuses.count }.by_at_least(2) - end - - it 'creates no more account than the limit allows' do - expect { subject.call(object[:id], prefetched_body: Oj.dump(object)) }.to change { sender.statuses.count }.by_at_most(5) + it 'creates statuses but not more than limit allows' do + expect { subject.call(object[:id], prefetched_body: Oj.dump(object)) } + .to change { sender.statuses.count }.by_at_least(2) + .and change { sender.statuses.count }.by_at_most(3) end end end diff --git a/spec/services/activitypub/process_account_service_spec.rb b/spec/services/activitypub/process_account_service_spec.rb index 5f6822185c986e..e399daf2a7b200 100644 --- a/spec/services/activitypub/process_account_service_spec.rb +++ b/spec/services/activitypub/process_account_service_spec.rb @@ -601,7 +601,7 @@ }.with_indifferent_access webfinger = { subject: "acct:user#{i}@foo.test", - links: [{ rel: 'self', href: "https://foo.test/users/#{i}" }], + links: [{ rel: 'self', href: "https://foo.test/users/#{i}", type: 'application/activity+json' }], }.with_indifferent_access stub_request(:get, "https://foo.test/users/#{i}").to_return(status: 200, body: actor_json.to_json, headers: { 'Content-Type': 'application/activity+json' }) stub_request(:get, "https://foo.test/users/#{i}/featured").to_return(status: 200, body: featured_json.to_json, headers: { 'Content-Type': 'application/activity+json' }) diff --git a/spec/services/activitypub/process_status_update_service_spec.rb b/spec/services/activitypub/process_status_update_service_spec.rb index 969e0d3db334c6..37be11e6628694 100644 --- a/spec/services/activitypub/process_status_update_service_spec.rb +++ b/spec/services/activitypub/process_status_update_service_spec.rb @@ -46,14 +46,13 @@ def poll_option_json(name, votes) end describe '#call' do - it 'updates text' do + it 'updates text and content warning' do subject.call(status, json, json) - expect(status.reload.text).to eq 'Hello universe' - end - - it 'updates content warning' do - subject.call(status, json, json) - expect(status.reload.spoiler_text).to eq 'Show more' + expect(status.reload) + .to have_attributes( + text: eq('Hello universe'), + spoiler_text: eq('Show more') + ) end context 'when the changes are only in sanitized-out HTML' do @@ -73,12 +72,9 @@ def poll_option_json(name, votes) subject.call(status, json, json) end - it 'does not create any edits' do + it 'does not create any edits and does not mark status edited' do expect(status.reload.edits).to be_empty - end - - it 'does not mark status as edited' do - expect(status.edited?).to be false + expect(status).to_not be_edited end end @@ -96,15 +92,9 @@ def poll_option_json(name, votes) subject.call(status, json, json) end - it 'does not create any edits' do + it 'does not create any edits, mark status edited, or update text' do expect(status.reload.edits).to be_empty - end - - it 'does not mark status as edited' do - expect(status.reload.edited?).to be false - end - - it 'does not update the text' do + expect(status.reload).to_not be_edited expect(status.reload.text).to eq 'Hello world' end end @@ -143,19 +133,10 @@ def poll_option_json(name, votes) subject.call(status, json, json) end - it 'does not create any edits' do + it 'does not create any edits, mark status edited, update text but does update tallies' do expect(status.reload.edits).to be_empty - end - - it 'does not mark status as edited' do - expect(status.reload.edited?).to be false - end - - it 'does not update the text' do + expect(status.reload).to_not be_edited expect(status.reload.text).to eq 'Hello world' - end - - it 'updates tallies' do expect(status.poll.reload.cached_tallies).to eq [4, 3] end end @@ -195,19 +176,10 @@ def poll_option_json(name, votes) subject.call(status, json, json) end - it 'does not create any edits' do + it 'does not create any edits, mark status edited, update text, or update tallies' do expect(status.reload.edits).to be_empty - end - - it 'does not mark status as edited' do - expect(status.reload.edited?).to be false - end - - it 'does not update the text' do + expect(status.reload).to_not be_edited expect(status.reload.text).to eq 'Hello world' - end - - it 'does not update tallies' do expect(status.poll.reload.cached_tallies).to eq [0, 0] end end @@ -219,13 +191,10 @@ def poll_option_json(name, votes) status.snapshot!(rate_limit: false) end - it 'does not create any edits' do - expect { subject.call(status, json, json) }.to_not(change { status.reload.edits.pluck(&:id) }) - end - - it 'does not update the text, spoiler_text or edited_at' do + it 'does not create any edits or update relevant attributes' do expect { subject.call(status, json, json) } - .to_not(change { status.reload.attributes.slice('text', 'spoiler_text', 'edited_at').values }) + .to not_change { status.reload.edits.pluck(&:id) } + .and(not_change { status.reload.attributes.slice('text', 'spoiler_text', 'edited_at').values }) end end @@ -243,12 +212,9 @@ def poll_option_json(name, votes) subject.call(status, json, json) end - it 'does not create any edits' do + it 'does not create any edits or mark status edited' do expect(status.reload.edits).to be_empty - end - - it 'does not mark status as edited' do - expect(status.edited?).to be false + expect(status).to_not be_edited end end @@ -267,12 +233,9 @@ def poll_option_json(name, votes) subject.call(status, json, json) end - it 'does not create any edits' do + it 'does not create any edits or mark status edited' do expect(status.reload.edits).to be_empty - end - - it 'does not mark status as edited' do - expect(status.edited?).to be false + expect(status).to_not be_edited end end @@ -456,11 +419,8 @@ def poll_option_json(name, votes) subject.call(status, json, json) end - it 'removes poll' do + it 'removes poll and records media change in edit' do expect(status.reload.poll).to be_nil - end - - it 'records media change in edit' do expect(status.edits.reload.last.poll_options).to be_nil end end @@ -486,26 +446,21 @@ def poll_option_json(name, votes) subject.call(status, json, json) end - it 'creates a poll' do + it 'creates a poll and records media change in edit' do poll = status.reload.poll expect(poll).to_not be_nil expect(poll.options).to eq %w(Foo Bar Baz) - end - - it 'records media change in edit' do expect(status.edits.reload.last.poll_options).to eq %w(Foo Bar Baz) end end - it 'creates edit history' do - subject.call(status, json, json) - expect(status.edits.reload.map(&:text)).to eq ['Hello world', 'Hello universe'] - end - - it 'sets edited timestamp' do + it 'creates edit history and sets edit timestamp' do subject.call(status, json, json) - expect(status.reload.edited_at.to_s).to eq '2021-09-08 22:39:25 UTC' + expect(status.edits.reload.map(&:text)) + .to eq ['Hello world', 'Hello universe'] + expect(status.reload.edited_at.to_s) + .to eq '2021-09-08 22:39:25 UTC' end describe 'ng word is set' do diff --git a/spec/services/activitypub/synchronize_followers_service_spec.rb b/spec/services/activitypub/synchronize_followers_service_spec.rb index 648f9a33212c3e..974368b7d77e79 100644 --- a/spec/services/activitypub/synchronize_followers_service_spec.rb +++ b/spec/services/activitypub/synchronize_followers_service_spec.rb @@ -13,11 +13,9 @@ let(:collection_uri) { 'http://example.com/partial-followers' } let(:items) do - [ - ActivityPub::TagManager.instance.uri_for(alice), - ActivityPub::TagManager.instance.uri_for(eve), - ActivityPub::TagManager.instance.uri_for(mallory), - ] + [alice, eve, mallory].map do |account| + ActivityPub::TagManager.instance.uri_for(account) + end end let(:payload) do @@ -40,20 +38,15 @@ subject.call(actor, collection_uri) end - it 'keeps expected followers' do - expect(alice.following?(actor)).to be true - end - - it 'removes local followers not in the remote list' do - expect(bob.following?(actor)).to be false - end - - it 'converts follow requests to follow relationships when they have been accepted' do - expect(mallory.following?(actor)).to be true - end - - it 'sends an Undo Follow to the actor' do - expect(ActivityPub::DeliveryWorker).to have_received(:perform_async).with(anything, eve.id, actor.inbox_url) + it 'maintains following records and sends Undo Follow to actor' do + expect(alice) + .to be_following(actor) # Keep expected followers + expect(bob) + .to_not be_following(actor) # Remove local followers not in remote list + expect(mallory) + .to be_following(actor) # Convert follow request to follow when accepted + expect(ActivityPub::DeliveryWorker) + .to have_received(:perform_async).with(anything, eve.id, actor.inbox_url) # Send Undo Follow to actor end end diff --git a/spec/services/backup_service_spec.rb b/spec/services/backup_service_spec.rb index 74b23f85c228ca..1434df49db2451 100644 --- a/spec/services/backup_service_spec.rb +++ b/spec/services/backup_service_spec.rb @@ -62,6 +62,7 @@ def expect_outbox_export aggregate_failures do expect(body.scan('@context').count).to eq 1 + expect(body.scan('orderedItems').count).to eq 1 expect(json['@context']).to_not be_nil expect(json['type']).to eq 'OrderedCollection' expect(json['totalItems']).to eq 4 diff --git a/spec/services/fan_out_on_write_service_spec.rb b/spec/services/fan_out_on_write_service_spec.rb index de20af93176ada..18a235238fc4e8 100644 --- a/spec/services/fan_out_on_write_service_spec.rb +++ b/spec/services/fan_out_on_write_service_spec.rb @@ -85,29 +85,15 @@ def antenna_with_options(owner, **options) context 'when status is public' do let(:visibility) { 'public' } - it 'is added to the home feed of its author', :inline_jobs do - expect(home_feed_of(alice)).to include status.id - end - - it 'is added to the home feed of the mentioned follower', :inline_jobs do - expect(home_feed_of(bob)).to include status.id - end - - it 'is added to the home feed of a follower', :inline_jobs do - expect(home_feed_of(bob)).to include status.id - expect(home_feed_of(tom)).to include status.id - end - - it 'is added to the tag follower', :inline_jobs do - expect(home_feed_of(tagf)).to include status.id - end + it 'adds status to home feed of author and followers and broadcasts', :inline_jobs do + expect(status.id) + .to be_in(home_feed_of(alice)) + .and be_in(home_feed_of(bob)) + .and be_in(home_feed_of(tom)) + .and be_in(home_feed_of(tagf)) - it 'is broadcast to the hashtag stream', :inline_jobs do expect(redis).to have_received(:publish).with('timeline:hashtag:hoge', anything) expect(redis).to have_received(:publish).with('timeline:hashtag:hoge:local', anything) - end - - it 'is broadcast to the public stream', :inline_jobs do expect(redis).to have_received(:publish).with('timeline:public', anything) expect(redis).to have_received(:publish).with('timeline:public:local', anything) expect(redis).to have_received(:publish).with('timeline:public:media', anything) @@ -116,12 +102,9 @@ def antenna_with_options(owner, **options) context 'when local timeline is disabled', :inline_jobs do let(:ltl_enabled) { false } - it 'is broadcast to the hashtag stream', :inline_jobs do + it 'does not add status to local timeline', :inline_jobs do expect(redis).to have_received(:publish).with('timeline:hashtag:hoge', anything) expect(redis).to_not have_received(:publish).with('timeline:hashtag:hoge:local', anything) - end - - it 'is broadcast to the public stream', :inline_jobs do expect(redis).to have_received(:publish).with('timeline:public', anything) expect(redis).to_not have_received(:publish).with('timeline:public:local', anything) end @@ -286,25 +269,16 @@ def antenna_with_options(owner, **options) context 'when status is limited' do let(:visibility) { 'limited' } - it 'is added to the home feed of its author', :inline_jobs do - expect(home_feed_of(alice)).to include status.id - end - - it 'is added to the home feed of the mentioned follower', :inline_jobs do - expect(home_feed_of(bob)).to include status.id - end + it 'adds status to home feed of author and mentioned followers and does not broadcast', :inline_jobs do + expect(status.id) + .to be_in(home_feed_of(alice)) + .and be_in(home_feed_of(bob)) + expect(status.id) + .to_not be_in(home_feed_of(tom)) + expect(status.id) + .to_not be_in(home_feed_of(tagf)) - it 'is not added to the home feed of the other follower', :inline_jobs do - expect(home_feed_of(tom)).to_not include status.id - end - - it 'is not added to the tag follower', :inline_jobs do - expect(home_feed_of(tagf)).to_not include status.id - end - - it 'is not broadcast publicly', :inline_jobs do - expect(redis).to_not have_received(:publish).with('timeline:hashtag:hoge', anything) - expect(redis).to_not have_received(:publish).with('timeline:public', anything) + expect_no_broadcasting end context 'with list' do @@ -349,26 +323,15 @@ def antenna_with_options(owner, **options) context 'when status is private' do let(:visibility) { 'private' } - it 'is added to the home feed of its author', :inline_jobs do - expect(home_feed_of(alice)).to include status.id - end - - it 'is added to the home feed of a follower', :inline_jobs do - expect(home_feed_of(bob)).to include status.id - expect(home_feed_of(tom)).to include status.id - end + it 'is added to the home feed of its author and mentioned followers and does not broadcast', :inline_jobs do + expect(status.id) + .to be_in(home_feed_of(alice)) + .and be_in(home_feed_of(bob)) + .and be_in(home_feed_of(tom)) + expect(status.id) + .to_not be_in(home_feed_of(tagf)) - it 'is not added to the tag follower', :inline_jobs do - expect(home_feed_of(tagf)).to_not include status.id - end - - it 'is not broadcast publicly', :inline_jobs do - expect(redis).to_not have_received(:publish).with('timeline:hashtag:hoge', anything) - expect(redis).to_not have_received(:publish).with('timeline:public', anything) - end - - it 'is added to the home feed of the mentioned follower', :inline_jobs do - expect(home_feed_of(bob)).to include status.id + expect_no_broadcasting end context 'with list' do @@ -430,20 +393,14 @@ def antenna_with_options(owner, **options) context 'when status is public_unlisted' do let(:visibility) { 'public_unlisted' } - it 'is added to the home feed of its author', :inline_jobs do - expect(home_feed_of(alice)).to include status.id - end - - it 'is added to the home feed of a follower', :inline_jobs do - expect(home_feed_of(bob)).to include status.id - expect(home_feed_of(tom)).to include status.id - end - - it 'is added to the tag follower', :inline_jobs do - expect(home_feed_of(tagf)).to include status.id - end + it 'is added to the home feed of its author and mentioned followers and does not broadcast', :inline_jobs do + expect(status.id) + .to be_in(home_feed_of(alice)) + .and be_in(home_feed_of(bob)) + .and be_in(home_feed_of(tom)) + expect(status.id) + .to be_in(home_feed_of(tagf)) - it 'is broadcast publicly', :inline_jobs do expect(redis).to have_received(:publish).with('timeline:hashtag:hoge', anything) expect(redis).to have_received(:publish).with('timeline:public:local', anything) expect(redis).to have_received(:publish).with('timeline:public', anything) @@ -549,20 +506,14 @@ def antenna_with_options(owner, **options) context 'when status is unlisted' do let(:visibility) { 'unlisted' } - it 'is added to the home feed of its author', :inline_jobs do - expect(home_feed_of(alice)).to include status.id - end - - it 'is added to the home feed of a follower', :inline_jobs do - expect(home_feed_of(bob)).to include status.id - expect(home_feed_of(tom)).to include status.id - end - - it 'is added to the tag follower', :inline_jobs do - expect(home_feed_of(tagf)).to include status.id - end + it 'is added to the home feed of its author and mentioned followers and does not broadcast', :inline_jobs do + expect(status.id) + .to be_in(home_feed_of(alice)) + .and be_in(home_feed_of(bob)) + .and be_in(home_feed_of(tom)) + expect(status.id) + .to be_in(home_feed_of(tagf)) - it 'is not broadcast publicly', :inline_jobs do expect(redis).to have_received(:publish).with('timeline:hashtag:hoge', anything) expect(redis).to_not have_received(:publish).with('timeline:public', anything) end @@ -570,27 +521,25 @@ def antenna_with_options(owner, **options) context 'with searchability public_unlisted' do let(:searchability) { 'public_unlisted' } - it 'is broadcast to the hashtag stream', :inline_jobs do + it 'is added to the home feed of its author and mentioned followers and does not broadcast', :inline_jobs do + expect(status.id) + .to be_in(home_feed_of(tagf)) + expect(redis).to have_received(:publish).with('timeline:hashtag:hoge', anything) expect(redis).to have_received(:publish).with('timeline:hashtag:hoge:local', anything) end - - it 'is added to the tag follower', :inline_jobs do - expect(home_feed_of(tagf)).to include status.id - end end context 'with searchability private' do let(:searchability) { 'private' } - it 'is not broadcast to the hashtag stream', :inline_jobs do + it 'is added to the home feed of its author and mentioned followers and does not broadcast', :inline_jobs do + expect(status.id) + .to_not be_in(home_feed_of(tagf)) + expect(redis).to_not have_received(:publish).with('timeline:hashtag:hoge', anything) expect(redis).to_not have_received(:publish).with('timeline:hashtag:hoge:local', anything) end - - it 'is not added to the tag follower', :inline_jobs do - expect(home_feed_of(tagf)).to_not include status.id - end end context 'when local timeline is disabled' do @@ -670,25 +619,16 @@ def antenna_with_options(owner, **options) context 'when status is direct' do let(:visibility) { 'direct' } - it 'is added to the home feed of its author', :inline_jobs do - expect(home_feed_of(alice)).to include status.id - end + it 'is added to the home feed of its author and mentioned followers and does not broadcast', :inline_jobs do + expect(status.id) + .to be_in(home_feed_of(alice)) + .and be_in(home_feed_of(bob)) + expect(status.id) + .to_not be_in(home_feed_of(tom)) + expect(status.id) + .to_not be_in(home_feed_of(tagf)) - it 'is added to the home feed of the mentioned follower', :inline_jobs do - expect(home_feed_of(bob)).to include status.id - end - - it 'is not added to the home feed of the other follower', :inline_jobs do - expect(home_feed_of(tom)).to_not include status.id - end - - it 'is not added to the tag follower', :inline_jobs do - expect(home_feed_of(tagf)).to_not include status.id - end - - it 'is not broadcast publicly', :inline_jobs do - expect(redis).to_not have_received(:publish).with('timeline:hashtag:hoge', anything) - expect(redis).to_not have_received(:publish).with('timeline:public', anything) + expect_no_broadcasting end context 'with list' do @@ -746,16 +686,15 @@ def antenna_with_options(owner, **options) expect(notification.mention.status_id).to eq status.id end - it 'inserts home feed for reply', :inline_jobs do - expect(home_feed_of(bob)).to include status.id - end + it 'is added to the home feed of its author and mentioned followers and does not broadcast', :inline_jobs do + expect(status.id) + .to be_in(home_feed_of(alice)) + .and be_in(home_feed_of(bob)) + .and be_in(home_feed_of(zilu)) + expect(status.id) + .to_not be_in(home_feed_of(tom)) - it 'inserts home feed for non-replied but mentioned and following replied account', :inline_jobs do - expect(home_feed_of(zilu)).to include status.id - end - - it 'does not insert home feed for non-replied, non-following replied account but mentioned', :inline_jobs do - expect(home_feed_of(tom)).to_not include status.id + expect_no_broadcasting end end @@ -776,16 +715,15 @@ def antenna_with_options(owner, **options) expect(notification.mention.status_id).to eq status.id end - it 'inserts home feed for reply', :inline_jobs do - expect(home_feed_of(bob)).to include status.id - end + it 'is added to the home feed of its author and mentioned followers and does not broadcast', :inline_jobs do + expect(status.id) + .to be_in(home_feed_of(alice)) + .and be_in(home_feed_of(bob)) + .and be_in(home_feed_of(zilu)) + expect(status.id) + .to_not be_in(home_feed_of(tom)) - it 'inserts home feed for non-replied but mentioned and following replied account', :inline_jobs do - expect(home_feed_of(zilu)).to include status.id - end - - it 'does not insert home feed for non-replied, non-following replied account but mentioned', :inline_jobs do - expect(home_feed_of(tom)).to_not include status.id + expect_no_broadcasting end end end @@ -820,4 +758,13 @@ def antenna_with_options(owner, **options) expect(notification).to be_nil end end + + def expect_no_broadcasting + expect(redis) + .to_not have_received(:publish) + .with('timeline:hashtag:hoge', anything) + expect(redis) + .to_not have_received(:publish) + .with('timeline:public', anything) + end end diff --git a/spec/services/report_service_spec.rb b/spec/services/report_service_spec.rb index 393a59e30ed5f3..24fffcce635bbc 100644 --- a/spec/services/report_service_spec.rb +++ b/spec/services/report_service_spec.rb @@ -23,6 +23,11 @@ stub_request(:post, 'http://example.com/inbox').to_return(status: 200) end + it 'does not have an application' do + report = subject.call(source_account, remote_account) + expect(report.application).to be_nil + end + context 'when forward is true', :inline_jobs do let(:forward) { true } @@ -96,6 +101,15 @@ end end + context 'when passed an application' do + let(:application) { Fabricate(:application) } + + it 'has an application' do + report = subject.call(source_account, target_account, application: application) + expect(report.application).to eq application + end + end + context 'when the reported status is a DM' do subject do -> { described_class.new.call(source_account, target_account, status_ids: [status.id]) } diff --git a/spec/support/javascript_errors.rb b/spec/support/javascript_errors.rb index 76452853622b78..ef5945f37dcb79 100644 --- a/spec/support/javascript_errors.rb +++ b/spec/support/javascript_errors.rb @@ -5,6 +5,7 @@ # Classes of intermittent ignorable errors ignored_errors = [ /Error while trying to use the following icon from the Manifest/, # https://github.com/mastodon/mastodon/pull/30793 + /Manifest: Line: 1, column: 1, Syntax error/, # Similar parsing/interruption issue as above ] errors = page.driver.browser.logs.get(:browser).reject do |error| ignored_errors.any? { |pattern| pattern.match(error.message) } diff --git a/spec/validators/note_length_validator_spec.rb b/spec/validators/note_length_validator_spec.rb index 66fccad3ece3be..3bca93a283da2f 100644 --- a/spec/validators/note_length_validator_spec.rb +++ b/spec/validators/note_length_validator_spec.rb @@ -6,7 +6,7 @@ subject { described_class.new(attributes: { note: true }, maximum: 500) } describe '#validate' do - it 'adds an error when text is over 500 characters' do + it 'adds an error when text is over configured character limit' do text = 'a' * 520 account = instance_double(Account, note: text, errors: activemodel_errors) @@ -14,16 +14,16 @@ expect(account.errors).to have_received(:add) end - it 'counts URLs as 23 characters flat' do - text = ('a' * 476) + " http://#{'b' * 30}.com/example" + it 'reduces calculated length of auto-linkable space-separated URLs' do + text = [starting_string, example_link].join(' ') account = instance_double(Account, note: text, errors: activemodel_errors) subject.validate_each(account, 'note', text) expect(account.errors).to_not have_received(:add) end - it 'does not count non-autolinkable URLs as 23 characters flat' do - text = ('a' * 476) + "http://#{'b' * 30}.com/example" + it 'does not reduce calculated length of non-autolinkable URLs' do + text = [starting_string, example_link].join account = instance_double(Account, note: text, errors: activemodel_errors) subject.validate_each(account, 'note', text) @@ -32,6 +32,14 @@ private + def starting_string + 'a' * 476 + end + + def example_link + "http://#{'b' * 30}.com/example" + end + def activemodel_errors instance_double(ActiveModel::Errors, add: nil) end diff --git a/spec/validators/reaction_validator_spec.rb b/spec/validators/reaction_validator_spec.rb index d73104cb6928fa..f99c1cb5f93ddf 100644 --- a/spec/validators/reaction_validator_spec.rb +++ b/spec/validators/reaction_validator_spec.rb @@ -19,8 +19,9 @@ expect(reaction.errors).to be_empty end - it 'adds error when 8 reactions already exist' do - %w(🐘 ❤️ 🙉 😍 😋 😂 😞 👍).each do |name| + it 'adds error when reaction limit count has already been reached' do + stub_const 'ReactionValidator::LIMIT', 2 + %w(🐘 ❤️).each do |name| announcement.announcement_reactions.create!(name: name, account: Fabricate(:account)) end diff --git a/spec/validators/status_length_validator_spec.rb b/spec/validators/status_length_validator_spec.rb index ead69dfe21df6e..249b90f4904e3d 100644 --- a/spec/validators/status_length_validator_spec.rb +++ b/spec/validators/status_length_validator_spec.rb @@ -42,23 +42,23 @@ expect(status.errors).to have_received(:add) end - it 'counts URLs as 23 characters flat' do - text = ('a' * 476) + " http://#{'b' * 30}.com/example" + it 'reduces calculated length of auto-linkable space-separated URLs' do + text = [starting_string, example_link].join(' ') status = status_double(text: text) subject.validate(status) expect(status.errors).to_not have_received(:add) end - it 'does not count non-autolinkable URLs as 23 characters flat' do - text = ('a' * 476) + "http://#{'b' * 30}.com/example" + it 'does not reduce calculated length of non-autolinkable URLs' do + text = [starting_string, example_link].join status = status_double(text: text) subject.validate(status) expect(status.errors).to have_received(:add) end - it 'does not count overly long URLs as 23 characters flat' do + it 'does not reduce calculated length of count overly long URLs' do text = "http://example.com/valid?#{'#foo?' * 1000}" status = status_double(text: text) subject.validate(status) @@ -84,6 +84,14 @@ private + def starting_string + 'a' * 476 + end + + def example_link + "http://#{'b' * 30}.com/example" + end + def status_double(spoiler_text: '', text: '') instance_double( Status, diff --git a/yarn.lock b/yarn.lock index 826b64696df6ff..7a8ee5532f3f0e 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2869,7 +2869,7 @@ __metadata: eslint-plugin-react-hooks: "npm:^4.6.0" file-loader: "npm:^6.2.0" font-awesome: "npm:^4.7.0" - fuzzysort: "npm:^2.0.4" + fuzzysort: "npm:^3.0.0" glob: "npm:^10.2.6" history: "npm:^4.10.1" hoist-non-react-statics: "npm:^3.3.2" @@ -2890,7 +2890,7 @@ __metadata: postcss: "npm:^8.4.24" postcss-loader: "npm:^4.3.0" postcss-preset-env: "npm:^9.5.2" - prettier: "npm:^3.0.0" + prettier: "npm:^3.3.3" prop-types: "npm:^15.8.1" punycode: "npm:^2.3.0" react: "npm:^18.2.0" @@ -2929,6 +2929,7 @@ __metadata: tiny-queue: "npm:^0.2.1" twitter-text: "npm:3.1.0" typescript: "npm:^5.0.4" + use-debounce: "npm:^10.0.0" webpack: "npm:^4.47.0" webpack-assets-manifest: "npm:^4.0.6" webpack-bundle-analyzer: "npm:^4.8.0" @@ -3755,9 +3756,9 @@ __metadata: linkType: hard "@types/lodash@npm:^4.14.195": - version: 4.17.6 - resolution: "@types/lodash@npm:4.17.6" - checksum: 10c0/3b197ac47af9443fee8c4719c5ffde527d7febc018b827d44a6bc2523c728c7adfdd25196fdcfe3eed827993e0c41a917d0da6e78938b18b2be94164789f1117 + version: 4.17.7 + resolution: "@types/lodash@npm:4.17.7" + checksum: 10c0/40c965b5ffdcf7ff5c9105307ee08b782da228c01b5c0529122c554c64f6b7168fc8f11dc79aa7bae4e67e17efafaba685dc3a47e294dbf52a65ed2b67100561 languageName: node linkType: hard @@ -4135,11 +4136,11 @@ __metadata: linkType: hard "@types/ws@npm:^8.5.9": - version: 8.5.10 - resolution: "@types/ws@npm:8.5.10" + version: 8.5.11 + resolution: "@types/ws@npm:8.5.11" dependencies: "@types/node": "npm:*" - checksum: 10c0/e9af279b984c4a04ab53295a40aa95c3e9685f04888df5c6920860d1dd073fcc57c7bd33578a04b285b2c655a0b52258d34bee0a20569dca8defb8393e1e5d29 + checksum: 10c0/50bd2e1a12659fa024a97d7e8c267fbf2a2c2251f1edf2057aa7dfc99682f5c025a188df9e27414675c78d3b189346a3567e1e4c218ad79a9d2b0f1f2b860c3a languageName: node linkType: hard @@ -8903,10 +8904,10 @@ __metadata: languageName: node linkType: hard -"fuzzysort@npm:^2.0.4": - version: 2.0.4 - resolution: "fuzzysort@npm:2.0.4" - checksum: 10c0/3170d16fccc0f4ac5e31323dbab7d0da7b1a4024878ed4d6b4ec86c0df94e12dc335f8d4181e38d97ca7919ac51bc5de4a9c2ec94914a4e51f9e9c05208c9ea9 +"fuzzysort@npm:^3.0.0": + version: 3.0.2 + resolution: "fuzzysort@npm:3.0.2" + checksum: 10c0/c6cdbd092a8e91ed822aeac6d4fb95559759c10602cb29f27307c1cabd01fdd384fa399f7757722435b595244efb000cd63f144104c41b8551b2faff123279cb languageName: node linkType: hard @@ -9545,13 +9546,13 @@ __metadata: languageName: node linkType: hard -"https-proxy-agent@npm:^7.0.1, https-proxy-agent@npm:^7.0.4": - version: 7.0.4 - resolution: "https-proxy-agent@npm:7.0.4" +"https-proxy-agent@npm:^7.0.1, https-proxy-agent@npm:^7.0.5": + version: 7.0.5 + resolution: "https-proxy-agent@npm:7.0.5" dependencies: agent-base: "npm:^7.0.2" debug: "npm:4" - checksum: 10c0/bc4f7c38da32a5fc622450b6cb49a24ff596f9bd48dcedb52d2da3fa1c1a80e100fb506bd59b326c012f21c863c69b275c23de1a01d0b84db396822fdf25e52b + checksum: 10c0/2490e3acec397abeb88807db52cac59102d5ed758feee6df6112ab3ccd8325e8a1ce8bce6f4b66e5470eca102d31e425ace904242e4fa28dbe0c59c4bafa7b2c languageName: node linkType: hard @@ -9648,9 +9649,9 @@ __metadata: linkType: hard "immutable@npm:^4.0.0, immutable@npm:^4.0.0-rc.1, immutable@npm:^4.3.0": - version: 4.3.6 - resolution: "immutable@npm:4.3.6" - checksum: 10c0/7d0952a768b4fadcee47230ed86dc9505a4517095eceaf5a47e65288571c42400c6e4a2ae21eca4eda957cb7bc50720213135b62cf6a181639111f8acae128c3 + version: 4.3.7 + resolution: "immutable@npm:4.3.7" + checksum: 10c0/9b099197081b22f6433003e34929da8ecddbbdc1474cdc8aa3b7669dee4adda349c06143de22def36016d1b6de5322b043eccd7a11db1dad2ca85dad4fff5435 languageName: node linkType: hard @@ -11122,8 +11123,8 @@ __metadata: linkType: hard "jsdom@npm:^24.0.0": - version: 24.1.0 - resolution: "jsdom@npm:24.1.0" + version: 24.1.1 + resolution: "jsdom@npm:24.1.1" dependencies: cssstyle: "npm:^4.0.1" data-urls: "npm:^5.0.0" @@ -11131,11 +11132,11 @@ __metadata: form-data: "npm:^4.0.0" html-encoding-sniffer: "npm:^4.0.0" http-proxy-agent: "npm:^7.0.2" - https-proxy-agent: "npm:^7.0.4" + https-proxy-agent: "npm:^7.0.5" is-potential-custom-element-name: "npm:^1.0.1" - nwsapi: "npm:^2.2.10" + nwsapi: "npm:^2.2.12" parse5: "npm:^7.1.2" - rrweb-cssom: "npm:^0.7.0" + rrweb-cssom: "npm:^0.7.1" saxes: "npm:^6.0.0" symbol-tree: "npm:^3.2.4" tough-cookie: "npm:^4.1.4" @@ -11144,14 +11145,14 @@ __metadata: whatwg-encoding: "npm:^3.1.1" whatwg-mimetype: "npm:^4.0.0" whatwg-url: "npm:^14.0.0" - ws: "npm:^8.17.0" + ws: "npm:^8.18.0" xml-name-validator: "npm:^5.0.0" peerDependencies: canvas: ^2.11.2 peerDependenciesMeta: canvas: optional: true - checksum: 10c0/34eadd8a7ae20c1505abe7a0f3988b2f0881cce7e27d75c4f5224f440f81f8ac08f4f449695b0f4178f048ed1c1709f3594e9d3f2fe0406c28e8da6eddd44f5a + checksum: 10c0/02d6bfe32f09f26329c0e53ad9f9883a3c671fc1f75725167d2089ca412f5b7ca85ff8aa62327d1cc6fc70ffbb3b18dfc7642c4b2096c2c8b19aaf9a48473eb3 languageName: node linkType: hard @@ -12444,10 +12445,10 @@ __metadata: languageName: node linkType: hard -"nwsapi@npm:^2.2.10, nwsapi@npm:^2.2.2": - version: 2.2.10 - resolution: "nwsapi@npm:2.2.10" - checksum: 10c0/43dfa150387bd2a578e37556d0ae3330d5617f99e5a7b64e3400d4c2785620762aa6169caf8f5fbce17b7ef29c372060b602594320c374fba0a39da4163d77ed +"nwsapi@npm:^2.2.12, nwsapi@npm:^2.2.2": + version: 2.2.12 + resolution: "nwsapi@npm:2.2.12" + checksum: 10c0/95e9623d63df111405503df8c5d800e26f71675d319e2c9c70cddfa31e5ace1d3f8b6d98d354544fc156a1506d920ec291e303fab761e4f99296868e199a466e languageName: node linkType: hard @@ -13224,8 +13225,8 @@ __metadata: linkType: hard "pino@npm:^9.0.0": - version: 9.2.0 - resolution: "pino@npm:9.2.0" + version: 9.3.1 + resolution: "pino@npm:9.3.1" dependencies: atomic-sleep: "npm:^1.0.0" fast-redact: "npm:^3.1.1" @@ -13240,7 +13241,7 @@ __metadata: thread-stream: "npm:^3.0.0" bin: pino: bin.js - checksum: 10c0/5fbd226ff7dab0961232b5aa5eca0530cdc5bb29f6bf17d929e42239293b1a587a26cc311db6abc1090c9dd57e8f7b031eae341b41d00d4a642b4f1736474c80 + checksum: 10c0/ab1e81b3e5a91852136d80a592939883eeb81442e5d3a2c070bdbdeb47c5aaa297ead246530b10eb6d5ff59445f4645d1333d342f255d9f002f73aea843e74ee languageName: node linkType: hard @@ -14156,12 +14157,12 @@ __metadata: languageName: node linkType: hard -"prettier@npm:^3.0.0": - version: 3.3.2 - resolution: "prettier@npm:3.3.2" +"prettier@npm:^3.3.3": + version: 3.3.3 + resolution: "prettier@npm:3.3.3" bin: prettier: bin/prettier.cjs - checksum: 10c0/39ed27d17f0238da6dd6571d63026566bd790d3d0edac57c285fbab525982060c8f1e01955fe38134ab10f0951a6076da37f015db8173c02f14bc7f0803a384c + checksum: 10c0/b85828b08e7505716324e4245549b9205c0cacb25342a030ba8885aba2039a115dbcf75a0b7ca3b37bc9d101ee61fab8113fc69ca3359f2a226f1ecc07ad2e26 languageName: node linkType: hard @@ -15427,10 +15428,10 @@ __metadata: languageName: node linkType: hard -"rrweb-cssom@npm:^0.7.0": - version: 0.7.0 - resolution: "rrweb-cssom@npm:0.7.0" - checksum: 10c0/278350b1f383f76db20e37394361b709740bd4f5f27f924e1c3c3fdd7112b2ae37ed9bc7cee63776f7df395b9b0f644d1f8be104990e3028d276a3288cd7e564 +"rrweb-cssom@npm:^0.7.1": + version: 0.7.1 + resolution: "rrweb-cssom@npm:0.7.1" + checksum: 10c0/127b8ca6c8aac45e2755abbae6138d4a813b1bedc2caabf79466ae83ab3cfc84b5bfab513b7033f0aa4561c7753edf787d0dd01163ceacdee2e8eb1b6bf7237e languageName: node linkType: hard @@ -17617,6 +17618,15 @@ __metadata: languageName: node linkType: hard +"use-debounce@npm:^10.0.0": + version: 10.0.1 + resolution: "use-debounce@npm:10.0.1" + peerDependencies: + react: ">=16.8.0" + checksum: 10c0/377a11814a708f5c392f465cbbe2d119a8a2635c8226cc5e30eba397c4436f8e8234385d069467b369d105ed0d3be733c6a08d8ae1004017c6d6f58f4d4c24d8 + languageName: node + linkType: hard + "use-isomorphic-layout-effect@npm:^1.1.1, use-isomorphic-layout-effect@npm:^1.1.2": version: 1.1.2 resolution: "use-isomorphic-layout-effect@npm:1.1.2" @@ -18588,7 +18598,7 @@ __metadata: languageName: node linkType: hard -"ws@npm:^8.11.0, ws@npm:^8.12.1, ws@npm:^8.17.0": +"ws@npm:^8.11.0, ws@npm:^8.12.1, ws@npm:^8.18.0": version: 8.18.0 resolution: "ws@npm:8.18.0" peerDependencies: