From 0dd4595704896fecb69315c1617dcb74b1cfaf67 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Tue, 9 Jul 2024 09:27:13 +0200 Subject: [PATCH 001/126] fix(deps): update dependency glob to v10.4.4 (#30967) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- yarn.lock | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/yarn.lock b/yarn.lock index 87586a916c..e377c52129 100644 --- a/yarn.lock +++ b/yarn.lock @@ -9009,8 +9009,8 @@ __metadata: linkType: hard "glob@npm:^10.2.2, glob@npm:^10.2.6, glob@npm:^10.3.10": - version: 10.4.3 - resolution: "glob@npm:10.4.3" + version: 10.4.4 + resolution: "glob@npm:10.4.4" dependencies: foreground-child: "npm:^3.1.0" jackspeak: "npm:^3.1.2" @@ -9020,7 +9020,7 @@ __metadata: path-scurry: "npm:^1.11.1" bin: glob: dist/esm/bin.mjs - checksum: 10c0/bea148e5dae96c17e2764f4764c72376a6ab7072b27a21e861ae4af6f97f3e810d79d67f64de52f63ce1d7fdb73b7306f61c65b48d0f61ca7c8647ce8acaf9a7 + checksum: 10c0/8f0887ae6b9e7ec97841c88f3189643a326c9c37f9881050979c131a2198f2230d4b0a196b71ec6a6694871c25fb8631a72af6e2ea941a667c55f155765546ab languageName: node linkType: hard From 7a30c689530c93e8ea473e39cfb2e2ff6d9d2807 Mon Sep 17 00:00:00 2001 From: Matt Jankowski Date: Tue, 9 Jul 2024 03:34:15 -0400 Subject: [PATCH 002/126] Use `scope module: ...` block for `.well-known` routes (#30959) --- config/routes.rb | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) diff --git a/config/routes.rb b/config/routes.rb index 4b3bd4f187..5862731ba9 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -63,12 +63,16 @@ Rails.application.routes.draw do tokens: 'oauth/tokens' end - get '.well-known/oauth-authorization-server', to: 'well_known/oauth_metadata#show', as: :oauth_metadata, defaults: { format: 'json' } - get '.well-known/host-meta', to: 'well_known/host_meta#show', as: :host_meta, defaults: { format: 'xml' } - get '.well-known/nodeinfo', to: 'well_known/node_info#index', as: :nodeinfo, defaults: { format: 'json' } - get '.well-known/webfinger', to: 'well_known/webfinger#show', as: :webfinger - get '.well-known/change-password', to: redirect('/auth/edit') - get '.well-known/proxy', to: redirect { |_, request| "/authorize_interaction?#{request.params.to_query}" } + scope path: '.well-known' do + scope module: :well_known do + get 'oauth-authorization-server', to: 'oauth_metadata#show', as: :oauth_metadata, defaults: { format: 'json' } + get 'host-meta', to: 'host_meta#show', as: :host_meta, defaults: { format: 'xml' } + get 'nodeinfo', to: 'node_info#index', as: :nodeinfo, defaults: { format: 'json' } + get 'webfinger', to: 'webfinger#show', as: :webfinger + end + get 'change-password', to: redirect('/auth/edit'), as: nil + get 'proxy', to: redirect { |_, request| "/authorize_interaction?#{request.params.to_query}" }, as: nil + end get '/nodeinfo/2.0', to: 'well_known/node_info#show', as: :nodeinfo_schema From f47d761e12a16c4338447aa8dbeca8365ee812cc Mon Sep 17 00:00:00 2001 From: Matt Jankowski Date: Tue, 9 Jul 2024 03:34:19 -0400 Subject: [PATCH 003/126] Remove unneeded `controller` option in routes (#30958) --- config/routes.rb | 2 +- config/routes/settings.rb | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/config/routes.rb b/config/routes.rb index 5862731ba9..2c06762c22 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -98,7 +98,7 @@ Rails.application.routes.draw do namespace :auth do resource :setup, only: [:show, :update], controller: :setup - resource :challenge, only: [:create], controller: :challenges + resource :challenge, only: [:create] get 'sessions/security_key_options', to: 'sessions#webauthn_options' post 'captcha_confirmation', to: 'confirmations#confirm_captcha', as: :captcha_confirmation end diff --git a/config/routes/settings.rb b/config/routes/settings.rb index b14606656b..297b80942c 100644 --- a/config/routes/settings.rb +++ b/config/routes/settings.rb @@ -26,9 +26,9 @@ namespace :settings do resources :follows, only: :index, controller: :following_accounts resources :blocks, only: :index, controller: :blocked_accounts resources :mutes, only: :index, controller: :muted_accounts - resources :lists, only: :index, controller: :lists + resources :lists, only: :index resources :domain_blocks, only: :index, controller: :blocked_domains - resources :bookmarks, only: :index, controller: :bookmarks + resources :bookmarks, only: :index end resources :two_factor_authentication_methods, only: [:index] do From 249b4117f9fbdac3888d3807a81c0e83e39d7de5 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Tue, 9 Jul 2024 07:36:13 +0000 Subject: [PATCH 004/126] New Crowdin Translations (automated) (#30970) Co-authored-by: GitHub Actions --- app/javascript/mastodon/locales/ry.json | 39 +++++++++++++++++++++++-- 1 file changed, 37 insertions(+), 2 deletions(-) diff --git a/app/javascript/mastodon/locales/ry.json b/app/javascript/mastodon/locales/ry.json index 67aad91005..f3a68b15a1 100644 --- a/app/javascript/mastodon/locales/ry.json +++ b/app/javascript/mastodon/locales/ry.json @@ -3,6 +3,8 @@ "about.contact": "Контакт:", "about.disclaimer": "Mastodon є задарьнов проґрамов из удпертым кодом тай торговов значков Mastodon gGmbH.", "about.domain_blocks.no_reason_available": "Причины не ясні", + "about.domain_blocks.preamble": "Майбульш Mastodon поволят вам позирати контент тай комуніковати из хосновачами из другых федерованых серверув. Туй лиш уняткы учинені про сись конкретный сервер.", + "about.domain_blocks.silenced.explanation": "Вы майбульш не будете видіти профілі тай контент из сього сервера, кидь не будете го самі глядати авадь пудпишете ся на нього.", "about.domain_blocks.silenced.title": "Обмежено", "about.domain_blocks.suspended.explanation": "Ниякі податкы из сього сервера не будут уброблені, усокочені ци поміняні, што чинит невозможнов хоть-яку інтеракцію ци зязок из хосновачами из сього сервера.", "about.domain_blocks.suspended.title": "Заблоковано", @@ -20,6 +22,7 @@ "account.browse_more_on_origin_server": "Позирайте бульше на ориґіналнум профілю", "account.cancel_follow_request": "Удмінити пудписку", "account.copy": "Зкопіровати удкликованя на профіл", + "account.direct": "Пошептати @{name}", "account.disable_notifications": "Бульше не сповіщати ми коли {name} пише", "account.domain_blocked": "Домен заблокованый", "account.edit_profile": "Управити профіл", @@ -39,8 +42,10 @@ "account.joined_short": "Датум прикапчованя", "account.languages": "Поміняти убрані языкы", "account.link_verified_on": "Властность сього удкликованя было звірено {date}", + "account.locked_info": "Сись профіл є замкнутый. Ґазда акаунта буде ручно провіряти тко го може зафоловити.", "account.media": "Медіа", - "account.moved_to": "Хосновач {name} указав, ож новый профіл йим є:", + "account.mention": "Спомянути @{name}", + "account.moved_to": "Хосновач {name} указав, ож новый профіл му є:", "account.mute": "Стишити {name}", "account.mute_notifications_short": "Стишити голошіня", "account.mute_short": "Стишити", @@ -60,9 +65,12 @@ "account.unblock_short": "Розблоковати", "account.unendorse": "Не указовати на профілови", "account.unfollow": "Удписати ся", + "account.unmute": "Указовати {name}", "account.unmute_notifications_short": "Указовати голошіня", "account.unmute_short": "Указовати", "account_note.placeholder": "Клопкніт обы додати примітку", + "admin.dashboard.retention.average": "Середньоє", + "admin.dashboard.retention.cohort": "Місяць прикапчованя", "admin.dashboard.retention.cohort_size": "Нові хосновачі", "admin.impact_report.instance_accounts": "Профілі из акаунтув, котрі ся удалят", "admin.impact_report.instance_followers": "Пудписникы, котрых стратят наші хосновачі", @@ -70,11 +78,38 @@ "admin.impact_report.title": "Вплыв цілком", "alert.rate_limited.message": "Попробуйте зась по {retry_time, time, medium}.", "alert.rate_limited.title": "Частота обмежена", + "alert.unexpected.message": "Стала ся нечекана хыба.", + "alert.unexpected.title": "Ийой!", + "announcement.announcement": "Голошіня", + "audio.hide": "Зпрятати звук", + "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": "Не годни сьме указати зажадану сторунку. Годно быти спозад хыбы у нашум сістемі, авадь проблемы зумісности бравзера.", + "bundle_column_error.error.title": "Ийой!", + "bundle_column_error.network.body": "Стала ся хыба як сьме пробовали напаровати сторунку. Годно ся йсе было стати спозад слабого споєня вашого інтернета, авадь сервера.", + "bundle_column_error.network.title": "Хыба споєня", + "bundle_column_error.retry": "Попробуйте зась", "bundle_column_error.return": "Вернути ся на головну", "bundle_column_error.routing.body": "Не можеме найти сяку сторунку. Бизувні сьте, ож URL у адресному шорикови є добрый?", "bundle_column_error.routing.title": "404", "bundle_modal_error.close": "Заперти", "bundle_modal_error.message": "Штось ся показило, закидь сьме ладовали сись компонент.", "bundle_modal_error.retry": "Попробовати зась", - "closed_registrations.other_server_instructions": "Mastodon є децентралізованов платформов, можете си учинити профіл и на другому серверови тай комуніковати из сим." + "closed_registrations.other_server_instructions": "Mastodon є децентралізованов платформов, можете си учинити профіл и на другому серверови тай комуніковати из сим.", + "closed_registrations_modal.description": "Раз не мож учинити профіл на {domain}, айбо не мусите мати профіл ипен на серверови {domain} обы хосновати Mastodon.", + "closed_registrations_modal.find_another_server": "Найти другый сервер", + "column.about": "За сайт", + "column.blocks": "Заблоковані хосновачі", + "column.bookmarks": "Усокоченоє", + "column.direct": "Шептаня", + "column.directory": "Никати профілі", + "column.domain_blocks": "Заблоковані домены", + "column.favourites": "Убраноє" } From 7542a134d5fecf82d14dcc1860be87cf6645ec7f Mon Sep 17 00:00:00 2001 From: Renaud Chaput Date: Tue, 9 Jul 2024 12:47:08 +0200 Subject: [PATCH 005/126] Add a file for Sidekiq to signal it is ready to process jobs (#30971) --- config/initializers/sidekiq.rb | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/config/initializers/sidekiq.rb b/config/initializers/sidekiq.rb index 53b02edc40..e1d98b8ba3 100644 --- a/config/initializers/sidekiq.rb +++ b/config/initializers/sidekiq.rb @@ -2,9 +2,21 @@ require_relative '../../lib/mastodon/sidekiq_middleware' +SIDEKIQ_WILL_PROCESSES_JOBS_FILE = Rails.root.join('tmp', 'sidekiq_process_has_started_and_will_begin_processing_jobs').freeze + Sidekiq.configure_server do |config| config.redis = REDIS_SIDEKIQ_PARAMS + # This is used in Kubernetes setups, to signal that the Sidekiq process has started and will begin processing jobs + # This comes from https://github.com/sidekiq/sidekiq/wiki/Kubernetes#sidekiq + config.on(:startup) do + FileUtils.touch(SIDEKIQ_WILL_PROCESSES_JOBS_FILE) + end + + config.on(:shutdown) do + FileUtils.rm_f(SIDEKIQ_WILL_PROCESSES_JOBS_FILE) + end + config.server_middleware do |chain| chain.add Mastodon::SidekiqMiddleware end From 3875bd138d279eb26efce9f446fe91f49cf38f55 Mon Sep 17 00:00:00 2001 From: Daniel M Brasil Date: Tue, 9 Jul 2024 09:41:49 -0300 Subject: [PATCH 006/126] Fix HTTP 500 in `/api/v1/polls/:id/votes` (#25598) --- app/controllers/api/v1/polls/votes_controller.rb | 4 ++-- spec/requests/api/v1/polls/votes_spec.rb | 11 ++++++++++- 2 files changed, 12 insertions(+), 3 deletions(-) diff --git a/app/controllers/api/v1/polls/votes_controller.rb b/app/controllers/api/v1/polls/votes_controller.rb index 513b937ef2..ad1b82cb52 100644 --- a/app/controllers/api/v1/polls/votes_controller.rb +++ b/app/controllers/api/v1/polls/votes_controller.rb @@ -8,7 +8,7 @@ class Api::V1::Polls::VotesController < Api::BaseController before_action :set_poll def create - VoteService.new.call(current_account, @poll, vote_params[:choices]) + VoteService.new.call(current_account, @poll, vote_params) render json: @poll, serializer: REST::PollSerializer end @@ -22,6 +22,6 @@ class Api::V1::Polls::VotesController < Api::BaseController end def vote_params - params.permit(choices: []) + params.require(:choices) end end diff --git a/spec/requests/api/v1/polls/votes_spec.rb b/spec/requests/api/v1/polls/votes_spec.rb index e2b22708be..669f64b6e4 100644 --- a/spec/requests/api/v1/polls/votes_spec.rb +++ b/spec/requests/api/v1/polls/votes_spec.rb @@ -10,9 +10,10 @@ RSpec.describe 'API V1 Polls Votes' do describe 'POST /api/v1/polls/:poll_id/votes' do let(:poll) { Fabricate(:poll) } + let(:params) { { choices: %w(1) } } before do - post "/api/v1/polls/#{poll.id}/votes", params: { choices: %w(1) }, headers: headers + post "/api/v1/polls/#{poll.id}/votes", params: params, headers: headers end it 'creates a vote', :aggregate_failures do @@ -24,6 +25,14 @@ RSpec.describe 'API V1 Polls Votes' do expect(poll.reload.cached_tallies).to eq [0, 1] end + context 'when the required choices param is not provided' do + let(:params) { {} } + + it 'returns http bad request' do + expect(response).to have_http_status(400) + end + end + private def vote From ef2e48e6dac1ed327fc6ac07b0adf252d10ff607 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Tue, 9 Jul 2024 14:53:31 +0200 Subject: [PATCH 007/126] fix(deps): update dependency glob to v10.4.5 (#30972) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- yarn.lock | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/yarn.lock b/yarn.lock index e377c52129..85a336a4a3 100644 --- a/yarn.lock +++ b/yarn.lock @@ -9009,8 +9009,8 @@ __metadata: linkType: hard "glob@npm:^10.2.2, glob@npm:^10.2.6, glob@npm:^10.3.10": - version: 10.4.4 - resolution: "glob@npm:10.4.4" + version: 10.4.5 + resolution: "glob@npm:10.4.5" dependencies: foreground-child: "npm:^3.1.0" jackspeak: "npm:^3.1.2" @@ -9020,7 +9020,7 @@ __metadata: path-scurry: "npm:^1.11.1" bin: glob: dist/esm/bin.mjs - checksum: 10c0/8f0887ae6b9e7ec97841c88f3189643a326c9c37f9881050979c131a2198f2230d4b0a196b71ec6a6694871c25fb8631a72af6e2ea941a667c55f155765546ab + checksum: 10c0/19a9759ea77b8e3ca0a43c2f07ecddc2ad46216b786bb8f993c445aee80d345925a21e5280c7b7c6c59e860a0154b84e4b2b60321fea92cd3c56b4a7489f160e languageName: node linkType: hard From 967505ee9bcacf0e5189aa06c654ff586c198a46 Mon Sep 17 00:00:00 2001 From: David Roetzel Date: Tue, 9 Jul 2024 15:11:34 +0200 Subject: [PATCH 008/126] Add size limit for all PreviewCard URLs (#30973) --- app/models/preview_card.rb | 7 +++++- app/services/fetch_link_card_service.rb | 7 ++---- spec/fixtures/requests/long_canonical_url.txt | 18 +++++++++++++++ spec/services/fetch_link_card_service_spec.rb | 22 ++++++++----------- 4 files changed, 35 insertions(+), 19 deletions(-) create mode 100644 spec/fixtures/requests/long_canonical_url.txt diff --git a/app/models/preview_card.rb b/app/models/preview_card.rb index eac02ac14f..5a11351e58 100644 --- a/app/models/preview_card.rb +++ b/app/models/preview_card.rb @@ -46,6 +46,11 @@ class PreviewCard < ApplicationRecord y_comp: 4, }.freeze + # URL size limit to safely store in PosgreSQL's unique indexes + # Technically this is a byte-size limit but we use it as a + # character limit to work with length validation + URL_CHARACTER_LIMIT = 2692 + self.inheritance_column = false enum :type, { link: 0, photo: 1, video: 2, rich: 3 } @@ -63,7 +68,7 @@ class PreviewCard < ApplicationRecord convert_options: { all: '-quality 90 +profile "!icc,*" +set date:modify +set date:create +set date:timestamp' }, validate_media_type: false - validates :url, presence: true, uniqueness: true, url: true + validates :url, presence: true, uniqueness: true, url: true, length: { maximum: URL_CHARACTER_LIMIT } validates_attachment_content_type :image, content_type: IMAGE_MIME_TYPES validates_attachment_size :image, less_than: LIMIT remotable_attachment :image, LIMIT diff --git a/app/services/fetch_link_card_service.rb b/app/services/fetch_link_card_service.rb index 436e024c99..adabb1096e 100644 --- a/app/services/fetch_link_card_service.rb +++ b/app/services/fetch_link_card_service.rb @@ -15,9 +15,6 @@ class FetchLinkCardService < BaseService ) }iox - # URL size limit to safely store in PosgreSQL's unique indexes - BYTESIZE_LIMIT = 2692 - def call(status) @status = status @original_url = parse_urls @@ -32,7 +29,7 @@ class FetchLinkCardService < BaseService end attach_card if @card&.persisted? - rescue HTTP::Error, OpenSSL::SSL::SSLError, Addressable::URI::InvalidURIError, Mastodon::HostValidationError, Mastodon::LengthValidationError, EncodingError => e + rescue HTTP::Error, OpenSSL::SSL::SSLError, Addressable::URI::InvalidURIError, Mastodon::HostValidationError, Mastodon::LengthValidationError, EncodingError, ActiveRecord::RecordInvalid => e Rails.logger.debug { "Error fetching link #{@original_url}: #{e}" } nil end @@ -88,7 +85,7 @@ class FetchLinkCardService < BaseService def bad_url?(uri) # Avoid local instance URLs and invalid URLs - uri.host.blank? || TagManager.instance.local_url?(uri.to_s) || !%w(http https).include?(uri.scheme) || uri.to_s.bytesize > BYTESIZE_LIMIT + uri.host.blank? || TagManager.instance.local_url?(uri.to_s) || !%w(http https).include?(uri.scheme) end def mention_link?(anchor) diff --git a/spec/fixtures/requests/long_canonical_url.txt b/spec/fixtures/requests/long_canonical_url.txt new file mode 100644 index 0000000000..97d6c93961 --- /dev/null +++ b/spec/fixtures/requests/long_canonical_url.txt @@ -0,0 +1,18 @@ +HTTP/1.1 200 OK +server: nginx +date: Thu, 13 Jun 2024 14:33:13 GMT +content-type: text/html; charset=utf-8 +content-length: 3225 +accept-ranges: bytes + + + + + + + Very long canonical URL + + +

We have very long URLs

+ + diff --git a/spec/services/fetch_link_card_service_spec.rb b/spec/services/fetch_link_card_service_spec.rb index b2cd99cea6..342902cdb3 100644 --- a/spec/services/fetch_link_card_service_spec.rb +++ b/spec/services/fetch_link_card_service_spec.rb @@ -31,6 +31,7 @@ RSpec.describe FetchLinkCardService do stub_request(:get, 'http://example.com/latin1_posing_as_utf8_recoverable').to_return(request_fixture('latin1_posing_as_utf8_recoverable.txt')) stub_request(:get, 'http://example.com/aergerliche-umlaute').to_return(request_fixture('redirect_with_utf8_url.txt')) stub_request(:get, 'http://example.com/page_without_title').to_return(request_fixture('page_without_title.txt')) + stub_request(:get, 'http://example.com/long_canonical_url').to_return(request_fixture('long_canonical_url.txt')) Rails.cache.write('oembed_endpoint:example.com', oembed_cache) if oembed_cache @@ -233,19 +234,6 @@ RSpec.describe FetchLinkCardService do end end - context 'with an URL too long for PostgreSQL unique indexes' do - let(:url) { "http://example.com/#{'a' * 2674}" } - let(:status) { Fabricate(:status, text: url) } - - it 'does not fetch the URL' do - expect(a_request(:get, url)).to_not have_been_made - end - - it 'does not create a preview card' do - expect(status.preview_card).to be_nil - end - end - context 'with a URL of a page with oEmbed support' do let(:html) { 'Hello world' } let(:status) { Fabricate(:status, text: 'http://example.com/html') } @@ -296,6 +284,14 @@ RSpec.describe FetchLinkCardService do end end end + + context 'with a URL of a page that includes a canonical URL too long for PostgreSQL unique indexes' do + let(:status) { Fabricate(:status, text: 'test http://example.com/long_canonical_url') } + + it 'does not create a preview card' do + expect(status.preview_card).to be_nil + end + end end context 'with a remote status' do From c9f08f77ed8a262a4db806d814e2701794873a70 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Wed, 10 Jul 2024 08:55:26 +0200 Subject: [PATCH 009/126] fix(deps): update dependency sass to v1.77.7 (#30981) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- yarn.lock | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/yarn.lock b/yarn.lock index 85a336a4a3..cf7e5a8b95 100644 --- a/yarn.lock +++ b/yarn.lock @@ -15462,15 +15462,15 @@ __metadata: linkType: hard "sass@npm:^1.62.1": - version: 1.77.6 - resolution: "sass@npm:1.77.6" + version: 1.77.7 + resolution: "sass@npm:1.77.7" dependencies: chokidar: "npm:>=3.0.0 <4.0.0" immutable: "npm:^4.0.0" source-map-js: "npm:>=0.6.2 <2.0.0" bin: sass: sass.js - checksum: 10c0/fe5a393c0aa29eda9f83c06be9b94788b61fe8bad0616ee6e3a25d21ab504f430d40c0064fdca89b02b8e426411ae6dcd906c91f2e48c263575c3d392b6daeb1 + checksum: 10c0/6cacbf4b5165d30a9be0f09438aed85ff0617e5087442e65c23c8464750ff1b9988855a58f36b420b62f992d1e82403f99810aba7731519d3d026847e21a5635 languageName: node linkType: hard From d0137910c61a565cfdaa8cf29d3e15e6345e5066 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Wed, 10 Jul 2024 12:04:11 +0200 Subject: [PATCH 010/126] chore(deps): update dependency ruby to v3.3.4 (#30969) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- .ruby-version | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.ruby-version b/.ruby-version index 619b537668..a0891f563f 100644 --- a/.ruby-version +++ b/.ruby-version @@ -1 +1 @@ -3.3.3 +3.3.4 From 8dea897a3b2a6be08911515d291eb679dc3cd792 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Wed, 10 Jul 2024 10:04:52 +0000 Subject: [PATCH 011/126] chore(deps): update docker.io/ruby docker tag to v3.3.4 (#30980) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- Dockerfile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Dockerfile b/Dockerfile index 7f7eca06da..52d3758dc6 100644 --- a/Dockerfile +++ b/Dockerfile @@ -12,7 +12,7 @@ ARG BUILDPLATFORM=${BUILDPLATFORM} # Ruby image to use for base image, change with [--build-arg RUBY_VERSION="3.3.x"] # renovate: datasource=docker depName=docker.io/ruby -ARG RUBY_VERSION="3.3.3" +ARG RUBY_VERSION="3.3.4" # # Node version to use in base image, change with [--build-arg NODE_MAJOR_VERSION="20"] # renovate: datasource=node-version depName=node ARG NODE_MAJOR_VERSION="20" From 9984fca9a065e49acde0858487bc3cf10a744cea Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Wed, 10 Jul 2024 12:40:19 +0200 Subject: [PATCH 012/126] New Crowdin Translations (automated) (#30983) Co-authored-by: GitHub Actions --- app/javascript/mastodon/locales/cs.json | 16 +++++----- app/javascript/mastodon/locales/ry.json | 41 ++++++++++++++++++++++++- config/locales/cs.yml | 2 +- config/locales/doorkeeper.lv.yml | 6 ++-- config/locales/ry.yml | 20 ++++++++++++ 5 files changed, 73 insertions(+), 12 deletions(-) diff --git a/app/javascript/mastodon/locales/cs.json b/app/javascript/mastodon/locales/cs.json index e96e283970..12de5d5ecd 100644 --- a/app/javascript/mastodon/locales/cs.json +++ b/app/javascript/mastodon/locales/cs.json @@ -197,7 +197,7 @@ "copy_icon_button.copied": "Zkopírováno do schránky", "copypaste.copied": "Zkopírováno", "copypaste.copy_to_clipboard": "Zkopírovat do schránky", - "directory.federated": "Ze známého fedivesmíru", + "directory.federated": "Ze známého fediversu", "directory.local": "Pouze z {domain}", "directory.new_arrivals": "Nově příchozí", "directory.recently_active": "Nedávno aktivní", @@ -213,7 +213,7 @@ "domain_block_modal.block_account_instead": "Raději blokovat @{name}", "domain_block_modal.they_can_interact_with_old_posts": "Lidé z tohoto serveru mohou interagovat s vašimi starými příspěvky.", "domain_block_modal.they_cant_follow": "Nikdo z tohoto serveru vás nemůže sledovat.", - "domain_block_modal.they_wont_know": "Nebude vědět, že je zablokován.", + "domain_block_modal.they_wont_know": "Nebude vědět, že je zablokován*a.", "domain_block_modal.title": "Blokovat doménu?", "domain_block_modal.you_will_lose_followers": "Všichni vaši sledující z tohoto serveru budou odstraněni.", "domain_block_modal.you_wont_see_posts": "Neuvidíte příspěvky ani upozornění od uživatelů z tohoto serveru.", @@ -341,7 +341,7 @@ "hashtag.column_settings.tag_mode.any": "Jakýkoliv z těchto", "hashtag.column_settings.tag_mode.none": "Žádný z těchto", "hashtag.column_settings.tag_toggle": "Zahrnout v tomto sloupci další štítky", - "hashtag.counter_by_accounts": "{count, plural, one {{counter} účastník} few {{counter} účastníci} other {{counter} účastníků}}", + "hashtag.counter_by_accounts": "{count, plural, one {{counter} účastník*ice} few {{counter} účastníci} other {{counter} účastníků}}", "hashtag.counter_by_uses": "{count, plural, one {{counter} příspěvek} few {{counter} příspěvky} other {{counter} příspěvků}}", "hashtag.counter_by_uses_today": "Dnes {count, plural, one {{counter} příspěvek} few {{counter} příspěvky} other {{counter} příspěvků}}", "hashtag.follow": "Sledovat hashtag", @@ -440,7 +440,7 @@ "mute_modal.show_options": "Zobrazit možnosti", "mute_modal.they_can_mention_and_follow": "Mohou vás zmínit a sledovat, ale neuvidíte je.", "mute_modal.they_wont_know": "Nebudou vědět, že byli skryti.", - "mute_modal.title": "Ztlumit uživatele?", + "mute_modal.title": "Ztlumit uživatele*ku?", "mute_modal.you_wont_see_mentions": "Neuvidíte příspěvky, které je zmiňují.", "mute_modal.you_wont_see_posts": "Stále budou moci vidět vaše příspěvky, ale vy jejich neuvidíte.", "navigation_bar.about": "O aplikaci", @@ -566,8 +566,8 @@ "onboarding.share.message": "Jsem {username} na #Mastodonu! Pojď mě sledovat na {url}", "onboarding.share.next_steps": "Možné další kroky:", "onboarding.share.title": "Sdílejte svůj profil", - "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.lead": "Nyní jste součástí Mastodonu, unikátní sociální sítě, kde vy - ne algoritmus - vytváří vaše vlastní prožitky. Začněte na této nové sociální platformě:", + "onboarding.start.skip": "Nepotřebujete pomoci začít?", "onboarding.start.title": "Dokázali jste to!", "onboarding.steps.follow_people.body": "Mastodon je o sledování zajimavých lidí.", "onboarding.steps.follow_people.title": "Přispůsobit vlastní domovský kanál", @@ -581,7 +581,7 @@ "onboarding.tips.accounts_from_other_servers": "Víte, že? Protože je Mastodon decentralizovaný, některé profily, na které narazíte, budou hostovány na jiných serverech, než je ten váš. A přesto s nimi můžete bezproblémově komunikovat! Jejich server se nachází v druhé polovině uživatelského jména!", "onboarding.tips.migration": "Víte, že? Pokud máte pocit, že {domain} pro vás v budoucnu není vhodnou volbou, můžete se přesunout na jiný Mastodon server, aniž byste přišli o své sledující. Můžete dokonce hostovat svůj vlastní server!", "onboarding.tips.verification": "Víte, že? Svůj účet můžete ověřit tak, že na své webové stránky umístíte odkaz na váš Mastodon profil a odkaz na stránku přidáte do svého profilu. Nejsou k tomu potřeba žádné poplatky ani dokumenty!", - "password_confirmation.exceeds_maxlength": "Potvrzení hesla překračuje maximální délku hesla", + "password_confirmation.exceeds_maxlength": "Potvrzení hesla překračuje maximální povolenou délku hesla", "password_confirmation.mismatching": "Zadaná hesla se neshodují", "picture_in_picture.restore": "Vrátit zpět", "poll.closed": "Uzavřeno", @@ -665,7 +665,7 @@ "report.unfollow": "Přestat sledovat @{name}", "report.unfollow_explanation": "Tento účet sledujete. Abyste už neviděli jeho příspěvky ve své domovské časové ose, přestaňte jej sledovat.", "report_notification.attached_statuses": "{count, plural, one {{count} připojený příspěvek} few {{count} připojené příspěvky} many {{count} připojených příspěvků} other {{count} připojených příspěvků}}", - "report_notification.categories.legal": "Zákonné", + "report_notification.categories.legal": "Právní ustanovení", "report_notification.categories.other": "Ostatní", "report_notification.categories.spam": "Spam", "report_notification.categories.violation": "Porušení pravidla", diff --git a/app/javascript/mastodon/locales/ry.json b/app/javascript/mastodon/locales/ry.json index f3a68b15a1..4f2e2410ef 100644 --- a/app/javascript/mastodon/locales/ry.json +++ b/app/javascript/mastodon/locales/ry.json @@ -82,6 +82,7 @@ "alert.unexpected.title": "Ийой!", "announcement.announcement": "Голошіня", "audio.hide": "Зпрятати звук", + "block_modal.remote_users_caveat": "Попросиме ґазду сервера {domain} честовати вашоє рішеня. Айбо не ґарантуєме повный соглас, бо даякі серверы можут брати блокованя по-инчакому. Публичні дописы годно быти видко незалоґованым хосновачам.", "block_modal.show_less": "Указати менше", "block_modal.show_more": "Указати бульше", "block_modal.they_cant_mention": "Они не можут вас споминати авадь слідовати.", @@ -111,5 +112,43 @@ "column.direct": "Шептаня", "column.directory": "Никати профілі", "column.domain_blocks": "Заблоковані домены", - "column.favourites": "Убраноє" + "column.favourites": "Убраноє", + "column.follow_requests": "Запросы на пудписку", + "column.lists": "Исписы", + "column.mutes": "Стишені хосновачі", + "column.notifications": "Убвіщеня", + "column.pins": "Закріплені публикації", + "column_back_button.label": "Назад", + "column_header.hide_settings": "Спрятати штімованя", + "column_header.moveLeft_settings": "Посунути колонку до ліва", + "column_header.moveRight_settings": "Посунути колонку до права", + "column_header.pin": "Закріпити", + "column_header.show_settings": "Указати штімованя", + "column_header.unpin": "Удкріпити", + "column_subheading.settings": "Штімованя", + "compose.language.change": "Поміняти язык", + "compose.language.search": "Глядати языкы...", + "compose.published.body": "Пост опубликованый.", + "compose.saved.body": "Пост усокоченый.", + "compose_form.direct_message_warning_learn_more": "Читайте бульше", + "compose_form.encryption_warning": "Публикації на Mastodon не шіфрувут ся. Не шырьте чутливу інформацію через Mastodon.", + "compose_form.hashtag_warning": "Сись пост не буде ся появляти у исписови по гештеґови, бо вун не є публичный. Лишек публичні посты буде видко за гештеґом.", + "compose_form.lock_disclaimer": "Ваш профіл є {locked}. Хоть-тко може ся на вас пудписати, обы видїти ваші ексклузівні посты.", + "compose_form.lock_disclaimer.lock": "замкнено", + "compose_form.placeholder": "Што нового?", + "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": "Стіл", + "compose_form.publish": "Публикація", + "compose_form.publish_form": "Нова публикація", + "compose_form.reply": "Удповідь", + "copypaste.copy_to_clipboard": "Копіровати у памнять", + "directory.recently_active": "Недавно актівні", + "disabled_account_banner.account_settings": "Штімованя акаунта", + "disabled_account_banner.text": "Ваш акаунт {disabledAccount} раз є неактівный.", + "dismissable_banner.community_timeline": "Туй сут недавні публикації уд профілув на серверови {domain}." } diff --git a/config/locales/cs.yml b/config/locales/cs.yml index 20e7e4d46b..7e0aaaeefb 100644 --- a/config/locales/cs.yml +++ b/config/locales/cs.yml @@ -118,7 +118,7 @@ cs: promote: Povýšit protocol: Protokol public: Veřejný - push_subscription_expires: Odebírání PuSH expiruje + push_subscription_expires: Odebírání PuSH vyprší redownload: Obnovit profil redownloaded_msg: Profil účtu %{username} byl úspěšně obnoven ze zdroje reject: Zamítnout diff --git a/config/locales/doorkeeper.lv.yml b/config/locales/doorkeeper.lv.yml index 5aa5daef3f..11c5020305 100644 --- a/config/locales/doorkeeper.lv.yml +++ b/config/locales/doorkeeper.lv.yml @@ -25,7 +25,7 @@ lv: edit: Labot submit: Apstiprināt confirmations: - destroy: Vai esi pārliecināts? + destroy: Vai tiešām? edit: title: Labot lietotni form: @@ -69,7 +69,7 @@ lv: buttons: revoke: Atsaukt confirmations: - revoke: Vai esi pārliecināts? + revoke: Vai tiešām? index: authorized_at: Autorizētas %{date} description_html: Šīs ir lietotnes, kas var piekļūt Tavam kontam ar API. Ja šeit ir lietotnes, kuras neatpazīsti, vai lietotne darbojas ne tā, kā paredzēts, vari atsaukt tās piekļuvi. @@ -135,6 +135,7 @@ lv: media: Multividesu pielikumi mutes: Apklusinātie notifications: Paziņojumi + profile: Tavs Mastodon profils push: Uznirstošie paziņojumi reports: Ziņojumi search: Meklēt @@ -165,6 +166,7 @@ lv: admin:write:reports: veikt moderācijas darbības pārskatos crypto: lieto pilnīgu šifrēšanu follow: mainīt konta attiecības + profile: lasīt tikai Tava konta profila informāciju push: saņemt savus push paziņojumus read: lasīt visus sava konta datus read:accounts: apskatīt kontu informāciju diff --git a/config/locales/ry.yml b/config/locales/ry.yml index 6fe57b65cd..e384b7f1b7 100644 --- a/config/locales/ry.yml +++ b/config/locales/ry.yml @@ -1 +1,21 @@ +--- ry: + accounts: + follow: Пудписати ся + following: Пудпискы + posts: + few: Публикації + one: Публикація + other: Публикації + posts_tab_heading: Публикації + imports: + titles: + following: Імпортованя пудписок + types: + following: Испис пудписок + notification_mailer: + follow: + body: "%{name} ся пудписує ся на вас!" + subject: "%{name} ся пудписує ся на вас" + relationships: + following: Пудпискы From 182b9248c0e798e4b0fba8339d2817ed2f094b42 Mon Sep 17 00:00:00 2001 From: Renaud Chaput Date: Wed, 10 Jul 2024 14:23:24 +0200 Subject: [PATCH 013/126] Fix SCSS mixed declarations deprecation (#30986) --- app/javascript/styles/mastodon/components.scss | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/app/javascript/styles/mastodon/components.scss b/app/javascript/styles/mastodon/components.scss index c114885d17..da86a4caa7 100644 --- a/app/javascript/styles/mastodon/components.scss +++ b/app/javascript/styles/mastodon/components.scss @@ -1366,6 +1366,8 @@ body > [data-popper-placement] { min-height: 54px; border-bottom: 1px solid var(--background-border-color); cursor: auto; + opacity: 1; + animation: fade 150ms linear; @keyframes fade { 0% { @@ -1377,9 +1379,6 @@ body > [data-popper-placement] { } } - opacity: 1; - animation: fade 150ms linear; - .media-gallery, .video-player, .audio-player, @@ -4851,8 +4850,10 @@ a.status-card { &__menu { @include search-popout; - padding: 0; - background: $ui-secondary-color; + & { + padding: 0; + background: $ui-secondary-color; + } } &__menu-list { From 36592d10aa497db6c9a9764ee539242cc2cfdec7 Mon Sep 17 00:00:00 2001 From: Renaud Chaput Date: Wed, 10 Jul 2024 14:57:25 +0200 Subject: [PATCH 014/126] Change Sidekiq readiness file to use an environment variable (#30988) --- Dockerfile | 4 +++- config/initializers/sidekiq.rb | 19 ++++++++++++------- 2 files changed, 15 insertions(+), 8 deletions(-) diff --git a/Dockerfile b/Dockerfile index 52d3758dc6..758db9bcc9 100644 --- a/Dockerfile +++ b/Dockerfile @@ -67,7 +67,9 @@ ENV \ # Optimize jemalloc 5.x performance MALLOC_CONF="narenas:2,background_thread:true,thp:never,dirty_decay_ms:1000,muzzy_decay_ms:0" \ # Enable libvips, should not be changed - MASTODON_USE_LIBVIPS=true + MASTODON_USE_LIBVIPS=true \ +# Sidekiq will touch tmp/sidekiq_process_has_started_and_will_begin_processing_jobs to indicate it is ready. This can be used for a readiness check in Kubernetes + MASTODON_SIDEKIQ_READY_FILENAME=sidekiq_process_has_started_and_will_begin_processing_jobs # Set default shell used for running commands SHELL ["/bin/bash", "-o", "pipefail", "-o", "errexit", "-c"] diff --git a/config/initializers/sidekiq.rb b/config/initializers/sidekiq.rb index e1d98b8ba3..5b2f317bf2 100644 --- a/config/initializers/sidekiq.rb +++ b/config/initializers/sidekiq.rb @@ -2,19 +2,24 @@ require_relative '../../lib/mastodon/sidekiq_middleware' -SIDEKIQ_WILL_PROCESSES_JOBS_FILE = Rails.root.join('tmp', 'sidekiq_process_has_started_and_will_begin_processing_jobs').freeze - Sidekiq.configure_server do |config| config.redis = REDIS_SIDEKIQ_PARAMS # This is used in Kubernetes setups, to signal that the Sidekiq process has started and will begin processing jobs # This comes from https://github.com/sidekiq/sidekiq/wiki/Kubernetes#sidekiq - config.on(:startup) do - FileUtils.touch(SIDEKIQ_WILL_PROCESSES_JOBS_FILE) - end + ready_filename = ENV.fetch('MASTODON_SIDEKIQ_READY_FILENAME', nil) + if ready_filename + raise 'MASTODON_SIDEKIQ_READY_FILENAME is not a valid filename' if File.basename(ready_filename) != ready_filename - config.on(:shutdown) do - FileUtils.rm_f(SIDEKIQ_WILL_PROCESSES_JOBS_FILE) + ready_path = Rails.root.join('tmp', ready_filename) + + config.on(:startup) do + FileUtils.touch(ready_path) + end + + config.on(:shutdown) do + FileUtils.rm_f(ready_path) + end end config.server_middleware do |chain| From 2ea9336b6855b44126a55106a81e96ea68eaf8ff Mon Sep 17 00:00:00 2001 From: David Roetzel Date: Wed, 10 Jul 2024 16:25:39 +0200 Subject: [PATCH 015/126] Do not pass unknown encoding names to nokogiri. (#30987) --- app/lib/link_details_extractor.rb | 9 ++++++++- .../alternative_utf8_spelling_in_header.txt | 18 ++++++++++++++++++ spec/services/fetch_link_card_service_spec.rb | 9 +++++++++ 3 files changed, 35 insertions(+), 1 deletion(-) create mode 100644 spec/fixtures/requests/alternative_utf8_spelling_in_header.txt diff --git a/app/lib/link_details_extractor.rb b/app/lib/link_details_extractor.rb index 72992d2f42..d81f4a3062 100644 --- a/app/lib/link_details_extractor.rb +++ b/app/lib/link_details_extractor.rb @@ -274,7 +274,7 @@ class LinkDetailsExtractor end def detect_encoding_and_parse_document - [detect_encoding, nil, @html_charset].uniq.each do |encoding| + [detect_encoding, nil, header_encoding].uniq.each do |encoding| document = Nokogiri::HTML(@html, nil, encoding) return document if document.to_s.valid_encoding? end @@ -286,6 +286,13 @@ class LinkDetailsExtractor guess&.fetch(:confidence, 0).to_i > 60 ? guess&.fetch(:encoding, nil) : nil end + def header_encoding + Encoding.find(@html_charset).name if @html_charset + rescue ArgumentError + # Encoding from HTTP header is not recognized by ruby + nil + end + def detector @detector ||= CharlockHolmes::EncodingDetector.new.tap do |detector| detector.strip_tags = true diff --git a/spec/fixtures/requests/alternative_utf8_spelling_in_header.txt b/spec/fixtures/requests/alternative_utf8_spelling_in_header.txt new file mode 100644 index 0000000000..7aaea370e8 --- /dev/null +++ b/spec/fixtures/requests/alternative_utf8_spelling_in_header.txt @@ -0,0 +1,18 @@ +HTTP/1.1 200 OK +server: nginx +date: Thu, 13 Jun 2024 14:33:13 GMT +content-type: text/html; charset=utf8 +content-length: 192 +accept-ranges: bytes + + + + + + Webserver Configs R Us + + +

Welcome

+

Sneaky non-UTF character:

+ + diff --git a/spec/services/fetch_link_card_service_spec.rb b/spec/services/fetch_link_card_service_spec.rb index 342902cdb3..2f64f40558 100644 --- a/spec/services/fetch_link_card_service_spec.rb +++ b/spec/services/fetch_link_card_service_spec.rb @@ -32,6 +32,7 @@ RSpec.describe FetchLinkCardService do stub_request(:get, 'http://example.com/aergerliche-umlaute').to_return(request_fixture('redirect_with_utf8_url.txt')) stub_request(:get, 'http://example.com/page_without_title').to_return(request_fixture('page_without_title.txt')) stub_request(:get, 'http://example.com/long_canonical_url').to_return(request_fixture('long_canonical_url.txt')) + stub_request(:get, 'http://example.com/alternative_utf8_spelling_in_header').to_return(request_fixture('alternative_utf8_spelling_in_header.txt')) Rails.cache.write('oembed_endpoint:example.com', oembed_cache) if oembed_cache @@ -292,6 +293,14 @@ RSpec.describe FetchLinkCardService do expect(status.preview_card).to be_nil end end + + context 'with a URL where the `Content-Type` header uses `utf8` instead of `utf-8`' do + let(:status) { Fabricate(:status, text: 'test http://example.com/alternative_utf8_spelling_in_header') } + + it 'does not create a preview card' do + expect(status.preview_card.title).to eq 'Webserver Configs R Us' + end + end end context 'with a remote status' do From 0d4a8a53d548aa4db43e52085f85126c2bf543d1 Mon Sep 17 00:00:00 2001 From: Renaud Chaput Date: Wed, 10 Jul 2024 14:23:24 +0200 Subject: [PATCH 016/126] [Glitch] Fix SCSS mixed declarations deprecation Port 182b9248c0e798e4b0fba8339d2817ed2f094b42 to glitch-soc --- app/javascript/flavours/glitch/styles/components.scss | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/app/javascript/flavours/glitch/styles/components.scss b/app/javascript/flavours/glitch/styles/components.scss index 0f78aa45dc..533a564e99 100644 --- a/app/javascript/flavours/glitch/styles/components.scss +++ b/app/javascript/flavours/glitch/styles/components.scss @@ -1430,6 +1430,8 @@ body > [data-popper-placement] { min-height: 54px; border-bottom: 1px solid var(--background-border-color); cursor: auto; + opacity: 1; + animation: fade 150ms linear; @keyframes fade { 0% { @@ -1441,9 +1443,6 @@ body > [data-popper-placement] { } } - opacity: 1; - animation: fade 150ms linear; - .media-gallery, .video-player, .audio-player, @@ -5199,8 +5198,10 @@ a.status-card { &__menu { @include search-popout; - padding: 0; - background: $ui-secondary-color; + & { + padding: 0; + background: $ui-secondary-color; + } } &__menu-list { From 959ad1d6be5b84bd55df4e7ad04cc94e824fce5c Mon Sep 17 00:00:00 2001 From: Claire Date: Wed, 10 Jul 2024 17:46:33 +0200 Subject: [PATCH 017/126] Fix deprecation warning in win95 theme --- app/javascript/styles/win95.scss | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/app/javascript/styles/win95.scss b/app/javascript/styles/win95.scss index 66d451303a..2302dc40d5 100644 --- a/app/javascript/styles/win95.scss +++ b/app/javascript/styles/win95.scss @@ -2503,6 +2503,7 @@ body { background: $win95-tooltip-yellow; border: 1px solid black; padding: 4px; + margin-bottom: 24px; h1, h1 small { color:black; @@ -2510,8 +2511,6 @@ body { text-overflow: unset; } - margin-bottom: 24px; - &:after { content: ""; display:block; From d436696f46814eb4c786e48dec6dd05b4bb5c278 Mon Sep 17 00:00:00 2001 From: Emelia Smith Date: Wed, 10 Jul 2024 17:59:18 +0200 Subject: [PATCH 018/126] Streaming: Fix incorrect type definitions (#30977) --- streaming/index.js | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/streaming/index.js b/streaming/index.js index 65a63bb114..2ba8b15407 100644 --- a/streaming/index.js +++ b/streaming/index.js @@ -1107,7 +1107,7 @@ const startServer = async () => { /** * @param {http.IncomingMessage} req - * @param {WebSocket} ws + * @param {import('ws').WebSocket} ws * @param {string[]} streamName * @returns {function(string, string): void} */ @@ -1324,7 +1324,7 @@ const startServer = async () => { /** * @typedef WebSocketSession - * @property {WebSocket & { isAlive: boolean}} websocket + * @property {import('ws').WebSocket & { isAlive: boolean}} websocket * @property {http.IncomingMessage & ResolvedAccount} request * @property {import('pino').Logger} logger * @property {Object.} subscriptions @@ -1450,7 +1450,7 @@ const startServer = async () => { }; /** - * @param {WebSocket & { isAlive: boolean }} ws + * @param {import('ws').WebSocket & { isAlive: boolean }} ws * @param {http.IncomingMessage & ResolvedAccount} req * @param {import('pino').Logger} log */ From 182fee1c454dcd71ecf408ddc2c534bf6ee3a49a Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Wed, 10 Jul 2024 18:18:15 +0200 Subject: [PATCH 019/126] New Crowdin Translations (automated) (#2738) * New Crowdin translations * Fix bogus no.yml * Fix bogus simple_form.no.yml --------- Co-authored-by: GitHub Actions Co-authored-by: Claire --- app/javascript/flavours/glitch/locales/de.json | 3 +-- app/javascript/flavours/glitch/locales/es-AR.json | 3 +-- app/javascript/flavours/glitch/locales/ko.json | 5 +++++ app/javascript/flavours/glitch/locales/zh-CN.json | 3 +-- app/javascript/flavours/glitch/locales/zh-TW.json | 3 +-- config/locales-glitch/simple_form.ko.yml | 2 ++ 6 files changed, 11 insertions(+), 8 deletions(-) diff --git a/app/javascript/flavours/glitch/locales/de.json b/app/javascript/flavours/glitch/locales/de.json index caad1ebcfe..6a20c8c396 100644 --- a/app/javascript/flavours/glitch/locales/de.json +++ b/app/javascript/flavours/glitch/locales/de.json @@ -154,6 +154,5 @@ "status.in_reply_to": "Dieser Toot ist eine Antwort", "status.is_poll": "Dieser Toot ist eine Umfrage", "status.local_only": "Nur auf deiner Instanz sichtbar", - "status.uncollapse": "Ausklappen", - "suggestions.dismiss": "Vorschlag ablehnen" + "status.uncollapse": "Ausklappen" } diff --git a/app/javascript/flavours/glitch/locales/es-AR.json b/app/javascript/flavours/glitch/locales/es-AR.json index 95dc7c85a6..706109d6e8 100644 --- a/app/javascript/flavours/glitch/locales/es-AR.json +++ b/app/javascript/flavours/glitch/locales/es-AR.json @@ -155,6 +155,5 @@ "status.in_reply_to": "Esta publicación es una respuesta", "status.is_poll": "Esta publicación es una encuesta", "status.local_only": "Sólo visible para tu instancia", - "status.uncollapse": "Descolapsar", - "suggestions.dismiss": "Descartar sugerencia" + "status.uncollapse": "Descolapsar" } diff --git a/app/javascript/flavours/glitch/locales/ko.json b/app/javascript/flavours/glitch/locales/ko.json index b1da79d102..18e61dc034 100644 --- a/app/javascript/flavours/glitch/locales/ko.json +++ b/app/javascript/flavours/glitch/locales/ko.json @@ -25,6 +25,9 @@ "compose.content-type.plain_meta": "고급 양식 없이 작성", "compose.disable_threaded_mode": "글타래 모드 비활성화", "compose.enable_threaded_mode": "글타래 모드 활성화", + "compose_form.sensitive.hide": "{count, plural, other {미디어를 민감함으로 표시}}", + "compose_form.sensitive.marked": "{count, plural, other {미디어가 민감함으로 표시되었습니다}}", + "compose_form.sensitive.unmarked": "{count, plural, other {미디어가 민감함으로 표시되지 않았습니다}}", "confirmation_modal.do_not_ask_again": "다음부터 확인창을 띄우지 않기", "confirmations.deprecated_settings.confirm": "마스토돈 설정 사용", "confirmations.deprecated_settings.message": "사용하던 몇몇 기기별 글리치 {app_settings}은 마스토돈 {preferences}으로 대체되었습니다:", @@ -61,6 +64,7 @@ "notification_purge.btn_invert": "선택반전", "notification_purge.btn_none": "전체선택해제", "notification_purge.start": "알림 삭제모드로 들어가기", + "notifications.column_settings.filter_bar.show_bar": "필터 막대 표시", "notifications.marked_clear": "선택된 알림 모두 삭제", "notifications.marked_clear_confirmation": "정말로 선택된 알림들을 영구적으로 삭제할까요?", "settings.always_show_spoilers_field": "열람주의 항목을 언제나 활성화", @@ -124,6 +128,7 @@ "settings.shared_settings_link": "사용자 설정", "settings.show_action_bar": "접힌 글에 액션 버튼들 보이기", "settings.show_content_type_choice": "글을 작성할 때 콘텐트 타입을 고를 수 있도록 합니다", + "settings.show_published_toast": "게시물을 게시/저장할 때 토스트 표시", "settings.show_reply_counter": "대략적인 답글 개수를 표시합니다", "settings.side_arm": "보조 작성 버튼:", "settings.side_arm.none": "없음", diff --git a/app/javascript/flavours/glitch/locales/zh-CN.json b/app/javascript/flavours/glitch/locales/zh-CN.json index 26f142807a..e9999136fb 100644 --- a/app/javascript/flavours/glitch/locales/zh-CN.json +++ b/app/javascript/flavours/glitch/locales/zh-CN.json @@ -155,6 +155,5 @@ "status.in_reply_to": "此嘟文是回复", "status.is_poll": "此嘟文是投票", "status.local_only": "此嘟文仅本站可见", - "status.uncollapse": "展开", - "suggestions.dismiss": "关闭建议" + "status.uncollapse": "展开" } diff --git a/app/javascript/flavours/glitch/locales/zh-TW.json b/app/javascript/flavours/glitch/locales/zh-TW.json index 2fcb217434..aaf0065150 100644 --- a/app/javascript/flavours/glitch/locales/zh-TW.json +++ b/app/javascript/flavours/glitch/locales/zh-TW.json @@ -151,6 +151,5 @@ "status.in_reply_to": "貼文有回覆", "status.is_poll": "貼文有投票", "status.local_only": "只在此實例可見", - "status.uncollapse": "展開", - "suggestions.dismiss": "關閉建議" + "status.uncollapse": "展開" } diff --git a/config/locales-glitch/simple_form.ko.yml b/config/locales-glitch/simple_form.ko.yml index f9420f1336..96e1320141 100644 --- a/config/locales-glitch/simple_form.ko.yml +++ b/config/locales-glitch/simple_form.ko.yml @@ -8,6 +8,7 @@ ko: setting_default_content_type_markdown: 게시물을 작성할 때, 형식을 지정하지 않았다면, 마크다운이라고 가정합니다 setting_default_content_type_plain: 게시물을 작성할 때, 형식을 지정하지 않았다면, 일반적인 텍스트라고 가정합니다. (마스토돈의 기본 동작) setting_default_language: 작성하는 게시물의 언어는 자동으로 설정될 수 있습니다, 하지만 언제나 정확하지는 않습니다 + setting_show_followers_count: 팔로워 카운트를 프로필에서 숨깁니다. 팔로워 수를 숨기면 나에게도 보이지 않으며 몇몇 앱에서는 팔로워 수가 음수로 표시될 수 있습니다. setting_skin: 선택한 마스토돈 풍미의 스킨을 바꿉니다 labels: defaults: @@ -16,6 +17,7 @@ ko: setting_default_content_type_markdown: 마크다운 setting_default_content_type_plain: 일반 텍스트 setting_favourite_modal: 관심글을 지정할 때 확인 창을 띄웁니다(글리치 풍미에만 적용됨) + setting_show_followers_count: 팔로워 수 표시 setting_skin: 스킨 setting_system_emoji_font: 에모지에 시스템 기본 폰트 적용하기 (글리치 풍미에만 적용됨) notification_emails: From 631a5eec85946848bf0b15562f82260c1f7721d8 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Wed, 10 Jul 2024 21:59:34 +0200 Subject: [PATCH 020/126] chore(deps): update dependency charlock_holmes to v0.7.9 (#30992) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- Gemfile.lock | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Gemfile.lock b/Gemfile.lock index 1c253719e4..18c2d34808 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -159,7 +159,7 @@ GEM case_transform (0.2) activesupport cbor (0.5.9.8) - charlock_holmes (0.7.8) + charlock_holmes (0.7.9) chewy (7.6.0) activesupport (>= 5.2) elasticsearch (>= 7.14.0, < 8) From 24bdba34132b0a6e193e7246304601a8ad453425 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Thu, 11 Jul 2024 12:30:55 +0200 Subject: [PATCH 021/126] chore(deps): update dependency rubocop to v1.65.0 (#30985) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- Gemfile.lock | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/Gemfile.lock b/Gemfile.lock index 18c2d34808..2d085152e8 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -583,7 +583,7 @@ GEM orm_adapter (0.5.0) ox (2.14.18) parallel (1.25.1) - parser (3.3.3.0) + parser (3.3.4.0) ast (~> 2.4.1) racc parslet (2.0.0) @@ -733,13 +733,13 @@ GEM rspec-mocks (~> 3.0) sidekiq (>= 5, < 8) rspec-support (3.13.1) - rubocop (1.64.1) + rubocop (1.65.0) json (~> 2.3) language_server-protocol (>= 3.17.0) parallel (~> 1.10) parser (>= 3.3.0.2) rainbow (>= 2.2.2, < 4.0) - regexp_parser (>= 1.8, < 3.0) + regexp_parser (>= 2.4, < 3.0) rexml (>= 3.2.5, < 4.0) rubocop-ast (>= 1.31.1, < 2.0) ruby-progressbar (~> 1.7) From c244b70dc21f1a41f16588820490082a1e99b7ae Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Thu, 11 Jul 2024 10:38:35 +0000 Subject: [PATCH 022/126] New Crowdin Translations (automated) (#30993) Co-authored-by: GitHub Actions --- app/javascript/mastodon/locales/ar.json | 24 ++++++++++++------------ app/javascript/mastodon/locales/kab.json | 6 ++++++ config/locales/ar.yml | 5 +++++ 3 files changed, 23 insertions(+), 12 deletions(-) diff --git a/app/javascript/mastodon/locales/ar.json b/app/javascript/mastodon/locales/ar.json index a9e1bdb270..115f6335b6 100644 --- a/app/javascript/mastodon/locales/ar.json +++ b/app/javascript/mastodon/locales/ar.json @@ -4,7 +4,7 @@ "about.disclaimer": "ماستدون برنامج حر ومفتوح المصدر وعلامة تجارية لـ Mastodon GmbH.", "about.domain_blocks.no_reason_available": "السبب غير متوفر", "about.domain_blocks.preamble": "يسمح لك ماستدون عموماً بعرض المحتوى من المستخدمين من أي خادم آخر في الفدرالية والتفاعل معهم. وهذه هي الاستثناءات التي وضعت على هذا الخادم بالذات.", - "about.domain_blocks.silenced.explanation": "عموماً، لن ترى ملفات التعريف والمحتوى من هذا الخادم، إلا إذا كنت تبحث عنه بشكل صريح أو تختار أن تتابعه.", + "about.domain_blocks.silenced.explanation": "لن تظهر لك ملفات التعريف الشخصية والمحتوى من هذا الخادوم، إلا إن بحثت عنه عمدًا أو تابعته.", "about.domain_blocks.silenced.title": "محدود", "about.domain_blocks.suspended.explanation": "لن يتم معالجة أي بيانات من هذا الخادم أو تخزينها أو تبادلها، مما يجعل أي تفاعل أو اتصال مع المستخدمين من هذا الخادم مستحيلا.", "about.domain_blocks.suspended.title": "مُعلّق", @@ -21,7 +21,7 @@ "account.blocked": "محظور", "account.browse_more_on_origin_server": "تصفح المزيد في الملف الشخصي الأصلي", "account.cancel_follow_request": "إلغاء طلب المتابعة", - "account.copy": "نسخ الرابط إلى الحساب", + "account.copy": "نسخ الرابط إلى الملف الشخصي", "account.direct": "إشارة خاصة لـ @{name}", "account.disable_notifications": "توقف عن إشعاري عندما ينشر @{name}", "account.domain_blocked": "اسم النِّطاق محظور", @@ -32,7 +32,7 @@ "account.featured_tags.last_status_never": "لا توجد رسائل", "account.featured_tags.title": "وسوم {name} المميَّزة", "account.follow": "متابعة", - "account.follow_back": "رد المتابعة", + "account.follow_back": "تابعهم بالمثل", "account.followers": "مُتابِعون", "account.followers.empty": "لا أحدَ يُتابع هذا المُستخدم إلى حد الآن.", "account.following": "الاشتراكات", @@ -51,7 +51,7 @@ "account.mute_notifications_short": "كتم الإشعارات", "account.mute_short": "اكتم", "account.muted": "مَكتوم", - "account.mutual": "متبادل", + "account.mutual": "متبادلة", "account.no_bio": "لم يتم تقديم وصف.", "account.open_original_page": "افتح الصفحة الأصلية", "account.posts": "منشورات", @@ -70,8 +70,8 @@ "account.unmute_notifications_short": "إلغاء كَتم الإشعارات", "account.unmute_short": "إلغاء الكتم", "account_note.placeholder": "اضغط لإضافة مُلاحظة", - "admin.dashboard.daily_retention": "معدل الاحتفاظ بالمستخدم بعد التسجيل بيوم", - "admin.dashboard.monthly_retention": "معدل الاحتفاظ بالمستخدم بعد التسجيل بالشهور", + "admin.dashboard.daily_retention": "معدّل بقاء المستخدمين بعد إنشاء الحسابات، بالأيام", + "admin.dashboard.monthly_retention": "معدّل بقاء المستخدمين بعد إنشاء الحسابات، بالشهور", "admin.dashboard.retention.average": "المعدل", "admin.dashboard.retention.cohort": "شهر التسجيل", "admin.dashboard.retention.cohort_size": "المستخدمون الجدد", @@ -87,12 +87,12 @@ "attachments_list.unprocessed": "(غير معالَج)", "audio.hide": "إخفاء المقطع الصوتي", "block_modal.remote_users_caveat": "سوف نطلب من الخادم {domain} أن يحترم قرارك، لكن الالتزام غير مضمون لأن بعض الخواديم قد تتعامل مع نصوص الكتل بشكل مختلف. قد تظل المنشورات العامة مرئية للمستخدمين غير المسجلين الدخول.", - "block_modal.show_less": "أظهر الأقل", - "block_modal.show_more": "أظهر المزيد", + "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.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": "انسخ تقرير الخطأ", @@ -156,7 +156,7 @@ "compose_form.poll.single": "اختر واحدا", "compose_form.poll.switch_to_multiple": "تغيِير الاستطلاع للسماح باِخيارات مُتعدِّدة", "compose_form.poll.switch_to_single": "تغيِير الاستطلاع للسماح باِخيار واحد فقط", - "compose_form.poll.type": "الأسلوب", + "compose_form.poll.type": "الطراز", "compose_form.publish": "نشر", "compose_form.publish_form": "منشور جديد", "compose_form.reply": "ردّ", diff --git a/app/javascript/mastodon/locales/kab.json b/app/javascript/mastodon/locales/kab.json index fcaa8f143e..868edbc8c0 100644 --- a/app/javascript/mastodon/locales/kab.json +++ b/app/javascript/mastodon/locales/kab.json @@ -28,9 +28,12 @@ "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.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}}", "account.following": "Yeṭṭafaṛ", + "account.following_counter": "{count, plural, one {{counter} yettwaḍfaren} other {{counter} yettwaḍfaren}}", "account.follows.empty": "Ar tura, amseqdac-agi ur yeṭṭafaṛ yiwen.", "account.go_to_profile": "Ddu ɣer umaɣnu", "account.hide_reblogs": "Ffer ayen i ibeṭṭu @{name}", @@ -53,6 +56,7 @@ "account.requested_follow": "{name} yessuter ad k·m-yeḍfer", "account.share": "Bḍu amaɣnu n @{name}", "account.show_reblogs": "Ssken-d inebḍa n @{name}", + "account.statuses_counter": "{count, plural, one {{counter} n tsuffeɣt} other {{counter} n tsuffaɣ}}", "account.unblock": "Serreḥ i @{name}", "account.unblock_domain": "Ssken-d {domain}", "account.unblock_short": "Serreḥ", @@ -560,6 +564,7 @@ "status.edited_x_times": "Tettwaẓreg {count, plural, one {{count} n tikkelt} other {{count} n tikkal}}", "status.embed": "Seddu", "status.favourite": "Amenyaf", + "status.favourites": "{count, plural, one {n usmenyaf} other {n ismenyafen}}", "status.filter": "Sizdeg tassufeɣt-a", "status.filtered": "Yettwasizdeg", "status.hide": "Ffer tasuffeɣt", @@ -579,6 +584,7 @@ "status.read_more": "Issin ugar", "status.reblog": "Bḍu", "status.reblogged_by": "Yebḍa-tt {name}", + "status.reblogs": "{count, plural, one {n usnerni} other {n yisnernuyen}}", "status.reblogs.empty": "Ula yiwen ur yebḍi tajewwiqt-agi ar tura. Ticki yebḍa-tt yiwen, ad d-iban da.", "status.redraft": "Kkes tɛiwdeḍ tira", "status.remove_bookmark": "Kkes tacreḍt", diff --git a/config/locales/ar.yml b/config/locales/ar.yml index 2ca7538c32..4df24c984c 100644 --- a/config/locales/ar.yml +++ b/config/locales/ar.yml @@ -1762,6 +1762,10 @@ ar: webauthn_authentication: مفاتيح الأمان severed_relationships: download: تنزيل (%{count}) + lost_followers: المتابعون المفقودون + lost_follows: المتابعات المفقودة + preamble: بحجبكم اسم نطاق قد تخسرون متابَعاتٍ، و كذلك إذا قرّر مديرو الخادوم حظر خادوم ما. و في هذه الحالات يكون بوسعكم تنزيل قائمة بالصلات المبتورة لمعاينتها، مع القدرة على استيرادها إلى خادوم آخر. + purged: حذف مدير خادومكم المعلومات عن هذا الخادوم. statuses: attached: audio: @@ -1978,6 +1982,7 @@ ar: edit_profile_title: قم بتخصيص ملفك التعريفي explanation: ها هي بعض النصائح قبل بداية الاستخدام feature_action: اعرف المزيد + feature_audience: يتيح لكم مًستُدون إدارة جمهوركم بلا وسطاء. فبتنصيب و تشغيل مَستُودون على بنيتكم التحتية تمكنكم متابعة مستخدمي مَستُدون من أيّ خادوم،كما يمكنهم متابعتكم، بلا تحكُّم من أي طرف ثالث. feature_audience_title: اِبنوا جُمهورَكم بِثِقَة feature_control: أنتم الأدرى بالمحتوى الذي تريدون أن تطالعوه في فيض المنشورات الرئيس. لا خوارزميات تتحكم فيما يظهر لكم ولا إعلانات تضيع وقتكم. بحساب واحد تمكنكم متابعة من تشاؤون على أيّ خادوم ماستدون، وتلقّى منشوراتهم بترتيبها الزمني، لتصنعوا ركنكم الأليف في الإنترنت. feature_control_title: تحكَّموا في فيض المنشورات الخاص بكم From 6c375297236ecd1df7a5e82c24ad025b46be46cc Mon Sep 17 00:00:00 2001 From: Matt Jankowski Date: Thu, 11 Jul 2024 07:13:55 -0400 Subject: [PATCH 023/126] Use `module: :auth` to wrap `devise_for` routes config (#30990) --- config/routes.rb | 10 +++------- 1 file changed, 3 insertions(+), 7 deletions(-) diff --git a/config/routes.rb b/config/routes.rb index 2c06762c22..e4f091043d 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -104,13 +104,9 @@ Rails.application.routes.draw do end end - devise_for :users, path: 'auth', format: false, controllers: { - omniauth_callbacks: 'auth/omniauth_callbacks', - sessions: 'auth/sessions', - registrations: 'auth/registrations', - passwords: 'auth/passwords', - confirmations: 'auth/confirmations', - } + scope module: :auth do + devise_for :users, path: 'auth', format: false + end with_options constraints: ->(req) { req.format.nil? || req.format.html? } do get '/users/:username', to: redirect_with_vary('/@%{username}') From 8c8bee5a36e0cd0b5d35903f8891896447c3e060 Mon Sep 17 00:00:00 2001 From: Renaud Chaput Date: Thu, 11 Jul 2024 15:43:42 +0200 Subject: [PATCH 024/126] Change disabled buttons color in light mode to make it more visible (#30998) --- app/javascript/styles/mastodon-light/diff.scss | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/app/javascript/styles/mastodon-light/diff.scss b/app/javascript/styles/mastodon-light/diff.scss index 07e9d9868b..a41272364a 100644 --- a/app/javascript/styles/mastodon-light/diff.scss +++ b/app/javascript/styles/mastodon-light/diff.scss @@ -48,6 +48,10 @@ html { } } +.icon-button:disabled { + color: darken($action-button-color, 25%); +} + .account__header__bar .avatar .account__avatar { border-color: $white; } From e26052192d2bc11ef8adb7bb5f9d4d0fcbfc94f4 Mon Sep 17 00:00:00 2001 From: Renaud Chaput Date: Thu, 11 Jul 2024 15:43:42 +0200 Subject: [PATCH 025/126] [Glitch] Change disabled buttons color in light mode to make it more visible Port 8c8bee5a36e0cd0b5d35903f8891896447c3e060 to glitch-soc Signed-off-by: Claire --- .../flavours/glitch/styles/mastodon-light/diff.scss | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/app/javascript/flavours/glitch/styles/mastodon-light/diff.scss b/app/javascript/flavours/glitch/styles/mastodon-light/diff.scss index 4040ee0fe0..1f5059c321 100644 --- a/app/javascript/flavours/glitch/styles/mastodon-light/diff.scss +++ b/app/javascript/flavours/glitch/styles/mastodon-light/diff.scss @@ -48,6 +48,10 @@ html { } } +.icon-button:disabled { + color: darken($action-button-color, 25%); +} + .account__header__bar .avatar .account__avatar { border-color: $white; } From ad52b04a1c88574ae3be2c56bead1b0638b253fc Mon Sep 17 00:00:00 2001 From: Claire Date: Thu, 11 Jul 2024 21:42:58 +0200 Subject: [PATCH 026/126] Add setting to disable hover cards (#30931) Co-authored-by: Eugen Rochko --- app/javascript/mastodon/components/status.jsx | 2 +- app/javascript/mastodon/components/status_content.jsx | 2 +- .../features/notifications/components/notification.jsx | 4 ++-- app/javascript/mastodon/features/ui/index.jsx | 4 ++-- app/javascript/mastodon/initial_state.js | 2 ++ app/models/concerns/user/has_settings.rb | 4 ++++ app/models/user_settings.rb | 1 + app/serializers/initial_state_serializer.rb | 1 + app/views/settings/preferences/appearance/show.html.haml | 1 + config/locales/simple_form.en.yml | 1 + 10 files changed, 16 insertions(+), 6 deletions(-) diff --git a/app/javascript/mastodon/components/status.jsx b/app/javascript/mastodon/components/status.jsx index dce48d7036..502dc8bee3 100644 --- a/app/javascript/mastodon/components/status.jsx +++ b/app/javascript/mastodon/components/status.jsx @@ -562,7 +562,7 @@ class Status extends ImmutablePureComponent { {status.get('edited_at') && *} - +
{statusAvatar}
diff --git a/app/javascript/mastodon/components/status_content.jsx b/app/javascript/mastodon/components/status_content.jsx index 82135b85ca..96452374dc 100644 --- a/app/javascript/mastodon/components/status_content.jsx +++ b/app/javascript/mastodon/components/status_content.jsx @@ -116,7 +116,7 @@ class StatusContent extends PureComponent { if (mention) { link.addEventListener('click', this.onMentionClick.bind(this, mention), false); - link.removeAttribute('title'); + link.setAttribute('title', `@${mention.get('acct')}`); link.setAttribute('href', `/@${mention.get('acct')}`); link.setAttribute('data-hover-card-account', mention.get('id')); } else if (link.textContent[0] === '#' || (link.previousSibling && link.previousSibling.textContent && link.previousSibling.textContent[link.previousSibling.textContent.length - 1] === '#')) { diff --git a/app/javascript/mastodon/features/notifications/components/notification.jsx b/app/javascript/mastodon/features/notifications/components/notification.jsx index 272893042d..986628fdc8 100644 --- a/app/javascript/mastodon/features/notifications/components/notification.jsx +++ b/app/javascript/mastodon/features/notifications/components/notification.jsx @@ -435,7 +435,7 @@ class Notification extends ImmutablePureComponent { const targetAccount = report.get('target_account'); const targetDisplayNameHtml = { __html: targetAccount.get('display_name_html') }; - const targetLink = ; + const targetLink = ; return ( @@ -458,7 +458,7 @@ class Notification extends ImmutablePureComponent { const { notification } = this.props; const account = notification.get('account'); const displayNameHtml = { __html: account.get('display_name_html') }; - const link = ; + const link = ; switch(notification.get('type')) { case 'follow': diff --git a/app/javascript/mastodon/features/ui/index.jsx b/app/javascript/mastodon/features/ui/index.jsx index d41132f9ca..d9f609620c 100644 --- a/app/javascript/mastodon/features/ui/index.jsx +++ b/app/javascript/mastodon/features/ui/index.jsx @@ -25,7 +25,7 @@ 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 } from '../../initial_state'; +import initialState, { me, owner, singleUserMode, trendsEnabled, trendsAsLanding, disableHoverCards } from '../../initial_state'; import BundleColumnError from './components/bundle_column_error'; import Header from './components/header'; @@ -588,7 +588,7 @@ class UI extends PureComponent { {layout !== 'mobile' && } - + {!disableHoverCards && } diff --git a/app/javascript/mastodon/initial_state.js b/app/javascript/mastodon/initial_state.js index 9ec3df0df8..60b35cb31a 100644 --- a/app/javascript/mastodon/initial_state.js +++ b/app/javascript/mastodon/initial_state.js @@ -15,6 +15,7 @@ * @property {boolean=} boost_modal * @property {boolean=} delete_modal * @property {boolean=} disable_swiping + * @property {boolean=} disable_hover_cards * @property {string=} disabled_account_id * @property {string} display_media * @property {string} domain @@ -86,6 +87,7 @@ export const autoPlayGif = getMeta('auto_play_gif'); export const boostModal = getMeta('boost_modal'); export const deleteModal = getMeta('delete_modal'); export const disableSwiping = getMeta('disable_swiping'); +export const disableHoverCards = getMeta('disable_hover_cards'); export const disabledAccountId = getMeta('disabled_account_id'); export const displayMedia = getMeta('display_media'); export const domain = getMeta('domain'); diff --git a/app/models/concerns/user/has_settings.rb b/app/models/concerns/user/has_settings.rb index 65373325f0..1202f2033f 100644 --- a/app/models/concerns/user/has_settings.rb +++ b/app/models/concerns/user/has_settings.rb @@ -91,6 +91,10 @@ module User::HasSettings settings['web.disable_swiping'] end + def setting_disable_hover_cards + settings['web.disable_hover_cards'] + end + def setting_always_send_emails settings['always_send_emails'] end diff --git a/app/models/user_settings.rb b/app/models/user_settings.rb index 6571632fcd..0ae8ab8ec7 100644 --- a/app/models/user_settings.rb +++ b/app/models/user_settings.rb @@ -25,6 +25,7 @@ class UserSettings setting :use_pending_items, default: false setting :use_system_font, default: false setting :disable_swiping, default: false + setting :disable_hover_cards, default: false setting :delete_modal, default: true setting :reblog_modal, default: false setting :reduce_motion, default: false diff --git a/app/serializers/initial_state_serializer.rb b/app/serializers/initial_state_serializer.rb index 72aaabcfcb..13f332c95c 100644 --- a/app/serializers/initial_state_serializer.rb +++ b/app/serializers/initial_state_serializer.rb @@ -24,6 +24,7 @@ class InitialStateSerializer < ActiveModel::Serializer store[:expand_spoilers] = object_account_user.setting_expand_spoilers store[:reduce_motion] = object_account_user.setting_reduce_motion store[:disable_swiping] = object_account_user.setting_disable_swiping + store[:disable_hover_cards] = object_account_user.setting_disable_hover_cards store[:advanced_layout] = object_account_user.setting_advanced_layout store[:use_blurhash] = object_account_user.setting_use_blurhash store[:use_pending_items] = object_account_user.setting_use_pending_items diff --git a/app/views/settings/preferences/appearance/show.html.haml b/app/views/settings/preferences/appearance/show.html.haml index e89e015b29..f34ce4a6aa 100644 --- a/app/views/settings/preferences/appearance/show.html.haml +++ b/app/views/settings/preferences/appearance/show.html.haml @@ -56,6 +56,7 @@ = ff.input :'web.auto_play', wrapper: :with_label, recommended: true, label: I18n.t('simple_form.labels.defaults.setting_auto_play_gif') = ff.input :'web.reduce_motion', wrapper: :with_label, label: I18n.t('simple_form.labels.defaults.setting_reduce_motion') = ff.input :'web.disable_swiping', wrapper: :with_label, label: I18n.t('simple_form.labels.defaults.setting_disable_swiping') + = ff.input :'web.disable_hover_cards', wrapper: :with_label, label: I18n.t('simple_form.labels.defaults.setting_disable_hover_cards') = ff.input :'web.use_system_font', wrapper: :with_label, label: I18n.t('simple_form.labels.defaults.setting_system_font_ui') %h4= t 'appearance.discovery' diff --git a/config/locales/simple_form.en.yml b/config/locales/simple_form.en.yml index fdc9f61813..0313d4683e 100644 --- a/config/locales/simple_form.en.yml +++ b/config/locales/simple_form.en.yml @@ -211,6 +211,7 @@ en: setting_default_privacy: Posting privacy setting_default_sensitive: Always mark media as sensitive setting_delete_modal: Show confirmation dialog 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 From bb702e6b2037b5b0f2e76b6f9d390fa0fd7abc54 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Fri, 12 Jul 2024 10:18:35 +0200 Subject: [PATCH 027/126] fix(deps): update dependency sass to v1.77.8 (#31005) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- yarn.lock | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/yarn.lock b/yarn.lock index cf7e5a8b95..403a8310d0 100644 --- a/yarn.lock +++ b/yarn.lock @@ -15462,15 +15462,15 @@ __metadata: linkType: hard "sass@npm:^1.62.1": - version: 1.77.7 - resolution: "sass@npm:1.77.7" + version: 1.77.8 + resolution: "sass@npm:1.77.8" dependencies: chokidar: "npm:>=3.0.0 <4.0.0" immutable: "npm:^4.0.0" source-map-js: "npm:>=0.6.2 <2.0.0" bin: sass: sass.js - checksum: 10c0/6cacbf4b5165d30a9be0f09438aed85ff0617e5087442e65c23c8464750ff1b9988855a58f36b420b62f992d1e82403f99810aba7731519d3d026847e21a5635 + checksum: 10c0/2bfd62794070352c804f949e69bd8bb5b4ec846deeb924251b2c3f7b503170fb1ae186f513f0166907749eb34e0277dee747edcb78c886fb471aac01be1e864c languageName: node linkType: hard From 73d53827ea3ef1605f97f99bf3cbeeccb30638be Mon Sep 17 00:00:00 2001 From: Matt Jankowski Date: Fri, 12 Jul 2024 04:19:15 -0400 Subject: [PATCH 028/126] Add change assertion to invites destroy spec (#31004) --- spec/controllers/invites_controller_spec.rb | 19 ++++++++----------- 1 file changed, 8 insertions(+), 11 deletions(-) diff --git a/spec/controllers/invites_controller_spec.rb b/spec/controllers/invites_controller_spec.rb index 3190c82884..5221941267 100644 --- a/spec/controllers/invites_controller_spec.rb +++ b/spec/controllers/invites_controller_spec.rb @@ -69,19 +69,16 @@ describe InvitesController do end end - describe 'DELETE #create' do + describe 'DELETE #destroy' do + subject { delete :destroy, params: { id: invite.id } } + let(:invite) { Fabricate(:invite, user: user, expires_at: nil) } - before do - delete :destroy, params: { id: invite.id } - end - - it 'redirects' do - expect(response).to redirect_to invites_path - end - - it 'expires invite' do - expect(invite.reload).to be_expired + it 'expires invite and redirects' do + expect { subject } + .to(change { invite.reload.expired? }.to(true)) + expect(response) + .to redirect_to invites_path end end end From cd1bc94cd2232b2583c6d3d1924fd0ae00f542bc Mon Sep 17 00:00:00 2001 From: Nick Schonning Date: Fri, 12 Jul 2024 04:22:31 -0400 Subject: [PATCH 029/126] Regen RuboCop TODO for 1.65.0 (#31003) --- .rubocop_todo.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.rubocop_todo.yml b/.rubocop_todo.yml index b05d1bc6bd..357ed99545 100644 --- a/.rubocop_todo.yml +++ b/.rubocop_todo.yml @@ -1,6 +1,6 @@ # This configuration was generated by # `rubocop --auto-gen-config --auto-gen-only-exclude --no-offense-counts --no-auto-gen-timestamp` -# using RuboCop version 1.64.1. +# using RuboCop version 1.65.0. # The point is for the user to remove these configuration records # one by one as the offenses are removed from the code base. # Note that changes in the inspected code, or installation of new @@ -14,7 +14,7 @@ Lint/NonLocalExitFromIterator: Metrics/AbcSize: Max: 82 -# Configuration parameters: CountBlocks, Max. +# Configuration parameters: CountBlocks, CountModifierForms, Max. Metrics/BlockNesting: Exclude: - 'lib/tasks/mastodon.rake' From fdad4dc918d0eb8538d79173e86c82fd6d0290a6 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Fri, 12 Jul 2024 10:23:04 +0200 Subject: [PATCH 030/126] fix(deps): update babel monorepo to v7.24.8 (#31002) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- yarn.lock | 222 +++++++++++++++++++++++++++--------------------------- 1 file changed, 111 insertions(+), 111 deletions(-) diff --git a/yarn.lock b/yarn.lock index 403a8310d0..988c6c79cf 100644 --- a/yarn.lock +++ b/yarn.lock @@ -52,45 +52,45 @@ __metadata: languageName: node linkType: hard -"@babel/compat-data@npm:^7.22.6, @babel/compat-data@npm:^7.24.7": - version: 7.24.7 - resolution: "@babel/compat-data@npm:7.24.7" - checksum: 10c0/dcd93a5632b04536498fbe2be5af1057f635fd7f7090483d8e797878559037e5130b26862ceb359acbae93ed27e076d395ddb4663db6b28a665756ffd02d324f +"@babel/compat-data@npm:^7.22.6, @babel/compat-data@npm:^7.24.8": + version: 7.24.8 + resolution: "@babel/compat-data@npm:7.24.8" + checksum: 10c0/7f465e9d8e44c5b516eeb3001362a3cd9a6df51dd90d3ac9868e1e7fa631ac57fc781cec6700110d4f555ba37fe59c4a71927b445106fe0062e79e79ffe11091 languageName: node linkType: hard "@babel/core@npm:^7.10.4, @babel/core@npm:^7.11.6, @babel/core@npm:^7.12.3, @babel/core@npm:^7.22.1, @babel/core@npm:^7.24.4": - version: 7.24.7 - resolution: "@babel/core@npm:7.24.7" + version: 7.24.8 + resolution: "@babel/core@npm:7.24.8" dependencies: "@ampproject/remapping": "npm:^2.2.0" "@babel/code-frame": "npm:^7.24.7" - "@babel/generator": "npm:^7.24.7" - "@babel/helper-compilation-targets": "npm:^7.24.7" - "@babel/helper-module-transforms": "npm:^7.24.7" - "@babel/helpers": "npm:^7.24.7" - "@babel/parser": "npm:^7.24.7" + "@babel/generator": "npm:^7.24.8" + "@babel/helper-compilation-targets": "npm:^7.24.8" + "@babel/helper-module-transforms": "npm:^7.24.8" + "@babel/helpers": "npm:^7.24.8" + "@babel/parser": "npm:^7.24.8" "@babel/template": "npm:^7.24.7" - "@babel/traverse": "npm:^7.24.7" - "@babel/types": "npm:^7.24.7" + "@babel/traverse": "npm:^7.24.8" + "@babel/types": "npm:^7.24.8" convert-source-map: "npm:^2.0.0" debug: "npm:^4.1.0" gensync: "npm:^1.0.0-beta.2" json5: "npm:^2.2.3" semver: "npm:^6.3.1" - checksum: 10c0/4004ba454d3c20a46ea66264e06c15b82e9f6bdc35f88819907d24620da70dbf896abac1cb4cc4b6bb8642969e45f4d808497c9054a1388a386cf8c12e9b9e0d + checksum: 10c0/5e21b40cc69746deda3fe3d6540351d9cb0d1ad5aea055b7c319db26071ff5789fd9580d1aa47b114f07631e8e2109f4e71696ca11d7c7e60d157767022c1bd2 languageName: node linkType: hard -"@babel/generator@npm:^7.24.7, @babel/generator@npm:^7.7.2": - version: 7.24.7 - resolution: "@babel/generator@npm:7.24.7" +"@babel/generator@npm:^7.24.8, @babel/generator@npm:^7.7.2": + version: 7.24.8 + resolution: "@babel/generator@npm:7.24.8" dependencies: - "@babel/types": "npm:^7.24.7" + "@babel/types": "npm:^7.24.8" "@jridgewell/gen-mapping": "npm:^0.3.5" "@jridgewell/trace-mapping": "npm:^0.3.25" jsesc: "npm:^2.5.1" - checksum: 10c0/06b1f3350baf527a3309e50ffd7065f7aee04dd06e1e7db794ddfde7fe9d81f28df64edd587173f8f9295496a7ddb74b9a185d4bf4de7bb619e6d4ec45c8fd35 + checksum: 10c0/e8a278e75a895f13a7b17dd79abe1e894fe82a5ed3abb127c33c14c66773d69993762521c094c6c364723f8f7375683b0d4a96097781175a29407baedf67b769 languageName: node linkType: hard @@ -123,16 +123,16 @@ __metadata: languageName: node linkType: hard -"@babel/helper-compilation-targets@npm:^7.22.6, @babel/helper-compilation-targets@npm:^7.24.7": - version: 7.24.7 - resolution: "@babel/helper-compilation-targets@npm:7.24.7" +"@babel/helper-compilation-targets@npm:^7.22.6, @babel/helper-compilation-targets@npm:^7.24.7, @babel/helper-compilation-targets@npm:^7.24.8": + version: 7.24.8 + resolution: "@babel/helper-compilation-targets@npm:7.24.8" dependencies: - "@babel/compat-data": "npm:^7.24.7" - "@babel/helper-validator-option": "npm:^7.24.7" - browserslist: "npm:^4.22.2" + "@babel/compat-data": "npm:^7.24.8" + "@babel/helper-validator-option": "npm:^7.24.8" + browserslist: "npm:^4.23.1" lru-cache: "npm:^5.1.1" semver: "npm:^6.3.1" - checksum: 10c0/1d580a9bcacefe65e6bf02ba1dafd7ab278269fef45b5e281d8354d95c53031e019890464e7f9351898c01502dd2e633184eb0bcda49ed2ecd538675ce310f51 + checksum: 10c0/2885c44ef6aaf82b7e4352b30089bb09fbe08ed5ec24eb452c2bdc3c021e2a65ab412f74b3d67ec1398da0356c730b33a2ceca1d67d34c85080d31ca6efa9aec languageName: node linkType: hard @@ -231,9 +231,9 @@ __metadata: languageName: node linkType: hard -"@babel/helper-module-transforms@npm:^7.24.7": - version: 7.24.7 - resolution: "@babel/helper-module-transforms@npm:7.24.7" +"@babel/helper-module-transforms@npm:^7.24.7, @babel/helper-module-transforms@npm:^7.24.8": + version: 7.24.8 + resolution: "@babel/helper-module-transforms@npm:7.24.8" dependencies: "@babel/helper-environment-visitor": "npm:^7.24.7" "@babel/helper-module-imports": "npm:^7.24.7" @@ -242,7 +242,7 @@ __metadata: "@babel/helper-validator-identifier": "npm:^7.24.7" peerDependencies: "@babel/core": ^7.0.0 - checksum: 10c0/4f311755fcc3b4cbdb689386309cdb349cf0575a938f0b9ab5d678e1a81bbb265aa34ad93174838245f2ac7ff6d5ddbd0104638a75e4e961958ed514355687b6 + checksum: 10c0/b76496d5045af55be9de60e59e65e56a43033f01ccc746b26b7af911c358668c206b688ce70a23ab31ec04f9728f3a38e8d01073c85244115ab62f271a7fa3d1 languageName: node linkType: hard @@ -255,10 +255,10 @@ __metadata: languageName: node linkType: hard -"@babel/helper-plugin-utils@npm:^7.0.0, @babel/helper-plugin-utils@npm:^7.10.4, @babel/helper-plugin-utils@npm:^7.12.13, @babel/helper-plugin-utils@npm:^7.14.5, @babel/helper-plugin-utils@npm:^7.18.6, @babel/helper-plugin-utils@npm:^7.22.5, @babel/helper-plugin-utils@npm:^7.24.7, @babel/helper-plugin-utils@npm:^7.8.0, @babel/helper-plugin-utils@npm:^7.8.3": - version: 7.24.7 - resolution: "@babel/helper-plugin-utils@npm:7.24.7" - checksum: 10c0/c3d38cd9b3520757bb4a279255cc3f956fc0ac1c193964bd0816ebd5c86e30710be8e35252227e0c9d9e0f4f56d9b5f916537f2bc588084b0988b4787a967d31 +"@babel/helper-plugin-utils@npm:^7.0.0, @babel/helper-plugin-utils@npm:^7.10.4, @babel/helper-plugin-utils@npm:^7.12.13, @babel/helper-plugin-utils@npm:^7.14.5, @babel/helper-plugin-utils@npm:^7.18.6, @babel/helper-plugin-utils@npm:^7.22.5, @babel/helper-plugin-utils@npm:^7.24.7, @babel/helper-plugin-utils@npm:^7.24.8, @babel/helper-plugin-utils@npm:^7.8.0, @babel/helper-plugin-utils@npm:^7.8.3": + version: 7.24.8 + resolution: "@babel/helper-plugin-utils@npm:7.24.8" + checksum: 10c0/0376037f94a3bfe6b820a39f81220ac04f243eaee7193774b983e956c1750883ff236b30785795abbcda43fac3ece74750566830c2daa4d6e3870bb0dff34c2d languageName: node linkType: hard @@ -317,10 +317,10 @@ __metadata: languageName: node linkType: hard -"@babel/helper-string-parser@npm:^7.24.7": - version: 7.24.7 - resolution: "@babel/helper-string-parser@npm:7.24.7" - checksum: 10c0/47840c7004e735f3dc93939c77b099bb41a64bf3dda0cae62f60e6f74a5ff80b63e9b7cf77b5ec25a324516381fc994e1f62f922533236a8e3a6af57decb5e1e +"@babel/helper-string-parser@npm:^7.24.8": + version: 7.24.8 + resolution: "@babel/helper-string-parser@npm:7.24.8" + checksum: 10c0/6361f72076c17fabf305e252bf6d580106429014b3ab3c1f5c4eb3e6d465536ea6b670cc0e9a637a77a9ad40454d3e41361a2909e70e305116a23d68ce094c08 languageName: node linkType: hard @@ -331,10 +331,10 @@ __metadata: languageName: node linkType: hard -"@babel/helper-validator-option@npm:^7.24.7": - version: 7.24.7 - resolution: "@babel/helper-validator-option@npm:7.24.7" - checksum: 10c0/21aea2b7bc5cc8ddfb828741d5c8116a84cbc35b4a3184ec53124f08e09746f1f67a6f9217850188995ca86059a7942e36d8965a6730784901def777b7e8a436 +"@babel/helper-validator-option@npm:^7.24.7, @babel/helper-validator-option@npm:^7.24.8": + version: 7.24.8 + resolution: "@babel/helper-validator-option@npm:7.24.8" + checksum: 10c0/73db93a34ae89201351288bee7623eed81a54000779462a986105b54ffe82069e764afd15171a428b82e7c7a9b5fec10b5d5603b216317a414062edf5c67a21f languageName: node linkType: hard @@ -350,13 +350,13 @@ __metadata: languageName: node linkType: hard -"@babel/helpers@npm:^7.24.7": - version: 7.24.7 - resolution: "@babel/helpers@npm:7.24.7" +"@babel/helpers@npm:^7.24.8": + version: 7.24.8 + resolution: "@babel/helpers@npm:7.24.8" dependencies: "@babel/template": "npm:^7.24.7" - "@babel/types": "npm:^7.24.7" - checksum: 10c0/aa8e230f6668773e17e141dbcab63e935c514b4b0bf1fed04d2eaefda17df68e16b61a56573f7f1d4d1e605ce6cc162b5f7e9fdf159fde1fd9b77c920ae47d27 + "@babel/types": "npm:^7.24.8" + checksum: 10c0/42b8939b0a0bf72d6df9721973eb0fd7cd48f42641c5c9c740916397faa586255c06d36c6e6a7e091860723096281c620f6ffaee0011a3bb254a6f5475d89a12 languageName: node linkType: hard @@ -372,12 +372,12 @@ __metadata: languageName: node linkType: hard -"@babel/parser@npm:^7.1.0, @babel/parser@npm:^7.14.7, @babel/parser@npm:^7.20.7, @babel/parser@npm:^7.24.7": - version: 7.24.7 - resolution: "@babel/parser@npm:7.24.7" +"@babel/parser@npm:^7.1.0, @babel/parser@npm:^7.14.7, @babel/parser@npm:^7.20.7, @babel/parser@npm:^7.24.7, @babel/parser@npm:^7.24.8": + version: 7.24.8 + resolution: "@babel/parser@npm:7.24.8" bin: parser: ./bin/babel-parser.js - checksum: 10c0/8b244756872185a1c6f14b979b3535e682ff08cb5a2a5fd97cc36c017c7ef431ba76439e95e419d43000c5b07720495b00cf29a7f0d9a483643d08802b58819b + checksum: 10c0/ce69671de8fa6f649abf849be262707ac700b573b8b1ce1893c66cc6cd76aeb1294a19e8c290b0eadeb2f47d3f413a2e57a281804ffbe76bfb9fa50194cf3c52 languageName: node linkType: hard @@ -755,21 +755,21 @@ __metadata: languageName: node linkType: hard -"@babel/plugin-transform-classes@npm:^7.24.7": - version: 7.24.7 - resolution: "@babel/plugin-transform-classes@npm:7.24.7" +"@babel/plugin-transform-classes@npm:^7.24.8": + version: 7.24.8 + resolution: "@babel/plugin-transform-classes@npm:7.24.8" dependencies: "@babel/helper-annotate-as-pure": "npm:^7.24.7" - "@babel/helper-compilation-targets": "npm:^7.24.7" + "@babel/helper-compilation-targets": "npm:^7.24.8" "@babel/helper-environment-visitor": "npm:^7.24.7" "@babel/helper-function-name": "npm:^7.24.7" - "@babel/helper-plugin-utils": "npm:^7.24.7" + "@babel/helper-plugin-utils": "npm:^7.24.8" "@babel/helper-replace-supers": "npm:^7.24.7" "@babel/helper-split-export-declaration": "npm:^7.24.7" globals: "npm:^11.1.0" peerDependencies: "@babel/core": ^7.0.0-0 - checksum: 10c0/e51dba7ce8b770d1eee929e098d5a3be3efc3e8b941e22dda7d0097dc4e7be5feabd2da7b707ac06fcac5661b31223c541941dec08ce76c1faa55544d87d06ec + checksum: 10c0/4423da0f747bdb6aab1995d98a74533fa679f637ec20706810dd57fb4ba2b1885ec8cae6a0b2c3f69f27165de6ff6aa2da9c4061c893848736a8267d0c653079 languageName: node linkType: hard @@ -785,14 +785,14 @@ __metadata: languageName: node linkType: hard -"@babel/plugin-transform-destructuring@npm:^7.24.7": - version: 7.24.7 - resolution: "@babel/plugin-transform-destructuring@npm:7.24.7" +"@babel/plugin-transform-destructuring@npm:^7.24.8": + version: 7.24.8 + resolution: "@babel/plugin-transform-destructuring@npm:7.24.8" dependencies: - "@babel/helper-plugin-utils": "npm:^7.24.7" + "@babel/helper-plugin-utils": "npm:^7.24.8" peerDependencies: "@babel/core": ^7.0.0-0 - checksum: 10c0/929f07a807fb62230bfbf881cfcedf187ac5daf2f1b01da94a75c7a0f6f72400268cf4bcfee534479e43260af8193e42c31ee03c8b0278ba77d0036ed6709c27 + checksum: 10c0/804968c1d5f5072c717505296c1e5d5ec33e90550423de66de82bbcb78157156e8470bbe77a04ab8c710a88a06360a30103cf223ac7eff4829adedd6150de5ce languageName: node linkType: hard @@ -938,16 +938,16 @@ __metadata: languageName: node linkType: hard -"@babel/plugin-transform-modules-commonjs@npm:^7.24.7": - version: 7.24.7 - resolution: "@babel/plugin-transform-modules-commonjs@npm:7.24.7" +"@babel/plugin-transform-modules-commonjs@npm:^7.24.7, @babel/plugin-transform-modules-commonjs@npm:^7.24.8": + version: 7.24.8 + resolution: "@babel/plugin-transform-modules-commonjs@npm:7.24.8" dependencies: - "@babel/helper-module-transforms": "npm:^7.24.7" - "@babel/helper-plugin-utils": "npm:^7.24.7" + "@babel/helper-module-transforms": "npm:^7.24.8" + "@babel/helper-plugin-utils": "npm:^7.24.8" "@babel/helper-simple-access": "npm:^7.24.7" peerDependencies: "@babel/core": ^7.0.0-0 - checksum: 10c0/9442292b3daf6a5076cdc3c4c32bf423bda824ccaeb0dd0dc8b3effaa1fecfcb0130ae6e647fef12a5d5ff25bcc99a0d6bfc6d24a7525345e1bcf46fcdf81752 + checksum: 10c0/f1cf552307ebfced20d3907c1dd8be941b277f0364aa655e2b5fee828c84c54065745183104dae86f1f93ea0406db970a463ef7ceaaed897623748e99640e5a7 languageName: node linkType: hard @@ -1062,16 +1062,16 @@ __metadata: languageName: node linkType: hard -"@babel/plugin-transform-optional-chaining@npm:^7.24.7": - version: 7.24.7 - resolution: "@babel/plugin-transform-optional-chaining@npm:7.24.7" +"@babel/plugin-transform-optional-chaining@npm:^7.24.7, @babel/plugin-transform-optional-chaining@npm:^7.24.8": + version: 7.24.8 + resolution: "@babel/plugin-transform-optional-chaining@npm:7.24.8" dependencies: - "@babel/helper-plugin-utils": "npm:^7.24.7" + "@babel/helper-plugin-utils": "npm:^7.24.8" "@babel/helper-skip-transparent-expression-wrappers": "npm:^7.24.7" "@babel/plugin-syntax-optional-chaining": "npm:^7.8.3" peerDependencies: "@babel/core": ^7.0.0-0 - checksum: 10c0/b9e3649b299e103b0d1767bbdba56574d065ff776e5350403b7bfd4e3982743c0cdb373d33bdbf94fa3c322d155e45d0aad946acf0aa741b870aed22dfec8b8e + checksum: 10c0/4ffbe1aad7dec7c9aa2bf6ceb4b2f91f96815b2784f2879bde80e46934f59d64a12cb2c6262e40897c4754d77d2c35d8a5cfed63044fdebf94978b1ed3d14b17 languageName: node linkType: hard @@ -1279,14 +1279,14 @@ __metadata: languageName: node linkType: hard -"@babel/plugin-transform-typeof-symbol@npm:^7.24.7": - version: 7.24.7 - resolution: "@babel/plugin-transform-typeof-symbol@npm:7.24.7" +"@babel/plugin-transform-typeof-symbol@npm:^7.24.8": + version: 7.24.8 + resolution: "@babel/plugin-transform-typeof-symbol@npm:7.24.8" dependencies: - "@babel/helper-plugin-utils": "npm:^7.24.7" + "@babel/helper-plugin-utils": "npm:^7.24.8" peerDependencies: "@babel/core": ^7.0.0-0 - checksum: 10c0/5649e7260a138681e68b296ab5931e2b1f132f287d6b4131d49b24f9dc20d62902b7e9d63c4d2decd5683b41df35ef4b9b03f58c7f9f65e4c25a6d8bbf04e9e9 + checksum: 10c0/2f570a4fbbdc5fd85f48165a97452826560051e3b8efb48c3bb0a0a33ee8485633439e7b71bfe3ef705583a1df43f854f49125bd759abdedc195b2cf7e60012a languageName: node linkType: hard @@ -1352,13 +1352,13 @@ __metadata: linkType: hard "@babel/preset-env@npm:^7.11.0, @babel/preset-env@npm:^7.12.1, @babel/preset-env@npm:^7.22.4": - version: 7.24.7 - resolution: "@babel/preset-env@npm:7.24.7" + version: 7.24.8 + resolution: "@babel/preset-env@npm:7.24.8" dependencies: - "@babel/compat-data": "npm:^7.24.7" - "@babel/helper-compilation-targets": "npm:^7.24.7" - "@babel/helper-plugin-utils": "npm:^7.24.7" - "@babel/helper-validator-option": "npm:^7.24.7" + "@babel/compat-data": "npm:^7.24.8" + "@babel/helper-compilation-targets": "npm:^7.24.8" + "@babel/helper-plugin-utils": "npm:^7.24.8" + "@babel/helper-validator-option": "npm:^7.24.8" "@babel/plugin-bugfix-firefox-class-in-computed-class-key": "npm:^7.24.7" "@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression": "npm:^7.24.7" "@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining": "npm:^7.24.7" @@ -1389,9 +1389,9 @@ __metadata: "@babel/plugin-transform-block-scoping": "npm:^7.24.7" "@babel/plugin-transform-class-properties": "npm:^7.24.7" "@babel/plugin-transform-class-static-block": "npm:^7.24.7" - "@babel/plugin-transform-classes": "npm:^7.24.7" + "@babel/plugin-transform-classes": "npm:^7.24.8" "@babel/plugin-transform-computed-properties": "npm:^7.24.7" - "@babel/plugin-transform-destructuring": "npm:^7.24.7" + "@babel/plugin-transform-destructuring": "npm:^7.24.8" "@babel/plugin-transform-dotall-regex": "npm:^7.24.7" "@babel/plugin-transform-duplicate-keys": "npm:^7.24.7" "@babel/plugin-transform-dynamic-import": "npm:^7.24.7" @@ -1404,7 +1404,7 @@ __metadata: "@babel/plugin-transform-logical-assignment-operators": "npm:^7.24.7" "@babel/plugin-transform-member-expression-literals": "npm:^7.24.7" "@babel/plugin-transform-modules-amd": "npm:^7.24.7" - "@babel/plugin-transform-modules-commonjs": "npm:^7.24.7" + "@babel/plugin-transform-modules-commonjs": "npm:^7.24.8" "@babel/plugin-transform-modules-systemjs": "npm:^7.24.7" "@babel/plugin-transform-modules-umd": "npm:^7.24.7" "@babel/plugin-transform-named-capturing-groups-regex": "npm:^7.24.7" @@ -1414,7 +1414,7 @@ __metadata: "@babel/plugin-transform-object-rest-spread": "npm:^7.24.7" "@babel/plugin-transform-object-super": "npm:^7.24.7" "@babel/plugin-transform-optional-catch-binding": "npm:^7.24.7" - "@babel/plugin-transform-optional-chaining": "npm:^7.24.7" + "@babel/plugin-transform-optional-chaining": "npm:^7.24.8" "@babel/plugin-transform-parameters": "npm:^7.24.7" "@babel/plugin-transform-private-methods": "npm:^7.24.7" "@babel/plugin-transform-private-property-in-object": "npm:^7.24.7" @@ -1425,7 +1425,7 @@ __metadata: "@babel/plugin-transform-spread": "npm:^7.24.7" "@babel/plugin-transform-sticky-regex": "npm:^7.24.7" "@babel/plugin-transform-template-literals": "npm:^7.24.7" - "@babel/plugin-transform-typeof-symbol": "npm:^7.24.7" + "@babel/plugin-transform-typeof-symbol": "npm:^7.24.8" "@babel/plugin-transform-unicode-escapes": "npm:^7.24.7" "@babel/plugin-transform-unicode-property-regex": "npm:^7.24.7" "@babel/plugin-transform-unicode-regex": "npm:^7.24.7" @@ -1434,11 +1434,11 @@ __metadata: babel-plugin-polyfill-corejs2: "npm:^0.4.10" babel-plugin-polyfill-corejs3: "npm:^0.10.4" babel-plugin-polyfill-regenerator: "npm:^0.6.1" - core-js-compat: "npm:^3.31.0" + core-js-compat: "npm:^3.37.1" semver: "npm:^6.3.1" peerDependencies: "@babel/core": ^7.0.0-0 - checksum: 10c0/c6714346f3ccc1271eaa90051c75b8bb57b20ef57408ab68740e2f3552693ae0ee5a4bcce3a00211d40e4947af1f7b8ab422066b953f0095461937fb72d11274 + checksum: 10c0/a6f29498ec58989845a61f9c10b1b4e80586f1810a33db461d597cdb0ad2cd847381a993038b09f727512a08b2c1a33a330a5d4e6d65463ee98a1b4302d52ec6 languageName: node linkType: hard @@ -1503,11 +1503,11 @@ __metadata: linkType: hard "@babel/runtime@npm:^7.0.0, @babel/runtime@npm:^7.1.2, @babel/runtime@npm:^7.11.2, @babel/runtime@npm:^7.12.0, @babel/runtime@npm:^7.12.13, @babel/runtime@npm:^7.12.5, @babel/runtime@npm:^7.13.8, @babel/runtime@npm:^7.18.3, @babel/runtime@npm:^7.2.0, @babel/runtime@npm:^7.20.13, @babel/runtime@npm:^7.22.3, @babel/runtime@npm:^7.3.1, @babel/runtime@npm:^7.5.5, @babel/runtime@npm:^7.6.3, @babel/runtime@npm:^7.8.4, @babel/runtime@npm:^7.8.7, @babel/runtime@npm:^7.9.2": - version: 7.24.7 - resolution: "@babel/runtime@npm:7.24.7" + version: 7.24.8 + resolution: "@babel/runtime@npm:7.24.8" dependencies: regenerator-runtime: "npm:^0.14.0" - checksum: 10c0/b6fa3ec61a53402f3c1d75f4d808f48b35e0dfae0ec8e2bb5c6fc79fb95935da75766e0ca534d0f1c84871f6ae0d2ebdd950727cfadb745a2cdbef13faef5513 + checksum: 10c0/f24b30af6b3ecae19165b3b032f9bc37b2d1769677bd63b69a6f81061967cfc847aa822518402ea6616b1d301d7eb46986b99c9f69cdb5880834fca2e6b34881 languageName: node linkType: hard @@ -1522,32 +1522,32 @@ __metadata: languageName: node linkType: hard -"@babel/traverse@npm:7, @babel/traverse@npm:^7.24.7": - version: 7.24.7 - resolution: "@babel/traverse@npm:7.24.7" +"@babel/traverse@npm:7, @babel/traverse@npm:^7.24.7, @babel/traverse@npm:^7.24.8": + version: 7.24.8 + resolution: "@babel/traverse@npm:7.24.8" dependencies: "@babel/code-frame": "npm:^7.24.7" - "@babel/generator": "npm:^7.24.7" + "@babel/generator": "npm:^7.24.8" "@babel/helper-environment-visitor": "npm:^7.24.7" "@babel/helper-function-name": "npm:^7.24.7" "@babel/helper-hoist-variables": "npm:^7.24.7" "@babel/helper-split-export-declaration": "npm:^7.24.7" - "@babel/parser": "npm:^7.24.7" - "@babel/types": "npm:^7.24.7" + "@babel/parser": "npm:^7.24.8" + "@babel/types": "npm:^7.24.8" debug: "npm:^4.3.1" globals: "npm:^11.1.0" - checksum: 10c0/a5135e589c3f1972b8877805f50a084a04865ccb1d68e5e1f3b94a8841b3485da4142e33413d8fd76bc0e6444531d3adf1f59f359c11ffac452b743d835068ab + checksum: 10c0/67a5cc35824455cdb54fb9e196a44b3186283e29018a9c2331f51763921e18e891b3c60c283615a27540ec8eb4c8b89f41c237b91f732a7aa518b2eb7a0d434d languageName: node linkType: hard -"@babel/types@npm:^7.0.0, @babel/types@npm:^7.0.0-beta.49, @babel/types@npm:^7.12.11, @babel/types@npm:^7.12.6, @babel/types@npm:^7.20.7, @babel/types@npm:^7.24.7, @babel/types@npm:^7.3.3, @babel/types@npm:^7.4.4, @babel/types@npm:^7.8.3": - version: 7.24.7 - resolution: "@babel/types@npm:7.24.7" +"@babel/types@npm:^7.0.0, @babel/types@npm:^7.0.0-beta.49, @babel/types@npm:^7.12.11, @babel/types@npm:^7.12.6, @babel/types@npm:^7.20.7, @babel/types@npm:^7.24.7, @babel/types@npm:^7.24.8, @babel/types@npm:^7.3.3, @babel/types@npm:^7.4.4, @babel/types@npm:^7.8.3": + version: 7.24.8 + resolution: "@babel/types@npm:7.24.8" dependencies: - "@babel/helper-string-parser": "npm:^7.24.7" + "@babel/helper-string-parser": "npm:^7.24.8" "@babel/helper-validator-identifier": "npm:^7.24.7" to-fast-properties: "npm:^2.0.0" - checksum: 10c0/d9ecbfc3eb2b05fb1e6eeea546836ac30d990f395ef3fe3f75ced777a222c3cfc4489492f72e0ce3d9a5a28860a1ce5f81e66b88cf5088909068b3ff4fab72c1 + checksum: 10c0/2d7bf561ae993e794cb052c5a81d3a6d1877da13e1e2eb2a59ae75a8fb1c965b618fb3e4abd42548f5f9a4587d3a149185a32d6c4c4ea82195da7dd86f2da0f1 languageName: node linkType: hard @@ -5676,7 +5676,7 @@ __metadata: languageName: node linkType: hard -"browserslist@npm:^4.0.0, browserslist@npm:^4.22.2, browserslist@npm:^4.23.0, browserslist@npm:^4.23.1": +"browserslist@npm:^4.0.0, browserslist@npm:^4.23.0, browserslist@npm:^4.23.1": version: 4.23.1 resolution: "browserslist@npm:4.23.1" dependencies: @@ -6392,12 +6392,12 @@ __metadata: languageName: node linkType: hard -"core-js-compat@npm:^3.31.0, core-js-compat@npm:^3.36.1": - version: 3.36.1 - resolution: "core-js-compat@npm:3.36.1" +"core-js-compat@npm:^3.36.1, core-js-compat@npm:^3.37.1": + version: 3.37.1 + resolution: "core-js-compat@npm:3.37.1" dependencies: browserslist: "npm:^4.23.0" - checksum: 10c0/70fba18a4095cd8ac04e5ba8cee251e328935859cf2851c1f67770068ea9f9fe71accb1b7de17cd3c9a28d304a4c41712bd9aa895110ebb6e3be71b666b029d1 + checksum: 10c0/4e2da9c900f2951a57947af7aeef4d16f2c75d7f7e966c0d0b62953f65225003ade5e84d3ae98847f65b24c109c606821d9dc925db8ca418fb761e7c81963c2a languageName: node linkType: hard From 28ad3588e4936f3429e5f062c76c37f50a2f38fb Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Fri, 12 Jul 2024 08:25:27 +0000 Subject: [PATCH 031/126] New Crowdin Translations (automated) (#31006) Co-authored-by: GitHub Actions --- app/javascript/mastodon/locales/be.json | 4 ++++ config/locales/simple_form.da.yml | 1 + config/locales/simple_form.de.yml | 1 + config/locales/simple_form.es-AR.yml | 1 + config/locales/simple_form.es-MX.yml | 1 + config/locales/simple_form.es.yml | 1 + config/locales/simple_form.fi.yml | 1 + config/locales/simple_form.fo.yml | 1 + config/locales/simple_form.gl.yml | 1 + config/locales/simple_form.is.yml | 1 + config/locales/simple_form.it.yml | 1 + config/locales/simple_form.nl.yml | 1 + config/locales/simple_form.pl.yml | 1 + config/locales/simple_form.pt-PT.yml | 1 + config/locales/simple_form.sl.yml | 1 + config/locales/simple_form.sr-Latn.yml | 1 + config/locales/simple_form.sr.yml | 1 + config/locales/simple_form.tr.yml | 1 + config/locales/simple_form.vi.yml | 1 + config/locales/simple_form.zh-TW.yml | 1 + 20 files changed, 23 insertions(+) diff --git a/app/javascript/mastodon/locales/be.json b/app/javascript/mastodon/locales/be.json index 643725270c..df29fbd418 100644 --- a/app/javascript/mastodon/locales/be.json +++ b/app/javascript/mastodon/locales/be.json @@ -35,7 +35,9 @@ "account.follow_back": "Падпісацца ў адказ", "account.followers": "Падпісчыкі", "account.followers.empty": "Ніхто пакуль не падпісаны на гэтага карыстальніка.", + "account.followers_counter": "{count, plural, one {{counter} падпісчык} few {{counter} падпісчыкі} many {{counter} падпісчыкаў} other {{counter} падпісчыка}}", "account.following": "Падпіскі", + "account.following_counter": "{count, plural, one {{counter} падпіска} few {{counter} падпіскі} many {{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} допіс} few {{counter} допісы} many {{counter} допісаў} other {{counter} допісу}}", "account.unblock": "Разблакіраваць @{name}", "account.unblock_domain": "Разблакіраваць дамен {domain}", "account.unblock_short": "Разблакіраваць", @@ -412,6 +415,7 @@ "limited_account_hint.title": "Гэты профіль быў схаваны мадэратарамі", "link_preview.author": "Ад {name}", "link_preview.more_from_author": "Больш ад {name}", + "link_preview.shares": "{count, plural, one {{counter} допіс} few {{counter} допісы} many {{counter} допісаў} other {{counter} допісу}}", "lists.account.add": "Дадаць да спісу", "lists.account.remove": "Выдаліць са спісу", "lists.delete": "Выдаліць спіс", diff --git a/config/locales/simple_form.da.yml b/config/locales/simple_form.da.yml index 0719e26430..73a32cf2fd 100644 --- a/config/locales/simple_form.da.yml +++ b/config/locales/simple_form.da.yml @@ -211,6 +211,7 @@ da: setting_default_privacy: Fortrolighed for indlæg setting_default_sensitive: Markér altid medier som sensitive setting_delete_modal: Vis bekræftelsesdialog før et indlæg slettes + setting_disable_hover_cards: Deaktivér profilforhåndsvisning ved svæv (hover) setting_disable_swiping: Deaktivér strygebevægelser setting_display_media: Medievisning setting_display_media_default: Standard diff --git a/config/locales/simple_form.de.yml b/config/locales/simple_form.de.yml index 7d39786697..5711d2a12a 100644 --- a/config/locales/simple_form.de.yml +++ b/config/locales/simple_form.de.yml @@ -211,6 +211,7 @@ de: setting_default_privacy: Beitragssichtbarkeit setting_default_sensitive: Medien immer mit einer Inhaltswarnung versehen setting_delete_modal: Bestätigungsdialog beim Löschen eines Beitrags anzeigen + setting_disable_hover_cards: Profilvorschau deaktivieren, wenn die Maus über das Profil bewegt wird setting_disable_swiping: Wischgesten deaktivieren setting_display_media: Darstellung von Medien setting_display_media_default: Standard diff --git a/config/locales/simple_form.es-AR.yml b/config/locales/simple_form.es-AR.yml index e346a23a02..1d1ac87689 100644 --- a/config/locales/simple_form.es-AR.yml +++ b/config/locales/simple_form.es-AR.yml @@ -211,6 +211,7 @@ es-AR: setting_default_privacy: Privacidad de mensajes setting_default_sensitive: Siempre marcar medios como sensibles setting_delete_modal: Mostrar diálogo de confirmación antes de eliminar un mensaje + setting_disable_hover_cards: Deshabilitar previsualización del perfil al pasar el cursor setting_disable_swiping: Deshabilitar movimientos de deslizamiento setting_display_media: Visualización de medios setting_display_media_default: Predeterminada diff --git a/config/locales/simple_form.es-MX.yml b/config/locales/simple_form.es-MX.yml index b3c8a857e8..19a1c9d0c0 100644 --- a/config/locales/simple_form.es-MX.yml +++ b/config/locales/simple_form.es-MX.yml @@ -211,6 +211,7 @@ es-MX: setting_default_privacy: Privacidad de publicaciones setting_default_sensitive: Marcar siempre imágenes como sensibles setting_delete_modal: Mostrar diálogo de confirmación antes de borrar un toot + setting_disable_hover_cards: Desactivar vista previa del perfil al pasar el cursor setting_disable_swiping: Deshabilitar movimientos de deslizamiento setting_display_media: Visualización multimedia setting_display_media_default: Por defecto diff --git a/config/locales/simple_form.es.yml b/config/locales/simple_form.es.yml index 2fb5cab987..cc71e19266 100644 --- a/config/locales/simple_form.es.yml +++ b/config/locales/simple_form.es.yml @@ -211,6 +211,7 @@ es: setting_default_privacy: Privacidad de publicaciones setting_default_sensitive: Marcar siempre imágenes como sensibles setting_delete_modal: Mostrar diálogo de confirmación antes de borrar una publicación + setting_disable_hover_cards: Desactivar vista previa del perfil al pasar el cursor setting_disable_swiping: Deshabilitar movimientos de deslizamiento setting_display_media: Visualización multimedia setting_display_media_default: Por defecto diff --git a/config/locales/simple_form.fi.yml b/config/locales/simple_form.fi.yml index b0bc8c735b..214308ba5c 100644 --- a/config/locales/simple_form.fi.yml +++ b/config/locales/simple_form.fi.yml @@ -211,6 +211,7 @@ fi: setting_default_privacy: Julkaisun näkyvyys setting_default_sensitive: Merkitse media aina arkaluonteiseksi setting_delete_modal: Kysy vahvistusta ennen julkaisun poistamista + setting_disable_hover_cards: Poista käytöstä profiilin esikatselu osoitettaessa setting_disable_swiping: Poista pyyhkäisyeleet käytöstä setting_display_media: Median näyttäminen setting_display_media_default: Oletus diff --git a/config/locales/simple_form.fo.yml b/config/locales/simple_form.fo.yml index 7d4da2b51e..8f0b51719f 100644 --- a/config/locales/simple_form.fo.yml +++ b/config/locales/simple_form.fo.yml @@ -211,6 +211,7 @@ fo: setting_default_privacy: Hvussu privatir eru postar? setting_default_sensitive: Merk altíð miðlafílur sum viðkvæmar setting_delete_modal: Vís váttanarmynd, áðrenn postar verða strikaðir + setting_disable_hover_cards: Ger undanvísing, tá músin verður flutt yvir vangan, óvirkna setting_disable_swiping: Ger sveipurørslur óvirknar setting_display_media: Vístir miðlar setting_display_media_default: Sjálvvirði diff --git a/config/locales/simple_form.gl.yml b/config/locales/simple_form.gl.yml index e46ccb8737..0653d76204 100644 --- a/config/locales/simple_form.gl.yml +++ b/config/locales/simple_form.gl.yml @@ -211,6 +211,7 @@ gl: setting_default_privacy: Privacidade da publicación setting_default_sensitive: Marcar sempre multimedia como sensible setting_delete_modal: Solicitar confirmación antes de eliminar unha publicación + setting_disable_hover_cards: Desactivar vista previa do perfil ao poñerse enriba setting_disable_swiping: Desactivar opcións de desprazamento setting_display_media: Mostrar multimedia setting_display_media_default: Por defecto diff --git a/config/locales/simple_form.is.yml b/config/locales/simple_form.is.yml index 044e24deb0..cc267db8d5 100644 --- a/config/locales/simple_form.is.yml +++ b/config/locales/simple_form.is.yml @@ -211,6 +211,7 @@ is: setting_default_privacy: Gagnaleynd færslna setting_default_sensitive: Alltaf merkja myndefni sem viðkvæmt setting_delete_modal: Birta staðfestingarglugga áður en færslu er eytt + setting_disable_hover_cards: Gera óvirka forskoðun notandasniðs við yfirsvif setting_disable_swiping: Gera strokuhreyfingar óvirkar setting_display_media: Birting myndefnis setting_display_media_default: Sjálfgefið diff --git a/config/locales/simple_form.it.yml b/config/locales/simple_form.it.yml index f5624344b9..540812faa9 100644 --- a/config/locales/simple_form.it.yml +++ b/config/locales/simple_form.it.yml @@ -211,6 +211,7 @@ it: setting_default_privacy: Privacy dei post setting_default_sensitive: Segna sempre i media come sensibili setting_delete_modal: Mostra dialogo di conferma prima di eliminare un post + setting_disable_hover_cards: Disabilita l'anteprima del profilo al passaggio del mouse setting_disable_swiping: Disabilita i movimenti di scorrimento setting_display_media: Visualizzazione dei media setting_display_media_default: Predefinita diff --git a/config/locales/simple_form.nl.yml b/config/locales/simple_form.nl.yml index 2271d7037e..d6bdb7a6f0 100644 --- a/config/locales/simple_form.nl.yml +++ b/config/locales/simple_form.nl.yml @@ -211,6 +211,7 @@ nl: setting_default_privacy: Zichtbaarheid van nieuwe berichten setting_default_sensitive: Media altijd als gevoelig markeren setting_delete_modal: Vraag voor het verwijderen van een bericht een bevestiging + setting_disable_hover_cards: Profielvoorbeeld uitschakelen bij zweven setting_disable_swiping: Swipebewegingen uitschakelen setting_display_media: Mediaweergave setting_display_media_default: Standaard diff --git a/config/locales/simple_form.pl.yml b/config/locales/simple_form.pl.yml index 9d82384af9..b8de10de26 100644 --- a/config/locales/simple_form.pl.yml +++ b/config/locales/simple_form.pl.yml @@ -211,6 +211,7 @@ pl: setting_default_privacy: Widoczność wpisów setting_default_sensitive: Zawsze oznaczaj zawartość multimedialną jako wrażliwą setting_delete_modal: Pytaj o potwierdzenie przed usunięciem wpisu + setting_disable_hover_cards: Wyłącz podgląd profilu po najechaniu setting_disable_swiping: Wyłącz ruchy przesuwania setting_display_media: Wyświetlanie zawartości multimedialnej setting_display_media_default: Domyślne diff --git a/config/locales/simple_form.pt-PT.yml b/config/locales/simple_form.pt-PT.yml index 7fcbb210c5..f993687b91 100644 --- a/config/locales/simple_form.pt-PT.yml +++ b/config/locales/simple_form.pt-PT.yml @@ -211,6 +211,7 @@ pt-PT: setting_default_privacy: Privacidade da publicação setting_default_sensitive: Marcar sempre os media como problemáticos setting_delete_modal: Solicitar confirmação antes de eliminar uma publicação + setting_disable_hover_cards: Desativar visualização de perfil ao passar o cursor setting_disable_swiping: Desativar os movimentos de deslize setting_display_media: Visualização de media setting_display_media_default: Pré-definição diff --git a/config/locales/simple_form.sl.yml b/config/locales/simple_form.sl.yml index 96b36307a5..1e3f3046ad 100644 --- a/config/locales/simple_form.sl.yml +++ b/config/locales/simple_form.sl.yml @@ -211,6 +211,7 @@ sl: setting_default_privacy: Zasebnost objave setting_default_sensitive: Vedno označi medije kot občutljive setting_delete_modal: Pred brisanjem objave prikaži okno za pritrditev + setting_disable_hover_cards: Onemogoči predogled profila pod kazalko setting_disable_swiping: Onemogoči poteze drsanja setting_display_media: Prikaz medijev setting_display_media_default: Privzeto diff --git a/config/locales/simple_form.sr-Latn.yml b/config/locales/simple_form.sr-Latn.yml index 710f81e84f..22c07aa7c6 100644 --- a/config/locales/simple_form.sr-Latn.yml +++ b/config/locales/simple_form.sr-Latn.yml @@ -211,6 +211,7 @@ sr-Latn: setting_default_privacy: Privatnost objava setting_default_sensitive: Uvek označi multimediju kao osetljivu setting_delete_modal: Prikaži dijalog za potvrdu pre brisanja objave + setting_disable_hover_cards: Onemogući pregled profila prelaskom kursora setting_disable_swiping: Onemogući pokrete prevlačenja setting_display_media: Prikaz medija setting_display_media_default: Podrazumevano diff --git a/config/locales/simple_form.sr.yml b/config/locales/simple_form.sr.yml index c5fbc9185a..10c1796637 100644 --- a/config/locales/simple_form.sr.yml +++ b/config/locales/simple_form.sr.yml @@ -211,6 +211,7 @@ sr: setting_default_privacy: Приватност објава setting_default_sensitive: Увек означи мултимедију као осетљиву setting_delete_modal: Прикажи дијалог за потврду пре брисања објаве + setting_disable_hover_cards: Онемогући преглед профила преласком курсора setting_disable_swiping: Онемогући покрете превлачења setting_display_media: Приказ медија setting_display_media_default: Подразумевано diff --git a/config/locales/simple_form.tr.yml b/config/locales/simple_form.tr.yml index 697417a541..b1e90122ec 100644 --- a/config/locales/simple_form.tr.yml +++ b/config/locales/simple_form.tr.yml @@ -211,6 +211,7 @@ tr: setting_default_privacy: Gönderi gizliliği setting_default_sensitive: Medyayı her zaman hassas olarak işaretle setting_delete_modal: Bir gönderiyi silmeden önce onay iletişim kutusu göster + setting_disable_hover_cards: Üstüne geldiğinde profil önizlemesini devre dışı bırak setting_disable_swiping: Kaydırma hareketlerini devre dışı bırak setting_display_media: Medya görüntüleme setting_display_media_default: Varsayılan diff --git a/config/locales/simple_form.vi.yml b/config/locales/simple_form.vi.yml index e5063e6112..9006156db1 100644 --- a/config/locales/simple_form.vi.yml +++ b/config/locales/simple_form.vi.yml @@ -211,6 +211,7 @@ vi: setting_default_privacy: Kiểu đăng setting_default_sensitive: Đánh dấu media nhạy cảm setting_delete_modal: Hỏi trước khi xóa tút + setting_disable_hover_cards: Tắt thẻ xem trước hồ sơ setting_disable_swiping: Không dùng chuyển động vuốt setting_display_media: Media nhạy cảm setting_display_media_default: Mặc định diff --git a/config/locales/simple_form.zh-TW.yml b/config/locales/simple_form.zh-TW.yml index b7a67c6a6f..7c460a25f5 100644 --- a/config/locales/simple_form.zh-TW.yml +++ b/config/locales/simple_form.zh-TW.yml @@ -211,6 +211,7 @@ zh-TW: setting_default_privacy: 嘟文隱私設定 setting_default_sensitive: 總是將媒體標記為敏感內容 setting_delete_modal: 刪除嘟文前先詢問我 + setting_disable_hover_cards: 停用於滑鼠懸停時預覽個人檔案 setting_disable_swiping: 停用滑動手勢 setting_display_media: 媒體顯示 setting_display_media_default: 預設 From 43e24dbb13f497cf13bf301e40f8790ba5960f2d Mon Sep 17 00:00:00 2001 From: Matt Jankowski Date: Fri, 12 Jul 2024 04:30:52 -0400 Subject: [PATCH 032/126] Use `include_pagination_headers` in more places (#30999) --- .../requests/api/v1/accounts/statuses_spec.rb | 50 ++++++------------- spec/requests/api/v1/conversations_spec.rb | 8 ++- .../statuses/favourited_by_accounts_spec.rb | 6 ++- .../v1/statuses/reblogged_by_accounts_spec.rb | 6 ++- spec/requests/api/v2/admin/accounts_spec.rb | 3 +- 5 files changed, 31 insertions(+), 42 deletions(-) diff --git a/spec/requests/api/v1/accounts/statuses_spec.rb b/spec/requests/api/v1/accounts/statuses_spec.rb index 371867b215..97cdbe0156 100644 --- a/spec/requests/api/v1/accounts/statuses_spec.rb +++ b/spec/requests/api/v1/accounts/statuses_spec.rb @@ -10,12 +10,15 @@ describe 'API V1 Accounts Statuses' do describe 'GET /api/v1/accounts/:account_id/statuses' do it 'returns expected headers', :aggregate_failures do - Fabricate(:status, account: user.account) + status = Fabricate(:status, account: user.account) get "/api/v1/accounts/#{user.account.id}/statuses", params: { limit: 1 }, headers: headers - expect(response).to have_http_status(200) - expect(links_from_header.size) - .to eq(2) + expect(response) + .to have_http_status(200) + .and include_pagination_headers( + prev: api_v1_account_statuses_url(limit: 1, min_id: status.id), + next: api_v1_account_statuses_url(limit: 1, max_id: status.id) + ) end context 'with only media' do @@ -55,16 +58,9 @@ describe 'API V1 Accounts Statuses' do it 'returns http success and includes a header link' do get "/api/v1/accounts/#{user.account.id}/statuses", params: { pinned: true }, headers: headers - expect(response).to have_http_status(200) - expect(links_from_header.size) - .to eq(1) - expect(links_from_header) - .to contain_exactly( - have_attributes( - href: /pinned=true/, - attr_pairs: contain_exactly(['rel', 'prev']) - ) - ) + expect(response) + .to have_http_status(200) + .and include_pagination_headers(prev: api_v1_account_statuses_url(pinned: true, min_id: Status.first.id)) end end @@ -77,19 +73,11 @@ describe 'API V1 Accounts Statuses' do it 'returns http success and header pagination links to prev and next' do get "/api/v1/accounts/#{user.account.id}/statuses", params: { pinned: true }, headers: headers - expect(response).to have_http_status(200) - expect(links_from_header.size) - .to eq(2) - expect(links_from_header) - .to contain_exactly( - have_attributes( - href: /pinned=true/, - attr_pairs: contain_exactly(['rel', 'next']) - ), - have_attributes( - href: /pinned=true/, - attr_pairs: contain_exactly(['rel', 'prev']) - ) + expect(response) + .to have_http_status(200) + .and include_pagination_headers( + prev: api_v1_account_statuses_url(pinned: true, min_id: Status.first.id), + next: api_v1_account_statuses_url(pinned: true, max_id: Status.first.id) ) end end @@ -138,12 +126,4 @@ describe 'API V1 Accounts Statuses' do end end end - - private - - def links_from_header - response - .headers['Link'] - .links - end end diff --git a/spec/requests/api/v1/conversations_spec.rb b/spec/requests/api/v1/conversations_spec.rb index f4776f18d9..f136e1f4e8 100644 --- a/spec/requests/api/v1/conversations_spec.rb +++ b/spec/requests/api/v1/conversations_spec.rb @@ -20,8 +20,12 @@ RSpec.describe 'API V1 Conversations' do it 'returns pagination headers', :aggregate_failures do get '/api/v1/conversations', params: { limit: 1 }, headers: headers - expect(response).to have_http_status(200) - expect(response.headers['Link'].links.size).to eq(2) + expect(response) + .to have_http_status(200) + .and include_pagination_headers( + prev: api_v1_conversations_url(limit: 1, min_id: Status.first.id), + next: api_v1_conversations_url(limit: 1, max_id: Status.first.id) + ) end it 'returns conversations', :aggregate_failures do diff --git a/spec/requests/api/v1/statuses/favourited_by_accounts_spec.rb b/spec/requests/api/v1/statuses/favourited_by_accounts_spec.rb index 44296f4c37..2fd79f424b 100644 --- a/spec/requests/api/v1/statuses/favourited_by_accounts_spec.rb +++ b/spec/requests/api/v1/statuses/favourited_by_accounts_spec.rb @@ -29,8 +29,10 @@ RSpec.describe 'API V1 Statuses Favourited by Accounts' do expect(response) .to have_http_status(200) - expect(response.headers['Link'].links.size) - .to eq(2) + .and include_pagination_headers( + prev: api_v1_status_favourited_by_index_url(limit: 2, since_id: Favourite.last.id), + next: api_v1_status_favourited_by_index_url(limit: 2, max_id: Favourite.first.id) + ) expect(body_as_json.size) .to eq(2) diff --git a/spec/requests/api/v1/statuses/reblogged_by_accounts_spec.rb b/spec/requests/api/v1/statuses/reblogged_by_accounts_spec.rb index 6f99ce9464..5fc54042f9 100644 --- a/spec/requests/api/v1/statuses/reblogged_by_accounts_spec.rb +++ b/spec/requests/api/v1/statuses/reblogged_by_accounts_spec.rb @@ -28,8 +28,10 @@ RSpec.describe 'API V1 Statuses Reblogged by Accounts' do expect(response) .to have_http_status(200) - expect(response.headers['Link'].links.size) - .to eq(2) + .and include_pagination_headers( + prev: api_v1_status_reblogged_by_index_url(limit: 2, since_id: bob.statuses.first.id), + next: api_v1_status_reblogged_by_index_url(limit: 2, max_id: alice.statuses.first.id) + ) expect(body_as_json.size) .to eq(2) diff --git a/spec/requests/api/v2/admin/accounts_spec.rb b/spec/requests/api/v2/admin/accounts_spec.rb index f5db93233c..8f52c6a613 100644 --- a/spec/requests/api/v2/admin/accounts_spec.rb +++ b/spec/requests/api/v2/admin/accounts_spec.rb @@ -83,7 +83,8 @@ RSpec.describe 'API V2 Admin Accounts' do let(:params) { { limit: 1 } } it 'sets the correct pagination headers' do - expect(response.headers['Link'].find_link(%w(rel next)).href).to eq api_v2_admin_accounts_url(limit: 1, max_id: admin_account.id) + expect(response) + .to include_pagination_headers(next: api_v2_admin_accounts_url(limit: 1, max_id: admin_account.id)) end end end From 9cc0607358dda4e3dd46e7bcee05e6545175f626 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Fri, 12 Jul 2024 11:29:10 +0200 Subject: [PATCH 033/126] chore(deps): update dependency database_cleaner-active_record to v2.2.0 (#31007) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- Gemfile.lock | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Gemfile.lock b/Gemfile.lock index 2d085152e8..8bb1620646 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -180,7 +180,7 @@ GEM css_parser (1.17.1) addressable csv (3.3.0) - database_cleaner-active_record (2.1.0) + database_cleaner-active_record (2.2.0) activerecord (>= 5.a) database_cleaner-core (~> 2.0.0) database_cleaner-core (2.0.1) From c929b4cace3f95fe54fdafe449ea7e972c8d61e8 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Fri, 12 Jul 2024 11:29:43 +0200 Subject: [PATCH 034/126] chore(deps): update dependency pghero to v3.6.0 (#30994) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- Gemfile.lock | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Gemfile.lock b/Gemfile.lock index 8bb1620646..5c673a6282 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -590,8 +590,8 @@ GEM pastel (0.8.0) tty-color (~> 0.5) pg (1.5.6) - pghero (3.5.0) - activerecord (>= 6) + pghero (3.6.0) + activerecord (>= 6.1) premailer (1.23.0) addressable css_parser (>= 1.12.0) From 8d2a93b0cba756d1fffdbc6f2d2ffa39b571044b Mon Sep 17 00:00:00 2001 From: Claire Date: Thu, 11 Jul 2024 21:42:58 +0200 Subject: [PATCH 035/126] [Glitch] Add setting to disable hover cards Port ad52b04a1c88574ae3be2c56bead1b0638b253fc to glitch-soc Co-authored-by: Eugen Rochko --- app/javascript/flavours/glitch/components/status_content.jsx | 2 +- app/javascript/flavours/glitch/components/status_header.jsx | 1 + app/javascript/flavours/glitch/features/ui/index.jsx | 4 ++-- app/javascript/flavours/glitch/initial_state.js | 2 ++ 4 files changed, 6 insertions(+), 3 deletions(-) diff --git a/app/javascript/flavours/glitch/components/status_content.jsx b/app/javascript/flavours/glitch/components/status_content.jsx index c28f85eb72..634ab0db29 100644 --- a/app/javascript/flavours/glitch/components/status_content.jsx +++ b/app/javascript/flavours/glitch/components/status_content.jsx @@ -181,7 +181,7 @@ class StatusContent extends PureComponent { if (mention) { link.addEventListener('click', this.onMentionClick.bind(this, mention), false); - link.removeAttribute('title'); + link.setAttribute('title', `@${mention.get('acct')}`); link.setAttribute('data-hover-card-account', mention.get('id')); if (rewriteMentions !== 'no') { while (link.firstChild) link.removeChild(link.firstChild); diff --git a/app/javascript/flavours/glitch/components/status_header.jsx b/app/javascript/flavours/glitch/components/status_header.jsx index ee4573659c..2dd09d68ef 100644 --- a/app/javascript/flavours/glitch/components/status_header.jsx +++ b/app/javascript/flavours/glitch/components/status_header.jsx @@ -51,6 +51,7 @@ export default class StatusHeader extends PureComponent { target='_blank' onClick={this.handleAccountClick} rel='noopener noreferrer' + title={status.getIn(['account', 'acct'])} data-hover-card-account={status.getIn(['account', 'id'])} >
diff --git a/app/javascript/flavours/glitch/features/ui/index.jsx b/app/javascript/flavours/glitch/features/ui/index.jsx index 747922f23e..221f789a31 100644 --- a/app/javascript/flavours/glitch/features/ui/index.jsx +++ b/app/javascript/flavours/glitch/features/ui/index.jsx @@ -27,7 +27,7 @@ import { clearHeight } from '../../actions/height_cache'; import { expandNotifications, notificationsSetVisibility } from '../../actions/notifications'; import { fetchServer, fetchServerTranslationLanguages } from '../../actions/server'; import { expandHomeTimeline } from '../../actions/timelines'; -import initialState, { me, owner, singleUserMode, trendsEnabled, trendsAsLanding } from '../../initial_state'; +import initialState, { me, owner, singleUserMode, trendsEnabled, trendsAsLanding, disableHoverCards } from '../../initial_state'; import BundleColumnError from './components/bundle_column_error'; import Header from './components/header'; @@ -651,7 +651,7 @@ class UI extends PureComponent { {layout !== 'mobile' && } - + {!disableHoverCards && } diff --git a/app/javascript/flavours/glitch/initial_state.js b/app/javascript/flavours/glitch/initial_state.js index 4492813fd3..c5628f51ce 100644 --- a/app/javascript/flavours/glitch/initial_state.js +++ b/app/javascript/flavours/glitch/initial_state.js @@ -17,6 +17,7 @@ * @property {boolean} crop_images * @property {boolean=} delete_modal * @property {boolean=} disable_swiping + * @property {boolean=} disable_hover_cards * @property {string=} disabled_account_id * @property {string} display_media * @property {string} domain @@ -106,6 +107,7 @@ export const boostModal = getMeta('boost_modal'); export const cropImages = getMeta('crop_images'); export const deleteModal = getMeta('delete_modal'); export const disableSwiping = getMeta('disable_swiping'); +export const disableHoverCards = getMeta('disable_hover_cards'); export const disabledAccountId = getMeta('disabled_account_id'); export const displayMedia = getMeta('display_media'); export const domain = getMeta('domain'); From 35a437a03f4e1f606afea8953f0be62807da91cc Mon Sep 17 00:00:00 2001 From: David Roetzel Date: Fri, 12 Jul 2024 14:09:52 +0200 Subject: [PATCH 036/126] Destroy `NotificationRequest`s that are dismissed (#31008) --- .../v1/notifications/requests_controller.rb | 8 ++--- app/models/notification_policy.rb | 2 +- app/models/notification_request.rb | 5 ++- ...ve_dismissed_from_notification_requests.rb | 14 ++++++++ db/schema.rb | 4 +-- .../notification_request_fabricator.rb | 1 - spec/models/notification_request_spec.rb | 12 +------ .../api/v1/notifications/requests_spec.rb | 18 ++-------- spec/services/notify_service_spec.rb | 33 +++++++++++++++++++ 9 files changed, 57 insertions(+), 40 deletions(-) create mode 100644 db/post_migrate/20240712064044_remove_dismissed_from_notification_requests.rb diff --git a/app/controllers/api/v1/notifications/requests_controller.rb b/app/controllers/api/v1/notifications/requests_controller.rb index 0e58379a38..9ae80c28ed 100644 --- a/app/controllers/api/v1/notifications/requests_controller.rb +++ b/app/controllers/api/v1/notifications/requests_controller.rb @@ -28,14 +28,14 @@ class Api::V1::Notifications::RequestsController < Api::BaseController end def dismiss - @request.update!(dismissed: true) + @request.destroy! render_empty end private def load_requests - requests = NotificationRequest.where(account: current_account).where(dismissed: truthy_param?(:dismissed) || false).includes(:last_status, from_account: [:account_stat, :user]).to_a_paginated_by_id( + requests = NotificationRequest.where(account: current_account).includes(:last_status, from_account: [:account_stat, :user]).to_a_paginated_by_id( limit_param(DEFAULT_ACCOUNTS_LIMIT), params_slice(:max_id, :since_id, :min_id) ) @@ -68,8 +68,4 @@ class Api::V1::Notifications::RequestsController < Api::BaseController def pagination_since_id @requests.first.id end - - def pagination_params(core_params) - params.slice(:dismissed).permit(:dismissed).merge(core_params) - end end diff --git a/app/models/notification_policy.rb b/app/models/notification_policy.rb index f10b0c2a81..2bb58004e3 100644 --- a/app/models/notification_policy.rb +++ b/app/models/notification_policy.rb @@ -31,6 +31,6 @@ class NotificationPolicy < ApplicationRecord private def pending_notification_requests - @pending_notification_requests ||= notification_requests.where(dismissed: false).limit(MAX_MEANINGFUL_COUNT).pick(Arel.sql('count(*), coalesce(sum(notifications_count), 0)::bigint')) + @pending_notification_requests ||= notification_requests.limit(MAX_MEANINGFUL_COUNT).pick(Arel.sql('count(*), coalesce(sum(notifications_count), 0)::bigint')) end end diff --git a/app/models/notification_request.rb b/app/models/notification_request.rb index 6e9cae6625..2f601ac36b 100644 --- a/app/models/notification_request.rb +++ b/app/models/notification_request.rb @@ -9,12 +9,13 @@ # from_account_id :bigint(8) not null # last_status_id :bigint(8) # notifications_count :bigint(8) default(0), not null -# dismissed :boolean default(FALSE), not null # created_at :datetime not null # updated_at :datetime not null # class NotificationRequest < ApplicationRecord + self.ignored_columns += %w(dismissed) + include Paginable MAX_MEANINGFUL_COUNT = 100 @@ -34,8 +35,6 @@ class NotificationRequest < ApplicationRecord end def reconsider_existence! - return if dismissed? - prepare_notifications_count if notifications_count.positive? diff --git a/db/post_migrate/20240712064044_remove_dismissed_from_notification_requests.rb b/db/post_migrate/20240712064044_remove_dismissed_from_notification_requests.rb new file mode 100644 index 0000000000..0d85838073 --- /dev/null +++ b/db/post_migrate/20240712064044_remove_dismissed_from_notification_requests.rb @@ -0,0 +1,14 @@ +# frozen_string_literal: true + +class RemoveDismissedFromNotificationRequests < ActiveRecord::Migration[7.1] + def up + safety_assured do + execute 'DELETE FROM notification_requests WHERE dismissed' + remove_column :notification_requests, :dismissed + end + end + + def down + add_column :notification_requests, :dismissed, :boolean, default: false, null: false + end +end diff --git a/db/schema.rb b/db/schema.rb index 5f8c7e693f..87c49d7415 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_06_07_094856) do +ActiveRecord::Schema[7.1].define(version: 2024_07_12_064044) do # These are extensions that must be enabled in order to support this database enable_extension "plpgsql" @@ -706,11 +706,9 @@ ActiveRecord::Schema[7.1].define(version: 2024_06_07_094856) do t.bigint "from_account_id", null: false t.bigint "last_status_id" t.bigint "notifications_count", default: 0, null: false - t.boolean "dismissed", default: false, null: false t.datetime "created_at", null: false t.datetime "updated_at", null: false t.index ["account_id", "from_account_id"], name: "index_notification_requests_on_account_id_and_from_account_id", unique: true - t.index ["account_id", "id"], name: "index_notification_requests_on_account_id_and_id", order: { id: :desc }, where: "(dismissed = false)" t.index ["from_account_id"], name: "index_notification_requests_on_from_account_id" t.index ["last_status_id"], name: "index_notification_requests_on_last_status_id" end diff --git a/spec/fabricators/notification_request_fabricator.rb b/spec/fabricators/notification_request_fabricator.rb index 05a13b8ef8..a20d3b3ef2 100644 --- a/spec/fabricators/notification_request_fabricator.rb +++ b/spec/fabricators/notification_request_fabricator.rb @@ -4,5 +4,4 @@ Fabricator(:notification_request) do account from_account { Fabricate.build(:account) } last_status { Fabricate.build(:status) } - dismissed false end diff --git a/spec/models/notification_request_spec.rb b/spec/models/notification_request_spec.rb index 07bbc3e0a8..4adddc194f 100644 --- a/spec/models/notification_request_spec.rb +++ b/spec/models/notification_request_spec.rb @@ -4,9 +4,7 @@ require 'rails_helper' RSpec.describe NotificationRequest do describe '#reconsider_existence!' do - subject { Fabricate(:notification_request, dismissed: dismissed) } - - let(:dismissed) { false } + subject { Fabricate(:notification_request) } context 'when there are remaining notifications' do before do @@ -28,14 +26,6 @@ RSpec.describe NotificationRequest do subject.reconsider_existence! end - context 'when dismissed' do - let(:dismissed) { true } - - it 'leaves request intact' do - expect(subject.destroyed?).to be false - end - end - it 'removes the request' do expect(subject.destroyed?).to be true end diff --git a/spec/requests/api/v1/notifications/requests_spec.rb b/spec/requests/api/v1/notifications/requests_spec.rb index 23ddfd2bda..d3a9753246 100644 --- a/spec/requests/api/v1/notifications/requests_spec.rb +++ b/spec/requests/api/v1/notifications/requests_spec.rb @@ -17,7 +17,6 @@ RSpec.describe 'Requests' do before do Fabricate(:notification_request, account: user.account) - Fabricate(:notification_request, account: user.account, dismissed: true) end it_behaves_like 'forbidden for wrong scope', 'write write:notifications' @@ -29,16 +28,6 @@ RSpec.describe 'Requests' do expect(response).to have_http_status(200) end end - - context 'with dismissed' do - let(:params) { { dismissed: '1' } } - - it 'returns http success', :aggregate_failures do - subject - - expect(response).to have_http_status(200) - end - end end describe 'POST /api/v1/notifications/requests/:id/accept' do @@ -78,15 +67,14 @@ RSpec.describe 'Requests' do post "/api/v1/notifications/requests/#{notification_request.id}/dismiss", headers: headers end - let(:notification_request) { Fabricate(:notification_request, account: user.account) } + let!(:notification_request) { Fabricate(:notification_request, account: user.account) } it_behaves_like 'forbidden for wrong scope', 'read read:notifications' - it 'returns http success and dismisses the notification request', :aggregate_failures do - subject + it 'returns http success and destroys the notification request', :aggregate_failures do + expect { subject }.to change(NotificationRequest, :count).by(-1) expect(response).to have_http_status(200) - expect(notification_request.reload.dismissed?).to be true end context 'when notification request belongs to someone else' do diff --git a/spec/services/notify_service_spec.rb b/spec/services/notify_service_spec.rb index c695855bec..c7e00129b2 100644 --- a/spec/services/notify_service_spec.rb +++ b/spec/services/notify_service_spec.rb @@ -129,6 +129,39 @@ RSpec.describe NotifyService do end end + context 'with filtered notifications' do + let(:unknown) { Fabricate(:account, username: 'unknown') } + let(:status) { Fabricate(:status, account: unknown) } + let(:activity) { Fabricate(:mention, account: recipient, status: status) } + let(:type) { :mention } + + before do + Fabricate(:notification_policy, account: recipient, filter_not_following: true) + end + + it 'creates a filtered notification' do + expect { subject }.to change(Notification, :count) + expect(Notification.last).to be_filtered + end + + context 'when no notification request exists' do + it 'creates a notification request' do + expect { subject }.to change(NotificationRequest, :count) + end + end + + context 'when a notification request exists' do + let!(:notification_request) do + Fabricate(:notification_request, account: recipient, from_account: unknown, last_status: Fabricate(:status, account: unknown)) + end + + it 'updates the existing notification request' do + expect { subject }.to_not change(NotificationRequest, :count) + expect(notification_request.reload.last_status).to eq status + end + end + end + describe NotifyService::DismissCondition do subject { described_class.new(notification) } From b87c41115e99becdfc8a6a66300b4fc6fe39bf3b Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Fri, 12 Jul 2024 14:20:32 +0200 Subject: [PATCH 037/126] chore(deps): update dependency rubocop-rspec to v3.0.3 (#31009) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- Gemfile.lock | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Gemfile.lock b/Gemfile.lock index 5c673a6282..98a3571731 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -756,7 +756,7 @@ GEM rack (>= 1.1) rubocop (>= 1.33.0, < 2.0) rubocop-ast (>= 1.31.1, < 2.0) - rubocop-rspec (3.0.2) + rubocop-rspec (3.0.3) rubocop (~> 1.61) rubocop-rspec_rails (2.30.0) rubocop (~> 1.61) From c953dca1dee71f32b547e68977568cd076a6f7ae Mon Sep 17 00:00:00 2001 From: Emelia Smith Date: Fri, 12 Jul 2024 14:23:09 +0200 Subject: [PATCH 038/126] Streaming: use pgPool.query instead of manually acquiring & releasing a connection (#30964) --- streaming/index.js | 77 +++++++++++++++------------------------------- 1 file changed, 24 insertions(+), 53 deletions(-) diff --git a/streaming/index.js b/streaming/index.js index 2ba8b15407..dd9ea0c7f6 100644 --- a/streaming/index.js +++ b/streaming/index.js @@ -524,43 +524,27 @@ const startServer = async () => { * @param {any} req * @returns {Promise} */ - const accountFromToken = (token, req) => new Promise((resolve, reject) => { - pgPool.connect((err, client, done) => { - if (err) { - reject(err); - return; - } + const accountFromToken = async (token, req) => { + const result = await pgPool.query('SELECT oauth_access_tokens.id, oauth_access_tokens.resource_owner_id, users.account_id, users.chosen_languages, oauth_access_tokens.scopes, devices.device_id FROM oauth_access_tokens INNER JOIN users ON oauth_access_tokens.resource_owner_id = users.id LEFT OUTER JOIN devices ON oauth_access_tokens.id = devices.access_token_id WHERE oauth_access_tokens.token = $1 AND oauth_access_tokens.revoked_at IS NULL LIMIT 1', [token]); - // @ts-ignore - client.query('SELECT oauth_access_tokens.id, oauth_access_tokens.resource_owner_id, users.account_id, users.chosen_languages, oauth_access_tokens.scopes, devices.device_id FROM oauth_access_tokens INNER JOIN users ON oauth_access_tokens.resource_owner_id = users.id LEFT OUTER JOIN devices ON oauth_access_tokens.id = devices.access_token_id WHERE oauth_access_tokens.token = $1 AND oauth_access_tokens.revoked_at IS NULL LIMIT 1', [token], (err, result) => { - done(); + if (result.rows.length === 0) { + throw new AuthenticationError('Invalid access token'); + } - if (err) { - reject(err); - return; - } + req.accessTokenId = result.rows[0].id; + req.scopes = result.rows[0].scopes.split(' '); + req.accountId = result.rows[0].account_id; + req.chosenLanguages = result.rows[0].chosen_languages; + req.deviceId = result.rows[0].device_id; - if (result.rows.length === 0) { - reject(new AuthenticationError('Invalid access token')); - return; - } - - req.accessTokenId = result.rows[0].id; - req.scopes = result.rows[0].scopes.split(' '); - req.accountId = result.rows[0].account_id; - req.chosenLanguages = result.rows[0].chosen_languages; - req.deviceId = result.rows[0].device_id; - - resolve({ - accessTokenId: result.rows[0].id, - scopes: result.rows[0].scopes.split(' '), - accountId: result.rows[0].account_id, - chosenLanguages: result.rows[0].chosen_languages, - deviceId: result.rows[0].device_id - }); - }); - }); - }); + return { + accessTokenId: result.rows[0].id, + scopes: result.rows[0].scopes.split(' '), + accountId: result.rows[0].account_id, + chosenLanguages: result.rows[0].chosen_languages, + deviceId: result.rows[0].device_id + }; + }; /** * @param {any} req @@ -771,28 +755,15 @@ const startServer = async () => { * @param {any} req * @returns {Promise.} */ - const authorizeListAccess = (listId, req) => new Promise((resolve, reject) => { + const authorizeListAccess = async (listId, req) => { const { accountId } = req; - pgPool.connect((err, client, done) => { - if (err) { - reject(); - return; - } + const result = await pgPool.query('SELECT id, account_id FROM lists WHERE id = $1 AND account_id = $2 LIMIT 1', [listId, accountId]); - // @ts-ignore - client.query('SELECT id, account_id FROM lists WHERE id = $1 LIMIT 1', [listId], (err, result) => { - done(); - - if (err || result.rows.length === 0 || result.rows[0].account_id !== accountId) { - reject(); - return; - } - - resolve(); - }); - }); - }); + if (result.rows.length === 0) { + throw new AuthenticationError('List not found'); + } + }; /** * @param {string[]} channelIds From 00cb4a0313190bfa118966692a649db9c8328094 Mon Sep 17 00:00:00 2001 From: Matt Jankowski Date: Fri, 12 Jul 2024 10:09:16 -0400 Subject: [PATCH 039/126] Avoid repeated factory creation in media_attachments_vacuum_spec (#31000) --- .../vacuum/media_attachments_vacuum_spec.rb | 39 +++++++------------ 1 file changed, 14 insertions(+), 25 deletions(-) diff --git a/spec/lib/vacuum/media_attachments_vacuum_spec.rb b/spec/lib/vacuum/media_attachments_vacuum_spec.rb index 3c17ecb000..1039c36cea 100644 --- a/spec/lib/vacuum/media_attachments_vacuum_spec.rb +++ b/spec/lib/vacuum/media_attachments_vacuum_spec.rb @@ -17,32 +17,21 @@ RSpec.describe Vacuum::MediaAttachmentsVacuum do let!(:old_unattached_media) { Fabricate(:media_attachment, account_id: nil, created_at: 10.days.ago) } let!(:new_unattached_media) { Fabricate(:media_attachment, account_id: nil, created_at: 1.hour.ago) } - before do - subject.perform - end + before { subject.perform } - it 'deletes cache of remote media attachments past the retention period' do - expect(old_remote_media.reload.file).to be_blank - end - - it 'does not touch local media attachments past the retention period' do - expect(old_local_media.reload.file).to_not be_blank - end - - it 'does not delete cache of remote media attachments within the retention period' do - expect(new_remote_media.reload.file).to_not be_blank - end - - it 'does not touch local media attachments within the retention period' do - expect(new_local_media.reload.file).to_not be_blank - end - - it 'deletes unattached media attachments past TTL' do - expect { old_unattached_media.reload }.to raise_error(ActiveRecord::RecordNotFound) - end - - it 'does not delete unattached media attachments within TTL' do - expect(new_unattached_media.reload).to be_persisted + it 'handles attachments based on metadata details' do + expect(old_remote_media.reload.file) # Remote and past retention period + .to be_blank + expect(old_local_media.reload.file) # Local and past retention + .to_not be_blank + expect(new_remote_media.reload.file) # Remote and within retention + .to_not be_blank + expect(new_local_media.reload.file) # Local and within retention + .to_not be_blank + expect { old_unattached_media.reload } # Unattached and past TTL + .to raise_error(ActiveRecord::RecordNotFound) + expect(new_unattached_media.reload) # Unattached and within TTL + .to be_persisted end end end From d61b536df30c6368a45fd4750c01322b14011b48 Mon Sep 17 00:00:00 2001 From: mogaminsk Date: Mon, 15 Jul 2024 16:38:48 +0900 Subject: [PATCH 040/126] Add i18n strings for instance favicon and logo settings label (#31016) --- config/locales/simple_form.en.yml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/config/locales/simple_form.en.yml b/config/locales/simple_form.en.yml index 0313d4683e..6bc7c6ac52 100644 --- a/config/locales/simple_form.en.yml +++ b/config/locales/simple_form.en.yml @@ -243,11 +243,13 @@ en: 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 From 17117109adacd5811317b4927594992a9c5ddffb Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Mon, 15 Jul 2024 07:44:37 +0000 Subject: [PATCH 041/126] New Crowdin Translations (automated) (#31018) Co-authored-by: GitHub Actions --- app/javascript/mastodon/locales/ar.json | 1 + app/javascript/mastodon/locales/de.json | 8 ++++---- app/javascript/mastodon/locales/ja.json | 4 ++++ app/javascript/mastodon/locales/si.json | 17 ++++++++++++++++ app/javascript/mastodon/locales/tok.json | 25 ++++++++++++++++++++++++ config/locales/devise.nl.yml | 2 +- config/locales/doorkeeper.nl.yml | 2 +- config/locales/ja.yml | 1 + config/locales/simple_form.ca.yml | 1 + config/locales/simple_form.eo.yml | 1 + config/locales/simple_form.he.yml | 1 + config/locales/simple_form.ja.yml | 1 + config/locales/simple_form.ko.yml | 1 + config/locales/simple_form.nl.yml | 2 +- config/locales/simple_form.sl.yml | 2 +- config/locales/simple_form.sq.yml | 1 + config/locales/simple_form.th.yml | 1 + config/locales/simple_form.uk.yml | 1 + config/locales/simple_form.zh-CN.yml | 1 + 19 files changed, 65 insertions(+), 8 deletions(-) diff --git a/app/javascript/mastodon/locales/ar.json b/app/javascript/mastodon/locales/ar.json index 115f6335b6..5509769e04 100644 --- a/app/javascript/mastodon/locales/ar.json +++ b/app/javascript/mastodon/locales/ar.json @@ -35,6 +35,7 @@ "account.follow_back": "تابعهم بالمثل", "account.followers": "مُتابِعون", "account.followers.empty": "لا أحدَ يُتابع هذا المُستخدم إلى حد الآن.", + "account.followers_counter": "{count, plural, zero {}one {{counter} متابع} two {{counter} متابعين} few {{counter} متابعين} many {{counter} متابعين} other {{counter} متابعين}}", "account.following": "الاشتراكات", "account.follows.empty": "لا يُتابع هذا المُستخدمُ أيَّ أحدٍ حتى الآن.", "account.go_to_profile": "اذهب إلى الملف الشخصي", diff --git a/app/javascript/mastodon/locales/de.json b/app/javascript/mastodon/locales/de.json index 86438757a3..0f3b3c91a9 100644 --- a/app/javascript/mastodon/locales/de.json +++ b/app/javascript/mastodon/locales/de.json @@ -205,10 +205,10 @@ "disabled_account_banner.text": "Dein Konto {disabledAccount} ist derzeit deaktiviert.", "dismissable_banner.community_timeline": "Das sind die neuesten öffentlichen Beiträge von Profilen, deren Konten von {domain} verwaltet werden.", "dismissable_banner.dismiss": "Ablehnen", - "dismissable_banner.explore_links": "Diese Nachrichten werden heute am häufigsten im sozialen Netzwerk geteilt. Neuere Nachrichten, die von vielen verschiedenen Profilen veröffentlicht wurden, werden höher eingestuft.", - "dismissable_banner.explore_statuses": "Diese Beiträge stammen aus dem gesamten sozialen Netzwerk und gewinnen derzeit an Reichweite. Neuere Beiträge, die häufiger geteilt und favorisiert wurden, werden höher eingestuft.", - "dismissable_banner.explore_tags": "Das sind Hashtags, die derzeit an Reichweite gewinnen. Hashtags, die von vielen verschiedenen Profilen verwendet werden, werden höher eingestuft.", - "dismissable_banner.public_timeline": "Das sind die neuesten öffentlichen Beiträge von Profilen im sozialen Netzwerk, denen Leute auf {domain} folgen.", + "dismissable_banner.explore_links": "Diese Nachrichten werden heute am häufigsten im Social Web geteilt. Neuere Nachrichten, die von vielen verschiedenen Profilen geteilt wurden, erscheinen weiter oben.", + "dismissable_banner.explore_statuses": "Diese Beiträge sind heute im Social Web sehr beliebt. Neuere Beiträge, die häufiger geteilt und favorisiert wurden, erscheinen weiter oben.", + "dismissable_banner.explore_tags": "Diese Hashtags sind heute im Social Web sehr beliebt. Hashtags, die von vielen verschiedenen Profilen verwendet werden, erscheinen weiter oben.", + "dismissable_banner.public_timeline": "Das sind die neuesten öffentlichen Beiträge von Profilen im Social Web, denen Leute auf {domain} folgen.", "domain_block_modal.block": "Server blockieren", "domain_block_modal.block_account_instead": "Stattdessen @{name} blockieren", "domain_block_modal.they_can_interact_with_old_posts": "Profile von diesem Server werden mit deinen älteren Beiträgen interagieren können.", diff --git a/app/javascript/mastodon/locales/ja.json b/app/javascript/mastodon/locales/ja.json index f3ba028eab..36974c7602 100644 --- a/app/javascript/mastodon/locales/ja.json +++ b/app/javascript/mastodon/locales/ja.json @@ -35,7 +35,9 @@ "account.follow_back": "フォローバック", "account.followers": "フォロワー", "account.followers.empty": "まだ誰もフォローしていません。", + "account.followers_counter": "{count, plural, other {{counter} フォロワー}}", "account.following": "フォロー中", + "account.following_counter": "{count, plural, 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, other {{counter} 投稿}}", "account.unblock": "@{name}さんのブロックを解除", "account.unblock_domain": "{domain}のブロックを解除", "account.unblock_short": "ブロック解除", @@ -412,6 +415,7 @@ "limited_account_hint.title": "このプロフィールは{domain}のモデレーターによって非表示にされています。", "link_preview.author": "{name}", "link_preview.more_from_author": "{name}さんの投稿をもっと読む", + "link_preview.shares": "{count, plural, other {{counter}件の投稿}}", "lists.account.add": "リストに追加", "lists.account.remove": "リストから外す", "lists.delete": "リストを削除", diff --git a/app/javascript/mastodon/locales/si.json b/app/javascript/mastodon/locales/si.json index fbfdfaa659..3a67beed52 100644 --- a/app/javascript/mastodon/locales/si.json +++ b/app/javascript/mastodon/locales/si.json @@ -33,6 +33,7 @@ "account.mute": "@{name} නිහඬ කරන්න", "account.mute_short": "නිහඬ", "account.muted": "නිහඬ කළා", + "account.open_original_page": "මුල් පිටුව අරින්න", "account.posts": "ලිපි", "account.posts_with_replies": "ලිපි සහ පිළිතුරු", "account.report": "@{name} වාර්තා කරන්න", @@ -51,6 +52,10 @@ "alert.unexpected.title": "අපොයි!", "announcement.announcement": "නිවේදනය", "audio.hide": "හඬපටය සඟවන්න", + "block_modal.show_less": "අඩුවෙන් පෙන්වන්න", + "block_modal.show_more": "තව පෙන්වන්න", + "block_modal.they_will_know": "අවහිර කළ බව දකිනු ඇත.", + "block_modal.title": "අවහිර කරන්නද?", "boost_modal.combo": "ඊළඟ වතාවේ මෙය මඟ හැරීමට {combo} එබීමට හැකිය", "bundle_column_error.copy_stacktrace": "දෝෂ වාර්තාවේ පිටපතක්", "bundle_column_error.error.title": "අපොයි!", @@ -100,10 +105,13 @@ "compose_form.lock_disclaimer.lock": "අගුළු දමා ඇත", "compose_form.placeholder": "ඔබගේ සිතුවිලි මොනවාද?", "compose_form.poll.duration": "මත විමසීමේ කාලය", + "compose_form.poll.option_placeholder": "විකල්පය {number}", "compose_form.poll.switch_to_multiple": "තේරීම් කිහිපයකට මත විමසුම වෙනස් කරන්න", "compose_form.poll.switch_to_single": "තනි තේරීමකට මත විමසුම වෙනස් කරන්න", + "compose_form.poll.type": "ශෛලිය", "compose_form.publish": "ප්‍රකාශනය", "compose_form.publish_form": "නව ලිපිය", + "compose_form.reply": "පිළිතුරු", "compose_form.spoiler.marked": "අන්තර්ගත අවවාදය ඉවත් කරන්න", "compose_form.spoiler.unmarked": "අන්තර්ගත අවවාදයක් එක් කරන්න", "confirmation_modal.cancel": "අවලංගු", @@ -123,6 +131,7 @@ "conversation.mark_as_read": "කියවූ බව යොදන්න", "conversation.open": "සංවාදය බලන්න", "conversation.with": "{names} සමඟ", + "copy_icon_button.copied": "පසුරුපුවරුවට පිටපත් විය", "copypaste.copied": "පිටපත් විය", "copypaste.copy_to_clipboard": "පසුරුපුවරුවට පිටපතක්", "directory.federated": "දන්නා ෆෙඩිවර්ස් වෙතින්", @@ -130,6 +139,9 @@ "directory.new_arrivals": "නව පැමිණීම්", "directory.recently_active": "මෑත දී සක්‍රියයි", "disabled_account_banner.account_settings": "ගිණුමේ සැකසුම්", + "dismissable_banner.dismiss": "ඉවතලන්න", + "domain_pill.server": "සේවාදායකය", + "domain_pill.username": "පරිශ්‍රීලක නාමය", "embed.instructions": "පහත කේතය පිටපත් කිරීමෙන් මෙම ලිපිය ඔබගේ අඩවියට කාවද්දන්න.", "embed.preview": "මෙන්න එය පෙනෙන අන්දම:", "emoji_button.activity": "ක්‍රියාකාරකම", @@ -178,9 +190,13 @@ "filter_modal.select_filter.search": "සොයන්න හෝ සාදන්න", "filter_modal.select_filter.title": "මෙම ලිපිය පෙරන්න", "filter_modal.title.status": "ලිපියක් පෙරන්න", + "filtered_notifications_banner.title": "පෙරූ දැනුම්දීම්", + "firehose.all": "සියල්ල", "firehose.local": "මෙම සේවාදායකය", "firehose.remote": "වෙනත් සේවාදායක", "follow_request.reject": "ප්‍රතික්‍ෂේප", + "follow_suggestions.dismiss": "නැවත පෙන්වන්න එපා", + "follow_suggestions.view_all": "සියල්ල බලන්න", "footer.about": "පිළිබඳව", "footer.directory": "පැතිකඩ නාමාවලිය", "footer.get_app": "යෙදුම ගන්න", @@ -202,6 +218,7 @@ "home.pending_critical_update.link": "යාවත්කාල බලන්න", "home.show_announcements": "නිවේදන පෙන්වන්න", "interaction_modal.login.action": "මුලට ගෙනයන්න", + "interaction_modal.on_another_server": "වෙනත් සේවාදායකයක", "interaction_modal.on_this_server": "මෙම සේවාදායකයෙහි", "interaction_modal.title.favourite": "{name}ගේ ලිපිය ප්‍රිය කරන්න", "interaction_modal.title.follow": "{name} අනුගමනය", diff --git a/app/javascript/mastodon/locales/tok.json b/app/javascript/mastodon/locales/tok.json index 80d412a20b..fcdef5f32c 100644 --- a/app/javascript/mastodon/locales/tok.json +++ b/app/javascript/mastodon/locales/tok.json @@ -170,6 +170,8 @@ "domain_block_modal.block": "o weka e ma", "domain_block_modal.you_will_lose_followers": "ma ni la jan alasa ale sina li weka", "domain_block_modal.you_wont_see_posts": "sina ken ala lukin e toki tan jan pi ma ni", + "domain_pill.server": "ma", + "domain_pill.username": "nimi jan", "embed.preview": "ni li jo e sitelen ni:", "emoji_button.activity": "musi", "emoji_button.flags": "len ma", @@ -274,6 +276,7 @@ "load_pending": "{count, plural, other {ijo sin #}}", "loading_indicator.label": "ni li kama…", "media_gallery.toggle_visible": "{number, plural, other {o len e sitelen}}", + "mute_modal.title": "sina wile ala wile kute e jan ni?", "navigation_bar.about": "sona", "navigation_bar.blocks": "jan weka", "navigation_bar.compose": "o pali e toki sin", @@ -290,24 +293,33 @@ "notification.follow": " {name} li kute e sina", "notification.follow_request": "{name} li wile kute e sina", "notification.mention": "jan {name} li toki e sina", + "notification.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", + "notification_requests.dismiss": "o weka", "notifications.column_settings.favourite": "ijo pona:", "notifications.column_settings.follow": "jan kute sin", "notifications.column_settings.poll": "pana lon pana ni:", "notifications.column_settings.reblog": "wawa:", + "notifications.column_settings.status": "toki sin:", "notifications.column_settings.update": "ante toki:", "notifications.filter.all": "ale", + "notifications.filter.boosts": "wawa", "notifications.filter.favourites": "ijo pona", + "notifications.filter.mentions": "toki pi toki sina", "notifications.filter.polls": "pana lon pana ni", + "onboarding.action.back": "o tawa monsi", + "onboarding.actions.back": "o tawa monsi", "onboarding.compose.template": "toki a, #Mastodon o!", "onboarding.profile.display_name": "nimi tawa jan ante", + "onboarding.profile.note": "sona sina", "onboarding.share.lead": "o toki lon nasin Masoton pi alasa sina tawa jan", "onboarding.share.message": "ilo #Mastodon la mi jan {username} a! o kute e mi lon ni: {url}", "onboarding.start.title": "sina o kama pona a!", "onboarding.tips.migration": "sina sona ala sona e ni? tenpo kama la sina pilin ike tawa ma {domain} la, sina ken tawa ma ante lon ilo Masoton. jan li kute e sina la jan ni li awen kute e sina. kin la sina ken lawa e ma pi sina taso a!", + "poll.closed": "ona li pini", "poll.total_people": "{count, plural, other {jan #}}", "poll.total_votes": "{count, plural, other {pana #}}", "poll.vote": "o pana", @@ -315,9 +327,15 @@ "poll.votes": "{votes, plural, other {pana #}}", "privacy.direct.long": "jan ale lon toki", "privacy.public.short": "tawa ale", + "regeneration_indicator.label": "ni li kama…", + "relative_time.days": "{number}d", "relative_time.full.just_now": "tenpo ni", + "relative_time.hours": "{number}h", "relative_time.just_now": "tenpo ni", + "relative_time.minutes": "{number}m", + "relative_time.seconds": "{number}s", "relative_time.today": "tenpo suno ni", + "reply_indicator.cancel": "o ala", "report.block": "o weka e jan", "report.block_explanation": "sina kama lukin ala e toki ona. ona li kama ala ken lukin e toki sina li kama ala ken kute e sina. ona li ken sona e kama ni.", "report.categories.other": "ante", @@ -336,6 +354,7 @@ "report.thanks.title": "sina wile ala lukin e ni anu seme?", "report.unfollow": "o pini kute e {name}", "report_notification.categories.legal": "ike tawa nasin lawa", + "report_notification.categories.other": "ante", "search.placeholder": "o alasa", "search.quick_action.go_to_account": "o tawa lipu jan {x}", "search_popout.language_code": "nimi toki kepeken nasin ISO", @@ -343,6 +362,7 @@ "search_results.see_all": "ale", "search_results.statuses": "toki", "search_results.title": "o alasa e {q}", + "server_banner.administered_by": "jan lawa:", "status.block": "o weka e @{name}", "status.cancel_reblog_private": "o pini e pana", "status.delete": "o weka", @@ -356,12 +376,14 @@ "status.media.open": "o open", "status.media.show": "o lukin", "status.media_hidden": "sitelen li len", + "status.more": "kin", "status.mute": "o len e @{name}", "status.mute_conversation": "o kute ala e ijo pi toki ni", "status.pin": "o sewi lon lipu sina", "status.pinned": "toki sewi", "status.reblog": "o wawa", "status.share": "o pana tawa ante", + "status.show_filter_reason": "o lukin", "status.show_less": "o lili e ni", "status.show_less_all": "o lili e ale", "status.show_more": "o suli e ni", @@ -378,7 +400,9 @@ "timeline_hint.resources.follows": "jan lukin", "timeline_hint.resources.statuses": "ijo pi tenpo suli", "trends.trending_now": "jan mute li toki", + "units.short.billion": "{count}B", "units.short.million": "{count}AAA", + "units.short.thousand": "{count}K", "upload_button.label": "o pana e sitelen anu kalama", "upload_error.limit": "ilo li ken ala e suli pi ijo ni.", "upload_form.audio_description": "o toki e ijo kute tawa jan pi kute ala, tawa jan pi kute lili", @@ -386,6 +410,7 @@ "upload_form.edit": "o ante", "upload_form.thumbnail": "o ante e sitelen lili", "upload_form.video_description": "o toki e ijo kute tawa jan pi kute ala, tawa jan pi kute lili, e ijo lukin tawa jan pi lukin ala, tawa jan pi lukin lili", + "upload_modal.analyzing_picture": "ilo li lukin e sitelen...", "upload_modal.choose_image": "o wile e sitelen", "upload_modal.description_placeholder": "mi pu jaki tan soweli", "upload_modal.detect_text": "ilo o alasa e nimi tan sitelen", diff --git a/config/locales/devise.nl.yml b/config/locales/devise.nl.yml index ab6ae84db4..662401a57a 100644 --- a/config/locales/devise.nl.yml +++ b/config/locales/devise.nl.yml @@ -75,7 +75,7 @@ nl: title: Een van jouw beveiligingssleutels is verwijderd webauthn_disabled: explanation: Verificatie met beveiligingssleutels is uitgeschakeld voor je account. - extra: Het is nu alleen mogelijk om in te loggen met een door de authenticatie-app gegeneerde toegangscode. + extra: Het is nu alleen mogelijk om in te loggen met een door de authenticatie-app gegeneerde toegangscode als extra controle. subject: 'Mastodon: Verificatie met beveiligingssleutels is uitgeschakeld' title: Beveiligingssleutels uitgeschakeld webauthn_enabled: diff --git a/config/locales/doorkeeper.nl.yml b/config/locales/doorkeeper.nl.yml index 4115e0a17e..0a3d8fd081 100644 --- a/config/locales/doorkeeper.nl.yml +++ b/config/locales/doorkeeper.nl.yml @@ -129,7 +129,7 @@ nl: crypto: End-to-end-encryptie favourites: Favorieten filters: Filters - follow: Volgers, genegeerde en geblokkeerde gebruikers + follow: Gevolgde, genegeerde en geblokkeerde gebruikers follows: Volgend lists: Lijsten media: Mediabijlagen diff --git a/config/locales/ja.yml b/config/locales/ja.yml index ec6963517a..5142b55032 100644 --- a/config/locales/ja.yml +++ b/config/locales/ja.yml @@ -290,6 +290,7 @@ ja: filter_by_action: アクションでフィルター filter_by_user: ユーザーでフィルター title: 操作履歴 + unavailable_instance: "(ドメイン名が利用できません)" announcements: destroyed_msg: お知らせが削除されました edit: diff --git a/config/locales/simple_form.ca.yml b/config/locales/simple_form.ca.yml index d3dc4b13f1..4bb906abdb 100644 --- a/config/locales/simple_form.ca.yml +++ b/config/locales/simple_form.ca.yml @@ -211,6 +211,7 @@ ca: setting_default_privacy: Privacitat dels tuts setting_default_sensitive: Marcar sempre el contingut gràfic com a sensible setting_delete_modal: Mostra la finestra de confirmació abans d'esborrar un tut + setting_disable_hover_cards: Deshabilita la vista prèvia del perfil en passar-hi per sobre setting_disable_swiping: Desactiva les animacions setting_display_media: Visualització multimèdia setting_display_media_default: Per defecte diff --git a/config/locales/simple_form.eo.yml b/config/locales/simple_form.eo.yml index e83f71a2cb..40535bf96b 100644 --- a/config/locales/simple_form.eo.yml +++ b/config/locales/simple_form.eo.yml @@ -203,6 +203,7 @@ eo: setting_default_privacy: Privateco de afiŝado setting_default_sensitive: Ĉiam marki plurmediojn kiel tiklaj setting_delete_modal: Montri konfirman fenestron antaŭ ol forigi mesaĝon + setting_disable_hover_cards: Malebligi profilan antaŭmontron kiam oni musumas setting_disable_swiping: Malebligi svingajn movojn setting_display_media: Montrado de plurmedioj setting_display_media_default: Implicita diff --git a/config/locales/simple_form.he.yml b/config/locales/simple_form.he.yml index 65c6f6110f..1331d2f62b 100644 --- a/config/locales/simple_form.he.yml +++ b/config/locales/simple_form.he.yml @@ -211,6 +211,7 @@ he: setting_default_privacy: פרטיות ההודעות setting_default_sensitive: תמיד לתת סימון "רגיש" למדיה setting_delete_modal: להראות תיבת אישור לפני מחיקת חיצרוץ + setting_disable_hover_cards: כבה הצצה מקדימה לפרופיל בעת מעבר עכבר מעליו setting_disable_swiping: ביטול החלקת-צד setting_display_media: תצוגת מדיה setting_display_media_default: ברירת מחדל diff --git a/config/locales/simple_form.ja.yml b/config/locales/simple_form.ja.yml index 664082dabc..56b17ab000 100644 --- a/config/locales/simple_form.ja.yml +++ b/config/locales/simple_form.ja.yml @@ -211,6 +211,7 @@ ja: setting_default_privacy: 投稿の公開範囲 setting_default_sensitive: メディアを常に閲覧注意としてマークする setting_delete_modal: 投稿を削除する前に確認ダイアログを表示する + setting_disable_hover_cards: マウスオーバーでプロフィールをポップアップしない setting_disable_swiping: スワイプでの切り替えを無効にする setting_display_media: メディアの表示 setting_display_media_default: 標準 diff --git a/config/locales/simple_form.ko.yml b/config/locales/simple_form.ko.yml index 54d36eafe0..1107e4cba5 100644 --- a/config/locales/simple_form.ko.yml +++ b/config/locales/simple_form.ko.yml @@ -211,6 +211,7 @@ ko: setting_default_privacy: 게시물 프라이버시 setting_default_sensitive: 미디어를 언제나 민감한 콘텐츠로 설정 setting_delete_modal: 게시물 삭제 전 확인 창을 표시 + setting_disable_hover_cards: 호버시 프로필 미리보기를 비활성화 setting_disable_swiping: 스와이프 모션 비활성화 setting_display_media: 미디어 표시 setting_display_media_default: 기본 diff --git a/config/locales/simple_form.nl.yml b/config/locales/simple_form.nl.yml index d6bdb7a6f0..5110e1e6d0 100644 --- a/config/locales/simple_form.nl.yml +++ b/config/locales/simple_form.nl.yml @@ -211,7 +211,7 @@ nl: setting_default_privacy: Zichtbaarheid van nieuwe berichten setting_default_sensitive: Media altijd als gevoelig markeren setting_delete_modal: Vraag voor het verwijderen van een bericht een bevestiging - setting_disable_hover_cards: Profielvoorbeeld uitschakelen bij zweven + setting_disable_hover_cards: Profielvoorbeelden door eroverheen te zweven uitschakelen setting_disable_swiping: Swipebewegingen uitschakelen setting_display_media: Mediaweergave setting_display_media_default: Standaard diff --git a/config/locales/simple_form.sl.yml b/config/locales/simple_form.sl.yml index 1e3f3046ad..14551774fe 100644 --- a/config/locales/simple_form.sl.yml +++ b/config/locales/simple_form.sl.yml @@ -211,7 +211,7 @@ sl: setting_default_privacy: Zasebnost objave setting_default_sensitive: Vedno označi medije kot občutljive setting_delete_modal: Pred brisanjem objave prikaži okno za pritrditev - setting_disable_hover_cards: Onemogoči predogled profila pod kazalko + setting_disable_hover_cards: Onemogoči predogled profila pod kazalcem setting_disable_swiping: Onemogoči poteze drsanja setting_display_media: Prikaz medijev setting_display_media_default: Privzeto diff --git a/config/locales/simple_form.sq.yml b/config/locales/simple_form.sq.yml index c3c3920962..6fedf31572 100644 --- a/config/locales/simple_form.sq.yml +++ b/config/locales/simple_form.sq.yml @@ -211,6 +211,7 @@ sq: setting_default_privacy: Privatësi postimi setting_default_sensitive: Mediave vëru përherë shenjë si rezervat setting_delete_modal: Shfaq dialog ripohimi përpara fshirjes së një mesazhi + setting_disable_hover_cards: Çaktivizo paraparje profili, kur i kalohet kursori përsipër setting_disable_swiping: Çaktivizo lëvizje me fërkim setting_display_media: Shfaqje mediash setting_display_media_default: Parazgjedhje diff --git a/config/locales/simple_form.th.yml b/config/locales/simple_form.th.yml index 0d9a88bc38..cdc82367f9 100644 --- a/config/locales/simple_form.th.yml +++ b/config/locales/simple_form.th.yml @@ -211,6 +211,7 @@ th: setting_default_privacy: ความเป็นส่วนตัวของการโพสต์ setting_default_sensitive: ทำเครื่องหมายสื่อว่าละเอียดอ่อนเสมอ setting_delete_modal: แสดงกล่องโต้ตอบการยืนยันก่อนลบโพสต์ + setting_disable_hover_cards: ปิดใช้งานตัวอย่างโปรไฟล์เมื่อวางเมาส์เหนือ setting_disable_swiping: ปิดใช้งานการเคลื่อนไหวในการปัด setting_display_media: การแสดงสื่อ setting_display_media_default: ค่าเริ่มต้น diff --git a/config/locales/simple_form.uk.yml b/config/locales/simple_form.uk.yml index 11337f2f61..332f2c91dc 100644 --- a/config/locales/simple_form.uk.yml +++ b/config/locales/simple_form.uk.yml @@ -211,6 +211,7 @@ uk: setting_default_privacy: Видимість дописів setting_default_sensitive: Позначати медіа делікатними setting_delete_modal: Показувати діалог підтвердження під час видалення допису + setting_disable_hover_cards: Вимкнути попередній перегляд профілю при наведенні setting_disable_swiping: Вимкнути рух посування setting_display_media: Показ медіа setting_display_media_default: За промовчанням diff --git a/config/locales/simple_form.zh-CN.yml b/config/locales/simple_form.zh-CN.yml index 6058cc00cf..bbee8b6706 100644 --- a/config/locales/simple_form.zh-CN.yml +++ b/config/locales/simple_form.zh-CN.yml @@ -211,6 +211,7 @@ zh-CN: setting_default_privacy: 嘟文默认可见范围 setting_default_sensitive: 始终标记媒体为敏感内容 setting_delete_modal: 在删除嘟文前询问我 + setting_disable_hover_cards: 禁用悬停资料预览 setting_disable_swiping: 禁用滑动动作 setting_display_media: 媒体显示 setting_display_media_default: 默认 From 1dd82620712eecc18f1acd72b5a8585d37e254cf Mon Sep 17 00:00:00 2001 From: Claire Date: Mon, 15 Jul 2024 11:29:57 +0200 Subject: [PATCH 042/126] Add optional `filtered` attribute to notification entities in REST API (#31011) --- .../rest/notification_serializer.rb | 4 +++ spec/requests/api/v1/notifications_spec.rb | 26 ++++++++++++++----- 2 files changed, 23 insertions(+), 7 deletions(-) diff --git a/app/serializers/rest/notification_serializer.rb b/app/serializers/rest/notification_serializer.rb index 966819585f..ee17af8076 100644 --- a/app/serializers/rest/notification_serializer.rb +++ b/app/serializers/rest/notification_serializer.rb @@ -3,6 +3,8 @@ class REST::NotificationSerializer < ActiveModel::Serializer attributes :id, :type, :created_at, :group_key + attribute :filtered, if: :filtered? + belongs_to :from_account, key: :account, serializer: REST::AccountSerializer belongs_to :target_status, key: :status, if: :status_type?, serializer: REST::StatusSerializer belongs_to :report, if: :report_type?, serializer: REST::ReportSerializer @@ -32,4 +34,6 @@ class REST::NotificationSerializer < ActiveModel::Serializer def moderation_warning_event? object.type == :moderation_warning end + + delegate :filtered?, to: :object end diff --git a/spec/requests/api/v1/notifications_spec.rb b/spec/requests/api/v1/notifications_spec.rb index 9ff0674317..c9034c17dc 100644 --- a/spec/requests/api/v1/notifications_spec.rb +++ b/spec/requests/api/v1/notifications_spec.rb @@ -20,8 +20,8 @@ RSpec.describe 'Notifications' do before do first_status = PostStatusService.new.call(user.account, text: 'Test') ReblogService.new.call(bob.account, first_status) - mentioning_status = PostStatusService.new.call(bob.account, text: 'Hello @alice') - mentioning_status.mentions.first + PostStatusService.new.call(bob.account, text: 'Hello @alice') + PostStatusService.new.call(tom.account, text: 'Hello @alice', visibility: :direct) # Filtered by default FavouriteService.new.call(bob.account, first_status) FavouriteService.new.call(tom.account, first_status) FollowService.new.call(bob.account, user.account) @@ -34,10 +34,22 @@ RSpec.describe 'Notifications' do subject expect(response).to have_http_status(200) - expect(body_json_types).to include 'reblog' - expect(body_json_types).to include 'mention' - expect(body_json_types).to include 'favourite' - expect(body_json_types).to include 'follow' + expect(body_as_json.size).to eq 5 + expect(body_json_types).to include('reblog', 'mention', 'favourite', 'follow') + expect(body_as_json.any? { |x| x[:filtered] }).to be false + end + end + + context 'with include_filtered' do + let(:params) { { include_filtered: true } } + + it 'returns expected notification types, including filtered notifications' do + subject + + expect(response).to have_http_status(200) + expect(body_as_json.size).to eq 6 + expect(body_json_types).to include('reblog', 'mention', 'favourite', 'follow') + expect(body_as_json.any? { |x| x[:filtered] }).to be true end end @@ -96,7 +108,7 @@ RSpec.describe 'Notifications' do it 'returns the requested number of notifications paginated', :aggregate_failures do subject - notifications = user.account.notifications + notifications = user.account.notifications.browserable expect(body_as_json.size) .to eq(params[:limit]) From 91ef4a6fc5d8536378a2d3bc456711bcb95bd8f4 Mon Sep 17 00:00:00 2001 From: Matt Jankowski Date: Mon, 15 Jul 2024 06:42:18 -0400 Subject: [PATCH 043/126] Add assertion about key columns to account key generate spec (#30635) --- spec/models/account_spec.rb | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) diff --git a/spec/models/account_spec.rb b/spec/models/account_spec.rb index 225929ae39..dfb1f5bc61 100644 --- a/spec/models/account_spec.rb +++ b/spec/models/account_spec.rb @@ -1015,21 +1015,26 @@ RSpec.describe Account do context 'when is local' do it 'generates keys' do - account = described_class.create!(domain: nil, username: Faker::Internet.user_name(separators: ['_'])) - expect(account.keypair).to be_private - expect(account.keypair).to be_public + account = described_class.create!(domain: nil, username: 'user_without_keys') + + expect(account) + .to be_private_key + .and be_public_key + expect(account.keypair) + .to be_private + .and be_public end end context 'when is remote' do it 'does not generate keys' do key = OpenSSL::PKey::RSA.new(1024).public_key - account = described_class.create!(domain: 'remote', uri: 'https://remote/actor', username: Faker::Internet.user_name(separators: ['_']), public_key: key.to_pem) + account = described_class.create!(domain: 'remote', uri: 'https://remote/actor', username: 'remote_user_with_public', public_key: key.to_pem) expect(account.keypair.params).to eq key.params end it 'normalizes domain' do - account = described_class.create!(domain: 'にゃん', uri: 'https://xn--r9j5b5b/actor', username: Faker::Internet.user_name(separators: ['_'])) + account = described_class.create!(domain: 'にゃん', uri: 'https://xn--r9j5b5b/actor', username: 'remote_user_with_idn_domain') expect(account.domain).to eq 'xn--r9j5b5b' end end From 543b59fa14a7e9b55a5a96d2cb0f38391108a561 Mon Sep 17 00:00:00 2001 From: Matt Jankowski Date: Mon, 15 Jul 2024 09:03:23 -0400 Subject: [PATCH 044/126] Clean up `theme_helper` style builders (#30617) --- app/helpers/theme_helper.rb | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/app/helpers/theme_helper.rb b/app/helpers/theme_helper.rb index d15259851c..fab899a533 100644 --- a/app/helpers/theme_helper.rb +++ b/app/helpers/theme_helper.rb @@ -3,8 +3,10 @@ module ThemeHelper def theme_style_tags(theme) if theme == 'system' - stylesheet_pack_tag('mastodon-light', media: 'not all and (prefers-color-scheme: dark)', crossorigin: 'anonymous') + - stylesheet_pack_tag('default', media: '(prefers-color-scheme: dark)', crossorigin: 'anonymous') + ''.html_safe.tap do |tags| + tags << stylesheet_pack_tag('mastodon-light', media: 'not all and (prefers-color-scheme: dark)', crossorigin: 'anonymous') + tags << stylesheet_pack_tag('default', media: '(prefers-color-scheme: dark)', crossorigin: 'anonymous') + end else stylesheet_pack_tag theme, media: 'all', crossorigin: 'anonymous' end @@ -12,8 +14,10 @@ module ThemeHelper def theme_color_tags(theme) if theme == 'system' - tag.meta(name: 'theme-color', content: Themes::THEME_COLORS[:dark], media: '(prefers-color-scheme: dark)') + - tag.meta(name: 'theme-color', content: Themes::THEME_COLORS[:light], media: '(prefers-color-scheme: light)') + ''.html_safe.tap do |tags| + tags << tag.meta(name: 'theme-color', content: Themes::THEME_COLORS[:dark], media: '(prefers-color-scheme: dark)') + tags << tag.meta(name: 'theme-color', content: Themes::THEME_COLORS[:light], media: '(prefers-color-scheme: light)') + end else tag.meta name: 'theme-color', content: theme_color_for(theme) end From 0b97ec3f7b0922067c1047d621975e65bfe96ad7 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Mon, 15 Jul 2024 15:03:57 +0200 Subject: [PATCH 045/126] fix(deps): update dependency @babel/core to v7.24.9 (#31029) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- yarn.lock | 38 +++++++++++++++++++------------------- 1 file changed, 19 insertions(+), 19 deletions(-) diff --git a/yarn.lock b/yarn.lock index 988c6c79cf..01645ca93b 100644 --- a/yarn.lock +++ b/yarn.lock @@ -60,37 +60,37 @@ __metadata: linkType: hard "@babel/core@npm:^7.10.4, @babel/core@npm:^7.11.6, @babel/core@npm:^7.12.3, @babel/core@npm:^7.22.1, @babel/core@npm:^7.24.4": - version: 7.24.8 - resolution: "@babel/core@npm:7.24.8" + version: 7.24.9 + resolution: "@babel/core@npm:7.24.9" dependencies: "@ampproject/remapping": "npm:^2.2.0" "@babel/code-frame": "npm:^7.24.7" - "@babel/generator": "npm:^7.24.8" + "@babel/generator": "npm:^7.24.9" "@babel/helper-compilation-targets": "npm:^7.24.8" - "@babel/helper-module-transforms": "npm:^7.24.8" + "@babel/helper-module-transforms": "npm:^7.24.9" "@babel/helpers": "npm:^7.24.8" "@babel/parser": "npm:^7.24.8" "@babel/template": "npm:^7.24.7" "@babel/traverse": "npm:^7.24.8" - "@babel/types": "npm:^7.24.8" + "@babel/types": "npm:^7.24.9" convert-source-map: "npm:^2.0.0" debug: "npm:^4.1.0" gensync: "npm:^1.0.0-beta.2" json5: "npm:^2.2.3" semver: "npm:^6.3.1" - checksum: 10c0/5e21b40cc69746deda3fe3d6540351d9cb0d1ad5aea055b7c319db26071ff5789fd9580d1aa47b114f07631e8e2109f4e71696ca11d7c7e60d157767022c1bd2 + checksum: 10c0/e104ec6efbf099f55184933e9ab078eb5821c792ddfef3e9c6561986ec4ff103f5c11e3d7d6e5e8929e50e2c58db1cc80e5b6f14b530335b6622095ec4b4124c languageName: node linkType: hard -"@babel/generator@npm:^7.24.8, @babel/generator@npm:^7.7.2": - version: 7.24.8 - resolution: "@babel/generator@npm:7.24.8" +"@babel/generator@npm:^7.24.8, @babel/generator@npm:^7.24.9, @babel/generator@npm:^7.7.2": + version: 7.24.9 + resolution: "@babel/generator@npm:7.24.9" dependencies: - "@babel/types": "npm:^7.24.8" + "@babel/types": "npm:^7.24.9" "@jridgewell/gen-mapping": "npm:^0.3.5" "@jridgewell/trace-mapping": "npm:^0.3.25" jsesc: "npm:^2.5.1" - checksum: 10c0/e8a278e75a895f13a7b17dd79abe1e894fe82a5ed3abb127c33c14c66773d69993762521c094c6c364723f8f7375683b0d4a96097781175a29407baedf67b769 + checksum: 10c0/cd1f7edce7717462546c349e15289d1267a3ed627c6f6583fbf51e78eacacc6500ec2f0024f08f1cc7138989e575635b931acf4549f9e728017a22176a9ea6b6 languageName: node linkType: hard @@ -231,9 +231,9 @@ __metadata: languageName: node linkType: hard -"@babel/helper-module-transforms@npm:^7.24.7, @babel/helper-module-transforms@npm:^7.24.8": - version: 7.24.8 - resolution: "@babel/helper-module-transforms@npm:7.24.8" +"@babel/helper-module-transforms@npm:^7.24.7, @babel/helper-module-transforms@npm:^7.24.8, @babel/helper-module-transforms@npm:^7.24.9": + version: 7.24.9 + resolution: "@babel/helper-module-transforms@npm:7.24.9" dependencies: "@babel/helper-environment-visitor": "npm:^7.24.7" "@babel/helper-module-imports": "npm:^7.24.7" @@ -242,7 +242,7 @@ __metadata: "@babel/helper-validator-identifier": "npm:^7.24.7" peerDependencies: "@babel/core": ^7.0.0 - checksum: 10c0/b76496d5045af55be9de60e59e65e56a43033f01ccc746b26b7af911c358668c206b688ce70a23ab31ec04f9728f3a38e8d01073c85244115ab62f271a7fa3d1 + checksum: 10c0/e27bca43bc113731ee4f2b33a4c5bf9c7eebf4d64487b814c305cbd5feb272c29fcd3d79634ba03131ade171e5972bc7ede8dbc83ba0deb02f1e62d318c87770 languageName: node linkType: hard @@ -1540,14 +1540,14 @@ __metadata: languageName: node linkType: hard -"@babel/types@npm:^7.0.0, @babel/types@npm:^7.0.0-beta.49, @babel/types@npm:^7.12.11, @babel/types@npm:^7.12.6, @babel/types@npm:^7.20.7, @babel/types@npm:^7.24.7, @babel/types@npm:^7.24.8, @babel/types@npm:^7.3.3, @babel/types@npm:^7.4.4, @babel/types@npm:^7.8.3": - version: 7.24.8 - resolution: "@babel/types@npm:7.24.8" +"@babel/types@npm:^7.0.0, @babel/types@npm:^7.0.0-beta.49, @babel/types@npm:^7.12.11, @babel/types@npm:^7.12.6, @babel/types@npm:^7.20.7, @babel/types@npm:^7.24.7, @babel/types@npm:^7.24.8, @babel/types@npm:^7.24.9, @babel/types@npm:^7.3.3, @babel/types@npm:^7.4.4, @babel/types@npm:^7.8.3": + version: 7.24.9 + resolution: "@babel/types@npm:7.24.9" dependencies: "@babel/helper-string-parser": "npm:^7.24.8" "@babel/helper-validator-identifier": "npm:^7.24.7" to-fast-properties: "npm:^2.0.0" - checksum: 10c0/2d7bf561ae993e794cb052c5a81d3a6d1877da13e1e2eb2a59ae75a8fb1c965b618fb3e4abd42548f5f9a4587d3a149185a32d6c4c4ea82195da7dd86f2da0f1 + checksum: 10c0/4970b3481cab39c5c3fdb7c28c834df5c7049f3c7f43baeafe121bb05270ebf0da7c65b097abf314877f213baa591109c82204f30d66cdd46c22ece4a2f32415 languageName: node linkType: hard From 9d0bce40724eb77b7cc3917091b62e4ab159e29e Mon Sep 17 00:00:00 2001 From: David Roetzel Date: Mon, 15 Jul 2024 15:42:47 +0200 Subject: [PATCH 046/126] Move filtered notifications bar in scrollable area (#30996) Co-authored-by: Claire --- .../mastodon/features/notifications/index.jsx | 11 ++++++++--- app/javascript/styles/mastodon/components.scss | 3 +-- 2 files changed, 9 insertions(+), 5 deletions(-) diff --git a/app/javascript/mastodon/features/notifications/index.jsx b/app/javascript/mastodon/features/notifications/index.jsx index d45f517152..54883096ef 100644 --- a/app/javascript/mastodon/features/notifications/index.jsx +++ b/app/javascript/mastodon/features/notifications/index.jsx @@ -223,6 +223,13 @@ class Notifications extends PureComponent { let scrollContainer; + const prepend = ( + <> + {needsNotificationPermission && } + + + ); + if (signedIn) { scrollContainer = ( } + prepend={prepend} alwaysPrepend emptyMessage={emptyMessage} onLoadMore={this.handleLoadOlder} @@ -282,8 +289,6 @@ class Notifications extends PureComponent { {filterBarContainer} - - {scrollContainer} diff --git a/app/javascript/styles/mastodon/components.scss b/app/javascript/styles/mastodon/components.scss index da86a4caa7..e94ce2d8f4 100644 --- a/app/javascript/styles/mastodon/components.scss +++ b/app/javascript/styles/mastodon/components.scss @@ -10192,8 +10192,7 @@ noscript { .filtered-notifications-banner { display: flex; align-items: center; - border: 1px solid var(--background-border-color); - border-top: 0; + border-bottom: 1px solid var(--background-border-color); padding: 24px 32px; gap: 16px; color: $darker-text-color; From 70969ac64c4cf2811be9aa2f8510e3d831f2533c Mon Sep 17 00:00:00 2001 From: David Roetzel Date: Mon, 15 Jul 2024 15:42:47 +0200 Subject: [PATCH 047/126] [Glitch] Move filtered notifications bar in scrollable area Port 9d0bce40724eb77b7cc3917091b62e4ab159e29e to glitch-soc Co-authored-by: Claire Signed-off-by: Claire --- .../flavours/glitch/features/notifications/index.jsx | 11 ++++++++--- app/javascript/flavours/glitch/styles/components.scss | 3 +-- 2 files changed, 9 insertions(+), 5 deletions(-) diff --git a/app/javascript/flavours/glitch/features/notifications/index.jsx b/app/javascript/flavours/glitch/features/notifications/index.jsx index b4f1bf5dfe..bc32f9a7d2 100644 --- a/app/javascript/flavours/glitch/features/notifications/index.jsx +++ b/app/javascript/flavours/glitch/features/notifications/index.jsx @@ -258,6 +258,13 @@ class Notifications extends PureComponent { let scrollContainer; + const prepend = ( + <> + {needsNotificationPermission && } + + + ); + if (signedIn) { scrollContainer = ( } + prepend={prepend} alwaysPrepend emptyMessage={emptyMessage} onLoadMore={this.handleLoadOlder} @@ -356,8 +363,6 @@ class Notifications extends PureComponent { {filterBarContainer} - - {scrollContainer} diff --git a/app/javascript/flavours/glitch/styles/components.scss b/app/javascript/flavours/glitch/styles/components.scss index 533a564e99..06225b61e6 100644 --- a/app/javascript/flavours/glitch/styles/components.scss +++ b/app/javascript/flavours/glitch/styles/components.scss @@ -10746,8 +10746,7 @@ noscript { .filtered-notifications-banner { display: flex; align-items: center; - border: 1px solid var(--background-border-color); - border-top: 0; + border-bottom: 1px solid var(--background-border-color); padding: 24px 32px; gap: 16px; color: $darker-text-color; From 905921b2efaa7bda5acca1c19056a18186ec24ff Mon Sep 17 00:00:00 2001 From: Michael Stanclift Date: Tue, 16 Jul 2024 02:06:19 -0500 Subject: [PATCH 048/126] Add missing "Update Report" string in audit log (#31033) --- config/locales/en.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/config/locales/en.yml b/config/locales/en.yml index 20df80c272..0e3d209ff3 100644 --- a/config/locales/en.yml +++ b/config/locales/en.yml @@ -226,6 +226,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: From c3a2f9d99309bbe2754be9ea3f5257c434ff34b0 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Tue, 16 Jul 2024 14:14:25 +0200 Subject: [PATCH 049/126] chore(deps): update dependency json-schema to v4.3.1 (#31012) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- Gemfile.lock | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Gemfile.lock b/Gemfile.lock index 98a3571731..935b28215c 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -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) From c27d194eb27aeedb16e17dfb2a8f2be7c0636851 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Tue, 16 Jul 2024 15:20:34 +0200 Subject: [PATCH 050/126] fix(deps): update dependency pino to v9.3.1 (#31032) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- yarn.lock | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/yarn.lock b/yarn.lock index 01645ca93b..c5d0480061 100644 --- a/yarn.lock +++ b/yarn.lock @@ -13196,8 +13196,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" @@ -13212,7 +13212,7 @@ __metadata: thread-stream: "npm:^3.0.0" bin: pino: bin.js - checksum: 10c0/5fbd226ff7dab0961232b5aa5eca0530cdc5bb29f6bf17d929e42239293b1a587a26cc311db6abc1090c9dd57e8f7b031eae341b41d00d4a642b4f1736474c80 + checksum: 10c0/ab1e81b3e5a91852136d80a592939883eeb81442e5d3a2c070bdbdeb47c5aaa297ead246530b10eb6d5ff59445f4645d1333d342f255d9f002f73aea843e74ee languageName: node linkType: hard From fa54b6121691dfb5d64a42aa6bf07b4d67aa504f Mon Sep 17 00:00:00 2001 From: Adam Niedzielski Date: Tue, 16 Jul 2024 15:21:16 +0200 Subject: [PATCH 051/126] Handle missing links in Webfinger response (#31030) --- app/lib/webfinger.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/lib/webfinger.rb b/app/lib/webfinger.rb index ae8a3b1eae..aeafe19702 100644 --- a/app/lib/webfinger.rb +++ b/app/lib/webfinger.rb @@ -26,7 +26,7 @@ class Webfinger private def links - @links ||= @json['links'].index_by { |link| link['rel'] } + @links ||= @json.fetch('links', []).index_by { |link| link['rel'] } end def validate_response! From aa88aca0ad89f24fead6a1c6dbfad9def94bd47e Mon Sep 17 00:00:00 2001 From: Emelia Smith Date: Tue, 16 Jul 2024 15:23:08 +0200 Subject: [PATCH 052/126] Add optional OAuth application to reports (#30539) --- app/controllers/api/v1/reports_controller.rb | 2 +- app/models/report.rb | 2 ++ app/services/report_service.rb | 4 +++- app/views/admin/reports/_header_details.html.haml | 6 ++++++ config/locales/en.yml | 1 + .../20240713171841_add_application_to_reports.rb | 8 ++++++++ ...13171909_validate_add_application_to_reports.rb | 7 +++++++ db/schema.rb | 4 +++- spec/lib/activitypub/activity/flag_spec.rb | 1 + spec/requests/api/v1/reports_spec.rb | 1 + spec/services/report_service_spec.rb | 14 ++++++++++++++ 11 files changed, 47 insertions(+), 3 deletions(-) create mode 100644 db/migrate/20240713171841_add_application_to_reports.rb create mode 100644 db/migrate/20240713171909_validate_add_application_to_reports.rb diff --git a/app/controllers/api/v1/reports_controller.rb b/app/controllers/api/v1/reports_controller.rb index 300c9faa3f..72f358bb5b 100644 --- a/app/controllers/api/v1/reports_controller.rb +++ b/app/controllers/api/v1/reports_controller.rb @@ -10,7 +10,7 @@ class Api::V1::ReportsController < Api::BaseController @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/models/report.rb b/app/models/report.rb index 3df5a20e18..17c1503436 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/services/report_service.rb b/app/services/report_service.rb index dea6df7b0a..c95e216c79 100644 --- a/app/services/report_service.rb +++ b/app/services/report_service.rb @@ -10,6 +10,7 @@ class ReportService < BaseService @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 @@ class ReportService < BaseService uri: @options[:uri], forwarded: forward_to_origin?, category: @category, - rule_ids: @rule_ids + rule_ids: @rule_ids, + application: @application ) end diff --git a/app/views/admin/reports/_header_details.html.haml b/app/views/admin/reports/_header_details.html.haml index 45790b9cd5..434231f733 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/config/locales/en.yml b/config/locales/en.yml index 0e3d209ff3..cccb172163 100644 --- a/config/locales/en.yml +++ b/config/locales/en.yml @@ -639,6 +639,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/db/migrate/20240713171841_add_application_to_reports.rb b/db/migrate/20240713171841_add_application_to_reports.rb new file mode 100644 index 0000000000..42ba14e9b2 --- /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 0000000000..34ae690a39 --- /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 87c49d7415..66da12f713 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" @@ -929,6 +929,7 @@ ActiveRecord::Schema[7.1].define(version: 2024_07_12_064044) do 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)" @@ -1361,6 +1362,7 @@ ActiveRecord::Schema[7.1].define(version: 2024_07_12_064044) do 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_statuses", "accounts", on_delete: :cascade add_foreign_key "session_activations", "oauth_access_tokens", column: "access_token_id", name: "fk_957e5bda89", on_delete: :cascade add_foreign_key "session_activations", "users", name: "fk_e5fda67334", on_delete: :cascade diff --git a/spec/lib/activitypub/activity/flag_spec.rb b/spec/lib/activitypub/activity/flag_spec.rb index 426cd97df9..be1bd42a14 100644 --- a/spec/lib/activitypub/activity/flag_spec.rb +++ b/spec/lib/activitypub/activity/flag_spec.rb @@ -36,6 +36,7 @@ RSpec.describe ActivityPub::Activity::Flag do 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/requests/api/v1/reports_spec.rb b/spec/requests/api/v1/reports_spec.rb index 491c6263d3..a72d9bbcd8 100644 --- a/spec/requests/api/v1/reports_spec.rb +++ b/spec/requests/api/v1/reports_spec.rb @@ -47,6 +47,7 @@ RSpec.describe 'Reports' do 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/report_service_spec.rb b/spec/services/report_service_spec.rb index bf1f937191..6518c5c27a 100644 --- a/spec/services/report_service_spec.rb +++ b/spec/services/report_service_spec.rb @@ -23,6 +23,11 @@ RSpec.describe ReportService do 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 @@ RSpec.describe ReportService do 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]) } From a609940ec9a370a18789ad87532a098fe6e564c9 Mon Sep 17 00:00:00 2001 From: Adam Niedzielski Date: Tue, 16 Jul 2024 15:23:26 +0200 Subject: [PATCH 053/126] Fix test description in hashtag_bar (#30827) --- app/javascript/mastodon/components/__tests__/hashtag_bar.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/javascript/mastodon/components/__tests__/hashtag_bar.tsx b/app/javascript/mastodon/components/__tests__/hashtag_bar.tsx index b7225fc92e..f86c1a2a6b 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'], From 66430cb25c824cfad0394216d8e7a523533bcf4b Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Tue, 16 Jul 2024 17:24:56 +0200 Subject: [PATCH 054/126] New Crowdin Translations (automated) (#31038) Co-authored-by: GitHub Actions --- app/javascript/mastodon/locales/cy.json | 29 ++++++++-------- app/javascript/mastodon/locales/gl.json | 4 +-- app/javascript/mastodon/locales/kab.json | 2 +- app/javascript/mastodon/locales/zh-TW.json | 10 +++--- config/locales/cy.yml | 9 ++--- config/locales/devise.cy.yml | 2 +- config/locales/devise.zh-TW.yml | 4 +-- config/locales/doorkeeper.cy.yml | 8 +++-- config/locales/simple_form.ca.yml | 2 ++ config/locales/simple_form.cy.yml | 2 ++ config/locales/simple_form.da.yml | 2 ++ config/locales/simple_form.de.yml | 2 ++ config/locales/simple_form.eo.yml | 1 + config/locales/simple_form.es-AR.yml | 2 ++ config/locales/simple_form.es-MX.yml | 2 ++ config/locales/simple_form.es.yml | 2 ++ config/locales/simple_form.fi.yml | 2 ++ config/locales/simple_form.fo.yml | 2 ++ config/locales/simple_form.gl.yml | 2 ++ config/locales/simple_form.he.yml | 2 ++ config/locales/simple_form.hu.yml | 3 ++ config/locales/simple_form.is.yml | 2 ++ config/locales/simple_form.it.yml | 2 ++ config/locales/simple_form.ko.yml | 2 ++ config/locales/simple_form.lt.yml | 3 ++ config/locales/simple_form.nl.yml | 2 ++ config/locales/simple_form.pl.yml | 2 ++ config/locales/simple_form.pt-PT.yml | 2 ++ config/locales/simple_form.sl.yml | 2 ++ config/locales/simple_form.sq.yml | 2 ++ config/locales/simple_form.sr-Latn.yml | 2 ++ config/locales/simple_form.sr.yml | 2 ++ config/locales/simple_form.sv.yml | 2 ++ config/locales/simple_form.tr.yml | 2 ++ config/locales/simple_form.uk.yml | 2 ++ config/locales/simple_form.zh-CN.yml | 2 ++ config/locales/simple_form.zh-TW.yml | 18 +++++----- config/locales/zh-TW.yml | 40 +++++++++++----------- 38 files changed, 123 insertions(+), 60 deletions(-) diff --git a/app/javascript/mastodon/locales/cy.json b/app/javascript/mastodon/locales/cy.json index 1c7e61832c..9a3fab6155 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", @@ -484,9 +485,9 @@ "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 +804,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/gl.json b/app/javascript/mastodon/locales/gl.json index 03287c7e52..c1e0f97f80 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", diff --git a/app/javascript/mastodon/locales/kab.json b/app/javascript/mastodon/locales/kab.json index 868edbc8c0..a5c3280712 100644 --- a/app/javascript/mastodon/locales/kab.json +++ b/app/javascript/mastodon/locales/kab.json @@ -580,7 +580,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}", diff --git a/app/javascript/mastodon/locales/zh-TW.json b/app/javascript/mastodon/locales/zh-TW.json index 04469a971d..b9a5fc0714 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", @@ -552,7 +552,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": "您隨時可以稍候於設定中完成此操作,將有更多自訂選項可使用。", @@ -797,7 +797,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/config/locales/cy.yml b/config/locales/cy.yml index 35ed5ade8a..cd48b3e3b0 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/devise.cy.yml b/config/locales/devise.cy.yml index 523ae70b04..b41e12f85d 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.zh-TW.yml b/config/locales/devise.zh-TW.yml index 7ead831e4f..3e3af9f323 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.cy.yml b/config/locales/doorkeeper.cy.yml index e79aa0359f..e023bc0603 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/simple_form.ca.yml b/config/locales/simple_form.ca.yml index 4bb906abdb..2e0199d7fd 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 5e8fd85293..cd5bc1add7 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 73a32cf2fd..9e949d1683 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 5711d2a12a..332d951395 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.eo.yml b/config/locales/simple_form.eo.yml index 40535bf96b..021be93b5d 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 1d1ac87689..71d9726b07 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 19a1c9d0c0..730e9b265b 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 cc71e19266..f2d91349ad 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 214308ba5c..de099a21be 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 8f0b51719f..b334d4f034 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.gl.yml b/config/locales/simple_form.gl.yml index 0653d76204..57bf31b42d 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 1331d2f62b..f79ddb9b34 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 6ccca2bc84..518a82ec16 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 cc267db8d5..9e28ef9be6 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 540812faa9..eddc86b4e1 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.ko.yml b/config/locales/simple_form.ko.yml index 1107e4cba5..b94b4b3d40 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.lt.yml b/config/locales/simple_form.lt.yml index feec37ae00..b31803409b 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 5110e1e6d0..5633193406 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.pl.yml b/config/locales/simple_form.pl.yml index b8de10de26..39e1814195 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 f993687b91..ef7dfd00a8 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 14551774fe..a937f17206 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 6fedf31572..4236d7dce2 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 22c07aa7c6..40b710b078 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 10c1796637..c0a9ac2d89 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 11d142a2bd..2281e4b4ab 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 b1e90122ec..f098bfd3ca 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 332f2c91dc..2f494534ea 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.zh-CN.yml b/config/locales/simple_form.zh-CN.yml index bbee8b6706..ab440e04f4 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 7c460a25f5..15ccaf8a17 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/zh-TW.yml b/config/locales/zh-TW.yml index 1317d5f707..3a548c2265 100644 --- a/config/locales/zh-TW.yml +++ b/config/locales/zh-TW.yml @@ -227,7 +227,7 @@ zh-TW: 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 +264,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 +383,7 @@ zh-TW: confirm: 停權 permanent_action: 撤銷停權將不會回復任何資料或跟隨關係 preamble_html: 您將要停權 %{domain} 及其子網域。 - remove_all_data: 此操作將從您伺服器移除所有來自此網域帳號之內容、媒體、個人檔案資料。 + remove_all_data: 此操作將自您伺服器移除所有來自此網域帳號之內容、媒體、個人檔案資料。 stop_communication: 您伺服器將停止與這些伺服器交流。 title: 確認對 %{domain} 網域之封鎖 undo_relationships: 此操作將撤銷任何您伺服器與此伺服器帳號間之跟隨關係。 @@ -555,11 +555,11 @@ zh-TW: relays: add_new: 新增中繼站 delete: 刪除 - description_html: "聯邦中繼站 是種中繼伺服器,會於訂閱並推送至此中繼站的伺服器之間交換大量的公開嘟文。中繼站也能協助小型或中型伺服器從聯邦宇宙中探索內容,而無須本地使用者手動跟隨遠端伺服器的其他使用者。" + description_html: "聯邦中繼站 是種中繼伺服器,會於訂閱並推送至此中繼站的伺服器之間交換大量的公開嘟文。中繼站也能協助小型或中型伺服器自聯邦宇宙中探索內容,而無須本地使用者手動跟隨遠端伺服器的其他使用者。" disable: 停用 disabled: 停用 enable: 啟用 - enable_hint: 啟用後,您的伺服器將訂閱該中繼的所有公開文章,並將會此伺服器的公開文章發送給它。 + enable_hint: 啟用後,您的伺服器將訂閱該中繼的所有公開文章,並將此伺服器的公開文章向它發送。 enabled: 已啟用 inbox_url: 中繼 URL pending: 等待中繼站審核 @@ -648,7 +648,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 +671,7 @@ zh-TW: description_html: 透過使用者角色,您可以自訂您的使用者可以存取 Mastodon 的哪些功能與區域。 edit: 編輯「%{name}」角色 everyone: 預設權限 - everyone_full_description_html: 這是會影響所有使用者基本角色,即使是那些沒有被分配角色的使用者也一樣。其他所有的角色都從它繼承權限。 + everyone_full_description_html: 這是會影響所有使用者基本角色,即使是那些沒有被分配角色的使用者也一樣。其他所有的角色都自它繼承權限。 permissions_count: other: "%{count} 個權限" privileges: @@ -757,8 +757,8 @@ zh-TW: title: 探索 trends: 熱門趨勢 domain_blocks: - all: 給任何人 - disabled: 給沒有人 + all: 至任何人 + disabled: 至沒有人 users: 套用至所有登入的本站使用者 registrations: moderation_recommandation: 對所有人開放註冊之前,請確保您有人手充足且反應靈敏的管理員團隊! @@ -797,7 +797,7 @@ zh-TW: back_to_account: 返回帳號資訊頁面 back_to_report: 回到檢舉報告頁面 batch: - remove_from_report: 從檢舉報告中移除 + remove_from_report: 自檢舉報告中移除 report: 檢舉報告 deleted: 已刪除 favourites: 最愛 @@ -1055,7 +1055,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 +1138,7 @@ zh-TW: x_seconds: "%{count}秒" deletes: challenge_not_passed: 您所輸入的資料不正確 - confirm_password: 輸入您現在的密碼以驗證身份 + confirm_password: 輸入您目前的密碼以驗證身份 confirm_username: 請輸入您的使用者名稱以作確認 proceed: 刪除帳號 success_msg: 您的帳號已經成功刪除 @@ -1170,7 +1170,7 @@ zh-TW: recipient: 此致 reject_appeal: 駁回申訴 status: '嘟文編號 #%{id}' - status_removed: 嘟文已從系統中移除 + status_removed: 嘟文已自系統中移除 title: "%{action} 來自 %{date}" title_actions: delete_statuses: 嘟文移除 @@ -1238,10 +1238,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 +1262,7 @@ zh-TW: statuses: back_to_filter: 回到過濾器 batch: - remove: 從過濾器中移除 + remove: 自過濾器中移除 index: hint: 此過濾器會套用至所選之各別嘟文,不管它們有無符合其他條件。您可以從網頁介面中將更多嘟文加入至此過濾器。 title: 已過濾之嘟文 @@ -1419,7 +1419,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 +1552,7 @@ zh-TW: mutual: 跟隨彼此 primary: 主要 relationship: 關係 - remove_selected_domains: 從所選取網域中移除所有跟隨者 + remove_selected_domains: 自所選取網域中移除所有跟隨者 remove_selected_followers: 移除選取的跟隨者 remove_selected_follows: 取消跟隨選取的使用者 status: 帳號狀態 @@ -1599,7 +1599,7 @@ zh-TW: current_session: 目前的 session date: 日期 description: "%{platform} 上的 %{browser}" - explanation: 這些是現在正登入於您 Mastodon 帳號的瀏覽器。 + explanation: 這些是目前正登入於您 Mastodon 帳號的瀏覽器。 ip: IP 位址 platforms: adobe_air: Adobe Air From 00c110ac7ba0dd82840f1ff32113ed0e616c3470 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Wed, 17 Jul 2024 09:23:07 +0200 Subject: [PATCH 055/126] New Crowdin Translations (automated) (#31047) Co-authored-by: GitHub Actions --- app/javascript/mastodon/locales/ga.json | 294 ++++++++++++++++++++++++ app/javascript/mastodon/locales/lt.json | 4 +- config/locales/activerecord.ga.yml | 33 +++ config/locales/ca.yml | 2 + config/locales/da.yml | 1 + config/locales/de.yml | 2 + config/locales/devise.ga.yml | 89 +++++++ config/locales/doorkeeper.ga.yml | 2 + config/locales/en-GB.yml | 1 + config/locales/es-AR.yml | 1 + config/locales/fi.yml | 1 + config/locales/fo.yml | 2 + config/locales/he.yml | 1 + config/locales/hu.yml | 2 + config/locales/it.yml | 2 + config/locales/ko.yml | 1 + config/locales/lt.yml | 19 ++ config/locales/nl.yml | 1 + config/locales/nn.yml | 2 + config/locales/pt-PT.yml | 2 + config/locales/simple_form.en-GB.yml | 3 + config/locales/simple_form.nn.yml | 3 + config/locales/simple_form.vi.yml | 2 + config/locales/sl.yml | 1 + config/locales/sq.yml | 1 + config/locales/sv.yml | 1 + config/locales/tr.yml | 1 + config/locales/uk.yml | 1 + config/locales/vi.yml | 2 + config/locales/zh-CN.yml | 2 + config/locales/zh-TW.yml | 2 + 31 files changed, 479 insertions(+), 2 deletions(-) diff --git a/app/javascript/mastodon/locales/ga.json b/app/javascript/mastodon/locales/ga.json index edf7618148..468c7a03a1 100644 --- a/app/javascript/mastodon/locales/ga.json +++ b/app/javascript/mastodon/locales/ga.json @@ -17,9 +17,12 @@ "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", @@ -29,9 +32,12 @@ "account.featured_tags.last_status_never": "Níl postáil ar bith ann", "account.featured_tags.title": "Haischlib {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.following_counter": "{count, plural, one {{counter} ag leanúint} other {{counter} ag leanúint}}", "account.follows.empty": "Ní leanann an t-úsáideoir seo duine ar bith fós.", "account.go_to_profile": "Téigh go dtí próifíl", "account.hide_reblogs": "Folaigh moltaí ó @{name}", @@ -44,7 +50,11 @@ "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.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,6 +89,14 @@ "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í.", @@ -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í", @@ -117,6 +144,9 @@ "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.poll.type": "Stíl", + "compose_form.publish": "Postáil", "compose_form.publish_form": "Foilsigh\n", + "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_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": "These hashtags are gaining traction among people on this and other servers of the decentralized network right now.", + "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,33 +247,48 @@ "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.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", @@ -215,14 +297,31 @@ "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 {níl éinne} 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_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": "Include additional tags in this column", + "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}", @@ -262,6 +381,8 @@ "keyboard_shortcuts.direct": "to open direct messages column", "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", @@ -286,15 +407,21 @@ "keyboard_shortcuts.unfocus": "to un-focus compose 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,20 +430,38 @@ "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.", "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", @@ -326,17 +471,41 @@ "not_signed_in_indicator.not_signed_in": "You need to sign in to access this resource.", "notification.admin.report": "Tuairiscigh {name} {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.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.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 +516,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.action.back": "Tóg ar ais mé", + "onboarding.actions.back": "Tóg ar ais mé", "onboarding.actions.go_to_explore": "See what's trending", "onboarding.actions.go_to_home": "Go to your home feed", + "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": "You curate your own home feed. The more people you follow, the more active and interesting it will be. These profiles may be a good starting point—you can always unfollow them later!", "onboarding.follows.title": "Popular on Mastodon", + "onboarding.profile.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": "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": "Tá sé déanta agat!", "onboarding.steps.follow_people.body": "You curate your own feed. Lets fill it with interesting people.", "onboarding.steps.follow_people.title": "Follow {count, plural, one {one person} other {# people}}", "onboarding.steps.publish_status.body": "Say hello to the world.", + "onboarding.steps.publish_status.title": "Déan do chéad phostáil", "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.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", @@ -382,10 +595,21 @@ "poll_button.add_poll": "Cruthaigh suirbhé", "poll_button.remove_poll": "Bain suirbhé", "privacy.change": "Adjust status privacy", + "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,47 +621,90 @@ "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.other": "Eile", "report_notification.categories.spam": "Turscar", "report_notification.categories.violation": "Sárú rialach", "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_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": "Uile", "search_results.hashtags": "Haischlibeanna", + "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", + "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": "Open this status in the moderation interface", "status.block": "Bac @{name}", "status.bookmark": "Leabharmharcanna", @@ -445,15 +712,23 @@ "status.cannot_reblog": "Ní féidir an phostáil seo a mholadh", "status.copy": "Copy link to status", "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", @@ -466,8 +741,11 @@ "status.reblog": "Mol", "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}", @@ -482,38 +760,54 @@ "status.title.with_attachments": "{user} posted {attachmentCount, plural, one {an attachment} other {# attachments}}", "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_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": "Describe for people with hearing loss", "upload_form.description": "Describe for the visually impaired", "upload_form.edit": "Cuir in eagar", + "upload_form.thumbnail": "Athraigh mionsamhail", "upload_form.video_description": "Describe for people with hearing loss or visual impairment", "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/lt.json b/app/javascript/mastodon/locales/lt.json index bb69b73399..258e8ce08e 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", diff --git a/config/locales/activerecord.ga.yml b/config/locales/activerecord.ga.yml index 236cc479e1..1b61edb2e2 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/ca.yml b/config/locales/ca.yml index f892df02c1..4d0e2ab389 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/da.yml b/config/locales/da.yml index fc7373cc94..75da9a0b36 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 82ed9d8178..81b7cd172d 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.ga.yml b/config/locales/devise.ga.yml index 6e6bd0a013..e083896f37 100644 --- a/config/locales/devise.ga.yml +++ b/config/locales/devise.ga.yml @@ -11,19 +11,108 @@ 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: Your password has been changed successfully. + 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 diff --git a/config/locales/doorkeeper.ga.yml b/config/locales/doorkeeper.ga.yml index a263a6b15d..9ac4740691 100644 --- a/config/locales/doorkeeper.ga.yml +++ b/config/locales/doorkeeper.ga.yml @@ -40,6 +40,7 @@ ga: accounts: Cuntais bookmarks: Leabharmharcanna conversations: Comhráite + favourites: Ceanáin filters: Scagairí follows: Cuntais leanta lists: Liostaí @@ -47,5 +48,6 @@ ga: search: Cuardaigh statuses: Postálacha scopes: + read:favourites: féach ar do cheanáin write:filters: cruthaigh scagairí write:lists: cruthaigh liostaí diff --git a/config/locales/en-GB.yml b/config/locales/en-GB.yml index 928823b995..a45ba290b7 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: diff --git a/config/locales/es-AR.yml b/config/locales/es-AR.yml index fda1566e22..8c55551ce0 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: diff --git a/config/locales/fi.yml b/config/locales/fi.yml index be87258daf..2d10250f68 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: diff --git a/config/locales/fo.yml b/config/locales/fo.yml index 945a2216a3..6a5401ced4 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/he.yml b/config/locales/he.yml index 3ba823f99b..ecafbec960 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: diff --git a/config/locales/hu.yml b/config/locales/hu.yml index 19076910e2..5def03d902 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/it.yml b/config/locales/it.yml index 1e17c5cbd0..68e1608d9c 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/ko.yml b/config/locales/ko.yml index f7feb73ba0..632bd7c097 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 e731deedc8..004f5b4d04 100644 --- a/config/locales/lt.yml +++ b/config/locales/lt.yml @@ -542,6 +542,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 +665,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 +923,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 +1064,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 +1126,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 +1213,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 baab2cb587..3b88dd9528 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: diff --git a/config/locales/nn.yml b/config/locales/nn.yml index 2da30e6627..ec77a2edf8 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/pt-PT.yml b/config/locales/pt-PT.yml index 839ae2184e..1df423bb7d 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.en-GB.yml b/config/locales/simple_form.en-GB.yml index eaf0501a27..c1f2a015e9 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.nn.yml b/config/locales/simple_form.nn.yml index a200e1206e..c9075a89c2 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.vi.yml b/config/locales/simple_form.vi.yml index 9006156db1..c45da47137 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/sl.yml b/config/locales/sl.yml index 6087b1a174..344368a08a 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: diff --git a/config/locales/sq.yml b/config/locales/sq.yml index 5439f08a04..c4bed80cc7 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 91b1720b55..de2664f8b5 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 c690d22580..6b28e17441 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: diff --git a/config/locales/uk.yml b/config/locales/uk.yml index 9994cd9d0d..69f5ca665c 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: diff --git a/config/locales/vi.yml b/config/locales/vi.yml index 467356d65a..48e026d377 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 794b8344c1..d2d64152fa 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 3a548c2265..375c79048a 100644 --- a/config/locales/zh-TW.yml +++ b/config/locales/zh-TW.yml @@ -223,6 +223,7 @@ zh-TW: update_custom_emoji: 更新自訂 emoji 表情符號 update_domain_block: 更新網域封鎖 update_ip_block: 更新 IP 規則 + update_report: 更新檢舉報告 update_status: 更新狀態 update_user_role: 更新角色 actions: @@ -626,6 +627,7 @@ zh-TW: report: '檢舉 #%{id}' reported_account: 被檢舉使用者 reported_by: 檢舉人 + reported_with_application: 透過應用程式檢舉 resolved: 已解決 resolved_msg: 檢舉報告已處理完成! skip_to_actions: 跳過行動 From 81877e79505f387284c7a9de88f631eab758a319 Mon Sep 17 00:00:00 2001 From: Matt Jankowski Date: Wed, 17 Jul 2024 03:24:14 -0400 Subject: [PATCH 056/126] Reduce extra round trips in `AP::FetchRemoteStatusService` spec (#31045) --- .../fetch_remote_status_service_spec.rb | 26 ++++++++----------- 1 file changed, 11 insertions(+), 15 deletions(-) diff --git a/spec/services/activitypub/fetch_remote_status_service_spec.rb b/spec/services/activitypub/fetch_remote_status_service_spec.rb index c3adb9c470..635fcb7976 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 @@ RSpec.describe ActivityPub::FetchRemoteStatusService do 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 @@ RSpec.describe ActivityPub::FetchRemoteStatusService do 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 @@ RSpec.describe ActivityPub::FetchRemoteStatusService do 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 @@ RSpec.describe ActivityPub::FetchRemoteStatusService do 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 @@ RSpec.describe ActivityPub::FetchRemoteStatusService do 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 From f5e90f3de3efa52c9f8ea72ffdbf091d5032cc4b Mon Sep 17 00:00:00 2001 From: Matt Jankowski Date: Wed, 17 Jul 2024 03:33:08 -0400 Subject: [PATCH 057/126] Reduce extra round trips in `AP::SynchronizeFollowersService` spec (#31044) --- .../synchronize_followers_service_spec.rb | 31 +++++++------------ 1 file changed, 12 insertions(+), 19 deletions(-) diff --git a/spec/services/activitypub/synchronize_followers_service_spec.rb b/spec/services/activitypub/synchronize_followers_service_spec.rb index 648f9a3321..974368b7d7 100644 --- a/spec/services/activitypub/synchronize_followers_service_spec.rb +++ b/spec/services/activitypub/synchronize_followers_service_spec.rb @@ -13,11 +13,9 @@ RSpec.describe ActivityPub::SynchronizeFollowersService do 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 @@ RSpec.describe ActivityPub::SynchronizeFollowersService do 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 From 76c2c5c748ba47c2b7bc13570cd4301516290d90 Mon Sep 17 00:00:00 2001 From: Matt Jankowski Date: Wed, 17 Jul 2024 04:09:34 -0400 Subject: [PATCH 058/126] Reduce extra round trips in `activitypub` controller specs (#31041) --- .../collections_controller_spec.rb | 32 ++---- ...lowers_synchronizations_controller_spec.rb | 27 ++--- .../activitypub/outboxes_controller_spec.rb | 107 +++++------------- .../activitypub/replies_controller_spec.rb | 16 +-- 4 files changed, 56 insertions(+), 126 deletions(-) diff --git a/spec/controllers/activitypub/collections_controller_spec.rb b/spec/controllers/activitypub/collections_controller_spec.rb index 11ef03c842..a5718fbd7d 100644 --- a/spec/controllers/activitypub/collections_controller_spec.rb +++ b/spec/controllers/activitypub/collections_controller_spec.rb @@ -25,14 +25,12 @@ RSpec.describe ActivityPub::CollectionsController do context 'without signature' do let(:remote_account) { nil } - 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' - it 'returns orderedItems with correct items' do + 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' + expect(body_as_json[:orderedItems]) .to be_an(Array) .and have_attributes(size: 3) @@ -66,14 +64,12 @@ RSpec.describe ActivityPub::CollectionsController do let(:remote_account) { Fabricate(:account, domain: 'example.com') } context 'when getting a featured resource' 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' - it 'returns orderedItems with expected items' do + 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' + expect(body_as_json[:orderedItems]) .to be_an(Array) .and have_attributes(size: 3) @@ -92,16 +88,14 @@ RSpec.describe ActivityPub::CollectionsController do 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 @@ RSpec.describe ActivityPub::CollectionsController do 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 b50c7b9cdc..c030078d43 100644 --- a/spec/controllers/activitypub/followers_synchronizations_controller_spec.rb +++ b/spec/controllers/activitypub/followers_synchronizations_controller_spec.rb @@ -37,25 +37,18 @@ RSpec.describe ActivityPub::FollowersSynchronizationsController do 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.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(response.media_type).to eq 'application/activity+json' + + 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 ead231f29f..3c8e8e399f 100644 --- a/spec/controllers/activitypub/outboxes_controller_spec.rb +++ b/spec/controllers/activitypub/outboxes_controller_spec.rb @@ -25,22 +25,13 @@ RSpec.describe ActivityPub::OutboxesController do 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 @@ RSpec.describe ActivityPub::OutboxesController do context 'with page requested' do let(:page) { 'true' } - it 'returns http success' do + it_behaves_like 'cacheable response' + + it 'returns http success and correct media type and vary header 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 + 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 @@ RSpec.describe ActivityPub::OutboxesController do 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 @@ RSpec.describe ActivityPub::OutboxesController do 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 @@ RSpec.describe ActivityPub::OutboxesController do 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 @@ RSpec.describe ActivityPub::OutboxesController do 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 db7f60d3f8..c556e07270 100644 --- a/spec/controllers/activitypub/replies_controller_spec.rb +++ b/spec/controllers/activitypub/replies_controller_spec.rb @@ -66,19 +66,15 @@ RSpec.describe ActivityPub::RepliesController do context 'when status is public' do let(:parent_visibility) { :public } - let(:json) { body_as_json } - let(:page_json) { json[:first] } - - 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 + let(:page_json) { body_as_json[:first] } it_behaves_like 'cacheable response' + 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 + context 'without only_other_accounts' do it "returns items with thread author's replies" do expect(page_json).to be_a Hash From 4957771a8ae36e46cba4b8c4a6278f0e95e5850a Mon Sep 17 00:00:00 2001 From: Claire Date: Wed, 17 Jul 2024 11:18:25 +0200 Subject: [PATCH 059/126] Update rexml to version 3.3.2 (#31048) --- Gemfile.lock | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Gemfile.lock b/Gemfile.lock index 935b28215c..04505a7cc4 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -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) From aa4d8987a00fe82490fb949b82d3baa33d0acd49 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Wed, 17 Jul 2024 12:42:54 +0200 Subject: [PATCH 060/126] chore(deps): update dependency faker to v3.4.2 (#31046) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- Gemfile.lock | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Gemfile.lock b/Gemfile.lock index 04505a7cc4..c3e3adbbf3 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -231,7 +231,7 @@ GEM 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) From c5f8256801c8c840becf0ea7201bb891adf3c35a Mon Sep 17 00:00:00 2001 From: Matt Jankowski Date: Thu, 18 Jul 2024 03:45:59 -0400 Subject: [PATCH 061/126] Reduce extra factories in `FanOutOnWriteService` spec (#31053) --- .../services/fan_out_on_write_service_spec.rb | 85 ++++++++----------- 1 file changed, 34 insertions(+), 51 deletions(-) diff --git a/spec/services/fan_out_on_write_service_spec.rb b/spec/services/fan_out_on_write_service_spec.rb index 82cdffb8cf..c6dd020cdf 100644 --- a/spec/services/fan_out_on_write_service_spec.rb +++ b/spec/services/fan_out_on_write_service_spec.rb @@ -34,21 +34,14 @@ RSpec.describe FanOutOnWriteService do context 'when status is public' do let(:visibility) { 'public' } - it 'is added to the home feed of its author' do - expect(home_feed_of(alice)).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)) - 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 broadcast to the hashtag stream' 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' 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) @@ -58,60 +51,41 @@ RSpec.describe FanOutOnWriteService do context 'when status is limited' do let(:visibility) { 'limited' } - it 'is added to the home feed of its author' do - expect(home_feed_of(alice)).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)) - 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' do - expect(home_feed_of(tom)).to_not include status.id - end - - it 'is not broadcast publicly' 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 end context 'when status is private' do let(:visibility) { 'private' } - it 'is added to the home feed of its author' do - expect(home_feed_of(alice)).to include status.id - end + it 'adds status to home feed of author and 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)) - 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 not broadcast publicly' 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 end context 'when status is direct' do let(:visibility) { 'direct' } - it 'is added to the home feed of its author' 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)) - 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' do - expect(home_feed_of(tom)).to_not include status.id - end - - it 'is not broadcast publicly' 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 'when handling status updates' do @@ -131,4 +105,13 @@ RSpec.describe FanOutOnWriteService do end 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 From 2616fde9e6edfbdbf31efad5d1818ad950ab4d4c Mon Sep 17 00:00:00 2001 From: Matt Jankowski Date: Thu, 18 Jul 2024 03:49:44 -0400 Subject: [PATCH 062/126] Use change-requiring records in admin/reports controller spec (#31052) --- spec/controllers/admin/reports_controller_spec.rb | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/spec/controllers/admin/reports_controller_spec.rb b/spec/controllers/admin/reports_controller_spec.rb index 02760154fb..5849163b5f 100644 --- a/spec/controllers/admin/reports_controller_spec.rb +++ b/spec/controllers/admin/reports_controller_spec.rb @@ -64,7 +64,7 @@ describe Admin::ReportsController do 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 Admin::ReportsController do 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)) From 64c7ffdc656135b7986ce92d645f5355f638cfe4 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Thu, 18 Jul 2024 09:53:36 +0200 Subject: [PATCH 063/126] chore(deps): update dependency ruby-vips to v2.2.2 (#31050) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- Gemfile.lock | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/Gemfile.lock b/Gemfile.lock index c3e3adbbf3..c9781a4050 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -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) From 47ea83d2469e461b82e6d837ea83ad561128fe7a Mon Sep 17 00:00:00 2001 From: Matt Jankowski Date: Thu, 18 Jul 2024 04:00:19 -0400 Subject: [PATCH 064/126] Reduce factory creation in `AP::ProcessStatusUpdateService` spec (#31051) --- .../process_status_update_service_spec.rb | 101 +++++------------- 1 file changed, 28 insertions(+), 73 deletions(-) diff --git a/spec/services/activitypub/process_status_update_service_spec.rb b/spec/services/activitypub/process_status_update_service_spec.rb index e451d15dc0..a97e840802 100644 --- a/spec/services/activitypub/process_status_update_service_spec.rb +++ b/spec/services/activitypub/process_status_update_service_spec.rb @@ -40,14 +40,13 @@ RSpec.describe ActivityPub::ProcessStatusUpdateService do 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 @@ -67,12 +66,9 @@ RSpec.describe ActivityPub::ProcessStatusUpdateService do 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 @@ -90,15 +86,9 @@ RSpec.describe ActivityPub::ProcessStatusUpdateService do 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 @@ -137,19 +127,10 @@ RSpec.describe ActivityPub::ProcessStatusUpdateService do 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 @@ -189,19 +170,10 @@ RSpec.describe ActivityPub::ProcessStatusUpdateService do 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 @@ -213,13 +185,10 @@ RSpec.describe ActivityPub::ProcessStatusUpdateService do 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 @@ -237,12 +206,9 @@ RSpec.describe ActivityPub::ProcessStatusUpdateService do 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 @@ -261,12 +227,9 @@ RSpec.describe ActivityPub::ProcessStatusUpdateService do 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 @@ -412,11 +375,8 @@ RSpec.describe ActivityPub::ProcessStatusUpdateService do 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 @@ -442,26 +402,21 @@ RSpec.describe ActivityPub::ProcessStatusUpdateService do 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 + it 'creates edit history and sets edit timestamp' do subject.call(status, json, json) - expect(status.edits.reload.map(&:text)).to eq ['Hello world', 'Hello universe'] - end - - it 'sets edited 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 end end From 7d090b2ab6a76676c861f737c3b6922da8c1292b Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Thu, 18 Jul 2024 10:00:29 +0200 Subject: [PATCH 065/126] New Crowdin Translations (automated) (#31055) Co-authored-by: GitHub Actions --- app/javascript/mastodon/locales/ga.json | 76 +- app/javascript/mastodon/locales/kab.json | 4 +- config/locales/bg.yml | 2 + config/locales/devise.ga.yml | 6 + config/locales/doorkeeper.ga.yml | 144 ++ config/locales/ga.yml | 1532 +++++++++++++++++++++- config/locales/gl.yml | 2 + config/locales/hi.yml | 2 + config/locales/hu.yml | 2 +- config/locales/simple_form.bg.yml | 3 + config/locales/simple_form.ga.yml | 265 ++++ config/locales/sl.yml | 1 + config/locales/tr.yml | 1 + 13 files changed, 1999 insertions(+), 41 deletions(-) diff --git a/app/javascript/mastodon/locales/ga.json b/app/javascript/mastodon/locales/ga.json index 468c7a03a1..8c5039e2a4 100644 --- a/app/javascript/mastodon/locales/ga.json +++ b/app/javascript/mastodon/locales/ga.json @@ -29,8 +29,8 @@ "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í", @@ -38,7 +38,7 @@ "account.followers_counter": "{count, plural, one {{counter} leantóir} other {{counter} leantóirí}}", "account.following": "Ag leanúint", "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 duine ar bith fós.", + "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.", @@ -46,7 +46,7 @@ "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}", @@ -66,7 +66,7 @@ "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}", @@ -100,7 +100,7 @@ "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", @@ -135,9 +135,9 @@ "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", @@ -161,7 +161,7 @@ "compose_form.poll.switch_to_single": "Athraigh suirbhé chun cead a thabhairt do rogha amháin", "compose_form.poll.type": "Stíl", "compose_form.publish": "Postáil", - "compose_form.publish_form": "Foilsigh\n", + "compose_form.publish_form": "Post nua", "compose_form.reply": "Freagra", "compose_form.save_changes": "Nuashonrú", "compose_form.spoiler.marked": "Bain rabhadh ábhair", @@ -291,7 +291,7 @@ "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", @@ -377,7 +377,7 @@ "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.description": "Cur síos", "keyboard_shortcuts.direct": "to open direct messages column", "keyboard_shortcuts.down": "Bog síos ar an liosta", "keyboard_shortcuts.enter": "Oscail postáil", @@ -394,17 +394,17 @@ "keyboard_shortcuts.my_profile": "Oscail do phróifíl", "keyboard_shortcuts.notifications": "to open notifications column", "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á", @@ -545,12 +545,12 @@ "notifications_permission_banner.title": "Ná caill aon rud go deo", "onboarding.action.back": "Tóg ar ais mé", "onboarding.actions.back": "Tóg ar ais mé", - "onboarding.actions.go_to_explore": "See what's trending", - "onboarding.actions.go_to_home": "Go to your home feed", + "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": "You curate your own home feed. The more people you follow, the more active and interesting it will be. These profiles may be a good starting point—you can always unfollow them later!", - "onboarding.follows.title": "Popular on Mastodon", + "onboarding.follows.lead": "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", @@ -566,17 +566,17 @@ "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": "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.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": "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.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": "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.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ú!", @@ -594,7 +594,7 @@ "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", @@ -687,8 +687,8 @@ "search_popout.specific_date": "dáta ar leith", "search_popout.user": "úsáideoir", "search_results.accounts": "Próifílí", - "search_results.all": "Uile", - "search_results.hashtags": "Haischlibeanna", + "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", @@ -705,12 +705,12 @@ "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": "Open this status in the moderation interface", + "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", @@ -734,11 +734,11 @@ "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}}", @@ -757,7 +757,7 @@ "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", diff --git a/app/javascript/mastodon/locales/kab.json b/app/javascript/mastodon/locales/kab.json index a5c3280712..ab0a6ce22b 100644 --- a/app/javascript/mastodon/locales/kab.json +++ b/app/javascript/mastodon/locales/kab.json @@ -28,7 +28,7 @@ "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,6 +38,7 @@ "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", @@ -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", diff --git a/config/locales/bg.yml b/config/locales/bg.yml index 602a26225c..c0abc3c845 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/devise.ga.yml b/config/locales/devise.ga.yml index e083896f37..cc8ae0874e 100644 --- a/config/locales/devise.ga.yml +++ b/config/locales/devise.ga.yml @@ -116,3 +116,9 @@ ga: 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/doorkeeper.ga.yml b/config/locales/doorkeeper.ga.yml index 9ac4740691..09857768e3 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,38 +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/ga.yml b/config/locales/ga.yml index a3ad293e5b..370f3e82e6 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: Remove all followers from the selected domains 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: This browser doesn't support security keys + otp_required: To use security keys please enable two-factor authentication first. + registered_on: Registered on %{date} diff --git a/config/locales/gl.yml b/config/locales/gl.yml index c9f08dcad7..d1c8633bad 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/hi.yml b/config/locales/hi.yml index b67de192f2..0bfc30027a 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 5def03d902..df32bd39d1 100644 --- a/config/locales/hu.yml +++ b/config/locales/hu.yml @@ -226,7 +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_report: Bejelentés frissítése update_status: Bejegyzés frissítése update_user_role: Szerepkör frissítése actions: diff --git a/config/locales/simple_form.bg.yml b/config/locales/simple_form.bg.yml index f14a21b0c7..564f72e8c2 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.ga.yml b/config/locales/simple_form.ga.yml index 3597544ce3..2effe1a10c 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/sl.yml b/config/locales/sl.yml index 344368a08a..f63aadd6c8 100644 --- a/config/locales/sl.yml +++ b/config/locales/sl.yml @@ -663,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/tr.yml b/config/locales/tr.yml index 6b28e17441..9855b56924 100644 --- a/config/locales/tr.yml +++ b/config/locales/tr.yml @@ -639,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 From f587ff643f552a32a1c43e103a474a5065cd3657 Mon Sep 17 00:00:00 2001 From: Renaud Chaput Date: Thu, 18 Jul 2024 16:36:09 +0200 Subject: [PATCH 066/126] Grouped Notifications UI (#30440) Co-authored-by: Eugen Rochko Co-authored-by: Claire --- .../api/v2_alpha/notifications_controller.rb | 53 +- app/javascript/mastodon/actions/markers.ts | 14 +- .../mastodon/actions/notification_groups.ts | 144 +++++ .../mastodon/actions/notifications.js | 13 +- .../actions/notifications_migration.tsx | 18 + .../mastodon/actions/notifications_typed.ts | 9 +- app/javascript/mastodon/actions/streaming.js | 11 +- app/javascript/mastodon/api/notifications.ts | 18 + .../mastodon/api_types/notifications.ts | 145 +++++ app/javascript/mastodon/api_types/reports.ts | 16 + .../mastodon/components/load_gap.tsx | 12 +- app/javascript/mastodon/components/status.jsx | 8 +- .../mastodon/components/status_list.jsx | 2 +- .../compose/components/edit_indicator.jsx | 10 +- .../compose/components/reply_indicator.jsx | 10 +- .../components/column_settings.jsx | 11 + .../filtered_notifications_banner.tsx | 4 +- .../components/moderation_warning.tsx | 51 +- .../notifications/components/notification.jsx | 4 +- .../relationships_severance_event.jsx | 15 +- .../containers/column_settings_container.js | 8 +- .../mastodon/features/notifications/index.jsx | 2 +- .../components/avatar_group.tsx | 31 ++ .../components/embedded_status.tsx | 93 ++++ .../components/embedded_status_content.tsx | 165 ++++++ .../components/names_list.tsx | 51 ++ .../components/notification_admin_report.tsx | 132 +++++ .../components/notification_admin_sign_up.tsx | 31 ++ .../components/notification_favourite.tsx | 45 ++ .../components/notification_follow.tsx | 31 ++ .../notification_follow_request.tsx | 78 +++ .../components/notification_group.tsx | 134 +++++ .../notification_group_with_status.tsx | 91 ++++ .../components/notification_mention.tsx | 55 ++ .../notification_moderation_warning.tsx | 13 + .../components/notification_poll.tsx | 41 ++ .../components/notification_reblog.tsx | 45 ++ .../notification_severed_relationships.tsx | 15 + .../components/notification_status.tsx | 31 ++ .../components/notification_update.tsx | 31 ++ .../components/notification_with_status.tsx | 73 +++ .../features/notifications_v2/filter_bar.tsx | 145 +++++ .../features/notifications_v2/index.tsx | 354 ++++++++++++ .../features/notifications_wrapper.jsx | 13 + .../features/ui/components/columns_area.jsx | 4 +- .../ui/components/navigation_panel.jsx | 9 +- app/javascript/mastodon/features/ui/index.jsx | 9 +- .../features/ui/util/async-components.js | 10 +- app/javascript/mastodon/locales/en.json | 15 +- .../mastodon/models/notification_group.ts | 207 +++++++ app/javascript/mastodon/reducers/index.ts | 2 + app/javascript/mastodon/reducers/markers.ts | 22 +- .../mastodon/reducers/notification_groups.ts | 508 ++++++++++++++++++ .../mastodon/reducers/notifications.js | 4 +- .../mastodon/selectors/notifications.ts | 34 ++ app/javascript/mastodon/selectors/settings.ts | 40 ++ .../styles/mastodon/components.scss | 293 +++++++++- app/models/notification.rb | 1 + app/models/notification_group.rb | 8 +- .../rest/notification_group_serializer.rb | 1 + .../rest/notification_serializer.rb | 1 + app/services/notify_service.rb | 4 +- config/routes.rb | 1 + package.json | 1 + yarn.lock | 10 + 65 files changed, 3329 insertions(+), 131 deletions(-) create mode 100644 app/javascript/mastodon/actions/notification_groups.ts create mode 100644 app/javascript/mastodon/actions/notifications_migration.tsx create mode 100644 app/javascript/mastodon/api/notifications.ts create mode 100644 app/javascript/mastodon/api_types/notifications.ts create mode 100644 app/javascript/mastodon/api_types/reports.ts create mode 100644 app/javascript/mastodon/features/notifications_v2/components/avatar_group.tsx create mode 100644 app/javascript/mastodon/features/notifications_v2/components/embedded_status.tsx create mode 100644 app/javascript/mastodon/features/notifications_v2/components/embedded_status_content.tsx create mode 100644 app/javascript/mastodon/features/notifications_v2/components/names_list.tsx create mode 100644 app/javascript/mastodon/features/notifications_v2/components/notification_admin_report.tsx create mode 100644 app/javascript/mastodon/features/notifications_v2/components/notification_admin_sign_up.tsx create mode 100644 app/javascript/mastodon/features/notifications_v2/components/notification_favourite.tsx create mode 100644 app/javascript/mastodon/features/notifications_v2/components/notification_follow.tsx create mode 100644 app/javascript/mastodon/features/notifications_v2/components/notification_follow_request.tsx create mode 100644 app/javascript/mastodon/features/notifications_v2/components/notification_group.tsx create mode 100644 app/javascript/mastodon/features/notifications_v2/components/notification_group_with_status.tsx create mode 100644 app/javascript/mastodon/features/notifications_v2/components/notification_mention.tsx create mode 100644 app/javascript/mastodon/features/notifications_v2/components/notification_moderation_warning.tsx create mode 100644 app/javascript/mastodon/features/notifications_v2/components/notification_poll.tsx create mode 100644 app/javascript/mastodon/features/notifications_v2/components/notification_reblog.tsx create mode 100644 app/javascript/mastodon/features/notifications_v2/components/notification_severed_relationships.tsx create mode 100644 app/javascript/mastodon/features/notifications_v2/components/notification_status.tsx create mode 100644 app/javascript/mastodon/features/notifications_v2/components/notification_update.tsx create mode 100644 app/javascript/mastodon/features/notifications_v2/components/notification_with_status.tsx create mode 100644 app/javascript/mastodon/features/notifications_v2/filter_bar.tsx create mode 100644 app/javascript/mastodon/features/notifications_v2/index.tsx create mode 100644 app/javascript/mastodon/features/notifications_wrapper.jsx create mode 100644 app/javascript/mastodon/models/notification_group.ts create mode 100644 app/javascript/mastodon/reducers/notification_groups.ts create mode 100644 app/javascript/mastodon/selectors/notifications.ts create mode 100644 app/javascript/mastodon/selectors/settings.ts diff --git a/app/controllers/api/v2_alpha/notifications_controller.rb b/app/controllers/api/v2_alpha/notifications_controller.rb index edba23ab4a..83d40a0886 100644 --- a/app/controllers/api/v2_alpha/notifications_controller.rb +++ b/app/controllers/api/v2_alpha/notifications_controller.rb @@ -12,10 +12,27 @@ class Api::V2Alpha::NotificationsController < Api::BaseController 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 @@ class Api::V2Alpha::NotificationsController < Api::BaseController 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) - ) + 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) + 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/mastodon/actions/markers.ts b/app/javascript/mastodon/actions/markers.ts index 03f577c540..77d91d9b9c 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 0000000000..8fdec6e48b --- /dev/null +++ b/app/javascript/mastodon/actions/notification_groups.ts @@ -0,0 +1,144 @@ +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) { + 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 6a59d5624e..7e4320c27b 100644 --- a/app/javascript/mastodon/actions/notifications.js +++ b/app/javascript/mastodon/actions/notifications.js @@ -32,7 +32,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'; @@ -174,7 +173,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'); @@ -257,16 +256,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 0000000000..f856e56828 --- /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 176362f4b1..88d942d45e 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/streaming.js b/app/javascript/mastodon/actions/streaming.js index e7fe1c53ed..f50f41b0d9 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 } from './notifications'; import { updateStatus } from './statuses'; import { @@ -98,10 +99,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 'conversation': // @ts-expect-error dispatch(updateConversations(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 0000000000..c1ab6f70ca --- /dev/null +++ b/app/javascript/mastodon/api/notifications.ts @@ -0,0 +1,18 @@ +import api, { apiRequest, getLinks } from 'mastodon/api'; +import type { ApiNotificationGroupJSON } from 'mastodon/api_types/notifications'; + +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: 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 0000000000..d7cbbca73b --- /dev/null +++ b/app/javascript/mastodon/api_types/notifications.ts @@ -0,0 +1,145 @@ +// 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', + 'reblog', + 'mention', + 'poll', + 'status', + 'update', + 'admin.sign_up', + 'admin.report', + 'moderation_warning', + 'severed_relationships', +]; + +export type NotificationWithStatusType = + | 'favourite' + | 'reblog' + | 'status' + | 'mention' + | '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 0000000000..b11cfdd2eb --- /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/load_gap.tsx b/app/javascript/mastodon/components/load_gap.tsx index 1d4193a359..544b5e1461 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 ( + ); +}; + +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 0000000000..fc20f05836 --- /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 0000000000..057ed1b395 --- /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/ui/components/columns_area.jsx b/app/javascript/mastodon/features/ui/components/columns_area.jsx index 19c2f40ac6..063ac28d96 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, @@ -32,7 +32,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 ff90eef359..2648923bfc 100644 --- a/app/javascript/mastodon/features/ui/components/navigation_panel.jsx +++ b/app/javascript/mastodon/features/ui/components/navigation_panel.jsx @@ -34,6 +34,7 @@ import { NavigationPortal } from 'mastodon/components/navigation_portal'; import { identityContextPropShape, withIdentity } from 'mastodon/identity_context'; import { timelinePreview, trendsEnabled } 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'; @@ -59,15 +60,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 d9f609620c..f36e0cf501 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'; @@ -49,7 +49,7 @@ import { Favourites, DirectTimeline, HashtagTimeline, - Notifications, + NotificationsWrapper, NotificationRequests, NotificationRequest, FollowRequests, @@ -71,6 +71,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'; @@ -205,7 +206,7 @@ class SwitchingColumnsArea extends PureComponent { - + @@ -405,7 +406,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 b8a2359d92..7c4372d5a6 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/en.json b/app/javascript/mastodon/locales/en.json index 13296e1d20..60bdfd1d44 100644 --- a/app/javascript/mastodon/locales/en.json +++ b/app/javascript/mastodon/locales/en.json @@ -443,6 +443,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.blocks": "Blocked users", @@ -470,6 +472,10 @@ "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.favourite": "{name} favorited your post", "notification.follow": "{name} followed you", @@ -485,7 +491,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.", @@ -503,6 +510,8 @@ "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.beta.category": "Experimental features", + "notifications.column_settings.beta.grouping": "Group notifications", "notifications.column_settings.favourite": "Favorites:", "notifications.column_settings.filter_bar.advanced": "Display all categories", "notifications.column_settings.filter_bar.category": "Quick filter bar", @@ -666,9 +675,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/models/notification_group.ts b/app/javascript/mastodon/models/notification_group.ts new file mode 100644 index 0000000000..5fe1e6f2e4 --- /dev/null +++ b/app/javascript/mastodon/models/notification_group.ts @@ -0,0 +1,207 @@ +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 NotificationGroupReblog = BaseNotificationWithStatus<'reblog'>; +export type NotificationGroupStatus = BaseNotificationWithStatus<'status'>; +export type NotificationGroupMention = BaseNotificationWithStatus<'mention'>; +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' + | '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 + | NotificationGroupReblog + | NotificationGroupStatus + | NotificationGroupMention + | 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 'reblog': + case 'status': + case 'mention': + 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 'reblog': + case 'status': + case 'mention': + 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 6296ef2026..b92de0dbcd 100644 --- a/app/javascript/mastodon/reducers/index.ts +++ b/app/javascript/mastodon/reducers/index.ts @@ -24,6 +24,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'; @@ -65,6 +66,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 ec85d0f173..b1f10b5fa2 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 0000000000..e59f3e7ca1 --- /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 79aa5651ff..622f5e8e88 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, @@ -290,7 +290,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 0000000000..1b1ed2154c --- /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 0000000000..64d9440bc8 --- /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/components.scss b/app/javascript/styles/mastodon/components.scss index e94ce2d8f4..5a0a41c978 100644 --- a/app/javascript/styles/mastodon/components.scss +++ b/app/javascript/styles/mastodon/components.scss @@ -1611,14 +1611,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; } } @@ -2209,41 +2214,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; } } } @@ -10193,8 +10185,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; @@ -10204,10 +10196,8 @@ noscript { color: $secondary-text-color; } - .icon { - width: 24px; - height: 24px; - padding: 2px; + .notification-group__icon { + color: inherit; } &__text { @@ -10345,6 +10335,251 @@ 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 { + &__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; + cursor: pointer; + -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/models/notification.rb b/app/models/notification.rb index 01abe74f5e..6d40411478 100644 --- a/app/models/notification.rb +++ b/app/models/notification.rb @@ -30,6 +30,7 @@ class Notification < ApplicationRecord 'Poll' => :poll, }.freeze + # Please update app/javascript/api_types/notification.ts if you change this PROPERTIES = { mention: { filterable: true, diff --git a/app/models/notification_group.rb b/app/models/notification_group.rb index b1cbd7c19a..223945f07b 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/serializers/rest/notification_group_serializer.rb b/app/serializers/rest/notification_group_serializer.rb index 9aa5663f4e..749f717754 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? diff --git a/app/serializers/rest/notification_serializer.rb b/app/serializers/rest/notification_serializer.rb index ee17af8076..320bc86961 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/notify_service.rb b/app/services/notify_service.rb index d69b5af141..acbb3fc784 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 @@ -217,9 +216,8 @@ class NotifyService < BaseService 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) "#{type_prefix}-#{hour_bucket}" end diff --git a/config/routes.rb b/config/routes.rb index e4f091043d..93bdb95969 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -29,6 +29,7 @@ Rails.application.routes.draw do /lists/(*any) /links/(*any) /notifications/(*any) + /notifications_v2/(*any) /favourites /bookmarks /pinned diff --git a/package.json b/package.json index 404c4f486f..4571ca03af 100644 --- a/package.json +++ b/package.json @@ -123,6 +123,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", diff --git a/yarn.lock b/yarn.lock index c5d0480061..86640faa05 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2910,6 +2910,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" @@ -17543,6 +17544,15 @@ __metadata: languageName: node linkType: hard +"use-debounce@npm:^10.0.0": + version: 10.0.0 + resolution: "use-debounce@npm:10.0.0" + peerDependencies: + react: ">=16.8.0" + checksum: 10c0/c1166cba52dedeab17e3e29275af89c57a3e8981b75f6e38ae2896ac36ecd4ed7d8fff5f882ba4b2f91eac7510d5ae0dd89fa4f7d081622ed436c3c89eda5cd1 + 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" From 6e47637dd4f93169ec783c01f4f9b4dfb7cb66ce Mon Sep 17 00:00:00 2001 From: Claire Date: Thu, 18 Jul 2024 17:23:40 +0200 Subject: [PATCH 067/126] Fix grouping across hourly buckets happening in a 12 seconds window instead of 12 hours window (#31062) --- app/services/notify_service.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/services/notify_service.rb b/app/services/notify_service.rb index acbb3fc784..23f92c816b 100644 --- a/app/services/notify_service.rb +++ b/app/services/notify_service.rb @@ -217,7 +217,7 @@ class NotifyService < BaseService hour_bucket = previous_bucket if hour_bucket < previous_bucket + MAXIMUM_GROUP_SPAN_HOURS # We do not concern ourselves with race conditions since we use hour buckets - redis.set(redis_key, hour_bucket, ex: MAXIMUM_GROUP_SPAN_HOURS) + redis.set(redis_key, hour_bucket, ex: MAXIMUM_GROUP_SPAN_HOURS.hours.to_i) "#{type_prefix}-#{hour_bucket}" end From 41b7281b56ea64b13fdf07d5ce7efadcbe65bd1c Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Thu, 18 Jul 2024 17:23:43 +0200 Subject: [PATCH 068/126] fix(deps): update dependency use-debounce to v10.0.1 (#31060) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- yarn.lock | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/yarn.lock b/yarn.lock index 86640faa05..1a17c5862f 100644 --- a/yarn.lock +++ b/yarn.lock @@ -17545,11 +17545,11 @@ __metadata: linkType: hard "use-debounce@npm:^10.0.0": - version: 10.0.0 - resolution: "use-debounce@npm:10.0.0" + version: 10.0.1 + resolution: "use-debounce@npm:10.0.1" peerDependencies: react: ">=16.8.0" - checksum: 10c0/c1166cba52dedeab17e3e29275af89c57a3e8981b75f6e38ae2896ac36ecd4ed7d8fff5f882ba4b2f91eac7510d5ae0dd89fa4f7d081622ed436c3c89eda5cd1 + checksum: 10c0/377a11814a708f5c392f465cbbe2d119a8a2635c8226cc5e30eba397c4436f8e8234385d069467b369d105ed0d3be733c6a08d8ae1004017c6d6f58f4d4c24d8 languageName: node linkType: hard From 848b59c8ae366895eb690a062698bd8f653e5959 Mon Sep 17 00:00:00 2001 From: Matt Jankowski Date: Thu, 18 Jul 2024 11:23:46 -0400 Subject: [PATCH 069/126] Reduce factory creation in `MediaAttachment` model spec (#31058) --- spec/models/media_attachment_spec.rb | 99 +++++++++++++++++----------- spec/rails_helper.rb | 1 + 2 files changed, 62 insertions(+), 38 deletions(-) diff --git a/spec/models/media_attachment_spec.rb b/spec/models/media_attachment_spec.rb index 24e8ca39c1..3142b291fb 100644 --- a/spec/models/media_attachment_spec.rb +++ b/spec/models/media_attachment_spec.rb @@ -90,7 +90,7 @@ RSpec.describe MediaAttachment, :attachment_processing do 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 @@ RSpec.describe MediaAttachment, :attachment_processing do # 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 @@ RSpec.describe MediaAttachment, :attachment_processing do 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 @@ RSpec.describe MediaAttachment, :attachment_processing do 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 @@ RSpec.describe MediaAttachment, :attachment_processing do describe 'ogg with cover art' do let(:media) { Fabricate(:media_attachment, file: attachment_fixture('boop.ogg')) } + let(:expected_media_duration) { 0.235102 } + + # The libvips and ImageMagick implementations produce different results + let(:expected_background_color) { Rails.configuration.x.use_vips ? '#268cd9' : '#3088d4' } 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 + expect(media) + .to have_attributes( + type: eq('audio'), + thumbnail: be_present, + file_file_name: not_eq('boop.ogg') + ) - expect(media.file.meta['colors']['background']).to eq(expected_background_color) - expect(media.file_file_name).to_not eq 'boop.ogg' - end - - 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 @@ RSpec.describe MediaAttachment, :attachment_processing do 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 79031f1a94..d4b9bddf93 100644 --- a/spec/rails_helper.rb +++ b/spec/rails_helper.rb @@ -161,6 +161,7 @@ RSpec::Sidekiq.configure do |config| 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) From 82344342c1c5adb3f6a4b376559db737a9e982b7 Mon Sep 17 00:00:00 2001 From: Matt Jankowski Date: Thu, 18 Jul 2024 11:45:40 -0400 Subject: [PATCH 070/126] Add link to org-level contribution guidelines to contributing doc (#31043) --- CONTRIBUTING.md | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index b68a9bde3e..8286fdd2f7 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -11,6 +11,11 @@ You can contribute in the following ways: If your contributions are accepted into Mastodon, you can request to be paid through [our OpenCollective](https://opencollective.com/mastodon). +Please review the org-level [contribution guidelines] for high-level acceptance +criteria guidance. + +[contribution guidelines]: https://github.com/mastodon/.github/blob/main/CONTRIBUTING.md + ## API Changes and Additions Please note that any changes or additions made to the API should have an accompanying pull request on [our documentation repository](https://github.com/mastodon/documentation). From 7224e2405413b816b2fbc171a9a9e7b86bae0261 Mon Sep 17 00:00:00 2001 From: Renaud Chaput Date: Thu, 18 Jul 2024 16:36:09 +0200 Subject: [PATCH 071/126] [Glitch] Grouped Notifications UI Port f587ff643f552a32a1c43e103a474a5065cd3657 to glitch-soc Co-authored-by: Eugen Rochko Co-authored-by: Claire Signed-off-by: Claire --- app/javascript/flavours/glitch/actions/app.ts | 3 + .../flavours/glitch/actions/markers.ts | 14 +- .../glitch/actions/notification_groups.ts | 144 +++++ .../flavours/glitch/actions/notifications.js | 13 +- .../actions/notifications_migration.tsx | 18 + .../glitch/actions/notifications_typed.ts | 9 +- .../flavours/glitch/actions/streaming.js | 11 +- .../flavours/glitch/api/notifications.ts | 18 + .../glitch/api_types/notifications.ts | 145 +++++ .../flavours/glitch/api_types/reports.ts | 16 + .../flavours/glitch/components/load_gap.tsx | 12 +- .../flavours/glitch/components/status.jsx | 16 +- .../glitch/components/status_header.jsx | 4 +- .../glitch/components/status_list.jsx | 2 +- .../glitch/components/status_prepend.jsx | 2 +- .../compose/components/edit_indicator.jsx | 10 +- .../compose/components/reply_indicator.jsx | 10 +- .../components/column_settings.jsx | 11 + .../filtered_notifications_banner.tsx | 4 +- .../components/moderation_warning.tsx | 51 +- .../relationships_severance_event.jsx | 15 +- .../containers/column_settings_container.js | 8 +- .../glitch/features/notifications/index.jsx | 2 +- .../components/avatar_group.tsx | 31 ++ .../components/embedded_status.tsx | 93 ++++ .../components/embedded_status_content.tsx | 165 ++++++ .../components/names_list.tsx | 51 ++ .../components/notification_admin_report.tsx | 132 +++++ .../components/notification_admin_sign_up.tsx | 31 ++ .../components/notification_favourite.tsx | 45 ++ .../components/notification_follow.tsx | 31 ++ .../notification_follow_request.tsx | 78 +++ .../components/notification_group.tsx | 134 +++++ .../notification_group_with_status.tsx | 91 ++++ .../components/notification_mention.tsx | 55 ++ .../notification_moderation_warning.tsx | 13 + .../components/notification_poll.tsx | 41 ++ .../components/notification_reblog.tsx | 45 ++ .../notification_severed_relationships.tsx | 15 + .../components/notification_status.tsx | 31 ++ .../components/notification_update.tsx | 31 ++ .../components/notification_with_status.tsx | 73 +++ .../features/notifications_v2/filter_bar.tsx | 145 +++++ .../features/notifications_v2/index.tsx | 354 ++++++++++++ .../glitch/features/notifications_wrapper.jsx | 13 + .../features/ui/components/columns_area.jsx | 4 +- .../ui/components/navigation_panel.jsx | 9 +- .../flavours/glitch/features/ui/index.jsx | 15 +- .../features/ui/util/async-components.js | 10 +- .../glitch/models/notification_group.ts | 207 +++++++ .../flavours/glitch/reducers/index.ts | 2 + .../flavours/glitch/reducers/markers.ts | 25 +- .../glitch/reducers/notification_groups.ts | 508 ++++++++++++++++++ .../flavours/glitch/reducers/notifications.js | 4 +- .../glitch/selectors/notifications.ts | 34 ++ .../flavours/glitch/selectors/settings.ts | 40 ++ .../flavours/glitch/styles/components.scss | 295 +++++++++- 57 files changed, 3271 insertions(+), 118 deletions(-) create mode 100644 app/javascript/flavours/glitch/actions/notification_groups.ts create mode 100644 app/javascript/flavours/glitch/actions/notifications_migration.tsx create mode 100644 app/javascript/flavours/glitch/api/notifications.ts create mode 100644 app/javascript/flavours/glitch/api_types/notifications.ts create mode 100644 app/javascript/flavours/glitch/api_types/reports.ts create mode 100644 app/javascript/flavours/glitch/features/notifications_v2/components/avatar_group.tsx create mode 100644 app/javascript/flavours/glitch/features/notifications_v2/components/embedded_status.tsx create mode 100644 app/javascript/flavours/glitch/features/notifications_v2/components/embedded_status_content.tsx create mode 100644 app/javascript/flavours/glitch/features/notifications_v2/components/names_list.tsx create mode 100644 app/javascript/flavours/glitch/features/notifications_v2/components/notification_admin_report.tsx create mode 100644 app/javascript/flavours/glitch/features/notifications_v2/components/notification_admin_sign_up.tsx create mode 100644 app/javascript/flavours/glitch/features/notifications_v2/components/notification_favourite.tsx create mode 100644 app/javascript/flavours/glitch/features/notifications_v2/components/notification_follow.tsx create mode 100644 app/javascript/flavours/glitch/features/notifications_v2/components/notification_follow_request.tsx create mode 100644 app/javascript/flavours/glitch/features/notifications_v2/components/notification_group.tsx create mode 100644 app/javascript/flavours/glitch/features/notifications_v2/components/notification_group_with_status.tsx create mode 100644 app/javascript/flavours/glitch/features/notifications_v2/components/notification_mention.tsx create mode 100644 app/javascript/flavours/glitch/features/notifications_v2/components/notification_moderation_warning.tsx create mode 100644 app/javascript/flavours/glitch/features/notifications_v2/components/notification_poll.tsx create mode 100644 app/javascript/flavours/glitch/features/notifications_v2/components/notification_reblog.tsx create mode 100644 app/javascript/flavours/glitch/features/notifications_v2/components/notification_severed_relationships.tsx create mode 100644 app/javascript/flavours/glitch/features/notifications_v2/components/notification_status.tsx create mode 100644 app/javascript/flavours/glitch/features/notifications_v2/components/notification_update.tsx create mode 100644 app/javascript/flavours/glitch/features/notifications_v2/components/notification_with_status.tsx create mode 100644 app/javascript/flavours/glitch/features/notifications_v2/filter_bar.tsx create mode 100644 app/javascript/flavours/glitch/features/notifications_v2/index.tsx create mode 100644 app/javascript/flavours/glitch/features/notifications_wrapper.jsx create mode 100644 app/javascript/flavours/glitch/models/notification_group.ts create mode 100644 app/javascript/flavours/glitch/reducers/notification_groups.ts create mode 100644 app/javascript/flavours/glitch/selectors/notifications.ts create mode 100644 app/javascript/flavours/glitch/selectors/settings.ts diff --git a/app/javascript/flavours/glitch/actions/app.ts b/app/javascript/flavours/glitch/actions/app.ts index 6fbfc07f68..be1a5cced2 100644 --- a/app/javascript/flavours/glitch/actions/app.ts +++ b/app/javascript/flavours/glitch/actions/app.ts @@ -2,6 +2,9 @@ import { createAction } from '@reduxjs/toolkit'; import type { LayoutType } from '../is_mobile'; +export const focusApp = createAction('APP_FOCUS'); +export const unfocusApp = createAction('APP_UNFOCUS'); + interface ChangeLayoutPayload { layout: LayoutType; } diff --git a/app/javascript/flavours/glitch/actions/markers.ts b/app/javascript/flavours/glitch/actions/markers.ts index a85af1c4be..861eae41ec 100644 --- a/app/javascript/flavours/glitch/actions/markers.ts +++ b/app/javascript/flavours/glitch/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/flavours/glitch/actions/notification_groups.ts b/app/javascript/flavours/glitch/actions/notification_groups.ts new file mode 100644 index 0000000000..3f6d14a978 --- /dev/null +++ b/app/javascript/flavours/glitch/actions/notification_groups.ts @@ -0,0 +1,144 @@ +import { createAction } from '@reduxjs/toolkit'; + +import { + apiClearNotifications, + apiFetchNotifications, +} from 'flavours/glitch/api/notifications'; +import type { ApiAccountJSON } from 'flavours/glitch/api_types/accounts'; +import type { + ApiNotificationGroupJSON, + ApiNotificationJSON, +} from 'flavours/glitch/api_types/notifications'; +import { allNotificationTypes } from 'flavours/glitch/api_types/notifications'; +import type { ApiStatusJSON } from 'flavours/glitch/api_types/statuses'; +import type { NotificationGap } from 'flavours/glitch/reducers/notification_groups'; +import { + selectSettingsNotificationsExcludedTypes, + selectSettingsNotificationsQuickFilterActive, +} from 'flavours/glitch/selectors/settings'; +import type { AppDispatch } from 'flavours/glitch/store'; +import { + createAppAsyncThunk, + createDataLoadingThunk, +} from 'flavours/glitch/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) { + 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/flavours/glitch/actions/notifications.js b/app/javascript/flavours/glitch/actions/notifications.js index 3a1af501c8..7a97e71bdd 100644 --- a/app/javascript/flavours/glitch/actions/notifications.js +++ b/app/javascript/flavours/glitch/actions/notifications.js @@ -43,7 +43,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'); @@ -269,16 +268,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/flavours/glitch/actions/notifications_migration.tsx b/app/javascript/flavours/glitch/actions/notifications_migration.tsx new file mode 100644 index 0000000000..32844d4b42 --- /dev/null +++ b/app/javascript/flavours/glitch/actions/notifications_migration.tsx @@ -0,0 +1,18 @@ +import { createAppAsyncThunk } from 'flavours/glitch/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/flavours/glitch/actions/notifications_typed.ts b/app/javascript/flavours/glitch/actions/notifications_typed.ts index 176362f4b1..55896f4c37 100644 --- a/app/javascript/flavours/glitch/actions/notifications_typed.ts +++ b/app/javascript/flavours/glitch/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 'flavours/glitch/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/flavours/glitch/actions/streaming.js b/app/javascript/flavours/glitch/actions/streaming.js index a55240646f..7b006c1be7 100644 --- a/app/javascript/flavours/glitch/actions/streaming.js +++ b/app/javascript/flavours/glitch/actions/streaming.js @@ -10,6 +10,7 @@ import { deleteAnnouncement, } from './announcements'; import { updateConversations } from './conversations'; +import { processNewNotificationForGroups } from './notification_groups'; import { updateNotifications, expandNotifications } from './notifications'; import { updateStatus } from './statuses'; import { @@ -98,10 +99,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 'conversation': // @ts-expect-error dispatch(updateConversations(JSON.parse(data.payload))); diff --git a/app/javascript/flavours/glitch/api/notifications.ts b/app/javascript/flavours/glitch/api/notifications.ts new file mode 100644 index 0000000000..fe71878822 --- /dev/null +++ b/app/javascript/flavours/glitch/api/notifications.ts @@ -0,0 +1,18 @@ +import api, { apiRequest, getLinks } from 'flavours/glitch/api'; +import type { ApiNotificationGroupJSON } from 'flavours/glitch/api_types/notifications'; + +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: response.data, links: getLinks(response) }; +}; + +export const apiClearNotifications = () => + apiRequest('POST', 'v1/notifications/clear'); diff --git a/app/javascript/flavours/glitch/api_types/notifications.ts b/app/javascript/flavours/glitch/api_types/notifications.ts new file mode 100644 index 0000000000..ea37556d8d --- /dev/null +++ b/app/javascript/flavours/glitch/api_types/notifications.ts @@ -0,0 +1,145 @@ +// See app/serializers/rest/notification_group_serializer.rb + +import type { AccountWarningAction } from 'flavours/glitch/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', + 'reblog', + 'mention', + 'poll', + 'status', + 'update', + 'admin.sign_up', + 'admin.report', + 'moderation_warning', + 'severed_relationships', +]; + +export type NotificationWithStatusType = + | 'favourite' + | 'reblog' + | 'status' + | 'mention' + | '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/flavours/glitch/api_types/reports.ts b/app/javascript/flavours/glitch/api_types/reports.ts new file mode 100644 index 0000000000..b11cfdd2eb --- /dev/null +++ b/app/javascript/flavours/glitch/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/flavours/glitch/components/load_gap.tsx b/app/javascript/flavours/glitch/components/load_gap.tsx index f0d15d3776..1870185c29 100644 --- a/app/javascript/flavours/glitch/components/load_gap.tsx +++ b/app/javascript/flavours/glitch/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 ( + ); +}; + +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/flavours/glitch/features/notifications_v2/index.tsx b/app/javascript/flavours/glitch/features/notifications_v2/index.tsx new file mode 100644 index 0000000000..9405171375 --- /dev/null +++ b/app/javascript/flavours/glitch/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 'flavours/glitch/actions/notification_groups'; +import { compareId } from 'flavours/glitch/compare_id'; +import { Icon } from 'flavours/glitch/components/icon'; +import { NotSignedInIndicator } from 'flavours/glitch/components/not_signed_in_indicator'; +import { useIdentity } from 'flavours/glitch/identity_context'; +import type { NotificationGap } from 'flavours/glitch/reducers/notification_groups'; +import { + selectUnreadNotificationGroupsCount, + selectPendingNotificationGroupsCount, +} from 'flavours/glitch/selectors/notifications'; +import { + selectNeedsNotificationPermission, + selectSettingsNotificationsExcludedTypes, + selectSettingsNotificationsQuickFilterActive, + selectSettingsNotificationsQuickFilterShow, + selectSettingsNotificationsShowUnread, +} from 'flavours/glitch/selectors/settings'; +import { useAppDispatch, useAppSelector } from 'flavours/glitch/store'; +import type { RootState } from 'flavours/glitch/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/flavours/glitch/features/notifications_wrapper.jsx b/app/javascript/flavours/glitch/features/notifications_wrapper.jsx new file mode 100644 index 0000000000..15ab3367cc --- /dev/null +++ b/app/javascript/flavours/glitch/features/notifications_wrapper.jsx @@ -0,0 +1,13 @@ +import Notifications from 'flavours/glitch/features/notifications'; +import Notifications_v2 from 'flavours/glitch/features/notifications_v2'; +import { useAppSelector } from 'flavours/glitch/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/flavours/glitch/features/ui/components/columns_area.jsx b/app/javascript/flavours/glitch/features/ui/components/columns_area.jsx index 9166499c5a..e4c67ed65e 100644 --- a/app/javascript/flavours/glitch/features/ui/components/columns_area.jsx +++ b/app/javascript/flavours/glitch/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, @@ -32,7 +32,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/flavours/glitch/features/ui/components/navigation_panel.jsx b/app/javascript/flavours/glitch/features/ui/components/navigation_panel.jsx index 98d82342cf..6153b3ceaa 100644 --- a/app/javascript/flavours/glitch/features/ui/components/navigation_panel.jsx +++ b/app/javascript/flavours/glitch/features/ui/components/navigation_panel.jsx @@ -33,6 +33,7 @@ import { NavigationPortal } from 'flavours/glitch/components/navigation_portal'; import { identityContextPropShape, withIdentity } from 'flavours/glitch/identity_context'; import { timelinePreview, trendsEnabled } from 'flavours/glitch/initial_state'; import { transientSingleColumn } from 'flavours/glitch/is_mobile'; +import { selectUnreadNotificationGroupsCount } from 'flavours/glitch/selectors/notifications'; import { preferencesLink } from 'flavours/glitch/utils/backend_links'; import ColumnLink from './column_link'; @@ -60,15 +61,19 @@ const messages = defineMessages({ }); const NotificationsLink = () => { + const optedInGroupedNotifications = useSelector((state) => state.getIn(['settings', 'notifications', 'groupingBeta'], false)); const count = useSelector(state => state.getIn(['local_settings', 'notifications', 'tab_badge']) ? state.getIn(['notifications', 'unread']) : 0); const intl = useIntl(); + const newCount = useSelector(selectUnreadNotificationGroupsCount); + return ( } - activeIcon={} + icon={} + activeIcon={} text={intl.formatMessage(messages.notifications)} /> ); diff --git a/app/javascript/flavours/glitch/features/ui/index.jsx b/app/javascript/flavours/glitch/features/ui/index.jsx index 221f789a31..7a2aa21f88 100644 --- a/app/javascript/flavours/glitch/features/ui/index.jsx +++ b/app/javascript/flavours/glitch/features/ui/index.jsx @@ -12,8 +12,9 @@ import Favico from 'favico.js'; import { debounce } from 'lodash'; import { HotKeys } from 'react-hotkeys'; -import { changeLayout } from 'flavours/glitch/actions/app'; +import { focusApp, unfocusApp, changeLayout } from 'flavours/glitch/actions/app'; import { synchronouslySubmitMarkers, submitMarkers, fetchMarkers } from 'flavours/glitch/actions/markers'; +import { initializeNotifications } from 'flavours/glitch/actions/notifications_migration'; import { INTRODUCTION_VERSION } from 'flavours/glitch/actions/onboarding'; import { HoverCardController } from 'flavours/glitch/components/hover_card_controller'; import { Permalink } from 'flavours/glitch/components/permalink'; @@ -24,7 +25,7 @@ import { WithRouterPropTypes } from 'flavours/glitch/utils/react_router'; import { uploadCompose, resetCompose, changeComposeSpoilerness } from '../../actions/compose'; import { clearHeight } from '../../actions/height_cache'; -import { expandNotifications, notificationsSetVisibility } from '../../actions/notifications'; +import { notificationsSetVisibility } 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'; @@ -51,7 +52,7 @@ import { Favourites, DirectTimeline, HashtagTimeline, - Notifications, + NotificationsWrapper, NotificationRequests, NotificationRequest, FollowRequests, @@ -74,6 +75,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'; @@ -214,7 +216,7 @@ class SwitchingColumnsArea extends PureComponent { - + @@ -304,7 +306,10 @@ class UI extends PureComponent { const visibility = !document[this.visibilityHiddenProp]; this.props.dispatch(notificationsSetVisibility(visibility)); if (visibility) { + this.props.dispatch(focusApp()); this.props.dispatch(submitMarkers({ immediate: true })); + } else { + this.props.dispatch(unfocusApp()); } }; @@ -419,7 +424,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/flavours/glitch/features/ui/util/async-components.js b/app/javascript/flavours/glitch/features/ui/util/async-components.js index a312cefff7..e334e1a3b6 100644 --- a/app/javascript/flavours/glitch/features/ui/util/async-components.js +++ b/app/javascript/flavours/glitch/features/ui/util/async-components.js @@ -7,7 +7,15 @@ export function Compose () { } export function Notifications () { - return import(/* webpackChunkName: "flavours/glitch/async/notifications" */'../../notifications'); + return import(/* webpackChunkName: "flavours/glitch/async/notifications_v1" */'../../notifications'); +} + +export function Notifications_v2 () { + return import(/* webpackChunkName: "flavours/glitch/async/notifications_v2" */'../../notifications_v2'); +} + +export function NotificationsWrapper () { + return import(/* webpackChunkName: "flavours/glitch/async/notifications" */'../../notifications_wrapper'); } export function HomeTimeline () { diff --git a/app/javascript/flavours/glitch/models/notification_group.ts b/app/javascript/flavours/glitch/models/notification_group.ts new file mode 100644 index 0000000000..6c8b8eb6e3 --- /dev/null +++ b/app/javascript/flavours/glitch/models/notification_group.ts @@ -0,0 +1,207 @@ +import type { + ApiAccountRelationshipSeveranceEventJSON, + ApiAccountWarningJSON, + BaseNotificationGroupJSON, + ApiNotificationGroupJSON, + ApiNotificationJSON, + NotificationType, + NotificationWithStatusType, +} from 'flavours/glitch/api_types/notifications'; +import type { ApiReportJSON } from 'flavours/glitch/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 NotificationGroupReblog = BaseNotificationWithStatus<'reblog'>; +export type NotificationGroupStatus = BaseNotificationWithStatus<'status'>; +export type NotificationGroupMention = BaseNotificationWithStatus<'mention'>; +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' + | '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 + | NotificationGroupReblog + | NotificationGroupStatus + | NotificationGroupMention + | 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 'reblog': + case 'status': + case 'mention': + 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 'reblog': + case 'status': + case 'mention': + 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/flavours/glitch/reducers/index.ts b/app/javascript/flavours/glitch/reducers/index.ts index 3fee5818f9..d8d50be7d2 100644 --- a/app/javascript/flavours/glitch/reducers/index.ts +++ b/app/javascript/flavours/glitch/reducers/index.ts @@ -25,6 +25,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'; @@ -68,6 +69,7 @@ const reducers = { search, media_attachments, notifications, + notificationGroups: notificationGroupsReducer, height_cache, custom_emojis, lists, diff --git a/app/javascript/flavours/glitch/reducers/markers.ts b/app/javascript/flavours/glitch/reducers/markers.ts index 380e9d3995..8b997e47be 100644 --- a/app/javascript/flavours/glitch/reducers/markers.ts +++ b/app/javascript/flavours/glitch/reducers/markers.ts @@ -1,6 +1,10 @@ import { createReducer } from '@reduxjs/toolkit'; -import { submitMarkersAction } from 'flavours/glitch/actions/markers'; +import { + submitMarkersAction, + fetchMarkers, +} from 'flavours/glitch/actions/markers'; +import { compareId } from 'flavours/glitch/compare_id'; const initialState = { home: '0', @@ -15,4 +19,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/flavours/glitch/reducers/notification_groups.ts b/app/javascript/flavours/glitch/reducers/notification_groups.ts new file mode 100644 index 0000000000..b0b284b696 --- /dev/null +++ b/app/javascript/flavours/glitch/reducers/notification_groups.ts @@ -0,0 +1,508 @@ +import { createReducer, isAnyOf } from '@reduxjs/toolkit'; + +import { + authorizeFollowRequestSuccess, + blockAccountSuccess, + muteAccountSuccess, + rejectFollowRequestSuccess, +} from 'flavours/glitch/actions/accounts_typed'; +import { focusApp, unfocusApp } from 'flavours/glitch/actions/app'; +import { blockDomainSuccess } from 'flavours/glitch/actions/domain_blocks_typed'; +import { fetchMarkers } from 'flavours/glitch/actions/markers'; +import { + clearNotifications, + fetchNotifications, + fetchNotificationsGap, + processNewNotificationForGroups, + loadPending, + updateScrollPosition, + markNotificationsAsRead, + mountNotifications, + unmountNotifications, +} from 'flavours/glitch/actions/notification_groups'; +import { + disconnectTimeline, + timelineDelete, +} from 'flavours/glitch/actions/timelines_typed'; +import type { ApiNotificationJSON } from 'flavours/glitch/api_types/notifications'; +import { compareId } from 'flavours/glitch/compare_id'; +import { usePendingItems } from 'flavours/glitch/initial_state'; +import { + NOTIFICATIONS_GROUP_MAX_AVATARS, + createNotificationGroupFromJSON, + createNotificationGroupFromNotificationJSON, +} from 'flavours/glitch/models/notification_group'; +import type { NotificationGroup } from 'flavours/glitch/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/flavours/glitch/reducers/notifications.js b/app/javascript/flavours/glitch/reducers/notifications.js index 226f2affe1..b3c138583c 100644 --- a/app/javascript/flavours/glitch/reducers/notifications.js +++ b/app/javascript/flavours/glitch/reducers/notifications.js @@ -12,6 +12,7 @@ import { import { fetchMarkers, } from '../actions/markers'; +import { clearNotifications } from '../actions/notification_groups'; import { NOTIFICATIONS_MOUNT, NOTIFICATIONS_UNMOUNT, @@ -21,7 +22,6 @@ import { NOTIFICATIONS_EXPAND_REQUEST, NOTIFICATIONS_EXPAND_FAIL, NOTIFICATIONS_FILTER_SET, - NOTIFICATIONS_CLEAR, NOTIFICATIONS_SCROLL_TOP, NOTIFICATIONS_LOAD_PENDING, NOTIFICATIONS_DELETE_MARKED_REQUEST, @@ -332,7 +332,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/flavours/glitch/selectors/notifications.ts b/app/javascript/flavours/glitch/selectors/notifications.ts new file mode 100644 index 0000000000..7cc64aa6c5 --- /dev/null +++ b/app/javascript/flavours/glitch/selectors/notifications.ts @@ -0,0 +1,34 @@ +import { createSelector } from '@reduxjs/toolkit'; + +import { compareId } from 'flavours/glitch/compare_id'; +import type { RootState } from 'flavours/glitch/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/flavours/glitch/selectors/settings.ts b/app/javascript/flavours/glitch/selectors/settings.ts new file mode 100644 index 0000000000..ce2b8b15e5 --- /dev/null +++ b/app/javascript/flavours/glitch/selectors/settings.ts @@ -0,0 +1,40 @@ +import type { RootState } from 'flavours/glitch/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/flavours/glitch/styles/components.scss b/app/javascript/flavours/glitch/styles/components.scss index 06225b61e6..bcc3655155 100644 --- a/app/javascript/flavours/glitch/styles/components.scss +++ b/app/javascript/flavours/glitch/styles/components.scss @@ -1790,10 +1790,19 @@ body > [data-popper-placement] { } } -.status__wrapper-direct { +.status__wrapper-direct, +.notification-ungrouped--direct { background: rgba($ui-highlight-color, 0.05); - .status__prepend { + &:focus { + background: rgba($ui-highlight-color, 0.1); + } +} + +.status__wrapper-direct, +.notification-ungrouped--direct { + .status__prepend, + .notification-ungrouped__header { color: $highlight-text-color; } } @@ -2389,41 +2398,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; } } } @@ -10747,8 +10743,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; @@ -10758,10 +10754,8 @@ noscript { color: $secondary-text-color; } - .icon { - width: 24px; - height: 24px; - padding: 2px; + .notification-group__icon { + color: inherit; } &__text { @@ -10899,6 +10893,251 @@ noscript { } } +.notification-group { + display: flex; + align-items: flex-start; + gap: 8px; + padding: 10px 14px; // glitch: reduced padding + 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 { + &__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; + cursor: pointer; + -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; From 8e0aed8ac73dda2138a71a090e1560ace9b9bcf1 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Fri, 19 Jul 2024 10:21:09 +0200 Subject: [PATCH 072/126] New Crowdin Translations (automated) (#31072) Co-authored-by: GitHub Actions --- app/javascript/mastodon/locales/an.json | 1 - app/javascript/mastodon/locales/ar.json | 1 - app/javascript/mastodon/locales/ast.json | 45 ++++++----- app/javascript/mastodon/locales/be.json | 1 - app/javascript/mastodon/locales/bg.json | 1 - app/javascript/mastodon/locales/bn.json | 1 - app/javascript/mastodon/locales/br.json | 1 - app/javascript/mastodon/locales/ca.json | 1 - app/javascript/mastodon/locales/ckb.json | 1 - app/javascript/mastodon/locales/co.json | 1 - app/javascript/mastodon/locales/cs.json | 1 - app/javascript/mastodon/locales/cy.json | 1 - app/javascript/mastodon/locales/da.json | 20 ++++- app/javascript/mastodon/locales/de.json | 15 +++- app/javascript/mastodon/locales/el.json | 1 - app/javascript/mastodon/locales/en-GB.json | 1 - app/javascript/mastodon/locales/eo.json | 1 - app/javascript/mastodon/locales/es-AR.json | 13 ++++ app/javascript/mastodon/locales/es-MX.json | 15 +++- app/javascript/mastodon/locales/es.json | 15 +++- app/javascript/mastodon/locales/et.json | 1 - app/javascript/mastodon/locales/eu.json | 1 - app/javascript/mastodon/locales/fa.json | 1 - app/javascript/mastodon/locales/fi.json | 1 - app/javascript/mastodon/locales/fo.json | 15 +++- app/javascript/mastodon/locales/fr-CA.json | 1 - app/javascript/mastodon/locales/fr.json | 1 - app/javascript/mastodon/locales/fy.json | 1 - app/javascript/mastodon/locales/ga.json | 39 ++++++---- app/javascript/mastodon/locales/gd.json | 1 - app/javascript/mastodon/locales/gl.json | 1 - app/javascript/mastodon/locales/he.json | 1 - app/javascript/mastodon/locales/hr.json | 1 - app/javascript/mastodon/locales/hu.json | 15 +++- app/javascript/mastodon/locales/hy.json | 1 - app/javascript/mastodon/locales/ia.json | 1 - app/javascript/mastodon/locales/id.json | 1 - app/javascript/mastodon/locales/ie.json | 1 - app/javascript/mastodon/locales/io.json | 1 - app/javascript/mastodon/locales/is.json | 1 - app/javascript/mastodon/locales/it.json | 13 ++++ app/javascript/mastodon/locales/ja.json | 1 - app/javascript/mastodon/locales/kab.json | 1 - app/javascript/mastodon/locales/kk.json | 1 - app/javascript/mastodon/locales/ko.json | 1 - app/javascript/mastodon/locales/ku.json | 1 - app/javascript/mastodon/locales/kw.json | 1 - app/javascript/mastodon/locales/la.json | 1 - app/javascript/mastodon/locales/lad.json | 1 - app/javascript/mastodon/locales/lt.json | 1 - app/javascript/mastodon/locales/lv.json | 1 - app/javascript/mastodon/locales/ms.json | 1 - app/javascript/mastodon/locales/my.json | 1 - app/javascript/mastodon/locales/nl.json | 15 +++- app/javascript/mastodon/locales/nn.json | 1 - app/javascript/mastodon/locales/no.json | 1 - app/javascript/mastodon/locales/oc.json | 1 - app/javascript/mastodon/locales/pl.json | 15 +++- app/javascript/mastodon/locales/pt-BR.json | 1 - app/javascript/mastodon/locales/pt-PT.json | 1 - app/javascript/mastodon/locales/ro.json | 1 - app/javascript/mastodon/locales/ru.json | 1 - app/javascript/mastodon/locales/sa.json | 1 - app/javascript/mastodon/locales/sc.json | 1 - app/javascript/mastodon/locales/sco.json | 1 - app/javascript/mastodon/locales/si.json | 1 - app/javascript/mastodon/locales/sk.json | 1 - app/javascript/mastodon/locales/sl.json | 13 ++++ app/javascript/mastodon/locales/sq.json | 1 - app/javascript/mastodon/locales/sr-Latn.json | 1 - app/javascript/mastodon/locales/sr.json | 1 - app/javascript/mastodon/locales/sv.json | 6 +- app/javascript/mastodon/locales/ta.json | 1 - app/javascript/mastodon/locales/te.json | 1 - app/javascript/mastodon/locales/th.json | 1 - app/javascript/mastodon/locales/tok.json | 1 - app/javascript/mastodon/locales/tr.json | 1 - app/javascript/mastodon/locales/uk.json | 1 - app/javascript/mastodon/locales/ur.json | 1 - app/javascript/mastodon/locales/uz.json | 1 - app/javascript/mastodon/locales/vi.json | 1 - app/javascript/mastodon/locales/zh-CN.json | 15 +++- app/javascript/mastodon/locales/zh-HK.json | 1 - app/javascript/mastodon/locales/zh-TW.json | 13 ++++ config/locales/activerecord.ast.yml | 2 +- config/locales/ast.yml | 78 ++++++++++++-------- config/locales/devise.ast.yml | 22 +++--- config/locales/devise.ga.yml | 2 +- config/locales/doorkeeper.ast.yml | 10 +-- config/locales/en-GB.yml | 1 + config/locales/es-AR.yml | 1 + config/locales/es-MX.yml | 2 + config/locales/es.yml | 2 + config/locales/ga.yml | 8 +- config/locales/he.yml | 1 + config/locales/lt.yml | 1 + config/locales/pl.yml | 2 + config/locales/simple_form.ast.yml | 29 ++++---- config/locales/simple_form.kab.yml | 1 + 99 files changed, 336 insertions(+), 176 deletions(-) diff --git a/app/javascript/mastodon/locales/an.json b/app/javascript/mastodon/locales/an.json index 752b6c3564..d8f41b29bd 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 5509769e04..9cfda3cbc2 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 3f32a8bf15..883737eb4a 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 df29fbd418..e2120d80d9 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 98e84c45d7..0e29f55e76 100644 --- a/app/javascript/mastodon/locales/bg.json +++ b/app/javascript/mastodon/locales/bg.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/bn.json b/app/javascript/mastodon/locales/bn.json index a203c43f03..6d64c00a2f 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 a150fb4902..76cd9d4574 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 3123e29d8d..1719b105f0 100644 --- a/app/javascript/mastodon/locales/ca.json +++ b/app/javascript/mastodon/locales/ca.json @@ -485,7 +485,6 @@ "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.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.", diff --git a/app/javascript/mastodon/locales/ckb.json b/app/javascript/mastodon/locales/ckb.json index 3ebf9391d2..379706a3e0 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 78f8e6fd78..4520663b52 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 12de5d5ecd..213fe5e530 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 9a3fab6155..e4c10cc142 100644 --- a/app/javascript/mastodon/locales/cy.json +++ b/app/javascript/mastodon/locales/cy.json @@ -481,7 +481,6 @@ "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.", diff --git a/app/javascript/mastodon/locales/da.json b/app/javascript/mastodon/locales/da.json index d8c178d295..9316884d71 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 0f3b3c91a9..3ba058b9a7 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 5442624b36..3c0ef467bf 100644 --- a/app/javascript/mastodon/locales/el.json +++ b/app/javascript/mastodon/locales/el.json @@ -389,7 +389,6 @@ "notification.follow_request": "Ο/H {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/en-GB.json b/app/javascript/mastodon/locales/en-GB.json index 94d7defc7e..6143c6e1ca 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/eo.json b/app/javascript/mastodon/locales/eo.json index e7cfc03468..211f4ad8d9 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 28e8de9237..2e22865493 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 c10a161015..837bbbc2ce 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 259fc1795b..a6cecf1605 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 94f5ef5d9e..b07229adec 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 97c4250d22..bd1b51ba3e 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 18f6466d48..9dc429f7de 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 0767dd5e37..4b330ec60b 100644 --- a/app/javascript/mastodon/locales/fi.json +++ b/app/javascript/mastodon/locales/fi.json @@ -485,7 +485,6 @@ "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.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.", diff --git a/app/javascript/mastodon/locales/fo.json b/app/javascript/mastodon/locales/fo.json index c27ffe0aa7..dd3d448834 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 4324855003..94b73bbf18 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 cd67cda539..fd256fe716 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 d787c16bf3..a04a5b25bf 100644 --- a/app/javascript/mastodon/locales/fy.json +++ b/app/javascript/mastodon/locales/fy.json @@ -455,7 +455,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 8c5039e2a4..711c97f66c 100644 --- a/app/javascript/mastodon/locales/ga.json +++ b/app/javascript/mastodon/locales/ga.json @@ -207,7 +207,7 @@ "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_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": "These hashtags are gaining traction among people on this and other servers of the decentralized network right now.", + "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", @@ -263,7 +263,7 @@ "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.", @@ -298,7 +298,7 @@ "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 {níl éinne} one {duine amháin} two {# daoine} few {# daoine} many {# daoine} other {# daoine}} b'fhéidir go mbeadh a fhios agat", + "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", @@ -340,7 +340,7 @@ "hashtag.column_settings.tag_mode.all": "Iad seo go léir", "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": "Include additional tags in this column", + "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", @@ -375,10 +375,10 @@ "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.column": "Colún fócas", + "keyboard_shortcuts.compose": "Fócas a chumadh textarea", "keyboard_shortcuts.description": "Cur síos", - "keyboard_shortcuts.direct": "to open direct messages column", + "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", @@ -387,12 +387,12 @@ "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": "Oscail liosta postálacha pinn", "keyboard_shortcuts.profile": "Oscail próifíl an t-údar", @@ -443,6 +443,8 @@ "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", @@ -468,8 +470,12 @@ "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ú", @@ -485,7 +491,8 @@ "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.", @@ -503,6 +510,8 @@ "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", @@ -666,9 +675,13 @@ "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", @@ -787,11 +800,11 @@ "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": "Describe for people with hearing loss", + "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.thumbnail": "Athraigh mionsamhail", - "upload_form.video_description": "Describe for people with hearing loss or visual impairment", + "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…", diff --git a/app/javascript/mastodon/locales/gd.json b/app/javascript/mastodon/locales/gd.json index fec025045c..93268c2715 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 c1e0f97f80..1f76ae951d 100644 --- a/app/javascript/mastodon/locales/gl.json +++ b/app/javascript/mastodon/locales/gl.json @@ -485,7 +485,6 @@ "notification.moderation_warning.action_silence": "A túa conta foi limitada.", "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.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.", diff --git a/app/javascript/mastodon/locales/he.json b/app/javascript/mastodon/locales/he.json index 8111a56e89..148b3285dd 100644 --- a/app/javascript/mastodon/locales/he.json +++ b/app/javascript/mastodon/locales/he.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/hr.json b/app/javascript/mastodon/locales/hr.json index c8f6f01862..5d087dae94 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 1fcadc8f9c..fd9ce38eb1 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 b4abe9bf09..4a197185e3 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 ace6402ee1..db1ead30c8 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 f4e5e1baea..e139796bf1 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 c75788c430..3ece43918b 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 6aa954ae57..839939687d 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 1a38591b85..733e2e541d 100644 --- a/app/javascript/mastodon/locales/is.json +++ b/app/javascript/mastodon/locales/is.json @@ -485,7 +485,6 @@ "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.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.", diff --git a/app/javascript/mastodon/locales/it.json b/app/javascript/mastodon/locales/it.json index 73c4f9ba60..419b6bcd9f 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 36974c7602..13583bc1d8 100644 --- a/app/javascript/mastodon/locales/ja.json +++ b/app/javascript/mastodon/locales/ja.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/kab.json b/app/javascript/mastodon/locales/kab.json index ab0a6ce22b..d12cf04366 100644 --- a/app/javascript/mastodon/locales/kab.json +++ b/app/javascript/mastodon/locales/kab.json @@ -383,7 +383,6 @@ "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ɣ", diff --git a/app/javascript/mastodon/locales/kk.json b/app/javascript/mastodon/locales/kk.json index efeee16c65..74fb33a91a 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 fe3582c1d8..6619cdb2d6 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 5248cdfa51..3821216a9a 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 1afcf645cf..f59f342cbe 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 aa209fcc00..e35e7112be 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 292f00818c..ee45e09ad1 100644 --- a/app/javascript/mastodon/locales/lad.json +++ b/app/javascript/mastodon/locales/lad.json @@ -457,7 +457,6 @@ "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", - "notification.poll": "Anketa en ke votates eskapo", "notification.reblog": "{name} repartajo tu publikasyon", "notification.relationships_severance_event": "Koneksyones pedridas kon {name}", "notification.relationships_severance_event.learn_more": "Ambezate mas", diff --git a/app/javascript/mastodon/locales/lt.json b/app/javascript/mastodon/locales/lt.json index 258e8ce08e..f8a2995c57 100644 --- a/app/javascript/mastodon/locales/lt.json +++ b/app/javascript/mastodon/locales/lt.json @@ -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 701569fa05..d4623a8b31 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 88c093bdee..dc34867106 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 46c8d18069..cb3ea9723b 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 8246d8dfd2..05c8aa4e26 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", @@ -485,7 +491,8 @@ "notification.moderation_warning.action_silence": "Jouw account is beperkt.", "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.poll": "Een peiling waaraan je hebt deelgenomen, is verlopen", + "notification.private_mention": "{name} heeft je privé genoemd", "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": "Groepsmeldingen", "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": "regel 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 0fb0edf0a0..f5efedb1ae 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 2bda373404..f2476bf14c 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 d977eed4af..c02c821afc 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 ddfe1d4fbc..75987f5d29 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 34d0ba36e6..9ebde4e6a4 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 6a6feca309..a0359fd868 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 35abf1b021..bbae711269 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 97a1f0b09c..971d6c77ca 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 c3880a6b03..7f8dae326e 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 8955573737..f13514fd02 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 397f63fed4..7c4d1db60e 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 3a67beed52..c4f82c4133 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 ed877f7667..cff79c6b9b 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 2a3d74a80f..b8c995b8d1 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 96b7b3fefc..219561688b 100644 --- a/app/javascript/mastodon/locales/sq.json +++ b/app/javascript/mastodon/locales/sq.json @@ -485,7 +485,6 @@ "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.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ë.", diff --git a/app/javascript/mastodon/locales/sr-Latn.json b/app/javascript/mastodon/locales/sr-Latn.json index 71b69d428a..38ff12bdcf 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 2c4649f9d0..047e8cf3a8 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 1833a2cfde..ba07d5a1c7 100644 --- a/app/javascript/mastodon/locales/sv.json +++ b/app/javascript/mastodon/locales/sv.json @@ -469,6 +469,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 +485,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 +503,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,7 +668,9 @@ "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.open": "Öppna rapport", "search.no_recent_searches": "Inga sökningar nyligen", diff --git a/app/javascript/mastodon/locales/ta.json b/app/javascript/mastodon/locales/ta.json index d44ac424f4..bb26986b81 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 c06472561f..471890b9a3 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 64abb394bf..083a0eb33f 100644 --- a/app/javascript/mastodon/locales/th.json +++ b/app/javascript/mastodon/locales/th.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/tok.json b/app/javascript/mastodon/locales/tok.json index fcdef5f32c..e581978f24 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 ac39a3fd7b..0b20b60f9e 100644 --- a/app/javascript/mastodon/locales/tr.json +++ b/app/javascript/mastodon/locales/tr.json @@ -485,7 +485,6 @@ "notification.moderation_warning.action_silence": "Hesabınız sınırlandırıldı.", "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.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.", diff --git a/app/javascript/mastodon/locales/uk.json b/app/javascript/mastodon/locales/uk.json index 67ebb031ae..76abe8d299 100644 --- a/app/javascript/mastodon/locales/uk.json +++ b/app/javascript/mastodon/locales/uk.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/ur.json b/app/javascript/mastodon/locales/ur.json index cf53eb6fe8..3c61846e9c 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 4824b1d332..90ad67d287 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 70932d10be..7a88bee364 100644 --- a/app/javascript/mastodon/locales/vi.json +++ b/app/javascript/mastodon/locales/vi.json @@ -485,7 +485,6 @@ "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.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.", diff --git a/app/javascript/mastodon/locales/zh-CN.json b/app/javascript/mastodon/locales/zh-CN.json index f2accae0d0..f6c0feecfd 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 09a497e889..4b717a77da 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 b9a5fc0714..dca4cd134a 100644 --- a/app/javascript/mastodon/locales/zh-TW.json +++ b/app/javascript/mastodon/locales/zh-TW.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} 關於 {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": "快速過濾器", @@ -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": "搜尋", diff --git a/config/locales/activerecord.ast.yml b/config/locales/activerecord.ast.yml index 2d532071a9..d139a32570 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/ast.yml b/config/locales/ast.yml index 9e6ec6d233..567e5357eb 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/devise.ast.yml b/config/locales/devise.ast.yml index 47372c2f07..c353607043 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.ga.yml b/config/locales/devise.ga.yml index cc8ae0874e..ca51bb9467 100644 --- a/config/locales/devise.ga.yml +++ b/config/locales/devise.ga.yml @@ -91,7 +91,7 @@ ga: 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: Your password has been changed successfully. + 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. diff --git a/config/locales/doorkeeper.ast.yml b/config/locales/doorkeeper.ast.yml index 0564e49dac..0df15a07b6 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/en-GB.yml b/config/locales/en-GB.yml index a45ba290b7..fecdab4c7d 100644 --- a/config/locales/en-GB.yml +++ b/config/locales/en-GB.yml @@ -639,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/es-AR.yml b/config/locales/es-AR.yml index 8c55551ce0..5add90ae62 100644 --- a/config/locales/es-AR.yml +++ b/config/locales/es-AR.yml @@ -639,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 976b7a4f30..22531d2403 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 aef5100a6d..567526fe8b 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/ga.yml b/config/locales/ga.yml index 370f3e82e6..647c46d7cf 100644 --- a/config/locales/ga.yml +++ b/config/locales/ga.yml @@ -1656,7 +1656,7 @@ ga: mutual: Frithpháirteach primary: Príomha relationship: Gaol - remove_selected_domains: Remove all followers from the selected domains + 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 @@ -2029,6 +2029,6 @@ ga: 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: This browser doesn't support security keys - otp_required: To use security keys please enable two-factor authentication first. - registered_on: Registered on %{date} + 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/he.yml b/config/locales/he.yml index ecafbec960..105bd059f2 100644 --- a/config/locales/he.yml +++ b/config/locales/he.yml @@ -663,6 +663,7 @@ he: report: 'דווח על #%{id}' reported_account: חשבון מדווח reported_by: דווח על ידי + reported_with_application: דיווחים באמצעות יישומון resolved: פתור resolved_msg: הדו"ח נפתר בהצלחה! skip_to_actions: דלג/י לפעולות diff --git a/config/locales/lt.yml b/config/locales/lt.yml index 004f5b4d04..1e717b6c20 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: diff --git a/config/locales/pl.yml b/config/locales/pl.yml index 7497f17843..b0c733102e 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/simple_form.ast.yml b/config/locales/simple_form.ast.yml index d1950ab15f..c222c9aef5 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.kab.yml b/config/locales/simple_form.kab.yml index 63e2b9aacf..e68355da6a 100644 --- a/config/locales/simple_form.kab.yml +++ b/config/locales/simple_form.kab.yml @@ -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 From 784e0885333769b47c8a94fde0c34bb14b1b93bb Mon Sep 17 00:00:00 2001 From: Michael Stanclift Date: Fri, 19 Jul 2024 03:30:26 -0500 Subject: [PATCH 073/126] Fix double border on column filter on narrow screens (#31068) --- app/javascript/styles/mastodon/components.scss | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/app/javascript/styles/mastodon/components.scss b/app/javascript/styles/mastodon/components.scss index 5a0a41c978..adcbad202d 100644 --- a/app/javascript/styles/mastodon/components.scss +++ b/app/javascript/styles/mastodon/components.scss @@ -7380,6 +7380,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; From 05342529dd5ecdd6a737451f5c3ca55de24af3e9 Mon Sep 17 00:00:00 2001 From: Matt Jankowski Date: Fri, 19 Jul 2024 04:31:34 -0400 Subject: [PATCH 074/126] Reduce factory creation in AP activity move spec (#31064) --- spec/lib/activitypub/activity/move_spec.rb | 67 +++++++++------------- 1 file changed, 27 insertions(+), 40 deletions(-) diff --git a/spec/lib/activitypub/activity/move_spec.rb b/spec/lib/activitypub/activity/move_spec.rb index d69ef21516..02c3380ab3 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 @@ RSpec.describe ActivityPub::Activity::Move do 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 @@ RSpec.describe ActivityPub::Activity::Move do 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 From adadfdbc0355d9195815d25ad22fdee96e13ce6c Mon Sep 17 00:00:00 2001 From: Matt Jankowski Date: Fri, 19 Jul 2024 04:32:43 -0400 Subject: [PATCH 075/126] Update `strong_migrations` to version 2.0.0 (#31061) --- Gemfile | 2 +- Gemfile.lock | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/Gemfile b/Gemfile index ef52d50cac..135b94c773 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 c9781a4050..c08c14cb5c 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -821,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) @@ -1046,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) From 2e63e802b32599537d80f524628a5affeb089df5 Mon Sep 17 00:00:00 2001 From: Claire Date: Fri, 19 Jul 2024 12:13:50 +0200 Subject: [PATCH 076/126] Fix inconsistent padding in glitch-soc's grouped notifications (#2784) --- app/javascript/flavours/glitch/styles/components.scss | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/javascript/flavours/glitch/styles/components.scss b/app/javascript/flavours/glitch/styles/components.scss index bcc3655155..0bc63e247a 100644 --- a/app/javascript/flavours/glitch/styles/components.scss +++ b/app/javascript/flavours/glitch/styles/components.scss @@ -11046,7 +11046,7 @@ noscript { } .notification-ungrouped { - padding: 16px 24px; + padding: 10px 14px; // glitch: reduced padding border-bottom: 1px solid var(--background-border-color); &__header { From e768b23aa995130c14a7160165eabcf1e8570dfd Mon Sep 17 00:00:00 2001 From: Claire Date: Fri, 19 Jul 2024 17:26:44 +0200 Subject: [PATCH 077/126] Remove routerHistory parameters from composer actions (#31077) --- app/javascript/mastodon/actions/compose.js | 29 ++++++++++--------- app/javascript/mastodon/actions/statuses.js | 8 ++--- app/javascript/mastodon/components/router.tsx | 2 +- app/javascript/mastodon/components/status.jsx | 4 +-- .../mastodon/components/status_action_bar.jsx | 12 ++++---- .../mastodon/containers/status_container.jsx | 26 ++++++++--------- .../account_timeline/components/header.jsx | 11 +++---- .../containers/header_container.jsx | 8 ++--- .../compose/components/compose_form.jsx | 7 ++--- .../containers/compose_form_container.js | 4 +-- .../components/conversation.jsx | 6 ++-- .../notifications/components/notification.jsx | 2 +- .../containers/notification_container.js | 4 +-- .../mastodon/features/onboarding/index.jsx | 7 ++--- .../picture_in_picture/components/footer.jsx | 4 +-- .../features/status/components/action_bar.jsx | 15 ++++------ .../containers/detailed_status_container.js | 20 ++++++------- .../mastodon/features/status/index.jsx | 22 +++++++------- 18 files changed, 91 insertions(+), 100 deletions(-) diff --git a/app/javascript/mastodon/actions/compose.js b/app/javascript/mastodon/actions/compose.js index 0bcba7d57f..4f2ed450dd 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'; @@ -88,9 +89,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'); } }; @@ -110,14 +111,14 @@ 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); }; } @@ -133,38 +134,38 @@ 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 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']); @@ -214,8 +215,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)); @@ -249,7 +250,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/statuses.js b/app/javascript/mastodon/actions/statuses.js index a60b80dc2c..1907d3aa91 100644 --- a/app/javascript/mastodon/actions/statuses.js +++ b/app/javascript/mastodon/actions/statuses.js @@ -93,7 +93,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')) { @@ -104,7 +104,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)); @@ -124,7 +124,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]); @@ -141,7 +141,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)); diff --git a/app/javascript/mastodon/components/router.tsx b/app/javascript/mastodon/components/router.tsx index 42b926659c..33fb60abb7 100644 --- a/app/javascript/mastodon/components/router.tsx +++ b/app/javascript/mastodon/components/router.tsx @@ -22,7 +22,7 @@ type LocationState = MastodonLocationState | null | undefined; type HistoryPath = Path | LocationDescriptor; -const browserHistory = createBrowserHistory(); +export const browserHistory = createBrowserHistory(); const originalPush = browserHistory.push.bind(browserHistory); const originalReplace = browserHistory.replace.bind(browserHistory); diff --git a/app/javascript/mastodon/components/status.jsx b/app/javascript/mastodon/components/status.jsx index 1723080e95..fe5f38889b 100644 --- a/app/javascript/mastodon/components/status.jsx +++ b/app/javascript/mastodon/components/status.jsx @@ -268,7 +268,7 @@ class Status extends ImmutablePureComponent { handleHotkeyReply = e => { e.preventDefault(); - this.props.onReply(this._properStatus(), this.props.history); + this.props.onReply(this._properStatus()); }; handleHotkeyFavourite = () => { @@ -281,7 +281,7 @@ class Status extends ImmutablePureComponent { handleHotkeyMention = e => { e.preventDefault(); - this.props.onMention(this._properStatus().get('account'), this.props.history); + this.props.onMention(this._properStatus().get('account')); }; handleHotkeyOpen = () => { diff --git a/app/javascript/mastodon/components/status_action_bar.jsx b/app/javascript/mastodon/components/status_action_bar.jsx index c79eae8460..2a7bd0a305 100644 --- a/app/javascript/mastodon/components/status_action_bar.jsx +++ b/app/javascript/mastodon/components/status_action_bar.jsx @@ -118,7 +118,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); } @@ -157,15 +157,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 = () => { @@ -173,11 +173,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/containers/status_container.jsx b/app/javascript/mastodon/containers/status_container.jsx index 4a9b525777..e2c0af3533 100644 --- a/app/javascript/mastodon/containers/status_container.jsx +++ b/app/javascript/mastodon/containers/status_container.jsx @@ -76,7 +76,7 @@ const makeMapStateToProps = () => { const mapDispatchToProps = (dispatch, { intl, contextType }) => ({ - onReply (status, router) { + onReply (status) { dispatch((_, getState) => { let state = getState(); @@ -86,10 +86,10 @@ 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)); } }); }, @@ -144,22 +144,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) { @@ -168,11 +168,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'))); } }); }, @@ -185,12 +185,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) { diff --git a/app/javascript/mastodon/features/account_timeline/components/header.jsx b/app/javascript/mastodon/features/account_timeline/components/header.jsx index a2463b8764..403c423025 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'; @@ -36,7 +34,6 @@ class Header extends ImmutablePureComponent { hideTabs: PropTypes.bool, domain: PropTypes.string.isRequired, hidden: PropTypes.bool, - ...WithRouterPropTypes, }; handleFollow = () => { @@ -48,11 +45,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 = () => { @@ -155,4 +152,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 d55d8c58e4..90298879d7 100644 --- a/app/javascript/mastodon/features/account_timeline/containers/header_container.jsx +++ b/app/javascript/mastodon/features/account_timeline/containers/header_container.jsx @@ -77,12 +77,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 9b4d3dfeb5..b5e8dabb7b 100644 --- a/app/javascript/mastodon/features/compose/components/compose_form.jsx +++ b/app/javascript/mastodon/features/compose/components/compose_form.jsx @@ -10,8 +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'; @@ -71,7 +69,6 @@ class ComposeForm extends ImmutablePureComponent { singleColumn: PropTypes.bool, lang: PropTypes.string, maxChars: PropTypes.number, - ...WithOptionalRouterPropTypes }; static defaultProps = { @@ -120,7 +117,7 @@ class ComposeForm extends ImmutablePureComponent { return; } - this.props.onSubmit(this.props.history || null); + this.props.onSubmit(); if (e) { e.preventDefault(); @@ -317,4 +314,4 @@ class ComposeForm extends ImmutablePureComponent { } -export default withOptionalRouter(injectIntl(ComposeForm)); +export default injectIntl(ComposeForm); 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 b5e5300334..bda2edba60 100644 --- a/app/javascript/mastodon/features/compose/containers/compose_form_container.js +++ b/app/javascript/mastodon/features/compose/containers/compose_form_container.js @@ -37,8 +37,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 a2b72f7162..63dc705e40 100644 --- a/app/javascript/mastodon/features/direct_timeline/components/conversation.jsx +++ b/app/javascript/mastodon/features/direct_timeline/components/conversation.jsx @@ -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)); diff --git a/app/javascript/mastodon/features/notifications/components/notification.jsx b/app/javascript/mastodon/features/notifications/components/notification.jsx index 70a3252509..f1eada1359 100644 --- a/app/javascript/mastodon/features/notifications/components/notification.jsx +++ b/app/javascript/mastodon/features/notifications/components/notification.jsx @@ -101,7 +101,7 @@ class Notification extends ImmutablePureComponent { e.preventDefault(); const { notification, onMention } = this.props; - onMention(notification.get('account'), this.props.history); + onMention(notification.get('account')); }; handleHotkeyFavourite = () => { diff --git a/app/javascript/mastodon/features/notifications/containers/notification_container.js b/app/javascript/mastodon/features/notifications/containers/notification_container.js index 650acf4ccd..7b7e6e919c 100644 --- a/app/javascript/mastodon/features/notifications/containers/notification_container.js +++ b/app/javascript/mastodon/features/notifications/containers/notification_container.js @@ -34,8 +34,8 @@ const makeMapStateToProps = () => { }; const mapDispatchToProps = dispatch => ({ - onMention: (account, router) => { - dispatch(mentionCompose(account, router)); + onMention: (account) => { + dispatch(mentionCompose(account)); }, onModalReblog (status, privacy) { diff --git a/app/javascript/mastodon/features/onboarding/index.jsx b/app/javascript/mastodon/features/onboarding/index.jsx index 529d53f257..d100a1c3d5 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 ba0642da28..8404bf61b7 100644 --- a/app/javascript/mastodon/features/picture_in_picture/components/footer.jsx +++ b/app/javascript/mastodon/features/picture_in_picture/components/footer.jsx @@ -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 = () => { diff --git a/app/javascript/mastodon/features/status/components/action_bar.jsx b/app/javascript/mastodon/features/status/components/action_bar.jsx index d610539987..d90ca464a7 100644 --- a/app/javascript/mastodon/features/status/components/action_bar.jsx +++ b/app/javascript/mastodon/features/status/components/action_bar.jsx @@ -4,7 +4,6 @@ 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'; @@ -23,7 +22,6 @@ import RepeatPrivateIcon from '@/svg-icons/repeat_private.svg?react'; import RepeatPrivateActiveIcon from '@/svg-icons/repeat_private_active.svg?react'; import { identityContextPropShape, withIdentity } from 'mastodon/identity_context'; import { PERMISSION_MANAGE_USERS, PERMISSION_MANAGE_FEDERATION } from 'mastodon/permissions'; -import { WithRouterPropTypes } from 'mastodon/utils/react_router'; import { IconButton } from '../../../components/icon_button'; import DropdownMenuContainer from '../../../containers/dropdown_menu_container'; @@ -91,7 +89,6 @@ class ActionBar extends PureComponent { onPin: PropTypes.func, onEmbed: PropTypes.func, intl: PropTypes.object.isRequired, - ...WithRouterPropTypes, }; handleReplyClick = () => { @@ -111,23 +108,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 = () => { @@ -323,4 +320,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 c3d4fec4db..f85c3822d7 100644 --- a/app/javascript/mastodon/features/status/containers/detailed_status_container.js +++ b/app/javascript/mastodon/features/status/containers/detailed_status_container.js @@ -55,7 +55,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) { @@ -64,11 +64,11 @@ 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)); } }); }, @@ -115,27 +115,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) { diff --git a/app/javascript/mastodon/features/status/index.jsx b/app/javascript/mastodon/features/status/index.jsx index 7f37cb50d2..b0fbea9e22 100644 --- a/app/javascript/mastodon/features/status/index.jsx +++ b/app/javascript/mastodon/features/status/index.jsx @@ -280,11 +280,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({ @@ -336,33 +336,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) => { From 3a00f89aa1f2280b995512cd5f91568e6d349cc6 Mon Sep 17 00:00:00 2001 From: kyori19 Date: Sat, 20 Jul 2024 00:31:48 +0900 Subject: [PATCH 078/126] Respect `Account::DISPLAY_NAME_LENGTH_LIMIT` in account spec correctly (#31075) --- spec/models/account_spec.rb | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/spec/models/account_spec.rb b/spec/models/account_spec.rb index dfb1f5bc61..5f918f159a 100644 --- a/spec/models/account_spec.rb +++ b/spec/models/account_spec.rb @@ -775,7 +775,7 @@ RSpec.describe Account do 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 @@ -821,7 +821,7 @@ RSpec.describe Account do 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 @@ -837,6 +837,10 @@ RSpec.describe Account do '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 From 65a8dc7869360bd4e4fb45d876f7a2bd019d16c8 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Fri, 19 Jul 2024 17:32:06 +0200 Subject: [PATCH 079/126] chore(deps): update dependency selenium-webdriver to v4.23.0 (#31073) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- Gemfile.lock | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Gemfile.lock b/Gemfile.lock index c08c14cb5c..006a918446 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -781,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) @@ -894,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) From 0397df9bef82042221f35e9938ad5b917fa1d4fc Mon Sep 17 00:00:00 2001 From: Matt Jankowski Date: Fri, 19 Jul 2024 11:32:42 -0400 Subject: [PATCH 080/126] Resolve `TODO` in `api/v1/admin/domain_*` controllers (#31067) --- app/controllers/api/v1/admin/domain_allows_controller.rb | 7 +------ app/controllers/api/v1/admin/domain_blocks_controller.rb | 7 +------ 2 files changed, 2 insertions(+), 12 deletions(-) diff --git a/app/controllers/api/v1/admin/domain_allows_controller.rb b/app/controllers/api/v1/admin/domain_allows_controller.rb index 9801d832b8..0cd5aebd53 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 @@ class Api::V1::Admin::DomainAllowsController < Api::BaseController 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 a20a4a9c7f..28d91ef93c 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 @@ class Api::V1::Admin::DomainBlocksController < Api::BaseController 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_reports, :private_comment, :public_comment, :obfuscate) end From 9f05a06dee264a80827a03569664931f8d443588 Mon Sep 17 00:00:00 2001 From: Michael Stanclift Date: Fri, 19 Jul 2024 03:30:26 -0500 Subject: [PATCH 081/126] [Glitch] Fix double border on column filter on narrow screens Port 784e0885333769b47c8a94fde0c34bb14b1b93bb to glitch-soc Signed-off-by: Claire --- app/javascript/flavours/glitch/styles/components.scss | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/app/javascript/flavours/glitch/styles/components.scss b/app/javascript/flavours/glitch/styles/components.scss index 0bc63e247a..cb22ca3674 100644 --- a/app/javascript/flavours/glitch/styles/components.scss +++ b/app/javascript/flavours/glitch/styles/components.scss @@ -7933,6 +7933,11 @@ img.modal-warning { display: flex; flex-shrink: 0; + @media screen and (max-width: $no-gap-breakpoint) { + border-right: 0; + border-left: 0; + } + button { background: transparent; border: 0; From 95984b729a8465da36c51182e0fe5a8e518475cb Mon Sep 17 00:00:00 2001 From: Claire Date: Fri, 19 Jul 2024 17:26:44 +0200 Subject: [PATCH 082/126] [Glitch] Remove routerHistory parameters from composer actions Port e768b23aa995130c14a7160165eabcf1e8570dfd to glitch-soc Signed-off-by: Claire --- .../flavours/glitch/actions/compose.js | 30 +++++++++---------- .../flavours/glitch/actions/statuses.js | 8 ++--- .../flavours/glitch/components/router.tsx | 2 +- .../flavours/glitch/components/status.jsx | 4 +-- .../glitch/components/status_action_bar.jsx | 12 ++++---- .../glitch/containers/status_container.js | 26 ++++++++-------- .../account_timeline/components/header.jsx | 11 +++---- .../containers/header_container.jsx | 8 ++--- .../compose/components/compose_form.jsx | 9 ++---- .../containers/compose_form_container.js | 8 ++--- .../components/conversation.jsx | 6 ++-- .../notifications/components/notification.jsx | 2 +- .../containers/notification_container.js | 4 +-- .../glitch/features/onboarding/index.jsx | 7 ++--- .../picture_in_picture/components/footer.jsx | 4 +-- .../features/status/components/action_bar.jsx | 15 ++++------ .../containers/detailed_status_container.js | 20 ++++++------- .../flavours/glitch/features/status/index.jsx | 22 +++++++------- 18 files changed, 94 insertions(+), 104 deletions(-) diff --git a/app/javascript/flavours/glitch/actions/compose.js b/app/javascript/flavours/glitch/actions/compose.js index 8eab532f55..2041278a1c 100644 --- a/app/javascript/flavours/glitch/actions/compose.js +++ b/app/javascript/flavours/glitch/actions/compose.js @@ -4,6 +4,7 @@ import axios from 'axios'; import { throttle } from 'lodash'; import api from 'flavours/glitch/api'; +import { browserHistory } from 'flavours/glitch/components/router'; import { search as emojiSearch } from 'flavours/glitch/features/emoji/emoji_mart_search_light'; import { tagHistory } from 'flavours/glitch/settings'; import { recoverHashtags } from 'flavours/glitch/utils/hashtag'; @@ -94,9 +95,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'); } }; @@ -117,7 +118,7 @@ export function changeCompose(text) { }; } -export function replyCompose(status, routerHistory) { +export function replyCompose(status) { return (dispatch, getState) => { const prependCWRe = getState().getIn(['local_settings', 'prepend_cw_re']); dispatch({ @@ -126,7 +127,7 @@ export function replyCompose(status, routerHistory) { prependCWRe: prependCWRe, }); - ensureComposeIsVisible(getState, routerHistory); + ensureComposeIsVisible(getState); }; } @@ -142,38 +143,38 @@ 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 directCompose(account) { return (dispatch, getState) => { dispatch({ type: COMPOSE_DIRECT, account: account, }); - ensureComposeIsVisible(getState, routerHistory); + ensureComposeIsVisible(getState); }; } -export function submitCompose(routerHistory, overridePrivacy = null) { +export function submitCompose(overridePrivacy = null) { return function (dispatch, getState) { let status = getState().getIn(['compose', 'text'], ''); const media = getState().getIn(['compose', 'media_attachments']); @@ -230,11 +231,10 @@ export function submitCompose(routerHistory, overridePrivacy = null) { 'Idempotency-Key': getState().getIn(['compose', 'idempotencyKey']), }, }).then(function (response) { - if (routerHistory - && (routerHistory.location.pathname === '/publish' || routerHistory.location.pathname === '/statuses/new') + if ((browserHistory.location.pathname === '/publish' || browserHistory.location.pathname === '/statuses/new') && window.history.state && !getState().getIn(['compose', 'advanced_options', 'threaded_mode'])) { - routerHistory.goBack(); + browserHistory.goBack(); } dispatch(insertIntoTagHistory(response.data.tags, status)); @@ -272,7 +272,7 @@ export function submitCompose(routerHistory, overridePrivacy = null) { 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) { diff --git a/app/javascript/flavours/glitch/actions/statuses.js b/app/javascript/flavours/glitch/actions/statuses.js index c4d292567d..054626bda0 100644 --- a/app/javascript/flavours/glitch/actions/statuses.js +++ b/app/javascript/flavours/glitch/actions/statuses.js @@ -94,7 +94,7 @@ export function redraft(status, raw_text, content_type) { }; } -export const editStatus = (id, routerHistory) => (dispatch, getState) => { +export const editStatus = (id) => (dispatch, getState) => { let status = getState().getIn(['statuses', id]); if (status.get('poll')) { @@ -105,7 +105,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, response.data.content_type)); }).catch(error => { dispatch(fetchStatusSourceFail(error)); @@ -125,7 +125,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]); @@ -142,7 +142,7 @@ export function deleteStatus(id, routerHistory, withRedraft = false) { if (withRedraft) { dispatch(redraft(status, response.data.text, response.data.content_type)); - ensureComposeIsVisible(getState, routerHistory); + ensureComposeIsVisible(getState); } }).catch(error => { dispatch(deleteStatusFail(id, error)); diff --git a/app/javascript/flavours/glitch/components/router.tsx b/app/javascript/flavours/glitch/components/router.tsx index 0637c35ada..48f35d8aed 100644 --- a/app/javascript/flavours/glitch/components/router.tsx +++ b/app/javascript/flavours/glitch/components/router.tsx @@ -22,7 +22,7 @@ type LocationState = MastodonLocationState | null | undefined; type HistoryPath = Path | LocationDescriptor; -const browserHistory = createBrowserHistory(); +export const browserHistory = createBrowserHistory(); const originalPush = browserHistory.push.bind(browserHistory); const originalReplace = browserHistory.replace.bind(browserHistory); diff --git a/app/javascript/flavours/glitch/components/status.jsx b/app/javascript/flavours/glitch/components/status.jsx index c115251d65..e002e4df8c 100644 --- a/app/javascript/flavours/glitch/components/status.jsx +++ b/app/javascript/flavours/glitch/components/status.jsx @@ -442,7 +442,7 @@ class Status extends ImmutablePureComponent { handleHotkeyReply = e => { e.preventDefault(); - this.props.onReply(this.props.status, this.props.history); + this.props.onReply(this.props.status); }; handleHotkeyFavourite = (e) => { @@ -459,7 +459,7 @@ class Status extends ImmutablePureComponent { handleHotkeyMention = e => { e.preventDefault(); - this.props.onMention(this.props.status.get('account'), this.props.history); + this.props.onMention(this.props.status.get('account')); }; handleHotkeyOpen = () => { diff --git a/app/javascript/flavours/glitch/components/status_action_bar.jsx b/app/javascript/flavours/glitch/components/status_action_bar.jsx index 3dfe403987..7b00f84f1b 100644 --- a/app/javascript/flavours/glitch/components/status_action_bar.jsx +++ b/app/javascript/flavours/glitch/components/status_action_bar.jsx @@ -108,7 +108,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); } @@ -145,15 +145,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 = () => { @@ -161,11 +161,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/flavours/glitch/containers/status_container.js b/app/javascript/flavours/glitch/containers/status_container.js index 1430a0c845..a05ed5fe4f 100644 --- a/app/javascript/flavours/glitch/containers/status_container.js +++ b/app/javascript/flavours/glitch/containers/status_container.js @@ -93,7 +93,7 @@ const makeMapStateToProps = () => { const mapDispatchToProps = (dispatch, { intl, contextType }) => ({ - onReply (status, router) { + onReply (status) { dispatch((_, getState) => { let state = getState(); @@ -104,11 +104,11 @@ const mapDispatchToProps = (dispatch, { intl, contextType }) => ({ message: intl.formatMessage(messages.replyMessage), confirm: intl.formatMessage(messages.replyConfirm), onDoNotAsk: () => dispatch(changeLocalSetting(['confirm_before_clearing_draft'], false)), - onConfirm: () => dispatch(replyCompose(status, router)), + onConfirm: () => dispatch(replyCompose(status)), }, })); } else { - dispatch(replyCompose(status, router)); + dispatch(replyCompose(status)); } }); }, @@ -182,22 +182,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) { @@ -206,11 +206,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'))); } }); }, @@ -223,12 +223,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) { diff --git a/app/javascript/flavours/glitch/features/account_timeline/components/header.jsx b/app/javascript/flavours/glitch/features/account_timeline/components/header.jsx index 37258d9d83..10a035a0fc 100644 --- a/app/javascript/flavours/glitch/features/account_timeline/components/header.jsx +++ b/app/javascript/flavours/glitch/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 'flavours/glitch/utils/react_router'; - import ActionBar from '../../account/components/action_bar'; import InnerHeader from '../../account/components/header'; @@ -36,7 +34,6 @@ class Header extends ImmutablePureComponent { hideTabs: PropTypes.bool, domain: PropTypes.string.isRequired, hidden: PropTypes.bool, - ...WithRouterPropTypes, }; handleFollow = () => { @@ -48,11 +45,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 = () => { @@ -158,4 +155,4 @@ class Header extends ImmutablePureComponent { } -export default withRouter(Header); +export default Header; diff --git a/app/javascript/flavours/glitch/features/account_timeline/containers/header_container.jsx b/app/javascript/flavours/glitch/features/account_timeline/containers/header_container.jsx index 1e85a08cd9..ba1241d829 100644 --- a/app/javascript/flavours/glitch/features/account_timeline/containers/header_container.jsx +++ b/app/javascript/flavours/glitch/features/account_timeline/containers/header_container.jsx @@ -75,12 +75,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/flavours/glitch/features/compose/components/compose_form.jsx b/app/javascript/flavours/glitch/features/compose/components/compose_form.jsx index 6f16abfc7f..ffed051c37 100644 --- a/app/javascript/flavours/glitch/features/compose/components/compose_form.jsx +++ b/app/javascript/flavours/glitch/features/compose/components/compose_form.jsx @@ -10,8 +10,6 @@ import ImmutablePureComponent from 'react-immutable-pure-component'; import { length } from 'stringz'; -import { WithOptionalRouterPropTypes, withOptionalRouter } from 'flavours/glitch/utils/react_router'; - import AutosuggestInput from '../../../components/autosuggest_input'; import AutosuggestTextarea from '../../../components/autosuggest_textarea'; import { Button } from '../../../components/button'; @@ -81,7 +79,6 @@ class ComposeForm extends ImmutablePureComponent { singleColumn: PropTypes.bool, lang: PropTypes.string, maxChars: PropTypes.number, - ...WithOptionalRouterPropTypes }; static defaultProps = { @@ -141,9 +138,9 @@ class ComposeForm extends ImmutablePureComponent { // Submit unless there are media with missing descriptions if (this.props.mediaDescriptionConfirmation && this.props.media && this.props.media.some(item => !item.get('description'))) { const firstWithoutDescription = this.props.media.find(item => !item.get('description')); - this.props.onMediaDescriptionConfirm(this.props.history || null, firstWithoutDescription.get('id'), overridePrivacy); + this.props.onMediaDescriptionConfirm(firstWithoutDescription.get('id'), overridePrivacy); } else { - this.props.onSubmit(this.props.history || null, overridePrivacy); + this.props.onSubmit(overridePrivacy); } }; @@ -351,4 +348,4 @@ class ComposeForm extends ImmutablePureComponent { } -export default withOptionalRouter(injectIntl(ComposeForm)); +export default injectIntl(ComposeForm); diff --git a/app/javascript/flavours/glitch/features/compose/containers/compose_form_container.js b/app/javascript/flavours/glitch/features/compose/containers/compose_form_container.js index 067621c84b..227e793869 100644 --- a/app/javascript/flavours/glitch/features/compose/containers/compose_form_container.js +++ b/app/javascript/flavours/glitch/features/compose/containers/compose_form_container.js @@ -82,8 +82,8 @@ const mapDispatchToProps = (dispatch, { intl }) => ({ dispatch(changeCompose(text)); }, - onSubmit (router, overridePrivacy = null) { - dispatch(submitCompose(router, overridePrivacy)); + onSubmit (overridePrivacy = null) { + dispatch(submitCompose(overridePrivacy)); }, onClearSuggestions () { @@ -110,14 +110,14 @@ const mapDispatchToProps = (dispatch, { intl }) => ({ dispatch(insertEmojiCompose(position, data, needsSpace)); }, - onMediaDescriptionConfirm (routerHistory, mediaId, overridePrivacy = null) { + onMediaDescriptionConfirm (mediaId, overridePrivacy = null) { dispatch(openModal({ modalType: 'CONFIRM', modalProps: { message: intl.formatMessage(messages.missingDescriptionMessage), confirm: intl.formatMessage(messages.missingDescriptionConfirm), onConfirm: () => { - dispatch(submitCompose(routerHistory, overridePrivacy)); + dispatch(submitCompose(overridePrivacy)); }, secondary: intl.formatMessage(messages.missingDescriptionEdit), onSecondary: () => dispatch(openModal({ diff --git a/app/javascript/flavours/glitch/features/direct_timeline/components/conversation.jsx b/app/javascript/flavours/glitch/features/direct_timeline/components/conversation.jsx index 7071c8719d..839de34dd4 100644 --- a/app/javascript/flavours/glitch/features/direct_timeline/components/conversation.jsx +++ b/app/javascript/flavours/glitch/features/direct_timeline/components/conversation.jsx @@ -126,14 +126,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)); diff --git a/app/javascript/flavours/glitch/features/notifications/components/notification.jsx b/app/javascript/flavours/glitch/features/notifications/components/notification.jsx index 0751258be9..1a049847d5 100644 --- a/app/javascript/flavours/glitch/features/notifications/components/notification.jsx +++ b/app/javascript/flavours/glitch/features/notifications/components/notification.jsx @@ -92,7 +92,7 @@ class Notification extends ImmutablePureComponent { e.preventDefault(); const { notification, onMention } = this.props; - onMention(notification.get('account'), this.props.history); + onMention(notification.get('account')); }; handleHotkeyFavourite = () => { diff --git a/app/javascript/flavours/glitch/features/notifications/containers/notification_container.js b/app/javascript/flavours/glitch/features/notifications/containers/notification_container.js index 338d27d8d6..b4df05b828 100644 --- a/app/javascript/flavours/glitch/features/notifications/containers/notification_container.js +++ b/app/javascript/flavours/glitch/features/notifications/containers/notification_container.js @@ -31,8 +31,8 @@ const makeMapStateToProps = () => { }; const mapDispatchToProps = dispatch => ({ - onMention: (account, router) => { - dispatch(mentionCompose(account, router)); + onMention: (account) => { + dispatch(mentionCompose(account)); }, onModalReblog (status, privacy) { diff --git a/app/javascript/flavours/glitch/features/onboarding/index.jsx b/app/javascript/flavours/glitch/features/onboarding/index.jsx index 187ee3b770..7922b61677 100644 --- a/app/javascript/flavours/glitch/features/onboarding/index.jsx +++ b/app/javascript/flavours/glitch/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'; @@ -34,11 +34,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/flavours/glitch/features/picture_in_picture/components/footer.jsx b/app/javascript/flavours/glitch/features/picture_in_picture/components/footer.jsx index 13ad86f801..2b27070007 100644 --- a/app/javascript/flavours/glitch/features/picture_in_picture/components/footer.jsx +++ b/app/javascript/flavours/glitch/features/picture_in_picture/components/footer.jsx @@ -63,13 +63,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 = () => { diff --git a/app/javascript/flavours/glitch/features/status/components/action_bar.jsx b/app/javascript/flavours/glitch/features/status/components/action_bar.jsx index 808712b021..3377019bdc 100644 --- a/app/javascript/flavours/glitch/features/status/components/action_bar.jsx +++ b/app/javascript/flavours/glitch/features/status/components/action_bar.jsx @@ -4,7 +4,6 @@ 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'; @@ -23,7 +22,6 @@ import RepeatPrivateActiveIcon from '@/svg-icons/repeat_private_active.svg?react import { identityContextPropShape, withIdentity } from 'flavours/glitch/identity_context'; import { PERMISSION_MANAGE_USERS, PERMISSION_MANAGE_FEDERATION } from 'flavours/glitch/permissions'; import { accountAdminLink, statusAdminLink } from 'flavours/glitch/utils/backend_links'; -import { WithRouterPropTypes } from 'flavours/glitch/utils/react_router'; import { IconButton } from '../../../components/icon_button'; import DropdownMenuContainer from '../../../containers/dropdown_menu_container'; @@ -78,7 +76,6 @@ class ActionBar extends PureComponent { onPin: PropTypes.func, onEmbed: PropTypes.func, intl: PropTypes.object.isRequired, - ...WithRouterPropTypes, }; handleReplyClick = () => { @@ -98,23 +95,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 = () => { @@ -262,4 +259,4 @@ class ActionBar extends PureComponent { } -export default withRouter(withIdentity(injectIntl(ActionBar))); +export default withIdentity(injectIntl(ActionBar)); diff --git a/app/javascript/flavours/glitch/features/status/containers/detailed_status_container.js b/app/javascript/flavours/glitch/features/status/containers/detailed_status_container.js index 7cb9735cfe..9663f7ca4e 100644 --- a/app/javascript/flavours/glitch/features/status/containers/detailed_status_container.js +++ b/app/javascript/flavours/glitch/features/status/containers/detailed_status_container.js @@ -52,7 +52,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) { @@ -61,11 +61,11 @@ 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)); } }); }, @@ -112,27 +112,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) { diff --git a/app/javascript/flavours/glitch/features/status/index.jsx b/app/javascript/flavours/glitch/features/status/index.jsx index 00639a667e..eb965046d1 100644 --- a/app/javascript/flavours/glitch/features/status/index.jsx +++ b/app/javascript/flavours/glitch/features/status/index.jsx @@ -324,11 +324,11 @@ class Status extends ImmutablePureComponent { message: intl.formatMessage(messages.replyMessage), confirm: intl.formatMessage(messages.replyConfirm), onDoNotAsk: () => dispatch(changeLocalSetting(['confirm_before_clearing_draft'], false)), - onConfirm: () => dispatch(replyCompose(status, this.props.history)), + onConfirm: () => dispatch(replyCompose(status)), }, })); } else { - dispatch(replyCompose(status, this.props.history)); + dispatch(replyCompose(status)); } } else { dispatch(openModal({ @@ -384,33 +384,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, history) => { - this.props.dispatch(directCompose(account, history)); + handleDirectClick = (account) => { + this.props.dispatch(directCompose(account)); }; - handleMentionClick = (account, history) => { - this.props.dispatch(mentionCompose(account, history)); + handleMentionClick = (account) => { + this.props.dispatch(mentionCompose(account)); }; handleOpenMedia = (media, index, lang) => { From 2774980589fd5d95a2a812527c269a4368e6889e Mon Sep 17 00:00:00 2001 From: Claire Date: Mon, 22 Jul 2024 09:37:27 +0200 Subject: [PATCH 083/126] Fix syntax error in grouped notifications CTE on some PostgreSQL versions (#31098) --- app/models/notification.rb | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/app/models/notification.rb b/app/models/notification.rb index 6d40411478..8b77b2a03b 100644 --- a/app/models/notification.rb +++ b/app/models/notification.rb @@ -149,7 +149,7 @@ class Notification < ApplicationRecord .with_recursive( grouped_notifications: [ query - .select('notifications.*', "ARRAY[COALESCE(notifications.group_key, 'ungrouped-' || notifications.id)] groups") + .select('notifications.*', "ARRAY[COALESCE(notifications.group_key, 'ungrouped-' || notifications.id)] AS groups") .limit(1), query .joins('CROSS JOIN grouped_notifications') @@ -177,7 +177,7 @@ class Notification < ApplicationRecord .with_recursive( grouped_notifications: [ query - .select('notifications.*', "ARRAY[COALESCE(notifications.group_key, 'ungrouped-' || notifications.id)] groups") + .select('notifications.*', "ARRAY[COALESCE(notifications.group_key, 'ungrouped-' || notifications.id)] AS groups") .limit(1), query .joins('CROSS JOIN grouped_notifications') From 77ec5e11e4385546e9b10c597c0b40002a809082 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Mon, 22 Jul 2024 07:38:52 +0000 Subject: [PATCH 084/126] chore(deps): update dependency email_spec to v2.3.0 (#31097) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- Gemfile.lock | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/Gemfile.lock b/Gemfile.lock index 006a918446..3815e6960c 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -222,9 +222,9 @@ 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) @@ -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) From 22d2fba2790e258096334d13e4688ae7810ebb4f Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Mon, 22 Jul 2024 07:39:38 +0000 Subject: [PATCH 085/126] chore(deps): update definitelytyped types (non-major) (#31095) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- yarn.lock | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/yarn.lock b/yarn.lock index 1a17c5862f..7ffd614f68 100644 --- a/yarn.lock +++ b/yarn.lock @@ -3737,9 +3737,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 @@ -4117,11 +4117,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 From 6ee5d3b5591d96c492035274e4668cfa7891fe70 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Mon, 22 Jul 2024 09:39:56 +0200 Subject: [PATCH 086/126] fix(deps): update dependency jsdom to v24.1.1 (#31088) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- yarn.lock | 40 ++++++++++++++++++++-------------------- 1 file changed, 20 insertions(+), 20 deletions(-) diff --git a/yarn.lock b/yarn.lock index 7ffd614f68..bd6efa72fe 100644 --- a/yarn.lock +++ b/yarn.lock @@ -9518,13 +9518,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 @@ -11095,8 +11095,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" @@ -11104,11 +11104,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" @@ -11117,14 +11117,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 @@ -12417,10 +12417,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 @@ -15361,10 +15361,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 @@ -18515,7 +18515,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: From ef796446e5b0827bc73a27d573b930b27efef579 Mon Sep 17 00:00:00 2001 From: Matt Jankowski Date: Mon, 22 Jul 2024 03:46:41 -0400 Subject: [PATCH 087/126] Ignore manifest JS parse/interrupt error on CI (#31080) --- spec/support/javascript_errors.rb | 1 + 1 file changed, 1 insertion(+) diff --git a/spec/support/javascript_errors.rb b/spec/support/javascript_errors.rb index 7645285362..ef5945f37d 100644 --- a/spec/support/javascript_errors.rb +++ b/spec/support/javascript_errors.rb @@ -5,6 +5,7 @@ RSpec.configure do |config| # 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) } From 5a60a3b80c8fe1769ba737a286169636476e686c Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Mon, 22 Jul 2024 10:01:24 +0200 Subject: [PATCH 088/126] New Crowdin Translations (automated) (#31087) Co-authored-by: GitHub Actions --- app/javascript/mastodon/locales/bg.json | 14 ++ app/javascript/mastodon/locales/ca.json | 14 ++ app/javascript/mastodon/locales/el.json | 164 +++++++++++++++++++++++ app/javascript/mastodon/locales/fi.json | 26 +++- app/javascript/mastodon/locales/fy.json | 1 + app/javascript/mastodon/locales/gl.json | 14 ++ app/javascript/mastodon/locales/he.json | 14 ++ app/javascript/mastodon/locales/is.json | 14 ++ app/javascript/mastodon/locales/ja.json | 2 + app/javascript/mastodon/locales/kab.json | 43 +++--- app/javascript/mastodon/locales/lad.json | 10 ++ app/javascript/mastodon/locales/nl.json | 8 +- app/javascript/mastodon/locales/sq.json | 14 ++ app/javascript/mastodon/locales/sv.json | 3 + app/javascript/mastodon/locales/th.json | 6 + app/javascript/mastodon/locales/tr.json | 14 ++ app/javascript/mastodon/locales/uk.json | 14 ++ app/javascript/mastodon/locales/vi.json | 14 ++ config/locales/activerecord.el.yml | 4 +- config/locales/doorkeeper.el.yml | 107 ++++++++------- config/locales/doorkeeper.kab.yml | 10 +- config/locales/el.yml | 11 +- config/locales/fi.yml | 6 +- config/locales/is.yml | 2 + config/locales/kab.yml | 2 +- config/locales/nl.yml | 1 + config/locales/simple_form.ja.yml | 2 + config/locales/simple_form.kab.yml | 10 +- config/locales/simple_form.lad.yml | 1 + config/locales/uk.yml | 1 + 30 files changed, 442 insertions(+), 104 deletions(-) diff --git a/app/javascript/mastodon/locales/bg.json b/app/javascript/mastodon/locales/bg.json index 0e29f55e76..b2dff17407 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} ви последва", @@ -485,6 +491,8 @@ "notification.moderation_warning.action_silence": "Вашият акаунт е ограничен.", "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}, което значи че повече не може да получавате новости от тях или да взаимодействате с тях.", @@ -502,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": "Лента за бърз филтър", @@ -665,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/ca.json b/app/javascript/mastodon/locales/ca.json index 1719b105f0..80c85ce178 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,6 +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 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.", @@ -502,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", @@ -665,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/el.json b/app/javascript/mastodon/locales/el.json index 3c0ef467bf..cba2525f37 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,21 +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.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": "Επισημάνσεις:", @@ -412,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": "Αποτελέσματα δημοσκόπησης", @@ -422,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": "Μη χάσεις στιγμή", @@ -429,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": "Αποθήκευση και συνέχεια", @@ -438,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Τα καταφέρατε!", @@ -450,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": "Βάλε το πίσω", @@ -468,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": "Προτεινόμενα", @@ -486,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": "Αποκλεισμός", @@ -529,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": "Αναζήτηση", @@ -541,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": "Όλα", @@ -554,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}", @@ -571,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": "Περισσότερα", @@ -592,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": "Αφαίρεση σελιδοδείκτη", @@ -610,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/fi.json b/app/javascript/mastodon/locales/fi.json index 4b330ec60b..5ba77dd72e 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,6 +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": "Ää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.", @@ -502,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", @@ -591,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", @@ -622,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", @@ -665,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/fy.json b/app/javascript/mastodon/locales/fy.json index a04a5b25bf..e3b3a96568 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", diff --git a/app/javascript/mastodon/locales/gl.json b/app/javascript/mastodon/locales/gl.json index 1f76ae951d..d64789b86c 100644 --- a/app/javascript/mastodon/locales/gl.json +++ b/app/javascript/mastodon/locales/gl.json @@ -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", @@ -485,6 +491,8 @@ "notification.moderation_warning.action_silence": "A túa conta foi limitada.", "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.", @@ -502,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", @@ -665,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 148b3285dd..3687df7b87 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} במעקב אחרייך", @@ -485,6 +491,8 @@ "notification.moderation_warning.action_silence": "חשבונך הוגבל.", "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}, ולפיכך לא תעודכנו יותר על ידם ולא תוכלו להיות איתם בקשר.", @@ -502,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": "שורת סינון מהיר", @@ -665,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/is.json b/app/javascript/mastodon/locales/is.json index 733e2e541d..27d23aafd0 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,6 +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 þú 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.", @@ -502,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", @@ -665,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/ja.json b/app/javascript/mastodon/locales/ja.json index 13583bc1d8..5168c1c0c0 100644 --- a/app/javascript/mastodon/locales/ja.json +++ b/app/javascript/mastodon/locales/ja.json @@ -502,6 +502,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": "クイックフィルターバー:", diff --git a/app/javascript/mastodon/locales/kab.json b/app/javascript/mastodon/locales/kab.json index d12cf04366..776b3446a2 100644 --- a/app/javascript/mastodon/locales/kab.json +++ b/app/javascript/mastodon/locales/kab.json @@ -20,10 +20,10 @@ "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ɣ", @@ -45,7 +45,7 @@ "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.", @@ -103,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", @@ -210,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", @@ -247,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}", @@ -305,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", @@ -327,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", @@ -388,11 +388,12 @@ "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", @@ -400,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", @@ -415,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}}", @@ -425,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", @@ -521,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", @@ -608,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/lad.json b/app/javascript/mastodon/locales/lad.json index ee45e09ad1..2dc360f9ed 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,15 +450,20 @@ "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", + "notification.poll": "Anketa en ke votates eskapo", "notification.reblog": "{name} repartajo tu publikasyon", "notification.relationships_severance_event": "Koneksyones pedridas kon {name}", "notification.relationships_severance_event.learn_more": "Ambezate mas", @@ -633,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/nl.json b/app/javascript/mastodon/locales/nl.json index 05c8aa4e26..027c09280c 100644 --- a/app/javascript/mastodon/locales/nl.json +++ b/app/javascript/mastodon/locales/nl.json @@ -491,8 +491,8 @@ "notification.moderation_warning.action_silence": "Jouw account is beperkt.", "notification.moderation_warning.action_suspend": "Jouw account is opgeschort.", "notification.own_poll": "Jouw peiling is beëindigd", - "notification.poll": "Een peiling waaraan je hebt deelgenomen, is verlopen", - "notification.private_mention": "{name} heeft je privé genoemd", + "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.", @@ -511,7 +511,7 @@ "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": "Groepsmeldingen", + "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", @@ -681,7 +681,7 @@ "report_notification.categories.spam": "Spam", "report_notification.categories.spam_sentence": "spam", "report_notification.categories.violation": "Overtreden regel(s)", - "report_notification.categories.violation_sentence": "regel overtreden", + "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/sq.json b/app/javascript/mastodon/locales/sq.json index 219561688b..6f378b145e 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,6 +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 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ë.", @@ -502,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", @@ -665,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/sv.json b/app/javascript/mastodon/locales/sv.json index ba07d5a1c7..53e2dde42e 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", @@ -672,6 +674,7 @@ "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/th.json b/app/javascript/mastodon/locales/th.json index 083a0eb33f..ab8179863c 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,6 +487,7 @@ "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} ซึ่งหมายความว่าคุณจะไม่สามารถรับการอัปเดตจากเขาหรือโต้ตอบกับเขาได้อีกต่อไป", @@ -666,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/tr.json b/app/javascript/mastodon/locales/tr.json index 0b20b60f9e..ae7b5ba25d 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", @@ -485,6 +491,8 @@ "notification.moderation_warning.action_silence": "Hesabınız sınırlandırıldı.", "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.", @@ -502,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", @@ -665,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 76abe8d299..b5cd1f7b28 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,6 +491,8 @@ "notification.moderation_warning.action_silence": "Ваш обліковий запис було обмежено.", "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}, що означає, що ви більше не можете отримувати оновлення від них або взаємодіяти з ними.", @@ -502,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": "Панель швидкого фільтра", @@ -665,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/vi.json b/app/javascript/mastodon/locales/vi.json index 7a88bee364..0f2cc996a2 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,6 +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 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.", @@ -502,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", @@ -665,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/config/locales/activerecord.el.yml b/config/locales/activerecord.el.yml index 01e9a75f98..1c3bcc6ebf 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/doorkeeper.el.yml b/config/locales/doorkeeper.el.yml index 1cb9b3513b..167cc6bd44 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.kab.yml b/config/locales/doorkeeper.kab.yml index 33aecd8c6f..d79c711e60 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 47b2250f0e..e177bf342a 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/fi.yml b/config/locales/fi.yml index 2d10250f68..c93c5edc0e 100644 --- a/config/locales/fi.yml +++ b/config/locales/fi.yml @@ -606,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ä @@ -638,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/is.yml b/config/locales/is.yml index 7ac50cd572..a4cc282d1d 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/kab.yml b/config/locales/kab.yml index b2fc9d8477..a094936aaf 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/nl.yml b/config/locales/nl.yml index 3b88dd9528..91872754f5 100644 --- a/config/locales/nl.yml +++ b/config/locales/nl.yml @@ -639,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/simple_form.ja.yml b/config/locales/simple_form.ja.yml index 56b17ab000..a4bd956508 100644 --- a/config/locales/simple_form.ja.yml +++ b/config/locales/simple_form.ja.yml @@ -243,11 +243,13 @@ ja: 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.kab.yml b/config/locales/simple_form.kab.yml index e68355da6a..b4c0e0032b 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: @@ -112,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.lad.yml b/config/locales/simple_form.lad.yml index cef58e4601..65647a77db 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/uk.yml b/config/locales/uk.yml index 69f5ca665c..a5cdcfefb4 100644 --- a/config/locales/uk.yml +++ b/config/locales/uk.yml @@ -663,6 +663,7 @@ uk: report: 'Скарга #%{id}' reported_account: Обліковий запис порушника reported_by: Відправник скарги + reported_with_application: Повідомлено через застосунок resolved: Вирішено resolved_msg: Скаргу успішно вирішено! skip_to_actions: Перейти до дій From 6e4305de69bb3356d5d0038611052490527d3325 Mon Sep 17 00:00:00 2001 From: Matt Jankowski Date: Mon, 22 Jul 2024 04:02:31 -0400 Subject: [PATCH 089/126] Fix spec descriptions around configurable limit values (#31079) --- spec/models/account_spec.rb | 2 +- spec/validators/note_length_validator_spec.rb | 18 +++++++++++++----- spec/validators/reaction_validator_spec.rb | 5 +++-- .../validators/status_length_validator_spec.rb | 18 +++++++++++++----- 4 files changed, 30 insertions(+), 13 deletions(-) diff --git a/spec/models/account_spec.rb b/spec/models/account_spec.rb index 5f918f159a..7153c7466e 100644 --- a/spec/models/account_spec.rb +++ b/spec/models/account_spec.rb @@ -592,7 +592,7 @@ RSpec.describe Account do 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) diff --git a/spec/validators/note_length_validator_spec.rb b/spec/validators/note_length_validator_spec.rb index 66fccad3ec..3bca93a283 100644 --- a/spec/validators/note_length_validator_spec.rb +++ b/spec/validators/note_length_validator_spec.rb @@ -6,7 +6,7 @@ describe NoteLengthValidator do 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 @@ describe NoteLengthValidator do 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 @@ describe NoteLengthValidator do 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 d73104cb69..f99c1cb5f9 100644 --- a/spec/validators/reaction_validator_spec.rb +++ b/spec/validators/reaction_validator_spec.rb @@ -19,8 +19,9 @@ describe ReactionValidator do 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 ead69dfe21..249b90f490 100644 --- a/spec/validators/status_length_validator_spec.rb +++ b/spec/validators/status_length_validator_spec.rb @@ -42,23 +42,23 @@ describe StatusLengthValidator do 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 @@ describe StatusLengthValidator do 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, From ced5e853c7d7c7f2b849d904964ef92e93ad27c8 Mon Sep 17 00:00:00 2001 From: Claire Date: Mon, 22 Jul 2024 10:56:05 +0200 Subject: [PATCH 090/126] Fix duplicate `orderedItems` in user archive's `outbox.json` (#31099) --- app/lib/activitypub/adapter.rb | 2 +- app/services/backup_service.rb | 6 +++--- spec/lib/activitypub/adapter_spec.rb | 10 +++++----- spec/services/backup_service_spec.rb | 1 + 4 files changed, 10 insertions(+), 9 deletions(-) diff --git a/app/lib/activitypub/adapter.rb b/app/lib/activitypub/adapter.rb index 098b6296fb..5b9437eb8d 100644 --- a/app/lib/activitypub/adapter.rb +++ b/app/lib/activitypub/adapter.rb @@ -20,6 +20,6 @@ class ActivityPub::Adapter < ActiveModelSerializers::Adapter::Base 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/services/backup_service.rb b/app/services/backup_service.rb index 1e90184376..133a764873 100644 --- a/app/services/backup_service.rb +++ b/app/services/backup_service.rb @@ -19,8 +19,8 @@ class BackupService < BaseService 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 @@ class BackupService < BaseService file.write(statuses.map do |status| item = serialize_payload(ActivityPub::ActivityPresenter.from_status(status), 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/spec/lib/activitypub/adapter_spec.rb b/spec/lib/activitypub/adapter_spec.rb index 7d8d703ec2..5ecdfe8120 100644 --- a/spec/lib/activitypub/adapter_spec.rb +++ b/spec/lib/activitypub/adapter_spec.rb @@ -59,7 +59,7 @@ RSpec.describe ActivityPub::Adapter do 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 @@ RSpec.describe ActivityPub::Adapter do 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 @@ RSpec.describe ActivityPub::Adapter do 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 @@ RSpec.describe ActivityPub::Adapter do 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 @@ RSpec.describe ActivityPub::Adapter do 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/services/backup_service_spec.rb b/spec/services/backup_service_spec.rb index 145b06e372..878405a0fe 100644 --- a/spec/services/backup_service_spec.rb +++ b/spec/services/backup_service_spec.rb @@ -60,6 +60,7 @@ RSpec.describe BackupService do 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 2 From 80d9bff6df137afc3376f47b62d10a2e3e9456e2 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Mon, 22 Jul 2024 15:39:37 +0200 Subject: [PATCH 091/126] fix(deps): update dependency immutable to v4.3.7 (#31100) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- yarn.lock | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/yarn.lock b/yarn.lock index bd6efa72fe..04e233c3c3 100644 --- a/yarn.lock +++ b/yarn.lock @@ -9621,9 +9621,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 From 03dea64b794f3e6cd1e03df72578ed0004a4d84c Mon Sep 17 00:00:00 2001 From: Claire Date: Mon, 22 Jul 2024 17:45:07 +0200 Subject: [PATCH 092/126] Refactor code for reblogging and favouriting (#31102) --- .../mastodon/actions/interactions.js | 50 +++++++++++++++++++ .../mastodon/containers/status_container.jsx | 28 ++--------- .../containers/notification_container.js | 28 ++--------- .../picture_in_picture/components/footer.jsx | 23 ++------- .../containers/detailed_status_container.js | 28 ++--------- .../mastodon/features/status/index.jsx | 28 ++--------- 6 files changed, 73 insertions(+), 112 deletions(-) diff --git a/app/javascript/mastodon/actions/interactions.js b/app/javascript/mastodon/actions/interactions.js index 57f2459c01..9d39b7a57f 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 } 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'; @@ -432,3 +436,49 @@ export function unpinFail(status, error) { skipLoading: true, }; } + +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) { + 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) { + dispatch(openModal({ modalType: 'BOOST', modalProps: { status, onReblog: toggleReblogWithoutConfirmation } })); + } else { + 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/containers/status_container.jsx b/app/javascript/mastodon/containers/status_container.jsx index e2c0af3533..8e34ace873 100644 --- a/app/javascript/mastodon/containers/status_container.jsx +++ b/app/javascript/mastodon/containers/status_container.jsx @@ -21,11 +21,9 @@ import { initAddFilter, } from '../actions/filters'; import { - reblog, - favourite, + toggleReblog, + toggleFavourite, bookmark, - unreblog, - unfavourite, unbookmark, pin, unpin, @@ -46,7 +44,7 @@ import { 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({ @@ -94,28 +92,12 @@ const mapDispatchToProps = (dispatch, { intl, contextType }) => ({ }); }, - 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)); }, onFavourite (status) { - if (status.get('favourited')) { - dispatch(unfavourite(status)); - } else { - dispatch(favourite(status)); - } + dispatch(toggleFavourite(status.get('id'))); }, onBookmark (status) { diff --git a/app/javascript/mastodon/features/notifications/containers/notification_container.js b/app/javascript/mastodon/features/notifications/containers/notification_container.js index 7b7e6e919c..98a3cf8b1e 100644 --- a/app/javascript/mastodon/features/notifications/containers/notification_container.js +++ b/app/javascript/mastodon/features/notifications/containers/notification_container.js @@ -2,17 +2,13 @@ import { connect } from 'react-redux'; import { mentionCompose } from '../../../actions/compose'; import { - reblog, - favourite, - unreblog, - unfavourite, + toggleFavourite, + toggleReblog, } from '../../../actions/interactions'; -import { openModal } from '../../../actions/modal'; import { hideStatus, revealStatus, } from '../../../actions/statuses'; -import { boostModal } from '../../../initial_state'; import { makeGetNotification, makeGetStatus, makeGetReport } from '../../../selectors'; import Notification from '../components/notification'; @@ -38,28 +34,12 @@ const mapDispatchToProps = dispatch => ({ dispatch(mentionCompose(account)); }, - 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)); }, onFavourite (status) { - if (status.get('favourited')) { - dispatch(unfavourite(status)); - } else { - dispatch(favourite(status)); - } + dispatch(toggleFavourite(status.get('id'))); }, onToggleHidden (status) { 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 8404bf61b7..d5226eb346 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'; @@ -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/containers/detailed_status_container.js b/app/javascript/mastodon/features/status/containers/detailed_status_container.js index f85c3822d7..f37860d25c 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, } from '../../../actions/interactions'; @@ -27,7 +25,7 @@ import { hideStatus, revealStatus, } 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'; @@ -73,28 +71,12 @@ const mapDispatchToProps = (dispatch, { intl }) => ({ }); }, - 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)); }, onFavourite (status) { - if (status.get('favourited')) { - dispatch(unfavourite(status)); - } else { - dispatch(favourite(status)); - } + dispatch(toggleFavourite(status.get('id'))); }, onPin (status) { diff --git a/app/javascript/mastodon/features/status/index.jsx b/app/javascript/mastodon/features/status/index.jsx index b0fbea9e22..e9df3697a2 100644 --- a/app/javascript/mastodon/features/status/index.jsx +++ b/app/javascript/mastodon/features/status/index.jsx @@ -38,12 +38,10 @@ import { unblockDomain, } from '../../actions/domain_blocks'; import { - favourite, - unfavourite, + toggleFavourite, bookmark, unbookmark, - reblog, - unreblog, + toggleReblog, pin, unpin, } from '../../actions/interactions'; @@ -64,7 +62,7 @@ import { import ColumnHeader from '../../components/column_header'; import { textForScreenReader, defaultMediaVisibility } from '../../components/status'; import StatusContainer from '../../containers/status_container'; -import { boostModal, deleteModal } from '../../initial_state'; +import { deleteModal } from '../../initial_state'; import { makeGetStatus, makeGetPictureInPicture } from '../../selectors'; import Column from '../ui/components/column'; import { attachFullscreenListener, detachFullscreenListener, isFullscreen } from '../ui/util/fullscreen'; @@ -244,11 +242,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', @@ -298,24 +292,12 @@ class Status extends ImmutablePureComponent { } }; - handleModalReblog = (status, privacy) => { - this.props.dispatch(reblog({ statusId: status.get('id'), visibility: privacy })); - }; - handleReblogClick = (status, e) => { const { dispatch } = 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.handleModalReblog(status); - } else { - dispatch(openModal({ modalType: 'BOOST', modalProps: { status, onReblog: this.handleModalReblog } })); - } - } + dispatch(toggleReblog(status.get('id'), e && e.shiftKey)); } else { dispatch(openModal({ modalType: 'INTERACTION', From 9cb94271333ccfe488fa84d49e3351f18594e480 Mon Sep 17 00:00:00 2001 From: Claire Date: Mon, 22 Jul 2024 18:03:58 +0200 Subject: [PATCH 093/126] Refactor CW handling in an action (#31103) --- app/javascript/mastodon/actions/statuses.js | 15 +++++++++++++++ .../mastodon/containers/status_container.jsx | 9 ++------- .../direct_timeline/components/conversation.jsx | 8 ++------ .../containers/notification_container.js | 9 ++------- .../containers/detailed_status_container.js | 9 ++------- 5 files changed, 23 insertions(+), 27 deletions(-) diff --git a/app/javascript/mastodon/actions/statuses.js b/app/javascript/mastodon/actions/statuses.js index 1907d3aa91..26abaf1bcc 100644 --- a/app/javascript/mastodon/actions/statuses.js +++ b/app/javascript/mastodon/actions/statuses.js @@ -308,6 +308,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, diff --git a/app/javascript/mastodon/containers/status_container.jsx b/app/javascript/mastodon/containers/status_container.jsx index 8e34ace873..c803822dc0 100644 --- a/app/javascript/mastodon/containers/status_container.jsx +++ b/app/javascript/mastodon/containers/status_container.jsx @@ -36,8 +36,7 @@ import { muteStatus, unmuteStatus, deleteStatus, - hideStatus, - revealStatus, + toggleStatusSpoilers, toggleStatusCollapse, editStatus, translateStatus, @@ -223,11 +222,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/direct_timeline/components/conversation.jsx b/app/javascript/mastodon/features/direct_timeline/components/conversation.jsx index 63dc705e40..326ea3e5ac 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'; @@ -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/containers/notification_container.js b/app/javascript/mastodon/features/notifications/containers/notification_container.js index 98a3cf8b1e..d64f2a679c 100644 --- a/app/javascript/mastodon/features/notifications/containers/notification_container.js +++ b/app/javascript/mastodon/features/notifications/containers/notification_container.js @@ -6,8 +6,7 @@ import { toggleReblog, } from '../../../actions/interactions'; import { - hideStatus, - revealStatus, + toggleStatusSpoilers, } from '../../../actions/statuses'; import { makeGetNotification, makeGetStatus, makeGetReport } from '../../../selectors'; import Notification from '../components/notification'; @@ -43,11 +42,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/status/containers/detailed_status_container.js b/app/javascript/mastodon/features/status/containers/detailed_status_container.js index f37860d25c..5ab1013700 100644 --- a/app/javascript/mastodon/features/status/containers/detailed_status_container.js +++ b/app/javascript/mastodon/features/status/containers/detailed_status_container.js @@ -22,8 +22,7 @@ import { muteStatus, unmuteStatus, deleteStatus, - hideStatus, - revealStatus, + toggleStatusSpoilers, } from '../../../actions/statuses'; import { deleteModal } from '../../../initial_state'; import { makeGetStatus, makeGetPictureInPicture } from '../../../selectors'; @@ -156,11 +155,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'))); }, }); From 55705d8191f31c1089095956fb4124f7505b4bd7 Mon Sep 17 00:00:00 2001 From: Claire Date: Mon, 22 Jul 2024 21:30:06 +0200 Subject: [PATCH 094/126] Fix reblogging after refactor (#31105) --- app/javascript/mastodon/actions/interactions.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/app/javascript/mastodon/actions/interactions.js b/app/javascript/mastodon/actions/interactions.js index 9d39b7a57f..b296a5006a 100644 --- a/app/javascript/mastodon/actions/interactions.js +++ b/app/javascript/mastodon/actions/interactions.js @@ -460,9 +460,9 @@ export function toggleReblog(statusId, skipModal = false) { status = status.set('account', state.accounts.get(status.get('account'))); if (boostModal && !skipModal) { - dispatch(openModal({ modalType: 'BOOST', modalProps: { status, onReblog: toggleReblogWithoutConfirmation } })); + dispatch(openModal({ modalType: 'BOOST', modalProps: { status, onReblog: (status, privacy) => dispatch(toggleReblogWithoutConfirmation(status, privacy)) } })); } else { - toggleReblogWithoutConfirmation(status); + dispatch(toggleReblogWithoutConfirmation(status)); } }; } From f13a231b3980f76fc5b105ac8e430599df19e956 Mon Sep 17 00:00:00 2001 From: Claire Date: Mon, 22 Jul 2024 17:45:07 +0200 Subject: [PATCH 095/126] [Glitch] Refactor code for reblogging and favouriting Port 03dea64b794f3e6cd1e03df72578ed0004a4d84c to glitch-soc Signed-off-by: Claire --- .../flavours/glitch/actions/interactions.js | 62 +++++++++++++++++++ .../glitch/containers/status_container.js | 47 ++------------ .../containers/notification_container.js | 30 ++------- .../picture_in_picture/components/footer.jsx | 25 ++------ .../containers/detailed_status_container.js | 30 ++------- .../flavours/glitch/features/status/index.jsx | 47 ++------------ 6 files changed, 89 insertions(+), 152 deletions(-) diff --git a/app/javascript/flavours/glitch/actions/interactions.js b/app/javascript/flavours/glitch/actions/interactions.js index 57f2459c01..6790d3313b 100644 --- a/app/javascript/flavours/glitch/actions/interactions.js +++ b/app/javascript/flavours/glitch/actions/interactions.js @@ -1,7 +1,11 @@ +import { boostModal, favouriteModal } from 'flavours/glitch/initial_state'; + import api, { getLinks } from '../api'; import { fetchRelationships } from './accounts'; import { importFetchedAccounts, importFetchedStatus } 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'; @@ -432,3 +436,61 @@ export function unpinFail(status, error) { skipLoading: true, }; } + +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) { + 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'))); + + const missing_description_setting = state.getIn(['local_settings', 'confirm_boost_missing_media_description']); + const missing_description = status.get('media_attachments').some(item => !item.get('description')); + if (missing_description_setting && missing_description && !status.get('reblogged')) { + dispatch(openModal({ modalType: 'BOOST', modalProps: { status, onReblog: toggleReblogWithoutConfirmation, missingMediaDescription: true } })); + } else if (boostModal && !skipModal) { + dispatch(openModal({ modalType: 'BOOST', modalProps: { status, onReblog: toggleReblogWithoutConfirmation } })); + } else { + toggleReblogWithoutConfirmation(status); + } + }; +} + +export function toggleFavourite(statusId, skipModal = false) { + return (dispatch, getState) => { + const state = getState(); + let status = state.statuses.get(statusId); + + if (!status) + return; + + // The favourite 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 (status.get('favourited')) { + dispatch(unfavourite(status)); + } else { + if (favouriteModal && !skipModal) { + dispatch(openModal({ modalType: 'FAVOURITE', modalProps: { status, onFavourite: (status) => dispatch(favourite(status)) } })); + } else { + dispatch(favourite(status)); + } + } + }; +} diff --git a/app/javascript/flavours/glitch/containers/status_container.js b/app/javascript/flavours/glitch/containers/status_container.js index a05ed5fe4f..aac18eac0d 100644 --- a/app/javascript/flavours/glitch/containers/status_container.js +++ b/app/javascript/flavours/glitch/containers/status_container.js @@ -12,11 +12,9 @@ import { initAddFilter, } from 'flavours/glitch/actions/filters'; import { - reblog, - favourite, + toggleReblog, + toggleFavourite, bookmark, - unreblog, - unfavourite, unbookmark, pin, unpin, @@ -37,7 +35,7 @@ import { undoStatusTranslation, } from 'flavours/glitch/actions/statuses'; import Status from 'flavours/glitch/components/status'; -import { boostModal, favouriteModal, deleteModal } from 'flavours/glitch/initial_state'; +import { deleteModal } from 'flavours/glitch/initial_state'; import { makeGetStatus, makeGetPictureInPicture } from 'flavours/glitch/selectors'; import { showAlertForError } from '../actions/alerts'; @@ -113,25 +111,8 @@ const mapDispatchToProps = (dispatch, { intl, contextType }) => ({ }); }, - 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) { - dispatch((_, getState) => { - let state = getState(); - if (state.getIn(['local_settings', 'confirm_boost_missing_media_description']) && status.get('media_attachments').some(item => !item.get('description')) && !status.get('reblogged')) { - dispatch(openModal({ modalType: 'BOOST', modalProps: { status, onReblog: this.onModalReblog, missingMediaDescription: true } })); - } 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)); }, onBookmark (status) { @@ -142,26 +123,8 @@ const mapDispatchToProps = (dispatch, { intl, contextType }) => ({ } }, - onModalFavourite (status) { - dispatch(favourite(status)); - }, - onFavourite (status, e) { - if (status.get('favourited')) { - dispatch(unfavourite(status)); - } else { - if (e.shiftKey || !favouriteModal) { - this.onModalFavourite(status); - } else { - dispatch(openModal({ - modalType: 'FAVOURITE', - modalProps: { - status, - onFavourite: this.onModalFavourite, - }, - })); - } - } + dispatch(toggleFavourite(status.get('id'), e.shiftKey)); }, onPin (status) { diff --git a/app/javascript/flavours/glitch/features/notifications/containers/notification_container.js b/app/javascript/flavours/glitch/features/notifications/containers/notification_container.js index b4df05b828..8ecea4bc73 100644 --- a/app/javascript/flavours/glitch/features/notifications/containers/notification_container.js +++ b/app/javascript/flavours/glitch/features/notifications/containers/notification_container.js @@ -2,13 +2,9 @@ import { connect } from 'react-redux'; import { mentionCompose } from '../../../actions/compose'; import { - reblog, - favourite, - unreblog, - unfavourite, + toggleReblog, + toggleFavourite, } from '../../../actions/interactions'; -import { openModal } from '../../../actions/modal'; -import { boostModal } from '../../../initial_state'; import { makeGetNotification, makeGetStatus, makeGetReport } from '../../../selectors'; import Notification from '../components/notification'; @@ -35,28 +31,12 @@ const mapDispatchToProps = dispatch => ({ dispatch(mentionCompose(account)); }, - 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)); }, - onFavourite (status) { - if (status.get('favourited')) { - dispatch(unfavourite(status)); - } else { - dispatch(favourite(status)); - } + onFavourite (status, e) { + dispatch(toggleFavourite(status.get('id'), e.shiftKey)); }, }); diff --git a/app/javascript/flavours/glitch/features/picture_in_picture/components/footer.jsx b/app/javascript/flavours/glitch/features/picture_in_picture/components/footer.jsx index 2b27070007..3e26d84069 100644 --- a/app/javascript/flavours/glitch/features/picture_in_picture/components/footer.jsx +++ b/app/javascript/flavours/glitch/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 'flavours/glitch/actions/compose'; -import { reblog, favourite, unreblog, unfavourite } from 'flavours/glitch/actions/interactions'; +import { toggleReblog, toggleFavourite } from 'flavours/glitch/actions/interactions'; import { openModal } from 'flavours/glitch/actions/modal'; import { IconButton } from 'flavours/glitch/components/icon_button'; import { identityContextPropShape, withIdentity } from 'flavours/glitch/identity_context'; -import { me, boostModal } from 'flavours/glitch/initial_state'; +import { me } from 'flavours/glitch/initial_state'; import { makeGetStatus } from 'flavours/glitch/selectors'; import { WithRouterPropTypes } from 'flavours/glitch/utils/react_router'; @@ -101,16 +101,12 @@ class Footer extends ImmutablePureComponent { } }; - handleFavouriteClick = () => { + handleFavouriteClick = e => { const { dispatch, status } = this.props; const { signedIn } = this.props.identity; if (signedIn) { - if (status.get('favourited')) { - dispatch(unfavourite(status)); - } else { - dispatch(favourite(status)); - } + dispatch(toggleFavourite(status.get('id'), e && e.shiftKey)); } else { dispatch(openModal({ modalType: 'INTERACTION', @@ -123,23 +119,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/flavours/glitch/features/status/containers/detailed_status_container.js b/app/javascript/flavours/glitch/features/status/containers/detailed_status_container.js index 9663f7ca4e..1c9e3ccce1 100644 --- a/app/javascript/flavours/glitch/features/status/containers/detailed_status_container.js +++ b/app/javascript/flavours/glitch/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, } from '../../../actions/interactions'; @@ -25,7 +23,7 @@ import { unmuteStatus, deleteStatus, } from '../../../actions/statuses'; -import { boostModal, deleteModal } from '../../../initial_state'; +import { deleteModal } from '../../../initial_state'; import { makeGetStatus } from '../../../selectors'; import DetailedStatus from '../components/detailed_status'; @@ -70,28 +68,12 @@ const mapDispatchToProps = (dispatch, { intl }) => ({ }); }, - 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)); }, - onFavourite (status) { - if (status.get('favourited')) { - dispatch(unfavourite(status)); - } else { - dispatch(favourite(status)); - } + onFavourite (status, e) { + dispatch(toggleFavourite(status.get('id'), e.shiftKey)); }, onPin (status) { diff --git a/app/javascript/flavours/glitch/features/status/index.jsx b/app/javascript/flavours/glitch/features/status/index.jsx index eb965046d1..2fca4b61b6 100644 --- a/app/javascript/flavours/glitch/features/status/index.jsx +++ b/app/javascript/flavours/glitch/features/status/index.jsx @@ -32,12 +32,10 @@ import { directCompose, } from '../../actions/compose'; import { - favourite, - unfavourite, + toggleFavourite, bookmark, unbookmark, - reblog, - unreblog, + toggleReblog, pin, unpin, } from '../../actions/interactions'; @@ -59,7 +57,7 @@ import { import ColumnHeader from '../../components/column_header'; import { textForScreenReader, defaultMediaVisibility } from '../../components/status'; import StatusContainer from '../../containers/status_container'; -import { boostModal, favouriteModal, deleteModal } from '../../initial_state'; +import { deleteModal } from '../../initial_state'; import { makeGetStatus, makeGetPictureInPicture } from '../../selectors'; import Column from '../ui/components/column'; import { attachFullscreenListener, detachFullscreenListener, isFullscreen } from '../ui/util/fullscreen'; @@ -268,30 +266,13 @@ class Status extends ImmutablePureComponent { this.setState({ showMedia: !this.state.showMedia }); }; - handleModalFavourite = (status) => { - this.props.dispatch(favourite(status)); - }; handleFavouriteClick = (status, e) => { const { dispatch } = this.props; const { signedIn } = this.props.identity; if (signedIn) { - if (status.get('favourited')) { - dispatch(unfavourite(status)); - } else { - if ((e && e.shiftKey) || !favouriteModal) { - this.handleModalFavourite(status); - } else { - dispatch(openModal({ - modalType: 'FAVOURITE', - modalProps: { - status, - onFavourite: this.handleModalFavourite, - }, - })); - } - } + dispatch(toggleFavourite(status.get('id'), e && e.shiftKey)); } else { dispatch(openModal({ modalType: 'INTERACTION', @@ -342,28 +323,12 @@ class Status extends ImmutablePureComponent { } }; - handleModalReblog = (status, privacy) => { - const { dispatch } = this.props; - - if (status.get('reblogged')) { - dispatch(unreblog({ statusId: status.get('id') })); - } else { - dispatch(reblog({ statusId: status.get('id'), visibility: privacy })); - } - }; - handleReblogClick = (status, e) => { - const { settings, dispatch } = this.props; + const { dispatch } = this.props; const { signedIn } = this.props.identity; if (signedIn) { - if (settings.get('confirm_boost_missing_media_description') && status.get('media_attachments').some(item => !item.get('description')) && !status.get('reblogged')) { - dispatch(openModal({ modalType: 'BOOST', modalProps: { status, onReblog: this.handleModalReblog, missingMediaDescription: true } })); - } else if ((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)); } else { dispatch(openModal({ modalType: 'INTERACTION', From 643b1ef3e97684da49879f9ca7e8781b2f1b3b00 Mon Sep 17 00:00:00 2001 From: Claire Date: Mon, 22 Jul 2024 18:03:58 +0200 Subject: [PATCH 096/126] [Glitch] Refactor CW handling in an action Port 9cb94271333ccfe488fa84d49e3351f18594e480 to glitch-soc Signed-off-by: Claire --- .../flavours/glitch/actions/statuses.js | 15 +++++++++++++++ .../glitch/containers/status_container.js | 9 ++------- .../direct_timeline/components/conversation.jsx | 8 ++------ 3 files changed, 19 insertions(+), 13 deletions(-) diff --git a/app/javascript/flavours/glitch/actions/statuses.js b/app/javascript/flavours/glitch/actions/statuses.js index 054626bda0..2ebe0bf96a 100644 --- a/app/javascript/flavours/glitch/actions/statuses.js +++ b/app/javascript/flavours/glitch/actions/statuses.js @@ -309,6 +309,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, diff --git a/app/javascript/flavours/glitch/containers/status_container.js b/app/javascript/flavours/glitch/containers/status_container.js index aac18eac0d..955adc5fa7 100644 --- a/app/javascript/flavours/glitch/containers/status_container.js +++ b/app/javascript/flavours/glitch/containers/status_container.js @@ -28,8 +28,7 @@ import { muteStatus, unmuteStatus, deleteStatus, - hideStatus, - revealStatus, + toggleStatusSpoilers, editStatus, translateStatus, undoStatusTranslation, @@ -234,11 +233,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'))); }, deployPictureInPicture (status, type, mediaProps) { diff --git a/app/javascript/flavours/glitch/features/direct_timeline/components/conversation.jsx b/app/javascript/flavours/glitch/features/direct_timeline/components/conversation.jsx index 839de34dd4..2c70f48a37 100644 --- a/app/javascript/flavours/glitch/features/direct_timeline/components/conversation.jsx +++ b/app/javascript/flavours/glitch/features/direct_timeline/components/conversation.jsx @@ -18,7 +18,7 @@ import ReplyIcon from '@/material-icons/400-24px/reply.svg?react'; import { replyCompose } from 'flavours/glitch/actions/compose'; import { markConversationRead, deleteConversation } from 'flavours/glitch/actions/conversations'; import { openModal } from 'flavours/glitch/actions/modal'; -import { muteStatus, unmuteStatus, revealStatus, hideStatus } from 'flavours/glitch/actions/statuses'; +import { muteStatus, unmuteStatus, toggleStatusSpoilers } from 'flavours/glitch/actions/statuses'; import AttachmentList from 'flavours/glitch/components/attachment_list'; import AvatarComposite from 'flavours/glitch/components/avatar_composite'; import { IconButton } from 'flavours/glitch/components/icon_button'; @@ -156,11 +156,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'))); if (lastStatus.get('spoiler_text')) { setExpanded(!expanded); From cbf25634a9144bb6420fb0350d7ea64bed4f763f Mon Sep 17 00:00:00 2001 From: Claire Date: Mon, 22 Jul 2024 21:30:06 +0200 Subject: [PATCH 097/126] [Glitch] Fix reblogging after refactor Port 55705d8191f31c1089095956fb4124f7505b4bd7 to glitch-soc Signed-off-by: Claire --- app/javascript/flavours/glitch/actions/interactions.js | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/app/javascript/flavours/glitch/actions/interactions.js b/app/javascript/flavours/glitch/actions/interactions.js index 6790d3313b..43673642f5 100644 --- a/app/javascript/flavours/glitch/actions/interactions.js +++ b/app/javascript/flavours/glitch/actions/interactions.js @@ -462,11 +462,11 @@ export function toggleReblog(statusId, skipModal = false) { const missing_description_setting = state.getIn(['local_settings', 'confirm_boost_missing_media_description']); const missing_description = status.get('media_attachments').some(item => !item.get('description')); if (missing_description_setting && missing_description && !status.get('reblogged')) { - dispatch(openModal({ modalType: 'BOOST', modalProps: { status, onReblog: toggleReblogWithoutConfirmation, missingMediaDescription: true } })); + dispatch(openModal({ modalType: 'BOOST', modalProps: { status, onReblog: (status, privacy) => dispatch(toggleReblogWithoutConfirmation(status, privacy)), missingMediaDescription: true } })); } else if (boostModal && !skipModal) { - dispatch(openModal({ modalType: 'BOOST', modalProps: { status, onReblog: toggleReblogWithoutConfirmation } })); + dispatch(openModal({ modalType: 'BOOST', modalProps: { status, onReblog: (status, privacy) => dispatch(toggleReblogWithoutConfirmation(status, privacy)) } })); } else { - toggleReblogWithoutConfirmation(status); + dispatch(toggleReblogWithoutConfirmation(status)); } }; } From af06d74574745deb738e6f526f4d74c31760102d Mon Sep 17 00:00:00 2001 From: Claire Date: Tue, 23 Jul 2024 08:20:17 +0200 Subject: [PATCH 098/126] Fix keyboard shortcuts and navigation in grouped notifications (#31076) --- app/javascript/mastodon/actions/accounts.js | 12 +++ app/javascript/mastodon/actions/compose.js | 18 ++++ app/javascript/mastodon/actions/statuses.js | 14 +++ app/javascript/mastodon/components/status.jsx | 15 +-- .../components/notification_group.tsx | 21 ++++- .../notification_group_with_status.tsx | 80 ++++++++++------ .../components/notification_with_status.tsx | 94 +++++++++++++------ 7 files changed, 188 insertions(+), 66 deletions(-) diff --git a/app/javascript/mastodon/actions/accounts.js b/app/javascript/mastodon/actions/accounts.js index cea915e5f1..9144235195 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 4f2ed450dd..aa1c6de20e 100644 --- a/app/javascript/mastodon/actions/compose.js +++ b/app/javascript/mastodon/actions/compose.js @@ -122,6 +122,18 @@ export function replyCompose(status) { }; } +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))); + } + }; +} + export function cancelReplyCompose() { return { type: COMPOSE_REPLY_CANCEL, @@ -154,6 +166,12 @@ export function mentionCompose(account) { }; } +export function mentionComposeById(accountId) { + return (dispatch, getState) => { + dispatch(mentionCompose(getState().accounts.get(accountId))); + }; +} + export function directCompose(account) { return (dispatch, getState) => { dispatch({ diff --git a/app/javascript/mastodon/actions/statuses.js b/app/javascript/mastodon/actions/statuses.js index 26abaf1bcc..340cee8024 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'; @@ -363,3 +365,15 @@ export const undoStatusTranslation = (id, pollId) => ({ id, pollId, }); + +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/components/status.jsx b/app/javascript/mastodon/components/status.jsx index fe5f38889b..6e3792d7dc 100644 --- a/app/javascript/mastodon/components/status.jsx +++ b/app/javascript/mastodon/components/status.jsx @@ -119,6 +119,7 @@ class Status extends ImmutablePureComponent { skipPrepend: PropTypes.bool, avatarSize: PropTypes.number, deployPictureInPicture: PropTypes.func, + unfocusable: PropTypes.bool, pictureInPicture: ImmutablePropTypes.contains({ inUse: PropTypes.bool, available: PropTypes.bool, @@ -355,7 +356,7 @@ class Status extends ImmutablePureComponent { }; render () { - const { intl, hidden, featured, unread, showThread, scrollKey, pictureInPicture, previousId, nextInReplyToId, rootId, skipPrepend, avatarSize = 46 } = this.props; + const { intl, hidden, featured, unfocusable, unread, showThread, scrollKey, pictureInPicture, previousId, nextInReplyToId, rootId, skipPrepend, avatarSize = 46 } = this.props; let { status, account, ...other } = this.props; @@ -381,8 +382,8 @@ class Status extends ImmutablePureComponent { if (hidden) { return ( - -
+ +
{status.getIn(['account', 'display_name']) || status.getIn(['account', 'username'])} {status.get('content')}
@@ -402,8 +403,8 @@ class Status extends ImmutablePureComponent { }; return ( - -
+ +
: {matchedFilters.join(', ')}. {' '} sosjale web (fediverse) kommunisearje.", "domain_pill.your_handle": "Jo fediverse-adres:", + "domain_pill.your_username": "Jo unike identifikaasje-adres op dizze server. It is mooglik dat der brûkers mei deselde brûkersnamme op ferskate servers te finen binne.", "embed.instructions": "Embed this status on your website by copying the code below.", "embed.preview": "Sa komt it der út te sjen:", "emoji_button.activity": "Aktiviteiten", @@ -290,6 +294,8 @@ "filter_modal.select_filter.subtitle": "In besteande kategory brûke of in nije oanmeitsje", "filter_modal.select_filter.title": "Dit berjocht filterje", "filter_modal.title.status": "In berjocht filterje", + "filtered_notifications_banner.mentions": "{count, plural, one {fermelding} other {fermeldingen}}", + "filtered_notifications_banner.pending_requests": "Meldingen fan {count, plural, =0 {net ien} one {ien persoan} other {# minsken}} dy’t jo miskien kenne", "filtered_notifications_banner.title": "Filtere meldingen", "firehose.all": "Alles", "firehose.local": "Dizze server", @@ -299,6 +305,8 @@ "follow_requests.unlocked_explanation": "Ek al is jo account net besletten, de meiwurkers fan {domain} tinke dat jo miskien de folgjende folchfersiken hânmjittich kontrolearje.", "follow_suggestions.curated_suggestion": "Spesjaal selektearre", "follow_suggestions.dismiss": "Net mear werjaan", + "follow_suggestions.featured_longer": "Hânmjittich selektearre troch it team fan {domain}", + "follow_suggestions.friends_of_friends_longer": "Populêr ûnder minsken dy’t jo folgje", "follow_suggestions.hints.featured": "Dit profyl is hânmjittich troch it {domain}-team selektearre.", "follow_suggestions.hints.friends_of_friends": "Dit profyl is populêr ûnder de minsken dy’t jo folgje.", "follow_suggestions.hints.most_followed": "Dit profyl is ien fan de meast folge op {domain}.", @@ -306,6 +314,8 @@ "follow_suggestions.hints.similar_to_recently_followed": "Dit profyl is hast lyk oan de profilen dy’t jo koartlyn folge hawwe.", "follow_suggestions.personalized_suggestion": "Personalisearre suggestje", "follow_suggestions.popular_suggestion": "Populêre suggestje", + "follow_suggestions.popular_suggestion_longer": "Populêr op {domain}", + "follow_suggestions.similar_to_recently_followed_longer": "Fergelykber mei accounts dy’t jo sûnt koart folgje", "follow_suggestions.view_all": "Alles werjaan", "follow_suggestions.who_to_follow": "Wa te folgjen", "followed_tags": "Folge hashtags", @@ -401,6 +411,8 @@ "limited_account_hint.action": "Profyl dochs besjen", "limited_account_hint.title": "Dit profyl is troch de behearders fan {domain} ferstoppe.", "link_preview.author": "Troch {name}", + "link_preview.more_from_author": "Mear fan {name}", + "link_preview.shares": "{count, plural, one {{counter} berjocht} other {{counter} berjochten}}", "lists.account.add": "Oan list tafoegje", "lists.account.remove": "Ut list fuortsmite", "lists.delete": "List fuortsmite", @@ -419,10 +431,17 @@ "loading_indicator.label": "Lade…", "media_gallery.toggle_visible": "{number, plural, one {ôfbylding ferstopje} other {ôfbyldingen ferstopje}}", "moved_to_account_banner.text": "Omdat jo nei {movedToAccount} ferhuze binne is jo account {disabledAccount} op dit stuit útskeakele.", + "mute_modal.hide_from_notifications": "Meldingen ferstopje", "mute_modal.hide_options": "Opsjes ferstopje", "mute_modal.indefinite": "Oant ik se net mear negearje", "mute_modal.show_options": "Opsjes toane", + "mute_modal.they_can_mention_and_follow": "De persoan kin jo fermelde en folgje, mar jo sjogge neat mear fan dizze persoan.", + "mute_modal.they_wont_know": "Se krije net te witten dat se negearre wurde.", "mute_modal.title": "Brûker negearje?", + "mute_modal.you_wont_see_mentions": "Jo sjogge gjin berjochten mear dy’t dizze account fermelde.", + "mute_modal.you_wont_see_posts": "De persoan kin jo berjochten noch hieltyd sjen, mar jo sjogge harren berjochten net mear.", + "name_and_others": "{name} en {count, plural, one {# oar} other {# oaren}}", + "name_and_others_with_link": "{name} en {count, plural, one {# oar} other {# oaren}}", "navigation_bar.about": "Oer", "navigation_bar.advanced_interface": "Yn avansearre webomjouwing iepenje", "navigation_bar.blocks": "Blokkearre brûkers", @@ -450,13 +469,31 @@ "navigation_bar.security": "Befeiliging", "not_signed_in_indicator.not_signed_in": "Jo moatte oanmelde om tagong ta dizze ynformaasje te krijen.", "notification.admin.report": "{name} hat {target} rapportearre", + "notification.admin.report_account": "{name} rapportearre {count, plural, one {in berjocht} other {# berjochten}} fan {target} foar {category}", + "notification.admin.report_account_other": "{name} rapportearre {count, plural, one {in berjocht} other {# berjochten}} fan {target}", + "notification.admin.report_statuses": "{name} rapportearre {target} foar {category}", + "notification.admin.report_statuses_other": "{name} hat {target} rapportearre", "notification.admin.sign_up": "{name} hat harren registrearre", "notification.favourite": "{name} hat jo berjocht as favoryt markearre", "notification.follow": "{name} folget dy", "notification.follow_request": "{name} hat dy in folchfersyk stjoerd", "notification.mention": "{name} hat dy fermeld", + "notification.moderation-warning.learn_more": "Mear ynfo", + "notification.moderation_warning": "Jo hawwe in moderaasje-warskôging ûntfongen", + "notification.moderation_warning.action_delete_statuses": "Guon fan jo berjochten binne fuortsmiten.", + "notification.moderation_warning.action_disable": "Jo account is útskeakele.", + "notification.moderation_warning.action_mark_statuses_as_sensitive": "Guon fan jo berjochten binne as gefoelich markearre.", + "notification.moderation_warning.action_none": "Jo account hat in moderaasje-warskôging ûntfongen.", + "notification.moderation_warning.action_sensitive": "Jo berjochten wurde fan no ôf as gefoelich markearre.", + "notification.moderation_warning.action_silence": "Jo account is beheind.", + "notification.moderation_warning.action_suspend": "Jo account is útsteld.", "notification.own_poll": "Jo poll is beëinige", + "notification.poll": "In enkête dêr’t jo oan meidien hawwe is beëinige", + "notification.private_mention": "{name} hat jo in priveeberjocht stjoerd", "notification.reblog": "{name} hat jo berjocht boost", + "notification.relationships_severance_event": "Ferlerne ferbiningen mei {name}", + "notification.relationships_severance_event.account_suspension": "In behearder fan {from} hat {target} útsteld, wat betsjut dat jo gjin updates mear fan harren ûntfange kinne of mei harren kommunisearje kinne.", + "notification.relationships_severance_event.domain_block": "In behearder fan {from} hat {target} blokkearre, ynklusyf {followersCount} fan jo folgers en {followingCount, plural, one {# account} other {# accounts}} dy’t jo folgje.", "notification.relationships_severance_event.learn_more": "Mear ynfo", "notification.status": "{name} hat in berjocht pleatst", "notification.update": "{name} hat in berjocht bewurke", @@ -623,8 +660,11 @@ "report_notification.attached_statuses": "{count, plural, one {{count} berjocht} other {{count} berjochten}} tafoege", "report_notification.categories.legal": "Juridysk", "report_notification.categories.other": "Oars", + "report_notification.categories.other_sentence": "oars", "report_notification.categories.spam": "Spam", + "report_notification.categories.spam_sentence": "spam", "report_notification.categories.violation": "Skeinde regels", + "report_notification.categories.violation_sentence": "skeinde regels", "report_notification.open": "Rapport iepenje", "search.no_recent_searches": "Gjin resinte sykopdrachten", "search.placeholder": "Sykje", @@ -669,9 +709,11 @@ "status.direct": "Privee fermelde @{name}", "status.direct_indicator": "Priveefermelding", "status.edit": "Bewurkje", + "status.edited": "Lêst bywurke op {date}", "status.edited_x_times": "{count, plural, one {{count} kear} other {{count} kearen}} bewurke", "status.embed": "Ynslute", "status.favourite": "Favoryt", + "status.favourites": "{count, plural, one {favoryt} other {favoriten}}", "status.filter": "Dit berjocht filterje", "status.filtered": "Filtere", "status.hide": "Berjocht ferstopje", @@ -692,6 +734,7 @@ "status.reblog": "Booste", "status.reblog_private": "Boost nei oarspronklike ûntfangers", "status.reblogged_by": "{name} hat boost", + "status.reblogs": "{count, plural, one {boost} other {boosts}}", "status.reblogs.empty": "Net ien hat dit berjocht noch boost. Wannear’t ien dit docht, falt dat hjir te sjen.", "status.redraft": "Fuortsmite en opnij opstelle", "status.remove_bookmark": "Blêdwizer fuortsmite", diff --git a/app/javascript/mastodon/locales/gd.json b/app/javascript/mastodon/locales/gd.json index 93268c2715..f5488cfce4 100644 --- a/app/javascript/mastodon/locales/gd.json +++ b/app/javascript/mastodon/locales/gd.json @@ -523,7 +523,7 @@ "notifications.policy.filter_not_following_title": "Daoine nach eil thu a’ leantainn", "notifications.policy.filter_private_mentions_hint": "Criathraichte ach ma tha e a’ freagairt do dh’iomradh agad fhèin no ma tha thu a’ leantainn an t-seòladair", "notifications.policy.filter_private_mentions_title": "Iomraidhean prìobhaideach o choigrich", - "notifications.policy.title": "Falamhaich na brathan o…", + "notifications.policy.title": "Falaich na brathan o…", "notifications_permission_banner.enable": "Cuir brathan deasga an comas", "notifications_permission_banner.how_to_control": "Airson brathan fhaighinn nuair nach eil Mastodon fosgailte, cuir na brathan deasga an comas. Tha an smachd agad fhèin air dè na seòrsaichean de chonaltradh a ghineas brathan deasga leis a’ phutan {icon} gu h-àrd nuair a bhios iad air an cur an comas.", "notifications_permission_banner.title": "Na caill dad gu bràth tuilleadh", diff --git a/app/javascript/mastodon/locales/ia.json b/app/javascript/mastodon/locales/ia.json index db1ead30c8..22f9ec7dd5 100644 --- a/app/javascript/mastodon/locales/ia.json +++ b/app/javascript/mastodon/locales/ia.json @@ -443,6 +443,8 @@ "mute_modal.title": "Silentiar le usator?", "mute_modal.you_wont_see_mentions": "Tu non videra le messages que mentiona iste persona.", "mute_modal.you_wont_see_posts": "Iste persona pote totevia vider tu messages, ma tu non videra le sues.", + "name_and_others": "{name} e {count, plural, one {# altere} other {# alteres}}", + "name_and_others_with_link": "{name} e {count, plural, one {# altere} other {# alteres}}", "navigation_bar.about": "A proposito", "navigation_bar.advanced_interface": "Aperir in le interfacie web avantiate", "navigation_bar.blocks": "Usatores blocate", @@ -502,6 +504,8 @@ "notifications.column_settings.admin.report": "Nove reportos:", "notifications.column_settings.admin.sign_up": "Nove inscriptiones:", "notifications.column_settings.alert": "Notificationes de scriptorio", + "notifications.column_settings.beta.category": "Functionalitates experimental", + "notifications.column_settings.beta.grouping": "Notificationes de gruppo", "notifications.column_settings.favourite": "Favorites:", "notifications.column_settings.filter_bar.advanced": "Monstrar tote le categorias", "notifications.column_settings.filter_bar.category": "Barra de filtro rapide", diff --git a/app/javascript/mastodon/locales/lt.json b/app/javascript/mastodon/locales/lt.json index f8a2995c57..6899274f3e 100644 --- a/app/javascript/mastodon/locales/lt.json +++ b/app/javascript/mastodon/locales/lt.json @@ -695,7 +695,7 @@ "sign_in_banner.create_account": "Sukurti paskyrą", "sign_in_banner.follow_anyone": "Sek bet kurį asmenį visoje fediverse ir žiūrėk viską chronologine tvarka. Jokių algoritmų, reklamų ar paspaudimų.", "sign_in_banner.mastodon_is": "„Mastodon“ – tai geriausias būdas sekti, kas vyksta.", - "sign_in_banner.sign_in": "Prisijungimas", + "sign_in_banner.sign_in": "Prisijungti", "sign_in_banner.sso_redirect": "Prisijungti arba užsiregistruoti", "status.admin_account": "Atidaryti prižiūrėjimo sąsają @{name}", "status.admin_domain": "Atidaryti prižiūrėjimo sąsają {domain}", diff --git a/app/javascript/mastodon/locales/pt-PT.json b/app/javascript/mastodon/locales/pt-PT.json index a0359fd868..d492602d22 100644 --- a/app/javascript/mastodon/locales/pt-PT.json +++ b/app/javascript/mastodon/locales/pt-PT.json @@ -443,6 +443,8 @@ "mute_modal.title": "Silenciar utilizador?", "mute_modal.you_wont_see_mentions": "Não verá publicações que os mencionem.", "mute_modal.you_wont_see_posts": "Eles podem continuar a ver as suas publicações, mas você não verá as deles.", + "name_and_others": "{name} e {count, plural, one {# outro} other {# outros}}", + "name_and_others_with_link": "{name} e {count, plural, one {# outro} other {# outros}}", "navigation_bar.about": "Sobre", "navigation_bar.advanced_interface": "Abrir na interface web avançada", "navigation_bar.blocks": "Utilizadores bloqueados", @@ -470,6 +472,10 @@ "navigation_bar.security": "Segurança", "not_signed_in_indicator.not_signed_in": "Necessita de iniciar sessão para utilizar esta funcionalidade.", "notification.admin.report": "{name} denunciou {target}", + "notification.admin.report_account": "{name} denunciou {count, plural, one {uma publicação} other {# publicações}} de {target} por {category}", + "notification.admin.report_account_other": "{name} denunciou {count, plural, one {uma publicação} other {# publicações}} de {target}", + "notification.admin.report_statuses": "{name} denunicou {target} por {category}", + "notification.admin.report_statuses_other": "{name} denunciou {target}", "notification.admin.sign_up": "{name} inscreveu-se", "notification.favourite": "{name} assinalou a sua publicação como favorita", "notification.follow": "{name} começou a seguir-te", @@ -485,6 +491,8 @@ "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.private_mention": "{name} mencionou-o em privado", "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.", @@ -502,6 +510,8 @@ "notifications.column_settings.admin.report": "Novas denúncias:", "notifications.column_settings.admin.sign_up": "Novas inscrições:", "notifications.column_settings.alert": "Notificações no ambiente de trabalho", + "notifications.column_settings.beta.category": "Funcionalidades experimentais", + "notifications.column_settings.beta.grouping": "Agrupar notificações", "notifications.column_settings.favourite": "Favoritos:", "notifications.column_settings.filter_bar.advanced": "Mostrar todas as categorias", "notifications.column_settings.filter_bar.category": "Barra de filtros rápidos", @@ -665,9 +675,13 @@ "report.unfollow_explanation": "Está a seguir esta conta. Para não voltar a ver as publicações desta conta na sua página inicial, deixe de a seguir.", "report_notification.attached_statuses": "{count, plural,one {{count} publicação} other {{count} publicações}} em anexo", "report_notification.categories.legal": "Legal", + "report_notification.categories.legal_sentence": "conteúdo ilegal", "report_notification.categories.other": "Outro", + "report_notification.categories.other_sentence": "outro", "report_notification.categories.spam": "Spam", + "report_notification.categories.spam_sentence": "spam", "report_notification.categories.violation": "Violação de regra", + "report_notification.categories.violation_sentence": "violação de regra", "report_notification.open": "Abrir denúncia", "search.no_recent_searches": "Nenhuma pesquisa recente", "search.placeholder": "Pesquisar", diff --git a/app/javascript/mastodon/locales/th.json b/app/javascript/mastodon/locales/th.json index ab8179863c..3591d07d12 100644 --- a/app/javascript/mastodon/locales/th.json +++ b/app/javascript/mastodon/locales/th.json @@ -443,7 +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": "{name} และ {count, plural, other {# อื่น ๆ}}", + "name_and_others_with_link": "{name} และ {count, plural, other {# อื่น ๆ}}", "navigation_bar.about": "เกี่ยวกับ", "navigation_bar.advanced_interface": "เปิดในส่วนติดต่อเว็บขั้นสูง", "navigation_bar.blocks": "ผู้ใช้ที่ปิดกั้นอยู่", @@ -471,7 +472,10 @@ "navigation_bar.security": "ความปลอดภัย", "not_signed_in_indicator.not_signed_in": "คุณจำเป็นต้องเข้าสู่ระบบเพื่อเข้าถึงทรัพยากรนี้", "notification.admin.report": "{name} ได้รายงาน {target}", - "notification.admin.report_statuses_other": "{name} รายงาน {target}", + "notification.admin.report_account": "{name} ได้รายงาน {count, plural, other {# โพสต์}}จาก {target} สำหรับ {category}", + "notification.admin.report_account_other": "{name} ได้รายงาน {count, plural, 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} ได้ติดตามคุณ", @@ -487,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} ซึ่งหมายความว่าคุณจะไม่สามารถรับการอัปเดตจากเขาหรือโต้ตอบกับเขาได้อีกต่อไป", @@ -505,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": "แถบตัวกรองด่วน", @@ -668,12 +675,13 @@ "report.unfollow_explanation": "คุณกำลังติดตามบัญชีนี้ เพื่อไม่ให้เห็นโพสต์ของเขาในฟีดหน้าแรกของคุณอีกต่อไป ให้เลิกติดตามเขา", "report_notification.attached_statuses": "{count, plural, 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.categories.violation_sentence": "การละเมิดกฎ", "report_notification.open": "รายงานที่เปิด", "search.no_recent_searches": "ไม่มีการค้นหาล่าสุด", "search.placeholder": "ค้นหา", diff --git a/config/locales/ca.yml b/config/locales/ca.yml index 4d0e2ab389..321afb4dcb 100644 --- a/config/locales/ca.yml +++ b/config/locales/ca.yml @@ -471,6 +471,9 @@ ca: title: Recomanacions de comptes a seguir unsuppress: Restaurar les recomanacions de seguiment instances: + audit_log: + title: Registres recents d'auditoria + view_all: Mostra els registres d'auditoria complets availability: description_html: one: Si la tramesa cap el domini falla %{count} dia sense èxit, no es faran més intents d'entrega a no ser que es rebi una tramesa des de el domini. diff --git a/config/locales/da.yml b/config/locales/da.yml index 75da9a0b36..e699d9e8ad 100644 --- a/config/locales/da.yml +++ b/config/locales/da.yml @@ -471,6 +471,9 @@ da: title: Følg-anbefalinger unsuppress: Genopret følg-anbefaling instances: + audit_log: + title: Seneste Revisionslogger + view_all: Vis alle revisionslogger availability: description_html: one: Lykkes det ikke at levere til domænet i løbet af %{count} dag, foretages ingen yderligere leveringsforsøg, medmindre en levering fra domænet modtages. diff --git a/config/locales/de.yml b/config/locales/de.yml index 81b7cd172d..33df545385 100644 --- a/config/locales/de.yml +++ b/config/locales/de.yml @@ -1,7 +1,7 @@ --- de: about: - about_mastodon_html: 'Das soziale Netzwerk der Zukunft: Keine Werbung, keine Überwachung durch Unternehmen – dafür dezentral und mit Anstand! Beherrsche deine Daten mit Mastodon!' + about_mastodon_html: 'Das soziale Netzwerk der Zukunft: Keine Werbung, keine Überwachung durch Unternehmen – dafür dezentral und mit Anstand! Behalte mit Mastodon die Kontrolle über deine Daten!' contact_missing: Nicht festgelegt contact_unavailable: Nicht verfügbar hosted_on: Mastodon, gehostet auf %{domain} @@ -293,7 +293,7 @@ de: empty: Protokolle nicht gefunden. filter_by_action: Nach Aktion filtern filter_by_user: Nach Benutzer*in filtern - title: Protokoll + title: Audit-Log unavailable_instance: "(Server nicht verfügbar)" announcements: destroyed_msg: Ankündigung erfolgreich gelöscht! @@ -471,6 +471,9 @@ de: title: Folgeempfehlungen unsuppress: Folgeempfehlung nicht mehr unterbinden instances: + audit_log: + title: Neueste Audit-Logs + view_all: Alle Audit-Logs anzeigen availability: description_html: one: Wenn die Zustellung an die Domain %{count} Tag lang erfolglos bleibt, werden keine weiteren Zustellversuche unternommen, bis eine Zustellung von der Domain empfangen wird. @@ -588,7 +591,7 @@ de: notes: one: "%{count} Notiz" other: "%{count} Notizen" - action_log: Protokoll + action_log: Audit-Log action_taken_by: Maßnahme ergriffen von actions: delete_description_html: Der gemeldete Beitrag wird gelöscht und die ergriffene Maßnahme wird aufgezeichnet, um dir bei zukünftigen Verstößen des gleichen Kontos zu helfen. diff --git a/config/locales/en-GB.yml b/config/locales/en-GB.yml index fecdab4c7d..a7e6ed7a66 100644 --- a/config/locales/en-GB.yml +++ b/config/locales/en-GB.yml @@ -471,6 +471,9 @@ en-GB: title: Follow recommendations unsuppress: Restore follow recommendation 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. diff --git a/config/locales/es-AR.yml b/config/locales/es-AR.yml index 5add90ae62..35dc9a348d 100644 --- a/config/locales/es-AR.yml +++ b/config/locales/es-AR.yml @@ -471,6 +471,9 @@ es-AR: title: Recom. de cuentas a seguir unsuppress: Restablecer recomendaciones de cuentas para seguir instances: + audit_log: + title: Registros de auditoría recientes + view_all: Ver registros de auditoría completos availability: description_html: one: Si el envío al dominio falla durante %{count} día sin éxito, no se harán más intentos de entrega a menos que se reciba un envío desde el dominio. diff --git a/config/locales/fi.yml b/config/locales/fi.yml index c93c5edc0e..25604d6a1c 100644 --- a/config/locales/fi.yml +++ b/config/locales/fi.yml @@ -293,7 +293,7 @@ fi: empty: Lokeja ei löytynyt. filter_by_action: Suodata tapahtuman mukaan filter_by_user: Suodata käyttäjän mukaan - title: Auditointiloki + title: Tarkastusloki unavailable_instance: "(verkkotunnus ei saatavilla)" announcements: destroyed_msg: Tiedote poistettu onnistuneesti! @@ -471,6 +471,9 @@ fi: title: Seuraamissuositukset unsuppress: Palauta seuraamissuositus instances: + audit_log: + title: Viimeaikaiset tarkastuslokit + view_all: Näytä kaikki tarkastuslokit availability: description_html: one: Jos toimitus verkkotunnukseen epäonnistuu %{count} päivä ilman onnistumista, uusia yrityksiä ei tehdä ennen kuin toimitus alkaen verkkotunnukselta on vastaanotettu. @@ -693,7 +696,7 @@ fi: administrator: Ylläpitäjä administrator_description: Käyttäjät, joilla on tämä käyttöoikeus, ohittavat jokaisen käyttöoikeuden delete_user_data: Poistaa käyttäjän tiedot - delete_user_data_description: Salli käyttäjien poistaa muiden käyttäjien tiedot viipymättä + delete_user_data_description: Sallii käyttäjien poistaa muiden käyttäjien tiedot viipymättä invite_users: Kutsua käyttäjiä invite_users_description: Sallii käyttäjien kutsua uusia ihmisiä palvelimelle manage_announcements: Hallita tiedotteita @@ -724,7 +727,7 @@ fi: manage_users_description: Sallii käyttäjien tarkastella muiden käyttäjien tietoja ja suorittaa valvontatoimia heitä kohtaan manage_webhooks: Hallita webhookeja manage_webhooks_description: Sallii käyttäjien luoda webhookeja hallinnollisiin tapahtumiin - view_audit_log: Katsoa valvontalokia + view_audit_log: Katsoa tarkastuslokia view_audit_log_description: Sallii käyttäjien nähdä palvelimen hallinnollisten toimien historian view_dashboard: Katsoa koontinäyttöä view_dashboard_description: Sallii käyttäjien käyttää kojelautaa ja erilaisia mittareita diff --git a/config/locales/fo.yml b/config/locales/fo.yml index 6a5401ced4..b483a321a9 100644 --- a/config/locales/fo.yml +++ b/config/locales/fo.yml @@ -471,6 +471,9 @@ fo: title: Tilmæli at fylgja unsuppress: Endurskapa tilmæli at fylgja instances: + audit_log: + title: Feskir kanningarloggar + view_all: Vís fullar kanningarloggar availability: description_html: one: Um veiting til navnaøkið ikki riggar í %{count} dag, so verða ongar royndir at veita gjørdar, uttan so, at ein veiting frá navnaøkinum er móttikin. diff --git a/config/locales/fy.yml b/config/locales/fy.yml index 54e28608ef..054ae2fab2 100644 --- a/config/locales/fy.yml +++ b/config/locales/fy.yml @@ -226,6 +226,7 @@ fy: update_custom_emoji: Lokale emoji bywurkje update_domain_block: Domeinblokkade bywurkje update_ip_block: IP-rigel bywurkje + update_report: Rapportaazje bywurkje update_status: Berjocht bywurkje update_user_role: Rol bywurkje actions: @@ -293,6 +294,7 @@ fy: filter_by_action: Op aksje filterje filter_by_user: Op brûker filterje title: Auditlogboek + unavailable_instance: "(domeinnamme net beskikber)" announcements: destroyed_msg: Fuortsmiten fan meidieling slagge! edit: @@ -469,6 +471,9 @@ fy: title: Oanrekommandearre accounts unsuppress: Account wer oanrekommandearje instances: + audit_log: + title: Resinte auditlochboeken + view_all: Folsleine auditlochboeken besjen availability: description_html: one: As de besoarging oan it domein nei %{count} dag mislearjen bliuwt, dan sille der gjin fierdere besykjen ta besoarging dien wurde oant in besoarging fan it domein ûntfongen is. @@ -637,6 +642,7 @@ fy: report: 'Rapportaazje #%{id}' reported_account: Rapportearre account reported_by: Rapportearre troch + reported_with_application: Mei applikaasje rapportearre resolved: Oplost resolved_msg: Rapportaazje oplosse slagge! skip_to_actions: Gean daliks nei de maatregels @@ -780,6 +786,7 @@ fy: approved: Goedkarring fereaske om te registrearje te kinnen none: Net ien kin harren registrearje open: Elkenien kin harren registrearje + warning_hint: Wy riede jo oan om ‘Goedkarring fereaske om registrearje te kinnen’ te brûken, útsein jo der wis fan binne dat jo moderaasjeteam spam en kweawollende registraasjes tidich ôfhannelje kin. security: authorized_fetch: Ferifikaasje fan fedearre servers fereaskje authorized_fetch_hint: Ferifikaasje fereaskje fan federearre servers, makket in striktere hanthaving fan sawol brûkersnivo as server-levelblokken mooglik. Dit giet wol ten koste fan de prestaasjes, ferminderet it berik fan jo antwurden en kin kompatibiliteitsproblemen mei guon federearre services opleverje. Boppedat sil dit net foarkomme dat tawijde spilers jo iepenbiere artikelen en accounts ophelje. @@ -950,6 +957,7 @@ fy: delete: Fuortsmite edit_preset: Foarynstelling foar warskôging bewurkje empty: Jo hawwe noch gjin foarynstellingen foar warskôgingen tafoege. + title: Foarynstellingen foar warskôgingen webhooks: add_new: Einpunt tafoegje delete: Fuortsmite @@ -971,6 +979,9 @@ fy: title: Webhooks webhook: Webhook admin_mailer: + auto_close_registrations: + body: Yn ferbân mei in gebrek oan resinte moderatoraktiviteit, is de registraasjemodus op %{instance} automatysk wizige nei hânmjittige beoardieling troch moderatoren. Dit om foar te kommen dat %{instance} as platfoarm foar eventueel misbrûk brûkt wurde kin. Jo kinne op elk winske momint werom skeakelje nei iepen registraasjes. + subject: De registraasjemodus op %{instance} is automatysk wizige nei hânmjittige beoardieling troch moderatoren new_appeal: actions: delete_statuses: it fuortsmiten fan harren berjochten @@ -1669,6 +1680,8 @@ fy: user_domain_block: Jo hawwe %{target_name} blokkearre lost_followers: Ferlerne folgers lost_follows: Ferlerne folge accounts + preamble: Jo kinne folge accounts en folgers ferlieze wannear’t jo in domein blokkearje of wannear’t de moderators fan jo server beslisse om in eksterne server út te sluten. Wannear’t dat bart, kinne jo listen fan ferbrutsen folchrelaasjes downloade, dizze ynspektearje en mooglik ymportearje op in oare server. + purged: Ynformaasje oer dizze server is fuortsmiten troch de behearders fan jo server. type: Barren statuses: attached: diff --git a/config/locales/ga.yml b/config/locales/ga.yml index 647c46d7cf..57162e2ed1 100644 --- a/config/locales/ga.yml +++ b/config/locales/ga.yml @@ -495,6 +495,9 @@ ga: title: Moltaí leanúna unsuppress: Aischuir moladh leanúna instances: + audit_log: + title: Logchomhaid Iniúchta le Déanaí + view_all: Féach ar logaí iniúchta iomlána 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. diff --git a/config/locales/gl.yml b/config/locales/gl.yml index d1c8633bad..45ae60008c 100644 --- a/config/locales/gl.yml +++ b/config/locales/gl.yml @@ -471,6 +471,9 @@ gl: title: Recomendacións de seguimento unsuppress: Restablecer recomendación de seguimento instances: + audit_log: + title: Rexistros de Auditoría recentes + view_all: Ver os rexistros de auditoría completos availability: description_html: one: Se fallan as entregas ao dominio por %{count} día, non se farán máis intentos a menos que se reciba unha solicitude desde ese dominio. diff --git a/config/locales/he.yml b/config/locales/he.yml index 105bd059f2..5a9571da75 100644 --- a/config/locales/he.yml +++ b/config/locales/he.yml @@ -487,6 +487,9 @@ he: title: המלצות מעקב unsuppress: שחזור המלצות מעקב instances: + audit_log: + title: יומני ביקורת אחרונים + view_all: צפיה ביומני הביקורת המלאים availability: description_html: many: אם משלוח לדומיין נכשל במשך %{count} ימים שונים ולא מצליח, נסיונות משלוח נוספים לא יעשו אלא אם התקבל משלוח מהדומיין. diff --git a/config/locales/hu.yml b/config/locales/hu.yml index df32bd39d1..695b3786f2 100644 --- a/config/locales/hu.yml +++ b/config/locales/hu.yml @@ -471,6 +471,9 @@ hu: title: Követési ajánlatok unsuppress: Követési ajánlatok visszaállítása instances: + audit_log: + title: Legutóbbi auditnapló + view_all: Teljes auditnapló megtekintése availability: description_html: one: Ha a domainre történő kézbesítés %{count} teljes nap sikertelen, további kézbesítéseket már nem kísérlünk meg, hacsak mi nem kapunk kézbesítést a domaintől. diff --git a/config/locales/ia.yml b/config/locales/ia.yml index 7350ffceeb..101d1ecc81 100644 --- a/config/locales/ia.yml +++ b/config/locales/ia.yml @@ -226,6 +226,7 @@ ia: update_custom_emoji: Actualisar emoji personalisate update_domain_block: Actualisar blocada de dominio update_ip_block: Actualisar le regula IP + update_report: Actualisar le reporto update_status: Actualisar le message update_user_role: Actualisar rolo actions: @@ -638,6 +639,7 @@ ia: report: 'Reporto #%{id}' reported_account: Conto reportate reported_by: Reportate per + reported_with_application: Signalate con le application resolved: Resolvite resolved_msg: Reporto resolvite con successo! skip_to_actions: Saltar al actiones diff --git a/config/locales/is.yml b/config/locales/is.yml index a4cc282d1d..b008e284dd 100644 --- a/config/locales/is.yml +++ b/config/locales/is.yml @@ -471,6 +471,9 @@ is: title: Fylgja meðmælum unsuppress: Endurheimta að fylgja meðmælum instances: + audit_log: + title: Nýlegar atvikaskráningar + view_all: Skoða heildar-atvikaskráningar availability: description_html: one: Ef afhending til lénsins mistekst í %{count} dag, verður ekki reynt aftur að afhenda til lénsins nema ef afhending frá léninu berst. diff --git a/config/locales/it.yml b/config/locales/it.yml index 68e1608d9c..02c21ac312 100644 --- a/config/locales/it.yml +++ b/config/locales/it.yml @@ -471,6 +471,9 @@ it: title: Consigli su chi seguire unsuppress: Ripristina consigli su chi seguire instances: + audit_log: + title: Log di Controllo Recenti + view_all: Visualizza tutti i log availability: description_html: one: Se la consegna al dominio fallisce %{count} giorno, non sarà effettuato alcun tentativo di consegna ulteriore a meno che la consegna dal dominio non sia ricevuta. diff --git a/config/locales/ja.yml b/config/locales/ja.yml index 5142b55032..0eeb055170 100644 --- a/config/locales/ja.yml +++ b/config/locales/ja.yml @@ -223,6 +223,7 @@ ja: update_custom_emoji: カスタム絵文字を更新 update_domain_block: ドメインブロックを更新 update_ip_block: IPルールを更新 + update_report: 通報の更新 update_status: 投稿を更新 update_user_role: ロールを更新 actions: @@ -626,6 +627,7 @@ ja: report: '通報 #%{id}' reported_account: 報告対象アカウント reported_by: 報告者 + reported_with_application: 報告に使用されたアプリ resolved: 解決済み resolved_msg: 通報を解決済みにしました! skip_to_actions: アクションに移動 diff --git a/config/locales/kab.yml b/config/locales/kab.yml index a094936aaf..d6295ec9ae 100644 --- a/config/locales/kab.yml +++ b/config/locales/kab.yml @@ -810,7 +810,7 @@ kab: video: one: "%{count} n tbidyutt" other: "%{count} n tbidyutin" - edited_at_html: Tettwaẓreg %{date} + edited_at_html: Tettwaẓreg ass n %{date} open_in_web: Ldi deg Web poll: total_people: diff --git a/config/locales/ko.yml b/config/locales/ko.yml index 632bd7c097..4a1afee842 100644 --- a/config/locales/ko.yml +++ b/config/locales/ko.yml @@ -465,6 +465,9 @@ ko: title: 팔로우 추천 unsuppress: 팔로우 추천 복원 instances: + audit_log: + title: 최근 감사 기록 + view_all: 감사 기록 전체 보기 availability: description_html: other: 도메인에 대한 전달이 성공 없이 %{count}일 실패한다면, 이후의 전달 시도는 해당 도메인에서 전달이 오기 전까지는 만들어지지 않습니다. diff --git a/config/locales/nl.yml b/config/locales/nl.yml index 91872754f5..b23b4e10af 100644 --- a/config/locales/nl.yml +++ b/config/locales/nl.yml @@ -471,6 +471,9 @@ nl: title: Aanbevolen accounts unsuppress: Account weer aanbevelen instances: + audit_log: + title: Recente audit-logboeken + view_all: Volledige audit-logboeken inzien availability: description_html: one: Wanneer de bezorging aan het domein gedurende %{count} dag blijft mislukken dan worden er geen bezorgpogingen meer gedaan, totdat een bezorging van het domein wordt ontvangen. @@ -977,7 +980,7 @@ nl: webhook: Webhook admin_mailer: auto_close_registrations: - body: In verband met een gebrek aan recentelijke moderator-activiteit, is de registratie-modus op %{instance} automatisch veranderd naar handmatige beoordeling door moderatoren. Dit om te voorkomen dat %{instance} als platform voor eventueel misbruik kan worden gebruikt. Je kunt op elk gewenst moment veel terugschakelen naar open registraties. + body: In verband met een gebrek aan recentelijke moderatoractiviteit, is de registratiemodus op %{instance} automatisch gewijzigd naar handmatige beoordeling door moderatoren. Dit om te voorkomen dat %{instance} als platform voor eventueel misbruik kan worden gebruikt. Je kunt op elk gewenst moment weer terugschakelen naar open registraties. subject: De registratie-modus op %{instance} is automatisch veranderd naar handmatige beoordeling door moderatoren new_appeal: actions: diff --git a/config/locales/pl.yml b/config/locales/pl.yml index b0c733102e..8a2dab5b99 100644 --- a/config/locales/pl.yml +++ b/config/locales/pl.yml @@ -487,6 +487,9 @@ pl: title: Polecane konta unsuppress: Przywróć polecenie obserwacji konta instances: + audit_log: + title: Niedawne zdarzenia z dzienniku + view_all: Pokaż pełny dziennik zdarzeń availability: description_html: few: Jeśli dostarczenie do domeny nie powiedzie się %{count} dni bez powodzenia, nie zostaną podjęte dalsze próby dostawy, chyba że otrzymano dostawę od domeny. diff --git a/config/locales/pt-PT.yml b/config/locales/pt-PT.yml index 1df423bb7d..b0db0709c1 100644 --- a/config/locales/pt-PT.yml +++ b/config/locales/pt-PT.yml @@ -471,6 +471,9 @@ pt-PT: title: Seguir recomendações unsuppress: Restaurar recomendações de contas a seguir instances: + audit_log: + title: Registos de auditoria recentes + view_all: Ver registos de auditoria completos availability: description_html: one: Se a transmissão ao domínio falhar ao final de %{count} dia(s), não será feita mais nenhuma tentativa de transmissão a menos que seja recebida uma transmissão proveniente desse domínio. diff --git a/config/locales/simple_form.fy.yml b/config/locales/simple_form.fy.yml index 9e0f67b707..64e5dd68da 100644 --- a/config/locales/simple_form.fy.yml +++ b/config/locales/simple_form.fy.yml @@ -211,6 +211,7 @@ fy: setting_default_privacy: Sichtberheid fan nije berjochten setting_default_sensitive: Media altyd as gefoelich markearje setting_delete_modal: Freegje foar it fuortsmiten fan in berjocht in befêstiging + setting_disable_hover_cards: Profylfoarbylden troch der oerhinne te sweven útskeakelje setting_disable_swiping: Feibewegingen útskeakelje setting_display_media: Mediawerjefte setting_display_media_default: Standert @@ -242,11 +243,13 @@ fy: warn: Mei in warskôging ferstopje form_admin_settings: activity_api_enabled: Publyklik meitsjen fan sammele statistiken oer brûkersaktiviteiten yn de API + app_icon: App-piktogram backups_retention_period: Bewartermyn brûkersargyf bootstrap_timeline_accounts: Accounts dy’t altyd oan nije brûkers oanrekommandearre wurde closed_registrations_message: Oanpast berjocht wannear registraasje útskeakele is content_cache_retention_period: Bewartermyn foar eksterne ynhâld custom_css: Oanpaste CSS + favicon: Favicon mascot: Oanpaste maskotte (legacy) media_cache_retention_period: Bewartermyn mediabuffer peers_api_enabled: Publyklik meitsjen fan ûntdekte servers yn de API diff --git a/config/locales/simple_form.ia.yml b/config/locales/simple_form.ia.yml index 2d0af3001e..bee2454cf0 100644 --- a/config/locales/simple_form.ia.yml +++ b/config/locales/simple_form.ia.yml @@ -242,11 +242,13 @@ ia: warn: Celar con un advertimento form_admin_settings: activity_api_enabled: Publicar statisticas aggregate re le activitate de usator in le API + app_icon: Icone de app backups_retention_period: Periodo de retention del archivo de usator bootstrap_timeline_accounts: Recommenda sempre iste contos a nove usatores closed_registrations_message: Message personalisate quando le inscriptiones non es disponibile content_cache_retention_period: Periodo de retention del contento remote custom_css: CSS personalisate + favicon: Favicon mascot: Personalisar le mascotte (hereditage) media_cache_retention_period: Periodo de retention del cache multimedial peers_api_enabled: Publicar le lista de servitores discoperite in le API diff --git a/config/locales/simple_form.th.yml b/config/locales/simple_form.th.yml index cdc82367f9..c72112645b 100644 --- a/config/locales/simple_form.th.yml +++ b/config/locales/simple_form.th.yml @@ -83,7 +83,7 @@ th: closed_registrations_message: แสดงเมื่อมีการปิดการลงทะเบียน content_cache_retention_period: จะลบโพสต์ทั้งหมดจากเซิร์ฟเวอร์อื่น ๆ (รวมถึงการดันและการตอบกลับ) หลังจากจำนวนวันที่ระบุ โดยไม่คำนึงถึงการโต้ตอบใด ๆ ของผู้ใช้ในเซิร์ฟเวอร์กับโพสต์เหล่านั้น สิ่งนี้รวมถึงโพสต์ที่ผู้ใช้ในเซิร์ฟเวอร์ได้ทำเครื่องหมายโพสต์ว่าเป็นที่คั่นหน้าหรือรายการโปรด การกล่าวถึงแบบส่วนตัวระหว่างผู้ใช้จากอินสแตนซ์ที่แตกต่างกันจะหายไปและไม่สามารถคืนค่าได้เช่นกัน การใช้การตั้งค่านี้มีไว้สำหรับอินสแตนซ์ที่มีวัตถุประสงค์พิเศษและทำลายความคาดหวังของผู้ใช้จำนวนมากเมื่อนำไปใช้สำหรับการใช้งานที่มีวัตถุประสงค์ทั่วไป custom_css: คุณสามารถนำไปใช้ลักษณะที่กำหนดเองใน Mastodon รุ่นเว็บ - favicon: WEBP, PNG, GIF หรือ JPG เขียนทับ Favicon ของ Mastodon เริ่มต้นด้วยไอคอนที่กำหนดเอง + favicon: WEBP, PNG, GIF หรือ JPG เขียนทับไอคอนเว็บของ Mastodon เริ่มต้นด้วยไอคอนที่กำหนดเอง mascot: เขียนทับภาพประกอบในส่วนติดต่อเว็บขั้นสูง media_cache_retention_period: จะแคชไฟล์สื่อจากโพสต์ที่สร้างโดยผู้ใช้ระยะไกลในเซิร์ฟเวอร์ของคุณ เมื่อตั้งเป็นค่าบวก จะลบสื่อหลังจากจำนวนวันที่ระบุ หากมีการขอข้อมูลสื่อหลังจากมีการลบสื่อ จะดาวน์โหลดสื่อใหม่ หากเนื้อหาต้นฉบับยังคงใช้งานได้ เนื่องจากข้อจำกัดเกี่ยวกับความถี่ที่บัตรตัวอย่างลิงก์สำรวจไซต์จากบุคคลที่สาม ขอแนะนำให้ตั้งค่านี้เป็นอย่างน้อย 14 วัน มิฉะนั้นจะไม่อัปเดตบัตรตัวอย่างลิงก์ตามความต้องการก่อนเวลานั้น peers_api_enabled: รายการชื่อโดเมนที่เซิร์ฟเวอร์นี้พบในจักรวาลสหพันธ์ ไม่มีข้อมูลรวมอยู่ที่นี่เกี่ยวกับว่าคุณติดต่อกับเซิร์ฟเวอร์ที่กำหนดหรือไม่ เพียงแค่ว่าเซิร์ฟเวอร์ของคุณทราบเกี่ยวกับเซิร์ฟเวอร์ที่กำหนด มีการใช้สิ่งนี้โดยบริการที่เก็บรวบรวมสถิติในการติดต่อกับภายนอกในความหมายทั่วไป @@ -243,11 +243,13 @@ th: 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/sq.yml b/config/locales/sq.yml index c4bed80cc7..7ba5bf6570 100644 --- a/config/locales/sq.yml +++ b/config/locales/sq.yml @@ -470,6 +470,9 @@ sq: title: Rekomandime ndjekjeje unsuppress: Rikthe rekomandime ndjekjeje instances: + audit_log: + title: Regjistra Auditimesh Së Fundi + view_all: Shihni regjistra të plotë auditimesh availability: description_html: one: Nëse dhënia e mesazheve te përkatësia dështon për %{count} ditë pa sukses, s’do të bëhen përpjekje të tjera për dhënie, veç në u marrtë një dërgim prej përkatësisë. diff --git a/config/locales/th.yml b/config/locales/th.yml index df76d97c00..678b5ab638 100644 --- a/config/locales/th.yml +++ b/config/locales/th.yml @@ -223,6 +223,7 @@ th: update_custom_emoji: อัปเดตอีโมจิที่กำหนดเอง update_domain_block: อัปเดตการปิดกั้นโดเมน update_ip_block: อัปเดตกฎ IP + update_report: อัปเดตรายงาน update_status: อัปเดตโพสต์ update_user_role: อัปเดตบทบาท actions: @@ -462,6 +463,9 @@ th: title: คำแนะนำการติดตาม unsuppress: คืนค่าคำแนะนำการติดตาม instances: + audit_log: + title: รายการบันทึกการตรวจสอบล่าสุด + view_all: ดูรายการบันทึกการตรวจสอบแบบเต็ม availability: description_html: other: หากการจัดส่งไปยังโดเมนล้มเหลวเป็นเวลา %{count} วันที่แตกต่างกัน โดยไม่สำเร็จ จะไม่ทำการพยายามจัดส่งเพิ่มเติมเว้นแต่จะได้รับการจัดส่ง จาก โดเมน @@ -626,6 +630,7 @@ th: report: 'รายงาน #%{id}' reported_account: บัญชีที่ได้รับการรายงาน reported_by: รายงานโดย + reported_with_application: รายงานด้วยแอปพลิเคชัน resolved: แก้ปัญหาแล้ว resolved_msg: แก้ปัญหารายงานสำเร็จ! skip_to_actions: ข้ามไปยังการกระทำ diff --git a/config/locales/tr.yml b/config/locales/tr.yml index 9855b56924..f561781e59 100644 --- a/config/locales/tr.yml +++ b/config/locales/tr.yml @@ -471,6 +471,9 @@ tr: title: Takip önerileri unsuppress: Takip önerisini geri getir instances: + audit_log: + title: En Son Denetim Günlükleri + view_all: Tüm denetim günlüklerini görüntüle availability: description_html: one: Eğer alan adına teslimat %{count} gün boyunca başarısız olursa, alan adından bir teslimat gelmedikçe yeni bir iletim denemesi yapılmayacak. @@ -725,7 +728,7 @@ tr: manage_users_description: Kullanıcıların, diğer kullanıcıların ayrıntılarını görüntülemesine ve onlara karşı denetim eylemleri gerçekleştirmesine izin verir manage_webhooks: Webhookları Yönetme manage_webhooks_description: Kullanıcıların yönetsel olaylar için webhook kurmasına izin verir - view_audit_log: Denetim Kaydını Görüntüleme + view_audit_log: Denetim Günlüğünü Görüntüleme view_audit_log_description: Kullanıcıların sunucudaki yönetsel eylemlerin bir tarihçesini görüntülemesine izin verir view_dashboard: Ana Paneli Görüntüleme view_dashboard_description: Kullanıcıların ana panele ve çeşitli ölçütlere erişmesine izin verir diff --git a/config/locales/uk.yml b/config/locales/uk.yml index a5cdcfefb4..31ce3e6b79 100644 --- a/config/locales/uk.yml +++ b/config/locales/uk.yml @@ -487,6 +487,9 @@ uk: title: Поради щодо підписок unsuppress: Відновити поради щодо підписок instances: + audit_log: + title: Останні журнали перевірки + view_all: Переглянути повні журнали перевірки availability: description_html: few: Якщо доставлення до домену не вдалася за %{count} інших дні, жодних спроб доставлення не здійснюється, доки доставлення від домену не отримуватиметься. diff --git a/config/locales/vi.yml b/config/locales/vi.yml index 48e026d377..b44ba15a77 100644 --- a/config/locales/vi.yml +++ b/config/locales/vi.yml @@ -463,6 +463,9 @@ vi: title: Gợi ý theo dõi unsuppress: Mở lại gợi ý theo dõi instances: + audit_log: + title: Kiểm duyệt gần đây + view_all: Xem lịch sử đầy đủ availability: description_html: other: Nếu chuyển đến tên miền %{count} ngày mà không thành công, không chuyển gì nữa cho tới khi sự tiếp nhận từ máy chủ được nhận. diff --git a/config/locales/zh-CN.yml b/config/locales/zh-CN.yml index d2d64152fa..50921b07d8 100644 --- a/config/locales/zh-CN.yml +++ b/config/locales/zh-CN.yml @@ -463,6 +463,9 @@ zh-CN: title: 关注推荐 unsuppress: 恢复推荐关注 instances: + audit_log: + title: 近期审计日志 + view_all: 查看完整审计日志 availability: description_html: other: 如果连续 %{count} 天 均无法成功向该域名投递消息,则将不再尝试向其投递,直至收到来自该域名的消息。 diff --git a/config/locales/zh-TW.yml b/config/locales/zh-TW.yml index 375c79048a..388fe35d84 100644 --- a/config/locales/zh-TW.yml +++ b/config/locales/zh-TW.yml @@ -463,6 +463,9 @@ zh-TW: title: 跟隨建議 unsuppress: 回復跟隨建議 instances: + audit_log: + title: 近期審計紀錄 + view_all: 檢視完整審計紀錄 availability: description_html: other: 若於 %{count} 天向某個網域遞送失敗,除非收到某個網域的遞送表單,否則不會繼續嘗試遞送。 From efa7ad9d750316917b3931ada5ed90bebed891f0 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Thu, 25 Jul 2024 07:44:54 +0000 Subject: [PATCH 118/126] chore(deps): update dependency node to 20.16 (#31127) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- .nvmrc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.nvmrc b/.nvmrc index cecb936289..1bdd901e66 100644 --- a/.nvmrc +++ b/.nvmrc @@ -1 +1 @@ -20.15 +20.16 From 4d374cf73096be1e5347e131c91c99842e3c6dbb Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Thu, 25 Jul 2024 12:00:06 +0200 Subject: [PATCH 119/126] chore(deps): update dependency opentelemetry-exporter-otlp to v0.28.1 (#31139) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- Gemfile.lock | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/Gemfile.lock b/Gemfile.lock index 657fb77fea..31e317e819 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -289,7 +289,7 @@ GEM ruby-progressbar (~> 1.4) globalid (1.2.1) activesupport (>= 6.1) - google-protobuf (3.25.3) + google-protobuf (3.25.4) googleapis-common-protos-types (1.14.0) google-protobuf (~> 3.18) haml (6.3.0) @@ -495,7 +495,7 @@ GEM opentelemetry-api (1.3.0) opentelemetry-common (0.20.1) opentelemetry-api (~> 1.0) - opentelemetry-exporter-otlp (0.28.0) + opentelemetry-exporter-otlp (0.28.1) google-protobuf (>= 3.18) googleapis-common-protos-types (~> 1.3) opentelemetry-api (~> 1.1) @@ -578,7 +578,7 @@ GEM opentelemetry-common (~> 0.20) opentelemetry-registry (~> 0.2) opentelemetry-semantic_conventions - opentelemetry-semantic_conventions (1.10.0) + opentelemetry-semantic_conventions (1.10.1) opentelemetry-api (~> 1.0) orm_adapter (0.5.0) ox (2.14.18) From 34626b8291db22fafaa7963496bc304f2725ae58 Mon Sep 17 00:00:00 2001 From: Matt Jankowski Date: Thu, 25 Jul 2024 06:37:48 -0400 Subject: [PATCH 120/126] Update schema to reflect full `db:migrate` run results (#31128) --- db/schema.rb | 26 +++++++++++++------------- 1 file changed, 13 insertions(+), 13 deletions(-) diff --git a/db/schema.rb b/db/schema.rb index 66da12f713..453f1f7b89 100644 --- a/db/schema.rb +++ b/db/schema.rb @@ -194,8 +194,8 @@ ActiveRecord::Schema[7.1].define(version: 2024_07_13_171909) do t.integer "avatar_storage_schema_version" t.integer "header_storage_schema_version" t.string "devices_url" - t.integer "suspension_origin" t.datetime "sensitized_at", precision: nil + t.integer "suspension_origin" t.boolean "trendable" t.datetime "reviewed_at", precision: nil t.datetime "requested_review_at", precision: nil @@ -579,12 +579,12 @@ ActiveRecord::Schema[7.1].define(version: 2024_07_13_171909) do end create_table "ip_blocks", force: :cascade do |t| - t.datetime "created_at", precision: nil, null: false - t.datetime "updated_at", precision: nil, null: false - t.datetime "expires_at", precision: nil t.inet "ip", default: "0.0.0.0", null: false t.integer "severity", default: 0, null: false + t.datetime "expires_at", precision: nil t.text "comment", default: "", null: false + t.datetime "created_at", precision: nil, null: false + t.datetime "updated_at", precision: nil, null: false t.index ["ip"], name: "index_ip_blocks_on_ip", unique: true end @@ -1421,9 +1421,9 @@ ActiveRecord::Schema[7.1].define(version: 2024_07_13_171909) do add_index "instances", ["domain"], name: "index_instances_on_domain", unique: true create_view "user_ips", sql_definition: <<-SQL - SELECT t0.user_id, - t0.ip, - max(t0.used_at) AS used_at + SELECT user_id, + ip, + max(used_at) AS used_at FROM ( SELECT users.id AS user_id, users.sign_up_ip AS ip, users.created_at AS used_at @@ -1440,7 +1440,7 @@ ActiveRecord::Schema[7.1].define(version: 2024_07_13_171909) do login_activities.created_at FROM login_activities WHERE (login_activities.success = true)) t0 - GROUP BY t0.user_id, t0.ip; + GROUP BY user_id, ip; SQL create_view "account_summaries", materialized: true, sql_definition: <<-SQL SELECT accounts.id AS account_id, @@ -1461,9 +1461,9 @@ ActiveRecord::Schema[7.1].define(version: 2024_07_13_171909) do add_index "account_summaries", ["account_id"], name: "index_account_summaries_on_account_id", unique: true create_view "global_follow_recommendations", materialized: true, sql_definition: <<-SQL - SELECT t0.account_id, - sum(t0.rank) AS rank, - array_agg(t0.reason) AS reason + SELECT account_id, + sum(rank) AS rank, + array_agg(reason) AS reason FROM ( SELECT account_summaries.account_id, ((count(follows.id))::numeric / (1.0 + (count(follows.id))::numeric)) AS rank, 'most_followed'::text AS reason @@ -1487,8 +1487,8 @@ ActiveRecord::Schema[7.1].define(version: 2024_07_13_171909) do WHERE (follow_recommendation_suppressions.account_id = statuses.account_id))))) GROUP BY account_summaries.account_id HAVING (sum((status_stats.reblogs_count + status_stats.favourites_count)) >= (5)::numeric)) t0 - GROUP BY t0.account_id - ORDER BY (sum(t0.rank)) DESC; + GROUP BY account_id + ORDER BY (sum(rank)) DESC; SQL add_index "global_follow_recommendations", ["account_id"], name: "index_global_follow_recommendations_on_account_id", unique: true From e881a5967149e34046f91d3f4445ebb457348b93 Mon Sep 17 00:00:00 2001 From: Matt Jankowski Date: Thu, 25 Jul 2024 10:18:24 -0400 Subject: [PATCH 121/126] Add `User.unconfirmed` scope, reduce factories in `scheduler/user_cleanup` spec (#31063) --- app/models/user.rb | 1 + .../scheduler/user_cleanup_scheduler.rb | 2 +- .../scheduler/user_cleanup_scheduler_spec.rb | 30 ++++++++++--------- 3 files changed, 18 insertions(+), 15 deletions(-) diff --git a/app/models/user.rb b/app/models/user.rb index 8bc0b23ce8..7285456926 100644 --- a/app/models/user.rb +++ b/app/models/user.rb @@ -117,6 +117,7 @@ class User < ApplicationRecord scope :pending, -> { where(approved: false) } scope :approved, -> { where(approved: true) } scope :confirmed, -> { where.not(confirmed_at: nil) } + scope :unconfirmed, -> { where(confirmed_at: nil) } scope :enabled, -> { where(disabled: false) } scope :disabled, -> { where(disabled: true) } scope :active, -> { confirmed.signed_in_recently.account_not_suspended } diff --git a/app/workers/scheduler/user_cleanup_scheduler.rb b/app/workers/scheduler/user_cleanup_scheduler.rb index 74abc23701..9f58d9225b 100644 --- a/app/workers/scheduler/user_cleanup_scheduler.rb +++ b/app/workers/scheduler/user_cleanup_scheduler.rb @@ -16,7 +16,7 @@ class Scheduler::UserCleanupScheduler private def clean_unconfirmed_accounts! - User.where('confirmed_at is NULL AND confirmation_sent_at <= ?', UNCONFIRMED_ACCOUNTS_MAX_AGE_DAYS.days.ago).reorder(nil).find_in_batches do |batch| + User.unconfirmed.where(confirmation_sent_at: ..UNCONFIRMED_ACCOUNTS_MAX_AGE_DAYS.days.ago).reorder(nil).find_in_batches do |batch| # We have to do it separately because of missing database constraints AccountModerationNote.where(target_account_id: batch.map(&:account_id)).delete_all Account.where(id: batch.map(&:account_id)).delete_all diff --git a/spec/workers/scheduler/user_cleanup_scheduler_spec.rb b/spec/workers/scheduler/user_cleanup_scheduler_spec.rb index c3940901d4..7952f2c146 100644 --- a/spec/workers/scheduler/user_cleanup_scheduler_spec.rb +++ b/spec/workers/scheduler/user_cleanup_scheduler_spec.rb @@ -12,29 +12,31 @@ describe Scheduler::UserCleanupScheduler do describe '#perform' do before do - # Need to update the already-existing users because their initialization overrides confirmation_sent_at + # Update already-existing users because initialization overrides `confirmation_sent_at` new_unconfirmed_user.update!(confirmed_at: nil, confirmation_sent_at: Time.now.utc) old_unconfirmed_user.update!(confirmed_at: nil, confirmation_sent_at: 10.days.ago) confirmed_user.update!(confirmed_at: 1.day.ago) end - it 'deletes the old unconfirmed user, their account, and the moderation note' do + it 'deletes the old unconfirmed user and metadata while preserving confirmed user and newer unconfirmed user' do expect { subject.perform } - .to change { User.exists?(old_unconfirmed_user.id) }.from(true).to(false) - .and change { Account.exists?(old_unconfirmed_user.account_id) }.from(true).to(false) - expect { moderation_note.reload }.to raise_error(ActiveRecord::RecordNotFound) + .to change { User.exists?(old_unconfirmed_user.id) } + .from(true).to(false) + .and change { Account.exists?(old_unconfirmed_user.account_id) } + .from(true).to(false) + expect { moderation_note.reload } + .to raise_error(ActiveRecord::RecordNotFound) + expect_preservation_of(new_unconfirmed_user) + expect_preservation_of(confirmed_user) end - it 'does not delete the new unconfirmed user or their account' do - subject.perform - expect(User.exists?(new_unconfirmed_user.id)).to be true - expect(Account.exists?(new_unconfirmed_user.account_id)).to be true - end + private - it 'does not delete the confirmed user or their account' do - subject.perform - expect(User.exists?(confirmed_user.id)).to be true - expect(Account.exists?(confirmed_user.account_id)).to be true + def expect_preservation_of(user) + expect(User.exists?(user.id)) + .to be true + expect(Account.exists?(user.account_id)) + .to be true end end end From 337a7fcf30b7253830633dfe962d4411b6b2a370 Mon Sep 17 00:00:00 2001 From: Adam Niedzielski Date: Thu, 25 Jul 2024 16:24:19 +0200 Subject: [PATCH 122/126] =?UTF-8?q?Fix=20=C3=9F=20bug=20in=20regexp=20for?= =?UTF-8?q?=20mentions=20and=20tags=20(#31122)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/models/account.rb | 2 +- app/models/tag.rb | 2 +- spec/models/account_spec.rb | 8 ++++++++ spec/models/tag_spec.rb | 8 ++++++++ 4 files changed, 18 insertions(+), 2 deletions(-) diff --git a/app/models/account.rb b/app/models/account.rb index 8a990bb831..23ff07c769 100644 --- a/app/models/account.rb +++ b/app/models/account.rb @@ -68,7 +68,7 @@ class Account < ApplicationRecord INSTANCE_ACTOR_ID = -99 USERNAME_RE = /[a-z0-9_]+([a-z0-9_.-]+[a-z0-9_]+)?/i - MENTION_RE = %r{(? Date: Thu, 25 Jul 2024 10:28:08 -0400 Subject: [PATCH 123/126] Improve failure message on pagination matcher (#31146) --- spec/support/matchers/api_pagination.rb | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/spec/support/matchers/api_pagination.rb b/spec/support/matchers/api_pagination.rb index 81e27e44b8..f7d552b242 100644 --- a/spec/support/matchers/api_pagination.rb +++ b/spec/support/matchers/api_pagination.rb @@ -7,7 +7,7 @@ RSpec::Matchers.define :include_pagination_headers do |links| end.all? end - failure_message do |header| - "expected that #{header} would have the same values as #{links}." + failure_message do |response| + "expected that #{response.headers['Link']} would have the same values as #{links}." end end From fbf95216c55adac8af18bc709b4e3f456641013a Mon Sep 17 00:00:00 2001 From: Adam Niedzielski Date: Thu, 25 Jul 2024 16:51:44 +0200 Subject: [PATCH 124/126] Fix LinkCrawlWorker NoMethodError: undefined method `[]' for nil (#31144) --- app/lib/link_details_extractor.rb | 2 +- spec/lib/link_details_extractor_spec.rb | 18 ++++++++++++++++++ 2 files changed, 19 insertions(+), 1 deletion(-) diff --git a/app/lib/link_details_extractor.rb b/app/lib/link_details_extractor.rb index d81f4a3062..bd78aef7a9 100644 --- a/app/lib/link_details_extractor.rb +++ b/app/lib/link_details_extractor.rb @@ -101,7 +101,7 @@ class LinkDetailsExtractor end def json - @json ||= root_array(Oj.load(@data)).find { |obj| SUPPORTED_TYPES.include?(obj['@type']) } || {} + @json ||= root_array(Oj.load(@data)).compact.find { |obj| SUPPORTED_TYPES.include?(obj['@type']) } || {} end end diff --git a/spec/lib/link_details_extractor_spec.rb b/spec/lib/link_details_extractor_spec.rb index 2a4df70a8b..b1e5cedced 100644 --- a/spec/lib/link_details_extractor_spec.rb +++ b/spec/lib/link_details_extractor_spec.rb @@ -129,6 +129,24 @@ RSpec.describe LinkDetailsExtractor do include_examples 'structured data' end + context 'with the first tag is null' do + let(:html) { <<~HTML } + + + + + + + + HTML + + include_examples 'structured data' + end + context 'with preceding block of unsupported LD+JSON' do let(:html) { <<~HTML } From 5f5373397fd6d1bfde907c078174de6ca14d925e Mon Sep 17 00:00:00 2001 From: Matt Jankowski Date: Thu, 25 Jul 2024 10:59:56 -0400 Subject: [PATCH 125/126] Remove duplicate `omniauth_only?` helper method (#31066) --- app/controllers/application_controller.rb | 5 ----- 1 file changed, 5 deletions(-) diff --git a/app/controllers/application_controller.rb b/app/controllers/application_controller.rb index 66e0f7e305..62e3355ae6 100644 --- a/app/controllers/application_controller.rb +++ b/app/controllers/application_controller.rb @@ -20,7 +20,6 @@ class ApplicationController < ActionController::Base helper_method :current_theme helper_method :single_user_mode? helper_method :use_seamless_external_login? - helper_method :omniauth_only? helper_method :sso_account_settings helper_method :limited_federation_mode? helper_method :body_class_string @@ -137,10 +136,6 @@ class ApplicationController < ActionController::Base Devise.pam_authentication || Devise.ldap_authentication end - def omniauth_only? - ENV['OMNIAUTH_ONLY'] == 'true' - end - def sso_account_settings ENV.fetch('SSO_ACCOUNT_SETTINGS', nil) end From 887e64efd4abbf3980e008c7a5441b44fbd6c766 Mon Sep 17 00:00:00 2001 From: Adam Niedzielski Date: Thu, 25 Jul 2024 17:02:58 +0200 Subject: [PATCH 126/126] Allow @ at the end of an URL (#31124) --- config/initializers/twitter_regex.rb | 2 +- spec/lib/text_formatter_spec.rb | 8 ++++++++ 2 files changed, 9 insertions(+), 1 deletion(-) diff --git a/config/initializers/twitter_regex.rb b/config/initializers/twitter_regex.rb index 9ca4eb0da9..b932e97e2f 100644 --- a/config/initializers/twitter_regex.rb +++ b/config/initializers/twitter_regex.rb @@ -9,7 +9,7 @@ module Twitter::TwitterText class Regex REGEXEN[:valid_general_url_path_chars] = /[^\p{White_Space}<>()?]/iou - REGEXEN[:valid_url_path_ending_chars] = /[^\p{White_Space}()?!*"'「」<>;:=,.$%\[\]~&|@]|(?:#{REGEXEN[:valid_url_balanced_parens]})/iou + REGEXEN[:valid_url_path_ending_chars] = /[^\p{White_Space}()?!*"'「」<>;:=,.$%\[\]~&|]|(?:#{REGEXEN[:valid_url_balanced_parens]})/iou REGEXEN[:valid_url_balanced_parens] = / \( (?: diff --git a/spec/lib/text_formatter_spec.rb b/spec/lib/text_formatter_spec.rb index 8b922c018b..bde17bb79c 100644 --- a/spec/lib/text_formatter_spec.rb +++ b/spec/lib/text_formatter_spec.rb @@ -224,6 +224,14 @@ RSpec.describe TextFormatter do end end + context 'when given a URL with trailing @ symbol' do + let(:text) { 'https://gta.fandom.com/wiki/TW@ Content' } + + it 'matches the full URL' do + expect(subject).to include 'href="https://gta.fandom.com/wiki/TW@"' + end + end + context 'when given a URL containing unsafe code (XSS attack, visible part)' do let(:text) { 'http://example.com/bb' }