diff options
author | beatrix <beatrix.bitrot@gmail.com> | 2018-03-03 13:40:00 -0500 |
---|---|---|
committer | GitHub <noreply@github.com> | 2018-03-03 13:40:00 -0500 |
commit | 43a9a781a443a6b9296431fbcc4285b3ca6a1a57 (patch) | |
tree | d4bf067aeedcebbdc3d160eca6aa1a7c7d1bfa00 /app | |
parent | ee00da01d2e4cc455b92f1f4a7c9142c73048433 (diff) | |
parent | 65e2a4645e086110072efed5b3d4d1434c933e04 (diff) |
Merge pull request #377 from glitch-soc/merge-upstream
hhhhhhhhhnnnnnnnnnnnghh!!!!!
Diffstat (limited to 'app')
103 files changed, 1941 insertions, 1029 deletions
diff --git a/app/controllers/accounts_controller.rb b/app/controllers/accounts_controller.rb index c9725ed00..1efaf619b 100644 --- a/app/controllers/accounts_controller.rb +++ b/app/controllers/accounts_controller.rb @@ -1,6 +1,8 @@ # frozen_string_literal: true class AccountsController < ApplicationController + PAGE_SIZE = 20 + include AccountControllerConcern before_action :set_cache_headers @@ -17,13 +19,16 @@ class AccountsController < ApplicationController end @pinned_statuses = cache_collection(@account.pinned_statuses, Status) if show_pinned_statuses? - @statuses = filtered_statuses.paginate_by_max_id(20, params[:max_id], params[:since_id]) + @statuses = filtered_status_page(params) @statuses = cache_collection(@statuses, Status) - @next_url = next_url unless @statuses.empty? + unless @statuses.empty? + @older_url = older_url if @statuses.last.id > filtered_statuses.last.id + @newer_url = newer_url if @statuses.first.id < filtered_statuses.first.id + end end format.atom do - @entries = @account.stream_entries.where(hidden: false).with_includes.paginate_by_max_id(20, params[:max_id], params[:since_id]) + @entries = @account.stream_entries.where(hidden: false).with_includes.paginate_by_max_id(PAGE_SIZE, params[:max_id], params[:since_id]) render xml: OStatus::AtomSerializer.render(OStatus::AtomSerializer.new.feed(@account, @entries.reject { |entry| entry.status.nil? })) end @@ -70,13 +75,22 @@ class AccountsController < ApplicationController @account = Account.find_local!(params[:username]) end - def next_url + def older_url + ::Rails.logger.info("older: max_id #{@statuses.last.id}, url #{pagination_url(max_id: @statuses.last.id)}") + pagination_url(max_id: @statuses.last.id) + end + + def newer_url + pagination_url(min_id: @statuses.first.id) + end + + def pagination_url(max_id: nil, min_id: nil) if media_requested? - short_account_media_url(@account, max_id: @statuses.last.id) + short_account_media_url(@account, max_id: max_id, min_id: min_id) elsif replies_requested? - short_account_with_replies_url(@account, max_id: @statuses.last.id) + short_account_with_replies_url(@account, max_id: max_id, min_id: min_id) else - short_account_url(@account, max_id: @statuses.last.id) + short_account_url(@account, max_id: max_id, min_id: min_id) end end @@ -87,4 +101,12 @@ class AccountsController < ApplicationController def replies_requested? request.path.ends_with?('/with_replies') end + + def filtered_status_page(params) + if params[:min_id].present? + filtered_statuses.paginate_by_min_id(PAGE_SIZE, params[:min_id]).reverse + else + filtered_statuses.paginate_by_max_id(PAGE_SIZE, params[:max_id], params[:since_id]).to_a + end + end end diff --git a/app/controllers/api/base_controller.rb b/app/controllers/api/base_controller.rb index 52e68ab35..7b5168b31 100644 --- a/app/controllers/api/base_controller.rb +++ b/app/controllers/api/base_controller.rb @@ -51,6 +51,10 @@ class Api::BaseController < ApplicationController [params[:limit].to_i.abs, default_limit * 2].min end + def truthy_param?(key) + ActiveModel::Type::Boolean.new.cast(params[key]) + end + def current_resource_owner @current_user ||= User.find(doorkeeper_token.resource_owner_id) if doorkeeper_token end diff --git a/app/controllers/api/v1/accounts/search_controller.rb b/app/controllers/api/v1/accounts/search_controller.rb index 11e647c3c..7649da433 100644 --- a/app/controllers/api/v1/accounts/search_controller.rb +++ b/app/controllers/api/v1/accounts/search_controller.rb @@ -22,8 +22,4 @@ class Api::V1::Accounts::SearchController < Api::BaseController following: truthy_param?(:following) ) end - - def truthy_param?(key) - params[key] == 'true' - end end diff --git a/app/controllers/api/v1/accounts/statuses_controller.rb b/app/controllers/api/v1/accounts/statuses_controller.rb index 095f6937b..7261ccd24 100644 --- a/app/controllers/api/v1/accounts/statuses_controller.rb +++ b/app/controllers/api/v1/accounts/statuses_controller.rb @@ -28,9 +28,9 @@ class Api::V1::Accounts::StatusesController < Api::BaseController def account_statuses default_statuses.tap do |statuses| - statuses.merge!(only_media_scope) if params[:only_media] - statuses.merge!(pinned_scope) if params[:pinned] - statuses.merge!(no_replies_scope) if params[:exclude_replies] + statuses.merge!(only_media_scope) if truthy_param?(:only_media) + statuses.merge!(pinned_scope) if truthy_param?(:pinned) + statuses.merge!(no_replies_scope) if truthy_param?(:exclude_replies) end end diff --git a/app/controllers/api/v1/accounts_controller.rb b/app/controllers/api/v1/accounts_controller.rb index 4e73e9e8b..d64325944 100644 --- a/app/controllers/api/v1/accounts_controller.rb +++ b/app/controllers/api/v1/accounts_controller.rb @@ -13,9 +13,9 @@ class Api::V1::AccountsController < Api::BaseController end def follow - FollowService.new.call(current_user.account, @account.acct, reblogs: params[:reblogs]) + FollowService.new.call(current_user.account, @account.acct, reblogs: truthy_param?(:reblogs)) - options = @account.locked? ? {} : { following_map: { @account.id => { reblogs: params[:reblogs] } }, requested_map: { @account.id => false } } + options = @account.locked? ? {} : { following_map: { @account.id => { reblogs: truthy_param?(:reblogs) } }, requested_map: { @account.id => false } } render json: @account, serializer: REST::RelationshipSerializer, relationships: relationships(options) end @@ -26,7 +26,7 @@ class Api::V1::AccountsController < Api::BaseController end def mute - MuteService.new.call(current_user.account, @account, notifications: params[:notifications]) + MuteService.new.call(current_user.account, @account, notifications: truthy_param?(:notifications)) render json: @account, serializer: REST::RelationshipSerializer, relationships: relationships end diff --git a/app/controllers/api/v1/reports_controller.rb b/app/controllers/api/v1/reports_controller.rb index 22828217d..f5095e073 100644 --- a/app/controllers/api/v1/reports_controller.rb +++ b/app/controllers/api/v1/reports_controller.rb @@ -13,14 +13,14 @@ class Api::V1::ReportsController < Api::BaseController end def create - @report = current_account.reports.create!( - target_account: reported_account, + @report = ReportService.new.call( + current_account, + reported_account, status_ids: reported_status_ids, - comment: report_params[:comment] + comment: report_params[:comment], + forward: report_params[:forward] ) - User.staff.includes(:account).each { |u| AdminMailer.new_report(u.account, @report).deliver_later } - render json: @report, serializer: REST::ReportSerializer end @@ -39,6 +39,6 @@ class Api::V1::ReportsController < Api::BaseController end def report_params - params.permit(:account_id, :comment, status_ids: []) + params.permit(:account_id, :comment, :forward, status_ids: []) end end diff --git a/app/controllers/api/v1/search_controller.rb b/app/controllers/api/v1/search_controller.rb index d1b4e0402..99b635ad9 100644 --- a/app/controllers/api/v1/search_controller.rb +++ b/app/controllers/api/v1/search_controller.rb @@ -33,12 +33,8 @@ class Api::V1::SearchController < Api::BaseController SearchService.new.call( params[:q], RESULTS_LIMIT, - resolving_search?, + truthy_param?(:resolve), current_account ) end - - def resolving_search? - params[:resolve] == 'true' - end end diff --git a/app/controllers/api/v1/timelines/public_controller.rb b/app/controllers/api/v1/timelines/public_controller.rb index 49887778e..d7d70b94d 100644 --- a/app/controllers/api/v1/timelines/public_controller.rb +++ b/app/controllers/api/v1/timelines/public_controller.rb @@ -21,15 +21,23 @@ class Api::V1::Timelines::PublicController < Api::BaseController end def public_statuses - public_timeline_statuses.paginate_by_max_id( + statuses = public_timeline_statuses.paginate_by_max_id( limit_param(DEFAULT_STATUSES_LIMIT), params[:max_id], params[:since_id] ) + + if truthy_param?(:only_media) + # `SELECT DISTINCT id, updated_at` is too slow, so pluck ids at first, and then select id, updated_at with ids. + status_ids = statuses.joins(:media_attachments).distinct(:id).pluck(:id) + statuses.where(id: status_ids) + else + statuses + end end def public_timeline_statuses - Status.as_public_timeline(current_account, params[:local]) + Status.as_public_timeline(current_account, truthy_param?(:local)) end def insert_pagination_headers @@ -37,7 +45,7 @@ class Api::V1::Timelines::PublicController < Api::BaseController end def pagination_params(core_params) - params.permit(:local, :limit).merge(core_params) + params.permit(:local, :limit, :only_media).merge(core_params) end def next_path diff --git a/app/controllers/api/v1/timelines/tag_controller.rb b/app/controllers/api/v1/timelines/tag_controller.rb index 08db04a39..eb32611ad 100644 --- a/app/controllers/api/v1/timelines/tag_controller.rb +++ b/app/controllers/api/v1/timelines/tag_controller.rb @@ -29,16 +29,24 @@ class Api::V1::Timelines::TagController < Api::BaseController if @tag.nil? [] else - tag_timeline_statuses.paginate_by_max_id( + statuses = tag_timeline_statuses.paginate_by_max_id( limit_param(DEFAULT_STATUSES_LIMIT), params[:max_id], params[:since_id] ) + + if truthy_param?(:only_media) + # `SELECT DISTINCT id, updated_at` is too slow, so pluck ids at first, and then select id, updated_at with ids. + status_ids = statuses.joins(:media_attachments).distinct(:id).pluck(:id) + statuses.where(id: status_ids) + else + statuses + end end end def tag_timeline_statuses - Status.as_tag_timeline(@tag, current_account, params[:local]) + Status.as_tag_timeline(@tag, current_account, truthy_param?(:local)) end def insert_pagination_headers @@ -46,7 +54,7 @@ class Api::V1::Timelines::TagController < Api::BaseController end def pagination_params(core_params) - params.permit(:local, :limit).merge(core_params) + params.permit(:local, :limit, :only_media).merge(core_params) end def next_path diff --git a/app/controllers/application_controller.rb b/app/controllers/application_controller.rb index a296d96db..fc745eaec 100644 --- a/app/controllers/application_controller.rb +++ b/app/controllers/application_controller.rb @@ -15,7 +15,7 @@ class ApplicationController < ActionController::Base helper_method :current_flavour helper_method :current_skin helper_method :single_user_mode? - helper_method :use_pam? + helper_method :use_seamless_external_login? rescue_from ActionController::RoutingError, with: :not_found rescue_from ActiveRecord::RecordNotFound, with: :not_found @@ -146,8 +146,8 @@ class ApplicationController < ActionController::Base @single_user_mode ||= Rails.configuration.x.single_user_mode && Account.exists? end - def use_pam? - Devise.pam_authentication + def use_seamless_external_login? + Devise.pam_authentication || Devise.ldap_authentication end def current_account diff --git a/app/controllers/auth/sessions_controller.rb b/app/controllers/auth/sessions_controller.rb index 475cd540a..c9e507343 100644 --- a/app/controllers/auth/sessions_controller.rb +++ b/app/controllers/auth/sessions_controller.rb @@ -38,7 +38,7 @@ class Auth::SessionsController < Devise::SessionsController if session[:otp_user_id] User.find(session[:otp_user_id]) elsif user_params[:email] - if use_pam? && Devise.check_at_sign && user_params[:email].index('@').nil? + if use_seamless_external_login? && Devise.check_at_sign && user_params[:email].index('@').nil? User.joins(:account).find_by(accounts: { username: user_params[:email] }) else User.find_for_authentication(email: user_params[:email]) diff --git a/app/controllers/follower_accounts_controller.rb b/app/controllers/follower_accounts_controller.rb index 080cbde11..c74d3f86d 100644 --- a/app/controllers/follower_accounts_controller.rb +++ b/app/controllers/follower_accounts_controller.rb @@ -9,6 +9,8 @@ class FollowerAccountsController < ApplicationController respond_to do |format| format.html do use_pack 'public' + + @relationships = AccountRelationshipsPresenter.new(@follows.map(&:account_id), current_user.account_id) if user_signed_in? end format.json do diff --git a/app/controllers/following_accounts_controller.rb b/app/controllers/following_accounts_controller.rb index 74e83ad81..4c1e3f327 100644 --- a/app/controllers/following_accounts_controller.rb +++ b/app/controllers/following_accounts_controller.rb @@ -9,6 +9,8 @@ class FollowingAccountsController < ApplicationController respond_to do |format| format.html do use_pack 'public' + + @relationships = AccountRelationshipsPresenter.new(@follows.map(&:target_account_id), current_user.account_id) if user_signed_in? end format.json do diff --git a/app/javascript/flavours/glitch/styles/about.scss b/app/javascript/flavours/glitch/styles/about.scss index a25a50739..d97e23696 100644 --- a/app/javascript/flavours/glitch/styles/about.scss +++ b/app/javascript/flavours/glitch/styles/about.scss @@ -15,117 +15,169 @@ $small-breakpoint: 960px; } } -.show-xs, -.show-sm { - display: none; -} +.landing-page { + .grid { + display: grid; + grid-gap: 10px; + grid-template-columns: 1fr 2fr; + grid-auto-columns: 25%; + grid-auto-rows: max-content; + + .column-0 { + display: none; + } -.show-m { - display: block; -} + .column-1 { + grid-column: 1; + grid-row: 1; + } -@media screen and (max-width: $small-breakpoint) { - .hide-sm { - display: none !important; - } + .column-2 { + grid-column: 2; + grid-row: 1; + } - .show-sm { - display: block !important; - } -} + .column-3 { + grid-column: 3; + grid-row: 1 / 3; + } -@media screen and (max-width: $column-breakpoint) { - .hide-xs { - display: none !important; + .column-4 { + grid-column: 1 / 3; + grid-row: 2; + } } - .show-xs { - display: block !important; - } -} + @media screen and (max-width: $small-breakpoint) { + .grid { + grid-template-columns: 40% 60%; -.row { - display: flex; - flex-wrap: wrap; - margin: 0 -5px; + .column-0 { + display: none; + } - @for $i from 1 through 15 { - .column-#{$i} { - box-sizing: border-box; - min-height: 1px; - flex: 0 0 percentage($i / 15); - max-width: percentage($i / 15); - padding: 0 5px; + .column-1 { + grid-column: 1; + grid-row: 1; - @media screen and (max-width: $small-breakpoint) { - &-sm { - box-sizing: border-box; - min-height: 1px; - flex: 0 0 percentage($i / 15); - max-width: percentage($i / 15); - padding: 0 5px; - - @media screen and (max-width: $column-breakpoint) { - max-width: 100%; - flex: 0 0 100%; - margin-bottom: 10px; - - &:last-child { - margin-bottom: 0; - } - } + &.non-preview .landing-page__forms { + height: 100%; } } - @media screen and (max-width: $column-breakpoint) { - max-width: 100%; - flex: 0 0 100%; - margin-bottom: 10px; + .column-2 { + grid-column: 2; + grid-row: 1 / 3; - &:last-child { - margin-bottom: 0; + &.non-preview { + grid-column: 2; + grid-row: 1; + } + } + + .column-3 { + grid-column: 1; + grid-row: 2 / 4; + } + + .column-4 { + grid-column: 2; + grid-row: 3; + + &.non-preview { + grid-column: 1 / 3; + grid-row: 2; } } } } -} -.column-flex { - display: flex; - flex-direction: column; -} + @media screen and (max-width: $column-breakpoint) { + .grid { + grid-template-columns: auto; -.separator-or { - position: relative; - margin: 40px 0; - text-align: center; + .column-0 { + display: block; + grid-column: 1; + grid-row: 1; + } - &::before { - content: ""; - display: block; - width: 100%; - height: 0; - border-bottom: 1px solid rgba($ui-base-lighter-color, .6); - position: absolute; - top: 50%; - left: 0; + .column-1 { + grid-column: 1; + grid-row: 3; + + .brand { + display: none; + } + } + + .column-2 { + grid-column: 1; + grid-row: 2; + + .landing-page__logo, + .landing-page__call-to-action { + display: none; + } + + &.non-preview { + grid-column: 1; + grid-row: 2; + } + } + + .column-3 { + grid-column: 1; + grid-row: 5; + } + + .column-4 { + grid-column: 1; + grid-row: 4; + + &.non-preview { + grid-column: 1; + grid-row: 4; + } + } + } } - span { - display: inline-block; - background: $ui-base-color; - font-size: 12px; - font-weight: 500; - color: $ui-primary-color; - text-transform: uppercase; + .column-flex { + display: flex; + flex-direction: column; + } + + .separator-or { position: relative; - z-index: 1; - padding: 0 8px; - cursor: default; + margin: 40px 0; + text-align: center; + + &::before { + content: ""; + display: block; + width: 100%; + height: 0; + border-bottom: 1px solid rgba($ui-base-lighter-color, .6); + position: absolute; + top: 50%; + left: 0; + } + + span { + display: inline-block; + background: $ui-base-color; + font-size: 12px; + font-weight: 500; + color: $ui-primary-color; + text-transform: uppercase; + position: relative; + z-index: 1; + padding: 0 8px; + cursor: default; + } } -} -.landing-page { p, li { font-family: 'mastodon-font-sans-serif', sans-serif; @@ -502,7 +554,7 @@ $small-breakpoint: 960px; display: block; width: 80px; height: 80px; - border-radius: $ui-avatar-border-size; + border-radius: 48px; } } @@ -539,6 +591,7 @@ $small-breakpoint: 960px; img { position: static; + padding: 10px 0; } @media screen and (max-width: $small-breakpoint) { @@ -558,18 +611,33 @@ $small-breakpoint: 960px; } &__call-to-action { - margin-bottom: 10px; background: darken($ui-base-color, 4%); border-radius: 4px; padding: 25px 40px; overflow: hidden; .row { + display: flex; + flex-direction: row-reverse; + flex-wrap: wrap; + justify-content: space-between; align-items: center; } - .information-board__section { - padding: 0; + .row__information-board { + display: flex; + justify-content: flex-end; + align-items: flex-end; + + .information-board__section { + flex: 1 0 auto; + padding: 0 10px; + } + } + + .row__mascot { + flex: 1; + margin: 10px -50px 0 0; } } @@ -619,6 +687,8 @@ $small-breakpoint: 960px; &__short-description { .row { + display: flex; + flex-wrap: wrap; align-items: center; margin-bottom: 40px; } @@ -668,7 +738,6 @@ $small-breakpoint: 960px; height: 100%; @media screen and (max-width: $small-breakpoint) { - margin-bottom: 10px; height: auto; } @@ -717,15 +786,14 @@ $small-breakpoint: 960px; width: 100%; flex: 1 1 auto; overflow: hidden; + height: 100%; .column-header { color: inherit; font-family: inherit; font-size: 16px; - padding: 15px; line-height: inherit; font-weight: inherit; - margin: 0; } .column { @@ -942,93 +1010,54 @@ $small-breakpoint: 960px; } &.tag-page { - .features { - padding: 30px 0; - - .container-alt { - max-width: 820px; - - #mastodon-timeline { - margin-right: 0; - border-top-right-radius: 0; - } - - .about-mastodon { - .about-hashtag { - background: darken($ui-base-color, 4%); - padding: 0 20px 20px 30px; - border-radius: 0 5px 5px 0; - - .brand { - padding-top: 20px; - margin-bottom: 20px; - - img { - height: 48px; - width: auto; - } - } - - p { - strong { - color: $ui-secondary-color; - font-weight: 700; - } - } + .grid { + @media screen and (min-width: $small-breakpoint) { + grid-template-columns: 33% 67%; + } - .cta { - margin: 0; + .column-2 { + grid-column: 2; + grid-row: 1; + } + } - .button { - margin-right: 4px; - } - } - } + .brand { + text-align: unset; + padding: 0; - .features-list { - margin-left: 30px; - margin-right: 10px; - } - } + img { + height: 48px; + width: auto; } } - @media screen and (max-width: 675px) { - .features { - padding: 10px 0; + .cta { + margin: 0; - .container-alt { - display: flex; - flex-direction: column; - - #mastodon-timeline { - order: 2; - flex: 0 0 auto; - height: 60vh; - margin-bottom: 20px; - border-top-right-radius: 4px; - } + .button { + margin-right: 4px; + } + } - .about-mastodon { - order: 1; - flex: 0 0 auto; - max-width: 100%; + @media screen and (max-width: $column-breakpoint) { + .grid { + .column-1 { + grid-column: 1; + grid-row: 2; + } - .about-hashtag { - background: unset; - padding: 0; - border-radius: 0; + .column-2 { + grid-column: 1; + grid-row: 1; + } + } - .cta { - margin: 20px 0; - } - } + .brand { + margin: 0; + } - .features-list { - display: none; - } - } - } + .landing-page__features { + display: none; } } } diff --git a/app/javascript/mastodon/actions/reports.js b/app/javascript/mastodon/actions/reports.js index b19a07285..afa0c3412 100644 --- a/app/javascript/mastodon/actions/reports.js +++ b/app/javascript/mastodon/actions/reports.js @@ -10,6 +10,7 @@ export const REPORT_SUBMIT_FAIL = 'REPORT_SUBMIT_FAIL'; export const REPORT_STATUS_TOGGLE = 'REPORT_STATUS_TOGGLE'; export const REPORT_COMMENT_CHANGE = 'REPORT_COMMENT_CHANGE'; +export const REPORT_FORWARD_CHANGE = 'REPORT_FORWARD_CHANGE'; export function initReport(account, status) { return dispatch => { @@ -45,6 +46,7 @@ export function submitReport() { account_id: getState().getIn(['reports', 'new', 'account_id']), status_ids: getState().getIn(['reports', 'new', 'status_ids']), comment: getState().getIn(['reports', 'new', 'comment']), + forward: getState().getIn(['reports', 'new', 'forward']), }).then(response => { dispatch(closeModal()); dispatch(submitReportSuccess(response.data)); @@ -78,3 +80,10 @@ export function changeReportComment(comment) { comment, }; }; + +export function changeReportForward(forward) { + return { + type: REPORT_FORWARD_CHANGE, + forward, + }; +}; diff --git a/app/javascript/mastodon/actions/timelines.js b/app/javascript/mastodon/actions/timelines.js index df6a36379..858a12b15 100644 --- a/app/javascript/mastodon/actions/timelines.js +++ b/app/javascript/mastodon/actions/timelines.js @@ -120,7 +120,7 @@ export function refreshTimeline(timelineId, path, params = {}) { export const refreshHomeTimeline = () => refreshTimeline('home', '/api/v1/timelines/home'); export const refreshPublicTimeline = () => refreshTimeline('public', '/api/v1/timelines/public'); export const refreshCommunityTimeline = () => refreshTimeline('community', '/api/v1/timelines/public', { local: true }); -export const refreshAccountTimeline = accountId => refreshTimeline(`account:${accountId}`, `/api/v1/accounts/${accountId}/statuses`); +export const refreshAccountTimeline = (accountId, withReplies) => refreshTimeline(`account:${accountId}${withReplies ? ':with_replies' : ''}`, `/api/v1/accounts/${accountId}/statuses`, { exclude_replies: !withReplies }); export const refreshAccountMediaTimeline = accountId => refreshTimeline(`account:${accountId}:media`, `/api/v1/accounts/${accountId}/statuses`, { only_media: true }); export const refreshHashtagTimeline = hashtag => refreshTimeline(`hashtag:${hashtag}`, `/api/v1/timelines/tag/${hashtag}`); export const refreshListTimeline = id => refreshTimeline(`list:${id}`, `/api/v1/timelines/list/${id}`); @@ -161,7 +161,7 @@ export function expandTimeline(timelineId, path, params = {}) { export const expandHomeTimeline = () => expandTimeline('home', '/api/v1/timelines/home'); export const expandPublicTimeline = () => expandTimeline('public', '/api/v1/timelines/public'); export const expandCommunityTimeline = () => expandTimeline('community', '/api/v1/timelines/public', { local: true }); -export const expandAccountTimeline = accountId => expandTimeline(`account:${accountId}`, `/api/v1/accounts/${accountId}/statuses`); +export const expandAccountTimeline = (accountId, withReplies) => expandTimeline(`account:${accountId}${withReplies ? ':with_replies' : ''}`, `/api/v1/accounts/${accountId}/statuses`, { exclude_replies: !withReplies }); export const expandAccountMediaTimeline = accountId => expandTimeline(`account:${accountId}:media`, `/api/v1/accounts/${accountId}/statuses`, { only_media: true }); export const expandHashtagTimeline = hashtag => expandTimeline(`hashtag:${hashtag}`, `/api/v1/timelines/tag/${hashtag}`); export const expandListTimeline = id => expandTimeline(`list:${id}`, `/api/v1/timelines/list/${id}`); diff --git a/app/javascript/mastodon/components/media_gallery.js b/app/javascript/mastodon/components/media_gallery.js index 9e1bb77c2..3568a8440 100644 --- a/app/javascript/mastodon/components/media_gallery.js +++ b/app/javascript/mastodon/components/media_gallery.js @@ -283,8 +283,9 @@ export default class MediaGallery extends React.PureComponent { if (width) { style.height = width / this.props.media.getIn([0, 'meta', 'small', 'aspect']); } + } else if (width) { + style.height = width / (16/9); } else { - // crop the image style.height = height; } @@ -309,7 +310,7 @@ export default class MediaGallery extends React.PureComponent { if (this.isStandaloneEligible()) { children = <Item standalone onClick={this.handleClick} attachment={media.get(0)} />; } else { - children = media.take(4).map((attachment, i) => <Item key={attachment.get('id')} onClick={this.handleClick} attachment={attachment} index={i} size={size} containerWidth={width} containerHeight={height} />); + children = media.take(4).map((attachment, i) => <Item key={attachment.get('id')} onClick={this.handleClick} attachment={attachment} index={i} size={size} containerWidth={width} containerHeight={style.height} />); } } diff --git a/app/javascript/mastodon/components/status.js b/app/javascript/mastodon/components/status.js index c030510a0..c52cd5f09 100644 --- a/app/javascript/mastodon/components/status.js +++ b/app/javascript/mastodon/components/status.js @@ -184,6 +184,7 @@ export default class Status extends ImmutablePureComponent { src={video.get('url')} width={239} height={110} + inline sensitive={status.get('sensitive')} onOpenVideo={this.handleOpenVideo} /> diff --git a/app/javascript/mastodon/features/account/components/action_bar.js b/app/javascript/mastodon/features/account/components/action_bar.js index b4f812c9a..b538fa5fc 100644 --- a/app/javascript/mastodon/features/account/components/action_bar.js +++ b/app/javascript/mastodon/features/account/components/action_bar.js @@ -53,11 +53,11 @@ export default class ActionBar extends React.PureComponent { let extraInfo = ''; menu.push({ text: intl.formatMessage(messages.mention, { name: account.get('username') }), action: this.props.onMention }); + if ('share' in navigator) { menu.push({ text: intl.formatMessage(messages.share, { name: account.get('username') }), action: this.handleShare }); } - menu.push(null); - menu.push({ text: intl.formatMessage(messages.media), to: `/accounts/${account.get('id')}/media` }); + menu.push(null); if (account.get('id') === me) { diff --git a/app/javascript/mastodon/features/account_gallery/components/media_item.js b/app/javascript/mastodon/features/account_gallery/components/media_item.js index dda3d4e37..59c805c38 100644 --- a/app/javascript/mastodon/features/account_gallery/components/media_item.js +++ b/app/javascript/mastodon/features/account_gallery/components/media_item.js @@ -12,24 +12,26 @@ export default class MediaItem extends ImmutablePureComponent { render () { const { media } = this.props; const status = media.get('status'); + const focusX = media.getIn(['meta', 'focus', 'x']); + const focusY = media.getIn(['meta', 'focus', 'y']); + const x = ((focusX / 2) + .5) * 100; + const y = ((focusY / -2) + .5) * 100; + const style = {}; - let content, style; + let content; if (media.get('type') === 'gifv') { content = <span className='media-gallery__gifv__label'>GIF</span>; } if (!status.get('sensitive')) { - style = { backgroundImage: `url(${media.get('preview_url')})` }; + style.backgroundImage = `url(${media.get('preview_url')})`; + style.backgroundPosition = `${x}% ${y}%`; } return ( <div className='account-gallery__item'> - <Permalink - to={`/statuses/${status.get('id')}`} - href={status.get('url')} - style={style} - > + <Permalink to={`/statuses/${status.get('id')}`} href={status.get('url')} style={style}> {content} </Permalink> </div> diff --git a/app/javascript/mastodon/features/account_gallery/index.js b/app/javascript/mastodon/features/account_gallery/index.js index ece219a3d..4b408256a 100644 --- a/app/javascript/mastodon/features/account_gallery/index.js +++ b/app/javascript/mastodon/features/account_gallery/index.js @@ -11,7 +11,6 @@ import ImmutablePureComponent from 'react-immutable-pure-component'; import { getAccountGallery } from '../../selectors'; import MediaItem from './components/media_item'; import HeaderContainer from '../account_timeline/containers/header_container'; -import { FormattedMessage } from 'react-intl'; import { ScrollContainer } from 'react-router-scroll-4'; import LoadMore from '../../components/load_more'; @@ -89,10 +88,6 @@ export default class AccountGallery extends ImmutablePureComponent { <div className='scrollable' onScroll={this.handleScroll}> <HeaderContainer accountId={this.props.params.accountId} /> - <div className='account-section-headline'> - <FormattedMessage id='account.media' defaultMessage='Media' /> - </div> - <div className='account-gallery__container'> {medias.map(media => ( <MediaItem diff --git a/app/javascript/mastodon/features/account_timeline/components/header.js b/app/javascript/mastodon/features/account_timeline/components/header.js index 0ddb6b6c1..5cd4af1d3 100644 --- a/app/javascript/mastodon/features/account_timeline/components/header.js +++ b/app/javascript/mastodon/features/account_timeline/components/header.js @@ -6,6 +6,8 @@ import ActionBar from '../../account/components/action_bar'; import MissingIndicator from '../../../components/missing_indicator'; import ImmutablePureComponent from 'react-immutable-pure-component'; import MovedNote from './moved_note'; +import { FormattedMessage } from 'react-intl'; +import { NavLink } from 'react-router-dom'; export default class Header extends ImmutablePureComponent { @@ -91,6 +93,12 @@ export default class Header extends ImmutablePureComponent { onBlockDomain={this.handleBlockDomain} onUnblockDomain={this.handleUnblockDomain} /> + + <div className='account__section-headline'> + <NavLink exact to={`/accounts/${account.get('id')}`}><FormattedMessage id='account.posts' defaultMessage='Toots' /></NavLink> + <NavLink exact to={`/accounts/${account.get('id')}/with_replies`}><FormattedMessage id='account.posts_with_replies' defaultMessage='Toots with replies' /></NavLink> + <NavLink exact to={`/accounts/${account.get('id')}/media`}><FormattedMessage id='account.media' defaultMessage='Media' /></NavLink> + </div> </div> ); } diff --git a/app/javascript/mastodon/features/account_timeline/index.js b/app/javascript/mastodon/features/account_timeline/index.js index f8c85c296..aed009ef0 100644 --- a/app/javascript/mastodon/features/account_timeline/index.js +++ b/app/javascript/mastodon/features/account_timeline/index.js @@ -12,11 +12,15 @@ import ColumnBackButton from '../../components/column_back_button'; import { List as ImmutableList } from 'immutable'; import ImmutablePureComponent from 'react-immutable-pure-component'; -const mapStateToProps = (state, props) => ({ - statusIds: state.getIn(['timelines', `account:${props.params.accountId}`, 'items'], ImmutableList()), - isLoading: state.getIn(['timelines', `account:${props.params.accountId}`, 'isLoading']), - hasMore: !!state.getIn(['timelines', `account:${props.params.accountId}`, 'next']), -}); +const mapStateToProps = (state, { params: { accountId }, withReplies = false }) => { + const path = withReplies ? `${accountId}:with_replies` : accountId; + + return { + statusIds: state.getIn(['timelines', `account:${path}`, 'items'], ImmutableList()), + isLoading: state.getIn(['timelines', `account:${path}`, 'isLoading']), + hasMore: !!state.getIn(['timelines', `account:${path}`, 'next']), + }; +}; @connect(mapStateToProps) export default class AccountTimeline extends ImmutablePureComponent { @@ -27,23 +31,24 @@ export default class AccountTimeline extends ImmutablePureComponent { statusIds: ImmutablePropTypes.list, isLoading: PropTypes.bool, hasMore: PropTypes.bool, + withReplies: PropTypes.bool, }; componentWillMount () { this.props.dispatch(fetchAccount(this.props.params.accountId)); - this.props.dispatch(refreshAccountTimeline(this.props.params.accountId)); + this.props.dispatch(refreshAccountTimeline(this.props.params.accountId, this.props.withReplies)); } componentWillReceiveProps (nextProps) { - if (nextProps.params.accountId !== this.props.params.accountId && nextProps.params.accountId) { + if ((nextProps.params.accountId !== this.props.params.accountId && nextProps.params.accountId) || nextProps.withReplies !== this.props.withReplies) { this.props.dispatch(fetchAccount(nextProps.params.accountId)); - this.props.dispatch(refreshAccountTimeline(nextProps.params.accountId)); + this.props.dispatch(refreshAccountTimeline(nextProps.params.accountId, nextProps.params.withReplies)); } } handleScrollToBottom = () => { if (!this.props.isLoading && this.props.hasMore) { - this.props.dispatch(expandAccountTimeline(this.props.params.accountId)); + this.props.dispatch(expandAccountTimeline(this.props.params.accountId, this.props.withReplies)); } } diff --git a/app/javascript/mastodon/features/compose/components/search.js b/app/javascript/mastodon/features/compose/components/search.js index 398fc44ce..71c0a203f 100644 --- a/app/javascript/mastodon/features/compose/components/search.js +++ b/app/javascript/mastodon/features/compose/components/search.js @@ -4,6 +4,7 @@ import { defineMessages, injectIntl, FormattedMessage } from 'react-intl'; import Overlay from 'react-overlays/lib/Overlay'; import Motion from '../../ui/util/optional_motion'; import spring from 'react-motion/lib/spring'; +import { searchEnabled } from '../../../initial_state'; const messages = defineMessages({ placeholder: { id: 'search.placeholder', defaultMessage: 'Search' }, @@ -17,7 +18,7 @@ class SearchPopout extends React.PureComponent { render () { const { style } = this.props; - + const extraInformation = searchEnabled ? <FormattedMessage id='search_popout.tips.full_text' defaultMessage='Simple text returns statuses you have written, favourited, boosted, or have been mentioned in, as well as matching usernames, display names, and hashtags.' /> : <FormattedMessage id='search_popout.tips.text' defaultMessage='Simple text returns matching display names, usernames and hashtags' />; return ( <div style={{ ...style, position: 'absolute', width: 285 }}> <Motion defaultStyle={{ opacity: 0, scaleX: 0.85, scaleY: 0.75 }} style={{ opacity: spring(1, { damping: 35, stiffness: 400 }), scaleX: spring(1, { damping: 35, stiffness: 400 }), scaleY: spring(1, { damping: 35, stiffness: 400 }) }}> @@ -32,7 +33,7 @@ class SearchPopout extends React.PureComponent { <li><em>URL</em> <FormattedMessage id='search_popout.tips.status' defaultMessage='status' /></li> </ul> - <FormattedMessage id='search_popout.tips.text' defaultMessage='Simple text returns matching display names, usernames and hashtags' /> + {extraInformation} </div> )} </Motion> diff --git a/app/javascript/mastodon/features/status/components/detailed_status.js b/app/javascript/mastodon/features/status/components/detailed_status.js index abdb9a3f6..d4f21fc32 100644 --- a/app/javascript/mastodon/features/status/components/detailed_status.js +++ b/app/javascript/mastodon/features/status/components/detailed_status.js @@ -57,6 +57,7 @@ export default class DetailedStatus extends ImmutablePureComponent { src={video.get('url')} width={300} height={150} + inline onOpenVideo={this.handleOpenVideo} sensitive={status.get('sensitive')} /> diff --git a/app/javascript/mastodon/features/ui/components/bundle.js b/app/javascript/mastodon/features/ui/components/bundle.js index fc88e0c70..06a6c9cdd 100644 --- a/app/javascript/mastodon/features/ui/components/bundle.js +++ b/app/javascript/mastodon/features/ui/components/bundle.js @@ -26,7 +26,7 @@ class Bundle extends React.Component { onFetchFail: noop, } - static cache = {} + static cache = new Map state = { mod: undefined, @@ -51,13 +51,12 @@ class Bundle extends React.Component { load = (props) => { const { fetchComponent, onFetch, onFetchSuccess, onFetchFail, renderDelay } = props || this.props; + const cachedMod = Bundle.cache.get(fetchComponent); onFetch(); - if (Bundle.cache[fetchComponent.name]) { - const mod = Bundle.cache[fetchComponent.name]; - - this.setState({ mod: mod.default }); + if (cachedMod) { + this.setState({ mod: cachedMod.default }); onFetchSuccess(); return Promise.resolve(); } @@ -71,7 +70,7 @@ class Bundle extends React.Component { return fetchComponent() .then((mod) => { - Bundle.cache[fetchComponent.name] = mod; + Bundle.cache.set(fetchComponent, mod); this.setState({ mod: mod.default }); onFetchSuccess(); }) diff --git a/app/javascript/mastodon/features/ui/components/columns_area.js b/app/javascript/mastodon/features/ui/components/columns_area.js index a01e5a390..e82c46402 100644 --- a/app/javascript/mastodon/features/ui/components/columns_area.js +++ b/app/javascript/mastodon/features/ui/components/columns_area.js @@ -6,6 +6,7 @@ import ImmutablePureComponent from 'react-immutable-pure-component'; import ReactSwipeableViews from 'react-swipeable-views'; import { links, getIndex, getLink } from './tabs_bar'; +import { Link } from 'react-router-dom'; import BundleContainer from '../containers/bundle_container'; import ColumnLoading from './column_loading'; @@ -152,11 +153,19 @@ export default class ColumnsArea extends ImmutablePureComponent { this.pendingIndex = null; if (singleColumn) { - return columnIndex !== -1 ? ( - <ReactSwipeableViews index={columnIndex} onChangeIndex={this.handleSwipe} onTransitionEnd={this.handleAnimationEnd} animateTransitions={shouldAnimate} springConfig={{ duration: '400ms', delay: '0s', easeFunction: 'ease' }} style={{ height: '100%' }}> + const floatingActionButton = this.context.router.history.location.pathname === '/statuses/new' ? null : <Link key='floating-action-button' to='/statuses/new' className='floating-action-button'><i className='fa fa-pencil' /></Link>; + + return columnIndex !== -1 ? [ + <ReactSwipeableViews key='content' index={columnIndex} onChangeIndex={this.handleSwipe} onTransitionEnd={this.handleAnimationEnd} animateTransitions={shouldAnimate} springConfig={{ duration: '400ms', delay: '0s', easeFunction: 'ease' }} style={{ height: '100%' }}> {links.map(this.renderView)} - </ReactSwipeableViews> - ) : <div className='columns-area'>{children}</div>; + </ReactSwipeableViews>, + + floatingActionButton, + ] : [ + <div className='columns-area'>{children}</div>, + + floatingActionButton, + ]; } return ( diff --git a/app/javascript/mastodon/features/ui/components/report_modal.js b/app/javascript/mastodon/features/ui/components/report_modal.js index b5dfa422e..3ae97646f 100644 --- a/app/javascript/mastodon/features/ui/components/report_modal.js +++ b/app/javascript/mastodon/features/ui/components/report_modal.js @@ -1,6 +1,6 @@ import React from 'react'; import { connect } from 'react-redux'; -import { changeReportComment, submitReport } from '../../../actions/reports'; +import { changeReportComment, changeReportForward, submitReport } from '../../../actions/reports'; import { refreshAccountTimeline } from '../../../actions/timelines'; import PropTypes from 'prop-types'; import ImmutablePropTypes from 'react-immutable-proptypes'; @@ -10,8 +10,11 @@ import StatusCheckBox from '../../report/containers/status_check_box_container'; import { OrderedSet } from 'immutable'; import ImmutablePureComponent from 'react-immutable-pure-component'; import Button from '../../../components/button'; +import Toggle from 'react-toggle'; +import IconButton from '../../../components/icon_button'; const messages = defineMessages({ + close: { id: 'lightbox.close', defaultMessage: 'Close' }, placeholder: { id: 'report.placeholder', defaultMessage: 'Additional comments' }, submit: { id: 'report.submit', defaultMessage: 'Submit' }, }); @@ -26,6 +29,7 @@ const makeMapStateToProps = () => { isSubmitting: state.getIn(['reports', 'new', 'isSubmitting']), account: getAccount(state, accountId), comment: state.getIn(['reports', 'new', 'comment']), + forward: state.getIn(['reports', 'new', 'forward']), statusIds: OrderedSet(state.getIn(['timelines', `account:${accountId}`, 'items'])).union(state.getIn(['reports', 'new', 'status_ids'])), }; }; @@ -42,14 +46,19 @@ export default class ReportModal extends ImmutablePureComponent { account: ImmutablePropTypes.map, statusIds: ImmutablePropTypes.orderedSet.isRequired, comment: PropTypes.string.isRequired, + forward: PropTypes.bool, dispatch: PropTypes.func.isRequired, intl: PropTypes.object.isRequired, }; - handleCommentChange = (e) => { + handleCommentChange = e => { this.props.dispatch(changeReportComment(e.target.value)); } + handleForwardChange = e => { + this.props.dispatch(changeReportForward(e.target.checked)); + } + handleSubmit = () => { this.props.dispatch(submitReport()); } @@ -65,26 +74,25 @@ export default class ReportModal extends ImmutablePureComponent { } render () { - const { account, comment, intl, statusIds, isSubmitting } = this.props; + const { account, comment, intl, statusIds, isSubmitting, forward, onClose } = this.props; if (!account) { return null; } + const domain = account.get('acct').split('@')[1]; + return ( <div className='modal-root__modal report-modal'> <div className='report-modal__target'> + <IconButton className='media-modal__close' title={intl.formatMessage(messages.close)} icon='times' onClick={onClose} size={16} /> <FormattedMessage id='report.target' defaultMessage='Report {target}' values={{ target: <strong>{account.get('acct')}</strong> }} /> </div> <div className='report-modal__container'> - <div className='report-modal__statuses'> - <div> - {statusIds.map(statusId => <StatusCheckBox id={statusId} key={statusId} disabled={isSubmitting} />)} - </div> - </div> - <div className='report-modal__comment'> + <p><FormattedMessage id='report.hint' defaultMessage='The report will be sent to your instance moderators. You can provide an explanation of why you are reporting this account below:' /></p> + <textarea className='setting-text light' placeholder={intl.formatMessage(messages.placeholder)} @@ -92,11 +100,26 @@ export default class ReportModal extends ImmutablePureComponent { onChange={this.handleCommentChange} disabled={isSubmitting} /> + + {domain && ( + <div> + <p><FormattedMessage id='report.forward_hint' defaultMessage='The account is from another server. Send an anonymized copy of the report there as well?' /></p> + + <div className='setting-toggle'> + <Toggle id='report-forward' checked={forward} disabled={isSubmitting} onChange={this.handleForwardChange} /> + <label htmlFor='report-forward' className='setting-toggle__label'><FormattedMessage id='report.forward' defaultMessage='Forward to {target}' values={{ target: domain }} /></label> + </div> + </div> + )} + + <Button disabled={isSubmitting} text={intl.formatMessage(messages.submit)} onClick={this.handleSubmit} /> </div> - </div> - <div className='report-modal__action-bar'> - <Button disabled={isSubmitting} text={intl.formatMessage(messages.submit)} onClick={this.handleSubmit} /> + <div className='report-modal__statuses'> + <div> + {statusIds.map(statusId => <StatusCheckBox id={statusId} key={statusId} disabled={isSubmitting} />)} + </div> + </div> </div> </div> ); diff --git a/app/javascript/mastodon/features/ui/components/tabs_bar.js b/app/javascript/mastodon/features/ui/components/tabs_bar.js index 7694e5ab3..77fe5f5e2 100644 --- a/app/javascript/mastodon/features/ui/components/tabs_bar.js +++ b/app/javascript/mastodon/features/ui/components/tabs_bar.js @@ -6,14 +6,13 @@ import { debounce } from 'lodash'; import { isUserTouching } from '../../../is_mobile'; export const links = [ - <NavLink className='tabs-bar__link primary' to='/statuses/new' data-preview-title-id='tabs_bar.compose' data-preview-icon='pencil' ><i className='fa fa-fw fa-pencil' /><FormattedMessage id='tabs_bar.compose' defaultMessage='Compose' /></NavLink>, <NavLink className='tabs-bar__link primary' to='/timelines/home' data-preview-title-id='column.home' data-preview-icon='home' ><i className='fa fa-fw fa-home' /><FormattedMessage id='tabs_bar.home' defaultMessage='Home' /></NavLink>, <NavLink className='tabs-bar__link primary' to='/notifications' data-preview-title-id='column.notifications' data-preview-icon='bell' ><i className='fa fa-fw fa-bell' /><FormattedMessage id='tabs_bar.notifications' defaultMessage='Notifications' /></NavLink>, <NavLink className='tabs-bar__link secondary' to='/timelines/public/local' data-preview-title-id='column.community' data-preview-icon='users' ><i className='fa fa-fw fa-users' /><FormattedMessage id='tabs_bar.local_timeline' defaultMessage='Local' /></NavLink>, <NavLink className='tabs-bar__link secondary' exact to='/timelines/public' data-preview-title-id='column.public' data-preview-icon='globe' ><i className='fa fa-fw fa-globe' /><FormattedMessage id='tabs_bar.federated_timeline' defaultMessage='Federated' /></NavLink>, - <NavLink className='tabs-bar__link primary' style={{ flexGrow: '0', flexBasis: '30px' }} to='/getting-started' data-preview-title-id='getting_started.heading' data-preview-icon='asterisk' ><i className='fa fa-fw fa-asterisk' /></NavLink>, + <NavLink className='tabs-bar__link primary' style={{ flexGrow: '0', flexBasis: '30px' }} to='/getting-started' data-preview-title-id='getting_started.heading' data-preview-icon='bars' ><i className='fa fa-fw fa-bars' /></NavLink>, ]; export function getIndex (path) { diff --git a/app/javascript/mastodon/features/ui/index.js b/app/javascript/mastodon/features/ui/index.js index 5b0d7246a..ef909136f 100644 --- a/app/javascript/mastodon/features/ui/index.js +++ b/app/javascript/mastodon/features/ui/index.js @@ -398,6 +398,7 @@ export default class UI extends React.Component { <WrappedRoute path='/statuses/:statusId/favourites' component={Favourites} content={children} /> <WrappedRoute path='/accounts/:accountId' exact component={AccountTimeline} content={children} /> + <WrappedRoute path='/accounts/:accountId/with_replies' component={AccountTimeline} content={children} componentParams={{ withReplies: true }} /> <WrappedRoute path='/accounts/:accountId/followers' component={Followers} content={children} /> <WrappedRoute path='/accounts/:accountId/following' component={Following} content={children} /> <WrappedRoute path='/accounts/:accountId/media' component={AccountGallery} content={children} /> diff --git a/app/javascript/mastodon/features/ui/util/react_router_helpers.js b/app/javascript/mastodon/features/ui/util/react_router_helpers.js index 43007ddc3..32dfe320b 100644 --- a/app/javascript/mastodon/features/ui/util/react_router_helpers.js +++ b/app/javascript/mastodon/features/ui/util/react_router_helpers.js @@ -35,14 +35,19 @@ export class WrappedRoute extends React.Component { component: PropTypes.func.isRequired, content: PropTypes.node, multiColumn: PropTypes.bool, - } + componentParams: PropTypes.object, + }; + + static defaultProps = { + componentParams: {}, + }; renderComponent = ({ match }) => { - const { component, content, multiColumn } = this.props; + const { component, content, multiColumn, componentParams } = this.props; return ( <BundleContainer fetchComponent={component} loading={this.renderLoading} error={this.renderError}> - {Component => <Component params={match.params} multiColumn={multiColumn}>{content}</Component>} + {Component => <Component params={match.params} multiColumn={multiColumn} {...componentParams}>{content}</Component>} </BundleContainer> ); } diff --git a/app/javascript/mastodon/features/video/index.js b/app/javascript/mastodon/features/video/index.js index c81a5cb5f..98ebcb6f9 100644 --- a/app/javascript/mastodon/features/video/index.js +++ b/app/javascript/mastodon/features/video/index.js @@ -97,6 +97,7 @@ export default class Video extends React.PureComponent { onOpenVideo: PropTypes.func, onCloseVideo: PropTypes.func, detailed: PropTypes.bool, + inline: PropTypes.bool, intl: PropTypes.object.isRequired, }; @@ -105,6 +106,7 @@ export default class Video extends React.PureComponent { duration: 0, paused: true, dragging: false, + containerWidth: false, fullscreen: false, hovered: false, muted: false, @@ -113,6 +115,12 @@ export default class Video extends React.PureComponent { setPlayerRef = c => { this.player = c; + + if (c) { + this.setState({ + containerWidth: c.offsetWidth, + }); + } } setVideoRef = c => { @@ -246,12 +254,23 @@ export default class Video extends React.PureComponent { } render () { - const { preview, src, width, height, startTime, onOpenVideo, onCloseVideo, intl, alt, detailed } = this.props; - const { currentTime, duration, buffer, dragging, paused, fullscreen, hovered, muted, revealed } = this.state; + const { preview, src, inline, startTime, onOpenVideo, onCloseVideo, intl, alt, detailed } = this.props; + const { containerWidth, currentTime, duration, buffer, dragging, paused, fullscreen, hovered, muted, revealed } = this.state; const progress = (currentTime / duration) * 100; + const playerStyle = {}; + + let { width, height } = this.props; + + if (inline && containerWidth) { + width = containerWidth; + height = containerWidth / (16/9); + + playerStyle.width = width; + playerStyle.height = height; + } return ( - <div className={classNames('video-player', { inactive: !revealed, detailed, inline: width && height && !fullscreen, fullscreen })} style={{ width, height }} ref={this.setPlayerRef} onMouseEnter={this.handleMouseEnter} onMouseLeave={this.handleMouseLeave}> + <div className={classNames('video-player', { inactive: !revealed, detailed, inline: inline && !fullscreen, fullscreen })} style={playerStyle} ref={this.setPlayerRef} onMouseEnter={this.handleMouseEnter} onMouseLeave={this.handleMouseLeave}> <video ref={this.setVideoRef} src={src} diff --git a/app/javascript/mastodon/initial_state.js b/app/javascript/mastodon/initial_state.js index 6f1356324..df310e7e1 100644 --- a/app/javascript/mastodon/initial_state.js +++ b/app/javascript/mastodon/initial_state.js @@ -10,5 +10,6 @@ export const unfollowModal = getMeta('unfollow_modal'); export const boostModal = getMeta('boost_modal'); export const deleteModal = getMeta('delete_modal'); export const me = getMeta('me'); +export const searchEnabled = getMeta('search_enabled'); export default initialState; diff --git a/app/javascript/mastodon/locales/ar.json b/app/javascript/mastodon/locales/ar.json index 310c7aa55..b326bc3b1 100644 --- a/app/javascript/mastodon/locales/ar.json +++ b/app/javascript/mastodon/locales/ar.json @@ -13,7 +13,8 @@ "account.moved_to": "{name} إنتقل إلى :", "account.mute": "أكتم @{name}", "account.mute_notifications": "كتم إخطارات @{name}", - "account.posts": "المشاركات", + "account.posts": "التبويقات", + "account.posts_with_replies": "Toots with replies", "account.report": "أبلغ عن @{name}", "account.requested": "في انتظار الموافقة", "account.share": "مشاركة @{name}'s profile", @@ -50,7 +51,7 @@ "column_header.unpin": "فك التدبيس", "column_subheading.navigation": "التصفح", "column_subheading.settings": "الإعدادات", - "compose_form.hashtag_warning": "This toot won't be listed under any hashtag as it is unlisted. Only public toots can be searched by hashtag.", + "compose_form.hashtag_warning": "هذا التبويق لن يُدرَج تحت أي وسم كان بما أنه غير مُدرَج. لا يُسمح بالبحث إلّا عن التبويقات العمومية عن طريق الوسوم.", "compose_form.lock_disclaimer": "حسابك ليس {locked}. يمكن لأي شخص متابعتك و عرض المنشورات.", "compose_form.lock_disclaimer.lock": "مقفل", "compose_form.placeholder": "فيمَ تفكّر؟", @@ -207,6 +208,9 @@ "relative_time.minutes": "{number}m", "relative_time.seconds": "{number}s", "reply_indicator.cancel": "إلغاء", + "report.forward": "Forward to {target}", + "report.forward_hint": "The account is from another server. Send an anonymized copy of the report there as well?", + "report.hint": "The report will be sent to your instance moderators. You can provide an explanation of why you are reporting this account below:", "report.placeholder": "تعليقات إضافية", "report.submit": "إرسال", "report.target": "إبلاغ", @@ -216,6 +220,9 @@ "search_popout.tips.status": "حالة", "search_popout.tips.text": "جملة قصيرة تُمكّنُك من عرض أسماء و حسابات و كلمات رمزية", "search_popout.tips.user": "مستخدِم", + "search_results.accounts": "People", + "search_results.hashtags": "Hashtags", + "search_results.statuses": "Toots", "search_results.total": "{count, number} {count, plural, one {result} و {results}}", "standalone.public_title": "نظرة على ...", "status.block": "Block @{name}", @@ -252,6 +259,7 @@ "upload_area.title": "إسحب ثم أفلت للرفع", "upload_button.label": "إضافة وسائط", "upload_form.description": "وصف للمعاقين بصريا", + "upload_form.focus": "Crop", "upload_form.undo": "إلغاء", "upload_progress.label": "يرفع...", "video.close": "إغلاق الفيديو", diff --git a/app/javascript/mastodon/locales/bg.json b/app/javascript/mastodon/locales/bg.json index 8188ae2c0..90e394a19 100644 --- a/app/javascript/mastodon/locales/bg.json +++ b/app/javascript/mastodon/locales/bg.json @@ -14,6 +14,7 @@ "account.mute": "Mute @{name}", "account.mute_notifications": "Mute notifications from @{name}", "account.posts": "Публикации", + "account.posts_with_replies": "Toots with replies", "account.report": "Report @{name}", "account.requested": "В очакване на одобрение", "account.share": "Share @{name}'s profile", @@ -207,6 +208,9 @@ "relative_time.minutes": "{number}m", "relative_time.seconds": "{number}s", "reply_indicator.cancel": "Отказ", + "report.forward": "Forward to {target}", + "report.forward_hint": "The account is from another server. Send an anonymized copy of the report there as well?", + "report.hint": "The report will be sent to your instance moderators. You can provide an explanation of why you are reporting this account below:", "report.placeholder": "Additional comments", "report.submit": "Submit", "report.target": "Reporting", @@ -216,6 +220,9 @@ "search_popout.tips.status": "status", "search_popout.tips.text": "Simple text returns matching display names, usernames and hashtags", "search_popout.tips.user": "user", + "search_results.accounts": "People", + "search_results.hashtags": "Hashtags", + "search_results.statuses": "Toots", "search_results.total": "{count, number} {count, plural, one {result} other {results}}", "standalone.public_title": "A look inside...", "status.block": "Block @{name}", @@ -252,6 +259,7 @@ "upload_area.title": "Drag & drop to upload", "upload_button.label": "Добави медия", "upload_form.description": "Describe for the visually impaired", + "upload_form.focus": "Crop", "upload_form.undo": "Отмяна", "upload_progress.label": "Uploading...", "video.close": "Close video", diff --git a/app/javascript/mastodon/locales/ca.json b/app/javascript/mastodon/locales/ca.json index ecaae0847..95b75cfc9 100644 --- a/app/javascript/mastodon/locales/ca.json +++ b/app/javascript/mastodon/locales/ca.json @@ -1,29 +1,30 @@ { - "account.block": "Bloquejar @{name}", - "account.block_domain": "Amagar tot de {domain}", + "account.block": "Bloca @{name}", + "account.block_domain": "Amaga-ho tot de {domain}", "account.disclaimer_full": "La informació següent pot reflectir incompleta el perfil de l'usuari.", - "account.edit_profile": "Editar perfil", - "account.follow": "Seguir", + "account.edit_profile": "Edita el perfil", + "account.follow": "Segueix", "account.followers": "Seguidors", "account.follows": "Seguint", - "account.follows_you": "et segueix", + "account.follows_you": "Et segueix", "account.hide_reblogs": "Amaga els impulsos de @{name}", "account.media": "Media", "account.mention": "Esmentar @{name}", "account.moved_to": "{name} s'ha mogut a:", - "account.mute": "Silenciar @{name}", + "account.mute": "Silencia @{name}", "account.mute_notifications": "Notificacions desactivades de @{name}", - "account.posts": "Publicacions", + "account.posts": "Toots", + "account.posts_with_replies": "Toots with replies", "account.report": "Informe @{name}", "account.requested": "Esperant aprovació. Clic per a cancel·lar la petició de seguiment", - "account.share": "Compartir el perfil de @{name}", + "account.share": "Comparteix el perfil de @{name}", "account.show_reblogs": "Mostra els impulsos de @{name}", - "account.unblock": "Desbloquejar @{name}", + "account.unblock": "Desbloca @{name}", "account.unblock_domain": "Mostra {domain}", - "account.unfollow": "Deixar de seguir", + "account.unfollow": "Deixa de seguir", "account.unmute": "Treure silenci de @{name}", "account.unmute_notifications": "Activar notificacions de @{name}", - "account.view_full_profile": "Veure el perfil complet", + "account.view_full_profile": "Mostra el perfil complet", "boost_modal.combo": "Pots premer {combo} per saltar-te això el proper cop", "bundle_column_error.body": "S'ha produït un error en carregar aquest component.", "bundle_column_error.retry": "Torna-ho a provar", @@ -31,7 +32,7 @@ "bundle_modal_error.close": "Tanca", "bundle_modal_error.message": "S'ha produït un error en carregar aquest component.", "bundle_modal_error.retry": "Torna-ho a provar", - "column.blocks": "Usuaris bloquejats", + "column.blocks": "Usuaris blocats", "column.community": "Línia de temps local", "column.favourites": "Favorits", "column.follow_requests": "Peticions per seguir-te", @@ -45,46 +46,46 @@ "column_header.hide_settings": "Amaga la configuració", "column_header.moveLeft_settings": "Mou la columna cap a l'esquerra", "column_header.moveRight_settings": "Mou la columna cap a la dreta", - "column_header.pin": "Fixar", + "column_header.pin": "Fixa", "column_header.show_settings": "Mostra la configuració", - "column_header.unpin": "Deslligar", + "column_header.unpin": "No fixis", "column_subheading.navigation": "Navegació", "column_subheading.settings": "Configuració", "compose_form.hashtag_warning": "Aquest toot no es mostrarà en cap etiqueta ja que no està llistat. Només els toots públics poden ser cercats per etiqueta.", "compose_form.lock_disclaimer": "El teu compte no està bloquejat {locked}. Tothom pot seguir-te i veure els teus missatges a seguidors.", - "compose_form.lock_disclaimer.lock": "bloquejat", + "compose_form.lock_disclaimer.lock": "blocat", "compose_form.placeholder": "En què estàs pensant?", "compose_form.publish": "Toot", "compose_form.publish_loud": "{publish}!", - "compose_form.sensitive": "Marcar multimèdia com a sensible", - "compose_form.spoiler": "Amagar text darrera l'advertència", - "compose_form.spoiler_placeholder": "Escriu l'advertència aquí", - "confirmation_modal.cancel": "Cancel·lar", - "confirmations.block.confirm": "Bloquejar", - "confirmations.block.message": "Estàs segur que vols bloquejar {name}?", - "confirmations.delete.confirm": "Esborrar", - "confirmations.delete.message": "Estàs segur que vols esborrar aquest estat?", - "confirmations.delete_list.confirm": "Delete", - "confirmations.delete_list.message": "Estàs segur que vols esborrar permanenment aquesta llista?", - "confirmations.domain_block.confirm": "Amagar tot el domini", - "confirmations.domain_block.message": "Estàs realment, realment segur que vols bloquejar totalment {domain}? En la majoria dels casos bloquejar o silenciar és suficient i preferible.", - "confirmations.mute.confirm": "Silenciar", + "compose_form.sensitive": "Marca el contingut multimèdia com a sensible", + "compose_form.spoiler": "Amaga el text darrera darrere un avís", + "compose_form.spoiler_placeholder": "Escriu l'avís aquí", + "confirmation_modal.cancel": "Cancel·la", + "confirmations.block.confirm": "Bloca", + "confirmations.block.message": "Estàs segur que vols blocar {name}?", + "confirmations.delete.confirm": "Suprimeix", + "confirmations.delete.message": "Estàs segur que vols suprimir aquest estat?", + "confirmations.delete_list.confirm": "Suprimeix", + "confirmations.delete_list.message": "Estàs segur que vols suprimir permanentment aquesta llista?", + "confirmations.domain_block.confirm": "Amaga tot el domini", + "confirmations.domain_block.message": "Estàs realment, realment segur que vols blocar totalment {domain}? En la majoria dels casos blocar o silenciar uns pocs objectius és suficient i preferible.", + "confirmations.mute.confirm": "Silencia", "confirmations.mute.message": "Estàs segur que vols silenciar {name}?", - "confirmations.unfollow.confirm": "Deixar de seguir", + "confirmations.unfollow.confirm": "Deixa de seguir", "confirmations.unfollow.message": "Estàs segur que vols deixar de seguir {name}?", "embed.instructions": "Incrusta aquest estat al lloc web copiant el codi a continuació.", "embed.preview": "Aquí tenim quin aspecte tindrá:", "emoji_button.activity": "Activitat", "emoji_button.custom": "Personalitzat", - "emoji_button.flags": "Marques", - "emoji_button.food": "Menjar i Beure", - "emoji_button.label": "Inserir emoji", + "emoji_button.flags": "Banderes", + "emoji_button.food": "Menjar i beure", + "emoji_button.label": "Insereix un emoji", "emoji_button.nature": "Natura", "emoji_button.not_found": "Emojos no!! (╯°□°)╯︵ ┻━┻", "emoji_button.objects": "Objectes", "emoji_button.people": "Gent", - "emoji_button.recent": "Freqüentment utilitzat", - "emoji_button.search": "Cercar...", + "emoji_button.recent": "Usats freqüentment", + "emoji_button.search": "Cerca...", "emoji_button.search_results": "Resultats de la cerca", "emoji_button.symbols": "Símbols", "emoji_button.travel": "Viatges i Llocs", @@ -207,6 +208,9 @@ "relative_time.minutes": "fa {number} minuts", "relative_time.seconds": "fa {number} segons", "reply_indicator.cancel": "Cancel·lar", + "report.forward": "Forward to {target}", + "report.forward_hint": "The account is from another server. Send an anonymized copy of the report there as well?", + "report.hint": "The report will be sent to your instance moderators. You can provide an explanation of why you are reporting this account below:", "report.placeholder": "Comentaris addicionals", "report.submit": "Enviar", "report.target": "Informes", @@ -216,6 +220,9 @@ "search_popout.tips.status": "status", "search_popout.tips.text": "El text simple retorna coincidències amb els noms de visualització, els noms d'usuari i els hashtags", "search_popout.tips.user": "usuari", + "search_results.accounts": "People", + "search_results.hashtags": "Hashtags", + "search_results.statuses": "Toots", "search_results.total": "{count, number} {count, plural, un {result} altres {results}}", "standalone.public_title": "Una mirada a l'interior ...", "status.block": "Block @{name}", @@ -252,6 +259,7 @@ "upload_area.title": "Arrossega i deixa anar per carregar", "upload_button.label": "Afegir multimèdia", "upload_form.description": "Descriure els problemes visuals", + "upload_form.focus": "Crop", "upload_form.undo": "Desfer", "upload_progress.label": "Pujant...", "video.close": "Tancar el vídeo", diff --git a/app/javascript/mastodon/locales/de.json b/app/javascript/mastodon/locales/de.json index aadcfac97..7f29f83ce 100644 --- a/app/javascript/mastodon/locales/de.json +++ b/app/javascript/mastodon/locales/de.json @@ -14,6 +14,7 @@ "account.mute": "@{name} stummschalten", "account.mute_notifications": "Benachrichtigungen von @{name} verbergen", "account.posts": "Beiträge", + "account.posts_with_replies": "Toots with replies", "account.report": "@{name} melden", "account.requested": "Warte auf Erlaubnis. Klicke zum Abbrechen", "account.share": "Profil von @{name} teilen", @@ -207,6 +208,9 @@ "relative_time.minutes": "{number}m", "relative_time.seconds": "{number}s", "reply_indicator.cancel": "Abbrechen", + "report.forward": "Forward to {target}", + "report.forward_hint": "The account is from another server. Send an anonymized copy of the report there as well?", + "report.hint": "The report will be sent to your instance moderators. You can provide an explanation of why you are reporting this account below:", "report.placeholder": "Zusätzliche Kommentare", "report.submit": "Absenden", "report.target": "{target} melden", @@ -216,6 +220,9 @@ "search_popout.tips.status": "status", "search_popout.tips.text": "Simple text returns matching display names, usernames and hashtags", "search_popout.tips.user": "user", + "search_results.accounts": "People", + "search_results.hashtags": "Hashtags", + "search_results.statuses": "Toots", "search_results.total": "{count, number} {count, plural, one {Ergebnis} other {Ergebnisse}}", "standalone.public_title": "Ein kleiner Einblick …", "status.block": "Block @{name}", @@ -252,6 +259,7 @@ "upload_area.title": "Zum Hochladen hereinziehen", "upload_button.label": "Mediendatei hinzufügen", "upload_form.description": "Für Menschen mit Sehbehinderung beschreiben", + "upload_form.focus": "Crop", "upload_form.undo": "Entfernen", "upload_progress.label": "Wird hochgeladen …", "video.close": "Video schließen", diff --git a/app/javascript/mastodon/locales/defaultMessages.json b/app/javascript/mastodon/locales/defaultMessages.json index c0841d6f5..52a82ff27 100644 --- a/app/javascript/mastodon/locales/defaultMessages.json +++ b/app/javascript/mastodon/locales/defaultMessages.json @@ -318,11 +318,19 @@ { "descriptors": [ { + "defaultMessage": "Toots", + "id": "account.posts" + }, + { + "defaultMessage": "Toots with replies", + "id": "account.posts_with_replies" + }, + { "defaultMessage": "Media", "id": "account.media" } ], - "path": "app/javascript/mastodon/features/account_gallery/index.json" + "path": "app/javascript/mastodon/features/account_timeline/components/header.json" }, { "descriptors": [ @@ -651,6 +659,18 @@ { "descriptors": [ { + "defaultMessage": "People", + "id": "search_results.accounts" + }, + { + "defaultMessage": "Toots", + "id": "search_results.statuses" + }, + { + "defaultMessage": "Hashtags", + "id": "search_results.hashtags" + }, + { "defaultMessage": "{count, number} {count, plural, one {result} other {results}}", "id": "search_results.total" } @@ -707,12 +727,16 @@ { "descriptors": [ { + "defaultMessage": "Describe for the visually impaired", + "id": "upload_form.description" + }, + { "defaultMessage": "Undo", "id": "upload_form.undo" }, { - "defaultMessage": "Describe for the visually impaired", - "id": "upload_form.description" + "defaultMessage": "Crop", + "id": "upload_form.focus" } ], "path": "app/javascript/mastodon/features/compose/components/upload.json" @@ -1576,6 +1600,18 @@ { "defaultMessage": "Report {target}", "id": "report.target" + }, + { + "defaultMessage": "The report will be sent to your instance moderators. You can provide an explanation of why you are reporting this account below:", + "id": "report.hint" + }, + { + "defaultMessage": "The account is from another server. Send an anonymized copy of the report there as well?", + "id": "report.forward_hint" + }, + { + "defaultMessage": "Forward to {target}", + "id": "report.forward" } ], "path": "app/javascript/mastodon/features/ui/components/report_modal.json" @@ -1672,4 +1708,4 @@ ], "path": "app/javascript/mastodon/features/video/index.json" } -] +] \ No newline at end of file diff --git a/app/javascript/mastodon/locales/en.json b/app/javascript/mastodon/locales/en.json index e72c45bf2..d2d8f3995 100644 --- a/app/javascript/mastodon/locales/en.json +++ b/app/javascript/mastodon/locales/en.json @@ -14,6 +14,7 @@ "account.mute": "Mute @{name}", "account.mute_notifications": "Mute notifications from @{name}", "account.posts": "Toots", + "account.posts_with_replies": "Toots with replies", "account.report": "Report @{name}", "account.requested": "Awaiting approval. Click to cancel follow request", "account.share": "Share @{name}'s profile", @@ -214,6 +215,9 @@ "relative_time.minutes": "{number}m", "relative_time.seconds": "{number}s", "reply_indicator.cancel": "Cancel", + "report.forward": "Forward to {target}", + "report.forward_hint": "The account is from another server. Send an anonymized copy of the report there as well?", + "report.hint": "The report will be sent to your instance moderators. You can provide an explanation of why you are reporting this account below:", "report.placeholder": "Additional comments", "report.submit": "Submit", "report.target": "Reporting {target}", @@ -223,6 +227,9 @@ "search_popout.tips.status": "status", "search_popout.tips.text": "Simple text returns matching display names, usernames and hashtags", "search_popout.tips.user": "user", + "search_results.accounts": "People", + "search_results.hashtags": "Hashtags", + "search_results.statuses": "Toots", "search_results.total": "{count, number} {count, plural, one {result} other {results}}", "standalone.public_title": "A look inside...", "status.block": "Block @{name}", @@ -259,6 +266,7 @@ "upload_area.title": "Drag & drop to upload", "upload_button.label": "Add media", "upload_form.description": "Describe for the visually impaired", + "upload_form.focus": "Crop", "upload_form.undo": "Undo", "upload_progress.label": "Uploading...", "video.close": "Close video", diff --git a/app/javascript/mastodon/locales/eo.json b/app/javascript/mastodon/locales/eo.json index cf0b4f2ec..b6153145f 100644 --- a/app/javascript/mastodon/locales/eo.json +++ b/app/javascript/mastodon/locales/eo.json @@ -1,236 +1,243 @@ { "account.block": "Bloki @{name}", - "account.block_domain": "Kaŝi ĉion el {domain}", - "account.disclaimer_full": "La ĉi-subaj informoj povas ne plene reflekti la profilon de la uzanto.", - "account.edit_profile": "Redakti la profilon", + "account.block_domain": "Kaŝi ĉion de {domain}", + "account.disclaimer_full": "Subaj informoj povas reflekti la profilon de la uzanto nekomplete.", + "account.edit_profile": "Redakti profilon", "account.follow": "Sekvi", "account.followers": "Sekvantoj", "account.follows": "Sekvatoj", "account.follows_you": "Sekvas vin", - "account.hide_reblogs": "Maski diskonigitaĵojn de @{name}", - "account.media": "Sonbildaĵoj", + "account.hide_reblogs": "Kaŝi diskonigojn de @{name}", + "account.media": "Aŭdovidaĵoj", "account.mention": "Mencii @{name}", - "account.moved_to": "{name} movis al:", + "account.moved_to": "{name} moviĝis al:", "account.mute": "Silentigi @{name}", "account.mute_notifications": "Silentigi sciigojn el @{name}", - "account.posts": "Mesaĝoj", + "account.posts": "Hupoj", + "account.posts_with_replies": "Toots with replies", "account.report": "Signali @{name}", - "account.requested": "Atendas aprobon", + "account.requested": "Atendo de aprobo. Alklaku por nuligi peton de sekvado", "account.share": "Diskonigi la profilon de @{name}", - "account.show_reblogs": "Montri diskonigaĵojn de @{name}", + "account.show_reblogs": "Montri diskonigojn de @{name}", "account.unblock": "Malbloki @{name}", "account.unblock_domain": "Malkaŝi {domain}", - "account.unfollow": "Ne plus sekvi", + "account.unfollow": "Ne plu sekvi", "account.unmute": "Malsilentigi @{name}", "account.unmute_notifications": "Malsilentigi sciigojn de @{name}", "account.view_full_profile": "Vidi plenan profilon", - "boost_modal.combo": "La proksiman fojon, premu {combo} por pasigi", - "bundle_column_error.body": "Io malfunkciis ŝargante tiun ĉi komponanton.", + "boost_modal.combo": "Vi povas premi {combo} por preterpasi sekvafoje", + "bundle_column_error.body": "Io misfunkciis en la ŝargado de ĉi tiu elemento.", "bundle_column_error.retry": "Bonvolu reprovi", "bundle_column_error.title": "Reta eraro", "bundle_modal_error.close": "Fermi", - "bundle_modal_error.message": "Io malfunkciis ŝargante tiun ĉi komponanton.", + "bundle_modal_error.message": "Io misfunkciis en la ŝargado de ĉi tiu elemento.", "bundle_modal_error.retry": "Bonvolu reprovi", "column.blocks": "Blokitaj uzantoj", "column.community": "Loka tempolinio", - "column.favourites": "Favoritoj", - "column.follow_requests": "Abonpetoj", + "column.favourites": "Stelumoj", + "column.follow_requests": "Petoj de sekvado", "column.home": "Hejmo", "column.lists": "Listoj", "column.mutes": "Silentigitaj uzantoj", "column.notifications": "Sciigoj", - "column.pins": "Alpinglitaj pepoj", + "column.pins": "Alpinglitaj mesaĝoj", "column.public": "Fratara tempolinio", "column_back_button.label": "Reveni", "column_header.hide_settings": "Kaŝi agordojn", "column_header.moveLeft_settings": "Movi kolumnon maldekstren", "column_header.moveRight_settings": "Movi kolumnon dekstren", "column_header.pin": "Alpingli", - "column_header.show_settings": "Malkaŝi agordojn", + "column_header.show_settings": "Montri agordojn", "column_header.unpin": "Depingli", "column_subheading.navigation": "Navigado", "column_subheading.settings": "Agordoj", - "compose_form.hashtag_warning": "Ĉi tiu pepo ne estos listigita en iu ajn kradvorta listo pro ĝia videbleco estas “eksterlista”. Nur publikaj pepoj povas esti kradvorte trovitaj.", - "compose_form.lock_disclaimer": "Via konta ne estas ŝlosita. Iu ajn povas sekvi vin por vidi viajn privatajn pepojn.", + "compose_form.hashtag_warning": "Ĉi tiu mesaĝo ne estos listigita per ajna kradvorto. Nur publikaj mesaĝoj estas serĉeblaj per kradvortoj.", + "compose_form.lock_disclaimer": "Via konta ne estas {locked}. Iu ajn povas sekvi vin por vidi viajn mesaĝojn nur por sekvantoj.", "compose_form.lock_disclaimer.lock": "ŝlosita", "compose_form.placeholder": "Pri kio vi pensas?", "compose_form.publish": "Hup", "compose_form.publish_loud": "{publish}!", - "compose_form.sensitive": "Marki ke la enhavo estas tikla", - "compose_form.spoiler": "Kaŝi la tekston malantaŭ averto", - "compose_form.spoiler_placeholder": "Skribu tie vian averton", - "confirmation_modal.cancel": "Malfari", + "compose_form.sensitive": "Marki aŭdovidaĵon tikla", + "compose_form.spoiler": "Kaŝi tekston malantaŭ averto", + "compose_form.spoiler_placeholder": "Skribu vian averton ĉi tie", + "confirmation_modal.cancel": "Nuligi", "confirmations.block.confirm": "Bloki", - "confirmations.block.message": "Ĉu vi konfirmas la blokadon de {name}?", - "confirmations.delete.confirm": "Malaperigi", - "confirmations.delete.message": "Ĉu vi konfirmas la malaperigon de tiun pepon?", - "confirmations.delete_list.confirm": "Delete", - "confirmations.delete_list.message": "Ĉu vi certas forviŝi ĉi tiun liston por ĉiam?", - "confirmations.domain_block.confirm": "Kaŝi la tutan reton", - "confirmations.domain_block.message": "Ĉu vi vere, vere certas, ke vi volas bloki {domain} tute? Plej ofte, kelkaj celitaj blokadoj aŭ silentigoj estas sufiĉaj kaj preferindaj.", + "confirmations.block.message": "Ĉu vi certas, ke vi volas bloki {name}?", + "confirmations.delete.confirm": "Forigi", + "confirmations.delete.message": "Ĉu vi certas, ke vi volas forigi ĉi tiun mesaĝon?", + "confirmations.delete_list.confirm": "Forigi", + "confirmations.delete_list.message": "Ĉu vi certas, ke vi volas porĉiame forigi ĉi tiun liston?", + "confirmations.domain_block.confirm": "Kaŝi la tutan domajnon", + "confirmations.domain_block.message": "Ĉu vi vere, vere certas, ke vi volas tute bloki {domain}? Plej ofte, trafa blokado kaj silentigado sufiĉas kaj preferindas.", "confirmations.mute.confirm": "Silentigi", - "confirmations.mute.message": "Ĉu vi konfirmas la silentigon de {name}?", + "confirmations.mute.message": "Ĉu vi certas, ke vi volas silentigi {name}?", "confirmations.unfollow.confirm": "Ne plu sekvi", - "confirmations.unfollow.message": "Ĉu vi volas ĉesi sekvi {name}?", - "embed.instructions": "Enmetu tiun statkonigon ĉe vian retejon kopiante la ĉi-suban kodon.", + "confirmations.unfollow.message": "Ĉu vi certas, ke vi volas ĉesi sekvi {name}?", + "embed.instructions": "Enkorpigu ĉi tiun mesaĝon en vian retejon per kopio de la suba kodo.", "embed.preview": "Ĝi aperos tiel:", - "emoji_button.activity": "Aktivecoj", - "emoji_button.custom": "Personaj", + "emoji_button.activity": "Agadoj", + "emoji_button.custom": "Propraj", "emoji_button.flags": "Flagoj", "emoji_button.food": "Manĝi kaj trinki", - "emoji_button.label": "Enmeti mieneton", + "emoji_button.label": "Enmeti emoĝion", "emoji_button.nature": "Naturo", - "emoji_button.not_found": "Neniuj mienetoj!! (╯°□°)╯︵ ┻━┻", - "emoji_button.objects": "Objektoj", + "emoji_button.not_found": "Neniu emoĝio!! (╯°□°)╯︵ ┻━┻", + "emoji_button.objects": "Aĵoj", "emoji_button.people": "Homoj", "emoji_button.recent": "Ofte uzataj", "emoji_button.search": "Serĉo…", - "emoji_button.search_results": "Rezultatoj de serĉo", + "emoji_button.search_results": "Serĉaj rezultoj", "emoji_button.symbols": "Simboloj", - "emoji_button.travel": "Vojaĝoj & lokoj", + "emoji_button.travel": "Vojaĝoj kaj lokoj", "empty_column.community": "La loka tempolinio estas malplena. Skribu ion por plenigi ĝin!", - "empty_column.hashtag": "Ĝise, neniu enhavo estas asociita kun tiu kradvorto.", + "empty_column.hashtag": "Ankoraŭ estas nenio per ĉi tiu kradvorto.", "empty_column.home": "Via hejma tempolinio estas malplena! Vizitu {public} aŭ uzu la serĉilon por renkonti aliajn uzantojn.", "empty_column.home.public_timeline": "la publika tempolinio", - "empty_column.list": "Estas ankoraŭ nenio en ĉi tiu listo. Tuj kiam anoj de ĉi tiu listo publikigos, ties pepoj aperos ĉi tie.", - "empty_column.notifications": "Vi dume ne havas sciigojn. Interagi kun aliajn uzantojn por komenci la konversacion.", - "empty_column.public": "Estas nenio ĉi tie! Publike skribu ion, aŭ mane sekvu uzantojn de aliaj instancoj por plenigi la publikan tempolinion", - "follow_request.authorize": "Akcepti", + "empty_column.list": "Ankoraŭ estas nenio en ĉi tiu listo. Kiam membroj de ĉi tiu listo afiŝos novajn mesaĝojn, ili aperos ĉi tie.", + "empty_column.notifications": "Vi ankoraŭ ne havas sciigojn. Interagu kun aliaj por komenci konversacion.", + "empty_column.public": "Estas nenio ĉi tie! Publike skribu ion, aŭ mane sekvu uzantojn de aliaj nodoj por plenigi la publikan tempolinion", + "follow_request.authorize": "Rajtigi", "follow_request.reject": "Rifuzi", "getting_started.appsshort": "Aplikaĵoj", "getting_started.faq": "Oftaj demandoj", "getting_started.heading": "Por komenci", - "getting_started.open_source_notice": "Mastodono estas malfermkoda programo. Vi povas kontribui aŭ raporti problemojn en GitHub je {github}.", + "getting_started.open_source_notice": "Mastodon estas malfermitkoda programo. Vi povas kontribui aŭ raporti problemojn en GitHub je {github}.", "getting_started.userguide": "Gvidilo de uzo", "home.column_settings.advanced": "Precizaj agordoj", "home.column_settings.basic": "Bazaj agordoj", - "home.column_settings.filter_regex": "Forfiltri per regulesprimo", + "home.column_settings.filter_regex": "Filtri per regulesprimoj", "home.column_settings.show_reblogs": "Montri diskonigojn", "home.column_settings.show_replies": "Montri respondojn", - "home.settings": "Agordoj de la kolumno", - "keyboard_shortcuts.back": "reeniri", - "keyboard_shortcuts.boost": "diskonigi", - "keyboard_shortcuts.column": "fokusigi statuson en unu el la columnoj", - "keyboard_shortcuts.compose": "por fokusigi la redaktujon", - "keyboard_shortcuts.description": "Description", - "keyboard_shortcuts.down": "subenmovi en la listo", - "keyboard_shortcuts.enter": "to open status", - "keyboard_shortcuts.favourite": "ŝatitaren", - "keyboard_shortcuts.heading": "Keyboard Shortcuts", + "home.settings": "Kolumnaj agordoj", + "keyboard_shortcuts.back": "por reveni", + "keyboard_shortcuts.boost": "por diskonigi", + "keyboard_shortcuts.column": "por fokusigi mesaĝon en unu el la kolumnoj", + "keyboard_shortcuts.compose": "por fokusigi la tekstujon", + "keyboard_shortcuts.description": "Priskribo", + "keyboard_shortcuts.down": "por iri suben en la listo", + "keyboard_shortcuts.enter": "por malfermi mesaĝon", + "keyboard_shortcuts.favourite": "por stelumi", + "keyboard_shortcuts.heading": "Klavaraj mallongigoj", "keyboard_shortcuts.hotkey": "Rapidklavo", - "keyboard_shortcuts.legend": "por montri ĉi tiun legendon", - "keyboard_shortcuts.mention": "por sciigi ties aŭtoron", + "keyboard_shortcuts.legend": "por montri ĉi tiun noton", + "keyboard_shortcuts.mention": "por mencii la aŭtoron", "keyboard_shortcuts.reply": "por respondi", - "keyboard_shortcuts.search": "por fokusigi la serĉadon", - "keyboard_shortcuts.toot": "por ekredakti tute novan pepon", - "keyboard_shortcuts.unfocus": "por malfokusigi la redaktujon aŭ la serĉilon", - "keyboard_shortcuts.up": "por suprenmovi en la listo", + "keyboard_shortcuts.search": "por fokusigi la serĉilon", + "keyboard_shortcuts.toot": "por komenci tute novan mesaĝon", + "keyboard_shortcuts.unfocus": "por malfokusigi la tekstujon aŭ la serĉilon", + "keyboard_shortcuts.up": "por iri supren en la listo", "lightbox.close": "Fermi", - "lightbox.next": "Malantaŭa", + "lightbox.next": "Sekva", "lightbox.previous": "Antaŭa", "lists.account.add": "Aldoni al la listo", - "lists.account.remove": "Forviŝi de la listo", - "lists.delete": "Delete list", + "lists.account.remove": "Forigi de la listo", + "lists.delete": "Forigi la liston", "lists.edit": "Redakti la liston", "lists.new.create": "Aldoni liston", - "lists.new.title_placeholder": "Titulo de la nova listo", - "lists.search": "Serĉi el la homoj kiujn vi sekvas", + "lists.new.title_placeholder": "Titolo de la nova listo", + "lists.search": "Serĉi inter la homoj, kiujn vi sekvas", "lists.subheading": "Viaj listoj", - "loading_indicator.label": "Ŝarganta…", - "media_gallery.toggle_visible": "Baskuli videblecon", + "loading_indicator.label": "Ŝargado…", + "media_gallery.toggle_visible": "Baskuligi videblecon", "missing_indicator.label": "Ne trovita", - "missing_indicator.sublabel": "Ĉi tiu rimedo ne troviĝis", - "mute_modal.hide_notifications": "Ĉu kaŝi sciigojn el tiu ĉi uzanto?", + "missing_indicator.sublabel": "Ĉi tiu rimedo ne estis trovita", + "mute_modal.hide_notifications": "Ĉu kaŝi sciigojn el ĉi tiu uzanto?", "navigation_bar.blocks": "Blokitaj uzantoj", "navigation_bar.community_timeline": "Loka tempolinio", - "navigation_bar.edit_profile": "Redakti la profilon", - "navigation_bar.favourites": "Favoritaj", - "navigation_bar.follow_requests": "Abonpetoj", - "navigation_bar.info": "Plia informo", - "navigation_bar.keyboard_shortcuts": "Klavmallongigo", + "navigation_bar.edit_profile": "Redakti profilon", + "navigation_bar.favourites": "Stelumoj", + "navigation_bar.follow_requests": "Petoj de sekvado", + "navigation_bar.info": "Pri ĉiu tiu nodo", + "navigation_bar.keyboard_shortcuts": "Klavaraj mallongigoj", "navigation_bar.lists": "Listoj", "navigation_bar.logout": "Elsaluti", "navigation_bar.mutes": "Silentigitaj uzantoj", - "navigation_bar.pins": "Alpinglitaj pepoj", + "navigation_bar.pins": "Alpinglitaj mesaĝoj", "navigation_bar.preferences": "Preferoj", "navigation_bar.public_timeline": "Fratara tempolinio", - "notification.favourite": "{name} favoris vian mesaĝon", - "notification.follow": "{name} sekvis vin", + "notification.favourite": "{name} stelumis vian mesaĝon", + "notification.follow": "{name} eksekvis vin", "notification.mention": "{name} menciis vin", "notification.reblog": "{name} diskonigis vian mesaĝon", - "notifications.clear": "Forviŝi la sciigojn", - "notifications.clear_confirmation": "Ĉu vi certe volas malaperigi ĉiujn viajn sciigojn?", - "notifications.column_settings.alert": "Retumilaj atentigoj", - "notifications.column_settings.favourite": "Favoritoj:", + "notifications.clear": "Forviŝi sciigojn", + "notifications.clear_confirmation": "Ĉu vi certas, ke vi volas porĉiame forviŝi ĉiujn viajn sciigojn?", + "notifications.column_settings.alert": "Retumilaj sciigoj", + "notifications.column_settings.favourite": "Stelumoj:", "notifications.column_settings.follow": "Novaj sekvantoj:", "notifications.column_settings.mention": "Mencioj:", "notifications.column_settings.push": "Puŝsciigoj", - "notifications.column_settings.push_meta": "Tiu ĉi aparato", + "notifications.column_settings.push_meta": "Ĉi tiu aparato", "notifications.column_settings.reblog": "Diskonigoj:", - "notifications.column_settings.show": "Montri en kolono", + "notifications.column_settings.show": "Montri en kolumno", "notifications.column_settings.sound": "Eligi sonon", "onboarding.done": "Farita", - "onboarding.next": "Malantaŭa", - "onboarding.page_five.public_timelines": "La loka tempolinio enhavas mesaĝojn de ĉiuj ĉe {domain}. La federacia tempolinio enhavas ĉiujn mesaĝojn de uzantoj, kiujn iu ĉe {domain} sekvas. Ambaŭ tre utilas por trovi novajn kunparolantojn.", - "onboarding.page_four.home": "La hejma tempolinio enhavas la mesaĝojn de ĉiuj uzantoj, kiuj vi sekvas.", - "onboarding.page_four.notifications": "La sciiga kolumno informas vin kiam iu interagas kun vi.", - "onboarding.page_one.federation": "Mastodono estas reto de nedependaj serviloj, unuiĝintaj por krei pligrandan socian retejon. Ni nomas tiujn servilojn instancoj.", - "onboarding.page_one.full_handle": "Via tuta uzantnomo", - "onboarding.page_one.handle_hint": "Jen kion vi dirintus al viaj amikoj por serĉi.", - "onboarding.page_one.welcome": "Bonvenon al Mastodono!", - "onboarding.page_six.admin": "Via instancestro estas {admin}.", - "onboarding.page_six.almost_done": "Estas preskaŭ finita…", - "onboarding.page_six.appetoot": "Bonan a‘pepi’ton!", - "onboarding.page_six.apps_available": "{apps} estas elŝuteblaj por iOS, Androido kaj alioj.", - "onboarding.page_six.github": "Mastodono estas libera, senpaga kaj malfermkoda programaro. Vi povas signali cimojn, proponi funkciojn aŭ kontribui al gîa kreskado ĉe {github}.", - "onboarding.page_six.guidelines": "komunreguloj", - "onboarding.page_six.read_guidelines": "Ni petas vin: ne forgesu legi la {guidelines}n de {domain}!", - "onboarding.page_six.various_app": "telefon-aplikaĵoj", - "onboarding.page_three.profile": "Redaktu vian profilon por ŝanĝi vian avataron, priskribon kaj vian nomon. Vi tie trovos ankoraŭ aliajn agordojn.", - "onboarding.page_three.search": "Uzu la serĉokampo por trovi uzantojn kaj esplori kradvortojn tiel ke {illustration} kaj {introductions}. Por trovi iun, kiu ne estas ĉe ĉi tiu instanco, uzu ĝian kompletan uznomon.", - "onboarding.page_two.compose": "Skribu pepojn en la verkkolumno. Vi povas aldoni bildojn, ŝanĝi la agordojn de privateco kaj aldoni tiklavertojn (« content warning ») dank' al la piktogramoj malsupre.", - "onboarding.skip": "Pasigi", - "privacy.change": "Alĝustigi la privateco de la mesaĝo", - "privacy.direct.long": "Vidigi nur al la menciitaj personoj", + "onboarding.next": "Sekva", + "onboarding.page_five.public_timelines": "La loka tempolinio montras publikajn mesaĝojn de ĉiuj en {domain}. La fratara tempolinio montras publikajn mesaĝojn de ĉiuj, kiuj estas sekvataj de homoj en {domain}. Tio estas la publikaj tempolinioj, kio estas bona maniero por malkovri novajn homojn.", + "onboarding.page_four.home": "La hejma tempolinio montras mesaĝojn de ĉiuj uzantoj, kiujn vi sekvas.", + "onboarding.page_four.notifications": "La sciiga kolumno montras kiam iu interagas kun vi.", + "onboarding.page_one.federation": "Mastodon estas reto de sendependaj serviloj, unuiĝintaj por krei pligrandan socian reton. Ni nomas tiujn servilojn nodoj.", + "onboarding.page_one.full_handle": "Via kompleta uzantnomo", + "onboarding.page_one.handle_hint": "Jen kion vi petus al viaj amikoj serĉi.", + "onboarding.page_one.welcome": "Bonvenon en Mastodon!", + "onboarding.page_six.admin": "Via noda administranto estas {admin}.", + "onboarding.page_six.almost_done": "Preskaŭ finita…", + "onboarding.page_six.appetoot": "Saĝan mesaĝadon!", + "onboarding.page_six.apps_available": "{apps} estas disponeblaj por iOS, Android kaj aliaj platformoj.", + "onboarding.page_six.github": "Mastodon estas libera, senpaga kaj malfermitkoda programo. Vi povas raporti cimojn, proponi funkciojn aŭ kontribui al la kodo en {github}.", + "onboarding.page_six.guidelines": "komunumaj gvidlinioj", + "onboarding.page_six.read_guidelines": "Bonvolu atenti pri la {guidelines} de {domain}!", + "onboarding.page_six.various_app": "telefonaj aplikaĵoj", + "onboarding.page_three.profile": "Redaktu vian profilon por ŝanĝi vian profilbildon, priskribon kaj nomon. Vi ankaŭ trovos tie aliajn agordojn.", + "onboarding.page_three.search": "Uzu la serĉilon por trovi uzantojn kaj esplori kradvortojn, tiel {illustration} kaj {introductions}. Por trovi iun, kiu ne estas en ĉi tiu nodo, uzu ties kompletan uzantnomon.", + "onboarding.page_two.compose": "Skribu mesaĝojn en la skriba kolumno. Vi povas alŝuti bildojn, ŝanĝi privatecajn agordojn, kaj aldoni avertojn pri la enhavo per la subaj bildetoj.", + "onboarding.skip": "Preterpasi", + "privacy.change": "Agordi mesaĝan privatecon", + "privacy.direct.long": "Afiŝi nur al menciitaj uzantoj", "privacy.direct.short": "Rekta", - "privacy.private.long": "Vidigi nur al viaj sekvantoj", - "privacy.private.short": "Nursekvanta", - "privacy.public.long": "Vidigi en publikaj tempolinioj", + "privacy.private.long": "Afiŝi nur al sekvantoj", + "privacy.private.short": "Nur por sekvantoj", + "privacy.public.long": "Afiŝi en publikaj tempolinioj", "privacy.public.short": "Publika", - "privacy.unlisted.long": "Ne vidigi en publikaj tempolinioj", + "privacy.unlisted.long": "Ne afiŝi en publikaj tempolinioj", "privacy.unlisted.short": "Nelistigita", - "regeneration_indicator.label": "Elŝultanta…", - "regeneration_indicator.sublabel": "Via ĉefpaĝo estas preparanta!", + "regeneration_indicator.label": "Ŝargado…", + "regeneration_indicator.sublabel": "Via hejma fluo pretiĝas!", "relative_time.days": "{number}t", "relative_time.hours": "{number}h", "relative_time.just_now": "nun", "relative_time.minutes": "{number}m", "relative_time.seconds": "{number}s", - "reply_indicator.cancel": "Malfari", + "reply_indicator.cancel": "Nuligi", + "report.forward": "Forward to {target}", + "report.forward_hint": "The account is from another server. Send an anonymized copy of the report there as well?", + "report.hint": "The report will be sent to your instance moderators. You can provide an explanation of why you are reporting this account below:", "report.placeholder": "Pliaj komentoj", "report.submit": "Sendi", - "report.target": "Signalaĵo", + "report.target": "Signali {target}", "search.placeholder": "Serĉi", "search_popout.search_format": "Detala serĉo", "search_popout.tips.hashtag": "kradvorto", - "search_popout.tips.status": "statkonigo", - "search_popout.tips.text": "Simpla teksto eligas la kongruajn afiŝnomojn, uznomojn kaj kradvortojn", + "search_popout.tips.status": "mesaĝoj", + "search_popout.tips.text": "Simpla teksto montras la kongruajn afiŝitajn nomojn, uzantnomojn kaj kradvortojn", "search_popout.tips.user": "uzanto", - "search_results.total": "{count, number} {count, plural, one {rezultato} other {rezultatoj}}", - "standalone.public_title": "Rigardeti…", - "status.block": "Block @{name}", - "status.cannot_reblog": "Tiun publikaĵon oni ne povas diskonigi", + "search_results.accounts": "People", + "search_results.hashtags": "Hashtags", + "search_results.statuses": "Toots", + "search_results.total": "{count, number} {count, plural, one {rezulto} other {rezultoj}}", + "standalone.public_title": "Enrigardo…", + "status.block": "Bloki @{name}", + "status.cannot_reblog": "Ĉi tiu mesaĝo ne diskonigeblas", "status.delete": "Forigi", - "status.embed": "Enmeti", - "status.favourite": "Favori", - "status.load_more": "Ŝargi plie", - "status.media_hidden": "Sonbildaĵo kaŝita", + "status.embed": "Enkorpigi", + "status.favourite": "Stelumi", + "status.load_more": "Ŝargi pli", + "status.media_hidden": "Aŭdovidaĵo kaŝita", "status.mention": "Mencii @{name}", "status.more": "Pli", "status.mute": "Silentigi @{name}", "status.mute_conversation": "Silentigi konversacion", - "status.open": "Disfaldi statkonigon", - "status.pin": "Pingli al la profilo", + "status.open": "Grandigi ĉi tiun mesaĝon", + "status.pin": "Alpingli en la profilo", "status.reblog": "Diskonigi", "status.reblogged_by": "{name} diskonigis", "status.reply": "Respondi", @@ -239,28 +246,29 @@ "status.sensitive_toggle": "Alklaki por vidi", "status.sensitive_warning": "Tikla enhavo", "status.share": "Diskonigi", - "status.show_less": "Refaldi", - "status.show_more": "Disfaldi", + "status.show_less": "Malgrandigi", + "status.show_more": "Grandigi", "status.unmute_conversation": "Malsilentigi konversacion", "status.unpin": "Depingli de profilo", "tabs_bar.compose": "Ekskribi", - "tabs_bar.federated_timeline": "Federacia tempolinio", + "tabs_bar.federated_timeline": "Fratara tempolinio", "tabs_bar.home": "Hejmo", "tabs_bar.local_timeline": "Loka tempolinio", "tabs_bar.notifications": "Sciigoj", "ui.beforeunload": "Via malneto perdiĝos se vi eliras de Mastodon.", - "upload_area.title": "Algliti por alŝuti", - "upload_button.label": "Aldoni sonbildaĵon", - "upload_form.description": "Priskribi por la misvidantaj", + "upload_area.title": "Altreni kaj lasi por alŝuti", + "upload_button.label": "Aldoni aŭdovidaĵon", + "upload_form.description": "Priskribi por misvidantaj homoj", + "upload_form.focus": "Crop", "upload_form.undo": "Malfari", - "upload_progress.label": "Alŝutanta…", + "upload_progress.label": "Alŝutado…", "video.close": "Fermi videon", - "video.exit_fullscreen": "Eliri el plenekrano", - "video.expand": "Vastigi videon", - "video.fullscreen": "Igi plenekrane", + "video.exit_fullscreen": "Eksigi plenekrana", + "video.expand": "Grandigi videon", + "video.fullscreen": "Igi plenekrana", "video.hide": "Kaŝi videon", "video.mute": "Silentigi", "video.pause": "Paŭzi", - "video.play": "Legi", + "video.play": "Ekigi", "video.unmute": "Malsilentigi" } diff --git a/app/javascript/mastodon/locales/es.json b/app/javascript/mastodon/locales/es.json index 4bb15396c..5f16ec974 100644 --- a/app/javascript/mastodon/locales/es.json +++ b/app/javascript/mastodon/locales/es.json @@ -14,6 +14,7 @@ "account.mute": "Silenciar a @{name}", "account.mute_notifications": "Silenciar notificaciones de @{name}", "account.posts": "Publicaciones", + "account.posts_with_replies": "Toots with replies", "account.report": "Reportar a @{name}", "account.requested": "Esperando aprobación", "account.share": "Compartir el perfil de @{name}", @@ -207,6 +208,9 @@ "relative_time.minutes": "{number}m", "relative_time.seconds": "{number}s", "reply_indicator.cancel": "Cancelar", + "report.forward": "Forward to {target}", + "report.forward_hint": "The account is from another server. Send an anonymized copy of the report there as well?", + "report.hint": "The report will be sent to your instance moderators. You can provide an explanation of why you are reporting this account below:", "report.placeholder": "Comentarios adicionales", "report.submit": "Publicar", "report.target": "Reportando", @@ -216,6 +220,9 @@ "search_popout.tips.status": "status", "search_popout.tips.text": "El texto simple devuelve correspondencias de nombre, usuario y hashtag", "search_popout.tips.user": "usuario", + "search_results.accounts": "People", + "search_results.hashtags": "Hashtags", + "search_results.statuses": "Toots", "search_results.total": "{count, number} {count, plural, one {resultado} other {resultados}}", "standalone.public_title": "Un pequeño vistazo...", "status.block": "Block @{name}", @@ -252,6 +259,7 @@ "upload_area.title": "Arrastra y suelta para subir", "upload_button.label": "Subir multimedia", "upload_form.description": "Describir para los usuarios con dificultad visual", + "upload_form.focus": "Crop", "upload_form.undo": "Deshacer", "upload_progress.label": "Subiendo…", "video.close": "Cerrar video", diff --git a/app/javascript/mastodon/locales/fa.json b/app/javascript/mastodon/locales/fa.json index 6846da66d..4fd467a66 100644 --- a/app/javascript/mastodon/locales/fa.json +++ b/app/javascript/mastodon/locales/fa.json @@ -14,6 +14,7 @@ "account.mute": "بیصدا کردن @{name}", "account.mute_notifications": "بیصداکردن اعلانها از طرف @{name}", "account.posts": "نوشتهها", + "account.posts_with_replies": "Toots with replies", "account.report": "گزارش @{name}", "account.requested": "در انتظار پذیرش", "account.share": "همرسانی نمایهٔ @{name}", @@ -207,6 +208,9 @@ "relative_time.minutes": "{number}m", "relative_time.seconds": "{number}s", "reply_indicator.cancel": "لغو", + "report.forward": "Forward to {target}", + "report.forward_hint": "The account is from another server. Send an anonymized copy of the report there as well?", + "report.hint": "The report will be sent to your instance moderators. You can provide an explanation of why you are reporting this account below:", "report.placeholder": "توضیح اضافه", "report.submit": "بفرست", "report.target": "گزارشدادن", @@ -216,6 +220,9 @@ "search_popout.tips.status": "نوشته", "search_popout.tips.text": "جستجوی متنی ساده برای نامها، نامهای کاربری، و هشتگها", "search_popout.tips.user": "کاربر", + "search_results.accounts": "People", + "search_results.hashtags": "Hashtags", + "search_results.statuses": "Toots", "search_results.total": "{count, number} {count, plural, one {نتیجه} other {نتیجه}}", "standalone.public_title": "نگاهی به کاربران این سرور...", "status.block": "Block @{name}", @@ -252,6 +259,7 @@ "upload_area.title": "برای بارگذاری به اینجا بکشید", "upload_button.label": "افزودن تصویر", "upload_form.description": "نوشتهٔ توضیحی برای کمبینایان و نابینایان", + "upload_form.focus": "Crop", "upload_form.undo": "واگردانی", "upload_progress.label": "بارگذاری...", "video.close": "بستن ویدیو", diff --git a/app/javascript/mastodon/locales/fi.json b/app/javascript/mastodon/locales/fi.json index eb81e7eb4..d27ba1834 100644 --- a/app/javascript/mastodon/locales/fi.json +++ b/app/javascript/mastodon/locales/fi.json @@ -1,266 +1,274 @@ { "account.block": "Estä @{name}", - "account.block_domain": "Hide everything from {domain}", - "account.disclaimer_full": "Information below may reflect the user's profile incompletely.", + "account.block_domain": "Piilota kaikki sisältö verkkotunnuksesta {domain}", + "account.disclaimer_full": "Alla olevat käyttäjän profiilitiedot saattavat olla epätäydellisiä.", "account.edit_profile": "Muokkaa", "account.follow": "Seuraa", "account.followers": "Seuraajia", "account.follows": "Seuraa", "account.follows_you": "Seuraa sinua", - "account.hide_reblogs": "Hide boosts from @{name}", + "account.hide_reblogs": "Piilota buustaukset käyttäjältä @{name}", "account.media": "Media", "account.mention": "Mainitse @{name}", - "account.moved_to": "{name} has moved to:", - "account.mute": "Mute @{name}", - "account.mute_notifications": "Mute notifications from @{name}", - "account.posts": "Postit", + "account.moved_to": "{name} on muuttanut instanssiin:", + "account.mute": "Mykistä @{name}", + "account.mute_notifications": "Mykistä ilmoitukset käyttäjältä @{name}", + "account.posts": "Töötit", + "account.posts_with_replies": "Toots with replies", "account.report": "Report @{name}", - "account.requested": "Odottaa hyväksyntää", - "account.share": "Share @{name}'s profile", - "account.show_reblogs": "Show boosts from @{name}", + "account.requested": "Odottaa hyväksyntää. Klikkaa peruuttaaksesi seurauspyynnön", + "account.share": "Jaa käyttäjän @{name} profiili", + "account.show_reblogs": "Näytä boostaukset käyttäjältä @{name}", "account.unblock": "Salli @{name}", - "account.unblock_domain": "Unhide {domain}", - "account.unfollow": "Lopeta seuraaminen", - "account.unmute": "Unmute @{name}", - "account.unmute_notifications": "Unmute notifications from @{name}", - "account.view_full_profile": "View full profile", - "boost_modal.combo": "You can press {combo} to skip this next time", - "bundle_column_error.body": "Something went wrong while loading this component.", - "bundle_column_error.retry": "Try again", + "account.unblock_domain": "Näytä {domain}", + "account.unfollow": "Lakkaa seuraamasta", + "account.unmute": "Poista mykistys käyttäjältä @{name}", + "account.unmute_notifications": "Poista mykistys käyttäjän @{name} ilmoituksilta", + "account.view_full_profile": "Näytä koko profiili", + "boost_modal.combo": "Voit painaa näppäimiä {combo} ohittaaksesi tämän ensi kerralla", + "bundle_column_error.body": "Jokin meni vikaan tätä komponenttia ladatessa.", + "bundle_column_error.retry": "Yritä uudestaan", "bundle_column_error.title": "Network error", - "bundle_modal_error.close": "Close", - "bundle_modal_error.message": "Something went wrong while loading this component.", - "bundle_modal_error.retry": "Try again", - "column.blocks": "Blocked users", + "bundle_modal_error.close": "Sulje", + "bundle_modal_error.message": "Jokin meni vikaan tätä komponenttia ladatessa.", + "bundle_modal_error.retry": "Yritä uudestaan", + "column.blocks": "Estetyt käyttäjät", "column.community": "Paikallinen aikajana", - "column.favourites": "Favourites", - "column.follow_requests": "Follow requests", + "column.favourites": "Suosikit", + "column.follow_requests": "Seurauspyynnöt", "column.home": "Koti", - "column.lists": "Lists", - "column.mutes": "Muted users", + "column.lists": "Listat", + "column.mutes": "Mykistetyt käyttäjät", "column.notifications": "Ilmoitukset", "column.pins": "Pinned toot", "column.public": "Yleinen aikajana", "column_back_button.label": "Takaisin", - "column_header.hide_settings": "Hide settings", - "column_header.moveLeft_settings": "Move column to the left", - "column_header.moveRight_settings": "Move column to the right", - "column_header.pin": "Pin", - "column_header.show_settings": "Show settings", - "column_header.unpin": "Unpin", - "column_subheading.navigation": "Navigation", - "column_subheading.settings": "Settings", - "compose_form.hashtag_warning": "This toot won't be listed under any hashtag as it is unlisted. Only public toots can be searched by hashtag.", - "compose_form.lock_disclaimer": "Your account is not {locked}. Anyone can follow you to view your follower-only posts.", - "compose_form.lock_disclaimer.lock": "locked", + "column_header.hide_settings": "Piilota asetukset", + "column_header.moveLeft_settings": "Siirrä saraketta vasemmalle", + "column_header.moveRight_settings": "Siirrä saraketta oikealle", + "column_header.pin": "Kiinnitä", + "column_header.show_settings": "Näytä asetukset", + "column_header.unpin": "Poista kiinnitys", + "column_subheading.navigation": "Navigaatio", + "column_subheading.settings": "Asetukset", + "compose_form.hashtag_warning": "Tämä töötti ei tule näkymään hashtag-hauissa, koska se ei näy julkisilla aikajanoilla. Vain julkisia tööttejä voi hakea hashtageilla.", + "compose_form.lock_disclaimer": "Tilisi ei ole {locked}. Kuka tahansa voi seurata tiliäsi ja nähdä vain seuraajille -postauksesi.", + "compose_form.lock_disclaimer.lock": "lukittu", "compose_form.placeholder": "Mitä sinulla on mielessä?", "compose_form.publish": "Toot", "compose_form.publish_loud": "{publish}!", "compose_form.sensitive": "Merkitse media herkäksi", "compose_form.spoiler": "Piiloita teksti varoituksen taakse", "compose_form.spoiler_placeholder": "Content warning", - "confirmation_modal.cancel": "Cancel", - "confirmations.block.confirm": "Block", - "confirmations.block.message": "Are you sure you want to block {name}?", + "confirmation_modal.cancel": "Peruuta", + "confirmations.block.confirm": "Estä", + "confirmations.block.message": "Oletko varma, että haluat estää käyttäjän {name}?", "confirmations.delete.confirm": "Delete", - "confirmations.delete.message": "Are you sure you want to delete this status?", + "confirmations.delete.message": "Oletko varma, että haluat poistaa tämän statuspäivityksen?", "confirmations.delete_list.confirm": "Delete", - "confirmations.delete_list.message": "Are you sure you want to permanently delete this list?", - "confirmations.domain_block.confirm": "Hide entire domain", - "confirmations.domain_block.message": "Are you really, really sure you want to block the entire {domain}? In most cases a few targeted blocks or mutes are sufficient and preferable.", - "confirmations.mute.confirm": "Mute", - "confirmations.mute.message": "Are you sure you want to mute {name}?", - "confirmations.unfollow.confirm": "Unfollow", - "confirmations.unfollow.message": "Are you sure you want to unfollow {name}?", - "embed.instructions": "Embed this status on your website by copying the code below.", - "embed.preview": "Here is what it will look like:", - "emoji_button.activity": "Activity", - "emoji_button.custom": "Custom", - "emoji_button.flags": "Flags", - "emoji_button.food": "Food & Drink", - "emoji_button.label": "Insert emoji", - "emoji_button.nature": "Nature", - "emoji_button.not_found": "No emojos!! (╯°□°)╯︵ ┻━┻", - "emoji_button.objects": "Objects", - "emoji_button.people": "People", - "emoji_button.recent": "Frequently used", - "emoji_button.search": "Search...", - "emoji_button.search_results": "Search results", - "emoji_button.symbols": "Symbols", - "emoji_button.travel": "Travel & Places", - "empty_column.community": "The local timeline is empty. Write something publicly to get the ball rolling!", - "empty_column.hashtag": "There is nothing in this hashtag yet.", - "empty_column.home": "Your home timeline is empty! Visit {public} or use search to get started and meet other users.", - "empty_column.home.public_timeline": "the public timeline", - "empty_column.list": "There is nothing in this list yet.", - "empty_column.notifications": "You don't have any notifications yet. Interact with others to start the conversation.", - "empty_column.public": "There is nothing here! Write something publicly, or manually follow users from other instances to fill it up", - "follow_request.authorize": "Authorize", - "follow_request.reject": "Reject", - "getting_started.appsshort": "Apps", + "confirmations.delete_list.message": "Oletko varma, että haluat poistaa tämän listan pysyvästi?", + "confirmations.domain_block.confirm": "Piilota koko verkko-osoite", + "confirmations.domain_block.message": "Oletko aivan oikeasti varma että haluat estää koko verkko-osoitteen {domain}? Useimmissa tapauksissa muutamat kohdistetut estot ja mykistykset ovat riittäviä ja suositeltavampia.", + "confirmations.mute.confirm": "Mykistä", + "confirmations.mute.message": "Oletko varma että haluat mykistää käyttäjän {name}?", + "confirmations.unfollow.confirm": "Lakkaa seuraamasta", + "confirmations.unfollow.message": "Oletko varma, että haluat lakata seuraamasta käyttäjää {name}?", + "embed.instructions": "Upota tämä statuspäivitys sivullesi kopioimalla alla oleva koodi.", + "embed.preview": "Tältä se tulee näyttämään:", + "emoji_button.activity": "Aktiviteetit", + "emoji_button.custom": "Mukautetut", + "emoji_button.flags": "Liput", + "emoji_button.food": "Ruoka ja juoma", + "emoji_button.label": "Lisää emoji", + "emoji_button.nature": "Luonto", + "emoji_button.not_found": "Ei emojeja!! (╯°□°)╯︵ ┻━┻", + "emoji_button.objects": "Objektit", + "emoji_button.people": "Ihmiset", + "emoji_button.recent": "Usein käytetyt", + "emoji_button.search": "Etsi...", + "emoji_button.search_results": "Hakutulokset", + "emoji_button.symbols": "Symbolit", + "emoji_button.travel": "Matkailu", + "empty_column.community": "Paikallinen aikajana on tyhjä. Kirjoita jotain julkista saadaksesi pyörät pyörimään!", + "empty_column.hashtag": "Tässä hashtagissa ei ole vielä mitään.", + "empty_column.home": "Kotiaikajanasi on tyhjä! Käy vierailemassa {public}ssa tai käytä hakutoimintoa aloittaaksesi ja tavataksesi muita käyttäjiä.", + "empty_column.home.public_timeline": "yleinen aikajana", + "empty_column.list": "Tämä lista on vielä tyhjä. Kun listan jäsenet julkaisevat statuspäivityksiä, ne näkyvät tässä.", + "empty_column.notifications": "Sinulle ei ole vielä ilmoituksia. Juttele muille aloittaaksesi keskustelun.", + "empty_column.public": "Täällä ei ole mitään! Kirjoita jotain julkisesti, tai käy manuaalisesti seuraamassa käyttäjiä muista instansseista saadaksesi sisältöä", + "follow_request.authorize": "Valtuuta", + "follow_request.reject": "Hylkää", + "getting_started.appsshort": "Sovellukset", "getting_started.faq": "FAQ", "getting_started.heading": "Aloitus", - "getting_started.open_source_notice": "Mastodon Mastodon on avoimen lähdekoodin ohjelma. Voit avustaa tai raportoida ongelmia GitHub palvelussa {github}.", - "getting_started.userguide": "User Guide", - "home.column_settings.advanced": "Advanced", - "home.column_settings.basic": "Basic", - "home.column_settings.filter_regex": "Filter out by regular expressions", - "home.column_settings.show_reblogs": "Show boosts", - "home.column_settings.show_replies": "Show replies", - "home.settings": "Column settings", - "keyboard_shortcuts.back": "to navigate back", - "keyboard_shortcuts.boost": "to boost", - "keyboard_shortcuts.column": "to focus a status in one of the columns", - "keyboard_shortcuts.compose": "to focus the compose textarea", + "getting_started.open_source_notice": "Mastodon on avoimen lähdekoodin ohjelma. Voit avustaa tai raportoida ongelmia GitHub palvelussa {github}.", + "getting_started.userguide": "Käyttöopas", + "home.column_settings.advanced": "Tarkemmat asetukset", + "home.column_settings.basic": "Perusasetukset", + "home.column_settings.filter_regex": "Suodata säännöllisten lauseiden avulla", + "home.column_settings.show_reblogs": "Näytä buustaukset", + "home.column_settings.show_replies": "Näytä vastaukset", + "home.settings": "Sarakeasetukset", + "keyboard_shortcuts.back": "liikkuaksesi taaksepäin", + "keyboard_shortcuts.boost": "buustataksesi", + "keyboard_shortcuts.column": "keskittääksesi statuspäivitykseen yhdessä sarakkeista", + "keyboard_shortcuts.compose": "aktivoidaksesi tekstinkirjoitusalueen", "keyboard_shortcuts.description": "Description", - "keyboard_shortcuts.down": "to move down in the list", + "keyboard_shortcuts.down": "liikkuaksesi listassa alaspäin", "keyboard_shortcuts.enter": "to open status", - "keyboard_shortcuts.favourite": "to favourite", - "keyboard_shortcuts.heading": "Keyboard Shortcuts", - "keyboard_shortcuts.hotkey": "Hotkey", - "keyboard_shortcuts.legend": "to display this legend", - "keyboard_shortcuts.mention": "to mention author", - "keyboard_shortcuts.reply": "to reply", - "keyboard_shortcuts.search": "to focus search", - "keyboard_shortcuts.toot": "to start a brand new toot", - "keyboard_shortcuts.unfocus": "to un-focus compose textarea/search", - "keyboard_shortcuts.up": "to move up in the list", + "keyboard_shortcuts.favourite": "tykätäksesi", + "keyboard_shortcuts.heading": "Näppäinoikotiet", + "keyboard_shortcuts.hotkey": "Pikanäppäin", + "keyboard_shortcuts.legend": "näyttääksesi tämän selitteen", + "keyboard_shortcuts.mention": "mainitaksesi julkaisijan", + "keyboard_shortcuts.reply": "vastataksesi", + "keyboard_shortcuts.search": "aktivoidaksesi hakukentän", + "keyboard_shortcuts.toot": "aloittaaksesi uuden töötin kirjoittamisen", + "keyboard_shortcuts.unfocus": "poistaaksesi aktivoinnin tekstikentästä/hakukentästä", + "keyboard_shortcuts.up": "liikkuaksesi listassa ylöspäin", "lightbox.close": "Sulje", - "lightbox.next": "Next", - "lightbox.previous": "Previous", - "lists.account.add": "Add to list", - "lists.account.remove": "Remove from list", + "lightbox.next": "Seuraava", + "lightbox.previous": "Edellinen", + "lists.account.add": "Lisää listaan", + "lists.account.remove": "Poista listalta", "lists.delete": "Delete list", - "lists.edit": "Edit list", - "lists.new.create": "Add list", - "lists.new.title_placeholder": "New list title", - "lists.search": "Search among people you follow", - "lists.subheading": "Your lists", + "lists.edit": "Muokkaa listaa", + "lists.new.create": "Lisää lista", + "lists.new.title_placeholder": "Uuden listan otsikko", + "lists.search": "Etsi seuraamiesi henkilöiden joukosta", + "lists.subheading": "Omat listat", "loading_indicator.label": "Ladataan...", - "media_gallery.toggle_visible": "Toggle visibility", - "missing_indicator.label": "Not found", - "missing_indicator.sublabel": "This resource could not be found", - "mute_modal.hide_notifications": "Hide notifications from this user?", - "navigation_bar.blocks": "Blocked users", + "media_gallery.toggle_visible": "Säädä näkyvyyttä", + "missing_indicator.label": "Ei löydetty", + "missing_indicator.sublabel": "Tätä resurssia ei löytynyt", + "mute_modal.hide_notifications": "Piilota ilmoitukset tältä käyttäjältä?", + "navigation_bar.blocks": "Estetyt käyttäjät", "navigation_bar.community_timeline": "Paikallinen aikajana", "navigation_bar.edit_profile": "Muokkaa profiilia", - "navigation_bar.favourites": "Favourites", - "navigation_bar.follow_requests": "Follow requests", - "navigation_bar.info": "Extended information", - "navigation_bar.keyboard_shortcuts": "Keyboard shortcuts", - "navigation_bar.lists": "Lists", + "navigation_bar.favourites": "Suosikit", + "navigation_bar.follow_requests": "Seurauspyynnöt", + "navigation_bar.info": "Tietoa tästä instanssista", + "navigation_bar.keyboard_shortcuts": "Näppäinoikotiet", + "navigation_bar.lists": "Listat", "navigation_bar.logout": "Kirjaudu ulos", - "navigation_bar.mutes": "Muted users", - "navigation_bar.pins": "Pinned toots", + "navigation_bar.mutes": "Mykistetyt käyttäjät", + "navigation_bar.pins": "Kiinnitetyt töötit", "navigation_bar.preferences": "Ominaisuudet", "navigation_bar.public_timeline": "Yleinen aikajana", "notification.favourite": "{name} tykkäsi statuksestasi", "notification.follow": "{name} seurasi sinua", "notification.mention": "{name} mainitsi sinut", "notification.reblog": "{name} buustasi statustasi", - "notifications.clear": "Clear notifications", - "notifications.clear_confirmation": "Are you sure you want to permanently clear all your notifications?", + "notifications.clear": "Tyhjennä ilmoitukset", + "notifications.clear_confirmation": "Oletko varma, että haluat lopullisesti tyhjentää kaikki ilmoituksesi?", "notifications.column_settings.alert": "Työpöytä ilmoitukset", "notifications.column_settings.favourite": "Tykkäyksiä:", "notifications.column_settings.follow": "Uusia seuraajia:", "notifications.column_settings.mention": "Mainintoja:", - "notifications.column_settings.push": "Push notifications", - "notifications.column_settings.push_meta": "This device", + "notifications.column_settings.push": "Push-ilmoitukset", + "notifications.column_settings.push_meta": "Tämä laite", "notifications.column_settings.reblog": "Buusteja:", "notifications.column_settings.show": "Näytä sarakkeessa", - "notifications.column_settings.sound": "Play sound", - "onboarding.done": "Done", - "onboarding.next": "Next", - "onboarding.page_five.public_timelines": "The local timeline shows public posts from everyone on {domain}. The federated timeline shows public posts from everyone who people on {domain} follow. These are the Public Timelines, a great way to discover new people.", - "onboarding.page_four.home": "The home timeline shows posts from people you follow.", - "onboarding.page_four.notifications": "The notifications column shows when someone interacts with you.", - "onboarding.page_one.federation": "Mastodon is a network of independent servers joining up to make one larger social network. We call these servers instances.", - "onboarding.page_one.full_handle": "Your full handle", + "notifications.column_settings.sound": "Soita ääni", + "onboarding.done": "Valmis", + "onboarding.next": "Seuraava", + "onboarding.page_five.public_timelines": "Paikallinen aikajana näyttää kaikki julkiset julkaisut kaikilta, jotka ovat verkko-osoitteessa {domain}. Yleinen aikajana näyttää julkiset julkaisut kaikilta niiltä, joita käyttäjät verkko-osoitteessa {domain} seuraavat. Nämä ovat julkiset aikajanat, ja ne ovat hyviä tapoja löytää uusia ihmisiä.", + "onboarding.page_four.home": "Kotiaikajana näyttää julkaisut ihmisiltä joita seuraat.", + "onboarding.page_four.notifications": "Ilmoitukset-sarake näyttää sinulle, kun joku on viestii kanssasi.", + "onboarding.page_one.federation": "Mastodon on yhteisöpalvelu, joka toimii monen itsenäisen palvelimen muodostamassa verkossa. Me kutsumme näitä palvelimia instansseiksi.", + "onboarding.page_one.full_handle": "Koko käyttäjänimesi", "onboarding.page_one.handle_hint": "This is what you would tell your friends to search for.", - "onboarding.page_one.welcome": "Welcome to Mastodon!", - "onboarding.page_six.admin": "Your instance's admin is {admin}.", - "onboarding.page_six.almost_done": "Almost done...", - "onboarding.page_six.appetoot": "Bon Appetoot!", - "onboarding.page_six.apps_available": "There are {apps} available for iOS, Android and other platforms.", + "onboarding.page_one.welcome": "Tervetuloa Mastodoniin!", + "onboarding.page_six.admin": "Instanssisi ylläpitäjä on {admin}.", + "onboarding.page_six.almost_done": "Melkein valmista...", + "onboarding.page_six.appetoot": "Bon Appetööt!", + "onboarding.page_six.apps_available": "{apps} on saatavilla iOS:lle, Androidille ja muille alustoille.", "onboarding.page_six.github": "Mastodon is free open-source software. You can report bugs, request features, or contribute to the code on {github}.", - "onboarding.page_six.guidelines": "community guidelines", - "onboarding.page_six.read_guidelines": "Please read {domain}'s {guidelines}!", - "onboarding.page_six.various_app": "mobile apps", - "onboarding.page_three.profile": "Edit your profile to change your avatar, bio, and display name. There, you will also find other preferences.", - "onboarding.page_three.search": "Use the search bar to find people and look at hashtags, such as {illustration} and {introductions}. To look for a person who is not on this instance, use their full handle.", - "onboarding.page_two.compose": "Write posts from the compose column. You can upload images, change privacy settings, and add content warnings with the icons below.", - "onboarding.skip": "Skip", - "privacy.change": "Adjust status privacy", - "privacy.direct.long": "Post to mentioned users only", - "privacy.direct.short": "Direct", - "privacy.private.long": "Post to followers only", - "privacy.private.short": "Followers-only", - "privacy.public.long": "Post to public timelines", - "privacy.public.short": "Public", - "privacy.unlisted.long": "Do not show in public timelines", - "privacy.unlisted.short": "Unlisted", - "regeneration_indicator.label": "Loading…", - "regeneration_indicator.sublabel": "Your home feed is being prepared!", + "onboarding.page_six.guidelines": "yhteisön säännöt", + "onboarding.page_six.read_guidelines": "Ole hyvä ja lue {domain}:n {guidelines}!", + "onboarding.page_six.various_app": "mobiilisovellukset", + "onboarding.page_three.profile": "Muokkaa profiiliasi muuttaaksesi kuvakettasi, esittelyäsi ja nimimerkkiäsi. Löydät sieltä myös muita henkilökohtaisia asetuksia.", + "onboarding.page_three.search": "Käytä hakukenttää löytääksesi ihmisiä ja etsiäksesi hashtageja, kuten {illustration} tai {introductions}. Hakeaksesi henkilöä joka on toisessa instanssissa, käytä hänen käyttäjänimeään kokonaisuudessaan.", + "onboarding.page_two.compose": "Kirjoita postauksia kirjoita-sarakkeessa. Voit ladata kuvia, vaihtaa yksityisyysasetuksia ja lisätä sisältövaroituksia alla olevista painikkeista.", + "onboarding.skip": "Ohita", + "privacy.change": "Säädä töötin yksityisyysasetuksia", + "privacy.direct.long": "Julkaise vain mainituille käyttäjille", + "privacy.direct.short": "Yksityisviesti", + "privacy.private.long": "Julkaise vain seuraajille", + "privacy.private.short": "Vain seuraajat", + "privacy.public.long": "Julkaise julkisille aikajanoille", + "privacy.public.short": "Julkinen", + "privacy.unlisted.long": "Älä julkaise yleisillä aikajanoilla", + "privacy.unlisted.short": "Julkinen, mutta älä näytä julkisella aikajanalla", + "regeneration_indicator.label": "Ladataan…", + "regeneration_indicator.sublabel": "Kotinäkymääsi valmistellaan!", "relative_time.days": "{number}d", "relative_time.hours": "{number}h", - "relative_time.just_now": "now", + "relative_time.just_now": "nyt", "relative_time.minutes": "{number}m", "relative_time.seconds": "{number}s", "reply_indicator.cancel": "Peruuta", - "report.placeholder": "Additional comments", + "report.forward": "Forward to {target}", + "report.forward_hint": "The account is from another server. Send an anonymized copy of the report there as well?", + "report.hint": "The report will be sent to your instance moderators. You can provide an explanation of why you are reporting this account below:", + "report.placeholder": "Lisäkommentit", "report.submit": "Submit", "report.target": "Reporting", "search.placeholder": "Hae", - "search_popout.search_format": "Advanced search format", - "search_popout.tips.hashtag": "hashtag", + "search_popout.search_format": "Tarkennettu haku", + "search_popout.tips.hashtag": "hashtagi", "search_popout.tips.status": "status", - "search_popout.tips.text": "Simple text returns matching display names, usernames and hashtags", - "search_popout.tips.user": "user", + "search_popout.tips.text": "Pelkkä tekstihaku palauttaa hakua vastaavat nimimerkit, käyttäjänimet ja hastagit", + "search_popout.tips.user": "käyttäjä", + "search_results.accounts": "People", + "search_results.hashtags": "Hashtags", + "search_results.statuses": "Toots", "search_results.total": "{count, number} {count, plural, one {result} other {results}}", - "standalone.public_title": "A look inside...", + "standalone.public_title": "Kurkistus sisälle...", "status.block": "Block @{name}", - "status.cannot_reblog": "This post cannot be boosted", + "status.cannot_reblog": "Tätä postausta ei voi buustata", "status.delete": "Poista", - "status.embed": "Embed", + "status.embed": "Upota", "status.favourite": "Tykkää", - "status.load_more": "Load more", - "status.media_hidden": "Media hidden", + "status.load_more": "Lataa lisää", + "status.media_hidden": "Media piilotettu", "status.mention": "Mainitse @{name}", - "status.more": "More", - "status.mute": "Mute @{name}", - "status.mute_conversation": "Mute conversation", - "status.open": "Expand this status", - "status.pin": "Pin on profile", + "status.more": "Lisää", + "status.mute": "Mykistä @{name}", + "status.mute_conversation": "Mykistä keskustelu", + "status.open": "Laajenna statuspäivitys", + "status.pin": "Kiinnitä profiiliin", "status.reblog": "Buustaa", "status.reblogged_by": "{name} buustasi", "status.reply": "Vastaa", - "status.replyAll": "Reply to thread", + "status.replyAll": "Vastaa ketjuun", "status.report": "Report @{name}", "status.sensitive_toggle": "Klikkaa nähdäksesi", "status.sensitive_warning": "Arkaluontoista sisältöä", - "status.share": "Share", - "status.show_less": "Show less", - "status.show_more": "Show more", - "status.unmute_conversation": "Unmute conversation", - "status.unpin": "Unpin from profile", + "status.share": "Jaa", + "status.show_less": "Näytä vähemmän", + "status.show_more": "Näytä lisää", + "status.unmute_conversation": "Poista mykistys keskustelulta", + "status.unpin": "Irrota profiilista", "tabs_bar.compose": "Luo", "tabs_bar.federated_timeline": "Federated", "tabs_bar.home": "Koti", - "tabs_bar.local_timeline": "Local", + "tabs_bar.local_timeline": "Paikallinen", "tabs_bar.notifications": "Ilmoitukset", - "ui.beforeunload": "Your draft will be lost if you leave Mastodon.", - "upload_area.title": "Drag & drop to upload", + "ui.beforeunload": "Luonnoksesi menetetään, jos poistut Mastodonista.", + "upload_area.title": "Raahaa ja pudota tähän ladataksesi", "upload_button.label": "Lisää mediaa", - "upload_form.description": "Describe for the visually impaired", + "upload_form.description": "Anna kuvaus näkörajoitteisia varten", + "upload_form.focus": "Crop", "upload_form.undo": "Peru", - "upload_progress.label": "Uploading...", - "video.close": "Close video", - "video.exit_fullscreen": "Exit full screen", - "video.expand": "Expand video", + "upload_progress.label": "Ladataan...", + "video.close": "Sulje video", + "video.exit_fullscreen": "Poistu koko näytön tilasta", + "video.expand": "Laajenna video", "video.fullscreen": "Full screen", - "video.hide": "Hide video", - "video.mute": "Mute sound", - "video.pause": "Pause", - "video.play": "Play", - "video.unmute": "Unmute sound" + "video.hide": "Piilota video", + "video.mute": "Mykistä ääni", + "video.pause": "Keskeytä", + "video.play": "Toista", + "video.unmute": "Poista mykistys ääneltä" } diff --git a/app/javascript/mastodon/locales/fr.json b/app/javascript/mastodon/locales/fr.json index 17075f6de..b10187dfd 100644 --- a/app/javascript/mastodon/locales/fr.json +++ b/app/javascript/mastodon/locales/fr.json @@ -14,6 +14,7 @@ "account.mute": "Masquer @{name}", "account.mute_notifications": "Ignorer les notifications de @{name}", "account.posts": "Statuts", + "account.posts_with_replies": "Toots with replies", "account.report": "Signaler", "account.requested": "Invitation envoyée", "account.share": "Partager le profil de @{name}", @@ -163,7 +164,7 @@ "notifications.column_settings.alert": "Notifications locales", "notifications.column_settings.favourite": "Favoris :", "notifications.column_settings.follow": "Nouveaux⋅elles abonné⋅e·s :", - "notifications.column_settings.mention": "Mentions :", + "notifications.column_settings.mention": "Mentions :", "notifications.column_settings.push": "Notifications push", "notifications.column_settings.push_meta": "Cet appareil", "notifications.column_settings.reblog": "Partages :", @@ -200,13 +201,16 @@ "privacy.unlisted.long": "Ne pas afficher dans les fils publics", "privacy.unlisted.short": "Non-listé", "regeneration_indicator.label": "Chargement…", - "regeneration_indicator.sublabel": "Votre page principale est en cours de préparation!", + "regeneration_indicator.sublabel": "Le flux de votre page principale est en cours de préparation !", "relative_time.days": "{number} j", "relative_time.hours": "{number} h", "relative_time.just_now": "à l’instant", "relative_time.minutes": "{number} min", "relative_time.seconds": "{number} s", "reply_indicator.cancel": "Annuler", + "report.forward": "Forward to {target}", + "report.forward_hint": "The account is from another server. Send an anonymized copy of the report there as well?", + "report.hint": "The report will be sent to your instance moderators. You can provide an explanation of why you are reporting this account below:", "report.placeholder": "Commentaires additionnels", "report.submit": "Envoyer", "report.target": "Signalement", @@ -216,6 +220,9 @@ "search_popout.tips.status": "statuts", "search_popout.tips.text": "Un texte simple renvoie les noms affichés, les noms d’utilisateur⋅ice et les hashtags correspondants", "search_popout.tips.user": "utilisateur⋅ice", + "search_results.accounts": "People", + "search_results.hashtags": "Hashtags", + "search_results.statuses": "Toots", "search_results.total": "{count, number} {count, plural, one {résultat} other {résultats}}", "standalone.public_title": "Jeter un coup d’œil…", "status.block": "Block @{name}", @@ -252,6 +259,7 @@ "upload_area.title": "Glissez et déposez pour envoyer", "upload_button.label": "Joindre un média", "upload_form.description": "Décrire pour les malvoyants", + "upload_form.focus": "Crop", "upload_form.undo": "Annuler", "upload_progress.label": "Envoi en cours…", "video.close": "Fermer la vidéo", diff --git a/app/javascript/mastodon/locales/gl.json b/app/javascript/mastodon/locales/gl.json index 9e8352ba4..0b91f57ae 100644 --- a/app/javascript/mastodon/locales/gl.json +++ b/app/javascript/mastodon/locales/gl.json @@ -13,7 +13,8 @@ "account.moved_to": "{name} marchou a:", "account.mute": "Acalar @{name}", "account.mute_notifications": "Acalar as notificacións de @{name}", - "account.posts": "Publicacións", + "account.posts": "Toots", + "account.posts_with_replies": "Toots with replies", "account.report": "Informar sobre @{name}", "account.requested": "Agardando aceptación. Pulse para cancelar a solicitude de seguimento", "account.share": "Compartir o perfil de @{name}", @@ -207,6 +208,9 @@ "relative_time.minutes": "{number}m", "relative_time.seconds": "{number}s", "reply_indicator.cancel": "Cancelar", + "report.forward": "Forward to {target}", + "report.forward_hint": "The account is from another server. Send an anonymized copy of the report there as well?", + "report.hint": "The report will be sent to your instance moderators. You can provide an explanation of why you are reporting this account below:", "report.placeholder": "Comentarios adicionais", "report.submit": "Enviar", "report.target": "Informar {target}", @@ -216,6 +220,9 @@ "search_popout.tips.status": "estado", "search_popout.tips.text": "Texto simple devolve coincidencias con nomes públicos, nomes de usuaria e etiquetas", "search_popout.tips.user": "usuaria", + "search_results.accounts": "People", + "search_results.hashtags": "Hashtags", + "search_results.statuses": "Toots", "search_results.total": "{count, number} {count,plural,one {result} outros {results}}", "standalone.public_title": "Ollada dentro...", "status.block": "Block @{name}", @@ -252,6 +259,7 @@ "upload_area.title": "Arrastre e solte para subir", "upload_button.label": "Engadir medios", "upload_form.description": "Describa para deficientes visuais", + "upload_form.focus": "Crop", "upload_form.undo": "Desfacer", "upload_progress.label": "Subindo...", "video.close": "Pechar video", diff --git a/app/javascript/mastodon/locales/he.json b/app/javascript/mastodon/locales/he.json index d6665295f..e430fabf8 100644 --- a/app/javascript/mastodon/locales/he.json +++ b/app/javascript/mastodon/locales/he.json @@ -14,6 +14,7 @@ "account.mute": "להשתיק את @{name}", "account.mute_notifications": "להסתיר התראות מאת @{name}", "account.posts": "הודעות", + "account.posts_with_replies": "Toots with replies", "account.report": "לדווח על @{name}", "account.requested": "בהמתנה לאישור", "account.share": "לשתף את אודות @{name}", @@ -207,6 +208,9 @@ "relative_time.minutes": "{number}m", "relative_time.seconds": "{number}s", "reply_indicator.cancel": "ביטול", + "report.forward": "Forward to {target}", + "report.forward_hint": "The account is from another server. Send an anonymized copy of the report there as well?", + "report.hint": "The report will be sent to your instance moderators. You can provide an explanation of why you are reporting this account below:", "report.placeholder": "הערות נוספות", "report.submit": "שליחה", "report.target": "דיווח", @@ -216,6 +220,9 @@ "search_popout.tips.status": "status", "search_popout.tips.text": "טקסט פשוט מחזיר כינויים, שמות משתמש והאשתגים", "search_popout.tips.user": "משתמש(ת)", + "search_results.accounts": "People", + "search_results.hashtags": "Hashtags", + "search_results.statuses": "Toots", "search_results.total": "{count, number} {count, plural, one {תוצאה} other {תוצאות}}", "standalone.public_title": "הצצה פנימה...", "status.block": "Block @{name}", @@ -252,6 +259,7 @@ "upload_area.title": "ניתן להעלות על ידי Drag & drop", "upload_button.label": "הוספת מדיה", "upload_form.description": "תיאור לכבדי ראיה", + "upload_form.focus": "Crop", "upload_form.undo": "ביטול", "upload_progress.label": "עולה...", "video.close": "סגירת וידאו", diff --git a/app/javascript/mastodon/locales/hr.json b/app/javascript/mastodon/locales/hr.json index c49ae160f..543a739bc 100644 --- a/app/javascript/mastodon/locales/hr.json +++ b/app/javascript/mastodon/locales/hr.json @@ -14,6 +14,7 @@ "account.mute": "Utišaj @{name}", "account.mute_notifications": "Mute notifications from @{name}", "account.posts": "Postovi", + "account.posts_with_replies": "Toots with replies", "account.report": "Prijavi @{name}", "account.requested": "Čeka pristanak", "account.share": "Share @{name}'s profile", @@ -207,6 +208,9 @@ "relative_time.minutes": "{number}m", "relative_time.seconds": "{number}s", "reply_indicator.cancel": "Otkaži", + "report.forward": "Forward to {target}", + "report.forward_hint": "The account is from another server. Send an anonymized copy of the report there as well?", + "report.hint": "The report will be sent to your instance moderators. You can provide an explanation of why you are reporting this account below:", "report.placeholder": "Dodatni komentari", "report.submit": "Pošalji", "report.target": "Prijavljivanje", @@ -216,6 +220,9 @@ "search_popout.tips.status": "status", "search_popout.tips.text": "Simple text returns matching display names, usernames and hashtags", "search_popout.tips.user": "user", + "search_results.accounts": "People", + "search_results.hashtags": "Hashtags", + "search_results.statuses": "Toots", "search_results.total": "{count, number} {count, plural, one {result} other {results}}", "standalone.public_title": "A look inside...", "status.block": "Block @{name}", @@ -252,6 +259,7 @@ "upload_area.title": "Povuci i spusti kako bi uploadao", "upload_button.label": "Dodaj media", "upload_form.description": "Describe for the visually impaired", + "upload_form.focus": "Crop", "upload_form.undo": "Poništi", "upload_progress.label": "Uploadam...", "video.close": "Close video", diff --git a/app/javascript/mastodon/locales/hu.json b/app/javascript/mastodon/locales/hu.json index 316687129..38b3698b6 100644 --- a/app/javascript/mastodon/locales/hu.json +++ b/app/javascript/mastodon/locales/hu.json @@ -7,13 +7,14 @@ "account.followers": "Követők", "account.follows": "Követve", "account.follows_you": "Követnek téged", - "account.hide_reblogs": "@{name} kedvenceinek elrejtése", + "account.hide_reblogs": "Rejtsd el a tülkölést @{name}-tól/től", "account.media": "Média", "account.mention": "@{name} említése", "account.moved_to": "{name} átköltözött:", "account.mute": "@{name} némítása", "account.mute_notifications": "@{name} értesítések némítása", "account.posts": "Státuszok", + "account.posts_with_replies": "Toots with replies", "account.report": "@{name} jelentése", "account.requested": "Engedélyre vár. Kattintson a követési kérés visszavonására", "account.share": "@{name} profiljának megosztása", @@ -207,6 +208,9 @@ "relative_time.minutes": "{number}m", "relative_time.seconds": "{number}s", "reply_indicator.cancel": "Mégsem", + "report.forward": "Forward to {target}", + "report.forward_hint": "The account is from another server. Send an anonymized copy of the report there as well?", + "report.hint": "The report will be sent to your instance moderators. You can provide an explanation of why you are reporting this account below:", "report.placeholder": "További kommentek", "report.submit": "Submit", "report.target": "Reporting", @@ -216,6 +220,9 @@ "search_popout.tips.status": "status", "search_popout.tips.text": "Simple text returns matching display names, usernames and hashtags", "search_popout.tips.user": "felhasználó", + "search_results.accounts": "People", + "search_results.hashtags": "Hashtags", + "search_results.statuses": "Toots", "search_results.total": "{count, number} {count, plural, one {result} other {results}}", "standalone.public_title": "Betekintés...", "status.block": "Block @{name}", @@ -252,6 +259,7 @@ "upload_area.title": "Húzza ide a feltöltéshez", "upload_button.label": "Média hozzáadása", "upload_form.description": "Describe for the visually impaired", + "upload_form.focus": "Crop", "upload_form.undo": "Mégsem", "upload_progress.label": "Uploading...", "video.close": "Close video", diff --git a/app/javascript/mastodon/locales/hy.json b/app/javascript/mastodon/locales/hy.json index f46db5b00..15d8f22e6 100644 --- a/app/javascript/mastodon/locales/hy.json +++ b/app/javascript/mastodon/locales/hy.json @@ -14,6 +14,7 @@ "account.mute": "Լռեցնել @{name}֊ին", "account.mute_notifications": "Անջատել ծանուցումները @{name}֊ից", "account.posts": "Գրառումներ", + "account.posts_with_replies": "Toots with replies", "account.report": "Բողոքել @{name}֊ից", "account.requested": "Հաստատման կարիք ունի։ Սեղմիր՝ հետեւելու հայցը չեղարկելու համար։", "account.share": "Կիսվել @{name}֊ի էջով", @@ -207,6 +208,9 @@ "relative_time.minutes": "{number}ր", "relative_time.seconds": "{number}վ", "reply_indicator.cancel": "Չեղարկել", + "report.forward": "Forward to {target}", + "report.forward_hint": "The account is from another server. Send an anonymized copy of the report there as well?", + "report.hint": "The report will be sent to your instance moderators. You can provide an explanation of why you are reporting this account below:", "report.placeholder": "Լրացուցիչ մեկնաբանություններ", "report.submit": "Ուղարկել", "report.target": "Բողոքել {target}֊ի մասին", @@ -216,6 +220,9 @@ "search_popout.tips.status": "թութ", "search_popout.tips.text": "Հասարակ տեքստը կվերադարձնի համընկնող անուններ, օգտանուններ ու պիտակներ", "search_popout.tips.user": "օգտատեր", + "search_results.accounts": "People", + "search_results.hashtags": "Hashtags", + "search_results.statuses": "Toots", "search_results.total": "{count, number} {count, plural, one {result} other {results}}", "standalone.public_title": "Այս պահին…", "status.block": "Արգելափակել @{name}֊ին", @@ -252,6 +259,7 @@ "upload_area.title": "Քաշիր ու նետիր՝ վերբեռնելու համար", "upload_button.label": "Ավելացնել մեդիա", "upload_form.description": "Նկարագրություն ավելացրու տեսողական խնդիրներ ունեցողների համար", + "upload_form.focus": "Crop", "upload_form.undo": "Հետարկել", "upload_progress.label": "Վերբեռնվում է…", "video.close": "Փակել տեսագրությունը", diff --git a/app/javascript/mastodon/locales/id.json b/app/javascript/mastodon/locales/id.json index 6edf855d3..ac4aaa1aa 100644 --- a/app/javascript/mastodon/locales/id.json +++ b/app/javascript/mastodon/locales/id.json @@ -14,6 +14,7 @@ "account.mute": "Bisukan @{name}", "account.mute_notifications": "Mute notifications from @{name}", "account.posts": "Postingan", + "account.posts_with_replies": "Toots with replies", "account.report": "Laporkan @{name}", "account.requested": "Menunggu persetujuan", "account.share": "Share @{name}'s profile", @@ -207,6 +208,9 @@ "relative_time.minutes": "{number}m", "relative_time.seconds": "{number}s", "reply_indicator.cancel": "Batal", + "report.forward": "Forward to {target}", + "report.forward_hint": "The account is from another server. Send an anonymized copy of the report there as well?", + "report.hint": "The report will be sent to your instance moderators. You can provide an explanation of why you are reporting this account below:", "report.placeholder": "Komentar tambahan", "report.submit": "Kirim", "report.target": "Melaporkan", @@ -216,6 +220,9 @@ "search_popout.tips.status": "status", "search_popout.tips.text": "Simple text returns matching display names, usernames and hashtags", "search_popout.tips.user": "user", + "search_results.accounts": "People", + "search_results.hashtags": "Hashtags", + "search_results.statuses": "Toots", "search_results.total": "{count} {count, plural, one {hasil} other {hasil}}", "standalone.public_title": "A look inside...", "status.block": "Block @{name}", @@ -252,6 +259,7 @@ "upload_area.title": "Seret & lepaskan untuk mengunggah", "upload_button.label": "Tambahkan media", "upload_form.description": "Describe for the visually impaired", + "upload_form.focus": "Crop", "upload_form.undo": "Undo", "upload_progress.label": "Mengunggah...", "video.close": "Close video", diff --git a/app/javascript/mastodon/locales/io.json b/app/javascript/mastodon/locales/io.json index 7aa7cb144..d431fac49 100644 --- a/app/javascript/mastodon/locales/io.json +++ b/app/javascript/mastodon/locales/io.json @@ -14,6 +14,7 @@ "account.mute": "Celar @{name}", "account.mute_notifications": "Mute notifications from @{name}", "account.posts": "Mesaji", + "account.posts_with_replies": "Toots with replies", "account.report": "Denuncar @{name}", "account.requested": "Vartante aprobo", "account.share": "Share @{name}'s profile", @@ -207,6 +208,9 @@ "relative_time.minutes": "{number}m", "relative_time.seconds": "{number}s", "reply_indicator.cancel": "Nihiligar", + "report.forward": "Forward to {target}", + "report.forward_hint": "The account is from another server. Send an anonymized copy of the report there as well?", + "report.hint": "The report will be sent to your instance moderators. You can provide an explanation of why you are reporting this account below:", "report.placeholder": "Plusa komenti", "report.submit": "Sendar", "report.target": "Denuncante", @@ -216,6 +220,9 @@ "search_popout.tips.status": "status", "search_popout.tips.text": "Simple text returns matching display names, usernames and hashtags", "search_popout.tips.user": "user", + "search_results.accounts": "People", + "search_results.hashtags": "Hashtags", + "search_results.statuses": "Toots", "search_results.total": "{count, number} {count, plural, one {rezulto} other {rezulti}}", "standalone.public_title": "A look inside...", "status.block": "Block @{name}", @@ -252,6 +259,7 @@ "upload_area.title": "Tranar faligar por kargar", "upload_button.label": "Adjuntar kontenajo", "upload_form.description": "Describe for the visually impaired", + "upload_form.focus": "Crop", "upload_form.undo": "Desfacar", "upload_progress.label": "Kargante...", "video.close": "Close video", diff --git a/app/javascript/mastodon/locales/it.json b/app/javascript/mastodon/locales/it.json index 61467df16..eec1a7feb 100644 --- a/app/javascript/mastodon/locales/it.json +++ b/app/javascript/mastodon/locales/it.json @@ -14,6 +14,7 @@ "account.mute": "Silenzia @{name}", "account.mute_notifications": "Mute notifications from @{name}", "account.posts": "Posts", + "account.posts_with_replies": "Toots with replies", "account.report": "Segnala @{name}", "account.requested": "In attesa di approvazione", "account.share": "Share @{name}'s profile", @@ -207,6 +208,9 @@ "relative_time.minutes": "{number}m", "relative_time.seconds": "{number}s", "reply_indicator.cancel": "Annulla", + "report.forward": "Forward to {target}", + "report.forward_hint": "The account is from another server. Send an anonymized copy of the report there as well?", + "report.hint": "The report will be sent to your instance moderators. You can provide an explanation of why you are reporting this account below:", "report.placeholder": "Commenti aggiuntivi", "report.submit": "Invia", "report.target": "Invio la segnalazione", @@ -216,6 +220,9 @@ "search_popout.tips.status": "status", "search_popout.tips.text": "Simple text returns matching display names, usernames and hashtags", "search_popout.tips.user": "user", + "search_results.accounts": "People", + "search_results.hashtags": "Hashtags", + "search_results.statuses": "Toots", "search_results.total": "{count} {count, plural, one {risultato} other {risultati}}", "standalone.public_title": "A look inside...", "status.block": "Block @{name}", @@ -252,6 +259,7 @@ "upload_area.title": "Trascina per caricare", "upload_button.label": "Aggiungi file multimediale", "upload_form.description": "Describe for the visually impaired", + "upload_form.focus": "Crop", "upload_form.undo": "Annulla", "upload_progress.label": "Sto caricando...", "video.close": "Close video", diff --git a/app/javascript/mastodon/locales/ja.json b/app/javascript/mastodon/locales/ja.json index 4449af52f..f1ad2911d 100644 --- a/app/javascript/mastodon/locales/ja.json +++ b/app/javascript/mastodon/locales/ja.json @@ -14,11 +14,12 @@ "account.mute": "@{name}さんをミュート", "account.mute_notifications": "@{name}さんからの通知を受け取らない", "account.posts": "投稿", + "account.posts_with_replies": "トゥートと返信", "account.report": "@{name}さんを通報", "account.requested": "フォロー承認待ちです。クリックしてキャンセル", "account.share": "@{name}さんのプロフィールを共有する", "account.show_reblogs": "@{name}さんからのブーストを表示", - "account.unblock": "@{name}さんのブロック解除", + "account.unblock": "@{name}さんのブロックを解除", "account.unblock_domain": "{domain}を表示", "account.unfollow": "フォロー解除", "account.unmute": "@{name}さんのミュートを解除", @@ -71,7 +72,7 @@ "confirmations.delete_list.confirm": "削除", "confirmations.delete_list.message": "本当にこのリストを完全に削除しますか?", "confirmations.domain_block.confirm": "ドメイン全体を非表示", - "confirmations.domain_block.message": "本当に{domain}全体を非表示にしますか? 多くの場合は個別にブロックやミュートするだけで充分であり、また好ましいです。", + "confirmations.domain_block.message": "本当に{domain}全体を非表示にしますか? 多くの場合は個別にブロックやミュートするだけで充分であり、また好ましいです。", "confirmations.mute.confirm": "ミュート", "confirmations.mute.message": "本当に{name}さんをミュートしますか?", "confirmations.unfollow.confirm": "フォロー解除", @@ -207,13 +208,16 @@ "privacy.unlisted.long": "公開TLで表示しない", "privacy.unlisted.short": "未収載", "regeneration_indicator.label": "読み込み中…", - "regeneration_indicator.sublabel": "ホームタイムラインは準備中です!", + "regeneration_indicator.sublabel": "ホームタイムラインは準備中です!", "relative_time.days": "{number}日前", "relative_time.hours": "{number}時間前", "relative_time.just_now": "今", "relative_time.minutes": "{number}分前", "relative_time.seconds": "{number}秒前", "reply_indicator.cancel": "キャンセル", + "report.forward": "{target} に転送する", + "report.forward_hint": "このアカウントは別のインスタンスに所属しています。通報内容を匿名で転送しますか?", + "report.hint": "通報内容はあなたのインスタンスのモデレーターへ送信されます。通報理由を入力してください。:", "report.placeholder": "追加コメント", "report.submit": "通報する", "report.target": "{target}さんを通報する", @@ -223,6 +227,9 @@ "search_popout.tips.status": "トゥート", "search_popout.tips.text": "表示名やユーザー名、ハッシュタグに一致する単純なテキスト", "search_popout.tips.user": "ユーザー", + "search_results.accounts": "人々", + "search_results.hashtags": "ハッシュタグ", + "search_results.statuses": "トゥート", "search_results.total": "{count, number}件の結果", "standalone.public_title": "今こんな話をしています...", "status.block": "@{name}さんをブロック", @@ -259,6 +266,7 @@ "upload_area.title": "ドラッグ&ドロップでアップロード", "upload_button.label": "メディアを追加", "upload_form.description": "視覚障害者のための説明", + "upload_form.focus": "焦点", "upload_form.undo": "やり直す", "upload_progress.label": "アップロード中...", "video.close": "動画を閉じる", diff --git a/app/javascript/mastodon/locales/ko.json b/app/javascript/mastodon/locales/ko.json index 02b4b18e2..8e7c82682 100644 --- a/app/javascript/mastodon/locales/ko.json +++ b/app/javascript/mastodon/locales/ko.json @@ -14,6 +14,7 @@ "account.mute": "@{name} 뮤트", "account.mute_notifications": "@{name}의 알림을 뮤트", "account.posts": "게시물", + "account.posts_with_replies": "Toots with replies", "account.report": "@{name} 신고", "account.requested": "승인 대기 중. 클릭해서 취소하기", "account.share": "@{name}의 프로파일 공유", @@ -207,6 +208,9 @@ "relative_time.minutes": "{number}분 전", "relative_time.seconds": "{number}초 전", "reply_indicator.cancel": "취소", + "report.forward": "Forward to {target}", + "report.forward_hint": "The account is from another server. Send an anonymized copy of the report there as well?", + "report.hint": "The report will be sent to your instance moderators. You can provide an explanation of why you are reporting this account below:", "report.placeholder": "코멘트", "report.submit": "신고하기", "report.target": "문제가 된 사용자", @@ -216,6 +220,9 @@ "search_popout.tips.status": "툿", "search_popout.tips.text": "단순한 텍스트 검색은 관계된 프로필 이름, 유저 이름 그리고 해시태그를 표시합니다", "search_popout.tips.user": "유저", + "search_results.accounts": "People", + "search_results.hashtags": "Hashtags", + "search_results.statuses": "Toots", "search_results.total": "{count, number}건의 결과", "standalone.public_title": "지금 이런 이야기를 하고 있습니다…", "status.block": "@{name} 차단", @@ -252,6 +259,7 @@ "upload_area.title": "드래그 & 드롭으로 업로드", "upload_button.label": "미디어 추가", "upload_form.description": "시각장애인을 위한 설명", + "upload_form.focus": "Crop", "upload_form.undo": "재시도", "upload_progress.label": "업로드 중...", "video.close": "동영상 닫기", diff --git a/app/javascript/mastodon/locales/nl.json b/app/javascript/mastodon/locales/nl.json index 11a012de5..315f92120 100644 --- a/app/javascript/mastodon/locales/nl.json +++ b/app/javascript/mastodon/locales/nl.json @@ -14,6 +14,7 @@ "account.mute": "Negeer @{name}", "account.mute_notifications": "Negeer meldingen van @{name}", "account.posts": "Toots", + "account.posts_with_replies": "Toots with replies", "account.report": "Rapporteer @{name}", "account.requested": "Wacht op goedkeuring. Klik om het volgverzoek te annuleren", "account.share": "Profiel van @{name} delen", @@ -207,6 +208,9 @@ "relative_time.minutes": "{number}m", "relative_time.seconds": "{number}s", "reply_indicator.cancel": "Annuleren", + "report.forward": "Forward to {target}", + "report.forward_hint": "The account is from another server. Send an anonymized copy of the report there as well?", + "report.hint": "The report will be sent to your instance moderators. You can provide an explanation of why you are reporting this account below:", "report.placeholder": "Extra opmerkingen", "report.submit": "Verzenden", "report.target": "Rapporteer {target}", @@ -216,9 +220,12 @@ "search_popout.tips.status": "toot", "search_popout.tips.text": "Gebruik gewone tekst om te zoeken op weergavenamen, gebruikersnamen en hashtags", "search_popout.tips.user": "gebruiker", + "search_results.accounts": "People", + "search_results.hashtags": "Hashtags", + "search_results.statuses": "Toots", "search_results.total": "{count, number} {count, plural, one {resultaat} other {resultaten}}", "standalone.public_title": "Een kijkje binnenin...", - "status.block": "Block @{name}", + "status.block": "Blokkeer @{name}", "status.cannot_reblog": "Deze toot kan niet geboost worden", "status.delete": "Verwijderen", "status.embed": "Embed", @@ -252,6 +259,7 @@ "upload_area.title": "Hierin slepen om te uploaden", "upload_button.label": "Media toevoegen", "upload_form.description": "Omschrijf dit voor mensen met een visuele beperking", + "upload_form.focus": "Crop", "upload_form.undo": "Ongedaan maken", "upload_progress.label": "Uploaden...", "video.close": "Video sluiten", diff --git a/app/javascript/mastodon/locales/no.json b/app/javascript/mastodon/locales/no.json index 21fd50183..b319ea1a5 100644 --- a/app/javascript/mastodon/locales/no.json +++ b/app/javascript/mastodon/locales/no.json @@ -14,6 +14,7 @@ "account.mute": "Demp @{name}", "account.mute_notifications": "Ignorer varsler fra @{name}", "account.posts": "Innlegg", + "account.posts_with_replies": "Toots with replies", "account.report": "Rapportér @{name}", "account.requested": "Venter på godkjennelse", "account.share": "Del @{name}s profil", @@ -207,6 +208,9 @@ "relative_time.minutes": "{number}m", "relative_time.seconds": "{number}s", "reply_indicator.cancel": "Avbryt", + "report.forward": "Forward to {target}", + "report.forward_hint": "The account is from another server. Send an anonymized copy of the report there as well?", + "report.hint": "The report will be sent to your instance moderators. You can provide an explanation of why you are reporting this account below:", "report.placeholder": "Tilleggskommentarer", "report.submit": "Send inn", "report.target": "Rapporterer", @@ -216,6 +220,9 @@ "search_popout.tips.status": "status", "search_popout.tips.text": "Enkel tekst returnerer matchende visningsnavn, brukernavn og emneknagger", "search_popout.tips.user": "bruker", + "search_results.accounts": "People", + "search_results.hashtags": "Hashtags", + "search_results.statuses": "Toots", "search_results.total": "{count, number} {count, plural, one {resultat} other {resultater}}", "standalone.public_title": "En titt inni...", "status.block": "Block @{name}", @@ -252,6 +259,7 @@ "upload_area.title": "Dra og slipp for å laste opp", "upload_button.label": "Legg til media", "upload_form.description": "Beskriv for synshemmede", + "upload_form.focus": "Crop", "upload_form.undo": "Angre", "upload_progress.label": "Laster opp...", "video.close": "Lukk video", diff --git a/app/javascript/mastodon/locales/oc.json b/app/javascript/mastodon/locales/oc.json index 3cf99028a..2402e1759 100644 --- a/app/javascript/mastodon/locales/oc.json +++ b/app/javascript/mastodon/locales/oc.json @@ -14,6 +14,7 @@ "account.mute": "Rescondre @{name}", "account.mute_notifications": "Rescondre las notificacions de @{name}", "account.posts": "Estatuts", + "account.posts_with_replies": "Toots with replies", "account.report": "Senhalar @{name}", "account.requested": "Invitacion mandada. Clicatz per anullar", "account.share": "Partejar lo perfil a @{name}", @@ -207,6 +208,9 @@ "relative_time.minutes": "fa {number}min", "relative_time.seconds": "fa {number}s", "reply_indicator.cancel": "Anullar", + "report.forward": "Forward to {target}", + "report.forward_hint": "The account is from another server. Send an anonymized copy of the report there as well?", + "report.hint": "The report will be sent to your instance moderators. You can provide an explanation of why you are reporting this account below:", "report.placeholder": "Comentaris addicionals", "report.submit": "Mandar", "report.target": "Senhalar {target}", @@ -216,6 +220,9 @@ "search_popout.tips.status": "estatut", "search_popout.tips.text": "Lo tèxt brut tòrna escais, noms d’utilizaire e etiquetas correspondents", "search_popout.tips.user": "utilizaire", + "search_results.accounts": "People", + "search_results.hashtags": "Hashtags", + "search_results.statuses": "Toots", "search_results.total": "{count, number} {count, plural, one {resultat} other {resultats}}", "standalone.public_title": "Una ulhada dedins…", "status.block": "Blocar @{name}", @@ -252,6 +259,7 @@ "upload_area.title": "Lisatz e depausatz per mandar", "upload_button.label": "Ajustar un mèdia", "upload_form.description": "Descripcion pels mal vesents", + "upload_form.focus": "Crop", "upload_form.undo": "Anullar", "upload_progress.label": "Mandadís…", "video.close": "Tampar la vidèo", diff --git a/app/javascript/mastodon/locales/pl.json b/app/javascript/mastodon/locales/pl.json index bcc28b65a..4eccc3655 100644 --- a/app/javascript/mastodon/locales/pl.json +++ b/app/javascript/mastodon/locales/pl.json @@ -14,6 +14,7 @@ "account.mute": "Wycisz @{name}", "account.mute_notifications": "Wycisz powiadomienia o @{name}", "account.posts": "Wpisy", + "account.posts_with_replies": "Wpisy z odpowiedziami", "account.report": "Zgłoś @{name}", "account.requested": "Oczekująca prośba, kliknij aby anulować", "account.share": "Udostępnij profil @{name}", @@ -99,7 +100,7 @@ "empty_column.home.public_timeline": "publiczna oś czasu", "empty_column.list": "Nie ma nic na tej liście. Kiedy członkowie listy dodadzą nowe wpisy, pojawia się one tutaj.", "empty_column.notifications": "Nie masz żadnych powiadomień. Rozpocznij interakcje z innymi użytkownikami.", - "empty_column.public": "Tu nic nie ma! Napisz coś publicznie, lub dodaj ludzi z innych instancji, aby to wyświetlić.", + "empty_column.public": "Tu nic nie ma! Napisz coś publicznie, lub dodaj ludzi z innych instancji, aby to wyświetlić", "follow_request.authorize": "Autoryzuj", "follow_request.reject": "Odrzuć", "getting_started.appsshort": "Aplikacje", @@ -134,11 +135,11 @@ "lightbox.next": "Następne", "lightbox.previous": "Poprzednie", "lists.account.add": "Dodaj do listy", - "lists.account.remove": "Usuń z listy", + "lists.account.remove": "Usunąć z listy", "lists.delete": "Usuń listę", "lists.edit": "Edytuj listę", "lists.new.create": "Utwórz listę", - "lists.new.title_placeholder": "Wprowadź tytuł listy…", + "lists.new.title_placeholder": "Wprowadź tytuł listy", "lists.search": "Szukaj wśród osób które śledzisz", "lists.subheading": "Twoje listy", "loading_indicator.label": "Ładowanie…", @@ -206,7 +207,7 @@ "privacy.public.short": "Publiczny", "privacy.unlisted.long": "Niewidoczny na publicznych osiach czasu", "privacy.unlisted.short": "Niewidoczny", - "regeneration_indicator.label": "Ładowanie…", + "regeneration_indicator.label": "Ładuję…", "regeneration_indicator.sublabel": "Twoja oś czasu jest przygotowywana!", "relative_time.days": "{number} dni", "relative_time.hours": "{number} godz.", @@ -214,6 +215,9 @@ "relative_time.minutes": "{number} min.", "relative_time.seconds": "{number} s.", "reply_indicator.cancel": "Anuluj", + "report.forward": "Przekaż na {target}", + "report.forward_hint": "To konto znajduje się na innej instancji. Czy chcesz wysłać anonimową kopię zgłoszenia rnież na nią?", + "report.hint": "Zgłoszenie zostanie wysłane moderatorom Twojej instancji. Poniżej możesz też umieścić wyjaśnieni dlaczego zgłaszasz to konto:", "report.placeholder": "Dodatkowe komentarze", "report.submit": "Wyślij", "report.target": "Zgłaszanie {target}", @@ -262,6 +266,7 @@ "upload_area.title": "Przeciągnij i upuść aby wysłać", "upload_button.label": "Dodaj zawartość multimedialną", "upload_form.description": "Wprowadź opis dla niewidomych i niedowidzących", + "upload_form.focus": "Crop", "upload_form.undo": "Cofnij", "upload_progress.label": "Wysyłanie", "video.close": "Zamknij film", diff --git a/app/javascript/mastodon/locales/pt-BR.json b/app/javascript/mastodon/locales/pt-BR.json index 3d63da850..c07661e92 100644 --- a/app/javascript/mastodon/locales/pt-BR.json +++ b/app/javascript/mastodon/locales/pt-BR.json @@ -14,6 +14,7 @@ "account.mute": "Silenciar @{name}", "account.mute_notifications": "Silenciar notificações de @{name}", "account.posts": "Posts", + "account.posts_with_replies": "Toots with replies", "account.report": "Denunciar @{name}", "account.requested": "Aguardando aprovação. Clique para cancelar a solicitação", "account.share": "Compartilhar perfil de @{name}", @@ -90,7 +91,7 @@ "emoji_button.travel": "Viagens & Lugares", "empty_column.community": "A timeline local está vazia. Escreva algo publicamente para começar!", "empty_column.hashtag": "Ainda não há qualquer conteúdo com essa hashtag.", - "empty_column.home": "Você ainda não segue usuário algo. Visite a timeline {public} ou use o buscador para procurar e conhecer outros usuários.", + "empty_column.home": "Você ainda não segue usuário algum. Visite a timeline {public} ou use o buscador para procurar e conhecer outros usuários.", "empty_column.home.public_timeline": "global", "empty_column.list": "Ainda não há nada nesta lista. Quando membros dessa lista fizerem novas postagens, elas aparecerão aqui.", "empty_column.notifications": "Você ainda não possui notificações. Interaja com outros usuários para começar a conversar.", @@ -207,6 +208,9 @@ "relative_time.minutes": "{number}m", "relative_time.seconds": "{number}s", "reply_indicator.cancel": "Cancelar", + "report.forward": "Forward to {target}", + "report.forward_hint": "The account is from another server. Send an anonymized copy of the report there as well?", + "report.hint": "The report will be sent to your instance moderators. You can provide an explanation of why you are reporting this account below:", "report.placeholder": "Comentários adicionais", "report.submit": "Enviar", "report.target": "Denunciar", @@ -216,6 +220,9 @@ "search_popout.tips.status": "status", "search_popout.tips.text": "Texto simples retorna nomes de exibição, usuários e hashtags correspondentes", "search_popout.tips.user": "usuário", + "search_results.accounts": "People", + "search_results.hashtags": "Hashtags", + "search_results.statuses": "Toots", "search_results.total": "{count, number} {count, plural, one {resultado} other {resultados}}", "standalone.public_title": "Dê uma espiada...", "status.block": "Block @{name}", @@ -252,6 +259,7 @@ "upload_area.title": "Arraste e solte para enviar", "upload_button.label": "Adicionar mídia", "upload_form.description": "Descreva a imagem para deficientes visuais", + "upload_form.focus": "Crop", "upload_form.undo": "Desfazer", "upload_progress.label": "Salvando...", "video.close": "Fechar vídeo", diff --git a/app/javascript/mastodon/locales/pt.json b/app/javascript/mastodon/locales/pt.json index 2fd13db15..61233a1b9 100644 --- a/app/javascript/mastodon/locales/pt.json +++ b/app/javascript/mastodon/locales/pt.json @@ -14,6 +14,7 @@ "account.mute": "Silenciar @{name}", "account.mute_notifications": "Silenciar notificações de @{name}", "account.posts": "Posts", + "account.posts_with_replies": "Toots with replies", "account.report": "Denunciar @{name}", "account.requested": "A aguardar aprovação", "account.share": "Partilhar o perfil @{name}", @@ -207,6 +208,9 @@ "relative_time.minutes": "{number}m", "relative_time.seconds": "{number}s", "reply_indicator.cancel": "Cancelar", + "report.forward": "Forward to {target}", + "report.forward_hint": "The account is from another server. Send an anonymized copy of the report there as well?", + "report.hint": "The report will be sent to your instance moderators. You can provide an explanation of why you are reporting this account below:", "report.placeholder": "Comentários adicionais", "report.submit": "Enviar", "report.target": "Denunciar", @@ -216,6 +220,9 @@ "search_popout.tips.status": "status", "search_popout.tips.text": "O texto simples retorna a correspondência de nomes, utilizadores e hashtags", "search_popout.tips.user": "utilizador", + "search_results.accounts": "People", + "search_results.hashtags": "Hashtags", + "search_results.statuses": "Toots", "search_results.total": "{count, number} {count, plural, one {resultado} other {resultados}}", "standalone.public_title": "Espreitar lá dentro...", "status.block": "Block @{name}", @@ -252,6 +259,7 @@ "upload_area.title": "Arraste e solte para enviar", "upload_button.label": "Adicionar media", "upload_form.description": "Descrição da imagem para pessoas com dificuldades visuais", + "upload_form.focus": "Crop", "upload_form.undo": "Anular", "upload_progress.label": "A gravar...", "video.close": "Fechar vídeo", diff --git a/app/javascript/mastodon/locales/ru.json b/app/javascript/mastodon/locales/ru.json index 58ffa8d55..76d3fec13 100644 --- a/app/javascript/mastodon/locales/ru.json +++ b/app/javascript/mastodon/locales/ru.json @@ -14,6 +14,7 @@ "account.mute": "Заглушить", "account.mute_notifications": "Скрыть уведомления от @{name}", "account.posts": "Посты", + "account.posts_with_replies": "Toots with replies", "account.report": "Пожаловаться", "account.requested": "Ожидает подтверждения", "account.share": "Поделиться профилем @{name}", @@ -207,6 +208,9 @@ "relative_time.minutes": "{number}м", "relative_time.seconds": "{number}с", "reply_indicator.cancel": "Отмена", + "report.forward": "Forward to {target}", + "report.forward_hint": "The account is from another server. Send an anonymized copy of the report there as well?", + "report.hint": "The report will be sent to your instance moderators. You can provide an explanation of why you are reporting this account below:", "report.placeholder": "Комментарий", "report.submit": "Отправить", "report.target": "Жалуемся на", @@ -216,6 +220,9 @@ "search_popout.tips.status": "статус", "search_popout.tips.text": "Простой ввод текста покажет совпадающие имена пользователей, отображаемые имена и хэштеги", "search_popout.tips.user": "пользователь", + "search_results.accounts": "People", + "search_results.hashtags": "Hashtags", + "search_results.statuses": "Toots", "search_results.total": "{count, number} {count, plural, one {результат} few {результата} many {результатов} other {результатов}}", "standalone.public_title": "Прямо сейчас", "status.block": "Заблокировать @{name}", @@ -252,6 +259,7 @@ "upload_area.title": "Перетащите сюда, чтобы загрузить", "upload_button.label": "Добавить медиаконтент", "upload_form.description": "Описать для людей с нарушениями зрения", + "upload_form.focus": "Crop", "upload_form.undo": "Отменить", "upload_progress.label": "Загрузка...", "video.close": "Закрыть видео", diff --git a/app/javascript/mastodon/locales/sk.json b/app/javascript/mastodon/locales/sk.json index 1a0629708..de273770a 100644 --- a/app/javascript/mastodon/locales/sk.json +++ b/app/javascript/mastodon/locales/sk.json @@ -4,7 +4,7 @@ "account.disclaimer_full": "Inofrmácie nižšie nemusia byť úplným odrazom uživateľovho účtu.", "account.edit_profile": "Upraviť profil", "account.follow": "Následovať", - "account.followers": "Následovaťelia", + "account.followers": "Sledujúci", "account.follows": "Sledujete", "account.follows_you": "Následuje vás", "account.hide_reblogs": "Skryť povýšenia od @{name}", @@ -13,7 +13,8 @@ "account.moved_to": "{name} sa presunul/a na:", "account.mute": "Ignorovať @{name}", "account.mute_notifications": "Stĺmiť notifikácie od @{name}", - "account.posts": "Správy", + "account.posts": "Hlášky", + "account.posts_with_replies": "Toots with replies", "account.report": "Nahlásiť @{name}", "account.requested": "Čaká na schválenie. Kliknite pre zrušenie žiadosti", "account.share": "Zdieľať @{name} profil", @@ -72,7 +73,7 @@ "confirmations.mute.message": "Naozaj chcete ignorovať {name}?", "confirmations.unfollow.confirm": "Nesledovať", "confirmations.unfollow.message": "Naozaj chcete prestať sledovať {name}?", - "embed.instructions": "Skopírujte kód uvedený nižšie pre pridanie tohto statusu na vašu web stránku.", + "embed.instructions": "Umiestnite kód uvedený nižšie pre pridanie tohto statusu na vašu web stránku.", "embed.preview": "Tu je ako to bude vyzerať:", "emoji_button.activity": "Aktivita", "emoji_button.custom": "Vlastné", @@ -100,7 +101,7 @@ "getting_started.appsshort": "Aplikácie", "getting_started.faq": "FAQ", "getting_started.heading": "Začíname", - "getting_started.open_source_notice": "Mastodon má otvorený kód. Nahlásiť chyby, alebo prispievať vlastným kódom môžeš na GitHube v {github}.", + "getting_started.open_source_notice": "Mastodon má otvorený kód. Nahlásiť chyby, alebo prispievať vlastným kódom môžete na GitHube v {github}.", "getting_started.userguide": "Používateľská príručka", "home.column_settings.advanced": "Rozšírené", "home.column_settings.basic": "Základné", @@ -122,11 +123,11 @@ "keyboard_shortcuts.mention": "spomenúť autora", "keyboard_shortcuts.reply": "odpovedať", "keyboard_shortcuts.search": "zamerať sa na vyhľadávanie", - "keyboard_shortcuts.toot": "začať úplne nový toot", - "keyboard_shortcuts.unfocus": "to un-focus compose textarea/search", + "keyboard_shortcuts.toot": "začať úplne novú hlášku", + "keyboard_shortcuts.unfocus": "nesústrediť sa na písaciu plochu, alebo hľadanie", "keyboard_shortcuts.up": "posunúť sa vyššie v zozname", "lightbox.close": "Zatvoriť", - "lightbox.next": "Ďalší", + "lightbox.next": "Ďalšie", "lightbox.previous": "Predchádzajúci", "lists.account.add": "Pridať do zoznamu", "lists.account.remove": "Odobrať zo zoznamu", @@ -159,10 +160,10 @@ "notification.mention": "{name} vás spomenul", "notification.reblog": "{name} re-tootol tvoj status", "notifications.clear": "Vyčistiť zoznam notifikácii", - "notifications.clear_confirmation": "Naozaj chcete nenávratne vymazať všetky vaše notifikácie?", + "notifications.clear_confirmation": "Naozaj chcete nenávratne prečistiť všetky vaše notifikácie?", "notifications.column_settings.alert": "Notifikácie na ploche", "notifications.column_settings.favourite": "Obľúbené:", - "notifications.column_settings.follow": "Nový nasledujúci:", + "notifications.column_settings.follow": "Noví následujúci:", "notifications.column_settings.mention": "Zmienenia:", "notifications.column_settings.push": "Push notifikácie", "notifications.column_settings.push_meta": "Toto zariadenie", @@ -175,7 +176,7 @@ "onboarding.page_four.home": "Domovská časová os zobrazí správy od ľudí ktorých sledujete.", "onboarding.page_four.notifications": "Stĺpec s notifikáciami zobrazí keď budete s niekým komunikovať.", "onboarding.page_one.federation": "Mastodon je sieť nezávislých serverov, spojením ktorých vzniká jedna veľká federovaná sociálna sieť.", - "onboarding.page_one.full_handle": "Your full handle", + "onboarding.page_one.full_handle": "Vaša celá prezývka aj s adresou", "onboarding.page_one.handle_hint": "Toto je čo by ste povedali vaším priateľom že majú hľadať.", "onboarding.page_one.welcome": "Vitajte na Mastodone!", "onboarding.page_six.admin": "Správca tohto servera je {admin}.", @@ -193,7 +194,7 @@ "privacy.change": "Zmeňiť viditeľnosť statusu", "privacy.direct.long": "Poslať priamo iba spomenutým používateľom", "privacy.direct.short": "Súkromne", - "privacy.private.long": "Poslať iba sledujúcim", + "privacy.private.long": "Poslať iba následovateľom", "privacy.private.short": "Iba pre sledujúcich", "privacy.public.long": "Poslať všetkým verejne", "privacy.public.short": "Verejné", @@ -207,23 +208,29 @@ "relative_time.minutes": "{number}m", "relative_time.seconds": "{number}s", "reply_indicator.cancel": "Zrušiť", + "report.forward": "Forward to {target}", + "report.forward_hint": "The account is from another server. Send an anonymized copy of the report there as well?", + "report.hint": "The report will be sent to your instance moderators. You can provide an explanation of why you are reporting this account below:", "report.placeholder": "Ďalšie komentáre", "report.submit": "Poslať", "report.target": "Nahlásenie {target}", "search.placeholder": "Hľadať", - "search_popout.search_format": "Pokročilý tvar vyhľadávania", - "search_popout.tips.hashtag": "hashtag", + "search_popout.search_format": "Pokročilý formát vyhľadávania", + "search_popout.tips.hashtag": "haštag", "search_popout.tips.status": "status", "search_popout.tips.text": "Jednoduchý text vráti zhodujúce sa mená, prezývky a hashtagy", "search_popout.tips.user": "používateľ", + "search_results.accounts": "People", + "search_results.hashtags": "Hashtags", + "search_results.statuses": "Toots", "search_results.total": "{count, number} {count, plural, one {result} ostatné {results}}", "standalone.public_title": "Pohľad dovnútra...", "status.block": "Blokovať @{name}", "status.cannot_reblog": "Tento príspevok nemôže byť re-tootnutý", "status.delete": "Zmazať", - "status.embed": "Embed", + "status.embed": "Vložiť", "status.favourite": "Páči sa mi", - "status.load_more": "Zobraziť viac", + "status.load_more": "Zobraz viac", "status.media_hidden": "Skryté médiá", "status.mention": "Napísať @{name}", "status.more": "Viac", @@ -239,8 +246,8 @@ "status.sensitive_toggle": "Kliknite pre zobrazenie", "status.sensitive_warning": "Chúlostivý obsah", "status.share": "Zdieľať", - "status.show_less": "Zobraziť menej", - "status.show_more": "Zobraziť viac", + "status.show_less": "Zobraz menej", + "status.show_more": "Zobraz viac", "status.unmute_conversation": "Prestať ignorovať konverzáciu", "status.unpin": "Odopnúť z profilu", "tabs_bar.compose": "Napísať", @@ -252,6 +259,7 @@ "upload_area.title": "Ťahaj a pusti pre nahratie", "upload_button.label": "Pridať médiá", "upload_form.description": "Opis pre slabo vidiacich", + "upload_form.focus": "Crop", "upload_form.undo": "Navrátiť", "upload_progress.label": "Nahráva sa...", "video.close": "Zavrieť video", diff --git a/app/javascript/mastodon/locales/sr-Latn.json b/app/javascript/mastodon/locales/sr-Latn.json index cd48967cb..bf67a52d6 100644 --- a/app/javascript/mastodon/locales/sr-Latn.json +++ b/app/javascript/mastodon/locales/sr-Latn.json @@ -14,6 +14,7 @@ "account.mute": "Ućutkaj korisnika @{name}", "account.mute_notifications": "Isključi obaveštenja od korisnika @{name}", "account.posts": "Statusa", + "account.posts_with_replies": "Toots with replies", "account.report": "Prijavi @{name}", "account.requested": "Čekam odobrenje. Kliknite da poništite zahtev za praćenje", "account.share": "Podeli profil korisnika @{name}", @@ -207,6 +208,9 @@ "relative_time.minutes": "{number}m", "relative_time.seconds": "{number}s", "reply_indicator.cancel": "Poništi", + "report.forward": "Forward to {target}", + "report.forward_hint": "The account is from another server. Send an anonymized copy of the report there as well?", + "report.hint": "The report will be sent to your instance moderators. You can provide an explanation of why you are reporting this account below:", "report.placeholder": "Dodatni komentari", "report.submit": "Pošalji", "report.target": "Prijavljujem {target}", @@ -216,6 +220,9 @@ "search_popout.tips.status": "status", "search_popout.tips.text": "Traženjem običnog teksta ćete dobiti sva pronađena imena, sva korisnička imena i sve nađene heštegove", "search_popout.tips.user": "korisnik", + "search_results.accounts": "People", + "search_results.hashtags": "Hashtags", + "search_results.statuses": "Toots", "search_results.total": "{count, number} {count, plural, one {rezultat} few {rezultata} other {rezultata}}", "standalone.public_title": "Pogled iznutra...", "status.block": "Block @{name}", @@ -252,6 +259,7 @@ "upload_area.title": "Prevucite ovde da otpremite", "upload_button.label": "Dodaj multimediju", "upload_form.description": "Opiši za slabovide osobe", + "upload_form.focus": "Crop", "upload_form.undo": "Opozovi", "upload_progress.label": "Otpremam...", "video.close": "Zatvori video", diff --git a/app/javascript/mastodon/locales/sr.json b/app/javascript/mastodon/locales/sr.json index 595a70ea6..d8d1ebae7 100644 --- a/app/javascript/mastodon/locales/sr.json +++ b/app/javascript/mastodon/locales/sr.json @@ -14,6 +14,7 @@ "account.mute": "Ућуткај корисника @{name}", "account.mute_notifications": "Искључи обавештења од корисника @{name}", "account.posts": "Статуса", + "account.posts_with_replies": "Toots with replies", "account.report": "Пријави @{name}", "account.requested": "Чекам одобрење. Кликните да поништите захтев за праћење", "account.share": "Подели профил корисника @{name}", @@ -207,6 +208,9 @@ "relative_time.minutes": "{number}m", "relative_time.seconds": "{number}s", "reply_indicator.cancel": "Поништи", + "report.forward": "Forward to {target}", + "report.forward_hint": "The account is from another server. Send an anonymized copy of the report there as well?", + "report.hint": "The report will be sent to your instance moderators. You can provide an explanation of why you are reporting this account below:", "report.placeholder": "Додатни коментари", "report.submit": "Пошаљи", "report.target": "Пријављујем {target}", @@ -216,6 +220,9 @@ "search_popout.tips.status": "статус", "search_popout.tips.text": "Тражењем обичног текста ћете добити сва пронађена имена, сва корисничка имена и све нађене хештегове", "search_popout.tips.user": "корисник", + "search_results.accounts": "People", + "search_results.hashtags": "Hashtags", + "search_results.statuses": "Toots", "search_results.total": "{count, number} {count, plural, one {резултат} few {резултата} other {резултата}}", "standalone.public_title": "Поглед изнутра...", "status.block": "Block @{name}", @@ -252,6 +259,7 @@ "upload_area.title": "Превуците овде да отпремите", "upload_button.label": "Додај мултимедију", "upload_form.description": "Опиши за слабовиде особе", + "upload_form.focus": "Crop", "upload_form.undo": "Опозови", "upload_progress.label": "Отпремам...", "video.close": "Затвори видео", diff --git a/app/javascript/mastodon/locales/sv.json b/app/javascript/mastodon/locales/sv.json index 3f25648c2..0bf66c547 100644 --- a/app/javascript/mastodon/locales/sv.json +++ b/app/javascript/mastodon/locales/sv.json @@ -14,6 +14,7 @@ "account.mute": "Tysta @{name}", "account.mute_notifications": "Stäng av notifieringar från @{name}", "account.posts": "Inlägg", + "account.posts_with_replies": "Toots with replies", "account.report": "Rapportera @{name}", "account.requested": "Inväntar godkännande. Klicka för att avbryta följförfrågan", "account.share": "Dela @{name}'s profil", @@ -207,6 +208,9 @@ "relative_time.minutes": "{number}m", "relative_time.seconds": "{number}s", "reply_indicator.cancel": "Ångra", + "report.forward": "Forward to {target}", + "report.forward_hint": "The account is from another server. Send an anonymized copy of the report there as well?", + "report.hint": "The report will be sent to your instance moderators. You can provide an explanation of why you are reporting this account below:", "report.placeholder": "Ytterligare kommentarer", "report.submit": "Skicka", "report.target": "Rapporterar {target}", @@ -216,6 +220,9 @@ "search_popout.tips.status": "status", "search_popout.tips.text": "Enkel text returnerar matchande visningsnamn, användarnamn och hashtags", "search_popout.tips.user": "användare", + "search_results.accounts": "People", + "search_results.hashtags": "Hashtags", + "search_results.statuses": "Toots", "search_results.total": "{count, number} {count, plural, ett {result} andra {results}}", "standalone.public_title": "En titt inuti...", "status.block": "Block @{name}", @@ -252,6 +259,7 @@ "upload_area.title": "Dra & släpp för att ladda upp", "upload_button.label": "Lägg till media", "upload_form.description": "Beskriv för synskadade", + "upload_form.focus": "Crop", "upload_form.undo": "Ångra", "upload_progress.label": "Laddar upp...", "video.close": "Stäng video", diff --git a/app/javascript/mastodon/locales/th.json b/app/javascript/mastodon/locales/th.json index 740fb80e7..d6ccc9412 100644 --- a/app/javascript/mastodon/locales/th.json +++ b/app/javascript/mastodon/locales/th.json @@ -14,6 +14,7 @@ "account.mute": "Mute @{name}", "account.mute_notifications": "Mute notifications from @{name}", "account.posts": "Posts", + "account.posts_with_replies": "Toots with replies", "account.report": "Report @{name}", "account.requested": "Awaiting approval", "account.share": "Share @{name}'s profile", @@ -207,6 +208,9 @@ "relative_time.minutes": "{number}m", "relative_time.seconds": "{number}s", "reply_indicator.cancel": "Cancel", + "report.forward": "Forward to {target}", + "report.forward_hint": "The account is from another server. Send an anonymized copy of the report there as well?", + "report.hint": "The report will be sent to your instance moderators. You can provide an explanation of why you are reporting this account below:", "report.placeholder": "Additional comments", "report.submit": "Submit", "report.target": "Reporting", @@ -216,6 +220,9 @@ "search_popout.tips.status": "status", "search_popout.tips.text": "Simple text returns matching display names, usernames and hashtags", "search_popout.tips.user": "user", + "search_results.accounts": "People", + "search_results.hashtags": "Hashtags", + "search_results.statuses": "Toots", "search_results.total": "{count, number} {count, plural, one {result} other {results}}", "standalone.public_title": "A look inside...", "status.block": "Block @{name}", @@ -252,6 +259,7 @@ "upload_area.title": "Drag & drop to upload", "upload_button.label": "Add media", "upload_form.description": "Describe for the visually impaired", + "upload_form.focus": "Crop", "upload_form.undo": "Undo", "upload_progress.label": "Uploading...", "video.close": "Close video", diff --git a/app/javascript/mastodon/locales/tr.json b/app/javascript/mastodon/locales/tr.json index 8805e52f4..702c8454d 100644 --- a/app/javascript/mastodon/locales/tr.json +++ b/app/javascript/mastodon/locales/tr.json @@ -14,6 +14,7 @@ "account.mute": "Sustur @{name}", "account.mute_notifications": "Mute notifications from @{name}", "account.posts": "Gönderiler", + "account.posts_with_replies": "Toots with replies", "account.report": "Rapor et @{name}", "account.requested": "Onay bekleniyor", "account.share": "Share @{name}'s profile", @@ -207,6 +208,9 @@ "relative_time.minutes": "{number}m", "relative_time.seconds": "{number}s", "reply_indicator.cancel": "İptal", + "report.forward": "Forward to {target}", + "report.forward_hint": "The account is from another server. Send an anonymized copy of the report there as well?", + "report.hint": "The report will be sent to your instance moderators. You can provide an explanation of why you are reporting this account below:", "report.placeholder": "Ek yorumlar", "report.submit": "Gönder", "report.target": "Raporlama", @@ -216,6 +220,9 @@ "search_popout.tips.status": "status", "search_popout.tips.text": "Simple text returns matching display names, usernames and hashtags", "search_popout.tips.user": "user", + "search_results.accounts": "People", + "search_results.hashtags": "Hashtags", + "search_results.statuses": "Toots", "search_results.total": "{count, number} {count, plural, one {sonuç} other {sonuçlar}}", "standalone.public_title": "A look inside...", "status.block": "Block @{name}", @@ -252,6 +259,7 @@ "upload_area.title": "Upload için sürükle bırak yapınız", "upload_button.label": "Görsel ekle", "upload_form.description": "Describe for the visually impaired", + "upload_form.focus": "Crop", "upload_form.undo": "Geri al", "upload_progress.label": "Yükleniyor...", "video.close": "Close video", diff --git a/app/javascript/mastodon/locales/uk.json b/app/javascript/mastodon/locales/uk.json index 2cdaba0ac..b5bd88cbb 100644 --- a/app/javascript/mastodon/locales/uk.json +++ b/app/javascript/mastodon/locales/uk.json @@ -14,6 +14,7 @@ "account.mute": "Заглушити", "account.mute_notifications": "Mute notifications from @{name}", "account.posts": "Пости", + "account.posts_with_replies": "Toots with replies", "account.report": "Поскаржитися", "account.requested": "Очікує підтвердження", "account.share": "Share @{name}'s profile", @@ -207,6 +208,9 @@ "relative_time.minutes": "{number}m", "relative_time.seconds": "{number}s", "reply_indicator.cancel": "Відмінити", + "report.forward": "Forward to {target}", + "report.forward_hint": "The account is from another server. Send an anonymized copy of the report there as well?", + "report.hint": "The report will be sent to your instance moderators. You can provide an explanation of why you are reporting this account below:", "report.placeholder": "Додаткові коментарі", "report.submit": "Відправити", "report.target": "Скаржимося на", @@ -216,6 +220,9 @@ "search_popout.tips.status": "status", "search_popout.tips.text": "Simple text returns matching display names, usernames and hashtags", "search_popout.tips.user": "user", + "search_results.accounts": "People", + "search_results.hashtags": "Hashtags", + "search_results.statuses": "Toots", "search_results.total": "{count, number} {count, plural, one {результат} few {результати} many {результатів} other {результатів}}", "standalone.public_title": "A look inside...", "status.block": "Block @{name}", @@ -252,6 +259,7 @@ "upload_area.title": "Перетягніть сюди, щоб завантажити", "upload_button.label": "Додати медіаконтент", "upload_form.description": "Describe for the visually impaired", + "upload_form.focus": "Crop", "upload_form.undo": "Відмінити", "upload_progress.label": "Завантаження...", "video.close": "Close video", diff --git a/app/javascript/mastodon/locales/zh-CN.json b/app/javascript/mastodon/locales/zh-CN.json index a02211b8a..7cc5903cd 100644 --- a/app/javascript/mastodon/locales/zh-CN.json +++ b/app/javascript/mastodon/locales/zh-CN.json @@ -14,6 +14,7 @@ "account.mute": "隐藏 @{name}", "account.mute_notifications": "隐藏来自 @{name} 的通知", "account.posts": "嘟文", + "account.posts_with_replies": "Toots with replies", "account.report": "举报 @{name}", "account.requested": "正在等待对方同意。点击以取消发送关注请求", "account.share": "分享 @{name} 的个人资料", @@ -207,6 +208,9 @@ "relative_time.minutes": "{number}分", "relative_time.seconds": "{number}秒", "reply_indicator.cancel": "取消", + "report.forward": "Forward to {target}", + "report.forward_hint": "The account is from another server. Send an anonymized copy of the report there as well?", + "report.hint": "The report will be sent to your instance moderators. You can provide an explanation of why you are reporting this account below:", "report.placeholder": "附言", "report.submit": "提交", "report.target": "举报 {target}", @@ -216,6 +220,9 @@ "search_popout.tips.status": "嘟文", "search_popout.tips.text": "使用普通字符进行搜索将会返回昵称、用户名和话题标签", "search_popout.tips.user": "用户", + "search_results.accounts": "People", + "search_results.hashtags": "Hashtags", + "search_results.statuses": "Toots", "search_results.total": "共 {count, number} 个结果", "standalone.public_title": "大家都在干啥?", "status.block": "屏蔽 @{name}", @@ -252,6 +259,7 @@ "upload_area.title": "将文件拖放到此处开始上传", "upload_button.label": "上传媒体文件", "upload_form.description": "为视觉障碍人士添加文字说明", + "upload_form.focus": "Crop", "upload_form.undo": "取消上传", "upload_progress.label": "上传中…", "video.close": "关闭视频", diff --git a/app/javascript/mastodon/locales/zh-HK.json b/app/javascript/mastodon/locales/zh-HK.json index 0a3ae423d..d21ecc463 100644 --- a/app/javascript/mastodon/locales/zh-HK.json +++ b/app/javascript/mastodon/locales/zh-HK.json @@ -14,6 +14,7 @@ "account.mute": "將 @{name} 靜音", "account.mute_notifications": "Mute notifications from @{name}", "account.posts": "文章", + "account.posts_with_replies": "Toots with replies", "account.report": "舉報 @{name}", "account.requested": "等候審批", "account.share": "分享 @{name} 的個人資料", @@ -207,6 +208,9 @@ "relative_time.minutes": "{number}m", "relative_time.seconds": "{number}s", "reply_indicator.cancel": "取消", + "report.forward": "Forward to {target}", + "report.forward_hint": "The account is from another server. Send an anonymized copy of the report there as well?", + "report.hint": "The report will be sent to your instance moderators. You can provide an explanation of why you are reporting this account below:", "report.placeholder": "額外訊息", "report.submit": "提交", "report.target": "舉報", @@ -216,6 +220,9 @@ "search_popout.tips.status": "status", "search_popout.tips.text": "Simple text returns matching display names, usernames and hashtags", "search_popout.tips.user": "user", + "search_results.accounts": "People", + "search_results.hashtags": "Hashtags", + "search_results.statuses": "Toots", "search_results.total": "{count, number} 項結果", "standalone.public_title": "站點一瞥…", "status.block": "Block @{name}", @@ -252,6 +259,7 @@ "upload_area.title": "將檔案拖放至此上載", "upload_button.label": "上載媒體檔案", "upload_form.description": "Describe for the visually impaired", + "upload_form.focus": "Crop", "upload_form.undo": "還原", "upload_progress.label": "上載中……", "video.close": "關閉影片", diff --git a/app/javascript/mastodon/locales/zh-TW.json b/app/javascript/mastodon/locales/zh-TW.json index 1201fe3c7..f1ae29283 100644 --- a/app/javascript/mastodon/locales/zh-TW.json +++ b/app/javascript/mastodon/locales/zh-TW.json @@ -14,6 +14,7 @@ "account.mute": "消音 @{name}", "account.mute_notifications": "Mute notifications from @{name}", "account.posts": "貼文", + "account.posts_with_replies": "Toots with replies", "account.report": "檢舉 @{name}", "account.requested": "正在等待許可", "account.share": "分享 @{name} 的用者資訊", @@ -207,6 +208,9 @@ "relative_time.minutes": "{number}m", "relative_time.seconds": "{number}s", "reply_indicator.cancel": "取消", + "report.forward": "Forward to {target}", + "report.forward_hint": "The account is from another server. Send an anonymized copy of the report there as well?", + "report.hint": "The report will be sent to your instance moderators. You can provide an explanation of why you are reporting this account below:", "report.placeholder": "更多訊息", "report.submit": "送出", "report.target": "通報中", @@ -216,6 +220,9 @@ "search_popout.tips.status": "status", "search_popout.tips.text": "Simple text returns matching display names, usernames and hashtags", "search_popout.tips.user": "user", + "search_results.accounts": "People", + "search_results.hashtags": "Hashtags", + "search_results.statuses": "Toots", "search_results.total": "{count, number} 項結果", "standalone.public_title": "站點一瞥…", "status.block": "Block @{name}", @@ -252,6 +259,7 @@ "upload_area.title": "拖放來上傳", "upload_button.label": "增加媒體", "upload_form.description": "Describe for the visually impaired", + "upload_form.focus": "Crop", "upload_form.undo": "復原", "upload_progress.label": "上傳中...", "video.close": "關閉影片", diff --git a/app/javascript/mastodon/reducers/reports.js b/app/javascript/mastodon/reducers/reports.js index a08bbec38..21ae6f93f 100644 --- a/app/javascript/mastodon/reducers/reports.js +++ b/app/javascript/mastodon/reducers/reports.js @@ -6,6 +6,7 @@ import { REPORT_CANCEL, REPORT_STATUS_TOGGLE, REPORT_COMMENT_CHANGE, + REPORT_FORWARD_CHANGE, } from '../actions/reports'; import { Map as ImmutableMap, Set as ImmutableSet } from 'immutable'; @@ -15,6 +16,7 @@ const initialState = ImmutableMap({ account_id: null, status_ids: ImmutableSet(), comment: '', + forward: false, }), }); @@ -42,6 +44,8 @@ export default function reports(state = initialState, action) { }); case REPORT_COMMENT_CHANGE: return state.setIn(['new', 'comment'], action.comment); + case REPORT_FORWARD_CHANGE: + return state.setIn(['new', 'forward'], action.forward); case REPORT_SUBMIT_REQUEST: return state.setIn(['new', 'isSubmitting'], true); case REPORT_SUBMIT_FAIL: diff --git a/app/javascript/styles/mastodon/about.scss b/app/javascript/styles/mastodon/about.scss index a95b75984..9ce83aa9b 100644 --- a/app/javascript/styles/mastodon/about.scss +++ b/app/javascript/styles/mastodon/about.scss @@ -15,117 +15,169 @@ $small-breakpoint: 960px; } } -.show-xs, -.show-sm { - display: none; -} +.landing-page { + .grid { + display: grid; + grid-gap: 10px; + grid-template-columns: 1fr 2fr; + grid-auto-columns: 25%; + grid-auto-rows: max-content; + + .column-0 { + display: none; + } -.show-m { - display: block; -} + .column-1 { + grid-column: 1; + grid-row: 1; + } -@media screen and (max-width: $small-breakpoint) { - .hide-sm { - display: none !important; - } + .column-2 { + grid-column: 2; + grid-row: 1; + } - .show-sm { - display: block !important; - } -} + .column-3 { + grid-column: 3; + grid-row: 1 / 3; + } -@media screen and (max-width: $column-breakpoint) { - .hide-xs { - display: none !important; + .column-4 { + grid-column: 1 / 3; + grid-row: 2; + } } - .show-xs { - display: block !important; - } -} + @media screen and (max-width: $small-breakpoint) { + .grid { + grid-template-columns: 40% 60%; -.row { - display: flex; - flex-wrap: wrap; - margin: 0 -5px; + .column-0 { + display: none; + } - @for $i from 1 through 15 { - .column-#{$i} { - box-sizing: border-box; - min-height: 1px; - flex: 0 0 percentage($i / 15); - max-width: percentage($i / 15); - padding: 0 5px; + .column-1 { + grid-column: 1; + grid-row: 1; - @media screen and (max-width: $small-breakpoint) { - &-sm { - box-sizing: border-box; - min-height: 1px; - flex: 0 0 percentage($i / 15); - max-width: percentage($i / 15); - padding: 0 5px; - - @media screen and (max-width: $column-breakpoint) { - max-width: 100%; - flex: 0 0 100%; - margin-bottom: 10px; - - &:last-child { - margin-bottom: 0; - } - } + &.non-preview .landing-page__forms { + height: 100%; } } - @media screen and (max-width: $column-breakpoint) { - max-width: 100%; - flex: 0 0 100%; - margin-bottom: 10px; + .column-2 { + grid-column: 2; + grid-row: 1 / 3; - &:last-child { - margin-bottom: 0; + &.non-preview { + grid-column: 2; + grid-row: 1; + } + } + + .column-3 { + grid-column: 1; + grid-row: 2 / 4; + } + + .column-4 { + grid-column: 2; + grid-row: 3; + + &.non-preview { + grid-column: 1 / 3; + grid-row: 2; } } } } -} -.column-flex { - display: flex; - flex-direction: column; -} + @media screen and (max-width: $column-breakpoint) { + .grid { + grid-template-columns: auto; -.separator-or { - position: relative; - margin: 40px 0; - text-align: center; + .column-0 { + display: block; + grid-column: 1; + grid-row: 1; + } - &::before { - content: ""; - display: block; - width: 100%; - height: 0; - border-bottom: 1px solid rgba($ui-base-lighter-color, .6); - position: absolute; - top: 50%; - left: 0; + .column-1 { + grid-column: 1; + grid-row: 3; + + .brand { + display: none; + } + } + + .column-2 { + grid-column: 1; + grid-row: 2; + + .landing-page__logo, + .landing-page__call-to-action { + display: none; + } + + &.non-preview { + grid-column: 1; + grid-row: 2; + } + } + + .column-3 { + grid-column: 1; + grid-row: 5; + } + + .column-4 { + grid-column: 1; + grid-row: 4; + + &.non-preview { + grid-column: 1; + grid-row: 4; + } + } + } } - span { - display: inline-block; - background: $ui-base-color; - font-size: 12px; - font-weight: 500; - color: $ui-primary-color; - text-transform: uppercase; + .column-flex { + display: flex; + flex-direction: column; + } + + .separator-or { position: relative; - z-index: 1; - padding: 0 8px; - cursor: default; + margin: 40px 0; + text-align: center; + + &::before { + content: ""; + display: block; + width: 100%; + height: 0; + border-bottom: 1px solid rgba($ui-base-lighter-color, .6); + position: absolute; + top: 50%; + left: 0; + } + + span { + display: inline-block; + background: $ui-base-color; + font-size: 12px; + font-weight: 500; + color: $ui-primary-color; + text-transform: uppercase; + position: relative; + z-index: 1; + padding: 0 8px; + cursor: default; + } } -} -.landing-page { p, li { font-family: 'mastodon-font-sans-serif', sans-serif; @@ -539,6 +591,7 @@ $small-breakpoint: 960px; img { position: static; + padding: 10px 0; } @media screen and (max-width: $small-breakpoint) { @@ -558,18 +611,33 @@ $small-breakpoint: 960px; } &__call-to-action { - margin-bottom: 10px; background: darken($ui-base-color, 4%); border-radius: 4px; padding: 25px 40px; overflow: hidden; .row { + display: flex; + flex-direction: row-reverse; + flex-wrap: wrap; + justify-content: space-between; align-items: center; } - .information-board__section { - padding: 0; + .row__information-board { + display: flex; + justify-content: flex-end; + align-items: flex-end; + + .information-board__section { + flex: 1 0 auto; + padding: 0 10px; + } + } + + .row__mascot { + flex: 1; + margin: 10px -50px 0 0; } } @@ -619,6 +687,8 @@ $small-breakpoint: 960px; &__short-description { .row { + display: flex; + flex-wrap: wrap; align-items: center; margin-bottom: 40px; } @@ -668,7 +738,6 @@ $small-breakpoint: 960px; height: 100%; @media screen and (max-width: $small-breakpoint) { - margin-bottom: 10px; height: auto; } @@ -717,6 +786,7 @@ $small-breakpoint: 960px; width: 100%; flex: 1 1 auto; overflow: hidden; + height: 100%; .column-header { color: inherit; @@ -942,93 +1012,54 @@ $small-breakpoint: 960px; } &.tag-page { - .features { - padding: 30px 0; - - .container-alt { - max-width: 820px; - - #mastodon-timeline { - margin-right: 0; - border-top-right-radius: 0; - } - - .about-mastodon { - .about-hashtag { - background: darken($ui-base-color, 4%); - padding: 0 20px 20px 30px; - border-radius: 0 5px 5px 0; - - .brand { - padding-top: 20px; - margin-bottom: 20px; - - img { - height: 48px; - width: auto; - } - } - - p { - strong { - color: $ui-secondary-color; - font-weight: 700; - } - } + .grid { + @media screen and (min-width: $small-breakpoint) { + grid-template-columns: 33% 67%; + } - .cta { - margin: 0; + .column-2 { + grid-column: 2; + grid-row: 1; + } + } - .button { - margin-right: 4px; - } - } - } + .brand { + text-align: unset; + padding: 0; - .features-list { - margin-left: 30px; - margin-right: 10px; - } - } + img { + height: 48px; + width: auto; } } - @media screen and (max-width: 675px) { - .features { - padding: 10px 0; + .cta { + margin: 0; - .container-alt { - display: flex; - flex-direction: column; - - #mastodon-timeline { - order: 2; - flex: 0 0 auto; - height: 60vh; - margin-bottom: 20px; - border-top-right-radius: 4px; - } + .button { + margin-right: 4px; + } + } - .about-mastodon { - order: 1; - flex: 0 0 auto; - max-width: 100%; + @media screen and (max-width: $column-breakpoint) { + .grid { + .column-1 { + grid-column: 1; + grid-row: 2; + } - .about-hashtag { - background: unset; - padding: 0; - border-radius: 0; + .column-2 { + grid-column: 1; + grid-row: 1; + } + } - .cta { - margin: 20px 0; - } - } + .brand { + margin: 0; + } - .features-list { - display: none; - } - } - } + .landing-page__features { + display: none; } } } diff --git a/app/javascript/styles/mastodon/accounts.scss b/app/javascript/styles/mastodon/accounts.scss index 9015d04cb..873963c90 100644 --- a/app/javascript/styles/mastodon/accounts.scss +++ b/app/javascript/styles/mastodon/accounts.scss @@ -97,32 +97,6 @@ } } - .controls { - position: absolute; - top: 15px; - left: 15px; - z-index: 2; - - .icon-button { - color: rgba($white, 0.8); - text-decoration: none; - font-size: 13px; - line-height: 13px; - font-weight: 500; - - .fa { - font-weight: 400; - margin-right: 5px; - } - - &:hover, - &:active, - &:focus { - color: $white; - } - } - } - .roles { margin-bottom: 30px; padding: 0 15px; @@ -226,6 +200,40 @@ } } +.card, +.account-grid-card { + .controls { + position: absolute; + top: 15px; + left: 15px; + z-index: 2; + + .icon-button { + color: rgba($white, 0.8); + text-decoration: none; + font-size: 13px; + line-height: 13px; + font-weight: 500; + + .fa { + font-weight: 400; + margin-right: 5px; + } + + &:hover, + &:active, + &:focus { + color: $white; + } + } + } +} + +.account-grid-card .controls { + left: auto; + right: 15px; +} + .pagination { padding: 30px 0; text-align: center; @@ -233,8 +241,8 @@ a, .current, - .next, - .prev, + .newer, + .older, .page, .gap { font-size: 14px; @@ -257,13 +265,13 @@ cursor: default; } - .prev, - .next { + .older, + .newer { text-transform: uppercase; color: $ui-secondary-color; } - .prev { + .older { float: left; padding-left: 0; @@ -273,7 +281,7 @@ } } - .next { + .newer { float: right; padding-right: 0; @@ -295,8 +303,8 @@ display: none; } - .next, - .prev { + .newer, + .older { display: inline-block; } } @@ -411,13 +419,14 @@ font-weight: 400; } - .note { + .account__header__content { padding: 10px 15px; padding-top: 15px; - box-sizing: border-box; color: lighten($ui-base-color, 26%); word-wrap: break-word; - min-height: 80px; + overflow: hidden; + text-overflow: ellipsis; + height: 5.5em; } } } diff --git a/app/javascript/styles/mastodon/components.scss b/app/javascript/styles/mastodon/components.scss index 0b5a721a7..d8364ef81 100644 --- a/app/javascript/styles/mastodon/components.scss +++ b/app/javascript/styles/mastodon/components.scss @@ -1878,7 +1878,7 @@ font-size: 14px; font-weight: 500; border-bottom: 2px solid lighten($ui-base-color, 8%); - transition: all 200ms linear; + transition: all 50ms linear; .fa { font-weight: 400; @@ -1895,7 +1895,6 @@ &:active { @media screen and (min-width: 631px) { background: lighten($ui-base-color, 14%); - transition: all 100ms linear; } } @@ -3891,8 +3890,7 @@ a.status-card { .boost-modal__action-bar, .confirmation-modal__action-bar, -.mute-modal__action-bar, -.report-modal__action-bar { +.mute-modal__action-bar { display: flex; justify-content: space-between; background: $ui-secondary-color; @@ -3936,21 +3934,94 @@ a.status-card { vertical-align: middle; } +.report-modal { + width: 90vw; + max-width: 700px; +} + +.report-modal__container { + display: flex; + border-top: 1px solid $ui-secondary-color; + + @media screen and (max-width: 480px) { + flex-wrap: wrap; + overflow-y: auto; + } +} + .report-modal__statuses, .report-modal__comment { - padding: 10px; + box-sizing: border-box; + width: 50%; + + @media screen and (max-width: 480px) { + width: 100%; + } } .report-modal__statuses { + flex: 1 1 auto; min-height: 20vh; max-height: 40vh; overflow-y: auto; overflow-x: hidden; + + @media screen and (max-width: 480px) { + max-height: 10vh; + } } .report-modal__comment { + padding: 20px; + border-right: 1px solid $ui-secondary-color; + max-width: 320px; + + p { + font-size: 14px; + line-height: 20px; + margin-bottom: 20px; + } + .setting-text { - margin-top: 10px; + display: block; + box-sizing: border-box; + width: 100%; + margin: 0; + color: $ui-base-color; + background: $white; + padding: 10px; + font-family: inherit; + font-size: 14px; + resize: vertical; + border: 0; + outline: 0; + border-radius: 4px; + border: 1px solid $ui-secondary-color; + margin-bottom: 20px; + + &:focus { + border: 1px solid darken($ui-secondary-color, 8%); + } + } + + .setting-toggle { + margin-top: 20px; + margin-bottom: 24px; + + &__label { + color: $ui-base-color; + font-size: 14px; + } + } + + @media screen and (max-width: 480px) { + padding: 10px; + max-width: 100%; + order: 2; + + .setting-toggle { + margin-bottom: 4px; + } } } @@ -4043,6 +4114,15 @@ a.status-card { } } +.report-modal__target { + padding: 20px; + + .media-modal__close { + top: 19px; + right: 15px; + } +} + .loading-bar { background-color: $ui-highlight-color; height: 3px; @@ -4154,6 +4234,7 @@ a.status-card { &.standalone { .media-gallery__item-gifv-thumbnail { transform: none; + top: 0; } } } @@ -4283,7 +4364,7 @@ a.status-card { &.inline { video { - object-fit: cover; + object-fit: contain; position: relative; top: 50%; transform: translateY(-50%); @@ -4503,64 +4584,96 @@ a.status-card { /* End Video Player */ .account-gallery__container { - margin: -2px; - padding: 4px; display: flex; + justify-content: center; flex-wrap: wrap; + padding: 2px; } .account-gallery__item { - flex: 1 1 auto; - width: calc(100% / 3 - 4px); - height: 95px; - margin: 2px; + flex-grow: 1; + width: 50%; + overflow: hidden; + position: relative; + + &::before { + content: ""; + display: block; + padding-top: 100%; + } a { display: block; - width: 100%; - height: 100%; + width: calc(100% - 4px); + height: calc(100% - 4px); + margin: 2px; + top: 0; + left: 0; background-color: $base-overlay-background; background-size: cover; background-position: center; - position: relative; + position: absolute; color: inherit; text-decoration: none; + border-radius: 4px; &:hover, &:active, &:focus { outline: 0; + + &::before { + content: ""; + display: block; + width: 100%; + height: 100%; + background: rgba($base-overlay-background, 0.3); + border-radius: 4px; + } } } } -.account-section-headline { - color: $ui-base-lighter-color; - background: lighten($ui-base-color, 2%); - border-bottom: 1px solid lighten($ui-base-color, 4%); - padding: 15px 10px; - font-size: 14px; - font-weight: 500; - position: relative; +.account__section-headline { + background: darken($ui-base-color, 4%); + border-bottom: 1px solid lighten($ui-base-color, 8%); cursor: default; + display: flex; - &::before, - &::after { + a { display: block; - content: ""; - position: absolute; - bottom: 0; - left: 18px; - width: 0; - height: 0; - border-style: solid; - border-width: 0 10px 10px; - border-color: transparent transparent lighten($ui-base-color, 4%); - } + flex: 1 1 auto; + color: $ui-primary-color; + padding: 15px 0; + font-size: 14px; + font-weight: 500; + text-align: center; + text-decoration: none; + position: relative; - &::after { - bottom: -1px; - border-color: transparent transparent $ui-base-color; + &.active { + color: $ui-secondary-color; + + &::before, + &::after { + display: block; + content: ""; + position: absolute; + bottom: 0; + left: 50%; + width: 0; + height: 0; + transform: translateX(-50%); + border-style: solid; + border-width: 0 10px 10px; + border-color: transparent transparent lighten($ui-base-color, 8%); + } + + &::after { + bottom: -1px; + border-color: transparent transparent $ui-base-color; + } + } } } @@ -4910,3 +5023,27 @@ noscript { left: 0; } } + +.floating-action-button { + position: fixed; + display: flex; + justify-content: center; + align-items: center; + width: 3.9375rem; + height: 3.9375rem; + bottom: 1.3125rem; + right: 1.3125rem; + background: darken($ui-highlight-color, 3%); + color: $white; + border-radius: 50%; + font-size: 21px; + line-height: 21px; + text-decoration: none; + box-shadow: 2px 3px 9px rgba($base-shadow-color, 0.4); + + &:hover, + &:focus, + &:active { + background: lighten($ui-highlight-color, 7%); + } +} diff --git a/app/javascript/styles/mastodon/forms.scss b/app/javascript/styles/mastodon/forms.scss index dec7d2284..2e38cda4e 100644 --- a/app/javascript/styles/mastodon/forms.scss +++ b/app/javascript/styles/mastodon/forms.scss @@ -278,6 +278,11 @@ code { .actions { margin-top: 30px; display: flex; + + &.actions--top { + margin-top: 0; + margin-bottom: 30px; + } } button, diff --git a/app/lib/activitypub/activity.rb b/app/lib/activitypub/activity.rb index 4617905c6..6f4a3b491 100644 --- a/app/lib/activitypub/activity.rb +++ b/app/lib/activitypub/activity.rb @@ -44,6 +44,8 @@ class ActivityPub::Activity ActivityPub::Activity::Accept when 'Reject' ActivityPub::Activity::Reject + when 'Flag' + ActivityPub::Activity::Flag end end end diff --git a/app/lib/activitypub/activity/flag.rb b/app/lib/activitypub/activity/flag.rb new file mode 100644 index 000000000..36d3c5730 --- /dev/null +++ b/app/lib/activitypub/activity/flag.rb @@ -0,0 +1,25 @@ +# frozen_string_literal: true + +class ActivityPub::Activity::Flag < ActivityPub::Activity + def perform + target_accounts = object_uris.map { |uri| account_from_uri(uri) }.compact.select(&:local?) + target_statuses_by_account = object_uris.map { |uri| status_from_uri(uri) }.compact.select(&:local?).group_by(&:account_id) + + target_accounts.each do |target_account| + next if Report.where(account: @account, target_account: target_account).exists? + + target_statuses = target_statuses_by_account[target_account.id] + + ReportService.new.call( + @account, + target_account, + status_ids: target_statuses.nil? ? [] : target_statuses.map(&:id), + comment: @json['content'] || '' + ) + end + end + + def object_uris + @object_uris ||= Array(@object.is_a?(Array) ? @object.map { |item| value_or_id(item) } : value_or_id(@object)) + end +end diff --git a/app/lib/activitypub/activity/reject.rb b/app/lib/activitypub/activity/reject.rb index d815feeb6..28d472883 100644 --- a/app/lib/activitypub/activity/reject.rb +++ b/app/lib/activitypub/activity/reject.rb @@ -17,6 +17,8 @@ class ActivityPub::Activity::Reject < ActivityPub::Activity follow_request = FollowRequest.find_by(account: target_account, target_account: @account) follow_request&.reject! + + UnfollowService.new.call(target_account, @account) if target_account.following?(@account) end def target_uri diff --git a/app/lib/exceptions.rb b/app/lib/exceptions.rb index b2489711d..95e3365c2 100644 --- a/app/lib/exceptions.rb +++ b/app/lib/exceptions.rb @@ -4,6 +4,7 @@ module Mastodon class Error < StandardError; end class NotPermittedError < Error; end class ValidationError < Error; end + class HostValidationError < ValidationError; end class RaceConditionError < Error; end class UnexpectedResponseError < Error diff --git a/app/lib/request.rb b/app/lib/request.rb index 7671f4ffc..5776b3d78 100644 --- a/app/lib/request.rb +++ b/app/lib/request.rb @@ -1,5 +1,8 @@ # frozen_string_literal: true +require 'ipaddr' +require 'socket' + class Request REQUEST_TARGET = '(request-target)' @@ -8,7 +11,7 @@ class Request def initialize(verb, url, **options) @verb = verb @url = Addressable::URI.parse(url).normalize - @options = options + @options = options.merge(socket_class: Socket) @headers = {} set_common_headers! @@ -87,4 +90,18 @@ class Request def http_client HTTP.timeout(:per_operation, timeout).follow(max_hops: 2) end + + class Socket < TCPSocket + class << self + def open(host, *args) + address = IPSocket.getaddress(host) + raise Mastodon::HostValidationError if PrivateAddressCheck.private_address? IPAddr.new(address) + super address, *args + end + + alias new open + end + end + + private_constant :Socket end diff --git a/app/lib/sidekiq_error_handler.rb b/app/lib/sidekiq_error_handler.rb new file mode 100644 index 000000000..23785cf05 --- /dev/null +++ b/app/lib/sidekiq_error_handler.rb @@ -0,0 +1,11 @@ +# frozen_string_literal: true + +class SidekiqErrorHandler + def call(*) + yield + rescue Mastodon::HostValidationError => e + Rails.logger.error "#{e.class}: #{e.message}" + Rails.logger.error e.backtrace.join("\n") + # Do not retry + end +end diff --git a/app/models/concerns/paginable.rb b/app/models/concerns/paginable.rb index 6061bf9bd..66695677e 100644 --- a/app/models/concerns/paginable.rb +++ b/app/models/concerns/paginable.rb @@ -10,5 +10,14 @@ module Paginable query = query.where(arel_table[:id].gt(since_id)) if since_id.present? query } + + # Differs from :paginate_by_max_id in that it gives the results immediately following min_id, + # whereas since_id gives the items with largest id, but with since_id as a cutoff. + # Results will be in ascending order by id. + scope :paginate_by_min_id, ->(limit, min_id = nil) { + query = reorder(arel_table[:id]).limit(limit) + query = query.where(arel_table[:id].gt(min_id)) if min_id.present? + query + } end end diff --git a/app/models/import.rb b/app/models/import.rb index ba88435bf..fdb4c6b80 100644 --- a/app/models/import.rb +++ b/app/models/import.rb @@ -26,7 +26,7 @@ class Import < ApplicationRecord validates :type, presence: true - has_attached_file :data, url: '/system/:hash.:extension', hash_secret: ENV['PAPERCLIP_SECRET'] + has_attached_file :data validates_attachment_content_type :data, content_type: FILE_TYPES validates_attachment_presence :data end diff --git a/app/models/report.rb b/app/models/report.rb index f55fb6d3e..dd123fc15 100644 --- a/app/models/report.rb +++ b/app/models/report.rb @@ -24,6 +24,10 @@ class Report < ApplicationRecord validates :comment, length: { maximum: 1000 } + def object_type + :flag + end + def statuses Status.where(id: status_ids).includes(:account, :media_attachments, :mentions) end diff --git a/app/models/user.rb b/app/models/user.rb index 197799294..b3e5f9352 100644 --- a/app/models/user.rb +++ b/app/models/user.rb @@ -44,7 +44,7 @@ class User < ApplicationRecord ACTIVE_DURATION = 14.days devise :two_factor_authenticatable, - otp_secret_encryption_key: ENV['OTP_SECRET'] + otp_secret_encryption_key: ENV.fetch('OTP_SECRET') devise :two_factor_backupable, otp_number_of_backup_codes: 10 @@ -52,7 +52,6 @@ class User < ApplicationRecord devise :registerable, :recoverable, :rememberable, :trackable, :validatable, :confirmable - devise :pam_authenticatable if Devise.pam_authentication devise :omniauthable belongs_to :account, inverse_of: :user @@ -117,6 +116,12 @@ class User < ApplicationRecord acc.destroy! unless save end + def ldap_setup(_attributes) + self.confirmed_at = Time.now.utc + self.admin = false + save! + end + def confirmed? confirmed_at.present? end @@ -247,17 +252,17 @@ class User < ApplicationRecord end def password_required? - return false if Devise.pam_authentication + return false if Devise.pam_authentication || Devise.ldap_authentication super end def send_reset_password_instructions - return false if encrypted_password.blank? && Devise.pam_authentication + return false if encrypted_password.blank? && (Devise.pam_authentication || Devise.ldap_authentication) super end def reset_password!(new_password, new_password_confirmation) - return false if encrypted_password.blank? && Devise.pam_authentication + return false if encrypted_password.blank? && (Devise.pam_authentication || Devise.ldap_authentication) super end @@ -280,6 +285,17 @@ class User < ApplicationRecord end end + def self.ldap_get_user(attributes = {}) + resource = joins(:account).find_by(accounts: { username: attributes[Devise.ldap_uid.to_sym].first }) + + if resource.blank? + resource = new(email: attributes[:mail].first, account_attributes: { username: attributes[Devise.ldap_uid.to_sym].first }) + resource.ldap_setup(attributes) + end + + resource + end + def self.authenticate_with_pam(attributes = {}) return nil unless Devise.pam_authentication super diff --git a/app/serializers/activitypub/flag_serializer.rb b/app/serializers/activitypub/flag_serializer.rb new file mode 100644 index 000000000..53e8f726d --- /dev/null +++ b/app/serializers/activitypub/flag_serializer.rb @@ -0,0 +1,27 @@ +# frozen_string_literal: true + +class ActivityPub::FlagSerializer < ActiveModel::Serializer + attributes :id, :type, :actor, :content + attribute :virtual_object, key: :object + + def id + # This is nil for now + ActivityPub::TagManager.instance.uri_for(object) + end + + def type + 'Flag' + end + + def actor + ActivityPub::TagManager.instance.uri_for(instance_options[:account] || object.account) + end + + def virtual_object + [ActivityPub::TagManager.instance.uri_for(object.target_account)] + object.statuses.map { |s| ActivityPub::TagManager.instance.uri_for(s) } + end + + def content + object.comment + end +end diff --git a/app/serializers/initial_state_serializer.rb b/app/serializers/initial_state_serializer.rb index 5434f1c56..1d17e2b0a 100644 --- a/app/serializers/initial_state_serializer.rb +++ b/app/serializers/initial_state_serializer.rb @@ -22,6 +22,7 @@ class InitialStateSerializer < ActiveModel::Serializer locale: I18n.locale, domain: Rails.configuration.x.local_domain, admin: object.admin&.id&.to_s, + search_enabled: Chewy.enabled?, } if object.current_account diff --git a/app/serializers/rest/instance_serializer.rb b/app/serializers/rest/instance_serializer.rb index 65907dad2..0168b18ea 100644 --- a/app/serializers/rest/instance_serializer.rb +++ b/app/serializers/rest/instance_serializer.rb @@ -4,7 +4,12 @@ class REST::InstanceSerializer < ActiveModel::Serializer include RoutingHelper attributes :uri, :title, :description, :email, - :version, :urls, :stats, :thumbnail, :max_toot_chars + :version, :urls, :stats, :thumbnail, :max_toot_chars, + :languages + + has_one :contact_account, serializer: REST::AccountSerializer + + delegate :contact_account, to: :instance_presenter def uri Rails.configuration.x.local_domain @@ -46,6 +51,10 @@ class REST::InstanceSerializer < ActiveModel::Serializer { streaming_api: Rails.configuration.x.streaming_api_base_url } end + def languages + [ENV.fetch('DEFAULT_LOCALE', I18n.default_locale)] + end + private def instance_presenter diff --git a/app/services/report_service.rb b/app/services/report_service.rb new file mode 100644 index 000000000..c06488a6d --- /dev/null +++ b/app/services/report_service.rb @@ -0,0 +1,54 @@ +# frozen_string_literal: true + +class ReportService < BaseService + def call(source_account, target_account, options = {}) + @source_account = source_account + @target_account = target_account + @status_ids = options.delete(:status_ids) || [] + @comment = options.delete(:comment) || '' + @options = options + + create_report! + notify_staff! + forward_to_origin! if !@target_account.local? && ActiveModel::Type::Boolean.new.cast(@options[:forward]) + + @report + end + + private + + def create_report! + @report = @source_account.reports.create!( + target_account: @target_account, + status_ids: @status_ids, + comment: @comment + ) + end + + def notify_staff! + User.staff.includes(:account).each do |u| + AdminMailer.new_report(u.account, @report).deliver_later + end + end + + def forward_to_origin! + ActivityPub::DeliveryWorker.perform_async( + payload, + some_local_account.id, + @target_account.inbox_url + ) + end + + def payload + Oj.dump(ActiveModelSerializers::SerializableResource.new( + @report, + serializer: ActivityPub::FlagSerializer, + adapter: ActivityPub::Adapter, + account: some_local_account + ).as_json) + end + + def some_local_account + @some_local_account ||= Account.local.where(suspended: false).first + end +end diff --git a/app/views/about/show.html.haml b/app/views/about/show.html.haml index bc357e522..37bfde887 100644 --- a/app/views/about/show.html.haml +++ b/app/views/about/show.html.haml @@ -7,51 +7,100 @@ .landing-page.alternative .container - .row - .column-4.hide-sm.show-xs.show-m - .landing-page__forms - .brand - = link_to root_url do - = image_tag asset_pack_path('logo_full.svg'), alt: 'Mastodon' - - .hide-xs + .grid + .column-0 + .brand + = link_to root_url do + = image_tag asset_pack_path('logo_full.svg'), alt: 'Mastodon' + + - if Setting.timeline_preview + .column-1 + .landing-page__forms + .brand + = link_to root_url do + = image_tag asset_pack_path('logo_full.svg'), alt: 'Mastodon' + = render 'forms' - .column-7.column-9-sm - .landing-page__hero - = image_tag @instance_presenter.hero&.file&.url || @instance_presenter.thumbnail&.file&.url || asset_pack_path('preview.jpg'), alt: @instance_presenter.site_title + - else + .column-1.non-preview + .landing-page__forms + .brand + = link_to root_url do + = image_tag asset_pack_path('logo_full.svg'), alt: 'Mastodon' - .landing-page__information - .landing-page__short-description + = render 'forms' + + - if Setting.timeline_preview + .column-2 + .landing-page__hero + = image_tag @instance_presenter.hero&.file&.url || @instance_presenter.thumbnail&.file&.url || asset_pack_path('preview.jpg'), alt: @instance_presenter.site_title + + .landing-page__information + .landing-page__short-description + .row + .landing-page__logo + = image_tag asset_pack_path('logo_transparent.svg'), alt: 'Mastodon' + + %h1 + = @instance_presenter.site_title + %small!= t 'about.hosted_on', domain: content_tag(:span, site_hostname) + + %p= @instance_presenter.site_description.html_safe.presence || t('about.generic_description', domain: site_hostname) + + .landing-page__call-to-action .row - .landing-page__logo.hide-xs - = image_tag asset_pack_path('logo_transparent.svg'), alt: 'Mastodon' + .row__information-board + .information-board__section + %span= t 'about.user_count_before' + %strong= number_with_delimiter @instance_presenter.user_count + %span= t 'about.user_count_after' + .information-board__section + %span= t 'about.status_count_before' + %strong= number_with_delimiter @instance_presenter.status_count + %span= t 'about.status_count_after' + .row__mascot + .landing-page__mascot + = image_tag asset_pack_path('elephant_ui_plane.svg') - %h1 - = @instance_presenter.site_title - %small!= t 'about.hosted_on', domain: content_tag(:span, site_hostname) + - else + .column-2.non-preview + .landing-page__hero + = image_tag @instance_presenter.hero&.file&.url || @instance_presenter.thumbnail&.file&.url || asset_pack_path('preview.jpg'), alt: @instance_presenter.site_title - %p= @instance_presenter.site_description.html_safe.presence || t('about.generic_description', domain: site_hostname) + .landing-page__information + .landing-page__short-description + .row + .landing-page__logo + = image_tag asset_pack_path('logo_transparent.svg'), alt: 'Mastodon' - .show-xs - .landing-page__forms - = render 'forms' - .landing-page__call-to-action.hide-xs - .row - .column-5 - .landing-page__mascot - = image_tag asset_pack_path('elephant_ui_plane.svg') - .column-5 - .information-board__section - %span= t 'about.user_count_before' - %strong= number_with_delimiter @instance_presenter.user_count - %span= t 'about.user_count_after' - .column-5 - .information-board__section - %span= t 'about.status_count_before' - %strong= number_with_delimiter @instance_presenter.status_count - %span= t 'about.status_count_after' - .landing-page__information + %h1 + = @instance_presenter.site_title + %small!= t 'about.hosted_on', domain: content_tag(:span, site_hostname) + + %p= @instance_presenter.site_description.html_safe.presence || t('about.generic_description', domain: site_hostname) + + .landing-page__call-to-action + .row + .row__information-board + .information-board__section + %span= t 'about.user_count_before' + %strong= number_with_delimiter @instance_presenter.user_count + %span= t 'about.user_count_after' + .information-board__section + %span= t 'about.status_count_before' + %strong= number_with_delimiter @instance_presenter.status_count + %span= t 'about.status_count_after' + .row__mascot + .landing-page__mascot + = image_tag asset_pack_path('elephant_ui_plane.svg') + + - if Setting.timeline_preview + .column-3 + #mastodon-timeline{ data: { props: Oj.dump(default_props) } } + + - if Setting.timeline_preview + .column-4.landing-page__information .landing-page__features %h3= t 'about.what_is_mastodon' %p= t 'about.about_mastodon_html' @@ -66,13 +115,18 @@ = link_to t('about.source_code'), @instance_presenter.source_url = " (#{@instance_presenter.version_number})" - .column-4.column-6-sm.column-flex - .show-sm.hide-xs - .landing-page__forms - .brand - = link_to root_url do - = image_tag asset_pack_path('logo_full.svg'), alt: 'Mastodon' + - else + .column-4.non-preview.landing-page__information + .landing-page__features + %h3= t 'about.what_is_mastodon' + %p= t 'about.about_mastodon_html' - = render 'forms' - - if Setting.timeline_preview - #mastodon-timeline{ data: { props: Oj.dump(default_props) } } + = render 'features' + + .landing-page__features__action + = link_to t('about.learn_more'), 'https://joinmastodon.org/', class: 'button button-alternative' + + .landing-page__footer + %p + = link_to t('about.source_code'), @instance_presenter.source_url + = " (#{@instance_presenter.version_number})" diff --git a/app/views/accounts/_follow_button.html.haml b/app/views/accounts/_follow_button.html.haml new file mode 100644 index 000000000..e476e0aff --- /dev/null +++ b/app/views/accounts/_follow_button.html.haml @@ -0,0 +1,23 @@ +- relationships ||= nil + +- unless account.memorial? || account.moved? + - if user_signed_in? + - requested = relationships ? relationships.requested[account.id].present? : current_account.requested?(account) + - following = relationships ? relationships.following[account.id].present? : current_account.following?(account) + + - if user_signed_in? && current_account.id != account.id && !requested + .controls + - if following + = link_to account_unfollow_path(account), data: { method: :post }, class: 'icon-button' do + = fa_icon 'user-times' + = t('accounts.unfollow') + - else + = link_to account_follow_path(account), data: { method: :post }, class: 'icon-button' do + = fa_icon 'user-plus' + = t('accounts.follow') + - elsif !user_signed_in? + .controls + .remote-follow + = link_to account_remote_follow_path(account), class: 'icon-button' do + = fa_icon 'user-plus' + = t('accounts.remote_follow') diff --git a/app/views/accounts/_grid_card.html.haml b/app/views/accounts/_grid_card.html.haml index 305eb2c44..95acbd581 100644 --- a/app/views/accounts/_grid_card.html.haml +++ b/app/views/accounts/_grid_card.html.haml @@ -1,9 +1,12 @@ .account-grid-card .account-grid-card__header{ style: "background-image: url(#{account.header.url(:original)})" } + = render 'accounts/follow_button', account: account, relationships: @relationships .account-grid-card__avatar .avatar= image_tag account.avatar.url(:original) .name = link_to TagManager.instance.url_for(account) do %span.display_name.emojify= display_name(account) - %span.username @#{account.acct} - %p.note.emojify= truncate(strip_tags(account.note), length: 150) + %span.username + @#{account.local? ? account.local_username_and_domain : account.acct} + = fa_icon('lock') if account.locked? + .account__header__content.p-note.emojify= Formatter.instance.simplified_format(account) diff --git a/app/views/accounts/_header.html.haml b/app/views/accounts/_header.html.haml index b0062752c..74251b923 100644 --- a/app/views/accounts/_header.html.haml +++ b/app/views/accounts/_header.html.haml @@ -1,24 +1,7 @@ - processed_bio = FrontmatterHandler.instance.process_bio Formatter.instance.simplified_format account .card.h-card.p-author{ style: "background-image: url(#{account.header.url(:original)})" } .card__illustration - - unless account.memorial? || account.moved? - - if user_signed_in? && current_account.id != account.id && !current_account.requested?(account) - .controls - - if current_account.following?(account) - = link_to account_unfollow_path(account), data: { method: :post }, class: 'icon-button' do - = fa_icon 'user-times' - = t('accounts.unfollow') - - else - = link_to account_follow_path(account), data: { method: :post }, class: 'icon-button' do - = fa_icon 'user-plus' - = t('accounts.follow') - - elsif !user_signed_in? - .controls - .remote-follow - = link_to account_remote_follow_path(account), class: 'icon-button' do - = fa_icon 'user-plus' - = t('accounts.remote_follow') - + = render 'accounts/follow_button', account: account .avatar= image_tag account.avatar.url(:original), class: 'u-photo' .card__bio diff --git a/app/views/accounts/show.html.haml b/app/views/accounts/show.html.haml index accad5f78..21c585dab 100644 --- a/app/views/accounts/show.html.haml +++ b/app/views/accounts/show.html.haml @@ -39,6 +39,9 @@ = render partial: 'stream_entries/status', collection: @statuses, as: :status - - if @statuses.size == 20 + - if @newer_url || @older_url .pagination - = link_to safe_join([t('pagination.next'), fa_icon('chevron-right')], ' '), @next_url, class: 'next', rel: 'next' + - if @older_url + = link_to safe_join([fa_icon('chevron-left'), t('pagination.older')], ' '), @older_url, class: 'older', rel: 'older' + - if @newer_url + = link_to safe_join([t('pagination.newer'), fa_icon('chevron-right')], ' '), @newer_url, class: 'newer', rel: 'newer' diff --git a/app/views/auth/passwords/edit.html.haml b/app/views/auth/passwords/edit.html.haml index 703c821c0..12880c227 100644 --- a/app/views/auth/passwords/edit.html.haml +++ b/app/views/auth/passwords/edit.html.haml @@ -4,7 +4,7 @@ = simple_form_for(resource, as: resource_name, url: password_path(resource_name), html: { method: :put }) do |f| = render 'shared/error_messages', object: resource - - if !use_pam? || resource.encrypted_password.present? + - if !use_seamless_external_login?? || resource.encrypted_password.present? = f.input :reset_password_token, as: :hidden = f.input :password, autofocus: true, placeholder: t('simple_form.labels.defaults.new_password'), input_html: { 'aria-label' => t('simple_form.labels.defaults.new_password'), :autocomplete => 'off' } @@ -13,6 +13,6 @@ .actions = f.button :button, t('auth.set_new_password'), type: :submit - else - = t('simple_form.labels.defaults.pam_account') + %p.hint= t('users.seamless_external_login') .form-footer= render 'auth/shared/links' diff --git a/app/views/auth/registrations/edit.html.haml b/app/views/auth/registrations/edit.html.haml index ca18caa56..fac702b38 100644 --- a/app/views/auth/registrations/edit.html.haml +++ b/app/views/auth/registrations/edit.html.haml @@ -4,7 +4,7 @@ = simple_form_for(resource, as: resource_name, url: registration_path(resource_name), html: { method: :put, class: 'auth_edit' }) do |f| = render 'shared/error_messages', object: resource - - if !use_pam? || resource.encrypted_password.present? + - if !use_seamless_external_login? || resource.encrypted_password.present? = f.input :email, placeholder: t('simple_form.labels.defaults.email'), input_html: { 'aria-label' => t('simple_form.labels.defaults.email') } = f.input :password, placeholder: t('simple_form.labels.defaults.new_password'), input_html: { 'aria-label' => t('simple_form.labels.defaults.new_password'), :autocomplete => 'off' } = f.input :password_confirmation, placeholder: t('simple_form.labels.defaults.confirm_new_password'), input_html: { 'aria-label' => t('simple_form.labels.defaults.confirm_new_password'), :autocomplete => 'off' } @@ -13,7 +13,7 @@ .actions = f.button :button, t('generic.save_changes'), type: :submit - else - = t('simple_form.labels.defaults.pam_account') + %p.hint= t('users.seamless_external_login') %hr/ diff --git a/app/views/auth/sessions/new.html.haml b/app/views/auth/sessions/new.html.haml index 1c3a0b6b4..0c9f9d5fe 100644 --- a/app/views/auth/sessions/new.html.haml +++ b/app/views/auth/sessions/new.html.haml @@ -5,7 +5,7 @@ = render partial: 'shared/og' = simple_form_for(resource, as: resource_name, url: session_path(resource_name)) do |f| - - if use_pam? + - if use_seamless_external_login? = f.input :email, autofocus: true, placeholder: t('simple_form.labels.defaults.username_or_email'), required: true, input_html: { 'aria-label' => t('simple_form.labels.defaults.username_or_email') } - else = f.input :email, autofocus: true, placeholder: t('simple_form.labels.defaults.email'), required: true, input_html: { 'aria-label' => t('simple_form.labels.defaults.email') } diff --git a/app/views/settings/preferences/show.html.haml b/app/views/settings/preferences/show.html.haml index 75dfa027e..102e4d200 100644 --- a/app/views/settings/preferences/show.html.haml +++ b/app/views/settings/preferences/show.html.haml @@ -4,7 +4,7 @@ = simple_form_for current_user, url: settings_preferences_path, html: { method: :put } do |f| = render 'shared/error_messages', object: current_user - .actions + .actions.actions--top = f.button :button, t('generic.save_changes'), type: :submit %h4= t 'preferences.languages' diff --git a/app/views/stream_entries/_detailed_status.html.haml b/app/views/stream_entries/_detailed_status.html.haml index 470bff218..e1122d5a2 100644 --- a/app/views/stream_entries/_detailed_status.html.haml +++ b/app/views/stream_entries/_detailed_status.html.haml @@ -22,7 +22,7 @@ - if !status.media_attachments.empty? - if status.media_attachments.first.video? - video = status.media_attachments.first - %div{ data: { component: 'Video', props: Oj.dump(src: video.file.url(:original), preview: video.file.url(:small), sensitive: status.sensitive? && !current_account&.user&.setting_display_sensitive_media, width: 670, height: 380, detailed: true) }} + %div{ data: { component: 'Video', props: Oj.dump(src: video.file.url(:original), preview: video.file.url(:small), sensitive: status.sensitive? && !current_account&.user&.setting_display_sensitive_media, width: 670, height: 380, detailed: true, inline: true) }} - else %div{ data: { component: 'MediaGallery', props: Oj.dump(height: 380, sensitive: status.sensitive? && !current_account&.user&.setting_display_sensitive_media, standalone: true, 'autoPlayGif': current_account&.user&.setting_auto_play_gif, 'reduceMotion': current_account&.user&.setting_reduce_motion, media: status.media_attachments.map { |a| ActiveModelSerializers::SerializableResource.new(a, serializer: REST::MediaAttachmentSerializer).as_json }) }} - elsif status.preview_cards.first diff --git a/app/views/stream_entries/_simple_status.html.haml b/app/views/stream_entries/_simple_status.html.haml index 03d416fd6..2ad1f5120 100644 --- a/app/views/stream_entries/_simple_status.html.haml +++ b/app/views/stream_entries/_simple_status.html.haml @@ -20,7 +20,6 @@ %a.status__content__spoiler-link{ href: '#' }= t('statuses.show_more') .e-content{ lang: status.language, style: "display: #{status.spoiler_text? ? 'none' : 'block'}; direction: #{rtl_status?(status) ? 'rtl' : 'ltr'}" }< = Formatter.instance.format(status, custom_emojify: true) - - unless status.media_attachments.empty? - if status.media_attachments.first.video? - video = status.media_attachments.first diff --git a/app/views/tags/_features.html.haml b/app/views/tags/_features.html.haml new file mode 100644 index 000000000..8fbc6b760 --- /dev/null +++ b/app/views/tags/_features.html.haml @@ -0,0 +1,25 @@ +.features-list + .features-list__row + .text + %h6= t 'about.features.real_conversation_title' + = t 'about.features.real_conversation_body' + .visual + = fa_icon 'fw comments' + .features-list__row + .text + %h6= t 'about.features.not_a_product_title' + = t 'about.features.not_a_product_body' + .visual + = fa_icon 'fw users' + .features-list__row + .text + %h6= t 'about.features.within_reach_title' + = t 'about.features.within_reach_body' + .visual + = fa_icon 'fw mobile' + .features-list__row + .text + %h6= t 'about.features.humane_approach_title' + = t 'about.features.humane_approach_body' + .visual + = fa_icon 'fw leaf' diff --git a/app/views/tags/show.html.haml b/app/views/tags/show.html.haml index 03f19e20a..000aa0c4d 100644 --- a/app/views/tags/show.html.haml +++ b/app/views/tags/show.html.haml @@ -5,48 +5,31 @@ %script#initial-state{ type: 'application/json' }!= json_escape(@initial_state_json) = render 'og' -.landing-page.tag-page +.landing-page.tag-page.alternative .features .container - #mastodon-timeline{ data: { props: Oj.dump(default_props.merge(hashtag: @tag.name)) } } + .grid + .column-1 + #mastodon-timeline{ data: { props: Oj.dump(default_props.merge(hashtag: @tag.name)) } } - .about-mastodon - .about-hashtag - .brand - = link_to root_url do - = image_tag asset_pack_path('logo_full.svg'), alt: 'Mastodon' + .column-2 + .about-mastodon + .about-hashtag.landing-page__information + .brand + = link_to root_url do + = image_tag asset_pack_path('logo_full.svg'), alt: 'Mastodon' - %p= t 'about.about_hashtag_html', hashtag: @tag.name + %p= t 'about.about_hashtag_html', hashtag: @tag.name - .cta - - if user_signed_in? - = link_to t('settings.back'), root_path, class: 'button button-secondary' - - else - = link_to t('auth.login'), new_user_session_path, class: 'button button-secondary' - = link_to t('about.learn_more'), about_path, class: 'button button-alternative' + .cta + - if user_signed_in? + = link_to t('settings.back'), root_path, class: 'button button-secondary' + - else + = link_to t('auth.login'), new_user_session_path, class: 'button button-secondary' + = link_to t('about.learn_more'), about_path, class: 'button button-alternative' - .features-list - .features-list__row - .text - %h6= t 'about.features.real_conversation_title' - = t 'about.features.real_conversation_body' - .visual - = fa_icon 'fw comments' - .features-list__row - .text - %h6= t 'about.features.not_a_product_title' - = t 'about.features.not_a_product_body' - .visual - = fa_icon 'fw users' - .features-list__row - .text - %h6= t 'about.features.within_reach_title' - = t 'about.features.within_reach_body' - .visual - = fa_icon 'fw mobile' - .features-list__row - .text - %h6= t 'about.features.humane_approach_title' - = t 'about.features.humane_approach_body' - .visual - = fa_icon 'fw leaf' + .landing-page__features.landing-page__information + %h3= t 'about.what_is_mastodon' + %p= t 'about.about_mastodon_html' + + = render 'features' |