diff --git a/Gemfile b/Gemfile index bdabf54ea6..a80f2b73f7 100644 --- a/Gemfile +++ b/Gemfile @@ -40,6 +40,7 @@ end gem 'net-ldap', '~> 0.17' gem 'omniauth-cas', '~> 2.0' gem 'omniauth-saml', '~> 1.10' +gem 'gitlab-omniauth-openid-connect', '~>0.5.0', require: 'omniauth_openid_connect' gem 'omniauth', '~> 1.9' gem 'omniauth-rails_csrf_protection', '~> 0.1' @@ -115,7 +116,7 @@ end group :test do gem 'capybara', '~> 3.36' gem 'climate_control', '~> 0.2' - gem 'faker', '~> 2.19' + gem 'faker', '~> 2.20' gem 'microformats', '~> 4.2' gem 'rails-controller-testing', '~> 1.0' gem 'rspec-sidekiq', '~> 3.1' diff --git a/Gemfile.lock b/Gemfile.lock index 26429aec45..7201a0c0e2 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -68,6 +68,7 @@ GEM zeitwerk (~> 2.3) addressable (2.8.0) public_suffix (>= 2.0.2, < 5.0) + aes_key_wrap (1.1.0) airbrussh (1.4.0) sshkit (>= 1.6.1, != 1.7.0) android_key_attestation (0.3.0) @@ -77,6 +78,7 @@ GEM ast (2.4.2) attr_encrypted (3.1.0) encryptor (~> 3.0.0) + attr_required (1.0.1) awrence (1.1.1) aws-eventstream (1.2.0) aws-partitions (1.558.0) @@ -126,7 +128,7 @@ GEM sshkit (>= 1.9.0) capistrano-bundler (2.0.1) capistrano (~> 3.1) - capistrano-rails (1.6.1) + capistrano-rails (1.6.2) capistrano (~> 3.1) capistrano-bundler (>= 1.1, < 3) capistrano-rbenv (2.2.0) @@ -210,8 +212,8 @@ GEM tzinfo excon (0.76.0) fabrication (2.27.0) - faker (2.19.0) - i18n (>= 1.6, < 2) + faker (2.20.0) + i18n (>= 1.8.11, < 2) faraday (1.9.3) faraday-em_http (~> 1.0) faraday-em_synchrony (~> 1.0) @@ -260,6 +262,10 @@ GEM fuubar (2.5.1) rspec-core (~> 3.0) ruby-progressbar (~> 1.4) + gitlab-omniauth-openid-connect (0.5.0) + addressable (~> 2.7) + omniauth (~> 1.9) + openid_connect (~> 1.2) globalid (1.0.0) activesupport (>= 5.0) hamlit (2.13.0) @@ -288,10 +294,11 @@ GEM domain_name (~> 0.5) http-form_data (2.3.0) http_accept_language (2.1.1) + httpclient (2.8.3) httplog (1.5.0) rack (>= 1.0) rainbow (>= 2.0.0) - i18n (1.9.1) + i18n (1.10.0) concurrent-ruby (~> 1.0) i18n-tasks (0.9.37) activesupport (>= 4.0.2) @@ -308,6 +315,10 @@ GEM jmespath (1.6.0) json (2.5.1) json-canonicalization (0.3.0) + json-jwt (1.13.0) + activesupport (>= 4.2) + aes_key_wrap + bindata json-ld (3.2.0) htmlentities (~> 4.3) json-canonicalization (~> 0.3) @@ -408,6 +419,16 @@ GEM omniauth-saml (1.10.3) omniauth (~> 1.3, >= 1.3.2) ruby-saml (~> 1.9) + openid_connect (1.2.0) + activemodel + attr_required (>= 1.0.0) + json-jwt (>= 1.5.0) + rack-oauth2 (>= 1.6.1) + swd (>= 1.0.0) + tzinfo + validate_email + validate_url + webfinger (>= 1.0.1) openssl (2.2.0) openssl-signature_algorithm (0.4.0) orm_adapter (0.5.0) @@ -451,6 +472,12 @@ GEM rack (>= 1.0, < 3) rack-cors (1.1.1) rack (>= 2.0.0) + rack-oauth2 (1.16.0) + activesupport + attr_required + httpclient + json-jwt (>= 1.11.0) + rack (>= 2.1.0) rack-proxy (0.7.0) rack rack-test (1.1.0) @@ -498,7 +525,7 @@ GEM rdf (~> 3.2) redcarpet (3.5.1) redis (4.5.1) - redis-namespace (1.8.1) + redis-namespace (1.8.2) redis (>= 3.0.4) regexp_parser (2.2.0) request_store (1.5.0) @@ -606,11 +633,15 @@ GEM sshkit (1.21.2) net-scp (>= 1.1.2) net-ssh (>= 2.8.0) - stackprof (0.2.17) + stackprof (0.2.19) statsd-ruby (1.5.0) stoplight (2.2.1) strong_migrations (0.7.9) activerecord (>= 5) + swd (1.2.0) + activesupport (>= 3) + attr_required (>= 0.0.5) + httpclient (>= 2.4) temple (0.8.2) terminal-table (3.0.2) unicode-display_width (>= 1.1.1, < 3) @@ -645,6 +676,12 @@ GEM unf_ext (0.0.8) unicode-display_width (2.1.0) uniform_notifier (1.14.2) + validate_email (0.1.6) + activemodel (>= 3.0) + mail (>= 2.2.5) + validate_url (1.0.13) + activemodel (>= 3.0.0) + public_suffix warden (1.2.9) rack (>= 2.0.9) webauthn (3.0.0.alpha1) @@ -657,6 +694,9 @@ GEM safety_net_attestation (~> 0.4.0) securecompare (~> 1.0) tpm-key_attestation (~> 0.9.0) + webfinger (1.1.0) + activesupport + httpclient (>= 2.4) webmock (3.14.0) addressable (>= 2.8.0) crack (>= 0.3.2) @@ -714,12 +754,13 @@ DEPENDENCIES dotenv-rails (~> 2.7) ed25519 (~> 1.3) fabrication (~> 2.27) - faker (~> 2.19) + faker (~> 2.20) fast_blank (~> 1.0) fastimage fog-core (<= 2.1.0) fog-openstack (~> 0.3) fuubar (~> 2.5) + gitlab-omniauth-openid-connect (~> 0.5.0) hamlit-rails (~> 0.2) hcaptcha (~> 7.1) hiredis (~> 0.6) diff --git a/app/chewy/statuses_index.rb b/app/chewy/statuses_index.rb index 1903c2ea30..65cbb6fcd0 100644 --- a/app/chewy/statuses_index.rb +++ b/app/chewy/statuses_index.rb @@ -57,7 +57,7 @@ class StatusesIndex < Chewy::Index field :id, type: 'long' field :account_id, type: 'long' - field :text, type: 'text', value: ->(status) { [status.spoiler_text, Formatter.instance.plaintext(status)].concat(status.media_attachments.map(&:description)).concat(status.preloadable_poll ? status.preloadable_poll.options : []).join("\n\n") } do + field :text, type: 'text', value: ->(status) { [status.spoiler_text, Formatter.instance.plaintext(status)].concat(status.ordered_media_attachments.map(&:description)).concat(status.preloadable_poll ? status.preloadable_poll.options : []).join("\n\n") } do field :stemmed, type: 'text', analyzer: 'content' end diff --git a/app/controllers/admin/domain_blocks_controller.rb b/app/controllers/admin/domain_blocks_controller.rb index b140c454c1..16defc1ea8 100644 --- a/app/controllers/admin/domain_blocks_controller.rb +++ b/app/controllers/admin/domain_blocks_controller.rb @@ -56,10 +56,6 @@ module Admin end end - def show - authorize @domain_block, :show? - end - def destroy authorize @domain_block, :destroy? UnblockDomainService.new.call(@domain_block) diff --git a/app/controllers/admin/instances_controller.rb b/app/controllers/admin/instances_controller.rb index 306ec1f532..5c82331dea 100644 --- a/app/controllers/admin/instances_controller.rb +++ b/app/controllers/admin/instances_controller.rb @@ -4,28 +4,26 @@ module Admin class InstancesController < BaseController before_action :set_instances, only: :index before_action :set_instance, except: :index - before_action :set_exhausted_deliveries_days, only: :show def index authorize :instance, :index? + preload_delivery_failures! end def show authorize :instance, :show? + @time_period = (6.days.ago.to_date...Time.now.utc.to_date) end def destroy authorize :instance, :destroy? - Admin::DomainPurgeWorker.perform_async(@instance.domain) - log_action :destroy, @instance redirect_to admin_instances_path, notice: I18n.t('admin.instances.destroyed_msg', domain: @instance.domain) end def clear_delivery_errors authorize :delivery, :clear_delivery_errors? - @instance.delivery_failure_tracker.clear_failures! redirect_to admin_instance_path(@instance.domain) end @@ -33,11 +31,9 @@ module Admin def restart_delivery authorize :delivery, :restart_delivery? - last_unavailable_domain = unavailable_domain - - if last_unavailable_domain.present? + if @instance.unavailable? @instance.delivery_failure_tracker.track_success! - log_action :destroy, last_unavailable_domain + log_action :destroy, @instance.unavailable_domain end redirect_to admin_instance_path(@instance.domain) @@ -45,8 +41,7 @@ module Admin def stop_delivery authorize :delivery, :stop_delivery? - - UnavailableDomain.create(domain: @instance.domain) + unavailable_domain = UnavailableDomain.create!(domain: @instance.domain) log_action :create, unavailable_domain redirect_to admin_instance_path(@instance.domain) end @@ -57,12 +52,11 @@ module Admin @instance = Instance.find(params[:id]) end - def set_exhausted_deliveries_days - @exhausted_deliveries_days = @instance.delivery_failure_tracker.exhausted_deliveries_days - end - def set_instances @instances = filtered_instances.page(params[:page]) + end + + def preload_delivery_failures! warning_domains_map = DeliveryFailureTracker.warning_domains_map @instances.each do |instance| @@ -70,10 +64,6 @@ module Admin end end - def unavailable_domain - UnavailableDomain.find_by(domain: @instance.domain) - end - def filtered_instances InstanceFilter.new(whitelist_mode? ? { allowed: true } : filter_params).results end diff --git a/app/controllers/api/v1/statuses_controller.rb b/app/controllers/api/v1/statuses_controller.rb index ddd7c33ae4..7de446ac42 100644 --- a/app/controllers/api/v1/statuses_controller.rb +++ b/app/controllers/api/v1/statuses_controller.rb @@ -10,6 +10,7 @@ class Api::V1::StatusesController < Api::BaseController before_action :set_thread, only: [:create] override_rate_limit_headers :create, family: :statuses + override_rate_limit_headers :update, family: :statuses # This API was originally unlimited, pagination cannot be introduced without # breaking backwards-compatibility. Arbitrarily high number to cover most diff --git a/app/controllers/auth/omniauth_callbacks_controller.rb b/app/controllers/auth/omniauth_callbacks_controller.rb index 991a50b034..f9cf6d6551 100644 --- a/app/controllers/auth/omniauth_callbacks_controller.rb +++ b/app/controllers/auth/omniauth_callbacks_controller.rb @@ -4,8 +4,6 @@ class Auth::OmniauthCallbacksController < Devise::OmniauthCallbacksController skip_before_action :verify_authenticity_token def self.provides_callback_for(provider) - provider_id = provider.to_s.chomp '_oauth2' - define_method provider do @user = User.find_for_oauth(request.env['omniauth.auth'], current_user) @@ -20,7 +18,7 @@ class Auth::OmniauthCallbacksController < Devise::OmniauthCallbacksController ) sign_in_and_redirect @user, event: :authentication - set_flash_message(:notice, :success, kind: provider_id.capitalize) if is_navigational_format? + set_flash_message(:notice, :success, kind: Devise.omniauth_configs[provider].strategy.display_name.capitalize) if is_navigational_format? else session["devise.#{provider}_data"] = request.env['omniauth.auth'] redirect_to new_user_registration_url @@ -33,7 +31,7 @@ class Auth::OmniauthCallbacksController < Devise::OmniauthCallbacksController end def after_sign_in_path_for(resource) - if resource.email_verified? + if resource.email_present? root_path else auth_setup_path(missing_email: '1') diff --git a/app/helpers/languages_helper.rb b/app/helpers/languages_helper.rb index f22cc6d284..9be35ad8ee 100644 --- a/app/helpers/languages_helper.rb +++ b/app/helpers/languages_helper.rb @@ -241,6 +241,15 @@ module LanguagesHelper code end + def valid_locale_cascade(*arr) + arr.each do |str| + locale = valid_locale_or_nil(str) + return locale if locale.present? + end + + nil + end + def valid_locale?(locale) locale.present? && SUPPORTED_LOCALES.key?(locale.to_sym) end diff --git a/app/helpers/statuses_helper.rb b/app/helpers/statuses_helper.rb index 25f079e9df..d328f89b7a 100644 --- a/app/helpers/statuses_helper.rb +++ b/app/helpers/statuses_helper.rb @@ -132,7 +132,7 @@ module StatusesHelper end def render_video_component(status, **options) - video = status.media_attachments.first + video = status.ordered_media_attachments.first meta = video.file.meta || {} @@ -150,12 +150,12 @@ module StatusesHelper }.merge(**options) react_component :video, component_params do - render partial: 'statuses/attachment_list', locals: { attachments: status.media_attachments } + render partial: 'statuses/attachment_list', locals: { attachments: status.ordered_media_attachments } end end def render_audio_component(status, **options) - audio = status.media_attachments.first + audio = status.ordered_media_attachments.first meta = audio.file.meta || {} @@ -170,7 +170,7 @@ module StatusesHelper }.merge(**options) react_component :audio, component_params do - render partial: 'statuses/attachment_list', locals: { attachments: status.media_attachments } + render partial: 'statuses/attachment_list', locals: { attachments: status.ordered_media_attachments } end end @@ -178,11 +178,11 @@ module StatusesHelper component_params = { sensitive: sensitized?(status, current_account), autoplay: prefers_autoplay?, - media: status.media_attachments.map { |a| ActiveModelSerializers::SerializableResource.new(a, serializer: REST::MediaAttachmentSerializer).as_json }, + media: status.ordered_media_attachments.map { |a| ActiveModelSerializers::SerializableResource.new(a, serializer: REST::MediaAttachmentSerializer).as_json }, }.merge(**options) react_component :media_gallery, component_params do - render partial: 'statuses/attachment_list', locals: { attachments: status.media_attachments } + render partial: 'statuses/attachment_list', locals: { attachments: status.ordered_media_attachments } end end diff --git a/app/javascript/flavours/glitch/components/admin/Counter.js b/app/javascript/flavours/glitch/components/admin/Counter.js index 2bc9ce482c..ecb2429509 100644 --- a/app/javascript/flavours/glitch/components/admin/Counter.js +++ b/app/javascript/flavours/glitch/components/admin/Counter.js @@ -68,12 +68,12 @@ export default class Counter extends React.PureComponent { ); } else { const measure = data[0]; - const percentChange = percIncrease(measure.previous_total * 1, measure.total * 1); + const percentChange = measure.previous_total && percIncrease(measure.previous_total * 1, measure.total * 1); content = ( - - 0, negative: percentChange < 0 })}>{percentChange > 0 && '+'} + {measure.human_value || } + {measure.previous_total && ( 0, negative: percentChange < 0 })}>{percentChange > 0 && '+'})} ); } diff --git a/app/javascript/flavours/glitch/components/media_attachments.js b/app/javascript/flavours/glitch/components/media_attachments.js new file mode 100644 index 0000000000..c8d133f09d --- /dev/null +++ b/app/javascript/flavours/glitch/components/media_attachments.js @@ -0,0 +1,119 @@ +import React from 'react'; +import PropTypes from 'prop-types'; +import ImmutablePropTypes from 'react-immutable-proptypes'; +import ImmutablePureComponent from 'react-immutable-pure-component'; +import { MediaGallery, Video, Audio } from 'flavours/glitch/util/async-components'; +import Bundle from 'flavours/glitch/features/ui/components/bundle'; +import noop from 'lodash/noop'; + +export default class MediaAttachments extends ImmutablePureComponent { + + static propTypes = { + status: ImmutablePropTypes.map.isRequired, + height: PropTypes.number, + width: PropTypes.number, + revealed: PropTypes.bool, + }; + + static defaultProps = { + height: 110, + width: 239, + }; + + updateOnProps = [ + 'status', + ]; + + renderLoadingMediaGallery = () => { + const { height, width } = this.props; + + return ( +
+ ); + } + + renderLoadingVideoPlayer = () => { + const { height, width } = this.props; + + return ( +
+ ); + } + + renderLoadingAudioPlayer = () => { + const { height, width } = this.props; + + return ( +
+ ); + } + + render () { + const { status, width, height, revealed } = this.props; + const mediaAttachments = status.get('media_attachments'); + + if (mediaAttachments.size === 0) { + return null; + } + + if (mediaAttachments.getIn([0, 'type']) === 'audio') { + const audio = mediaAttachments.get(0); + + return ( + + {Component => ( + + )} + + ); + } else if (mediaAttachments.getIn([0, 'type']) === 'video') { + const video = mediaAttachments.get(0); + + return ( + + {Component => ( + + )} + + ); + } else { + return ( + + {Component => ( + + )} + + ); + } + } + +} diff --git a/app/javascript/flavours/glitch/features/hashtag_timeline/components/column_settings.js b/app/javascript/flavours/glitch/features/hashtag_timeline/components/column_settings.js index 142118cefc..ede8907e50 100644 --- a/app/javascript/flavours/glitch/features/hashtag_timeline/components/column_settings.js +++ b/app/javascript/flavours/glitch/features/hashtag_timeline/components/column_settings.js @@ -40,7 +40,17 @@ class ColumnSettings extends React.PureComponent { } }; - onSelect = mode => value => this.props.onChange(['tags', mode], value); + onSelect = mode => value => { + const oldValue = this.tags(mode); + + // Prevent changes that add more than 4 tags, but allow removing + // tags that were already added before + if ((value.length > 4) && !(value < oldValue)) { + return; + } + + this.props.onChange(['tags', mode], value); + }; onToggle = () => { if (this.state.open && this.hasTags()) { diff --git a/app/javascript/flavours/glitch/features/report/components/status_check_box.js b/app/javascript/flavours/glitch/features/report/components/status_check_box.js index adb5e77a7d..76bf0eb851 100644 --- a/app/javascript/flavours/glitch/features/report/components/status_check_box.js +++ b/app/javascript/flavours/glitch/features/report/components/status_check_box.js @@ -1,14 +1,12 @@ import React from 'react'; import PropTypes from 'prop-types'; import ImmutablePropTypes from 'react-immutable-proptypes'; -import noop from 'lodash/noop'; import StatusContent from 'flavours/glitch/components/status_content'; -import { MediaGallery, Video } from 'flavours/glitch/util/async-components'; -import Bundle from 'flavours/glitch/features/ui/components/bundle'; import Avatar from 'flavours/glitch/components/avatar'; import DisplayName from 'flavours/glitch/components/display_name'; import RelativeTimestamp from 'flavours/glitch/components/relative_timestamp'; import Option from './option'; +import MediaAttachments from 'flavours/glitch/components/media_attachments'; export default class StatusCheckBox extends React.PureComponent { @@ -27,53 +25,10 @@ export default class StatusCheckBox extends React.PureComponent { render () { const { status, checked } = this.props; - let media = null; - if (status.get('reblog')) { return null; } - if (status.get('media_attachments').size > 0) { - if (status.get('media_attachments').some(item => item.get('type') === 'unknown')) { - - } else if (status.getIn(['media_attachments', 0, 'type']) === 'video') { - const video = status.getIn(['media_attachments', 0]); - - media = ( - - {Component => ( - - )} - - ); - } else { - media = ( - - {Component => ( - - )} - - ); - } - } - const labelComponent = (
@@ -84,7 +39,7 @@ export default class StatusCheckBox extends React.PureComponent {
·
- + } />
); diff --git a/app/javascript/flavours/glitch/features/ui/components/compare_history_modal.js b/app/javascript/flavours/glitch/features/ui/components/compare_history_modal.js index 1984432213..8fd528da0c 100644 --- a/app/javascript/flavours/glitch/features/ui/components/compare_history_modal.js +++ b/app/javascript/flavours/glitch/features/ui/components/compare_history_modal.js @@ -9,6 +9,7 @@ import escapeTextContentForBrowser from 'escape-html'; import InlineAccount from 'flavours/glitch/components/inline_account'; import IconButton from 'flavours/glitch/components/icon_button'; import RelativeTimestamp from 'flavours/glitch/components/relative_timestamp'; +import MediaAttachments from 'flavours/glitch/components/media_attachments'; const mapStateToProps = (state, { statusId }) => ({ versions: state.getIn(['history', statusId, 'items']), @@ -70,6 +71,25 @@ class CompareHistoryModal extends React.PureComponent { )}
+ + {!!currentVersion.get('poll') && ( +
+
    + {currentVersion.getIn(['poll', 'options']).map(option => ( +
  • + + + +
  • + ))} +
+
+ )} + +
diff --git a/app/javascript/flavours/glitch/styles/admin.scss b/app/javascript/flavours/glitch/styles/admin.scss index 0873ac3001..40cd899b35 100644 --- a/app/javascript/flavours/glitch/styles/admin.scss +++ b/app/javascript/flavours/glitch/styles/admin.scss @@ -367,6 +367,21 @@ body, } } + .positive-hint, + .negative-hint, + .neutral-hint { + a { + color: inherit; + text-decoration: underline; + + &:focus, + &:hover, + &:active { + text-decoration: none; + } + } + } + .positive-hint { color: $valid-value-color; font-weight: 500; @@ -1612,3 +1627,38 @@ a.sparkline { } } } + +.availability-indicator { + display: flex; + align-items: center; + margin-bottom: 30px; + font-size: 14px; + line-height: 21px; + + &__hint { + padding: 0 15px; + } + + &__graphic { + display: flex; + margin: 0 -2px; + + &__item { + display: block; + flex: 0 0 auto; + width: 4px; + height: 21px; + background: lighten($ui-base-color, 8%); + margin: 0 2px; + border-radius: 2px; + + &.positive { + background: $valid-value-color; + } + + &.negative { + background: $error-value-color; + } + } + } +} diff --git a/app/javascript/flavours/glitch/styles/components/index.scss b/app/javascript/flavours/glitch/styles/components/index.scss index 7364eba91a..016e31c633 100644 --- a/app/javascript/flavours/glitch/styles/components/index.scss +++ b/app/javascript/flavours/glitch/styles/components/index.scss @@ -1563,41 +1563,6 @@ button.icon-button.active i.fa-retweet { filter: none; } -.compare-history-modal { - .report-modal__target { - border-bottom: 1px solid $ui-secondary-color; - } - - &__container { - padding: 30px; - pointer-events: all; - } - - .status__content { - color: $inverted-text-color; - font-size: 19px; - line-height: 24px; - - .emojione { - width: 24px; - height: 24px; - margin: -1px 0 0; - } - - a { - color: $highlight-text-color; - } - - hr { - height: 0.25rem; - padding: 0; - background-color: $ui-secondary-color; - border: 0; - margin: 20px 0; - } - } -} - .loading-bar { background-color: $ui-highlight-color; height: 3px; diff --git a/app/javascript/flavours/glitch/styles/components/modal.scss b/app/javascript/flavours/glitch/styles/components/modal.scss index ae1afc3205..7e69183563 100644 --- a/app/javascript/flavours/glitch/styles/components/modal.scss +++ b/app/javascript/flavours/glitch/styles/components/modal.scss @@ -1041,6 +1041,47 @@ } } +.compare-history-modal { + .report-modal__target { + border-bottom: 1px solid $ui-secondary-color; + } + + &__container { + padding: 30px; + pointer-events: all; + } + + .status__content { + color: $inverted-text-color; + font-size: 19px; + line-height: 24px; + + .emojione { + width: 24px; + height: 24px; + margin: -1px 0 0; + } + + a { + color: $highlight-text-color; + } + + hr { + height: 0.25rem; + padding: 0; + background-color: $ui-secondary-color; + border: 0; + margin: 20px 0; + } + } + + .media-gallery, + .audio-player, + .video-player { + margin-top: 15px; + } +} + .embed-modal { width: auto; max-width: 80vw; diff --git a/app/javascript/flavours/glitch/styles/components/status.scss b/app/javascript/flavours/glitch/styles/components/status.scss index a49299af10..ad6c24ea63 100644 --- a/app/javascript/flavours/glitch/styles/components/status.scss +++ b/app/javascript/flavours/glitch/styles/components/status.scss @@ -538,7 +538,7 @@ .media-gallery, .audio-player, .video-player { - margin-top: 8px; + margin-top: 15px; max-width: 250px; } diff --git a/app/javascript/flavours/glitch/styles/mastodon-light/diff.scss b/app/javascript/flavours/glitch/styles/mastodon-light/diff.scss index 8f5309f2bc..87b83b5637 100644 --- a/app/javascript/flavours/glitch/styles/mastodon-light/diff.scss +++ b/app/javascript/flavours/glitch/styles/mastodon-light/diff.scss @@ -229,15 +229,21 @@ .mute-modal, .block-modal, .report-modal, +.report-dialog-modal, .embed-modal, .error-modal, .onboarding-modal, .report-modal__comment .setting-text__wrapper, -.report-modal__comment .setting-text { +.report-modal__comment .setting-text, +.report-dialog-modal__textarea { background: $white; border: 1px solid lighten($ui-base-color, 8%); } +.report-dialog-modal .dialog-option .poll__input { + color: $white; +} + .report-modal__comment { border-right-color: lighten($ui-base-color, 8%); } diff --git a/app/javascript/flavours/glitch/styles/tables.scss b/app/javascript/flavours/glitch/styles/tables.scss index 8b5933b7b5..598c67034e 100644 --- a/app/javascript/flavours/glitch/styles/tables.scss +++ b/app/javascript/flavours/glitch/styles/tables.scss @@ -65,6 +65,24 @@ } } + &.horizontal-table { + border-collapse: collapse; + border-style: hidden; + + & > tbody > tr > th, + & > tbody > tr > td { + padding: 11px 10px; + background: transparent; + border: 1px solid lighten($ui-base-color, 8%); + color: $secondary-text-color; + } + + & > tbody > tr > th { + color: $darker-text-color; + font-weight: 600; + } + } + &.batch-table { & > thead > tr > th { background: $ui-base-color; diff --git a/app/javascript/mastodon/components/admin/Counter.js b/app/javascript/mastodon/components/admin/Counter.js index 047e864b25..6edb7bcfca 100644 --- a/app/javascript/mastodon/components/admin/Counter.js +++ b/app/javascript/mastodon/components/admin/Counter.js @@ -68,12 +68,12 @@ export default class Counter extends React.PureComponent { ); } else { const measure = data[0]; - const percentChange = percIncrease(measure.previous_total * 1, measure.total * 1); + const percentChange = measure.previous_total && percIncrease(measure.previous_total * 1, measure.total * 1); content = ( - - 0, negative: percentChange < 0 })}>{percentChange > 0 && '+'} + {measure.human_value || } + {measure.previous_total && ( 0, negative: percentChange < 0 })}>{percentChange > 0 && '+'})} ); } diff --git a/app/javascript/mastodon/components/media_attachments.js b/app/javascript/mastodon/components/media_attachments.js new file mode 100644 index 0000000000..d27720de41 --- /dev/null +++ b/app/javascript/mastodon/components/media_attachments.js @@ -0,0 +1,116 @@ +import React from 'react'; +import PropTypes from 'prop-types'; +import ImmutablePropTypes from 'react-immutable-proptypes'; +import ImmutablePureComponent from 'react-immutable-pure-component'; +import { MediaGallery, Video, Audio } from 'mastodon/features/ui/util/async-components'; +import Bundle from 'mastodon/features/ui/components/bundle'; +import noop from 'lodash/noop'; + +export default class MediaAttachments extends ImmutablePureComponent { + + static propTypes = { + status: ImmutablePropTypes.map.isRequired, + height: PropTypes.number, + width: PropTypes.number, + }; + + static defaultProps = { + height: 110, + width: 239, + }; + + updateOnProps = [ + 'status', + ]; + + renderLoadingMediaGallery = () => { + const { height, width } = this.props; + + return ( +
+ ); + } + + renderLoadingVideoPlayer = () => { + const { height, width } = this.props; + + return ( +
+ ); + } + + renderLoadingAudioPlayer = () => { + const { height, width } = this.props; + + return ( +
+ ); + } + + render () { + const { status, width, height } = this.props; + const mediaAttachments = status.get('media_attachments'); + + if (mediaAttachments.size === 0) { + return null; + } + + if (mediaAttachments.getIn([0, 'type']) === 'audio') { + const audio = mediaAttachments.get(0); + + return ( + + {Component => ( + + )} + + ); + } else if (mediaAttachments.getIn([0, 'type']) === 'video') { + const video = mediaAttachments.get(0); + + return ( + + {Component => ( + + )} + + ); + } else { + return ( + + {Component => ( + + )} + + ); + } + } + +} diff --git a/app/javascript/mastodon/features/hashtag_timeline/components/column_settings.js b/app/javascript/mastodon/features/hashtag_timeline/components/column_settings.js index 142118cefc..ede8907e50 100644 --- a/app/javascript/mastodon/features/hashtag_timeline/components/column_settings.js +++ b/app/javascript/mastodon/features/hashtag_timeline/components/column_settings.js @@ -40,7 +40,17 @@ class ColumnSettings extends React.PureComponent { } }; - onSelect = mode => value => this.props.onChange(['tags', mode], value); + onSelect = mode => value => { + const oldValue = this.tags(mode); + + // Prevent changes that add more than 4 tags, but allow removing + // tags that were already added before + if ((value.length > 4) && !(value < oldValue)) { + return; + } + + this.props.onChange(['tags', mode], value); + }; onToggle = () => { if (this.state.open && this.hasTags()) { diff --git a/app/javascript/mastodon/features/report/components/status_check_box.js b/app/javascript/mastodon/features/report/components/status_check_box.js index a2eb3d6f57..373c60e21e 100644 --- a/app/javascript/mastodon/features/report/components/status_check_box.js +++ b/app/javascript/mastodon/features/report/components/status_check_box.js @@ -1,14 +1,12 @@ import React from 'react'; import PropTypes from 'prop-types'; import ImmutablePropTypes from 'react-immutable-proptypes'; -import noop from 'lodash/noop'; import StatusContent from 'mastodon/components/status_content'; -import { MediaGallery, Video } from 'mastodon/features/ui/util/async-components'; -import Bundle from 'mastodon/features/ui/components/bundle'; import Avatar from 'mastodon/components/avatar'; import DisplayName from 'mastodon/components/display_name'; import RelativeTimestamp from 'mastodon/components/relative_timestamp'; import Option from './option'; +import MediaAttachments from 'mastodon/components/media_attachments'; export default class StatusCheckBox extends React.PureComponent { @@ -27,51 +25,10 @@ export default class StatusCheckBox extends React.PureComponent { render () { const { status, checked } = this.props; - let media = null; - if (status.get('reblog')) { return null; } - if (status.get('media_attachments').size > 0) { - if (status.get('media_attachments').some(item => item.get('type') === 'unknown')) { - - } else if (status.getIn(['media_attachments', 0, 'type']) === 'video') { - const video = status.getIn(['media_attachments', 0]); - - media = ( - - {Component => ( - - )} - - ); - } else { - media = ( - - {Component => ( - - )} - - ); - } - } - const labelComponent = (
@@ -79,12 +36,13 @@ export default class StatusCheckBox extends React.PureComponent {
-
·
+
+ · +
- - {media} +
); diff --git a/app/javascript/mastodon/features/ui/components/compare_history_modal.js b/app/javascript/mastodon/features/ui/components/compare_history_modal.js index 40cfba3357..ecccc8f7df 100644 --- a/app/javascript/mastodon/features/ui/components/compare_history_modal.js +++ b/app/javascript/mastodon/features/ui/components/compare_history_modal.js @@ -9,6 +9,7 @@ import escapeTextContentForBrowser from 'escape-html'; import InlineAccount from 'mastodon/components/inline_account'; import IconButton from 'mastodon/components/icon_button'; import RelativeTimestamp from 'mastodon/components/relative_timestamp'; +import MediaAttachments from 'mastodon/components/media_attachments'; const mapStateToProps = (state, { statusId }) => ({ versions: state.getIn(['history', statusId, 'items']), @@ -70,6 +71,25 @@ class CompareHistoryModal extends React.PureComponent { )}
+ + {!!currentVersion.get('poll') && ( +
+
    + {currentVersion.getIn(['poll', 'options']).map(option => ( +
  • + + + +
  • + ))} +
+
+ )} + +
diff --git a/app/javascript/mastodon/locales/af.json b/app/javascript/mastodon/locales/af.json index a7e5313a3a..d31ed3fe90 100644 --- a/app/javascript/mastodon/locales/af.json +++ b/app/javascript/mastodon/locales/af.json @@ -18,12 +18,12 @@ "account.followers": "Followers", "account.followers.empty": "No one follows this user yet.", "account.followers_counter": "{count, plural, one {{counter} Follower} other {{counter} Followers}}", + "account.following": "Following", "account.following_counter": "{count, plural, one {{counter} Following} other {{counter} Following}}", "account.follows.empty": "This user doesn't follow anyone yet.", "account.follows_you": "Follows you", "account.hide_reblogs": "Hide boosts from @{name}", "account.joined": "Joined {date}", - "account.last_status": "Last active", "account.link_verified_on": "Ownership of this link was checked on {date}", "account.locked_info": "This account privacy status is set to locked. The owner manually reviews who can follow them.", "account.media": "Media", @@ -32,7 +32,6 @@ "account.mute": "Mute @{name}", "account.mute_notifications": "Mute notifications from @{name}", "account.muted": "Muted", - "account.never_active": "Never", "account.posts": "Toots", "account.posts_with_replies": "Toots and replies", "account.report": "Report @{name}", @@ -42,10 +41,12 @@ "account.statuses_counter": "{count, plural, one {{counter} Toot} other {{counter} Toots}}", "account.unblock": "Unblock @{name}", "account.unblock_domain": "Unblock domain {domain}", + "account.unblock_short": "Unblock", "account.unendorse": "Don't feature on profile", "account.unfollow": "Unfollow", "account.unmute": "Unmute @{name}", "account.unmute_notifications": "Unmute notifications from @{name}", + "account.unmute_short": "Unmute", "account_note.placeholder": "Click to add a note", "admin.dashboard.daily_retention": "User retention rate by day after sign-up", "admin.dashboard.monthly_retention": "User retention rate by month after sign-up", diff --git a/app/javascript/mastodon/locales/ar.json b/app/javascript/mastodon/locales/ar.json index 84708b1e2a..5fd1ab9e57 100644 --- a/app/javascript/mastodon/locales/ar.json +++ b/app/javascript/mastodon/locales/ar.json @@ -18,12 +18,12 @@ "account.followers": "المُتابِعون", "account.followers.empty": "لا أحدَ يُتابع هذا المُستخدم حتى الآن.", "account.followers_counter": "{count, plural, zero{لا مُتابع} one {مُتابعٌ واحِد} two{مُتابعانِ اِثنان} few{{counter} مُتابِعين} many{{counter} مُتابِعًا} other {{counter} مُتابع}}", + "account.following": "Following", "account.following_counter": "{count, plural, zero{لا يُتابِع} one {يُتابِعُ واحد} two{يُتابِعُ اِثنان} few{يُتابِعُ {counter}} many{يُتابِعُ {counter}} other {يُتابِعُ {counter}}}", "account.follows.empty": "لا يُتابع هذا المُستخدمُ أيَّ أحدٍ حتى الآن.", "account.follows_you": "يُتابِعُك", "account.hide_reblogs": "إخفاء مشاركات @{name}", "account.joined": "انضم في {date}", - "account.last_status": "آخر نشاط", "account.link_verified_on": "تمَّ التَّحقق مِن مِلْكيّة هذا الرابط بتاريخ {date}", "account.locked_info": "تمَّ تعيين حالة خصوصية هذا الحساب إلى مُقفَل. يُراجع المالك يدويًا من يمكنه متابعته.", "account.media": "وسائط", @@ -32,7 +32,6 @@ "account.mute": "كَتم @{name}", "account.mute_notifications": "كَتم الإشعارات من @{name}", "account.muted": "مَكتوم", - "account.never_active": "أبدًا", "account.posts": "منشورات", "account.posts_with_replies": "المنشورات والرُدود", "account.report": "الإبلاغ عن @{name}", @@ -42,10 +41,12 @@ "account.statuses_counter": "{count, plural, zero {لَا تَبويقات} one {تَبويقةٌ واحدة} two {تَبويقَتانِ اِثنتان} few {{counter} تَبويقات} many {{counter} تَبويقتًا} other {{counter} تَبويقة}}", "account.unblock": "إلغاء الحَظر عن @{name}", "account.unblock_domain": "إلغاء الحَظر عن النِّطاق {domain}", + "account.unblock_short": "Unblock", "account.unendorse": "لا تُرَوِّج لهُ في الملف الشخصي", "account.unfollow": "إلغاء المُتابعة", "account.unmute": "إلغاء الكَتم عن @{name}", "account.unmute_notifications": "إلغاء كَتم الإشعارات عن @{name}", + "account.unmute_short": "Unmute", "account_note.placeholder": "اضغط لإضافة مُلاحظة", "admin.dashboard.daily_retention": "User retention rate by day after sign-up", "admin.dashboard.monthly_retention": "User retention rate by month after sign-up", diff --git a/app/javascript/mastodon/locales/ast.json b/app/javascript/mastodon/locales/ast.json index 0627f57e1c..4ca5f01234 100644 --- a/app/javascript/mastodon/locales/ast.json +++ b/app/javascript/mastodon/locales/ast.json @@ -18,12 +18,12 @@ "account.followers": "Siguidores", "account.followers.empty": "Naide sigue a esti usuariu entá.", "account.followers_counter": "{count, plural, one {{counter} Follower} other {{counter} Followers}}", + "account.following": "Following", "account.following_counter": "{count, plural, one {{counter} Following} other {{counter} Following}}", "account.follows.empty": "Esti usuariu entá nun sigue a naide.", "account.follows_you": "Síguete", "account.hide_reblogs": "Anubrir les comparticiones de @{name}", "account.joined": "Joined {date}", - "account.last_status": "Cabera actividá", "account.link_verified_on": "La propiedá d'esti enllaz foi comprobada'l {date}", "account.locked_info": "This account privacy status is set to locked. The owner manually reviews who can follow them.", "account.media": "Media", @@ -32,7 +32,6 @@ "account.mute": "Silenciar a @{name}", "account.mute_notifications": "Mute notifications from @{name}", "account.muted": "Muted", - "account.never_active": "Enxamás", "account.posts": "Barritos", "account.posts_with_replies": "Barritos y rempuestes", "account.report": "Report @{name}", @@ -42,10 +41,12 @@ "account.statuses_counter": "{count, plural, one {{counter} Toot} other {{counter} Toots}}", "account.unblock": "Desbloquiar a @{name}", "account.unblock_domain": "Amosar {domain}", + "account.unblock_short": "Unblock", "account.unendorse": "Nun destacar nel perfil", "account.unfollow": "Dexar de siguir", "account.unmute": "Unmute @{name}", "account.unmute_notifications": "Unmute notifications from @{name}", + "account.unmute_short": "Unmute", "account_note.placeholder": "Click to add a note", "admin.dashboard.daily_retention": "User retention rate by day after sign-up", "admin.dashboard.monthly_retention": "User retention rate by month after sign-up", diff --git a/app/javascript/mastodon/locales/bg.json b/app/javascript/mastodon/locales/bg.json index f037444d65..2e7038aa9e 100644 --- a/app/javascript/mastodon/locales/bg.json +++ b/app/javascript/mastodon/locales/bg.json @@ -18,12 +18,12 @@ "account.followers": "Последователи", "account.followers.empty": "Все още никой не следва този потребител.", "account.followers_counter": "{count, plural, one {{counter} Последовател} other {{counter} Последователи}}", + "account.following": "Following", "account.following_counter": "{count, plural, one {{counter} Последван} other {{counter} Последвани}}", "account.follows.empty": "Този потребител все още не следва никого.", "account.follows_you": "Твой последовател", "account.hide_reblogs": "Скриване на споделяния от @{name}", "account.joined": "Joined {date}", - "account.last_status": "Последно активен/а", "account.link_verified_on": "Собствеността върху тази връзка е проверена на {date}", "account.locked_info": "Този акаунт е поверително заключен. Собственикът преглежда ръчно кой може да го следва.", "account.media": "Мултимедия", @@ -32,7 +32,6 @@ "account.mute": "Заглушаване на @{name}", "account.mute_notifications": "Заглушаване на известия от @{name}", "account.muted": "Заглушено", - "account.never_active": "Никога", "account.posts": "Публикации", "account.posts_with_replies": "Toots with replies", "account.report": "Докладване на @{name}", @@ -42,10 +41,12 @@ "account.statuses_counter": "{count, plural, one {{counter} Публикация} other {{counter} Публикации}}", "account.unblock": "Не блокирай", "account.unblock_domain": "Unhide {domain}", + "account.unblock_short": "Unblock", "account.unendorse": "Не включвайте в профила", "account.unfollow": "Не следвай", "account.unmute": "Раззаглушаване на @{name}", "account.unmute_notifications": "Раззаглушаване на известия от @{name}", + "account.unmute_short": "Unmute", "account_note.placeholder": "Click to add a note", "admin.dashboard.daily_retention": "User retention rate by day after sign-up", "admin.dashboard.monthly_retention": "User retention rate by month after sign-up", diff --git a/app/javascript/mastodon/locales/bn.json b/app/javascript/mastodon/locales/bn.json index 3387289a4c..38d70853e4 100644 --- a/app/javascript/mastodon/locales/bn.json +++ b/app/javascript/mastodon/locales/bn.json @@ -18,12 +18,12 @@ "account.followers": "অনুসরণকারী", "account.followers.empty": "এই ব্যক্তিকে এখনো কেউ অনুসরণ করে না।", "account.followers_counter": "{count, plural,one {{counter} জন অনুসরণকারী } other {{counter} জন অনুসরণকারী}}", + "account.following": "Following", "account.following_counter": "{count, plural,one {{counter} জনকে অনুসরণ} other {{counter} জনকে অনুসরণ}}", "account.follows.empty": "এই সদস্য কাওকে এখনো অনুসরণ করেন না.", "account.follows_you": "তোমাকে অনুসরণ করে", "account.hide_reblogs": "@{name}'র সমর্থনগুলি লুকিয়ে ফেলুন", "account.joined": "Joined {date}", - "account.last_status": "শেষ সক্রিয় ছিল", "account.link_verified_on": "এই লিংকের মালিকানা চেক করা হয়েছে {date} তারিখে", "account.locked_info": "এই নিবন্ধনের গোপনীয়তার ক্ষেত্র তালা দেওয়া আছে। নিবন্ধনকারী অনুসরণ করার অনুমতি যাদেরকে দেবেন, শুধু তারাই অনুসরণ করতে পারবেন।", "account.media": "মিডিয়া", @@ -32,7 +32,6 @@ "account.mute": "@{name} কে নিঃশব্দ করুন", "account.mute_notifications": "@{name} র প্রজ্ঞাপন আপনার কাছে নিঃশব্দ করুন", "account.muted": "নিঃশব্দ", - "account.never_active": "কখনও নয়", "account.posts": "টুট", "account.posts_with_replies": "টুট এবং মতামত", "account.report": "@{name} কে রিপোর্ট করুন", @@ -42,10 +41,12 @@ "account.statuses_counter": "{count, plural,one {{counter} টুট} other {{counter} টুট}}", "account.unblock": "@{name} র কার্যকলাপ দেখুন", "account.unblock_domain": "{domain} কে আবার দেখুন", + "account.unblock_short": "Unblock", "account.unendorse": "আপনার নিজের পাতায় এটা দেখবেন না", "account.unfollow": "অনুসরণ করো না", "account.unmute": "@{name} র কার্যকলাপ আবার দেখুন", "account.unmute_notifications": "@{name} র প্রজ্ঞাপন দেখুন", + "account.unmute_short": "Unmute", "account_note.placeholder": "নোট যোগ করতে ক্লিক করুন", "admin.dashboard.daily_retention": "User retention rate by day after sign-up", "admin.dashboard.monthly_retention": "User retention rate by month after sign-up", diff --git a/app/javascript/mastodon/locales/br.json b/app/javascript/mastodon/locales/br.json index 9a78feaab9..a07b21c78b 100644 --- a/app/javascript/mastodon/locales/br.json +++ b/app/javascript/mastodon/locales/br.json @@ -18,12 +18,12 @@ "account.followers": "Heulier·ezed·ien", "account.followers.empty": "Den na heul an implijer-mañ c'hoazh.", "account.followers_counter": "{count, plural, other{{counter} Heulier}}", + "account.following": "Following", "account.following_counter": "{count, plural, other {{counter} Heuliañ}}", "account.follows.empty": "An implijer·ez-mañ na heul den ebet.", "account.follows_you": "Ho heul", "account.hide_reblogs": "Kuzh toudoù rannet gant @{name}", "account.joined": "Amañ abaoe {date}", - "account.last_status": "Oberiantiz zivezhañ", "account.link_verified_on": "Gwiriet eo bet perc'hennidigezh al liamm d'an deiziad-mañ : {date}", "account.locked_info": "Prennet eo ar gont-mañ. Dibab a ra ar perc'henn ar re a c'hall heuliañ anezhi pe anezhañ.", "account.media": "Media", @@ -32,7 +32,6 @@ "account.mute": "Kuzhat @{name}", "account.mute_notifications": "Kuzh kemennoù eus @{name}", "account.muted": "Kuzhet", - "account.never_active": "Birviken", "account.posts": "a doudoù", "account.posts_with_replies": "Toudoù ha respontoù", "account.report": "Disklêriañ @{name}", @@ -42,10 +41,12 @@ "account.statuses_counter": "{count, plural, one {{counter} Toud} other {{counter} Toud}}", "account.unblock": "Diverzañ @{name}", "account.unblock_domain": "Diverzañ an domani {domain}", + "account.unblock_short": "Unblock", "account.unendorse": "Paouez da lakaat war-wel war ar profil", "account.unfollow": "Diheuliañ", "account.unmute": "Diguzhat @{name}", "account.unmute_notifications": "Diguzhat kemennoù a @{name}", + "account.unmute_short": "Unmute", "account_note.placeholder": "Klikit evit ouzhpenniñ un notenn", "admin.dashboard.daily_retention": "User retention rate by day after sign-up", "admin.dashboard.monthly_retention": "User retention rate by month after sign-up", diff --git a/app/javascript/mastodon/locales/ca.json b/app/javascript/mastodon/locales/ca.json index 915278f957..0182170fdb 100644 --- a/app/javascript/mastodon/locales/ca.json +++ b/app/javascript/mastodon/locales/ca.json @@ -18,12 +18,12 @@ "account.followers": "Seguidors", "account.followers.empty": "Encara ningú no segueix aquest usuari.", "account.followers_counter": "{count, plural, one {{counter} Seguidor} other {{counter} Seguidors}}", + "account.following": "Following", "account.following_counter": "{count, plural, other {{counter} Seguint}}", "account.follows.empty": "Aquest usuari encara no segueix a ningú.", "account.follows_you": "Et segueix", "account.hide_reblogs": "Amaga els impulsos de @{name}", "account.joined": "Unit des de {date}", - "account.last_status": "Darrer actiu", "account.link_verified_on": "La propietat d'aquest enllaç es va verificar el dia {date}", "account.locked_info": "Aquest estat de privadesa del compte està definit com a bloquejat. El propietari revisa manualment qui pot seguir-lo.", "account.media": "Mèdia", @@ -32,7 +32,6 @@ "account.mute": "Silencia @{name}", "account.mute_notifications": "Notificacions desactivades de @{name}", "account.muted": "Silenciat", - "account.never_active": "Mai", "account.posts": "Tuts", "account.posts_with_replies": "Tuts i respostes", "account.report": "Informar sobre @{name}", @@ -42,10 +41,12 @@ "account.statuses_counter": "{count, plural, one {{counter} Tut} other {{counter} Tuts}}", "account.unblock": "Desbloqueja @{name}", "account.unblock_domain": "Mostra {domain}", + "account.unblock_short": "Unblock", "account.unendorse": "No recomanar en el perfil", "account.unfollow": "Deixa de seguir", "account.unmute": "Treure silenci de @{name}", "account.unmute_notifications": "Activar notificacions de @{name}", + "account.unmute_short": "Unmute", "account_note.placeholder": "Fes clic per afegir una nota", "admin.dashboard.daily_retention": "Ràtio de retenció per dia després del registre", "admin.dashboard.monthly_retention": "Ràtio de retenció per mes després del registre", diff --git a/app/javascript/mastodon/locales/co.json b/app/javascript/mastodon/locales/co.json index 799fc877d8..4d75dbb08f 100644 --- a/app/javascript/mastodon/locales/co.json +++ b/app/javascript/mastodon/locales/co.json @@ -18,12 +18,12 @@ "account.followers": "Abbunati", "account.followers.empty": "Nisunu hè abbunatu à st'utilizatore.", "account.followers_counter": "{count, plural, one {{counter} Abbunatu} other {{counter} Abbunati}}", + "account.following": "Following", "account.following_counter": "{count, plural, one {{counter} Abbunamentu} other {{counter} Abbunamenti}}", "account.follows.empty": "St'utilizatore ùn seguita nisunu.", "account.follows_you": "Vi seguita", "account.hide_reblogs": "Piattà spartere da @{name}", "account.joined": "Quì dapoi {date}", - "account.last_status": "Ultima attività", "account.link_verified_on": "A prupietà di stu ligame hè stata verificata u {date}", "account.locked_info": "U statutu di vita privata di u contu hè chjosu. U pruprietariu esamina manualmente e dumande d'abbunamentu.", "account.media": "Media", @@ -32,7 +32,6 @@ "account.mute": "Piattà @{name}", "account.mute_notifications": "Piattà nutificazione da @{name}", "account.muted": "Piattatu", - "account.never_active": "Mai", "account.posts": "Statuti", "account.posts_with_replies": "Statuti è risposte", "account.report": "Palisà @{name}", @@ -42,10 +41,12 @@ "account.statuses_counter": "{count, plural, one {{counter} Statutu} other {{counter} Statuti}}", "account.unblock": "Sbluccà @{name}", "account.unblock_domain": "Ùn piattà più {domain}", + "account.unblock_short": "Unblock", "account.unendorse": "Ùn fà figurà nant'à u prufilu", "account.unfollow": "Ùn siguità più", "account.unmute": "Ùn piattà più @{name}", "account.unmute_notifications": "Ùn piattà più nutificazione da @{name}", + "account.unmute_short": "Unmute", "account_note.placeholder": "Senza cummentariu", "admin.dashboard.daily_retention": "User retention rate by day after sign-up", "admin.dashboard.monthly_retention": "User retention rate by month after sign-up", diff --git a/app/javascript/mastodon/locales/cs.json b/app/javascript/mastodon/locales/cs.json index 65043cc0e4..97f4674bac 100644 --- a/app/javascript/mastodon/locales/cs.json +++ b/app/javascript/mastodon/locales/cs.json @@ -18,12 +18,12 @@ "account.followers": "Sledující", "account.followers.empty": "Tohoto uživatele ještě nikdo nesleduje.", "account.followers_counter": "{count, plural, one {{counter} Sledující} few {{counter} Sledující} many {{counter} Sledujících} other {{counter} Sledujících}}", + "account.following": "Following", "account.following_counter": "{count, plural, one {{counter} Sledovaný} few {{counter} Sledovaní} many {{counter} Sledovaných} other {{counter} Sledovaných}}", "account.follows.empty": "Tento uživatel ještě nikoho nesleduje.", "account.follows_you": "Sleduje vás", "account.hide_reblogs": "Skrýt boosty od @{name}", "account.joined": "Založen {date}", - "account.last_status": "Naposledy aktivní", "account.link_verified_on": "Vlastnictví tohoto odkazu bylo zkontrolováno {date}", "account.locked_info": "Stav soukromí tohoto účtu je nastaven na zamčeno. Jeho vlastník ručně posuzuje, kdo ho může sledovat.", "account.media": "Média", @@ -32,7 +32,6 @@ "account.mute": "Skrýt @{name}", "account.mute_notifications": "Skrýt oznámení od @{name}", "account.muted": "Skryt", - "account.never_active": "Nikdy", "account.posts": "Příspěvky", "account.posts_with_replies": "Příspěvky a odpovědi", "account.report": "Nahlásit @{name}", @@ -42,10 +41,12 @@ "account.statuses_counter": "{count, plural, one {{counter} Příspěvek} few {{counter} Příspěvky} many {{counter} Příspěvků} other {{counter} Příspěvků}}", "account.unblock": "Odblokovat @{name}", "account.unblock_domain": "Odblokovat doménu {domain}", + "account.unblock_short": "Unblock", "account.unendorse": "Nezvýrazňovat na profilu", "account.unfollow": "Přestat sledovat", "account.unmute": "Zrušit skrytí @{name}", "account.unmute_notifications": "Zrušit skrytí oznámení od @{name}", + "account.unmute_short": "Unmute", "account_note.placeholder": "Klikněte pro přidání poznámky", "admin.dashboard.daily_retention": "User retention rate by day after sign-up", "admin.dashboard.monthly_retention": "User retention rate by month after sign-up", diff --git a/app/javascript/mastodon/locales/cy.json b/app/javascript/mastodon/locales/cy.json index ad73168656..79ef2dfc61 100644 --- a/app/javascript/mastodon/locales/cy.json +++ b/app/javascript/mastodon/locales/cy.json @@ -18,12 +18,12 @@ "account.followers": "Dilynwyr", "account.followers.empty": "Nid oes neb yn dilyn y defnyddiwr hwn eto.", "account.followers_counter": "{count, plural, one {{counter} Ddilynwr} other {{counter} o Ddilynwyr}}", + "account.following": "Following", "account.following_counter": "{count, plural, one {{counter} yn Dilyn} other {{counter} yn Dilyn}}", "account.follows.empty": "Nid yw'r defnyddiwr hwn yn dilyn unrhyw un eto.", "account.follows_you": "Yn eich dilyn chi", "account.hide_reblogs": "Cuddio bwstiau o @{name}", "account.joined": "Joined {date}", - "account.last_status": "Gweithredol olaf", "account.link_verified_on": "Gwiriwyd perchnogaeth y ddolen yma ar {date}", "account.locked_info": "Mae'r statws preifatrwydd cyfrif hwn wedi'i osod i gloi. Mae'r perchennog yn adolygu'r sawl sy'n gallu eu dilyn.", "account.media": "Cyfryngau", @@ -32,7 +32,6 @@ "account.mute": "Tawelu @{name}", "account.mute_notifications": "Cuddio hysbysiadau o @{name}", "account.muted": "Distewyd", - "account.never_active": "Byth", "account.posts": "Tŵtiau", "account.posts_with_replies": "Tŵtiau ac atebion", "account.report": "Adrodd @{name}", @@ -42,10 +41,12 @@ "account.statuses_counter": "{count, plural, one {{counter} Dŵt} other {{counter} o Dŵtiau}}", "account.unblock": "Dadflocio @{name}", "account.unblock_domain": "Dadguddio {domain}", + "account.unblock_short": "Unblock", "account.unendorse": "Peidio a'i arddangos ar fy mhroffil", "account.unfollow": "Dad-ddilyn", "account.unmute": "Dad-dawelu @{name}", "account.unmute_notifications": "Dad-dawelu hysbysiadau o @{name}", + "account.unmute_short": "Unmute", "account_note.placeholder": "Clicio i ychwanegu nodyn", "admin.dashboard.daily_retention": "User retention rate by day after sign-up", "admin.dashboard.monthly_retention": "User retention rate by month after sign-up", diff --git a/app/javascript/mastodon/locales/da.json b/app/javascript/mastodon/locales/da.json index 3c7a658a32..5861bac507 100644 --- a/app/javascript/mastodon/locales/da.json +++ b/app/javascript/mastodon/locales/da.json @@ -18,12 +18,12 @@ "account.followers": "Følgere", "account.followers.empty": "Ingen følger brugeren endnu.", "account.followers_counter": "{count, plural, one {{counter} Følger} other {{counter} Følgere}}", + "account.following": "Following", "account.following_counter": "{count, plural, one {{counter} Følges} other {{counter} Følges}}", "account.follows.empty": "Denne bruger følger ikke nogen endnu.", "account.follows_you": "Følger dig", "account.hide_reblogs": "Skjul fremhævelser fra @{name}", "account.joined": "Tilmeldt {date}", - "account.last_status": "Senest aktiv", "account.link_verified_on": "Ejerskab af dette link blev tjekket {date}", "account.locked_info": "Denne kontos fortrolighedsstatus er sat til låst. Ejeren bedømmer manuelt, hvem der kan følge vedkommende.", "account.media": "Medier", @@ -32,7 +32,6 @@ "account.mute": "Skjul @{name}", "account.mute_notifications": "Skjul notifikationer fra @{name}", "account.muted": "Tystnet", - "account.never_active": "Aldrig", "account.posts": "Indlæg", "account.posts_with_replies": "Indlæg og svar", "account.report": "Anmeld @{name}", @@ -42,10 +41,12 @@ "account.statuses_counter": "{count, plural, one {{counter} Indlæg} other {{counter} Indlæg}}", "account.unblock": "Fjern blokeringen af @{name}", "account.unblock_domain": "Afblokér domænet {domain}", + "account.unblock_short": "Unblock", "account.unendorse": "Fjern visning på din profil", "account.unfollow": "Følg ikke længere", "account.unmute": "Fjern tavsgjort for @{name}", "account.unmute_notifications": "Slå notifikationer om @{name} til igen", + "account.unmute_short": "Unmute", "account_note.placeholder": "Klik for at tilføje notat", "admin.dashboard.daily_retention": "Brugerfastholdelsesrate efter dag efter tilmelding", "admin.dashboard.monthly_retention": "User retention rate by month after sign-up", diff --git a/app/javascript/mastodon/locales/de.json b/app/javascript/mastodon/locales/de.json index 46bd3e07e7..5344a444e4 100644 --- a/app/javascript/mastodon/locales/de.json +++ b/app/javascript/mastodon/locales/de.json @@ -18,12 +18,12 @@ "account.followers": "Follower", "account.followers.empty": "Diesem Profil folgt noch niemand.", "account.followers_counter": "{count, plural, one {{counter} Follower} other {{counter} Follower}}", + "account.following": "Following", "account.following_counter": "{count, plural, one {{counter} Folgender} other {{counter} Folgende}}", "account.follows.empty": "Dieses Profil folgt noch niemandem.", "account.follows_you": "Folgt dir", "account.hide_reblogs": "Geteilte Beiträge von @{name} verbergen", "account.joined": "Beigetreten am {date}", - "account.last_status": "Zuletzt aktiv", "account.link_verified_on": "Besitz dieses Links wurde geprüft am {date}", "account.locked_info": "Der Privatsphärenstatus dieses Accounts wurde auf gesperrt gesetzt. Die Person bestimmt manuell wer ihm/ihr folgen darf.", "account.media": "Medien", @@ -32,7 +32,6 @@ "account.mute": "@{name} stummschalten", "account.mute_notifications": "Benachrichtigungen von @{name} stummschalten", "account.muted": "Stummgeschaltet", - "account.never_active": "Nie", "account.posts": "Beiträge", "account.posts_with_replies": "Beiträge und Antworten", "account.report": "@{name} melden", @@ -42,10 +41,12 @@ "account.statuses_counter": "{count, plural, one {{counter} Beitrag} other {{counter} Beiträge}}", "account.unblock": "@{name} entblocken", "account.unblock_domain": "{domain} wieder anzeigen", + "account.unblock_short": "Unblock", "account.unendorse": "Nicht auf Profil hervorheben", "account.unfollow": "Entfolgen", "account.unmute": "@{name} nicht mehr stummschalten", "account.unmute_notifications": "Benachrichtigungen von @{name} einschalten", + "account.unmute_short": "Unmute", "account_note.placeholder": "Notiz durch Klicken hinzufügen", "admin.dashboard.daily_retention": "Benutzerverbleibrate nach Tag nach Anmeldung", "admin.dashboard.monthly_retention": "Benutzerverbleibrate nach Monat nach Anmeldung", diff --git a/app/javascript/mastodon/locales/defaultMessages.json b/app/javascript/mastodon/locales/defaultMessages.json index cb999a9ef9..370765f9f3 100644 --- a/app/javascript/mastodon/locales/defaultMessages.json +++ b/app/javascript/mastodon/locales/defaultMessages.json @@ -1624,30 +1624,38 @@ }, { "descriptors": [ - { - "defaultMessage": "Follow", - "id": "account.follow" - }, { "defaultMessage": "Unfollow", "id": "account.unfollow" }, { - "defaultMessage": "Awaiting approval", + "defaultMessage": "Follow", + "id": "account.follow" + }, + { + "defaultMessage": "Cancel follow request", + "id": "account.cancel_follow_request" + }, + { + "defaultMessage": "Awaiting approval. Click to cancel follow request", "id": "account.requested" }, { - "defaultMessage": "Unblock @{name}", - "id": "account.unblock" + "defaultMessage": "Unblock", + "id": "account.unblock_short" }, { - "defaultMessage": "Unmute @{name}", - "id": "account.unmute" + "defaultMessage": "Unmute", + "id": "account.unmute_short" }, { "defaultMessage": "Unfollow", "id": "confirmations.unfollow.confirm" }, + { + "defaultMessage": "Edit profile", + "id": "account.edit_profile" + }, { "defaultMessage": "Are you sure you want to unfollow {name}?", "id": "confirmations.unfollow.message" @@ -1661,12 +1669,8 @@ "id": "account.followers" }, { - "defaultMessage": "Never", - "id": "account.never_active" - }, - { - "defaultMessage": "Last active", - "id": "account.last_status" + "defaultMessage": "Following", + "id": "account.following" } ], "path": "app/javascript/mastodon/features/directory/components/account_card.json" @@ -2007,10 +2011,6 @@ { "defaultMessage": "Getting started", "id": "getting_started.heading" - }, - { - "defaultMessage": "Profile directory", - "id": "getting_started.directory" } ], "path": "app/javascript/mastodon/features/getting_started/index.json" @@ -2742,7 +2742,7 @@ "id": "report.reasons.spam" }, { - "defaultMessage": "Malicious links, fake engagement, or repetetive replies", + "defaultMessage": "Malicious links, fake engagement, or repetitive replies", "id": "report.reasons.spam_description" }, { @@ -3402,6 +3402,10 @@ "defaultMessage": "About this server", "id": "navigation_bar.info" }, + { + "defaultMessage": "Profile directory", + "id": "getting_started.directory" + }, { "defaultMessage": "Mobile apps", "id": "navigation_bar.apps" @@ -3529,10 +3533,6 @@ "defaultMessage": "Lists", "id": "navigation_bar.lists" }, - { - "defaultMessage": "Profile directory", - "id": "getting_started.directory" - }, { "defaultMessage": "Preferences", "id": "navigation_bar.preferences" diff --git a/app/javascript/mastodon/locales/el.json b/app/javascript/mastodon/locales/el.json index 96fe6c6097..4e8765d13a 100644 --- a/app/javascript/mastodon/locales/el.json +++ b/app/javascript/mastodon/locales/el.json @@ -18,12 +18,12 @@ "account.followers": "Ακόλουθοι", "account.followers.empty": "Κανείς δεν ακολουθεί αυτό τον χρήστη ακόμα.", "account.followers_counter": "{count, plural, one {{counter} Ακόλουθος} other {{counter} Ακόλουθοι}}", + "account.following": "Following", "account.following_counter": "{count, plural, other {{counter} Ακολουθεί}}", "account.follows.empty": "Αυτός ο χρήστης δεν ακολουθεί κανέναν ακόμα.", "account.follows_you": "Σε ακολουθεί", "account.hide_reblogs": "Απόκρυψη προωθήσεων από @{name}", "account.joined": "Μέλος από τις {date}", - "account.last_status": "Τελευταία δραστηριότητα", "account.link_verified_on": "Η ιδιοκτησία αυτού του συνδέσμου ελέχθηκε την {date}", "account.locked_info": "Η κατάσταση απορρήτου αυτού του λογαριασμού είναι κλειδωμένη. Ο ιδιοκτήτης επιβεβαιώνει χειροκίνητα ποιος μπορεί να τον ακολουθήσει.", "account.media": "Πολυμέσα", @@ -32,7 +32,6 @@ "account.mute": "Σώπασε @{name}", "account.mute_notifications": "Σώπασε τις ειδοποιήσεις από @{name}", "account.muted": "Αποσιωπημένος/η", - "account.never_active": "Ποτέ", "account.posts": "Τουτ", "account.posts_with_replies": "Τουτ και απαντήσεις", "account.report": "Κατάγγειλε @{name}", @@ -42,10 +41,12 @@ "account.statuses_counter": "{count, plural, one {{counter} Τουτ} other {{counter} Τουτ}}", "account.unblock": "Ξεμπλόκαρε @{name}", "account.unblock_domain": "Αποκάλυψε το {domain}", + "account.unblock_short": "Unblock", "account.unendorse": "Άνευ προβολής στο προφίλ", "account.unfollow": "Διακοπή παρακολούθησης", "account.unmute": "Διακοπή αποσιώπησης @{name}", "account.unmute_notifications": "Διακοπή αποσιώπησης ειδοποιήσεων του/της @{name}", + "account.unmute_short": "Unmute", "account_note.placeholder": "Κλικ για να βάλεις σημείωση", "admin.dashboard.daily_retention": "User retention rate by day after sign-up", "admin.dashboard.monthly_retention": "User retention rate by month after sign-up", diff --git a/app/javascript/mastodon/locales/en.json b/app/javascript/mastodon/locales/en.json index 06c2b679c4..2afc1b75f9 100644 --- a/app/javascript/mastodon/locales/en.json +++ b/app/javascript/mastodon/locales/en.json @@ -18,12 +18,12 @@ "account.followers": "Followers", "account.followers.empty": "No one follows this user yet.", "account.followers_counter": "{count, plural, one {{counter} Follower} other {{counter} Followers}}", + "account.following": "Following", "account.following_counter": "{count, plural, one {{counter} Following} other {{counter} Following}}", "account.follows.empty": "This user doesn't follow anyone yet.", "account.follows_you": "Follows you", "account.hide_reblogs": "Hide boosts from @{name}", "account.joined": "Joined {date}", - "account.last_status": "Last active", "account.link_verified_on": "Ownership of this link was checked on {date}", "account.locked_info": "This account privacy status is set to locked. The owner manually reviews who can follow them.", "account.media": "Media", @@ -32,7 +32,6 @@ "account.mute": "Mute @{name}", "account.mute_notifications": "Mute notifications from @{name}", "account.muted": "Muted", - "account.never_active": "Never", "account.posts": "Posts", "account.posts_with_replies": "Posts and replies", "account.report": "Report @{name}", @@ -42,10 +41,12 @@ "account.statuses_counter": "{count, plural, one {{counter} Post} other {{counter} Posts}}", "account.unblock": "Unblock @{name}", "account.unblock_domain": "Unblock domain {domain}", + "account.unblock_short": "Unblock", "account.unendorse": "Don't feature on profile", "account.unfollow": "Unfollow", "account.unmute": "Unmute @{name}", "account.unmute_notifications": "Unmute notifications from @{name}", + "account.unmute_short": "Unmute", "account_note.placeholder": "Click to add note", "admin.dashboard.daily_retention": "User retention rate by day after sign-up", "admin.dashboard.monthly_retention": "User retention rate by month after sign-up", diff --git a/app/javascript/mastodon/locales/eo.json b/app/javascript/mastodon/locales/eo.json index 8ef35c03b0..0628392ae5 100644 --- a/app/javascript/mastodon/locales/eo.json +++ b/app/javascript/mastodon/locales/eo.json @@ -18,12 +18,12 @@ "account.followers": "Sekvantoj", "account.followers.empty": "Ankoraŭ neniu sekvas tiun uzanton.", "account.followers_counter": "{count, plural, one{{counter} Sekvanto} other {{counter} Sekvantoj}}", + "account.following": "Following", "account.following_counter": "{count, plural, one {{counter} Sekvato} other {{counter} Sekvatoj}}", "account.follows.empty": "Tiu uzanto ankoraŭ ne sekvas iun.", "account.follows_you": "Sekvas vin", "account.hide_reblogs": "Kaŝi diskonigojn de @{name}", "account.joined": "Kuniĝis {date}", - "account.last_status": "Laste aktiva", "account.link_verified_on": "La posedanto de tiu ligilo estis kontrolita je {date}", "account.locked_info": "La privateco de tiu konto estas elektita kiel fermita. La posedanto povas mane akcepti tiun, kiu povas sekvi rin.", "account.media": "Amaskomunikiloj", @@ -32,7 +32,6 @@ "account.mute": "Silentigi @{name}", "account.mute_notifications": "Silentigi sciigojn de @{name}", "account.muted": "Silentigita", - "account.never_active": "Neniam", "account.posts": "Mesaĝoj", "account.posts_with_replies": "Kun respondoj", "account.report": "Signali @{name}", @@ -42,10 +41,12 @@ "account.statuses_counter": "{count, plural, one {{counter} Mesaĝo} other {{counter} Mesaĝoj}}", "account.unblock": "Malbloki @{name}", "account.unblock_domain": "Malbloki {domain}", + "account.unblock_short": "Unblock", "account.unendorse": "Ne montri en profilo", "account.unfollow": "Ne plu sekvi", "account.unmute": "Malsilentigi @{name}", "account.unmute_notifications": "Malsilentigi sciigojn de @{name}", + "account.unmute_short": "Unmute", "account_note.placeholder": "Alklaku por aldoni noton", "admin.dashboard.daily_retention": "User retention rate by day after sign-up", "admin.dashboard.monthly_retention": "User retention rate by month after sign-up", diff --git a/app/javascript/mastodon/locales/es-AR.json b/app/javascript/mastodon/locales/es-AR.json index cfda3360f7..811f814be4 100644 --- a/app/javascript/mastodon/locales/es-AR.json +++ b/app/javascript/mastodon/locales/es-AR.json @@ -18,12 +18,12 @@ "account.followers": "Seguidores", "account.followers.empty": "Todavía nadie sigue a este usuario.", "account.followers_counter": "{count, plural, one {{counter} Seguidor} other {{counter} Seguidores}}", + "account.following": "Following", "account.following_counter": "{count, plural, other {{counter} Siguiendo}}", "account.follows.empty": "Todavía este usuario no sigue a nadie.", "account.follows_you": "Te sigue", "account.hide_reblogs": "Ocultar adhesiones de @{name}", "account.joined": "En este servidor desde {date}", - "account.last_status": "Última actividad", "account.link_verified_on": "La propiedad de este enlace fue verificada el {date}", "account.locked_info": "Esta cuenta es privada. El propietario manualmente revisa quién puede seguirle.", "account.media": "Medios", @@ -32,7 +32,6 @@ "account.mute": "Silenciar a @{name}", "account.mute_notifications": "Silenciar notificaciones de @{name}", "account.muted": "Silenciado", - "account.never_active": "Nunca", "account.posts": "Mensajes", "account.posts_with_replies": "Mensajes y respuestas públicas", "account.report": "Denunciar a @{name}", @@ -42,10 +41,12 @@ "account.statuses_counter": "{count, plural, one {{counter} Mensaje} other {{counter} Mensajes}}", "account.unblock": "Desbloquear a @{name}", "account.unblock_domain": "Desbloquear dominio {domain}", + "account.unblock_short": "Unblock", "account.unendorse": "No destacar en el perfil", "account.unfollow": "Dejar de seguir", "account.unmute": "Dejar de silenciar a @{name}", "account.unmute_notifications": "Dejar de silenciar las notificaciones de @{name}", + "account.unmute_short": "Unmute", "account_note.placeholder": "Hacé clic par agregar una nota", "admin.dashboard.daily_retention": "Tasa de retención de usuarios por día, después del registro", "admin.dashboard.monthly_retention": "Tasa de retención de usuarios por mes, después del registro", diff --git a/app/javascript/mastodon/locales/es-MX.json b/app/javascript/mastodon/locales/es-MX.json index e243bb8d8b..cb5d740fb0 100644 --- a/app/javascript/mastodon/locales/es-MX.json +++ b/app/javascript/mastodon/locales/es-MX.json @@ -18,12 +18,12 @@ "account.followers": "Seguidores", "account.followers.empty": "Todavía nadie sigue a este usuario.", "account.followers_counter": "{count, plural, one {{counter} Seguidor} other {{counter} Seguidores}}", + "account.following": "Following", "account.following_counter": "{count, plural, other {{counter} Siguiendo}}", "account.follows.empty": "Este usuario todavía no sigue a nadie.", "account.follows_you": "Te sigue", "account.hide_reblogs": "Ocultar retoots de @{name}", "account.joined": "Se unió el {date}", - "account.last_status": "Última actividad", "account.link_verified_on": "El proprietario de este link fue comprobado el {date}", "account.locked_info": "El estado de privacidad de esta cuenta està configurado como bloqueado. El proprietario debe revisar manualmente quien puede seguirle.", "account.media": "Multimedia", @@ -32,7 +32,6 @@ "account.mute": "Silenciar a @{name}", "account.mute_notifications": "Silenciar notificaciones de @{name}", "account.muted": "Silenciado", - "account.never_active": "Nunca", "account.posts": "Toots", "account.posts_with_replies": "Toots con respuestas", "account.report": "Reportar a @{name}", @@ -42,10 +41,12 @@ "account.statuses_counter": "{count, plural, one {{counter} Toot} other {{counter} Toots}}", "account.unblock": "Desbloquear a @{name}", "account.unblock_domain": "Mostrar a {domain}", + "account.unblock_short": "Unblock", "account.unendorse": "No mostrar en el perfil", "account.unfollow": "Dejar de seguir", "account.unmute": "Dejar de silenciar a @{name}", "account.unmute_notifications": "Dejar de silenciar las notificaciones de @{name}", + "account.unmute_short": "Unmute", "account_note.placeholder": "Clic para añadir nota", "admin.dashboard.daily_retention": "Tasa de retención de usuarios por día después del registro", "admin.dashboard.monthly_retention": "Tasa de retención de usuarios por mes después del registro", diff --git a/app/javascript/mastodon/locales/es.json b/app/javascript/mastodon/locales/es.json index 5725a0637f..d36798e7b9 100644 --- a/app/javascript/mastodon/locales/es.json +++ b/app/javascript/mastodon/locales/es.json @@ -18,12 +18,12 @@ "account.followers": "Seguidores", "account.followers.empty": "Todavía nadie sigue a este usuario.", "account.followers_counter": "{count, plural, one {{counter} Seguidor} other {{counter} Seguidores}}", + "account.following": "Following", "account.following_counter": "{count, plural, other {{counter} Siguiendo}}", "account.follows.empty": "Este usuario todavía no sigue a nadie.", "account.follows_you": "Te sigue", "account.hide_reblogs": "Ocultar retoots de @{name}", "account.joined": "Se unió el {date}", - "account.last_status": "Última actividad", "account.link_verified_on": "El proprietario de este link fue comprobado el {date}", "account.locked_info": "El estado de privacidad de esta cuenta està configurado como bloqueado. El proprietario debe revisar manualmente quien puede seguirle.", "account.media": "Multimedia", @@ -32,7 +32,6 @@ "account.mute": "Silenciar a @{name}", "account.mute_notifications": "Silenciar notificaciones de @{name}", "account.muted": "Silenciado", - "account.never_active": "Nunca", "account.posts": "Publicaciones", "account.posts_with_replies": "Publicaciones y respuestas", "account.report": "Reportar a @{name}", @@ -42,10 +41,12 @@ "account.statuses_counter": "{count, plural, one {{counter} Publicación} other {{counter} Publicaciones}}", "account.unblock": "Desbloquear a @{name}", "account.unblock_domain": "Mostrar a {domain}", + "account.unblock_short": "Unblock", "account.unendorse": "No mostrar en el perfil", "account.unfollow": "Dejar de seguir", "account.unmute": "Dejar de silenciar a @{name}", "account.unmute_notifications": "Dejar de silenciar las notificaciones de @{name}", + "account.unmute_short": "Unmute", "account_note.placeholder": "Clic para añadir nota", "admin.dashboard.daily_retention": "Tasa de retención de usuarios por día después del registro", "admin.dashboard.monthly_retention": "Tasa de retención de usuarios por mes después del registro", diff --git a/app/javascript/mastodon/locales/et.json b/app/javascript/mastodon/locales/et.json index 2eca42e09f..4b57f4b815 100644 --- a/app/javascript/mastodon/locales/et.json +++ b/app/javascript/mastodon/locales/et.json @@ -18,12 +18,12 @@ "account.followers": "Jälgijad", "account.followers.empty": "Keegi ei jälgi seda kasutajat veel.", "account.followers_counter": "{count, plural, one {{counter} Follower} other {{counter} Followers}}", + "account.following": "Following", "account.following_counter": "{count, plural, one {{counter} Following} other {{counter} Following}}", "account.follows.empty": "See kasutaja ei jälgi veel kedagi.", "account.follows_you": "Jälgib Teid", "account.hide_reblogs": "Peida upitused kasutajalt @{name}", "account.joined": "Joined {date}", - "account.last_status": "Viimati aktiivne", "account.link_verified_on": "Selle lingi autorsust kontrolliti {date}", "account.locked_info": "Selle konto privaatsussätteks on lukustatud. Omanik vaatab manuaalselt üle, kes teda jägida saab.", "account.media": "Meedia", @@ -32,7 +32,6 @@ "account.mute": "Vaigista @{name}", "account.mute_notifications": "Vaigista teated kasutajalt @{name}", "account.muted": "Vaigistatud", - "account.never_active": "Mitte kunagi", "account.posts": "Tuututused", "account.posts_with_replies": "Tuututused ja vastused", "account.report": "Raporteeri @{name}", @@ -42,10 +41,12 @@ "account.statuses_counter": "{count, plural, one {{counter} Toot} other {{counter} Toots}}", "account.unblock": "Eemalda blokeering @{name}", "account.unblock_domain": "Tee {domain} nähtavaks", + "account.unblock_short": "Unblock", "account.unendorse": "Ära kuva profiilil", "account.unfollow": "Ära jälgi", "account.unmute": "Ära vaigista @{name}", "account.unmute_notifications": "Ära vaigista teateid kasutajalt @{name}", + "account.unmute_short": "Unmute", "account_note.placeholder": "Click to add a note", "admin.dashboard.daily_retention": "User retention rate by day after sign-up", "admin.dashboard.monthly_retention": "User retention rate by month after sign-up", diff --git a/app/javascript/mastodon/locales/eu.json b/app/javascript/mastodon/locales/eu.json index 0d3eec7010..0b25e8e951 100644 --- a/app/javascript/mastodon/locales/eu.json +++ b/app/javascript/mastodon/locales/eu.json @@ -18,12 +18,12 @@ "account.followers": "Jarraitzaileak", "account.followers.empty": "Ez du inork erabiltzaile hau jarraitzen oraindik.", "account.followers_counter": "{count, plural, one {Jarraitzaile {counter}} other {{counter} jarraitzaile}}", + "account.following": "Following", "account.following_counter": "{count, plural, one {{counter} jarraitzen} other {{counter} jarraitzen}}", "account.follows.empty": "Erabiltzaile honek ez du inor jarraitzen oraindik.", "account.follows_you": "Jarraitzen dizu", "account.hide_reblogs": "Ezkutatu @{name}(r)en bultzadak", "account.joined": "{date}(e)an elkartua", - "account.last_status": "Azkenekoz aktiboa", "account.link_verified_on": "Esteka honen jabetzaren egiaztaketa data: {date}", "account.locked_info": "Kontu honen pribatutasun egoera blokeatuta gisa ezarri da. Jabeak eskuz erabakitzen du nork jarraitu diezaioken.", "account.media": "Multimedia", @@ -32,7 +32,6 @@ "account.mute": "Mututu @{name}", "account.mute_notifications": "Mututu @{name}(r)en jakinarazpenak", "account.muted": "Mutututa", - "account.never_active": "Inoiz ez", "account.posts": "Bidalketa", "account.posts_with_replies": "Bidalketak eta erantzunak", "account.report": "Salatu @{name}", @@ -42,10 +41,12 @@ "account.statuses_counter": "{count, plural, one {Bidalketa {counter}} other {{counter} bidalketa}}", "account.unblock": "Desblokeatu @{name}", "account.unblock_domain": "Berriz erakutsi {domain}", + "account.unblock_short": "Unblock", "account.unendorse": "Ez nabarmendu profilean", "account.unfollow": "Utzi jarraitzeari", "account.unmute": "Desmututu @{name}", "account.unmute_notifications": "Desmututu @{name}(r)en jakinarazpenak", + "account.unmute_short": "Unmute", "account_note.placeholder": "Click to add a note", "admin.dashboard.daily_retention": "Erabiltzaile atxikitze-tasa izena eman ondorengo eguneko", "admin.dashboard.monthly_retention": "Erabiltzaile atxikitze-tasa izena eman ondorengo hilabeteko", diff --git a/app/javascript/mastodon/locales/fa.json b/app/javascript/mastodon/locales/fa.json index 2024903d00..a81efacbbf 100644 --- a/app/javascript/mastodon/locales/fa.json +++ b/app/javascript/mastodon/locales/fa.json @@ -18,12 +18,12 @@ "account.followers": "پی‌گیرندگان", "account.followers.empty": "هنوز کسی این کاربر را پی‌گیری نمی‌کند.", "account.followers_counter": "{count, plural, one {{counter} پی‌گیرنده} other {{counter} پی‌گیرنده}}", + "account.following": "Following", "account.following_counter": "{count, plural, one {{counter} پی‌گرفته} other {{counter} پی‌گرفته}}", "account.follows.empty": "این کاربر هنوز پی‌گیر کسی نیست.", "account.follows_you": "پی می‌گیردتان", "account.hide_reblogs": "نهفتن تقویت‌های @{name}", "account.joined": "پیوسته از {date}", - "account.last_status": "آخرین فعّالیت", "account.link_verified_on": "مالکیت این پیوند در {date} بررسی شد", "account.locked_info": "این حساب خصوصی است. صاحبش تصمیم می‌گیرد که چه کسی پی‌گیرش باشد.", "account.media": "رسانه", @@ -32,7 +32,6 @@ "account.mute": "خموشاندن @{name}", "account.mute_notifications": "خموشاندن آگاهی‌ها از @{name}", "account.muted": "خموش", - "account.never_active": "هرگز", "account.posts": "فرسته", "account.posts_with_replies": "فرسته‌ها و پاسخ‌ها", "account.report": "گزارش @{name}", @@ -42,10 +41,12 @@ "account.statuses_counter": "{count, plural, one {{counter} فرسته} other {{counter} فرسته}}", "account.unblock": "رفع مسدودیت @{name}", "account.unblock_domain": "رفع مسدودیت دامنهٔ {domain}", + "account.unblock_short": "Unblock", "account.unendorse": "معرّفی نکردن در نمایه", "account.unfollow": "ناپی‌گیری", "account.unmute": "ناخموشی @{name}", "account.unmute_notifications": "ناخموشی آگاهی‌ها از @{name}", + "account.unmute_short": "Unmute", "account_note.placeholder": "برای افزودن یادداشت کلیک کنید", "admin.dashboard.daily_retention": "User retention rate by day after sign-up", "admin.dashboard.monthly_retention": "User retention rate by month after sign-up", diff --git a/app/javascript/mastodon/locales/fi.json b/app/javascript/mastodon/locales/fi.json index eaad6e358b..e6407b79e8 100644 --- a/app/javascript/mastodon/locales/fi.json +++ b/app/javascript/mastodon/locales/fi.json @@ -18,12 +18,12 @@ "account.followers": "Seuraajat", "account.followers.empty": "Kukaan ei seuraa tätä käyttäjää vielä.", "account.followers_counter": "{count, plural, one {{counter} seuraaja} other {{counter} seuraajat}}", + "account.following": "Following", "account.following_counter": "{count, plural, one {{counter} seuraa} other {{counter} seuraa}}", "account.follows.empty": "Tämä käyttäjä ei vielä seuraa ketään.", "account.follows_you": "Seuraa sinua", "account.hide_reblogs": "Piilota buustaukset käyttäjältä @{name}", "account.joined": "Liittynyt {date}", - "account.last_status": "Aktiivinen viimeksi", "account.link_verified_on": "Tämän linkin omistaja tarkistettiin {date}", "account.locked_info": "Tämän tilin yksityisyyden tila on asetettu lukituksi. Omistaja arvioi manuaalisesti, kuka voi seurata niitä.", "account.media": "Media", @@ -32,7 +32,6 @@ "account.mute": "Mykistä @{name}", "account.mute_notifications": "Mykistä ilmoitukset käyttäjältä @{name}", "account.muted": "Mykistetty", - "account.never_active": "Ei koskaan", "account.posts": "Viestit", "account.posts_with_replies": "Viestit ja vastaukset", "account.report": "Raportoi @{name}", @@ -42,10 +41,12 @@ "account.statuses_counter": "{count, plural, one {{counter} Toot} other {{counter} Toots}}", "account.unblock": "Salli @{name}", "account.unblock_domain": "Salli {domain}", + "account.unblock_short": "Unblock", "account.unendorse": "Poista suosittelu profiilistasi", "account.unfollow": "Lopeta seuraaminen", "account.unmute": "Poista käyttäjän @{name} mykistys", "account.unmute_notifications": "Poista mykistys käyttäjän @{name} ilmoituksilta", + "account.unmute_short": "Unmute", "account_note.placeholder": "Lisää muistiinpano napsauttamalla", "admin.dashboard.daily_retention": "Käyttäjän säilyminen rekisteröitymisen jälkeiseen päivään mennessä", "admin.dashboard.monthly_retention": "Käyttäjän säilyminen rekisteröitymisen jälkeiseen kuukauteen mennessä", diff --git a/app/javascript/mastodon/locales/fr.json b/app/javascript/mastodon/locales/fr.json index f85662775c..d5fdcebddc 100644 --- a/app/javascript/mastodon/locales/fr.json +++ b/app/javascript/mastodon/locales/fr.json @@ -18,12 +18,12 @@ "account.followers": "Abonnés", "account.followers.empty": "Personne ne suit cet·te utilisateur·rice pour l’instant.", "account.followers_counter": "{count, plural, one {{counter} Abonné·e} other {{counter} Abonné·e·s}}", + "account.following": "Following", "account.following_counter": "{count, plural, other {{counter} Abonnements}}", "account.follows.empty": "Cet·te utilisateur·rice ne suit personne pour l’instant.", "account.follows_you": "Vous suit", "account.hide_reblogs": "Masquer les partages de @{name}", "account.joined": "Ici depuis {date}", - "account.last_status": "Dernière activité", "account.link_verified_on": "La propriété de ce lien a été vérifiée le {date}", "account.locked_info": "Ce compte est privé. Son ou sa propriétaire approuve manuellement qui peut le suivre.", "account.media": "Médias", @@ -32,7 +32,6 @@ "account.mute": "Masquer @{name}", "account.mute_notifications": "Ignorer les notifications de @{name}", "account.muted": "Masqué·e", - "account.never_active": "Jamais", "account.posts": "Messages", "account.posts_with_replies": "Messages et réponses", "account.report": "Signaler @{name}", @@ -42,10 +41,12 @@ "account.statuses_counter": "{count, plural, one {{counter} Message} other {{counter} Messages}}", "account.unblock": "Débloquer @{name}", "account.unblock_domain": "Débloquer le domaine {domain}", + "account.unblock_short": "Unblock", "account.unendorse": "Ne plus recommander sur le profil", "account.unfollow": "Ne plus suivre", "account.unmute": "Ne plus masquer @{name}", "account.unmute_notifications": "Ne plus masquer les notifications de @{name}", + "account.unmute_short": "Unmute", "account_note.placeholder": "Cliquez pour ajouter une note", "admin.dashboard.daily_retention": "Taux de maintien des utilisateur·rice·s par jour après inscription", "admin.dashboard.monthly_retention": "Brugerfastholdelsesrate efter måned efter tilmelding", diff --git a/app/javascript/mastodon/locales/ga.json b/app/javascript/mastodon/locales/ga.json index 06a6bca5ba..aeb152e56c 100644 --- a/app/javascript/mastodon/locales/ga.json +++ b/app/javascript/mastodon/locales/ga.json @@ -18,12 +18,12 @@ "account.followers": "Followers", "account.followers.empty": "No one follows this user yet.", "account.followers_counter": "{count, plural, one {{counter} Follower} other {{counter} Followers}}", + "account.following": "Following", "account.following_counter": "{count, plural, one {{counter} Following} other {{counter} Following}}", "account.follows.empty": "This user doesn't follow anyone yet.", "account.follows_you": "Follows you", "account.hide_reblogs": "Hide boosts from @{name}", "account.joined": "Joined {date}", - "account.last_status": "Last active", "account.link_verified_on": "Ownership of this link was checked on {date}", "account.locked_info": "This account privacy status is set to locked. The owner manually reviews who can follow them.", "account.media": "Media", @@ -32,7 +32,6 @@ "account.mute": "Mute @{name}", "account.mute_notifications": "Mute notifications from @{name}", "account.muted": "Muted", - "account.never_active": "Never", "account.posts": "Toots", "account.posts_with_replies": "Toots and replies", "account.report": "Report @{name}", @@ -42,10 +41,12 @@ "account.statuses_counter": "{count, plural, one {{counter} Toot} other {{counter} Toots}}", "account.unblock": "Unblock @{name}", "account.unblock_domain": "Unhide {domain}", + "account.unblock_short": "Unblock", "account.unendorse": "Don't feature on profile", "account.unfollow": "Unfollow", "account.unmute": "Unmute @{name}", "account.unmute_notifications": "Unmute notifications from @{name}", + "account.unmute_short": "Unmute", "account_note.placeholder": "No comment provided", "admin.dashboard.daily_retention": "User retention rate by day after sign-up", "admin.dashboard.monthly_retention": "User retention rate by month after sign-up", diff --git a/app/javascript/mastodon/locales/gd.json b/app/javascript/mastodon/locales/gd.json index 35ab5e83ef..d71705c5c3 100644 --- a/app/javascript/mastodon/locales/gd.json +++ b/app/javascript/mastodon/locales/gd.json @@ -18,12 +18,12 @@ "account.followers": "Luchd-leantainn", "account.followers.empty": "Chan eil neach sam bith a’ leantainn air a’ chleachdaiche seo fhathast.", "account.followers_counter": "{count, plural, one {{counter} neach-leantainn} two {{counter} neach-leantainn} few {{counter} luchd-leantainn} other {{counter} luchd-leantainn}}", + "account.following": "Following", "account.following_counter": "{count, plural, one {A’ leantainn air {counter}} two {A’ leantainn air {counter}} few {A’ leantainn air {counter}} other {A’ leantainn air {counter}}}", "account.follows.empty": "Chan eil an cleachdaiche seo a’ leantainn air neach sam bith fhathast.", "account.follows_you": "’Gad leantainn", "account.hide_reblogs": "Falaich na brosnachaidhean o @{name}", "account.joined": "Air ballrachd fhaighinn {date}", - "account.last_status": "An gnìomh mu dheireadh", "account.link_verified_on": "Chaidh dearbhadh cò leis a tha an ceangal seo {date}", "account.locked_info": "Tha prìobhaideachd ghlaiste aig a’ chunntais seo. Nì an sealbhadair lèirmheas a làimh air cò dh’fhaodas leantainn orra.", "account.media": "Meadhanan", @@ -32,7 +32,6 @@ "account.mute": "Mùch @{name}", "account.mute_notifications": "Mùch na brathan o @{name}", "account.muted": "’Ga mhùchadh", - "account.never_active": "Chan ann idir", "account.posts": "Postaichean", "account.posts_with_replies": "Postaichean ’s freagairtean", "account.report": "Dèan gearan mu @{name}", @@ -42,10 +41,12 @@ "account.statuses_counter": "{count, plural, one {{counter} phost} two {{counter} phost} few {{counter} postaichean} other {{counter} post}}", "account.unblock": "Dì-bhac @{name}", "account.unblock_domain": "Dì-bhac an àrainn {domain}", + "account.unblock_short": "Unblock", "account.unendorse": "Na brosnaich air a’ phròifil", "account.unfollow": "Na lean tuilleadh", "account.unmute": "Dì-mhùch @{name}", "account.unmute_notifications": "Dì-mhùch na brathan o @{name}", + "account.unmute_short": "Unmute", "account_note.placeholder": "Briog airson nòta a chur ris", "admin.dashboard.daily_retention": "Reat glèidheadh nan cleachdaichean às dèidh an clàradh a-rèir latha", "admin.dashboard.monthly_retention": "Reat glèidheadh nan cleachdaichean às dèidh an clàradh a-rèir mìos", diff --git a/app/javascript/mastodon/locales/gl.json b/app/javascript/mastodon/locales/gl.json index 63d4d7dbc4..6db991aacf 100644 --- a/app/javascript/mastodon/locales/gl.json +++ b/app/javascript/mastodon/locales/gl.json @@ -18,12 +18,12 @@ "account.followers": "Seguidoras", "account.followers.empty": "Aínda ninguén segue esta usuaria.", "account.followers_counter": "{count, plural, one {{counter} Seguidora} other {{counter} Seguidoras}}", + "account.following": "Following", "account.following_counter": "{count, plural, one {{counter} Seguindo} other {{counter} Seguindo}}", "account.follows.empty": "Esta usuaria aínda non segue a ninguén.", "account.follows_you": "Séguete", "account.hide_reblogs": "Agochar repeticións de @{name}", "account.joined": "Uníuse {date}", - "account.last_status": "Última actividade", "account.link_verified_on": "A propiedade desta ligazón foi verificada o {date}", "account.locked_info": "Esta é unha conta privada. A propietaria revisa de xeito manual quen pode seguila.", "account.media": "Multimedia", @@ -32,7 +32,6 @@ "account.mute": "Acalar @{name}", "account.mute_notifications": "Acalar as notificacións de @{name}", "account.muted": "Acalada", - "account.never_active": "Nunca", "account.posts": "Publicacións", "account.posts_with_replies": "Publicacións e respostas", "account.report": "Informar sobre @{name}", @@ -42,10 +41,12 @@ "account.statuses_counter": "{count, plural, one {{counter} Publicación} other {{counter} Publicacións}}", "account.unblock": "Desbloquear @{name}", "account.unblock_domain": "Amosar {domain}", + "account.unblock_short": "Unblock", "account.unendorse": "Non amosar no perfil", "account.unfollow": "Deixar de seguir", "account.unmute": "Deixar de silenciar a @{name}", "account.unmute_notifications": "Deixar de silenciar as notificacións de @{name}", + "account.unmute_short": "Unmute", "account_note.placeholder": "Preme para engadir nota", "admin.dashboard.daily_retention": "Ratio de retención de usuarias após rexistrarse", "admin.dashboard.monthly_retention": "Ratio de retención de usuarias após un mes do rexistro", diff --git a/app/javascript/mastodon/locales/he.json b/app/javascript/mastodon/locales/he.json index fd97ce53cf..452b64d9ec 100644 --- a/app/javascript/mastodon/locales/he.json +++ b/app/javascript/mastodon/locales/he.json @@ -18,12 +18,12 @@ "account.followers": "עוקבים", "account.followers.empty": "אף אחד לא עוקב אחר המשתמש הזה עדיין.", "account.followers_counter": "{count, plural,one {עוקב אחד} other {{counter} עוקבים}}", + "account.following": "Following", "account.following_counter": "{count, plural,one {עוקב אחרי {counter}}other {עוקב אחרי {counter}}}", "account.follows.empty": "משתמש זה לא עוקב אחר אף אחד עדיין.", "account.follows_you": "במעקב אחריך", "account.hide_reblogs": "להסתיר הידהודים מאת @{name}", "account.joined": "הצטרפו ב{date}", - "account.last_status": "פעילות אחרונה", "account.link_verified_on": "בעלות על הקישור הזה נבדקה לאחרונה ב{date}", "account.locked_info": "מצב הפרטיות של החשבון הנוכחי הוגדר כנעול. בעל החשבון קובע באופן פרטני מי יכול לעקוב אחריו.", "account.media": "מדיה", @@ -32,7 +32,6 @@ "account.mute": "להשתיק את @{name}", "account.mute_notifications": "להסתיר התראות מאת @{name}", "account.muted": "מושתק", - "account.never_active": "אף פעם", "account.posts": "הודעות", "account.posts_with_replies": "Toots with replies", "account.report": "לדווח על @{name}", @@ -42,10 +41,12 @@ "account.statuses_counter": "{count, plural, one {{counter} Toot} other {{counter} Toots}}", "account.unblock": "הסרת חסימה מעל @{name}", "account.unblock_domain": "הסר חסימה מקהילת {domain}", + "account.unblock_short": "Unblock", "account.unendorse": "לא להציג בפרופיל", "account.unfollow": "הפסקת מעקב", "account.unmute": "הפסקת השתקת @{name}", "account.unmute_notifications": "להפסיק הסתרת הודעות מעם @{name}", + "account.unmute_short": "Unmute", "account_note.placeholder": "ללא הערה", "admin.dashboard.daily_retention": "User retention rate by day after sign-up", "admin.dashboard.monthly_retention": "User retention rate by month after sign-up", diff --git a/app/javascript/mastodon/locales/hi.json b/app/javascript/mastodon/locales/hi.json index b5d731ac46..bb08cc92e7 100644 --- a/app/javascript/mastodon/locales/hi.json +++ b/app/javascript/mastodon/locales/hi.json @@ -18,12 +18,12 @@ "account.followers": "फॉलोवर", "account.followers.empty": "कोई भी इस यूज़र् को फ़ॉलो नहीं करता है", "account.followers_counter": "{count, plural, one {{counter} अनुगामी} other {{counter} समर्थक}}", + "account.following": "Following", "account.following_counter": "{count, plural, one {{counter} निम्नलिखित} other {{counter} निम्नलिखित}}", "account.follows.empty": "यह यूज़र् अभी तक किसी को फॉलो नहीं करता है।", "account.follows_you": "आपको फॉलो करता है", "account.hide_reblogs": "@{name} के बूस्ट छुपाएं", "account.joined": "Joined {date}", - "account.last_status": "अंतिम सक्रिय", "account.link_verified_on": "इस लिंक का स्वामित्व {date} को चेक किया गया था", "account.locked_info": "यह खाता गोपनीयता स्थिति लॉक करने के लिए सेट है। मालिक मैन्युअल रूप से समीक्षा करता है कि कौन उनको फॉलो कर सकता है।", "account.media": "मीडिया", @@ -32,7 +32,6 @@ "account.mute": "म्यूट @{name}", "account.mute_notifications": "@{name} के नोटिफिकेशन म्यूट करे", "account.muted": "म्यूट है", - "account.never_active": "कभी नहीं दिखे", "account.posts": "टूट्स", "account.posts_with_replies": "टूट्स एवं जवाब", "account.report": "रिपोर्ट @{name}", @@ -42,10 +41,12 @@ "account.statuses_counter": "{count, plural, one {{counter} भोंपू} other {{counter} भोंपू}}", "account.unblock": "@{name} को अनब्लॉक करें", "account.unblock_domain": "{domain} दिखाए", + "account.unblock_short": "Unblock", "account.unendorse": "प्रोफ़ाइल पर न दिखाए", "account.unfollow": "अनफॉलो करें", "account.unmute": "अनम्यूट @{name}", "account.unmute_notifications": "@{name} के नोटिफिकेशन अनम्यूट करे", + "account.unmute_short": "Unmute", "account_note.placeholder": "नोट्स जोड़ने के लिए क्लिक करें", "admin.dashboard.daily_retention": "User retention rate by day after sign-up", "admin.dashboard.monthly_retention": "User retention rate by month after sign-up", diff --git a/app/javascript/mastodon/locales/hr.json b/app/javascript/mastodon/locales/hr.json index e8798aabaa..a74c819c07 100644 --- a/app/javascript/mastodon/locales/hr.json +++ b/app/javascript/mastodon/locales/hr.json @@ -18,12 +18,12 @@ "account.followers": "Pratitelji", "account.followers.empty": "Nitko još ne prati korisnika/cu.", "account.followers_counter": "{count, plural, one {{counter} pratitelj} other {{counter} pratitelja}}", + "account.following": "Following", "account.following_counter": "{count, plural, one {{counter} praćeni} few{{counter} praćena} other {{counter} praćenih}}", "account.follows.empty": "Korisnik/ca još ne prati nikoga.", "account.follows_you": "Prati te", "account.hide_reblogs": "Sakrij boostove od @{name}", "account.joined": "Pridružio se {date}", - "account.last_status": "Posljednja aktivnost", "account.link_verified_on": "Vlasništvo ove poveznice provjereno je {date}", "account.locked_info": "Status privatnosti ovog računa postavljen je na zaključano. Vlasnik ručno pregledava tko ih može pratiti.", "account.media": "Medijski sadržaj", @@ -32,7 +32,6 @@ "account.mute": "Utišaj @{name}", "account.mute_notifications": "Utišaj obavijesti od @{name}", "account.muted": "Utišano", - "account.never_active": "Nikad", "account.posts": "Tootovi", "account.posts_with_replies": "Tootovi i odgovori", "account.report": "Prijavi @{name}", @@ -42,10 +41,12 @@ "account.statuses_counter": "{count, plural, one {{counter} toot} other {{counter} toota}}", "account.unblock": "Deblokiraj @{name}", "account.unblock_domain": "Deblokiraj domenu {domain}", + "account.unblock_short": "Unblock", "account.unendorse": "Ne ističi na profilu", "account.unfollow": "Prestani pratiti", "account.unmute": "Poništi utišavanje @{name}", "account.unmute_notifications": "Ne utišavaj obavijesti od @{name}", + "account.unmute_short": "Unmute", "account_note.placeholder": "Kliknite za dodavanje bilješke", "admin.dashboard.daily_retention": "User retention rate by day after sign-up", "admin.dashboard.monthly_retention": "User retention rate by month after sign-up", diff --git a/app/javascript/mastodon/locales/hu.json b/app/javascript/mastodon/locales/hu.json index 107b47b73b..494ca5f628 100644 --- a/app/javascript/mastodon/locales/hu.json +++ b/app/javascript/mastodon/locales/hu.json @@ -18,12 +18,12 @@ "account.followers": "Követő", "account.followers.empty": "Ezt a felhasználót még senki sem követi.", "account.followers_counter": "{count, plural, one {{counter} Követő} other {{counter} Követő}}", + "account.following": "Following", "account.following_counter": "{count, plural, other {{counter} Követett}}", "account.follows.empty": "Ez a felhasználó még senkit sem követ.", "account.follows_you": "Követ téged", "account.hide_reblogs": "@{name} megtolásainak elrejtése", "account.joined": "Csatlakozott {date}", - "account.last_status": "Utoljára aktív", "account.link_verified_on": "A linket eredetiségét ebben az időpontban ellenőriztük: {date}", "account.locked_info": "Ennek a fióknak zárolt a láthatósága. A tulajdonos kézzel engedélyezi, hogy ki követheti őt.", "account.media": "Média", @@ -32,7 +32,6 @@ "account.mute": "@{name} némítása", "account.mute_notifications": "@{name} értesítéseinek némítása", "account.muted": "Némítva", - "account.never_active": "Soha", "account.posts": "Bejegyzések", "account.posts_with_replies": "Bejegyzések és válaszok", "account.report": "@{name} jelentése", @@ -42,10 +41,12 @@ "account.statuses_counter": "{count, plural, one {{counter} Bejegyzés} other {{counter} Bejegyzés}}", "account.unblock": "@{name} letiltásának feloldása", "account.unblock_domain": "{domain} elrejtésének feloldása", + "account.unblock_short": "Unblock", "account.unendorse": "Ne jelenjen meg a profilodon", "account.unfollow": "Követés megszüntetése", "account.unmute": "@{name} némítás feloldása", "account.unmute_notifications": "@{name} némított értesítéseinek feloldása", + "account.unmute_short": "Unmute", "account_note.placeholder": "Klikk a feljegyzéshez", "admin.dashboard.daily_retention": "Napi regisztráció utáni felhasználómegtartási arány", "admin.dashboard.monthly_retention": "Havi regisztráció utáni felhasználómegtartási arány", diff --git a/app/javascript/mastodon/locales/hy.json b/app/javascript/mastodon/locales/hy.json index 0f984b0bcf..934d41a414 100644 --- a/app/javascript/mastodon/locales/hy.json +++ b/app/javascript/mastodon/locales/hy.json @@ -18,12 +18,12 @@ "account.followers": "Հետեւողներ", "account.followers.empty": "Այս օգտատիրոջը դեռ ոչ մէկ չի հետեւում։", "account.followers_counter": "{count, plural, one {{counter} Հետեւորդ} other {{counter} Հետեւորդ}}", + "account.following": "Following", "account.following_counter": "{count, plural, one {{counter} հետեւած} other {{counter} հետեւած}}", "account.follows.empty": "Այս օգտատէրը դեռ ոչ մէկի չի հետեւում։", "account.follows_you": "Հետեւում է քեզ", "account.hide_reblogs": "Թաքցնել @{name}֊ի տարածածները", "account.joined": "Միացել է {date}-ից", - "account.last_status": "Վերջին այցը", "account.link_verified_on": "Սոյն յղման տիրապետումը ստուգուած է՝ {date}֊ին", "account.locked_info": "Սոյն հաշուի գաղտնիութեան մակարդակը նշուած է որպէս՝ փակ։ Հաշուի տէրն ընտրում է, թէ ով կարող է հետեւել իրեն։", "account.media": "Մեդիա", @@ -32,7 +32,6 @@ "account.mute": "Լռեցնել @{name}֊ին", "account.mute_notifications": "Անջատել ծանուցումները @{name}֊ից", "account.muted": "Լռեցուած", - "account.never_active": "Երբեք", "account.posts": "Գրառումներ", "account.posts_with_replies": "Գրառումներ եւ պատասխաններ", "account.report": "Բողոքել @{name}֊ի մասին", @@ -42,10 +41,12 @@ "account.statuses_counter": "{count, plural, one {{counter} Գրառում} other {{counter} Գրառումներ}}", "account.unblock": "Ապաարգելափակել @{name}֊ին", "account.unblock_domain": "Ցուցադրել {domain} թաքցուած տիրոյթի գրառումները", + "account.unblock_short": "Unblock", "account.unendorse": "Չցուցադրել անձնական էջում", "account.unfollow": "Ապահետեւել", "account.unmute": "Ապալռեցնել @{name}֊ին", "account.unmute_notifications": "Միացնել ծանուցումները @{name}֊ից", + "account.unmute_short": "Unmute", "account_note.placeholder": "Սեղմէ՛ք գրառելու համար\n", "admin.dashboard.daily_retention": "User retention rate by day after sign-up", "admin.dashboard.monthly_retention": "User retention rate by month after sign-up", diff --git a/app/javascript/mastodon/locales/id.json b/app/javascript/mastodon/locales/id.json index d9a66373a9..bc0b3c0873 100644 --- a/app/javascript/mastodon/locales/id.json +++ b/app/javascript/mastodon/locales/id.json @@ -18,12 +18,12 @@ "account.followers": "Pengikut", "account.followers.empty": "Pengguna ini belum ada pengikut.", "account.followers_counter": "{count, plural, other {{counter} Pengikut}}", + "account.following": "Following", "account.following_counter": "{count, plural, other {{counter} Mengikuti}}", "account.follows.empty": "Pengguna ini belum mengikuti siapapun.", "account.follows_you": "Mengikuti anda", "account.hide_reblogs": "Sembunyikan boosts dari @{name}", "account.joined": "Bergabung {date}", - "account.last_status": "Terakhir aktif", "account.link_verified_on": "Kepemilikan tautan ini telah dicek pada {date}", "account.locked_info": "Status privasi akun ini disetel untuk dikunci. Pemilik secara manual meninjau siapa yang dapat mengikutinya.", "account.media": "Media", @@ -32,7 +32,6 @@ "account.mute": "Bisukan @{name}", "account.mute_notifications": "Bisukan pemberitahuan dari @{name}", "account.muted": "Dibisukan", - "account.never_active": "Tak pernah", "account.posts": "Kiriman", "account.posts_with_replies": "Postingan dengan balasan", "account.report": "Laporkan @{name}", @@ -42,10 +41,12 @@ "account.statuses_counter": "{count, plural, other {{counter} Toot}}", "account.unblock": "Hapus blokir @{name}", "account.unblock_domain": "Buka blokir domain {domain}", + "account.unblock_short": "Unblock", "account.unendorse": "Jangan tampilkan di profil", "account.unfollow": "Berhenti mengikuti", "account.unmute": "Berhenti membisukan @{name}", "account.unmute_notifications": "Berhenti bisukan pemberitahuan dari @{name}", + "account.unmute_short": "Unmute", "account_note.placeholder": "Klik untuk menambah catatan", "admin.dashboard.daily_retention": "Tingkat retensi pengguna perhari setelah mendaftar", "admin.dashboard.monthly_retention": "Tingkat retensi pengguna perbulan setelah mendaftar", diff --git a/app/javascript/mastodon/locales/io.json b/app/javascript/mastodon/locales/io.json index ef4a489ada..a60f68fbaa 100644 --- a/app/javascript/mastodon/locales/io.json +++ b/app/javascript/mastodon/locales/io.json @@ -18,12 +18,12 @@ "account.followers": "Sequanti", "account.followers.empty": "No one follows this user yet.", "account.followers_counter": "{count, plural, one {{counter} Follower} other {{counter} Followers}}", + "account.following": "Following", "account.following_counter": "{count, plural, one {{counter} Following} other {{counter} Following}}", "account.follows.empty": "This user doesn't follow anyone yet.", "account.follows_you": "Sequas tu", "account.hide_reblogs": "Hide boosts from @{name}", "account.joined": "Joined {date}", - "account.last_status": "Last active", "account.link_verified_on": "Ownership of this link was checked on {date}", "account.locked_info": "This account privacy status is set to locked. The owner manually reviews who can follow them.", "account.media": "Media", @@ -32,7 +32,6 @@ "account.mute": "Celar @{name}", "account.mute_notifications": "Mute notifications from @{name}", "account.muted": "Muted", - "account.never_active": "Never", "account.posts": "Mesaji", "account.posts_with_replies": "Toots with replies", "account.report": "Denuncar @{name}", @@ -42,10 +41,12 @@ "account.statuses_counter": "{count, plural, one {{counter} Toot} other {{counter} Toots}}", "account.unblock": "Desblokusar @{name}", "account.unblock_domain": "Unhide {domain}", + "account.unblock_short": "Unblock", "account.unendorse": "Don't feature on profile", "account.unfollow": "Ne plus sequar", "account.unmute": "Ne plus celar @{name}", "account.unmute_notifications": "Unmute notifications from @{name}", + "account.unmute_short": "Unmute", "account_note.placeholder": "Click to add a note", "admin.dashboard.daily_retention": "User retention rate by day after sign-up", "admin.dashboard.monthly_retention": "User retention rate by month after sign-up", diff --git a/app/javascript/mastodon/locales/is.json b/app/javascript/mastodon/locales/is.json index 34e5393608..ab8c55d1ef 100644 --- a/app/javascript/mastodon/locales/is.json +++ b/app/javascript/mastodon/locales/is.json @@ -18,12 +18,12 @@ "account.followers": "Fylgjendur", "account.followers.empty": "Ennþá fylgist enginn með þessum notanda.", "account.followers_counter": "{count, plural, one {{counter} fylgjandi} other {{counter} fylgjendur}}", + "account.following": "Following", "account.following_counter": "{count, plural, one {{counter} fylgist með} other {{counter} fylgjast með}}", "account.follows.empty": "Þessi notandi fylgist ennþá ekki með neinum.", "account.follows_you": "Fylgir þér", "account.hide_reblogs": "Fela endurbirtingar fyrir @{name}", "account.joined": "Gerðist þátttakandi {date}", - "account.last_status": "Síðasta virkni", "account.link_verified_on": "Eignarhald á þessum tengli var athugað þann {date}", "account.locked_info": "Staða gagnaleyndar á þessum aðgangi er stillt á læsingu. Eigandinn yfirfer handvirkt hverjir geti fylgst með honum.", "account.media": "Myndskrár", @@ -32,7 +32,6 @@ "account.mute": "Þagga niður í @{name}", "account.mute_notifications": "Þagga tilkynningar frá @{name}", "account.muted": "Þaggað", - "account.never_active": "Aldrei", "account.posts": "Færslur", "account.posts_with_replies": "Færslur og svör", "account.report": "Kæra @{name}", @@ -42,10 +41,12 @@ "account.statuses_counter": "{count, plural, one {{counter} færsla} other {{counter} færslur}}", "account.unblock": "Aflétta útilokun af @{name}", "account.unblock_domain": "Aflétta útilokun lénsins {domain}", + "account.unblock_short": "Unblock", "account.unendorse": "Ekki birta á notandasniði", "account.unfollow": "Hætta að fylgja", "account.unmute": "Hætta að þagga niður í @{name}", "account.unmute_notifications": "Hætta að þagga tilkynningar frá @{name}", + "account.unmute_short": "Unmute", "account_note.placeholder": "Smelltu til að bæta við minnispunkti", "admin.dashboard.daily_retention": "Hlutfall virkra notenda eftir nýskráningu eftir dögum", "admin.dashboard.monthly_retention": "Hlutfall virkra notenda eftir nýskráningu eftir mánuðum", diff --git a/app/javascript/mastodon/locales/it.json b/app/javascript/mastodon/locales/it.json index 5530c5abf4..389986ef5c 100644 --- a/app/javascript/mastodon/locales/it.json +++ b/app/javascript/mastodon/locales/it.json @@ -18,12 +18,12 @@ "account.followers": "Follower", "account.followers.empty": "Nessuno segue ancora questo utente.", "account.followers_counter": "{count, plural, one {{counter} Follower} other {{counter} Follower}}", + "account.following": "Following", "account.following_counter": "{count, plural, other {{counter} Seguiti}}", "account.follows.empty": "Questo utente non segue nessuno ancora.", "account.follows_you": "Ti segue", "account.hide_reblogs": "Nascondi condivisioni da @{name}", "account.joined": "Su questa istanza dal {date}", - "account.last_status": "Ultima attività", "account.link_verified_on": "La proprietà di questo link è stata controllata il {date}", "account.locked_info": "Questo è un account privato. Il proprietario approva manualmente chi può seguirlo.", "account.media": "Media", @@ -32,7 +32,6 @@ "account.mute": "Silenzia @{name}", "account.mute_notifications": "Silenzia notifiche da @{name}", "account.muted": "Silenziato", - "account.never_active": "Mai", "account.posts": "Post", "account.posts_with_replies": "Post e risposte", "account.report": "Segnala @{name}", @@ -42,10 +41,12 @@ "account.statuses_counter": "{count, plural, one {{counter} Post} other {{counter} Post}}", "account.unblock": "Sblocca @{name}", "account.unblock_domain": "Sblocca il dominio {domain}", + "account.unblock_short": "Unblock", "account.unendorse": "Non mostrare sul profilo", "account.unfollow": "Smetti di seguire", "account.unmute": "Riattiva @{name}", "account.unmute_notifications": "Riattiva le notifiche da @{name}", + "account.unmute_short": "Unmute", "account_note.placeholder": "Clicca per aggiungere una nota", "admin.dashboard.daily_retention": "Tasso di ritenzione utente per giorno dopo la registrazione", "admin.dashboard.monthly_retention": "Tasso di ritenzione utente per mese dopo la registrazione", diff --git a/app/javascript/mastodon/locales/ja.json b/app/javascript/mastodon/locales/ja.json index f120df2aee..19b8cb705c 100644 --- a/app/javascript/mastodon/locales/ja.json +++ b/app/javascript/mastodon/locales/ja.json @@ -18,12 +18,12 @@ "account.followers": "フォロワー", "account.followers.empty": "まだ誰もフォローしていません。", "account.followers_counter": "{counter} フォロワー", + "account.following": "Following", "account.following_counter": "{counter} フォロー", "account.follows.empty": "まだ誰もフォローしていません。", "account.follows_you": "フォローされています", "account.hide_reblogs": "@{name}さんからのブーストを非表示", "account.joined": "{date} に登録", - "account.last_status": "最後の活動", "account.link_verified_on": "このリンクの所有権は{date}に確認されました", "account.locked_info": "このアカウントは承認制アカウントです。相手が承認するまでフォローは完了しません。", "account.media": "メディア", @@ -32,7 +32,6 @@ "account.mute": "@{name}さんをミュート", "account.mute_notifications": "@{name}さんからの通知を受け取らない", "account.muted": "ミュート済み", - "account.never_active": "活動なし", "account.posts": "投稿", "account.posts_with_replies": "投稿と返信", "account.report": "@{name}さんを通報", @@ -42,10 +41,12 @@ "account.statuses_counter": "{counter} 投稿", "account.unblock": "@{name}さんのブロックを解除", "account.unblock_domain": "{domain}のブロックを解除", + "account.unblock_short": "Unblock", "account.unendorse": "プロフィールから外す", "account.unfollow": "フォロー解除", "account.unmute": "@{name}さんのミュートを解除", "account.unmute_notifications": "@{name}さんからの通知を受け取るようにする", + "account.unmute_short": "Unmute", "account_note.placeholder": "クリックしてメモを追加", "admin.dashboard.daily_retention": "サインアップ後の日ごとのユーザー継続率", "admin.dashboard.monthly_retention": "サインアップ後の月ごとのユーザー継続率", diff --git a/app/javascript/mastodon/locales/ka.json b/app/javascript/mastodon/locales/ka.json index 5617700607..fd848a1647 100644 --- a/app/javascript/mastodon/locales/ka.json +++ b/app/javascript/mastodon/locales/ka.json @@ -18,12 +18,12 @@ "account.followers": "მიმდევრები", "account.followers.empty": "No one follows this user yet.", "account.followers_counter": "{count, plural, one {{counter} Follower} other {{counter} Followers}}", + "account.following": "Following", "account.following_counter": "{count, plural, one {{counter} Following} other {{counter} Following}}", "account.follows.empty": "This user doesn't follow anyone yet.", "account.follows_you": "მოგყვებათ", "account.hide_reblogs": "დაიმალოს ბუსტები @{name}-სგან", "account.joined": "Joined {date}", - "account.last_status": "Last active", "account.link_verified_on": "Ownership of this link was checked on {date}", "account.locked_info": "This account privacy status is set to locked. The owner manually reviews who can follow them.", "account.media": "მედია", @@ -32,7 +32,6 @@ "account.mute": "გააჩუმე @{name}", "account.mute_notifications": "გააჩუმე შეტყობინებები @{name}-სგან", "account.muted": "გაჩუმებული", - "account.never_active": "Never", "account.posts": "ტუტები", "account.posts_with_replies": "ტუტები და პასუხები", "account.report": "დაარეპორტე @{name}", @@ -42,10 +41,12 @@ "account.statuses_counter": "{count, plural, one {{counter} Toot} other {{counter} Toots}}", "account.unblock": "განბლოკე @{name}", "account.unblock_domain": "გამოაჩინე {domain}", + "account.unblock_short": "Unblock", "account.unendorse": "არ გამოირჩეს პროფილზე", "account.unfollow": "ნუღარ მიჰყვები", "account.unmute": "ნუღარ აჩუმებ @{name}-ს", "account.unmute_notifications": "ნუღარ აჩუმებ შეტყობინებებს @{name}-სგან", + "account.unmute_short": "Unmute", "account_note.placeholder": "Click to add a note", "admin.dashboard.daily_retention": "User retention rate by day after sign-up", "admin.dashboard.monthly_retention": "User retention rate by month after sign-up", diff --git a/app/javascript/mastodon/locales/kab.json b/app/javascript/mastodon/locales/kab.json index 0f0880100e..213f529e39 100644 --- a/app/javascript/mastodon/locales/kab.json +++ b/app/javascript/mastodon/locales/kab.json @@ -18,12 +18,12 @@ "account.followers": "Imeḍfaren", "account.followers.empty": "Ar tura, ulac yiwen i yeṭṭafaṛen amseqdac-agi.", "account.followers_counter": "{count, plural, one {{count} n umeḍfar} other {{count} n imeḍfaren}}", + "account.following": "Following", "account.following_counter": "{count, plural, one {{counter} yeṭṭafaren} aḍfar {{counter} wayeḍ}}", "account.follows.empty": "Ar tura, amseqdac-agi ur yeṭṭafaṛ yiwen.", "account.follows_you": "Yeṭṭafaṛ-ik", "account.hide_reblogs": "Ffer ayen i ibeṭṭu @{name}", "account.joined": "Yerna-d {date}", - "account.last_status": "Armud aneggaru", "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": "Amidya", @@ -32,7 +32,6 @@ "account.mute": "Sgugem @{name}", "account.mute_notifications": "Sgugem tilɣa sγur @{name}", "account.muted": "Yettwasgugem", - "account.never_active": "Werǧin", "account.posts": "Tijewwaqin", "account.posts_with_replies": "Tijewwaqin akked tririyin", "account.report": "Cetki ɣef @{name}", @@ -42,10 +41,12 @@ "account.statuses_counter": "{count, plural, one {{counter} ajewwaq} other {{counter} ijewwaqen}}", "account.unblock": "Serreḥ i @{name}", "account.unblock_domain": "Ssken-d {domain}", + "account.unblock_short": "Unblock", "account.unendorse": "Ur ttwellih ara fell-as deg umaɣnu-inek", "account.unfollow": "Ur ṭṭafaṛ ara", "account.unmute": "Kkes asgugem ɣef @{name}", "account.unmute_notifications": "Serreḥ ilɣa sɣur @{name}", + "account.unmute_short": "Unmute", "account_note.placeholder": "Ulac iwenniten", "admin.dashboard.daily_retention": "User retention rate by day after sign-up", "admin.dashboard.monthly_retention": "User retention rate by month after sign-up", diff --git a/app/javascript/mastodon/locales/kk.json b/app/javascript/mastodon/locales/kk.json index 3bd56653cd..1802d5fdfb 100644 --- a/app/javascript/mastodon/locales/kk.json +++ b/app/javascript/mastodon/locales/kk.json @@ -18,12 +18,12 @@ "account.followers": "Оқырмандар", "account.followers.empty": "Әлі ешкім жазылмаған.", "account.followers_counter": "{count, plural, one {{counter} Оқырман} other {{counter} Оқырман}}", + "account.following": "Following", "account.following_counter": "{count, plural, one {{counter} Жазылым} other {{counter} Жазылым}}", "account.follows.empty": "Ешкімге жазылмапты.", "account.follows_you": "Сізге жазылыпты", "account.hide_reblogs": "@{name} атты қолданушының әрекеттерін жасыру", "account.joined": "Joined {date}", - "account.last_status": "Соңғы белсенділік", "account.link_verified_on": "Сілтеме меншігі расталған күн {date}", "account.locked_info": "Бұл қолданушы өзі туралы мәліметтерді жасырған. Тек жазылғандар ғана көре алады.", "account.media": "Медиа", @@ -32,7 +32,6 @@ "account.mute": "Үнсіз қылу @{name}", "account.mute_notifications": "@{name} туралы ескертпелерді жасыру", "account.muted": "Үнсіз", - "account.never_active": "Ешқашан", "account.posts": "Жазбалар", "account.posts_with_replies": "Жазбалар мен жауаптар", "account.report": "Шағымдану @{name}", @@ -42,10 +41,12 @@ "account.statuses_counter": "{count, plural, one {{counter} Пост} other {{counter} Пост}}", "account.unblock": "Бұғаттан шығару @{name}", "account.unblock_domain": "Бұғаттан шығару {domain}", + "account.unblock_short": "Unblock", "account.unendorse": "Профильде рекомендемеу", "account.unfollow": "Оқымау", "account.unmute": "@{name} ескертпелерін қосу", "account.unmute_notifications": "@{name} ескертпелерін көрсету", + "account.unmute_short": "Unmute", "account_note.placeholder": "Жазба қалдыру үшін бас", "admin.dashboard.daily_retention": "User retention rate by day after sign-up", "admin.dashboard.monthly_retention": "User retention rate by month after sign-up", diff --git a/app/javascript/mastodon/locales/kmr.json b/app/javascript/mastodon/locales/kmr.json index 84c8978a42..43468eee4a 100644 --- a/app/javascript/mastodon/locales/kmr.json +++ b/app/javascript/mastodon/locales/kmr.json @@ -18,12 +18,12 @@ "account.followers": "Şopîner", "account.followers.empty": "Kesekî hin ev bikarhêner neşopandiye.", "account.followers_counter": "{count, plural, one {{counter} Follower} other {{counter} Followers}}", + "account.following": "Following", "account.following_counter": "{count, plural, one {{counter} Dişopîne} other {{counter} Dişopîne}}", "account.follows.empty": "Ev bikarhêner hin kesekî heya niha neşopandiye.", "account.follows_you": "Te dişopîne", "account.hide_reblogs": "Bilindkirinên ji @{name} veşêre", "account.joined": "Tevlîbû di {date} de", - "account.last_status": "Çalakiya dawî", "account.link_verified_on": "Xwedaniya li vê girêdanê di {date} de hatiye kontrolkirin", "account.locked_info": "Rewşa vê ajimêrê wek kilît kirî hatiye saz kirin. Xwedî yê ajimêrê, kesên vê bişopîne bi dest vekolin dike.", "account.media": "Medya", @@ -32,7 +32,6 @@ "account.mute": "@{name} Bêdeng bike", "account.mute_notifications": "Agahdariyan ji @{name} bêdeng bike", "account.muted": "Bêdengkirî", - "account.never_active": "Tu car", "account.posts": "Şandî", "account.posts_with_replies": "Şandî û bersiv", "account.report": "@{name} Ragihîne", @@ -42,10 +41,12 @@ "account.statuses_counter": "{count, plural,one {{counter} şandî}other {{counter} şandî}}", "account.unblock": "Astengê li ser @{name} rake", "account.unblock_domain": "Astengê li ser navperê {domain} rake", + "account.unblock_short": "Unblock", "account.unendorse": "Li ser profîl nîşan neke", "account.unfollow": "Neşopîne", "account.unmute": "@{name} Bêdeng bike", "account.unmute_notifications": "Agahdariyan ji @{name} bêdeng bike", + "account.unmute_short": "Unmute", "account_note.placeholder": "Bitikîne bo nîşeyekê tevlî bikî", "admin.dashboard.daily_retention": "Rêjeya ragirtina bikarhêner bi roj piştî tomarkirinê", "admin.dashboard.monthly_retention": "Rêjeya ragirtina bikarhêner bi meh piştî tomarkirinê", diff --git a/app/javascript/mastodon/locales/kn.json b/app/javascript/mastodon/locales/kn.json index 9da0f8c575..133ad1848e 100644 --- a/app/javascript/mastodon/locales/kn.json +++ b/app/javascript/mastodon/locales/kn.json @@ -18,12 +18,12 @@ "account.followers": "ಹಿಂಬಾಲಕರು", "account.followers.empty": "No one follows this user yet.", "account.followers_counter": "{count, plural, one {{counter} Follower} other {{counter} Followers}}", + "account.following": "Following", "account.following_counter": "{count, plural, one {{counter} Following} other {{counter} Following}}", "account.follows.empty": "This user doesn't follow anyone yet.", "account.follows_you": "Follows you", "account.hide_reblogs": "Hide boosts from @{name}", "account.joined": "Joined {date}", - "account.last_status": "Last active", "account.link_verified_on": "Ownership of this link was checked on {date}", "account.locked_info": "This account privacy status is set to locked. The owner manually reviews who can follow them.", "account.media": "Media", @@ -32,7 +32,6 @@ "account.mute": "Mute @{name}", "account.mute_notifications": "Mute notifications from @{name}", "account.muted": "Muted", - "account.never_active": "Never", "account.posts": "ಟೂಟ್‌ಗಳು", "account.posts_with_replies": "Toots and replies", "account.report": "Report @{name}", @@ -42,10 +41,12 @@ "account.statuses_counter": "{count, plural, one {{counter} Toot} other {{counter} Toots}}", "account.unblock": "Unblock @{name}", "account.unblock_domain": "Unhide {domain}", + "account.unblock_short": "Unblock", "account.unendorse": "Don't feature on profile", "account.unfollow": "Unfollow", "account.unmute": "Unmute @{name}", "account.unmute_notifications": "Unmute notifications from @{name}", + "account.unmute_short": "Unmute", "account_note.placeholder": "Click to add a note", "admin.dashboard.daily_retention": "User retention rate by day after sign-up", "admin.dashboard.monthly_retention": "User retention rate by month after sign-up", diff --git a/app/javascript/mastodon/locales/ko.json b/app/javascript/mastodon/locales/ko.json index 767fd8d460..79f6de0351 100644 --- a/app/javascript/mastodon/locales/ko.json +++ b/app/javascript/mastodon/locales/ko.json @@ -18,12 +18,12 @@ "account.followers": "팔로워", "account.followers.empty": "아직 아무도 이 유저를 팔로우하고 있지 않습니다.", "account.followers_counter": "{counter} 팔로워", + "account.following": "Following", "account.following_counter": "{counter} 팔로잉", "account.follows.empty": "이 유저는 아직 아무도 팔로우하고 있지 않습니다.", "account.follows_you": "날 팔로우합니다", "account.hide_reblogs": "@{name}의 부스트를 숨기기", "account.joined": "{date}에 가입함", - "account.last_status": "마지막 활동", "account.link_verified_on": "{date}에 이 링크의 소유권이 확인 됨", "account.locked_info": "이 계정의 프라이버시 설정은 잠금으로 설정되어 있습니다. 계정 소유자가 수동으로 팔로워를 승인합니다.", "account.media": "미디어", @@ -32,7 +32,6 @@ "account.mute": "@{name} 뮤트", "account.mute_notifications": "@{name}의 알림을 뮤트", "account.muted": "뮤트 됨", - "account.never_active": "없음", "account.posts": "게시물", "account.posts_with_replies": "게시물과 답장", "account.report": "@{name} 신고", @@ -42,10 +41,12 @@ "account.statuses_counter": "{counter} 게시물", "account.unblock": "차단 해제", "account.unblock_domain": "도메인 {domain} 차단 해제", + "account.unblock_short": "Unblock", "account.unendorse": "프로필에 추천하지 않기", "account.unfollow": "팔로우 해제", "account.unmute": "@{name} 뮤트 해제", "account.unmute_notifications": "@{name}의 알림 뮤트 해제", + "account.unmute_short": "Unmute", "account_note.placeholder": "클릭해서 노트 추가", "admin.dashboard.daily_retention": "가입 후 일별 사용자 유지율", "admin.dashboard.monthly_retention": "가입 후 월별 사용자 유지율", diff --git a/app/javascript/mastodon/locales/ku.json b/app/javascript/mastodon/locales/ku.json index a717021711..5a3e5a1f23 100644 --- a/app/javascript/mastodon/locales/ku.json +++ b/app/javascript/mastodon/locales/ku.json @@ -18,12 +18,12 @@ "account.followers": "شوێنکەوتووان", "account.followers.empty": "کەسێک شوێن ئەم بەکارهێنەرە نەکەوتووە", "account.followers_counter": "{count, plural, one {{counter} شوێنکەوتوو} other {{counter} شوێنکەوتوو}}", + "account.following": "Following", "account.following_counter": "{count, plural, one {{counter} Following} other {{counter} Following}}", "account.follows.empty": "ئەم بەکارهێنەرە تا ئێستا شوێن کەس نەکەوتووە.", "account.follows_you": "شوێنکەوتووەکانت", "account.hide_reblogs": "داشاردنی بووستەکان لە @{name}", "account.joined": "Joined {date}", - "account.last_status": "دوایین چالاکی", "account.link_verified_on": "خاوەنداریەتی ئەم لینکە لە {date} چێک کراوە", "account.locked_info": "تایبەتمەندی ئەم هەژمارەیە ڕیکخراوە بۆ قوفڵدراوە. خاوەنەکە بە دەستی پێداچوونەوە دەکات کە کێ دەتوانێت شوێنیان بکەوێت.", "account.media": "میدیا", @@ -32,7 +32,6 @@ "account.mute": "بێدەنگکردن @{name}", "account.mute_notifications": "هۆشیارکەرەوەکان لاببە لە @{name}", "account.muted": "بێ دەنگ", - "account.never_active": "هەرگیز", "account.posts": "توتس", "account.posts_with_replies": "توتس و وەڵامەکان", "account.report": "گوزارشت @{name}", @@ -42,10 +41,12 @@ "account.statuses_counter": "{count, plural, one {{counter} Following} other {{counter} Following}}", "account.unblock": "@{name} لاببە", "account.unblock_domain": "کردنەوەی دۆمەینی {domain}", + "account.unblock_short": "Unblock", "account.unendorse": "تایبەتمەندی لەسەر پرۆفایلەکە نیە", "account.unfollow": "بەدوادانەچو", "account.unmute": "بێدەنگکردنی @{name}", "account.unmute_notifications": "بێدەنگکردنی هۆشیارییەکان لە @{name}", + "account.unmute_short": "Unmute", "account_note.placeholder": "کرتەبکە بۆ زیادکردنی تێبینی", "admin.dashboard.daily_retention": "User retention rate by day after sign-up", "admin.dashboard.monthly_retention": "User retention rate by month after sign-up", diff --git a/app/javascript/mastodon/locales/kw.json b/app/javascript/mastodon/locales/kw.json index 0e8aa9cf84..0687326108 100644 --- a/app/javascript/mastodon/locales/kw.json +++ b/app/javascript/mastodon/locales/kw.json @@ -18,12 +18,12 @@ "account.followers": "Holyoryon", "account.followers.empty": "Ny wra nagonan holya'n devnydhyer ma hwath.", "account.followers_counter": "{count, plural, one {{counter} Holyer} other {{counter} Holyer}}", + "account.following": "Following", "account.following_counter": "{count, plural, one {Ow holya {counter}} other {Ow holya {counter}}}", "account.follows.empty": "Ny wra'n devnydhyer ma holya nagonan hwath.", "account.follows_you": "Y'th hol", "account.hide_reblogs": "Kudha kenerthow a @{name}", "account.joined": "Joined {date}", - "account.last_status": "Bew diwettha", "account.link_verified_on": "Perghenogeth an kolm ma a veu checkys dhe {date}", "account.locked_info": "Studh privetter an akont ma yw alhwedhys. An perghen a wra dasweles dre leuv piw a yll aga holya.", "account.media": "Myski", @@ -32,7 +32,6 @@ "account.mute": "Tawhe @{name}", "account.mute_notifications": "Tawhe gwarnyansow a @{name}", "account.muted": "Tawhes", - "account.never_active": "Nevra", "account.posts": "Postow", "account.posts_with_replies": "Postow ha gorthebow", "account.report": "Reportya @{name}", @@ -42,10 +41,12 @@ "account.statuses_counter": "{count, plural, one {{counter} Tout} other {{counter} Tout}}", "account.unblock": "Anlettya @{name}", "account.unblock_domain": "Anlettya gorfarth {domain}", + "account.unblock_short": "Unblock", "account.unendorse": "Na wra diskwedhes yn profil", "account.unfollow": "Anholya", "account.unmute": "Antawhe @{name}", "account.unmute_notifications": "Antawhe gwarnyansow a @{name}", + "account.unmute_short": "Unmute", "account_note.placeholder": "Klyckya dhe geworra noten", "admin.dashboard.daily_retention": "User retention rate by day after sign-up", "admin.dashboard.monthly_retention": "User retention rate by month after sign-up", diff --git a/app/javascript/mastodon/locales/lt.json b/app/javascript/mastodon/locales/lt.json index 600f4249e0..57f6c6216b 100644 --- a/app/javascript/mastodon/locales/lt.json +++ b/app/javascript/mastodon/locales/lt.json @@ -18,12 +18,12 @@ "account.followers": "Followers", "account.followers.empty": "No one follows this user yet.", "account.followers_counter": "{count, plural, one {{counter} Follower} other {{counter} Followers}}", + "account.following": "Following", "account.following_counter": "{count, plural, one {{counter} Following} other {{counter} Following}}", "account.follows.empty": "This user doesn't follow anyone yet.", "account.follows_you": "Follows you", "account.hide_reblogs": "Hide boosts from @{name}", "account.joined": "Joined {date}", - "account.last_status": "Last active", "account.link_verified_on": "Ownership of this link was checked on {date}", "account.locked_info": "This account privacy status is set to locked. The owner manually reviews who can follow them.", "account.media": "Media", @@ -32,7 +32,6 @@ "account.mute": "Mute @{name}", "account.mute_notifications": "Mute notifications from @{name}", "account.muted": "Užtildytas", - "account.never_active": "Niekada", "account.posts": "Toots", "account.posts_with_replies": "Toots and replies", "account.report": "Report @{name}", @@ -42,10 +41,12 @@ "account.statuses_counter": "{count, plural, one {{counter} Toot} other {{counter} Toots}}", "account.unblock": "Unblock @{name}", "account.unblock_domain": "Unhide {domain}", + "account.unblock_short": "Unblock", "account.unendorse": "Don't feature on profile", "account.unfollow": "Nebesekti", "account.unmute": "Unmute @{name}", "account.unmute_notifications": "Unmute notifications from @{name}", + "account.unmute_short": "Unmute", "account_note.placeholder": "Click to add a note", "admin.dashboard.daily_retention": "User retention rate by day after sign-up", "admin.dashboard.monthly_retention": "User retention rate by month after sign-up", diff --git a/app/javascript/mastodon/locales/lv.json b/app/javascript/mastodon/locales/lv.json index 07d93f5638..aa3c6de3d3 100644 --- a/app/javascript/mastodon/locales/lv.json +++ b/app/javascript/mastodon/locales/lv.json @@ -18,12 +18,12 @@ "account.followers": "Sekotāji", "account.followers.empty": "Šim lietotājam patreiz nav sekotāju.", "account.followers_counter": "{count, plural, one {{counter} Sekotājs} other {{counter} Sekotāji}}", + "account.following": "Following", "account.following_counter": "{count, plural, one {{counter} Sekojošs} other {{counter} Sekojoši}}", "account.follows.empty": "Šis lietotājs pagaidām nevienam neseko.", "account.follows_you": "Seko tev", "account.hide_reblogs": "Paslēpt paceltos ierakstus no lietotāja @{name}", "account.joined": "Pievienojās {date}", - "account.last_status": "Pēdējā aktivitāte", "account.link_verified_on": "Šīs saites piederība ir pārbaudīta {date}", "account.locked_info": "Šī konta privātuma statuss ir slēgts. Īpašnieks izskatīs, kurš viņam drīkst sekot.", "account.media": "Mediji", @@ -32,7 +32,6 @@ "account.mute": "Apklusināt @{name}", "account.mute_notifications": "Nerādīt paziņojumus no @{name}", "account.muted": "Apklusināts", - "account.never_active": "Nekad", "account.posts": "Ziņas", "account.posts_with_replies": "Ziņas un atbildes", "account.report": "Ziņot par lietotāju @{name}", @@ -42,10 +41,12 @@ "account.statuses_counter": "{count, plural, one {{counter} ziņa} other {{counter} ziņas}}", "account.unblock": "Atbloķēt lietotāju @{name}", "account.unblock_domain": "Atbloķēt domēnu {domain}", + "account.unblock_short": "Unblock", "account.unendorse": "Neattēlot profilā", "account.unfollow": "Pārstāt sekot", "account.unmute": "Noņemt apklusinājumu @{name}", "account.unmute_notifications": "Rādīt paziņojumus no lietotāja @{name}", + "account.unmute_short": "Unmute", "account_note.placeholder": "Noklikšķiniet, lai pievienotu piezīmi", "admin.dashboard.daily_retention": "Lietotāju saglabāšanas rādītājs dienā pēc reģistrēšanās", "admin.dashboard.monthly_retention": "Lietotāju saglabāšanas rādītājs mēnesī pēc reģistrēšanās", diff --git a/app/javascript/mastodon/locales/mk.json b/app/javascript/mastodon/locales/mk.json index 54eae6e6d4..a263d407b0 100644 --- a/app/javascript/mastodon/locales/mk.json +++ b/app/javascript/mastodon/locales/mk.json @@ -18,12 +18,12 @@ "account.followers": "Следбеници", "account.followers.empty": "Никој не го следи овој корисник сеуште.", "account.followers_counter": "{count, plural, one {{counter} Follower} other {{counter} Followers}}", + "account.following": "Following", "account.following_counter": "{count, plural, one {{counter} Following} other {{counter} Following}}", "account.follows.empty": "Корисникот не следи никој сеуште.", "account.follows_you": "Те следи тебе", "account.hide_reblogs": "Сокриј буст од @{name}", "account.joined": "Joined {date}", - "account.last_status": "Последно активен", "account.link_verified_on": "Сопстевноста на овај линк беше проверен на {date}", "account.locked_info": "Статусот на приватност на овај корисник е сетиран како заклучен. Корисникот одлучува кој можи да го следи него.", "account.media": "Медија", @@ -32,7 +32,6 @@ "account.mute": "Зачути го @{name}", "account.mute_notifications": "Исклучи известувања од @{name}", "account.muted": "Зачутено", - "account.never_active": "Никогаш", "account.posts": "Тутови", "account.posts_with_replies": "Тутови и реплики", "account.report": "Пријави @{name}", @@ -42,10 +41,12 @@ "account.statuses_counter": "{count, plural, one {{counter} Toot} other {{counter} Toots}}", "account.unblock": "Одблокирај @{name}", "account.unblock_domain": "Прикажи {domain}", + "account.unblock_short": "Unblock", "account.unendorse": "Не прикажувај на профил", "account.unfollow": "Одследи", "account.unmute": "Зачути го @{name}", "account.unmute_notifications": "Исклучи известувања од @{name}", + "account.unmute_short": "Unmute", "account_note.placeholder": "Click to add a note", "admin.dashboard.daily_retention": "User retention rate by day after sign-up", "admin.dashboard.monthly_retention": "User retention rate by month after sign-up", diff --git a/app/javascript/mastodon/locales/ml.json b/app/javascript/mastodon/locales/ml.json index 766bdfafdf..f20de55542 100644 --- a/app/javascript/mastodon/locales/ml.json +++ b/app/javascript/mastodon/locales/ml.json @@ -18,12 +18,12 @@ "account.followers": "പിന്തുടരുന്നവർ", "account.followers.empty": "ഈ ഉപയോക്താവിനെ ആരും ഇതുവരെ പിന്തുടരുന്നില്ല.", "account.followers_counter": "{count, plural, one {{counter} പിന്തുടരുന്നവർ} other {{counter} പിന്തുടരുന്നവർ}}", + "account.following": "Following", "account.following_counter": "{count, plural, one {{counter} പിന്തുടരുന്നു} other {{counter} പിന്തുടരുന്നു}}", "account.follows.empty": "ഈ ഉപയോക്താവ് ആരേയും ഇതുവരെ പിന്തുടരുന്നില്ല.", "account.follows_you": "നിങ്ങളെ പിന്തുടരുന്നു", "account.hide_reblogs": "@{name} ബൂസ്റ്റ് ചെയ്തവ മറയ്കുക", "account.joined": "{date} ൽ ചേർന്നു", - "account.last_status": "അവസാനം കണ്ടത്", "account.link_verified_on": "ഈ ലിങ്കിന്റെ ഉടമസ്തത {date} ഇൽ ഉറപ്പാക്കിയതാണ്", "account.locked_info": "ഈ അംഗത്വത്തിന്റെ സ്വകാര്യതാ നിലപാട് അനുസരിച്ച് പിന്തുടരുന്നവരെ തിരഞ്ഞെടുക്കാനുള്ള വിവേചനാധികാരം ഉടമസ്ഥനിൽ നിഷിപ്തമായിരിക്കുന്നു.", "account.media": "മീഡിയ", @@ -32,7 +32,6 @@ "account.mute": "@{name}-നെ(യെ) നിശ്ശബ്ദമാക്കൂ", "account.mute_notifications": "@{name} യിൽ നിന്നുള്ള അറിയിപ്പുകൾ നിശബ്ദമാക്കുക", "account.muted": "നിശ്ശബ്ദമാക്കിയിരിക്കുന്നു", - "account.never_active": "ഒരിക്കലും ഇല്ല", "account.posts": "പോസ്റ്റുകൾ", "account.posts_with_replies": "പോസ്റ്റുകളും മറുപടികളും", "account.report": "റിപ്പോർട്ട് ചെയ്യുക @{name}", @@ -42,10 +41,12 @@ "account.statuses_counter": "{count, plural, one {{counter} ടൂട്ട്} other {{counter} ടൂട്ടുകൾ}}", "account.unblock": "@{name} തടഞ്ഞത് മാറ്റുക", "account.unblock_domain": "{domain} എന്ന മേഖല വെളിപ്പെടുത്തുക", + "account.unblock_short": "Unblock", "account.unendorse": "പ്രൊഫൈലിൽ പ്രകടമാക്കരുത്", "account.unfollow": "പിന്തുടരുന്നത് നിര്‍ത്തുക", "account.unmute": "നിശ്ശബ്ദമാക്കുന്നത് നിർത്തുക @{name}", "account.unmute_notifications": "@{name} യിൽ നിന്നുള്ള അറിയിപ്പുകൾ പ്രസിദ്ധപ്പെടുത്തുക", + "account.unmute_short": "Unmute", "account_note.placeholder": "കുറിപ്പ് ചേർക്കാൻ ക്ലിക്കുചെയ്യുക", "admin.dashboard.daily_retention": "User retention rate by day after sign-up", "admin.dashboard.monthly_retention": "User retention rate by month after sign-up", diff --git a/app/javascript/mastodon/locales/mr.json b/app/javascript/mastodon/locales/mr.json index 9bbd247776..213c6c80dc 100644 --- a/app/javascript/mastodon/locales/mr.json +++ b/app/javascript/mastodon/locales/mr.json @@ -18,12 +18,12 @@ "account.followers": "अनुयायी", "account.followers.empty": "ह्या वापरकर्त्याचा आतापर्यंत कोणी अनुयायी नाही.", "account.followers_counter": "{count, plural, one {{counter} Follower} other {{counter} Followers}}", + "account.following": "Following", "account.following_counter": "{count, plural, one {{counter} Following} other {{counter} Following}}", "account.follows.empty": "हा वापरकर्ता अजूनपर्यंत कोणाचा अनुयायी नाही.", "account.follows_you": "तुमचा अनुयायी आहे", "account.hide_reblogs": "@{name} पासून सर्व बूस्ट लपवा", "account.joined": "Joined {date}", - "account.last_status": "शेवटचे सक्रिय", "account.link_verified_on": "Ownership of this link was checked on {date}", "account.locked_info": "This account privacy status is set to locked. The owner manually reviews who can follow them.", "account.media": "दृक्‌‌श्राव्य मजकूर", @@ -32,7 +32,6 @@ "account.mute": "@{name} ला मूक कारा", "account.mute_notifications": "Mute notifications from @{name}", "account.muted": "Muted", - "account.never_active": "Never", "account.posts": "Toots", "account.posts_with_replies": "Toots and replies", "account.report": "Report @{name}", @@ -42,10 +41,12 @@ "account.statuses_counter": "{count, plural, one {{counter} Toot} other {{counter} Toots}}", "account.unblock": "@{name} ला ब्लॉक करा", "account.unblock_domain": "उघड करा {domain}", + "account.unblock_short": "Unblock", "account.unendorse": "Don't feature on profile", "account.unfollow": "अनुयायी असणे थांबवा", "account.unmute": "Unmute @{name}", "account.unmute_notifications": "Unmute notifications from @{name}", + "account.unmute_short": "Unmute", "account_note.placeholder": "Click to add a note", "admin.dashboard.daily_retention": "User retention rate by day after sign-up", "admin.dashboard.monthly_retention": "User retention rate by month after sign-up", diff --git a/app/javascript/mastodon/locales/ms.json b/app/javascript/mastodon/locales/ms.json index 42dd341315..7b79d38a54 100644 --- a/app/javascript/mastodon/locales/ms.json +++ b/app/javascript/mastodon/locales/ms.json @@ -18,12 +18,12 @@ "account.followers": "Pengikut", "account.followers.empty": "Belum ada yang mengikuti pengguna ini.", "account.followers_counter": "{count, plural, one {{counter} Pengikut} other {{counter} Pengikut}}", + "account.following": "Following", "account.following_counter": "{count, plural, one {{counter} Diikuti} other {{counter} Diikuti}}", "account.follows.empty": "Pengguna ini belum mengikuti sesiapa.", "account.follows_you": "Mengikuti anda", "account.hide_reblogs": "Sembunyikan galakan daripada @{name}", "account.joined": "Sertai pada {date}", - "account.last_status": "Terakhir aktif", "account.link_verified_on": "Pemilikan pautan ini telah disemak pada {date}", "account.locked_info": "Status privasi akaun ini dikunci. Pemiliknya menyaring sendiri siapa yang boleh mengikutinya.", "account.media": "Media", @@ -32,7 +32,6 @@ "account.mute": "Bisukan @{name}", "account.mute_notifications": "Bisukan pemberitahuan daripada @{name}", "account.muted": "Dibisukan", - "account.never_active": "Jangan sesekali", "account.posts": "Hantaran", "account.posts_with_replies": "Hantaran dan balasan", "account.report": "Laporkan @{name}", @@ -42,10 +41,12 @@ "account.statuses_counter": "{count, plural, one {{counter} Hantaran} other {{counter} Hantaran}}", "account.unblock": "Nyahsekat @{name}", "account.unblock_domain": "Nyahsekat domain {domain}", + "account.unblock_short": "Unblock", "account.unendorse": "Jangan tampilkan di profil", "account.unfollow": "Nyahikut", "account.unmute": "Nyahbisukan @{name}", "account.unmute_notifications": "Nyahbisukan pemberitahuan daripada @{name}", + "account.unmute_short": "Unmute", "account_note.placeholder": "Klik untuk tambah catatan", "admin.dashboard.daily_retention": "User retention rate by day after sign-up", "admin.dashboard.monthly_retention": "User retention rate by month after sign-up", diff --git a/app/javascript/mastodon/locales/nl.json b/app/javascript/mastodon/locales/nl.json index 4ad3335a3d..4ab0d3b640 100644 --- a/app/javascript/mastodon/locales/nl.json +++ b/app/javascript/mastodon/locales/nl.json @@ -18,12 +18,12 @@ "account.followers": "Volgers", "account.followers.empty": "Niemand volgt nog deze gebruiker.", "account.followers_counter": "{count, plural, one {{counter} volger} other {{counter} volgers}}", + "account.following": "Following", "account.following_counter": "{count, plural, one {{counter} volgend} other {{counter} volgend}}", "account.follows.empty": "Deze gebruiker volgt nog niemand.", "account.follows_you": "Volgt jou", "account.hide_reblogs": "Boosts van @{name} verbergen", "account.joined": "Geregistreerd in {date}", - "account.last_status": "Laatst actief", "account.link_verified_on": "Eigendom van deze link is gecontroleerd op {date}", "account.locked_info": "De privacystatus van dit account is op besloten gezet. De eigenaar bepaalt handmatig wie hen kan volgen.", "account.media": "Media", @@ -32,7 +32,6 @@ "account.mute": "@{name} negeren", "account.mute_notifications": "Meldingen van @{name} negeren", "account.muted": "Genegeerd", - "account.never_active": "Nooit", "account.posts": "Toots", "account.posts_with_replies": "Toots en reacties", "account.report": "@{name} rapporteren", @@ -42,10 +41,12 @@ "account.statuses_counter": "{count, plural, one {{counter} toot} other {{counter} toots}}", "account.unblock": "@{name} deblokkeren", "account.unblock_domain": "{domain} niet langer verbergen", + "account.unblock_short": "Unblock", "account.unendorse": "Niet op profiel weergeven", "account.unfollow": "Ontvolgen", "account.unmute": "@{name} niet langer negeren", "account.unmute_notifications": "Meldingen van @{name} niet langer negeren", + "account.unmute_short": "Unmute", "account_note.placeholder": "Klik om een opmerking toe te voegen", "admin.dashboard.daily_retention": "User retention rate by day after sign-up", "admin.dashboard.monthly_retention": "User retention rate by month after sign-up", diff --git a/app/javascript/mastodon/locales/nn.json b/app/javascript/mastodon/locales/nn.json index 5fdbfd25dc..ddfeb2a974 100644 --- a/app/javascript/mastodon/locales/nn.json +++ b/app/javascript/mastodon/locales/nn.json @@ -18,12 +18,12 @@ "account.followers": "Fylgjarar", "account.followers.empty": "Ingen fylgjer denne brukaren enno.", "account.followers_counter": "{count, plural, one {{counter} fylgjar} other {{counter} fylgjarar}}", + "account.following": "Following", "account.following_counter": "{count, plural, one {{counter} fylgjar} other {{counter} fylgjar}}", "account.follows.empty": "Denne brukaren fylgjer ikkje nokon enno.", "account.follows_you": "Fylgjer deg", "account.hide_reblogs": "Gøym fremhevingar frå @{name}", "account.joined": "Vart med {date}", - "account.last_status": "Sist aktiv", "account.link_verified_on": "Eigarskap for denne lenkja vart sist sjekka {date}", "account.locked_info": "Denne kontoen er privat. Eigaren kan sjølv velja kven som kan fylgja han.", "account.media": "Media", @@ -32,7 +32,6 @@ "account.mute": "Målbind @{name}", "account.mute_notifications": "Målbind varsel frå @{name}", "account.muted": "Målbunden", - "account.never_active": "Aldri", "account.posts": "Tut", "account.posts_with_replies": "Tut og svar", "account.report": "Rapporter @{name}", @@ -42,10 +41,12 @@ "account.statuses_counter": "{count, plural, one {{counter} tut} other {{counter} tut}}", "account.unblock": "Slutt å blokera @{name}", "account.unblock_domain": "Vis {domain}", + "account.unblock_short": "Unblock", "account.unendorse": "Ikkje framhev på profil", "account.unfollow": "Slutt å fylgja", "account.unmute": "Av-demp @{name}", "account.unmute_notifications": "Vis varsel frå @{name}", + "account.unmute_short": "Unmute", "account_note.placeholder": "Klikk for å leggja til merknad", "admin.dashboard.daily_retention": "User retention rate by day after sign-up", "admin.dashboard.monthly_retention": "User retention rate by month after sign-up", diff --git a/app/javascript/mastodon/locales/no.json b/app/javascript/mastodon/locales/no.json index 2b90414f09..896989b143 100644 --- a/app/javascript/mastodon/locales/no.json +++ b/app/javascript/mastodon/locales/no.json @@ -18,12 +18,12 @@ "account.followers": "Følgere", "account.followers.empty": "Ingen følger denne brukeren ennå.", "account.followers_counter": "{count, plural, one {{counter} følger} other {{counter} følgere}}", + "account.following": "Following", "account.following_counter": "{count, plural, one {{counter} som følges} other {{counter} som følges}}", "account.follows.empty": "Denne brukeren følger ikke noen enda.", "account.follows_you": "Følger deg", "account.hide_reblogs": "Skjul fremhevinger fra @{name}", "account.joined": "Ble med den {date}", - "account.last_status": "Sist aktiv", "account.link_verified_on": "Eierskap av denne lenken ble sjekket {date}", "account.locked_info": "Denne kontoens personvernstatus er satt til låst. Eieren vurderer manuelt hvem som kan følge dem.", "account.media": "Media", @@ -32,7 +32,6 @@ "account.mute": "Demp @{name}", "account.mute_notifications": "Ignorer varsler fra @{name}", "account.muted": "Dempet", - "account.never_active": "Aldri", "account.posts": "Innlegg", "account.posts_with_replies": "Toots with replies", "account.report": "Rapportér @{name}", @@ -42,10 +41,12 @@ "account.statuses_counter": "{count, plural, one {{counter} tut} other {{counter} tuter}}", "account.unblock": "Avblokker @{name}", "account.unblock_domain": "Vis {domain}", + "account.unblock_short": "Unblock", "account.unendorse": "Ikke vis frem på profilen", "account.unfollow": "Avfølg", "account.unmute": "Avdemp @{name}", "account.unmute_notifications": "Vis varsler fra @{name}", + "account.unmute_short": "Unmute", "account_note.placeholder": "Klikk for å legge til et notat", "admin.dashboard.daily_retention": "User retention rate by day after sign-up", "admin.dashboard.monthly_retention": "User retention rate by month after sign-up", diff --git a/app/javascript/mastodon/locales/oc.json b/app/javascript/mastodon/locales/oc.json index 282a0aa59f..b1ee0a9779 100644 --- a/app/javascript/mastodon/locales/oc.json +++ b/app/javascript/mastodon/locales/oc.json @@ -18,12 +18,12 @@ "account.followers": "Seguidors", "account.followers.empty": "Degun sèc pas aqueste utilizaire pel moment.", "account.followers_counter": "{count, plural, one {{counter} Seguidor} other {{counter} Seguidors}}", + "account.following": "Following", "account.following_counter": "{count, plural, one {{counter} Abonaments} other {{counter} Abonaments}}", "account.follows.empty": "Aqueste utilizaire sèc pas degun pel moment.", "account.follows_you": "Vos sèc", "account.hide_reblogs": "Rescondre los partatges de @{name}", "account.joined": "Arribèt en {date}", - "account.last_status": "Darrièra activitat", "account.link_verified_on": "La proprietat d’aqueste ligam foguèt verificada lo {date}", "account.locked_info": "L’estatut de privacitat del compte es configurat sus clavat. Lo proprietari causís qual pòt sègre son compte.", "account.media": "Mèdias", @@ -32,7 +32,6 @@ "account.mute": "Rescondre @{name}", "account.mute_notifications": "Rescondre las notificacions de @{name}", "account.muted": "Mes en silenci", - "account.never_active": "Jamai", "account.posts": "Tuts", "account.posts_with_replies": "Tuts e responsas", "account.report": "Senhalar @{name}", @@ -42,10 +41,12 @@ "account.statuses_counter": "{count, plural, one {{counter} Tut} other {{counter} Tuts}}", "account.unblock": "Desblocar @{name}", "account.unblock_domain": "Desblocar {domain}", + "account.unblock_short": "Unblock", "account.unendorse": "Mostrar pas pel perfil", "account.unfollow": "Quitar de sègre", "account.unmute": "Quitar de rescondre @{name}", "account.unmute_notifications": "Mostrar las notificacions de @{name}", + "account.unmute_short": "Unmute", "account_note.placeholder": "Clicar per ajustar una nòta", "admin.dashboard.daily_retention": "User retention rate by day after sign-up", "admin.dashboard.monthly_retention": "User retention rate by month after sign-up", diff --git a/app/javascript/mastodon/locales/pa.json b/app/javascript/mastodon/locales/pa.json index a7e5313a3a..d31ed3fe90 100644 --- a/app/javascript/mastodon/locales/pa.json +++ b/app/javascript/mastodon/locales/pa.json @@ -18,12 +18,12 @@ "account.followers": "Followers", "account.followers.empty": "No one follows this user yet.", "account.followers_counter": "{count, plural, one {{counter} Follower} other {{counter} Followers}}", + "account.following": "Following", "account.following_counter": "{count, plural, one {{counter} Following} other {{counter} Following}}", "account.follows.empty": "This user doesn't follow anyone yet.", "account.follows_you": "Follows you", "account.hide_reblogs": "Hide boosts from @{name}", "account.joined": "Joined {date}", - "account.last_status": "Last active", "account.link_verified_on": "Ownership of this link was checked on {date}", "account.locked_info": "This account privacy status is set to locked. The owner manually reviews who can follow them.", "account.media": "Media", @@ -32,7 +32,6 @@ "account.mute": "Mute @{name}", "account.mute_notifications": "Mute notifications from @{name}", "account.muted": "Muted", - "account.never_active": "Never", "account.posts": "Toots", "account.posts_with_replies": "Toots and replies", "account.report": "Report @{name}", @@ -42,10 +41,12 @@ "account.statuses_counter": "{count, plural, one {{counter} Toot} other {{counter} Toots}}", "account.unblock": "Unblock @{name}", "account.unblock_domain": "Unblock domain {domain}", + "account.unblock_short": "Unblock", "account.unendorse": "Don't feature on profile", "account.unfollow": "Unfollow", "account.unmute": "Unmute @{name}", "account.unmute_notifications": "Unmute notifications from @{name}", + "account.unmute_short": "Unmute", "account_note.placeholder": "Click to add a note", "admin.dashboard.daily_retention": "User retention rate by day after sign-up", "admin.dashboard.monthly_retention": "User retention rate by month after sign-up", diff --git a/app/javascript/mastodon/locales/pl.json b/app/javascript/mastodon/locales/pl.json index 07e88ead2a..481675f5cd 100644 --- a/app/javascript/mastodon/locales/pl.json +++ b/app/javascript/mastodon/locales/pl.json @@ -18,12 +18,12 @@ "account.followers": "Śledzący", "account.followers.empty": "Nikt jeszcze nie śledzi tego użytkownika.", "account.followers_counter": "{count, plural, one {{counter} śledzący} few {{counter} śledzących} many {{counter} śledzących} other {{counter} śledzących}}", + "account.following": "Following", "account.following_counter": "{count, plural, one {{counter} śledzony} few {{counter} śledzonych} many {{counter} śledzonych} other {{counter} śledzonych}}", "account.follows.empty": "Ten użytkownik nie śledzi jeszcze nikogo.", "account.follows_you": "Śledzi Cię", "account.hide_reblogs": "Ukryj podbicia od @{name}", "account.joined": "Dołączył(a) {date}", - "account.last_status": "Ostatnia aktywność", "account.link_verified_on": "Własność tego odnośnika została potwierdzona {date}", "account.locked_info": "To konto jest prywatne. Właściciel ręcznie wybiera kto może go śledzić.", "account.media": "Zawartość multimedialna", @@ -32,7 +32,6 @@ "account.mute": "Wycisz @{name}", "account.mute_notifications": "Wycisz powiadomienia o @{name}", "account.muted": "Wyciszony", - "account.never_active": "Nigdy", "account.posts": "Wpisy", "account.posts_with_replies": "Wpisy i odpowiedzi", "account.report": "Zgłoś @{name}", @@ -42,10 +41,12 @@ "account.statuses_counter": "{count, plural, one {{counter} wpis} few {{counter} wpisy} many {{counter} wpisów} other {{counter} wpisów}}", "account.unblock": "Odblokuj @{name}", "account.unblock_domain": "Odblokuj domenę {domain}", + "account.unblock_short": "Unblock", "account.unendorse": "Przestań polecać", "account.unfollow": "Przestań śledzić", "account.unmute": "Cofnij wyciszenie @{name}", "account.unmute_notifications": "Cofnij wyciszenie powiadomień od @{name}", + "account.unmute_short": "Unmute", "account_note.placeholder": "Naciśnij aby dodać notatkę", "admin.dashboard.daily_retention": "User retention rate by day after sign-up", "admin.dashboard.monthly_retention": "User retention rate by month after sign-up", diff --git a/app/javascript/mastodon/locales/pt-BR.json b/app/javascript/mastodon/locales/pt-BR.json index 66410b252c..d23b5bfda8 100644 --- a/app/javascript/mastodon/locales/pt-BR.json +++ b/app/javascript/mastodon/locales/pt-BR.json @@ -18,12 +18,12 @@ "account.followers": "Seguidores", "account.followers.empty": "Nada aqui.", "account.followers_counter": "{count, plural, one {{counter} seguidor} other {{counter} seguidores}}", + "account.following": "Following", "account.following_counter": "{count, plural, one {segue {counter}} other {segue {counter}}}", "account.follows.empty": "Nada aqui.", "account.follows_you": "te segue", "account.hide_reblogs": "Ocultar boosts de @{name}", "account.joined": "Entrou em {date}", - "account.last_status": "Ativo pela última vez", "account.link_verified_on": "link verificado em {date}", "account.locked_info": "Trancado. Seguir requer aprovação manual do perfil.", "account.media": "Mídia", @@ -32,7 +32,6 @@ "account.mute": "Silenciar @{name}", "account.mute_notifications": "Ocultar notificações de @{name}", "account.muted": "Silenciado", - "account.never_active": "Nunca", "account.posts": "Toots", "account.posts_with_replies": "Com respostas", "account.report": "Denunciar @{name}", @@ -42,10 +41,12 @@ "account.statuses_counter": "{count, plural, one {{counter} Toot} other {{counter} Toots}}", "account.unblock": "Desbloquear @{name}", "account.unblock_domain": "Desbloquear domínio {domain}", + "account.unblock_short": "Unblock", "account.unendorse": "Remover", "account.unfollow": "Deixar de seguir", "account.unmute": "Dessilenciar @{name}", "account.unmute_notifications": "Mostrar notificações de @{name}", + "account.unmute_short": "Unmute", "account_note.placeholder": "Nota pessoal sobre este perfil aqui", "admin.dashboard.daily_retention": "User retention rate by day after sign-up", "admin.dashboard.monthly_retention": "Taxa de retenção de usuários por mês, após a inscrição", diff --git a/app/javascript/mastodon/locales/pt-PT.json b/app/javascript/mastodon/locales/pt-PT.json index 48e1fb0441..d36e2d0efe 100644 --- a/app/javascript/mastodon/locales/pt-PT.json +++ b/app/javascript/mastodon/locales/pt-PT.json @@ -18,12 +18,12 @@ "account.followers": "Seguidores", "account.followers.empty": "Ainda ninguém segue este utilizador.", "account.followers_counter": "{count, plural, one {{counter} Seguidor} other {{counter} Seguidores}}", + "account.following": "Following", "account.following_counter": "{count, plural, other {A seguir {counter}}}", "account.follows.empty": "Este utilizador ainda não segue ninguém.", "account.follows_you": "Segue-te", "account.hide_reblogs": "Esconder partilhas de @{name}", "account.joined": "Ingressou em {date}", - "account.last_status": "Última atividade", "account.link_verified_on": "A posse deste link foi verificada em {date}", "account.locked_info": "Esta conta é privada. O proprietário revê manualmente quem a pode seguir.", "account.media": "Média", @@ -32,7 +32,6 @@ "account.mute": "Silenciar @{name}", "account.mute_notifications": "Silenciar notificações de @{name}", "account.muted": "Silenciada", - "account.never_active": "Nunca", "account.posts": "Toots", "account.posts_with_replies": "Publicações e respostas", "account.report": "Denunciar @{name}", @@ -42,10 +41,12 @@ "account.statuses_counter": "{count, plural, one {{counter} Toot} other {{counter} Toots}}", "account.unblock": "Desbloquear @{name}", "account.unblock_domain": "Mostrar {domain}", + "account.unblock_short": "Unblock", "account.unendorse": "Não mostrar no perfil", "account.unfollow": "Deixar de seguir", "account.unmute": "Não silenciar @{name}", "account.unmute_notifications": "Deixar de silenciar @{name}", + "account.unmute_short": "Unmute", "account_note.placeholder": "Clique para adicionar nota", "admin.dashboard.daily_retention": "Taxa de retenção de utilizadores por dia após a inscrição", "admin.dashboard.monthly_retention": "Taxa de retenção de utilizadores por mês após a inscrição", diff --git a/app/javascript/mastodon/locales/ro.json b/app/javascript/mastodon/locales/ro.json index 6e3ee6c2f1..aed16677e8 100644 --- a/app/javascript/mastodon/locales/ro.json +++ b/app/javascript/mastodon/locales/ro.json @@ -18,12 +18,12 @@ "account.followers": "Abonați", "account.followers.empty": "Acest utilizator încă nu are abonați.", "account.followers_counter": "{count, plural, one {{counter} Abonat} few {{counter} Abonați} other {{counter} Abonați}}", + "account.following": "Following", "account.following_counter": "{count, plural, one {{counter} Abonament} few {{counter} Abonamente} other {{counter} Abonamente}}", "account.follows.empty": "Momentan acest utilizator nu are niciun abonament.", "account.follows_you": "Este abonat la tine", "account.hide_reblogs": "Ascunde distribuirile de la @{name}", "account.joined": "S-a înscris în {date}", - "account.last_status": "Ultima activitate", "account.link_verified_on": "Proprietatea acestui link a fost verificată pe {date}", "account.locked_info": "Acest profil este privat. Această persoană aprobă manual conturile care se abonează la ea.", "account.media": "Media", @@ -32,7 +32,6 @@ "account.mute": "Ignoră pe @{name}", "account.mute_notifications": "Ignoră notificările de la @{name}", "account.muted": "Ignorat", - "account.never_active": "Niciodată", "account.posts": "Postări", "account.posts_with_replies": "Postări și răspunsuri", "account.report": "Raportează pe @{name}", @@ -42,10 +41,12 @@ "account.statuses_counter": "{count, plural, one {{counter} Toot} other {{counter} Toots}}", "account.unblock": "Deblochează pe @{name}", "account.unblock_domain": "Deblochează domeniul {domain}", + "account.unblock_short": "Unblock", "account.unendorse": "Nu promova pe profil", "account.unfollow": "Nu mai urmări", "account.unmute": "Nu mai ignora pe @{name}", "account.unmute_notifications": "Activează notificările de la @{name}", + "account.unmute_short": "Unmute", "account_note.placeholder": "Click to add a note", "admin.dashboard.daily_retention": "User retention rate by day after sign-up", "admin.dashboard.monthly_retention": "User retention rate by month after sign-up", diff --git a/app/javascript/mastodon/locales/ru.json b/app/javascript/mastodon/locales/ru.json index 9cbd82f5c3..cacfac23a0 100644 --- a/app/javascript/mastodon/locales/ru.json +++ b/app/javascript/mastodon/locales/ru.json @@ -18,12 +18,12 @@ "account.followers": "Подписчики", "account.followers.empty": "На этого пользователя пока никто не подписан.", "account.followers_counter": "{count, plural, one {{counter} подписчик} many {{counter} подписчиков} other {{counter} подписчика}}", + "account.following": "Following", "account.following_counter": "{count, plural, one {{counter} подписка} many {{counter} подписок} other {{counter} подписки}}", "account.follows.empty": "Этот пользователь пока ни на кого не подписался.", "account.follows_you": "Подписан(а) на вас", "account.hide_reblogs": "Скрыть продвижения от @{name}", "account.joined": "Зарегистрирован(а) с {date}", - "account.last_status": "Последняя активность", "account.link_verified_on": "Владение этой ссылкой было проверено {date}", "account.locked_info": "Это закрытый аккаунт. Его владелец вручную одобряет подписчиков.", "account.media": "Медиа", @@ -32,7 +32,6 @@ "account.mute": "Игнорировать @{name}", "account.mute_notifications": "Скрыть уведомления от @{name}", "account.muted": "Игнорируется", - "account.never_active": "Никогда", "account.posts": "Посты", "account.posts_with_replies": "Посты и ответы", "account.report": "Пожаловаться на @{name}", @@ -42,10 +41,12 @@ "account.statuses_counter": "{count, plural, one {{counter} пост} many {{counter} постов} other {{counter} поста}}", "account.unblock": "Разблокировать @{name}", "account.unblock_domain": "Разблокировать {domain}", + "account.unblock_short": "Unblock", "account.unendorse": "Не рекомендовать в профиле", "account.unfollow": "Отписаться", "account.unmute": "Убрать {name} из игнорируемых", "account.unmute_notifications": "Показывать уведомления от @{name}", + "account.unmute_short": "Unmute", "account_note.placeholder": "Текст заметки", "admin.dashboard.daily_retention": "Уровень удержания пользователей после регистрации, в днях", "admin.dashboard.monthly_retention": "Уровень удержания пользователей после регистрации, в месяцах", diff --git a/app/javascript/mastodon/locales/sa.json b/app/javascript/mastodon/locales/sa.json index 3be5b50125..d94bf8c314 100644 --- a/app/javascript/mastodon/locales/sa.json +++ b/app/javascript/mastodon/locales/sa.json @@ -18,12 +18,12 @@ "account.followers": "अनुसर्तारः", "account.followers.empty": "नाऽनुसर्तारो वर्तन्ते", "account.followers_counter": "{count, plural, one {{counter} अनुसर्ता} two {{counter} अनुसर्तारौ} other {{counter} अनुसर्तारः}}", + "account.following": "Following", "account.following_counter": "{count, plural, one {{counter} अनुसृतः} two {{counter} अनुसृतौ} other {{counter} अनुसृताः}}", "account.follows.empty": "न कोऽप्यनुसृतो वर्तते", "account.follows_you": "त्वामनुसरति", "account.hide_reblogs": "@{name} मित्रस्य प्रकाशनानि छिद्यन्ताम्", "account.joined": "Joined {date}", - "account.last_status": "गतसक्रियता", "account.link_verified_on": "अन्तर्जालस्थानस्यास्य स्वामित्वं परीक्षितमासीत् {date} दिने", "account.locked_info": "एतस्या लेखायाः गुह्यता \"निषिद्ध\"इति वर्तते । स्वामी स्वयञ्चिनोति कोऽनुसर्ता भवितुमर्हतीति ।", "account.media": "सामग्री", @@ -32,7 +32,6 @@ "account.mute": "निःशब्दम् @{name}", "account.mute_notifications": "@{name} सूचनाः निष्क्रियन्ताम्", "account.muted": "निःशब्दम्", - "account.never_active": "नैव कदापि", "account.posts": "दौत्यानि", "account.posts_with_replies": "दौत्यानि प्रत्युत्तराणि च", "account.report": "आविद्यताम् @{name}", @@ -42,10 +41,12 @@ "account.statuses_counter": "{count, plural, one {{counter} दौत्यम्} two {{counter} दौत्ये} other {{counter} दौत्यानि}}", "account.unblock": "निषेधता नश्यताम् @{name}", "account.unblock_domain": "प्रदेशनिषेधता नश्यताम् {domain}", + "account.unblock_short": "Unblock", "account.unendorse": "व्यक्तिगतविवरणे मा प्रकाश्यताम्", "account.unfollow": "नश्यतामनुसरणम्", "account.unmute": "सशब्दम् @{name}", "account.unmute_notifications": "@{name} सूचनाः सक्रियन्ताम्", + "account.unmute_short": "Unmute", "account_note.placeholder": "टीकायोजनार्थं नुद्यताम्", "admin.dashboard.daily_retention": "User retention rate by day after sign-up", "admin.dashboard.monthly_retention": "User retention rate by month after sign-up", diff --git a/app/javascript/mastodon/locales/sc.json b/app/javascript/mastodon/locales/sc.json index cdc001ba8f..0f77e776b2 100644 --- a/app/javascript/mastodon/locales/sc.json +++ b/app/javascript/mastodon/locales/sc.json @@ -18,12 +18,12 @@ "account.followers": "Sighiduras", "account.followers.empty": "Nemos sighit ancora custa persone.", "account.followers_counter": "{count, plural, one {{counter} sighidura} other {{counter} sighiduras}}", + "account.following": "Following", "account.following_counter": "{count, plural, one {Sighende a {counter}} other {Sighende a {counter}}}", "account.follows.empty": "Custa persone non sighit ancora a nemos.", "account.follows_you": "Ti sighit", "account.hide_reblogs": "Cua is cumpartziduras de @{name}", "account.joined": "At aderidu su {date}", - "account.last_status": "Ùrtima atividade", "account.link_verified_on": "Sa propiedade de custu ligòngiu est istada controllada su {date}", "account.locked_info": "S'istadu de riservadesa de custu contu est istadu cunfiguradu comente blocadu. Sa persone chi tenet sa propiedade revisionat a manu chie dda podet sighire.", "account.media": "Cuntenutu multimediale", @@ -32,7 +32,6 @@ "account.mute": "Pone a @{name} a sa muda", "account.mute_notifications": "Disativa is notìficas de @{name}", "account.muted": "A sa muda", - "account.never_active": "Mai", "account.posts": "Publicatziones", "account.posts_with_replies": "Publicatziones e rispostas", "account.report": "Signala @{name}", @@ -42,10 +41,12 @@ "account.statuses_counter": "{count, plural, one {{counter} publicatzione} other {{counter} publicatziones}}", "account.unblock": "Isbloca a @{name}", "account.unblock_domain": "Isbloca su domìniu {domain}", + "account.unblock_short": "Unblock", "account.unendorse": "Non cussiges in su profilu", "account.unfollow": "Non sigas prus", "account.unmute": "Torra a ativare a @{name}", "account.unmute_notifications": "Ativa notìficas pro @{name}", + "account.unmute_short": "Unmute", "account_note.placeholder": "Incarca pro agiùnghere una nota", "admin.dashboard.daily_retention": "User retention rate by day after sign-up", "admin.dashboard.monthly_retention": "User retention rate by month after sign-up", diff --git a/app/javascript/mastodon/locales/si.json b/app/javascript/mastodon/locales/si.json index dc513c8a1b..bec751ac70 100644 --- a/app/javascript/mastodon/locales/si.json +++ b/app/javascript/mastodon/locales/si.json @@ -18,12 +18,12 @@ "account.followers": "Followers", "account.followers.empty": "No one follows this user yet.", "account.followers_counter": "{count, plural, one {{counter} Follower} other {{counter} Followers}}", + "account.following": "Following", "account.following_counter": "{count, plural, one {{counter} Following} other {{counter} Following}}", "account.follows.empty": "This user doesn't follow anyone yet.", "account.follows_you": "Follows you", "account.hide_reblogs": "Hide boosts from @{name}", "account.joined": "{date} එක් වී ඇත", - "account.last_status": "අවසන් වරට සක්‍රීය", "account.link_verified_on": "මෙම සබැඳියේ හිමිකාරිත්වය {date} දින පරීක්ෂා කරන ලදි", "account.locked_info": "This account privacy status is set to locked. The owner manually reviews who can follow them.", "account.media": "මාධ්‍යය", @@ -32,7 +32,6 @@ "account.mute": "@{name} නිහඬ කරන්න", "account.mute_notifications": "Mute notifications from @{name}", "account.muted": "Muted", - "account.never_active": "Never", "account.posts": "Toots", "account.posts_with_replies": "Toots and replies", "account.report": "@{name} වාර්තා කරන්න", @@ -42,10 +41,12 @@ "account.statuses_counter": "{count, plural, one {{counter} Toot} other {{counter} Toots}}", "account.unblock": "@{name} අනවහිර කරන්න", "account.unblock_domain": "{domain} වසම අනවහිර කරන්න", + "account.unblock_short": "Unblock", "account.unendorse": "පැතිකඩෙහි විශේෂාංග නොකරන්න", "account.unfollow": "Unfollow", "account.unmute": "Unmute @{name}", "account.unmute_notifications": "Unmute notifications from @{name}", + "account.unmute_short": "Unmute", "account_note.placeholder": "සටහන එකතු කිරීමට ක්ලික් කරන්න", "admin.dashboard.daily_retention": "User retention rate by day after sign-up", "admin.dashboard.monthly_retention": "User retention rate by month after sign-up", diff --git a/app/javascript/mastodon/locales/sk.json b/app/javascript/mastodon/locales/sk.json index 3c3ca14b46..deb9ffafc6 100644 --- a/app/javascript/mastodon/locales/sk.json +++ b/app/javascript/mastodon/locales/sk.json @@ -18,12 +18,12 @@ "account.followers": "Sledujúci", "account.followers.empty": "Tohto používateľa ešte nikto nenásleduje.", "account.followers_counter": "{count, plural, one {{counter} Sledujúci} few {{counter} Sledujúci} many {{counter} Sledujúci} other {{counter} Sledujúci}}", + "account.following": "Following", "account.following_counter": "{count, plural, one {{counter} Following} other {{counter} Following}}", "account.follows.empty": "Tento používateľ ešte nikoho nenasleduje.", "account.follows_you": "Nasleduje ťa", "account.hide_reblogs": "Skry vyzdvihnutia od @{name}", "account.joined": "Pridal/a sa v {date}", - "account.last_status": "Naposledy aktívny", "account.link_verified_on": "Vlastníctvo tohto odkazu bolo skontrolované {date}", "account.locked_info": "Stav súkromia pre tento účet je nastavený na zamknutý. Jeho vlastník sám prehodnocuje, kto ho môže sledovať.", "account.media": "Médiá", @@ -32,7 +32,6 @@ "account.mute": "Nevšímaj si @{name}", "account.mute_notifications": "Stĺm oboznámenia od @{name}", "account.muted": "Utíšený/á", - "account.never_active": "Nikdy", "account.posts": "Príspevky", "account.posts_with_replies": "Príspevky, aj s odpoveďami", "account.report": "Nahlás @{name}", @@ -42,10 +41,12 @@ "account.statuses_counter": "{count, plural, one {{counter} Toot} other {{counter} Toots}}", "account.unblock": "Odblokuj @{name}", "account.unblock_domain": "Prestaň skrývať {domain}", + "account.unblock_short": "Unblock", "account.unendorse": "Nezobrazuj na profile", "account.unfollow": "Prestaň následovať", "account.unmute": "Prestaň ignorovať @{name}", "account.unmute_notifications": "Zruš stĺmenie oboznámení od @{name}", + "account.unmute_short": "Unmute", "account_note.placeholder": "Klikni pre vloženie poznámky", "admin.dashboard.daily_retention": "User retention rate by day after sign-up", "admin.dashboard.monthly_retention": "User retention rate by month after sign-up", diff --git a/app/javascript/mastodon/locales/sl.json b/app/javascript/mastodon/locales/sl.json index d4475760be..a9c68d8cdd 100644 --- a/app/javascript/mastodon/locales/sl.json +++ b/app/javascript/mastodon/locales/sl.json @@ -18,12 +18,12 @@ "account.followers": "Sledilci", "account.followers.empty": "Nihče ne sledi temu uporabniku.", "account.followers_counter": "{count, plural, one {ima {count} sledilca} two {ima {count} sledilca} few {ima {count} sledilcev} other {ima {count} sledilce}}", + "account.following": "Following", "account.following_counter": "{count, plural, one {sledi {count} osebi} two {sledi {count} osebama} few {sledi {count} osebam} other {sledi {count} osebam}}", "account.follows.empty": "Ta uporabnik še ne sledi nikomur.", "account.follows_you": "Vam sledi", "account.hide_reblogs": "Skrij spodbude od @{name}", "account.joined": "Pridružen/a {date}", - "account.last_status": "Zadnja dejavnost", "account.link_verified_on": "Lastništvo te povezave je bilo preverjeno {date}", "account.locked_info": "Stanje zasebnosti računa je nastavljeno na zaklenjeno. Lastnik ročno pregleda, kdo ga lahko spremlja.", "account.media": "Mediji", @@ -32,7 +32,6 @@ "account.mute": "Utišaj @{name}", "account.mute_notifications": "Utišaj obvestila od @{name}", "account.muted": "Utišan", - "account.never_active": "Nikoli", "account.posts": "Tuti", "account.posts_with_replies": "Tuti in odgovori", "account.report": "Prijavi @{name}", @@ -42,10 +41,12 @@ "account.statuses_counter": "{count, plural, one {{counter} Toot} other {{counter} Toots}}", "account.unblock": "Odblokiraj @{name}", "account.unblock_domain": "Razkrij {domain}", + "account.unblock_short": "Unblock", "account.unendorse": "Ne vključi v profil", "account.unfollow": "Prenehaj slediti", "account.unmute": "Odtišaj @{name}", "account.unmute_notifications": "Vklopi obvestila od @{name}", + "account.unmute_short": "Unmute", "account_note.placeholder": "Click to add a note", "admin.dashboard.daily_retention": "User retention rate by day after sign-up", "admin.dashboard.monthly_retention": "User retention rate by month after sign-up", diff --git a/app/javascript/mastodon/locales/sq.json b/app/javascript/mastodon/locales/sq.json index b3a70dd277..2ce0353235 100644 --- a/app/javascript/mastodon/locales/sq.json +++ b/app/javascript/mastodon/locales/sq.json @@ -18,12 +18,12 @@ "account.followers": "Ndjekës", "account.followers.empty": "Këtë përdorues ende s’e ndjek kush.", "account.followers_counter": "{count, plural, one {{counter} Ndjekës} other {{counter} Ndjekës}}", + "account.following": "Following", "account.following_counter": "{count, plural, one {{counter} i Ndjekur} other {{counter} të Ndjekur}}", "account.follows.empty": "Ky përdorues ende s’ndjek kënd.", "account.follows_you": "Ju ndjek", "account.hide_reblogs": "Fshih përforcime nga @{name}", "account.joined": "U bë pjesë më {date}", - "account.last_status": "Aktiv së fundi më", "account.link_verified_on": "Pronësia e kësaj lidhjeje qe kontrolluar më {date}", "account.locked_info": "Gjendja e privatësisë së kësaj llogarie është caktuar si e kyçur. I zoti merr dorazi në shqyrtim cilët mund ta ndjekin.", "account.media": "Media", @@ -32,7 +32,6 @@ "account.mute": "Heshtoni @{name}", "account.mute_notifications": "Heshtoji njoftimet prej @{name}", "account.muted": "Heshtuar", - "account.never_active": "Kurrë", "account.posts": "Mesazhe", "account.posts_with_replies": "Mesazhe dhe përgjigje", "account.report": "Raportojeni @{name}", @@ -42,10 +41,12 @@ "account.statuses_counter": "{count, plural, one {{counter} Mesazh} other {{counter} Mesazhe}}", "account.unblock": "Zhbllokoje @{name}", "account.unblock_domain": "Zhblloko përkatësinë {domain}", + "account.unblock_short": "Unblock", "account.unendorse": "Mos e përfshi në profil", "account.unfollow": "Resht së ndjekuri", "account.unmute": "Ktheji zërin @{name}", "account.unmute_notifications": "Hiqua ndalimin e shfaqjes njoftimeve nga @{name}", + "account.unmute_short": "Unmute", "account_note.placeholder": "Klikoni për të shtuar shënim", "admin.dashboard.daily_retention": "Shkallë mbajtjeje përdoruesi, në ditë, pas regjistrimit", "admin.dashboard.monthly_retention": "Shkallë mbajtjeje përdoruesi, në muaj, pas regjistrimit", diff --git a/app/javascript/mastodon/locales/sr-Latn.json b/app/javascript/mastodon/locales/sr-Latn.json index 67a21e94dc..fff26e8a4c 100644 --- a/app/javascript/mastodon/locales/sr-Latn.json +++ b/app/javascript/mastodon/locales/sr-Latn.json @@ -18,12 +18,12 @@ "account.followers": "Pratioca", "account.followers.empty": "No one follows this user yet.", "account.followers_counter": "{count, plural, one {{counter} Follower} other {{counter} Followers}}", + "account.following": "Following", "account.following_counter": "{count, plural, one {{counter} Following} other {{counter} Following}}", "account.follows.empty": "This user doesn't follow anyone yet.", "account.follows_you": "Prati Vas", "account.hide_reblogs": "Sakrij podrške koje daje korisnika @{name}", "account.joined": "Joined {date}", - "account.last_status": "Last active", "account.link_verified_on": "Ownership of this link was checked on {date}", "account.locked_info": "This account privacy status is set to locked. The owner manually reviews who can follow them.", "account.media": "Mediji", @@ -32,7 +32,6 @@ "account.mute": "Ućutkaj korisnika @{name}", "account.mute_notifications": "Isključi obaveštenja od korisnika @{name}", "account.muted": "Muted", - "account.never_active": "Never", "account.posts": "Statusa", "account.posts_with_replies": "Toots with replies", "account.report": "Prijavi @{name}", @@ -42,10 +41,12 @@ "account.statuses_counter": "{count, plural, one {{counter} Toot} other {{counter} Toots}}", "account.unblock": "Odblokiraj korisnika @{name}", "account.unblock_domain": "Odblokiraj domen {domain}", + "account.unblock_short": "Unblock", "account.unendorse": "Don't feature on profile", "account.unfollow": "Otprati", "account.unmute": "Ukloni ućutkavanje korisniku @{name}", "account.unmute_notifications": "Uključi nazad obaveštenja od korisnika @{name}", + "account.unmute_short": "Unmute", "account_note.placeholder": "Click to add a note", "admin.dashboard.daily_retention": "User retention rate by day after sign-up", "admin.dashboard.monthly_retention": "User retention rate by month after sign-up", diff --git a/app/javascript/mastodon/locales/sr.json b/app/javascript/mastodon/locales/sr.json index 8eae28d93d..064a2dac88 100644 --- a/app/javascript/mastodon/locales/sr.json +++ b/app/javascript/mastodon/locales/sr.json @@ -18,12 +18,12 @@ "account.followers": "Пратиоци", "account.followers.empty": "Тренутно нико не прати овог корисника.", "account.followers_counter": "{count, plural, one {{counter} пратилац} few {{counter} пратиоца} other {{counter} пратилаца}}", + "account.following": "Following", "account.following_counter": "{count, plural, one {{counter} прати} few {{counter} прати} other {{counter} прати}}", "account.follows.empty": "Корисник тренутно не прати никога.", "account.follows_you": "Прати Вас", "account.hide_reblogs": "Сакриј подршке које даје корисника @{name}", "account.joined": "Придружио/ла се {date}", - "account.last_status": "Последњи пут активан/на", "account.link_verified_on": "Власништво над овом везом је проверено {date}", "account.locked_info": "Статус приватности овог налога је подешен на закључано. Власник ручно прегледа ко га може пратити.", "account.media": "Медији", @@ -32,7 +32,6 @@ "account.mute": "Ућуткај корисника @{name}", "account.mute_notifications": "Искључи обавештења од корисника @{name}", "account.muted": "Ућуткан", - "account.never_active": "Никада", "account.posts": "Трубе", "account.posts_with_replies": "Трубе и одговори", "account.report": "Пријави @{name}", @@ -42,10 +41,12 @@ "account.statuses_counter": "{count, plural, one {{counter} објава} few {{counter} објаве} other {{counter} објава}}", "account.unblock": "Одблокирај корисника @{name}", "account.unblock_domain": "Одблокирај домен {domain}", + "account.unblock_short": "Unblock", "account.unendorse": "Не истичи на налогу", "account.unfollow": "Отпрати", "account.unmute": "Уклони ућуткавање кориснику @{name}", "account.unmute_notifications": "Укључи назад обавештења од корисника @{name}", + "account.unmute_short": "Unmute", "account_note.placeholder": "Click to add a note", "admin.dashboard.daily_retention": "User retention rate by day after sign-up", "admin.dashboard.monthly_retention": "User retention rate by month after sign-up", diff --git a/app/javascript/mastodon/locales/sv.json b/app/javascript/mastodon/locales/sv.json index 09a2f51765..fed4e7bca0 100644 --- a/app/javascript/mastodon/locales/sv.json +++ b/app/javascript/mastodon/locales/sv.json @@ -18,12 +18,12 @@ "account.followers": "Följare", "account.followers.empty": "Ingen följer denna användare än.", "account.followers_counter": "{count, plural, one {{counter} Följare} other {{counter} Följare}}", + "account.following": "Following", "account.following_counter": "{count, plural, one {{counter} Följer} other {{counter} Följer}}", "account.follows.empty": "Denna användare följer inte någon än.", "account.follows_you": "Följer dig", "account.hide_reblogs": "Dölj knuffar från @{name}", "account.joined": "Gick med {date}", - "account.last_status": "Senast aktiv", "account.link_verified_on": "Ägarskap för detta konto kontrollerades den {date}", "account.locked_info": "Detta konto har låst integritetsstatus. Ägaren väljer manuellt vem som kan följa.", "account.media": "Media", @@ -32,7 +32,6 @@ "account.mute": "Tysta @{name}", "account.mute_notifications": "Stäng av notifieringar från @{name}", "account.muted": "Tystad", - "account.never_active": "Aldrig", "account.posts": "Tutningar", "account.posts_with_replies": "Tutningar och svar", "account.report": "Rapportera @{name}", @@ -42,10 +41,12 @@ "account.statuses_counter": "{count, plural,one {{counter} Tuta} other {{counter} Tutor}}", "account.unblock": "Avblockera @{name}", "account.unblock_domain": "Sluta dölja {domain}", + "account.unblock_short": "Unblock", "account.unendorse": "Visa inte på profil", "account.unfollow": "Sluta följ", "account.unmute": "Sluta tysta @{name}", "account.unmute_notifications": "Återaktivera aviseringar från @{name}", + "account.unmute_short": "Unmute", "account_note.placeholder": "Klicka för att lägga till anteckning", "admin.dashboard.daily_retention": "Användarlojalitet per dag efter registrering", "admin.dashboard.monthly_retention": "Användarlojalitet per månad efter registrering", diff --git a/app/javascript/mastodon/locales/szl.json b/app/javascript/mastodon/locales/szl.json index a7e5313a3a..d31ed3fe90 100644 --- a/app/javascript/mastodon/locales/szl.json +++ b/app/javascript/mastodon/locales/szl.json @@ -18,12 +18,12 @@ "account.followers": "Followers", "account.followers.empty": "No one follows this user yet.", "account.followers_counter": "{count, plural, one {{counter} Follower} other {{counter} Followers}}", + "account.following": "Following", "account.following_counter": "{count, plural, one {{counter} Following} other {{counter} Following}}", "account.follows.empty": "This user doesn't follow anyone yet.", "account.follows_you": "Follows you", "account.hide_reblogs": "Hide boosts from @{name}", "account.joined": "Joined {date}", - "account.last_status": "Last active", "account.link_verified_on": "Ownership of this link was checked on {date}", "account.locked_info": "This account privacy status is set to locked. The owner manually reviews who can follow them.", "account.media": "Media", @@ -32,7 +32,6 @@ "account.mute": "Mute @{name}", "account.mute_notifications": "Mute notifications from @{name}", "account.muted": "Muted", - "account.never_active": "Never", "account.posts": "Toots", "account.posts_with_replies": "Toots and replies", "account.report": "Report @{name}", @@ -42,10 +41,12 @@ "account.statuses_counter": "{count, plural, one {{counter} Toot} other {{counter} Toots}}", "account.unblock": "Unblock @{name}", "account.unblock_domain": "Unblock domain {domain}", + "account.unblock_short": "Unblock", "account.unendorse": "Don't feature on profile", "account.unfollow": "Unfollow", "account.unmute": "Unmute @{name}", "account.unmute_notifications": "Unmute notifications from @{name}", + "account.unmute_short": "Unmute", "account_note.placeholder": "Click to add a note", "admin.dashboard.daily_retention": "User retention rate by day after sign-up", "admin.dashboard.monthly_retention": "User retention rate by month after sign-up", diff --git a/app/javascript/mastodon/locales/ta.json b/app/javascript/mastodon/locales/ta.json index 8ea28b9657..bd59ddda89 100644 --- a/app/javascript/mastodon/locales/ta.json +++ b/app/javascript/mastodon/locales/ta.json @@ -18,12 +18,12 @@ "account.followers": "பின்தொடர்பவர்கள்", "account.followers.empty": "இதுவரை யாரும் இந்த பயனரைப் பின்தொடரவில்லை.", "account.followers_counter": "{count, plural, one {{counter} வாசகர்} other {{counter} வாசகர்கள்}}", + "account.following": "Following", "account.following_counter": "{count, plural,one {{counter} சந்தா} other {{counter} சந்தாக்கள்}}", "account.follows.empty": "இந்த பயனர் இதுவரை யாரையும் பின்தொடரவில்லை.", "account.follows_you": "உங்களைப் பின்தொடர்கிறார்", "account.hide_reblogs": "இருந்து ஊக்கியாக மறை @{name}", "account.joined": "Joined {date}", - "account.last_status": "கடைசி செயல்பாடு", "account.link_verified_on": "இந்த இணைப்பை உரிமையாளர் சரிபார்க்கப்பட்டது {date}", "account.locked_info": "இந்தக் கணக்கு தனியுரிமை நிலை பூட்டப்பட்டுள்ளது. அவர்களைப் பின்தொடர்பவர் யார் என்பதை உரிமையாளர் கைமுறையாக மதிப்பாய்வு செய்கிறார்.", "account.media": "ஊடகங்கள்", @@ -32,7 +32,6 @@ "account.mute": "ஊமையான @{name}", "account.mute_notifications": "அறிவிப்புகளை முடக்கு @{name}", "account.muted": "முடக்கியது", - "account.never_active": "எப்போதுமில்லை", "account.posts": "டூட்டுகள்", "account.posts_with_replies": "Toots மற்றும் பதில்கள்", "account.report": "@{name} -ஐப் புகாரளி", @@ -42,10 +41,12 @@ "account.statuses_counter": "{count, plural, one {{counter} டூட்} other {{counter} டூட்டுகள்}}", "account.unblock": "@{name} மீது தடை நீக்குக", "account.unblock_domain": "{domain} ஐ காண்பி", + "account.unblock_short": "Unblock", "account.unendorse": "சுயவிவரத்தில் இடம்பெற வேண்டாம்", "account.unfollow": "பின்தொடர்வதை நிறுத்துக", "account.unmute": "@{name} இன் மீது மௌனத் தடையை நீக்குக", "account.unmute_notifications": "@{name} இலிருந்து அறிவிப்புகளின் மீது மௌனத் தடையை நீக்குக", + "account.unmute_short": "Unmute", "account_note.placeholder": "குறிப்பு ஒன்றை சேர்க்க சொடுக்கவும்", "admin.dashboard.daily_retention": "User retention rate by day after sign-up", "admin.dashboard.monthly_retention": "User retention rate by month after sign-up", diff --git a/app/javascript/mastodon/locales/tai.json b/app/javascript/mastodon/locales/tai.json index 55a62bb550..9c0074184a 100644 --- a/app/javascript/mastodon/locales/tai.json +++ b/app/javascript/mastodon/locales/tai.json @@ -18,12 +18,12 @@ "account.followers": "Followers", "account.followers.empty": "No one follows this user yet.", "account.followers_counter": "{count, plural, one {{counter} Follower} other {{counter} Followers}}", + "account.following": "Following", "account.following_counter": "{count, plural, one {{counter} Following} other {{counter} Following}}", "account.follows.empty": "This user doesn't follow anyone yet.", "account.follows_you": "Follows you", "account.hide_reblogs": "Hide boosts from @{name}", "account.joined": "Joined {date}", - "account.last_status": "Last active", "account.link_verified_on": "Ownership of this link was checked on {date}", "account.locked_info": "This account privacy status is set to locked. The owner manually reviews who can follow them.", "account.media": "Mûi-thé", @@ -32,7 +32,6 @@ "account.mute": "Mute @{name}", "account.mute_notifications": "Mute notifications from @{name}", "account.muted": "Muted", - "account.never_active": "Never", "account.posts": "Toots", "account.posts_with_replies": "Toots and replies", "account.report": "Report @{name}", @@ -42,10 +41,12 @@ "account.statuses_counter": "{count, plural, one {{counter} Toot} other {{counter} Toots}}", "account.unblock": "Unblock @{name}", "account.unblock_domain": "Unblock domain {domain}", + "account.unblock_short": "Unblock", "account.unendorse": "Don't feature on profile", "account.unfollow": "Unfollow", "account.unmute": "Unmute @{name}", "account.unmute_notifications": "Unmute notifications from @{name}", + "account.unmute_short": "Unmute", "account_note.placeholder": "Click to add a note", "admin.dashboard.daily_retention": "User retention rate by day after sign-up", "admin.dashboard.monthly_retention": "User retention rate by month after sign-up", diff --git a/app/javascript/mastodon/locales/te.json b/app/javascript/mastodon/locales/te.json index 40e37d497f..6ac4f1d9bf 100644 --- a/app/javascript/mastodon/locales/te.json +++ b/app/javascript/mastodon/locales/te.json @@ -18,12 +18,12 @@ "account.followers": "అనుచరులు", "account.followers.empty": "ఈ వినియోగదారుడిని ఇంకా ఎవరూ అనుసరించడంలేదు.", "account.followers_counter": "{count, plural, one {{counter} Follower} other {{counter} Followers}}", + "account.following": "Following", "account.following_counter": "{count, plural, one {{counter} Following} other {{counter} Following}}", "account.follows.empty": "ఈ వినియోగదారి ఇంకా ఎవరినీ అనుసరించడంలేదు.", "account.follows_you": "మిమ్మల్ని అనుసరిస్తున్నారు", "account.hide_reblogs": "@{name} నుంచి బూస్ట్ లను దాచిపెట్టు", "account.joined": "Joined {date}", - "account.last_status": "Last active", "account.link_verified_on": "ఈ లంకె యొక్క యాజమాన్యం {date}న పరీక్షించబడింది", "account.locked_info": "ఈ ఖాతా యొక్క గోప్యత స్థితి లాక్ చేయబడి వుంది. ఈ ఖాతాను ఎవరు అనుసరించవచ్చో యజమానే నిర్ణయం తీసుకుంటారు.", "account.media": "మీడియా", @@ -32,7 +32,6 @@ "account.mute": "@{name}ను మ్యూట్ చెయ్యి", "account.mute_notifications": "@{name}నుంచి ప్రకటనలను మ్యూట్ చెయ్యి", "account.muted": "మ్యూట్ అయినవి", - "account.never_active": "Never", "account.posts": "టూట్లు", "account.posts_with_replies": "టూట్లు మరియు ప్రత్యుత్తరములు", "account.report": "@{name}పై ఫిర్యాదుచేయు", @@ -42,10 +41,12 @@ "account.statuses_counter": "{count, plural, one {{counter} Toot} other {{counter} Toots}}", "account.unblock": "@{name}పై బ్లాక్ ను తొలగించు", "account.unblock_domain": "{domain}ను దాచవద్దు", + "account.unblock_short": "Unblock", "account.unendorse": "ప్రొఫైల్లో చూపించవద్దు", "account.unfollow": "అనుసరించవద్దు", "account.unmute": "@{name}పై మ్యూట్ ని తొలగించు", "account.unmute_notifications": "@{name} నుంచి ప్రకటనలపై మ్యూట్ ని తొలగించు", + "account.unmute_short": "Unmute", "account_note.placeholder": "Click to add a note", "admin.dashboard.daily_retention": "User retention rate by day after sign-up", "admin.dashboard.monthly_retention": "User retention rate by month after sign-up", diff --git a/app/javascript/mastodon/locales/th.json b/app/javascript/mastodon/locales/th.json index 1b276c4673..c4e9a3f6f1 100644 --- a/app/javascript/mastodon/locales/th.json +++ b/app/javascript/mastodon/locales/th.json @@ -18,12 +18,12 @@ "account.followers": "ผู้ติดตาม", "account.followers.empty": "ยังไม่มีใครติดตามผู้ใช้นี้", "account.followers_counter": "{count, plural, other {{counter} ผู้ติดตาม}}", + "account.following": "Following", "account.following_counter": "{count, plural, other {{counter} กำลังติดตาม}}", "account.follows.empty": "ผู้ใช้นี้ยังไม่ได้ติดตามใคร", "account.follows_you": "ติดตามคุณ", "account.hide_reblogs": "ซ่อนการดันจาก @{name}", "account.joined": "เข้าร่วมเมื่อ {date}", - "account.last_status": "ใช้งานล่าสุด", "account.link_verified_on": "ตรวจสอบความเป็นเจ้าของของลิงก์นี้เมื่อ {date}", "account.locked_info": "มีการตั้งสถานะความเป็นส่วนตัวของบัญชีนี้เป็นล็อคอยู่ เจ้าของตรวจทานผู้ที่สามารถติดตามเขาด้วยตนเอง", "account.media": "สื่อ", @@ -32,7 +32,6 @@ "account.mute": "ซ่อน @{name}", "account.mute_notifications": "ซ่อนการแจ้งเตือนจาก @{name}", "account.muted": "ซ่อนอยู่", - "account.never_active": "ไม่เลย", "account.posts": "โพสต์", "account.posts_with_replies": "โพสต์และการตอบกลับ", "account.report": "รายงาน @{name}", @@ -42,10 +41,12 @@ "account.statuses_counter": "{count, plural, other {{counter} โพสต์}}", "account.unblock": "เลิกปิดกั้น @{name}", "account.unblock_domain": "เลิกปิดกั้นโดเมน {domain}", + "account.unblock_short": "Unblock", "account.unendorse": "ไม่แนะนำในโปรไฟล์", "account.unfollow": "เลิกติดตาม", "account.unmute": "เลิกซ่อน @{name}", "account.unmute_notifications": "เลิกซ่อนการแจ้งเตือนจาก @{name}", + "account.unmute_short": "Unmute", "account_note.placeholder": "คลิกเพื่อเพิ่มหมายเหตุ", "admin.dashboard.daily_retention": "User retention rate by day after sign-up", "admin.dashboard.monthly_retention": "User retention rate by month after sign-up", diff --git a/app/javascript/mastodon/locales/tr.json b/app/javascript/mastodon/locales/tr.json index 0d7c92f051..d4cee1569a 100644 --- a/app/javascript/mastodon/locales/tr.json +++ b/app/javascript/mastodon/locales/tr.json @@ -18,12 +18,12 @@ "account.followers": "Takipçi", "account.followers.empty": "Henüz kimse bu kullanıcıyı takip etmiyor.", "account.followers_counter": "{count, plural, one {{counter} Takipçi} other {{counter} Takipçi}}", + "account.following": "Following", "account.following_counter": "{count, plural, one {{counter} Takip Edilen} other {{counter} Takip Edilen}}", "account.follows.empty": "Bu kullanıcı henüz kimseyi takip etmiyor.", "account.follows_you": "Seni takip ediyor", "account.hide_reblogs": "@{name} kişisinin boostlarını gizle", "account.joined": "{date} tarihinde katıldı", - "account.last_status": "Son etkinlik", "account.link_verified_on": "Bu bağlantının sahipliği {date} tarihinde kontrol edildi", "account.locked_info": "Bu hesabın gizlilik durumu kilitli olarak ayarlanmış. Sahibi, onu kimin takip edebileceğini elle inceliyor.", "account.media": "Medya", @@ -32,7 +32,6 @@ "account.mute": "@{name} adlı kişiyi sessize al", "account.mute_notifications": "@{name} adlı kişinin bildirimlerini kapat", "account.muted": "Susturuldu", - "account.never_active": "Asla", "account.posts": "Gönderiler", "account.posts_with_replies": "Gönderiler ve yanıtlar", "account.report": "@{name} adlı kişiyi bildir", @@ -42,10 +41,12 @@ "account.statuses_counter": "{count, plural, one {{counter} Gönderi} other {{counter} Gönderi}}", "account.unblock": "@{name} adlı kişinin engelini kaldır", "account.unblock_domain": "{domain} alan adının engelini kaldır", + "account.unblock_short": "Unblock", "account.unendorse": "Profilde gösterme", "account.unfollow": "Takibi bırak", "account.unmute": "@{name} adlı kişinin sesini aç", "account.unmute_notifications": "@{name} adlı kişinin bildirimlerini aç", + "account.unmute_short": "Unmute", "account_note.placeholder": "Not eklemek için tıklayın", "admin.dashboard.daily_retention": "Kayıttan sonra günlük kullanıcı saklama oranı", "admin.dashboard.monthly_retention": "Kayıttan sonra aylık kullanıcı saklama oranı", diff --git a/app/javascript/mastodon/locales/tt.json b/app/javascript/mastodon/locales/tt.json index ebdbdbd6ef..20a4b2ecdb 100644 --- a/app/javascript/mastodon/locales/tt.json +++ b/app/javascript/mastodon/locales/tt.json @@ -18,12 +18,12 @@ "account.followers": "Followers", "account.followers.empty": "No one follows this user yet.", "account.followers_counter": "{count, plural, one {{counter} Follower} other {{counter} Followers}}", + "account.following": "Following", "account.following_counter": "{count, plural, one {{counter} Following} other {{counter} Following}}", "account.follows.empty": "This user doesn't follow anyone yet.", "account.follows_you": "Сезгә язылган", "account.hide_reblogs": "Hide boosts from @{name}", "account.joined": "Joined {date}", - "account.last_status": "Last active", "account.link_verified_on": "Ownership of this link was checked on {date}", "account.locked_info": "This account privacy status is set to locked. The owner manually reviews who can follow them.", "account.media": "Медиа", @@ -32,7 +32,6 @@ "account.mute": "Mute @{name}", "account.mute_notifications": "Mute notifications from @{name}", "account.muted": "Muted", - "account.never_active": "Беркайчан да", "account.posts": "Toots", "account.posts_with_replies": "Toots and replies", "account.report": "Report @{name}", @@ -42,10 +41,12 @@ "account.statuses_counter": "{count, plural, one {{counter} Toot} other {{counter} Toots}}", "account.unblock": "Unblock @{name}", "account.unblock_domain": "Unblock domain {domain}", + "account.unblock_short": "Unblock", "account.unendorse": "Don't feature on profile", "account.unfollow": "Язылынмау", "account.unmute": "Unmute @{name}", "account.unmute_notifications": "Unmute notifications from @{name}", + "account.unmute_short": "Unmute", "account_note.placeholder": "Click to add a note", "admin.dashboard.daily_retention": "User retention rate by day after sign-up", "admin.dashboard.monthly_retention": "User retention rate by month after sign-up", diff --git a/app/javascript/mastodon/locales/ug.json b/app/javascript/mastodon/locales/ug.json index a7e5313a3a..d31ed3fe90 100644 --- a/app/javascript/mastodon/locales/ug.json +++ b/app/javascript/mastodon/locales/ug.json @@ -18,12 +18,12 @@ "account.followers": "Followers", "account.followers.empty": "No one follows this user yet.", "account.followers_counter": "{count, plural, one {{counter} Follower} other {{counter} Followers}}", + "account.following": "Following", "account.following_counter": "{count, plural, one {{counter} Following} other {{counter} Following}}", "account.follows.empty": "This user doesn't follow anyone yet.", "account.follows_you": "Follows you", "account.hide_reblogs": "Hide boosts from @{name}", "account.joined": "Joined {date}", - "account.last_status": "Last active", "account.link_verified_on": "Ownership of this link was checked on {date}", "account.locked_info": "This account privacy status is set to locked. The owner manually reviews who can follow them.", "account.media": "Media", @@ -32,7 +32,6 @@ "account.mute": "Mute @{name}", "account.mute_notifications": "Mute notifications from @{name}", "account.muted": "Muted", - "account.never_active": "Never", "account.posts": "Toots", "account.posts_with_replies": "Toots and replies", "account.report": "Report @{name}", @@ -42,10 +41,12 @@ "account.statuses_counter": "{count, plural, one {{counter} Toot} other {{counter} Toots}}", "account.unblock": "Unblock @{name}", "account.unblock_domain": "Unblock domain {domain}", + "account.unblock_short": "Unblock", "account.unendorse": "Don't feature on profile", "account.unfollow": "Unfollow", "account.unmute": "Unmute @{name}", "account.unmute_notifications": "Unmute notifications from @{name}", + "account.unmute_short": "Unmute", "account_note.placeholder": "Click to add a note", "admin.dashboard.daily_retention": "User retention rate by day after sign-up", "admin.dashboard.monthly_retention": "User retention rate by month after sign-up", diff --git a/app/javascript/mastodon/locales/uk.json b/app/javascript/mastodon/locales/uk.json index e27eb5c214..b1f335a842 100644 --- a/app/javascript/mastodon/locales/uk.json +++ b/app/javascript/mastodon/locales/uk.json @@ -18,12 +18,12 @@ "account.followers": "Підписники", "account.followers.empty": "Ніхто ще не підписався на цього користувача.", "account.followers_counter": "{count, plural, one {{counter} Підписник} few {{counter} Підписники} many {{counter} Підписників} other {{counter} Підписники}}", + "account.following": "Following", "account.following_counter": "{count, plural, one {{counter} Підписка} few {{counter} Підписки} many {{counter} Підписок} other {{counter} Підписки}}", "account.follows.empty": "Цей користувач ще ні на кого не підписався.", "account.follows_you": "Підписаний(-а) на вас", "account.hide_reblogs": "Сховати передмухи від @{name}", "account.joined": "Долучення {date}", - "account.last_status": "Крайня активність", "account.link_verified_on": "Права власності на це посилання були перевірені {date}", "account.locked_info": "Статус конфіденційності цього облікового запису встановлено у заблокований. Власник вручну переглядає, хто може за ним стежити.", "account.media": "Медіа", @@ -32,7 +32,6 @@ "account.mute": "Заглушити @{name}", "account.mute_notifications": "Не показувати сповіщення від @{name}", "account.muted": "Заглушений", - "account.never_active": "Ніколи", "account.posts": "Дмухи", "account.posts_with_replies": "Дмухи й відповіді", "account.report": "Поскаржитися на @{name}", @@ -42,10 +41,12 @@ "account.statuses_counter": "{count, plural, one {{counter} Пост} few {{counter} Пости} many {{counter} Постів} other {{counter} Пости}}", "account.unblock": "Розблокувати @{name}", "account.unblock_domain": "Розблокувати {domain}", + "account.unblock_short": "Unblock", "account.unendorse": "Не публікувати у профілі", "account.unfollow": "Відписатися", "account.unmute": "Зняти глушення з @{name}", "account.unmute_notifications": "Показувати сповіщення від @{name}", + "account.unmute_short": "Unmute", "account_note.placeholder": "Коментарі відсутні", "admin.dashboard.daily_retention": "User retention rate by day after sign-up", "admin.dashboard.monthly_retention": "User retention rate by month after sign-up", diff --git a/app/javascript/mastodon/locales/ur.json b/app/javascript/mastodon/locales/ur.json index 3e71bcc066..9a40cdd47d 100644 --- a/app/javascript/mastodon/locales/ur.json +++ b/app/javascript/mastodon/locales/ur.json @@ -18,12 +18,12 @@ "account.followers": "پیروکار", "account.followers.empty": "\"ہنوز اس صارف کی کوئی پیروی نہیں کرتا\".", "account.followers_counter": "{count, plural,one {{counter} پیروکار} other {{counter} پیروکار}}", + "account.following": "Following", "account.following_counter": "{count, plural, one {{counter} پیروی کر رہے ہیں} other {{counter} پیروی کر رہے ہیں}}", "account.follows.empty": "\"یہ صارف ہنوز کسی کی پیروی نہیں کرتا ہے\".", "account.follows_you": "آپ کا پیروکار ہے", "account.hide_reblogs": "@{name} سے فروغ چھپائیں", "account.joined": "{date} شامل ہوئے", - "account.last_status": "آخری فعال", "account.link_verified_on": "اس لنک کی ملکیت کی توثیق {date} پر کی گئی تھی", "account.locked_info": "اس اکاونٹ کا اخفائی ضابطہ مقفل ہے۔ صارف کی پیروی کون کر سکتا ہے اس کا جائزہ وہ خود لیتا ہے.", "account.media": "وسائل", @@ -32,7 +32,6 @@ "account.mute": "خاموش @{name}", "account.mute_notifications": "@{name} سے اطلاعات خاموش کریں", "account.muted": "خاموش کردہ", - "account.never_active": "کبھی نہیں", "account.posts": "ٹوٹ", "account.posts_with_replies": "ٹوٹ اور جوابات", "account.report": "@{name} اطلاع کریں", @@ -42,10 +41,12 @@ "account.statuses_counter": "{count, plural, one {{counter} Toot} other {{counter} Toots}}", "account.unblock": "@{name} کو بحال کریں", "account.unblock_domain": "{domain} کو نہ چھپائیں", + "account.unblock_short": "Unblock", "account.unendorse": "مشخص پر نمایاں نہ کریں", "account.unfollow": "پیروی ترک کریں", "account.unmute": "@{name} کو با آواز کریں", "account.unmute_notifications": "@{name} سے اطلاعات کو با آواز کریں", + "account.unmute_short": "Unmute", "account_note.placeholder": "Click to add a note", "admin.dashboard.daily_retention": "User retention rate by day after sign-up", "admin.dashboard.monthly_retention": "User retention rate by month after sign-up", diff --git a/app/javascript/mastodon/locales/vi.json b/app/javascript/mastodon/locales/vi.json index ab777e31e4..217cd3861b 100644 --- a/app/javascript/mastodon/locales/vi.json +++ b/app/javascript/mastodon/locales/vi.json @@ -18,12 +18,12 @@ "account.followers": "Người theo dõi", "account.followers.empty": "Chưa có người theo dõi nào.", "account.followers_counter": "{count, plural, one {{counter} Người theo dõi} other {{counter} Người theo dõi}}", + "account.following": "Following", "account.following_counter": "{count, plural, one {{counter} Theo dõi} other {{counter} Theo dõi}}", "account.follows.empty": "Người này chưa theo dõi ai.", "account.follows_you": "Đang theo dõi bạn", "account.hide_reblogs": "Ẩn chia sẻ từ @{name}", "account.joined": "Đã tham gia {date}", - "account.last_status": "Online", "account.link_verified_on": "Liên kết này đã được xác thực vào {date}", "account.locked_info": "Đây là tài khoản riêng tư. Họ sẽ tự mình xét duyệt các yêu cầu theo dõi.", "account.media": "Media", @@ -32,7 +32,6 @@ "account.mute": "Ẩn @{name}", "account.mute_notifications": "Tắt thông báo từ @{name}", "account.muted": "Đã ẩn", - "account.never_active": "Chưa có bất cứ hoạt động nào", "account.posts": "Tút", "account.posts_with_replies": "Trả lời", "account.report": "Báo cáo @{name}", @@ -42,10 +41,12 @@ "account.statuses_counter": "{count, plural, one {{counter} Tút} other {{counter} Tút}}", "account.unblock": "Bỏ chặn @{name}", "account.unblock_domain": "Bỏ ẩn {domain}", + "account.unblock_short": "Unblock", "account.unendorse": "Ngưng tôn vinh người này", "account.unfollow": "Ngưng theo dõi", "account.unmute": "Bỏ ẩn @{name}", "account.unmute_notifications": "Mở lại thông báo từ @{name}", + "account.unmute_short": "Unmute", "account_note.placeholder": "Nhấn để thêm", "admin.dashboard.daily_retention": "Tỉ lệ người dùng sau đăng ký ở lại theo ngày", "admin.dashboard.monthly_retention": "Tỉ lệ người dùng sau đăng ký ở lại theo tháng", diff --git a/app/javascript/mastodon/locales/zgh.json b/app/javascript/mastodon/locales/zgh.json index df307d439d..0fc7c56dac 100644 --- a/app/javascript/mastodon/locales/zgh.json +++ b/app/javascript/mastodon/locales/zgh.json @@ -18,12 +18,12 @@ "account.followers": "ⵉⵎⴹⴼⴰⵕⵏ", "account.followers.empty": "No one follows this user yet.", "account.followers_counter": "{count, plural, one {{counter} Follower} other {{counter} Followers}}", + "account.following": "Following", "account.following_counter": "{count, plural, one {{counter} Following} other {{counter} Following}}", "account.follows.empty": "This user doesn't follow anyone yet.", "account.follows_you": "ⴹⴼⵕⵏ ⴽⵯⵏ", "account.hide_reblogs": "Hide boosts from @{name}", "account.joined": "Joined {date}", - "account.last_status": "Last active", "account.link_verified_on": "Ownership of this link was checked on {date}", "account.locked_info": "This account privacy status is set to locked. The owner manually reviews who can follow them.", "account.media": "ⴰⵙⵏⵖⵎⵉⵙ", @@ -32,7 +32,6 @@ "account.mute": "ⵥⵥⵉⵥⵏ @{name}", "account.mute_notifications": "ⵥⵥⵉⵥⵏ ⵜⵉⵏⵖⵎⵉⵙⵉⵏ ⵙⴳ @{name}", "account.muted": "ⵉⵜⵜⵓⵥⵉⵥⵏ", - "account.never_active": "ⵓⵙⴰⵔ", "account.posts": "Toots", "account.posts_with_replies": "Toots and replies", "account.report": "Report @{name}", @@ -42,10 +41,12 @@ "account.statuses_counter": "{count, plural, one {{counter} Toot} other {{counter} Toots}}", "account.unblock": "Unblock @{name}", "account.unblock_domain": "Unblock domain {domain}", + "account.unblock_short": "Unblock", "account.unendorse": "Don't feature on profile", "account.unfollow": "ⴽⴽⵙ ⴰⴹⴼⴼⵓⵕ", "account.unmute": "Unmute @{name}", "account.unmute_notifications": "Unmute notifications from @{name}", + "account.unmute_short": "Unmute", "account_note.placeholder": "Click to add a note", "admin.dashboard.daily_retention": "User retention rate by day after sign-up", "admin.dashboard.monthly_retention": "User retention rate by month after sign-up", diff --git a/app/javascript/mastodon/locales/zh-CN.json b/app/javascript/mastodon/locales/zh-CN.json index 7f6743e623..1be5f796fd 100644 --- a/app/javascript/mastodon/locales/zh-CN.json +++ b/app/javascript/mastodon/locales/zh-CN.json @@ -18,12 +18,12 @@ "account.followers": "关注者", "account.followers.empty": "目前无人关注此用户。", "account.followers_counter": "被 {counter} 人关注", + "account.following": "Following", "account.following_counter": "正在关注 {counter} 人", "account.follows.empty": "此用户目前尚未关注任何人。", "account.follows_you": "关注了你", "account.hide_reblogs": "隐藏来自 @{name} 的转嘟", "account.joined": "加入于 {date}", - "account.last_status": "最近活动", "account.link_verified_on": "此链接的所有权已在 {date} 检查", "account.locked_info": "此账户已锁嘟。账户的主人会手动审核关注者。", "account.media": "媒体", @@ -32,7 +32,6 @@ "account.mute": "隐藏 @{name}", "account.mute_notifications": "隐藏来自 @{name} 的通知", "account.muted": "已隐藏", - "account.never_active": "从未活跃", "account.posts": "嘟文", "account.posts_with_replies": "嘟文和回复", "account.report": "举报 @{name}", @@ -42,10 +41,12 @@ "account.statuses_counter": "{counter} 条嘟文", "account.unblock": "解除屏蔽 @{name}", "account.unblock_domain": "不再屏蔽 {domain} 实例", + "account.unblock_short": "Unblock", "account.unendorse": "不在个人资料中推荐此用户", "account.unfollow": "取消关注", "account.unmute": "不再隐藏 @{name}", "account.unmute_notifications": "不再隐藏来自 @{name} 的通知", + "account.unmute_short": "Unmute", "account_note.placeholder": "点击添加备注", "admin.dashboard.daily_retention": "注册后用户留存率(按日计算)", "admin.dashboard.monthly_retention": "注册后用户留存率(按月计算)", diff --git a/app/javascript/mastodon/locales/zh-HK.json b/app/javascript/mastodon/locales/zh-HK.json index 292b64042c..823fb37fb5 100644 --- a/app/javascript/mastodon/locales/zh-HK.json +++ b/app/javascript/mastodon/locales/zh-HK.json @@ -18,12 +18,12 @@ "account.followers": "關注者", "account.followers.empty": "尚未有人關注這位使用者。", "account.followers_counter": "有 {count, plural,one {{counter} 個} other {{counter} 個}}關注者", + "account.following": "Following", "account.following_counter": "正在關注 {count, plural,one {{counter}}other {{counter} 人}}", "account.follows.empty": "這位使用者尚未關注任何人。", "account.follows_you": "關注你", "account.hide_reblogs": "隱藏 @{name} 的轉推", "account.joined": "於 {date} 加入", - "account.last_status": "上次活躍時間", "account.link_verified_on": "此連結的所有權已在 {date} 檢查過", "account.locked_info": "這位使用者將私隱設定為「不公開」,會手動審批誰能關注他/她。", "account.media": "媒體", @@ -32,7 +32,6 @@ "account.mute": "將 @{name} 靜音", "account.mute_notifications": "將來自 @{name} 的通知靜音", "account.muted": "靜音", - "account.never_active": "永不", "account.posts": "文章", "account.posts_with_replies": "包含回覆的文章", "account.report": "舉報 @{name}", @@ -42,10 +41,12 @@ "account.statuses_counter": "{count, plural,one {{counter} 篇}other {{counter} 篇}}文章", "account.unblock": "解除對 @{name} 的封鎖", "account.unblock_domain": "解除對域名 {domain} 的封鎖", + "account.unblock_short": "Unblock", "account.unendorse": "不再於個人資料頁面推薦對方", "account.unfollow": "取消關注", "account.unmute": "取消 @{name} 的靜音", "account.unmute_notifications": "取消來自 @{name} 通知的靜音", + "account.unmute_short": "Unmute", "account_note.placeholder": "按此添加備注", "admin.dashboard.daily_retention": "User retention rate by day after sign-up", "admin.dashboard.monthly_retention": "User retention rate by month after sign-up", diff --git a/app/javascript/mastodon/locales/zh-TW.json b/app/javascript/mastodon/locales/zh-TW.json index 4da14a4757..a53f59ddf2 100644 --- a/app/javascript/mastodon/locales/zh-TW.json +++ b/app/javascript/mastodon/locales/zh-TW.json @@ -18,12 +18,12 @@ "account.followers": "跟隨者", "account.followers.empty": "尚未有人跟隨這位使用者。", "account.followers_counter": "被 {count, plural,one {{counter} 人}other {{counter} 人}} 跟隨", + "account.following": "Following", "account.following_counter": "正在跟隨 {count, plural,one {{counter}}other {{counter} 人}}", "account.follows.empty": "這位使用者尚未跟隨任何人。", "account.follows_you": "跟隨了您", "account.hide_reblogs": "隱藏來自 @{name} 的轉嘟", "account.joined": "加入於 {date}", - "account.last_status": "上次活躍時間", "account.link_verified_on": "已在 {date} 檢查此連結的擁有者權限", "account.locked_info": "此帳戶的隱私狀態被設為鎖定。該擁有者會手動審核能跟隨此帳戶的人。", "account.media": "媒體", @@ -32,7 +32,6 @@ "account.mute": "靜音 @{name}", "account.mute_notifications": "靜音來自 @{name} 的通知", "account.muted": "已靜音", - "account.never_active": "永不", "account.posts": "嘟文", "account.posts_with_replies": "嘟文與回覆", "account.report": "檢舉 @{name}", @@ -42,10 +41,12 @@ "account.statuses_counter": "{count, plural,one {{counter} 則}other {{counter} 則}}嘟文", "account.unblock": "取消封鎖 @{name}", "account.unblock_domain": "取消封鎖域名 {domain}", + "account.unblock_short": "Unblock", "account.unendorse": "不再於個人資料頁面推薦對方", "account.unfollow": "取消跟隨", "account.unmute": "取消靜音 @{name}", "account.unmute_notifications": "重新接收來自 @{name} 的通知", + "account.unmute_short": "Unmute", "account_note.placeholder": "按此添加備注", "admin.dashboard.daily_retention": "註冊後使用者存留率(日)", "admin.dashboard.monthly_retention": "註冊後使用者存留率(月)", diff --git a/app/javascript/styles/mastodon-light/diff.scss b/app/javascript/styles/mastodon-light/diff.scss index eb6bdea990..7a2dd03308 100644 --- a/app/javascript/styles/mastodon-light/diff.scss +++ b/app/javascript/styles/mastodon-light/diff.scss @@ -143,10 +143,15 @@ html { .box-widget input[type="password"], .box-widget textarea, .statuses-grid .detailed-status, +.report-dialog-modal__textarea, .audio-player { border: 1px solid lighten($ui-base-color, 8%); } +.report-dialog-modal .dialog-option .poll__input { + color: $white; +} + .search__input { @media screen and (max-width: $no-gap-breakpoint) { border-top: 0; @@ -342,6 +347,7 @@ html { .mute-modal, .block-modal, .report-modal, +.report-dialog-modal, .embed-modal, .error-modal, .onboarding-modal, diff --git a/app/javascript/styles/mastodon/admin.scss b/app/javascript/styles/mastodon/admin.scss index 0873ac3001..40cd899b35 100644 --- a/app/javascript/styles/mastodon/admin.scss +++ b/app/javascript/styles/mastodon/admin.scss @@ -367,6 +367,21 @@ body, } } + .positive-hint, + .negative-hint, + .neutral-hint { + a { + color: inherit; + text-decoration: underline; + + &:focus, + &:hover, + &:active { + text-decoration: none; + } + } + } + .positive-hint { color: $valid-value-color; font-weight: 500; @@ -1612,3 +1627,38 @@ a.sparkline { } } } + +.availability-indicator { + display: flex; + align-items: center; + margin-bottom: 30px; + font-size: 14px; + line-height: 21px; + + &__hint { + padding: 0 15px; + } + + &__graphic { + display: flex; + margin: 0 -2px; + + &__item { + display: block; + flex: 0 0 auto; + width: 4px; + height: 21px; + background: lighten($ui-base-color, 8%); + margin: 0 2px; + border-radius: 2px; + + &.positive { + background: $valid-value-color; + } + + &.negative { + background: $error-value-color; + } + } + } +} diff --git a/app/javascript/styles/mastodon/components.scss b/app/javascript/styles/mastodon/components.scss index d1d679ac25..295b0ddfb5 100644 --- a/app/javascript/styles/mastodon/components.scss +++ b/app/javascript/styles/mastodon/components.scss @@ -1127,7 +1127,7 @@ .media-gallery, .audio-player, .video-player { - margin-top: 8px; + margin-top: 15px; max-width: 250px; } @@ -5609,6 +5609,12 @@ a.status-card.compact:hover { margin: 20px 0; } } + + .media-gallery, + .audio-player, + .video-player { + margin-top: 15px; + } } .loading-bar { diff --git a/app/javascript/styles/mastodon/tables.scss b/app/javascript/styles/mastodon/tables.scss index 1f7e71776e..431b8a73a4 100644 --- a/app/javascript/styles/mastodon/tables.scss +++ b/app/javascript/styles/mastodon/tables.scss @@ -65,6 +65,24 @@ } } + &.horizontal-table { + border-collapse: collapse; + border-style: hidden; + + & > tbody > tr > th, + & > tbody > tr > td { + padding: 11px 10px; + background: transparent; + border: 1px solid lighten($ui-base-color, 8%); + color: $secondary-text-color; + } + + & > tbody > tr > th { + color: $darker-text-color; + font-weight: 600; + } + } + &.batch-table { & > thead > tr > th { background: $ui-base-color; diff --git a/app/lib/admin/metrics/dimension.rb b/app/lib/admin/metrics/dimension.rb index d8392ddfcc..81b89d9b32 100644 --- a/app/lib/admin/metrics/dimension.rb +++ b/app/lib/admin/metrics/dimension.rb @@ -9,6 +9,8 @@ class Admin::Metrics::Dimension software_versions: Admin::Metrics::Dimension::SoftwareVersionsDimension, tag_servers: Admin::Metrics::Dimension::TagServersDimension, tag_languages: Admin::Metrics::Dimension::TagLanguagesDimension, + instance_accounts: Admin::Metrics::Dimension::InstanceAccountsDimension, + instance_languages: Admin::Metrics::Dimension::InstanceLanguagesDimension, }.freeze def self.retrieve(dimension_keys, start_at, end_at, limit, params) diff --git a/app/lib/admin/metrics/dimension/instance_accounts_dimension.rb b/app/lib/admin/metrics/dimension/instance_accounts_dimension.rb new file mode 100644 index 0000000000..4eac8e611e --- /dev/null +++ b/app/lib/admin/metrics/dimension/instance_accounts_dimension.rb @@ -0,0 +1,35 @@ +# frozen_string_literal: true + +class Admin::Metrics::Dimension::InstanceAccountsDimension < Admin::Metrics::Dimension::BaseDimension + include LanguagesHelper + + def self.with_params? + true + end + + def key + 'instance_accounts' + end + + protected + + def perform_query + sql = <<-SQL.squish + SELECT accounts.username, count(follows.*) AS value + FROM accounts + LEFT JOIN follows ON follows.target_account_id = accounts.id + WHERE accounts.domain = $1 + GROUP BY accounts.id, follows.target_account_id + ORDER BY value DESC + LIMIT $2 + SQL + + rows = ActiveRecord::Base.connection.select_all(sql, nil, [[nil, params[:domain]], [nil, @limit]]) + + rows.map { |row| { key: row['username'], human_key: row['username'], value: row['value'].to_s } } + end + + def params + @params.permit(:domain) + end +end diff --git a/app/lib/admin/metrics/dimension/instance_languages_dimension.rb b/app/lib/admin/metrics/dimension/instance_languages_dimension.rb new file mode 100644 index 0000000000..1ede1a56e4 --- /dev/null +++ b/app/lib/admin/metrics/dimension/instance_languages_dimension.rb @@ -0,0 +1,37 @@ +# frozen_string_literal: true + +class Admin::Metrics::Dimension::InstanceLanguagesDimension < Admin::Metrics::Dimension::BaseDimension + include LanguagesHelper + + def self.with_params? + true + end + + def key + 'instance_languages' + end + + protected + + def perform_query + sql = <<-SQL.squish + SELECT COALESCE(statuses.language, 'und') AS language, count(*) AS value + FROM statuses + INNER JOIN accounts ON accounts.id = statuses.account_id + WHERE accounts.domain = $1 + AND statuses.id BETWEEN $2 AND $3 + AND statuses.reblog_of_id IS NULL + GROUP BY COALESCE(statuses.language, 'und') + ORDER BY count(*) DESC + LIMIT $4 + SQL + + rows = ActiveRecord::Base.connection.select_all(sql, nil, [[nil, params[:domain]], [nil, Mastodon::Snowflake.id_at(@start_at, with_random: false)], [nil, Mastodon::Snowflake.id_at(@end_at, with_random: false)], [nil, @limit]]) + + rows.map { |row| { key: row['language'], human_key: standard_locale_name(row['language']), value: row['value'].to_s } } + end + + def params + @params.permit(:domain) + end +end diff --git a/app/lib/admin/metrics/measure.rb b/app/lib/admin/metrics/measure.rb index a839498a13..0b510eb256 100644 --- a/app/lib/admin/metrics/measure.rb +++ b/app/lib/admin/metrics/measure.rb @@ -10,6 +10,12 @@ class Admin::Metrics::Measure tag_accounts: Admin::Metrics::Measure::TagAccountsMeasure, tag_uses: Admin::Metrics::Measure::TagUsesMeasure, tag_servers: Admin::Metrics::Measure::TagServersMeasure, + instance_accounts: Admin::Metrics::Measure::InstanceAccountsMeasure, + instance_media_attachments: Admin::Metrics::Measure::InstanceMediaAttachmentsMeasure, + instance_reports: Admin::Metrics::Measure::InstanceReportsMeasure, + instance_statuses: Admin::Metrics::Measure::InstanceStatusesMeasure, + instance_follows: Admin::Metrics::Measure::InstanceFollowsMeasure, + instance_followers: Admin::Metrics::Measure::InstanceFollowersMeasure, }.freeze def self.retrieve(measure_keys, start_at, end_at, params) diff --git a/app/lib/admin/metrics/measure/base_measure.rb b/app/lib/admin/metrics/measure/base_measure.rb index ed1df9c7d9..e33a6c494f 100644 --- a/app/lib/admin/metrics/measure/base_measure.rb +++ b/app/lib/admin/metrics/measure/base_measure.rb @@ -26,6 +26,14 @@ class Admin::Metrics::Measure::BaseMeasure raise NotImplementedError end + def unit + nil + end + + def total_in_time_range? + true + end + def total load[:total] end diff --git a/app/lib/admin/metrics/measure/instance_accounts_measure.rb b/app/lib/admin/metrics/measure/instance_accounts_measure.rb new file mode 100644 index 0000000000..4c61a064a8 --- /dev/null +++ b/app/lib/admin/metrics/measure/instance_accounts_measure.rb @@ -0,0 +1,58 @@ +# frozen_string_literal: true + +class Admin::Metrics::Measure::InstanceAccountsMeasure < Admin::Metrics::Measure::BaseMeasure + def self.with_params? + true + end + + def key + 'instance_accounts' + end + + def total_in_time_range? + false + end + + protected + + def perform_total_query + Account.where(domain: params[:domain]).count + end + + def perform_previous_total_query + nil + end + + def perform_data_query + sql = <<-SQL.squish + SELECT axis.*, ( + WITH new_accounts AS ( + SELECT accounts.id + FROM accounts + WHERE date_trunc('day', accounts.created_at)::date = axis.period + AND accounts.domain = $3::text + ) + SELECT count(*) FROM new_accounts + ) AS value + FROM ( + SELECT generate_series(date_trunc('day', $1::timestamp)::date, date_trunc('day', $2::timestamp)::date, interval '1 day') AS period + ) AS axis + SQL + + rows = ActiveRecord::Base.connection.select_all(sql, nil, [[nil, @start_at], [nil, @end_at], [nil, params[:domain]]]) + + rows.map { |row| { date: row['period'], value: row['value'].to_s } } + end + + def time_period + (@start_at.to_date..@end_at.to_date) + end + + def previous_time_period + ((@start_at.to_date - length_of_period)..(@end_at.to_date - length_of_period)) + end + + def params + @params.permit(:domain) + end +end diff --git a/app/lib/admin/metrics/measure/instance_followers_measure.rb b/app/lib/admin/metrics/measure/instance_followers_measure.rb new file mode 100644 index 0000000000..caa60013b2 --- /dev/null +++ b/app/lib/admin/metrics/measure/instance_followers_measure.rb @@ -0,0 +1,59 @@ +# frozen_string_literal: true + +class Admin::Metrics::Measure::InstanceFollowersMeasure < Admin::Metrics::Measure::BaseMeasure + def self.with_params? + true + end + + def key + 'instance_followers' + end + + def total_in_time_range? + false + end + + protected + + def perform_total_query + Follow.joins(:account).merge(Account.where(domain: params[:domain])).count + end + + def perform_previous_total_query + nil + end + + def perform_data_query + sql = <<-SQL.squish + SELECT axis.*, ( + WITH new_followers AS ( + SELECT follows.id + FROM follows + INNER JOIN accounts ON follows.account_id = accounts.id + WHERE date_trunc('day', follows.created_at)::date = axis.period + AND accounts.domain = $3::text + ) + SELECT count(*) FROM new_followers + ) AS value + FROM ( + SELECT generate_series(date_trunc('day', $1::timestamp)::date, date_trunc('day', $2::timestamp)::date, interval '1 day') AS period + ) AS axis + SQL + + rows = ActiveRecord::Base.connection.select_all(sql, nil, [[nil, @start_at], [nil, @end_at], [nil, params[:domain]]]) + + rows.map { |row| { date: row['period'], value: row['value'].to_s } } + end + + def time_period + (@start_at.to_date..@end_at.to_date) + end + + def previous_time_period + ((@start_at.to_date - length_of_period)..(@end_at.to_date - length_of_period)) + end + + def params + @params.permit(:domain) + end +end diff --git a/app/lib/admin/metrics/measure/instance_follows_measure.rb b/app/lib/admin/metrics/measure/instance_follows_measure.rb new file mode 100644 index 0000000000..b026c7e6d0 --- /dev/null +++ b/app/lib/admin/metrics/measure/instance_follows_measure.rb @@ -0,0 +1,59 @@ +# frozen_string_literal: true + +class Admin::Metrics::Measure::InstanceFollowsMeasure < Admin::Metrics::Measure::BaseMeasure + def self.with_params? + true + end + + def key + 'instance_follows' + end + + def total_in_time_range? + false + end + + protected + + def perform_total_query + Follow.joins(:target_account).merge(Account.where(domain: params[:domain])).count + end + + def perform_previous_total_query + nil + end + + def perform_data_query + sql = <<-SQL.squish + SELECT axis.*, ( + WITH new_follows AS ( + SELECT follows.id + FROM follows + INNER JOIN accounts ON follows.target_account_id = accounts.id + WHERE date_trunc('day', follows.created_at)::date = axis.period + AND accounts.domain = $3::text + ) + SELECT count(*) FROM new_follows + ) AS value + FROM ( + SELECT generate_series(date_trunc('day', $1::timestamp)::date, date_trunc('day', $2::timestamp)::date, interval '1 day') AS period + ) AS axis + SQL + + rows = ActiveRecord::Base.connection.select_all(sql, nil, [[nil, @start_at], [nil, @end_at], [nil, params[:domain]]]) + + rows.map { |row| { date: row['period'], value: row['value'].to_s } } + end + + def time_period + (@start_at.to_date..@end_at.to_date) + end + + def previous_time_period + ((@start_at.to_date - length_of_period)..(@end_at.to_date - length_of_period)) + end + + def params + @params.permit(:domain) + end +end diff --git a/app/lib/admin/metrics/measure/instance_media_attachments_measure.rb b/app/lib/admin/metrics/measure/instance_media_attachments_measure.rb new file mode 100644 index 0000000000..2e2154c92b --- /dev/null +++ b/app/lib/admin/metrics/measure/instance_media_attachments_measure.rb @@ -0,0 +1,69 @@ +# frozen_string_literal: true + +class Admin::Metrics::Measure::InstanceMediaAttachmentsMeasure < Admin::Metrics::Measure::BaseMeasure + include ActionView::Helpers::NumberHelper + + def self.with_params? + true + end + + def key + 'instance_media_attachments' + end + + def unit + 'bytes' + end + + def value_to_human_value(value) + number_to_human_size(value) + end + + def total_in_time_range? + false + end + + protected + + def perform_total_query + MediaAttachment.joins(:account).merge(Account.where(domain: params[:domain])).sum('COALESCE(file_file_size, 0) + COALESCE(thumbnail_file_size, 0)') + end + + def perform_previous_total_query + nil + end + + def perform_data_query + sql = <<-SQL.squish + SELECT axis.*, ( + WITH new_media_attachments AS ( + SELECT COALESCE(media_attachments.file_file_size, 0) + COALESCE(media_attachments.thumbnail_file_size, 0) AS size + FROM media_attachments + INNER JOIN accounts ON accounts.id = media_attachments.account_id + WHERE date_trunc('day', media_attachments.created_at)::date = axis.period + AND accounts.domain = $3::text + ) + SELECT SUM(size) FROM new_media_attachments + ) AS value + FROM ( + SELECT generate_series(date_trunc('day', $1::timestamp)::date, date_trunc('day', $2::timestamp)::date, interval '1 day') AS period + ) AS axis + SQL + + rows = ActiveRecord::Base.connection.select_all(sql, nil, [[nil, @start_at], [nil, @end_at], [nil, params[:domain]]]) + + rows.map { |row| { date: row['period'], value: row['value'].to_s } } + end + + def time_period + (@start_at.to_date..@end_at.to_date) + end + + def previous_time_period + ((@start_at.to_date - length_of_period)..(@end_at.to_date - length_of_period)) + end + + def params + @params.permit(:domain) + end +end diff --git a/app/lib/admin/metrics/measure/instance_reports_measure.rb b/app/lib/admin/metrics/measure/instance_reports_measure.rb new file mode 100644 index 0000000000..6b3f350674 --- /dev/null +++ b/app/lib/admin/metrics/measure/instance_reports_measure.rb @@ -0,0 +1,59 @@ +# frozen_string_literal: true + +class Admin::Metrics::Measure::InstanceReportsMeasure < Admin::Metrics::Measure::BaseMeasure + def self.with_params? + true + end + + def key + 'instance_reports' + end + + def total_in_time_range? + false + end + + protected + + def perform_total_query + Report.where(target_account: Account.where(domain: params[:domain])).count + end + + def perform_previous_total_query + nil + end + + def perform_data_query + sql = <<-SQL.squish + SELECT axis.*, ( + WITH new_reports AS ( + SELECT reports.id + FROM reports + INNER JOIN accounts ON accounts.id = reports.target_account_id + WHERE date_trunc('day', reports.created_at)::date = axis.period + AND accounts.domain = $3::text + ) + SELECT count(*) FROM new_reports + ) AS value + FROM ( + SELECT generate_series(date_trunc('day', $1::timestamp)::date, date_trunc('day', $2::timestamp)::date, interval '1 day') AS period + ) AS axis + SQL + + rows = ActiveRecord::Base.connection.select_all(sql, nil, [[nil, @start_at], [nil, @end_at], [nil, params[:domain]]]) + + rows.map { |row| { date: row['period'], value: row['value'].to_s } } + end + + def time_period + (@start_at.to_date..@end_at.to_date) + end + + def previous_time_period + ((@start_at.to_date - length_of_period)..(@end_at.to_date - length_of_period)) + end + + def params + @params.permit(:domain) + end +end diff --git a/app/lib/admin/metrics/measure/instance_statuses_measure.rb b/app/lib/admin/metrics/measure/instance_statuses_measure.rb new file mode 100644 index 0000000000..86b10da6c4 --- /dev/null +++ b/app/lib/admin/metrics/measure/instance_statuses_measure.rb @@ -0,0 +1,60 @@ +# frozen_string_literal: true + +class Admin::Metrics::Measure::InstanceStatusesMeasure < Admin::Metrics::Measure::BaseMeasure + def self.with_params? + true + end + + def key + 'instance_statuses' + end + + def total_in_time_range? + false + end + + protected + + def perform_total_query + Status.joins(:account).merge(Account.where(domain: params[:domain])).count + end + + def perform_previous_total_query + nil + end + + def perform_data_query + sql = <<-SQL.squish + SELECT axis.*, ( + WITH new_statuses AS ( + SELECT statuses.id + FROM statuses + INNER JOIN accounts ON accounts.id = statuses.account_id + WHERE statuses.id BETWEEN $3 AND $4 + AND accounts.domain = $5::text + AND date_trunc('day', statuses.created_at)::date = axis.period + ) + SELECT count(*) FROM new_statuses + ) AS value + FROM ( + SELECT generate_series(date_trunc('day', $1::timestamp)::date, date_trunc('day', $2::timestamp)::date, interval '1 day') AS period + ) AS axis + SQL + + rows = ActiveRecord::Base.connection.select_all(sql, nil, [[nil, @start_at], [nil, @end_at], [nil, Mastodon::Snowflake.id_at(@start_at, with_random: false)], [nil, Mastodon::Snowflake.id_at(@end_at, with_random: false)], [nil, params[:domain]]]) + + rows.map { |row| { date: row['period'], value: row['value'].to_s } } + end + + def time_period + (@start_at.to_date..@end_at.to_date) + end + + def previous_time_period + ((@start_at.to_date - length_of_period)..(@end_at.to_date - length_of_period)) + end + + def params + @params.permit(:domain) + end +end diff --git a/app/lib/delivery_failure_tracker.rb b/app/lib/delivery_failure_tracker.rb index 8907ade4c1..7b800fc0b7 100644 --- a/app/lib/delivery_failure_tracker.rb +++ b/app/lib/delivery_failure_tracker.rb @@ -30,7 +30,7 @@ class DeliveryFailureTracker end def exhausted_deliveries_days - Redis.current.smembers(exhausted_deliveries_key).sort.map { |date| Date.new(date.slice(0, 4).to_i, date.slice(4, 2).to_i, date.slice(6, 2).to_i) } + @exhausted_deliveries_days ||= Redis.current.smembers(exhausted_deliveries_key).sort.map { |date| Date.new(date.slice(0, 4).to_i, date.slice(4, 2).to_i, date.slice(6, 2).to_i) } end alias reset! track_success! diff --git a/app/lib/feed_manager.rb b/app/lib/feed_manager.rb index 2c16689bda..efc9da34bf 100644 --- a/app/lib/feed_manager.rb +++ b/app/lib/feed_manager.rb @@ -506,7 +506,7 @@ class FeedManager Formatter.instance.plaintext(status), status.spoiler_text, status.preloadable_poll ? status.preloadable_poll.options.join("\n\n") : nil, - status.media_attachments.map(&:description).join("\n\n"), + status.ordered_media_attachments.map(&:description).join("\n\n"), ].compact.join("\n\n") combined_regex.match?(combined_text) diff --git a/app/lib/rss/serializer.rb b/app/lib/rss/serializer.rb index fd56c568c7..7e3ed1f178 100644 --- a/app/lib/rss/serializer.rb +++ b/app/lib/rss/serializer.rb @@ -11,7 +11,7 @@ class RSS::Serializer .pub_date(status.created_at) .description(status.spoiler_text.presence || Formatter.instance.format(status, inline_poll_options: true).to_str) - status.media_attachments.each do |media| + status.ordered_media_attachments.each do |media| item.enclosure(full_asset_url(media.file.url(:original, false)), media.file.content_type, media.file.size) end end diff --git a/app/models/concerns/omniauthable.rb b/app/models/concerns/omniauthable.rb index 791a949110..a90d5d888a 100644 --- a/app/models/concerns/omniauthable.rb +++ b/app/models/concerns/omniauthable.rb @@ -13,7 +13,7 @@ module Omniauthable Devise.omniauth_configs.keys end - def email_verified? + def email_present? email && email !~ TEMP_EMAIL_REGEX end end @@ -40,16 +40,14 @@ module Omniauthable end def create_for_oauth(auth) - # Check if the user exists with provided email if the provider gives us a - # verified email. If no verified email was provided or the user already - # exists, we assign a temporary email and ask the user to verify it on + # Check if the user exists with provided email. If no email was provided, + # we assign a temporary email and ask the user to verify it on # the next step via Auth::SetupController.show strategy = Devise.omniauth_configs[auth.provider.to_sym].strategy assume_verified = strategy&.security&.assume_email_is_verified - email_is_verified = auth.info.verified || auth.info.verified_email || assume_verified + email_is_verified = auth.info.verified || auth.info.verified_email || auth.info.email_verified || assume_verified email = auth.info.verified_email || auth.info.email - email = nil unless email_is_verified user = User.find_by(email: email) if email_is_verified @@ -58,7 +56,7 @@ module Omniauthable user = User.new(user_params_from_auth(email, auth)) user.account.avatar_remote_url = auth.info.image if /\A#{URI::DEFAULT_PARSER.make_regexp(%w(http https))}\z/.match?(auth.info.image) - user.skip_confirmation! + user.skip_confirmation! if email_is_verified user.save! user end @@ -71,8 +69,8 @@ module Omniauthable agreement: true, external: true, account_attributes: { - username: ensure_unique_username(auth.uid), - display_name: auth.info.full_name || [auth.info.first_name, auth.info.last_name].join(' '), + username: ensure_unique_username(ensure_valid_username(auth.uid)), + display_name: auth.info.full_name || auth.info.name || [auth.info.first_name, auth.info.last_name].join(' '), }, } end @@ -88,5 +86,12 @@ module Omniauthable username end + + def ensure_valid_username(starting_username) + starting_username = starting_username.split('@')[0] + temp_username = starting_username.gsub(/[^a-z0-9_]+/i, '') + validated_username = temp_username.truncate(30, omission: '') + validated_username + end end end diff --git a/app/models/domain_block.rb b/app/models/domain_block.rb index bba04c6039..2b797ef918 100644 --- a/app/models/domain_block.rb +++ b/app/models/domain_block.rb @@ -30,6 +30,14 @@ class DomainBlock < ApplicationRecord scope :with_user_facing_limitations, -> { where(severity: [:silence, :suspend]).or(where(reject_media: true)) } scope :by_severity, -> { order(Arel.sql('(CASE severity WHEN 0 THEN 1 WHEN 1 THEN 2 WHEN 2 THEN 0 END), reject_media, domain')) } + def policies + if suspend? + [:suspend] + else + [severity.to_sym, reject_media? ? :reject_media : nil, reject_reports? ? :reject_reports : nil].reject { |policy| policy == :noop || policy.nil? } + end + end + class << self def suspend?(domain) !!rule_for(domain)&.suspend? diff --git a/app/models/featured_tag.rb b/app/models/featured_tag.rb index e02ae0705a..74d62e7778 100644 --- a/app/models/featured_tag.rb +++ b/app/models/featured_tag.rb @@ -4,8 +4,8 @@ # Table name: featured_tags # # id :bigint(8) not null, primary key -# account_id :bigint(8) -# tag_id :bigint(8) +# account_id :bigint(8) not null +# tag_id :bigint(8) not null # statuses_count :bigint(8) default(0), not null # last_status_at :datetime # created_at :datetime not null diff --git a/app/models/instance.rb b/app/models/instance.rb index 8949be054a..7434d3322b 100644 --- a/app/models/instance.rb +++ b/app/models/instance.rb @@ -32,35 +32,27 @@ class Instance < ApplicationRecord @delivery_failure_tracker ||= DeliveryFailureTracker.new(domain) end - def following_count - @following_count ||= Follow.where(account: accounts).count + def unavailable? + unavailable_domain.present? end - def followers_count - @followers_count ||= Follow.where(target_account: accounts).count - end - - def reports_count - @reports_count ||= Report.where(target_account: accounts).count - end - - def blocks_count - @blocks_count ||= Block.where(target_account: accounts).count - end - - def public_comment - domain_block&.public_comment - end - - def private_comment - domain_block&.private_comment - end - - def media_storage - @media_storage ||= MediaAttachment.where(account: accounts).sum(:file_file_size) + def failing? + failure_days.present? || unavailable? end def to_param domain end + + delegate :exhausted_deliveries_days, to: :delivery_failure_tracker + + def availability_over_days(num_days, end_date = Time.now.utc.to_date) + failures_map = exhausted_deliveries_days.index_with { true } + period_end_at = exhausted_deliveries_days.last || end_date + period_start_at = period_end_at - num_days.days + + (period_start_at..period_end_at).map do |date| + [date, failures_map[date]] + end + end end diff --git a/app/models/instance_filter.rb b/app/models/instance_filter.rb index 9e533c4aa9..e7e5166a1a 100644 --- a/app/models/instance_filter.rb +++ b/app/models/instance_filter.rb @@ -4,8 +4,7 @@ class InstanceFilter KEYS = %i( limited by_domain - warning - unavailable + availability ).freeze attr_reader :params @@ -34,12 +33,21 @@ class InstanceFilter Instance.joins(:domain_allow).reorder(Arel.sql('domain_allows.id desc')) when 'by_domain' Instance.matches_domain(value) - when 'warning' - Instance.where(domain: DeliveryFailureTracker.warning_domains) - when 'unavailable' - Instance.joins(:unavailable_domain) + when 'availability' + availability_scope(value) else raise "Unknown filter: #{key}" end end + + def availability_scope(value) + case value + when 'failing' + Instance.where(domain: DeliveryFailureTracker.warning_domains) + when 'unavailable' + Instance.joins(:unavailable_domain) + else + raise "Unknown availability: #{value}" + end + end end diff --git a/app/models/report.rb b/app/models/report.rb index 8ba2dd8fd2..6d41665401 100644 --- a/app/models/report.rb +++ b/app/models/report.rb @@ -63,8 +63,20 @@ class Report < ApplicationRecord Status.with_discarded.where(id: status_ids) end - def media_attachments - MediaAttachment.where(status_id: status_ids) + def media_attachments_count + statuses_to_query = [] + count = 0 + + statuses.pluck(:id, :ordered_media_attachment_ids).each do |id, ordered_ids| + if ordered_ids.nil? + statuses_to_query << id + else + count += ordered_ids.size + end + end + + count += MediaAttachment.where(status_id: statuses_to_query).count unless statuses_to_query.empty? + count end def rules diff --git a/app/models/status.rb b/app/models/status.rb index 6a848baee1..ba9d7f0aa8 100644 --- a/app/models/status.rb +++ b/app/models/status.rb @@ -3,31 +3,31 @@ # # Table name: statuses # -# id :bigint(8) not null, primary key -# uri :string -# text :text default(""), not null -# created_at :datetime not null -# updated_at :datetime not null -# in_reply_to_id :bigint(8) -# reblog_of_id :bigint(8) -# url :string -# sensitive :boolean default(FALSE), not null -# visibility :integer default("public"), not null -# spoiler_text :text default(""), not null -# reply :boolean default(FALSE), not null -# language :string -# conversation_id :bigint(8) -# local :boolean -# account_id :bigint(8) not null -# application_id :bigint(8) -# in_reply_to_account_id :bigint(8) -# local_only :boolean -# full_status_text :text default(""), not null -# poll_id :bigint(8) -# content_type :string -# deleted_at :datetime -# edited_at :datetime -# trendable :boolean +# id :bigint(8) not null, primary key +# uri :string +# text :text default(""), not null +# created_at :datetime not null +# updated_at :datetime not null +# in_reply_to_id :bigint(8) +# reblog_of_id :bigint(8) +# url :string +# sensitive :boolean default(FALSE), not null +# visibility :integer default("public"), not null +# spoiler_text :text default(""), not null +# reply :boolean default(FALSE), not null +# language :string +# conversation_id :bigint(8) +# local :boolean +# account_id :bigint(8) not null +# application_id :bigint(8) +# in_reply_to_account_id :bigint(8) +# local_only :boolean +# poll_id :bigint(8) +# content_type :string +# deleted_at :datetime +# edited_at :datetime +# trendable :boolean +# ordered_media_attachment_ids :bigint(8) is an Array # class Status < ApplicationRecord @@ -217,14 +217,18 @@ class Status < ApplicationRecord public_visibility? || unlisted_visibility? end - def snapshot!(media_attachments_changed: false, account_id: nil, at_time: nil) + def snapshot!(account_id: nil, at_time: nil, rate_limit: true) edits.create!( text: text, spoiler_text: spoiler_text, - media_attachments_changed: media_attachments_changed, + sensitive: sensitive, + ordered_media_attachment_ids: ordered_media_attachment_ids || media_attachments.pluck(:id), + media_descriptions: ordered_media_attachments.map(&:description), + poll_options: preloadable_poll&.options, account_id: account_id || self.account_id, content_type: content_type, - created_at: at_time || edited_at + created_at: at_time || edited_at, + rate_limit: rate_limit ) end @@ -235,7 +239,7 @@ class Status < ApplicationRecord alias sign? distributable? def with_media? - media_attachments.any? + ordered_media_attachments.any? end def with_preview_card? @@ -259,6 +263,15 @@ class Status < ApplicationRecord @emojis = CustomEmoji.from_text(fields.join(' '), account.domain) end + def ordered_media_attachments + if ordered_media_attachment_ids.nil? + media_attachments + else + map = media_attachments.index_by(&:id) + ordered_media_attachment_ids.map { |media_attachment_id| map[media_attachment_id] } + end + end + def replies_count status_stat&.replies_count || 0 end @@ -428,6 +441,63 @@ class Status < ApplicationRecord super || build_status_stat end + # Hack to use a "INSERT INTO ... SELECT ..." query instead of "INSERT INTO ... VALUES ..." query + def self._insert_record(values) + if values.is_a?(Hash) && values['reblog_of_id'].present? + primary_key = self.primary_key + primary_key_value = nil + + if primary_key + primary_key_value = values[primary_key] + + if !primary_key_value && prefetch_primary_key? + primary_key_value = next_sequence_value + values[primary_key] = primary_key_value + end + end + + # The following line is where we differ from stock ActiveRecord implementation + im = _compile_reblog_insert(values) + + # Since we are using SELECT instead of VALUES, a non-error `nil` return is possible. + # For our purposes, it's equivalent to a foreign key constraint violation + result = connection.insert(im, "#{self} Create", primary_key || false, primary_key_value) + raise ActiveRecord::InvalidForeignKey, "(reblog_of_id)=(#{values['reblog_of_id']}) is not present in table \"statuses\"" if result.nil? + + result + else + super + end + end + + def self._compile_reblog_insert(values) + # This is somewhat equivalent to the following code of ActiveRecord::Persistence: + # `arel_table.compile_insert(_substitute_values(values))` + # The main difference is that we use a `SELECT` instead of a `VALUES` clause, + # which means we have to build the `SELECT` clause ourselves and do a bit more + # manual work. + + # Instead of using Arel::InsertManager#values, we are going to use Arel::InsertManager#select + im = Arel::InsertManager.new + im.into(arel_table) + + binds = [] + reblog_bind = nil + values.each do |name, value| + attr = arel_table[name] + bind = predicate_builder.build_bind_attribute(attr.name, value) + + im.columns << attr + binds << bind + + reblog_bind = bind if name == 'reblog_of_id' + end + + im.select(arel_table.where(arel_table[:id].eq(reblog_bind)).where(arel_table[:deleted_at].eq(nil)).project(*binds)) + + im + end + private def update_status_stat!(attrs) diff --git a/app/models/status_edit.rb b/app/models/status_edit.rb index 3d8098fe76..33528eb0d9 100644 --- a/app/models/status_edit.rb +++ b/app/models/status_edit.rb @@ -3,18 +3,39 @@ # # Table name: status_edits # -# id :bigint(8) not null, primary key -# status_id :bigint(8) not null -# account_id :bigint(8) -# text :text default(""), not null -# spoiler_text :text default(""), not null -# media_attachments_changed :boolean default(FALSE), not null -# created_at :datetime not null -# updated_at :datetime not null -# content_type :string +# id :bigint(8) not null, primary key +# status_id :bigint(8) not null +# account_id :bigint(8) +# text :text default(""), not null +# spoiler_text :text default(""), not null +# created_at :datetime not null +# updated_at :datetime not null +# content_type :string +# ordered_media_attachment_ids :bigint(8) is an Array +# media_descriptions :text is an Array +# poll_options :string is an Array +# sensitive :boolean # class StatusEdit < ApplicationRecord + include RateLimitable + + self.ignored_columns = %w( + media_attachments_changed + ) + + class PreservedMediaAttachment < ActiveModelSerializers::Model + attributes :media_attachment, :description + + delegate :id, :type, :url, :preview_url, :remote_url, + :preview_remote_url, :text_url, :meta, :blurhash, + :not_processed?, :needs_redownload?, :local?, + :file, :thumbnail, :thumbnail_remote_url, + :shortcode, to: :media_attachment + end + + rate_limit by: :account, family: :statuses + belongs_to :status belongs_to :account, optional: true @@ -26,4 +47,17 @@ class StatusEdit < ApplicationRecord return @emojis if defined?(@emojis) @emojis = CustomEmoji.from_text([spoiler_text, text].join(' '), status.account.domain) end + + def ordered_media_attachments + return @ordered_media_attachments if defined?(@ordered_media_attachments) + + @ordered_media_attachments = begin + if ordered_media_attachment_ids.nil? + [] + else + map = status.media_attachments.index_by(&:id) + ordered_media_attachment_ids.map.with_index { |media_attachment_id, index| PreservedMediaAttachment.new(media_attachment: map[media_attachment_id], description: media_descriptions[index]) } + end + end + end end diff --git a/app/serializers/activitypub/note_serializer.rb b/app/serializers/activitypub/note_serializer.rb index aa552a7248..05f2ee14f1 100644 --- a/app/serializers/activitypub/note_serializer.rb +++ b/app/serializers/activitypub/note_serializer.rb @@ -15,7 +15,7 @@ class ActivityPub::NoteSerializer < ActivityPub::Serializer attribute :direct_message, if: :non_public? - has_many :media_attachments, key: :attachment + has_many :virtual_attachments, key: :attachment has_many :virtual_tags, key: :tag has_one :replies, serializer: ActivityPub::CollectionSerializer, if: :local? @@ -117,6 +117,10 @@ class ActivityPub::NoteSerializer < ActivityPub::Serializer object.account.sensitized? || object.sensitive || (!instance_options[:allow_local_only] && Setting.outgoing_spoilers.present?) end + def virtual_attachments + object.ordered_media_attachments + end + def virtual_tags object.active_mentions.to_a.sort_by(&:id) + object.tags + object.emojis end diff --git a/app/serializers/rest/admin/measure_serializer.rb b/app/serializers/rest/admin/measure_serializer.rb index 81d655c1a9..fc16b85f21 100644 --- a/app/serializers/rest/admin/measure_serializer.rb +++ b/app/serializers/rest/admin/measure_serializer.rb @@ -1,12 +1,20 @@ # frozen_string_literal: true class REST::Admin::MeasureSerializer < ActiveModel::Serializer - attributes :key, :total, :previous_total, :data + attributes :key, :unit, :total + + attribute :human_value, if: -> { object.respond_to?(:value_to_human_value) } + attribute :previous_total, if: -> { object.total_in_time_range? } + attribute :data def total object.total.to_s end + def human_value + object.value_to_human_value(object.total) + end + def previous_total object.previous_total.to_s end diff --git a/app/serializers/rest/status_edit_serializer.rb b/app/serializers/rest/status_edit_serializer.rb index a1f9e824e2..05ccd5e942 100644 --- a/app/serializers/rest/status_edit_serializer.rb +++ b/app/serializers/rest/status_edit_serializer.rb @@ -3,12 +3,18 @@ class REST::StatusEditSerializer < ActiveModel::Serializer has_one :account, serializer: REST::AccountSerializer - attributes :content, :spoiler_text, - :media_attachments_changed, :created_at + attributes :content, :spoiler_text, :sensitive, :created_at + has_many :ordered_media_attachments, key: :media_attachments, serializer: REST::MediaAttachmentSerializer has_many :emojis, serializer: REST::CustomEmojiSerializer + attribute :poll, if: -> { object.poll_options.present? } + def content Formatter.instance.format(object) end + + def poll + { options: object.poll_options.map { |title| { title: title } } } + end end diff --git a/app/serializers/rest/status_serializer.rb b/app/serializers/rest/status_serializer.rb index 7b5263eee4..0a00ed77ec 100644 --- a/app/serializers/rest/status_serializer.rb +++ b/app/serializers/rest/status_serializer.rb @@ -21,7 +21,7 @@ class REST::StatusSerializer < ActiveModel::Serializer belongs_to :application, if: :show_application? belongs_to :account, serializer: REST::AccountSerializer - has_many :media_attachments, serializer: REST::MediaAttachmentSerializer + has_many :ordered_media_attachments, key: :media_attachments, serializer: REST::MediaAttachmentSerializer has_many :ordered_mentions, key: :mentions has_many :tags has_many :emojis, serializer: REST::CustomEmojiSerializer diff --git a/app/services/activitypub/process_status_update_service.rb b/app/services/activitypub/process_status_update_service.rb index 7438a7c536..1260c0482a 100644 --- a/app/services/activitypub/process_status_update_service.rb +++ b/app/services/activitypub/process_status_update_service.rb @@ -76,13 +76,14 @@ class ActivityPub::ProcessStatusUpdateService < BaseService end end - removed_media_attachments = previous_media_attachments - next_media_attachments - added_media_attachments = next_media_attachments - previous_media_attachments + added_media_attachments = next_media_attachments - previous_media_attachments - MediaAttachment.where(id: removed_media_attachments.map(&:id)).update_all(status_id: nil) MediaAttachment.where(id: added_media_attachments.map(&:id)).update_all(status_id: @status.id) - @media_attachments_changed = true if removed_media_attachments.any? || added_media_attachments.any? + @status.ordered_media_attachment_ids = next_media_attachments.map(&:id) + @status.media_attachments.reload + + @media_attachments_changed = true if @status.ordered_media_attachment_ids_changed? end def update_poll! @@ -215,19 +216,13 @@ class ActivityPub::ProcessStatusUpdateService < BaseService return if @status.edits.any? - @status.snapshot!( - media_attachments_changed: false, - at_time: @status.created_at - ) + @status.snapshot!(at_time: @status.created_at, rate_limit: false) end def create_edit! return unless significant_changes? - @status.snapshot!( - media_attachments_changed: @media_attachments_changed || @poll_changed, - account_id: @account.id - ) + @status.snapshot!(account_id: @account.id, rate_limit: false) end def skip_download? diff --git a/app/services/fan_out_on_write_service.rb b/app/services/fan_out_on_write_service.rb index 08fae79358..f182cb83e1 100644 --- a/app/services/fan_out_on_write_service.rb +++ b/app/services/fan_out_on_write_service.rb @@ -118,7 +118,7 @@ class FanOutOnWriteService < BaseService Redis.current.publish('timeline:public', anonymous_payload) Redis.current.publish(@status.local? ? 'timeline:public:local' : 'timeline:public:remote', anonymous_payload) - if @status.media_attachments.any? + if @status.with_media? Redis.current.publish('timeline:public:media', anonymous_payload) Redis.current.publish(@status.local? ? 'timeline:public:local:media' : 'timeline:public:remote:media', anonymous_payload) end diff --git a/app/services/post_status_service.rb b/app/services/post_status_service.rb index c5061dd635..36592a531f 100644 --- a/app/services/post_status_service.rb +++ b/app/services/post_status_service.rb @@ -109,7 +109,10 @@ class PostStatusService < BaseService end def validate_media! - return if @options[:media_ids].blank? || !@options[:media_ids].is_a?(Enumerable) + if @options[:media_ids].blank? || !@options[:media_ids].is_a?(Enumerable) + @media = [] + return + end raise Mastodon::ValidationError, I18n.t('media_attachments.validations.too_many') if @options[:media_ids].size > 4 || @options[:poll].present? @@ -166,12 +169,13 @@ class PostStatusService < BaseService { text: @text, media_attachments: @media || [], + ordered_media_attachment_ids: (@options[:media_ids] || []).map(&:to_i) & @media.map(&:id), thread: @in_reply_to, poll_attributes: poll_attributes, sensitive: @sensitive, spoiler_text: @options[:spoiler_text] || '', visibility: @visibility, - language: valid_locale_or_nil(@options[:language].presence || @account.user&.preferred_posting_language || I18n.default_locale), + language: valid_locale_cascade(@options[:language], @account.user&.preferred_posting_language, I18n.default_locale), application: @options[:application], content_type: @options[:content_type] || @account.user&.setting_default_content_type, rate_limit: @options[:with_rate_limit], diff --git a/app/services/remove_status_service.rb b/app/services/remove_status_service.rb index 361cd4d822..c28e165725 100644 --- a/app/services/remove_status_service.rb +++ b/app/services/remove_status_service.rb @@ -40,7 +40,7 @@ class RemoveStatusService < BaseService remove_reblogs remove_from_hashtags remove_from_public - remove_from_media if @status.media_attachments.any? + remove_from_media if @status.with_media? remove_from_direct if status.direct_visibility? remove_media end diff --git a/app/services/update_status_service.rb b/app/services/update_status_service.rb index 6cbbd28766..f5155a2f52 100644 --- a/app/services/update_status_service.rb +++ b/app/services/update_status_service.rb @@ -18,8 +18,6 @@ class UpdateStatusService < BaseService @status = status @options = options @account_id = account_id - @media_attachments_changed = false - @poll_changed = false Status.transaction do create_previous_edit! @@ -42,14 +40,12 @@ class UpdateStatusService < BaseService def update_media_attachments! previous_media_attachments = @status.media_attachments.to_a next_media_attachments = validate_media! - removed_media_attachments = previous_media_attachments - next_media_attachments added_media_attachments = next_media_attachments - previous_media_attachments - MediaAttachment.where(id: removed_media_attachments.map(&:id)).update_all(status_id: nil) MediaAttachment.where(id: added_media_attachments.map(&:id)).update_all(status_id: @status.id) + @status.ordered_media_attachment_ids = (@options[:media_ids] || []).map(&:to_i) & next_media_attachments.map(&:id) @status.media_attachments.reload - @media_attachments_changed = true if removed_media_attachments.any? || added_media_attachments.any? end def validate_media! @@ -74,19 +70,18 @@ class UpdateStatusService < BaseService # If for some reasons the options were changed, it invalidates all previous # votes, so we need to remove them - @poll_changed = true if @options[:poll][:options] != poll.options || ActiveModel::Type::Boolean.new.cast(@options[:poll][:multiple]) != poll.multiple + poll_changed = true if @options[:poll][:options] != poll.options || ActiveModel::Type::Boolean.new.cast(@options[:poll][:multiple]) != poll.multiple poll.options = @options[:poll][:options] poll.hide_totals = @options[:poll][:hide_totals] || false poll.multiple = @options[:poll][:multiple] || false poll.expires_in = @options[:poll][:expires_in] - poll.reset_votes! if @poll_changed + poll.reset_votes! if poll_changed poll.save! @status.poll_id = poll.id elsif previous_poll.present? previous_poll.destroy - @poll_changed = true @status.poll_id = nil end end @@ -95,7 +90,7 @@ class UpdateStatusService < BaseService @status.text = @options[:text].presence || @options.delete(:spoiler_text) || '' if @options.key?(:text) @status.spoiler_text = @options[:spoiler_text] || '' if @options.key?(:spoiler_text) @status.sensitive = @options[:sensitive] || @options[:spoiler_text].present? if @options.key?(:sensitive) || @options.key?(:spoiler_text) - @status.language = valid_locale_or_nil(@options[:language] || @status.language || @status.account.user&.preferred_posting_language || I18n.default_locale) + @status.language = valid_locale_cascade(@options[:language], @status.language, @status.account.user&.preferred_posting_language, I18n.default_locale) @status.content_type = @options[:content_type] || @status.content_type @status.edited_at = Time.now.utc @@ -138,16 +133,10 @@ class UpdateStatusService < BaseService return if @status.edits.any? - @status.snapshot!( - media_attachments_changed: false, - at_time: @status.created_at - ) + @status.snapshot!(at_time: @status.created_at, rate_limit: false) end def create_edit! - @status.snapshot!( - media_attachments_changed: @media_attachments_changed || @poll_changed, - account_id: @account_id - ) + @status.snapshot!(account_id: @account_id) end end diff --git a/app/views/admin/domain_blocks/edit.html.haml b/app/views/admin/domain_blocks/edit.html.haml index c76a7a7f8c..15d70a39e5 100644 --- a/app/views/admin/domain_blocks/edit.html.haml +++ b/app/views/admin/domain_blocks/edit.html.haml @@ -21,10 +21,10 @@ = f.input :obfuscate, as: :boolean, wrapper: :with_label, label: I18n.t('admin.domain_blocks.obfuscate'), hint: I18n.t('admin.domain_blocks.obfuscate_hint') .field-group - = f.input :private_comment, wrapper: :with_label, label: I18n.t('admin.domain_blocks.private_comment'), hint: t('admin.domain_blocks.private_comment_hint'), rows: 6 + = f.input :private_comment, wrapper: :with_label, label: I18n.t('admin.domain_blocks.private_comment'), hint: t('admin.domain_blocks.private_comment_hint'), as: :string .field-group - = f.input :public_comment, wrapper: :with_label, label: I18n.t('admin.domain_blocks.public_comment'), hint: t('admin.domain_blocks.public_comment_hint'), rows: 6 + = f.input :public_comment, wrapper: :with_label, label: I18n.t('admin.domain_blocks.public_comment'), hint: t('admin.domain_blocks.public_comment_hint'), as: :string .actions = f.button :button, t('generic.save_changes'), type: :submit diff --git a/app/views/admin/domain_blocks/new.html.haml b/app/views/admin/domain_blocks/new.html.haml index b04ce7d9ca..0944573bf1 100644 --- a/app/views/admin/domain_blocks/new.html.haml +++ b/app/views/admin/domain_blocks/new.html.haml @@ -21,10 +21,10 @@ = f.input :obfuscate, as: :boolean, wrapper: :with_label, label: I18n.t('admin.domain_blocks.obfuscate'), hint: I18n.t('admin.domain_blocks.obfuscate_hint') .field-group - = f.input :private_comment, wrapper: :with_label, label: I18n.t('admin.domain_blocks.private_comment'), hint: t('admin.domain_blocks.private_comment_hint'), rows: 6 + = f.input :private_comment, wrapper: :with_label, label: I18n.t('admin.domain_blocks.private_comment'), hint: t('admin.domain_blocks.private_comment_hint'), as: :string .field-group - = f.input :public_comment, wrapper: :with_label, label: I18n.t('admin.domain_blocks.public_comment'), hint: t('admin.domain_blocks.public_comment_hint'), rows: 6 + = f.input :public_comment, wrapper: :with_label, label: I18n.t('admin.domain_blocks.public_comment'), hint: t('admin.domain_blocks.public_comment_hint'), as: :string .actions = f.button :button, t('.create'), type: :submit diff --git a/app/views/admin/domain_blocks/show.html.haml b/app/views/admin/domain_blocks/show.html.haml deleted file mode 100644 index e64aaa6295..0000000000 --- a/app/views/admin/domain_blocks/show.html.haml +++ /dev/null @@ -1,25 +0,0 @@ -- content_for :page_title do - = t('admin.domain_blocks.show.title', domain: @domain_block.domain) - -- if @domain_block.private_comment.present? - .speech-bubble - .speech-bubble__bubble - = simple_format(h(@domain_block.private_comment)) - .speech-bubble__owner= t 'admin.instances.private_comment' - -- if @domain_block.public_comment.present? - .speech-bubble - .speech-bubble__bubble - = simple_format(h(@domain_block.public_comment)) - .speech-bubble__owner= t 'admin.instances.public_comment' - -= simple_form_for @domain_block, url: admin_domain_block_path(@domain_block), method: :delete do |f| - - - unless (@domain_block.noop?) - %p= t(".retroactive.#{@domain_block.severity}") - %p.hint= t(:affected_accounts, - scope: [:admin, :domain_blocks, :show], - count: @domain_block.affected_accounts_count) - - .actions - = f.button :button, t('.undo'), type: :submit diff --git a/app/views/admin/instances/_exhausted_deliveries_days.haml b/app/views/admin/instances/_exhausted_deliveries_days.haml deleted file mode 100644 index e581f542dd..0000000000 --- a/app/views/admin/instances/_exhausted_deliveries_days.haml +++ /dev/null @@ -1,2 +0,0 @@ -%li.negative-hint - = l(exhausted_deliveries_days) diff --git a/app/views/admin/instances/_instance.html.haml b/app/views/admin/instances/_instance.html.haml index dc81007ac9..8a43960023 100644 --- a/app/views/admin/instances/_instance.html.haml +++ b/app/views/admin/instances/_instance.html.haml @@ -1,33 +1,15 @@ .directory__tag = link_to admin_instance_path(instance) do %h4 + = fa_icon 'warning fw' if instance.failing? = instance.domain + %small - if instance.domain_block - - first_item = true - - if !instance.domain_block.noop? - = t("admin.domain_blocks.severity.#{instance.domain_block.severity}") - - first_item = false - - unless instance.domain_block.suspend? - - if instance.domain_block.reject_media? - - unless first_item - • - = t('admin.domain_blocks.rejecting_media') - - first_item = false - - if instance.domain_block.reject_reports? - - unless first_item - • - = t('admin.domain_blocks.rejecting_reports') - - elsif whitelist_mode? + = instance.domain_block.policies.map { |policy| t(policy, scope: 'admin.instances.content_policies.policies') }.join(' • ') + - elsif instance.domain_allow = t('admin.accounts.whitelisted') - else = t('admin.accounts.no_limits_imposed') - - if instance.failure_days - = ' / ' - %span.negative-hint - = t('admin.instances.delivery.warning_message', count: instance.failure_days) - - if instance.unavailable_domain - = ' / ' - %span.negative-hint - = t('admin.instances.delivery.unavailable_message') + .trends__item__current{ title: t('admin.instances.known_accounts', count: instance.accounts_count) }= friendly_number_to_human instance.accounts_count diff --git a/app/views/admin/instances/index.html.haml b/app/views/admin/instances/index.html.haml index 797948d948..f8273718d4 100644 --- a/app/views/admin/instances/index.html.haml +++ b/app/views/admin/instances/index.html.haml @@ -17,22 +17,11 @@ %li= filter_link_to t('admin.instances.moderation.limited'), limited: '1' .filter-subset - %strong= t('admin.instances.delivery.title') + %strong= t('admin.instances.availability.title') %ul - %li= filter_link_to t('admin.instances.delivery.all'), warning: nil, unavailable: nil - %li= filter_link_to t('admin.instances.delivery.warning'), warning: '1', unavailable: nil - %li= filter_link_to t('admin.instances.delivery.unavailable'), warning: nil, unavailable: '1' - - .back-link - = link_to admin_instances_path() do - %i.fa.fa-chevron-left.fa-fw - = t('admin.instances.back_to_all') - = link_to admin_instances_path(limited: 1) do - %i.fa.fa-chevron-left.fa-fw - = t('admin.instances.back_to_limited') - = link_to admin_instances_path(warning: 1) do - %i.fa.fa-chevron-left.fa-fw - = t('admin.instances.back_to_warning') + %li= filter_link_to t('admin.instances.delivery.all'), availability: nil + %li= filter_link_to t('admin.instances.delivery.failing'), availability: 'failing' + %li= filter_link_to t('admin.instances.delivery.unavailable'), availability: 'unavailable' - unless whitelist_mode? = form_tag admin_instances_url, method: 'GET', class: 'simple_form' do diff --git a/app/views/admin/instances/show.html.haml b/app/views/admin/instances/show.html.haml index 4db8fd15cb..f4445f6b12 100644 --- a/app/views/admin/instances/show.html.haml +++ b/app/views/admin/instances/show.html.haml @@ -1,88 +1,92 @@ - content_for :page_title do = @instance.domain -.filters - .back-link - = link_to admin_instances_path() do - %i.fa.fa-chevron-left.fa-fw - = t('admin.instances.back_to_all') - = link_to admin_instances_path(limited: 1) do - %i.fa.fa-chevron-left.fa-fw - = t('admin.instances.back_to_limited') - = link_to admin_instances_path(warning: 1) do - %i.fa.fa-chevron-left.fa-fw - = t('admin.instances.back_to_warning') +- content_for :heading_actions do + = l(@time_period.first) + = ' - ' + = l(@time_period.last) -.dashboard__counters - %div - = link_to admin_accounts_path(origin: 'remote', by_domain: @instance.domain) do - .dashboard__counters__num= number_with_delimiter @instance.accounts_count - .dashboard__counters__label= t 'admin.accounts.title' - %div - = link_to admin_reports_path(by_target_domain: @instance.domain) do - .dashboard__counters__num= number_with_delimiter @instance.reports_count - .dashboard__counters__label= t 'admin.instances.total_reported' - %div - %div - .dashboard__counters__num= number_to_human_size @instance.media_storage - .dashboard__counters__label= t 'admin.instances.total_storage' - %div - %div - .dashboard__counters__num= number_with_delimiter @instance.following_count - .dashboard__counters__label= t 'admin.instances.total_followed_by_them' - %div - %div - .dashboard__counters__num= number_with_delimiter @instance.followers_count - .dashboard__counters__label= t 'admin.instances.total_followed_by_us' - %div - %div - .dashboard__counters__num= number_with_delimiter @instance.blocks_count - .dashboard__counters__label= t 'admin.instances.total_blocked_by_us' +%p + = fa_icon 'info fw' + = t('admin.instances.totals_time_period_hint_html') - %div - %div - .dashboard__counters__num - - if @instance.delivery_failure_tracker.available? - = fa_icon 'check' - - else - = fa_icon 'times' - .dashboard__counters__label= t 'admin.instances.delivery_available' - -- if @instance.private_comment.present? - .speech-bubble - .speech-bubble__bubble - = simple_format(h(@instance.private_comment)) - .speech-bubble__owner= t 'admin.instances.private_comment' - -- if @instance.public_comment.present? - .speech-bubble - .speech-bubble__bubble - = simple_format(h(@instance.public_comment)) - .speech-bubble__owner= t 'admin.instances.public_comment' - -- unless @exhausted_deliveries_days.empty? - %h4= t 'admin.instances.delivery_error_days' - %ul - = render partial: 'exhausted_deliveries_days', collection: @exhausted_deliveries_days - %p.hint - = t 'admin.instances.delivery_error_hint', count: DeliveryFailureTracker::FAILURE_DAYS_THRESHOLD +.dashboard + .dashboard__item + = react_admin_component :counter, measure: 'instance_accounts', start_at: @time_period.first, end_at: @time_period.last, params: { domain: @instance.domain }, label: t('admin.instances.dashboard.instance_accounts_measure'), href: admin_accounts_path(origin: 'remote', by_domain: @instance.domain) + .dashboard__item + = react_admin_component :counter, measure: 'instance_statuses', start_at: @time_period.first, end_at: @time_period.last, params: { domain: @instance.domain }, label: t('admin.instances.dashboard.instance_statuses_measure') + .dashboard__item + = react_admin_component :counter, measure: 'instance_media_attachments', start_at: @time_period.first, end_at: @time_period.last, params: { domain: @instance.domain }, label: t('admin.instances.dashboard.instance_media_attachments_measure') + .dashboard__item + = react_admin_component :counter, measure: 'instance_follows', start_at: @time_period.first, end_at: @time_period.last, params: { domain: @instance.domain }, label: t('admin.instances.dashboard.instance_follows_measure') + .dashboard__item + = react_admin_component :counter, measure: 'instance_followers', start_at: @time_period.first, end_at: @time_period.last, params: { domain: @instance.domain }, label: t('admin.instances.dashboard.instance_followers_measure') + .dashboard__item + = react_admin_component :counter, measure: 'instance_reports', start_at: @time_period.first, end_at: @time_period.last, params: { domain: @instance.domain }, label: t('admin.instances.dashboard.instance_reports_measure'), href: admin_reports_path(by_target_domain: @instance.domain) + .dashboard__item + = react_admin_component :dimension, dimension: 'instance_accounts', start_at: @time_period.first, end_at: @time_period.last, params: { domain: @instance.domain }, limit: 8, label: t('admin.instances.dashboard.instance_accounts_dimension') + .dashboard__item + = react_admin_component :dimension, dimension: 'instance_languages', start_at: @time_period.first, end_at: @time_period.last, params: { domain: @instance.domain }, limit: 8, label: t('admin.instances.dashboard.instance_languages_dimension') %hr.spacer/ -%div.action-buttons - %div - - if @instance.domain_allow - = link_to t('admin.domain_allows.undo'), admin_domain_allow_path(@instance.domain_allow), class: 'button button--destructive', data: { confirm: t('admin.accounts.are_you_sure'), method: :delete } - - elsif @instance.domain_block - = link_to t('admin.domain_blocks.edit'), edit_admin_domain_block_path(@instance.domain_block), class: 'button' - = link_to t('admin.domain_blocks.undo'), admin_domain_block_path(@instance.domain_block), class: 'button' +%h3= t('admin.instances.content_policies.title') + +- if whitelist_mode? + %p= t('admin.instances.content_policies.limited_federation_mode_description_html') + + - if @instance.domain_allow + = link_to t('admin.domain_allows.undo'), admin_domain_allow_path(@instance.domain_allow), class: 'button button--destructive', data: { confirm: t('admin.accounts.are_you_sure'), method: :delete } + - else + = link_to t('admin.domain_allows.add_new'), admin_domain_allows_path(domain_allow: { domain: @instance.domain }), class: 'button', method: :post +- else + %p= t('admin.instances.content_policies.description_html') + + - if @instance.domain_block + .table-wrapper + %table.table.horizontal-table + %tbody + %tr + %th= t('admin.instances.content_policies.comment') + %td= @instance.domain_block.private_comment + %tr + %th= t('admin.instances.content_policies.reason') + %td= @instance.domain_block.public_comment + %tr + %th= t('admin.instances.content_policies.policy') + %td= @instance.domain_block.policies.map { |policy| t(policy, scope: 'admin.instances.content_policies.policies') }.join(' • ') + + = link_to t('admin.domain_blocks.edit'), edit_admin_domain_block_path(@instance.domain_block), class: 'button' + = link_to t('admin.domain_blocks.undo'), admin_domain_block_path(@instance.domain_block), class: 'button', data: { confirm: t('admin.accounts.are_you_sure'), method: :delete } + - else + = link_to t('admin.domain_blocks.add_new'), new_admin_domain_block_path(_domain: @instance.domain), class: 'button' + +%hr.spacer/ + +%h3= t('admin.instances.availability.title') + +%p + = t('admin.instances.availability.description_html', count: DeliveryFailureTracker::FAILURE_DAYS_THRESHOLD) + +.availability-indicator + %ul.availability-indicator__graphic + - @instance.availability_over_days(14).each do |(date, failing)| + %li.availability-indicator__graphic__item{ class: failing ? 'negative' : 'neutral', title: l(date) } + .availability-indicator__hint + - if @instance.unavailable? + %span.negative-hint + = t('admin.instances.availability.failure_threshold_reached', date: l(@instance.unavailable_domain.created_at.to_date)) + = link_to t('admin.instances.delivery.restart'), restart_delivery_admin_instance_path(@instance), data: { confirm: t('admin.accounts.are_you_sure'), method: :post } + - elsif @instance.exhausted_deliveries_days.empty? + %span.positive-hint + = t('admin.instances.availability.no_failures_recorded') + = link_to t('admin.instances.delivery.stop'), stop_delivery_admin_instance_path(@instance), data: { confirm: t('admin.accounts.are_you_sure'), method: :post } - else - = link_to t('admin.domain_blocks.add_new'), new_admin_domain_block_path(_domain: @instance.domain), class: 'button' - - if @instance.delivery_failure_tracker.available? - - unless @exhausted_deliveries_days.empty? - = link_to t('admin.instances.delivery.clear'), clear_delivery_errors_admin_instance_path(@instance), data: { confirm: t('admin.accounts.are_you_sure'), method: :post }, class: 'button' - = link_to t('admin.instances.delivery.stop'), stop_delivery_admin_instance_path(@instance), data: { confirm: t('admin.accounts.are_you_sure'), method: :post }, class: 'button' - - else - = link_to t('admin.instances.delivery.restart'), restart_delivery_admin_instance_path(@instance), data: { confirm: t('admin.accounts.are_you_sure'), method: :post }, class: 'button' - - if !@instance.delivery_failure_tracker.available? || @instance.accounts_count.zero? || @instance.domain_block&.suspend? - = link_to t('admin.instances.purge'), admin_instance_path(@instance), data: { confirm: t('admin.instances.confirm_purge'), method: :delete }, class: 'button' + %span.negative-hint + = t('admin.instances.availability.failures_recorded', count: @instance.delivery_failure_tracker.days) + = link_to t('admin.instances.delivery.clear'), clear_delivery_errors_admin_instance_path(@instance), data: { confirm: t('admin.accounts.are_you_sure'), method: :post } unless @instance.exhausted_deliveries_days.empty? + +- if @instance.unavailable? + %p= t('admin.instances.purge_description_html') + + = link_to t('admin.instances.purge'), admin_instance_path(@instance), data: { confirm: t('admin.instances.confirm_purge'), method: :delete }, class: 'button button--destructive' diff --git a/app/views/admin/reports/_status.html.haml b/app/views/admin/reports/_status.html.haml index 4e06d4bbf0..1c033c4c34 100644 --- a/app/views/admin/reports/_status.html.haml +++ b/app/views/admin/reports/_status.html.haml @@ -11,15 +11,15 @@ %strong> Content warning: #{Formatter.instance.format_spoiler(status.proper)} = Formatter.instance.format(status.proper, custom_emojify: true) - - unless status.proper.media_attachments.empty? - - if status.proper.media_attachments.first.video? - - video = status.proper.media_attachments.first + - unless status.proper.ordered_media_attachments.empty? + - if status.proper.ordered_media_attachments.first.video? + - video = status.proper.ordered_media_attachments.first = react_component :video, src: video.file.url(:original), preview: video.file.url(:small), frameRate: video.file.meta.dig('original', 'frame_rate'), blurhash: video.blurhash, sensitive: status.proper.sensitive?, visible: false, width: 610, height: 343, inline: true, alt: video.description, media: [ActiveModelSerializers::SerializableResource.new(video, serializer: REST::MediaAttachmentSerializer)].as_json - - elsif status.proper.media_attachments.first.audio? - - audio = status.proper.media_attachments.first + - elsif status.proper.ordered_media_attachments.first.audio? + - audio = status.proper.ordered_media_attachments.first = react_component :audio, src: audio.file.url(:original), height: 110, alt: audio.description, duration: audio.file.meta.dig(:original, :duration) - else - = react_component :media_gallery, height: 343, sensitive: status.proper.sensitive?, visible: false, media: status.proper.media_attachments.map { |a| ActiveModelSerializers::SerializableResource.new(a, serializer: REST::MediaAttachmentSerializer).as_json } + = react_component :media_gallery, height: 343, sensitive: status.proper.sensitive?, visible: false, media: status.proper.ordered_media_attachments.map { |a| ActiveModelSerializers::SerializableResource.new(a, serializer: REST::MediaAttachmentSerializer).as_json } .detailed-status__meta - if status.application diff --git a/app/views/admin/reports/index.html.haml b/app/views/admin/reports/index.html.haml index 6191733733..248718a73d 100644 --- a/app/views/admin/reports/index.html.haml +++ b/app/views/admin/reports/index.html.haml @@ -59,11 +59,11 @@ %span.report-card__summary__item__content__icon{ title: t('admin.accounts.statuses') } = fa_icon('comment') - = report.statuses.count + = report.status_ids.size %span.report-card__summary__item__content__icon{ title: t('admin.accounts.media_attachments') } = fa_icon('camera') - = report.media_attachments.count + = report.media_attachments_count - if report.forwarded? · diff --git a/app/views/admin/trends/statuses/_status.html.haml b/app/views/admin/trends/statuses/_status.html.haml index edb27b9ff5..50a8553492 100644 --- a/app/views/admin/trends/statuses/_status.html.haml +++ b/app/views/admin/trends/statuses/_status.html.haml @@ -9,7 +9,7 @@ = link_to ActivityPub::TagManager.instance.url_for(status), target: '_blank', class: 'emojify', rel: 'noopener noreferrer' do = one_line_preview(status) - - status.media_attachments.each do |media_attachment| + - status.ordered_media_attachments.each do |media_attachment| %abbr{ title: media_attachment.description } = fa_icon 'link' = media_attachment.file_file_name diff --git a/app/views/disputes/strikes/show.html.haml b/app/views/disputes/strikes/show.html.haml index 7248b25741..0fc32b9186 100644 --- a/app/views/disputes/strikes/show.html.haml +++ b/app/views/disputes/strikes/show.html.haml @@ -53,7 +53,7 @@ = link_to short_account_status_url(@strike.target_account, status_id), class: 'emojify' do = one_line_preview(status) - - status.media_attachments.each do |media_attachment| + - status.ordered_media_attachments.each do |media_attachment| %abbr{ title: media_attachment.description } = fa_icon 'link' = media_attachment.file_file_name diff --git a/app/views/notification_mailer/_status.html.haml b/app/views/notification_mailer/_status.html.haml index 31460a76e1..f520208e11 100644 --- a/app/views/notification_mailer/_status.html.haml +++ b/app/views/notification_mailer/_status.html.haml @@ -33,9 +33,9 @@ %div.auto-dir = Formatter.instance.format(status) - - if status.media_attachments.size > 0 + - if status.ordered_media_attachments.size > 0 %p - - status.media_attachments.each do |a| + - status.ordered_media_attachments.each do |a| - if status.local? = link_to full_asset_url(a.file.url(:original)), full_asset_url(a.file.url(:original)) - else diff --git a/app/views/statuses/_detailed_status.html.haml b/app/views/statuses/_detailed_status.html.haml index 1922f53ce3..6ccf3725a6 100644 --- a/app/views/statuses/_detailed_status.html.haml +++ b/app/views/statuses/_detailed_status.html.haml @@ -25,10 +25,10 @@ - if status.preloadable_poll = render_poll_component(status) - - if !status.media_attachments.empty? - - if status.media_attachments.first.video? + - if !status.ordered_media_attachments.empty? + - if status.ordered_media_attachments.first.video? = render_video_component(status, width: 670, height: 380, detailed: true) - - elsif status.media_attachments.first.audio? + - elsif status.ordered_media_attachments.first.audio? = render_audio_component(status, width: 670, height: 380) - else = render_media_gallery_component(status, height: 380, standalone: true) diff --git a/app/views/statuses/_og_image.html.haml b/app/views/statuses/_og_image.html.haml index c8b6147ef7..5a647531ab 100644 --- a/app/views/statuses/_og_image.html.haml +++ b/app/views/statuses/_og_image.html.haml @@ -1,6 +1,6 @@ - if activity.is_a?(Status) && (activity.non_sensitive_with_media? || (activity.with_media? && Setting.preview_sensitive_media)) - player_card = false - - activity.media_attachments.each do |media| + - activity.ordered_media_attachments.each do |media| - if media.image? = opengraph 'og:image', full_asset_url(media.file.url(:original)) = opengraph 'og:image:type', media.file_content_type diff --git a/app/views/statuses/_simple_status.html.haml b/app/views/statuses/_simple_status.html.haml index b1e79a1cc6..67c6dfc7d5 100644 --- a/app/views/statuses/_simple_status.html.haml +++ b/app/views/statuses/_simple_status.html.haml @@ -37,10 +37,10 @@ - if status.preloadable_poll = render_poll_component(status) - - if !status.media_attachments.empty? - - if status.media_attachments.first.video? + - if !status.ordered_media_attachments.empty? + - if status.ordered_media_attachments.first.video? = render_video_component(status, width: 610, height: 343) - - elsif status.media_attachments.first.audio? + - elsif status.ordered_media_attachments.first.audio? = render_audio_component(status, width: 610, height: 343) - else = render_media_gallery_component(status, height: 343) diff --git a/app/views/user_mailer/warning.text.erb b/app/views/user_mailer/warning.text.erb index 31d7308aea..1f410f4414 100644 --- a/app/views/user_mailer/warning.text.erb +++ b/app/views/user_mailer/warning.text.erb @@ -32,4 +32,5 @@ --- <% end %> -<%= t 'user_mailer.warning.get_in_touch', instance: @instance %> +<%= t 'user_mailer.warning.appeal_description', instance: @instance %> +<%= disputes_strike_url(@warning) %> diff --git a/app/workers/admin/domain_purge_worker.rb b/app/workers/admin/domain_purge_worker.rb index 7cba2c89e6..095232a6d7 100644 --- a/app/workers/admin/domain_purge_worker.rb +++ b/app/workers/admin/domain_purge_worker.rb @@ -3,6 +3,8 @@ class Admin::DomainPurgeWorker include Sidekiq::Worker + sidekiq_options queue: 'pull', lock: :until_executed + def perform(domain) PurgeDomainService.new.call(domain) end diff --git a/config/initializers/omniauth.rb b/config/initializers/omniauth.rb index 1a041ad481..51241e5460 100644 --- a/config/initializers/omniauth.rb +++ b/config/initializers/omniauth.rb @@ -8,7 +8,8 @@ Devise.setup do |config| # CAS strategy if ENV['CAS_ENABLED'] == 'true' - cas_options = options + cas_options = {} + cas_options[:display_name] = ENV['CAS_DISPLAY_NAME'] || 'cas' cas_options[:url] = ENV['CAS_URL'] if ENV['CAS_URL'] cas_options[:host] = ENV['CAS_HOST'] if ENV['CAS_HOST'] cas_options[:port] = ENV['CAS_PORT'] if ENV['CAS_PORT'] @@ -36,7 +37,8 @@ Devise.setup do |config| # SAML strategy if ENV['SAML_ENABLED'] == 'true' - saml_options = options + saml_options = {} + saml_options[:display_name] = ENV['SAML_DISPLAY_NAME'] || 'saml' saml_options[:assertion_consumer_service_url] = ENV['SAML_ACS_URL'] if ENV['SAML_ACS_URL'] saml_options[:issuer] = ENV['SAML_ISSUER'] if ENV['SAML_ISSUER'] saml_options[:idp_sso_target_url] = ENV['SAML_IDP_SSO_TARGET_URL'] if ENV['SAML_IDP_SSO_TARGET_URL'] @@ -64,4 +66,39 @@ Devise.setup do |config| saml_options[:allowed_clock_drift] = ENV['SAML_ALLOWED_CLOCK_DRIFT'] if ENV['SAML_ALLOWED_CLOCK_DRIFT'] config.omniauth :saml, saml_options end + + # OpenID Connect Strategy + if ENV['OIDC_ENABLED'] == 'true' + oidc_options = {} + oidc_options[:display_name] = ENV['OIDC_DISPLAY_NAME'] || 'openid_connect' #OPTIONAL + oidc_options[:issuer] = ENV['OIDC_ISSUER'] if ENV['OIDC_ISSUER'] #NEED + oidc_options[:discovery] = ENV['OIDC_DISCOVERY'] == 'true' if ENV['OIDC_DISCOVERY'] #OPTIONAL (default: false) + oidc_options[:client_auth_method] = ENV['OIDC_CLIENT_AUTH_METHOD'] if ENV['OIDC_CLIENT_AUTH_METHOD'] #OPTIONAL (default: basic) + scope_string = ENV['OIDC_SCOPE'] if ENV['OIDC_SCOPE'] #NEED + scopes = scope_string.split(',') + oidc_options[:scope] = scopes.map { |x| x.to_sym } + oidc_options[:response_type] = ENV['OIDC_RESPONSE_TYPE'] if ENV['OIDC_RESPONSE_TYPE'] #OPTIONAL (default: code) + oidc_options[:response_mode] = ENV['OIDC_RESPONSE_MODE'] if ENV['OIDC_RESPONSE_MODE'] #OPTIONAL (default: query) + oidc_options[:display] = ENV['OIDC_DISPLAY'] if ENV['OIDC_DISPLAY'] #OPTIONAL (default: page) + oidc_options[:prompt] = ENV['OIDC_PROMPT'] if ENV['OIDC_PROMPT'] #OPTIONAL + oidc_options[:send_nonce] = ENV['OIDC_SEND_NONCE'] == 'true' if ENV['OIDC_SEND_NONCE'] #OPTIONAL (default: true) + oidc_options[:send_scope_to_token_endpoint] = ENV['OIDC_SEND_SCOPE_TO_TOKEN_ENDPOINT'] == 'true' if ENV['OIDC_SEND_SCOPE_TO_TOKEN_ENDPOINT'] #OPTIONAL (default: true) + oidc_options[:post_logout_redirect_uri] = ENV['OIDC_IDP_LOGOUT_REDIRECT_URI'] if ENV['OIDC_IDP_LOGOUT_REDIRECT_URI'] #OPTIONAL + oidc_options[:uid_field] = ENV['OIDC_UID_FIELD'] if ENV['OIDC_UID_FIELD'] #NEED + oidc_options[:client_options] = {} + oidc_options[:client_options][:identifier] = ENV['OIDC_CLIENT_ID'] if ENV['OIDC_CLIENT_ID'] #NEED + oidc_options[:client_options][:secret] = ENV['OIDC_CLIENT_SECRET'] if ENV['OIDC_CLIENT_SECRET'] #NEED + oidc_options[:client_options][:redirect_uri] = ENV['OIDC_REDIRECT_URI'] if ENV['OIDC_REDIRECT_URI'] #NEED + oidc_options[:client_options][:scheme] = ENV['OIDC_HTTP_SCHEME'] if ENV['OIDC_HTTP_SCHEME'] #OPTIONAL (default: https) + oidc_options[:client_options][:host] = ENV['OIDC_HOST'] if ENV['OIDC_HOST'] #OPTIONAL + oidc_options[:client_options][:port] = ENV['OIDC_PORT'] if ENV['OIDC_PORT'] #OPTIONAL + oidc_options[:client_options][:authorization_endpoint] = ENV['OIDC_AUTH_ENDPOINT'] if ENV['OIDC_AUTH_ENDPOINT'] #NEED when discovery != true + oidc_options[:client_options][:token_endpoint] = ENV['OIDC_TOKEN_ENDPOINT'] if ENV['OIDC_TOKEN_ENDPOINT'] #NEED when discovery != true + oidc_options[:client_options][:userinfo_endpoint] = ENV['OIDC_USER_INFO_ENDPOINT'] if ENV['OIDC_USER_INFO_ENDPOINT'] #NEED when discovery != true + oidc_options[:client_options][:jwks_uri] = ENV['OIDC_JWKS_URI'] if ENV['OIDC_JWKS_URI'] #NEED when discovery != true + oidc_options[:client_options][:end_session_endpoint] = ENV['OIDC_END_SESSION_ENDPOINT'] if ENV['OIDC_END_SESSION_ENDPOINT'] #OPTIONAL + oidc_options[:security] = {} + oidc_options[:security][:assume_email_is_verified] = ENV['OIDC_SECURITY_ASSUME_EMAIL_IS_VERIFIED'] == 'true' #OPTIONAL + config.omniauth :openid_connect, oidc_options + end end diff --git a/config/locales/en.yml b/config/locales/en.yml index 1964285b05..8f6100129c 100644 --- a/config/locales/en.yml +++ b/config/locales/en.yml @@ -450,21 +450,6 @@ en: reject_media_hint: Removes locally stored media files and refuses to download any in the future. Irrelevant for suspensions reject_reports: Reject reports reject_reports_hint: Ignore all reports coming from this domain. Irrelevant for suspensions - rejecting_media: rejecting media files - rejecting_reports: rejecting reports - severity: - silence: limited - suspend: suspended - show: - affected_accounts: - one: One account in the database affected - other: "%{count} accounts in the database affected" - zero: No account in the database is affected - retroactive: - silence: Undo limit of existing affected accounts from this domain - suspend: Unsuspend existing affected accounts from this domain - title: Undo domain block for %{domain} - undo: Undo undo: Undo domain block view: View domain block email_domain_blocks: @@ -495,23 +480,47 @@ en: title: Follow recommendations unsuppress: Restore follow recommendation instances: + 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. + other: If delivering to the domain fails on %{count} different days without succeeding, no further delivery attempts will be made unless a delivery from the domain is received. + failure_threshold_reached: Failure threshold reached on %{date}. + failures_recorded: + one: Failed attempt on %{count} day. + other: Failed attempts on %{count} different days. + no_failures_recorded: No failures on record. + title: Availability back_to_all: All back_to_limited: Limited back_to_warning: Warning by_domain: Domain confirm_purge: Are you sure you want to permanently delete data from this domain? + content_policies: + comment: Internal note + description_html: You can define content policies that will be applied to all accounts from this domain and any of its subdomains. + policies: + reject_media: Reject media + reject_reports: Reject reports + silence: Limit + suspend: Suspend + policy: Policy + reason: Public reason + title: Content policies + dashboard: + instance_accounts_dimension: Most followed accounts + instance_accounts_measure: stored accounts + instance_followers_measure: our followers there + instance_follows_measure: their followers here + instance_languages_dimension: Top languages + instance_media_attachments_measure: stored media attachments + instance_reports_measure: reports about them + instance_statuses_measure: stored posts delivery: all: All clear: Clear delivery errors restart: Restart delivery stop: Stop delivery - title: Delivery unavailable: Unavailable - unavailable_message: Delivery unavailable - warning: Warning - warning_message: - one: Delivery failure %{count} day - other: Delivery failure %{count} days delivery_available: Delivery is available delivery_error_days: Delivery error days delivery_error_hint: If delivery is not possible for %{count} days, it will be automatically marked as undeliverable. @@ -528,12 +537,14 @@ en: private_comment: Private comment public_comment: Public comment purge: Purge + purge_description_html: If you believe this domain is offline for good, you can delete all account records and associated data from this domain from your storage. This may take a while. title: Federation total_blocked_by_us: Blocked by us total_followed_by_them: Followed by them total_followed_by_us: Followed by us total_reported: Reports about them total_storage: Media attachments + totals_time_period_hint_html: The totals displayed below include data for all time. invites: deactivate_all: Deactivate all filter: @@ -1640,7 +1651,6 @@ en: sensitive: From now on, all your uploaded media files will be marked as sensitive and hidden behind a click-through warning. silence: You can still use your account but only people who are already following you will see your posts on this server, and you may be excluded from various discovery features. However, others may still manually follow you. suspend: You can no longer use your account, and your profile and other data are no longer accessible. You can still login to request a backup of your data until the data is fully removed in about 30 days, but we will retain some basic data to prevent you from evading the suspension. - get_in_touch: If you believe this is an error, you can reply to this e-mail to get in touch with the staff of %{instance}. reason: 'Reason:' statuses: 'Posts cited:' subject: diff --git a/config/routes.rb b/config/routes.rb index 3449fa03da..4ed2ee760c 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -194,7 +194,7 @@ Rails.application.routes.draw do get '/dashboard', to: 'dashboard#index' resources :domain_allows, only: [:new, :create, :show, :destroy] - resources :domain_blocks, only: [:new, :create, :show, :destroy, :update, :edit] + resources :domain_blocks, only: [:new, :create, :destroy, :update, :edit] resources :email_domain_blocks, only: [:index, :new, :create] do collection do diff --git a/db/migrate/20220302232632_add_ordered_media_attachment_ids_to_statuses.rb b/db/migrate/20220302232632_add_ordered_media_attachment_ids_to_statuses.rb new file mode 100644 index 0000000000..5443f32a2e --- /dev/null +++ b/db/migrate/20220302232632_add_ordered_media_attachment_ids_to_statuses.rb @@ -0,0 +1,5 @@ +class AddOrderedMediaAttachmentIdsToStatuses < ActiveRecord::Migration[6.1] + def change + add_column :statuses, :ordered_media_attachment_ids, :bigint, array: true + end +end diff --git a/db/migrate/20220303000827_add_ordered_media_attachment_ids_to_status_edits.rb b/db/migrate/20220303000827_add_ordered_media_attachment_ids_to_status_edits.rb new file mode 100644 index 0000000000..b1071f3593 --- /dev/null +++ b/db/migrate/20220303000827_add_ordered_media_attachment_ids_to_status_edits.rb @@ -0,0 +1,8 @@ +class AddOrderedMediaAttachmentIdsToStatusEdits < ActiveRecord::Migration[6.1] + def change + add_column :status_edits, :ordered_media_attachment_ids, :bigint, array: true + add_column :status_edits, :media_descriptions, :text, array: true + add_column :status_edits, :poll_options, :string, array: true + add_column :status_edits, :sensitive, :boolean + end +end diff --git a/db/migrate/20220307094650_fix_featured_tags_constraints.rb b/db/migrate/20220307094650_fix_featured_tags_constraints.rb new file mode 100644 index 0000000000..bad1c90d41 --- /dev/null +++ b/db/migrate/20220307094650_fix_featured_tags_constraints.rb @@ -0,0 +1,17 @@ +class FixFeaturedTagsConstraints < ActiveRecord::Migration[6.1] + def up + safety_assured do + execute 'DELETE FROM featured_tags WHERE tag_id IS NULL' + change_column_null :featured_tags, :tag_id, false + execute 'DELETE FROM featured_tags WHERE account_id IS NULL' + change_column_null :featured_tags, :account_id, false + end + end + + def down + safety_assured do + change_column_null :featured_tags, :tag_id, true + change_column_null :featured_tags, :account_id, true + end + end +end diff --git a/db/migrate/20220309213005_fix_reblog_deleted_at.rb b/db/migrate/20220309213005_fix_reblog_deleted_at.rb new file mode 100644 index 0000000000..8ec1813d95 --- /dev/null +++ b/db/migrate/20220309213005_fix_reblog_deleted_at.rb @@ -0,0 +1,9 @@ +class FixReblogDeletedAt < ActiveRecord::Migration[6.1] + disable_ddl_transaction! + + def up + safety_assured { execute 'UPDATE statuses s SET deleted_at = r.deleted_at FROM statuses r WHERE s.reblog_of_id = r.id AND r.deleted_at IS NOT NULL' } + end + + def down; end +end diff --git a/db/post_migrate/20220303203437_remove_media_attachments_changed_from_status_edits.rb b/db/post_migrate/20220303203437_remove_media_attachments_changed_from_status_edits.rb new file mode 100644 index 0000000000..09725c74ec --- /dev/null +++ b/db/post_migrate/20220303203437_remove_media_attachments_changed_from_status_edits.rb @@ -0,0 +1,7 @@ +# frozen_string_literal: true + +class RemoveMediaAttachmentsChangedFromStatusEdits < ActiveRecord::Migration[5.2] + def change + safety_assured { remove_column :status_edits, :media_attachments_changed, :boolean, default: false, null: false } + end +end diff --git a/db/schema.rb b/db/schema.rb index f8d85901d9..3f51b85d53 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.define(version: 2022_03_04_195405) do +ActiveRecord::Schema.define(version: 2022_03_09_213005) do # These are extensions that must be enabled in order to support this database enable_extension "plpgsql" @@ -391,7 +391,6 @@ ActiveRecord::Schema.define(version: 2022_03_04_195405) do t.bigint "parent_id" t.inet "ips", array: true t.datetime "last_refresh_at" - t.index ["domain"], name: "index_email_domain_blocks_on_domain", unique: true end @@ -420,8 +419,8 @@ ActiveRecord::Schema.define(version: 2022_03_04_195405) do end create_table "featured_tags", force: :cascade do |t| - t.bigint "account_id" - t.bigint "tag_id" + t.bigint "account_id", null: false + t.bigint "tag_id", null: false t.bigint "statuses_count", default: 0, null: false t.datetime "last_status_at" t.datetime "created_at", null: false @@ -845,10 +844,13 @@ ActiveRecord::Schema.define(version: 2022_03_04_195405) do t.bigint "account_id" t.text "text", default: "", null: false t.text "spoiler_text", default: "", null: false - t.boolean "media_attachments_changed", default: false, null: false t.datetime "created_at", precision: 6, null: false t.datetime "updated_at", precision: 6, null: false t.string "content_type" + t.bigint "ordered_media_attachment_ids", array: true + t.text "media_descriptions", array: true + t.string "poll_options", array: true + t.boolean "sensitive" t.index ["account_id"], name: "index_status_edits_on_account_id" t.index ["status_id"], name: "index_status_edits_on_status_id" end @@ -895,6 +897,7 @@ ActiveRecord::Schema.define(version: 2022_03_04_195405) do t.datetime "deleted_at" t.datetime "edited_at" t.boolean "trendable" + t.bigint "ordered_media_attachment_ids", array: true t.index ["account_id", "id", "visibility", "updated_at"], name: "index_statuses_20190820", order: { id: :desc }, where: "(deleted_at IS NULL)" t.index ["deleted_at"], name: "index_statuses_on_deleted_at", where: "(deleted_at IS NOT NULL)" t.index ["id", "account_id"], name: "index_statuses_local_20190824", order: { id: :desc }, where: "((local OR (uri IS NULL)) AND (deleted_at IS NULL) AND (visibility = 0) AND (reblog_of_id IS NULL) AND ((NOT reply) OR (in_reply_to_account_id = account_id)))" diff --git a/package.json b/package.json index 96aab9ef1e..463d47a8a2 100644 --- a/package.json +++ b/package.json @@ -61,7 +61,7 @@ }, "private": true, "dependencies": { - "@babel/core": "^7.17.2", + "@babel/core": "^7.17.5", "@babel/plugin-proposal-decorators": "^7.17.2", "@babel/plugin-transform-react-inline-elements": "^7.16.7", "@babel/plugin-transform-runtime": "^7.17.0", @@ -82,7 +82,7 @@ "babel-plugin-react-intl": "^6.2.0", "babel-plugin-transform-react-remove-prop-types": "^0.4.24", "babel-runtime": "^6.26.0", - "blurhash": "^1.1.4", + "blurhash": "^1.1.5", "classnames": "^2.3.1", "color-blend": "^3.0.1", "compression-webpack-plugin": "^6.1.1", @@ -95,7 +95,7 @@ "es6-symbol": "^3.1.3", "escape-html": "^1.0.3", "exif-js": "^2.3.0", - "express": "^4.17.1", + "express": "^4.17.3", "favico.js": "^0.3.10", "file-loader": "^6.2.0", "font-awesome": "^4.7.0", @@ -112,7 +112,7 @@ "js-yaml": "^4.1.0", "lodash": "^4.17.21", "mark-loader": "^0.1.6", - "marky": "^1.2.2", + "marky": "^1.2.4", "mini-css-extract-plugin": "^1.6.2", "mkdirp": "^1.0.4", "npmlog": "^6.0.1", @@ -176,14 +176,14 @@ }, "devDependencies": { "@testing-library/jest-dom": "^5.16.2", - "@testing-library/react": "^12.1.2", + "@testing-library/react": "^12.1.3", "babel-eslint": "^10.1.0", "babel-jest": "^27.5.1", "eslint": "^7.32.0", "eslint-plugin-import": "~2.25.4", "eslint-plugin-jsx-a11y": "~6.5.1", "eslint-plugin-promise": "~6.0.0", - "eslint-plugin-react": "~7.29.2", + "eslint-plugin-react": "~7.29.3", "jest": "^27.5.1", "raf": "^3.4.1", "react-intl-translations-manager": "^5.0.3", diff --git a/spec/controllers/admin/domain_blocks_controller_spec.rb b/spec/controllers/admin/domain_blocks_controller_spec.rb index fb23658c01..ecc79292b4 100644 --- a/spec/controllers/admin/domain_blocks_controller_spec.rb +++ b/spec/controllers/admin/domain_blocks_controller_spec.rb @@ -16,15 +16,6 @@ RSpec.describe Admin::DomainBlocksController, type: :controller do end end - describe 'GET #show' do - it 'returns http success' do - domain_block = Fabricate(:domain_block) - get :show, params: { id: domain_block.id } - - expect(response).to have_http_status(200) - end - end - describe 'POST #create' do it 'blocks the domain when succeeded to save' do allow(DomainBlockWorker).to receive(:perform_async).and_return(true) diff --git a/spec/models/report_spec.rb b/spec/models/report_spec.rb index df32a7c9d5..874be41328 100644 --- a/spec/models/report_spec.rb +++ b/spec/models/report_spec.rb @@ -11,14 +11,13 @@ describe Report do end end - describe 'media_attachments' do - it 'returns media attachments from statuses' do - status = Fabricate(:status) - media_attachment = Fabricate(:media_attachment, status: status) - _other_media_attachment = Fabricate(:media_attachment) - report = Fabricate(:report, status_ids: [status.id]) + describe 'media_attachments_count' do + it 'returns count of media attachments in statuses' do + status1 = Fabricate(:status, ordered_media_attachment_ids: [1, 2]) + status2 = Fabricate(:status, ordered_media_attachment_ids: [5]) + report = Fabricate(:report, status_ids: [status1.id, status2.id]) - expect(report.media_attachments).to eq [media_attachment] + expect(report.media_attachments_count).to eq 3 end end diff --git a/spec/services/activitypub/process_collection_service_spec.rb b/spec/services/activitypub/process_collection_service_spec.rb index 00d71a86ab..3eccaab5bb 100644 --- a/spec/services/activitypub/process_collection_service_spec.rb +++ b/spec/services/activitypub/process_collection_service_spec.rb @@ -91,6 +91,146 @@ RSpec.describe ActivityPub::ProcessCollectionService, type: :service do subject.call(json, forwarder) end + + context 'when receiving a fabricated status' do + let!(:actor) do + Fabricate(:account, + username: 'bob', + domain: 'example.com', + uri: 'https://example.com/users/bob', + public_key: "-----BEGIN PUBLIC KEY-----\nMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAuuYyoyfsRkYnXRotMsId\nW3euBDDfiv9oVqOxUVC7bhel8KednIMrMCRWFAkgJhbrlzbIkjVr68o1MP9qLcn7\nCmH/BXHp7yhuFTr4byjdJKpwB+/i2jNEsvDH5jR8WTAeTCe0x/QHg21V3F7dSI5m\nCCZ/1dSIyOXLRTWVlfDlm3rE4ntlCo+US3/7oSWbg/4/4qEnt1HC32kvklgScxua\n4LR5ATdoXa5bFoopPWhul7MJ6NyWCyQyScUuGdlj8EN4kmKQJvphKHrI9fvhgOuG\nTvhTR1S5InA4azSSchY0tXEEw/VNxraeX0KPjbgr6DPcwhPd/m0nhVDq0zVyVBBD\nMwIDAQAB\n-----END PUBLIC KEY-----\n", + private_key: nil) + end + + let(:payload) do + { + '@context': [ + 'https://www.w3.org/ns/activitystreams', + nil, + {'object': 'https://www.w3.org/ns/activitystreams#object'} + ], + 'id': 'https://example.com/users/bob/fake-status/activity', + 'type': 'Create', + 'actor': 'https://example.com/users/bob', + 'published': '2022-01-22T15:00:00Z', + 'to': [ + 'https://www.w3.org/ns/activitystreams#Public' + ], + 'cc': [ + 'https://example.com/users/bob/followers' + ], + 'signature': { + 'type': 'RsaSignature2017', + 'creator': 'https://example.com/users/bob#main-key', + 'created': '2022-03-09T21:57:25Z', + 'signatureValue': 'WculK0LelTQ0MvGwU9TPoq5pFzFfGYRDCJqjZ232/Udj4CHqDTGOSw5UTDLShqBOyycCkbZGrQwXG+dpyDpQLSe1UVPZ5TPQtc/9XtI57WlS2nMNpdvRuxGnnb2btPdesXZ7n3pCxo0zjaXrJMe0mqQh5QJO22mahb4bDwwmfTHgbD3nmkD+fBfGi+UV2qWwqr+jlV4L4JqNkh0gWljF5KTePLRRZCuWiQ/FAt7c67636cdIPf7fR+usjuZltTQyLZKEGuK8VUn2Gkfsx5qns7Vcjvlz1JqlAjyO8HPBbzTTHzUG2nUOIgC3PojCSWv6mNTmRGoLZzOscCAYQA6cKw==' + }, + '@id': 'https://example.com/users/bob/statuses/107928807471117876/activity', + '@type': 'https://www.w3.org/ns/activitystreams#Create', + 'https://www.w3.org/ns/activitystreams#actor': { + '@id': 'https://example.com/users/bob' + }, + 'https://www.w3.org/ns/activitystreams#cc': { + '@id': 'https://example.com/users/bob/followers' + }, + 'object': { + 'id': 'https://example.com/users/bob/fake-status', + 'type': 'Note', + 'published': '2022-01-22T15:00:00Z', + 'url': 'https://www.youtube.com/watch?v=dQw4w9WgXcQ&feature=puck-was-here', + 'attributedTo': 'https://example.com/users/bob', + 'to': [ + 'https://www.w3.org/ns/activitystreams#Public' + ], + 'cc': [ + 'https://example.com/users/bob/followers' + ], + 'sensitive': false, + 'atomUri': 'https://example.com/users/bob/fake-status', + 'conversation': 'tag:example.com,2022-03-09:objectId=15:objectType=Conversation', + 'content': '

puck was here

', + + '@id': 'https://example.com/users/bob/statuses/107928807471117876', + '@type': 'https://www.w3.org/ns/activitystreams#Note', + 'http://ostatus.org#atomUri': 'https://example.com/users/bob/statuses/107928807471117876', + 'http://ostatus.org#conversation': 'tag:example.com,2022-03-09:objectId=15:objectType=Conversation', + 'https://www.w3.org/ns/activitystreams#attachment': [], + 'https://www.w3.org/ns/activitystreams#attributedTo': { + '@id': 'https://example.com/users/bob' + }, + 'https://www.w3.org/ns/activitystreams#cc': { + '@id': 'https://example.com/users/bob/followers' + }, + 'https://www.w3.org/ns/activitystreams#content': [ + '

hello world

', + { + '@value': '

hello world

', + '@language': 'en' + } + ], + 'https://www.w3.org/ns/activitystreams#published': { + '@type': 'http://www.w3.org/2001/XMLSchema#dateTime', + '@value': '2022-03-09T21:55:07Z' + }, + 'https://www.w3.org/ns/activitystreams#replies': { + '@id': 'https://example.com/users/bob/statuses/107928807471117876/replies', + '@type': 'https://www.w3.org/ns/activitystreams#Collection', + 'https://www.w3.org/ns/activitystreams#first': { + '@type': 'https://www.w3.org/ns/activitystreams#CollectionPage', + 'https://www.w3.org/ns/activitystreams#items': [], + 'https://www.w3.org/ns/activitystreams#next': { + '@id': 'https://example.com/users/bob/statuses/107928807471117876/replies?only_other_accounts=true&page=true' + }, + 'https://www.w3.org/ns/activitystreams#partOf': { + '@id': 'https://example.com/users/bob/statuses/107928807471117876/replies' + } + } + }, + 'https://www.w3.org/ns/activitystreams#sensitive': false, + 'https://www.w3.org/ns/activitystreams#tag': [], + 'https://www.w3.org/ns/activitystreams#to': { + '@id': 'https://www.w3.org/ns/activitystreams#Public' + }, + 'https://www.w3.org/ns/activitystreams#url': { + '@id': 'https://example.com/@bob/107928807471117876' + } + }, + 'https://www.w3.org/ns/activitystreams#published': { + '@type': 'http://www.w3.org/2001/XMLSchema#dateTime', + '@value': '2022-03-09T21:55:07Z' + }, + 'https://www.w3.org/ns/activitystreams#to': { + '@id': 'https://www.w3.org/ns/activitystreams#Public' + } + } + end + + it 'does not process forged payload' do + expect(ActivityPub::Activity).not_to receive(:factory).with( + hash_including( + 'object' => hash_including( + 'id' => 'https://example.com/users/bob/fake-status' + ) + ), + anything(), + anything() + ) + + expect(ActivityPub::Activity).not_to receive(:factory).with( + hash_including( + 'object' => hash_including( + 'content' => '

puck was here

' + ) + ), + anything(), + anything() + ) + + subject.call(json, forwarder) + + expect(Status.where(uri: 'https://example.com/users/bob/fake-status').exists?).to be false + end + end end end end diff --git a/spec/services/activitypub/process_status_update_service_spec.rb b/spec/services/activitypub/process_status_update_service_spec.rb index 6ee1dcb43a..40b405217d 100644 --- a/spec/services/activitypub/process_status_update_service_spec.rb +++ b/spec/services/activitypub/process_status_update_service_spec.rb @@ -124,7 +124,7 @@ RSpec.describe ActivityPub::ProcessStatusUpdateService, type: :service do end it 'updates media attachments' do - media_attachment = status.media_attachments.reload.first + media_attachment = status.reload.ordered_media_attachments.first expect(media_attachment).to_not be_nil expect(media_attachment.remote_url).to eq 'https://example.com/foo.png' @@ -135,7 +135,7 @@ RSpec.describe ActivityPub::ProcessStatusUpdateService, type: :service do end it 'records media change in edit' do - expect(status.edits.reload.last.media_attachments_changed).to be true + expect(status.edits.reload.last.ordered_media_attachment_ids).to_not be_empty end end @@ -173,11 +173,11 @@ RSpec.describe ActivityPub::ProcessStatusUpdateService, type: :service do end it 'updates media attachments' do - expect(status.media_attachments.reload.map(&:remote_url)).to eq %w(https://example.com/foo.png) + expect(status.ordered_media_attachments.map(&:remote_url)).to eq %w(https://example.com/foo.png) end it 'records media change in edit' do - expect(status.edits.reload.last.media_attachments_changed).to be true + expect(status.edits.reload.last.ordered_media_attachment_ids).to_not be_empty end end @@ -193,7 +193,7 @@ RSpec.describe ActivityPub::ProcessStatusUpdateService, type: :service do end it 'records media change in edit' do - expect(status.edits.reload.last.media_attachments_changed).to be true + expect(status.edits.reload.last.poll_options).to be_nil end end @@ -226,7 +226,7 @@ RSpec.describe ActivityPub::ProcessStatusUpdateService, type: :service do end it 'records media change in edit' do - expect(status.edits.reload.last.media_attachments_changed).to be true + expect(status.edits.reload.last.poll_options).to eq %w(Foo Bar Baz) end end @@ -239,10 +239,5 @@ RSpec.describe ActivityPub::ProcessStatusUpdateService, type: :service do subject.call(status, json) expect(status.reload.edited_at.to_s).to eq '2021-09-08 22:39:25 UTC' end - - it 'records that no media has been changed in edit' do - subject.call(status, json) - expect(status.edits.reload.last.media_attachments_changed).to be false - end end end diff --git a/spec/services/reblog_service_spec.rb b/spec/services/reblog_service_spec.rb index e2077f282a..c0ae5eedcc 100644 --- a/spec/services/reblog_service_spec.rb +++ b/spec/services/reblog_service_spec.rb @@ -32,6 +32,18 @@ RSpec.describe ReblogService, type: :service do end end + context 'when the reblogged status is discarded in the meantime' do + let(:status) { Fabricate(:status, account: alice, visibility: :public) } + + before do + status.discard + end + + it 'raises an exception' do + expect { subject.call(alice, status) }.to raise_error ActiveRecord::ActiveRecordError + end + end + context 'ActivityPub' do let(:bob) { Fabricate(:account, username: 'bob', protocol: :activitypub, domain: 'example.com', inbox_url: 'http://example.com/inbox') } let(:status) { Fabricate(:status, account: bob) } diff --git a/spec/services/update_status_service_spec.rb b/spec/services/update_status_service_spec.rb index 4fd4837c62..78cc89cd46 100644 --- a/spec/services/update_status_service_spec.rb +++ b/spec/services/update_status_service_spec.rb @@ -21,7 +21,7 @@ RSpec.describe UpdateStatusService, type: :service do end it 'saves edit history' do - expect(status.edits.pluck(:text, :media_attachments_changed)).to eq [['Foo', false], ['Bar', false]] + expect(status.edits.pluck(:text)).to eq %w(Foo Bar) end end @@ -39,7 +39,7 @@ RSpec.describe UpdateStatusService, type: :service do end it 'saves edit history' do - expect(status.edits.pluck(:text, :spoiler_text, :media_attachments_changed)).to eq [['Foo', '', false], ['Foo', 'Bar', false]] + expect(status.edits.pluck(:text, :spoiler_text)).to eq [['Foo', ''], ['Foo', 'Bar']] end end @@ -54,11 +54,11 @@ RSpec.describe UpdateStatusService, type: :service do end it 'updates media attachments' do - expect(status.media_attachments.to_a).to eq [attached_media_attachment] + expect(status.ordered_media_attachments).to eq [attached_media_attachment] end - it 'detaches detached media attachments' do - expect(detached_media_attachment.reload.status_id).to be_nil + it 'does not detach detached media attachments' do + expect(detached_media_attachment.reload.status_id).to eq status.id end it 'attaches attached media attachments' do @@ -66,7 +66,7 @@ RSpec.describe UpdateStatusService, type: :service do end it 'saves edit history' do - expect(status.edits.pluck(:text, :media_attachments_changed)).to eq [['Foo', false], ['Foo', true]] + expect(status.edits.pluck(:ordered_media_attachment_ids)).to eq [[detached_media_attachment.id], [attached_media_attachment.id]] end end @@ -95,7 +95,7 @@ RSpec.describe UpdateStatusService, type: :service do end it 'saves edit history' do - expect(status.edits.pluck(:text, :media_attachments_changed)).to eq [['Foo', false], ['Foo', true]] + expect(status.edits.pluck(:poll_options)).to eq [%w(Foo Bar), %w(Bar Baz Foo)] end end diff --git a/yarn.lock b/yarn.lock index 7d7590bc95..4847200be2 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2,10 +2,10 @@ # yarn lockfile v1 -"@ampproject/remapping@^2.0.0": - version "2.1.0" - resolved "https://registry.yarnpkg.com/@ampproject/remapping/-/remapping-2.1.0.tgz#72becdf17ee44b2d1ac5651fb12f1952c336fe23" - integrity sha512-d5RysTlJ7hmw5Tw4UxgxcY3lkMe92n8sXCcuLPAyIAHK6j8DefDwtGnVVDgOnv+RnEosulDJ9NPKQL27bDId0g== +"@ampproject/remapping@^2.1.0": + version "2.1.2" + resolved "https://registry.yarnpkg.com/@ampproject/remapping/-/remapping-2.1.2.tgz#4edca94973ded9630d20101cd8559cedb8d8bd34" + integrity sha512-hoyByceqwKirw7w3Z7gnIIZC3Wx3J484Y3L/cMpXFbr7d9ZQj2mODrirNzcJa+SM3UlpWXYvKV4RlRpFXlWgXg== dependencies: "@jridgewell/trace-mapping" "^0.3.0" @@ -28,20 +28,20 @@ resolved "https://registry.yarnpkg.com/@babel/compat-data/-/compat-data-7.16.8.tgz#31560f9f29fdf1868de8cb55049538a1b9732a60" integrity sha512-m7OkX0IdKLKPpBlJtF561YJal5y/jyI5fNfWbPxh2D/nbzzGI4qRyrD8xO2jB24u7l+5I2a43scCG2IrfjC50Q== -"@babel/core@^7.1.0", "@babel/core@^7.12.3", "@babel/core@^7.17.2", "@babel/core@^7.7.2", "@babel/core@^7.8.0": - version "7.17.2" - resolved "https://registry.yarnpkg.com/@babel/core/-/core-7.17.2.tgz#2c77fc430e95139d816d39b113b31bf40fb22337" - integrity sha512-R3VH5G42VSDolRHyUO4V2cfag8WHcZyxdq5Z/m8Xyb92lW/Erm/6kM+XtRFGf3Mulre3mveni2NHfEUws8wSvw== +"@babel/core@^7.1.0", "@babel/core@^7.12.3", "@babel/core@^7.17.5", "@babel/core@^7.7.2", "@babel/core@^7.8.0": + version "7.17.5" + resolved "https://registry.yarnpkg.com/@babel/core/-/core-7.17.5.tgz#6cd2e836058c28f06a4ca8ee7ed955bbf37c8225" + integrity sha512-/BBMw4EvjmyquN5O+t5eh0+YqB3XXJkYD2cjKpYtWOfFy4lQ4UozNSmxAcWT8r2XtZs0ewG+zrfsqeR15i1ajA== dependencies: - "@ampproject/remapping" "^2.0.0" + "@ampproject/remapping" "^2.1.0" "@babel/code-frame" "^7.16.7" - "@babel/generator" "^7.17.0" + "@babel/generator" "^7.17.3" "@babel/helper-compilation-targets" "^7.16.7" "@babel/helper-module-transforms" "^7.16.7" "@babel/helpers" "^7.17.2" - "@babel/parser" "^7.17.0" + "@babel/parser" "^7.17.3" "@babel/template" "^7.16.7" - "@babel/traverse" "^7.17.0" + "@babel/traverse" "^7.17.3" "@babel/types" "^7.17.0" convert-source-map "^1.7.0" debug "^4.1.0" @@ -49,10 +49,10 @@ json5 "^2.1.2" semver "^6.3.0" -"@babel/generator@^7.17.0", "@babel/generator@^7.7.2": - version "7.17.0" - resolved "https://registry.yarnpkg.com/@babel/generator/-/generator-7.17.0.tgz#7bd890ba706cd86d3e2f727322346ffdbf98f65e" - integrity sha512-I3Omiv6FGOC29dtlZhkfXO6pgkmukJSlT26QjVvS1DGZe/NzSVCPG41X0tS21oZkJYlovfj9qDWgKP+Cn4bXxw== +"@babel/generator@^7.17.3", "@babel/generator@^7.7.2": + version "7.17.3" + resolved "https://registry.yarnpkg.com/@babel/generator/-/generator-7.17.3.tgz#a2c30b0c4f89858cb87050c3ffdfd36bdf443200" + integrity sha512-+R6Dctil/MgUsZsZAkYgK+ADNSZzJRRy0TvY65T71z/CR854xHQ1EweBYXdfT+HNeN7w0cSJJEzgxZMv40pxsg== dependencies: "@babel/types" "^7.17.0" jsesc "^2.5.1" @@ -310,10 +310,10 @@ chalk "^2.0.0" js-tokens "^4.0.0" -"@babel/parser@^7.1.0", "@babel/parser@^7.14.7", "@babel/parser@^7.16.7", "@babel/parser@^7.17.0", "@babel/parser@^7.7.0": - version "7.17.0" - resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.17.0.tgz#f0ac33eddbe214e4105363bb17c3341c5ffcc43c" - integrity sha512-VKXSCQx5D8S04ej+Dqsr1CzYvvWgf20jIw2D+YhQCrIlr2UZGaDds23Y0xg75/skOxpLCRpUZvk/1EAVkGoDOw== +"@babel/parser@^7.1.0", "@babel/parser@^7.14.7", "@babel/parser@^7.16.7", "@babel/parser@^7.17.3", "@babel/parser@^7.7.0": + version "7.17.3" + resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.17.3.tgz#b07702b982990bf6fdc1da5049a23fece4c5c3d0" + integrity sha512-7yJPvPV+ESz2IUTPbOL+YkIGyCqOyNIzdguKQuJGnH7bg1WTIifuM21YqokFt/THWh1AkCRn9IgoykTRCBVpzA== "@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression@^7.16.7": version "7.16.7" @@ -1040,18 +1040,18 @@ "@babel/parser" "^7.16.7" "@babel/types" "^7.16.7" -"@babel/traverse@^7.13.0", "@babel/traverse@^7.16.7", "@babel/traverse@^7.16.8", "@babel/traverse@^7.17.0", "@babel/traverse@^7.7.0", "@babel/traverse@^7.7.2": - version "7.17.0" - resolved "https://registry.yarnpkg.com/@babel/traverse/-/traverse-7.17.0.tgz#3143e5066796408ccc880a33ecd3184f3e75cd30" - integrity sha512-fpFIXvqD6kC7c7PUNnZ0Z8cQXlarCLtCUpt2S1Dx7PjoRtCFffvOkHHSom+m5HIxMZn5bIBVb71lhabcmjEsqg== +"@babel/traverse@^7.13.0", "@babel/traverse@^7.16.7", "@babel/traverse@^7.16.8", "@babel/traverse@^7.17.0", "@babel/traverse@^7.17.3", "@babel/traverse@^7.7.0", "@babel/traverse@^7.7.2": + version "7.17.3" + resolved "https://registry.yarnpkg.com/@babel/traverse/-/traverse-7.17.3.tgz#0ae0f15b27d9a92ba1f2263358ea7c4e7db47b57" + integrity sha512-5irClVky7TxRWIRtxlh2WPUUOLhcPN06AGgaQSB8AEwuyEBgJVuJ5imdHm5zxk8w0QS5T+tDfnDxAlhWjpb7cw== dependencies: "@babel/code-frame" "^7.16.7" - "@babel/generator" "^7.17.0" + "@babel/generator" "^7.17.3" "@babel/helper-environment-visitor" "^7.16.7" "@babel/helper-function-name" "^7.16.7" "@babel/helper-hoist-variables" "^7.16.7" "@babel/helper-split-export-declaration" "^7.16.7" - "@babel/parser" "^7.17.0" + "@babel/parser" "^7.17.3" "@babel/types" "^7.17.0" debug "^4.1.0" globals "^11.1.0" @@ -1493,13 +1493,14 @@ lodash "^4.17.15" redent "^3.0.0" -"@testing-library/react@^12.1.2": - version "12.1.2" - resolved "https://registry.yarnpkg.com/@testing-library/react/-/react-12.1.2.tgz#f1bc9a45943461fa2a598bb4597df1ae044cfc76" - integrity sha512-ihQiEOklNyHIpo2Y8FREkyD1QAea054U0MVbwH1m8N9TxeFz+KoJ9LkqoKqJlzx2JDm56DVwaJ1r36JYxZM05g== +"@testing-library/react@^12.1.3": + version "12.1.3" + resolved "https://registry.yarnpkg.com/@testing-library/react/-/react-12.1.3.tgz#ef26c5f122661ea9b6f672b23dc6b328cadbbf26" + integrity sha512-oCULRXWRrBtC9m6G/WohPo1GLcLesH7T4fuKzRAKn1CWVu9BzXtqLXDDTA6KhFNNtRwLtfSMr20HFl+Qrdrvmg== dependencies: "@babel/runtime" "^7.12.5" "@testing-library/dom" "^8.0.0" + "@types/react-dom" "*" "@tootallnate/once@1": version "1.1.2" @@ -1660,6 +1661,13 @@ resolved "https://registry.yarnpkg.com/@types/q/-/q-1.5.2.tgz#690a1475b84f2a884fd07cd797c00f5f31356ea8" integrity sha512-ce5d3q03Ex0sy4R14722Rmt6MT07Ua+k4FwDfdcToYJcMKNtRVQvJ6JCAPdAmAnbRb6CsX6aYb9m96NGod9uTw== +"@types/react-dom@*": + version "17.0.11" + resolved "https://registry.yarnpkg.com/@types/react-dom/-/react-dom-17.0.11.tgz#e1eadc3c5e86bdb5f7684e00274ae228e7bcc466" + integrity sha512-f96K3k+24RaLGVu/Y2Ng3e1EbZ8/cVJvypZWd7cy0ofCBaf2lcM46xNhycMZ2xGwbBjRql7hOlZ+e2WlJ5MH3Q== + dependencies: + "@types/react" "*" + "@types/react-redux@^7.1.20": version "7.1.20" resolved "https://registry.yarnpkg.com/@types/react-redux/-/react-redux-7.1.20.tgz#42f0e61ababb621e12c66c96dda94c58423bd7df" @@ -1887,13 +1895,13 @@ abab@^2.0.3, abab@^2.0.5: resolved "https://registry.yarnpkg.com/abab/-/abab-2.0.5.tgz#c0b678fb32d60fc1219c784d6a826fe385aeb79a" integrity sha512-9IK9EadsbHo6jLWIpxpR6pL0sazTXV6+SQv25ZB+F7Bj9mJNaOc4nCRabwd5M/JwmUa8idz6Eci6eKfJryPs6Q== -accepts@~1.3.4, accepts@~1.3.5, accepts@~1.3.7: - version "1.3.7" - resolved "https://registry.yarnpkg.com/accepts/-/accepts-1.3.7.tgz#531bc726517a3b2b41f850021c6cc15eaab507cd" - integrity sha512-Il80Qs2WjYlJIBNzNkK6KYqlVMTbZLXgHx2oT0pU/fjRHyEp+PEfEPY0R3WCwAGVOtauxh1hOxNgIf5bv7dQpA== +accepts@~1.3.4, accepts@~1.3.5, accepts@~1.3.8: + version "1.3.8" + resolved "https://registry.yarnpkg.com/accepts/-/accepts-1.3.8.tgz#0bf0be125b67014adcb0b0921e62db7bffe16b2e" + integrity sha512-PYAthTa2m2VKxuvSD3DPC/Gy+U+sOA1LAuT8mkmRuvw+NACSaeXEQ+NHcVF7rONl6qcaxV3Uuemwawk+7+SJLw== dependencies: - mime-types "~2.1.24" - negotiator "0.6.2" + mime-types "~2.1.34" + negotiator "0.6.3" acorn-globals@^6.0.0: version "6.0.0" @@ -2550,10 +2558,10 @@ bluebird@^3.5.5: resolved "https://registry.yarnpkg.com/bluebird/-/bluebird-3.7.2.tgz#9f229c15be272454ffa973ace0dbee79a1b0c36f" integrity sha512-XpNj6GDQzdfW+r2Wnn7xiSAd7TM3jzkxGXBGTtWKuSXv1xUV+azxAm8jdWZN06QTQk+2N2XB9jRDkvbmQmcRtg== -blurhash@^1.1.4: - version "1.1.4" - resolved "https://registry.yarnpkg.com/blurhash/-/blurhash-1.1.4.tgz#a7010ceb3019cd2c9809b17c910ebf6175d29244" - integrity sha512-MXIPz6zwYUKayju+Uidf83KhH0vodZfeRl6Ich8Gu+KGl0JgKiFq9LsfqV7cVU5fKD/AotmduZqvOfrGKOfTaA== +blurhash@^1.1.5: + version "1.1.5" + resolved "https://registry.yarnpkg.com/blurhash/-/blurhash-1.1.5.tgz#3034104cd5dce5a3e5caa871ae2f0f1f2d0ab566" + integrity sha512-a+LO3A2DfxTaTztsmkbLYmUzUeApi0LZuKalwbNmqAHR6HhJGMt1qSV/R3wc+w4DL28holjqO3Bg74aUGavGjg== bmp-js@^0.1.0: version "0.1.0" @@ -2570,20 +2578,20 @@ bn.js@^5.1.1: resolved "https://registry.yarnpkg.com/bn.js/-/bn.js-5.1.3.tgz#beca005408f642ebebea80b042b4d18d2ac0ee6b" integrity sha512-GkTiFpjFtUzU9CbMeJ5iazkCzGL3jrhzerzZIuqLABjbwRaFt33I9tUdSNryIptM+RxDet6OKm2WnLXzW51KsQ== -body-parser@1.19.1: - version "1.19.1" - resolved "https://registry.yarnpkg.com/body-parser/-/body-parser-1.19.1.tgz#1499abbaa9274af3ecc9f6f10396c995943e31d4" - integrity sha512-8ljfQi5eBk8EJfECMrgqNGWPEY5jWP+1IzkzkGdFFEwFQZZyaZ21UqdaHktgiMlH0xLHqIFtE/u2OYE5dOtViA== +body-parser@1.19.2: + version "1.19.2" + resolved "https://registry.yarnpkg.com/body-parser/-/body-parser-1.19.2.tgz#4714ccd9c157d44797b8b5607d72c0b89952f26e" + integrity sha512-SAAwOxgoCKMGs9uUAUFHygfLAyaniaoun6I8mFY9pRAJL9+Kec34aU+oIjDhTycub1jozEfEwx1W1IuOYxVSFw== dependencies: - bytes "3.1.1" + bytes "3.1.2" content-type "~1.0.4" debug "2.6.9" depd "~1.1.2" http-errors "1.8.1" iconv-lite "0.4.24" on-finished "~2.3.0" - qs "6.9.6" - raw-body "2.4.2" + qs "6.9.7" + raw-body "2.4.3" type-is "~1.6.18" bonjour@^3.5.0: @@ -2798,10 +2806,10 @@ bytes@3.0.0: resolved "https://registry.yarnpkg.com/bytes/-/bytes-3.0.0.tgz#d32815404d689699f85a4ea4fa8755dd13a96048" integrity sha1-0ygVQE1olpn4Wk6k+odV3ROpYEg= -bytes@3.1.1: - version "3.1.1" - resolved "https://registry.yarnpkg.com/bytes/-/bytes-3.1.1.tgz#3f018291cb4cbad9accb6e6970bca9c8889e879a" - integrity sha512-dWe4nWO/ruEOY7HkUJ5gFt1DCFV9zPRoJr8pV0/ASQermOZjtq8jMjOprC0Kd10GLN+l7xaUPvxzJFWtxGu8Fg== +bytes@3.1.2: + version "3.1.2" + resolved "https://registry.yarnpkg.com/bytes/-/bytes-3.1.2.tgz#8b0beeb98605adf1b128fa4386403c009e0221a5" + integrity sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg== cacache@^12.0.2: version "12.0.4" @@ -3319,10 +3327,10 @@ cookie-signature@1.0.6: resolved "https://registry.yarnpkg.com/cookie-signature/-/cookie-signature-1.0.6.tgz#e303a882b342cc3ee8ca513a79999734dab3ae2c" integrity sha1-4wOogrNCzD7oylE6eZmXNNqzriw= -cookie@0.4.1: - version "0.4.1" - resolved "https://registry.yarnpkg.com/cookie/-/cookie-0.4.1.tgz#afd713fe26ebd21ba95ceb61f9a8116e50a537d1" - integrity sha512-ZwrFkGJxUR3EIoXtO+yVE69Eb7KlixbaeAWfBQB9vVsNn/o+Yw69gBWSSDK825hQNdN+wF8zELf3dFNl/kxkUA== +cookie@0.4.2: + version "0.4.2" + resolved "https://registry.yarnpkg.com/cookie/-/cookie-0.4.2.tgz#0e41f24de5ecf317947c82fc789e06a884824432" + integrity sha512-aSWTXFzaKWkvHO1Ny/s+ePFpvKsPnjc551iI41v3ny/ow6tBG5Vd+FuqGNhh1LxOmVzOlGUriIlOaokOvhaStA== copy-concurrently@^1.0.0: version "1.0.5" @@ -4372,10 +4380,10 @@ eslint-plugin-promise@~6.0.0: resolved "https://registry.yarnpkg.com/eslint-plugin-promise/-/eslint-plugin-promise-6.0.0.tgz#017652c07c9816413a41e11c30adc42c3d55ff18" integrity sha512-7GPezalm5Bfi/E22PnQxDWH2iW9GTvAlUNTztemeHb6c1BniSyoeTrM87JkC0wYdi6aQrZX9p2qEiAno8aTcbw== -eslint-plugin-react@~7.29.2: - version "7.29.2" - resolved "https://registry.yarnpkg.com/eslint-plugin-react/-/eslint-plugin-react-7.29.2.tgz#2d4da69d30d0a736efd30890dc6826f3e91f3f7c" - integrity sha512-ypEBTKOy5liFQXZWMchJ3LN0JX1uPI6n7MN7OPHKacqXAxq5gYC30TdO7wqGYQyxD1OrzpobdHC3hDmlRWDg9w== +eslint-plugin-react@~7.29.3: + version "7.29.3" + resolved "https://registry.yarnpkg.com/eslint-plugin-react/-/eslint-plugin-react-7.29.3.tgz#f4eab757f2756d25d6d4c2a58a9e20b004791f05" + integrity sha512-MzW6TuCnDOcta67CkpDyRfRsEVx9FNMDV8wZsDqe1luHPdGTrQIUaUXD27Ja3gHsdOIs/cXzNchWGlqm+qRVRg== dependencies: array-includes "^3.1.4" array.prototype.flatmap "^1.2.5" @@ -4672,17 +4680,17 @@ expect@^27.5.1: jest-matcher-utils "^27.5.1" jest-message-util "^27.5.1" -express@^4.17.1, express@^4.17.2: - version "4.17.2" - resolved "https://registry.yarnpkg.com/express/-/express-4.17.2.tgz#c18369f265297319beed4e5558753cc8c1364cb3" - integrity sha512-oxlxJxcQlYwqPWKVJJtvQiwHgosH/LrLSPA+H4UxpyvSS6jC5aH+5MoHFM+KABgTOt0APue4w66Ha8jCUo9QGg== +express@^4.17.1, express@^4.17.3: + version "4.17.3" + resolved "https://registry.yarnpkg.com/express/-/express-4.17.3.tgz#f6c7302194a4fb54271b73a1fe7a06478c8f85a1" + integrity sha512-yuSQpz5I+Ch7gFrPCk4/c+dIBKlQUxtgwqzph132bsT6qhuzss6I8cLJQz7B3rFblzd6wtcI0ZbGltH/C4LjUg== dependencies: - accepts "~1.3.7" + accepts "~1.3.8" array-flatten "1.1.1" - body-parser "1.19.1" + body-parser "1.19.2" content-disposition "0.5.4" content-type "~1.0.4" - cookie "0.4.1" + cookie "0.4.2" cookie-signature "1.0.6" debug "2.6.9" depd "~1.1.2" @@ -4697,7 +4705,7 @@ express@^4.17.1, express@^4.17.2: parseurl "~1.3.3" path-to-regexp "0.1.7" proxy-addr "~2.0.7" - qs "6.9.6" + qs "6.9.7" range-parser "~1.2.1" safe-buffer "5.2.1" send "0.17.2" @@ -7123,10 +7131,10 @@ mark-loader@^0.1.6: resolved "https://registry.yarnpkg.com/mark-loader/-/mark-loader-0.1.6.tgz#0abb477dca7421d70e20128ff6489f5cae8676d5" integrity sha1-CrtHfcp0IdcOIBKP9kifXK6GdtU= -marky@^1.2.2: - version "1.2.2" - resolved "https://registry.yarnpkg.com/marky/-/marky-1.2.2.tgz#4456765b4de307a13d263a69b0c79bf226e68323" - integrity sha512-k1dB2HNeaNyORco8ulVEhctyEGkKHb2YWAhDsxeFlW2nROIirsctBYzKwwS3Vza+sKTS1zO4Z+n9/+9WbGLIxQ== +marky@^1.2.4: + version "1.2.4" + resolved "https://registry.yarnpkg.com/marky/-/marky-1.2.4.tgz#d02bb4c08be2366687c778ecd2a328971ce23d7f" + integrity sha512-zd2/GiSn6U3/jeFVZ0J9CA1LzQ8RfIVvXkb/U0swFHF/zT+dVohTAWjmo2DcIuofmIIIROlwTbd+shSeXmxr0w== md5.js@^1.3.4: version "1.3.5" @@ -7233,6 +7241,11 @@ mime-db@1.44.0, "mime-db@>= 1.43.0 < 2": resolved "https://registry.yarnpkg.com/mime-db/-/mime-db-1.44.0.tgz#fa11c5eb0aca1334b4233cb4d52f10c5a6272f92" integrity sha512-/NOTfLrsPBVeH7YtFPgsVWveuL+4SjjYxaQ1xtM1KMFj7HdxlBlxeyNLzhyJVx7r4rZGJAZ/6lkKCitSc/Nmpg== +mime-db@1.51.0: + version "1.51.0" + resolved "https://registry.yarnpkg.com/mime-db/-/mime-db-1.51.0.tgz#d9ff62451859b18342d960850dc3cfb77e63fb0c" + integrity sha512-5y8A56jg7XVQx2mbv1lu49NR4dokRnhZYTtL+KGfaa27uq4pSTXkwQkFJl4pkRMyNFz/EtYDSkiiEHx3F7UN6g== + mime-types@^2.1.12, mime-types@~2.1.17, mime-types@~2.1.24: version "2.1.27" resolved "https://registry.yarnpkg.com/mime-types/-/mime-types-2.1.27.tgz#47949f98e279ea53119f5722e0f34e529bec009f" @@ -7240,6 +7253,13 @@ mime-types@^2.1.12, mime-types@~2.1.17, mime-types@~2.1.24: dependencies: mime-db "1.44.0" +mime-types@~2.1.34: + version "2.1.34" + resolved "https://registry.yarnpkg.com/mime-types/-/mime-types-2.1.34.tgz#5a712f9ec1503511a945803640fafe09d3793c24" + integrity sha512-6cP692WwGIs9XXdOO4++N+7qjqv0rqxxVvJ3VHPh/Sc9mVZcQP+ZGhkKiTvWMQRr2tbHkJP/Yn7Y0npb3ZBs4A== + dependencies: + mime-db "1.51.0" + mime@1.6.0: version "1.6.0" resolved "https://registry.yarnpkg.com/mime/-/mime-1.6.0.tgz#32cd9e5c64553bd58d19a568af452acff04981b1" @@ -7462,10 +7482,10 @@ natural-compare@^1.4.0: resolved "https://registry.yarnpkg.com/natural-compare/-/natural-compare-1.4.0.tgz#4abebfeed7541f2c27acfb29bdbbd15c8d5ba4f7" integrity sha1-Sr6/7tdUHywnrPspvbvRXI1bpPc= -negotiator@0.6.2: - version "0.6.2" - resolved "https://registry.yarnpkg.com/negotiator/-/negotiator-0.6.2.tgz#feacf7ccf525a77ae9634436a64883ffeca346fb" - integrity sha512-hZXc7K2e+PgeI1eDBe/10Ard4ekbfrrqG8Ep+8Jmf4JID2bNg7NvCPOZN+kfF574pFQI7mum2AUqDidoKqcTOw== +negotiator@0.6.3: + version "0.6.3" + resolved "https://registry.yarnpkg.com/negotiator/-/negotiator-0.6.3.tgz#58e323a72fedc0d6f9cd4d31fe49f51479590ccd" + integrity sha512-+EUsqGPLsM+j/zdChZjsnX51g4XrHFOIXwfnCVPGlQk/k5giakcKsuxCObBRu6DSm9opw/O6slWbJdghQM4bBg== neo-async@^2.5.0, neo-async@^2.6.1, neo-async@^2.6.2: version "2.6.2" @@ -8792,10 +8812,10 @@ q@^1.1.2: resolved "https://registry.yarnpkg.com/q/-/q-1.5.1.tgz#7e32f75b41381291d04611f1bf14109ac00651d7" integrity sha1-fjL3W0E4EpHQRhHxvxQQmsAGUdc= -qs@6.9.6: - version "6.9.6" - resolved "https://registry.yarnpkg.com/qs/-/qs-6.9.6.tgz#26ed3c8243a431b2924aca84cc90471f35d5a0ee" - integrity sha512-TIRk4aqYLNoJUbd+g2lEdz5kLWIuTMRagAXxl78Q0RiVjAOugHmeKNGdd3cwo/ktpf9aL9epCfFqWDEKysUlLQ== +qs@6.9.7: + version "6.9.7" + resolved "https://registry.yarnpkg.com/qs/-/qs-6.9.7.tgz#4610846871485e1e048f44ae3b94033f0e675afe" + integrity sha512-IhMFgUmuNpyRfxA90umL7ByLlgRXu6tIfKPpF5TmcfRLlLCckfP/g3IQmju6jjpu+Hh8rA+2p6A27ZSPOOHdKw== querystring-es3@^0.2.0: version "0.2.1" @@ -8844,12 +8864,12 @@ range-parser@^1.2.1, range-parser@~1.2.1: resolved "https://registry.yarnpkg.com/range-parser/-/range-parser-1.2.1.tgz#3cf37023d199e1c24d1a55b84800c2f3e6468031" integrity sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg== -raw-body@2.4.2: - version "2.4.2" - resolved "https://registry.yarnpkg.com/raw-body/-/raw-body-2.4.2.tgz#baf3e9c21eebced59dd6533ac872b71f7b61cb32" - integrity sha512-RPMAFUJP19WIet/99ngh6Iv8fzAbqum4Li7AD6DtGaW2RpMB/11xDoalPiJMTbu6I3hkbMVkATvZrqb9EEqeeQ== +raw-body@2.4.3: + version "2.4.3" + resolved "https://registry.yarnpkg.com/raw-body/-/raw-body-2.4.3.tgz#8f80305d11c2a0a545c2d9d89d7a0286fcead43c" + integrity sha512-UlTNLIcu0uzb4D2f4WltY6cVjLi+/jEN4lgEUj3E04tpMDpUlkBo/eSn6zou9hum2VMNpCCUone0O0WeJim07g== dependencies: - bytes "3.1.1" + bytes "3.1.2" http-errors "1.8.1" iconv-lite "0.4.24" unpipe "1.0.0"