diff options
Diffstat (limited to 'app')
198 files changed, 3023 insertions, 2373 deletions
diff --git a/app/controllers/admin/dashboard_controller.rb b/app/controllers/admin/dashboard_controller.rb index 22bbcec19..f23ed1508 100644 --- a/app/controllers/admin/dashboard_controller.rb +++ b/app/controllers/admin/dashboard_controller.rb @@ -29,6 +29,7 @@ module Admin @hidden_service = ENV['ALLOW_ACCESS_TO_HIDDEN_SERVICE'] == 'true' @trending_hashtags = TrendingTags.get(7) @profile_directory = Setting.profile_directory + @timeline_preview = Setting.timeline_preview end private diff --git a/app/controllers/admin/settings_controller.rb b/app/controllers/admin/settings_controller.rb index a64e98868..dc1c79b7f 100644 --- a/app/controllers/admin/settings_controller.rb +++ b/app/controllers/admin/settings_controller.rb @@ -2,94 +2,29 @@ module Admin class SettingsController < BaseController - ADMIN_SETTINGS = %w( - site_contact_username - site_contact_email - site_title - site_short_description - site_description - site_extended_description - site_terms - registrations_mode - closed_registrations_message - open_deletion - timeline_preview - show_staff_badge - bootstrap_timeline_accounts - flavour - skin - flavour_and_skin - thumbnail - hero - mascot - min_invite_role - activity_api_enabled - peers_api_enabled - show_known_fediverse_at_about_page - preview_sensitive_media - custom_css - profile_directory - hide_followers_count - ).freeze - - BOOLEAN_SETTINGS = %w( - open_deletion - timeline_preview - show_staff_badge - activity_api_enabled - peers_api_enabled - show_known_fediverse_at_about_page - preview_sensitive_media - profile_directory - hide_followers_count - ).freeze - - UPLOAD_SETTINGS = %w( - thumbnail - hero - mascot - ).freeze - def edit authorize :settings, :show? + @admin_settings = Form::AdminSettings.new end def update authorize :settings, :update? - settings = settings_params - flavours_and_skin = settings.delete('flavour_and_skin') - if flavours_and_skin - settings['flavour'], settings['skin'] = flavours_and_skin.split('/', 2) - end + @admin_settings = Form::AdminSettings.new(settings_params) - settings.each do |key, value| - if UPLOAD_SETTINGS.include?(key) - upload = SiteUpload.where(var: key).first_or_initialize(var: key) - upload.update(file: value) - else - setting = Setting.where(var: key).first_or_initialize(var: key) - setting.update(value: value_for_update(key, value)) - end + if @admin_settings.save + flash[:notice] = I18n.t('generic.changes_saved_msg') + redirect_to edit_admin_settings_path + else + render :edit end - - flash[:notice] = I18n.t('generic.changes_saved_msg') - redirect_to edit_admin_settings_path end private def settings_params - params.require(:form_admin_settings).permit(ADMIN_SETTINGS) - end - - def value_for_update(key, value) - if BOOLEAN_SETTINGS.include?(key) - value == '1' - else - value - end + params.require(:form_admin_settings).permit(*Form::AdminSettings::KEYS) end end end diff --git a/app/controllers/api/v1/accounts/identity_proofs_controller.rb b/app/controllers/api/v1/accounts/identity_proofs_controller.rb new file mode 100644 index 000000000..bea51ae11 --- /dev/null +++ b/app/controllers/api/v1/accounts/identity_proofs_controller.rb @@ -0,0 +1,19 @@ +# frozen_string_literal: true + +class Api::V1::Accounts::IdentityProofsController < Api::BaseController + before_action :require_user! + before_action :set_account + + respond_to :json + + def index + @proofs = @account.identity_proofs.active + render json: @proofs, each_serializer: REST::IdentityProofSerializer + end + + private + + def set_account + @account = Account.find(params[:account_id]) + end +end diff --git a/app/controllers/concerns/account_controller_concern.rb b/app/controllers/concerns/account_controller_concern.rb index 8817fd7de..4f28941ae 100644 --- a/app/controllers/concerns/account_controller_concern.rb +++ b/app/controllers/concerns/account_controller_concern.rb @@ -69,6 +69,10 @@ module AccountControllerConcern end def check_account_suspension - gone if @account.suspended? + if @account.suspended? + skip_session! + expires_in(3.minutes, public: true) + gone + end end end diff --git a/app/controllers/directories_controller.rb b/app/controllers/directories_controller.rb index 70013d760..59247a21f 100644 --- a/app/controllers/directories_controller.rb +++ b/app/controllers/directories_controller.rb @@ -37,7 +37,7 @@ class DirectoriesController < ApplicationController end def set_accounts - @accounts = Account.discoverable.page(params[:page]).per(40).tap do |query| + @accounts = Account.discoverable.by_recent_status.page(params[:page]).per(40).tap do |query| query.merge!(Account.tagged_with(@tag.id)) if @tag end end diff --git a/app/controllers/relationships_controller.rb b/app/controllers/relationships_controller.rb index a0b9c77df..c87a0cf13 100644 --- a/app/controllers/relationships_controller.rb +++ b/app/controllers/relationships_controller.rb @@ -32,13 +32,14 @@ class RelationshipsController < ApplicationController def relationships_scope scope = begin if following_relationship? - current_account.following.joins(:account_stat) + current_account.following.eager_load(:account_stat).reorder(nil) else - current_account.followers.joins(:account_stat) + current_account.followers.eager_load(:account_stat).reorder(nil) end end - scope.merge!(Follow.recent) + scope.merge!(Follow.recent) if params[:order].blank? || params[:order] == 'recent' + scope.merge!(Account.by_recent_status) if params[:order] == 'active' scope.merge!(mutual_relationship_scope) if mutual_relationship? scope.merge!(moved_account_scope) if params[:status] == 'moved' scope.merge!(primary_account_scope) if params[:status] == 'primary' @@ -85,7 +86,7 @@ class RelationshipsController < ApplicationController end def current_params - params.slice(:page, :status, :relationship, :by_domain, :activity).permit(:page, :status, :relationship, :by_domain, :activity) + params.slice(:page, :status, :relationship, :by_domain, :activity, :order).permit(:page, :status, :relationship, :by_domain, :activity, :order) end def action_from_button diff --git a/app/controllers/settings/identity_proofs_controller.rb b/app/controllers/settings/identity_proofs_controller.rb index 4a3b89a5e..8f857fdcc 100644 --- a/app/controllers/settings/identity_proofs_controller.rb +++ b/app/controllers/settings/identity_proofs_controller.rb @@ -18,7 +18,12 @@ class Settings::IdentityProofsController < Settings::BaseController provider_username: params[:provider_username] ) - render layout: 'auth' + if current_account.username == params[:username] + render layout: 'auth' + else + flash[:alert] = I18n.t('identity_proofs.errors.wrong_user', proving: params[:username], current: current_account.username) + redirect_to settings_identity_proofs_path + end end def create @@ -26,6 +31,7 @@ class Settings::IdentityProofsController < Settings::BaseController @proof.token = resource_params[:token] if @proof.save + PostStatusService.new.call(current_user.account, text: post_params[:status_text]) if publish_proof? redirect_to @proof.on_success_path(params[:user_agent]) else flash[:alert] = I18n.t('identity_proofs.errors.failed', provider: @proof.provider.capitalize) @@ -36,10 +42,22 @@ class Settings::IdentityProofsController < Settings::BaseController private def check_required_params - redirect_to settings_identity_proofs_path unless [:provider, :provider_username, :token].all? { |k| params[k].present? } + redirect_to settings_identity_proofs_path unless [:provider, :provider_username, :username, :token].all? { |k| params[k].present? } end def resource_params params.require(:account_identity_proof).permit(:provider, :provider_username, :token) end + + def publish_proof? + ActiveModel::Type::Boolean.new.cast(post_params[:post_status]) + end + + def post_params + params.require(:account_identity_proof).permit(:post_status, :status_text) + end + + def set_body_classes + @body_classes = '' + end end diff --git a/app/helpers/admin/dashboard_helper.rb b/app/helpers/admin/dashboard_helper.rb new file mode 100644 index 000000000..4ee2cdef4 --- /dev/null +++ b/app/helpers/admin/dashboard_helper.rb @@ -0,0 +1,10 @@ +# frozen_string_literal: true + +module Admin::DashboardHelper + def feature_hint(feature, enabled) + indicator = safe_join([enabled ? t('simple_form.yes') : t('simple_form.no'), fa_icon('power-off fw')], ' ') + class_names = enabled ? 'pull-right positive-hint' : 'pull-right neutral-hint' + + safe_join([feature, content_tag(:span, indicator, class: class_names)]) + end +end diff --git a/app/helpers/admin/filter_helper.rb b/app/helpers/admin/filter_helper.rb index 4fd36ef42..0bda25974 100644 --- a/app/helpers/admin/filter_helper.rb +++ b/app/helpers/admin/filter_helper.rb @@ -7,7 +7,7 @@ module Admin::FilterHelper CUSTOM_EMOJI_FILTERS = %i(local remote by_domain shortcode).freeze TAGS_FILTERS = %i(hidden).freeze INSTANCES_FILTERS = %i(limited by_domain).freeze - FOLLOWERS_FILTERS = %i(relationship status by_domain activity).freeze + FOLLOWERS_FILTERS = %i(relationship status by_domain activity order).freeze FILTERS = ACCOUNT_FILTERS + REPORT_FILTERS + INVITE_FILTER + CUSTOM_EMOJI_FILTERS + TAGS_FILTERS + INSTANCES_FILTERS + FOLLOWERS_FILTERS diff --git a/app/helpers/stream_entries_helper.rb b/app/helpers/stream_entries_helper.rb index 1e49e4fc6..5ad2c438e 100644 --- a/app/helpers/stream_entries_helper.rb +++ b/app/helpers/stream_entries_helper.rb @@ -111,8 +111,8 @@ module StreamEntriesHelper end def poll_summary(status) - return unless status.poll - status.poll.options.map { |o| "[ ] #{o}" }.join("\n") + return unless status.preloadable_poll + status.preloadable_poll.options.map { |o| "[ ] #{o}" }.join("\n") end def status_description(status) diff --git a/app/javascript/flavours/glitch/actions/identity_proofs.js b/app/javascript/flavours/glitch/actions/identity_proofs.js new file mode 100644 index 000000000..a7241da20 --- /dev/null +++ b/app/javascript/flavours/glitch/actions/identity_proofs.js @@ -0,0 +1,30 @@ +import api from 'flavours/glitch/util/api'; + +export const IDENTITY_PROOFS_ACCOUNT_FETCH_REQUEST = 'IDENTITY_PROOFS_ACCOUNT_FETCH_REQUEST'; +export const IDENTITY_PROOFS_ACCOUNT_FETCH_SUCCESS = 'IDENTITY_PROOFS_ACCOUNT_FETCH_SUCCESS'; +export const IDENTITY_PROOFS_ACCOUNT_FETCH_FAIL = 'IDENTITY_PROOFS_ACCOUNT_FETCH_FAIL'; + +export const fetchAccountIdentityProofs = accountId => (dispatch, getState) => { + dispatch(fetchAccountIdentityProofsRequest(accountId)); + + api(getState).get(`/api/v1/accounts/${accountId}/identity_proofs`) + .then(({ data }) => dispatch(fetchAccountIdentityProofsSuccess(accountId, data))) + .catch(err => dispatch(fetchAccountIdentityProofsFail(accountId, err))); +}; + +export const fetchAccountIdentityProofsRequest = id => ({ + type: IDENTITY_PROOFS_ACCOUNT_FETCH_REQUEST, + id, +}); + +export const fetchAccountIdentityProofsSuccess = (accountId, identity_proofs) => ({ + type: IDENTITY_PROOFS_ACCOUNT_FETCH_SUCCESS, + accountId, + identity_proofs, +}); + +export const fetchAccountIdentityProofsFail = (accountId, err) => ({ + type: IDENTITY_PROOFS_ACCOUNT_FETCH_FAIL, + accountId, + err, +}); diff --git a/app/javascript/flavours/glitch/actions/search.js b/app/javascript/flavours/glitch/actions/search.js index bc094eed5..b2d24e10b 100644 --- a/app/javascript/flavours/glitch/actions/search.js +++ b/app/javascript/flavours/glitch/actions/search.js @@ -37,6 +37,7 @@ export function submitSearch() { params: { q: value, resolve: true, + limit: 10, }, }).then(response => { if (response.data.accounts) { diff --git a/app/javascript/flavours/glitch/components/status_action_bar.js b/app/javascript/flavours/glitch/components/status_action_bar.js index 1d3130604..e0cc652d2 100644 --- a/app/javascript/flavours/glitch/components/status_action_bar.js +++ b/app/javascript/flavours/glitch/components/status_action_bar.js @@ -146,7 +146,7 @@ export default class StatusActionBar extends ImmutablePureComponent { } handleBlockClick = () => { - this.props.onBlock(this.props.status.get('account')); + this.props.onBlock(this.props.status); } handleOpen = () => { diff --git a/app/javascript/flavours/glitch/components/status_content.js b/app/javascript/flavours/glitch/components/status_content.js index 98a34ebaf..a62844185 100644 --- a/app/javascript/flavours/glitch/components/status_content.js +++ b/app/javascript/flavours/glitch/components/status_content.js @@ -198,7 +198,7 @@ export default class StatusContent extends React.PureComponent { <p style={{ marginBottom: hidden && status.get('mentions').isEmpty() ? '0px' : null }} > - <span dangerouslySetInnerHTML={spoilerContent} /> + <span dangerouslySetInnerHTML={spoilerContent} lang={status.get('language')} /> {' '} <button tabIndex='0' className='status__content__spoiler-link' onClick={this.handleSpoilerClick}> {toggleText} @@ -213,6 +213,7 @@ export default class StatusContent extends React.PureComponent { style={directionStyle} tabIndex={!hidden ? 0 : null} dangerouslySetInnerHTML={content} + lang={status.get('language')} /> {media} </div> @@ -231,6 +232,7 @@ export default class StatusContent extends React.PureComponent { <div ref={this.setRef} dangerouslySetInnerHTML={content} + lang={status.get('language')} tabIndex='0' /> {media} @@ -243,7 +245,7 @@ export default class StatusContent extends React.PureComponent { style={directionStyle} tabIndex='0' > - <div ref={this.setRef} dangerouslySetInnerHTML={content} tabIndex='0' /> + <div ref={this.setRef} dangerouslySetInnerHTML={content} lang={status.get('language')} tabIndex='0' /> {media} </div> ); diff --git a/app/javascript/flavours/glitch/containers/status_container.js b/app/javascript/flavours/glitch/containers/status_container.js index f783878b0..60636feb4 100644 --- a/app/javascript/flavours/glitch/containers/status_container.js +++ b/app/javascript/flavours/glitch/containers/status_container.js @@ -35,6 +35,7 @@ const messages = defineMessages({ blockConfirm: { id: 'confirmations.block.confirm', defaultMessage: 'Block' }, replyConfirm: { id: 'confirmations.reply.confirm', defaultMessage: 'Reply' }, replyMessage: { id: 'confirmations.reply.message', defaultMessage: 'Replying now will overwrite the message you are currently composing. Are you sure you want to proceed?' }, + blockAndReport: { id: 'confirmations.block.block_and_report', defaultMessage: 'Block & Report' }, }); const makeMapStateToProps = () => { @@ -169,11 +170,17 @@ const mapDispatchToProps = (dispatch, { intl }) => ({ dispatch(openModal('VIDEO', { media, time })); }, - onBlock (account) { + onBlock (status) { + const account = status.get('account'); dispatch(openModal('CONFIRM', { message: <FormattedMessage id='confirmations.block.message' defaultMessage='Are you sure you want to block {name}?' values={{ name: <strong>@{account.get('acct')}</strong> }} />, confirm: intl.formatMessage(messages.blockConfirm), onConfirm: () => dispatch(blockAccount(account.get('id'))), + secondary: intl.formatMessage(messages.blockAndReport), + onSecondary: () => { + dispatch(blockAccount(account.get('id'))); + dispatch(initReport(account, status)); + }, })); }, diff --git a/app/javascript/flavours/glitch/features/account/components/action_bar.js b/app/javascript/flavours/glitch/features/account/components/action_bar.js index fdacb7298..a2c00c1c2 100644 --- a/app/javascript/flavours/glitch/features/account/components/action_bar.js +++ b/app/javascript/flavours/glitch/features/account/components/action_bar.js @@ -3,58 +3,19 @@ import ImmutablePropTypes from 'react-immutable-proptypes'; import PropTypes from 'prop-types'; import DropdownMenuContainer from 'flavours/glitch/containers/dropdown_menu_container'; import { NavLink } from 'react-router-dom'; -import { defineMessages, injectIntl, FormattedMessage, FormattedNumber } from 'react-intl'; +import { injectIntl, FormattedMessage, FormattedNumber } from 'react-intl'; import { me, isStaff } from 'flavours/glitch/util/initial_state'; import { profileLink, accountAdminLink } from 'flavours/glitch/util/backend_links'; - -const messages = defineMessages({ - mention: { id: 'account.mention', defaultMessage: 'Mention @{name}' }, - direct: { id: 'account.direct', defaultMessage: 'Direct message @{name}' }, - edit_profile: { id: 'account.edit_profile', defaultMessage: 'Edit profile' }, - unblock: { id: 'account.unblock', defaultMessage: 'Unblock @{name}' }, - unfollow: { id: 'account.unfollow', defaultMessage: 'Unfollow' }, - unmute: { id: 'account.unmute', defaultMessage: 'Unmute @{name}' }, - block: { id: 'account.block', defaultMessage: 'Block @{name}' }, - mute: { id: 'account.mute', defaultMessage: 'Mute @{name}' }, - follow: { id: 'account.follow', defaultMessage: 'Follow' }, - report: { id: 'account.report', defaultMessage: 'Report @{name}' }, - share: { id: 'account.share', defaultMessage: 'Share @{name}\'s profile' }, - media: { id: 'account.media', defaultMessage: 'Media' }, - blockDomain: { id: 'account.block_domain', defaultMessage: 'Hide everything from {domain}' }, - unblockDomain: { id: 'account.unblock_domain', defaultMessage: 'Unhide {domain}' }, - hideReblogs: { id: 'account.hide_reblogs', defaultMessage: 'Hide boosts from @{name}' }, - showReblogs: { id: 'account.show_reblogs', defaultMessage: 'Show boosts from @{name}' }, - endorse: { id: 'account.endorse', defaultMessage: 'Feature on profile' }, - unendorse: { id: 'account.unendorse', defaultMessage: 'Don\'t feature on profile' }, - add_or_remove_from_list: { id: 'account.add_or_remove_from_list', defaultMessage: 'Add or Remove from lists' }, - admin_account: { id: 'status.admin_account', defaultMessage: 'Open moderation interface for @{name}' }, -}); +import Icon from 'flavours/glitch/components/icon'; @injectIntl export default class ActionBar extends React.PureComponent { static propTypes = { account: ImmutablePropTypes.map.isRequired, - onFollow: PropTypes.func, - onBlock: PropTypes.func.isRequired, - onMention: PropTypes.func.isRequired, - onDirect: PropTypes.func.isRequired, - onReblogToggle: PropTypes.func.isRequired, - onReport: PropTypes.func.isRequired, - onMute: PropTypes.func.isRequired, - onBlockDomain: PropTypes.func.isRequired, - onUnblockDomain: PropTypes.func.isRequired, - onEndorseToggle: PropTypes.func.isRequired, - onAddToList: PropTypes.func.isRequired, intl: PropTypes.object.isRequired, }; - handleShare = () => { - navigator.share({ - url: this.props.account.get('url'), - }); - } - isStatusesPageActive = (match, location) => { if (!match) { return false; @@ -65,56 +26,12 @@ export default class ActionBar extends React.PureComponent { render () { const { account, intl } = this.props; - let menu = []; let extraInfo = ''; - menu.push({ text: intl.formatMessage(messages.mention, { name: account.get('username') }), action: this.props.onMention }); - menu.push({ text: intl.formatMessage(messages.direct, { name: account.get('username') }), action: this.props.onDirect }); - - if ('share' in navigator) { - menu.push({ text: intl.formatMessage(messages.share, { name: account.get('username') }), action: this.handleShare }); - } - - menu.push(null); - - if (account.get('id') === me) { - if (profileLink !== undefined) { - menu.push({ text: intl.formatMessage(messages.edit_profile), href: profileLink }); - } - } else { - if (account.getIn(['relationship', 'following'])) { - if (account.getIn(['relationship', 'showing_reblogs'])) { - menu.push({ text: intl.formatMessage(messages.hideReblogs, { name: account.get('username') }), action: this.props.onReblogToggle }); - } else { - menu.push({ text: intl.formatMessage(messages.showReblogs, { name: account.get('username') }), action: this.props.onReblogToggle }); - } - - menu.push({ text: intl.formatMessage(account.getIn(['relationship', 'endorsed']) ? messages.unendorse : messages.endorse), action: this.props.onEndorseToggle }); - menu.push({ text: intl.formatMessage(messages.add_or_remove_from_list), action: this.props.onAddToList }); - menu.push(null); - } - - if (account.getIn(['relationship', 'muting'])) { - menu.push({ text: intl.formatMessage(messages.unmute, { name: account.get('username') }), action: this.props.onMute }); - } else { - menu.push({ text: intl.formatMessage(messages.mute, { name: account.get('username') }), action: this.props.onMute }); - } - - if (account.getIn(['relationship', 'blocking'])) { - menu.push({ text: intl.formatMessage(messages.unblock, { name: account.get('username') }), action: this.props.onBlock }); - } else { - menu.push({ text: intl.formatMessage(messages.block, { name: account.get('username') }), action: this.props.onBlock }); - } - - menu.push({ text: intl.formatMessage(messages.report, { name: account.get('username') }), action: this.props.onReport }); - } - if (account.get('acct') !== account.get('username')) { - const domain = account.get('acct').split('@')[1]; - extraInfo = ( <div className='account__disclaimer'> - <FormattedMessage + <Icon icon='info-circle' fixedWidth /> <FormattedMessage id='account.disclaimer_full' defaultMessage="Information below may reflect the user's profile incompletely." /> @@ -124,22 +41,6 @@ export default class ActionBar extends React.PureComponent { </a> </div> ); - - menu.push(null); - - if (account.getIn(['relationship', 'domain_blocking'])) { - menu.push({ text: intl.formatMessage(messages.unblockDomain, { domain }), action: this.props.onUnblockDomain }); - } else { - menu.push({ text: intl.formatMessage(messages.blockDomain, { domain }), action: this.props.onBlockDomain }); - } - } - - if (account.get('id') !== me && isStaff && (accountAdminLink !== undefined)) { - menu.push(null); - menu.push({ - text: intl.formatMessage(messages.admin_account, { name: account.get('username') }), - href: accountAdminLink(account.get('id')), - }); } return ( @@ -147,10 +48,6 @@ export default class ActionBar extends React.PureComponent { {extraInfo} <div className='account__action-bar'> - <div className='account__action-bar-dropdown'> - <DropdownMenuContainer items={menu} icon='bars' size={24} direction='right' /> - </div> - <div className='account__action-bar-links'> <NavLink isActive={this.isStatusesPageActive} activeClassName='active' className='account__action-bar__tab' to={`/accounts/${account.get('id')}`}> <FormattedMessage id='account.posts' defaultMessage='Posts' /> diff --git a/app/javascript/flavours/glitch/features/account/components/header.js b/app/javascript/flavours/glitch/features/account/components/header.js index 96696c2a5..13f7741c8 100644 --- a/app/javascript/flavours/glitch/features/account/components/header.js +++ b/app/javascript/flavours/glitch/features/account/components/header.js @@ -3,12 +3,14 @@ import ImmutablePropTypes from 'react-immutable-proptypes'; import PropTypes from 'prop-types'; import { defineMessages, injectIntl, FormattedMessage } from 'react-intl'; import ImmutablePureComponent from 'react-immutable-pure-component'; - -import Avatar from 'flavours/glitch/components/avatar'; -import IconButton from 'flavours/glitch/components/icon_button'; - -import { autoPlayGif, me } from 'flavours/glitch/util/initial_state'; +import { autoPlayGif, me, isStaff } from 'flavours/glitch/util/initial_state'; import classNames from 'classnames'; +import Icon from 'flavours/glitch/components/icon'; +import Avatar from 'flavours/glitch/components/avatar'; +import Button from 'flavours/glitch/components/button'; +import { shortNumberFormat } from 'flavours/glitch/util/numbers'; +import { NavLink } from 'react-router-dom'; +import DropdownMenuContainer from 'flavours/glitch/containers/dropdown_menu_container'; const messages = defineMessages({ unfollow: { id: 'account.unfollow', defaultMessage: 'Unfollow' }, @@ -16,7 +18,34 @@ const messages = defineMessages({ requested: { id: 'account.requested', defaultMessage: 'Awaiting approval. Click to cancel follow request' }, unblock: { id: 'account.unblock', defaultMessage: 'Unblock @{name}' }, edit_profile: { id: 'account.edit_profile', defaultMessage: 'Edit profile' }, - link_verified_on: { id: 'account.link_verified_on', defaultMessage: 'Ownership of this link was checked on {date}' }, + linkVerifiedOn: { id: 'account.link_verified_on', defaultMessage: 'Ownership of this link was checked on {date}' }, + account_locked: { id: 'account.locked_info', defaultMessage: 'This account privacy status is set to locked. The owner manually reviews who can follow them.' }, + mention: { id: 'account.mention', defaultMessage: 'Mention @{name}' }, + direct: { id: 'account.direct', defaultMessage: 'Direct message @{name}' }, + edit_profile: { id: 'account.edit_profile', defaultMessage: 'Edit profile' }, + unblock: { id: 'account.unblock', defaultMessage: 'Unblock @{name}' }, + unmute: { id: 'account.unmute', defaultMessage: 'Unmute @{name}' }, + block: { id: 'account.block', defaultMessage: 'Block @{name}' }, + mute: { id: 'account.mute', defaultMessage: 'Mute @{name}' }, + report: { id: 'account.report', defaultMessage: 'Report @{name}' }, + share: { id: 'account.share', defaultMessage: 'Share @{name}\'s profile' }, + media: { id: 'account.media', defaultMessage: 'Media' }, + blockDomain: { id: 'account.block_domain', defaultMessage: 'Hide everything from {domain}' }, + unblockDomain: { id: 'account.unblock_domain', defaultMessage: 'Unhide {domain}' }, + hideReblogs: { id: 'account.hide_reblogs', defaultMessage: 'Hide boosts from @{name}' }, + showReblogs: { id: 'account.show_reblogs', defaultMessage: 'Show boosts from @{name}' }, + pins: { id: 'navigation_bar.pins', defaultMessage: 'Pinned toots' }, + preferences: { id: 'navigation_bar.preferences', defaultMessage: 'Preferences' }, + follow_requests: { id: 'navigation_bar.follow_requests', defaultMessage: 'Follow requests' }, + favourites: { id: 'navigation_bar.favourites', defaultMessage: 'Favourites' }, + lists: { id: 'navigation_bar.lists', defaultMessage: 'Lists' }, + blocks: { id: 'navigation_bar.blocks', defaultMessage: 'Blocked users' }, + domain_blocks: { id: 'navigation_bar.domain_blocks', defaultMessage: 'Hidden domains' }, + mutes: { id: 'navigation_bar.mutes', defaultMessage: 'Muted users' }, + endorse: { id: 'account.endorse', defaultMessage: 'Feature on profile' }, + unendorse: { id: 'account.unendorse', defaultMessage: 'Don\'t feature on profile' }, + add_or_remove_from_list: { id: 'account.add_or_remove_from_list', defaultMessage: 'Add or Remove from lists' }, + admin_account: { id: 'status.admin_account', defaultMessage: 'Open moderation interface for @{name}' }, }); const dateFormatOptions = { @@ -28,14 +57,16 @@ const dateFormatOptions = { minute: '2-digit', }; -@injectIntl -export default class Header extends ImmutablePureComponent { +export default @injectIntl +class Header extends ImmutablePureComponent { static propTypes = { account: ImmutablePropTypes.map, + identity_props: ImmutablePropTypes.list, onFollow: PropTypes.func.isRequired, onBlock: PropTypes.func.isRequired, intl: PropTypes.object.isRequired, + domain: PropTypes.string.isRequired, }; openEditProfile = () => { @@ -43,109 +74,191 @@ export default class Header extends ImmutablePureComponent { } render () { - const { account, intl } = this.props; + const { account, intl, domain, identity_proofs } = this.props; if (!account) { return null; } - let displayName = account.get('display_name_html'); - let fields = account.get('fields'); - let badge = account.get('bot') ? (<div className='roles'><div className='account-role bot'><FormattedMessage id='account.badges.bot' defaultMessage='Bot' /></div></div>) : null; - - let info = ''; - let mutingInfo = ''; + let info = []; let actionBtn = ''; + let lockedIcon = ''; + let menu = []; if (me !== account.get('id') && account.getIn(['relationship', 'followed_by'])) { - info = <span className='account--follows-info'><FormattedMessage id='account.follows_you' defaultMessage='Follows you' /></span>; + info.push(<span className='relationship-tag'><FormattedMessage id='account.follows_you' defaultMessage='Follows you' /></span>); } else if (me !== account.get('id') && account.getIn(['relationship', 'blocking'])) { - info = <span className='account--follows-info'><FormattedMessage id='account.blocked' defaultMessage='Blocked' /></span>; + info.push(<span className='relationship-tag'><FormattedMessage id='account.blocked' defaultMessage='Blocked' /></span>); } if (me !== account.get('id') && account.getIn(['relationship', 'muting'])) { - mutingInfo = <span className='account--muting-info'><FormattedMessage id='account.muted' defaultMessage='Muted' /></span>; + info.push(<span className='relationship-tag'><FormattedMessage id='account.muted' defaultMessage='Muted' /></span>); } else if (me !== account.get('id') && account.getIn(['relationship', 'domain_blocking'])) { - mutingInfo = <span className='account--muting-info'><FormattedMessage id='account.domain_blocked' defaultMessage='Domain hidden' /></span>; + info.push(<span className='relationship-tag'><FormattedMessage id='account.domain_blocked' defaultMessage='Domain hidden' /></span>); } if (me !== account.get('id')) { if (!account.get('relationship')) { // Wait until the relationship is loaded actionBtn = ''; } else if (account.getIn(['relationship', 'requested'])) { - actionBtn = ( - <div className='account--action-button'> - <IconButton size={26} active icon='hourglass' title={intl.formatMessage(messages.requested)} onClick={this.props.onFollow} /> - </div> - ); + actionBtn = <Button className='logo-button' text={intl.formatMessage(messages.requested)} onClick={this.props.onFollow} />; } else if (!account.getIn(['relationship', 'blocking'])) { - actionBtn = ( - <div className='account--action-button'> - <IconButton size={26} icon={account.getIn(['relationship', 'following']) ? 'user-times' : 'user-plus'} active={account.getIn(['relationship', 'following'])} title={intl.formatMessage(account.getIn(['relationship', 'following']) ? messages.unfollow : messages.follow)} onClick={this.props.onFollow} /> - </div> - ); + actionBtn = <Button className={classNames('logo-button', { 'button--destructive': account.getIn(['relationship', 'following']) })} text={intl.formatMessage(account.getIn(['relationship', 'following']) ? messages.unfollow : messages.follow)} onClick={this.props.onFollow} />; } else if (account.getIn(['relationship', 'blocking'])) { - actionBtn = ( - <div className='account--action-button'> - <IconButton size={26} icon='unlock' title={intl.formatMessage(messages.unblock, { name: account.get('username') })} onClick={this.props.onBlock} /> - </div> - ); + actionBtn = <Button className='logo-button' text={intl.formatMessage(messages.unblock, { name: account.get('username') })} onClick={this.props.onBlock} />; } } else { - actionBtn = ( - <div className='account--action-button'> - <IconButton size={26} icon='pencil' title={intl.formatMessage(messages.edit_profile)} onClick={this.openEditProfile} /> - </div> - ); + actionBtn = <Button className='logo-button' text={intl.formatMessage(messages.edit_profile)} onClick={this.openEditProfile} />; } if (account.get('moved') && !account.getIn(['relationship', 'following'])) { actionBtn = ''; } - const content = { __html: account.get('note_emojified') }; + if (account.get('locked')) { + lockedIcon = <Icon icon='lock' title={intl.formatMessage(messages.account_locked)} />; + } - return ( - <div className='account__header__wrapper'> - <div className={classNames('account__header', { inactive: !!account.get('moved') })} style={{ backgroundImage: `url(${autoPlayGif ? account.get('header') : account.get('header_static')})` }}> - <div> - <a - href={account.get('url')} - className='account__header__avatar' - role='presentation' - target='_blank' - rel='noopener' - > - <Avatar account={account} size={90} /> - </a> + if (account.get('id') !== me) { + menu.push({ text: intl.formatMessage(messages.mention, { name: account.get('username') }), action: this.props.onMention }); + menu.push({ text: intl.formatMessage(messages.direct, { name: account.get('username') }), action: this.props.onDirect }); + menu.push(null); + } + + if ('share' in navigator) { + menu.push({ text: intl.formatMessage(messages.share, { name: account.get('username') }), action: this.handleShare }); + menu.push(null); + } + + if (account.get('id') === me) { + menu.push({ text: intl.formatMessage(messages.edit_profile), href: '/settings/profile' }); + menu.push({ text: intl.formatMessage(messages.preferences), href: '/settings/preferences' }); + menu.push({ text: intl.formatMessage(messages.pins), to: '/pinned' }); + menu.push(null); + menu.push({ text: intl.formatMessage(messages.follow_requests), to: '/follow_requests' }); + menu.push({ text: intl.formatMessage(messages.favourites), to: '/favourites' }); + menu.push({ text: intl.formatMessage(messages.lists), to: '/lists' }); + menu.push(null); + menu.push({ text: intl.formatMessage(messages.mutes), to: '/mutes' }); + menu.push({ text: intl.formatMessage(messages.blocks), to: '/blocks' }); + menu.push({ text: intl.formatMessage(messages.domain_blocks), to: '/domain_blocks' }); + } else { + if (account.getIn(['relationship', 'following'])) { + if (account.getIn(['relationship', 'showing_reblogs'])) { + menu.push({ text: intl.formatMessage(messages.hideReblogs, { name: account.get('username') }), action: this.props.onReblogToggle }); + } else { + menu.push({ text: intl.formatMessage(messages.showReblogs, { name: account.get('username') }), action: this.props.onReblogToggle }); + } + + menu.push({ text: intl.formatMessage(account.getIn(['relationship', 'endorsed']) ? messages.unendorse : messages.endorse), action: this.props.onEndorseToggle }); + menu.push({ text: intl.formatMessage(messages.add_or_remove_from_list), action: this.props.onAddToList }); + menu.push(null); + } + + if (account.getIn(['relationship', 'muting'])) { + menu.push({ text: intl.formatMessage(messages.unmute, { name: account.get('username') }), action: this.props.onMute }); + } else { + menu.push({ text: intl.formatMessage(messages.mute, { name: account.get('username') }), action: this.props.onMute }); + } + + if (account.getIn(['relationship', 'blocking'])) { + menu.push({ text: intl.formatMessage(messages.unblock, { name: account.get('username') }), action: this.props.onBlock }); + } else { + menu.push({ text: intl.formatMessage(messages.block, { name: account.get('username') }), action: this.props.onBlock }); + } + + menu.push({ text: intl.formatMessage(messages.report, { name: account.get('username') }), action: this.props.onReport }); + } + + if (account.get('acct') !== account.get('username')) { + const domain = account.get('acct').split('@')[1]; - <span className='account__header__display-name' dangerouslySetInnerHTML={{ __html: displayName }} /> - <span className='account__header__username'>@{account.get('acct')} {account.get('locked') ? <i className='fa fa-lock' /> : null}</span> + menu.push(null); - {badge} + if (account.getIn(['relationship', 'domain_blocking'])) { + menu.push({ text: intl.formatMessage(messages.unblockDomain, { domain }), action: this.props.onUnblockDomain }); + } else { + menu.push({ text: intl.formatMessage(messages.blockDomain, { domain }), action: this.props.onBlockDomain }); + } + } - <div className='account__header__content' dangerouslySetInnerHTML={content} /> + if (account.get('id') !== me && isStaff) { + menu.push(null); + menu.push({ text: intl.formatMessage(messages.admin_account, { name: account.get('username') }), href: `/admin/accounts/${account.get('id')}` }); + } - {fields.size > 0 && ( - <div className='account__header__fields'> - {fields.map((pair, i) => ( - <dl key={i}> - <dt dangerouslySetInnerHTML={{ __html: pair.get('name_emojified') }} title={pair.get('name')} /> - <dd className={pair.get('verified_at') && 'verified'} title={pair.get('value_plain')}> - {pair.get('verified_at') && <span title={intl.formatMessage(messages.link_verified_on, { date: intl.formatDate(pair.get('verified_at'), dateFormatOptions) })}><i className='fa fa-check verified__mark' /></span>} <span dangerouslySetInnerHTML={{ __html: pair.get('value_emojified') }} /> - </dd> - </dl> - ))} - </div> - )} + const content = { __html: account.get('note_emojified') }; + const displayNameHtml = { __html: account.get('display_name_html') }; + const fields = account.get('fields'); + const badge = account.get('bot') ? (<div className='account-role bot'><FormattedMessage id='account.badges.bot' defaultMessage='Bot' /></div>) : null; + const acct = account.get('acct').indexOf('@') === -1 && domain ? `${account.get('acct')}@${domain}` : account.get('acct'); + return ( + <div className={classNames('account__header', { inactive: !!account.get('moved') })}> + <div className='account__header__image'> + <div className='account__header__info'> {info} - {mutingInfo} - {actionBtn} </div> + + <img src={autoPlayGif ? account.get('header') : account.get('header_static')} alt='' className='parallax' /> </div> - </div> + + <div className='account__header__bar'> + <div className='account__header__tabs'> + <a className='avatar' href={account.get('url')} rel='noopener' target='_blank'> + <Avatar account={account} size={90} /> + </a> + + <div className='spacer' /> + + <div className='account__header__tabs__buttons'> + {actionBtn} + + <DropdownMenuContainer items={menu} icon='ellipsis-v' size={24} direction='right' /> + </div> + </div> + + <div className='account__header__tabs__name'> + <h1> + <span dangerouslySetInnerHTML={displayNameHtml} /> {badge} + <small>@{acct} {lockedIcon}</small> + </h1> + </div> + + <div className='account__header__extra'> + <div className='account__header__bio'> + { (fields.size > 0 || identity_proofs.size > 0) && ( + <div className='account__header__fields'> + {identity_proofs.map((proof, i) => ( + <dl key={i}> + <dt dangerouslySetInnerHTML={{ __html: proof.get('provider') }} /> + + <dd className='verified'> + <a href={proof.get('proof_url')} target='_blank' rel='noopener'><span title={intl.formatMessage(messages.linkVerifiedOn, { date: intl.formatDate(proof.get('updated_at'), dateFormatOptions) })}> + <Icon id='check' className='verified__mark' /> + </span></a> + <a href={proof.get('profile_url')} target='_blank' rel='noopener'><span dangerouslySetInnerHTML={{ __html: ' '+proof.get('provider_username') }} /></a> + </dd> + </dl> + ))} + {fields.map((pair, i) => ( + <dl key={i}> + <dt dangerouslySetInnerHTML={{ __html: pair.get('name_emojified') }} title={pair.get('name')} /> + + <dd className={pair.get('verified_at') && 'verified'} title={pair.get('value_plain')}> + {pair.get('verified_at') && <span title={intl.formatMessage(messages.linkVerifiedOn, { date: intl.formatDate(pair.get('verified_at'), dateFormatOptions) })}><Icon id='check' className='verified__mark' /></span>} <span dangerouslySetInnerHTML={{ __html: pair.get('value_emojified') }} /> + </dd> + </dl> + ))} + </div> + )} + + {account.get('note').length > 0 && account.get('note') !== '<p></p>' && <div className='account__header__content' dangerouslySetInnerHTML={content} />} + </div> + </div> + </div> + </div> ); } diff --git a/app/javascript/flavours/glitch/features/account_timeline/components/header.js b/app/javascript/flavours/glitch/features/account_timeline/components/header.js index 8dc0be93e..96cabe847 100644 --- a/app/javascript/flavours/glitch/features/account_timeline/components/header.js +++ b/app/javascript/flavours/glitch/features/account_timeline/components/header.js @@ -13,6 +13,7 @@ export default class Header extends ImmutablePureComponent { static propTypes = { account: ImmutablePropTypes.map, + identity_proofs: ImmutablePropTypes.list, onFollow: PropTypes.func.isRequired, onBlock: PropTypes.func.isRequired, onMention: PropTypes.func.isRequired, @@ -25,6 +26,7 @@ export default class Header extends ImmutablePureComponent { onEndorseToggle: PropTypes.func.isRequired, onAddToList: PropTypes.func.isRequired, hideTabs: PropTypes.bool, + domain: PropTypes.string.isRequired, }; static contextTypes = { @@ -84,7 +86,7 @@ export default class Header extends ImmutablePureComponent { } render () { - const { account, hideTabs } = this.props; + const { account, hideTabs, identity_proofs } = this.props; if (account === null) { return <MissingIndicator />; @@ -96,13 +98,9 @@ export default class Header extends ImmutablePureComponent { <InnerHeader account={account} + identity_proofs={identity_proofs} onFollow={this.handleFollow} onBlock={this.handleBlock} - /> - - <ActionBar - account={account} - onBlock={this.handleBlock} onMention={this.handleMention} onDirect={this.handleDirect} onReblogToggle={this.handleReblogToggle} @@ -112,6 +110,11 @@ export default class Header extends ImmutablePureComponent { onUnblockDomain={this.handleUnblockDomain} onEndorseToggle={this.handleEndorseToggle} onAddToList={this.handleAddToList} + domain={this.props.domain} + /> + + <ActionBar + account={account} /> {!hideTabs && ( diff --git a/app/javascript/flavours/glitch/features/account_timeline/containers/header_container.js b/app/javascript/flavours/glitch/features/account_timeline/containers/header_container.js index e333c31a1..787a36658 100644 --- a/app/javascript/flavours/glitch/features/account_timeline/containers/header_container.js +++ b/app/javascript/flavours/glitch/features/account_timeline/containers/header_container.js @@ -21,11 +21,13 @@ import { openModal } from 'flavours/glitch/actions/modal'; import { blockDomain, unblockDomain } from 'flavours/glitch/actions/domain_blocks'; import { defineMessages, injectIntl, FormattedMessage } from 'react-intl'; import { unfollowModal } from 'flavours/glitch/util/initial_state'; +import { List as ImmutableList } from 'immutable'; const messages = defineMessages({ unfollowConfirm: { id: 'confirmations.unfollow.confirm', defaultMessage: 'Unfollow' }, blockConfirm: { id: 'confirmations.block.confirm', defaultMessage: 'Block' }, blockDomainConfirm: { id: 'confirmations.domain_block.confirm', defaultMessage: 'Hide entire domain' }, + blockAndReport: { id: 'confirmations.block.block_and_report', defaultMessage: 'Block & Report' }, }); const makeMapStateToProps = () => { @@ -33,6 +35,8 @@ const makeMapStateToProps = () => { const mapStateToProps = (state, { accountId }) => ({ account: getAccount(state, accountId), + domain: state.getIn(['meta', 'domain']), + identity_proofs: state.getIn(['identity_proofs', accountId], ImmutableList()), }); return mapStateToProps; @@ -64,6 +68,11 @@ const mapDispatchToProps = (dispatch, { intl }) => ({ message: <FormattedMessage id='confirmations.block.message' defaultMessage='Are you sure you want to block {name}?' values={{ name: <strong>@{account.get('acct')}</strong> }} />, confirm: intl.formatMessage(messages.blockConfirm), onConfirm: () => dispatch(blockAccount(account.get('id'))), + secondary: intl.formatMessage(messages.blockAndReport), + onSecondary: () => { + dispatch(blockAccount(account.get('id'))); + dispatch(initReport(account)); + }, })); } }, diff --git a/app/javascript/flavours/glitch/features/account_timeline/index.js b/app/javascript/flavours/glitch/features/account_timeline/index.js index d683b8789..9971c0f4a 100644 --- a/app/javascript/flavours/glitch/features/account_timeline/index.js +++ b/app/javascript/flavours/glitch/features/account_timeline/index.js @@ -12,6 +12,7 @@ import HeaderContainer from './containers/header_container'; import { List as ImmutableList } from 'immutable'; import ImmutablePureComponent from 'react-immutable-pure-component'; import { FormattedMessage } from 'react-intl'; +import { fetchAccountIdentityProofs } from '../../actions/identity_proofs'; const mapStateToProps = (state, { params: { accountId }, withReplies = false }) => { const path = withReplies ? `${accountId}:with_replies` : accountId; @@ -41,6 +42,7 @@ export default class AccountTimeline extends ImmutablePureComponent { const { params: { accountId }, withReplies } = this.props; this.props.dispatch(fetchAccount(accountId)); + this.props.dispatch(fetchAccountIdentityProofs(accountId)); if (!withReplies) { this.props.dispatch(expandAccountFeaturedTimeline(accountId)); } @@ -50,6 +52,7 @@ export default class AccountTimeline extends ImmutablePureComponent { componentWillReceiveProps (nextProps) { 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(fetchAccountIdentityProofs(nextProps.params.accountId)); if (!nextProps.withReplies) { this.props.dispatch(expandAccountFeaturedTimeline(nextProps.params.accountId)); } diff --git a/app/javascript/flavours/glitch/features/drawer/results/index.js b/app/javascript/flavours/glitch/features/drawer/results/index.js index ac7a14ef4..4574c0e1e 100644 --- a/app/javascript/flavours/glitch/features/drawer/results/index.js +++ b/app/javascript/flavours/glitch/features/drawer/results/index.js @@ -10,6 +10,7 @@ import spring from 'react-motion/lib/spring'; import { Link } from 'react-router-dom'; // Components. +import Icon from 'flavours/glitch/components/icon'; import AccountContainer from 'flavours/glitch/containers/account_container'; import StatusContainer from 'flavours/glitch/containers/status_container'; import Hashtag from 'flavours/glitch/components/hashtag'; @@ -62,6 +63,7 @@ export default function DrawerResults ({ }} > <header> + <Icon icon='search' fixedWidth /> <FormattedMessage {...messages.total} values={{ count }} @@ -69,7 +71,7 @@ export default function DrawerResults ({ </header> {accounts && accounts.size ? ( <section> - <h5><FormattedMessage id='search_results.accounts' defaultMessage='People' /></h5> + <h5><Icon icon='users' fixedWidth /><FormattedMessage id='search_results.accounts' defaultMessage='People' /></h5> {accounts.map( accountId => ( @@ -83,7 +85,7 @@ export default function DrawerResults ({ ) : null} {statuses && statuses.size ? ( <section> - <h5><FormattedMessage id='search_results.statuses' defaultMessage='Toots' /></h5> + <h5><Icon icon='quote-right' fixedWidth /><FormattedMessage id='search_results.statuses' defaultMessage='Toots' /></h5> {statuses.map( statusId => ( @@ -97,7 +99,7 @@ export default function DrawerResults ({ ) : null} {hashtags && hashtags.size ? ( <section> - <h5><FormattedMessage id='search_results.hashtags' defaultMessage='Hashtags' /></h5> + <h5><Icon icon='hashtag' fixedWidth /><FormattedMessage id='search_results.hashtags' defaultMessage='Hashtags' /></h5> {hashtags.map(hashtag => <Hashtag key={hashtag.get('name')} hashtag={hashtag} />)} </section> diff --git a/app/javascript/flavours/glitch/features/emoji_picker/index.js b/app/javascript/flavours/glitch/features/emoji_picker/index.js index d963039dc..a78117971 100644 --- a/app/javascript/flavours/glitch/features/emoji_picker/index.js +++ b/app/javascript/flavours/glitch/features/emoji_picker/index.js @@ -129,7 +129,6 @@ class ModifierPickerMenu extends React.PureComponent { active: PropTypes.bool, onSelect: PropTypes.func.isRequired, onClose: PropTypes.func.isRequired, - modifier: PropTypes.number, }; handleClick = e => { @@ -166,36 +165,20 @@ class ModifierPickerMenu extends React.PureComponent { setRef = c => { this.node = c; - if (this.node) { - this.node.querySelector('li:first-child button').focus(); // focus the first element when opened - } } render () { - const { active, modifier } = this.props; + const { active } = this.props; return ( - <ul - className='emoji-picker-dropdown__modifiers__menu' - style={{ display: active ? 'block' : 'none' }} - role='menuitem' - ref={this.setRef} - > - {[1, 2, 3, 4, 5, 6].map(i => ( - <li - onClick={this.handleClick} - role='menuitemradio' - aria-checked={i === (modifier || 1)} - data-index={i} - key={i} - > - <Emoji - emoji='fist' set='twitter' size={22} sheetSize={32} skin={i} - backgroundImageFn={backgroundImageFn} - /> - </li> - ))} - </ul> + <div className='emoji-picker-dropdown__modifiers__menu' style={{ display: active ? 'block' : 'none' }} ref={this.setRef}> + <button onClick={this.handleClick} data-index={1}><Emoji emoji='fist' set='twitter' size={22} sheetSize={32} skin={1} backgroundImageFn={backgroundImageFn} /></button> + <button onClick={this.handleClick} data-index={2}><Emoji emoji='fist' set='twitter' size={22} sheetSize={32} skin={2} backgroundImageFn={backgroundImageFn} /></button> + <button onClick={this.handleClick} data-index={3}><Emoji emoji='fist' set='twitter' size={22} sheetSize={32} skin={3} backgroundImageFn={backgroundImageFn} /></button> + <button onClick={this.handleClick} data-index={4}><Emoji emoji='fist' set='twitter' size={22} sheetSize={32} skin={4} backgroundImageFn={backgroundImageFn} /></button> + <button onClick={this.handleClick} data-index={5}><Emoji emoji='fist' set='twitter' size={22} sheetSize={32} skin={5} backgroundImageFn={backgroundImageFn} /></button> + <button onClick={this.handleClick} data-index={6}><Emoji emoji='fist' set='twitter' size={22} sheetSize={32} skin={6} backgroundImageFn={backgroundImageFn} /></button> + </div> ); } @@ -227,22 +210,10 @@ class ModifierPicker extends React.PureComponent { render () { const { active, modifier } = this.props; - function setRef(ref) { - if (!ref) { - return; - } - // TODO: It would be nice if we could pass props directly to emoji-mart's buttons. - const button = ref.querySelector('button'); - button.setAttribute('aria-haspopup', 'true'); - button.setAttribute('aria-expanded', active); - } - return ( <div className='emoji-picker-dropdown__modifiers'> - <div ref={setRef}> - <Emoji emoji='fist' set='twitter' size={22} sheetSize={32} skin={modifier} onClick={this.handleClick} backgroundImageFn={backgroundImageFn} /> - </div> - <ModifierPickerMenu active={active} modifier={modifier} onSelect={this.handleSelect} onClose={this.props.onClose} /> + <Emoji emoji='fist' set='twitter' size={22} sheetSize={32} skin={modifier} onClick={this.handleClick} backgroundImageFn={backgroundImageFn} /> + <ModifierPickerMenu active={active} onSelect={this.handleSelect} onClose={this.props.onClose} /> </div> ); } diff --git a/app/javascript/flavours/glitch/features/status/components/action_bar.js b/app/javascript/flavours/glitch/features/status/components/action_bar.js index 66cc10d78..8291319c3 100644 --- a/app/javascript/flavours/glitch/features/status/components/action_bar.js +++ b/app/javascript/flavours/glitch/features/status/components/action_bar.js @@ -98,7 +98,7 @@ export default class ActionBar extends React.PureComponent { } handleBlockClick = () => { - this.props.onBlock(this.props.status.get('account')); + this.props.onBlock(this.props.status); } handleReport = () => { diff --git a/app/javascript/flavours/glitch/features/status/containers/detailed_status_container.js b/app/javascript/flavours/glitch/features/status/containers/detailed_status_container.js index 6d3909ea7..e6c390537 100644 --- a/app/javascript/flavours/glitch/features/status/containers/detailed_status_container.js +++ b/app/javascript/flavours/glitch/features/status/containers/detailed_status_container.js @@ -38,6 +38,7 @@ const messages = defineMessages({ blockConfirm: { id: 'confirmations.block.confirm', defaultMessage: 'Block' }, replyConfirm: { id: 'confirmations.reply.confirm', defaultMessage: 'Reply' }, replyMessage: { id: 'confirmations.reply.message', defaultMessage: 'Replying now will overwrite the message you are currently composing. Are you sure you want to proceed?' }, + blockAndReport: { id: 'confirmations.block.block_and_report', defaultMessage: 'Block & Report' }, }); const makeMapStateToProps = () => { @@ -136,11 +137,17 @@ const mapDispatchToProps = (dispatch, { intl }) => ({ dispatch(openModal('VIDEO', { media, time })); }, - onBlock (account) { + onBlock (status) { + const account = status.get('account'); dispatch(openModal('CONFIRM', { message: <FormattedMessage id='confirmations.block.message' defaultMessage='Are you sure you want to block {name}?' values={{ name: <strong>@{account.get('acct')}</strong> }} />, confirm: intl.formatMessage(messages.blockConfirm), onConfirm: () => dispatch(blockAccount(account.get('id'))), + secondary: intl.formatMessage(messages.blockAndReport), + onSecondary: () => { + dispatch(blockAccount(account.get('id'))); + dispatch(initReport(account, status)); + }, })); }, diff --git a/app/javascript/flavours/glitch/features/status/index.js b/app/javascript/flavours/glitch/features/status/index.js index 73d3c7e9e..7f8f02188 100644 --- a/app/javascript/flavours/glitch/features/status/index.js +++ b/app/javascript/flavours/glitch/features/status/index.js @@ -54,6 +54,7 @@ const messages = defineMessages({ detailedStatus: { id: 'status.detailed_status', defaultMessage: 'Detailed conversation view' }, replyConfirm: { id: 'confirmations.reply.confirm', defaultMessage: 'Reply' }, replyMessage: { id: 'confirmations.reply.message', defaultMessage: 'Replying now will overwrite the message you are currently composing. Are you sure you want to proceed?' }, + blockAndReport: { id: 'confirmations.block.block_and_report', defaultMessage: 'Block & Report' }, tootHeading: { id: 'column.toot', defaultMessage: 'Toots and replies' }, }); @@ -279,13 +280,19 @@ export default class Status extends ImmutablePureComponent { this.setState({ isExpanded: !isExpanded, threadExpanded: !isExpanded }); } - handleBlockClick = (account) => { + handleBlockClick = (status) => { const { dispatch, intl } = this.props; + const account = status.get('account'); dispatch(openModal('CONFIRM', { message: <FormattedMessage id='confirmations.block.message' defaultMessage='Are you sure you want to block {name}?' values={{ name: <strong>@{account.get('acct')}</strong> }} />, confirm: intl.formatMessage(messages.blockConfirm), onConfirm: () => dispatch(blockAccount(account.get('id'))), + secondary: intl.formatMessage(messages.blockAndReport), + onSecondary: () => { + dispatch(blockAccount(account.get('id'))); + dispatch(initReport(account, status)); + }, })); } diff --git a/app/javascript/flavours/glitch/features/ui/components/confirmation_modal.js b/app/javascript/flavours/glitch/features/ui/components/confirmation_modal.js index 07281f818..970df30b6 100644 --- a/app/javascript/flavours/glitch/features/ui/components/confirmation_modal.js +++ b/app/javascript/flavours/glitch/features/ui/components/confirmation_modal.js @@ -11,6 +11,8 @@ export default class ConfirmationModal extends React.PureComponent { confirm: PropTypes.string.isRequired, onClose: PropTypes.func.isRequired, onConfirm: PropTypes.func.isRequired, + secondary: PropTypes.string, + onSecondary: PropTypes.func, onDoNotAsk: PropTypes.func, intl: PropTypes.object.isRequired, }; @@ -27,6 +29,11 @@ export default class ConfirmationModal extends React.PureComponent { } } + handleSecondary = () => { + this.props.onClose(); + this.props.onSecondary(); + } + handleCancel = () => { this.props.onClose(); } @@ -40,7 +47,7 @@ export default class ConfirmationModal extends React.PureComponent { } render () { - const { message, confirm, onDoNotAsk } = this.props; + const { message, confirm, secondary, onDoNotAsk } = this.props; return ( <div className='modal-root__modal confirmation-modal'> @@ -61,6 +68,9 @@ export default class ConfirmationModal extends React.PureComponent { <Button onClick={this.handleCancel} className='confirmation-modal__cancel-button'> <FormattedMessage id='confirmation_modal.cancel' defaultMessage='Cancel' /> </Button> + {secondary !== undefined && ( + <Button text={secondary} onClick={this.handleSecondary} className='confirmation-modal__secondary-button' /> + )} <Button text={confirm} onClick={this.handleClick} ref={this.setRef} /> </div> </div> diff --git a/app/javascript/flavours/glitch/reducers/identity_proofs.js b/app/javascript/flavours/glitch/reducers/identity_proofs.js new file mode 100644 index 000000000..58af0a5fa --- /dev/null +++ b/app/javascript/flavours/glitch/reducers/identity_proofs.js @@ -0,0 +1,25 @@ +import { Map as ImmutableMap, fromJS } from 'immutable'; +import { + IDENTITY_PROOFS_ACCOUNT_FETCH_REQUEST, + IDENTITY_PROOFS_ACCOUNT_FETCH_SUCCESS, + IDENTITY_PROOFS_ACCOUNT_FETCH_FAIL, +} from '../actions/identity_proofs'; + +const initialState = ImmutableMap(); + +export default function identityProofsReducer(state = initialState, action) { + switch(action.type) { + case IDENTITY_PROOFS_ACCOUNT_FETCH_REQUEST: + return state.set('isLoading', true); + case IDENTITY_PROOFS_ACCOUNT_FETCH_FAIL: + return state.set('isLoading', false); + case IDENTITY_PROOFS_ACCOUNT_FETCH_SUCCESS: + return state.update(identity_proofs => identity_proofs.withMutations(map => { + map.set('isLoading', false); + map.set('loaded', true); + map.set(action.accountId, fromJS(action.identity_proofs)); + })); + default: + return state; + } +}; diff --git a/app/javascript/flavours/glitch/reducers/index.js b/app/javascript/flavours/glitch/reducers/index.js index 7b3e0f651..76b38adb4 100644 --- a/app/javascript/flavours/glitch/reducers/index.js +++ b/app/javascript/flavours/glitch/reducers/index.js @@ -30,6 +30,7 @@ import listAdder from './list_adder'; import filters from './filters'; import pinnedAccountsEditor from './pinned_accounts_editor'; import polls from './polls'; +import identity_proofs from './identity_proofs'; const reducers = { dropdown_menu, @@ -57,6 +58,7 @@ const reducers = { notifications, height_cache, custom_emojis, + identity_proofs, lists, listEditor, listAdder, diff --git a/app/javascript/flavours/glitch/reducers/timelines.js b/app/javascript/flavours/glitch/reducers/timelines.js index ca71c3833..cb233de1c 100644 --- a/app/javascript/flavours/glitch/reducers/timelines.js +++ b/app/javascript/flavours/glitch/reducers/timelines.js @@ -73,14 +73,15 @@ const updateTimeline = (state, timeline, status) => { })); }; -const deleteStatus = (state, id, accountId, references) => { +const deleteStatus = (state, id, accountId, references, exclude_account = null) => { state.keySeq().forEach(timeline => { - state = state.updateIn([timeline, 'items'], list => list.filterNot(item => item === id)); + if (exclude_account === null || (timeline !== `account:${exclude_account}` && !timeline.startsWith(`account:${exclude_account}:`))) + state = state.updateIn([timeline, 'items'], list => list.filterNot(item => item === id)); }); // Remove reblogs of deleted status references.forEach(ref => { - state = deleteStatus(state, ref[0], ref[1], []); + state = deleteStatus(state, ref[0], ref[1], [], exclude_account); }); return state; @@ -99,7 +100,7 @@ const filterTimelines = (state, relationship, statuses) => { } references = statuses.filter(item => item.get('reblog') === status.get('id')).map(item => [item.get('id'), item.get('account')]); - state = deleteStatus(state, status.get('id'), status.get('account'), references); + state = deleteStatus(state, status.get('id'), status.get('account'), references, relationship.id); }); return state; diff --git a/app/javascript/flavours/glitch/styles/_mixins.scss b/app/javascript/flavours/glitch/styles/_mixins.scss index 586802185..d542b1083 100644 --- a/app/javascript/flavours/glitch/styles/_mixins.scss +++ b/app/javascript/flavours/glitch/styles/_mixins.scss @@ -1,6 +1,5 @@ @mixin avatar-radius() { border-radius: $ui-avatar-border-size; - background: transparent no-repeat; background-position: 50%; background-clip: padding-box; } diff --git a/app/javascript/flavours/glitch/styles/admin.scss b/app/javascript/flavours/glitch/styles/admin.scss index 42f53f525..05c7821e4 100644 --- a/app/javascript/flavours/glitch/styles/admin.scss +++ b/app/javascript/flavours/glitch/styles/admin.scss @@ -220,6 +220,11 @@ $content-width: 840px; color: $error-value-color; font-weight: 500; } + + .neutral-hint { + color: $dark-text-color; + font-weight: 500; + } } @media screen and (max-width: $no-columns-breakpoint) { diff --git a/app/javascript/flavours/glitch/styles/components/accounts.scss b/app/javascript/flavours/glitch/styles/components/accounts.scss index 0b7b58bb0..00380c575 100644 --- a/app/javascript/flavours/glitch/styles/components/accounts.scss +++ b/app/javascript/flavours/glitch/styles/components/accounts.scss @@ -79,68 +79,8 @@ background: lighten($ui-base-color, 4%); } -.account__header { - flex: 0 0 auto; - background: lighten($ui-base-color, 4%); - text-align: center; - background-size: cover; - background-position: center; - position: relative; - - .account__avatar { - @include avatar-radius(); - @include avatar-size(90px); - display: block; - margin: 0 auto 10px; - overflow: hidden; - } - - &.inactive { - opacity: 0.5; - - .account__header__avatar { - filter: grayscale(100%); - } - - .account__header__username { - color: $secondary-text-color; - } - } - - & > div { - background: rgba(lighten($ui-base-color, 4%), 0.9); - padding: 20px 10px; - } - - .account__header__content { - color: $secondary-text-color; - } - - .account__header__display-name { - color: $primary-text-color; - display: inline-block; - width: 100%; - font-size: 20px; - line-height: 27px; - font-weight: 500; - overflow: hidden; - text-overflow: ellipsis; - } - - .account__header__username { - color: $highlight-text-color; - font-size: 14px; - font-weight: 400; - display: block; - margin-bottom: 10px; - overflow: hidden; - text-overflow: ellipsis; - } -} - .account__disclaimer { padding: 10px; - border-top: 1px solid lighten($ui-base-color, 8%); color: $dark-text-color; strong { @@ -166,39 +106,6 @@ } } -.account__header__content { - color: $darker-text-color; - font-size: 14px; - font-weight: 400; - overflow: hidden; - word-break: normal; - word-wrap: break-word; - - p { - margin-bottom: 20px; - - &:last-child { - margin-bottom: 0; - } - } - - a { - color: inherit; - text-decoration: underline; - - &:hover { - text-decoration: none; - } - } -} - -.account__header__display-name { - .emojione { - width: 25px; - height: 25px; - } -} - .account__action-bar { border-top: 1px solid lighten($ui-base-color, 8%); border-bottom: 1px solid lighten($ui-base-color, 8%); @@ -208,24 +115,6 @@ display: flex; } -.account__action-bar-dropdown { - padding: 10px; - - .dropdown--active { - .dropdown__content.dropdown__right { - left: 6px; - right: initial; - } - - &::after { - bottom: initial; - margin-left: 11px; - margin-top: -7px; - right: initial; - } - } -} - .account__action-bar-links { display: flex; flex: 1 1 auto; @@ -241,6 +130,10 @@ padding: 10px 0; border-bottom: 4px solid transparent; + &:first-child { + border-left: 0; + } + &.active { border-bottom: 4px solid $ui-highlight-color; } @@ -270,15 +163,6 @@ } } -.account__header__avatar { - background-size: 90px 90px; - display: block; - height: 90px; - margin: 0 auto 10px; - overflow: hidden; - width: 90px; -} - .account-authorize { padding: 14px 10px; @@ -427,42 +311,22 @@ } } -.account--follows-info { +.relationship-tag { color: $primary-text-color; - position: absolute; - top: 10px; - left: 10px; - opacity: 0.7; - display: inline-block; + margin-bottom: 4px; + display: block; vertical-align: top; - background-color: rgba($base-overlay-background, 0.4); + background-color: $base-overlay-background; text-transform: uppercase; font-size: 11px; font-weight: 500; padding: 4px; border-radius: 4px; -} - -.account--muting-info { - color: $primary-text-color; - position: absolute; - top: 40px; - left: 10px; opacity: 0.7; - display: inline-block; - vertical-align: top; - background-color: rgba($base-overlay-background, 0.4); - text-transform: uppercase; - font-size: 11px; - font-weight: 500; - padding: 4px; - border-radius: 4px; -} -.account--action-button { - position: absolute; - top: 10px; - right: 20px; + &:hover { + opacity: 1; + } } .account-gallery__container { @@ -614,8 +478,193 @@ } } -.account__header .roles { - margin-top: 20px; - margin-bottom: 20px; - padding: 0 15px; +.account__header__content { + color: $darker-text-color; + font-size: 14px; + font-weight: 400; + overflow: hidden; + word-break: normal; + word-wrap: break-word; + + p { + margin-bottom: 20px; + + &:last-child { + margin-bottom: 0; + } + } + + a { + color: inherit; + text-decoration: underline; + + &:hover { + text-decoration: none; + } + } +} + +.account__header { + overflow: hidden; + + &.inactive { + opacity: 0.5; + + .account__header__image, + .account__avatar { + filter: grayscale(100%); + } + } + + &__info { + position: absolute; + top: 10px; + left: 10px; + } + + &__image { + overflow: hidden; + height: 145px; + position: relative; + background: darken($ui-base-color, 4%); + + img { + object-fit: cover; + display: block; + width: 100%; + height: 100%; + margin: 0; + } + } + + &__bar { + position: relative; + background: lighten($ui-base-color, 4%); + padding: 5px; + border-bottom: 1px solid lighten($ui-base-color, 12%); + + .avatar { + display: block; + flex: 0 0 auto; + width: 94px; + margin-left: -2px; + + .account__avatar { + background: darken($ui-base-color, 8%); + border: 2px solid lighten($ui-base-color, 4%); + } + } + } + + &__tabs { + display: flex; + align-items: flex-start; + padding: 7px 5px; + margin-top: -55px; + + &__buttons { + display: flex; + align-items: center; + padding-top: 55px; + overflow: hidden; + + .icon-button { + border: 1px solid lighten($ui-base-color, 12%); + border-radius: 4px; + box-sizing: content-box; + padding: 2px; + } + + .button { + margin: 0 8px; + } + } + + &__name { + padding: 5px; + + .account-role { + vertical-align: top; + } + + .emojione { + width: 22px; + height: 22px; + } + + h1 { + font-size: 16px; + line-height: 24px; + color: $primary-text-color; + font-weight: 500; + overflow: hidden; + white-space: nowrap; + text-overflow: ellipsis; + + small { + display: block; + font-size: 14px; + color: $darker-text-color; + font-weight: 400; + overflow: hidden; + text-overflow: ellipsis; + } + } + } + + .spacer { + flex: 1 1 auto; + } + } + + &__bio { + overflow: hidden; + margin: 0 -5px; + + .account__header__content { + padding: 20px 15px; + padding-bottom: 5px; + color: $primary-text-color; + } + + .account__header__fields { + margin: 0; + border-top: 1px solid lighten($ui-base-color, 12%); + + a { + color: lighten($ui-highlight-color, 8%); + } + + dl:first-child .verified { + border-radius: 0 4px 0 0; + } + + .verified a { + color: $valid-value-color; + } + } + } + + &__extra { + margin-top: 4px; + + &__links { + font-size: 14px; + color: $darker-text-color; + + a { + display: inline-block; + color: $darker-text-color; + text-decoration: none; + padding: 10px; + padding-top: 20px; + font-weight: 500; + + strong { + font-weight: 700; + color: $primary-text-color; + } + } + } + } } diff --git a/app/javascript/flavours/glitch/styles/components/drawer.scss b/app/javascript/flavours/glitch/styles/components/drawer.scss index f4931c36c..d22783b94 100644 --- a/app/javascript/flavours/glitch/styles/components/drawer.scss +++ b/app/javascript/flavours/glitch/styles/components/drawer.scss @@ -196,43 +196,35 @@ overflow-y: auto; & > header { - border-bottom: 1px solid darken($ui-base-color, 4%); - padding: 15px 10px; color: $dark-text-color; background: lighten($ui-base-color, 2%); - font-size: 14px; + padding: 15px; font-weight: 500; + font-size: 16px; + cursor: default; + + .fa { + display: inline-block; + margin-right: 5px; + } } & > section { - background: $ui-base-color; - margin-bottom: 20px; + margin-bottom: 5px; h5 { - position: relative; - - &::before { - content: ""; - display: block; - position: absolute; - left: 0; - right: 0; - top: 50%; - width: 100%; - height: 0; - border-top: 1px solid lighten($ui-base-color, 8%); - } + background: darken($ui-base-color, 4%); + border-bottom: 1px solid lighten($ui-base-color, 8%); + cursor: default; + display: flex; + padding: 15px; + font-weight: 500; + font-size: 16px; + color: $dark-text-color; - span { + .fa { display: inline-block; - background: $ui-base-color; - color: $darker-text-color; - font-size: 14px; - font-weight: 500; - padding: 10px; - position: relative; - z-index: 1; - cursor: default; + margin-right: 5px; } } diff --git a/app/javascript/flavours/glitch/styles/components/emoji.scss b/app/javascript/flavours/glitch/styles/components/emoji.scss index ccfd42f28..dd386d698 100644 --- a/app/javascript/flavours/glitch/styles/components/emoji.scss +++ b/app/javascript/flavours/glitch/styles/components/emoji.scss @@ -44,11 +44,11 @@ box-shadow: 1px 2px 6px rgba($base-shadow-color, 0.2); overflow: hidden; - li { + button { display: block; cursor: pointer; border: 0; - padding: 3px 8px; + padding: 4px 8px; background: transparent; &:hover, diff --git a/app/javascript/flavours/glitch/styles/components/emoji_picker.scss b/app/javascript/flavours/glitch/styles/components/emoji_picker.scss index 171623352..dcc551c5b 100644 --- a/app/javascript/flavours/glitch/styles/components/emoji_picker.scss +++ b/app/javascript/flavours/glitch/styles/components/emoji_picker.scss @@ -1,5 +1,3 @@ -@import '~emoji-mart/css/emoji-mart.css'; - .emoji-mart { &, * { @@ -53,14 +51,6 @@ &:hover { color: darken($lighter-text-color, 4%); - - svg { - fill: darken($lighter-text-color, 4%); - } - } - - svg { - fill: $lighter-text-color; } } @@ -69,19 +59,11 @@ &:hover { color: darken($highlight-text-color, 4%); - - svg { - fill: darken($highlight-text-color, 4%); - } } .emoji-mart-anchor-bar { bottom: 0; } - - svg { - fill: $highlight-text-color; - } } .emoji-mart-anchor-bar { @@ -101,6 +83,7 @@ } svg { + fill: currentColor; max-height: 18px; } } @@ -120,14 +103,15 @@ } .emoji-mart-search { - margin: 10px 40px 10px 5px; + padding: 10px; + padding-right: 45px; background: $simple-background-color; input { font-size: 14px; font-weight: 400; padding: 7px 9px; - font-family: $font-sans-serif; + font-family: inherit; display: block; width: 100%; background: rgba($ui-secondary-color, 0.3); @@ -182,7 +166,6 @@ font-weight: 500; padding: 5px 6px; background: $simple-background-color; - font-family: $font-sans-serif; } } diff --git a/app/javascript/flavours/glitch/styles/components/index.scss b/app/javascript/flavours/glitch/styles/components/index.scss index b9811f25c..b098676b0 100644 --- a/app/javascript/flavours/glitch/styles/components/index.scss +++ b/app/javascript/flavours/glitch/styles/components/index.scss @@ -35,6 +35,17 @@ transition: all 200ms ease-out; } + &--destructive { + transition: none; + + &:active, + &:focus, + &:hover { + background-color: $error-red; + transition: none; + } + } + &:disabled { background-color: $ui-primary-color; cursor: default; @@ -269,9 +280,7 @@ .display-name { display: block; - padding: 6px 0; max-width: 100%; - height: 36px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; @@ -1263,7 +1272,6 @@ noscript { @import 'domains'; @import 'status'; @import 'modal'; -@import 'metadata'; @import 'composer'; @import 'columns'; @import 'regeneration_indicator'; diff --git a/app/javascript/flavours/glitch/styles/components/metadata.scss b/app/javascript/flavours/glitch/styles/components/metadata.scss index da045574a..e69de29bb 100644 --- a/app/javascript/flavours/glitch/styles/components/metadata.scss +++ b/app/javascript/flavours/glitch/styles/components/metadata.scss @@ -1,45 +0,0 @@ -.account__header .account__header__fields { - font-size: 15px; - line-height: 20px; - overflow: hidden; - margin: 20px -10px -20px; - border-bottom: 0; - border-top: 0; - - dl { - background: $ui-base-color; - border-top: 1px solid lighten($ui-base-color, 4%); - border-bottom: 0; - display: flex; - } - - dt, - dd { - box-sizing: border-box; - padding: 14px 5px; - text-align: center; - max-height: 48px; - overflow: hidden; - white-space: nowrap; - text-overflow: ellipsis; - } - - dt { - color: $darker-text-color; - background: lighten($ui-base-color, 13%); - width: 120px; - flex: 0 0 auto; - font-weight: 500; - } - - dd { - flex: 1 1 auto; - color: $primary-text-color; - background: $ui-base-color; - - &.verified { - border: 1px solid rgba($valid-value-color, 0.5); - background: rgba($valid-value-color, 0.25); - } - } -} diff --git a/app/javascript/flavours/glitch/styles/components/modal.scss b/app/javascript/flavours/glitch/styles/components/modal.scss index 3598959e7..fece8593b 100644 --- a/app/javascript/flavours/glitch/styles/components/modal.scss +++ b/app/javascript/flavours/glitch/styles/components/modal.scss @@ -671,6 +671,7 @@ .confirmation-modal__action-bar, .mute-modal__action-bar { + .confirmation-modal__secondary-button, .confirmation-modal__cancel-button, .mute-modal__cancel-button { background-color: transparent; diff --git a/app/javascript/flavours/glitch/styles/components/status.scss b/app/javascript/flavours/glitch/styles/components/status.scss index 9d2757065..b73dd3d09 100644 --- a/app/javascript/flavours/glitch/styles/components/status.scss +++ b/app/javascript/flavours/glitch/styles/components/status.scss @@ -357,6 +357,7 @@ .status__info__account { display: flex; + align-items: center; } .status-check-box { diff --git a/app/javascript/flavours/glitch/styles/containers.scss b/app/javascript/flavours/glitch/styles/containers.scss index fd334f869..b27524739 100644 --- a/app/javascript/flavours/glitch/styles/containers.scss +++ b/app/javascript/flavours/glitch/styles/containers.scss @@ -10,12 +10,10 @@ } .logo-container { - margin: 100px auto; - margin-bottom: 50px; + margin: 100px auto 50px; - @media screen and (max-width: 400px) { - margin: 30px auto; - margin-bottom: 20px; + @media screen and (max-width: 500px) { + margin: 40px auto 0; } h1 { @@ -683,6 +681,7 @@ color: $darker-text-color; text-decoration: none; padding: 15px; + font-weight: 500; strong { font-weight: 700; diff --git a/app/javascript/flavours/glitch/styles/forms.scss b/app/javascript/flavours/glitch/styles/forms.scss index 9ef45e425..91888d305 100644 --- a/app/javascript/flavours/glitch/styles/forms.scss +++ b/app/javascript/flavours/glitch/styles/forms.scss @@ -475,6 +475,42 @@ code { } } } + + &__overlay-area { + position: relative; + + &__overlay { + position: absolute; + top: 0; + left: 0; + width: 100%; + height: 100%; + display: flex; + justify-content: center; + align-items: center; + background: rgba($ui-base-color, 0.65); + backdrop-filter: blur(2px); + border-radius: 4px; + + &__content { + text-align: center; + + &.rich-formatting { + &, + p { + color: $primary-text-color; + } + } + } + } + } +} + +.block-icon { + display: block; + margin: 0 auto; + margin-bottom: 10px; + font-size: 24px; } .flash-message { @@ -818,13 +854,19 @@ code { flex: 1; flex-direction: column; flex-shrink: 1; + max-width: 50%; &-sep { + align-self: center; flex-grow: 0; overflow: visible; position: relative; z-index: 1; } + + p { + word-break: break-word; + } } .account__avatar { @@ -846,12 +888,13 @@ code { height: 100%; left: 50%; position: absolute; + top: 0; width: 1px; } } &__row { - align-items: center; + align-items: flex-start; display: flex; flex-direction: row; } diff --git a/app/javascript/flavours/glitch/styles/metadata.scss b/app/javascript/flavours/glitch/styles/metadata.scss deleted file mode 100644 index 280848959..000000000 --- a/app/javascript/flavours/glitch/styles/metadata.scss +++ /dev/null @@ -1,56 +0,0 @@ -.account__header__fields { - $meta-table-border: lighten($ui-base-color, 8%); - padding: 0; - margin: 15px -15px -15px -15px; - border: 0 none; - border-top: 1px solid $meta-table-border; - border-bottom: 1px solid $meta-table-border; - font-size: 14px; - line-height: 20px; - - dl { - display: flex; - border-bottom: 1px solid $meta-table-border; - } - - dt, - dd { - box-sizing: border-box; - padding: 14px; - text-align: center; - max-height: 48px; - overflow: hidden; - white-space: nowrap; - text-overflow: ellipsis; - } - - dt { - padding-left: 15px; - font-weight: 500; - text-align: center; - width: 120px; - flex: 0 0 auto; - color: $secondary-text-color; - background: darken($ui-base-color, 8%); - } - - dd { - flex: 1 1 auto; - color: $darker-text-color; - } - - a { - color: $highlight-text-color; - text-decoration: none; - - &:hover, - &:focus, - &:active { - text-decoration: underline; - } - } - - dl:last-child { - border-bottom: 0; - } -} diff --git a/app/javascript/flavours/glitch/styles/stream_entries.scss b/app/javascript/flavours/glitch/styles/stream_entries.scss index 45dcf70ed..6735049b9 100644 --- a/app/javascript/flavours/glitch/styles/stream_entries.scss +++ b/app/javascript/flavours/glitch/styles/stream_entries.scss @@ -192,6 +192,7 @@ .status__info .status__display-name { display: block; max-width: 100%; + padding: 6px 0; padding-right: 25px; margin: initial; diff --git a/app/javascript/flavours/glitch/styles/widgets.scss b/app/javascript/flavours/glitch/styles/widgets.scss index 645192ea4..307e509d5 100644 --- a/app/javascript/flavours/glitch/styles/widgets.scss +++ b/app/javascript/flavours/glitch/styles/widgets.scss @@ -352,6 +352,7 @@ border-radius: 50%; position: relative; margin-left: -10px; + background: darken($ui-base-color, 8%); border: 2px solid $ui-base-color; &:nth-child(1) { diff --git a/app/javascript/flavours/glitch/util/api.js b/app/javascript/flavours/glitch/util/api.js index 033d2d67b..c59a24518 100644 --- a/app/javascript/flavours/glitch/util/api.js +++ b/app/javascript/flavours/glitch/util/api.js @@ -13,10 +13,14 @@ export const getLinks = response => { }; let csrfHeader = {}; + function setCSRFHeader() { - const csrfToken = document.querySelector('meta[name=csrf-token]').content; - csrfHeader['X-CSRF-Token'] = csrfToken; + const csrfToken = document.querySelector('meta[name=csrf-token]'); + if (csrfToken) { + csrfHeader['X-CSRF-Token'] = csrfToken.content; + } } + ready(setCSRFHeader); export default getState => axios.create({ diff --git a/app/javascript/flavours/glitch/util/emoji/emoji_picker.js b/app/javascript/flavours/glitch/util/emoji/emoji_picker.js index 73fcaa8c8..044d38cb2 100644 --- a/app/javascript/flavours/glitch/util/emoji/emoji_picker.js +++ b/app/javascript/flavours/glitch/util/emoji/emoji_picker.js @@ -1,5 +1,5 @@ -import Picker from 'emoji-mart/dist-modern/components/picker/picker'; -import Emoji from 'emoji-mart/dist-modern/components/emoji/emoji'; +import Picker from 'emoji-mart/dist-es/components/picker/picker'; +import Emoji from 'emoji-mart/dist-es/components/emoji/emoji'; export { Picker, diff --git a/app/javascript/mastodon/actions/identity_proofs.js b/app/javascript/mastodon/actions/identity_proofs.js new file mode 100644 index 000000000..449debf61 --- /dev/null +++ b/app/javascript/mastodon/actions/identity_proofs.js @@ -0,0 +1,30 @@ +import api from '../api'; + +export const IDENTITY_PROOFS_ACCOUNT_FETCH_REQUEST = 'IDENTITY_PROOFS_ACCOUNT_FETCH_REQUEST'; +export const IDENTITY_PROOFS_ACCOUNT_FETCH_SUCCESS = 'IDENTITY_PROOFS_ACCOUNT_FETCH_SUCCESS'; +export const IDENTITY_PROOFS_ACCOUNT_FETCH_FAIL = 'IDENTITY_PROOFS_ACCOUNT_FETCH_FAIL'; + +export const fetchAccountIdentityProofs = accountId => (dispatch, getState) => { + dispatch(fetchAccountIdentityProofsRequest(accountId)); + + api(getState).get(`/api/v1/accounts/${accountId}/identity_proofs`) + .then(({ data }) => dispatch(fetchAccountIdentityProofsSuccess(accountId, data))) + .catch(err => dispatch(fetchAccountIdentityProofsFail(accountId, err))); +}; + +export const fetchAccountIdentityProofsRequest = id => ({ + type: IDENTITY_PROOFS_ACCOUNT_FETCH_REQUEST, + id, +}); + +export const fetchAccountIdentityProofsSuccess = (accountId, identity_proofs) => ({ + type: IDENTITY_PROOFS_ACCOUNT_FETCH_SUCCESS, + accountId, + identity_proofs, +}); + +export const fetchAccountIdentityProofsFail = (accountId, err) => ({ + type: IDENTITY_PROOFS_ACCOUNT_FETCH_FAIL, + accountId, + err, +}); diff --git a/app/javascript/mastodon/actions/search.js b/app/javascript/mastodon/actions/search.js index b670d25c3..7c06670eb 100644 --- a/app/javascript/mastodon/actions/search.js +++ b/app/javascript/mastodon/actions/search.js @@ -37,6 +37,7 @@ export function submitSearch() { params: { q: value, resolve: true, + limit: 5, }, }).then(response => { if (response.data.accounts) { diff --git a/app/javascript/mastodon/api.js b/app/javascript/mastodon/api.js index 4be3eadb0..98d59de43 100644 --- a/app/javascript/mastodon/api.js +++ b/app/javascript/mastodon/api.js @@ -13,10 +13,14 @@ export const getLinks = response => { }; let csrfHeader = {}; + function setCSRFHeader() { - const csrfToken = document.querySelector('meta[name=csrf-token]').content; - csrfHeader['X-CSRF-Token'] = csrfToken; + const csrfToken = document.querySelector('meta[name=csrf-token]'); + if (csrfToken) { + csrfHeader['X-CSRF-Token'] = csrfToken.content; + } } + ready(setCSRFHeader); export default getState => axios.create({ diff --git a/app/javascript/mastodon/components/status_action_bar.js b/app/javascript/mastodon/components/status_action_bar.js index 53d17d418..0bfbd8879 100644 --- a/app/javascript/mastodon/components/status_action_bar.js +++ b/app/javascript/mastodon/components/status_action_bar.js @@ -139,7 +139,7 @@ class StatusActionBar extends ImmutablePureComponent { } handleBlockClick = () => { - this.props.onBlock(this.props.status.get('account')); + this.props.onBlock(this.props.status); } handleOpen = () => { diff --git a/app/javascript/mastodon/components/status_content.js b/app/javascript/mastodon/components/status_content.js index 70713047d..fa8901386 100644 --- a/app/javascript/mastodon/components/status_content.js +++ b/app/javascript/mastodon/components/status_content.js @@ -183,14 +183,14 @@ export default class StatusContent extends React.PureComponent { return ( <div className={classNames} ref={this.setRef} tabIndex='0' style={directionStyle} onMouseDown={this.handleMouseDown} onMouseUp={this.handleMouseUp}> <p style={{ marginBottom: hidden && status.get('mentions').isEmpty() ? '0px' : null }}> - <span dangerouslySetInnerHTML={spoilerContent} /> + <span dangerouslySetInnerHTML={spoilerContent} lang={status.get('language')} /> {' '} <button tabIndex='0' className={`status__content__spoiler-link ${hidden ? 'status__content__spoiler-link--show-more' : 'status__content__spoiler-link--show-less'}`} onClick={this.handleSpoilerClick}>{toggleText}</button> </p> {mentionsPlaceholder} - <div tabIndex={!hidden ? 0 : null} className={`status__content__text ${!hidden ? 'status__content__text--visible' : ''}`} style={directionStyle} dangerouslySetInnerHTML={content} /> + <div tabIndex={!hidden ? 0 : null} className={`status__content__text ${!hidden ? 'status__content__text--visible' : ''}`} style={directionStyle} dangerouslySetInnerHTML={content} lang={status.get('language')} /> </div> ); } else if (this.props.onClick) { @@ -202,6 +202,7 @@ export default class StatusContent extends React.PureComponent { className={classNames} style={directionStyle} dangerouslySetInnerHTML={content} + lang={status.get('language')} onMouseDown={this.handleMouseDown} onMouseUp={this.handleMouseUp} />, @@ -220,6 +221,7 @@ export default class StatusContent extends React.PureComponent { className='status__content' style={directionStyle} dangerouslySetInnerHTML={content} + lang={status.get('language')} /> ); } diff --git a/app/javascript/mastodon/containers/status_container.js b/app/javascript/mastodon/containers/status_container.js index b3555c76e..0fce674e2 100644 --- a/app/javascript/mastodon/containers/status_container.js +++ b/app/javascript/mastodon/containers/status_container.js @@ -38,6 +38,7 @@ const messages = defineMessages({ blockConfirm: { id: 'confirmations.block.confirm', defaultMessage: 'Block' }, replyConfirm: { id: 'confirmations.reply.confirm', defaultMessage: 'Reply' }, replyMessage: { id: 'confirmations.reply.message', defaultMessage: 'Replying now will overwrite the message you are currently composing. Are you sure you want to proceed?' }, + blockAndReport: { id: 'confirmations.block.block_and_report', defaultMessage: 'Block & Report' }, }); const makeMapStateToProps = () => { @@ -134,11 +135,17 @@ const mapDispatchToProps = (dispatch, { intl }) => ({ dispatch(openModal('VIDEO', { media, time })); }, - onBlock (account) { + onBlock (status) { + const account = status.get('account'); dispatch(openModal('CONFIRM', { message: <FormattedMessage id='confirmations.block.message' defaultMessage='Are you sure you want to block {name}?' values={{ name: <strong>@{account.get('acct')}</strong> }} />, confirm: intl.formatMessage(messages.blockConfirm), onConfirm: () => dispatch(blockAccount(account.get('id'))), + secondary: intl.formatMessage(messages.blockAndReport), + onSecondary: () => { + dispatch(blockAccount(account.get('id'))); + dispatch(initReport(account, status)); + }, })); }, diff --git a/app/javascript/mastodon/features/account/components/action_bar.js b/app/javascript/mastodon/features/account/components/action_bar.js deleted file mode 100644 index 8ed4c917a..000000000 --- a/app/javascript/mastodon/features/account/components/action_bar.js +++ /dev/null @@ -1,190 +0,0 @@ -import React from 'react'; -import ImmutablePropTypes from 'react-immutable-proptypes'; -import PropTypes from 'prop-types'; -import DropdownMenuContainer from '../../../containers/dropdown_menu_container'; -import { NavLink } from 'react-router-dom'; -import { defineMessages, injectIntl, FormattedMessage } from 'react-intl'; -import { me, isStaff } from '../../../initial_state'; -import { shortNumberFormat } from '../../../utils/numbers'; - -const messages = defineMessages({ - mention: { id: 'account.mention', defaultMessage: 'Mention @{name}' }, - direct: { id: 'account.direct', defaultMessage: 'Direct message @{name}' }, - edit_profile: { id: 'account.edit_profile', defaultMessage: 'Edit profile' }, - unblock: { id: 'account.unblock', defaultMessage: 'Unblock @{name}' }, - unfollow: { id: 'account.unfollow', defaultMessage: 'Unfollow' }, - unmute: { id: 'account.unmute', defaultMessage: 'Unmute @{name}' }, - block: { id: 'account.block', defaultMessage: 'Block @{name}' }, - mute: { id: 'account.mute', defaultMessage: 'Mute @{name}' }, - follow: { id: 'account.follow', defaultMessage: 'Follow' }, - report: { id: 'account.report', defaultMessage: 'Report @{name}' }, - share: { id: 'account.share', defaultMessage: 'Share @{name}\'s profile' }, - media: { id: 'account.media', defaultMessage: 'Media' }, - blockDomain: { id: 'account.block_domain', defaultMessage: 'Hide everything from {domain}' }, - unblockDomain: { id: 'account.unblock_domain', defaultMessage: 'Unhide {domain}' }, - hideReblogs: { id: 'account.hide_reblogs', defaultMessage: 'Hide boosts from @{name}' }, - showReblogs: { id: 'account.show_reblogs', defaultMessage: 'Show boosts from @{name}' }, - pins: { id: 'navigation_bar.pins', defaultMessage: 'Pinned toots' }, - preferences: { id: 'navigation_bar.preferences', defaultMessage: 'Preferences' }, - follow_requests: { id: 'navigation_bar.follow_requests', defaultMessage: 'Follow requests' }, - favourites: { id: 'navigation_bar.favourites', defaultMessage: 'Favourites' }, - lists: { id: 'navigation_bar.lists', defaultMessage: 'Lists' }, - blocks: { id: 'navigation_bar.blocks', defaultMessage: 'Blocked users' }, - domain_blocks: { id: 'navigation_bar.domain_blocks', defaultMessage: 'Hidden domains' }, - mutes: { id: 'navigation_bar.mutes', defaultMessage: 'Muted users' }, - endorse: { id: 'account.endorse', defaultMessage: 'Feature on profile' }, - unendorse: { id: 'account.unendorse', defaultMessage: 'Don\'t feature on profile' }, - add_or_remove_from_list: { id: 'account.add_or_remove_from_list', defaultMessage: 'Add or Remove from lists' }, - admin_account: { id: 'status.admin_account', defaultMessage: 'Open moderation interface for @{name}' }, -}); - -export default @injectIntl -class ActionBar extends React.PureComponent { - - static propTypes = { - account: ImmutablePropTypes.map.isRequired, - onFollow: PropTypes.func, - onBlock: PropTypes.func.isRequired, - onMention: PropTypes.func.isRequired, - onDirect: PropTypes.func.isRequired, - onReblogToggle: PropTypes.func.isRequired, - onReport: PropTypes.func.isRequired, - onMute: PropTypes.func.isRequired, - onBlockDomain: PropTypes.func.isRequired, - onUnblockDomain: PropTypes.func.isRequired, - onEndorseToggle: PropTypes.func.isRequired, - onAddToList: PropTypes.func.isRequired, - intl: PropTypes.object.isRequired, - }; - - handleShare = () => { - navigator.share({ - url: this.props.account.get('url'), - }); - } - - isStatusesPageActive = (match, location) => { - if (!match) { - return false; - } - return !location.pathname.match(/\/(followers|following)\/?$/); - } - - render () { - const { account, intl } = this.props; - - let menu = []; - let extraInfo = ''; - - if (account.get('id') !== me) { - menu.push({ text: intl.formatMessage(messages.mention, { name: account.get('username') }), action: this.props.onMention }); - menu.push({ text: intl.formatMessage(messages.direct, { name: account.get('username') }), action: this.props.onDirect }); - menu.push(null); - } - - if ('share' in navigator) { - menu.push({ text: intl.formatMessage(messages.share, { name: account.get('username') }), action: this.handleShare }); - menu.push(null); - } - - if (account.get('id') === me) { - menu.push({ text: intl.formatMessage(messages.edit_profile), href: '/settings/profile' }); - menu.push({ text: intl.formatMessage(messages.preferences), href: '/settings/preferences' }); - menu.push({ text: intl.formatMessage(messages.pins), to: '/pinned' }); - menu.push(null); - menu.push({ text: intl.formatMessage(messages.follow_requests), to: '/follow_requests' }); - menu.push({ text: intl.formatMessage(messages.favourites), to: '/favourites' }); - menu.push({ text: intl.formatMessage(messages.lists), to: '/lists' }); - menu.push(null); - menu.push({ text: intl.formatMessage(messages.mutes), to: '/mutes' }); - menu.push({ text: intl.formatMessage(messages.blocks), to: '/blocks' }); - menu.push({ text: intl.formatMessage(messages.domain_blocks), to: '/domain_blocks' }); - } else { - if (account.getIn(['relationship', 'following'])) { - if (account.getIn(['relationship', 'showing_reblogs'])) { - menu.push({ text: intl.formatMessage(messages.hideReblogs, { name: account.get('username') }), action: this.props.onReblogToggle }); - } else { - menu.push({ text: intl.formatMessage(messages.showReblogs, { name: account.get('username') }), action: this.props.onReblogToggle }); - } - - menu.push({ text: intl.formatMessage(account.getIn(['relationship', 'endorsed']) ? messages.unendorse : messages.endorse), action: this.props.onEndorseToggle }); - menu.push({ text: intl.formatMessage(messages.add_or_remove_from_list), action: this.props.onAddToList }); - menu.push(null); - } - - if (account.getIn(['relationship', 'muting'])) { - menu.push({ text: intl.formatMessage(messages.unmute, { name: account.get('username') }), action: this.props.onMute }); - } else { - menu.push({ text: intl.formatMessage(messages.mute, { name: account.get('username') }), action: this.props.onMute }); - } - - if (account.getIn(['relationship', 'blocking'])) { - menu.push({ text: intl.formatMessage(messages.unblock, { name: account.get('username') }), action: this.props.onBlock }); - } else { - menu.push({ text: intl.formatMessage(messages.block, { name: account.get('username') }), action: this.props.onBlock }); - } - - menu.push({ text: intl.formatMessage(messages.report, { name: account.get('username') }), action: this.props.onReport }); - } - - if (account.get('acct') !== account.get('username')) { - const domain = account.get('acct').split('@')[1]; - - extraInfo = ( - <div className='account__disclaimer'> - <FormattedMessage - id='account.disclaimer_full' - defaultMessage="Information below may reflect the user's profile incompletely." - /> - {' '} - <a target='_blank' rel='noopener' href={account.get('url')}> - <FormattedMessage id='account.view_full_profile' defaultMessage='View full profile' /> - </a> - </div> - ); - - menu.push(null); - - if (account.getIn(['relationship', 'domain_blocking'])) { - menu.push({ text: intl.formatMessage(messages.unblockDomain, { domain }), action: this.props.onUnblockDomain }); - } else { - menu.push({ text: intl.formatMessage(messages.blockDomain, { domain }), action: this.props.onBlockDomain }); - } - } - - if (account.get('id') !== me && isStaff) { - menu.push(null); - menu.push({ text: intl.formatMessage(messages.admin_account, { name: account.get('username') }), href: `/admin/accounts/${account.get('id')}` }); - } - - return ( - <div> - {extraInfo} - - <div className='account__action-bar'> - <div className='account__action-bar-links'> - <NavLink isActive={this.isStatusesPageActive} activeClassName='active' className='account__action-bar__tab' to={`/accounts/${account.get('id')}`} title={intl.formatNumber(account.get('statuses_count'))}> - <FormattedMessage id='account.posts' defaultMessage='Toots' /> - <strong>{shortNumberFormat(account.get('statuses_count'))}</strong> - </NavLink> - - <NavLink exact activeClassName='active' className='account__action-bar__tab' to={`/accounts/${account.get('id')}/following`} title={intl.formatNumber(account.get('following_count'))}> - <FormattedMessage id='account.follows' defaultMessage='Follows' /> - <strong>{shortNumberFormat(account.get('following_count'))}</strong> - </NavLink> - - <NavLink exact activeClassName='active' className='account__action-bar__tab' to={`/accounts/${account.get('id')}/followers`} title={intl.formatNumber(account.get('followers_count'))}> - <FormattedMessage id='account.followers' defaultMessage='Followers' /> - <strong>{shortNumberFormat(account.get('followers_count'))}</strong> - </NavLink> - </div> - - <div className='account__action-bar-dropdown'> - <DropdownMenuContainer items={menu} icon='ellipsis-v' size={24} direction='right' /> - </div> - </div> - </div> - ); - } - -} diff --git a/app/javascript/mastodon/features/account/components/header.js b/app/javascript/mastodon/features/account/components/header.js index 7fe6d6a4f..f21ba8a9c 100644 --- a/app/javascript/mastodon/features/account/components/header.js +++ b/app/javascript/mastodon/features/account/components/header.js @@ -2,13 +2,15 @@ import React from 'react'; import ImmutablePropTypes from 'react-immutable-proptypes'; import PropTypes from 'prop-types'; import { defineMessages, injectIntl, FormattedMessage } from 'react-intl'; -import IconButton from '../../../components/icon_button'; -import Motion from '../../ui/util/optional_motion'; -import spring from 'react-motion/lib/spring'; +import Button from 'mastodon/components/button'; import ImmutablePureComponent from 'react-immutable-pure-component'; -import { autoPlayGif, me } from '../../../initial_state'; +import { autoPlayGif, me, isStaff } from 'mastodon/initial_state'; import classNames from 'classnames'; import Icon from 'mastodon/components/icon'; +import Avatar from 'mastodon/components/avatar'; +import { shortNumberFormat } from 'mastodon/utils/numbers'; +import { NavLink } from 'react-router-dom'; +import DropdownMenuContainer from 'mastodon/containers/dropdown_menu_container'; const messages = defineMessages({ unfollow: { id: 'account.unfollow', defaultMessage: 'Unfollow' }, @@ -18,6 +20,32 @@ const messages = defineMessages({ edit_profile: { id: 'account.edit_profile', defaultMessage: 'Edit profile' }, linkVerifiedOn: { id: 'account.link_verified_on', defaultMessage: 'Ownership of this link was checked on {date}' }, account_locked: { id: 'account.locked_info', defaultMessage: 'This account privacy status is set to locked. The owner manually reviews who can follow them.' }, + mention: { id: 'account.mention', defaultMessage: 'Mention @{name}' }, + direct: { id: 'account.direct', defaultMessage: 'Direct message @{name}' }, + edit_profile: { id: 'account.edit_profile', defaultMessage: 'Edit profile' }, + unblock: { id: 'account.unblock', defaultMessage: 'Unblock @{name}' }, + unmute: { id: 'account.unmute', defaultMessage: 'Unmute @{name}' }, + block: { id: 'account.block', defaultMessage: 'Block @{name}' }, + mute: { id: 'account.mute', defaultMessage: 'Mute @{name}' }, + report: { id: 'account.report', defaultMessage: 'Report @{name}' }, + share: { id: 'account.share', defaultMessage: 'Share @{name}\'s profile' }, + media: { id: 'account.media', defaultMessage: 'Media' }, + blockDomain: { id: 'account.block_domain', defaultMessage: 'Hide everything from {domain}' }, + unblockDomain: { id: 'account.unblock_domain', defaultMessage: 'Unhide {domain}' }, + hideReblogs: { id: 'account.hide_reblogs', defaultMessage: 'Hide boosts from @{name}' }, + showReblogs: { id: 'account.show_reblogs', defaultMessage: 'Show boosts from @{name}' }, + pins: { id: 'navigation_bar.pins', defaultMessage: 'Pinned toots' }, + preferences: { id: 'navigation_bar.preferences', defaultMessage: 'Preferences' }, + follow_requests: { id: 'navigation_bar.follow_requests', defaultMessage: 'Follow requests' }, + favourites: { id: 'navigation_bar.favourites', defaultMessage: 'Favourites' }, + lists: { id: 'navigation_bar.lists', defaultMessage: 'Lists' }, + blocks: { id: 'navigation_bar.blocks', defaultMessage: 'Blocked users' }, + domain_blocks: { id: 'navigation_bar.domain_blocks', defaultMessage: 'Hidden domains' }, + mutes: { id: 'navigation_bar.mutes', defaultMessage: 'Muted users' }, + endorse: { id: 'account.endorse', defaultMessage: 'Feature on profile' }, + unendorse: { id: 'account.unendorse', defaultMessage: 'Don\'t feature on profile' }, + add_or_remove_from_list: { id: 'account.add_or_remove_from_list', defaultMessage: 'Add or Remove from lists' }, + admin_account: { id: 'status.admin_account', defaultMessage: 'Open moderation interface for @{name}' }, }); const dateFormatOptions = { @@ -29,120 +57,66 @@ const dateFormatOptions = { minute: '2-digit', }; -class Avatar extends ImmutablePureComponent { - - static propTypes = { - account: ImmutablePropTypes.map.isRequired, - }; - - state = { - isHovered: false, - }; - - handleMouseOver = () => { - if (this.state.isHovered) return; - this.setState({ isHovered: true }); - } - - handleMouseOut = () => { - if (!this.state.isHovered) return; - this.setState({ isHovered: false }); - } - - render () { - const { account } = this.props; - const { isHovered } = this.state; - - return ( - <Motion defaultStyle={{ radius: 90 }} style={{ radius: spring(isHovered ? 30 : 90, { stiffness: 180, damping: 12 }) }}> - {({ radius }) => ( - <a - href={account.get('url')} - className='account__header__avatar' - role='presentation' - target='_blank' - rel='noopener' - style={{ borderRadius: `${radius}px`, backgroundImage: `url(${autoPlayGif || isHovered ? account.get('avatar') : account.get('avatar_static')})` }} - onMouseOver={this.handleMouseOver} - onMouseOut={this.handleMouseOut} - onFocus={this.handleMouseOver} - onBlur={this.handleMouseOut} - > - <span style={{ display: 'none' }}>{account.get('acct')}</span> - </a> - )} - </Motion> - ); - } - -} - export default @injectIntl class Header extends ImmutablePureComponent { static propTypes = { account: ImmutablePropTypes.map, + identity_props: ImmutablePropTypes.list, onFollow: PropTypes.func.isRequired, onBlock: PropTypes.func.isRequired, intl: PropTypes.object.isRequired, + domain: PropTypes.string.isRequired, }; openEditProfile = () => { window.open('/settings/profile', '_blank'); } + isStatusesPageActive = (match, location) => { + if (!match) { + return false; + } + + return !location.pathname.match(/\/(followers|following)\/?$/); + } + render () { - const { account, intl } = this.props; + const { account, intl, domain, identity_proofs } = this.props; if (!account) { return null; } - let info = ''; - let mutingInfo = ''; + let info = []; let actionBtn = ''; let lockedIcon = ''; + let menu = []; if (me !== account.get('id') && account.getIn(['relationship', 'followed_by'])) { - info = <span className='account--follows-info'><FormattedMessage id='account.follows_you' defaultMessage='Follows you' /></span>; + info.push(<span key='followed_by' className='relationship-tag'><FormattedMessage id='account.follows_you' defaultMessage='Follows you' /></span>); } else if (me !== account.get('id') && account.getIn(['relationship', 'blocking'])) { - info = <span className='account--follows-info'><FormattedMessage id='account.blocked' defaultMessage='Blocked' /></span>; + info.push(<span key='blocked' className='relationship-tag'><FormattedMessage id='account.blocked' defaultMessage='Blocked' /></span>); } if (me !== account.get('id') && account.getIn(['relationship', 'muting'])) { - mutingInfo = <span className='account--muting-info'><FormattedMessage id='account.muted' defaultMessage='Muted' /></span>; + info.push(<span key='muted' className='relationship-tag'><FormattedMessage id='account.muted' defaultMessage='Muted' /></span>); } else if (me !== account.get('id') && account.getIn(['relationship', 'domain_blocking'])) { - mutingInfo = <span className='account--muting-info'><FormattedMessage id='account.domain_blocked' defaultMessage='Domain hidden' /></span>; + info.push(<span key='domain_blocked' className='relationship-tag'><FormattedMessage id='account.domain_blocked' defaultMessage='Domain hidden' /></span>); } if (me !== account.get('id')) { if (!account.get('relationship')) { // Wait until the relationship is loaded actionBtn = ''; } else if (account.getIn(['relationship', 'requested'])) { - actionBtn = ( - <div className='account--action-button'> - <IconButton size={26} active icon='hourglass' title={intl.formatMessage(messages.requested)} onClick={this.props.onFollow} /> - </div> - ); + actionBtn = <Button className='logo-button' text={intl.formatMessage(messages.requested)} onClick={this.props.onFollow} />; } else if (!account.getIn(['relationship', 'blocking'])) { - actionBtn = ( - <div className='account--action-button'> - <IconButton size={26} icon={account.getIn(['relationship', 'following']) ? 'user-times' : 'user-plus'} active={account.getIn(['relationship', 'following'])} title={intl.formatMessage(account.getIn(['relationship', 'following']) ? messages.unfollow : messages.follow)} onClick={this.props.onFollow} /> - </div> - ); + actionBtn = <Button disabled={account.getIn(['relationship', 'blocked_by'])} className={classNames('logo-button', { 'button--destructive': account.getIn(['relationship', 'following']) })} text={intl.formatMessage(account.getIn(['relationship', 'following']) ? messages.unfollow : messages.follow)} onClick={this.props.onFollow} />; } else if (account.getIn(['relationship', 'blocking'])) { - actionBtn = ( - <div className='account--action-button'> - <IconButton size={26} icon='unlock' title={intl.formatMessage(messages.unblock, { name: account.get('username') })} onClick={this.props.onBlock} /> - </div> - ); + actionBtn = <Button className='logo-button' text={intl.formatMessage(messages.unblock, { name: account.get('username') })} onClick={this.props.onBlock} />; } } else { - actionBtn = ( - <div className='account--action-button'> - <IconButton size={26} icon='pencil' title={intl.formatMessage(messages.edit_profile)} onClick={this.openEditProfile} /> - </div> - ); + actionBtn = <Button className='logo-button' text={intl.formatMessage(messages.edit_profile)} onClick={this.openEditProfile} />; } if (account.get('moved') && !account.getIn(['relationship', 'following'])) { @@ -153,40 +127,157 @@ class Header extends ImmutablePureComponent { lockedIcon = <Icon id='lock' title={intl.formatMessage(messages.account_locked)} />; } + if (account.get('id') !== me) { + menu.push({ text: intl.formatMessage(messages.mention, { name: account.get('username') }), action: this.props.onMention }); + menu.push({ text: intl.formatMessage(messages.direct, { name: account.get('username') }), action: this.props.onDirect }); + menu.push(null); + } + + if ('share' in navigator) { + menu.push({ text: intl.formatMessage(messages.share, { name: account.get('username') }), action: this.handleShare }); + menu.push(null); + } + + if (account.get('id') === me) { + menu.push({ text: intl.formatMessage(messages.edit_profile), href: '/settings/profile' }); + menu.push({ text: intl.formatMessage(messages.preferences), href: '/settings/preferences' }); + menu.push({ text: intl.formatMessage(messages.pins), to: '/pinned' }); + menu.push(null); + menu.push({ text: intl.formatMessage(messages.follow_requests), to: '/follow_requests' }); + menu.push({ text: intl.formatMessage(messages.favourites), to: '/favourites' }); + menu.push({ text: intl.formatMessage(messages.lists), to: '/lists' }); + menu.push(null); + menu.push({ text: intl.formatMessage(messages.mutes), to: '/mutes' }); + menu.push({ text: intl.formatMessage(messages.blocks), to: '/blocks' }); + menu.push({ text: intl.formatMessage(messages.domain_blocks), to: '/domain_blocks' }); + } else { + if (account.getIn(['relationship', 'following'])) { + if (account.getIn(['relationship', 'showing_reblogs'])) { + menu.push({ text: intl.formatMessage(messages.hideReblogs, { name: account.get('username') }), action: this.props.onReblogToggle }); + } else { + menu.push({ text: intl.formatMessage(messages.showReblogs, { name: account.get('username') }), action: this.props.onReblogToggle }); + } + + menu.push({ text: intl.formatMessage(account.getIn(['relationship', 'endorsed']) ? messages.unendorse : messages.endorse), action: this.props.onEndorseToggle }); + menu.push({ text: intl.formatMessage(messages.add_or_remove_from_list), action: this.props.onAddToList }); + menu.push(null); + } + + if (account.getIn(['relationship', 'muting'])) { + menu.push({ text: intl.formatMessage(messages.unmute, { name: account.get('username') }), action: this.props.onMute }); + } else { + menu.push({ text: intl.formatMessage(messages.mute, { name: account.get('username') }), action: this.props.onMute }); + } + + if (account.getIn(['relationship', 'blocking'])) { + menu.push({ text: intl.formatMessage(messages.unblock, { name: account.get('username') }), action: this.props.onBlock }); + } else { + menu.push({ text: intl.formatMessage(messages.block, { name: account.get('username') }), action: this.props.onBlock }); + } + + menu.push({ text: intl.formatMessage(messages.report, { name: account.get('username') }), action: this.props.onReport }); + } + + if (account.get('acct') !== account.get('username')) { + const domain = account.get('acct').split('@')[1]; + + menu.push(null); + + if (account.getIn(['relationship', 'domain_blocking'])) { + menu.push({ text: intl.formatMessage(messages.unblockDomain, { domain }), action: this.props.onUnblockDomain }); + } else { + menu.push({ text: intl.formatMessage(messages.blockDomain, { domain }), action: this.props.onBlockDomain }); + } + } + + if (account.get('id') !== me && isStaff) { + menu.push(null); + menu.push({ text: intl.formatMessage(messages.admin_account, { name: account.get('username') }), href: `/admin/accounts/${account.get('id')}` }); + } + const content = { __html: account.get('note_emojified') }; const displayNameHtml = { __html: account.get('display_name_html') }; const fields = account.get('fields'); - const badge = account.get('bot') ? (<div className='roles'><div className='account-role bot'><FormattedMessage id='account.badges.bot' defaultMessage='Bot' /></div></div>) : null; + const badge = account.get('bot') ? (<div className='account-role bot'><FormattedMessage id='account.badges.bot' defaultMessage='Bot' /></div>) : null; + const acct = account.get('acct').indexOf('@') === -1 && domain ? `${account.get('acct')}@${domain}` : account.get('acct'); return ( - <div className={classNames('account__header', { inactive: !!account.get('moved') })} style={{ backgroundImage: `url(${autoPlayGif ? account.get('header') : account.get('header_static')})` }}> - <div> - <Avatar account={account} /> + <div className={classNames('account__header', { inactive: !!account.get('moved') })}> + <div className='account__header__image'> + <div className='account__header__info'> + {info} + </div> - <span className='account__header__display-name' dangerouslySetInnerHTML={displayNameHtml} /> - <span className='account__header__username'>@{account.get('acct')} {lockedIcon}</span> + <img src={autoPlayGif ? account.get('header') : account.get('header_static')} alt='' className='parallax' /> + </div> - {badge} + <div className='account__header__bar'> + <div className='account__header__tabs'> + <a className='avatar' href={account.get('url')} rel='noopener' target='_blank'> + <Avatar account={account} size={90} /> + </a> - <div className='account__header__content' dangerouslySetInnerHTML={content} /> + <div className='spacer' /> - {fields.size > 0 && ( - <div className='account__header__fields'> - {fields.map((pair, i) => ( - <dl key={i}> - <dt dangerouslySetInnerHTML={{ __html: pair.get('name_emojified') }} title={pair.get('name')} /> + <div className='account__header__tabs__buttons'> + {actionBtn} - <dd className={pair.get('verified_at') && 'verified'} title={pair.get('value_plain')}> - {pair.get('verified_at') && <span title={intl.formatMessage(messages.linkVerifiedOn, { date: intl.formatDate(pair.get('verified_at'), dateFormatOptions) })}><Icon id='check' className='verified__mark' /></span>} <span dangerouslySetInnerHTML={{ __html: pair.get('value_emojified') }} /> - </dd> - </dl> - ))} + <DropdownMenuContainer items={menu} icon='ellipsis-v' size={24} direction='right' /> </div> - )} + </div> + + <div className='account__header__tabs__name'> + <h1> + <span dangerouslySetInnerHTML={displayNameHtml} /> {badge} + <small>@{acct} {lockedIcon}</small> + </h1> + </div> + + <div className='account__header__extra'> + <div className='account__header__bio'> + { (fields.size > 0 || identity_proofs.size > 0) && ( + <div className='account__header__fields'> + {identity_proofs.map((proof, i) => ( + <dl key={i}> + <dt dangerouslySetInnerHTML={{ __html: proof.get('provider') }} /> + + <dd className='verified'> + <a href={proof.get('proof_url')} target='_blank' rel='noopener'><span title={intl.formatMessage(messages.linkVerifiedOn, { date: intl.formatDate(proof.get('updated_at'), dateFormatOptions) })}> + <Icon id='check' className='verified__mark' /> + </span></a> + <a href={proof.get('profile_url')} target='_blank' rel='noopener'><span dangerouslySetInnerHTML={{ __html: ' '+proof.get('provider_username') }} /></a> + </dd> + </dl> + ))} + {fields.map((pair, i) => ( + <dl key={i}> + <dt dangerouslySetInnerHTML={{ __html: pair.get('name_emojified') }} title={pair.get('name')} /> - {info} - {mutingInfo} - {actionBtn} + <dd className={pair.get('verified_at') && 'verified'} title={pair.get('value_plain')}> + {pair.get('verified_at') && <span title={intl.formatMessage(messages.linkVerifiedOn, { date: intl.formatDate(pair.get('verified_at'), dateFormatOptions) })}><Icon id='check' className='verified__mark' /></span>} <span dangerouslySetInnerHTML={{ __html: pair.get('value_emojified') }} /> + </dd> + </dl> + ))} + </div> + )} + + {account.get('note').length > 0 && account.get('note') !== '<p></p>' && <div className='account__header__content' dangerouslySetInnerHTML={content} />} + </div> + + <div className='account__header__extra__links'> + <NavLink isActive={this.isStatusesPageActive} activeClassName='active' to={`/accounts/${account.get('id')}`} title={intl.formatNumber(account.get('statuses_count'))}> + <strong>{shortNumberFormat(account.get('statuses_count'))}</strong> <FormattedMessage id='account.posts' defaultMessage='Toots' /> + </NavLink> + + <NavLink exact activeClassName='active' to={`/accounts/${account.get('id')}/following`} title={intl.formatNumber(account.get('following_count'))}> + <strong>{shortNumberFormat(account.get('following_count'))}</strong> <FormattedMessage id='account.follows' defaultMessage='Follows' /> + </NavLink> + + <NavLink exact activeClassName='active' to={`/accounts/${account.get('id')}/followers`} title={intl.formatNumber(account.get('followers_count'))}> + <strong>{shortNumberFormat(account.get('followers_count'))}</strong> <FormattedMessage id='account.followers' defaultMessage='Followers' /> + </NavLink> + </div> + </div> </div> </div> ); diff --git a/app/javascript/mastodon/features/account_timeline/components/header.js b/app/javascript/mastodon/features/account_timeline/components/header.js index 779e116e0..27dfcc516 100644 --- a/app/javascript/mastodon/features/account_timeline/components/header.js +++ b/app/javascript/mastodon/features/account_timeline/components/header.js @@ -2,7 +2,6 @@ import React from 'react'; import ImmutablePropTypes from 'react-immutable-proptypes'; import PropTypes from 'prop-types'; import InnerHeader from '../../account/components/header'; -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'; @@ -13,6 +12,7 @@ export default class Header extends ImmutablePureComponent { static propTypes = { account: ImmutablePropTypes.map, + identity_proofs: ImmutablePropTypes.list, onFollow: PropTypes.func.isRequired, onBlock: PropTypes.func.isRequired, onMention: PropTypes.func.isRequired, @@ -25,6 +25,7 @@ export default class Header extends ImmutablePureComponent { onEndorseToggle: PropTypes.func.isRequired, onAddToList: PropTypes.func.isRequired, hideTabs: PropTypes.bool, + domain: PropTypes.string.isRequired, }; static contextTypes = { @@ -84,7 +85,7 @@ export default class Header extends ImmutablePureComponent { } render () { - const { account, hideTabs } = this.props; + const { account, hideTabs, identity_proofs } = this.props; if (account === null) { return <MissingIndicator />; @@ -96,13 +97,9 @@ export default class Header extends ImmutablePureComponent { <InnerHeader account={account} + identity_proofs={identity_proofs} onFollow={this.handleFollow} onBlock={this.handleBlock} - /> - - <ActionBar - account={account} - onBlock={this.handleBlock} onMention={this.handleMention} onDirect={this.handleDirect} onReblogToggle={this.handleReblogToggle} @@ -112,6 +109,7 @@ export default class Header extends ImmutablePureComponent { onUnblockDomain={this.handleUnblockDomain} onEndorseToggle={this.handleEndorseToggle} onAddToList={this.handleAddToList} + domain={this.props.domain} /> {!hideTabs && ( diff --git a/app/javascript/mastodon/features/account_timeline/containers/header_container.js b/app/javascript/mastodon/features/account_timeline/containers/header_container.js index 0fd79d036..4d4ae6e82 100644 --- a/app/javascript/mastodon/features/account_timeline/containers/header_container.js +++ b/app/javascript/mastodon/features/account_timeline/containers/header_container.js @@ -21,11 +21,13 @@ import { openModal } from '../../../actions/modal'; import { blockDomain, unblockDomain } from '../../../actions/domain_blocks'; import { defineMessages, injectIntl, FormattedMessage } from 'react-intl'; import { unfollowModal } from '../../../initial_state'; +import { List as ImmutableList } from 'immutable'; const messages = defineMessages({ unfollowConfirm: { id: 'confirmations.unfollow.confirm', defaultMessage: 'Unfollow' }, blockConfirm: { id: 'confirmations.block.confirm', defaultMessage: 'Block' }, blockDomainConfirm: { id: 'confirmations.domain_block.confirm', defaultMessage: 'Hide entire domain' }, + blockAndReport: { id: 'confirmations.block.block_and_report', defaultMessage: 'Block & Report' }, }); const makeMapStateToProps = () => { @@ -33,6 +35,8 @@ const makeMapStateToProps = () => { const mapStateToProps = (state, { accountId }) => ({ account: getAccount(state, accountId), + domain: state.getIn(['meta', 'domain']), + identity_proofs: state.getIn(['identity_proofs', accountId], ImmutableList()), }); return mapStateToProps; @@ -64,6 +68,11 @@ const mapDispatchToProps = (dispatch, { intl }) => ({ message: <FormattedMessage id='confirmations.block.message' defaultMessage='Are you sure you want to block {name}?' values={{ name: <strong>@{account.get('acct')}</strong> }} />, confirm: intl.formatMessage(messages.blockConfirm), onConfirm: () => dispatch(blockAccount(account.get('id'))), + secondary: intl.formatMessage(messages.blockAndReport), + onSecondary: () => { + dispatch(blockAccount(account.get('id'))); + dispatch(initReport(account)); + }, })); } }, diff --git a/app/javascript/mastodon/features/account_timeline/index.js b/app/javascript/mastodon/features/account_timeline/index.js index afc484c60..71341debb 100644 --- a/app/javascript/mastodon/features/account_timeline/index.js +++ b/app/javascript/mastodon/features/account_timeline/index.js @@ -12,15 +12,19 @@ import ColumnBackButton from '../../components/column_back_button'; import { List as ImmutableList } from 'immutable'; import ImmutablePureComponent from 'react-immutable-pure-component'; import { FormattedMessage } from 'react-intl'; +import { fetchAccountIdentityProofs } from '../../actions/identity_proofs'; + +const emptyList = ImmutableList(); const mapStateToProps = (state, { params: { accountId }, withReplies = false }) => { const path = withReplies ? `${accountId}:with_replies` : accountId; return { - statusIds: state.getIn(['timelines', `account:${path}`, 'items'], ImmutableList()), - featuredStatusIds: withReplies ? ImmutableList() : state.getIn(['timelines', `account:${accountId}:pinned`, 'items'], ImmutableList()), + statusIds: state.getIn(['timelines', `account:${path}`, 'items'], emptyList), + featuredStatusIds: withReplies ? ImmutableList() : state.getIn(['timelines', `account:${accountId}:pinned`, 'items'], emptyList), isLoading: state.getIn(['timelines', `account:${path}`, 'isLoading']), - hasMore: state.getIn(['timelines', `account:${path}`, 'hasMore']), + hasMore: state.getIn(['timelines', `account:${path}`, 'hasMore']), + blockedBy: state.getIn(['relationships', accountId, 'blocked_by'], false), }; }; @@ -36,24 +40,31 @@ class AccountTimeline extends ImmutablePureComponent { isLoading: PropTypes.bool, hasMore: PropTypes.bool, withReplies: PropTypes.bool, + blockedBy: PropTypes.bool, }; componentWillMount () { const { params: { accountId }, withReplies } = this.props; this.props.dispatch(fetchAccount(accountId)); + this.props.dispatch(fetchAccountIdentityProofs(accountId)); + if (!withReplies) { this.props.dispatch(expandAccountFeaturedTimeline(accountId)); } + this.props.dispatch(expandAccountTimeline(accountId, { withReplies })); } componentWillReceiveProps (nextProps) { 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(fetchAccountIdentityProofs(nextProps.params.accountId)); + if (!nextProps.withReplies) { this.props.dispatch(expandAccountFeaturedTimeline(nextProps.params.accountId)); } + this.props.dispatch(expandAccountTimeline(nextProps.params.accountId, { withReplies: nextProps.params.withReplies })); } } @@ -63,7 +74,7 @@ class AccountTimeline extends ImmutablePureComponent { } render () { - const { shouldUpdateScroll, statusIds, featuredStatusIds, isLoading, hasMore } = this.props; + const { shouldUpdateScroll, statusIds, featuredStatusIds, isLoading, hasMore, blockedBy } = this.props; if (!statusIds && isLoading) { return ( @@ -73,6 +84,8 @@ class AccountTimeline extends ImmutablePureComponent { ); } + const emptyMessage = blockedBy ? <FormattedMessage id='empty_column.account_timeline_blocked' defaultMessage='You are blocked' /> : <FormattedMessage id='empty_column.account_timeline' defaultMessage='No toots here!' />; + return ( <Column> <ColumnBackButton /> @@ -81,13 +94,13 @@ class AccountTimeline extends ImmutablePureComponent { prepend={<HeaderContainer accountId={this.props.params.accountId} />} alwaysPrepend scrollKey='account_timeline' - statusIds={statusIds} + statusIds={blockedBy ? emptyList : statusIds} featuredStatusIds={featuredStatusIds} isLoading={isLoading} hasMore={hasMore} onLoadMore={this.handleLoadMore} shouldUpdateScroll={shouldUpdateScroll} - emptyMessage={<FormattedMessage id='empty_column.account_timeline' defaultMessage='No toots here!' />} + emptyMessage={emptyMessage} /> </Column> ); diff --git a/app/javascript/mastodon/features/compose/components/emoji_picker_dropdown.js b/app/javascript/mastodon/features/compose/components/emoji_picker_dropdown.js index 038d93483..c1429c756 100644 --- a/app/javascript/mastodon/features/compose/components/emoji_picker_dropdown.js +++ b/app/javascript/mastodon/features/compose/components/emoji_picker_dropdown.js @@ -50,7 +50,6 @@ class ModifierPickerMenu extends React.PureComponent { active: PropTypes.bool, onSelect: PropTypes.func.isRequired, onClose: PropTypes.func.isRequired, - modifier: PropTypes.number, }; handleClick = e => { @@ -87,36 +86,20 @@ class ModifierPickerMenu extends React.PureComponent { setRef = c => { this.node = c; - if (this.node) { - this.node.querySelector('li:first-child button').focus(); // focus the first element when opened - } } render () { - const { active, modifier } = this.props; + const { active } = this.props; return ( - <ul - className='emoji-picker-dropdown__modifiers__menu' - style={{ display: active ? 'block' : 'none' }} - role='menuitem' - ref={this.setRef} - > - {[1, 2, 3, 4, 5, 6].map(i => ( - <li - onClick={this.handleClick} - role='menuitemradio' - aria-checked={i === (modifier || 1)} - data-index={i} - key={i} - > - <Emoji - emoji='fist' set='twitter' size={22} sheetSize={32} skin={i} - backgroundImageFn={backgroundImageFn} - /> - </li> - ))} - </ul> + <div className='emoji-picker-dropdown__modifiers__menu' style={{ display: active ? 'block' : 'none' }} ref={this.setRef}> + <button onClick={this.handleClick} data-index={1}><Emoji emoji='fist' set='twitter' size={22} sheetSize={32} skin={1} backgroundImageFn={backgroundImageFn} /></button> + <button onClick={this.handleClick} data-index={2}><Emoji emoji='fist' set='twitter' size={22} sheetSize={32} skin={2} backgroundImageFn={backgroundImageFn} /></button> + <button onClick={this.handleClick} data-index={3}><Emoji emoji='fist' set='twitter' size={22} sheetSize={32} skin={3} backgroundImageFn={backgroundImageFn} /></button> + <button onClick={this.handleClick} data-index={4}><Emoji emoji='fist' set='twitter' size={22} sheetSize={32} skin={4} backgroundImageFn={backgroundImageFn} /></button> + <button onClick={this.handleClick} data-index={5}><Emoji emoji='fist' set='twitter' size={22} sheetSize={32} skin={5} backgroundImageFn={backgroundImageFn} /></button> + <button onClick={this.handleClick} data-index={6}><Emoji emoji='fist' set='twitter' size={22} sheetSize={32} skin={6} backgroundImageFn={backgroundImageFn} /></button> + </div> ); } @@ -148,22 +131,10 @@ class ModifierPicker extends React.PureComponent { render () { const { active, modifier } = this.props; - function setRef(ref) { - if (!ref) { - return; - } - // TODO: It would be nice if we could pass props directly to emoji-mart's buttons. - const button = ref.querySelector('button'); - button.setAttribute('aria-haspopup', 'true'); - button.setAttribute('aria-expanded', active); - } - return ( <div className='emoji-picker-dropdown__modifiers'> - <div ref={setRef}> - <Emoji emoji='fist' set='twitter' size={22} sheetSize={32} skin={modifier} onClick={this.handleClick} backgroundImageFn={backgroundImageFn} /> - </div> - <ModifierPickerMenu active={active} modifier={modifier} onSelect={this.handleSelect} onClose={this.props.onClose} /> + <Emoji emoji='fist' set='twitter' size={22} sheetSize={32} skin={modifier} onClick={this.handleClick} backgroundImageFn={backgroundImageFn} /> + <ModifierPickerMenu active={active} onSelect={this.handleSelect} onClose={this.props.onClose} /> </div> ); } diff --git a/app/javascript/mastodon/features/direct_timeline/components/column_settings.js b/app/javascript/mastodon/features/direct_timeline/components/column_settings.js deleted file mode 100644 index b629c128d..000000000 --- a/app/javascript/mastodon/features/direct_timeline/components/column_settings.js +++ /dev/null @@ -1,35 +0,0 @@ -import React from 'react'; -import PropTypes from 'prop-types'; -import ImmutablePropTypes from 'react-immutable-proptypes'; -import { defineMessages, injectIntl, FormattedMessage } from 'react-intl'; -import SettingText from '../../../components/setting_text'; - -const messages = defineMessages({ - filter_regex: { id: 'home.column_settings.filter_regex', defaultMessage: 'Filter out by regular expressions' }, - settings: { id: 'home.settings', defaultMessage: 'Column settings' }, -}); - -export default @injectIntl -class ColumnSettings extends React.PureComponent { - - static propTypes = { - settings: ImmutablePropTypes.map.isRequired, - onChange: PropTypes.func.isRequired, - intl: PropTypes.object.isRequired, - }; - - render () { - const { settings, onChange, intl } = this.props; - - return ( - <div> - <span className='column-settings__section'><FormattedMessage id='home.column_settings.advanced' defaultMessage='Advanced' /></span> - - <div className='column-settings__row'> - <SettingText settings={settings} settingKey={['regex', 'body']} onChange={onChange} label={intl.formatMessage(messages.filter_regex)} /> - </div> - </div> - ); - } - -} diff --git a/app/javascript/mastodon/features/direct_timeline/containers/column_settings_container.js b/app/javascript/mastodon/features/direct_timeline/containers/column_settings_container.js deleted file mode 100644 index 38054ce9e..000000000 --- a/app/javascript/mastodon/features/direct_timeline/containers/column_settings_container.js +++ /dev/null @@ -1,17 +0,0 @@ -import { connect } from 'react-redux'; -import ColumnSettings from '../components/column_settings'; -import { changeSetting } from '../../../actions/settings'; - -const mapStateToProps = state => ({ - settings: state.getIn(['settings', 'direct']), -}); - -const mapDispatchToProps = dispatch => ({ - - onChange (key, checked) { - dispatch(changeSetting(['direct', ...key], checked)); - }, - -}); - -export default connect(mapStateToProps, mapDispatchToProps)(ColumnSettings); diff --git a/app/javascript/mastodon/features/emoji/emoji_picker.js b/app/javascript/mastodon/features/emoji/emoji_picker.js index 73fcaa8c8..044d38cb2 100644 --- a/app/javascript/mastodon/features/emoji/emoji_picker.js +++ b/app/javascript/mastodon/features/emoji/emoji_picker.js @@ -1,5 +1,5 @@ -import Picker from 'emoji-mart/dist-modern/components/picker/picker'; -import Emoji from 'emoji-mart/dist-modern/components/emoji/emoji'; +import Picker from 'emoji-mart/dist-es/components/picker/picker'; +import Emoji from 'emoji-mart/dist-es/components/emoji/emoji'; export { Picker, diff --git a/app/javascript/mastodon/features/followers/index.js b/app/javascript/mastodon/features/followers/index.js index ce56f270c..167f61b31 100644 --- a/app/javascript/mastodon/features/followers/index.js +++ b/app/javascript/mastodon/features/followers/index.js @@ -20,6 +20,7 @@ import ScrollableList from '../../components/scrollable_list'; const mapStateToProps = (state, props) => ({ accountIds: state.getIn(['user_lists', 'followers', props.params.accountId, 'items']), hasMore: !!state.getIn(['user_lists', 'followers', props.params.accountId, 'next']), + blockedBy: state.getIn(['relationships', props.params.accountId, 'blocked_by'], false), }); export default @connect(mapStateToProps) @@ -31,6 +32,7 @@ class Followers extends ImmutablePureComponent { shouldUpdateScroll: PropTypes.func, accountIds: ImmutablePropTypes.list, hasMore: PropTypes.bool, + blockedBy: PropTypes.bool, }; componentWillMount () { @@ -50,7 +52,7 @@ class Followers extends ImmutablePureComponent { }, 300, { leading: true }); render () { - const { shouldUpdateScroll, accountIds, hasMore } = this.props; + const { shouldUpdateScroll, accountIds, hasMore, blockedBy } = this.props; if (!accountIds) { return ( @@ -60,7 +62,7 @@ class Followers extends ImmutablePureComponent { ); } - const emptyMessage = <FormattedMessage id='account.followers.empty' defaultMessage='No one follows this user yet.' />; + const emptyMessage = blockedBy ? <FormattedMessage id='empty_column.account_timeline_blocked' defaultMessage='You are blocked' /> : <FormattedMessage id='account.followers.empty' defaultMessage='No one follows this user yet.' />; return ( <Column> @@ -75,7 +77,7 @@ class Followers extends ImmutablePureComponent { alwaysPrepend emptyMessage={emptyMessage} > - {accountIds.map(id => + {blockedBy ? [] : accountIds.map(id => <AccountContainer key={id} id={id} withNote={false} /> )} </ScrollableList> diff --git a/app/javascript/mastodon/features/following/index.js b/app/javascript/mastodon/features/following/index.js index bda0438a0..87638e051 100644 --- a/app/javascript/mastodon/features/following/index.js +++ b/app/javascript/mastodon/features/following/index.js @@ -20,6 +20,7 @@ import ScrollableList from '../../components/scrollable_list'; const mapStateToProps = (state, props) => ({ accountIds: state.getIn(['user_lists', 'following', props.params.accountId, 'items']), hasMore: !!state.getIn(['user_lists', 'following', props.params.accountId, 'next']), + blockedBy: state.getIn(['relationships', props.params.accountId, 'blocked_by'], false), }); export default @connect(mapStateToProps) @@ -31,6 +32,7 @@ class Following extends ImmutablePureComponent { shouldUpdateScroll: PropTypes.func, accountIds: ImmutablePropTypes.list, hasMore: PropTypes.bool, + blockedBy: PropTypes.bool, }; componentWillMount () { @@ -50,7 +52,7 @@ class Following extends ImmutablePureComponent { }, 300, { leading: true }); render () { - const { shouldUpdateScroll, accountIds, hasMore } = this.props; + const { shouldUpdateScroll, accountIds, hasMore, blockedBy } = this.props; if (!accountIds) { return ( @@ -60,7 +62,7 @@ class Following extends ImmutablePureComponent { ); } - const emptyMessage = <FormattedMessage id='account.follows.empty' defaultMessage="This user doesn't follow anyone yet." />; + const emptyMessage = blockedBy ? <FormattedMessage id='empty_column.account_timeline_blocked' defaultMessage='You are blocked' /> : <FormattedMessage id='account.follows.empty' defaultMessage="This user doesn't follow anyone yet." />; return ( <Column> @@ -75,7 +77,7 @@ class Following extends ImmutablePureComponent { alwaysPrepend emptyMessage={emptyMessage} > - {accountIds.map(id => + {blockedBy ? [] : accountIds.map(id => <AccountContainer key={id} id={id} withNote={false} /> )} </ScrollableList> diff --git a/app/javascript/mastodon/features/status/components/action_bar.js b/app/javascript/mastodon/features/status/components/action_bar.js index 73be1fc5f..3e511b7a6 100644 --- a/app/javascript/mastodon/features/status/components/action_bar.js +++ b/app/javascript/mastodon/features/status/components/action_bar.js @@ -92,7 +92,7 @@ class ActionBar extends React.PureComponent { } handleBlockClick = () => { - this.props.onBlock(this.props.status.get('account')); + this.props.onBlock(this.props.status); } handleReport = () => { diff --git a/app/javascript/mastodon/features/status/containers/detailed_status_container.js b/app/javascript/mastodon/features/status/containers/detailed_status_container.js index 2c0db0a6b..61e0c428a 100644 --- a/app/javascript/mastodon/features/status/containers/detailed_status_container.js +++ b/app/javascript/mastodon/features/status/containers/detailed_status_container.js @@ -38,6 +38,7 @@ const messages = defineMessages({ blockConfirm: { id: 'confirmations.block.confirm', defaultMessage: 'Block' }, replyConfirm: { id: 'confirmations.reply.confirm', defaultMessage: 'Reply' }, replyMessage: { id: 'confirmations.reply.message', defaultMessage: 'Replying now will overwrite the message you are currently composing. Are you sure you want to proceed?' }, + blockAndReport: { id: 'confirmations.block.block_and_report', defaultMessage: 'Block & Report' }, }); const makeMapStateToProps = () => { @@ -135,11 +136,17 @@ const mapDispatchToProps = (dispatch, { intl }) => ({ dispatch(openModal('VIDEO', { media, time })); }, - onBlock (account) { + onBlock (status) { + const account = status.get('account'); dispatch(openModal('CONFIRM', { message: <FormattedMessage id='confirmations.block.message' defaultMessage='Are you sure you want to block {name}?' values={{ name: <strong>@{account.get('acct')}</strong> }} />, confirm: intl.formatMessage(messages.blockConfirm), onConfirm: () => dispatch(blockAccount(account.get('id'))), + secondary: intl.formatMessage(messages.blockAndReport), + onSecondary: () => { + dispatch(blockAccount(account.get('id'))); + dispatch(initReport(account, status)); + }, })); }, diff --git a/app/javascript/mastodon/features/status/index.js b/app/javascript/mastodon/features/status/index.js index 3b5febcac..c0ea460e8 100644 --- a/app/javascript/mastodon/features/status/index.js +++ b/app/javascript/mastodon/features/status/index.js @@ -57,6 +57,7 @@ const messages = defineMessages({ detailedStatus: { id: 'status.detailed_status', defaultMessage: 'Detailed conversation view' }, replyConfirm: { id: 'confirmations.reply.confirm', defaultMessage: 'Reply' }, replyMessage: { id: 'confirmations.reply.message', defaultMessage: 'Replying now will overwrite the message you are currently composing. Are you sure you want to proceed?' }, + blockAndReport: { id: 'confirmations.block.block_and_report', defaultMessage: 'Block & Report' }, }); const makeMapStateToProps = () => { @@ -253,13 +254,19 @@ class Status extends ImmutablePureComponent { } } - handleBlockClick = (account) => { + handleBlockClick = (status) => { const { dispatch, intl } = this.props; + const account = status.get('account'); dispatch(openModal('CONFIRM', { message: <FormattedMessage id='confirmations.block.message' defaultMessage='Are you sure you want to block {name}?' values={{ name: <strong>@{account.get('acct')}</strong> }} />, confirm: intl.formatMessage(messages.blockConfirm), onConfirm: () => dispatch(blockAccount(account.get('id'))), + secondary: intl.formatMessage(messages.blockAndReport), + onSecondary: () => { + dispatch(blockAccount(account.get('id'))); + dispatch(initReport(account, status)); + }, })); } diff --git a/app/javascript/mastodon/features/ui/components/confirmation_modal.js b/app/javascript/mastodon/features/ui/components/confirmation_modal.js index f0f3ad134..1227fa453 100644 --- a/app/javascript/mastodon/features/ui/components/confirmation_modal.js +++ b/app/javascript/mastodon/features/ui/components/confirmation_modal.js @@ -11,6 +11,8 @@ class ConfirmationModal extends React.PureComponent { confirm: PropTypes.string.isRequired, onClose: PropTypes.func.isRequired, onConfirm: PropTypes.func.isRequired, + secondary: PropTypes.string, + onSecondary: PropTypes.func, intl: PropTypes.object.isRequired, }; @@ -23,6 +25,11 @@ class ConfirmationModal extends React.PureComponent { this.props.onConfirm(); } + handleSecondary = () => { + this.props.onClose(); + this.props.onSecondary(); + } + handleCancel = () => { this.props.onClose(); } @@ -32,7 +39,7 @@ class ConfirmationModal extends React.PureComponent { } render () { - const { message, confirm } = this.props; + const { message, confirm, secondary } = this.props; return ( <div className='modal-root__modal confirmation-modal'> @@ -44,6 +51,9 @@ class ConfirmationModal extends React.PureComponent { <Button onClick={this.handleCancel} className='confirmation-modal__cancel-button'> <FormattedMessage id='confirmation_modal.cancel' defaultMessage='Cancel' /> </Button> + {secondary !== undefined && ( + <Button text={secondary} onClick={this.handleSecondary} className='confirmation-modal__secondary-button' /> + )} <Button text={confirm} onClick={this.handleClick} ref={this.setRef} /> </div> </div> diff --git a/app/javascript/mastodon/locales/ar.json b/app/javascript/mastodon/locales/ar.json index 0acc7aedb..6ed799941 100644 --- a/app/javascript/mastodon/locales/ar.json +++ b/app/javascript/mastodon/locales/ar.json @@ -5,7 +5,6 @@ "account.block_domain": "إخفاء كل شيئ قادم من إسم النطاق {domain}", "account.blocked": "محظور", "account.direct": "رسالة خاصة إلى @{name}", - "account.disclaimer_full": "قد لا تعكس المعلومات أدناه الملف الشخصي الكامل للمستخدم.", "account.domain_blocked": "النطاق مخفي", "account.edit_profile": "تعديل الملف الشخصي", "account.endorse": "خاصّية على الملف الشخصي", @@ -36,7 +35,6 @@ "account.unfollow": "إلغاء المتابعة", "account.unmute": "إلغاء الكتم عن @{name}", "account.unmute_notifications": "إلغاء كتم إخطارات @{name}", - "account.view_full_profile": "عرض الملف الشخصي كاملا", "alert.unexpected.message": "لقد طرأ هناك خطأ غير متوقّع.", "alert.unexpected.title": "المعذرة !", "boost_modal.combo": "يمكنك/ي ضغط {combo} لتخطّي هذه في المرّة القادمة", @@ -85,6 +83,7 @@ "compose_form.spoiler.unmarked": "النص غير مخفي", "compose_form.spoiler_placeholder": "تنبيه عن المحتوى", "confirmation_modal.cancel": "إلغاء", + "confirmations.block.block_and_report": "Block & Report", "confirmations.block.confirm": "حجب", "confirmations.block.message": "هل أنت متأكد أنك تريد حجب {name} ؟", "confirmations.delete.confirm": "حذف", @@ -133,7 +132,6 @@ "empty_column.mutes": "لم تقم بكتم أي مستخدم بعد.", "empty_column.notifications": "لم تتلق أي إشعار بعدُ. تفاعل مع المستخدمين الآخرين لإنشاء محادثة.", "empty_column.public": "لا يوجد أي شيء هنا ! قم بنشر شيء ما للعامة، أو إتبع المستخدمين الآخرين المتواجدين على الخوادم الأخرى لملء خيط المحادثات", - "error_boundary.it_crashed": "It crashed!", "follow_request.authorize": "ترخيص", "follow_request.reject": "رفض", "getting_started.developers": "المُطوِّرون", @@ -248,6 +246,7 @@ "notification.favourite": "أُعجِب {name} بمنشورك", "notification.follow": "{name} يتابعك", "notification.mention": "{name} ذكرك", + "notification.poll": "A poll you have voted in has ended", "notification.reblog": "{name} قام بترقية تبويقك", "notifications.clear": "إمسح الإخطارات", "notifications.clear_confirmation": "أمتأكد من أنك تود مسح جل الإخطارات الخاصة بك و المتلقاة إلى حد الآن ؟", @@ -258,6 +257,7 @@ "notifications.column_settings.filter_bar.show": "عرض", "notifications.column_settings.follow": "متابعُون جُدُد :", "notifications.column_settings.mention": "الإشارات :", + "notifications.column_settings.poll": "Poll results:", "notifications.column_settings.push": "الإخطارات المدفوعة", "notifications.column_settings.reblog": "الترقيّات:", "notifications.column_settings.show": "إعرِضها في عمود", @@ -267,6 +267,7 @@ "notifications.filter.favourites": "المفضلة", "notifications.filter.follows": "يتابِع", "notifications.filter.mentions": "الإشارات", + "notifications.filter.polls": "Poll results", "notifications.group": "{count} إشعارات", "poll.closed": "Closed", "poll.refresh": "Refresh", @@ -308,7 +309,6 @@ "search_results.hashtags": "الوُسوم", "search_results.statuses": "التبويقات", "search_results.total": "{count, number} {count, plural, one {result} و {results}}", - "standalone.public_title": "نظرة على ...", "status.admin_account": "افتح الواجهة الإدارية لـ @{name}", "status.admin_status": "افتح هذا المنشور على واجهة الإشراف", "status.block": "Block @{name}", diff --git a/app/javascript/mastodon/locales/ast.json b/app/javascript/mastodon/locales/ast.json index 86454c2d3..a341567a7 100644 --- a/app/javascript/mastodon/locales/ast.json +++ b/app/javascript/mastodon/locales/ast.json @@ -5,7 +5,6 @@ "account.block_domain": "Anubrir tolo de {domain}", "account.blocked": "Blocked", "account.direct": "Unviar un mensaxe direutu a @{name}", - "account.disclaimer_full": "La información d'embaxo podría reflexar de mou incompletu'l perfil del usuariu.", "account.domain_blocked": "Dominiu anubríu", "account.edit_profile": "Editar el perfil", "account.endorse": "Destacar nel perfil", @@ -36,7 +35,6 @@ "account.unfollow": "Unfollow", "account.unmute": "Unmute @{name}", "account.unmute_notifications": "Unmute notifications from @{name}", - "account.view_full_profile": "Ver el perfil completu", "alert.unexpected.message": "Asocedió un fallu inesperáu.", "alert.unexpected.title": "¡Ups!", "boost_modal.combo": "Pues primir {combo} pa saltar esto la próxima vegada", @@ -85,6 +83,7 @@ "compose_form.spoiler.unmarked": "El testu va anubrise", "compose_form.spoiler_placeholder": "Escribi equí l'avertencia", "confirmation_modal.cancel": "Encaboxar", + "confirmations.block.block_and_report": "Block & Report", "confirmations.block.confirm": "Block", "confirmations.block.message": "¿De xuru que quies bloquiar a {name}?", "confirmations.delete.confirm": "Delete", @@ -133,7 +132,6 @@ "empty_column.mutes": "Entá nun silenciesti a dengún usuariu.", "empty_column.notifications": "Entá nun tienes dengún avisu. Interactua con otros p'aniciar la conversación.", "empty_column.public": "There is nothing here! Write something publicly, or manually follow users from other instances to fill it up", - "error_boundary.it_crashed": "It crashed!", "follow_request.authorize": "Autorizar", "follow_request.reject": "Refugar", "getting_started.developers": "Desendolcadores", @@ -248,6 +246,7 @@ "notification.favourite": "{name} favourited your status", "notification.follow": "{name} siguióte", "notification.mention": "{name} mentóte", + "notification.poll": "A poll you have voted in has ended", "notification.reblog": "{name} compartió'l to estáu", "notifications.clear": "Llimpiar avisos", "notifications.clear_confirmation": "¿De xuru que quies llimpiar dafechu tolos avisos?", @@ -258,6 +257,7 @@ "notifications.column_settings.filter_bar.show": "Show", "notifications.column_settings.follow": "Siguidores nuevos:", "notifications.column_settings.mention": "Menciones:", + "notifications.column_settings.poll": "Poll results:", "notifications.column_settings.push": "Push notifications", "notifications.column_settings.reblog": "Toots compartíos:", "notifications.column_settings.show": "Amosar en columna", @@ -267,6 +267,7 @@ "notifications.filter.favourites": "Favourites", "notifications.filter.follows": "Follows", "notifications.filter.mentions": "Mentions", + "notifications.filter.polls": "Poll results", "notifications.group": "{count} avisos", "poll.closed": "Closed", "poll.refresh": "Refresh", @@ -308,7 +309,6 @@ "search_results.hashtags": "Etiquetes", "search_results.statuses": "Toots", "search_results.total": "{count, number} {count, plural, one {result} other {results}}", - "standalone.public_title": "A look inside...", "status.admin_account": "Open moderation interface for @{name}", "status.admin_status": "Open this status in the moderation interface", "status.block": "Bloquiar a @{name}", diff --git a/app/javascript/mastodon/locales/bg.json b/app/javascript/mastodon/locales/bg.json index ef9c34cac..49e043582 100644 --- a/app/javascript/mastodon/locales/bg.json +++ b/app/javascript/mastodon/locales/bg.json @@ -5,7 +5,6 @@ "account.block_domain": "Hide everything from {domain}", "account.blocked": "Blocked", "account.direct": "Direct Message @{name}", - "account.disclaimer_full": "Information below may reflect the user's profile incompletely.", "account.domain_blocked": "Domain hidden", "account.edit_profile": "Редактирай профила си", "account.endorse": "Feature on profile", @@ -36,7 +35,6 @@ "account.unfollow": "Не следвай", "account.unmute": "Unmute @{name}", "account.unmute_notifications": "Unmute notifications from @{name}", - "account.view_full_profile": "View full profile", "alert.unexpected.message": "An unexpected error occurred.", "alert.unexpected.title": "Oops!", "boost_modal.combo": "You can press {combo} to skip this next time", @@ -85,6 +83,7 @@ "compose_form.spoiler.unmarked": "Text is not hidden", "compose_form.spoiler_placeholder": "Content warning", "confirmation_modal.cancel": "Cancel", + "confirmations.block.block_and_report": "Block & Report", "confirmations.block.confirm": "Block", "confirmations.block.message": "Are you sure you want to block {name}?", "confirmations.delete.confirm": "Delete", @@ -133,7 +132,6 @@ "empty_column.mutes": "You haven't muted any users 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", - "error_boundary.it_crashed": "It crashed!", "follow_request.authorize": "Authorize", "follow_request.reject": "Reject", "getting_started.developers": "Developers", @@ -248,6 +246,7 @@ "notification.favourite": "{name} хареса твоята публикация", "notification.follow": "{name} те последва", "notification.mention": "{name} те спомена", + "notification.poll": "A poll you have voted in has ended", "notification.reblog": "{name} сподели твоята публикация", "notifications.clear": "Clear notifications", "notifications.clear_confirmation": "Are you sure you want to permanently clear all your notifications?", @@ -258,6 +257,7 @@ "notifications.column_settings.filter_bar.show": "Show", "notifications.column_settings.follow": "Нови последователи:", "notifications.column_settings.mention": "Споменавания:", + "notifications.column_settings.poll": "Poll results:", "notifications.column_settings.push": "Push notifications", "notifications.column_settings.reblog": "Споделяния:", "notifications.column_settings.show": "Покажи в колона", @@ -267,6 +267,7 @@ "notifications.filter.favourites": "Favourites", "notifications.filter.follows": "Follows", "notifications.filter.mentions": "Mentions", + "notifications.filter.polls": "Poll results", "notifications.group": "{count} notifications", "poll.closed": "Closed", "poll.refresh": "Refresh", @@ -308,7 +309,6 @@ "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.admin_account": "Open moderation interface for @{name}", "status.admin_status": "Open this status in the moderation interface", "status.block": "Block @{name}", diff --git a/app/javascript/mastodon/locales/bn.json b/app/javascript/mastodon/locales/bn.json new file mode 100644 index 000000000..0d095bdeb --- /dev/null +++ b/app/javascript/mastodon/locales/bn.json @@ -0,0 +1,383 @@ +{ + "account.add_or_remove_from_list": "লিস্টে আরো যুক্ত বা মুছে ফেলুন", + "account.badges.bot": "রোবট", + "account.block": "@{name} কে বন্ধ করুন", + "account.block_domain": "{domain} থেকে সব সরিয়ে ফেলুন", + "account.blocked": "বন্ধ করা হয়েছে", + "account.direct": "@{name}কে সরকারি পাঠান", + "account.domain_blocked": "বেবিসিটটি সরানো আছে", + "account.edit_profile": "Edit profile", + "account.endorse": "Feature on profile", + "account.follow": "Follow", + "account.followers": "Followers", + "account.followers.empty": "No one follows this user yet.", + "account.follows": "Follows", + "account.follows.empty": "This user doesn't follow anyone yet.", + "account.follows_you": "Follows you", + "account.hide_reblogs": "Hide boosts from @{name}", + "account.link_verified_on": "Ownership of this link was checked on {date}", + "account.locked_info": "This account privacy status is set to locked. The owner manually reviews who can follow them.", + "account.media": "Media", + "account.mention": "Mention @{name}", + "account.moved_to": "{name} has moved to:", + "account.mute": "Mute @{name}", + "account.mute_notifications": "Mute notifications from @{name}", + "account.muted": "Muted", + "account.posts": "Toots", + "account.posts_with_replies": "Toots and replies", + "account.report": "Report @{name}", + "account.requested": "Awaiting approval. Click to cancel follow request", + "account.share": "Share @{name}'s profile", + "account.show_reblogs": "Show boosts from @{name}", + "account.unblock": "Unblock @{name}", + "account.unblock_domain": "Unhide {domain}", + "account.unendorse": "Don't feature on profile", + "account.unfollow": "Unfollow", + "account.unmute": "Unmute @{name}", + "account.unmute_notifications": "Unmute notifications from @{name}", + "alert.unexpected.message": "An unexpected error occurred.", + "alert.unexpected.title": "Oops!", + "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", + "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", + "column.community": "Local timeline", + "column.direct": "Direct messages", + "column.domain_blocks": "Hidden domains", + "column.favourites": "Favourites", + "column.follow_requests": "Follow requests", + "column.home": "Home", + "column.lists": "Lists", + "column.mutes": "Muted users", + "column.notifications": "Notifications", + "column.pins": "Pinned toot", + "column.public": "Federated timeline", + "column_back_button.label": "Back", + "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.settings": "Settings", + "community.column_settings.media_only": "Media Only", + "compose_form.direct_message_warning": "This toot will only be sent to all the mentioned users.", + "compose_form.direct_message_warning_learn_more": "Learn more", + "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", + "compose_form.placeholder": "What is on your mind?", + "compose_form.poll.add_option": "Add a choice", + "compose_form.poll.duration": "Poll duration", + "compose_form.poll.option_placeholder": "Choice {number}", + "compose_form.poll.remove_option": "Remove this choice", + "compose_form.publish": "Toot", + "compose_form.publish_loud": "{publish}!", + "compose_form.sensitive.marked": "Media is marked as sensitive", + "compose_form.sensitive.unmarked": "Media is not marked as sensitive", + "compose_form.spoiler.marked": "Text is hidden behind warning", + "compose_form.spoiler.unmarked": "Text is not hidden", + "compose_form.spoiler_placeholder": "Write your warning here", + "confirmation_modal.cancel": "Cancel", + "confirmations.block.block_and_report": "Block & Report", + "confirmations.block.confirm": "Block", + "confirmations.block.message": "Are you sure you want to block {name}?", + "confirmations.delete.confirm": "Delete", + "confirmations.delete.message": "Are you sure you want to delete this status?", + "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. You will not see content from that domain in any public timelines or your notifications. Your followers from that domain will be removed.", + "confirmations.mute.confirm": "Mute", + "confirmations.mute.message": "Are you sure you want to mute {name}?", + "confirmations.redraft.confirm": "Delete & redraft", + "confirmations.redraft.message": "Are you sure you want to delete this status and re-draft it? Favourites and boosts will be lost, and replies to the original post will be orphaned.", + "confirmations.reply.confirm": "Reply", + "confirmations.reply.message": "Replying now will overwrite the message you are currently composing. Are you sure you want to proceed?", + "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.account_timeline": "No toots here!", + "empty_column.blocks": "You haven't blocked any users yet.", + "empty_column.community": "The local timeline is empty. Write something publicly to get the ball rolling!", + "empty_column.direct": "You don't have any direct messages yet. When you send or receive one, it will show up here.", + "empty_column.domain_blocks": "There are no hidden domains yet.", + "empty_column.favourited_statuses": "You don't have any favourite toots yet. When you favourite one, it will show up here.", + "empty_column.favourites": "No one has favourited this toot yet. When someone does, they will show up here.", + "empty_column.follow_requests": "You don't have any follow requests yet. When you receive one, it will show up here.", + "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. When members of this list post new statuses, they will appear here.", + "empty_column.lists": "You don't have any lists yet. When you create one, it will show up here.", + "empty_column.mutes": "You haven't muted any users 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 servers to fill it up", + "follow_request.authorize": "Authorize", + "follow_request.reject": "Reject", + "getting_started.developers": "Developers", + "getting_started.directory": "Profile directory", + "getting_started.documentation": "Documentation", + "getting_started.heading": "Getting started", + "getting_started.invite": "Invite people", + "getting_started.open_source_notice": "Mastodon is open source software. You can contribute or report issues on GitHub at {github}.", + "getting_started.security": "Security", + "getting_started.terms": "Terms of service", + "hashtag.column_header.tag_mode.all": "and {additional}", + "hashtag.column_header.tag_mode.any": "or {additional}", + "hashtag.column_header.tag_mode.none": "without {additional}", + "hashtag.column_settings.select.no_options_message": "No suggestions found", + "hashtag.column_settings.select.placeholder": "Enter hashtags…", + "hashtag.column_settings.tag_mode.all": "All of these", + "hashtag.column_settings.tag_mode.any": "Any of these", + "hashtag.column_settings.tag_mode.none": "None of these", + "hashtag.column_settings.tag_toggle": "Include additional tags in this column", + "home.column_settings.basic": "Basic", + "home.column_settings.show_reblogs": "Show boosts", + "home.column_settings.show_replies": "Show replies", + "intervals.full.days": "{number, plural, one {# day} other {# days}}", + "intervals.full.hours": "{number, plural, one {# hour} other {# hours}}", + "intervals.full.minutes": "{number, plural, one {# minute} other {# minutes}}", + "introduction.federation.action": "Next", + "introduction.federation.federated.headline": "Federated", + "introduction.federation.federated.text": "Public posts from other servers of the fediverse will appear in the federated timeline.", + "introduction.federation.home.headline": "Home", + "introduction.federation.home.text": "Posts from people you follow will appear in your home feed. You can follow anyone on any server!", + "introduction.federation.local.headline": "Local", + "introduction.federation.local.text": "Public posts from people on the same server as you will appear in the local timeline.", + "introduction.interactions.action": "Finish toot-orial!", + "introduction.interactions.favourite.headline": "Favourite", + "introduction.interactions.favourite.text": "You can save a toot for later, and let the author know that you liked it, by favouriting it.", + "introduction.interactions.reblog.headline": "Boost", + "introduction.interactions.reblog.text": "You can share other people's toots with your followers by boosting them.", + "introduction.interactions.reply.headline": "Reply", + "introduction.interactions.reply.text": "You can reply to other people's and your own toots, which will chain them together in a conversation.", + "introduction.welcome.action": "Let's go!", + "introduction.welcome.headline": "First steps", + "introduction.welcome.text": "Welcome to the fediverse! In a few moments, you'll be able to broadcast messages and talk to your friends across a wide variety of servers. But this server, {domain}, is special—it hosts your profile, so remember its name.", + "keyboard_shortcuts.back": "to navigate back", + "keyboard_shortcuts.blocked": "to open blocked users list", + "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", + "keyboard_shortcuts.description": "Description", + "keyboard_shortcuts.direct": "to open direct messages column", + "keyboard_shortcuts.down": "to move down in the list", + "keyboard_shortcuts.enter": "to open status", + "keyboard_shortcuts.favourite": "to favourite", + "keyboard_shortcuts.favourites": "to open favourites list", + "keyboard_shortcuts.federated": "to open federated timeline", + "keyboard_shortcuts.heading": "Keyboard Shortcuts", + "keyboard_shortcuts.home": "to open home timeline", + "keyboard_shortcuts.hotkey": "Hotkey", + "keyboard_shortcuts.legend": "to display this legend", + "keyboard_shortcuts.local": "to open local timeline", + "keyboard_shortcuts.mention": "to mention author", + "keyboard_shortcuts.muted": "to open muted users list", + "keyboard_shortcuts.my_profile": "to open your profile", + "keyboard_shortcuts.notifications": "to open notifications column", + "keyboard_shortcuts.pinned": "to open pinned toots list", + "keyboard_shortcuts.profile": "to open author's profile", + "keyboard_shortcuts.reply": "to reply", + "keyboard_shortcuts.requests": "to open follow requests list", + "keyboard_shortcuts.search": "to focus search", + "keyboard_shortcuts.start": "to open \"get started\" column", + "keyboard_shortcuts.toggle_hidden": "to show/hide text behind CW", + "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", + "lightbox.close": "Close", + "lightbox.next": "Next", + "lightbox.previous": "Previous", + "lists.account.add": "Add to list", + "lists.account.remove": "Remove from list", + "lists.delete": "Delete list", + "lists.edit": "Edit list", + "lists.edit.submit": "Change title", + "lists.new.create": "Add list", + "lists.new.title_placeholder": "New list title", + "lists.search": "Search among people you follow", + "lists.subheading": "Your lists", + "loading_indicator.label": "Loading...", + "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.apps": "Mobile apps", + "navigation_bar.blocks": "Blocked users", + "navigation_bar.community_timeline": "Local timeline", + "navigation_bar.compose": "Compose new toot", + "navigation_bar.direct": "Direct messages", + "navigation_bar.discover": "Discover", + "navigation_bar.domain_blocks": "Hidden domains", + "navigation_bar.edit_profile": "Edit profile", + "navigation_bar.favourites": "Favourites", + "navigation_bar.filters": "Muted words", + "navigation_bar.follow_requests": "Follow requests", + "navigation_bar.info": "About this server", + "navigation_bar.keyboard_shortcuts": "Hotkeys", + "navigation_bar.lists": "Lists", + "navigation_bar.logout": "Logout", + "navigation_bar.mutes": "Muted users", + "navigation_bar.personal": "Personal", + "navigation_bar.pins": "Pinned toots", + "navigation_bar.preferences": "Preferences", + "navigation_bar.public_timeline": "Federated timeline", + "navigation_bar.security": "Security", + "notification.favourite": "{name} favourited your status", + "notification.follow": "{name} followed you", + "notification.mention": "{name} mentioned you", + "notification.poll": "A poll you have voted in has ended", + "notification.reblog": "{name} boosted your status", + "notifications.clear": "Clear notifications", + "notifications.clear_confirmation": "Are you sure you want to permanently clear all your notifications?", + "notifications.column_settings.alert": "Desktop notifications", + "notifications.column_settings.favourite": "Favourites:", + "notifications.column_settings.filter_bar.advanced": "Display all categories", + "notifications.column_settings.filter_bar.category": "Quick filter bar", + "notifications.column_settings.filter_bar.show": "Show", + "notifications.column_settings.follow": "New followers:", + "notifications.column_settings.mention": "Mentions:", + "notifications.column_settings.poll": "Poll results:", + "notifications.column_settings.push": "Push notifications", + "notifications.column_settings.reblog": "Boosts:", + "notifications.column_settings.show": "Show in column", + "notifications.column_settings.sound": "Play sound", + "notifications.filter.all": "All", + "notifications.filter.boosts": "Boosts", + "notifications.filter.favourites": "Favourites", + "notifications.filter.follows": "Follows", + "notifications.filter.mentions": "Mentions", + "notifications.filter.polls": "Poll results", + "notifications.group": "{count} notifications", + "poll.closed": "Closed", + "poll.refresh": "Refresh", + "poll.total_votes": "{count, plural, one {# vote} other {# votes}}", + "poll.vote": "Vote", + "poll_button.add_poll": "Add a poll", + "poll_button.remove_poll": "Remove poll", + "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!", + "relative_time.days": "{number}d", + "relative_time.hours": "{number}h", + "relative_time.just_now": "now", + "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 server moderators. You can provide an explanation of why you are reporting this account below:", + "report.placeholder": "Additional comments", + "report.submit": "Submit", + "report.target": "Report {target}", + "search.placeholder": "Search", + "search_popout.search_format": "Advanced search format", + "search_popout.tips.full_text": "Simple text returns statuses you have written, favourited, boosted, or have been mentioned in, as well as matching usernames, display names, and hashtags.", + "search_popout.tips.hashtag": "hashtag", + "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}}", + "status.admin_account": "Open moderation interface for @{name}", + "status.admin_status": "Open this status in the moderation interface", + "status.block": "Block @{name}", + "status.cancel_reblog_private": "Unboost", + "status.cannot_reblog": "This post cannot be boosted", + "status.copy": "Copy link to status", + "status.delete": "Delete", + "status.detailed_status": "Detailed conversation view", + "status.direct": "Direct message @{name}", + "status.embed": "Embed", + "status.favourite": "Favourite", + "status.filtered": "Filtered", + "status.load_more": "Load more", + "status.media_hidden": "Media hidden", + "status.mention": "Mention @{name}", + "status.more": "More", + "status.mute": "Mute @{name}", + "status.mute_conversation": "Mute conversation", + "status.open": "Expand this status", + "status.pin": "Pin on profile", + "status.pinned": "Pinned toot", + "status.read_more": "Read more", + "status.reblog": "Boost", + "status.reblog_private": "Boost to original audience", + "status.reblogged_by": "{name} boosted", + "status.reblogs.empty": "No one has boosted this toot yet. When someone does, they will show up here.", + "status.redraft": "Delete & re-draft", + "status.reply": "Reply", + "status.replyAll": "Reply to thread", + "status.report": "Report @{name}", + "status.sensitive_toggle": "Click to view", + "status.sensitive_warning": "Sensitive content", + "status.share": "Share", + "status.show_less": "Show less", + "status.show_less_all": "Show less for all", + "status.show_more": "Show more", + "status.show_more_all": "Show more for all", + "status.show_thread": "Show thread", + "status.unmute_conversation": "Unmute conversation", + "status.unpin": "Unpin from profile", + "suggestions.dismiss": "Dismiss suggestion", + "suggestions.header": "You might be interested in…", + "tabs_bar.federated_timeline": "Federated", + "tabs_bar.home": "Home", + "tabs_bar.local_timeline": "Local", + "tabs_bar.notifications": "Notifications", + "tabs_bar.search": "Search", + "time_remaining.days": "{number, plural, one {# day} other {# days}} left", + "time_remaining.hours": "{number, plural, one {# hour} other {# hours}} left", + "time_remaining.minutes": "{number, plural, one {# minute} other {# minutes}} left", + "time_remaining.moments": "Moments remaining", + "time_remaining.seconds": "{number, plural, one {# second} other {# seconds}} left", + "trends.count_by_accounts": "{count} {rawCount, plural, one {person} other {people}} talking", + "ui.beforeunload": "Your draft will be lost if you leave Mastodon.", + "upload_area.title": "Drag & drop to upload", + "upload_button.label": "Add media (JPEG, PNG, GIF, WebM, MP4, MOV)", + "upload_error.limit": "File upload limit exceeded.", + "upload_error.poll": "File upload not allowed with polls.", + "upload_form.description": "Describe for the visually impaired", + "upload_form.focus": "Crop", + "upload_form.undo": "Delete", + "upload_progress.label": "Uploading...", + "video.close": "Close video", + "video.exit_fullscreen": "Exit full screen", + "video.expand": "Expand video", + "video.fullscreen": "Full screen", + "video.hide": "Hide video", + "video.mute": "Mute sound", + "video.pause": "Pause", + "video.play": "Play", + "video.unmute": "Unmute sound" +} diff --git a/app/javascript/mastodon/locales/ca.json b/app/javascript/mastodon/locales/ca.json index e7333f6fe..6c98c6ae7 100644 --- a/app/javascript/mastodon/locales/ca.json +++ b/app/javascript/mastodon/locales/ca.json @@ -5,7 +5,6 @@ "account.block_domain": "Amaga-ho tot de {domain}", "account.blocked": "Bloquejat", "account.direct": "Missatge directe @{name}", - "account.disclaimer_full": "La informació següent pot reflectir incompleta el perfil de l'usuari.", "account.domain_blocked": "Domini ocult", "account.edit_profile": "Editar el perfil", "account.endorse": "Recomanar en el teu perfil", @@ -36,7 +35,6 @@ "account.unfollow": "Deixa de seguir", "account.unmute": "Treure silenci de @{name}", "account.unmute_notifications": "Activar notificacions de @{name}", - "account.view_full_profile": "Mostra el perfil complet", "alert.unexpected.message": "S'ha produït un error inesperat.", "alert.unexpected.title": "Vaja!", "boost_modal.combo": "Pots premer {combo} per saltar-te això el proper cop", @@ -85,6 +83,7 @@ "compose_form.spoiler.unmarked": "Text no ocult", "compose_form.spoiler_placeholder": "Escriu l'avís aquí", "confirmation_modal.cancel": "Cancel·la", + "confirmations.block.block_and_report": "Block & Report", "confirmations.block.confirm": "Bloca", "confirmations.block.message": "Estàs segur que vols blocar {name}?", "confirmations.delete.confirm": "Suprimeix", @@ -133,7 +132,6 @@ "empty_column.mutes": "Encara no has silenciat cap usuari.", "empty_column.notifications": "Encara no tens notificacions. Interactua amb altres per iniciar la conversa.", "empty_column.public": "No hi ha res aquí! Escriu públicament alguna cosa o manualment segueix usuaris d'altres servidors per omplir-ho", - "error_boundary.it_crashed": "It crashed!", "follow_request.authorize": "Autoritzar", "follow_request.reject": "Rebutjar", "getting_started.developers": "Desenvolupadors", @@ -158,7 +156,7 @@ "home.column_settings.show_replies": "Mostrar respostes", "intervals.full.days": "{number, plural, one {# day} other {# days}}", "intervals.full.hours": "{number, plural, one {# hour} other {# hours}}", - "intervals.full.minutes": "{number, plural, one {# minute} other {# minutes}}", + "intervals.full.minutes": "{number, plural, one {# minut} other {# minuts}}", "introduction.federation.action": "Següent", "introduction.federation.federated.headline": "Federada", "introduction.federation.federated.text": "Les publicacions públiques d'altres servidors del fedivers apareixeran a la línia de temps federada.", @@ -248,6 +246,7 @@ "notification.favourite": "{name} ha afavorit el teu estat", "notification.follow": "{name} et segueix", "notification.mention": "{name} t'ha esmentat", + "notification.poll": "Ha finalitzat una enquesta en la que has votat", "notification.reblog": "{name} ha retootejat el teu estat", "notifications.clear": "Netejar notificacions", "notifications.clear_confirmation": "Estàs segur que vols esborrar permanenment totes les teves notificacions?", @@ -258,6 +257,7 @@ "notifications.column_settings.filter_bar.show": "Mostra", "notifications.column_settings.follow": "Nous seguidors:", "notifications.column_settings.mention": "Mencions:", + "notifications.column_settings.poll": "Resultats de l’enquesta:", "notifications.column_settings.push": "Push notificacions", "notifications.column_settings.reblog": "Impulsos:", "notifications.column_settings.show": "Mostrar en la columna", @@ -267,6 +267,7 @@ "notifications.filter.favourites": "Favorits", "notifications.filter.follows": "Seguiments", "notifications.filter.mentions": "Mencions", + "notifications.filter.polls": "Resultats de l'enquesta", "notifications.group": "{count} notificacions", "poll.closed": "Finalitzada", "poll.refresh": "Actualitza", @@ -308,7 +309,6 @@ "search_results.hashtags": "Etiquetes", "search_results.statuses": "Toots", "search_results.total": "{count, number} {count, plural, un {result} altres {results}}", - "standalone.public_title": "Una mirada a l'interior ...", "status.admin_account": "Obre l'interfície de moderació per a @{name}", "status.admin_status": "Obre aquest estat a la interfície de moderació", "status.block": "Block @{name}", diff --git a/app/javascript/mastodon/locales/co.json b/app/javascript/mastodon/locales/co.json index 5f4d520d6..154feab98 100644 --- a/app/javascript/mastodon/locales/co.json +++ b/app/javascript/mastodon/locales/co.json @@ -5,7 +5,6 @@ "account.block_domain": "Piattà tuttu da {domain}", "account.blocked": "Bluccatu", "account.direct": "Missaghju direttu @{name}", - "account.disclaimer_full": "Ghjè pussibule chì l’infurmazione quì sottu ùn rifletta micca u prufile sanu di l’utilizatore.", "account.domain_blocked": "Duminiu piattatu", "account.edit_profile": "Mudificà u prufile", "account.endorse": "Fà figurà nant'à u prufilu", @@ -36,7 +35,6 @@ "account.unfollow": "Ùn siguità più", "account.unmute": "Ùn piattà più @{name}", "account.unmute_notifications": "Ùn piattà più nutificazione da @{name}", - "account.view_full_profile": "Vede tuttu u prufile", "alert.unexpected.message": "Un prublemu inaspettatu hè accadutu.", "alert.unexpected.title": "Uups!", "boost_modal.combo": "Pudete appughjà nant'à {combo} per saltà quessa a prussima volta", @@ -73,10 +71,10 @@ "compose_form.lock_disclaimer": "U vostru contu ùn hè micca {locked}. Tuttu u mondu pò seguitavi è vede i vostri statuti privati.", "compose_form.lock_disclaimer.lock": "privatu", "compose_form.placeholder": "À chè pensate?", - "compose_form.poll.add_option": "Add a choice", - "compose_form.poll.duration": "Poll duration", - "compose_form.poll.option_placeholder": "Choice {number}", - "compose_form.poll.remove_option": "Remove this choice", + "compose_form.poll.add_option": "Aghjustà una scelta", + "compose_form.poll.duration": "Durata di u scandagliu", + "compose_form.poll.option_placeholder": "Scelta {number}", + "compose_form.poll.remove_option": "Toglie sta scelta", "compose_form.publish": "Toot", "compose_form.publish_loud": "{publish}!", "compose_form.sensitive.marked": "Media indicatu cum'è sensibile", @@ -85,6 +83,7 @@ "compose_form.spoiler.unmarked": "Testu micca piattatu", "compose_form.spoiler_placeholder": "Scrive u vostr'avertimentu quì", "confirmation_modal.cancel": "Annullà", + "confirmations.block.block_and_report": "Bluccà è signalà", "confirmations.block.confirm": "Bluccà", "confirmations.block.message": "Site sicuru·a che vulete bluccà @{name}?", "confirmations.delete.confirm": "Toglie", @@ -133,12 +132,11 @@ "empty_column.mutes": "Per avà ùn avete manc'un utilizatore piattatu.", "empty_column.notifications": "Ùn avete ancu nisuna nutificazione. Interact with others to start the conversation.", "empty_column.public": "Ùn c'hè nunda quì! Scrivete qualcosa in pubblicu o seguitate utilizatori d'altri servori per empie a linea pubblica", - "error_boundary.it_crashed": "It crashed!", "follow_request.authorize": "Auturizà", "follow_request.reject": "Righjittà", "getting_started.developers": "Sviluppatori", "getting_started.directory": "Annuariu di i prufili", - "getting_started.documentation": "Documentation", + "getting_started.documentation": "Ducumentazione", "getting_started.heading": "Per principià", "getting_started.invite": "Invità ghjente", "getting_started.open_source_notice": "Mastodon ghjè un lugiziale liberu. Pudete cuntribuisce à u codice o a traduzione, o palisà un bug, nant'à GitHub: {github}.", @@ -156,9 +154,9 @@ "home.column_settings.basic": "Bàsichi", "home.column_settings.show_reblogs": "Vede e spartere", "home.column_settings.show_replies": "Vede e risposte", - "intervals.full.days": "{number, plural, one {# day} other {# days}}", - "intervals.full.hours": "{number, plural, one {# hour} other {# hours}}", - "intervals.full.minutes": "{number, plural, one {# minute} other {# minutes}}", + "intervals.full.days": "{number, plural, one {# ghjornu} other {# ghjorni}}", + "intervals.full.hours": "{number, plural, one {# ora} other {# ore}}", + "intervals.full.minutes": "{number, plural, one {# minuta} other {# minute}}", "introduction.federation.action": "Cuntinuà", "introduction.federation.federated.headline": "Federata", "introduction.federation.federated.text": "I statuti pubblichi da l'altri servori di u fediverse saranu mustrati nant'à a linea pubblica federata.", @@ -240,7 +238,7 @@ "navigation_bar.lists": "Liste", "navigation_bar.logout": "Scunnettassi", "navigation_bar.mutes": "Utilizatori piattati", - "navigation_bar.personal": "Personal", + "navigation_bar.personal": "Persunale", "navigation_bar.pins": "Statuti puntarulati", "navigation_bar.preferences": "Preferenze", "navigation_bar.public_timeline": "Linea pubblica glubale", @@ -248,6 +246,7 @@ "notification.favourite": "{name} hà aghjuntu u vostru statutu à i so favuriti", "notification.follow": "{name} v'hà seguitatu", "notification.mention": "{name} v'hà mintuvatu", + "notification.poll": "Un scandagliu induve avete vutatu hè finitu", "notification.reblog": "{name} hà spartutu u vostru statutu", "notifications.clear": "Purgà e nutificazione", "notifications.clear_confirmation": "Site sicuru·a che vulete toglie tutte ste nutificazione?", @@ -258,6 +257,7 @@ "notifications.column_settings.filter_bar.show": "Mustrà", "notifications.column_settings.follow": "Abbunati novi:", "notifications.column_settings.mention": "Minzione:", + "notifications.column_settings.poll": "Risultati:", "notifications.column_settings.push": "Nutificazione Push", "notifications.column_settings.reblog": "Spartere:", "notifications.column_settings.show": "Mustrà indè a colonna", @@ -267,13 +267,14 @@ "notifications.filter.favourites": "Favuriti", "notifications.filter.follows": "Abbunamenti", "notifications.filter.mentions": "Minzione", + "notifications.filter.polls": "Risultati di u scandagliu", "notifications.group": "{count} nutificazione", "poll.closed": "Chjosu", "poll.refresh": "Attualizà", "poll.total_votes": "{count, plural, one {# votu} other {# voti}}", "poll.vote": "Vutà", - "poll_button.add_poll": "Add a poll", - "poll_button.remove_poll": "Remove poll", + "poll_button.add_poll": "Aghjustà un scandagliu", + "poll_button.remove_poll": "Toglie u scandagliu", "privacy.change": "Mudificà a cunfidenzialità di u statutu", "privacy.direct.long": "Mandà solu à quelli chì so mintuvati", "privacy.direct.short": "Direttu", @@ -308,7 +309,6 @@ "search_results.hashtags": "Hashtag", "search_results.statuses": "Statuti", "search_results.total": "{count, number} {count, plural, one {risultatu} other {risultati}}", - "standalone.public_title": "Una vista à l'internu...", "status.admin_account": "Apre l'interfaccia di muderazione per @{name}", "status.admin_status": "Apre stu statutu in l'interfaccia di muderazione", "status.block": "Bluccà @{name}", @@ -366,7 +366,7 @@ "upload_area.title": "Drag & drop per caricà un fugliale", "upload_button.label": "Aghjunghje un media (JPEG, PNG, GIF, WebM, MP4, MOV)", "upload_error.limit": "Limita di caricamentu di fugliali trapassata.", - "upload_error.poll": "File upload not allowed with polls.", + "upload_error.poll": "Ùn si pò micca caricà fugliali cù i scandagli.", "upload_form.description": "Discrive per i malvistosi", "upload_form.focus": "Cambià a vista", "upload_form.undo": "Sguassà", diff --git a/app/javascript/mastodon/locales/cs.json b/app/javascript/mastodon/locales/cs.json index 7ccbdef00..e711961e7 100644 --- a/app/javascript/mastodon/locales/cs.json +++ b/app/javascript/mastodon/locales/cs.json @@ -5,7 +5,6 @@ "account.block_domain": "Skrýt vše z {domain}", "account.blocked": "Blokován/a", "account.direct": "Poslat přímou zprávu uživateli @{name}", - "account.disclaimer_full": "Níže uvedené informace nemusejí zcela odrážet profil uživatele.", "account.domain_blocked": "Doména skryta", "account.edit_profile": "Upravit profil", "account.endorse": "Představit na profilu", @@ -27,7 +26,7 @@ "account.posts": "Tooty", "account.posts_with_replies": "Tooty a odpovědi", "account.report": "Nahlásit uživatele @{name}", - "account.requested": "Požadavek čeká na schválení. Kliknutím zrušíte požadavek o sledování", + "account.requested": "Čekám na schválení. Kliknutím zrušíte požadavek o sledování", "account.share": "Sdílet profil uživatele @{name}", "account.show_reblogs": "Zobrazit boosty od uživatele @{name}", "account.unblock": "Odblokovat uživatele @{name}", @@ -36,7 +35,6 @@ "account.unfollow": "Přestat sledovat", "account.unmute": "Odkrýt uživatele @{name}", "account.unmute_notifications": "Odkrýt oznámení od uživatele @{name}", - "account.view_full_profile": "Zobrazit celý profil", "alert.unexpected.message": "Objevila se neočekávaná chyba.", "alert.unexpected.title": "Jejda!", "boost_modal.combo": "Příště můžete pro přeskočení kliknout na {combo}", @@ -85,6 +83,7 @@ "compose_form.spoiler.unmarked": "Text není skrytý", "compose_form.spoiler_placeholder": "Sem napište vaše varování", "confirmation_modal.cancel": "Zrušit", + "confirmations.block.block_and_report": "Blokovat a nahlásit", "confirmations.block.confirm": "Blokovat", "confirmations.block.message": "Jste si jistý/á, že chcete zablokovat uživatele {name}?", "confirmations.delete.confirm": "Smazat", @@ -133,7 +132,6 @@ "empty_column.mutes": "Ještě jste neskryl/a žádné uživatele.", "empty_column.notifications": "Ještě nemáte žádná oznámení. Začněte konverzaci komunikováním s ostatními.", "empty_column.public": "Tady nic není! Napište něco veřejně, nebo začněte ručně sledovat uživatele z jiných serverů, aby tu něco přibylo", - "error_boundary.it_crashed": "It crashed!", "follow_request.authorize": "Autorizovat", "follow_request.reject": "Odmítnout", "getting_started.developers": "Vývojáři", @@ -161,7 +159,7 @@ "intervals.full.minutes": "{number, plural, one {# minuta} few {# minuty} many {# minuty} other {# minut}}", "introduction.federation.action": "Další", "introduction.federation.federated.headline": "Federovaná", - "introduction.federation.federated.text": "Veřejné příspěvky z jiných serverů na fediverse se zobrazí na federované časové ose.", + "introduction.federation.federated.text": "Veřejné příspěvky z jiných serverů ve fedivesmíru se zobrazí na federované časové ose.", "introduction.federation.home.headline": "Domů", "introduction.federation.home.text": "Příspěvky od lidí, které sledujete, se objeví ve vašem domovském proudu. Můžete sledovat kohokoliv na jakémkoliv serveru!", "introduction.federation.local.headline": "Místní", @@ -175,7 +173,7 @@ "introduction.interactions.reply.text": "Můžete odpovídat na tooty jiných lidí i vaše vlastní, což je propojí do konverzace.", "introduction.welcome.action": "Jdeme na to!", "introduction.welcome.headline": "První kroky", - "introduction.welcome.text": "Vítejte na fediverse! Za malou chvíli budete moci posílat zprávy a povídat si se svými přátely přes širokou škálu serverů. Tento server, {domain}, je však speciální—je na něm váš profil, proto si zapamatujte jeho jméno.", + "introduction.welcome.text": "Vítejte ve fedivesmíru! Za malou chvíli budete moci posílat zprávy a povídat si se svými přátely přes širokou škálu serverů. Tento server, {domain}, je však speciální—je na něm váš profil, proto si zapamatujte jeho jméno.", "keyboard_shortcuts.back": "k návratu zpět", "keyboard_shortcuts.blocked": "k otevření seznamu blokovaných uživatelů", "keyboard_shortcuts.boost": "k boostnutí", @@ -248,6 +246,7 @@ "notification.favourite": "{name} si oblíbil/a váš toot", "notification.follow": "{name} vás začal/a sledovat", "notification.mention": "{name} vás zmínil/a", + "notification.poll": "Anketa, ve které jste hlasoval/a, skončila", "notification.reblog": "{name} boostnul/a váš toot", "notifications.clear": "Vymazat oznámení", "notifications.clear_confirmation": "Jste si jistý/á, že chcete trvale vymazat všechna vaše oznámení?", @@ -258,6 +257,7 @@ "notifications.column_settings.filter_bar.show": "Zobrazit", "notifications.column_settings.follow": "Noví sledující:", "notifications.column_settings.mention": "Zmínky:", + "notifications.column_settings.poll": "Výsledky anket:", "notifications.column_settings.push": "Push oznámení", "notifications.column_settings.reblog": "Boosty:", "notifications.column_settings.show": "Zobrazit ve sloupci", @@ -267,6 +267,7 @@ "notifications.filter.favourites": "Oblíbení", "notifications.filter.follows": "Sledování", "notifications.filter.mentions": "Zmínky", + "notifications.filter.polls": "Výsledky anket", "notifications.group": "{count} oznámení", "poll.closed": "Uzavřena", "poll.refresh": "Obnovit", @@ -308,9 +309,8 @@ "search_results.hashtags": "Hashtagy", "search_results.statuses": "Tooty", "search_results.total": "{count, number} {count, plural, one {výsledek} few {výsledky} many {výsledku} other {výsledků}}", - "standalone.public_title": "Nahlédněte dovnitř...", - "status.admin_account": "Otevřít moderační rozhraní pro uživatele @{name}", - "status.admin_status": "Otevřít tento toot v moderačním rozhraní", + "status.admin_account": "Otevřít moderátorské rozhraní pro uživatele @{name}", + "status.admin_status": "Otevřít tento toot v moderátorském rozhraní", "status.block": "Zablokovat uživatele @{name}", "status.cancel_reblog_private": "Zrušit boost", "status.cannot_reblog": "Tento příspěvek nemůže být boostnutý", diff --git a/app/javascript/mastodon/locales/cy.json b/app/javascript/mastodon/locales/cy.json index 635226d7b..f03b54750 100644 --- a/app/javascript/mastodon/locales/cy.json +++ b/app/javascript/mastodon/locales/cy.json @@ -5,7 +5,6 @@ "account.block_domain": "Cuddio popeth rhag {domain}", "account.blocked": "Blociwyd", "account.direct": "Neges breifat @{name}", - "account.disclaimer_full": "Gall y wybodaeth isod adlewyrchu darlun anghyflawn o broffil defnyddiwr.", "account.domain_blocked": "Parth wedi ei guddio", "account.edit_profile": "Golygu proffil", "account.endorse": "Arddangos ar fy mhroffil", @@ -36,7 +35,6 @@ "account.unfollow": "Dad-ddilyn", "account.unmute": "Dad-dawelu @{name}", "account.unmute_notifications": "Dad-dawelu hysbysiadau o @{name}", - "account.view_full_profile": "Gweld proffil llawn", "alert.unexpected.message": "Digwyddodd gwall annisgwyl.", "alert.unexpected.title": "Wps!", "boost_modal.combo": "Mae modd gwasgu {combo} er mwyn sgipio hyn tro nesa", @@ -85,6 +83,7 @@ "compose_form.spoiler.unmarked": "Nid yw'r testun wedi ei guddio", "compose_form.spoiler_placeholder": "Ysgrifenwch eich rhybudd yma", "confirmation_modal.cancel": "Canslo", + "confirmations.block.block_and_report": "Block & Report", "confirmations.block.confirm": "Blocio", "confirmations.block.message": "Ydych chi'n sicr eich bod eisiau blocio {name}?", "confirmations.delete.confirm": "Dileu", @@ -133,7 +132,6 @@ "empty_column.mutes": "Nid ydych wedi tawelu unrhyw ddefnyddwyr eto.", "empty_column.notifications": "Nid oes gennych unrhyw hysbysiadau eto. Rhyngweithiwch ac eraill i ddechrau'r sgwrs.", "empty_column.public": "Does dim byd yma! Ysgrifennwch rhywbeth yn gyhoeddus, neu dilynwch ddefnyddwyr o achosion eraill i'w lenwi", - "error_boundary.it_crashed": "It crashed!", "follow_request.authorize": "Caniatau", "follow_request.reject": "Gwrthod", "getting_started.developers": "Datblygwyr", @@ -248,6 +246,7 @@ "notification.favourite": "hoffodd {name} eich tŵt", "notification.follow": "dilynodd {name} chi", "notification.mention": "Soniodd {name} amdanoch chi", + "notification.poll": "A poll you have voted in has ended", "notification.reblog": "Hysbysebodd {name} eich tŵt", "notifications.clear": "Clirio hysbysiadau", "notifications.clear_confirmation": "Ydych chi'n sicr eich bod am glirio'ch holl hysbysiadau am byth?", @@ -258,6 +257,7 @@ "notifications.column_settings.filter_bar.show": "Dangos", "notifications.column_settings.follow": "Dilynwyr newydd:", "notifications.column_settings.mention": "Crybwylliadau:", + "notifications.column_settings.poll": "Poll results:", "notifications.column_settings.push": "Hysbysiadau push", "notifications.column_settings.reblog": "Hybiadau:", "notifications.column_settings.show": "Dangos yn y golofn", @@ -267,6 +267,7 @@ "notifications.filter.favourites": "Ffefrynnau", "notifications.filter.follows": "Yn dilyn", "notifications.filter.mentions": "Crybwylliadau", + "notifications.filter.polls": "Poll results", "notifications.group": "{count} o hysbysiadau", "poll.closed": "Closed", "poll.refresh": "Refresh", @@ -308,7 +309,6 @@ "search_results.hashtags": "Hanshnodau", "search_results.statuses": "Tŵtiau", "search_results.total": "{count, number} {count, plural, one {result} arall {results}}", - "standalone.public_title": "Golwg tu fewn...", "status.admin_account": "Open moderation interface for @{name}", "status.admin_status": "Open this tŵt in the moderation interface", "status.block": "Blocio @{name}", diff --git a/app/javascript/mastodon/locales/da.json b/app/javascript/mastodon/locales/da.json index 86df1447e..1be8d989d 100644 --- a/app/javascript/mastodon/locales/da.json +++ b/app/javascript/mastodon/locales/da.json @@ -5,7 +5,6 @@ "account.block_domain": "Skjul alt fra {domain}", "account.blocked": "Blokeret", "account.direct": "Send en direkte besked til @{name}", - "account.disclaimer_full": "Nedenstående oplysninger reflekterer ikke nødvendigvis brugerens profil fuldstændigt.", "account.domain_blocked": "Domænet er blevet skjult", "account.edit_profile": "Rediger profil", "account.endorse": "Fremhæv på profil", @@ -36,7 +35,6 @@ "account.unfollow": "Følg ikke længere", "account.unmute": "Fjern dæmpningen af @{name}", "account.unmute_notifications": "Fjern dæmpningen af notifikationer fra @{name}", - "account.view_full_profile": "Se fuld profil", "alert.unexpected.message": "Der opstod en uventet fejl.", "alert.unexpected.title": "Ups!", "boost_modal.combo": "Du kan trykke {combo} for at springe dette over næste gang", @@ -85,6 +83,7 @@ "compose_form.spoiler.unmarked": "Teksten er ikke skjult", "compose_form.spoiler_placeholder": "Skriv din advarsel her", "confirmation_modal.cancel": "Annuller", + "confirmations.block.block_and_report": "Block & Report", "confirmations.block.confirm": "Bloker", "confirmations.block.message": "Er du sikker på, du vil blokere {name}?", "confirmations.delete.confirm": "Slet", @@ -117,7 +116,7 @@ "emoji_button.search_results": "Søgeresultater", "emoji_button.symbols": "Symboler", "emoji_button.travel": "Rejser & steder", - "empty_column.account_timeline": "No toots here!", + "empty_column.account_timeline": "Ingen bidrag her!", "empty_column.blocks": "Du har ikke blokeret nogen endnu.", "empty_column.community": "Den lokale tidslinje er tom. Skriv noget offentligt for at starte lavinen!", "empty_column.direct": "Du har endnu ingen direkte beskeder. Når du sender eller modtager en, vil den vises her.", @@ -132,8 +131,7 @@ "empty_column.lists": "Du har endnu ingen lister. Når du opretter en, vil den blive vist her.", "empty_column.mutes": "Du har endnu ikke dæmpet nogen som helst bruger.", "empty_column.notifications": "Du har endnu ingen notifikationer. Tag ud og bland dig med folkemængden for at starte samtalen.", - "empty_column.public": "Der er ikke noget at se her! Skriv noget offentligt eller start ud med manuelt at følge brugere fra andre instanser for st udfylde tomrummet", - "error_boundary.it_crashed": "It crashed!", + "empty_column.public": "Der er ikke noget at se her! Skriv noget offentligt eller start ud med manuelt at følge brugere fra andre server for at udfylde tomrummet", "follow_request.authorize": "Godkend", "follow_request.reject": "Afvis", "getting_started.developers": "Udviklere", @@ -144,9 +142,9 @@ "getting_started.open_source_notice": "Mastodon er et open source software. Du kan bidrage eller rapporterer fejl på GitHub {github}.", "getting_started.security": "Sikkerhed", "getting_started.terms": "Vilkår", - "hashtag.column_header.tag_mode.all": "and {additional}", - "hashtag.column_header.tag_mode.any": "or {additional}", - "hashtag.column_header.tag_mode.none": "without {additional}", + "hashtag.column_header.tag_mode.all": "og {additional}", + "hashtag.column_header.tag_mode.any": "eller {additional}", + "hashtag.column_header.tag_mode.none": "uden {additional}", "hashtag.column_settings.select.no_options_message": "No suggestions found", "hashtag.column_settings.select.placeholder": "Enter hashtags…", "hashtag.column_settings.tag_mode.all": "All of these", @@ -161,20 +159,20 @@ "intervals.full.minutes": "{number, plural, one {# minute} other {# minutes}}", "introduction.federation.action": "Næste", "introduction.federation.federated.headline": "Federated", - "introduction.federation.federated.text": "Public posts from other servers of the fediverse will appear in the federated timeline.", + "introduction.federation.federated.text": "Offentlige bidrag fra andre servere af fediversen vil komme til syne i den federated timeline.", "introduction.federation.home.headline": "Home", "introduction.federation.home.text": "Posts from people you follow will appear in your home feed. You can follow anyone on any server!", "introduction.federation.local.headline": "Local", "introduction.federation.local.text": "Public posts from people on the same server as you will appear in the local timeline.", - "introduction.interactions.action": "Finish tutorial!", - "introduction.interactions.favourite.headline": "Favourite", + "introduction.interactions.action": "Slut tutorial!", + "introduction.interactions.favourite.headline": "Favorisere", "introduction.interactions.favourite.text": "You can save a toot for later, and let the author know that you liked it, by favouriting it.", "introduction.interactions.reblog.headline": "Boost", "introduction.interactions.reblog.text": "You can share other people's toots with your followers by boosting them.", - "introduction.interactions.reply.headline": "Reply", - "introduction.interactions.reply.text": "You can reply to other people's and your own toots, which will chain them together in a conversation.", - "introduction.welcome.action": "Let's go!", - "introduction.welcome.headline": "First steps", + "introduction.interactions.reply.headline": "Svar", + "introduction.interactions.reply.text": "Du kan svare andres og din egen bidrag, hvilke vil kæde dem sammen i en konversation.", + "introduction.welcome.action": "Læd os gå!", + "introduction.welcome.headline": "Første skridt", "introduction.welcome.text": "Welcome to the fediverse! In a few moments, you'll be able to broadcast messages and talk to your friends across a wide variety of servers. But this server, {domain}, is special—it hosts your profile, so remember its name.", "keyboard_shortcuts.back": "for at navigere dig tilbage", "keyboard_shortcuts.blocked": "for at åbne listen over blokerede brugere", @@ -248,6 +246,7 @@ "notification.favourite": "{name} favoriserede din status", "notification.follow": "{name} fulgte dig", "notification.mention": "{name} nævnte dig", + "notification.poll": "A poll you have voted in has ended", "notification.reblog": "{name} fremhævede din status", "notifications.clear": "Ryd notifikationer", "notifications.clear_confirmation": "Er du sikker på, du vil rydde alle dine notifikationer permanent?", @@ -258,6 +257,7 @@ "notifications.column_settings.filter_bar.show": "Show", "notifications.column_settings.follow": "Nye følgere:", "notifications.column_settings.mention": "Omtale:", + "notifications.column_settings.poll": "Poll results:", "notifications.column_settings.push": "Push notifikationer", "notifications.column_settings.reblog": "Fremhævelser:", "notifications.column_settings.show": "Vis i kolonne", @@ -267,6 +267,7 @@ "notifications.filter.favourites": "Favoritter", "notifications.filter.follows": "Følger", "notifications.filter.mentions": "Mentions", + "notifications.filter.polls": "Poll results", "notifications.group": "{count} notifikationer", "poll.closed": "Closed", "poll.refresh": "Refresh", @@ -308,7 +309,6 @@ "search_results.hashtags": "Emnetags", "search_results.statuses": "Trut", "search_results.total": "{count, number} {count, plural, et {result} andre {results}}", - "standalone.public_title": "Et kig indenfor...", "status.admin_account": "Open moderation interface for @{name}", "status.admin_status": "Open this status in the moderation interface", "status.block": "Bloker @{name}", diff --git a/app/javascript/mastodon/locales/de.json b/app/javascript/mastodon/locales/de.json index 734737c55..a335af1bd 100644 --- a/app/javascript/mastodon/locales/de.json +++ b/app/javascript/mastodon/locales/de.json @@ -5,7 +5,6 @@ "account.block_domain": "Alles von {domain} verstecken", "account.blocked": "Blockiert", "account.direct": "Direktnachricht an @{name}", - "account.disclaimer_full": "Das Profil wird möglicherweise unvollständig wiedergegeben.", "account.domain_blocked": "Domain versteckt", "account.edit_profile": "Profil bearbeiten", "account.endorse": "Auf Profil hervorheben", @@ -36,7 +35,6 @@ "account.unfollow": "Entfolgen", "account.unmute": "@{name} nicht mehr stummschalten", "account.unmute_notifications": "Benachrichtigungen von @{name} einschalten", - "account.view_full_profile": "Vollständiges Profil anzeigen", "alert.unexpected.message": "Ein unerwarteter Fehler ist aufgetreten.", "alert.unexpected.title": "Hoppla!", "boost_modal.combo": "Du kannst {combo} drücken, um dies beim nächsten Mal zu überspringen", @@ -73,10 +71,10 @@ "compose_form.lock_disclaimer": "Dein Profil ist nicht {locked}. Wer dir folgen will, kann das jederzeit tun und dann auch deine privaten Beiträge sehen.", "compose_form.lock_disclaimer.lock": "gesperrt", "compose_form.placeholder": "Was gibt's Neues?", - "compose_form.poll.add_option": "Add a choice", - "compose_form.poll.duration": "Poll duration", - "compose_form.poll.option_placeholder": "Choice {number}", - "compose_form.poll.remove_option": "Remove this choice", + "compose_form.poll.add_option": "Eine Auswahl hinzufügen", + "compose_form.poll.duration": "Umfragedauer", + "compose_form.poll.option_placeholder": "Auswahl {number}", + "compose_form.poll.remove_option": "Auswahl entfernen", "compose_form.publish": "Tröt", "compose_form.publish_loud": "{publish}!", "compose_form.sensitive.marked": "Medien sind als heikel markiert", @@ -85,6 +83,7 @@ "compose_form.spoiler.unmarked": "Text ist nicht versteckt", "compose_form.spoiler_placeholder": "Inhaltswarnung", "confirmation_modal.cancel": "Abbrechen", + "confirmations.block.block_and_report": "Block & Report", "confirmations.block.confirm": "Blockieren", "confirmations.block.message": "Bist du dir sicher, dass du {name} blockieren möchtest?", "confirmations.delete.confirm": "Löschen", @@ -133,7 +132,6 @@ "empty_column.mutes": "Du hast keine Profile stummgeschaltet.", "empty_column.notifications": "Du hast noch keine Mitteilungen. Interagiere mit anderen, um ins Gespräch zu kommen.", "empty_column.public": "Hier ist nichts zu sehen! Schreibe etwas öffentlich oder folge Profilen von anderen Servern, um die Zeitleiste aufzufüllen", - "error_boundary.it_crashed": "It crashed!", "follow_request.authorize": "Erlauben", "follow_request.reject": "Ablehnen", "getting_started.developers": "Entwickler", @@ -147,18 +145,18 @@ "hashtag.column_header.tag_mode.all": "und {additional}", "hashtag.column_header.tag_mode.any": "oder {additional}", "hashtag.column_header.tag_mode.none": "ohne {additional}", - "hashtag.column_settings.select.no_options_message": "No suggestions found", - "hashtag.column_settings.select.placeholder": "Enter hashtags…", + "hashtag.column_settings.select.no_options_message": "Keine Vorschläge gefunden", + "hashtag.column_settings.select.placeholder": "Hashtags eintragen…", "hashtag.column_settings.tag_mode.all": "All diese", "hashtag.column_settings.tag_mode.any": "Eine von diesen", "hashtag.column_settings.tag_mode.none": "Keine von diesen", - "hashtag.column_settings.tag_toggle": "Include additional tags in this column", + "hashtag.column_settings.tag_toggle": "Zusätzliche Tags für diese Spalte einfügen", "home.column_settings.basic": "Einfach", "home.column_settings.show_reblogs": "Geteilte Beiträge anzeigen", "home.column_settings.show_replies": "Antworten anzeigen", - "intervals.full.days": "{number, plural, one {# day} other {# days}}", - "intervals.full.hours": "{number, plural, one {# hour} other {# hours}}", - "intervals.full.minutes": "{number, plural, one {# minute} other {# minutes}}", + "intervals.full.days": "{number, plural, one {# Tag} other {# Tage}}", + "intervals.full.hours": "{number, plural, one {# Stunde} other {# Stunden}}", + "intervals.full.minutes": "{number, plural, one {# Minute} other {# Minuten}}", "introduction.federation.action": "Weiter", "introduction.federation.federated.headline": "Föderiert", "introduction.federation.federated.text": "Öffentliche Beiträge von anderen Servern im Fediverse erscheinen in der föderierten Zeitleiste.", @@ -214,7 +212,7 @@ "lists.account.remove": "Von der Liste entfernen", "lists.delete": "Delete list", "lists.edit": "Liste bearbeiten", - "lists.edit.submit": "Change title", + "lists.edit.submit": "Titel ändern", "lists.new.create": "Liste hinzufügen", "lists.new.title_placeholder": "Neuer Titel der Liste", "lists.search": "Suche nach Leuten denen du folgst", @@ -248,6 +246,7 @@ "notification.favourite": "{name} hat deinen Beitrag favorisiert", "notification.follow": "{name} folgt dir", "notification.mention": "{name} hat dich erwähnt", + "notification.poll": "Eine Umfrage in der du abgestimmt hast ist vorbei", "notification.reblog": "{name} hat deinen Beitrag geteilt", "notifications.clear": "Mitteilungen löschen", "notifications.clear_confirmation": "Bist du dir sicher, dass du alle Mitteilungen löschen möchtest?", @@ -258,6 +257,7 @@ "notifications.column_settings.filter_bar.show": "Anzeigen", "notifications.column_settings.follow": "Neue Folgende:", "notifications.column_settings.mention": "Erwähnungen:", + "notifications.column_settings.poll": "Ergebnisse der Umfrage:", "notifications.column_settings.push": "Push-Benachrichtigungen", "notifications.column_settings.reblog": "Geteilte Beiträge:", "notifications.column_settings.show": "In der Spalte anzeigen", @@ -267,13 +267,14 @@ "notifications.filter.favourites": "Favoriten", "notifications.filter.follows": "Folgende", "notifications.filter.mentions": "Erwähnungen", + "notifications.filter.polls": "Ergebnisse der Umfrage", "notifications.group": "{count} Benachrichtigungen", - "poll.closed": "Closed", - "poll.refresh": "Refresh", - "poll.total_votes": "{count, plural, one {# vote} other {# votes}}", - "poll.vote": "Vote", - "poll_button.add_poll": "Add a poll", - "poll_button.remove_poll": "Remove poll", + "poll.closed": "Geschlossen", + "poll.refresh": "Aktualisieren", + "poll.total_votes": "{count, plural, one {# Stimme} other {# Stimmen}}", + "poll.vote": "Abstimmen", + "poll_button.add_poll": "Eine Umfrage erstellen", + "poll_button.remove_poll": "Umfrage entfernen", "privacy.change": "Sichtbarkeit des Beitrags anpassen", "privacy.direct.long": "Beitrag nur an erwähnte Profile", "privacy.direct.short": "Direkt", @@ -308,7 +309,6 @@ "search_results.hashtags": "Hashtags", "search_results.statuses": "Beiträge", "search_results.total": "{count, number} {count, plural, one {Ergebnis} other {Ergebnisse}}", - "standalone.public_title": "Ein kleiner Einblick …", "status.admin_account": "Öffne Moderationsoberfläche für @{name}", "status.admin_status": "Öffne diesen Status in der Moderationsoberfläche", "status.block": "Blockiere @{name}", @@ -356,17 +356,17 @@ "tabs_bar.local_timeline": "Lokal", "tabs_bar.notifications": "Mitteilungen", "tabs_bar.search": "Suchen", - "time_remaining.days": "{number, plural, one {# day} other {# days}} left", - "time_remaining.hours": "{number, plural, one {# hour} other {# hours}} left", - "time_remaining.minutes": "{number, plural, one {# minute} other {# minutes}} left", - "time_remaining.moments": "Moments remaining", - "time_remaining.seconds": "{number, plural, one {# second} other {# seconds}} left", + "time_remaining.days": "{number, plural, one {# Tag} other {# Tage}} verbleibend", + "time_remaining.hours": "{number, plural, one {# Stunde} other {# Stunden}} verbleibend", + "time_remaining.minutes": "{number, plural, one {# Minute} other {# Minuten}} verbleibend", + "time_remaining.moments": "Momente verbleibend", + "time_remaining.seconds": "{number, plural, one {# Sekunde} other {# Sekunden}} verbleibend", "trends.count_by_accounts": "{count} {rawCount, plural, eine {Person} other {Personen}} reden darüber", "ui.beforeunload": "Dein Entwurf geht verloren, wenn du Mastodon verlässt.", "upload_area.title": "Zum Hochladen hereinziehen", "upload_button.label": "Mediendatei hinzufügen (JPEG, PNG, GIF, WebM, MP4, MOV)", "upload_error.limit": "Dateiupload-Limit erreicht.", - "upload_error.poll": "File upload not allowed with polls.", + "upload_error.poll": "Dateiuploads sind in Kombination mit Umfragen nicht erlaubt.", "upload_form.description": "Für Menschen mit Sehbehinderung beschreiben", "upload_form.focus": "Thumbnail bearbeiten", "upload_form.undo": "Löschen", diff --git a/app/javascript/mastodon/locales/defaultMessages.json b/app/javascript/mastodon/locales/defaultMessages.json index 8261ce578..a83933d57 100644 --- a/app/javascript/mastodon/locales/defaultMessages.json +++ b/app/javascript/mastodon/locales/defaultMessages.json @@ -480,6 +480,10 @@ "id": "confirmations.reply.message" }, { + "defaultMessage": "Block & Report", + "id": "confirmations.block.block_and_report" + }, + { "defaultMessage": "Are you sure you want to block {name}?", "id": "confirmations.block.message" } @@ -527,6 +531,10 @@ "id": "confirmations.domain_block.confirm" }, { + "defaultMessage": "Block & Report", + "id": "confirmations.block.block_and_report" + }, + { "defaultMessage": "Are you sure you want to unfollow {name}?", "id": "confirmations.unfollow.message" }, @@ -553,24 +561,40 @@ { "descriptors": [ { - "defaultMessage": "Mention @{name}", - "id": "account.mention" + "defaultMessage": "Unfollow", + "id": "account.unfollow" }, { - "defaultMessage": "Direct message @{name}", - "id": "account.direct" + "defaultMessage": "Follow", + "id": "account.follow" }, { - "defaultMessage": "Edit profile", - "id": "account.edit_profile" + "defaultMessage": "Awaiting approval. Click to cancel follow request", + "id": "account.requested" }, { "defaultMessage": "Unblock @{name}", "id": "account.unblock" }, { - "defaultMessage": "Unfollow", - "id": "account.unfollow" + "defaultMessage": "Edit profile", + "id": "account.edit_profile" + }, + { + "defaultMessage": "Ownership of this link was checked on {date}", + "id": "account.link_verified_on" + }, + { + "defaultMessage": "This account privacy status is set to locked. The owner manually reviews who can follow them.", + "id": "account.locked_info" + }, + { + "defaultMessage": "Mention @{name}", + "id": "account.mention" + }, + { + "defaultMessage": "Direct message @{name}", + "id": "account.direct" }, { "defaultMessage": "Unmute @{name}", @@ -585,10 +609,6 @@ "id": "account.mute" }, { - "defaultMessage": "Follow", - "id": "account.follow" - }, - { "defaultMessage": "Report @{name}", "id": "account.report" }, @@ -665,59 +685,6 @@ "id": "status.admin_account" }, { - "defaultMessage": "Information below may reflect the user's profile incompletely.", - "id": "account.disclaimer_full" - }, - { - "defaultMessage": "View full profile", - "id": "account.view_full_profile" - }, - { - "defaultMessage": "Toots", - "id": "account.posts" - }, - { - "defaultMessage": "Follows", - "id": "account.follows" - }, - { - "defaultMessage": "Followers", - "id": "account.followers" - } - ], - "path": "app/javascript/mastodon/features/account/components/action_bar.json" - }, - { - "descriptors": [ - { - "defaultMessage": "Unfollow", - "id": "account.unfollow" - }, - { - "defaultMessage": "Follow", - "id": "account.follow" - }, - { - "defaultMessage": "Awaiting approval. Click to cancel follow request", - "id": "account.requested" - }, - { - "defaultMessage": "Unblock @{name}", - "id": "account.unblock" - }, - { - "defaultMessage": "Edit profile", - "id": "account.edit_profile" - }, - { - "defaultMessage": "Ownership of this link was checked on {date}", - "id": "account.link_verified_on" - }, - { - "defaultMessage": "This account privacy status is set to locked. The owner manually reviews who can follow them.", - "id": "account.locked_info" - }, - { "defaultMessage": "Follows you", "id": "account.follows_you" }, @@ -736,6 +703,18 @@ { "defaultMessage": "Bot", "id": "account.badges.bot" + }, + { + "defaultMessage": "Toots", + "id": "account.posts" + }, + { + "defaultMessage": "Follows", + "id": "account.follows" + }, + { + "defaultMessage": "Followers", + "id": "account.followers" } ], "path": "app/javascript/mastodon/features/account/components/header.json" @@ -2100,6 +2079,10 @@ "id": "confirmations.reply.message" }, { + "defaultMessage": "Block & Report", + "id": "confirmations.block.block_and_report" + }, + { "defaultMessage": "Are you sure you want to block {name}?", "id": "confirmations.block.message" } @@ -2149,6 +2132,10 @@ "id": "confirmations.reply.message" }, { + "defaultMessage": "Block & Report", + "id": "confirmations.block.block_and_report" + }, + { "defaultMessage": "Are you sure you want to block {name}?", "id": "confirmations.block.message" } diff --git a/app/javascript/mastodon/locales/el.json b/app/javascript/mastodon/locales/el.json index d0bbc830b..701410a81 100644 --- a/app/javascript/mastodon/locales/el.json +++ b/app/javascript/mastodon/locales/el.json @@ -5,7 +5,6 @@ "account.block_domain": "Απόκρυψε τα πάντα από το {domain}", "account.blocked": "Αποκλεισμένος/η", "account.direct": "Προσωπικό μήνυμα προς @{name}", - "account.disclaimer_full": "Οι παρακάτω πληροφορίες μπορει να μην αντανακλούν το προφίλ του χρήστη επαρκως.", "account.domain_blocked": "Κρυμμένος τομέας", "account.edit_profile": "Επεξεργασία προφίλ", "account.endorse": "Προβολή στο προφίλ", @@ -36,7 +35,6 @@ "account.unfollow": "Διακοπή παρακολούθησης", "account.unmute": "Διακοπή αποσιώπησης του/της @{name}", "account.unmute_notifications": "Διακοπή αποσιώπησης ειδοποιήσεων του/της @{name}", - "account.view_full_profile": "Δες το πλήρες προφίλ", "alert.unexpected.message": "Προέκυψε απροσδόκητο σφάλμα.", "alert.unexpected.title": "Εεπ!", "boost_modal.combo": "Μπορείς να πατήσεις {combo} για να το προσπεράσεις αυτό την επόμενη φορά", @@ -85,6 +83,7 @@ "compose_form.spoiler.unmarked": "Μη κρυμμένο κείμενο", "compose_form.spoiler_placeholder": "Γράψε την προειδοποίησή σου εδώ", "confirmation_modal.cancel": "Άκυρο", + "confirmations.block.block_and_report": "Block & Report", "confirmations.block.confirm": "Απόκλεισε", "confirmations.block.message": "Σίγουρα θες να αποκλείσεις τον/την {name};", "confirmations.delete.confirm": "Διέγραψε", @@ -133,7 +132,6 @@ "empty_column.mutes": "Δεν έχεις αποσιωπήσει κανένα χρήστη ακόμα.", "empty_column.notifications": "Δεν έχεις ειδοποιήσεις ακόμα. Αλληλεπίδρασε με άλλους χρήστες για να ξεκινήσεις την κουβέντα.", "empty_column.public": "Δεν υπάρχει τίποτα εδώ! Γράψε κάτι δημόσιο, ή ακολούθησε χειροκίνητα χρήστες από άλλους κόμβους για να τη γεμίσεις", - "error_boundary.it_crashed": "It crashed!", "follow_request.authorize": "Ενέκρινε", "follow_request.reject": "Απέρριψε", "getting_started.developers": "Ανάπτυξη", @@ -158,7 +156,7 @@ "home.column_settings.show_replies": "Εμφάνιση απαντήσεων", "intervals.full.days": "{number, plural, one {# day} other {# days}}", "intervals.full.hours": "{number, plural, one {# hour} other {# hours}}", - "intervals.full.minutes": "{number, plural, one {# minute} other {# minutes}}", + "intervals.full.minutes": "{number, plural, one {# λεπτό} other {# λεπτά}}", "introduction.federation.action": "Επόμενο", "introduction.federation.federated.headline": "Ομοσπονδιακή", "introduction.federation.federated.text": "Οι δημόσιες αναρτήσεις από άλλους κόμβους του fediverse θα εμφανίζονται στην ομοσπονδιακή ροή.", @@ -248,6 +246,7 @@ "notification.favourite": "Ο/Η {name} σημείωσε ως αγαπημένη την κατάστασή σου", "notification.follow": "Ο/Η {name} σε ακολούθησε", "notification.mention": "Ο/Η {name} σε ανέφερε", + "notification.poll": "Έλαβε τέλος μια από τις ψηφοφορίες που συμμετείχες", "notification.reblog": "Ο/Η {name} προώθησε την κατάστασή σου", "notifications.clear": "Καθαρισμός ειδοποιήσεων", "notifications.clear_confirmation": "Σίγουρα θέλεις να καθαρίσεις όλες τις ειδοποιήσεις σου;", @@ -258,6 +257,7 @@ "notifications.column_settings.filter_bar.show": "Εμφάνιση", "notifications.column_settings.follow": "Νέοι ακόλουθοι:", "notifications.column_settings.mention": "Αναφορές:", + "notifications.column_settings.poll": "Αποτελέσματα ψηφοφορίας:", "notifications.column_settings.push": "Άμεσες ειδοποιήσεις", "notifications.column_settings.reblog": "Προωθήσεις:", "notifications.column_settings.show": "Εμφάνισε σε στήλη", @@ -267,6 +267,7 @@ "notifications.filter.favourites": "Αγαπημένα", "notifications.filter.follows": "Ακόλουθοι", "notifications.filter.mentions": "Αναφορές", + "notifications.filter.polls": "Αποτελέσματα ψηφοφορίας", "notifications.group": "{count} ειδοποιήσεις", "poll.closed": "Κλειστή", "poll.refresh": "Ανανέωση", @@ -308,7 +309,6 @@ "search_results.hashtags": "Ταμπέλες", "search_results.statuses": "Τουτ", "search_results.total": "{count, number} {count, plural, zero {αποτελέσματα} one {αποτέλεσμα} other {αποτελέσματα}}", - "standalone.public_title": "Μια πρώτη γεύση...", "status.admin_account": "Άνοιγμα λειτουργίας διαμεσολάβησης για τον/την @{name}", "status.admin_status": "Άνοιγμα αυτής της δημοσίευσης στη λειτουργία διαμεσολάβησης", "status.block": "Αποκλεισμός @{name}", diff --git a/app/javascript/mastodon/locales/en.json b/app/javascript/mastodon/locales/en.json index 1c45d6f20..e47081f9e 100644 --- a/app/javascript/mastodon/locales/en.json +++ b/app/javascript/mastodon/locales/en.json @@ -5,7 +5,6 @@ "account.block_domain": "Hide everything from {domain}", "account.blocked": "Blocked", "account.direct": "Direct message @{name}", - "account.disclaimer_full": "Information below may reflect the user's profile incompletely.", "account.domain_blocked": "Domain hidden", "account.edit_profile": "Edit profile", "account.endorse": "Feature on profile", @@ -36,7 +35,6 @@ "account.unfollow": "Unfollow", "account.unmute": "Unmute @{name}", "account.unmute_notifications": "Unmute notifications from @{name}", - "account.view_full_profile": "View full profile", "alert.unexpected.message": "An unexpected error occurred.", "alert.unexpected.title": "Oops!", "boost_modal.combo": "You can press {combo} to skip this next time", @@ -89,6 +87,7 @@ "compose_form.spoiler.unmarked": "Text is not hidden", "compose_form.spoiler_placeholder": "Write your warning here", "confirmation_modal.cancel": "Cancel", + "confirmations.block.block_and_report": "Block & Report", "confirmations.block.confirm": "Block", "confirmations.block.message": "Are you sure you want to block {name}?", "confirmations.delete.confirm": "Delete", diff --git a/app/javascript/mastodon/locales/eo.json b/app/javascript/mastodon/locales/eo.json index 05e7e12d8..dd2188d8e 100644 --- a/app/javascript/mastodon/locales/eo.json +++ b/app/javascript/mastodon/locales/eo.json @@ -5,7 +5,6 @@ "account.block_domain": "Kaŝi ĉion de {domain}", "account.blocked": "Blokita", "account.direct": "Rekte mesaĝi @{name}", - "account.disclaimer_full": "Subaj informoj povas reflekti la profilon de la uzanto nekomplete.", "account.domain_blocked": "Domajno kaŝita", "account.edit_profile": "Redakti profilon", "account.endorse": "Montri en profilo", @@ -36,7 +35,6 @@ "account.unfollow": "Ne plu sekvi", "account.unmute": "Malsilentigi @{name}", "account.unmute_notifications": "Malsilentigi sciigojn de @{name}", - "account.view_full_profile": "Vidi plenan profilon", "alert.unexpected.message": "Neatendita eraro okazis.", "alert.unexpected.title": "Ups!", "boost_modal.combo": "Vi povas premi {combo} por preterpasi sekvafoje", @@ -85,6 +83,7 @@ "compose_form.spoiler.unmarked": "Teksto ne kaŝita", "compose_form.spoiler_placeholder": "Skribu vian averton ĉi tie", "confirmation_modal.cancel": "Nuligi", + "confirmations.block.block_and_report": "Block & Report", "confirmations.block.confirm": "Bloki", "confirmations.block.message": "Ĉu vi certas, ke vi volas bloki {name}?", "confirmations.delete.confirm": "Forigi", @@ -133,7 +132,6 @@ "empty_column.mutes": "Vi ne ankoraŭ silentigis iun uzanton.", "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 serviloj por plenigi la publikan tempolinion", - "error_boundary.it_crashed": "It crashed!", "follow_request.authorize": "Rajtigi", "follow_request.reject": "Rifuzi", "getting_started.developers": "Programistoj", @@ -152,13 +150,13 @@ "hashtag.column_settings.tag_mode.all": "Ĉiuj", "hashtag.column_settings.tag_mode.any": "Iu ajn", "hashtag.column_settings.tag_mode.none": "Neniu", - "hashtag.column_settings.tag_toggle": "Include additional tags in this column", + "hashtag.column_settings.tag_toggle": "Inkluzivi pluajn etikedojn por ĉi tiu kolumno", "home.column_settings.basic": "Bazaj agordoj", "home.column_settings.show_reblogs": "Montri diskonigojn", "home.column_settings.show_replies": "Montri respondojn", "intervals.full.days": "{number, plural, one {# day} other {# days}}", "intervals.full.hours": "{number, plural, one {# hour} other {# hours}}", - "intervals.full.minutes": "{number, plural, one {# minute} other {# minutes}}", + "intervals.full.minutes": "{number, plural, one {# minuto} other {# minutoj}}", "introduction.federation.action": "Sekva", "introduction.federation.federated.headline": "Federated", "introduction.federation.federated.text": "Publikaj mesaĝoj el aliaj serviloj de la Fediverse aperos en la fratara tempolinio.", @@ -248,6 +246,7 @@ "notification.favourite": "{name} stelumis vian mesaĝon", "notification.follow": "{name} eksekvis vin", "notification.mention": "{name} menciis vin", + "notification.poll": "A poll you have voted in has ended", "notification.reblog": "{name} diskonigis vian mesaĝon", "notifications.clear": "Forviŝi sciigojn", "notifications.clear_confirmation": "Ĉu vi certas, ke vi volas porĉiame forviŝi ĉiujn viajn sciigojn?", @@ -258,6 +257,7 @@ "notifications.column_settings.filter_bar.show": "Montri", "notifications.column_settings.follow": "Novaj sekvantoj:", "notifications.column_settings.mention": "Mencioj:", + "notifications.column_settings.poll": "Poll results:", "notifications.column_settings.push": "Puŝsciigoj", "notifications.column_settings.reblog": "Diskonigoj:", "notifications.column_settings.show": "Montri en kolumno", @@ -267,6 +267,7 @@ "notifications.filter.favourites": "Stelumoj", "notifications.filter.follows": "Sekvoj", "notifications.filter.mentions": "Mencioj", + "notifications.filter.polls": "Poll results", "notifications.group": "{count} sciigoj", "poll.closed": "Finita", "poll.refresh": "Aktualigi", @@ -308,7 +309,6 @@ "search_results.hashtags": "Kradvortoj", "search_results.statuses": "Mesaĝoj", "search_results.total": "{count, number} {count, plural, one {rezulto} other {rezultoj}}", - "standalone.public_title": "Enrigardo…", "status.admin_account": "Malfermi la kontrolan interfacon por @{name}", "status.admin_status": "Malfermi ĉi tiun mesaĝon en la kontrola interfaco", "status.block": "Bloki @{name}", diff --git a/app/javascript/mastodon/locales/es.json b/app/javascript/mastodon/locales/es.json index bf20e5f9d..97d03d840 100644 --- a/app/javascript/mastodon/locales/es.json +++ b/app/javascript/mastodon/locales/es.json @@ -5,7 +5,6 @@ "account.block_domain": "Ocultar todo de {domain}", "account.blocked": "Bloqueado", "account.direct": "Direct Message @{name}", - "account.disclaimer_full": "La siguiente información del usuario puede estar incompleta.", "account.domain_blocked": "Dominio oculto", "account.edit_profile": "Editar perfil", "account.endorse": "Mostrar en perfil", @@ -36,7 +35,6 @@ "account.unfollow": "Dejar de seguir", "account.unmute": "Dejar de silenciar a @{name}", "account.unmute_notifications": "Dejar de silenciar las notificaciones de @{name}", - "account.view_full_profile": "Ver perfil completo", "alert.unexpected.message": "Hubo un error inesperado.", "alert.unexpected.title": "Oops!", "boost_modal.combo": "Puedes presionar {combo} para saltear este aviso la próxima vez", @@ -85,6 +83,7 @@ "compose_form.spoiler.unmarked": "Texto no oculto", "compose_form.spoiler_placeholder": "Advertencia de contenido", "confirmation_modal.cancel": "Cancelar", + "confirmations.block.block_and_report": "Block & Report", "confirmations.block.confirm": "Bloquear", "confirmations.block.message": "¿Estás seguro de que quieres bloquear a {name}?", "confirmations.delete.confirm": "Eliminar", @@ -133,7 +132,6 @@ "empty_column.mutes": "Aún no has silenciado a ningún usuario.", "empty_column.notifications": "No tienes ninguna notificación aún. Interactúa con otros para empezar una conversación.", "empty_column.public": "¡No hay nada aquí! Escribe algo públicamente, o sigue usuarios de otras instancias manualmente para llenarlo", - "error_boundary.it_crashed": "It crashed!", "follow_request.authorize": "Autorizar", "follow_request.reject": "Rechazar", "getting_started.developers": "Desarrolladores", @@ -248,6 +246,7 @@ "notification.favourite": "{name} marcó tu estado como favorito", "notification.follow": "{name} te empezó a seguir", "notification.mention": "{name} te ha mencionado", + "notification.poll": "A poll you have voted in has ended", "notification.reblog": "{name} ha retooteado tu estado", "notifications.clear": "Limpiar notificaciones", "notifications.clear_confirmation": "¿Seguro que quieres limpiar permanentemente todas tus notificaciones?", @@ -258,6 +257,7 @@ "notifications.column_settings.filter_bar.show": "Show", "notifications.column_settings.follow": "Nuevos seguidores:", "notifications.column_settings.mention": "Menciones:", + "notifications.column_settings.poll": "Poll results:", "notifications.column_settings.push": "Notificaciones push", "notifications.column_settings.reblog": "Retoots:", "notifications.column_settings.show": "Mostrar en columna", @@ -267,6 +267,7 @@ "notifications.filter.favourites": "Favourites", "notifications.filter.follows": "Follows", "notifications.filter.mentions": "Mentions", + "notifications.filter.polls": "Poll results", "notifications.group": "{count} notificaciones", "poll.closed": "Closed", "poll.refresh": "Refresh", @@ -308,7 +309,6 @@ "search_results.hashtags": "Etiquetas", "search_results.statuses": "Toots", "search_results.total": "{count, number} {count, plural, one {resultado} other {resultados}}", - "standalone.public_title": "Un pequeño vistazo...", "status.admin_account": "Open moderation interface for @{name}", "status.admin_status": "Open this status in the moderation interface", "status.block": "Block @{name}", diff --git a/app/javascript/mastodon/locales/eu.json b/app/javascript/mastodon/locales/eu.json index 0915ee6cc..17f84dc27 100644 --- a/app/javascript/mastodon/locales/eu.json +++ b/app/javascript/mastodon/locales/eu.json @@ -5,7 +5,6 @@ "account.block_domain": "Ezkutatu {domain} domeinuko guztia", "account.blocked": "Blokeatuta", "account.direct": "Mezu zuzena @{name}(r)i", - "account.disclaimer_full": "Baliteke beheko informazioak erabiltzailearen profilaren zati bat baino ez erakustea.", "account.domain_blocked": "Ezkutatutako domeinua", "account.edit_profile": "Aldatu profila", "account.endorse": "Nabarmendu profilean", @@ -36,7 +35,6 @@ "account.unfollow": "Jarraitzeari utzi", "account.unmute": "Desmututu @{name}", "account.unmute_notifications": "Desmututu @{name}(r)en jakinarazpenak", - "account.view_full_profile": "Ikusi profil osoa", "alert.unexpected.message": "Ustekabeko errore bat gertatu da.", "alert.unexpected.title": "Ene!", "boost_modal.combo": "{combo} sakatu dezakezu hurrengoan hau saltatzeko", @@ -85,6 +83,7 @@ "compose_form.spoiler.unmarked": "Testua ez dago ezkutatuta", "compose_form.spoiler_placeholder": "Idatzi zure abisua hemen", "confirmation_modal.cancel": "Utzi", + "confirmations.block.block_and_report": "Block & Report", "confirmations.block.confirm": "Block", "confirmations.block.message": "Ziur {name} blokeatu nahi duzula?", "confirmations.delete.confirm": "Ezabatu", @@ -133,7 +132,6 @@ "empty_column.mutes": "Ez duzu erabiltzailerik mututu oraindik.", "empty_column.notifications": "Ez duzu jakinarazpenik oraindik. Jarri besteekin harremanetan elkarrizketa abiatzeko.", "empty_column.public": "Ez dago ezer hemen! Idatzi zerbait publikoki edo jarraitu eskuz beste zerbitzari batzuetako erabiltzaileak hau betetzen joateko", - "error_boundary.it_crashed": "It crashed!", "follow_request.authorize": "Baimendu", "follow_request.reject": "Ukatu", "getting_started.developers": "Garatzaileak", @@ -248,6 +246,7 @@ "notification.favourite": "{name}(e)k zure mezua gogoko du", "notification.follow": "{name}(e)k jarraitzen zaitu", "notification.mention": "{name}(e)k aipatu zaitu", + "notification.poll": "A poll you have voted in has ended", "notification.reblog": "{name}(e)k bultzada eman dio zure mezuari", "notifications.clear": "Garbitu jakinarazpenak", "notifications.clear_confirmation": "Ziur zure jakinarazpen guztiak behin betirako garbitu nahi dituzula?", @@ -258,6 +257,7 @@ "notifications.column_settings.filter_bar.show": "Erakutsi", "notifications.column_settings.follow": "Jarraitzaile berriak:", "notifications.column_settings.mention": "Aipamenak:", + "notifications.column_settings.poll": "Poll results:", "notifications.column_settings.push": "Push jakinarazpenak", "notifications.column_settings.reblog": "Bultzadak:", "notifications.column_settings.show": "Erakutsi zutabean", @@ -267,6 +267,7 @@ "notifications.filter.favourites": "Gogokoak", "notifications.filter.follows": "Jarraipenak", "notifications.filter.mentions": "Aipamenak", + "notifications.filter.polls": "Poll results", "notifications.group": "{count} jakinarazpen", "poll.closed": "Closed", "poll.refresh": "Refresh", @@ -308,7 +309,6 @@ "search_results.hashtags": "Traolak", "search_results.statuses": "Toot-ak", "search_results.total": "{count, number} {count, plural, one {result} other {results}}", - "standalone.public_title": "Begiradatxo bat...", "status.admin_account": "Ireki @{name} erabiltzailearen moderazio interfazea", "status.admin_status": "Ireki mezu hau moderazio interfazean", "status.block": "Block @{name}", diff --git a/app/javascript/mastodon/locales/fa.json b/app/javascript/mastodon/locales/fa.json index e4003d6a0..91a27e366 100644 --- a/app/javascript/mastodon/locales/fa.json +++ b/app/javascript/mastodon/locales/fa.json @@ -5,7 +5,6 @@ "account.block_domain": "پنهانسازی همه چیز از سرور {domain}", "account.blocked": "مسدودشده", "account.direct": "پیغام خصوصی به @{name}", - "account.disclaimer_full": "اطلاعات زیر ممکن است نمایهٔ این کاربر را به تمامی نشان ندهد.", "account.domain_blocked": "دامین پنهانشده", "account.edit_profile": "ویرایش نمایه", "account.endorse": "نمایش در نمایه", @@ -36,7 +35,6 @@ "account.unfollow": "پایان پیگیری", "account.unmute": "باصدا کردن @{name}", "account.unmute_notifications": "باصداکردن اعلانها از طرف @{name}", - "account.view_full_profile": "نمایش نمایهٔ کامل", "alert.unexpected.message": "خطای پیشبینینشدهای رخ داد.", "alert.unexpected.title": "ای وای!", "boost_modal.combo": "دکمهٔ {combo} را بزنید تا دیگر این را نبینید", @@ -73,10 +71,10 @@ "compose_form.lock_disclaimer": "حساب شما {locked} نیست. هر کسی میتواند پیگیر شما شود و نوشتههای ویژهٔ پیگیران شما را ببیند.", "compose_form.lock_disclaimer.lock": "قفل", "compose_form.placeholder": "تازه چه خبر؟", - "compose_form.poll.add_option": "Add a choice", - "compose_form.poll.duration": "Poll duration", - "compose_form.poll.option_placeholder": "Choice {number}", - "compose_form.poll.remove_option": "Remove this choice", + "compose_form.poll.add_option": "افزودن گزینه", + "compose_form.poll.duration": "مدت نظرسنجی", + "compose_form.poll.option_placeholder": "گزینهٔ {number}", + "compose_form.poll.remove_option": "حذف این گزینه", "compose_form.publish": "بوق", "compose_form.publish_loud": "{publish}!", "compose_form.sensitive.marked": "این تصویر به عنوان حساس علامتگذاری شده", @@ -85,6 +83,7 @@ "compose_form.spoiler.unmarked": "نوشته پنهان نیست", "compose_form.spoiler_placeholder": "هشدار محتوا", "confirmation_modal.cancel": "بیخیال", + "confirmations.block.block_and_report": "مسدودسازی و گزارش", "confirmations.block.confirm": "مسدود کن", "confirmations.block.message": "آیا واقعاً میخواهید {name} را مسدود کنید؟", "confirmations.delete.confirm": "پاک کن", @@ -133,7 +132,6 @@ "empty_column.mutes": "شما هنوز هیچ کاربری را بیصدا نکردهاید.", "empty_column.notifications": "هنوز هیچ اعلانی ندارید. به نوشتههای دیگران واکنش نشان دهید تا گفتگو آغاز شود.", "empty_column.public": "اینجا هنوز چیزی نیست! خودتان چیزی بنویسید یا کاربران سرورهای دیگر را پی بگیرید تا اینجا پر شود", - "error_boundary.it_crashed": "It crashed!", "follow_request.authorize": "اجازه دهید", "follow_request.reject": "اجازه ندهید", "getting_started.developers": "برای برنامهنویسان", @@ -156,9 +154,9 @@ "home.column_settings.basic": "اصلی", "home.column_settings.show_reblogs": "نمایش بازبوقها", "home.column_settings.show_replies": "نمایش پاسخها", - "intervals.full.days": "{number, plural, one {# day} other {# days}}", - "intervals.full.hours": "{number, plural, one {# hour} other {# hours}}", - "intervals.full.minutes": "{number, plural, one {# minute} other {# minutes}}", + "intervals.full.days": "{number, plural, one {# روز} other {# روز}}", + "intervals.full.hours": "{number, plural, one {# ساعت} other {# ساعت}}", + "intervals.full.minutes": "{number, plural, one {# دقیقه} other {# دقیقه}}", "introduction.federation.action": "بعدی", "introduction.federation.federated.headline": "فهرست همهٔ سرورها", "introduction.federation.federated.text": "نوشتههای عمومی سرورهای دیگر در این فهرست نمایش مییابند.", @@ -248,6 +246,7 @@ "notification.favourite": "{name} نوشتهٔ شما را پسندید", "notification.follow": "{name} پیگیر شما شد", "notification.mention": "{name} از شما نام برد", + "notification.poll": "نظرسنجیای که در آن رأی دادید به پایان رسیده است", "notification.reblog": "{name} نوشتهٔ شما را بازبوقید", "notifications.clear": "پاککردن اعلانها", "notifications.clear_confirmation": "واقعاً میخواهید همهٔ اعلانهایتان را برای همیشه پاک کنید؟", @@ -258,6 +257,7 @@ "notifications.column_settings.filter_bar.show": "نمایش", "notifications.column_settings.follow": "پیگیران تازه:", "notifications.column_settings.mention": "نامبردنها:", + "notifications.column_settings.poll": "نتایج نظرسنجی:", "notifications.column_settings.push": "اعلانها از سمت سرور", "notifications.column_settings.reblog": "بازبوقها:", "notifications.column_settings.show": "نمایش در ستون", @@ -267,13 +267,14 @@ "notifications.filter.favourites": "پسندیدهها", "notifications.filter.follows": "پیگیریها", "notifications.filter.mentions": "گفتگوها", + "notifications.filter.polls": "نتایج نظرسنجی", "notifications.group": "{count} اعلان", "poll.closed": "پایانیافته", "poll.refresh": "بهروزرسانی", "poll.total_votes": "{count, plural, one {# رأی} other {# رأی}}", "poll.vote": "رأی", - "poll_button.add_poll": "Add a poll", - "poll_button.remove_poll": "Remove poll", + "poll_button.add_poll": "افزودن نظرسنجی", + "poll_button.remove_poll": "حذف نظرسنجی", "privacy.change": "تنظیم حریم خصوصی نوشتهها", "privacy.direct.long": "تنها به کاربران نامبردهشده نشان بده", "privacy.direct.short": "مستقیم", @@ -308,7 +309,6 @@ "search_results.hashtags": "هشتگها", "search_results.statuses": "بوقها", "search_results.total": "{count, number} {count, plural, one {نتیجه} other {نتیجه}}", - "standalone.public_title": "نگاهی به کاربران این سرور...", "status.admin_account": "محیط مدیریت مربوط به @{name} را باز کن", "status.admin_status": "این نوشته را در محیط مدیریت باز کن", "status.block": "مسدودسازی @{name}", @@ -356,19 +356,19 @@ "tabs_bar.local_timeline": "محلی", "tabs_bar.notifications": "اعلانها", "tabs_bar.search": "جستجو", - "time_remaining.days": "{number, plural, one {# روز} other {# روز}} left", - "time_remaining.hours": "{number, plural, one {# ساعت} other {# ساعت}} left", - "time_remaining.minutes": "{number, plural, one {# دقیقه} other {# دقیقه}} left", + "time_remaining.days": "{number, plural, one {# روز} other {# روز}} باقی مانده", + "time_remaining.hours": "{number, plural, one {# ساعت} other {# ساعت}} باقی مانده", + "time_remaining.minutes": "{number, plural, one {# دقیقه} other {# دقیقه}} باقی مانده", "time_remaining.moments": "زمان باقیمانده", - "time_remaining.seconds": "{number, plural, one {# ثانیه} other {# ثانیه}} left", + "time_remaining.seconds": "{number, plural, one {# ثانیه} other {# ثانیه}} باقی مانده", "trends.count_by_accounts": "{count} {rawCount, plural, one {نفر نوشته است} other {نفر نوشتهاند}}", "ui.beforeunload": "اگر از ماستدون خارج شوید پیشنویس شما پاک خواهد شد.", "upload_area.title": "برای بارگذاری به اینجا بکشید", "upload_button.label": "افزودن عکس و ویدیو (JPEG, PNG, GIF, WebM, MP4, MOV)", "upload_error.limit": "از حد مجاز باگذاری فراتر رفتید.", - "upload_error.poll": "File upload not allowed with polls.", + "upload_error.poll": "باگذاری پرونده در نظرسنجیها ممکن نیست.", "upload_form.description": "نوشتهٔ توضیحی برای کمبینایان و نابینایان", - "upload_form.focus": "بریدن لبهها", + "upload_form.focus": "تغییر پیشنمایش", "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 9949d741e..68381f6b3 100644 --- a/app/javascript/mastodon/locales/fi.json +++ b/app/javascript/mastodon/locales/fi.json @@ -5,7 +5,6 @@ "account.block_domain": "Piilota kaikki sisältö verkkotunnuksesta {domain}", "account.blocked": "Estetty", "account.direct": "Viesti käyttäjälle @{name}", - "account.disclaimer_full": "Alla olevat käyttäjän profiilitiedot saattavat olla epätäydellisiä.", "account.domain_blocked": "Verkko-osoite piilotettu", "account.edit_profile": "Muokkaa", "account.endorse": "Suosittele profiilissasi", @@ -36,7 +35,6 @@ "account.unfollow": "Lakkaa seuraamasta", "account.unmute": "Poista käyttäjän @{name} mykistys", "account.unmute_notifications": "Poista mykistys käyttäjän @{name} ilmoituksilta", - "account.view_full_profile": "Näytä koko profiili", "alert.unexpected.message": "Tapahtui odottamaton virhe.", "alert.unexpected.title": "Hups!", "boost_modal.combo": "Ensi kerralla voit ohittaa tämän painamalla {combo}", @@ -85,6 +83,7 @@ "compose_form.spoiler.unmarked": "Teksti ei ole piilotettu", "compose_form.spoiler_placeholder": "Sisältövaroitus", "confirmation_modal.cancel": "Peruuta", + "confirmations.block.block_and_report": "Block & Report", "confirmations.block.confirm": "Estä", "confirmations.block.message": "Haluatko varmasti estää käyttäjän {name}?", "confirmations.delete.confirm": "Poista", @@ -133,7 +132,6 @@ "empty_column.mutes": "Et ole mykistänyt vielä yhtään käyttäjää.", "empty_column.notifications": "Sinulle ei ole vielä ilmoituksia. Aloita keskustelu juttelemalla muille.", "empty_column.public": "Täällä ei ole mitään! Saat sisältöä, kun kirjoitat jotain julkisesti tai käyt seuraamassa muiden instanssien käyttäjiä", - "error_boundary.it_crashed": "It crashed!", "follow_request.authorize": "Valtuuta", "follow_request.reject": "Hylkää", "getting_started.developers": "Kehittäjille", @@ -248,6 +246,7 @@ "notification.favourite": "{name} tykkäsi tilastasi", "notification.follow": "{name} seurasi sinua", "notification.mention": "{name} mainitsi sinut", + "notification.poll": "A poll you have voted in has ended", "notification.reblog": "{name} buustasi tilaasi", "notifications.clear": "Tyhjennä ilmoitukset", "notifications.clear_confirmation": "Haluatko varmasti poistaa kaikki ilmoitukset pysyvästi?", @@ -258,6 +257,7 @@ "notifications.column_settings.filter_bar.show": "Show", "notifications.column_settings.follow": "Uudet seuraajat:", "notifications.column_settings.mention": "Maininnat:", + "notifications.column_settings.poll": "Poll results:", "notifications.column_settings.push": "Push-ilmoitukset", "notifications.column_settings.reblog": "Buustit:", "notifications.column_settings.show": "Näytä sarakkeessa", @@ -267,6 +267,7 @@ "notifications.filter.favourites": "Favourites", "notifications.filter.follows": "Follows", "notifications.filter.mentions": "Mentions", + "notifications.filter.polls": "Poll results", "notifications.group": "{count} notifications", "poll.closed": "Closed", "poll.refresh": "Refresh", @@ -308,7 +309,6 @@ "search_results.hashtags": "Hashtagit", "search_results.statuses": "Tuuttaukset", "search_results.total": "{count, number} {count, plural, one {result} other {results}}", - "standalone.public_title": "Kurkistus sisälle...", "status.admin_account": "Open moderation interface for @{name}", "status.admin_status": "Open this status in the moderation interface", "status.block": "Estä @{name}", diff --git a/app/javascript/mastodon/locales/fr.json b/app/javascript/mastodon/locales/fr.json index b257a16b9..4d7451248 100644 --- a/app/javascript/mastodon/locales/fr.json +++ b/app/javascript/mastodon/locales/fr.json @@ -5,7 +5,6 @@ "account.block_domain": "Tout masquer venant de {domain}", "account.blocked": "Bloqué", "account.direct": "Envoyer un message direct à @{name}", - "account.disclaimer_full": "Les données ci-dessous peuvent ne pas refléter ce profil dans sa totalité.", "account.domain_blocked": "Domaine caché", "account.edit_profile": "Modifier le profil", "account.endorse": "Figure sur le profil", @@ -36,7 +35,6 @@ "account.unfollow": "Ne plus suivre", "account.unmute": "Ne plus masquer @{name}", "account.unmute_notifications": "Réactiver les notifications de @{name}", - "account.view_full_profile": "Afficher le profil complet", "alert.unexpected.message": "Une erreur inattendue s’est produite.", "alert.unexpected.title": "Oups !", "boost_modal.combo": "Vous pouvez appuyer sur {combo} pour pouvoir passer ceci, la prochaine fois", @@ -85,6 +83,7 @@ "compose_form.spoiler.unmarked": "Le texte n’est pas caché", "compose_form.spoiler_placeholder": "Écrivez ici votre avertissement", "confirmation_modal.cancel": "Annuler", + "confirmations.block.block_and_report": "Block & Report", "confirmations.block.confirm": "Bloquer", "confirmations.block.message": "Confirmez-vous le blocage de {name} ?", "confirmations.delete.confirm": "Supprimer", @@ -133,7 +132,6 @@ "empty_column.mutes": "Vous n’avez pas encore mis d'utilisateur·rice·s en silence.", "empty_column.notifications": "Vous n’avez pas encore de notification. Interagissez avec d’autres personnes pour débuter la conversation.", "empty_column.public": "Il n’y a rien ici ! Écrivez quelque chose publiquement, ou bien suivez manuellement des personnes d’autres instances pour remplir le fil public", - "error_boundary.it_crashed": "It crashed!", "follow_request.authorize": "Accepter", "follow_request.reject": "Rejeter", "getting_started.developers": "Développeur·euse·s", @@ -248,6 +246,7 @@ "notification.favourite": "{name} a ajouté à ses favoris :", "notification.follow": "{name} vous suit", "notification.mention": "{name} vous a mentionné :", + "notification.poll": "A poll you have voted in has ended", "notification.reblog": "{name} a partagé votre statut :", "notifications.clear": "Nettoyer les notifications", "notifications.clear_confirmation": "Voulez-vous vraiment supprimer toutes vos notifications ?", @@ -258,6 +257,7 @@ "notifications.column_settings.filter_bar.show": "Afficher", "notifications.column_settings.follow": "Nouveaux⋅elles abonné⋅e·s :", "notifications.column_settings.mention": "Mentions :", + "notifications.column_settings.poll": "Poll results:", "notifications.column_settings.push": "Notifications", "notifications.column_settings.reblog": "Partages :", "notifications.column_settings.show": "Afficher dans la colonne", @@ -267,6 +267,7 @@ "notifications.filter.favourites": "Favoris", "notifications.filter.follows": "Abonné·e·s", "notifications.filter.mentions": "Mentions", + "notifications.filter.polls": "Poll results", "notifications.group": "{count} notifications", "poll.closed": "Fermé", "poll.refresh": "Actualiser", @@ -308,7 +309,6 @@ "search_results.hashtags": "Hashtags", "search_results.statuses": "Pouets", "search_results.total": "{count, number} {count, plural, one {résultat} other {résultats}}", - "standalone.public_title": "Un aperçu…", "status.admin_account": "Ouvrir l'interface de modération pour @{name}", "status.admin_status": "Ouvrir ce statut dans l'interface de modération", "status.block": "Bloquer @{name}", diff --git a/app/javascript/mastodon/locales/gl.json b/app/javascript/mastodon/locales/gl.json index 83adc563f..3011e7d07 100644 --- a/app/javascript/mastodon/locales/gl.json +++ b/app/javascript/mastodon/locales/gl.json @@ -5,7 +5,6 @@ "account.block_domain": "Ocultar calquer contido de {domain}", "account.blocked": "Bloqueada", "account.direct": "Mensaxe directa @{name}", - "account.disclaimer_full": "A información inferior podería mostrar un perfil incompleto da usuaria.", "account.domain_blocked": "Dominio agochado", "account.edit_profile": "Editar perfil", "account.endorse": "Mostrado no perfil", @@ -36,7 +35,6 @@ "account.unfollow": "Non seguir", "account.unmute": "Non acalar @{name}", "account.unmute_notifications": "Desbloquear as notificacións de @{name}", - "account.view_full_profile": "Ver o perfil completo", "alert.unexpected.message": "Aconteceu un fallo non agardado.", "alert.unexpected.title": "Vaia!", "boost_modal.combo": "Pulse {combo} para saltar esto a próxima vez", @@ -85,6 +83,7 @@ "compose_form.spoiler.unmarked": "O texto non está agochado", "compose_form.spoiler_placeholder": "Escriba o aviso aquí", "confirmation_modal.cancel": "Cancelar", + "confirmations.block.block_and_report": "Block & Report", "confirmations.block.confirm": "Bloquear", "confirmations.block.message": "Está segura de querer bloquear a {name}?", "confirmations.delete.confirm": "Borrar", @@ -133,7 +132,6 @@ "empty_column.mutes": "Non acalou ningunha usuaria polo de agora.", "empty_column.notifications": "Aínda non ten notificacións. Interactúe con outras para iniciar unha conversa.", "empty_column.public": "Nada por aquí! Escriba algo de xeito público, ou siga manualmente usuarias de outros servidores para ir enchéndoa", - "error_boundary.it_crashed": "It crashed!", "follow_request.authorize": "Autorizar", "follow_request.reject": "Rexeitar", "getting_started.developers": "Desenvolvedoras", @@ -152,13 +150,13 @@ "hashtag.column_settings.tag_mode.all": "Todos estos", "hashtag.column_settings.tag_mode.any": "Calquera de estos", "hashtag.column_settings.tag_mode.none": "Ningún de estos", - "hashtag.column_settings.tag_toggle": "Include additional tags in this column", + "hashtag.column_settings.tag_toggle": "Incluír etiquetas adicionais para esta columna", "home.column_settings.basic": "Básico", "home.column_settings.show_reblogs": "Mostrar repeticións", "home.column_settings.show_replies": "Mostrar respostas", "intervals.full.days": "{number, plural, one {# day} other {# days}}", "intervals.full.hours": "{number, plural, one {# hour} other {# hours}}", - "intervals.full.minutes": "{number, plural, one {# minute} other {# minutes}}", + "intervals.full.minutes": "{number, plural, one {# minuto} other {# minutos}}", "introduction.federation.action": "Seguinte", "introduction.federation.federated.headline": "Federated", "introduction.federation.federated.text": "Publicacións públicas desde outros servidores do fediverso aparecerán na liña temporal federada.", @@ -248,6 +246,7 @@ "notification.favourite": "{name} marcou como favorito o seu estado", "notification.follow": "{name} está a seguila", "notification.mention": "{name} mencionoute", + "notification.poll": "Unha sondaxe na que votou xa rematou", "notification.reblog": "{name} promoveu o seu estado", "notifications.clear": "Limpar notificacións", "notifications.clear_confirmation": "Estás seguro de que queres limpar permanentemente todas as túas notificacións?", @@ -258,6 +257,7 @@ "notifications.column_settings.filter_bar.show": "Mostrar", "notifications.column_settings.follow": "Novos seguidores:", "notifications.column_settings.mention": "Mencións:", + "notifications.column_settings.poll": "Resultados da sondaxe:", "notifications.column_settings.push": "Enviar notificacións", "notifications.column_settings.reblog": "Promocións:", "notifications.column_settings.show": "Mostrar en columna", @@ -267,6 +267,7 @@ "notifications.filter.favourites": "Favoritos", "notifications.filter.follows": "Seguimentos", "notifications.filter.mentions": "Mencións", + "notifications.filter.polls": "Resultados da sondaxe", "notifications.group": "{count} notificacións", "poll.closed": "Closed", "poll.refresh": "Refresh", @@ -308,7 +309,6 @@ "search_results.hashtags": "Etiquetas", "search_results.statuses": "Toots", "search_results.total": "{count, number} {count,plural,one {result} outros {results}}", - "standalone.public_title": "Ollada dentro...", "status.admin_account": "Abrir interface de moderación para @{name}", "status.admin_status": "Abrir este estado na interface de moderación", "status.block": "Block @{name}", diff --git a/app/javascript/mastodon/locales/he.json b/app/javascript/mastodon/locales/he.json index 07d2a9c34..c136c111f 100644 --- a/app/javascript/mastodon/locales/he.json +++ b/app/javascript/mastodon/locales/he.json @@ -5,7 +5,6 @@ "account.block_domain": "להסתיר הכל מהקהילה {domain}", "account.blocked": "Blocked", "account.direct": "Direct Message @{name}", - "account.disclaimer_full": "המידע להלן עשוי להיות לא עדכני או לא שלם.", "account.domain_blocked": "Domain hidden", "account.edit_profile": "עריכת פרופיל", "account.endorse": "Feature on profile", @@ -36,7 +35,6 @@ "account.unfollow": "הפסקת מעקב", "account.unmute": "הפסקת השתקת @{name}", "account.unmute_notifications": "להפסיק הסתרת הודעות מעם @{name}", - "account.view_full_profile": "הצגת פרופיל מלא", "alert.unexpected.message": "אירעה שגיאה בלתי צפויה.", "alert.unexpected.title": "אופס!", "boost_modal.combo": "ניתן להקיש {combo} כדי לדלג בפעם הבאה", @@ -85,6 +83,7 @@ "compose_form.spoiler.unmarked": "Text is not hidden", "compose_form.spoiler_placeholder": "אזהרת תוכן", "confirmation_modal.cancel": "ביטול", + "confirmations.block.block_and_report": "Block & Report", "confirmations.block.confirm": "לחסום", "confirmations.block.message": "לחסום את {name}?", "confirmations.delete.confirm": "למחוק", @@ -133,7 +132,6 @@ "empty_column.mutes": "You haven't muted any users yet.", "empty_column.notifications": "אין התראות עדיין. יאללה, הגיע הזמן להתחיל להתערבב.", "empty_column.public": "אין פה כלום! כדי למלא את הטור הזה אפשר לכתוב משהו, או להתחיל לעקוב אחרי אנשים מקהילות אחרות", - "error_boundary.it_crashed": "It crashed!", "follow_request.authorize": "קבלה", "follow_request.reject": "דחיה", "getting_started.developers": "Developers", @@ -248,6 +246,7 @@ "notification.favourite": "חצרוצך חובב על ידי {name}", "notification.follow": "{name} במעקב אחרייך", "notification.mention": "אוזכרת על ידי {name}", + "notification.poll": "A poll you have voted in has ended", "notification.reblog": "חצרוצך הודהד על ידי {name}", "notifications.clear": "הסרת התראות", "notifications.clear_confirmation": "להסיר את כל ההתראות? בטוח?", @@ -258,6 +257,7 @@ "notifications.column_settings.filter_bar.show": "Show", "notifications.column_settings.follow": "עוקבים חדשים:", "notifications.column_settings.mention": "פניות:", + "notifications.column_settings.poll": "Poll results:", "notifications.column_settings.push": "הודעות בדחיפה", "notifications.column_settings.reblog": "הדהודים:", "notifications.column_settings.show": "הצגה בטור", @@ -267,6 +267,7 @@ "notifications.filter.favourites": "Favourites", "notifications.filter.follows": "Follows", "notifications.filter.mentions": "Mentions", + "notifications.filter.polls": "Poll results", "notifications.group": "{count} notifications", "poll.closed": "Closed", "poll.refresh": "Refresh", @@ -308,7 +309,6 @@ "search_results.hashtags": "Hashtags", "search_results.statuses": "Toots", "search_results.total": "{count, number} {count, plural, one {תוצאה} other {תוצאות}}", - "standalone.public_title": "הצצה פנימה...", "status.admin_account": "Open moderation interface for @{name}", "status.admin_status": "Open this status in the moderation interface", "status.block": "Block @{name}", diff --git a/app/javascript/mastodon/locales/hr.json b/app/javascript/mastodon/locales/hr.json index 0312da592..86bd01a79 100644 --- a/app/javascript/mastodon/locales/hr.json +++ b/app/javascript/mastodon/locales/hr.json @@ -5,7 +5,6 @@ "account.block_domain": "Sakrij sve sa {domain}", "account.blocked": "Blocked", "account.direct": "Direct Message @{name}", - "account.disclaimer_full": "Ovaj korisnik je sa druge instance. Ovaj broj bi mogao biti veći.", "account.domain_blocked": "Domain hidden", "account.edit_profile": "Uredi profil", "account.endorse": "Feature on profile", @@ -36,7 +35,6 @@ "account.unfollow": "Prestani slijediti", "account.unmute": "Poništi utišavanje @{name}", "account.unmute_notifications": "Unmute notifications from @{name}", - "account.view_full_profile": "View full profile", "alert.unexpected.message": "An unexpected error occurred.", "alert.unexpected.title": "Oops!", "boost_modal.combo": "Možeš pritisnuti {combo} kako bi ovo preskočio sljedeći put", @@ -85,6 +83,7 @@ "compose_form.spoiler.unmarked": "Text is not hidden", "compose_form.spoiler_placeholder": "Upozorenje o sadržaju", "confirmation_modal.cancel": "Otkaži", + "confirmations.block.block_and_report": "Block & Report", "confirmations.block.confirm": "Blokiraj", "confirmations.block.message": "Želiš li sigurno blokirati {name}?", "confirmations.delete.confirm": "Obriši", @@ -133,7 +132,6 @@ "empty_column.mutes": "You haven't muted any users yet.", "empty_column.notifications": "Još nemaš notifikacija. Komuniciraj sa drugima kako bi započeo razgovor.", "empty_column.public": "Ovdje nema ništa! Napiši nešto javno, ili ručno slijedi korisnike sa drugih instanci kako bi popunio", - "error_boundary.it_crashed": "It crashed!", "follow_request.authorize": "Autoriziraj", "follow_request.reject": "Odbij", "getting_started.developers": "Developers", @@ -248,6 +246,7 @@ "notification.favourite": "{name} je lajkao tvoj status", "notification.follow": "{name} te sada slijedi", "notification.mention": "{name} te je spomenuo", + "notification.poll": "A poll you have voted in has ended", "notification.reblog": "{name} je podigao tvoj status", "notifications.clear": "Očisti notifikacije", "notifications.clear_confirmation": "Želiš li zaista obrisati sve svoje notifikacije?", @@ -258,6 +257,7 @@ "notifications.column_settings.filter_bar.show": "Show", "notifications.column_settings.follow": "Novi sljedbenici:", "notifications.column_settings.mention": "Spominjanja:", + "notifications.column_settings.poll": "Poll results:", "notifications.column_settings.push": "Push notifications", "notifications.column_settings.reblog": "Boostovi:", "notifications.column_settings.show": "Prikaži u stupcu", @@ -267,6 +267,7 @@ "notifications.filter.favourites": "Favourites", "notifications.filter.follows": "Follows", "notifications.filter.mentions": "Mentions", + "notifications.filter.polls": "Poll results", "notifications.group": "{count} notifications", "poll.closed": "Closed", "poll.refresh": "Refresh", @@ -308,7 +309,6 @@ "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.admin_account": "Open moderation interface for @{name}", "status.admin_status": "Open this status in the moderation interface", "status.block": "Block @{name}", diff --git a/app/javascript/mastodon/locales/hu.json b/app/javascript/mastodon/locales/hu.json index 20b21be73..507e04400 100644 --- a/app/javascript/mastodon/locales/hu.json +++ b/app/javascript/mastodon/locales/hu.json @@ -5,7 +5,6 @@ "account.block_domain": "Minden elrejtése innen: {domain}", "account.blocked": "Blocked", "account.direct": "Direct Message @{name}", - "account.disclaimer_full": "Az alul található információk hiányosan mutathatják be a felhasználót.", "account.domain_blocked": "Domain hidden", "account.edit_profile": "Profil szerkesztése", "account.endorse": "Feature on profile", @@ -36,7 +35,6 @@ "account.unfollow": "Követés abbahagyása", "account.unmute": "@{name} kinémítása", "account.unmute_notifications": "@{name} értesítéseinek kinémítása", - "account.view_full_profile": "Teljes profil megtekintése", "alert.unexpected.message": "An unexpected error occurred.", "alert.unexpected.title": "Oops!", "boost_modal.combo": "Megnyomhatod {combo}, hogy átugord következő alkalommal", @@ -85,6 +83,7 @@ "compose_form.spoiler.unmarked": "Text is not hidden", "compose_form.spoiler_placeholder": "Figyelmeztetését írja ide", "confirmation_modal.cancel": "Bezár", + "confirmations.block.block_and_report": "Block & Report", "confirmations.block.confirm": "Letilt", "confirmations.block.message": "Biztos benne, hogy le szeretné tiltani {name}?", "confirmations.delete.confirm": "Töröl", @@ -133,7 +132,6 @@ "empty_column.mutes": "You haven't muted any users yet.", "empty_column.notifications": "Jelenleg nincsenek értesítései. Lépj kapcsolatba másokkal, hogy indítsd el a beszélgetést.", "empty_column.public": "Jelenleg semmi nincs itt! Írj valamit publikusan vagy kövess más szervereken levő felhasználókat, hogy megtöltsd", - "error_boundary.it_crashed": "It crashed!", "follow_request.authorize": "Engedélyez", "follow_request.reject": "Visszautasít", "getting_started.developers": "Developers", @@ -248,6 +246,7 @@ "notification.favourite": "{name} kedvencnek jelölte az állapotod", "notification.follow": "{name} követ téged", "notification.mention": "{name} megemlített", + "notification.poll": "A poll you have voted in has ended", "notification.reblog": "{name} rebloggolta az állapotod", "notifications.clear": "Értesítések törlése", "notifications.clear_confirmation": "Biztos benne, hogy véglegesen törölni akarja az összes értesítését?", @@ -258,6 +257,7 @@ "notifications.column_settings.filter_bar.show": "Show", "notifications.column_settings.follow": "Új követők:", "notifications.column_settings.mention": "Megemítéseim:", + "notifications.column_settings.poll": "Poll results:", "notifications.column_settings.push": "Push értesítések", "notifications.column_settings.reblog": "Rebloggolások:", "notifications.column_settings.show": "Oszlopban mutatás", @@ -267,6 +267,7 @@ "notifications.filter.favourites": "Favourites", "notifications.filter.follows": "Follows", "notifications.filter.mentions": "Mentions", + "notifications.filter.polls": "Poll results", "notifications.group": "{count} notifications", "poll.closed": "Closed", "poll.refresh": "Refresh", @@ -308,7 +309,6 @@ "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.admin_account": "Open moderation interface for @{name}", "status.admin_status": "Open this status in the moderation interface", "status.block": "Block @{name}", diff --git a/app/javascript/mastodon/locales/hy.json b/app/javascript/mastodon/locales/hy.json index b96d9499e..a4c8bffba 100644 --- a/app/javascript/mastodon/locales/hy.json +++ b/app/javascript/mastodon/locales/hy.json @@ -5,7 +5,6 @@ "account.block_domain": "Թաքցնել ամենը հետեւյալ տիրույթից՝ {domain}", "account.blocked": "Blocked", "account.direct": "Direct Message @{name}", - "account.disclaimer_full": "Ներքոհիշյալը կարող է ոչ ամբողջությամբ արտացոլել օգտատիրոջ էջի տվյալները։", "account.domain_blocked": "Domain hidden", "account.edit_profile": "Խմբագրել անձնական էջը", "account.endorse": "Feature on profile", @@ -36,7 +35,6 @@ "account.unfollow": "Չհետեւել", "account.unmute": "Ապալռեցնել @{name}֊ին", "account.unmute_notifications": "Միացնել ծանուցումները @{name}֊ից", - "account.view_full_profile": "Դիտել ամբողջական տարբերակը։", "alert.unexpected.message": "An unexpected error occurred.", "alert.unexpected.title": "Oops!", "boost_modal.combo": "Կարող ես սեղմել {combo}՝ սա հաջորդ անգամ բաց թողնելու համար", @@ -85,6 +83,7 @@ "compose_form.spoiler.unmarked": "Text is not hidden", "compose_form.spoiler_placeholder": "Գրիր նախազգուշացումդ այստեղ", "confirmation_modal.cancel": "Չեղարկել", + "confirmations.block.block_and_report": "Block & Report", "confirmations.block.confirm": "Արգելափակել", "confirmations.block.message": "Վստա՞հ ես, որ ուզում ես արգելափակել {name}֊ին։", "confirmations.delete.confirm": "Ջնջել", @@ -133,7 +132,6 @@ "empty_column.mutes": "You haven't muted any users yet.", "empty_column.notifications": "Ոչ մի ծանուցում դեռ չունես։ Բզիր մյուսներին՝ խոսակցությունը սկսելու համար։", "empty_column.public": "Այստեղ բան չկա՛։ Հրապարակային մի բան գրիր կամ հետեւիր այլ հանգույցներից էակների՝ այն լցնելու համար։", - "error_boundary.it_crashed": "It crashed!", "follow_request.authorize": "Վավերացնել", "follow_request.reject": "Մերժել", "getting_started.developers": "Developers", @@ -248,6 +246,7 @@ "notification.favourite": "{name} հավանեց թութդ", "notification.follow": "{name} սկսեց հետեւել քեզ", "notification.mention": "{name} նշեց քեզ", + "notification.poll": "A poll you have voted in has ended", "notification.reblog": "{name} տարածեց թութդ", "notifications.clear": "Մաքրել ծանուցումները", "notifications.clear_confirmation": "Վստա՞հ ես, որ ուզում ես մշտապես մաքրել քո բոլոր ծանուցումները։", @@ -258,6 +257,7 @@ "notifications.column_settings.filter_bar.show": "Show", "notifications.column_settings.follow": "Նոր հետեւողներ՝", "notifications.column_settings.mention": "Նշումներ՝", + "notifications.column_settings.poll": "Poll results:", "notifications.column_settings.push": "Հրելու ծանուցումներ", "notifications.column_settings.reblog": "Տարածածներից՝", "notifications.column_settings.show": "Ցուցադրել սյունում", @@ -267,6 +267,7 @@ "notifications.filter.favourites": "Favourites", "notifications.filter.follows": "Follows", "notifications.filter.mentions": "Mentions", + "notifications.filter.polls": "Poll results", "notifications.group": "{count} notifications", "poll.closed": "Closed", "poll.refresh": "Refresh", @@ -308,7 +309,6 @@ "search_results.hashtags": "Hashtags", "search_results.statuses": "Toots", "search_results.total": "{count, number} {count, plural, one {result} other {results}}", - "standalone.public_title": "Այս պահին…", "status.admin_account": "Open moderation interface for @{name}", "status.admin_status": "Open this status in the moderation interface", "status.block": "Արգելափակել @{name}֊ին", diff --git a/app/javascript/mastodon/locales/id.json b/app/javascript/mastodon/locales/id.json index 2b00ece08..5319705dc 100644 --- a/app/javascript/mastodon/locales/id.json +++ b/app/javascript/mastodon/locales/id.json @@ -5,7 +5,6 @@ "account.block_domain": "Sembunyikan segalanya dari {domain}", "account.blocked": "Terblokir", "account.direct": "Direct Message @{name}", - "account.disclaimer_full": "Informasi di bawah mungkin tidak mencerminkan profil user secara lengkap.", "account.domain_blocked": "Domain disembunyikan", "account.edit_profile": "Ubah profil", "account.endorse": "Feature on profile", @@ -36,7 +35,6 @@ "account.unfollow": "Berhenti mengikuti", "account.unmute": "Berhenti membisukan @{name}", "account.unmute_notifications": "Munculkan notifikasi dari @{name}", - "account.view_full_profile": "Lihat profil lengkap", "alert.unexpected.message": "An unexpected error occurred.", "alert.unexpected.title": "Oops!", "boost_modal.combo": "Anda dapat menekan {combo} untuk melewati ini", @@ -85,6 +83,7 @@ "compose_form.spoiler.unmarked": "Teks tidak tersembunyi", "compose_form.spoiler_placeholder": "Peringatan konten", "confirmation_modal.cancel": "Batal", + "confirmations.block.block_and_report": "Block & Report", "confirmations.block.confirm": "Blokir", "confirmations.block.message": "Apa anda yakin ingin memblokir {name}?", "confirmations.delete.confirm": "Hapus", @@ -133,7 +132,6 @@ "empty_column.mutes": "You haven't muted any users yet.", "empty_column.notifications": "Anda tidak memiliki notifikasi apapun. Berinteraksi dengan orang lain untuk memulai percakapan.", "empty_column.public": "Tidak ada apapun disini! Tulis sesuatu, atau ikuti pengguna lain dari server lain untuk mengisi ini", - "error_boundary.it_crashed": "It crashed!", "follow_request.authorize": "Izinkan", "follow_request.reject": "Tolak", "getting_started.developers": "Developers", @@ -248,6 +246,7 @@ "notification.favourite": "{name} menyukai status anda", "notification.follow": "{name} mengikuti anda", "notification.mention": "{name} mentioned you", + "notification.poll": "A poll you have voted in has ended", "notification.reblog": "{name} mem-boost status anda", "notifications.clear": "Hapus notifikasi", "notifications.clear_confirmation": "Apa anda yakin hendak menghapus semua notifikasi anda?", @@ -258,6 +257,7 @@ "notifications.column_settings.filter_bar.show": "Show", "notifications.column_settings.follow": "Pengikut baru:", "notifications.column_settings.mention": "Balasan:", + "notifications.column_settings.poll": "Poll results:", "notifications.column_settings.push": "Push notifications", "notifications.column_settings.reblog": "Boost:", "notifications.column_settings.show": "Tampilkan dalam kolom", @@ -267,6 +267,7 @@ "notifications.filter.favourites": "Favourites", "notifications.filter.follows": "Follows", "notifications.filter.mentions": "Mentions", + "notifications.filter.polls": "Poll results", "notifications.group": "{count} notifications", "poll.closed": "Closed", "poll.refresh": "Refresh", @@ -308,7 +309,6 @@ "search_results.hashtags": "Hashtags", "search_results.statuses": "Toots", "search_results.total": "{count, number} {count, plural, one {hasil} other {hasil}}", - "standalone.public_title": "A look inside...", "status.admin_account": "Open moderation interface for @{name}", "status.admin_status": "Open this status in the moderation interface", "status.block": "Block @{name}", diff --git a/app/javascript/mastodon/locales/io.json b/app/javascript/mastodon/locales/io.json index 7e0e5563c..300bc4484 100644 --- a/app/javascript/mastodon/locales/io.json +++ b/app/javascript/mastodon/locales/io.json @@ -5,7 +5,6 @@ "account.block_domain": "Hide everything from {domain}", "account.blocked": "Blocked", "account.direct": "Direct Message @{name}", - "account.disclaimer_full": "Information below may reflect the user's profile incompletely.", "account.domain_blocked": "Domain hidden", "account.edit_profile": "Modifikar profilo", "account.endorse": "Feature on profile", @@ -36,7 +35,6 @@ "account.unfollow": "Ne plus sequar", "account.unmute": "Ne plus celar @{name}", "account.unmute_notifications": "Unmute notifications from @{name}", - "account.view_full_profile": "View full profile", "alert.unexpected.message": "An unexpected error occurred.", "alert.unexpected.title": "Oops!", "boost_modal.combo": "Tu povas presar sur {combo} por omisar co en la venonta foyo", @@ -85,6 +83,7 @@ "compose_form.spoiler.unmarked": "Text is not hidden", "compose_form.spoiler_placeholder": "Averto di kontenajo", "confirmation_modal.cancel": "Cancel", + "confirmations.block.block_and_report": "Block & Report", "confirmations.block.confirm": "Block", "confirmations.block.message": "Are you sure you want to block {name}?", "confirmations.delete.confirm": "Delete", @@ -133,7 +132,6 @@ "empty_column.mutes": "You haven't muted any users yet.", "empty_column.notifications": "Tu havas ankore nula savigo. Komunikez kun altri por debutar la konverso.", "empty_column.public": "Esas nulo hike! Skribez ulo publike, o manuale sequez uzeri de altra instaluri por plenigar ol.", - "error_boundary.it_crashed": "It crashed!", "follow_request.authorize": "Yurizar", "follow_request.reject": "Refuzar", "getting_started.developers": "Developers", @@ -248,6 +246,7 @@ "notification.favourite": "{name} favorizis tua mesajo", "notification.follow": "{name} sequeskis tu", "notification.mention": "{name} mencionis tu", + "notification.poll": "A poll you have voted in has ended", "notification.reblog": "{name} repetis tua mesajo", "notifications.clear": "Efacar savigi", "notifications.clear_confirmation": "Ka tu esas certa, ke tu volas efacar omna tua savigi?", @@ -258,6 +257,7 @@ "notifications.column_settings.filter_bar.show": "Show", "notifications.column_settings.follow": "Nova sequanti:", "notifications.column_settings.mention": "Mencioni:", + "notifications.column_settings.poll": "Poll results:", "notifications.column_settings.push": "Push notifications", "notifications.column_settings.reblog": "Repeti:", "notifications.column_settings.show": "Montrar en kolumno", @@ -267,6 +267,7 @@ "notifications.filter.favourites": "Favourites", "notifications.filter.follows": "Follows", "notifications.filter.mentions": "Mentions", + "notifications.filter.polls": "Poll results", "notifications.group": "{count} notifications", "poll.closed": "Closed", "poll.refresh": "Refresh", @@ -308,7 +309,6 @@ "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.admin_account": "Open moderation interface for @{name}", "status.admin_status": "Open this status in the moderation interface", "status.block": "Block @{name}", diff --git a/app/javascript/mastodon/locales/it.json b/app/javascript/mastodon/locales/it.json index e4cd96475..d70a88dbb 100644 --- a/app/javascript/mastodon/locales/it.json +++ b/app/javascript/mastodon/locales/it.json @@ -5,7 +5,6 @@ "account.block_domain": "Nascondi tutto da {domain}", "account.blocked": "Bloccato", "account.direct": "Invia messaggio diretto a @{name}", - "account.disclaimer_full": "Il profilo dell'utente mostrato qui sotto potrebbe essere incompleto.", "account.domain_blocked": "Dominio nascosto", "account.edit_profile": "Modifica profilo", "account.endorse": "Metti in evidenza sul profilo", @@ -36,7 +35,6 @@ "account.unfollow": "Non seguire", "account.unmute": "Non silenziare @{name}", "account.unmute_notifications": "Non silenziare più le notifiche da @{name}", - "account.view_full_profile": "Vedi profilo completo", "alert.unexpected.message": "Si è verificato un errore inatteso.", "alert.unexpected.title": "Oops!", "boost_modal.combo": "Puoi premere {combo} per saltare questo passaggio la prossima volta", @@ -85,6 +83,7 @@ "compose_form.spoiler.unmarked": "Il testo non è nascosto", "compose_form.spoiler_placeholder": "Content warning", "confirmation_modal.cancel": "Annulla", + "confirmations.block.block_and_report": "Block & Report", "confirmations.block.confirm": "Blocca", "confirmations.block.message": "Sei sicuro di voler bloccare {name}?", "confirmations.delete.confirm": "Cancella", @@ -133,7 +132,6 @@ "empty_column.mutes": "Non hai ancora silenziato nessun utente.", "empty_column.notifications": "Non hai ancora nessuna notifica. Interagisci con altri per iniziare conversazioni.", "empty_column.public": "Qui non c'è nulla! Scrivi qualcosa pubblicamente, o aggiungi utenti da altri server per riempire questo spazio", - "error_boundary.it_crashed": "It crashed!", "follow_request.authorize": "Autorizza", "follow_request.reject": "Rifiuta", "getting_started.developers": "Sviluppatori", @@ -248,6 +246,7 @@ "notification.favourite": "{name} ha apprezzato il tuo post", "notification.follow": "{name} ha iniziato a seguirti", "notification.mention": "{name} ti ha menzionato", + "notification.poll": "A poll you have voted in has ended", "notification.reblog": "{name} ha condiviso il tuo post", "notifications.clear": "Cancella notifiche", "notifications.clear_confirmation": "Vuoi davvero cancellare tutte le notifiche?", @@ -258,6 +257,7 @@ "notifications.column_settings.filter_bar.show": "Mostra", "notifications.column_settings.follow": "Nuovi seguaci:", "notifications.column_settings.mention": "Menzioni:", + "notifications.column_settings.poll": "Poll results:", "notifications.column_settings.push": "Notifiche push", "notifications.column_settings.reblog": "Post condivisi:", "notifications.column_settings.show": "Mostra in colonna", @@ -267,6 +267,7 @@ "notifications.filter.favourites": "Apprezzati", "notifications.filter.follows": "Seguaci", "notifications.filter.mentions": "Menzioni", + "notifications.filter.polls": "Poll results", "notifications.group": "{count} notifiche", "poll.closed": "Chiuso", "poll.refresh": "Aggiorna", @@ -308,7 +309,6 @@ "search_results.hashtags": "Hashtag", "search_results.statuses": "Toot", "search_results.total": "{count} {count, plural, one {risultato} other {risultati}}", - "standalone.public_title": "Un'occhiata all'interno...", "status.admin_account": "Apri interfaccia di moderazione per @{name}", "status.admin_status": "Apri questo status nell'interfaccia di moderazione", "status.block": "Blocca @{name}", diff --git a/app/javascript/mastodon/locales/ja.json b/app/javascript/mastodon/locales/ja.json index ca66fbf2a..423ff3dce 100644 --- a/app/javascript/mastodon/locales/ja.json +++ b/app/javascript/mastodon/locales/ja.json @@ -5,7 +5,6 @@ "account.block_domain": "{domain}全体を非表示", "account.blocked": "ブロック済み", "account.direct": "@{name}さんにダイレクトメッセージ", - "account.disclaimer_full": "以下の情報は不正確な可能性があります。", "account.domain_blocked": "ドメイン非表示中", "account.edit_profile": "プロフィールを編集", "account.endorse": "プロフィールで紹介する", @@ -36,7 +35,6 @@ "account.unfollow": "フォロー解除", "account.unmute": "@{name}さんのミュートを解除", "account.unmute_notifications": "@{name}さんからの通知を受け取るようにする", - "account.view_full_profile": "全ての情報を見る", "alert.unexpected.message": "不明なエラーが発生しました。", "alert.unexpected.title": "エラー!", "boost_modal.combo": "次からは{combo}を押せばスキップできます", @@ -78,7 +76,7 @@ "compose_form.lock_disclaimer.lock": "承認制", "compose_form.placeholder": "今なにしてる?", "compose_form.poll.add_option": "Add a choice", - "compose_form.poll.duration": "Poll duration", + "compose_form.poll.duration": "投票期間", "compose_form.poll.option_placeholder": "Choice {number}", "compose_form.poll.remove_option": "Remove this choice", "compose_form.publish": "トゥート", @@ -89,6 +87,7 @@ "compose_form.spoiler.unmarked": "閲覧注意が設定されていません", "compose_form.spoiler_placeholder": "ここに警告を書いてください", "confirmation_modal.cancel": "キャンセル", + "confirmations.block.block_and_report": "Block & Report", "confirmations.block.confirm": "ブロック", "confirmations.block.message": "本当に{name}さんをブロックしますか?", "confirmations.delete.confirm": "削除", @@ -161,7 +160,7 @@ "home.column_settings.show_replies": "返信表示", "intervals.full.days": "{number, plural, one {# day} other {# days}}", "intervals.full.hours": "{number, plural, one {# hour} other {# hours}}", - "intervals.full.minutes": "{number, plural, one {# minute} other {# minutes}}", + "intervals.full.minutes": "{number}分", "introduction.federation.action": "次へ", "introduction.federation.federated.headline": "連合タイムライン", "introduction.federation.federated.text": "Fediverseの他のサーバーからの公開投稿は連合タイムラインに表示されます。", @@ -252,6 +251,7 @@ "notification.favourite": "{name}さんがあなたのトゥートをお気に入りに登録しました", "notification.follow": "{name}さんにフォローされました", "notification.mention": "{name}さんがあなたに返信しました", + "notification.poll": "A poll you have voted in has ended", "notification.reblog": "{name}さんがあなたのトゥートをブーストしました", "notifications.clear": "通知を消去", "notifications.clear_confirmation": "本当に通知を消去しますか?", @@ -262,6 +262,7 @@ "notifications.column_settings.filter_bar.show": "表示", "notifications.column_settings.follow": "新しいフォロワー:", "notifications.column_settings.mention": "返信:", + "notifications.column_settings.poll": "Poll results:", "notifications.column_settings.push": "プッシュ通知", "notifications.column_settings.reblog": "ブースト:", "notifications.column_settings.show": "カラムに表示", @@ -271,13 +272,14 @@ "notifications.filter.favourites": "お気に入り", "notifications.filter.follows": "フォロー", "notifications.filter.mentions": "返信", + "notifications.filter.polls": "Poll results", "notifications.group": "{count} 件の通知", "poll.closed": "終了", "poll.refresh": "更新", - "poll.total_votes": "{count, plural, one {# 票} other {# 票}}", + "poll.total_votes": "{count}票", "poll.vote": "Vote", "poll_button.add_poll": "Add a poll", - "poll_button.remove_poll": "Remove poll", + "poll_button.remove_poll": "投票を削除", "privacy.change": "公開範囲を変更", "privacy.direct.long": "メンションしたユーザーだけに公開", "privacy.direct.short": "ダイレクト", @@ -359,19 +361,19 @@ "tabs_bar.local_timeline": "ローカル", "tabs_bar.notifications": "通知", "tabs_bar.search": "検索", - "time_remaining.days": "残り {number, plural, one {# 日} other {# 日}}", - "time_remaining.hours": "残り {number, plural, one {# 時間} other {# 時間}}", - "time_remaining.minutes": "残り {number, plural, one {# 分} other {# 分}}", + "time_remaining.days": "残り{number}日", + "time_remaining.hours": "残り{number}時間", + "time_remaining.minutes": "残り{number}分", "time_remaining.moments": "まもなく終了", - "time_remaining.seconds": "残り {number, plural, one {# 秒} other {# 秒}}", - "trends.count_by_accounts": "{count} {rawCount, plural, one {人} other {人}} がトゥート", + "time_remaining.seconds": "残り{number}秒", + "trends.count_by_accounts": "{count}人がトゥート", "ui.beforeunload": "Mastodonから離れると送信前の投稿は失われます。", "upload_area.title": "ドラッグ&ドロップでアップロード", "upload_button.label": "メディアを追加 (JPEG, PNG, GIF, WebM, MP4, MOV)", "upload_error.limit": "アップロードできる上限を超えています。", "upload_error.poll": "File upload not allowed with polls.", "upload_form.description": "視覚障害者のための説明", - "upload_form.focus": "焦点", + "upload_form.focus": "プレビューを変更", "upload_form.undo": "削除", "upload_progress.label": "アップロード中...", "video.close": "動画を閉じる", diff --git a/app/javascript/mastodon/locales/ka.json b/app/javascript/mastodon/locales/ka.json index 21afe8df3..fa1d823d0 100644 --- a/app/javascript/mastodon/locales/ka.json +++ b/app/javascript/mastodon/locales/ka.json @@ -5,7 +5,6 @@ "account.block_domain": "დაიმალოს ყველაფერი დომენიდან {domain}", "account.blocked": "დაიბლოკა", "account.direct": "პირდაპირი წერილი @{name}-ს", - "account.disclaimer_full": "ქვემოთ მოცემულმა ინფორმაციამ შეიძლება სრულად არ ასახოს მომხმარებლის პროფილი.", "account.domain_blocked": "დომენი დამალულია", "account.edit_profile": "პროფილის ცვლილება", "account.endorse": "გამორჩევა პროფილზე", @@ -36,7 +35,6 @@ "account.unfollow": "ნუღარ მიჰყვები", "account.unmute": "ნუღარ აჩუმებ @{name}-ს", "account.unmute_notifications": "ნუღარ აჩუმებ შეტყობინებებს @{name}-სგან", - "account.view_full_profile": "სრული პროფილის ჩვენება", "alert.unexpected.message": "წარმოიშვა მოულოდნელი შეცდომა.", "alert.unexpected.title": "უპს!", "boost_modal.combo": "შეგიძლიათ დააჭიროთ {combo}-ს რათა შემდეგ ჯერზე გამოტოვოთ ეს", @@ -85,6 +83,7 @@ "compose_form.spoiler.unmarked": "ტექსტი არაა დამალული", "compose_form.spoiler_placeholder": "თქვენი გაფრთხილება დაწერეთ აქ", "confirmation_modal.cancel": "უარყოფა", + "confirmations.block.block_and_report": "Block & Report", "confirmations.block.confirm": "ბლოკი", "confirmations.block.message": "დარწმუნებული ხართ, გსურთ დაბლოკოთ {name}?", "confirmations.delete.confirm": "გაუქმება", @@ -133,7 +132,6 @@ "empty_column.mutes": "You haven't muted any users yet.", "empty_column.notifications": "ჯერ შეტყობინებები არ გაქვთ. საუბრის დასაწყებად იურთიერთქმედეთ სხვებთან.", "empty_column.public": "აქ არაფერია! შესავსებად, დაწერეთ რაიმე ღიად ან ხელით გაჰყევით მომხმარებლებს სხვა ინსტანციებისგან", - "error_boundary.it_crashed": "It crashed!", "follow_request.authorize": "ავტორიზაცია", "follow_request.reject": "უარყოფა", "getting_started.developers": "დეველოპერები", @@ -248,6 +246,7 @@ "notification.favourite": "{name}-მა თქვენი სტატუსი აქცია ფავორიტად", "notification.follow": "{name} გამოგყვათ", "notification.mention": "{name}-მა გასახელათ", + "notification.poll": "A poll you have voted in has ended", "notification.reblog": "{name}-მა დაბუსტა თქვენი სტატუსი", "notifications.clear": "შეტყობინებების გასუფთავება", "notifications.clear_confirmation": "დარწმუნებული ხართ, გსურთ სამუდამოდ წაშალოთ ყველა თქვენი შეტყობინება?", @@ -258,6 +257,7 @@ "notifications.column_settings.filter_bar.show": "Show", "notifications.column_settings.follow": "ახალი მიმდევრები:", "notifications.column_settings.mention": "ხსენებები:", + "notifications.column_settings.poll": "Poll results:", "notifications.column_settings.push": "ფუშ შეტყობინებები", "notifications.column_settings.reblog": "ბუსტები:", "notifications.column_settings.show": "გამოჩნდეს სვეტში", @@ -267,6 +267,7 @@ "notifications.filter.favourites": "Favourites", "notifications.filter.follows": "Follows", "notifications.filter.mentions": "Mentions", + "notifications.filter.polls": "Poll results", "notifications.group": "{count} შეტყობინება", "poll.closed": "Closed", "poll.refresh": "Refresh", @@ -308,7 +309,6 @@ "search_results.hashtags": "ჰეშტეგები", "search_results.statuses": "ტუტები", "search_results.total": "{count, number} {count, plural, one {result} other {results}}", - "standalone.public_title": "შიდა ხედი...", "status.admin_account": "Open moderation interface for @{name}", "status.admin_status": "Open this status in the moderation interface", "status.block": "დაბლოკე @{name}", diff --git a/app/javascript/mastodon/locales/kk.json b/app/javascript/mastodon/locales/kk.json index 034810fdd..12cdf25c9 100644 --- a/app/javascript/mastodon/locales/kk.json +++ b/app/javascript/mastodon/locales/kk.json @@ -5,7 +5,6 @@ "account.block_domain": "Домендегі барлығын бұғатта {domain}", "account.blocked": "Бұғатталды", "account.direct": "Жеке хат @{name}", - "account.disclaimer_full": "Қолданушы туралы барлық мәліметті көрсетпеуі мүмкін.", "account.domain_blocked": "Домен жабық", "account.edit_profile": "Профильді өңдеу", "account.endorse": "Профильде рекомендеу", @@ -36,7 +35,6 @@ "account.unfollow": "Оқымау", "account.unmute": "@{name} ескертпелерін қосу", "account.unmute_notifications": "@{name} ескертпелерін көрсету", - "account.view_full_profile": "Толқы профилін көрсету", "alert.unexpected.message": "Бір нәрсе дұрыс болмады.", "alert.unexpected.title": "Өй!", "boost_modal.combo": "Келесіде өткізіп жіберу үшін басыңыз {combo}", @@ -55,7 +53,7 @@ "column.home": "Басты бет", "column.lists": "Тізімдер", "column.mutes": "Үнсіз қолданушылар", - "column.notifications": "Notifications", + "column.notifications": "Ескертпелер", "column.pins": "Жабыстырылған жазбалар", "column.public": "Жаһандық желі", "column_back_button.label": "Артқа", @@ -73,10 +71,10 @@ "compose_form.lock_disclaimer": "Аккаунтыңыз {locked} емес. Кез келген адам жазылып, сізді оқи алады.", "compose_form.lock_disclaimer.lock": "жабық", "compose_form.placeholder": "Не бөліскіңіз келеді?", - "compose_form.poll.add_option": "Add a choice", - "compose_form.poll.duration": "Poll duration", - "compose_form.poll.option_placeholder": "Choice {number}", - "compose_form.poll.remove_option": "Remove this choice", + "compose_form.poll.add_option": "Жауап қос", + "compose_form.poll.duration": "Сауалнама мерзімі", + "compose_form.poll.option_placeholder": "Жауап {number}", + "compose_form.poll.remove_option": "Бұл жауапты өшір", "compose_form.publish": "Түрт", "compose_form.publish_loud": "{publish}!", "compose_form.sensitive.marked": "Медиа нәзік деп белгіленген", @@ -85,6 +83,7 @@ "compose_form.spoiler.unmarked": "Мәтін жасырылмаған", "compose_form.spoiler_placeholder": "Ескертуіңізді осында жазыңыз", "confirmation_modal.cancel": "Қайтып алу", + "confirmations.block.block_and_report": "Block & Report", "confirmations.block.confirm": "Бұғаттау", "confirmations.block.message": "{name} атты қолданушыны бұғаттайтыныңызға сенімдісіз бе?", "confirmations.delete.confirm": "Өшіру", @@ -133,7 +132,6 @@ "empty_column.mutes": "Әзірше ешқандай үнсізге қойылған қолданушы жоқ.", "empty_column.notifications": "Әзірше ешқандай ескертпе жоқ. Басқалармен араласуды бастаңыз және пікірталастарға қатысыңыз.", "empty_column.public": "Ештеңе жоқ бұл жерде! Өзіңіз бастап жазып көріңіз немесе басқаларға жазылыңыз", - "error_boundary.it_crashed": "It crashed!", "follow_request.authorize": "Авторизация", "follow_request.reject": "Қабылдамау", "getting_started.developers": "Жасаушылар тобы", @@ -156,8 +154,8 @@ "home.column_settings.basic": "Негізгі", "home.column_settings.show_reblogs": "Бөлісулерді көрсету", "home.column_settings.show_replies": "Жауаптарды көрсету", - "intervals.full.days": "{number, plural, one {# day} other {# days}}", - "intervals.full.hours": "{number, plural, one {# hour} other {# hours}}", + "intervals.full.days": "{number, plural, one {# күн} other {# күн}}", + "intervals.full.hours": "{number, plural, one {# сағат} other {# сағат}}", "intervals.full.minutes": "{number, plural, one {# minute} other {# minutes}}", "introduction.federation.action": "Келесі", "introduction.federation.federated.headline": "Жаһандық", @@ -224,7 +222,7 @@ "missing_indicator.label": "Табылмады", "missing_indicator.sublabel": "Бұл ресурс табылмады", "mute_modal.hide_notifications": "Бұл қолданушы ескертпелерін жасырамыз ба?", - "navigation_bar.apps": "Мобиль қосымшаларMobile apps", + "navigation_bar.apps": "Мобиль қосымшалар", "navigation_bar.blocks": "Бұғатталғандар", "navigation_bar.community_timeline": "Жергілікті желі", "navigation_bar.compose": "Жаңа жазба бастау", @@ -248,6 +246,7 @@ "notification.favourite": "{name} жазбаңызды таңдаулыға қосты", "notification.follow": "{name} сізге жазылды", "notification.mention": "{name} сізді атап өтті", + "notification.poll": "A poll you have voted in has ended", "notification.reblog": "{name} жазбаңызды бөлісті", "notifications.clear": "Ескертпелерді тазарт", "notifications.clear_confirmation": "Шынымен барлық ескертпелерді өшіресіз бе?", @@ -258,6 +257,7 @@ "notifications.column_settings.filter_bar.show": "Көрсету", "notifications.column_settings.follow": "Жаңа оқырмандар:", "notifications.column_settings.mention": "Аталымдар:", + "notifications.column_settings.poll": "Poll results:", "notifications.column_settings.push": "Push ескертпелер", "notifications.column_settings.reblog": "Бөлісулер:", "notifications.column_settings.show": "Бағанда көрсет", @@ -267,13 +267,14 @@ "notifications.filter.favourites": "Таңдаулылар", "notifications.filter.follows": "Жазылулар", "notifications.filter.mentions": "Аталымдар", + "notifications.filter.polls": "Poll results", "notifications.group": "{count} ескертпе", "poll.closed": "Жабық", "poll.refresh": "Жаңарту", "poll.total_votes": "{count, plural, one {# дауыс} other {# дауыс}}", "poll.vote": "Дауыс беру", - "poll_button.add_poll": "Add a poll", - "poll_button.remove_poll": "Remove poll", + "poll_button.add_poll": "Сауалнама қосу", + "poll_button.remove_poll": "Сауалнаманы өшіру", "privacy.change": "Құпиялылықты реттеу", "privacy.direct.long": "Аталған адамдарға ғана көрінетін жазба", "privacy.direct.short": "Тікелей", @@ -308,7 +309,6 @@ "search_results.hashtags": "Хэштегтер", "search_results.statuses": "Жазбалар", "search_results.total": "{count, number} {count, plural, one {result} other {results}}", - "standalone.public_title": "Ішкі көрініс...", "status.admin_account": "@{name} үшін модерация интерфейсін аш", "status.admin_status": "Бұл жазбаны модерация интерфейсінде аш", "status.block": "Бұғаттау @{name}", @@ -366,7 +366,7 @@ "upload_area.title": "Жүктеу үшін сүйреп әкеліңіз", "upload_button.label": "Медиа қосу (JPEG, PNG, GIF, WebM, MP4, MOV)", "upload_error.limit": "Файл жүктеу лимитінен асып кеттіңіз.", - "upload_error.poll": "File upload not allowed with polls.", + "upload_error.poll": "Сауалнамамен бірге файл жүктеуге болмайды", "upload_form.description": "Көру қабілеті нашар адамдар үшін сипаттаңыз", "upload_form.focus": "Превьюді өзгерту", "upload_form.undo": "Өшіру", diff --git a/app/javascript/mastodon/locales/ko.json b/app/javascript/mastodon/locales/ko.json index cbd68d195..433592ffd 100644 --- a/app/javascript/mastodon/locales/ko.json +++ b/app/javascript/mastodon/locales/ko.json @@ -5,7 +5,6 @@ "account.block_domain": "{domain} 전체를 숨김", "account.blocked": "차단 됨", "account.direct": "@{name}으로부터의 다이렉트 메시지", - "account.disclaimer_full": "여기 있는 정보는 유저의 프로파일을 정확히 반영하지 못 할 수도 있습니다.", "account.domain_blocked": "도메인 숨겨짐", "account.edit_profile": "프로필 편집", "account.endorse": "프로필에 나타내기", @@ -36,7 +35,6 @@ "account.unfollow": "팔로우 해제", "account.unmute": "뮤트 해제", "account.unmute_notifications": "@{name}의 알림 뮤트 해제", - "account.view_full_profile": "전체 프로필 보기", "alert.unexpected.message": "예측하지 못한 에러가 발생했습니다.", "alert.unexpected.title": "앗!", "boost_modal.combo": "{combo}를 누르면 다음부터 이 과정을 건너뛸 수 있습니다", @@ -73,10 +71,10 @@ "compose_form.lock_disclaimer": "이 계정은 {locked}로 설정 되어 있지 않습니다. 누구나 이 계정을 팔로우 할 수 있으며, 팔로워 공개의 포스팅을 볼 수 있습니다.", "compose_form.lock_disclaimer.lock": "비공개", "compose_form.placeholder": "지금 무엇을 하고 있나요?", - "compose_form.poll.add_option": "Add a choice", - "compose_form.poll.duration": "Poll duration", - "compose_form.poll.option_placeholder": "Choice {number}", - "compose_form.poll.remove_option": "Remove this choice", + "compose_form.poll.add_option": "항목 추가", + "compose_form.poll.duration": "투표 기간", + "compose_form.poll.option_placeholder": "{number}번 항목", + "compose_form.poll.remove_option": "이 항목 삭제", "compose_form.publish": "툿", "compose_form.publish_loud": "{publish}!", "compose_form.sensitive.marked": "미디어가 열람주의로 설정되어 있습니다", @@ -85,6 +83,7 @@ "compose_form.spoiler.unmarked": "열람주의가 설정 되어 있지 않습니다", "compose_form.spoiler_placeholder": "경고", "confirmation_modal.cancel": "취소", + "confirmations.block.block_and_report": "차단하고 신고하기", "confirmations.block.confirm": "차단", "confirmations.block.message": "정말로 {name}를 차단하시겠습니까?", "confirmations.delete.confirm": "삭제", @@ -133,7 +132,6 @@ "empty_column.mutes": "아직 아무도 뮤트하지 않았습니다.", "empty_column.notifications": "아직 알림이 없습니다. 다른 사람과 대화를 시작해 보세요.", "empty_column.public": "여기엔 아직 아무 것도 없습니다! 공개적으로 무언가 포스팅하거나, 다른 서버의 유저를 팔로우 해서 채워보세요", - "error_boundary.it_crashed": "It crashed!", "follow_request.authorize": "허가", "follow_request.reject": "거부", "getting_started.developers": "개발자", @@ -152,19 +150,19 @@ "hashtag.column_settings.tag_mode.all": "모두", "hashtag.column_settings.tag_mode.any": "아무것이든", "hashtag.column_settings.tag_mode.none": "이것들을 제외하고", - "hashtag.column_settings.tag_toggle": "Include additional tags in this column", + "hashtag.column_settings.tag_toggle": "추가 해시태그를 이 컬럼에 추가합니다", "home.column_settings.basic": "기본 설정", "home.column_settings.show_reblogs": "부스트 표시", "home.column_settings.show_replies": "답글 표시", - "intervals.full.days": "{number, plural, one {# day} other {# days}}", - "intervals.full.hours": "{number, plural, one {# hour} other {# hours}}", - "intervals.full.minutes": "{number, plural, one {# minute} other {# minutes}}", + "intervals.full.days": "{number} 일", + "intervals.full.hours": "{number} 시간", + "intervals.full.minutes": "{number} 분", "introduction.federation.action": "다음", - "introduction.federation.federated.headline": "Federated", + "introduction.federation.federated.headline": "연합", "introduction.federation.federated.text": "페디버스의 다른 서버의 공개 게시물이 연합 타임라인에 나타납니다.", - "introduction.federation.home.headline": "Home", + "introduction.federation.home.headline": "홈", "introduction.federation.home.text": "당신이 팔로우 하고 있는 사람의 게시물이 홈 타임라인에 나타납니다. 어느 서버에 있는 사람이라도 팔로우가 가능합니다!", - "introduction.federation.local.headline": "Local", + "introduction.federation.local.headline": "로컬", "introduction.federation.local.text": "같은 서버에 있는 공개 게시물은 로컬 타임라인에 나타납니다.", "introduction.interactions.action": "튜토리얼 마치기!", "introduction.interactions.favourite.headline": "즐겨찾기", @@ -248,6 +246,7 @@ "notification.favourite": "{name}님이 즐겨찾기 했습니다", "notification.follow": "{name}님이 나를 팔로우 했습니다", "notification.mention": "{name}님이 답글을 보냈습니다", + "notification.poll": "당신이 참여 한 투표가 종료되었습니다", "notification.reblog": "{name}님이 부스트 했습니다", "notifications.clear": "알림 지우기", "notifications.clear_confirmation": "정말로 알림을 삭제하시겠습니까?", @@ -258,6 +257,7 @@ "notifications.column_settings.filter_bar.show": "표시", "notifications.column_settings.follow": "새 팔로워:", "notifications.column_settings.mention": "답글:", + "notifications.column_settings.poll": "투표 결과:", "notifications.column_settings.push": "푸시 알림", "notifications.column_settings.reblog": "부스트:", "notifications.column_settings.show": "컬럼에 표시", @@ -267,13 +267,14 @@ "notifications.filter.favourites": "즐겨찾기", "notifications.filter.follows": "팔로우", "notifications.filter.mentions": "멘션", + "notifications.filter.polls": "투표 결과", "notifications.group": "{count} 개의 알림", "poll.closed": "마감됨", "poll.refresh": "새로고침", - "poll.total_votes": "명 참여", + "poll.total_votes": "{count} 명 참여", "poll.vote": "투표", - "poll_button.add_poll": "Add a poll", - "poll_button.remove_poll": "Remove poll", + "poll_button.add_poll": "투표 추가", + "poll_button.remove_poll": "투표 삭제", "privacy.change": "포스트의 프라이버시 설정을 변경", "privacy.direct.long": "멘션한 사용자에게만 공개", "privacy.direct.short": "다이렉트", @@ -308,7 +309,6 @@ "search_results.hashtags": "해시태그", "search_results.statuses": "툿", "search_results.total": "{count, number}건의 결과", - "standalone.public_title": "지금 이런 이야기를 하고 있습니다…", "status.admin_account": "@{name}에 대한 모더레이션 인터페이스 열기", "status.admin_status": "모더레이션 인터페이스에서 이 게시물 열기", "status.block": "@{name} 차단", @@ -356,17 +356,17 @@ "tabs_bar.local_timeline": "로컬", "tabs_bar.notifications": "알림", "tabs_bar.search": "검색", - "time_remaining.days": "일 남음", - "time_remaining.hours": "시간 남음", - "time_remaining.minutes": "분 남음", + "time_remaining.days": "{number} 일 남음", + "time_remaining.hours": "{number} 시간 남음", + "time_remaining.minutes": "{number} 분 남음", "time_remaining.moments": "남은 시간", - "time_remaining.seconds": "초 남음", - "trends.count_by_accounts": "{count} {rawCount, plural, one {명} other {명}} 의 사람들이 말하고 있습니다", + "time_remaining.seconds": "{number} 초 남음", + "trends.count_by_accounts": "{count} 명의 사람들이 말하고 있습니다", "ui.beforeunload": "지금 나가면 저장되지 않은 항목을 잃게 됩니다.", "upload_area.title": "드래그 & 드롭으로 업로드", "upload_button.label": "미디어 추가 (JPEG, PNG, GIF, WebM, MP4, MOV)", "upload_error.limit": "파일 업로드 제한에 도달했습니다.", - "upload_error.poll": "File upload not allowed with polls.", + "upload_error.poll": "파일 업로드는 투표와 함께 첨부할 수 없습니다.", "upload_form.description": "시각장애인을 위한 설명", "upload_form.focus": "미리보기 변경", "upload_form.undo": "삭제", diff --git a/app/javascript/mastodon/locales/lv.json b/app/javascript/mastodon/locales/lv.json index ab784d1b4..0fa0c4fde 100644 --- a/app/javascript/mastodon/locales/lv.json +++ b/app/javascript/mastodon/locales/lv.json @@ -5,7 +5,6 @@ "account.block_domain": "Slēpt visu no {domain}", "account.blocked": "Bloķēts", "account.direct": "Privātā ziņa @{name}", - "account.disclaimer_full": "Informācija zemāk var nepilnīgi atspoguļot lietotāja profilu.", "account.domain_blocked": "Domēns ir paslēpts", "account.edit_profile": "Labot profilu", "account.endorse": "Izcelts profilā", @@ -36,7 +35,6 @@ "account.unfollow": "Nesekot", "account.unmute": "Noņemt apklusinājumu no lietotāja @{name}", "account.unmute_notifications": "Rādīt paziņojumus no lietotāja @{name}", - "account.view_full_profile": "Apskatīt pilnu profilu", "alert.unexpected.message": "Negaidīta kļūda.", "alert.unexpected.title": "Ups!", "boost_modal.combo": "Nospied {combo} lai izlaistu šo nākamreiz", @@ -85,6 +83,7 @@ "compose_form.spoiler.unmarked": "Teksts nav paslēpts", "compose_form.spoiler_placeholder": "Ieraksti Savu brīdinājuma tekstu šeit", "confirmation_modal.cancel": "Atcelt", + "confirmations.block.block_and_report": "Block & Report", "confirmations.block.confirm": "Bloķēt", "confirmations.block.message": "Vai tiešām vēlies bloķēt lietotāju {name}?", "confirmations.delete.confirm": "Dzēst", @@ -133,7 +132,6 @@ "empty_column.mutes": "Tu neesi nevienu apklusinājis.", "empty_column.notifications": "Tev nav paziņojumu. Iesaisties sarunās ar citiem.", "empty_column.public": "Šeit nekā nav, tukšums! Ieraksti kaut ko publiski, vai uzmeklē un seko kādam no citas instances", - "error_boundary.it_crashed": "It crashed!", "follow_request.authorize": "Autorizēt", "follow_request.reject": "Noraidīt", "getting_started.developers": "Developers", @@ -248,6 +246,7 @@ "notification.favourite": "{name} favourited your status", "notification.follow": "{name} followed you", "notification.mention": "{name} mentioned you", + "notification.poll": "A poll you have voted in has ended", "notification.reblog": "{name} boosted your status", "notifications.clear": "Clear notifications", "notifications.clear_confirmation": "Are you sure you want to permanently clear all your notifications?", @@ -258,6 +257,7 @@ "notifications.column_settings.filter_bar.show": "Show", "notifications.column_settings.follow": "New followers:", "notifications.column_settings.mention": "Mentions:", + "notifications.column_settings.poll": "Poll results:", "notifications.column_settings.push": "Push notifications", "notifications.column_settings.reblog": "Boosts:", "notifications.column_settings.show": "Show in column", @@ -267,6 +267,7 @@ "notifications.filter.favourites": "Favourites", "notifications.filter.follows": "Follows", "notifications.filter.mentions": "Mentions", + "notifications.filter.polls": "Poll results", "notifications.group": "{count} notifications", "poll.closed": "Closed", "poll.refresh": "Refresh", @@ -308,7 +309,6 @@ "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.admin_account": "Open moderation interface for @{name}", "status.admin_status": "Open this status in the moderation interface", "status.block": "Block @{name}", diff --git a/app/javascript/mastodon/locales/ms.json b/app/javascript/mastodon/locales/ms.json index 9f8f797c8..eedd4c6f3 100644 --- a/app/javascript/mastodon/locales/ms.json +++ b/app/javascript/mastodon/locales/ms.json @@ -5,7 +5,6 @@ "account.block_domain": "Hide everything from {domain}", "account.blocked": "Blocked", "account.direct": "Direct message @{name}", - "account.disclaimer_full": "Information below may reflect the user's profile incompletely.", "account.domain_blocked": "Domain hidden", "account.edit_profile": "Edit profile", "account.endorse": "Feature on profile", @@ -36,7 +35,6 @@ "account.unfollow": "Unfollow", "account.unmute": "Unmute @{name}", "account.unmute_notifications": "Unmute notifications from @{name}", - "account.view_full_profile": "View full profile", "alert.unexpected.message": "An unexpected error occurred.", "alert.unexpected.title": "Oops!", "boost_modal.combo": "You can press {combo} to skip this next time", @@ -85,6 +83,7 @@ "compose_form.spoiler.unmarked": "Text is not hidden", "compose_form.spoiler_placeholder": "Write your warning here", "confirmation_modal.cancel": "Cancel", + "confirmations.block.block_and_report": "Block & Report", "confirmations.block.confirm": "Block", "confirmations.block.message": "Are you sure you want to block {name}?", "confirmations.delete.confirm": "Delete", @@ -133,7 +132,6 @@ "empty_column.mutes": "You haven't muted any users 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", - "error_boundary.it_crashed": "It crashed!", "follow_request.authorize": "Authorize", "follow_request.reject": "Reject", "getting_started.developers": "Developers", @@ -248,6 +246,7 @@ "notification.favourite": "{name} favourited your status", "notification.follow": "{name} followed you", "notification.mention": "{name} mentioned you", + "notification.poll": "A poll you have voted in has ended", "notification.reblog": "{name} boosted your status", "notifications.clear": "Clear notifications", "notifications.clear_confirmation": "Are you sure you want to permanently clear all your notifications?", @@ -258,6 +257,7 @@ "notifications.column_settings.filter_bar.show": "Show", "notifications.column_settings.follow": "New followers:", "notifications.column_settings.mention": "Mentions:", + "notifications.column_settings.poll": "Poll results:", "notifications.column_settings.push": "Push notifications", "notifications.column_settings.reblog": "Boosts:", "notifications.column_settings.show": "Show in column", @@ -267,6 +267,7 @@ "notifications.filter.favourites": "Favourites", "notifications.filter.follows": "Follows", "notifications.filter.mentions": "Mentions", + "notifications.filter.polls": "Poll results", "notifications.group": "{count} notifications", "poll.closed": "Closed", "poll.refresh": "Refresh", @@ -308,7 +309,6 @@ "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.admin_account": "Open moderation interface for @{name}", "status.admin_status": "Open this status in the moderation interface", "status.block": "Block @{name}", diff --git a/app/javascript/mastodon/locales/nl.json b/app/javascript/mastodon/locales/nl.json index 84ae28037..e5e4748d7 100644 --- a/app/javascript/mastodon/locales/nl.json +++ b/app/javascript/mastodon/locales/nl.json @@ -5,7 +5,6 @@ "account.block_domain": "Verberg alles van {domain}", "account.blocked": "Geblokkeerd", "account.direct": "Direct Message @{name}", - "account.disclaimer_full": "De informatie hieronder kan een incompleet beeld geven van dit gebruikersprofiel.", "account.domain_blocked": "Domein verborgen", "account.edit_profile": "Profiel bewerken", "account.endorse": "Op profiel weergeven", @@ -36,7 +35,6 @@ "account.unfollow": "Ontvolgen", "account.unmute": "@{name} niet langer negeren", "account.unmute_notifications": "@{name} meldingen niet langer negeren", - "account.view_full_profile": "Volledig profiel tonen", "alert.unexpected.message": "Er deed zich een onverwachte fout voor", "alert.unexpected.title": "Oeps!", "boost_modal.combo": "Je kunt {combo} klikken om dit de volgende keer over te slaan", @@ -85,6 +83,7 @@ "compose_form.spoiler.unmarked": "Tekst is niet verborgen", "compose_form.spoiler_placeholder": "Waarschuwingstekst", "confirmation_modal.cancel": "Annuleren", + "confirmations.block.block_and_report": "Block & Report", "confirmations.block.confirm": "Blokkeren", "confirmations.block.message": "Weet je het zeker dat je {name} wilt blokkeren?", "confirmations.delete.confirm": "Verwijderen", @@ -133,7 +132,6 @@ "empty_column.mutes": "Jij hebt nog geen gebruikers genegeerd.", "empty_column.notifications": "Je hebt nog geen meldingen. Begin met iemand een gesprek.", "empty_column.public": "Er is hier helemaal niks! Toot iets in het openbaar of volg mensen van andere servers om het te vullen", - "error_boundary.it_crashed": "It crashed!", "follow_request.authorize": "Goedkeuren", "follow_request.reject": "Afkeuren", "getting_started.developers": "Ontwikkelaars", @@ -248,6 +246,7 @@ "notification.favourite": "{name} voegde jouw toot als favoriet toe", "notification.follow": "{name} volgt jou nu", "notification.mention": "{name} vermeldde jou", + "notification.poll": "A poll you have voted in has ended", "notification.reblog": "{name} boostte jouw toot", "notifications.clear": "Meldingen verwijderen", "notifications.clear_confirmation": "Weet je het zeker dat je al jouw meldingen wilt verwijderen?", @@ -258,6 +257,7 @@ "notifications.column_settings.filter_bar.show": "Tonen", "notifications.column_settings.follow": "Nieuwe volgers:", "notifications.column_settings.mention": "Vermeldingen:", + "notifications.column_settings.poll": "Poll results:", "notifications.column_settings.push": "Pushmeldingen", "notifications.column_settings.reblog": "Boosts:", "notifications.column_settings.show": "In kolom tonen", @@ -267,6 +267,7 @@ "notifications.filter.favourites": "Favorieten", "notifications.filter.follows": "Die jij volgt", "notifications.filter.mentions": "Vermeldingen", + "notifications.filter.polls": "Poll results", "notifications.group": "{count} meldingen", "poll.closed": "Gesloten", "poll.refresh": "Vernieuwen", @@ -308,7 +309,6 @@ "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.admin_account": "Moderatie-omgeving van @{name} openen", "status.admin_status": "Deze toot in de moderatie-omgeving openen", "status.block": "Blokkeer @{name}", diff --git a/app/javascript/mastodon/locales/no.json b/app/javascript/mastodon/locales/no.json index 45a3d500f..9556c5ad8 100644 --- a/app/javascript/mastodon/locales/no.json +++ b/app/javascript/mastodon/locales/no.json @@ -5,7 +5,6 @@ "account.block_domain": "Skjul alt fra {domain}", "account.blocked": "Blocked", "account.direct": "Direct Message @{name}", - "account.disclaimer_full": "Informasjonen nedenfor kan gi et ufullstendig bilde av brukerens profil.", "account.domain_blocked": "Domain hidden", "account.edit_profile": "Rediger profil", "account.endorse": "Feature on profile", @@ -36,7 +35,6 @@ "account.unfollow": "Avfølg", "account.unmute": "Avdemp @{name}", "account.unmute_notifications": "Vis varsler fra @{name}", - "account.view_full_profile": "Vis hele profilen", "alert.unexpected.message": "An unexpected error occurred.", "alert.unexpected.title": "Oops!", "boost_modal.combo": "You kan trykke {combo} for å hoppe over dette neste gang", @@ -85,6 +83,7 @@ "compose_form.spoiler.unmarked": "Text is not hidden", "compose_form.spoiler_placeholder": "Innholdsadvarsel", "confirmation_modal.cancel": "Avbryt", + "confirmations.block.block_and_report": "Block & Report", "confirmations.block.confirm": "Blokkèr", "confirmations.block.message": "Er du sikker på at du vil blokkere {name}?", "confirmations.delete.confirm": "Slett", @@ -133,7 +132,6 @@ "empty_column.mutes": "You haven't muted any users yet.", "empty_column.notifications": "Du har ingen varsler ennå. Kommuniser med andre for å begynne samtalen.", "empty_column.public": "Det er ingenting her! Skriv noe offentlig, eller følg brukere manuelt fra andre instanser for å fylle den opp", - "error_boundary.it_crashed": "It crashed!", "follow_request.authorize": "Autorisér", "follow_request.reject": "Avvis", "getting_started.developers": "Developers", @@ -248,6 +246,7 @@ "notification.favourite": "{name} likte din status", "notification.follow": "{name} fulgte deg", "notification.mention": "{name} nevnte deg", + "notification.poll": "A poll you have voted in has ended", "notification.reblog": "{name} fremhevde din status", "notifications.clear": "Fjern varsler", "notifications.clear_confirmation": "Er du sikker på at du vil fjerne alle dine varsler permanent?", @@ -258,6 +257,7 @@ "notifications.column_settings.filter_bar.show": "Show", "notifications.column_settings.follow": "Nye følgere:", "notifications.column_settings.mention": "Nevnt:", + "notifications.column_settings.poll": "Poll results:", "notifications.column_settings.push": "Push varsler", "notifications.column_settings.reblog": "Fremhevet:", "notifications.column_settings.show": "Vis i kolonne", @@ -267,6 +267,7 @@ "notifications.filter.favourites": "Favourites", "notifications.filter.follows": "Follows", "notifications.filter.mentions": "Mentions", + "notifications.filter.polls": "Poll results", "notifications.group": "{count} notifications", "poll.closed": "Closed", "poll.refresh": "Refresh", @@ -308,7 +309,6 @@ "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.admin_account": "Open moderation interface for @{name}", "status.admin_status": "Open this status in the moderation interface", "status.block": "Block @{name}", diff --git a/app/javascript/mastodon/locales/oc.json b/app/javascript/mastodon/locales/oc.json index 625cd49f0..8fc8762a4 100644 --- a/app/javascript/mastodon/locales/oc.json +++ b/app/javascript/mastodon/locales/oc.json @@ -5,7 +5,6 @@ "account.block_domain": "Tot amagar del domeni {domain}", "account.blocked": "Blocat", "account.direct": "Escriure un MP a @{name}", - "account.disclaimer_full": "Aquelas informacions de perfil pòdon èsser incomplètas.", "account.domain_blocked": "Domeni amagat", "account.edit_profile": "Modificar lo perfil", "account.endorse": "Mostrar pel perfil", @@ -36,7 +35,6 @@ "account.unfollow": "Quitar de sègre", "account.unmute": "Quitar de rescondre @{name}", "account.unmute_notifications": "Mostrar las notificacions de @{name}", - "account.view_full_profile": "Veire lo perfil complèt", "alert.unexpected.message": "Una error s’es producha.", "alert.unexpected.title": "Ops !", "boost_modal.combo": "Podètz botar {combo} per passar aquò lo còp que ven", @@ -73,10 +71,10 @@ "compose_form.lock_disclaimer": "Vòstre compte es pas {locked}. Tot lo monde pòt vos sègre e veire los estatuts reservats als seguidors.", "compose_form.lock_disclaimer.lock": "clavat", "compose_form.placeholder": "A de qué pensatz ?", - "compose_form.poll.add_option": "Add a choice", - "compose_form.poll.duration": "Poll duration", - "compose_form.poll.option_placeholder": "Choice {number}", - "compose_form.poll.remove_option": "Remove this choice", + "compose_form.poll.add_option": "Ajustar una causida", + "compose_form.poll.duration": "Durada del sondatge", + "compose_form.poll.option_placeholder": "Opcion {number}", + "compose_form.poll.remove_option": "Levar aquesta opcion", "compose_form.publish": "Tut", "compose_form.publish_loud": "{publish} !", "compose_form.sensitive.marked": "Lo mèdia es marcat coma sensible", @@ -85,6 +83,7 @@ "compose_form.spoiler.unmarked": "Lo tèxte es pas rescondut", "compose_form.spoiler_placeholder": "Escrivètz l’avertiment aquí", "confirmation_modal.cancel": "Anullar", + "confirmations.block.block_and_report": "Block & Report", "confirmations.block.confirm": "Blocar", "confirmations.block.message": "Volètz vertadièrament blocar {name} ?", "confirmations.delete.confirm": "Escafar", @@ -133,7 +132,6 @@ "empty_column.mutes": "Encara avètz pas mes en silenci degun.", "empty_column.notifications": "Avètz pas encara de notificacions. Respondètz a qualqu’un per començar una conversacion.", "empty_column.public": "I a pas res aquí ! Escrivètz quicòm de public, o seguètz de personas d’autres servidors per garnir lo flux public", - "error_boundary.it_crashed": "It crashed!", "follow_request.authorize": "Acceptar", "follow_request.reject": "Regetar", "getting_started.developers": "Desvelopaires", @@ -156,9 +154,9 @@ "home.column_settings.basic": "Basic", "home.column_settings.show_reblogs": "Mostrar los partatges", "home.column_settings.show_replies": "Mostrar las responsas", - "intervals.full.days": "{number, plural, one {# day} other {# days}}", - "intervals.full.hours": "{number, plural, one {# hour} other {# hours}}", - "intervals.full.minutes": "{number, plural, one {# minute} other {# minutes}}", + "intervals.full.days": "{number, plural, one {# jorn} other {# jorns}}", + "intervals.full.hours": "{number, plural, one {# ora} other {# oras}}", + "intervals.full.minutes": "{number, plural, one {# minuta} other {# minutas}}", "introduction.federation.action": "Seguent", "introduction.federation.federated.headline": "Federat", "introduction.federation.federated.text": "Los tuts publics d’autres servidors del fediverse apareisseràn dins lo flux d’actualitats.", @@ -248,6 +246,7 @@ "notification.favourite": "{name} a ajustat a sos favorits", "notification.follow": "{name} vos sèc", "notification.mention": "{name} vos a mencionat", + "notification.poll": "Avètz participat a un sondatge que ven de s’acabar", "notification.reblog": "{name} a partejat vòstre estatut", "notifications.clear": "Escafar", "notifications.clear_confirmation": "Volètz vertadièrament escafar totas vòstras las notificacions ?", @@ -258,6 +257,7 @@ "notifications.column_settings.filter_bar.show": "Mostrar", "notifications.column_settings.follow": "Nòus seguidors :", "notifications.column_settings.mention": "Mencions :", + "notifications.column_settings.poll": "Resultats del sondatge :", "notifications.column_settings.push": "Notificacions", "notifications.column_settings.reblog": "Partatges :", "notifications.column_settings.show": "Mostrar dins la colomna", @@ -267,13 +267,14 @@ "notifications.filter.favourites": "Favorits", "notifications.filter.follows": "Seguiments", "notifications.filter.mentions": "Mencions", + "notifications.filter.polls": "Resultats del sondatge", "notifications.group": "{count} notificacions", "poll.closed": "Tampat", "poll.refresh": "Actualizar", "poll.total_votes": "{count, plural, one {# vòte} other {# vòtes}}", "poll.vote": "Votar", - "poll_button.add_poll": "Add a poll", - "poll_button.remove_poll": "Remove poll", + "poll_button.add_poll": "Ajustar un sondatge", + "poll_button.remove_poll": "Levar lo sondatge", "privacy.change": "Ajustar la confidencialitat del messatge", "privacy.direct.long": "Mostrar pas qu’a las personas mencionadas", "privacy.direct.short": "Dirècte", @@ -308,7 +309,6 @@ "search_results.hashtags": "Etiquetas", "search_results.statuses": "Tuts", "search_results.total": "{count, number} {count, plural, one {resultat} other {resultats}}", - "standalone.public_title": "Una ulhada dedins…", "status.admin_account": "Dobrir l’interfàcia de moderacion per @{name}", "status.admin_status": "Dobrir aqueste estatut dins l’interfàcia de moderacion", "status.block": "Blocar @{name}", @@ -366,7 +366,7 @@ "upload_area.title": "Lisatz e depausatz per mandar", "upload_button.label": "Ajustar un mèdia (JPEG, PNG, GIF, WebM, MP4, MOV)", "upload_error.limit": "Talha maximum pels mandadís subrepassada.", - "upload_error.poll": "File upload not allowed with polls.", + "upload_error.poll": "Lo mandadís de fichièr es pas autorizat pels sondatges.", "upload_form.description": "Descripcion pels mal vesents", "upload_form.focus": "Modificar l’apercebut", "upload_form.undo": "Suprimir", diff --git a/app/javascript/mastodon/locales/pl.json b/app/javascript/mastodon/locales/pl.json index 9d7bef774..107ac8757 100644 --- a/app/javascript/mastodon/locales/pl.json +++ b/app/javascript/mastodon/locales/pl.json @@ -5,7 +5,6 @@ "account.block_domain": "Blokuj wszystko z {domain}", "account.blocked": "Zablokowany(-a)", "account.direct": "Wyślij wiadomość bezpośrednią do @{name}", - "account.disclaimer_full": "Poniższe informacje mogą nie odwzorowywać bezbłędnie profilu użytkownika.", "account.domain_blocked": "Ukryto domenę", "account.edit_profile": "Edytuj profil", "account.endorse": "Polecaj na profilu", @@ -36,7 +35,6 @@ "account.unfollow": "Przestań śledzić", "account.unmute": "Cofnij wyciszenie @{name}", "account.unmute_notifications": "Cofnij wyciszenie powiadomień od @{name}", - "account.view_full_profile": "Wyświetl pełny profil", "alert.unexpected.message": "Wystąpił nieoczekiwany błąd.", "alert.unexpected.title": "O nie!", "boost_modal.combo": "Naciśnij {combo}, aby pominąć to następnym razem", @@ -89,6 +87,7 @@ "compose_form.spoiler.unmarked": "Tekst nie jest ukryty", "compose_form.spoiler_placeholder": "Wprowadź swoje ostrzeżenie o zawartości", "confirmation_modal.cancel": "Anuluj", + "confirmations.block.block_and_report": "Block & Report", "confirmations.block.confirm": "Zablokuj", "confirmations.block.message": "Czy na pewno chcesz zablokować {name}?", "confirmations.delete.confirm": "Usuń", @@ -137,7 +136,6 @@ "empty_column.mutes": "Nie wyciszyłeś(-aś) jeszcze żadnego użytkownika.", "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 serwerów, aby to wyświetlić", - "error_boundary.it_crashed": "It crashed!", "follow_request.authorize": "Autoryzuj", "follow_request.reject": "Odrzuć", "getting_started.developers": "Dla programistów", @@ -253,6 +251,7 @@ "notification.favourite": "{name} dodał(a) Twój wpis do ulubionych", "notification.follow": "{name} zaczął(-ęła) Cię śledzić", "notification.mention": "{name} wspomniał(a) o tobie", + "notification.poll": "A poll you have voted in has ended", "notification.reblog": "{name} podbił(a) Twój wpis", "notifications.clear": "Wyczyść powiadomienia", "notifications.clear_confirmation": "Czy na pewno chcesz bezpowrotnie usunąć wszystkie powiadomienia?", @@ -263,6 +262,7 @@ "notifications.column_settings.filter_bar.show": "Pokaż", "notifications.column_settings.follow": "Nowi śledzący:", "notifications.column_settings.mention": "Wspomnienia:", + "notifications.column_settings.poll": "Poll results:", "notifications.column_settings.push": "Powiadomienia push", "notifications.column_settings.reblog": "Podbicia:", "notifications.column_settings.show": "Pokaż w kolumnie", @@ -272,6 +272,7 @@ "notifications.filter.favourites": "Ulubione", "notifications.filter.follows": "Śledzenia", "notifications.filter.mentions": "Wspomienia", + "notifications.filter.polls": "Poll results", "notifications.group": "{count, number} {count, plural, one {powiadomienie} few {powiadomienia} many {powiadomień} more {powiadomień}}", "poll.closed": "Zamknięte", "poll.refresh": "Odśwież", @@ -313,7 +314,6 @@ "search_results.hashtags": "Hashtagi", "search_results.statuses": "Wpisy", "search_results.total": "{count, number} {count, plural, one {wynik} few {wyniki} many {wyników} more {wyników}}", - "standalone.public_title": "Spojrzenie w głąb…", "status.admin_account": "Otwórz interfejs moderacyjny dla @{name}", "status.admin_status": "Otwórz ten wpis w interfejsie moderacyjnym", "status.block": "Zablokuj @{name}", diff --git a/app/javascript/mastodon/locales/pt-BR.json b/app/javascript/mastodon/locales/pt-BR.json index 9562ce648..7533a462b 100644 --- a/app/javascript/mastodon/locales/pt-BR.json +++ b/app/javascript/mastodon/locales/pt-BR.json @@ -5,7 +5,6 @@ "account.block_domain": "Esconder tudo de {domain}", "account.blocked": "Bloqueado", "account.direct": "Direct Message @{name}", - "account.disclaimer_full": "As informações abaixo podem refletir o perfil do usuário de maneira incompleta.", "account.domain_blocked": "Domínio escondido", "account.edit_profile": "Editar perfil", "account.endorse": "Destacar no perfil", @@ -36,7 +35,6 @@ "account.unfollow": "Deixar de seguir", "account.unmute": "Não silenciar @{name}", "account.unmute_notifications": "Retirar silêncio das notificações vindas de @{name}", - "account.view_full_profile": "Ver perfil completo", "alert.unexpected.message": "Um erro inesperado ocorreu.", "alert.unexpected.title": "Oops!", "boost_modal.combo": "Você pode pressionar {combo} para ignorar este diálogo na próxima vez", @@ -85,6 +83,7 @@ "compose_form.spoiler.unmarked": "O texto não está escondido", "compose_form.spoiler_placeholder": "Aviso de conteúdo", "confirmation_modal.cancel": "Cancelar", + "confirmations.block.block_and_report": "Block & Report", "confirmations.block.confirm": "Bloquear", "confirmations.block.message": "Você tem certeza de que quer bloquear {name}?", "confirmations.delete.confirm": "Excluir", @@ -133,7 +132,6 @@ "empty_column.mutes": "Você ainda não silenciou nenhum usuário.", "empty_column.notifications": "Você ainda não possui notificações. Interaja com outros usuários para começar a conversar.", "empty_column.public": "Não há nada aqui! Escreva algo publicamente ou siga manualmente usuários de outras instâncias", - "error_boundary.it_crashed": "It crashed!", "follow_request.authorize": "Autorizar", "follow_request.reject": "Rejeitar", "getting_started.developers": "Desenvolvedores", @@ -248,6 +246,7 @@ "notification.favourite": "{name} adicionou a sua postagem aos favoritos", "notification.follow": "{name} te seguiu", "notification.mention": "{name} te mencionou", + "notification.poll": "A poll you have voted in has ended", "notification.reblog": "{name} compartilhou a sua postagem", "notifications.clear": "Limpar notificações", "notifications.clear_confirmation": "Você tem certeza de que quer limpar todas as suas notificações permanentemente?", @@ -258,6 +257,7 @@ "notifications.column_settings.filter_bar.show": "Mostrar", "notifications.column_settings.follow": "Novos seguidores:", "notifications.column_settings.mention": "Menções:", + "notifications.column_settings.poll": "Poll results:", "notifications.column_settings.push": "Enviar notificações", "notifications.column_settings.reblog": "Compartilhamento:", "notifications.column_settings.show": "Mostrar nas colunas", @@ -267,6 +267,7 @@ "notifications.filter.favourites": "Favoritos", "notifications.filter.follows": "Seguidores", "notifications.filter.mentions": "Menções", + "notifications.filter.polls": "Poll results", "notifications.group": "{count} notificações", "poll.closed": "Closed", "poll.refresh": "Refresh", @@ -308,7 +309,6 @@ "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.admin_account": "Abrir interface de moderação para @{name}", "status.admin_status": "Abrir esse status na interface de moderação", "status.block": "Block @{name}", diff --git a/app/javascript/mastodon/locales/pt.json b/app/javascript/mastodon/locales/pt.json index fa2ade697..001a48b04 100644 --- a/app/javascript/mastodon/locales/pt.json +++ b/app/javascript/mastodon/locales/pt.json @@ -5,7 +5,6 @@ "account.block_domain": "Esconder tudo do domínio {domain}", "account.blocked": "Bloqueado", "account.direct": "Mensagem directa @{name}", - "account.disclaimer_full": "As informações abaixo podem reflectir o perfil do utilizador de forma incompleta.", "account.domain_blocked": "Domínio escondido", "account.edit_profile": "Editar perfil", "account.endorse": "Atributo no perfil", @@ -36,7 +35,6 @@ "account.unfollow": "Deixar de seguir", "account.unmute": "Não silenciar @{name}", "account.unmute_notifications": "Deixar de silenciar @{name}", - "account.view_full_profile": "Ver perfil completo", "alert.unexpected.message": "Ocorreu um erro inesperado.", "alert.unexpected.title": "Bolas!", "boost_modal.combo": "Pode clicar {combo} para não voltar a ver", @@ -85,6 +83,7 @@ "compose_form.spoiler.unmarked": "O texto não está escondido", "compose_form.spoiler_placeholder": "Escreve o teu aviso aqui", "confirmation_modal.cancel": "Cancelar", + "confirmations.block.block_and_report": "Block & Report", "confirmations.block.confirm": "Bloquear", "confirmations.block.message": "De certeza que queres bloquear {name}?", "confirmations.delete.confirm": "Eliminar", @@ -133,7 +132,6 @@ "empty_column.mutes": "Ainda não silenciaste qualquer utilizador.", "empty_column.notifications": "Não tens notificações. Interage com outros utilizadores para iniciar uma conversa.", "empty_column.public": "Não há nada aqui! Escreve algo publicamente ou segue outros utilizadores para veres aqui os conteúdos públicos", - "error_boundary.it_crashed": "It crashed!", "follow_request.authorize": "Autorizar", "follow_request.reject": "Rejeitar", "getting_started.developers": "Responsáveis pelo desenvolvimento", @@ -248,6 +246,7 @@ "notification.favourite": "{name} adicionou o teu post aos favoritos", "notification.follow": "{name} seguiu-te", "notification.mention": "{name} mencionou-te", + "notification.poll": "A poll you have voted in has ended", "notification.reblog": "{name} partilhou o teu post", "notifications.clear": "Limpar notificações", "notifications.clear_confirmation": "Queres mesmo limpar todas as notificações?", @@ -258,6 +257,7 @@ "notifications.column_settings.filter_bar.show": "Mostrar", "notifications.column_settings.follow": "Novos seguidores:", "notifications.column_settings.mention": "Menções:", + "notifications.column_settings.poll": "Poll results:", "notifications.column_settings.push": "Notificações Push", "notifications.column_settings.reblog": "Partilhas:", "notifications.column_settings.show": "Mostrar nas colunas", @@ -267,6 +267,7 @@ "notifications.filter.favourites": "Favoritas", "notifications.filter.follows": "Seguimento", "notifications.filter.mentions": "Referências", + "notifications.filter.polls": "Poll results", "notifications.group": "{count} notificações", "poll.closed": "Fechado", "poll.refresh": "Recarregar", @@ -308,7 +309,6 @@ "search_results.hashtags": "Hashtags", "search_results.statuses": "Publicações", "search_results.total": "{count, number} {count, plural, one {resultado} other {resultados}}", - "standalone.public_title": "Espreitar lá dentro...", "status.admin_account": "Abrir a interface de moderação para @{name}", "status.admin_status": "Abrir esta publicação na interface de moderação", "status.block": "Block @{name}", diff --git a/app/javascript/mastodon/locales/ro.json b/app/javascript/mastodon/locales/ro.json index 071fbb507..7192e10b9 100644 --- a/app/javascript/mastodon/locales/ro.json +++ b/app/javascript/mastodon/locales/ro.json @@ -5,7 +5,6 @@ "account.block_domain": "Ascunde tot de la {domain}", "account.blocked": "Blocat", "account.direct": "Mesaj direct @{name}", - "account.disclaimer_full": "Informațiile de mai jos pot reflecta profilul utilizatorului incomplet.", "account.domain_blocked": "Domeniu ascuns", "account.edit_profile": "Editează profilul", "account.endorse": "Redistribuie pe profil", @@ -36,7 +35,6 @@ "account.unfollow": "Nu mai urmări", "account.unmute": "Activează notificările de la @{name}", "account.unmute_notifications": "Activează notificările de la @{name}", - "account.view_full_profile": "Vezi profilul complet", "alert.unexpected.message": "A apărut o eroare neașteptată.", "alert.unexpected.title": "Hopa!", "boost_modal.combo": "Poți apăsa {combo} pentru a omite asta data viitoare", @@ -85,6 +83,7 @@ "compose_form.spoiler.unmarked": "Textul nu este ascuns", "compose_form.spoiler_placeholder": "Scrie averitzarea aici", "confirmation_modal.cancel": "Anulează", + "confirmations.block.block_and_report": "Block & Report", "confirmations.block.confirm": "Blochează", "confirmations.block.message": "Ești sigur că vrei să blochezi {name}?", "confirmations.delete.confirm": "Șterge", @@ -133,7 +132,6 @@ "empty_column.mutes": "Nu ai oprit nici un utilizator incă.", "empty_column.notifications": "Nu ai nici o notificare încă. Interacționează cu alții pentru a începe o conversație.", "empty_column.public": "Nu este nimci aici încă! Scrie ceva public, sau urmărește alți utilizatori din alte instanțe pentru a porni fluxul", - "error_boundary.it_crashed": "It crashed!", "follow_request.authorize": "Autorizează", "follow_request.reject": "Respinge", "getting_started.developers": "Dezvoltatori", @@ -248,6 +246,7 @@ "notification.favourite": "{name} a adăugat statusul tău la favorite", "notification.follow": "{name} te urmărește", "notification.mention": "{name} te-a menționat", + "notification.poll": "A poll you have voted in has ended", "notification.reblog": "{name} a redistribuit postarea ta", "notifications.clear": "Șterge notificările", "notifications.clear_confirmation": "Ești sigur că vrei să ștergi toate notificările?", @@ -258,6 +257,7 @@ "notifications.column_settings.filter_bar.show": "Arată", "notifications.column_settings.follow": "Noi urmăritori:", "notifications.column_settings.mention": "Mențiuni:", + "notifications.column_settings.poll": "Poll results:", "notifications.column_settings.push": "Notificări push", "notifications.column_settings.reblog": "Redistribuite:", "notifications.column_settings.show": "Arată în coloană", @@ -267,6 +267,7 @@ "notifications.filter.favourites": "Favorite", "notifications.filter.follows": "Urmărește", "notifications.filter.mentions": "Menționări", + "notifications.filter.polls": "Poll results", "notifications.group": "{count} notificări", "poll.closed": "Closed", "poll.refresh": "Refresh", @@ -308,7 +309,6 @@ "search_results.hashtags": "Hashtaguri", "search_results.statuses": "Postări", "search_results.total": "{count, number} {count, plural, one {result} other {results}}", - "standalone.public_title": "Se întâmplă acum...", "status.admin_account": "Open moderation interface for @{name}", "status.admin_status": "Open this status in the moderation interface", "status.block": "Blochează @{name}", diff --git a/app/javascript/mastodon/locales/ru.json b/app/javascript/mastodon/locales/ru.json index 1e149c470..09425c32e 100644 --- a/app/javascript/mastodon/locales/ru.json +++ b/app/javascript/mastodon/locales/ru.json @@ -5,7 +5,6 @@ "account.block_domain": "Блокировать все с {domain}", "account.blocked": "Заблокирован(а)", "account.direct": "Написать @{name}", - "account.disclaimer_full": "Нижеуказанная информация может не полностью отражать профиль пользователя.", "account.domain_blocked": "Домен скрыт", "account.edit_profile": "Изменить профиль", "account.endorse": "Рекомендовать в профиле", @@ -36,7 +35,6 @@ "account.unfollow": "Отписаться", "account.unmute": "Снять глушение", "account.unmute_notifications": "Показывать уведомления от @{name}", - "account.view_full_profile": "Показать полный профиль", "alert.unexpected.message": "Что-то пошло не так.", "alert.unexpected.title": "Ой!", "boost_modal.combo": "Нажмите {combo}, чтобы пропустить это в следующий раз", @@ -85,6 +83,7 @@ "compose_form.spoiler.unmarked": "Текст не скрыт", "compose_form.spoiler_placeholder": "Текст предупреждения", "confirmation_modal.cancel": "Отмена", + "confirmations.block.block_and_report": "Block & Report", "confirmations.block.confirm": "Заблокировать", "confirmations.block.message": "Вы уверены, что хотите заблокировать {name}?", "confirmations.delete.confirm": "Удалить", @@ -133,7 +132,6 @@ "empty_column.mutes": "Вы ещё никого не заглушили.", "empty_column.notifications": "У Вас еще нет уведомлений. Заведите знакомство с другими пользователями, чтобы начать разговор.", "empty_column.public": "Здесь ничего нет! Опубликуйте что-нибудь или подпишитесь на пользователей с других узлов, чтобы заполнить ленту.", - "error_boundary.it_crashed": "It crashed!", "follow_request.authorize": "Авторизовать", "follow_request.reject": "Отказать", "getting_started.developers": "Для разработчиков", @@ -248,6 +246,7 @@ "notification.favourite": "{name} понравился Ваш статус", "notification.follow": "{name} подписался(-лась) на Вас", "notification.mention": "{name} упомянул(а) Вас", + "notification.poll": "A poll you have voted in has ended", "notification.reblog": "{name} продвинул(а) Ваш статус", "notifications.clear": "Очистить уведомления", "notifications.clear_confirmation": "Вы уверены, что хотите очистить все уведомления?", @@ -258,6 +257,7 @@ "notifications.column_settings.filter_bar.show": "Show", "notifications.column_settings.follow": "Новые подписчики:", "notifications.column_settings.mention": "Упоминания:", + "notifications.column_settings.poll": "Poll results:", "notifications.column_settings.push": "Push-уведомления", "notifications.column_settings.reblog": "Продвижения:", "notifications.column_settings.show": "Показывать в колонке", @@ -267,6 +267,7 @@ "notifications.filter.favourites": "Favourites", "notifications.filter.follows": "Follows", "notifications.filter.mentions": "Mentions", + "notifications.filter.polls": "Poll results", "notifications.group": "{count} уведомл.", "poll.closed": "Closed", "poll.refresh": "Refresh", @@ -308,7 +309,6 @@ "search_results.hashtags": "Хэштеги", "search_results.statuses": "Посты", "search_results.total": "{count, number} {count, plural, one {результат} few {результата} many {результатов} other {результатов}}", - "standalone.public_title": "Прямо сейчас", "status.admin_account": "Open moderation interface for @{name}", "status.admin_status": "Open this status in the moderation interface", "status.block": "Заблокировать @{name}", diff --git a/app/javascript/mastodon/locales/sk.json b/app/javascript/mastodon/locales/sk.json index 17b50522f..5542198f7 100644 --- a/app/javascript/mastodon/locales/sk.json +++ b/app/javascript/mastodon/locales/sk.json @@ -5,7 +5,6 @@ "account.block_domain": "Ukry všetko z {domain}", "account.blocked": "Blokovaný/á", "account.direct": "Súkromná správa pre @{name}", - "account.disclaimer_full": "Inofrmácie uvedené nižšie nemusia byť úplným odrazom uživateľovho účtu.", "account.domain_blocked": "Doména ukrytá", "account.edit_profile": "Upraviť profil", "account.endorse": "Zobrazuj na profile", @@ -36,7 +35,6 @@ "account.unfollow": "Prestaň následovať", "account.unmute": "Prestaň ignorovať @{name}", "account.unmute_notifications": "Zrušiť stlmenie oznámení od @{name}", - "account.view_full_profile": "Pozri celý profil", "alert.unexpected.message": "Vyskytla sa nečakaná chyba.", "alert.unexpected.title": "Oops!", "boost_modal.combo": "Nabudúce môžeš kliknúť {combo} pre preskočenie", @@ -73,10 +71,10 @@ "compose_form.lock_disclaimer": "Váš účet nie je {locked}. Ktokoľvek ťa môže nasledovať a vidieť tvoje správy pre sledujúcich.", "compose_form.lock_disclaimer.lock": "zamknutý", "compose_form.placeholder": "Čo máš na mysli?", - "compose_form.poll.add_option": "Add a choice", - "compose_form.poll.duration": "Poll duration", - "compose_form.poll.option_placeholder": "Choice {number}", - "compose_form.poll.remove_option": "Remove this choice", + "compose_form.poll.add_option": "Pridaj voľbu", + "compose_form.poll.duration": "Trvanie ankety", + "compose_form.poll.option_placeholder": "Voľba {number}", + "compose_form.poll.remove_option": "Odstráň túto voľbu", "compose_form.publish": "Pošli", "compose_form.publish_loud": "{publish}!", "compose_form.sensitive.marked": "Médiálny obsah je označený ako chúlostivý", @@ -85,6 +83,7 @@ "compose_form.spoiler.unmarked": "Text nieje ukrytý", "compose_form.spoiler_placeholder": "Sem napíš tvoje varovanie", "confirmation_modal.cancel": "Zruš", + "confirmations.block.block_and_report": "Block & Report", "confirmations.block.confirm": "Blokuj", "confirmations.block.message": "Si si istý/á, že chceš blokovať {name}?", "confirmations.delete.confirm": "Vymaž", @@ -133,7 +132,6 @@ "empty_column.mutes": "Ešte si nestĺmil žiadných užívateľov.", "empty_column.notifications": "Ešte nemáš žiadne oznámenia. Začni komunikovať s ostatnými, aby diskusia mohla začať.", "empty_column.public": "Ešte tu nič nie je. Napíš niečo verejne, alebo začni sledovať užívateľov z iných serverov, aby tu niečo pribudlo", - "error_boundary.it_crashed": "It crashed!", "follow_request.authorize": "Povoľ prístup", "follow_request.reject": "Odmietni", "getting_started.developers": "Vývojári", @@ -156,9 +154,9 @@ "home.column_settings.basic": "Základné", "home.column_settings.show_reblogs": "Zobraziť povýšené", "home.column_settings.show_replies": "Ukázať odpovede", - "intervals.full.days": "{number, plural, one {# day} other {# days}}", - "intervals.full.hours": "{number, plural, one {# hour} other {# hours}}", - "intervals.full.minutes": "{number, plural, one {# minute} other {# minutes}}", + "intervals.full.days": "{number, plural, one {# deň} few {# dní} many {# dní} other {# dni}}", + "intervals.full.hours": "{number, plural, one {# hodina} few {# hodín} many {# hodín} other {# hodiny}}", + "intervals.full.minutes": "{number, plural, one {# minúta} few {# minút} many {# minút} other {# minúty}}", "introduction.federation.action": "Ďalej", "introduction.federation.federated.headline": "Federated", "introduction.federation.federated.text": "Verejné príspevky z ostatných serverov vo fediverse budú zobrazenie vo federovanej časovej osi.", @@ -245,9 +243,10 @@ "navigation_bar.preferences": "Voľby", "navigation_bar.public_timeline": "Federovaná časová os", "navigation_bar.security": "Zabezbečenie", - "notification.favourite": "{name} sa páči tvoj status", + "notification.favourite": "{name} si obľúbil/a tvoj príspevok", "notification.follow": "{name} ťa začal/a následovať", "notification.mention": "{name} ťa spomenul/a", + "notification.poll": "Anketa v ktorej si hlasoval/a sa skončila", "notification.reblog": "{name} zdieľal/a tvoj status", "notifications.clear": "Vyčistiť zoznam notifikácii", "notifications.clear_confirmation": "Naozaj chcete nenávratne prečistiť všetky vaše notifikácie?", @@ -258,6 +257,7 @@ "notifications.column_settings.filter_bar.show": "Ukáž", "notifications.column_settings.follow": "Noví následujúci:", "notifications.column_settings.mention": "Zmienenia:", + "notifications.column_settings.poll": "Výsledky ankiet:", "notifications.column_settings.push": "Push notifikácie", "notifications.column_settings.reblog": "Boosty:", "notifications.column_settings.show": "Zobraziť v stĺpci", @@ -267,13 +267,14 @@ "notifications.filter.favourites": "Obľúbené", "notifications.filter.follows": "Sledovania", "notifications.filter.mentions": "Iba spomenutia", + "notifications.filter.polls": "Výsledky ankiet", "notifications.group": "{count} oboznámení", "poll.closed": "Uzatvorená", "poll.refresh": "Aktualizuj", "poll.total_votes": "{count, plural, one {# hlas} few {# hlasov} many {# hlasov} other {# hlasy}}", "poll.vote": "Hlasuj", - "poll_button.add_poll": "Add a poll", - "poll_button.remove_poll": "Remove poll", + "poll_button.add_poll": "Pridaj anketu", + "poll_button.remove_poll": "Odstráň anketu", "privacy.change": "Uprav súkromie príspevku", "privacy.direct.long": "Pošli iba spomenutým používateľom", "privacy.direct.short": "Súkromne", @@ -308,7 +309,6 @@ "search_results.hashtags": "Haštagy", "search_results.statuses": "Príspevky", "search_results.total": "{count, number} {count, plural, one {výsledok} many {výsledkov} other {výsledky}}", - "standalone.public_title": "Náhľad dovnútra...", "status.admin_account": "Otvor moderovacie rozhranie užívateľa @{name}", "status.admin_status": "Otvor tento príspevok v moderovacom rozhraní", "status.block": "Blokovať @{name}", @@ -366,7 +366,7 @@ "upload_area.title": "Pretiahni a pusť pre nahratie", "upload_button.label": "Pridať médiálny súbor (JPEG, PNG, GIF, WebM, MP4, MOV)", "upload_error.limit": "Limit pre nahrávanie súborov bol prekročený.", - "upload_error.poll": "File upload not allowed with polls.", + "upload_error.poll": "Nahrávanie súborov pri anketách nieje dovolené.", "upload_form.description": "Opis pre slabo vidiacich", "upload_form.focus": "Pozmeň náhľad", "upload_form.undo": "Vymaž", diff --git a/app/javascript/mastodon/locales/sl.json b/app/javascript/mastodon/locales/sl.json index 9ee2e5b52..bef4efe0e 100644 --- a/app/javascript/mastodon/locales/sl.json +++ b/app/javascript/mastodon/locales/sl.json @@ -5,7 +5,6 @@ "account.block_domain": "Skrij vse iz {domain}", "account.blocked": "Blokirano", "account.direct": "Neposredno sporočilo @{name}", - "account.disclaimer_full": "Spodnje informacije lahko nepopolno prikazujejo profil uporabnika.", "account.domain_blocked": "Skrita domena", "account.edit_profile": "Uredi profil", "account.endorse": "Zmožnost profila", @@ -36,7 +35,6 @@ "account.unfollow": "Prenehaj slediti", "account.unmute": "Odtišaj @{name}", "account.unmute_notifications": "Vklopi obvestila od @{name}", - "account.view_full_profile": "Ogled celotnega profila", "alert.unexpected.message": "Zgodila se je nepričakovana napaka.", "alert.unexpected.title": "Uups!", "boost_modal.combo": "Če želite naslednjič preskočiti to, lahko pritisnete {combo}", @@ -85,6 +83,7 @@ "compose_form.spoiler.unmarked": "Besedilo ni skrito", "compose_form.spoiler_placeholder": "Napišite opozorilo tukaj", "confirmation_modal.cancel": "Prekliči", + "confirmations.block.block_and_report": "Block & Report", "confirmations.block.confirm": "Block", "confirmations.block.message": "Ali ste prepričani, da želite blokirati {name}?", "confirmations.delete.confirm": "Delete", @@ -133,7 +132,6 @@ "empty_column.mutes": "You haven't muted any users yet.", "empty_column.notifications": "Nimate še nobenih obvestil. Poveži se z drugimi, da začnete pogovor.", "empty_column.public": "Tukaj ni ničesar! Da ga napolnite, napišite nekaj javnega ali pa ročno sledite uporabnikom iz drugih vozlišč", - "error_boundary.it_crashed": "It crashed!", "follow_request.authorize": "Odobri", "follow_request.reject": "Zavrni", "getting_started.developers": "Developers", @@ -248,6 +246,7 @@ "notification.favourite": "{name} favourited your status", "notification.follow": "{name} followed you", "notification.mention": "{name} mentioned you", + "notification.poll": "A poll you have voted in has ended", "notification.reblog": "{name} boosted your status", "notifications.clear": "Clear notifications", "notifications.clear_confirmation": "Are you sure you want to permanently clear all your notifications?", @@ -258,6 +257,7 @@ "notifications.column_settings.filter_bar.show": "Show", "notifications.column_settings.follow": "New followers:", "notifications.column_settings.mention": "Mentions:", + "notifications.column_settings.poll": "Poll results:", "notifications.column_settings.push": "Push notifications", "notifications.column_settings.reblog": "Boosts:", "notifications.column_settings.show": "Show in column", @@ -267,6 +267,7 @@ "notifications.filter.favourites": "Favourites", "notifications.filter.follows": "Follows", "notifications.filter.mentions": "Mentions", + "notifications.filter.polls": "Poll results", "notifications.group": "{count} notifications", "poll.closed": "Closed", "poll.refresh": "Refresh", @@ -308,7 +309,6 @@ "search_results.hashtags": "Hashtags", "search_results.statuses": "Tuti", "search_results.total": "{count, number} {count, plural, one {result} other {results}}", - "standalone.public_title": "A look inside...", "status.admin_account": "Open moderation interface for @{name}", "status.admin_status": "Open this status in the moderation interface", "status.block": "Block @{name}", diff --git a/app/javascript/mastodon/locales/sq.json b/app/javascript/mastodon/locales/sq.json index 498b1bdd6..b86c6e2ee 100644 --- a/app/javascript/mastodon/locales/sq.json +++ b/app/javascript/mastodon/locales/sq.json @@ -5,7 +5,6 @@ "account.block_domain": "Fshih gjithçka prej {domain}", "account.blocked": "E bllokuar", "account.direct": "Mesazh i drejtpërdrejt për @{name}", - "account.disclaimer_full": "Të dhënat më poshtë mund ta pasqyrojnë pjesërisht profilin e përdoruesit.", "account.domain_blocked": "Përkatësi e fshehur", "account.edit_profile": "Përpunoni profilin", "account.endorse": "Pasqyrojeni në profil", @@ -36,7 +35,6 @@ "account.unfollow": "Resht së ndjekuri", "account.unmute": "Ktheji zërin @{name}", "account.unmute_notifications": "Hiqua ndalimin e shfaqjes njoftimeve nga @{name}", - "account.view_full_profile": "Shihni profilin e plotë", "alert.unexpected.message": "Ndodhi një gabim të papritur.", "alert.unexpected.title": "Hëm!", "boost_modal.combo": "Mund të shtypni {combo}, që të anashkalohet kjo herës tjetër", @@ -85,6 +83,7 @@ "compose_form.spoiler.unmarked": "Teksti s’është i fshehur", "compose_form.spoiler_placeholder": "Shkruani këtu sinjalizimin tuaj", "confirmation_modal.cancel": "Anuloje", + "confirmations.block.block_and_report": "Block & Report", "confirmations.block.confirm": "Bllokoje", "confirmations.block.message": "Jeni i sigurt se doni të bllokohet {name}?", "confirmations.delete.confirm": "Fshije", @@ -133,7 +132,6 @@ "empty_column.mutes": "S’keni heshtuar ende ndonjë përdorues.", "empty_column.notifications": "Ende s’keni ndonjë njoftim. Ndërveproni me të tjerët që të nisë biseda.", "empty_column.public": "S’ka gjë këtu! Shkruani diçka publikisht, ose ndiqni dorazi përdorues prej instancash të tjera, që ta mbushni këtë zonë", - "error_boundary.it_crashed": "It crashed!", "follow_request.authorize": "Autorizoje", "follow_request.reject": "Hidhe tej", "getting_started.developers": "Zhvillues", @@ -248,6 +246,7 @@ "notification.favourite": "{name} parapëlqeu gjendjen tuaj", "notification.follow": "{name} zuri t’ju ndjekë", "notification.mention": "{name} ju ka përmendur", + "notification.poll": "A poll you have voted in has ended", "notification.reblog": "përforcoi gjendjen tuaj", "notifications.clear": "Pastroji njoftimet", "notifications.clear_confirmation": "Jeni i sigurt se doni të pastrohen përgjithmonë krejt njoftimet tuaja?", @@ -258,6 +257,7 @@ "notifications.column_settings.filter_bar.show": "Shfaq", "notifications.column_settings.follow": "Ndjekës të rinj:", "notifications.column_settings.mention": "Përmendje:", + "notifications.column_settings.poll": "Poll results:", "notifications.column_settings.push": "Njoftime Push", "notifications.column_settings.reblog": "Përforcime:", "notifications.column_settings.show": "Shfaq në shtylla", @@ -267,6 +267,7 @@ "notifications.filter.favourites": "Të parapëlqyer", "notifications.filter.follows": "Ndjekje", "notifications.filter.mentions": "Përmendje", + "notifications.filter.polls": "Poll results", "notifications.group": "%(count)s njoftime", "poll.closed": "Closed", "poll.refresh": "Refresh", @@ -308,7 +309,6 @@ "search_results.hashtags": "Hashtagë", "search_results.statuses": "Mesazhe", "search_results.total": "{count, number} {count, plural, një {result} {results} të tjera}", - "standalone.public_title": "Një pamje brenda…", "status.admin_account": "Hap ndërfaqe moderimi për @{name}", "status.admin_status": "Hape këtë gjendje te ndërfaqja e moderimit", "status.block": "Blloko @{name}", diff --git a/app/javascript/mastodon/locales/sr-Latn.json b/app/javascript/mastodon/locales/sr-Latn.json index abc1df5de..155935306 100644 --- a/app/javascript/mastodon/locales/sr-Latn.json +++ b/app/javascript/mastodon/locales/sr-Latn.json @@ -5,7 +5,6 @@ "account.block_domain": "Sakrij sve sa domena {domain}", "account.blocked": "Blocked", "account.direct": "Direct Message @{name}", - "account.disclaimer_full": "Navedene informacije možda ne odslikavaju korisnički profil u potpunosti.", "account.domain_blocked": "Domain hidden", "account.edit_profile": "Izmeni profil", "account.endorse": "Feature on profile", @@ -36,7 +35,6 @@ "account.unfollow": "Otprati", "account.unmute": "Ukloni ućutkavanje korisniku @{name}", "account.unmute_notifications": "Uključi nazad obaveštenja od korisnika @{name}", - "account.view_full_profile": "Vidi ceo profil", "alert.unexpected.message": "An unexpected error occurred.", "alert.unexpected.title": "Oops!", "boost_modal.combo": "Možete pritisnuti {combo} da preskočite ovo sledeći put", @@ -85,6 +83,7 @@ "compose_form.spoiler.unmarked": "Text is not hidden", "compose_form.spoiler_placeholder": "Ovde upišite upozorenje", "confirmation_modal.cancel": "Poništi", + "confirmations.block.block_and_report": "Block & Report", "confirmations.block.confirm": "Blokiraj", "confirmations.block.message": "Da li ste sigurni da želite da blokirate korisnika {name}?", "confirmations.delete.confirm": "Obriši", @@ -133,7 +132,6 @@ "empty_column.mutes": "You haven't muted any users yet.", "empty_column.notifications": "Trenutno nemate obaveštenja. Družite se malo da započnete razgovore.", "empty_column.public": "Ovde nema ničega! Napišite nešto javno, ili nađite korisnike sa drugih instanci koje ćete zapratiti da popunite ovu prazninu", - "error_boundary.it_crashed": "It crashed!", "follow_request.authorize": "Odobri", "follow_request.reject": "Odbij", "getting_started.developers": "Developers", @@ -248,6 +246,7 @@ "notification.favourite": "{name} je stavio Vaš status kao omiljeni", "notification.follow": "{name} Vas je zapratio", "notification.mention": "{name} Vas je pomenuo", + "notification.poll": "A poll you have voted in has ended", "notification.reblog": "{name} je podržao(la) Vaš status", "notifications.clear": "Očisti obaveštenja", "notifications.clear_confirmation": "Da li ste sigurno da trajno želite da očistite Vaša obaveštenja?", @@ -258,6 +257,7 @@ "notifications.column_settings.filter_bar.show": "Show", "notifications.column_settings.follow": "Novi pratioci:", "notifications.column_settings.mention": "Pominjanja:", + "notifications.column_settings.poll": "Poll results:", "notifications.column_settings.push": "Guraj obaveštenja", "notifications.column_settings.reblog": "Podrški:", "notifications.column_settings.show": "Prikaži u koloni", @@ -267,6 +267,7 @@ "notifications.filter.favourites": "Favourites", "notifications.filter.follows": "Follows", "notifications.filter.mentions": "Mentions", + "notifications.filter.polls": "Poll results", "notifications.group": "{count} notifications", "poll.closed": "Closed", "poll.refresh": "Refresh", @@ -308,7 +309,6 @@ "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.admin_account": "Open moderation interface for @{name}", "status.admin_status": "Open this status in the moderation interface", "status.block": "Block @{name}", diff --git a/app/javascript/mastodon/locales/sr.json b/app/javascript/mastodon/locales/sr.json index ac7f97c6d..1124ed8d5 100644 --- a/app/javascript/mastodon/locales/sr.json +++ b/app/javascript/mastodon/locales/sr.json @@ -5,7 +5,6 @@ "account.block_domain": "Сакриј све са домена {domain}", "account.blocked": "Блокиран", "account.direct": "Директна порука @{name}", - "account.disclaimer_full": "Наведене информације можда не одсликавају кориснички профил у потпуности.", "account.domain_blocked": "Домен сакривен", "account.edit_profile": "Измени профил", "account.endorse": "Приказати на профилу", @@ -36,7 +35,6 @@ "account.unfollow": "Отпрати", "account.unmute": "Уклони ућуткавање кориснику @{name}", "account.unmute_notifications": "Укључи назад обавештења од корисника @{name}", - "account.view_full_profile": "Види цео профил", "alert.unexpected.message": "Појавила се неочекивана грешка.", "alert.unexpected.title": "Упс!", "boost_modal.combo": "Можете притиснути {combo} да прескочите ово следећи пут", @@ -85,6 +83,7 @@ "compose_form.spoiler.unmarked": "Текст није сакривен", "compose_form.spoiler_placeholder": "Овде упишите упозорење", "confirmation_modal.cancel": "Поништи", + "confirmations.block.block_and_report": "Block & Report", "confirmations.block.confirm": "Блокирај", "confirmations.block.message": "Да ли сте сигурни да желите да блокирате корисника {name}?", "confirmations.delete.confirm": "Обриши", @@ -133,7 +132,6 @@ "empty_column.mutes": "Још увек немате ућутканих корисника.", "empty_column.notifications": "Тренутно немате обавештења. Дружите се мало да започнете разговор.", "empty_column.public": "Овде нема ничега! Напишите нешто јавно, или нађите кориснике са других инстанци које ћете запратити да попуните ову празнину", - "error_boundary.it_crashed": "It crashed!", "follow_request.authorize": "Одобри", "follow_request.reject": "Одбиј", "getting_started.developers": "Програмери", @@ -248,6 +246,7 @@ "notification.favourite": "{name} је ставио/ла Ваш статус као омиљени", "notification.follow": "{name} Вас је запратио/ла", "notification.mention": "{name} Вас је поменуо/ла", + "notification.poll": "A poll you have voted in has ended", "notification.reblog": "{name} је подржао/ла Ваш статус", "notifications.clear": "Очисти обавештења", "notifications.clear_confirmation": "Да ли сте сигурно да трајно желите да очистите Ваша обавештења?", @@ -258,6 +257,7 @@ "notifications.column_settings.filter_bar.show": "Show", "notifications.column_settings.follow": "Нови пратиоци:", "notifications.column_settings.mention": "Помињања:", + "notifications.column_settings.poll": "Poll results:", "notifications.column_settings.push": "Гурај обавештења", "notifications.column_settings.reblog": "Подршки:", "notifications.column_settings.show": "Прикажи у колони", @@ -267,6 +267,7 @@ "notifications.filter.favourites": "Favourites", "notifications.filter.follows": "Follows", "notifications.filter.mentions": "Mentions", + "notifications.filter.polls": "Poll results", "notifications.group": "{count} обавештења", "poll.closed": "Closed", "poll.refresh": "Refresh", @@ -308,7 +309,6 @@ "search_results.hashtags": "Тарабе", "search_results.statuses": "Трубе", "search_results.total": "{count, number} {count, plural, one {резултат} few {резултата} other {резултата}}", - "standalone.public_title": "Поглед изнутра...", "status.admin_account": "Open moderation interface for @{name}", "status.admin_status": "Open this status in the moderation interface", "status.block": "Блокирај @{name}", diff --git a/app/javascript/mastodon/locales/sv.json b/app/javascript/mastodon/locales/sv.json index cd002ee02..9093637b3 100644 --- a/app/javascript/mastodon/locales/sv.json +++ b/app/javascript/mastodon/locales/sv.json @@ -5,7 +5,6 @@ "account.block_domain": "Dölj allt från {domain}", "account.blocked": "Blockerad", "account.direct": "Direktmeddelande @{name}", - "account.disclaimer_full": "Informationen nedan kan spegla användarens profil ofullständigt.", "account.domain_blocked": "Domän dold", "account.edit_profile": "Redigera profil", "account.endorse": "Feature on profile", @@ -36,7 +35,6 @@ "account.unfollow": "Sluta följa", "account.unmute": "Ta bort tystad @{name}", "account.unmute_notifications": "Återaktivera notifikationer från @{name}", - "account.view_full_profile": "Visa hela profilen", "alert.unexpected.message": "Ett oväntat fel uppstod.", "alert.unexpected.title": "Oops!", "boost_modal.combo": "Du kan trycka {combo} för att slippa denna nästa gång", @@ -85,6 +83,7 @@ "compose_form.spoiler.unmarked": "Texten är inte dold", "compose_form.spoiler_placeholder": "Skriv din varning här", "confirmation_modal.cancel": "Ångra", + "confirmations.block.block_and_report": "Block & Report", "confirmations.block.confirm": "Blockera", "confirmations.block.message": "Är du säker att du vill blockera {name}?", "confirmations.delete.confirm": "Ta bort", @@ -133,7 +132,6 @@ "empty_column.mutes": "You haven't muted any users yet.", "empty_column.notifications": "Du har inga meddelanden än. Interagera med andra för att starta konversationen.", "empty_column.public": "Det finns inget här! Skriv något offentligt, eller följ manuellt användarna från andra instanser för att fylla på det", - "error_boundary.it_crashed": "It crashed!", "follow_request.authorize": "Godkänn", "follow_request.reject": "Avvisa", "getting_started.developers": "Utvecklare", @@ -248,6 +246,7 @@ "notification.favourite": "{name} favoriserade din status", "notification.follow": "{name} följer dig", "notification.mention": "{name} nämnde dig", + "notification.poll": "A poll you have voted in has ended", "notification.reblog": "{name} knuffade din status", "notifications.clear": "Rensa meddelanden", "notifications.clear_confirmation": "Är du säker på att du vill radera alla dina meddelanden permanent?", @@ -258,6 +257,7 @@ "notifications.column_settings.filter_bar.show": "Show", "notifications.column_settings.follow": "Nya följare:", "notifications.column_settings.mention": "Omnämningar:", + "notifications.column_settings.poll": "Poll results:", "notifications.column_settings.push": "Push meddelanden", "notifications.column_settings.reblog": "Knuffar:", "notifications.column_settings.show": "Visa i kolumnen", @@ -267,6 +267,7 @@ "notifications.filter.favourites": "Favourites", "notifications.filter.follows": "Follows", "notifications.filter.mentions": "Mentions", + "notifications.filter.polls": "Poll results", "notifications.group": "{count} aviseringar", "poll.closed": "Closed", "poll.refresh": "Refresh", @@ -308,7 +309,6 @@ "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.admin_account": "Open moderation interface for @{name}", "status.admin_status": "Open this status in the moderation interface", "status.block": "Block @{name}", diff --git a/app/javascript/mastodon/locales/ta.json b/app/javascript/mastodon/locales/ta.json index 9f8f797c8..eedd4c6f3 100644 --- a/app/javascript/mastodon/locales/ta.json +++ b/app/javascript/mastodon/locales/ta.json @@ -5,7 +5,6 @@ "account.block_domain": "Hide everything from {domain}", "account.blocked": "Blocked", "account.direct": "Direct message @{name}", - "account.disclaimer_full": "Information below may reflect the user's profile incompletely.", "account.domain_blocked": "Domain hidden", "account.edit_profile": "Edit profile", "account.endorse": "Feature on profile", @@ -36,7 +35,6 @@ "account.unfollow": "Unfollow", "account.unmute": "Unmute @{name}", "account.unmute_notifications": "Unmute notifications from @{name}", - "account.view_full_profile": "View full profile", "alert.unexpected.message": "An unexpected error occurred.", "alert.unexpected.title": "Oops!", "boost_modal.combo": "You can press {combo} to skip this next time", @@ -85,6 +83,7 @@ "compose_form.spoiler.unmarked": "Text is not hidden", "compose_form.spoiler_placeholder": "Write your warning here", "confirmation_modal.cancel": "Cancel", + "confirmations.block.block_and_report": "Block & Report", "confirmations.block.confirm": "Block", "confirmations.block.message": "Are you sure you want to block {name}?", "confirmations.delete.confirm": "Delete", @@ -133,7 +132,6 @@ "empty_column.mutes": "You haven't muted any users 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", - "error_boundary.it_crashed": "It crashed!", "follow_request.authorize": "Authorize", "follow_request.reject": "Reject", "getting_started.developers": "Developers", @@ -248,6 +246,7 @@ "notification.favourite": "{name} favourited your status", "notification.follow": "{name} followed you", "notification.mention": "{name} mentioned you", + "notification.poll": "A poll you have voted in has ended", "notification.reblog": "{name} boosted your status", "notifications.clear": "Clear notifications", "notifications.clear_confirmation": "Are you sure you want to permanently clear all your notifications?", @@ -258,6 +257,7 @@ "notifications.column_settings.filter_bar.show": "Show", "notifications.column_settings.follow": "New followers:", "notifications.column_settings.mention": "Mentions:", + "notifications.column_settings.poll": "Poll results:", "notifications.column_settings.push": "Push notifications", "notifications.column_settings.reblog": "Boosts:", "notifications.column_settings.show": "Show in column", @@ -267,6 +267,7 @@ "notifications.filter.favourites": "Favourites", "notifications.filter.follows": "Follows", "notifications.filter.mentions": "Mentions", + "notifications.filter.polls": "Poll results", "notifications.group": "{count} notifications", "poll.closed": "Closed", "poll.refresh": "Refresh", @@ -308,7 +309,6 @@ "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.admin_account": "Open moderation interface for @{name}", "status.admin_status": "Open this status in the moderation interface", "status.block": "Block @{name}", diff --git a/app/javascript/mastodon/locales/te.json b/app/javascript/mastodon/locales/te.json index 02896333e..c93ff63df 100644 --- a/app/javascript/mastodon/locales/te.json +++ b/app/javascript/mastodon/locales/te.json @@ -5,7 +5,6 @@ "account.block_domain": "{domain} నుంచి అన్నీ దాచిపెట్టు", "account.blocked": "బ్లాక్ అయినవి", "account.direct": "@{name}కు నేరుగా సందేశం పంపు", - "account.disclaimer_full": "క్రింది సమాచారం వాడుకరి యొక్క ప్రొఫైల్ను అసంపూర్తిగా ప్రతిబింబించవచ్చు.", "account.domain_blocked": "డొమైన్ దాచిపెట్టబడినది", "account.edit_profile": "ప్రొఫైల్ని సవరించండి", "account.endorse": "ప్రొఫైల్లో చూపించు", @@ -36,7 +35,6 @@ "account.unfollow": "అనుసరించవద్దు", "account.unmute": "@{name}పై మ్యూట్ ని తొలగించు", "account.unmute_notifications": "@{name} నుంచి ప్రకటనలపై మ్యూట్ ని తొలగించు", - "account.view_full_profile": "పూర్తి ప్రొఫైల్ను చూడండి", "alert.unexpected.message": "అనుకోని తప్పు జరిగినది.", "alert.unexpected.title": "అయ్యో!", "boost_modal.combo": "మీరు తదుపరిసారి దీనిని దాటవేయడానికి {combo} నొక్కవచ్చు", @@ -73,10 +71,10 @@ "compose_form.lock_disclaimer": "మీ ఖాతా {locked} చేయబడలేదు. ఎవరైనా మిమ్మల్ని అనుసరించి మీ అనుచరులకు-మాత్రమే పోస్ట్లను వీక్షించవచ్చు.", "compose_form.lock_disclaimer.lock": "బిగించబడినది", "compose_form.placeholder": "మీ మనస్సులో ఏముంది?", - "compose_form.poll.add_option": "Add a choice", - "compose_form.poll.duration": "Poll duration", - "compose_form.poll.option_placeholder": "Choice {number}", - "compose_form.poll.remove_option": "Remove this choice", + "compose_form.poll.add_option": "ఒక ఎంపికను చేర్చండి", + "compose_form.poll.duration": "ఎన్నిక వ్యవధి", + "compose_form.poll.option_placeholder": "ఎంపిక {number}", + "compose_form.poll.remove_option": "ఈ ఎంపికను తొలగించు", "compose_form.publish": "టూట్", "compose_form.publish_loud": "{publish}!", "compose_form.sensitive.marked": "మీడియా సున్నితమైనదిగా గుర్తించబడింది", @@ -85,6 +83,7 @@ "compose_form.spoiler.unmarked": "పాఠ్యం దాచబడలేదు", "compose_form.spoiler_placeholder": "ఇక్కడ మీ హెచ్చరికను రాయండి", "confirmation_modal.cancel": "రద్దు చెయ్యి", + "confirmations.block.block_and_report": "Block & Report", "confirmations.block.confirm": "బ్లాక్ చేయి", "confirmations.block.message": "మీరు ఖచ్చితంగా {name}ని బ్లాక్ చేయాలనుకుంటున్నారా?", "confirmations.delete.confirm": "తొలగించు", @@ -132,8 +131,7 @@ "empty_column.lists": "మీకు ఇంకా జాబితాలు ఏమీ లేవు. మీరు ఒకటి సృష్టించగానే, అది ఇక్కడ కనబడుతుంది.", "empty_column.mutes": "మీరు ఇంకా ఏ వినియోగదారులనూ మ్యూట్ చేయలేదు.", "empty_column.notifications": "మీకు ఇంకా ఏ నోటిఫికేషన్లు లేవు. సంభాషణను ప్రారంభించడానికి ఇతరులతో ప్రతిస్పందించండి.", - "empty_column.public": "ఇక్కడ ఏమీ లేదు! దీన్ని నింపడానికి బహిరంగంగా ఏదైనా వ్రాయండి, లేదా ఇతర దృష్టాంతాల్లోని వినియోగదారులను అనుసరించండి", - "error_boundary.it_crashed": "It crashed!", + "empty_column.public": "ఇక్కడ ఏమీ లేదు! దీన్ని నింపడానికి బహిరంగంగా ఏదైనా వ్రాయండి, లేదా ఇతర సేవికల నుండి వినియోగదారులను అనుసరించండి", "follow_request.authorize": "అనుమతించు", "follow_request.reject": "తిరస్కరించు", "getting_started.developers": "డెవలపర్లు", @@ -152,7 +150,7 @@ "hashtag.column_settings.tag_mode.all": "ఇవన్నీ", "hashtag.column_settings.tag_mode.any": "వీటిలో ఏవైనా", "hashtag.column_settings.tag_mode.none": "ఇవేవీ కావు", - "hashtag.column_settings.tag_toggle": "Include additional tags in this column", + "hashtag.column_settings.tag_toggle": "ఈ నిలువు వరుసలో మరికొన్ని ట్యాగులను చేర్చండి", "home.column_settings.basic": "ప్రాథమిక", "home.column_settings.show_reblogs": "బూస్ట్ లను చూపించు", "home.column_settings.show_replies": "ప్రత్యుత్తరాలను చూపించు", @@ -214,7 +212,7 @@ "lists.account.remove": "జాబితా నుండి తొలగించు", "lists.delete": "జాబితాను తొలగించు", "lists.edit": "జాబితాను సవరించు", - "lists.edit.submit": "Change title", + "lists.edit.submit": "శీర్షిక మార్చు", "lists.new.create": "జాబితాను జోడించు", "lists.new.title_placeholder": "కొత్త జాబితా శీర్షిక", "lists.search": "మీరు అనుసరించే వ్యక్తులలో శోధించండి", @@ -248,6 +246,7 @@ "notification.favourite": "{name} మీ స్టేటస్ ను ఇష్టపడ్డారు", "notification.follow": "{name} మిమ్మల్ని అనుసరిస్తున్నారు", "notification.mention": "{name} మిమ్మల్ని ప్రస్తావించారు", + "notification.poll": "మీరు పాల్గొనిన ఎన్సిక ముగిసినది", "notification.reblog": "{name} మీ స్టేటస్ ను బూస్ట్ చేసారు", "notifications.clear": "ప్రకటనలను తుడిచివేయు", "notifications.clear_confirmation": "మీరు మీ అన్ని నోటిఫికేషన్లను శాశ్వతంగా తొలగించాలనుకుంటున్నారా?", @@ -258,6 +257,7 @@ "notifications.column_settings.filter_bar.show": "చూపించు", "notifications.column_settings.follow": "క్రొత్త అనుచరులు:", "notifications.column_settings.mention": "ప్రస్తావనలు:", + "notifications.column_settings.poll": "ఎన్నిక ఫలితాలు:", "notifications.column_settings.push": "పుష్ ప్రకటనలు", "notifications.column_settings.reblog": "బూస్ట్ లు:", "notifications.column_settings.show": "నిలువు వరుసలో చూపు", @@ -267,13 +267,14 @@ "notifications.filter.favourites": "ఇష్టాలు", "notifications.filter.follows": "అనుసరిస్తున్నవి", "notifications.filter.mentions": "పేర్కొన్నవి", + "notifications.filter.polls": "ఎన్నిక ఫలితాలు", "notifications.group": "{count} ప్రకటనలు", - "poll.closed": "Closed", - "poll.refresh": "Refresh", + "poll.closed": "మూసివేయబడినవి", + "poll.refresh": "నవీకరించు", "poll.total_votes": "{count, plural, one {# vote} other {# votes}}", - "poll.vote": "Vote", - "poll_button.add_poll": "Add a poll", - "poll_button.remove_poll": "Remove poll", + "poll.vote": "ఎన్నుకోండి", + "poll_button.add_poll": "ఒక ఎన్నికను చేర్చు", + "poll_button.remove_poll": "ఎన్నికను తొలగించు", "privacy.change": "స్టేటస్ గోప్యతను సర్దుబాటు చేయండి", "privacy.direct.long": "పేర్కొన్న వినియోగదారులకు మాత్రమే పోస్ట్ చేయి", "privacy.direct.short": "ప్రత్యక్ష", @@ -293,7 +294,7 @@ "reply_indicator.cancel": "రద్దు చెయ్యి", "report.forward": "{target}కి ఫార్వార్డ్ చేయండి", "report.forward_hint": "ఖాతా మరొక సర్వర్లో ఉంది. నివేదిక యొక్క ఒక అనామకంగా ఉన్న కాపీని అక్కడికి కూడా పంపించమంటారా?", - "report.hint": "మీ దుష్టాంత మోడరేటర్లకు నివేదిక పంపబడుతుంది. దిగువ ఈ ఖాతాను ఎందుకు నివేదిస్తున్నారనేదాని వివరణను మీరు అందించవచ్చు:", + "report.hint": "మీ సేవిక మోడరేటర్లకు నివేదిక పంపబడుతుంది. ఈ ఖాతాను ఎందుకు నివేదిస్తున్నారనేదాని వివరణను మీరు దిగువన అందించవచ్చు:", "report.placeholder": "అదనపు వ్యాఖ్యలు", "report.submit": "సమర్పించండి", "report.target": "{target}పై ఫిర్యాదు చేయండి", @@ -308,13 +309,12 @@ "search_results.hashtags": "హాష్ ట్యాగ్లు", "search_results.statuses": "టూట్లు", "search_results.total": "{count, number} {count, plural, one {result} other {results}}", - "standalone.public_title": "లోపలికి ఒక చూపు...", "status.admin_account": "@{name} కొరకు సమన్వయ వినిమయసీమను తెరువు", "status.admin_status": "సమన్వయ వినిమయసీమలో ఈ స్టేటస్ ను తెరవండి", "status.block": "@{name} ను బ్లాక్ చేయి", "status.cancel_reblog_private": "బూస్ట్ను తొలగించు", "status.cannot_reblog": "ఈ పోస్ట్ను బూస్ట్ చేయడం సాధ్యం కాదు", - "status.copy": "Copy link to status", + "status.copy": "లంకెను స్టేటస్కు కాపీ చేయి", "status.delete": "తొలగించు", "status.detailed_status": "వివరణాత్మక సంభాషణ వీక్షణ", "status.direct": "@{name}కు నేరుగా సందేశం పంపు", @@ -359,7 +359,7 @@ "time_remaining.days": "{number, plural, one {# day} other {# days}} left", "time_remaining.hours": "{number, plural, one {# hour} other {# hours}} left", "time_remaining.minutes": "{number, plural, one {# minute} other {# minutes}} left", - "time_remaining.moments": "Moments remaining", + "time_remaining.moments": "కొన్ని క్షణాలు మాత్రమే మిగిలి ఉన్నాయి", "time_remaining.seconds": "{number, plural, one {# second} other {# seconds}} left", "trends.count_by_accounts": "{count} {rawCount, plural, one {person} other {people}} మాట్లాడుతున్నారు", "ui.beforeunload": "మీరు మాస్టొడొన్ను వదిలివేస్తే మీ డ్రాఫ్ట్లు పోతాయి.", diff --git a/app/javascript/mastodon/locales/th.json b/app/javascript/mastodon/locales/th.json index 6d120ac76..e15382402 100644 --- a/app/javascript/mastodon/locales/th.json +++ b/app/javascript/mastodon/locales/th.json @@ -1,74 +1,72 @@ { - "account.add_or_remove_from_list": "Add or Remove from lists", + "account.add_or_remove_from_list": "เพิ่มหรือเอาออกจากรายการ", "account.badges.bot": "บอต", - "account.block": "บล็อค @{name}", + "account.block": "ปิดกั้น @{name}", "account.block_domain": "ซ่อนทุกอย่างจาก {domain}", - "account.blocked": "ถูกบล็อค", - "account.direct": "Direct Message @{name}", - "account.disclaimer_full": "Information below may reflect the user's profile incompletely.", - "account.domain_blocked": "Domain hidden", - "account.edit_profile": "Edit profile", + "account.blocked": "ปิดกั้นอยู่", + "account.direct": "ส่งข้อความโดยตรงถึง @{name}", + "account.domain_blocked": "ซ่อนโดเมนอยู่", + "account.edit_profile": "แก้ไขโปรไฟล์", "account.endorse": "Feature on profile", "account.follow": "ติดตาม", "account.followers": "ผู้ติดตาม", - "account.followers.empty": "ยังไม่มีใครติดตาม", + "account.followers.empty": "ยังไม่มีใครติดตามผู้ใช้นี้", "account.follows": "ติดตาม", - "account.follows.empty": "ยังไม่ได้ติดตามใคร", + "account.follows.empty": "ผู้ใช้นี้ยังไม่ได้ติดตามใคร", "account.follows_you": "ติดตามคุณ", - "account.hide_reblogs": "Hide boosts from @{name}", + "account.hide_reblogs": "ซ่อนการดันจาก @{name}", "account.link_verified_on": "Ownership of this link was checked on {date}", "account.locked_info": "This account privacy status is set to locked. The owner manually reviews who can follow them.", - "account.media": "Media", - "account.mention": "Mention @{name}", - "account.moved_to": "{name} has moved to:", - "account.mute": "Mute @{name}", - "account.mute_notifications": "Mute notifications from @{name}", - "account.muted": "Muted", - "account.posts": "Posts", - "account.posts_with_replies": "Toots with replies", - "account.report": "Report @{name}", - "account.requested": "Awaiting approval", - "account.share": "Share @{name}'s profile", - "account.show_reblogs": "Show boosts from @{name}", - "account.unblock": "Unblock @{name}", - "account.unblock_domain": "Unhide {domain}", + "account.media": "สื่อ", + "account.mention": "กล่าวถึง @{name}", + "account.moved_to": "{name} ได้ย้ายไปยัง:", + "account.mute": "ปิดเสียง @{name}", + "account.mute_notifications": "ปิดเสียงการแจ้งเตือนจาก @{name}", + "account.muted": "ปิดเสียงอยู่", + "account.posts": "โพสต์", + "account.posts_with_replies": "โพสต์และการตอบกลับ", + "account.report": "รายงาน @{name}", + "account.requested": "กำลังรอการอนุมัติ คลิกเพื่อยกเลิกคำขอติดตาม", + "account.share": "แบ่งปันโปรไฟล์ของ @{name}", + "account.show_reblogs": "แสดงการดันจาก @{name}", + "account.unblock": "เลิกปิดกั้น @{name}", + "account.unblock_domain": "เลิกซ่อน {domain}", "account.unendorse": "Don't feature on profile", - "account.unfollow": "Unfollow", - "account.unmute": "Unmute @{name}", - "account.unmute_notifications": "Unmute notifications from @{name}", - "account.view_full_profile": "View full profile", - "alert.unexpected.message": "An unexpected error occurred.", - "alert.unexpected.title": "Oops!", + "account.unfollow": "เลิกติดตาม", + "account.unmute": "เลิกปิดเสียง @{name}", + "account.unmute_notifications": "เลิกปิดเสียงการแจ้งเตือนจาก @{name}", + "alert.unexpected.message": "เกิดข้อผิดพลาดที่ไม่คาดคิด", + "alert.unexpected.title": "อุปส์!", "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", - "bundle_column_error.title": "Network error", - "bundle_modal_error.close": "Close", + "bundle_column_error.retry": "ลองอีกครั้ง", + "bundle_column_error.title": "ข้อผิดพลาดเครือข่าย", + "bundle_modal_error.close": "ปิด", "bundle_modal_error.message": "Something went wrong while loading this component.", - "bundle_modal_error.retry": "Try again", - "column.blocks": "Blocked users", - "column.community": "Local timeline", - "column.direct": "Direct messages", - "column.domain_blocks": "Hidden domains", - "column.favourites": "Favourites", - "column.follow_requests": "Follow requests", - "column.home": "Home", - "column.lists": "Lists", - "column.mutes": "Muted users", - "column.notifications": "Notifications", - "column.pins": "Pinned toot", - "column.public": "Federated timeline", - "column_back_button.label": "Back", - "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.settings": "Settings", - "community.column_settings.media_only": "Media Only", + "bundle_modal_error.retry": "ลองอีกครั้ง", + "column.blocks": "ผู้ใช้ที่ปิดกั้นอยู่", + "column.community": "เส้นเวลาในเว็บ", + "column.direct": "ข้อความโดยตรง", + "column.domain_blocks": "โดเมนที่ซ่อนอยู่", + "column.favourites": "รายการโปรด", + "column.follow_requests": "คำขอติดตาม", + "column.home": "หน้าแรก", + "column.lists": "รายการ", + "column.mutes": "ผู้ใช้ที่ปิดเสียงอยู่", + "column.notifications": "การแจ้งเตือน", + "column.pins": "โพสต์ที่ปักหมุด", + "column.public": "เส้นเวลาที่ติดต่อกับภายนอก", + "column_back_button.label": "ย้อนกลับ", + "column_header.hide_settings": "ซ่อนการตั้งค่า", + "column_header.moveLeft_settings": "ย้ายคอลัมน์ไปทางซ้าย", + "column_header.moveRight_settings": "ย้ายคอลัมน์ไปทางขวา", + "column_header.pin": "ปักหมุด", + "column_header.show_settings": "แสดงการตั้งค่า", + "column_header.unpin": "ถอนหมุด", + "column_subheading.settings": "การตั้งค่า", + "community.column_settings.media_only": "สื่อเท่านั้น", "compose_form.direct_message_warning": "This toot will only be visible to all the mentioned users.", - "compose_form.direct_message_warning_learn_more": "Learn more", + "compose_form.direct_message_warning_learn_more": "เรียนรู้เพิ่มเติม", "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", @@ -77,89 +75,89 @@ "compose_form.poll.duration": "Poll duration", "compose_form.poll.option_placeholder": "Choice {number}", "compose_form.poll.remove_option": "Remove this choice", - "compose_form.publish": "Toot", + "compose_form.publish": "โพสต์", "compose_form.publish_loud": "{publish}!", "compose_form.sensitive.marked": "Media is marked as sensitive", "compose_form.sensitive.unmarked": "Media is not marked as sensitive", "compose_form.spoiler.marked": "Text is hidden behind warning", "compose_form.spoiler.unmarked": "Text is not hidden", - "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}?", - "confirmations.delete.confirm": "Delete", - "confirmations.delete.message": "Are you sure you want to delete this status?", - "confirmations.delete_list.confirm": "Delete", - "confirmations.delete_list.message": "Are you sure you want to permanently delete this list?", + "compose_form.spoiler_placeholder": "เขียนคำเตือนของคุณที่นี่", + "confirmation_modal.cancel": "ยกเลิก", + "confirmations.block.block_and_report": "Block & Report", + "confirmations.block.confirm": "ปิดกั้น", + "confirmations.block.message": "คุณแน่ใจหรือไม่ว่าต้องการปิดกั้น {name}?", + "confirmations.delete.confirm": "ลบ", + "confirmations.delete.message": "คุณแน่ใจหรือไม่ว่าต้องการลบสถานะนี้?", + "confirmations.delete_list.confirm": "ลบ", + "confirmations.delete_list.message": "คุณแน่ใจหรือไม่ว่าต้องการลบรายการนี้อย่างถาวร?", "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.redraft.confirm": "Delete & redraft", + "confirmations.mute.confirm": "ปิดเสียง", + "confirmations.mute.message": "คุณแน่ใจหรือไม่ว่าต้องการปิดเสียง {name}?", + "confirmations.redraft.confirm": "ลบแล้วร่างใหม่", "confirmations.redraft.message": "Are you sure you want to delete this status and re-draft it? You will lose all replies, boosts and favourites to it.", - "confirmations.reply.confirm": "Reply", + "confirmations.reply.confirm": "ตอบกลับ", "confirmations.reply.message": "Replying now will overwrite the message you are currently composing. Are you sure you want to proceed?", - "confirmations.unfollow.confirm": "Unfollow", - "confirmations.unfollow.message": "Are you sure you want to unfollow {name}?", + "confirmations.unfollow.confirm": "เลิกติดตาม", + "confirmations.unfollow.message": "คุณแน่ใจหรือไม่ว่าต้องการเลิกติดตาม {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.activity": "กิจกรรม", + "emoji_button.custom": "กำหนดเอง", + "emoji_button.flags": "ธง", + "emoji_button.food": "อาหารและเครื่องดื่ม", + "emoji_button.label": "แทรกอีโมจิ", + "emoji_button.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.account_timeline": "No toots here!", + "emoji_button.objects": "วัตถุ", + "emoji_button.people": "ผู้คน", + "emoji_button.recent": "ที่ใช้บ่อย", + "emoji_button.search": "ค้นหา...", + "emoji_button.search_results": "ผลลัพธ์การค้นหา", + "emoji_button.symbols": "สัญลักษณ์", + "emoji_button.travel": "การเดินทางและสถานที่", + "empty_column.account_timeline": "ไม่มีโพสต์ที่นี่!", "empty_column.blocks": "You haven't blocked any users yet.", "empty_column.community": "The local timeline is empty. Write something publicly to get the ball rolling!", "empty_column.direct": "You don't have any direct messages yet. When you send or receive one, it will show up here.", - "empty_column.domain_blocks": "There are no hidden domains yet.", + "empty_column.domain_blocks": "ยังไม่มีโดเมนที่ซ่อนอยู่", "empty_column.favourited_statuses": "You don't have any favourite toots yet. When you favourite one, it will show up here.", "empty_column.favourites": "No one has favourited this toot yet. When someone does, they will show up here.", "empty_column.follow_requests": "You don't have any follow requests yet. When you receive one, it will show up here.", "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.home.public_timeline": "เส้นเวลาสาธารณะ", "empty_column.list": "There is nothing in this list yet.", "empty_column.lists": "You don't have any lists yet. When you create one, it will show up here.", "empty_column.mutes": "You haven't muted any users 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", - "error_boundary.it_crashed": "It crashed!", - "follow_request.authorize": "Authorize", - "follow_request.reject": "Reject", - "getting_started.developers": "Developers", - "getting_started.directory": "Profile directory", - "getting_started.documentation": "Documentation", - "getting_started.heading": "Getting started", - "getting_started.invite": "Invite people", + "follow_request.authorize": "อนุญาต", + "follow_request.reject": "ปฏิเสธ", + "getting_started.developers": "นักพัฒนา", + "getting_started.directory": "ไดเรกทอรีโปรไฟล์", + "getting_started.documentation": "เอกสารประกอบ", + "getting_started.heading": "เริ่มต้นใช้งาน", + "getting_started.invite": "เชิญผู้คน", "getting_started.open_source_notice": "Mastodon is open source software. You can contribute or report issues on GitHub at {github}.", - "getting_started.security": "Security", + "getting_started.security": "ความปลอดภัย", "getting_started.terms": "Terms of service", - "hashtag.column_header.tag_mode.all": "and {additional}", - "hashtag.column_header.tag_mode.any": "or {additional}", - "hashtag.column_header.tag_mode.none": "without {additional}", - "hashtag.column_settings.select.no_options_message": "No suggestions found", - "hashtag.column_settings.select.placeholder": "Enter hashtags…", + "hashtag.column_header.tag_mode.all": "และ {additional}", + "hashtag.column_header.tag_mode.any": "หรือ {additional}", + "hashtag.column_header.tag_mode.none": "โดยไม่มี {additional}", + "hashtag.column_settings.select.no_options_message": "ไม่พบข้อเสนอแนะ", + "hashtag.column_settings.select.placeholder": "ป้อนแฮชแท็ก…", "hashtag.column_settings.tag_mode.all": "All of these", "hashtag.column_settings.tag_mode.any": "Any of these", "hashtag.column_settings.tag_mode.none": "None of these", "hashtag.column_settings.tag_toggle": "Include additional tags in this column", - "home.column_settings.basic": "Basic", - "home.column_settings.show_reblogs": "Show boosts", - "home.column_settings.show_replies": "Show replies", + "home.column_settings.basic": "พื้นฐาน", + "home.column_settings.show_reblogs": "แสดงการดัน", + "home.column_settings.show_replies": "แสดงการตอบกลับ", "intervals.full.days": "{number, plural, one {# day} other {# days}}", "intervals.full.hours": "{number, plural, one {# hour} other {# hours}}", "intervals.full.minutes": "{number, plural, one {# minute} other {# minutes}}", - "introduction.federation.action": "Next", + "introduction.federation.action": "ถัดไป", "introduction.federation.federated.headline": "Federated", "introduction.federation.federated.text": "Public posts from other servers of the fediverse will appear in the federated timeline.", "introduction.federation.home.headline": "Home", @@ -181,7 +179,7 @@ "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", - "keyboard_shortcuts.description": "Description", + "keyboard_shortcuts.description": "คำอธิบาย", "keyboard_shortcuts.direct": "to open direct messages column", "keyboard_shortcuts.down": "to move down in the list", "keyboard_shortcuts.enter": "to open status", @@ -190,7 +188,7 @@ "keyboard_shortcuts.federated": "to open federated timeline", "keyboard_shortcuts.heading": "Keyboard Shortcuts", "keyboard_shortcuts.home": "to open home timeline", - "keyboard_shortcuts.hotkey": "Hotkey", + "keyboard_shortcuts.hotkey": "ปุ่มลัด", "keyboard_shortcuts.legend": "to display this legend", "keyboard_shortcuts.local": "to open local timeline", "keyboard_shortcuts.mention": "to mention author", @@ -207,177 +205,179 @@ "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", - "lightbox.close": "Close", - "lightbox.next": "Next", - "lightbox.previous": "Previous", - "lists.account.add": "Add to list", - "lists.account.remove": "Remove from list", - "lists.delete": "Delete list", - "lists.edit": "Edit list", - "lists.edit.submit": "Change title", - "lists.new.create": "Add list", - "lists.new.title_placeholder": "New list title", - "lists.search": "Search among people you follow", - "lists.subheading": "Your lists", - "loading_indicator.label": "Loading...", - "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.apps": "Mobile apps", - "navigation_bar.blocks": "Blocked users", - "navigation_bar.community_timeline": "Local timeline", - "navigation_bar.compose": "Compose new toot", - "navigation_bar.direct": "Direct messages", - "navigation_bar.discover": "Discover", - "navigation_bar.domain_blocks": "Hidden domains", - "navigation_bar.edit_profile": "Edit profile", - "navigation_bar.favourites": "Favourites", - "navigation_bar.filters": "Muted words", - "navigation_bar.follow_requests": "Follow requests", - "navigation_bar.info": "About this instance", - "navigation_bar.keyboard_shortcuts": "Keyboard shortcuts", - "navigation_bar.lists": "Lists", - "navigation_bar.logout": "Logout", - "navigation_bar.mutes": "Muted users", - "navigation_bar.personal": "Personal", - "navigation_bar.pins": "Pinned toots", - "navigation_bar.preferences": "Preferences", - "navigation_bar.public_timeline": "Federated timeline", - "navigation_bar.security": "Security", - "notification.favourite": "{name} favourited your status", - "notification.follow": "{name} followed you", - "notification.mention": "{name} mentioned you", - "notification.reblog": "{name} boosted your status", - "notifications.clear": "Clear notifications", - "notifications.clear_confirmation": "Are you sure you want to permanently clear all your notifications?", + "lightbox.close": "ปิด", + "lightbox.next": "ถัดไป", + "lightbox.previous": "ก่อนหน้า", + "lists.account.add": "เพิ่มไปยังรายการ", + "lists.account.remove": "เอาออกจากรายการ", + "lists.delete": "ลบรายการ", + "lists.edit": "แก้ไขรายการ", + "lists.edit.submit": "เปลี่ยนชื่อเรื่อง", + "lists.new.create": "เพิ่มรายการ", + "lists.new.title_placeholder": "ชื่อเรื่องรายการใหม่", + "lists.search": "ค้นหาในหมู่ผู้คนที่คุณติดตาม", + "lists.subheading": "รายการของคุณ", + "loading_indicator.label": "กำลังโหลด...", + "media_gallery.toggle_visible": "เปิด/ปิดการมองเห็น", + "missing_indicator.label": "ไม่พบ", + "missing_indicator.sublabel": "ไม่พบทรัพยากรนี้", + "mute_modal.hide_notifications": "ซ่อนการแจ้งเตือนจากผู้ใช้นี้?", + "navigation_bar.apps": "แอปสำหรับมือถือ", + "navigation_bar.blocks": "ผู้ใช้ที่ปิดกั้นอยู่", + "navigation_bar.community_timeline": "เส้นเวลาในเว็บ", + "navigation_bar.compose": "เขียนโพสต์ใหม่", + "navigation_bar.direct": "ข้อความโดยตรง", + "navigation_bar.discover": "ค้นพบ", + "navigation_bar.domain_blocks": "โดเมนที่ซ่อนอยู่", + "navigation_bar.edit_profile": "แก้ไขโปรไฟล์", + "navigation_bar.favourites": "รายการโปรด", + "navigation_bar.filters": "คำที่ปิดเสียงอยู่", + "navigation_bar.follow_requests": "คำขอติดตาม", + "navigation_bar.info": "เกี่ยวกับเซิร์ฟเวอร์นี้", + "navigation_bar.keyboard_shortcuts": "ปุ่มลัด", + "navigation_bar.lists": "รายการ", + "navigation_bar.logout": "ออกจากระบบ", + "navigation_bar.mutes": "ผู้ใช้ที่ปิดเสียงอยู่", + "navigation_bar.personal": "ส่วนบุคคล", + "navigation_bar.pins": "โพสต์ที่ปักหมุด", + "navigation_bar.preferences": "การกำหนดลักษณะ", + "navigation_bar.public_timeline": "เส้นเวลาที่ติดต่อกับภายนอก", + "navigation_bar.security": "ความปลอดภัย", + "notification.favourite": "{name} ได้ชื่นชอบสถานะของคุณ", + "notification.follow": "{name} ได้ติดตามคุณ", + "notification.mention": "{name} ได้กล่าวถึงคุณ", + "notification.poll": "A poll you have voted in has ended", + "notification.reblog": "{name} ได้ดันสถานะของคุณ", + "notifications.clear": "ล้างการแจ้งเตือน", + "notifications.clear_confirmation": "คุณแน่ใจหรือไม่ว่าต้องการล้างการแจ้งเตือนทั้งหมดของคุณอย่างถาวร?", "notifications.column_settings.alert": "Desktop notifications", - "notifications.column_settings.favourite": "Favourites:", - "notifications.column_settings.filter_bar.advanced": "Display all categories", - "notifications.column_settings.filter_bar.category": "Quick filter bar", - "notifications.column_settings.filter_bar.show": "Show", - "notifications.column_settings.follow": "New followers:", - "notifications.column_settings.mention": "Mentions:", - "notifications.column_settings.push": "Push notifications", - "notifications.column_settings.reblog": "Boosts:", - "notifications.column_settings.show": "Show in column", - "notifications.column_settings.sound": "Play sound", - "notifications.filter.all": "All", - "notifications.filter.boosts": "Boosts", - "notifications.filter.favourites": "Favourites", - "notifications.filter.follows": "Follows", - "notifications.filter.mentions": "Mentions", - "notifications.group": "{count} notifications", - "poll.closed": "Closed", + "notifications.column_settings.favourite": "รายการโปรด:", + "notifications.column_settings.filter_bar.advanced": "แสดงหมวดหมู่ทั้งหมด", + "notifications.column_settings.filter_bar.category": "แถบตัวกรองด่วน", + "notifications.column_settings.filter_bar.show": "แสดง", + "notifications.column_settings.follow": "ผู้ติดตามใหม่:", + "notifications.column_settings.mention": "การกล่าวถึง:", + "notifications.column_settings.poll": "Poll results:", + "notifications.column_settings.push": "การแจ้งเตือนแบบผลัก", + "notifications.column_settings.reblog": "การดัน:", + "notifications.column_settings.show": "แสดงในคอลัมน์", + "notifications.column_settings.sound": "เล่นเสียง", + "notifications.filter.all": "ทั้งหมด", + "notifications.filter.boosts": "การดัน", + "notifications.filter.favourites": "รายการโปรด", + "notifications.filter.follows": "การติดตาม", + "notifications.filter.mentions": "การกล่าวถึง", + "notifications.filter.polls": "Poll results", + "notifications.group": "{count} การแจ้งเตือน", + "poll.closed": "ปิดแล้ว", "poll.refresh": "Refresh", "poll.total_votes": "{count, plural, one {# vote} other {# votes}}", "poll.vote": "Vote", "poll_button.add_poll": "Add a poll", "poll_button.remove_poll": "Remove poll", "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 post to public timelines", - "privacy.unlisted.short": "Unlisted", - "regeneration_indicator.label": "Loading…", + "privacy.direct.long": "โพสต์ไปยังผู้ใช้ที่กล่าวถึงเท่านั้น", + "privacy.direct.short": "โดยตรง", + "privacy.private.long": "โพสต์ไปยังผู้ติดตามเท่านั้น", + "privacy.private.short": "ผู้ติดตามเท่านั้น", + "privacy.public.long": "โพสต์ไปยังเส้นเวลาสาธารณะ", + "privacy.public.short": "สาธารณะ", + "privacy.unlisted.long": "ไม่โพสต์ไปยังเส้นเวลาสาธารณะ", + "privacy.unlisted.short": "ไม่อยู่ในรายการ", + "regeneration_indicator.label": "กำลังโหลด…", "regeneration_indicator.sublabel": "Your home feed is being prepared!", - "relative_time.days": "{number}d", - "relative_time.hours": "{number}h", - "relative_time.just_now": "now", - "relative_time.minutes": "{number}m", - "relative_time.seconds": "{number}s", - "reply_indicator.cancel": "Cancel", - "report.forward": "Forward to {target}", + "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": "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", - "search.placeholder": "Search", - "search_popout.search_format": "Advanced search format", + "report.placeholder": "ความคิดเห็นเพิ่มเติม", + "report.submit": "ส่ง", + "report.target": "กำลังรายงาน {target}", + "search.placeholder": "ค้นหา", + "search_popout.search_format": "รูปแบบการค้นหาขั้นสูง", "search_popout.tips.full_text": "Simple text returns statuses you have written, favourited, boosted, or have been mentioned in, as well as matching usernames, display names, and hashtags.", - "search_popout.tips.hashtag": "hashtag", - "search_popout.tips.status": "status", + "search_popout.tips.hashtag": "แฮชแท็ก", + "search_popout.tips.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_popout.tips.user": "ผู้ใช้", + "search_results.accounts": "ผู้คน", + "search_results.hashtags": "แฮชแท็ก", + "search_results.statuses": "โพสต์", "search_results.total": "{count, number} {count, plural, one {result} other {results}}", - "standalone.public_title": "A look inside...", - "status.admin_account": "Open moderation interface for @{name}", - "status.admin_status": "Open this status in the moderation interface", - "status.block": "Block @{name}", - "status.cancel_reblog_private": "Unboost", - "status.cannot_reblog": "This post cannot be boosted", - "status.copy": "Copy link to status", - "status.delete": "Delete", - "status.detailed_status": "Detailed conversation view", - "status.direct": "Direct message @{name}", + "status.admin_account": "เปิดส่วนติดต่อการควบคุมสำหรับ @{name}", + "status.admin_status": "เปิดสถานะนี้ในส่วนติดต่อการควบคุม", + "status.block": "ปิดกั้น @{name}", + "status.cancel_reblog_private": "เลิกดัน", + "status.cannot_reblog": "ไม่สามารถดันโพสต์นี้", + "status.copy": "คัดลอกลิงก์ไปยังสถานะ", + "status.delete": "ลบ", + "status.detailed_status": "มุมมองการสนทนาโดยละเอียด", + "status.direct": "ส่งข้อความโดยตรงถึง @{name}", "status.embed": "Embed", - "status.favourite": "Favourite", - "status.filtered": "Filtered", - "status.load_more": "Load more", - "status.media_hidden": "Media hidden", - "status.mention": "Mention @{name}", - "status.more": "More", - "status.mute": "Mute @{name}", - "status.mute_conversation": "Mute conversation", - "status.open": "Expand this status", - "status.pin": "Pin on profile", - "status.pinned": "Pinned toot", - "status.read_more": "Read more", - "status.reblog": "Boost", - "status.reblog_private": "Boost to original audience", - "status.reblogged_by": "{name} boosted", + "status.favourite": "ชื่นชอบ", + "status.filtered": "กรองอยู่", + "status.load_more": "โหลดเพิ่มเติม", + "status.media_hidden": "ซ่อนสื่ออยู่", + "status.mention": "กล่าวถึง @{name}", + "status.more": "เพิ่มเติม", + "status.mute": "ปิดเสียง @{name}", + "status.mute_conversation": "ปิดเสียงการสนทนา", + "status.open": "ขยายสถานะนี้", + "status.pin": "ปักหมุดในโปรไฟล์", + "status.pinned": "โพสต์ที่ปักหมุด", + "status.read_more": "อ่านเพิ่มเติม", + "status.reblog": "ดัน", + "status.reblog_private": "ดันไปยังผู้ชมดั้งเดิม", + "status.reblogged_by": "{name} ได้ดัน", "status.reblogs.empty": "No one has boosted this toot yet. When someone does, they will show up here.", - "status.redraft": "Delete & re-draft", - "status.reply": "Reply", - "status.replyAll": "Reply to thread", - "status.report": "Report @{name}", - "status.sensitive_toggle": "Click to view", - "status.sensitive_warning": "Sensitive content", - "status.share": "Share", - "status.show_less": "Show less", - "status.show_less_all": "Show less for all", - "status.show_more": "Show more", - "status.show_more_all": "Show more for all", - "status.show_thread": "Show thread", - "status.unmute_conversation": "Unmute conversation", - "status.unpin": "Unpin from profile", - "suggestions.dismiss": "Dismiss suggestion", - "suggestions.header": "You might be interested in…", - "tabs_bar.federated_timeline": "Federated", - "tabs_bar.home": "Home", - "tabs_bar.local_timeline": "Local", - "tabs_bar.notifications": "Notifications", - "tabs_bar.search": "Search", + "status.redraft": "ลบแล้วร่างใหม่", + "status.reply": "ตอบกลับ", + "status.replyAll": "ตอบกลับกระทู้", + "status.report": "รายงาน @{name}", + "status.sensitive_toggle": "คลิกเพื่อดู", + "status.sensitive_warning": "เนื้อหาที่ละเอียดอ่อน", + "status.share": "แบ่งปัน", + "status.show_less": "แสดงน้อยลง", + "status.show_less_all": "แสดงน้อยลงทั้งหมด", + "status.show_more": "แสดงเพิ่มเติม", + "status.show_more_all": "แสดงเพิ่มเติมทั้งหมด", + "status.show_thread": "แสดงกระทู้", + "status.unmute_conversation": "เลิกปิดเสียงการสนทนา", + "status.unpin": "ถอนหมุดจากโปรไฟล์", + "suggestions.dismiss": "ยกเลิกข้อเสนอแนะ", + "suggestions.header": "คุณอาจสนใจ…", + "tabs_bar.federated_timeline": "ที่ติดต่อกับภายนอก", + "tabs_bar.home": "หน้าแรก", + "tabs_bar.local_timeline": "ในเว็บ", + "tabs_bar.notifications": "การแจ้งเตือน", + "tabs_bar.search": "ค้นหา", "time_remaining.days": "{number, plural, one {# day} other {# days}} left", "time_remaining.hours": "{number, plural, one {# hour} other {# hours}} left", "time_remaining.minutes": "{number, plural, one {# minute} other {# minutes}} left", "time_remaining.moments": "Moments remaining", "time_remaining.seconds": "{number, plural, one {# second} other {# seconds}} left", "trends.count_by_accounts": "{count} {rawCount, plural, one {person} other {people}} talking", - "ui.beforeunload": "Your draft will be lost if you leave Mastodon.", - "upload_area.title": "Drag & drop to upload", - "upload_button.label": "Add media", - "upload_error.limit": "File upload limit exceeded.", + "ui.beforeunload": "แบบร่างของคุณจะหายไปหากคุณออกจาก Mastodon", + "upload_area.title": "ลากแล้วปล่อยเพื่ออัปโหลด", + "upload_button.label": "เพิ่มสื่อ (JPEG, PNG, GIF, WebM, MP4, MOV)", + "upload_error.limit": "เกินขีดจำกัดการอัปโหลดไฟล์", "upload_error.poll": "File upload not allowed with polls.", "upload_form.description": "Describe for the visually impaired", - "upload_form.focus": "Crop", - "upload_form.undo": "Undo", - "upload_progress.label": "Uploading...", - "video.close": "Close video", - "video.exit_fullscreen": "Exit full screen", - "video.expand": "Expand video", - "video.fullscreen": "Full screen", - "video.hide": "Hide video", - "video.mute": "Mute sound", - "video.pause": "Pause", - "video.play": "Play", - "video.unmute": "Unmute sound" + "upload_form.focus": "ตัวอย่างการเปลี่ยนแปลง", + "upload_form.undo": "ลบ", + "upload_progress.label": "กำลังอัปโหลด...", + "video.close": "ปิดวิดีโอ", + "video.exit_fullscreen": "ออกจากเต็มหน้าจอ", + "video.expand": "ขยายวิดีโอ", + "video.fullscreen": "เต็มหน้าจอ", + "video.hide": "ซ่อนวิดีโอ", + "video.mute": "ปิดเสียง", + "video.pause": "หยุดชั่วคราว", + "video.play": "เล่น", + "video.unmute": "เลิกปิดเสียง" } diff --git a/app/javascript/mastodon/locales/tr.json b/app/javascript/mastodon/locales/tr.json index 28b34fa04..cbe1c5726 100644 --- a/app/javascript/mastodon/locales/tr.json +++ b/app/javascript/mastodon/locales/tr.json @@ -5,7 +5,6 @@ "account.block_domain": "{domain} alanından her şeyi gizle", "account.blocked": "Engellenmiş", "account.direct": "Direct Message @{name}", - "account.disclaimer_full": "Aşağıdaki bilgiler, kullanıcının profilini tam olarak yansıtmayabilir.", "account.domain_blocked": "Alan adı gizlendi", "account.edit_profile": "Profili düzenle", "account.endorse": "Profildeki özellik", @@ -36,7 +35,6 @@ "account.unfollow": "Takipten vazgeç", "account.unmute": "Sesi aç @{name}", "account.unmute_notifications": "@{name} kullanıcısından bildirimleri aç", - "account.view_full_profile": "Tüm profili görüntüle", "alert.unexpected.message": "Beklenmedik bir hata oluştu.", "alert.unexpected.title": "Hay aksi!", "boost_modal.combo": "Bir dahaki sefere {combo} tuşuna basabilirsiniz", @@ -85,6 +83,7 @@ "compose_form.spoiler.unmarked": "Metin gizli değil", "compose_form.spoiler_placeholder": "İçerik uyarısı", "confirmation_modal.cancel": "İptal", + "confirmations.block.block_and_report": "Block & Report", "confirmations.block.confirm": "Engelle", "confirmations.block.message": "{name} kullanıcısını engellemek istiyor musunuz?", "confirmations.delete.confirm": "Sil", @@ -133,7 +132,6 @@ "empty_column.mutes": "Henüz hiçbir kullanıcıyı sessize almadınız.", "empty_column.notifications": "Henüz hiçbir bildiriminiz yok. Diğer insanlarla sobhet edebilmek için etkileşime geçebilirsiniz.", "empty_column.public": "Burada hiçbir şey yok! Herkese açık bir şeyler yazın veya burayı doldurmak için diğer sunuculardaki kullanıcıları takip edin", - "error_boundary.it_crashed": "It crashed!", "follow_request.authorize": "Yetkilendir", "follow_request.reject": "Reddet", "getting_started.developers": "Geliştiriciler", @@ -248,6 +246,7 @@ "notification.favourite": "{name} senin durumunu favorilere ekledi", "notification.follow": "{name} seni takip ediyor", "notification.mention": "{name} mentioned you", + "notification.poll": "A poll you have voted in has ended", "notification.reblog": "{name} senin durumunu boost etti", "notifications.clear": "Bildirimleri temizle", "notifications.clear_confirmation": "Tüm bildirimlerinizi kalıcı olarak temizlemek ister misiniz?", @@ -258,6 +257,7 @@ "notifications.column_settings.filter_bar.show": "Show", "notifications.column_settings.follow": "Yeni takipçiler:", "notifications.column_settings.mention": "Bahsedilenler:", + "notifications.column_settings.poll": "Poll results:", "notifications.column_settings.push": "Push notifications", "notifications.column_settings.reblog": "Boost’lar:", "notifications.column_settings.show": "Bildirimlerde göster", @@ -267,6 +267,7 @@ "notifications.filter.favourites": "Favourites", "notifications.filter.follows": "Follows", "notifications.filter.mentions": "Mentions", + "notifications.filter.polls": "Poll results", "notifications.group": "{count} notifications", "poll.closed": "Closed", "poll.refresh": "Refresh", @@ -308,7 +309,6 @@ "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.admin_account": "@{name} için denetim arayüzünü açın", "status.admin_status": "Denetim arayüzünde bu durumu açın", "status.block": "Block @{name}", diff --git a/app/javascript/mastodon/locales/uk.json b/app/javascript/mastodon/locales/uk.json index bd492e9e9..fc1c4f5d5 100644 --- a/app/javascript/mastodon/locales/uk.json +++ b/app/javascript/mastodon/locales/uk.json @@ -5,7 +5,6 @@ "account.block_domain": "Заглушити {domain}", "account.blocked": "Заблоковані", "account.direct": "Пряме повідомлення @{name}", - "account.disclaimer_full": "Інфомація знизу може відображати профіль користувача неповністю.", "account.domain_blocked": "Домен приховано", "account.edit_profile": "Редагувати профіль", "account.endorse": "Feature on profile", @@ -36,7 +35,6 @@ "account.unfollow": "Відписатися", "account.unmute": "Зняти глушення @{name}", "account.unmute_notifications": "Показувати сповіщення від @{name}", - "account.view_full_profile": "Показати профіль повністю", "alert.unexpected.message": "Трапилась неочікувана помилка.", "alert.unexpected.title": "Ой!", "boost_modal.combo": "Ви можете натиснути {combo}, щоб пропустити це наступного разу", @@ -85,6 +83,7 @@ "compose_form.spoiler.unmarked": "Текст видимий", "compose_form.spoiler_placeholder": "Попередження щодо прихованого тексту", "confirmation_modal.cancel": "Відмінити", + "confirmations.block.block_and_report": "Block & Report", "confirmations.block.confirm": "Заблокувати", "confirmations.block.message": "Ви впевнені, що хочете заблокувати {name}?", "confirmations.delete.confirm": "Видалити", @@ -133,7 +132,6 @@ "empty_column.mutes": "You haven't muted any users yet.", "empty_column.notifications": "У вас ще немає сповіщень. Переписуйтесь з іншими користувачами, щоб почати розмову.", "empty_column.public": "Тут поки нічого немає! Опублікуйте щось, або вручну підпишіться на користувачів інших інстанцій, щоб заповнити стрічку", - "error_boundary.it_crashed": "It crashed!", "follow_request.authorize": "Авторизувати", "follow_request.reject": "Відмовити", "getting_started.developers": "Розробникам", @@ -248,6 +246,7 @@ "notification.favourite": "{name} вподобав(-ла) ваш допис", "notification.follow": "{name} підписався(-лась) на Вас", "notification.mention": "{name} згадав(-ла) Вас", + "notification.poll": "A poll you have voted in has ended", "notification.reblog": "{name} передмухнув(-ла) Ваш допис", "notifications.clear": "Очистити сповіщення", "notifications.clear_confirmation": "Ви впевнені, що хочете назавжди видалити всі сповіщеня?", @@ -258,6 +257,7 @@ "notifications.column_settings.filter_bar.show": "Show", "notifications.column_settings.follow": "Нові підписники:", "notifications.column_settings.mention": "Згадки:", + "notifications.column_settings.poll": "Poll results:", "notifications.column_settings.push": "Push-сповіщення", "notifications.column_settings.reblog": "Передмухи:", "notifications.column_settings.show": "Показати в колонці", @@ -267,6 +267,7 @@ "notifications.filter.favourites": "Favourites", "notifications.filter.follows": "Follows", "notifications.filter.mentions": "Mentions", + "notifications.filter.polls": "Poll results", "notifications.group": "{count} сповіщень", "poll.closed": "Closed", "poll.refresh": "Refresh", @@ -308,7 +309,6 @@ "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.admin_account": "Open moderation interface for @{name}", "status.admin_status": "Open this status in the moderation interface", "status.block": "Block @{name}", diff --git a/app/javascript/mastodon/locales/whitelist_bn.json b/app/javascript/mastodon/locales/whitelist_bn.json new file mode 100644 index 000000000..0d4f101c7 --- /dev/null +++ b/app/javascript/mastodon/locales/whitelist_bn.json @@ -0,0 +1,2 @@ +[ +] diff --git a/app/javascript/mastodon/locales/zh-CN.json b/app/javascript/mastodon/locales/zh-CN.json index ae319d232..702be0ded 100644 --- a/app/javascript/mastodon/locales/zh-CN.json +++ b/app/javascript/mastodon/locales/zh-CN.json @@ -5,7 +5,6 @@ "account.block_domain": "隐藏来自 {domain} 的内容", "account.blocked": "已屏蔽", "account.direct": "发送私信给 @{name}", - "account.disclaimer_full": "此处显示的信息可能不是全部内容。", "account.domain_blocked": "网站已屏蔽", "account.edit_profile": "修改个人资料", "account.endorse": "Feature on profile", @@ -36,7 +35,6 @@ "account.unfollow": "取消关注", "account.unmute": "不再隐藏 @{name}", "account.unmute_notifications": "不再隐藏来自 @{name} 的通知", - "account.view_full_profile": "查看完整资料", "alert.unexpected.message": "发生了意外错误。", "alert.unexpected.title": "哎呀!", "boost_modal.combo": "下次按住 {combo} 即可跳过此提示", @@ -85,6 +83,7 @@ "compose_form.spoiler.unmarked": "正文未被折叠", "compose_form.spoiler_placeholder": "折叠部分的警告消息", "confirmation_modal.cancel": "取消", + "confirmations.block.block_and_report": "Block & Report", "confirmations.block.confirm": "屏蔽", "confirmations.block.message": "你确定要屏蔽 {name} 吗?", "confirmations.delete.confirm": "删除", @@ -133,7 +132,6 @@ "empty_column.mutes": "You haven't muted any users yet.", "empty_column.notifications": "你还没有收到过任何通知,快向其他用户搭讪吧。", "empty_column.public": "这里神马都没有!写一些公开的嘟文,或者关注其他实例的用户后,这里就会有嘟文出现了哦!", - "error_boundary.it_crashed": "It crashed!", "follow_request.authorize": "同意", "follow_request.reject": "拒绝", "getting_started.developers": "开发", @@ -248,6 +246,7 @@ "notification.favourite": "{name} 收藏了你的嘟文", "notification.follow": "{name} 开始关注你", "notification.mention": "{name} 提及你", + "notification.poll": "A poll you have voted in has ended", "notification.reblog": "{name} 转嘟了你的嘟文", "notifications.clear": "清空通知列表", "notifications.clear_confirmation": "你确定要永久清空通知列表吗?", @@ -258,6 +257,7 @@ "notifications.column_settings.filter_bar.show": "Show", "notifications.column_settings.follow": "当有人关注你时:", "notifications.column_settings.mention": "当有人在嘟文中提及你时:", + "notifications.column_settings.poll": "Poll results:", "notifications.column_settings.push": "推送通知", "notifications.column_settings.reblog": "当有人转嘟了你的嘟文时:", "notifications.column_settings.show": "在通知栏显示", @@ -267,6 +267,7 @@ "notifications.filter.favourites": "Favourites", "notifications.filter.follows": "Follows", "notifications.filter.mentions": "Mentions", + "notifications.filter.polls": "Poll results", "notifications.group": "{count} 条通知", "poll.closed": "Closed", "poll.refresh": "Refresh", @@ -308,7 +309,6 @@ "search_results.hashtags": "话题标签", "search_results.statuses": "嘟文", "search_results.total": "共 {count, number} 个结果", - "standalone.public_title": "大家都在干啥?", "status.admin_account": "Open moderation interface for @{name}", "status.admin_status": "Open this status in the moderation interface", "status.block": "屏蔽 @{name}", diff --git a/app/javascript/mastodon/locales/zh-HK.json b/app/javascript/mastodon/locales/zh-HK.json index 4fde7ef45..5ea738bc9 100644 --- a/app/javascript/mastodon/locales/zh-HK.json +++ b/app/javascript/mastodon/locales/zh-HK.json @@ -5,7 +5,6 @@ "account.block_domain": "隱藏來自 {domain} 的一切文章", "account.blocked": "封鎖", "account.direct": "私訊 @{name}", - "account.disclaimer_full": "下列資料不一定完整。", "account.domain_blocked": "服務站被隱藏", "account.edit_profile": "修改個人資料", "account.endorse": "Feature on profile", @@ -36,7 +35,6 @@ "account.unfollow": "取消關注", "account.unmute": "取消 @{name} 的靜音", "account.unmute_notifications": "取消來自 @{name} 通知的靜音", - "account.view_full_profile": "查看完整資料", "alert.unexpected.message": "發生不可預期的錯誤。", "alert.unexpected.title": "噢!", "boost_modal.combo": "如你想在下次路過這顯示,請按{combo},", @@ -85,6 +83,7 @@ "compose_form.spoiler.unmarked": "文字沒有被隱藏", "compose_form.spoiler_placeholder": "敏感警告訊息", "confirmation_modal.cancel": "取消", + "confirmations.block.block_and_report": "Block & Report", "confirmations.block.confirm": "封鎖", "confirmations.block.message": "你確定要封鎖{name}嗎?", "confirmations.delete.confirm": "刪除", @@ -133,7 +132,6 @@ "empty_column.mutes": "You haven't muted any users yet.", "empty_column.notifications": "你沒有任何通知紀錄,快向其他用戶搭訕吧。", "empty_column.public": "跨站時間軸暫時沒有內容!快寫一些公共的文章,或者關注另一些服務站的用戶吧!你和本站、友站的交流,將決定這裏出現的內容。", - "error_boundary.it_crashed": "It crashed!", "follow_request.authorize": "批准", "follow_request.reject": "拒絕", "getting_started.developers": "開發者", @@ -248,6 +246,7 @@ "notification.favourite": "{name} 收藏了你的文章", "notification.follow": "{name} 開始關注你", "notification.mention": "{name} 提及你", + "notification.poll": "A poll you have voted in has ended", "notification.reblog": "{name} 轉推你的文章", "notifications.clear": "清空通知紀錄", "notifications.clear_confirmation": "你確定要清空通知紀錄嗎?", @@ -258,6 +257,7 @@ "notifications.column_settings.filter_bar.show": "Show", "notifications.column_settings.follow": "關注你:", "notifications.column_settings.mention": "提及你:", + "notifications.column_settings.poll": "Poll results:", "notifications.column_settings.push": "推送通知", "notifications.column_settings.reblog": "轉推你的文章:", "notifications.column_settings.show": "在通知欄顯示", @@ -267,6 +267,7 @@ "notifications.filter.favourites": "Favourites", "notifications.filter.follows": "Follows", "notifications.filter.mentions": "Mentions", + "notifications.filter.polls": "Poll results", "notifications.group": "{count} 條通知", "poll.closed": "Closed", "poll.refresh": "Refresh", @@ -308,7 +309,6 @@ "search_results.hashtags": "標籤", "search_results.statuses": "文章", "search_results.total": "{count, number} 項結果", - "standalone.public_title": "站點一瞥…", "status.admin_account": "Open moderation interface for @{name}", "status.admin_status": "Open this status in the moderation interface", "status.block": "封鎖 @{name}", diff --git a/app/javascript/mastodon/locales/zh-TW.json b/app/javascript/mastodon/locales/zh-TW.json index 9a116a702..6d33ef070 100644 --- a/app/javascript/mastodon/locales/zh-TW.json +++ b/app/javascript/mastodon/locales/zh-TW.json @@ -1,222 +1,220 @@ { - "account.add_or_remove_from_list": "Add or Remove from lists", + "account.add_or_remove_from_list": "從名單中新增或移除", "account.badges.bot": "機器人", "account.block": "封鎖 @{name}", - "account.block_domain": "隱藏來自 {domain} 的一切嘟文", - "account.blocked": "已被封鎖的", - "account.direct": "發送私訊給 @{name}", - "account.disclaimer_full": "下列資料不一定完整。", - "account.domain_blocked": "站點被隱藏", - "account.edit_profile": "編輯使用者資訊", - "account.endorse": "在個人資訊頁面上推薦對方", + "account.block_domain": "隱藏來自 {domain} 的所有嘟文", + "account.blocked": "已封鎖", + "account.direct": "傳私訊給 @{name}", + "account.domain_blocked": "已隱藏網域", + "account.edit_profile": "編輯個人資料", + "account.endorse": "在個人資料推薦對方", "account.follow": "關注", "account.followers": "關注者", - "account.followers.empty": "還沒有人關注這個使用者。", + "account.followers.empty": "還沒有人關注這位使用者。", "account.follows": "正在關注", - "account.follows.empty": "這個使用者還沒有關注任何人。", - "account.follows_you": "關注你", + "account.follows.empty": "這個使用者尚未關注任何使用者。", + "account.follows_you": "關注了你", "account.hide_reblogs": "隱藏來自 @{name} 的轉推", - "account.link_verified_on": "Ownership of this link was checked on {date}", - "account.locked_info": "This account privacy status is set to locked. The owner manually reviews who can follow them.", + "account.link_verified_on": "此連結的所有權已在 {date} 檢查", + "account.locked_info": "此帳號的隱私狀態被設為鎖定,擁有者將手動審核可關注此帳號的人。", "account.media": "媒體", - "account.mention": "提到 @{name}", - "account.moved_to": "{name} 已經移至:", + "account.mention": "提及 @{name}", + "account.moved_to": "{name} 已遷移至:", "account.mute": "靜音 @{name}", "account.mute_notifications": "靜音來自 @{name} 的通知", - "account.muted": "靜音", + "account.muted": "已靜音", "account.posts": "嘟文", "account.posts_with_replies": "嘟文與回覆", "account.report": "檢舉 @{name}", - "account.requested": "正在等待對方同意。點擊以取消發送關注請求", - "account.share": "分享 @{name} 的使用者資訊", + "account.requested": "正在等待核准。按一下取消關注請求", + "account.share": "分享 @{name} 的個人資料", "account.show_reblogs": "顯示來自 @{name} 的嘟文", "account.unblock": "取消封鎖 @{name}", - "account.unblock_domain": "不再隱藏 {domain}", - "account.unendorse": "不再於個人資訊頁面上推薦對方", + "account.unblock_domain": "取消隱藏 {domain}", + "account.unendorse": "不再於個人資料頁面推薦對方", "account.unfollow": "取消關注", "account.unmute": "不再靜音 @{name}", - "account.unmute_notifications": "不再對來自 @{name} 的通知靜音", - "account.view_full_profile": "查看完整資訊", - "alert.unexpected.message": "發生非預期的錯誤。", + "account.unmute_notifications": "不再靜音來自 @{name} 的通知", + "alert.unexpected.message": "發生了非預期的錯誤。", "alert.unexpected.title": "哎呀!", - "boost_modal.combo": "下次你可以按 {combo} 來跳過", - "bundle_column_error.body": "加載本組件出錯。", + "boost_modal.combo": "下次您可以按 {combo} 跳過", + "bundle_column_error.body": "載入此組件時發生錯誤。", "bundle_column_error.retry": "重試", "bundle_column_error.title": "網路錯誤", "bundle_modal_error.close": "關閉", - "bundle_modal_error.message": "加載本組件出錯。", + "bundle_modal_error.message": "載入此組件時發生錯誤。", "bundle_modal_error.retry": "重試", "column.blocks": "封鎖的使用者", "column.community": "本地時間軸", "column.direct": "私訊", - "column.domain_blocks": "隱藏的站點", + "column.domain_blocks": "隱藏的網域", "column.favourites": "最愛", "column.follow_requests": "關注請求", "column.home": "主頁", "column.lists": "名單", - "column.mutes": "靜音的使用者", + "column.mutes": "被靜音的使用者", "column.notifications": "通知", - "column.pins": "置頂嘟文", - "column.public": "其他站點時間軸", + "column.pins": "釘選的嘟文", + "column.public": "聯邦時間軸", "column_back_button.label": "上一頁", "column_header.hide_settings": "隱藏設定", - "column_header.moveLeft_settings": "將欄左移", - "column_header.moveRight_settings": "將欄右移", - "column_header.pin": "固定", + "column_header.moveLeft_settings": "將欄位向左移動", + "column_header.moveRight_settings": "將欄位向右移動", + "column_header.pin": "釘選", "column_header.show_settings": "顯示設定", - "column_header.unpin": "取下", + "column_header.unpin": "取消釘選", "column_subheading.settings": "設定", "community.column_settings.media_only": "僅媒體", - "compose_form.direct_message_warning": "這條嘟文僅對有被提及的使用者才能看到。", + "compose_form.direct_message_warning": "這條嘟文只有被提及的使用者才能看到。", "compose_form.direct_message_warning_learn_more": "了解更多", - "compose_form.hashtag_warning": "此則推文將不會在任何主題標籤中看見,只有公開的推文可以用主題標籤來搜尋。", - "compose_form.lock_disclaimer": "你的帳號沒有{locked}。任何人都可以關注你,看到發給關注者的嘟文。", + "compose_form.hashtag_warning": "因這則嘟文設成「不公開」,因此它不會列在任何「#」標籤下。只有公開嘟文才能用「#」標籤找到。", + "compose_form.lock_disclaimer": "您的帳戶尚未{locked}。任何人都能關注您並看到您設定成僅關注者能看的嘟文。", "compose_form.lock_disclaimer.lock": "上鎖", - "compose_form.placeholder": "在想些什麼?", - "compose_form.poll.add_option": "Add a choice", - "compose_form.poll.duration": "Poll duration", - "compose_form.poll.option_placeholder": "Choice {number}", - "compose_form.poll.remove_option": "Remove this choice", + "compose_form.placeholder": "您正在想些什麼?", + "compose_form.poll.add_option": "新增選擇", + "compose_form.poll.duration": "投票期限", + "compose_form.poll.option_placeholder": "第 {number} 個選擇", + "compose_form.poll.remove_option": "移除此選擇", "compose_form.publish": "嘟掉", "compose_form.publish_loud": "{publish}!", - "compose_form.sensitive.marked": "此媒體已被標註為敏感的", - "compose_form.sensitive.unmarked": "此媒體未被標註為敏感的", - "compose_form.spoiler.marked": "文字隱藏在警告後", - "compose_form.spoiler.unmarked": "文字不是隱藏的", - "compose_form.spoiler_placeholder": "內容警告", + "compose_form.sensitive.marked": "此媒體被標記為敏感內容", + "compose_form.sensitive.unmarked": "此媒體未被標記為敏感內容", + "compose_form.spoiler.marked": "正文已隱藏在警告之後", + "compose_form.spoiler.unmarked": "正文未被隱藏", + "compose_form.spoiler_placeholder": "請在此處寫入警告訊息", "confirmation_modal.cancel": "取消", + "confirmations.block.block_and_report": "Block & Report", "confirmations.block.confirm": "封鎖", "confirmations.block.message": "你確定要封鎖 {name} ?", "confirmations.delete.confirm": "刪除", - "confirmations.delete.message": "你確定要刪除這個狀態?", + "confirmations.delete.message": "你確定要刪除這條嘟文?", "confirmations.delete_list.confirm": "刪除", - "confirmations.delete_list.message": "確定要永久性地刪除這個名單嗎?", + "confirmations.delete_list.message": "確定要永久刪除此名單?", "confirmations.domain_block.confirm": "隱藏整個網域", - "confirmations.domain_block.message": "你真的確定要靜音所有來自 {domain} 的內容嗎? 多數情況下,封鎖或靜音幾個特定用戶應該就能滿足你的需求了。來自該站點的內容將不再出現在你的公共時間軸或通知裡。來自該站點的關注者將會被移除。", - "confirmations.mute.confirm": "消音", - "confirmations.mute.message": "你確定要消音 {name} ?", - "confirmations.redraft.confirm": "刪除 & 編輯", - "confirmations.redraft.message": "你確定要刪除這條嘟文並重新編輯它嗎?所有相關的轉嘟與最愛都會被刪除,而對原始嘟文的回覆將會變成孤兒。", - "confirmations.reply.confirm": "Reply", - "confirmations.reply.message": "Replying now will overwrite the message you are currently composing. Are you sure you want to proceed?", + "confirmations.domain_block.message": "確定封鎖整個 {domain} 嗎?多數情況下,封鎖或靜音幾個特定使用者應該就能滿足你的需求了。您將不能在任何公開時間軸或通知中看到來自該網域的內容。來自該網域的關注者將被移除。", + "confirmations.mute.confirm": "靜音", + "confirmations.mute.message": "確定靜音 {name} ?", + "confirmations.redraft.confirm": "刪除並重新編輯", + "confirmations.redraft.message": "你確定要刪除這條嘟文並重新編輯它嗎?這麼做將失去轉嘟和最愛,而對原始嘟文的回覆將被孤立。", + "confirmations.reply.confirm": "回覆", + "confirmations.reply.message": "現在回覆將蓋掉您目前正在撰寫的訊息。是否仍要回覆?", "confirmations.unfollow.confirm": "取消關注", - "confirmations.unfollow.message": "真的不要繼續關注 {name} 了嗎?", - "embed.instructions": "要內嵌此嘟文,請將以下代碼貼進你的網站。", - "embed.preview": "看上去會變成這樣:", + "confirmations.unfollow.message": "真的要取消關注 {name} 嗎?", + "embed.instructions": "要嵌入此嘟文,請將以下代碼貼進你的網站。", + "embed.preview": "他會顯示成這樣:", "emoji_button.activity": "活動", "emoji_button.custom": "自訂", - "emoji_button.flags": "旗幟", + "emoji_button.flags": "旗標", "emoji_button.food": "飲食", "emoji_button.label": "插入表情符號", - "emoji_button.nature": "自然", - "emoji_button.not_found": "沒有表情符號吼!! (╯°□°)╯︵ ┻━┻", + "emoji_button.nature": "大自然", + "emoji_button.not_found": "就沒這表情符號吼!! (╯°□°)╯︵ ┻━┻", "emoji_button.objects": "物件", "emoji_button.people": "使用者", - "emoji_button.recent": "常用", + "emoji_button.recent": "最常使用", "emoji_button.search": "搜尋…", "emoji_button.search_results": "搜尋結果", "emoji_button.symbols": "符號", "emoji_button.travel": "旅遊與地點", - "empty_column.account_timeline": "No toots here!", + "empty_column.account_timeline": "這裡還沒有嘟文!", "empty_column.blocks": "你還沒有封鎖任何使用者。", - "empty_column.community": "本地時間軸是空的。公開寫點什麼吧!", - "empty_column.direct": "你還沒有使用過私訊。當你發出或著收到私訊時,它會在這裡顯示。", - "empty_column.domain_blocks": "還沒有隱藏任何網域。", - "empty_column.favourited_statuses": "你還沒有收藏任何嘟文。收藏後的嘟文會顯示在這裡。", - "empty_column.favourites": "還沒有人收藏此嘟文。如果有人收藏,會顯示在這裡。", - "empty_column.follow_requests": "還沒有人請求關注你。如果收到關注請求,會顯示在這裡。", - "empty_column.hashtag": "這個主題標籤下什麼都沒有。", - "empty_column.home": "你還沒關注任何人。造訪{public}或利用搜尋功能找到其他用者。", + "empty_column.community": "本地時間軸是空的。快公開嘟些文搶頭香啊!", + "empty_column.direct": "您還沒有任何私訊。當您私訊別人或收到私訊時,它將於此顯示。", + "empty_column.domain_blocks": "尚未隱藏任何網域。", + "empty_column.favourited_statuses": "你還沒有將任何嘟文標為最愛。最愛的嘟文將顯示於此。", + "empty_column.favourites": "還沒有人將此嘟文標為最愛。如果有人標成最愛,則會顯示在這裡。", + "empty_column.follow_requests": "您尚未收到任何關注請求。收到時會顯示於此。", + "empty_column.hashtag": "這個「#」標籤下什麼都沒有。", + "empty_column.home": "您的首頁時間軸是空的!前往 {public} 或使用搜尋功能來認識其他人。", "empty_column.home.public_timeline": "公開時間軸", - "empty_column.list": "此份名單尚未有東西。當此名單的成員嘟出了新的狀態時,它們就會出現在這裡。", + "empty_column.list": "此份名單還沒有東西。當此名單的成員嘟出了新的嘟文時,它們就會出現在這裡。", "empty_column.lists": "你還沒有建立任何名單。你建立的名單將會顯示在這裡。", "empty_column.mutes": "你還沒有靜音任何使用者。", - "empty_column.notifications": "還沒有任何通知。和別的使用者互動來開始對話。", - "empty_column.public": "這裡什麼都沒有! 寫一些公開的嘟文,或著關注其他站點的使用者後,這裡就會有嘟文出現了", - "error_boundary.it_crashed": "It crashed!", + "empty_column.notifications": "您尚未收到任何通知,和別人互動開啟對話吧。", + "empty_column.public": "這裡什麼都沒有!嘗試寫些公開的嘟文,或著自己關注其他伺服器的使用者後就會有嘟文出現了", "follow_request.authorize": "授權", "follow_request.reject": "拒絕", - "getting_started.developers": "開發", - "getting_started.directory": "Profile directory", + "getting_started.developers": "開發者", + "getting_started.directory": "個人資料目錄", "getting_started.documentation": "文件", - "getting_started.heading": "馬上開始", + "getting_started.heading": "開始使用", "getting_started.invite": "邀請使用者", - "getting_started.open_source_notice": "Mastodon 是開源軟體。你可以在 GitHub {github} 上做出貢獻或是回報問題。", - "getting_started.security": "登入資訊", - "getting_started.terms": "使用條款", - "hashtag.column_header.tag_mode.all": "and {additional}", - "hashtag.column_header.tag_mode.any": "or {additional}", - "hashtag.column_header.tag_mode.none": "without {additional}", - "hashtag.column_settings.select.no_options_message": "No suggestions found", - "hashtag.column_settings.select.placeholder": "Enter hashtags…", - "hashtag.column_settings.tag_mode.all": "All of these", - "hashtag.column_settings.tag_mode.any": "Any of these", - "hashtag.column_settings.tag_mode.none": "None of these", - "hashtag.column_settings.tag_toggle": "Include additional tags in this column", + "getting_started.open_source_notice": "Mastodon 是開源軟體。你可以在 GitHub {github} 上貢獻或是回報問題。", + "getting_started.security": "安全性", + "getting_started.terms": "服務條款", + "hashtag.column_header.tag_mode.all": "以及{additional}", + "hashtag.column_header.tag_mode.any": "或是{additional}", + "hashtag.column_header.tag_mode.none": "而不用{additional}", + "hashtag.column_settings.select.no_options_message": "找不到建議", + "hashtag.column_settings.select.placeholder": "輸入「#」標籤…", + "hashtag.column_settings.tag_mode.all": "全部", + "hashtag.column_settings.tag_mode.any": "任一", + "hashtag.column_settings.tag_mode.none": "全都不要", + "hashtag.column_settings.tag_toggle": "對此欄位加入額外標籤", "home.column_settings.basic": "基本", "home.column_settings.show_reblogs": "顯示轉推", - "home.column_settings.show_replies": "顯示回應", - "intervals.full.days": "{number, plural, one {# day} other {# days}}", - "intervals.full.hours": "{number, plural, one {# hour} other {# hours}}", - "intervals.full.minutes": "{number, plural, one {# minute} other {# minutes}}", - "introduction.federation.action": "Next", - "introduction.federation.federated.headline": "Federated", - "introduction.federation.federated.text": "Public posts from other servers of the fediverse will appear in the federated timeline.", - "introduction.federation.home.headline": "Home", - "introduction.federation.home.text": "Posts from people you follow will appear in your home feed. You can follow anyone on any server!", - "introduction.federation.local.headline": "Local", - "introduction.federation.local.text": "Public posts from people on the same server as you will appear in the local timeline.", - "introduction.interactions.action": "Finish tutorial!", - "introduction.interactions.favourite.headline": "Favourite", - "introduction.interactions.favourite.text": "You can save a toot for later, and let the author know that you liked it, by favouriting it.", - "introduction.interactions.reblog.headline": "Boost", - "introduction.interactions.reblog.text": "You can share other people's toots with your followers by boosting them.", - "introduction.interactions.reply.headline": "Reply", - "introduction.interactions.reply.text": "You can reply to other people's and your own toots, which will chain them together in a conversation.", - "introduction.welcome.action": "Let's go!", - "introduction.welcome.headline": "First steps", - "introduction.welcome.text": "Welcome to the fediverse! In a few moments, you'll be able to broadcast messages and talk to your friends across a wide variety of servers. But this server, {domain}, is special—it hosts your profile, so remember its name.", - "keyboard_shortcuts.back": "回到上一個", - "keyboard_shortcuts.blocked": "到封鎖的使用者名單", - "keyboard_shortcuts.boost": "到轉推", - "keyboard_shortcuts.column": "選擇第 X 欄中的嘟文", - "keyboard_shortcuts.compose": "焦點移至撰寫文字區塊", + "home.column_settings.show_replies": "顯示回覆", + "intervals.full.days": "{number, plural, one {# 天} other {# 天}}", + "intervals.full.hours": "{number, plural, one {# 小時} other {# 小時}}", + "intervals.full.minutes": "{number, plural, one {# 分鐘} other {# 分鐘}}", + "introduction.federation.action": "下一步", + "introduction.federation.federated.headline": "聯邦", + "introduction.federation.federated.text": "來自聯邦網路中其他伺服器的公開嘟文將會在聯邦網路時間軸中顯示。", + "introduction.federation.home.headline": "首頁", + "introduction.federation.home.text": "您所關注使用者所發的嘟文將顯示在首頁的訊息來源。您能關注任何伺服器上的任何人!", + "introduction.federation.local.headline": "本地", + "introduction.federation.local.text": "跟您同伺服器之使用者所發的公開嘟文將會顯示在本地時間軸中。", + "introduction.interactions.action": "完成教學!", + "introduction.interactions.favourite.headline": "最愛", + "introduction.interactions.favourite.text": "您能稍候儲存嘟文,或者將嘟文加到最愛,讓作者知道您喜歡這嘟文。", + "introduction.interactions.reblog.headline": "轉嘟", + "introduction.interactions.reblog.text": "您能透過轉嘟他人嘟文來分享給您的關注者。", + "introduction.interactions.reply.headline": "回覆", + "introduction.interactions.reply.text": "您能回覆其他人或自己的嘟文。將會把這些回覆串成一串對話。", + "introduction.welcome.action": "開始!", + "introduction.welcome.headline": "第一步", + "introduction.welcome.text": "歡迎來到聯邦!稍候您將可以廣播訊息並跨各種各式各樣的伺服器與朋友聊天。但這台伺服器,{domain},十分特殊 -- 它寄管了您的個人資料,所以請記住這台伺服器的名稱。", + "keyboard_shortcuts.back": "返回上一頁", + "keyboard_shortcuts.blocked": "開啟「封鎖的使用者」名單", + "keyboard_shortcuts.boost": "轉嘟", + "keyboard_shortcuts.column": "將焦點放在其中一欄的嘟文", + "keyboard_shortcuts.compose": "將焦點移至撰寫文字區塊", "keyboard_shortcuts.description": "描述", - "keyboard_shortcuts.direct": "到私訊欄", - "keyboard_shortcuts.down": "在列表往下移動", - "keyboard_shortcuts.enter": "看嘟文", - "keyboard_shortcuts.favourite": "收藏", - "keyboard_shortcuts.favourites": "到收藏名單", - "keyboard_shortcuts.federated": "到其他站點時間軸", + "keyboard_shortcuts.direct": "開啟私訊欄", + "keyboard_shortcuts.down": "在名單中往下移動", + "keyboard_shortcuts.enter": "檢視嘟文", + "keyboard_shortcuts.favourite": "加入最愛", + "keyboard_shortcuts.favourites": "開啟最愛名單", + "keyboard_shortcuts.federated": "開啟聯邦時間軸", "keyboard_shortcuts.heading": "鍵盤快速鍵", - "keyboard_shortcuts.home": "到主頁時間軸", + "keyboard_shortcuts.home": "開啟首頁時間軸", "keyboard_shortcuts.hotkey": "快速鍵", - "keyboard_shortcuts.legend": "顯示這個說明", - "keyboard_shortcuts.local": "到本地時間軸", - "keyboard_shortcuts.mention": "到提到的作者", - "keyboard_shortcuts.muted": "到靜音的使用者列表", - "keyboard_shortcuts.my_profile": "到你的個人資訊頁", - "keyboard_shortcuts.notifications": "打開通知欄", - "keyboard_shortcuts.pinned": "到收藏的嘟文名單", - "keyboard_shortcuts.profile": "到嘟文作者的個人資訊頁", - "keyboard_shortcuts.reply": "到回應", - "keyboard_shortcuts.requests": "打開關注請求名單", - "keyboard_shortcuts.search": "把滑鼠移動到搜尋", - "keyboard_shortcuts.start": "到「馬上開始」", - "keyboard_shortcuts.toggle_hidden": "顯示或隱藏被標為敏感的嘟文", - "keyboard_shortcuts.toot": "新的嘟文", - "keyboard_shortcuts.unfocus": "取消輸入", - "keyboard_shortcuts.up": "在列表往上移動", + "keyboard_shortcuts.legend": "顯示此說明", + "keyboard_shortcuts.local": "開啟本地時間軸", + "keyboard_shortcuts.mention": "提及作者", + "keyboard_shortcuts.muted": "開啟靜音使用者名單", + "keyboard_shortcuts.my_profile": "開啟個人資料頁面", + "keyboard_shortcuts.notifications": "開啟通知欄", + "keyboard_shortcuts.pinned": "開啟釘選的嘟文名單", + "keyboard_shortcuts.profile": "開啟作者的個人資料頁", + "keyboard_shortcuts.reply": "回應嘟文", + "keyboard_shortcuts.requests": "開啟關注請求名單", + "keyboard_shortcuts.search": "將焦點移至搜尋框", + "keyboard_shortcuts.start": "開啟「開始使用」欄位", + "keyboard_shortcuts.toggle_hidden": "顯示/隱藏在內容警告之後的正文", + "keyboard_shortcuts.toot": "開始發出新嘟文", + "keyboard_shortcuts.unfocus": "取消輸入文字區塊 / 搜尋的焦點", + "keyboard_shortcuts.up": "在名單中往上移動", "lightbox.close": "關閉", - "lightbox.next": "繼續", - "lightbox.previous": "回退", - "lists.account.add": "加到名單裡", + "lightbox.next": "下一步", + "lightbox.previous": "上一步", + "lists.account.add": "新增至名單", "lists.account.remove": "從名單中移除", "lists.delete": "刪除名單", - "lists.edit": "修改名單", - "lists.edit.submit": "Change title", + "lists.edit": "編輯名單", + "lists.edit.submit": "變更標題", "lists.new.create": "新增名單", - "lists.new.title_placeholder": "名單名稱", + "lists.new.title_placeholder": "新名單標題", "lists.search": "搜尋您關注的使用者", "lists.subheading": "您的名單", "loading_indicator.label": "讀取中...", @@ -227,53 +225,56 @@ "navigation_bar.apps": "行動應用程式", "navigation_bar.blocks": "封鎖的使用者", "navigation_bar.community_timeline": "本地時間軸", - "navigation_bar.compose": "寫新的嘟文", + "navigation_bar.compose": "撰寫新嘟文", "navigation_bar.direct": "私訊", "navigation_bar.discover": "探索", - "navigation_bar.domain_blocks": "隱藏的站點", - "navigation_bar.edit_profile": "編輯使用者資訊", - "navigation_bar.favourites": "最愛", - "navigation_bar.filters": "消音的詞", + "navigation_bar.domain_blocks": "隱藏的網域", + "navigation_bar.edit_profile": "編輯個人資料", + "navigation_bar.favourites": "最愛內容", + "navigation_bar.filters": "靜音詞彙", "navigation_bar.follow_requests": "關注請求", - "navigation_bar.info": "關於本站", - "navigation_bar.keyboard_shortcuts": "快捷鍵", + "navigation_bar.info": "關於此伺服器", + "navigation_bar.keyboard_shortcuts": "快速鍵", "navigation_bar.lists": "名單", "navigation_bar.logout": "登出", "navigation_bar.mutes": "靜音的使用者", "navigation_bar.personal": "個人", - "navigation_bar.pins": "置頂嘟文", + "navigation_bar.pins": "釘選的嘟文", "navigation_bar.preferences": "偏好設定", - "navigation_bar.public_timeline": "其他站點時間軸", - "navigation_bar.security": "登入資訊", - "notification.favourite": "{name}把你的嘟文加入了最愛", - "notification.follow": "{name}關注了你", - "notification.mention": "{name}提到了你", + "navigation_bar.public_timeline": "聯邦時間軸", + "navigation_bar.security": "安全性", + "notification.favourite": "{name} 把你的嘟文加入了最愛", + "notification.follow": "{name} 關注了你", + "notification.mention": "{name} 提到了你", + "notification.poll": "您投過的投票已經結束", "notification.reblog": "{name}轉嘟了你的嘟文", "notifications.clear": "清除通知", "notifications.clear_confirmation": "確定要永久清除你的通知嗎?", "notifications.column_settings.alert": "桌面通知", "notifications.column_settings.favourite": "最愛:", - "notifications.column_settings.filter_bar.advanced": "Display all categories", - "notifications.column_settings.filter_bar.category": "Quick filter bar", - "notifications.column_settings.filter_bar.show": "Show", - "notifications.column_settings.follow": "新的關注者:", - "notifications.column_settings.mention": "提到:", + "notifications.column_settings.filter_bar.advanced": "顯示所有分類", + "notifications.column_settings.filter_bar.category": "快速過濾欄", + "notifications.column_settings.filter_bar.show": "顯示", + "notifications.column_settings.follow": "新關注者:", + "notifications.column_settings.mention": "提及:", + "notifications.column_settings.poll": "投票結果:", "notifications.column_settings.push": "推送通知", "notifications.column_settings.reblog": "轉嘟:", - "notifications.column_settings.show": "顯示在欄位中", + "notifications.column_settings.show": "在欄位中顯示", "notifications.column_settings.sound": "播放音效", - "notifications.filter.all": "All", - "notifications.filter.boosts": "Boosts", - "notifications.filter.favourites": "Favourites", - "notifications.filter.follows": "Follows", - "notifications.filter.mentions": "Mentions", + "notifications.filter.all": "全部", + "notifications.filter.boosts": "轉嘟", + "notifications.filter.favourites": "最愛", + "notifications.filter.follows": "關注的使用者", + "notifications.filter.mentions": "提及", + "notifications.filter.polls": "投票結果", "notifications.group": "{count} 條通知", - "poll.closed": "Closed", - "poll.refresh": "Refresh", - "poll.total_votes": "{count, plural, one {# vote} other {# votes}}", - "poll.vote": "Vote", - "poll_button.add_poll": "Add a poll", - "poll_button.remove_poll": "Remove poll", + "poll.closed": "已關閉", + "poll.refresh": "重新整理", + "poll.total_votes": "{count, plural, one {# 個投票} other {# 個投票}}", + "poll.vote": "投票", + "poll_button.add_poll": "建立投票", + "poll_button.remove_poll": "移除投票", "privacy.change": "調整隱私狀態", "privacy.direct.long": "只有被提到的使用者能看到", "privacy.direct.short": "私訊", @@ -293,7 +294,7 @@ "reply_indicator.cancel": "取消", "report.forward": "轉寄到 {target}", "report.forward_hint": "這個帳戶屬於其他站點。要像該站點發送匿名的檢舉訊息嗎?", - "report.hint": "這項訊息會發送到你該站點的管理員。你可以提供檢舉這個帳戶的理由:", + "report.hint": "這項訊息會發送到您伺服器的管理員。你可以提供檢舉這個帳戶的理由:", "report.placeholder": "更多訊息", "report.submit": "送出", "report.target": "檢舉 {target}", @@ -301,20 +302,19 @@ "search_popout.search_format": "進階搜尋格式", "search_popout.tips.full_text": "輸入簡單的文字,搜尋由你撰寫、最愛、轉嘟或提你的嘟文,以及符合使用者名稱、帳戶名稱和標籤。", "search_popout.tips.hashtag": "主題標籤", - "search_popout.tips.status": "狀態", + "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.admin_account": "Open moderation interface for @{name}", - "status.admin_status": "Open this status in the moderation interface", + "status.admin_account": "開啟 @{name} 的管理介面", + "status.admin_status": "在管理介面開啟此嘟文", "status.block": "封鎖 @{name}", "status.cancel_reblog_private": "取消轉嘟", "status.cannot_reblog": "這篇嘟文無法被轉嘟", - "status.copy": "Copy link to status", + "status.copy": "將連結複製到嘟文中", "status.delete": "刪除", "status.detailed_status": "對話的詳細內容", "status.direct": "發送私訊給 @{name}", @@ -328,9 +328,9 @@ "status.mute": "靜音 @{name}", "status.mute_conversation": "靜音對話", "status.open": "展開嘟文", - "status.pin": "置頂到個人資訊頁", - "status.pinned": "置頂嘟文", - "status.read_more": "Read more", + "status.pin": "釘選到個人資料頁", + "status.pinned": "釘選的嘟文", + "status.read_more": "閱讀更多", "status.reblog": "轉嘟", "status.reblog_private": "轉嘟給原有關注者", "status.reblogged_by": "{name} 轉嘟了", @@ -346,29 +346,29 @@ "status.show_less_all": "減少顯示這類嘟文", "status.show_more": "顯示更多", "status.show_more_all": "顯示更多這類嘟文", - "status.show_thread": "Show thread", + "status.show_thread": "顯示討論串", "status.unmute_conversation": "解除此對話的靜音", "status.unpin": "解除置頂", - "suggestions.dismiss": "Dismiss suggestion", - "suggestions.header": "You might be interested in…", + "suggestions.dismiss": "關閉建議", + "suggestions.header": "您可能對這些東西有興趣…", "tabs_bar.federated_timeline": "其他站點", "tabs_bar.home": "主頁", "tabs_bar.local_timeline": "本站", "tabs_bar.notifications": "通知", "tabs_bar.search": "搜尋", - "time_remaining.days": "{number, plural, one {# day} other {# days}} left", - "time_remaining.hours": "{number, plural, one {# hour} other {# hours}} left", - "time_remaining.minutes": "{number, plural, one {# minute} other {# minutes}} left", - "time_remaining.moments": "Moments remaining", - "time_remaining.seconds": "{number, plural, one {# second} other {# seconds}} left", + "time_remaining.days": "剩餘{number, plural, one {# 天數} other {# 天數}}", + "time_remaining.hours": "剩餘{number, plural, one {# 小時} other {# 小時}}", + "time_remaining.minutes": "剩餘{number, plural, one {# 分鐘} other {# 分鐘}}", + "time_remaining.moments": "剩餘時間", + "time_remaining.seconds": "剩餘 {number, plural, one {# 秒} other {# 秒}}", "trends.count_by_accounts": "{count} 位使用者在討論", "ui.beforeunload": "如果離開 Mastodon,你的草稿將會不見。", "upload_area.title": "拖放來上傳", "upload_button.label": "上傳媒體檔案 (JPEG, PNG, GIF, WebM, MP4, MOV)", - "upload_error.limit": "File upload limit exceeded.", - "upload_error.poll": "File upload not allowed with polls.", + "upload_error.limit": "已達到檔案上傳限制。", + "upload_error.poll": "不允許在投票上傳檔案。", "upload_form.description": "為視障人士增加文字說明", - "upload_form.focus": "裁切", + "upload_form.focus": "變更預覽", "upload_form.undo": "刪除", "upload_progress.label": "上傳中...", "video.close": "關閉影片", diff --git a/app/javascript/mastodon/reducers/identity_proofs.js b/app/javascript/mastodon/reducers/identity_proofs.js new file mode 100644 index 000000000..58af0a5fa --- /dev/null +++ b/app/javascript/mastodon/reducers/identity_proofs.js @@ -0,0 +1,25 @@ +import { Map as ImmutableMap, fromJS } from 'immutable'; +import { + IDENTITY_PROOFS_ACCOUNT_FETCH_REQUEST, + IDENTITY_PROOFS_ACCOUNT_FETCH_SUCCESS, + IDENTITY_PROOFS_ACCOUNT_FETCH_FAIL, +} from '../actions/identity_proofs'; + +const initialState = ImmutableMap(); + +export default function identityProofsReducer(state = initialState, action) { + switch(action.type) { + case IDENTITY_PROOFS_ACCOUNT_FETCH_REQUEST: + return state.set('isLoading', true); + case IDENTITY_PROOFS_ACCOUNT_FETCH_FAIL: + return state.set('isLoading', false); + case IDENTITY_PROOFS_ACCOUNT_FETCH_SUCCESS: + return state.update(identity_proofs => identity_proofs.withMutations(map => { + map.set('isLoading', false); + map.set('loaded', true); + map.set(action.accountId, fromJS(action.identity_proofs)); + })); + default: + return state; + } +}; diff --git a/app/javascript/mastodon/reducers/index.js b/app/javascript/mastodon/reducers/index.js index a7e9c4d0f..981ad8e64 100644 --- a/app/javascript/mastodon/reducers/index.js +++ b/app/javascript/mastodon/reducers/index.js @@ -30,6 +30,7 @@ import filters from './filters'; import conversations from './conversations'; import suggestions from './suggestions'; import polls from './polls'; +import identity_proofs from './identity_proofs'; const reducers = { dropdown_menu, @@ -56,6 +57,7 @@ const reducers = { notifications, height_cache, custom_emojis, + identity_proofs, lists, listEditor, listAdder, diff --git a/app/javascript/mastodon/reducers/timelines.js b/app/javascript/mastodon/reducers/timelines.js index 94b570ecd..6a972f967 100644 --- a/app/javascript/mastodon/reducers/timelines.js +++ b/app/javascript/mastodon/reducers/timelines.js @@ -78,14 +78,15 @@ const updateTimeline = (state, timeline, status) => { })); }; -const deleteStatus = (state, id, accountId, references) => { +const deleteStatus = (state, id, accountId, references, exclude_account = null) => { state.keySeq().forEach(timeline => { - state = state.updateIn([timeline, 'items'], list => list.filterNot(item => item === id)); + if (exclude_account === null || (timeline !== `account:${exclude_account}` && !timeline.startsWith(`account:${exclude_account}:`))) + state = state.updateIn([timeline, 'items'], list => list.filterNot(item => item === id)); }); // Remove reblogs of deleted status references.forEach(ref => { - state = deleteStatus(state, ref[0], ref[1], []); + state = deleteStatus(state, ref[0], ref[1], [], exclude_account); }); return state; @@ -104,7 +105,7 @@ const filterTimelines = (state, relationship, statuses) => { } references = statuses.filter(item => item.get('reblog') === status.get('id')).map(item => [item.get('id'), item.get('account')]); - state = deleteStatus(state, status.get('id'), status.get('account'), references); + state = deleteStatus(state, status.get('id'), status.get('account'), references, relationship.id); }); return state; diff --git a/app/javascript/styles/mastodon/admin.scss b/app/javascript/styles/mastodon/admin.scss index 42f53f525..05c7821e4 100644 --- a/app/javascript/styles/mastodon/admin.scss +++ b/app/javascript/styles/mastodon/admin.scss @@ -220,6 +220,11 @@ $content-width: 840px; color: $error-value-color; font-weight: 500; } + + .neutral-hint { + color: $dark-text-color; + font-weight: 500; + } } @media screen and (max-width: $no-columns-breakpoint) { diff --git a/app/javascript/styles/mastodon/components.scss b/app/javascript/styles/mastodon/components.scss index 5b86778bb..2ad93c59d 100644 --- a/app/javascript/styles/mastodon/components.scss +++ b/app/javascript/styles/mastodon/components.scss @@ -1186,57 +1186,6 @@ a .account__avatar { white-space: nowrap; } -.account__header { - flex: 0 0 auto; - background: lighten($ui-base-color, 4%); - text-align: center; - background-size: cover; - background-position: center; - position: relative; - - &.inactive { - opacity: 0.5; - - .account__header__avatar { - filter: grayscale(100%); - } - - .account__header__username { - color: $secondary-text-color; - } - } - - & > div { - background: rgba(lighten($ui-base-color, 4%), 0.9); - padding: 20px 10px; - } - - .account__header__content { - color: $secondary-text-color; - } - - .account__header__display-name { - color: $primary-text-color; - display: inline-block; - width: 100%; - font-size: 20px; - line-height: 27px; - font-weight: 500; - overflow: hidden; - text-overflow: ellipsis; - } - - .account__header__username { - color: $highlight-text-color; - font-size: 14px; - font-weight: 400; - display: block; - margin-bottom: 10px; - overflow: hidden; - text-overflow: ellipsis; - } -} - .account__disclaimer { padding: 10px; border-top: 1px solid lighten($ui-base-color, 8%); @@ -1265,39 +1214,6 @@ a .account__avatar { } } -.account__header__content { - color: $darker-text-color; - font-size: 14px; - font-weight: 400; - overflow: hidden; - word-break: normal; - word-wrap: break-word; - - p { - margin-bottom: 20px; - - &:last-child { - margin-bottom: 0; - } - } - - a { - color: inherit; - text-decoration: underline; - - &:hover { - text-decoration: none; - } - } -} - -.account__header__display-name { - .emojione { - width: 25px; - height: 25px; - } -} - .account__action-bar { border-top: 1px solid lighten($ui-base-color, 8%); border-bottom: 1px solid lighten($ui-base-color, 8%); @@ -1369,15 +1285,6 @@ a .account__avatar { } } -.account__header__avatar { - background-size: 90px 90px; - display: block; - height: 90px; - margin: 0 auto 10px; - overflow: hidden; - width: 90px; -} - .account-authorize { padding: 14px 10px; @@ -3154,42 +3061,22 @@ a.status-card.compact:hover { } } -.account--follows-info { +.relationship-tag { color: $primary-text-color; - position: absolute; - top: 10px; - left: 10px; - opacity: 0.7; - display: inline-block; + margin-bottom: 4px; + display: block; vertical-align: top; - background-color: rgba($base-overlay-background, 0.4); + background-color: $base-overlay-background; text-transform: uppercase; font-size: 11px; font-weight: 500; padding: 4px; border-radius: 4px; -} - -.account--muting-info { - color: $primary-text-color; - position: absolute; - top: 40px; - left: 10px; opacity: 0.7; - display: inline-block; - vertical-align: top; - background-color: rgba($base-overlay-background, 0.4); - text-transform: uppercase; - font-size: 11px; - font-weight: 500; - padding: 4px; - border-radius: 4px; -} -.account--action-button { - position: absolute; - top: 10px; - right: 20px; + &:hover { + opacity: 1; + } } .setting-toggle { @@ -3339,11 +3226,11 @@ a.status-card.compact:hover { box-shadow: 1px 2px 6px rgba($base-shadow-color, 0.2); overflow: hidden; - li { + button { display: block; cursor: pointer; border: 0; - padding: 3px 8px; + padding: 4px 8px; background: transparent; &:hover, @@ -4245,6 +4132,7 @@ a.status-card.compact:hover { .confirmation-modal__action-bar, .mute-modal__action-bar { + .confirmation-modal__secondary-button, .confirmation-modal__cancel-button, .mute-modal__cancel-button { background-color: transparent; @@ -5348,53 +5236,193 @@ noscript { } } -.account__header .roles { - margin-top: 20px; - margin-bottom: 20px; - padding: 0 15px; +.account__header__content { + color: $darker-text-color; + font-size: 14px; + font-weight: 400; + overflow: hidden; + word-break: normal; + word-wrap: break-word; + + p { + margin-bottom: 20px; + + &:last-child { + margin-bottom: 0; + } + } + + a { + color: inherit; + text-decoration: underline; + + &:hover { + text-decoration: none; + } + } } -.account__header .account__header__fields { - font-size: 14px; - line-height: 20px; +.account__header { overflow: hidden; - margin: 20px -10px -20px; - border-bottom: 0; - border-top: 0; - dl { - border-top: 1px solid lighten($ui-base-color, 4%); - border-bottom: 0; - display: flex; + &.inactive { + opacity: 0.5; + + .account__header__image, + .account__avatar { + filter: grayscale(100%); + } } - dt, - dd { - box-sizing: border-box; - padding: 14px 5px; - text-align: center; - max-height: 48px; - overflow: hidden; - white-space: nowrap; - text-overflow: ellipsis; + &__info { + position: absolute; + top: 10px; + left: 10px; } - dt { - color: $darker-text-color; + &__image { + overflow: hidden; + height: 145px; + position: relative; background: darken($ui-base-color, 4%); - width: 120px; - flex: 0 0 auto; - font-weight: 500; + + img { + object-fit: cover; + display: block; + width: 100%; + height: 100%; + margin: 0; + } } - dd { - flex: 1 1 auto; - color: $primary-text-color; - background: $ui-base-color; + &__bar { + position: relative; + background: lighten($ui-base-color, 4%); + padding: 5px; + border-bottom: 1px solid lighten($ui-base-color, 12%); + + .avatar { + display: block; + flex: 0 0 auto; + width: 94px; + margin-left: -2px; - &.verified { - border: 1px solid rgba($valid-value-color, 0.5); - background: rgba($valid-value-color, 0.25); + .account__avatar { + background: darken($ui-base-color, 8%); + border: 2px solid lighten($ui-base-color, 4%); + } + } + } + + &__tabs { + display: flex; + align-items: flex-start; + padding: 7px 5px; + margin-top: -55px; + + &__buttons { + display: flex; + align-items: center; + padding-top: 55px; + overflow: hidden; + + .icon-button { + border: 1px solid lighten($ui-base-color, 12%); + border-radius: 4px; + box-sizing: content-box; + padding: 2px; + } + + .button { + margin: 0 8px; + } + } + + &__name { + padding: 5px; + + .account-role { + vertical-align: top; + } + + .emojione { + width: 22px; + height: 22px; + } + + h1 { + font-size: 16px; + line-height: 24px; + color: $primary-text-color; + font-weight: 500; + overflow: hidden; + white-space: nowrap; + text-overflow: ellipsis; + + small { + display: block; + font-size: 14px; + color: $darker-text-color; + font-weight: 400; + overflow: hidden; + text-overflow: ellipsis; + } + } + } + + .spacer { + flex: 1 1 auto; + } + } + + &__bio { + overflow: hidden; + margin: 0 -5px; + + .account__header__content { + padding: 20px 15px; + padding-bottom: 5px; + color: $primary-text-color; + } + + .account__header__fields { + margin: 0; + border-top: 1px solid lighten($ui-base-color, 12%); + + a { + color: lighten($ui-highlight-color, 8%); + } + + dl:first-child .verified { + border-radius: 0 4px 0 0; + } + + .verified a { + color: $valid-value-color; + } + } + } + + &__extra { + margin-top: 4px; + + &__links { + font-size: 14px; + color: $darker-text-color; + + a { + display: inline-block; + color: $darker-text-color; + text-decoration: none; + padding: 10px; + padding-top: 20px; + font-weight: 500; + + strong { + font-weight: 700; + color: $primary-text-color; + } + } } } } diff --git a/app/javascript/styles/mastodon/containers.scss b/app/javascript/styles/mastodon/containers.scss index a98fa52c4..368c2304b 100644 --- a/app/javascript/styles/mastodon/containers.scss +++ b/app/javascript/styles/mastodon/containers.scss @@ -10,12 +10,10 @@ } .logo-container { - margin: 100px auto; - margin-bottom: 50px; + margin: 100px auto 50px; - @media screen and (max-width: 400px) { - margin: 30px auto; - margin-bottom: 20px; + @media screen and (max-width: 500px) { + margin: 40px auto 0; } h1 { @@ -677,6 +675,7 @@ color: $darker-text-color; text-decoration: none; padding: 15px; + font-weight: 500; strong { font-weight: 700; diff --git a/app/javascript/styles/mastodon/emoji_picker.scss b/app/javascript/styles/mastodon/emoji_picker.scss index 94578ffee..e49084b5f 100644 --- a/app/javascript/styles/mastodon/emoji_picker.scss +++ b/app/javascript/styles/mastodon/emoji_picker.scss @@ -1,5 +1,3 @@ -@import '~emoji-mart/css/emoji-mart.css'; - .emoji-mart { &, * { @@ -53,14 +51,6 @@ &:hover { color: darken($lighter-text-color, 4%); - - svg { - fill: darken($lighter-text-color, 4%); - } - } - - svg { - fill: $lighter-text-color; } } @@ -69,19 +59,11 @@ &:hover { color: darken($highlight-text-color, 4%); - - svg { - fill: darken($highlight-text-color, 4%); - } } .emoji-mart-anchor-bar { bottom: -1px; } - - svg { - fill: $highlight-text-color; - } } .emoji-mart-anchor-bar { @@ -101,6 +83,7 @@ } svg { + fill: currentColor; max-height: 18px; } } @@ -120,14 +103,15 @@ } .emoji-mart-search { - margin: 10px 40px 10px 5px; + padding: 10px; + padding-right: 45px; background: $simple-background-color; input { font-size: 14px; font-weight: 400; padding: 7px 9px; - font-family: $font-sans-serif; + font-family: inherit; display: block; width: 100%; background: rgba($ui-secondary-color, 0.3); @@ -182,7 +166,6 @@ font-weight: 500; padding: 5px 6px; background: $simple-background-color; - font-family: $font-sans-serif; } } diff --git a/app/javascript/styles/mastodon/forms.scss b/app/javascript/styles/mastodon/forms.scss index 9ef45e425..91888d305 100644 --- a/app/javascript/styles/mastodon/forms.scss +++ b/app/javascript/styles/mastodon/forms.scss @@ -475,6 +475,42 @@ code { } } } + + &__overlay-area { + position: relative; + + &__overlay { + position: absolute; + top: 0; + left: 0; + width: 100%; + height: 100%; + display: flex; + justify-content: center; + align-items: center; + background: rgba($ui-base-color, 0.65); + backdrop-filter: blur(2px); + border-radius: 4px; + + &__content { + text-align: center; + + &.rich-formatting { + &, + p { + color: $primary-text-color; + } + } + } + } + } +} + +.block-icon { + display: block; + margin: 0 auto; + margin-bottom: 10px; + font-size: 24px; } .flash-message { @@ -818,13 +854,19 @@ code { flex: 1; flex-direction: column; flex-shrink: 1; + max-width: 50%; &-sep { + align-self: center; flex-grow: 0; overflow: visible; position: relative; z-index: 1; } + + p { + word-break: break-word; + } } .account__avatar { @@ -846,12 +888,13 @@ code { height: 100%; left: 50%; position: absolute; + top: 0; width: 1px; } } &__row { - align-items: center; + align-items: flex-start; display: flex; flex-direction: row; } diff --git a/app/javascript/styles/mastodon/stream_entries.scss b/app/javascript/styles/mastodon/stream_entries.scss index d8bd30377..a739c446d 100644 --- a/app/javascript/styles/mastodon/stream_entries.scss +++ b/app/javascript/styles/mastodon/stream_entries.scss @@ -99,9 +99,9 @@ } } - &:active, - &:focus, - &:hover { + &:active:not(:disabled), + &:focus:not(:disabled), + &:hover:not(:disabled) { background: lighten($ui-highlight-color, 10%); svg path:last-child { diff --git a/app/javascript/styles/mastodon/widgets.scss b/app/javascript/styles/mastodon/widgets.scss index 645192ea4..307e509d5 100644 --- a/app/javascript/styles/mastodon/widgets.scss +++ b/app/javascript/styles/mastodon/widgets.scss @@ -352,6 +352,7 @@ border-radius: 50%; position: relative; margin-left: -10px; + background: darken($ui-base-color, 8%); border: 2px solid $ui-base-color; &:nth-child(1) { diff --git a/app/lib/activitypub/activity/announce.rb b/app/lib/activitypub/activity/announce.rb index 9f8ffd9fb..1aa6ee9ec 100644 --- a/app/lib/activitypub/activity/announce.rb +++ b/app/lib/activitypub/activity/announce.rb @@ -47,6 +47,10 @@ class ActivityPub::Activity::Announce < ActivityPub::Activity followed_by_local_accounts? || requested_through_relay? || reblog_of_local_status? end + def requested_through_relay? + super || Relay.find_by(inbox_url: @account.inbox_url)&.enabled? + end + def reblog_of_local_status? status_from_uri(object_uri)&.account&.local? end diff --git a/app/lib/activitypub/activity/create.rb b/app/lib/activitypub/activity/create.rb index 8fe7b9138..dabdcbcf7 100644 --- a/app/lib/activitypub/activity/create.rb +++ b/app/lib/activitypub/activity/create.rb @@ -68,7 +68,7 @@ class ActivityPub::Activity::Create < ActivityPub::Activity thread: replied_to_status, conversation: conversation_from_uri(@object['conversation']), media_attachment_ids: process_attachments.take(4).map(&:id), - owned_poll: process_poll, + poll: process_poll, } end end @@ -240,11 +240,11 @@ class ActivityPub::Activity::Create < ActivityPub::Activity end def poll_vote? - return false if replied_to_status.nil? || replied_to_status.poll.nil? || !replied_to_status.local? || !replied_to_status.poll.options.include?(@object['name']) + return false if replied_to_status.nil? || replied_to_status.preloadable_poll.nil? || !replied_to_status.local? || !replied_to_status.preloadable_poll.options.include?(@object['name']) - unless replied_to_status.poll.expired? - replied_to_status.poll.votes.create!(account: @account, choice: replied_to_status.poll.options.index(@object['name']), uri: @object['id']) - ActivityPub::DistributePollUpdateWorker.perform_in(3.minutes, replied_to_status.id) unless replied_to_status.poll.hide_totals? + unless replied_to_status.preloadable_poll.expired? + replied_to_status.preloadable_poll.votes.create!(account: @account, choice: replied_to_status.preloadable_poll.options.index(@object['name']), uri: @object['id']) + ActivityPub::DistributePollUpdateWorker.perform_in(3.minutes, replied_to_status.id) unless replied_to_status.preloadable_poll.hide_totals? end true diff --git a/app/lib/activitypub/activity/update.rb b/app/lib/activitypub/activity/update.rb index bc9a63f98..70035325b 100644 --- a/app/lib/activitypub/activity/update.rb +++ b/app/lib/activitypub/activity/update.rb @@ -23,8 +23,8 @@ class ActivityPub::Activity::Update < ActivityPub::Activity return reject_payload! if invalid_origin?(@object['id']) status = Status.find_by(uri: object_uri, account_id: @account.id) - return if status.nil? || status.poll.nil? + return if status.nil? || status.preloadable_poll.nil? - ActivityPub::ProcessPollService.new.call(status.poll, @object) + ActivityPub::ProcessPollService.new.call(status.preloadable_poll, @object) end end diff --git a/app/lib/activitypub/adapter.rb b/app/lib/activitypub/adapter.rb index 99f4d9305..94eb2899c 100644 --- a/app/lib/activitypub/adapter.rb +++ b/app/lib/activitypub/adapter.rb @@ -1,30 +1,24 @@ # frozen_string_literal: true class ActivityPub::Adapter < ActiveModelSerializers::Adapter::Base - CONTEXT = { - '@context': [ - 'https://www.w3.org/ns/activitystreams', - 'https://w3id.org/security/v1', - - { - 'manuallyApprovesFollowers' => 'as:manuallyApprovesFollowers', - 'sensitive' => 'as:sensitive', - 'movedTo' => { '@id' => 'as:movedTo', '@type' => '@id' }, - 'alsoKnownAs' => { '@id' => 'as:alsoKnownAs', '@type' => '@id' }, - 'Hashtag' => 'as:Hashtag', - 'ostatus' => 'http://ostatus.org#', - 'atomUri' => 'ostatus:atomUri', - 'inReplyToAtomUri' => 'ostatus:inReplyToAtomUri', - 'conversation' => 'ostatus:conversation', - 'toot' => 'http://joinmastodon.org/ns#', - 'Emoji' => 'toot:Emoji', - 'focalPoint' => { '@container' => '@list', '@id' => 'toot:focalPoint' }, - 'featured' => { '@id' => 'toot:featured', '@type' => '@id' }, - 'schema' => 'http://schema.org#', - 'PropertyValue' => 'schema:PropertyValue', - 'value' => 'schema:value', - }, - ], + NAMED_CONTEXT_MAP = { + activitystreams: 'https://www.w3.org/ns/activitystreams', + security: 'https://w3id.org/security/v1', + }.freeze + + CONTEXT_EXTENSION_MAP = { + manually_approves_followers: { 'manuallyApprovesFollowers' => 'as:manuallyApprovesFollowers' }, + sensitive: { 'sensitive' => 'as:sensitive' }, + hashtag: { 'Hashtag' => 'as:Hashtag' }, + moved_to: { 'movedTo' => { '@id' => 'as:movedTo', '@type' => '@id' } }, + also_known_as: { 'alsoKnownAs' => { '@id' => 'as:alsoKnownAs', '@type' => '@id' } }, + emoji: { 'toot' => 'http://joinmastodon.org/ns#', 'Emoji' => 'toot:Emoji' }, + featured: { 'toot' => 'http://joinmastodon.org/ns#', 'featured' => { '@id' => 'toot:featured', '@type' => '@id' } }, + property_value: { 'schema' => 'http://schema.org#', 'PropertyValue' => 'schema:PropertyValue', 'value' => 'schema:value' }, + atom_uri: { 'ostatus' => 'http://ostatus.org#', 'atomUri' => 'ostatus:atomUri' }, + conversation: { 'ostatus' => 'http://ostatus.org#', 'inReplyToAtomUri' => 'ostatus:inReplyToAtomUri', 'conversation' => 'ostatus:conversation' }, + focal_point: { 'toot' => 'http://joinmastodon.org/ns#', 'focalPoint' => { '@container' => '@list', '@id' => 'toot:focalPoint' } }, + identity_proof: { 'toot' => 'http://joinmastodon.org/ns#', 'IdentityProof' => 'toot:IdentityProof' }, }.freeze def self.default_key_transform @@ -36,8 +30,36 @@ class ActivityPub::Adapter < ActiveModelSerializers::Adapter::Base end def serializable_hash(options = nil) - options = serialization_options(options) - serialized_hash = ActiveModelSerializers::Adapter::Attributes.new(serializer, instance_options).serializable_hash(options) - CONTEXT.merge(self.class.transform_key_casing!(serialized_hash, instance_options)) + options = serialization_options(options) + serialized_hash = serializer.serializable_hash(options) + serialized_hash = self.class.transform_key_casing!(serialized_hash, instance_options) + + { '@context' => serialized_context }.merge(serialized_hash) + end + + private + + def serialized_context + context_array = [] + + serializer_options = serializer.send(:instance_options) || {} + named_contexts = [:activitystreams] + serializer._named_contexts.keys + serializer_options.fetch(:named_contexts, {}).keys + context_extensions = serializer._context_extensions.keys + serializer_options.fetch(:context_extensions, {}).keys + + named_contexts.each do |key| + context_array << NAMED_CONTEXT_MAP[key] + end + + extensions = context_extensions.each_with_object({}) do |key, h| + h.merge!(CONTEXT_EXTENSION_MAP[key]) + end + + context_array << extensions unless extensions.empty? + + if context_array.size == 1 + context_array.first + else + context_array + end end end diff --git a/app/lib/activitypub/serializer.rb b/app/lib/activitypub/serializer.rb new file mode 100644 index 000000000..07bd8c494 --- /dev/null +++ b/app/lib/activitypub/serializer.rb @@ -0,0 +1,30 @@ +# frozen_string_literal: true + +class ActivityPub::Serializer < ActiveModel::Serializer + with_options instance_writer: false, instance_reader: true do |serializer| + serializer.class_attribute :_named_contexts + serializer.class_attribute :_context_extensions + + self._named_contexts ||= {} + self._context_extensions ||= {} + end + + def self.inherited(base) + super + + base._named_contexts = _named_contexts.dup + base._context_extensions = _context_extensions.dup + end + + def self.context(*named_contexts) + named_contexts.each do |context| + _named_contexts[context] = true + end + end + + def self.context_extensions(*extension_names) + extension_names.each do |extension_name| + _context_extensions[extension_name] = true + end + end +end diff --git a/app/lib/formatter.rb b/app/lib/formatter.rb index aadf03b2a..59dfc9004 100644 --- a/app/lib/formatter.rb +++ b/app/lib/formatter.rb @@ -19,8 +19,8 @@ class Formatter raw_content = status.text - if options[:inline_poll_options] && status.poll - raw_content = raw_content + "\n\n" + status.poll.options.map { |title| "[ ] #{title}" }.join("\n") + if options[:inline_poll_options] && status.preloadable_poll + raw_content = raw_content + "\n\n" + status.preloadable_poll.options.map { |title| "[ ] #{title}" }.join("\n") end return '' if raw_content.blank? diff --git a/app/lib/language_detector.rb b/app/lib/language_detector.rb index 70a9084d1..1e90af42d 100644 --- a/app/lib/language_detector.rb +++ b/app/lib/language_detector.rb @@ -3,7 +3,7 @@ class LanguageDetector include Singleton - CHARACTER_THRESHOLD = 140 + WORDS_THRESHOLD = 4 RELIABLE_CHARACTERS_RE = /[\p{Hebrew}\p{Arabic}\p{Syriac}\p{Thaana}\p{Nko}\p{Han}\p{Katakana}\p{Hiragana}\p{Hangul}]+/m def initialize @@ -37,7 +37,7 @@ class LanguageDetector end def sufficient_text_length?(text) - text.size >= CHARACTER_THRESHOLD + text.split(/\s+/).size >= WORDS_THRESHOLD end def language_specific_character_set?(text) diff --git a/app/lib/proof_provider/keybase.rb b/app/lib/proof_provider/keybase.rb index 96322a265..628972e9d 100644 --- a/app/lib/proof_provider/keybase.rb +++ b/app/lib/proof_provider/keybase.rb @@ -1,7 +1,8 @@ # frozen_string_literal: true class ProofProvider::Keybase - BASE_URL = 'https://keybase.io' + BASE_URL = ENV.fetch('KEYBASE_BASE_URL', 'https://keybase.io') + DOMAIN = ENV.fetch('KEYBASE_DOMAIN', Rails.configuration.x.local_domain) class Error < StandardError; end @@ -27,7 +28,8 @@ class ProofProvider::Keybase return end - return if @proof.provider_username.blank? + # Do not perform synchronous validation for remote accounts + return if @proof.provider_username.blank? || !@proof.account.local? if verifier.valid? @proof.verified = true diff --git a/app/lib/proof_provider/keybase/config_serializer.rb b/app/lib/proof_provider/keybase/config_serializer.rb index 474ea74e2..5241d201f 100644 --- a/app/lib/proof_provider/keybase/config_serializer.rb +++ b/app/lib/proof_provider/keybase/config_serializer.rb @@ -2,6 +2,7 @@ class ProofProvider::Keybase::ConfigSerializer < ActiveModel::Serializer include RoutingHelper + include ActionView::Helpers::TextHelper attributes :version, :domain, :display_name, :username, :brand_color, :logo, :description, :prefill_url, @@ -13,7 +14,7 @@ class ProofProvider::Keybase::ConfigSerializer < ActiveModel::Serializer end def domain - Rails.configuration.x.local_domain + ProofProvider::Keybase::DOMAIN end def display_name @@ -29,11 +30,11 @@ class ProofProvider::Keybase::ConfigSerializer < ActiveModel::Serializer end def description - Setting.site_short_description.presence || Setting.site_description.presence || I18n.t('about.about_mastodon_html') + strip_tags(Setting.site_short_description.presence || I18n.t('about.about_mastodon_html')) end def username - { min: 1, max: 30, re: Account::USERNAME_RE.inspect } + { min: 1, max: 30, re: '[a-z0-9_]+([a-z0-9_\.-]+[a-z0-9_]+)?' } end def prefill_url @@ -65,6 +66,6 @@ class ProofProvider::Keybase::ConfigSerializer < ActiveModel::Serializer end def contact - [Setting.site_contact_email.presence].compact + [Setting.site_contact_email.presence || 'unknown'].compact end end diff --git a/app/lib/proof_provider/keybase/verifier.rb b/app/lib/proof_provider/keybase/verifier.rb index 86f249dd7..ab1422323 100644 --- a/app/lib/proof_provider/keybase/verifier.rb +++ b/app/lib/proof_provider/keybase/verifier.rb @@ -49,14 +49,10 @@ class ProofProvider::Keybase::Verifier def query_params { - domain: domain, + domain: ProofProvider::Keybase::DOMAIN, kb_username: @provider_username, username: @local_username, sig_hash: @token, } end - - def domain - Rails.configuration.x.local_domain - end end diff --git a/app/models/account.rb b/app/models/account.rb index 6b539f004..a82251d2e 100644 --- a/app/models/account.rb +++ b/app/models/account.rb @@ -98,7 +98,7 @@ class Account < ApplicationRecord scope :matches_display_name, ->(value) { where(arel_table[:display_name].matches("#{value}%")) } scope :matches_domain, ->(value) { where(arel_table[:domain].matches("%#{value}%")) } scope :searchable, -> { without_suspended.where(moved_to_account_id: nil) } - scope :discoverable, -> { searchable.without_silenced.where(discoverable: true).joins(:account_stat).where(AccountStat.arel_table[:followers_count].gteq(MIN_FOLLOWERS_DISCOVERY)).by_recent_status } + scope :discoverable, -> { searchable.without_silenced.where(discoverable: true).joins(:account_stat).where(AccountStat.arel_table[:followers_count].gteq(MIN_FOLLOWERS_DISCOVERY)) } scope :tagged_with, ->(tag) { joins(:accounts_tags).where(accounts_tags: { tag_id: tag }) } scope :by_recent_status, -> { order(Arel.sql('(case when account_stats.last_status_at is null then 1 else 0 end) asc, account_stats.last_status_at desc')) } scope :popular, -> { order('account_stats.followers_count desc') } diff --git a/app/models/account_identity_proof.rb b/app/models/account_identity_proof.rb index e7a3f97e5..1ac234735 100644 --- a/app/models/account_identity_proof.rb +++ b/app/models/account_identity_proof.rb @@ -26,7 +26,7 @@ class AccountIdentityProof < ApplicationRecord scope :active, -> { where(verified: true, live: true) } - after_create_commit :queue_worker + after_commit :queue_worker, if: :saved_change_to_token? delegate :refresh!, :on_success_path, :badge, to: :provider_instance diff --git a/app/models/follow_request.rb b/app/models/follow_request.rb index c5451a050..96ac7eaa5 100644 --- a/app/models/follow_request.rb +++ b/app/models/follow_request.rb @@ -26,7 +26,7 @@ class FollowRequest < ApplicationRecord def authorize! account.follow!(target_account, reblogs: show_reblogs, uri: uri) - MergeWorker.perform_async(target_account.id, account.id) + MergeWorker.perform_async(target_account.id, account.id) if account.local? destroy! end diff --git a/app/models/form/admin_settings.rb b/app/models/form/admin_settings.rb index 929c65793..0fcbd0605 100644 --- a/app/models/form/admin_settings.rb +++ b/app/models/form/admin_settings.rb @@ -3,57 +3,108 @@ class Form::AdminSettings include ActiveModel::Model - delegate( - :site_contact_username, - :site_contact_username=, - :site_contact_email, - :site_contact_email=, - :site_title, - :site_title=, - :site_short_description, - :site_short_description=, - :site_description, - :site_description=, - :site_extended_description, - :site_extended_description=, - :site_terms, - :site_terms=, - :registrations_mode, - :registrations_mode=, - :closed_registrations_message, - :closed_registrations_message=, - :open_deletion, - :open_deletion=, - :timeline_preview, - :timeline_preview=, - :show_staff_badge, - :show_staff_badge=, - :bootstrap_timeline_accounts, - :bootstrap_timeline_accounts=, - :hide_followers_count, - :hide_followers_count=, - :flavour, - :flavour=, - :skin, - :skin=, - :min_invite_role, - :min_invite_role=, - :activity_api_enabled, - :activity_api_enabled=, - :peers_api_enabled, - :peers_api_enabled=, - :show_known_fediverse_at_about_page, - :show_known_fediverse_at_about_page=, - :preview_sensitive_media, - :preview_sensitive_media=, - :custom_css, - :custom_css=, - :profile_directory, - :profile_directory=, - to: Setting - ) + KEYS = %i( + site_contact_username + site_contact_email + site_title + site_short_description + site_description + site_extended_description + site_terms + registrations_mode + closed_registrations_message + open_deletion + timeline_preview + show_staff_badge + bootstrap_timeline_accounts + flavour + skin + min_invite_role + activity_api_enabled + peers_api_enabled + show_known_fediverse_at_about_page + preview_sensitive_media + custom_css + profile_directory + hide_followers_count + flavour_and_skin + ).freeze + + BOOLEAN_KEYS = %i( + open_deletion + timeline_preview + show_staff_badge + activity_api_enabled + peers_api_enabled + show_known_fediverse_at_about_page + preview_sensitive_media + profile_directory + hide_followers_count + ).freeze + + UPLOAD_KEYS = %i( + thumbnail + hero + mascot + ).freeze + + PSEUDO_KEYS = %i( + flavour_and_skin + ).freeze + + attr_accessor(*KEYS) + + validates :site_short_description, :site_description, :site_extended_description, :site_terms, :closed_registrations_message, html: true + validates :registrations_mode, inclusion: { in: %w(open approved none) } + validates :min_invite_role, inclusion: { in: %w(disabled user moderator admin) } + validates :site_contact_email, :site_contact_username, presence: true + validates :site_contact_username, existing_username: true + validates :bootstrap_timeline_accounts, existing_username: { multiple: true } + + def initialize(_attributes = {}) + super + initialize_attributes + end + + def save + return false unless valid? + + KEYS.each do |key| + next if PSEUDO_KEYS.include?(key) + value = instance_variable_get("@#{key}") + + if UPLOAD_KEYS.include?(key) + upload = SiteUpload.where(var: key).first_or_initialize(var: key) + upload.update(file: value) + else + setting = Setting.where(var: key).first_or_initialize(var: key) + setting.update(value: typecast_value(key, value)) + end + end + end def flavour_and_skin "#{Setting.flavour}/#{Setting.skin}" end + + def flavour_and_skin=(value) + @flavour, @skin = value.split('/', 2) + end + + private + + def initialize_attributes + KEYS.each do |key| + next if PSEUDO_KEYS.include?(key) + instance_variable_set("@#{key}", Setting.public_send(key)) if instance_variable_get("@#{key}").nil? + end + end + + def typecast_value(key, value) + if BOOLEAN_KEYS.include?(key) + value == '1' + else + value + end + end end diff --git a/app/models/instance.rb b/app/models/instance.rb index 7448d465c..7bf000d40 100644 --- a/app/models/instance.rb +++ b/app/models/instance.rb @@ -7,7 +7,7 @@ class Instance def initialize(resource) @domain = resource.domain - @accounts_count = resource.accounts_count + @accounts_count = resource.is_a?(DomainBlock) ? nil : resource.accounts_count @domain_block = resource.is_a?(DomainBlock) ? resource : DomainBlock.find_by(domain: domain) end @@ -15,6 +15,10 @@ class Instance Rails.cache.fetch("#{cache_key}/sample_accounts", expires_in: 12.hours) { Account.where(domain: domain).searchable.joins(:account_stat).popular.limit(3) } end + def cached_accounts_count + @accounts_count || Rails.cache.fetch("#{cache_key}/count", expires_in: 12.hours) { Account.where(domain: domain).count } + end + def to_param domain end diff --git a/app/models/notification.rb b/app/models/notification.rb index 982136c05..300269e24 100644 --- a/app/models/notification.rb +++ b/app/models/notification.rb @@ -25,7 +25,7 @@ class Notification < ApplicationRecord poll: 'Poll', }.freeze - STATUS_INCLUDES = [:account, :application, :media_attachments, :tags, active_mentions: :account, reblog: [:account, :application, :media_attachments, :tags, active_mentions: :account]].freeze + STATUS_INCLUDES = [:account, :application, :preloadable_poll, :media_attachments, :tags, active_mentions: :account, reblog: [:account, :application, :preloadable_poll, :media_attachments, :tags, active_mentions: :account]].freeze belongs_to :account, optional: true belongs_to :from_account, class_name: 'Account', optional: true diff --git a/app/models/status.rb b/app/models/status.rb index c049401e8..e7fa0220b 100644 --- a/app/models/status.rb +++ b/app/models/status.rb @@ -47,7 +47,7 @@ class Status < ApplicationRecord belongs_to :account, inverse_of: :statuses belongs_to :in_reply_to_account, foreign_key: 'in_reply_to_account_id', class_name: 'Account', optional: true belongs_to :conversation, optional: true - belongs_to :poll, optional: true + belongs_to :preloadable_poll, class_name: 'Poll', foreign_key: 'poll_id', optional: true belongs_to :thread, foreign_key: 'in_reply_to_id', class_name: 'Status', inverse_of: :replies, optional: true belongs_to :reblog, foreign_key: 'reblog_of_id', class_name: 'Status', inverse_of: :reblogs, optional: true @@ -66,7 +66,7 @@ class Status < ApplicationRecord has_one :notification, as: :activity, dependent: :destroy has_one :stream_entry, as: :activity, inverse_of: :status has_one :status_stat, inverse_of: :status - has_one :owned_poll, class_name: 'Poll', inverse_of: :status, dependent: :destroy + has_one :poll, inverse_of: :status, dependent: :destroy validates :uri, uniqueness: true, presence: true, unless: :local? validates :text, presence: true, unless: -> { with_media? || reblog? } @@ -75,7 +75,7 @@ class Status < ApplicationRecord validates :reblog, uniqueness: { scope: :account }, if: :reblog? validates :visibility, exclusion: { in: %w(direct limited) }, if: :reblog? - accepts_nested_attributes_for :owned_poll + accepts_nested_attributes_for :poll default_scope { recent } @@ -112,7 +112,7 @@ class Status < ApplicationRecord :tags, :preview_cards, :stream_entry, - :poll, + :preloadable_poll, account: :account_stat, active_mentions: { account: :account_stat }, reblog: [ @@ -123,7 +123,7 @@ class Status < ApplicationRecord :media_attachments, :conversation, :status_stat, - :poll, + :preloadable_poll, account: :account_stat, active_mentions: { account: :account_stat }, ], @@ -219,10 +219,11 @@ class Status < ApplicationRecord def emojis return @emojis if defined?(@emojis) - fields = [spoiler_text, text] - fields += owned_poll.options unless owned_poll.nil? + + fields = [spoiler_text, text] + fields += preloadable_poll.options unless preloadable_poll.nil? + @emojis = CustomEmoji.from_text(fields.join(' '), account.domain) - @emojis end def mark_for_mass_destruction! @@ -473,7 +474,7 @@ class Status < ApplicationRecord end def set_poll_id - update_column(:poll_id, owned_poll.id) unless owned_poll.nil? + update_column(:poll_id, poll.id) unless poll.nil? end def set_visibility diff --git a/app/models/user.rb b/app/models/user.rb index 47657a670..66c1543ff 100644 --- a/app/models/user.rb +++ b/app/models/user.rb @@ -124,7 +124,8 @@ class User < ApplicationRecord end def confirm - new_user = !confirmed? + new_user = !confirmed? + self.approved = true if open_registrations? super @@ -136,7 +137,8 @@ class User < ApplicationRecord end def confirm! - new_user = !confirmed? + new_user = !confirmed? + self.approved = true if open_registrations? skip_confirmation! save! @@ -264,7 +266,11 @@ class User < ApplicationRecord private def set_approved - self.approved = Setting.registrations_mode == 'open' || invited? + self.approved = open_registrations? || invited? + end + + def open_registrations? + Setting.registrations_mode == 'open' end def sanitize_languages diff --git a/app/presenters/account_relationships_presenter.rb b/app/presenters/account_relationships_presenter.rb index e4aaa65f6..b05673a3d 100644 --- a/app/presenters/account_relationships_presenter.rb +++ b/app/presenters/account_relationships_presenter.rb @@ -1,7 +1,7 @@ # frozen_string_literal: true class AccountRelationshipsPresenter - attr_reader :following, :followed_by, :blocking, + attr_reader :following, :followed_by, :blocking, :blocked_by, :muting, :requested, :domain_blocking, :endorsed @@ -12,6 +12,7 @@ class AccountRelationshipsPresenter @following = cached[:following].merge(Account.following_map(@uncached_account_ids, @current_account_id)) @followed_by = cached[:followed_by].merge(Account.followed_by_map(@uncached_account_ids, @current_account_id)) @blocking = cached[:blocking].merge(Account.blocking_map(@uncached_account_ids, @current_account_id)) + @blocked_by = cached[:blocked_by].merge(Account.blocked_by_map(@uncached_account_ids, @current_account_id)) @muting = cached[:muting].merge(Account.muting_map(@uncached_account_ids, @current_account_id)) @requested = cached[:requested].merge(Account.requested_map(@uncached_account_ids, @current_account_id)) @domain_blocking = cached[:domain_blocking].merge(Account.domain_blocking_map(@uncached_account_ids, @current_account_id)) @@ -22,6 +23,7 @@ class AccountRelationshipsPresenter @following.merge!(options[:following_map] || {}) @followed_by.merge!(options[:followed_by_map] || {}) @blocking.merge!(options[:blocking_map] || {}) + @blocked_by.merge!(options[:blocked_by_map] || {}) @muting.merge!(options[:muting_map] || {}) @requested.merge!(options[:requested_map] || {}) @domain_blocking.merge!(options[:domain_blocking_map] || {}) @@ -37,6 +39,7 @@ class AccountRelationshipsPresenter following: {}, followed_by: {}, blocking: {}, + blocked_by: {}, muting: {}, requested: {}, domain_blocking: {}, @@ -64,6 +67,7 @@ class AccountRelationshipsPresenter following: { account_id => following[account_id] }, followed_by: { account_id => followed_by[account_id] }, blocking: { account_id => blocking[account_id] }, + blocked_by: { account_id => blocked_by[account_id] }, muting: { account_id => muting[account_id] }, requested: { account_id => requested[account_id] }, domain_blocking: { account_id => domain_blocking[account_id] }, diff --git a/app/presenters/instance_presenter.rb b/app/presenters/instance_presenter.rb index 94a2c1692..d234516e0 100644 --- a/app/presenters/instance_presenter.rb +++ b/app/presenters/instance_presenter.rb @@ -8,6 +8,7 @@ class InstancePresenter :site_description, :site_extended_description, :site_terms, + :closed_registrations_message, to: Setting ) diff --git a/app/serializers/activitypub/accept_follow_serializer.rb b/app/serializers/activitypub/accept_follow_serializer.rb index 3e23591a5..1c1c6ab73 100644 --- a/app/serializers/activitypub/accept_follow_serializer.rb +++ b/app/serializers/activitypub/accept_follow_serializer.rb @@ -1,6 +1,6 @@ # frozen_string_literal: true -class ActivityPub::AcceptFollowSerializer < ActiveModel::Serializer +class ActivityPub::AcceptFollowSerializer < ActivityPub::Serializer attributes :id, :type, :actor has_one :object, serializer: ActivityPub::FollowSerializer diff --git a/app/serializers/activitypub/activity_serializer.rb b/app/serializers/activitypub/activity_serializer.rb index c001e28aa..c06d5c87c 100644 --- a/app/serializers/activitypub/activity_serializer.rb +++ b/app/serializers/activitypub/activity_serializer.rb @@ -1,6 +1,6 @@ # frozen_string_literal: true -class ActivityPub::ActivitySerializer < ActiveModel::Serializer +class ActivityPub::ActivitySerializer < ActivityPub::Serializer attributes :id, :type, :actor, :published, :to, :cc has_one :proper, key: :object, serializer: ActivityPub::NoteSerializer, if: :serialize_object? diff --git a/app/serializers/activitypub/actor_serializer.rb b/app/serializers/activitypub/actor_serializer.rb index 6746c1782..0644219fb 100644 --- a/app/serializers/activitypub/actor_serializer.rb +++ b/app/serializers/activitypub/actor_serializer.rb @@ -1,8 +1,13 @@ # frozen_string_literal: true -class ActivityPub::ActorSerializer < ActiveModel::Serializer +class ActivityPub::ActorSerializer < ActivityPub::Serializer include RoutingHelper + context :security + + context_extensions :manually_approves_followers, :featured, :also_known_as, + :moved_to, :property_value, :hashtag, :emoji, :identity_proof + attributes :id, :type, :following, :followers, :inbox, :outbox, :featured, :preferred_username, :name, :summary, @@ -16,7 +21,7 @@ class ActivityPub::ActorSerializer < ActiveModel::Serializer attribute :moved_to, if: :moved? attribute :also_known_as, if: :also_known_as? - class EndpointsSerializer < ActiveModel::Serializer + class EndpointsSerializer < ActivityPub::Serializer include RoutingHelper attributes :shared_inbox @@ -110,7 +115,7 @@ class ActivityPub::ActorSerializer < ActiveModel::Serializer end def virtual_attachments - object.fields + object.fields + object.identity_proofs.active end def moved_to @@ -124,7 +129,7 @@ class ActivityPub::ActorSerializer < ActiveModel::Serializer class CustomEmojiSerializer < ActivityPub::EmojiSerializer end - class TagSerializer < ActiveModel::Serializer + class TagSerializer < ActivityPub::Serializer include RoutingHelper attributes :type, :href, :name @@ -142,7 +147,7 @@ class ActivityPub::ActorSerializer < ActiveModel::Serializer end end - class Account::FieldSerializer < ActiveModel::Serializer + class Account::FieldSerializer < ActivityPub::Serializer attributes :type, :name, :value def type @@ -153,4 +158,24 @@ class ActivityPub::ActorSerializer < ActiveModel::Serializer Formatter.instance.format_field(object.account, object.value) end end + + class AccountIdentityProofSerializer < ActivityPub::Serializer + attributes :type, :name, :signature_algorithm, :signature_value + + def type + 'IdentityProof' + end + + def name + object.provider_username + end + + def signature_algorithm + object.provider + end + + def signature_value + object.token + end + end end diff --git a/app/serializers/activitypub/add_serializer.rb b/app/serializers/activitypub/add_serializer.rb index c0906e8d0..6f5aab17f 100644 --- a/app/serializers/activitypub/add_serializer.rb +++ b/app/serializers/activitypub/add_serializer.rb @@ -1,6 +1,6 @@ # frozen_string_literal: true -class ActivityPub::AddSerializer < ActiveModel::Serializer +class ActivityPub::AddSerializer < ActivityPub::Serializer include RoutingHelper attributes :type, :actor, :target diff --git a/app/serializers/activitypub/block_serializer.rb b/app/serializers/activitypub/block_serializer.rb index 624ce2fce..e6c69329d 100644 --- a/app/serializers/activitypub/block_serializer.rb +++ b/app/serializers/activitypub/block_serializer.rb @@ -1,6 +1,6 @@ # frozen_string_literal: true -class ActivityPub::BlockSerializer < ActiveModel::Serializer +class ActivityPub::BlockSerializer < ActivityPub::Serializer attributes :id, :type, :actor attribute :virtual_object, key: :object diff --git a/app/serializers/activitypub/collection_serializer.rb b/app/serializers/activitypub/collection_serializer.rb index b03609957..da1ba735f 100644 --- a/app/serializers/activitypub/collection_serializer.rb +++ b/app/serializers/activitypub/collection_serializer.rb @@ -1,6 +1,6 @@ # frozen_string_literal: true -class ActivityPub::CollectionSerializer < ActiveModel::Serializer +class ActivityPub::CollectionSerializer < ActivityPub::Serializer def self.serializer_for(model, options) return ActivityPub::NoteSerializer if model.class.name == 'Status' return ActivityPub::CollectionSerializer if model.class.name == 'ActivityPub::CollectionPresenter' diff --git a/app/serializers/activitypub/delete_actor_serializer.rb b/app/serializers/activitypub/delete_actor_serializer.rb index ddf59be97..a6c5e2385 100644 --- a/app/serializers/activitypub/delete_actor_serializer.rb +++ b/app/serializers/activitypub/delete_actor_serializer.rb @@ -1,6 +1,6 @@ # frozen_string_literal: true -class ActivityPub::DeleteActorSerializer < ActiveModel::Serializer +class ActivityPub::DeleteActorSerializer < ActivityPub::Serializer attributes :id, :type, :actor, :to attribute :virtual_object, key: :object diff --git a/app/serializers/activitypub/delete_serializer.rb b/app/serializers/activitypub/delete_serializer.rb index 5012a8383..a7d5bd469 100644 --- a/app/serializers/activitypub/delete_serializer.rb +++ b/app/serializers/activitypub/delete_serializer.rb @@ -1,7 +1,9 @@ # frozen_string_literal: true -class ActivityPub::DeleteSerializer < ActiveModel::Serializer - class TombstoneSerializer < ActiveModel::Serializer +class ActivityPub::DeleteSerializer < ActivityPub::Serializer + class TombstoneSerializer < ActivityPub::Serializer + context_extensions :atom_uri + attributes :id, :type, :atom_uri def id diff --git a/app/serializers/activitypub/emoji_serializer.rb b/app/serializers/activitypub/emoji_serializer.rb index 7b06b1e5d..4dc38f3ea 100644 --- a/app/serializers/activitypub/emoji_serializer.rb +++ b/app/serializers/activitypub/emoji_serializer.rb @@ -1,8 +1,10 @@ # frozen_string_literal: true -class ActivityPub::EmojiSerializer < ActiveModel::Serializer +class ActivityPub::EmojiSerializer < ActivityPub::Serializer include RoutingHelper + context_extensions :emoji + attributes :id, :type, :name, :updated has_one :icon, serializer: ActivityPub::ImageSerializer diff --git a/app/serializers/activitypub/flag_serializer.rb b/app/serializers/activitypub/flag_serializer.rb index 1e7a46dd9..2f2a707d3 100644 --- a/app/serializers/activitypub/flag_serializer.rb +++ b/app/serializers/activitypub/flag_serializer.rb @@ -1,6 +1,6 @@ # frozen_string_literal: true -class ActivityPub::FlagSerializer < ActiveModel::Serializer +class ActivityPub::FlagSerializer < ActivityPub::Serializer attributes :id, :type, :actor, :content attribute :virtual_object, key: :object diff --git a/app/serializers/activitypub/follow_serializer.rb b/app/serializers/activitypub/follow_serializer.rb index bb204ee8f..9228d7716 100644 --- a/app/serializers/activitypub/follow_serializer.rb +++ b/app/serializers/activitypub/follow_serializer.rb @@ -1,6 +1,6 @@ # frozen_string_literal: true -class ActivityPub::FollowSerializer < ActiveModel::Serializer +class ActivityPub::FollowSerializer < ActivityPub::Serializer attributes :id, :type, :actor attribute :virtual_object, key: :object diff --git a/app/serializers/activitypub/image_serializer.rb b/app/serializers/activitypub/image_serializer.rb index 3c08f77e8..1060f9691 100644 --- a/app/serializers/activitypub/image_serializer.rb +++ b/app/serializers/activitypub/image_serializer.rb @@ -1,8 +1,10 @@ # frozen_string_literal: true -class ActivityPub::ImageSerializer < ActiveModel::Serializer +class ActivityPub::ImageSerializer < ActivityPub::Serializer include RoutingHelper + context_extensions :focal_point + attributes :type, :media_type, :url attribute :focal_point, if: :focal_point? diff --git a/app/serializers/activitypub/like_serializer.rb b/app/serializers/activitypub/like_serializer.rb index c1a7ff6f6..0f170ddb4 100644 --- a/app/serializers/activitypub/like_serializer.rb +++ b/app/serializers/activitypub/like_serializer.rb @@ -1,6 +1,6 @@ # frozen_string_literal: true -class ActivityPub::LikeSerializer < ActiveModel::Serializer +class ActivityPub::LikeSerializer < ActivityPub::Serializer attributes :id, :type, :actor attribute :virtual_object, key: :object diff --git a/app/serializers/activitypub/note_serializer.rb b/app/serializers/activitypub/note_serializer.rb index 553f333d8..d11cfa59a 100644 --- a/app/serializers/activitypub/note_serializer.rb +++ b/app/serializers/activitypub/note_serializer.rb @@ -1,6 +1,9 @@ # frozen_string_literal: true -class ActivityPub::NoteSerializer < ActiveModel::Serializer +class ActivityPub::NoteSerializer < ActivityPub::Serializer + context_extensions :atom_uri, :conversation, :sensitive, + :hashtag, :emoji, :focal_point + attributes :id, :type, :summary, :in_reply_to, :published, :url, :attributed_to, :to, :cc, :sensitive, @@ -26,7 +29,7 @@ class ActivityPub::NoteSerializer < ActiveModel::Serializer end def type - object.poll ? 'Question' : 'Note' + object.preloadable_poll ? 'Question' : 'Note' end def summary @@ -122,32 +125,32 @@ class ActivityPub::NoteSerializer < ActiveModel::Serializer end def poll_options - object.poll.loaded_options + object.preloadable_poll.loaded_options end def poll_and_multiple? - object.poll&.multiple? + object.preloadable_poll&.multiple? end def poll_and_not_multiple? - object.poll && !object.poll.multiple? + object.preloadable_poll && !object.preloadable_poll.multiple? end def closed - object.poll.expires_at.iso8601 + object.preloadable_poll.expires_at.iso8601 end alias end_time closed def poll_and_expires? - object.poll&.expires_at&.present? + object.preloadable_poll&.expires_at&.present? end def poll_and_expired? - object.poll&.expired? + object.preloadable_poll&.expired? end - class MediaAttachmentSerializer < ActiveModel::Serializer + class MediaAttachmentSerializer < ActivityPub::Serializer include RoutingHelper attributes :type, :media_type, :url, :name @@ -178,7 +181,7 @@ class ActivityPub::NoteSerializer < ActiveModel::Serializer end end - class MentionSerializer < ActiveModel::Serializer + class MentionSerializer < ActivityPub::Serializer attributes :type, :href, :name def type @@ -194,7 +197,7 @@ class ActivityPub::NoteSerializer < ActiveModel::Serializer end end - class TagSerializer < ActiveModel::Serializer + class TagSerializer < ActivityPub::Serializer include RoutingHelper attributes :type, :href, :name @@ -215,8 +218,8 @@ class ActivityPub::NoteSerializer < ActiveModel::Serializer class CustomEmojiSerializer < ActivityPub::EmojiSerializer end - class OptionSerializer < ActiveModel::Serializer - class RepliesSerializer < ActiveModel::Serializer + class OptionSerializer < ActivityPub::Serializer + class RepliesSerializer < ActivityPub::Serializer attributes :type, :total_items def type diff --git a/app/serializers/activitypub/public_key_serializer.rb b/app/serializers/activitypub/public_key_serializer.rb index 38e9e93ba..62ed49e81 100644 --- a/app/serializers/activitypub/public_key_serializer.rb +++ b/app/serializers/activitypub/public_key_serializer.rb @@ -1,6 +1,8 @@ # frozen_string_literal: true -class ActivityPub::PublicKeySerializer < ActiveModel::Serializer +class ActivityPub::PublicKeySerializer < ActivityPub::Serializer + context :security + attributes :id, :owner, :public_key_pem def id diff --git a/app/serializers/activitypub/reject_follow_serializer.rb b/app/serializers/activitypub/reject_follow_serializer.rb index 7814f4f57..4996c9a3c 100644 --- a/app/serializers/activitypub/reject_follow_serializer.rb +++ b/app/serializers/activitypub/reject_follow_serializer.rb @@ -1,6 +1,6 @@ # frozen_string_literal: true -class ActivityPub::RejectFollowSerializer < ActiveModel::Serializer +class ActivityPub::RejectFollowSerializer < ActivityPub::Serializer attributes :id, :type, :actor has_one :object, serializer: ActivityPub::FollowSerializer diff --git a/app/serializers/activitypub/remove_serializer.rb b/app/serializers/activitypub/remove_serializer.rb index c2a5ae1b3..7fefda59d 100644 --- a/app/serializers/activitypub/remove_serializer.rb +++ b/app/serializers/activitypub/remove_serializer.rb @@ -1,6 +1,6 @@ # frozen_string_literal: true -class ActivityPub::RemoveSerializer < ActiveModel::Serializer +class ActivityPub::RemoveSerializer < ActivityPub::Serializer include RoutingHelper attributes :type, :actor, :target diff --git a/app/serializers/activitypub/undo_announce_serializer.rb b/app/serializers/activitypub/undo_announce_serializer.rb index 4fc042727..6758af679 100644 --- a/app/serializers/activitypub/undo_announce_serializer.rb +++ b/app/serializers/activitypub/undo_announce_serializer.rb @@ -1,6 +1,6 @@ # frozen_string_literal: true -class ActivityPub::UndoAnnounceSerializer < ActiveModel::Serializer +class ActivityPub::UndoAnnounceSerializer < ActivityPub::Serializer attributes :id, :type, :actor, :to has_one :object, serializer: ActivityPub::ActivitySerializer diff --git a/app/serializers/activitypub/undo_block_serializer.rb b/app/serializers/activitypub/undo_block_serializer.rb index 2f43d8402..b4f049377 100644 --- a/app/serializers/activitypub/undo_block_serializer.rb +++ b/app/serializers/activitypub/undo_block_serializer.rb @@ -1,6 +1,6 @@ # frozen_string_literal: true -class ActivityPub::UndoBlockSerializer < ActiveModel::Serializer +class ActivityPub::UndoBlockSerializer < ActivityPub::Serializer attributes :id, :type, :actor has_one :object, serializer: ActivityPub::BlockSerializer diff --git a/app/serializers/activitypub/undo_follow_serializer.rb b/app/serializers/activitypub/undo_follow_serializer.rb index e5b7f143d..9b3e0ca3c 100644 --- a/app/serializers/activitypub/undo_follow_serializer.rb +++ b/app/serializers/activitypub/undo_follow_serializer.rb @@ -1,6 +1,6 @@ # frozen_string_literal: true -class ActivityPub::UndoFollowSerializer < ActiveModel::Serializer +class ActivityPub::UndoFollowSerializer < ActivityPub::Serializer attributes :id, :type, :actor has_one :object, serializer: ActivityPub::FollowSerializer diff --git a/app/serializers/activitypub/undo_like_serializer.rb b/app/serializers/activitypub/undo_like_serializer.rb index 25f4ccaae..20c786cb7 100644 --- a/app/serializers/activitypub/undo_like_serializer.rb +++ b/app/serializers/activitypub/undo_like_serializer.rb @@ -1,6 +1,6 @@ # frozen_string_literal: true -class ActivityPub::UndoLikeSerializer < ActiveModel::Serializer +class ActivityPub::UndoLikeSerializer < ActivityPub::Serializer attributes :id, :type, :actor has_one :object, serializer: ActivityPub::LikeSerializer diff --git a/app/serializers/activitypub/update_poll_serializer.rb b/app/serializers/activitypub/update_poll_serializer.rb index f7933346f..b894f309f 100644 --- a/app/serializers/activitypub/update_poll_serializer.rb +++ b/app/serializers/activitypub/update_poll_serializer.rb @@ -1,12 +1,12 @@ # frozen_string_literal: true -class ActivityPub::UpdatePollSerializer < ActiveModel::Serializer +class ActivityPub::UpdatePollSerializer < ActivityPub::Serializer attributes :id, :type, :actor, :to has_one :object, serializer: ActivityPub::NoteSerializer def id - [ActivityPub::TagManager.instance.uri_for(object), '#updates/', object.poll.updated_at.to_i].join + [ActivityPub::TagManager.instance.uri_for(object), '#updates/', object.preloadable_poll.updated_at.to_i].join end def type diff --git a/app/serializers/activitypub/update_serializer.rb b/app/serializers/activitypub/update_serializer.rb index 48d7a1929..a5eb857d3 100644 --- a/app/serializers/activitypub/update_serializer.rb +++ b/app/serializers/activitypub/update_serializer.rb @@ -1,6 +1,6 @@ # frozen_string_literal: true -class ActivityPub::UpdateSerializer < ActiveModel::Serializer +class ActivityPub::UpdateSerializer < ActivityPub::Serializer attributes :id, :type, :actor, :to has_one :object, serializer: ActivityPub::ActorSerializer diff --git a/app/serializers/activitypub/vote_serializer.rb b/app/serializers/activitypub/vote_serializer.rb index 248190404..71ef5c77e 100644 --- a/app/serializers/activitypub/vote_serializer.rb +++ b/app/serializers/activitypub/vote_serializer.rb @@ -1,7 +1,7 @@ # frozen_string_literal: true -class ActivityPub::VoteSerializer < ActiveModel::Serializer - class NoteSerializer < ActiveModel::Serializer +class ActivityPub::VoteSerializer < ActivityPub::Serializer + class NoteSerializer < ActivityPub::Serializer attributes :id, :type, :name, :attributed_to, :in_reply_to, :to diff --git a/app/serializers/manifest_serializer.rb b/app/serializers/manifest_serializer.rb index cc8b9a4d4..28127437d 100644 --- a/app/serializers/manifest_serializer.rb +++ b/app/serializers/manifest_serializer.rb @@ -18,7 +18,7 @@ class ManifestSerializer < ActiveModel::Serializer end def description - strip_tags(object.site_description.presence || I18n.t('about.about_mastodon_html')) + strip_tags(object.site_short_description.presence || I18n.t('about.about_mastodon_html')) end def icons diff --git a/app/serializers/oembed_serializer.rb b/app/serializers/oembed_serializer.rb index 0c8350e2d..01689633b 100644 --- a/app/serializers/oembed_serializer.rb +++ b/app/serializers/oembed_serializer.rb @@ -43,6 +43,7 @@ class OEmbedSerializer < ActiveModel::Serializer style: 'max-width: 100%; border: 0', width: width, height: height, + allowfullscreen: true, } content_tag(:iframe, nil, attributes) + content_tag(:script, nil, src: full_asset_url('embed.js', skip_pipeline: true), async: true) diff --git a/app/serializers/rest/identity_proof_serializer.rb b/app/serializers/rest/identity_proof_serializer.rb new file mode 100644 index 000000000..0e7415935 --- /dev/null +++ b/app/serializers/rest/identity_proof_serializer.rb @@ -0,0 +1,17 @@ +# frozen_string_literal: true + +class REST::IdentityProofSerializer < ActiveModel::Serializer + attributes :provider, :provider_username, :updated_at, :proof_url, :profile_url + + def proof_url + object.badge.proof_url + end + + def profile_url + object.badge.profile_url + end + + def provider + object.provider.capitalize + end +end diff --git a/app/serializers/rest/relationship_serializer.rb b/app/serializers/rest/relationship_serializer.rb index c6c722a54..1a3fd915c 100644 --- a/app/serializers/rest/relationship_serializer.rb +++ b/app/serializers/rest/relationship_serializer.rb @@ -1,7 +1,7 @@ # frozen_string_literal: true class REST::RelationshipSerializer < ActiveModel::Serializer - attributes :id, :following, :showing_reblogs, :followed_by, :blocking, + attributes :id, :following, :showing_reblogs, :followed_by, :blocking, :blocked_by, :muting, :muting_notifications, :requested, :domain_blocking, :endorsed @@ -27,6 +27,10 @@ class REST::RelationshipSerializer < ActiveModel::Serializer instance_options[:relationships].blocking[object.id] || false end + def blocked_by + instance_options[:relationships].blocked_by[object.id] || false + end + def muting instance_options[:relationships].muting[object.id] ? true : false end diff --git a/app/serializers/rest/status_serializer.rb b/app/serializers/rest/status_serializer.rb index 7185121d6..a7b797368 100644 --- a/app/serializers/rest/status_serializer.rb +++ b/app/serializers/rest/status_serializer.rb @@ -23,7 +23,7 @@ class REST::StatusSerializer < ActiveModel::Serializer has_many :emojis, serializer: REST::CustomEmojiSerializer has_one :preview_card, key: :card, serializer: REST::PreviewCardSerializer - has_one :poll, serializer: REST::PollSerializer + has_one :preloadable_poll, key: :poll, serializer: REST::PollSerializer def id object.id.to_s diff --git a/app/services/activitypub/fetch_remote_poll_service.rb b/app/services/activitypub/fetch_remote_poll_service.rb index 44a23712c..854a32d05 100644 --- a/app/services/activitypub/fetch_remote_poll_service.rb +++ b/app/services/activitypub/fetch_remote_poll_service.rb @@ -5,6 +5,7 @@ class ActivityPub::FetchRemotePollService < BaseService def call(poll, on_behalf_of = nil) json = fetch_resource(poll.status.uri, true, on_behalf_of) + return unless supported_context?(json) ActivityPub::ProcessPollService.new.call(poll, json) end end diff --git a/app/services/activitypub/process_account_service.rb b/app/services/activitypub/process_account_service.rb index 5e3308428..6d0609ca0 100644 --- a/app/services/activitypub/process_account_service.rb +++ b/app/services/activitypub/process_account_service.rb @@ -24,6 +24,7 @@ class ActivityPub::ProcessAccountService < BaseService create_account if @account.nil? update_account process_tags + process_attachments else raise Mastodon::RaceConditionError end @@ -151,7 +152,7 @@ class ActivityPub::ProcessAccountService < BaseService def property_values return unless @json['attachment'].is_a?(Array) - @json['attachment'].select { |attachment| attachment['type'] == 'PropertyValue' }.map { |attachment| attachment.slice('name', 'value') } + as_array(@json['attachment']).select { |attachment| attachment['type'] == 'PropertyValue' }.map { |attachment| attachment.slice('name', 'value') } end def mismatching_origin?(url) @@ -231,6 +232,23 @@ class ActivityPub::ProcessAccountService < BaseService end end + def process_attachments + return if @json['attachment'].blank? + + previous_proofs = @account.identity_proofs.to_a + current_proofs = [] + + as_array(@json['attachment']).each do |attachment| + next unless equals_or_includes?(attachment['type'], 'IdentityProof') + current_proofs << process_identity_proof(attachment) + end + + previous_proofs.each do |previous_proof| + next if current_proofs.any? { |current_proof| current_proof.id == previous_proof.id } + previous_proof.delete + end + end + def process_emoji(tag) return if skip_download? return if tag['name'].blank? || tag['icon'].blank? || tag['icon']['url'].blank? @@ -247,4 +265,12 @@ class ActivityPub::ProcessAccountService < BaseService emoji.image_remote_url = image_url emoji.save end + + def process_identity_proof(attachment) + provider = attachment['signatureAlgorithm'] + provider_username = attachment['name'] + token = attachment['signatureValue'] + + @account.identity_proofs.where(provider: provider, provider_username: provider_username).find_or_create_by(provider: provider, provider_username: provider_username, token: token) + end end diff --git a/app/services/activitypub/process_poll_service.rb b/app/services/activitypub/process_poll_service.rb index ee248169d..61357abd3 100644 --- a/app/services/activitypub/process_poll_service.rb +++ b/app/services/activitypub/process_poll_service.rb @@ -5,7 +5,7 @@ class ActivityPub::ProcessPollService < BaseService def call(poll, json) @json = json - return unless supported_context? && expected_type? + return unless expected_type? previous_expires_at = poll.expires_at @@ -54,10 +54,6 @@ class ActivityPub::ProcessPollService < BaseService private - def supported_context? - super(@json) - end - def expected_type? equals_or_includes_any?(@json['type'], %w(Question)) end diff --git a/app/services/post_status_service.rb b/app/services/post_status_service.rb index 820c553c9..333bf88d8 100644 --- a/app/services/post_status_service.rb +++ b/app/services/post_status_service.rb @@ -162,7 +162,7 @@ class PostStatusService < BaseService text: @text, media_attachments: @media || [], thread: @in_reply_to, - owned_poll_attributes: poll_attributes, + poll_attributes: poll_attributes, sensitive: (@options[:sensitive].nil? ? @account.user&.setting_default_sensitive : @options[:sensitive]) || @options[:spoiler_text].present?, spoiler_text: @options[:spoiler_text] || '', visibility: @visibility, diff --git a/app/services/vote_service.rb b/app/services/vote_service.rb index 0cace6c00..81af9ef3a 100644 --- a/app/services/vote_service.rb +++ b/app/services/vote_service.rb @@ -11,14 +11,14 @@ class VoteService < BaseService @choices = choices @votes = [] - return if @poll.expired? - ApplicationRecord.transaction do @choices.each do |choice| @votes << @poll.votes.create!(account: @account, choice: choice) end end + ActivityTracker.increment('activity:interactions') + if @poll.account.local? distribute_poll! else diff --git a/app/validators/existing_username_validator.rb b/app/validators/existing_username_validator.rb new file mode 100644 index 000000000..4388a0c98 --- /dev/null +++ b/app/validators/existing_username_validator.rb @@ -0,0 +1,20 @@ +# frozen_string_literal: true + +class ExistingUsernameValidator < ActiveModel::EachValidator + def validate_each(record, attribute, value) + return if value.blank? + + if options[:multiple] + missing_usernames = value.split(',').map { |username| username unless Account.find_local(username) }.compact + record.errors.add(attribute, I18n.t('existing_username_validator.not_found_multiple', usernames: missing_usernames.join(', '))) if missing_usernames.any? + else + record.errors.add(attribute, I18n.t('existing_username_validator.not_found')) unless Account.find_local(value) + end + end + + private + + def valid_html?(str) + Nokogiri::HTML.fragment(str).to_s == str + end +end diff --git a/app/validators/html_validator.rb b/app/validators/html_validator.rb new file mode 100644 index 000000000..b7caee5a9 --- /dev/null +++ b/app/validators/html_validator.rb @@ -0,0 +1,18 @@ +# frozen_string_literal: true + +class HtmlValidator < ActiveModel::EachValidator + def validate_each(record, attribute, value) + return if value.blank? + errors = html_errors(value) + unless errors.empty? + record.errors.add(attribute, I18n.t('html_validator.invalid_markup', error: errors.first.to_s)) + end + end + + private + + def html_errors(str) + fragment = Nokogiri::HTML.fragment(str) + fragment.errors + end +end diff --git a/app/views/about/_registration.html.haml b/app/views/about/_registration.html.haml index 9cb4eb2bc..09cbe2e28 100644 --- a/app/views/about/_registration.html.haml +++ b/app/views/about/_registration.html.haml @@ -1,16 +1,23 @@ = simple_form_for(new_user, url: user_registration_path) do |f| - %p.lead= t('about.federation_hint_html', instance: content_tag(:strong, site_hostname)) + .simple_form__overlay-area + %p.lead= t('about.federation_hint_html', instance: content_tag(:strong, site_hostname)) - .fields-group - = f.simple_fields_for :account do |account_fields| - = account_fields.input :username, wrapper: :with_label, autofocus: true, label: false, required: true, input_html: { 'aria-label' => t('simple_form.labels.defaults.username'), :autocomplete => 'off', placeholder: t('simple_form.labels.defaults.username') }, append: "@#{site_hostname}", hint: false, disabled: closed_registrations? + .fields-group + = f.simple_fields_for :account do |account_fields| + = account_fields.input :username, wrapper: :with_label, label: false, required: true, input_html: { 'aria-label' => t('simple_form.labels.defaults.username'), :autocomplete => 'off', placeholder: t('simple_form.labels.defaults.username') }, append: "@#{site_hostname}", hint: false, disabled: closed_registrations? - = f.input :email, placeholder: t('simple_form.labels.defaults.email'), required: true, input_html: { 'aria-label' => t('simple_form.labels.defaults.email'), :autocomplete => 'off' }, hint: false, disabled: closed_registrations? - = f.input :password, placeholder: t('simple_form.labels.defaults.password'), required: true, input_html: { 'aria-label' => t('simple_form.labels.defaults.password'), :autocomplete => 'off' }, hint: false, disabled: closed_registrations? - = f.input :password_confirmation, placeholder: t('simple_form.labels.defaults.confirm_password'), required: true, input_html: { 'aria-label' => t('simple_form.labels.defaults.confirm_password'), :autocomplete => 'off' }, hint: false, disabled: closed_registrations? + = f.input :email, placeholder: t('simple_form.labels.defaults.email'), required: true, input_html: { 'aria-label' => t('simple_form.labels.defaults.email'), :autocomplete => 'off' }, hint: false, disabled: closed_registrations? + = f.input :password, placeholder: t('simple_form.labels.defaults.password'), required: true, input_html: { 'aria-label' => t('simple_form.labels.defaults.password'), :autocomplete => 'off' }, hint: false, disabled: closed_registrations? + = f.input :password_confirmation, placeholder: t('simple_form.labels.defaults.confirm_password'), required: true, input_html: { 'aria-label' => t('simple_form.labels.defaults.confirm_password'), :autocomplete => 'off' }, hint: false, disabled: closed_registrations? - .fields-group - = f.input :agreement, as: :boolean, wrapper: :with_label, label: t('auth.checkbox_agreement_html', rules_path: about_more_path, terms_path: terms_path), disabled: closed_registrations? + .fields-group + = f.input :agreement, as: :boolean, wrapper: :with_label, label: t('auth.checkbox_agreement_html', rules_path: about_more_path, terms_path: terms_path), disabled: closed_registrations? - .actions - = f.button :button, sign_up_message, type: :submit, class: 'button button-primary', disabled: closed_registrations? + .actions + = f.button :button, sign_up_message, type: :submit, class: 'button button-primary', disabled: closed_registrations? + + - if closed_registrations? && @instance_presenter.closed_registrations_message.present? + .simple_form__overlay-area__overlay + .simple_form__overlay-area__overlay__content.rich-formatting + .block-icon= fa_icon 'warning' + = @instance_presenter.closed_registrations_message.html_safe diff --git a/app/views/admin/dashboard/index.html.haml b/app/views/admin/dashboard/index.html.haml index fa3d70e9e..d448e3862 100644 --- a/app/views/admin/dashboard/index.html.haml +++ b/app/views/admin/dashboard/index.html.haml @@ -40,35 +40,17 @@ %h4= t 'admin.dashboard.features' %ul %li - = link_to t('admin.dashboard.feature_registrations'), edit_admin_settings_path - - if @registrations_enabled - %span.pull-right.positive-hint= fa_icon 'check fw' - - else - %span.pull-right.negative-hint= fa_icon 'times fw' - %li - = link_to t('admin.dashboard.feature_invites'), edit_admin_settings_path - - if @invites_enabled - %span.pull-right.positive-hint= fa_icon 'check fw' - - else - %span.pull-right.negative-hint= fa_icon 'times fw' - %li - = link_to t('admin.dashboard.feature_deletions'), edit_admin_settings_path - - if @deletions_enabled - %span.pull-right.positive-hint= fa_icon 'check fw' - - else - %span.pull-right.negative-hint= fa_icon 'times fw' - %li - = link_to t('admin.dashboard.feature_profile_directory'), edit_admin_settings_path - - if @profile_directory - %span.pull-right.positive-hint= fa_icon 'check fw' - - else - %span.pull-right.negative-hint= fa_icon 'times fw' - %li - = link_to t('admin.dashboard.feature_relay'), admin_relays_path - - if @relay_enabled - %span.pull-right.positive-hint= fa_icon 'check fw' - - else - %span.pull-right.negative-hint= fa_icon 'times fw' + = feature_hint(link_to(t('admin.dashboard.feature_registrations'), edit_admin_settings_path), @registrations_enabled) + %li + = feature_hint(link_to(t('admin.dashboard.feature_invites'), edit_admin_settings_path), @invites_enabled) + %li + = feature_hint(link_to(t('admin.dashboard.feature_deletions'), edit_admin_settings_path), @deletions_enabled) + %li + = feature_hint(link_to(t('admin.dashboard.feature_profile_directory'), edit_admin_settings_path), @profile_directory) + %li + = feature_hint(link_to(t('admin.dashboard.feature_timeline_preview'), edit_admin_settings_path), @timeline_preview) + %li + = feature_hint(link_to(t('admin.dashboard.feature_relay'), admin_relays_path), @relay_enabled) .dashboard__widgets__versions %div @@ -103,47 +85,19 @@ %h4= t 'admin.dashboard.config' %ul %li - = t('admin.dashboard.search') - - if @search_enabled - %span.pull-right.positive-hint= fa_icon 'check fw' - - else - %span.pull-right.negative-hint= fa_icon 'times fw' - %li - = t('admin.dashboard.single_user_mode') - - if @single_user_mode - %span.pull-right.positive-hint= fa_icon 'check fw' - - else - %span.pull-right.negative-hint= fa_icon 'times fw' - %li - LDAP - - if @ldap_enabled - %span.pull-right.positive-hint= fa_icon 'check fw' - - else - %span.pull-right.negative-hint= fa_icon 'times fw' - %li - CAS - - if @cas_enabled - %span.pull-right.positive-hint= fa_icon 'check fw' - - else - %span.pull-right.negative-hint= fa_icon 'times fw' - %li - SAML - - if @saml_enabled - %span.pull-right.positive-hint= fa_icon 'check fw' - - else - %span.pull-right.negative-hint= fa_icon 'times fw' - %li - PAM - - if @pam_enabled - %span.pull-right.positive-hint= fa_icon 'check fw' - - else - %span.pull-right.negative-hint= fa_icon 'times fw' - %li - = t 'admin.dashboard.hidden_service' - - if @hidden_service - %span.pull-right.positive-hint= fa_icon 'check fw' - - else - %span.pull-right.negative-hint= fa_icon 'times fw' + = feature_hint(t('admin.dashboard.search'), @search_enabled) + %li + = feature_hint(t('admin.dashboard.single_user_mode'), @single_user_mode) + %li + = feature_hint('LDAP', @ldap_enabled) + %li + = feature_hint('CAS', @cas_enabled) + %li + = feature_hint('SAML', @saml_enabled) + %li + = feature_hint('PAM', @pam_enabled) + %li + = feature_hint(t('admin.dashboard.hidden_service'), @hidden_service) .dashboard__widgets__trends %div diff --git a/app/views/admin/instances/index.html.haml b/app/views/admin/instances/index.html.haml index 235927140..9574c3147 100644 --- a/app/views/admin/instances/index.html.haml +++ b/app/views/admin/instances/index.html.haml @@ -33,7 +33,7 @@ %h4 = instance.domain %small - = t('admin.instances.known_accounts', count: instance.accounts_count) + = t('admin.instances.known_accounts', count: instance.cached_accounts_count) - if instance.domain_block - if !instance.domain_block.noop? diff --git a/app/views/admin/settings/edit.html.haml b/app/views/admin/settings/edit.html.haml index 9995e0b2a..475fb3a2f 100644 --- a/app/views/admin/settings/edit.html.haml +++ b/app/views/admin/settings/edit.html.haml @@ -2,6 +2,7 @@ = t('admin.settings.title') = simple_form_for @admin_settings, url: admin_settings_path, html: { method: :patch } do |f| + = render 'shared/error_messages', object: @admin_settings .fields-group = f.input :site_title, wrapper: :with_label, label: t('admin.settings.site_title') diff --git a/app/views/relationships/show.html.haml b/app/views/relationships/show.html.haml index fc9613731..1de4e373f 100644 --- a/app/views/relationships/show.html.haml +++ b/app/views/relationships/show.html.haml @@ -22,11 +22,18 @@ %li= filter_link_to t('generic.all'), activity: nil %li= filter_link_to t('relationships.dormant'), activity: 'dormant' + .filter-subset + %strong= t 'generic.order_by' + %ul + %li= filter_link_to t('relationships.most_recent'), order: nil + %li= filter_link_to t('relationships.last_active'), order: 'active' + = form_for(@form, url: relationships_path, method: :patch) do |f| = hidden_field_tag :page, params[:page] || 1 = hidden_field_tag :relationship, params[:relationship] = hidden_field_tag :status, params[:status] = hidden_field_tag :activity, params[:activity] + = hidden_field_tag :order, params[:order] .batch-table .batch-table__toolbar diff --git a/app/views/settings/identity_proofs/new.html.haml b/app/views/settings/identity_proofs/new.html.haml index 8ce6e61c9..5e4e9895d 100644 --- a/app/views/settings/identity_proofs/new.html.haml +++ b/app/views/settings/identity_proofs/new.html.haml @@ -27,5 +27,10 @@ %p= t('identity_proofs.i_am_html', username: content_tag(:strong, @proof.provider_username), service: @proof.provider.capitalize) + .connection-prompt__post + = f.input :post_status, label: t('identity_proofs.publicize_checkbox'), as: :boolean, wrapper: :with_label, :input_html => { checked: true } + + = f.input :status_text, as: :text, input_html: { value: t('identity_proofs.publicize_toot', username: @proof.provider_username, service: @proof.provider.capitalize, url: @proof.badge.proof_url), rows: 4 } + = f.button :button, t('identity_proofs.authorize'), type: :submit = link_to t('simple_form.no'), settings_identity_proofs_url, class: 'button negative' diff --git a/app/views/stream_entries/_detailed_status.html.haml b/app/views/stream_entries/_detailed_status.html.haml index d18ecd37a..4459581d9 100644 --- a/app/views/stream_entries/_detailed_status.html.haml +++ b/app/views/stream_entries/_detailed_status.html.haml @@ -22,9 +22,9 @@ %a.status__content__spoiler-link{ href: '#' }= t('statuses.show_more') .e-content{ lang: status.language, style: "display: #{!current_account&.user&.setting_expand_spoilers && status.spoiler_text? ? 'none' : 'block'}; direction: #{rtl_status?(status) ? 'rtl' : 'ltr'}" }= Formatter.instance.format(status, custom_emojify: true, autoplay: autoplay) - - if status.poll - = react_component :poll, disabled: true, poll: ActiveModelSerializers::SerializableResource.new(status.poll, serializer: REST::PollSerializer, scope: current_user, scope_name: :current_user).as_json do - = render partial: 'stream_entries/poll', locals: { status: status, poll: status.poll, autoplay: autoplay } + - if status.preloadable_poll + = react_component :poll, disabled: true, poll: ActiveModelSerializers::SerializableResource.new(status.preloadable_poll, serializer: REST::PollSerializer, scope: current_user, scope_name: :current_user).as_json do + = render partial: 'stream_entries/poll', locals: { status: status, poll: status.preloadable_poll, autoplay: autoplay } - elsif !status.media_attachments.empty? - if status.media_attachments.first.video? - video = status.media_attachments.first diff --git a/app/views/stream_entries/_simple_status.html.haml b/app/views/stream_entries/_simple_status.html.haml index 1952128a0..6d2a408ea 100644 --- a/app/views/stream_entries/_simple_status.html.haml +++ b/app/views/stream_entries/_simple_status.html.haml @@ -27,9 +27,9 @@ .e-content{ lang: status.language, style: "display: #{!current_account&.user&.setting_expand_spoilers && status.spoiler_text? ? 'none' : 'block'}; direction: #{rtl_status?(status) ? 'rtl' : 'ltr'}" }< = Formatter.instance.format(status, custom_emojify: true, autoplay: autoplay) - - if status.poll - = react_component :poll, disabled: true, poll: ActiveModelSerializers::SerializableResource.new(status.poll, serializer: REST::PollSerializer, scope: current_user, scope_name: :current_user).as_json do - = render partial: 'stream_entries/poll', locals: { status: status, poll: status.poll, autoplay: autoplay } + - if status.preloadable_poll + = react_component :poll, disabled: true, poll: ActiveModelSerializers::SerializableResource.new(status.preloadable_poll, serializer: REST::PollSerializer, scope: current_user, scope_name: :current_user).as_json do + = render partial: 'stream_entries/poll', locals: { status: status, poll: status.preloadable_poll, autoplay: autoplay } - elsif !status.media_attachments.empty? - if status.media_attachments.first.video? - video = status.media_attachments.first diff --git a/app/workers/activitypub/distribute_poll_update_worker.rb b/app/workers/activitypub/distribute_poll_update_worker.rb index 5536bd744..98b227111 100644 --- a/app/workers/activitypub/distribute_poll_update_worker.rb +++ b/app/workers/activitypub/distribute_poll_update_worker.rb @@ -9,7 +9,7 @@ class ActivityPub::DistributePollUpdateWorker @status = Status.find(status_id) @account = @status.account - return if @status.poll.nil? || @status.local_only? + return if @status.preloadable_poll.nil? || @status.local_only? ActivityPub::DeliveryWorker.push_bulk(inboxes) do |inbox_url| [payload, @account.id, inbox_url] @@ -29,7 +29,7 @@ class ActivityPub::DistributePollUpdateWorker def inboxes return @inboxes if defined?(@inboxes) - @inboxes = [@status.mentions, @status.reblogs, @status.poll.votes].flat_map do |relation| + @inboxes = [@status.mentions, @status.reblogs, @status.preloadable_poll.votes].flat_map do |relation| relation.includes(:account).map do |record| record.account.preferred_inbox_url if !record.account.local? && record.account.activitypub? end |