From 790d3bc6370f1baf0d00ccf89e81387204c65194 Mon Sep 17 00:00:00 2001 From: Eugen Rochko Date: Thu, 11 Oct 2018 00:50:18 +0200 Subject: [PATCH 01/87] Move network calls out of transaction in ActivityPub handler (#8951) Mention and emoji code may perform network calls, but does not need to do that inside the database transaction. This may improve availability of database connections when using pgBouncer in transaction mode. --- app/lib/activitypub/activity/create.rb | 81 ++++++++++++++++---------- 1 file changed, 50 insertions(+), 31 deletions(-) diff --git a/app/lib/activitypub/activity/create.rb b/app/lib/activitypub/activity/create.rb index 9782897884..b889461cb0 100644 --- a/app/lib/activitypub/activity/create.rb +++ b/app/lib/activitypub/activity/create.rb @@ -22,12 +22,16 @@ class ActivityPub::Activity::Create < ActivityPub::Activity private def process_status - status_params = process_status_params + @tags = [] + @mentions = [] + @params = {} + + process_status_params + process_tags ApplicationRecord.transaction do - @status = Status.create!(status_params) - - process_tags(@status) + @status = Status.create!(@params) + attach_tags(@status) end resolve_thread(@status) @@ -42,62 +46,77 @@ class ActivityPub::Activity::Create < ActivityPub::Activity end def process_status_params - { - uri: @object['id'], - url: object_url || @object['id'], - account: @account, - text: text_from_content || '', - language: detected_language, - spoiler_text: text_from_summary || '', - created_at: @object['published'], - override_timestamps: @options[:override_timestamps], - reply: @object['inReplyTo'].present?, - sensitive: @object['sensitive'] || false, - visibility: visibility_from_audience, - thread: replied_to_status, - conversation: conversation_from_uri(@object['conversation']), - media_attachment_ids: process_attachments.take(4).map(&:id), - } + @params = begin + { + uri: @object['id'], + url: object_url || @object['id'], + account: @account, + text: text_from_content || '', + language: detected_language, + spoiler_text: text_from_summary || '', + created_at: @object['published'], + override_timestamps: @options[:override_timestamps], + reply: @object['inReplyTo'].present?, + sensitive: @object['sensitive'] || false, + visibility: visibility_from_audience, + thread: replied_to_status, + conversation: conversation_from_uri(@object['conversation']), + media_attachment_ids: process_attachments.take(4).map(&:id), + } + end end - def process_tags(status) + def attach_tags(status) + @tags.each do |tag| + status.tags << tag + TrendingTags.record_use!(hashtag, status.account, status.created_at) if status.public_visibility? + end + + @mentions.each do |mention| + mention.status = status + mention.save + end + end + + def process_tags return if @object['tag'].nil? as_array(@object['tag']).each do |tag| if equals_or_includes?(tag['type'], 'Hashtag') - process_hashtag tag, status + process_hashtag tag elsif equals_or_includes?(tag['type'], 'Mention') - process_mention tag, status + process_mention tag elsif equals_or_includes?(tag['type'], 'Emoji') - process_emoji tag, status + process_emoji tag end end end - def process_hashtag(tag, status) + def process_hashtag(tag) return if tag['name'].blank? hashtag = tag['name'].gsub(/\A#/, '').mb_chars.downcase hashtag = Tag.where(name: hashtag).first_or_create(name: hashtag) - return if status.tags.include?(hashtag) + return if @tags.include?(hashtag) - status.tags << hashtag - TrendingTags.record_use!(hashtag, status.account, status.created_at) if status.public_visibility? + @tags << hashtag rescue ActiveRecord::RecordInvalid nil end - def process_mention(tag, status) + def process_mention(tag) return if tag['href'].blank? account = account_from_uri(tag['href']) account = ::FetchRemoteAccountService.new.call(tag['href'], id: false) if account.nil? + return if account.nil? - account.mentions.create(status: status) + + @mentions << Mention.new(account: account) end - def process_emoji(tag, _status) + def process_emoji(tag) return if skip_download? return if tag['name'].blank? || tag['icon'].blank? || tag['icon']['url'].blank? From 87fdd139b890e60f752bf71e3b09d79eaefcf7b5 Mon Sep 17 00:00:00 2001 From: Eugen Rochko Date: Thu, 11 Oct 2018 01:31:03 +0200 Subject: [PATCH 02/87] Do not push DMs into the home feed (#8940) * Do not push DMs into the home feed * Show DMs column after sending a DM, if DMs column is not already shown --- app/javascript/mastodon/actions/compose.js | 29 ++++++++++--------- .../mastodon/actions/conversations.js | 11 +++++++ .../compose/components/compose_form.js | 6 +++- .../features/compose/components/upload.js | 6 +++- .../containers/compose_form_container.js | 4 +-- .../compose/containers/upload_container.js | 4 +-- .../features/direct_timeline/index.js | 5 +++- .../mastodon/reducers/conversations.js | 7 +++++ app/services/batched_remove_status_service.rb | 11 ------- app/services/fan_out_on_write_service.rb | 25 +--------------- app/services/remove_status_service.rb | 8 ----- 11 files changed, 52 insertions(+), 64 deletions(-) diff --git a/app/javascript/mastodon/actions/compose.js b/app/javascript/mastodon/actions/compose.js index 6d975cd1e4..f726712283 100644 --- a/app/javascript/mastodon/actions/compose.js +++ b/app/javascript/mastodon/actions/compose.js @@ -56,7 +56,7 @@ export function changeCompose(text) { }; }; -export function replyCompose(status, router) { +export function replyCompose(status, routerHistory) { return (dispatch, getState) => { dispatch({ type: COMPOSE_REPLY, @@ -64,7 +64,7 @@ export function replyCompose(status, router) { }); if (!getState().getIn(['compose', 'mounted'])) { - router.push('/statuses/new'); + routerHistory.push('/statuses/new'); } }; }; @@ -81,7 +81,7 @@ export function resetCompose() { }; }; -export function mentionCompose(account, router) { +export function mentionCompose(account, routerHistory) { return (dispatch, getState) => { dispatch({ type: COMPOSE_MENTION, @@ -89,12 +89,12 @@ export function mentionCompose(account, router) { }); if (!getState().getIn(['compose', 'mounted'])) { - router.push('/statuses/new'); + routerHistory.push('/statuses/new'); } }; }; -export function directCompose(account, router) { +export function directCompose(account, routerHistory) { return (dispatch, getState) => { dispatch({ type: COMPOSE_DIRECT, @@ -102,12 +102,12 @@ export function directCompose(account, router) { }); if (!getState().getIn(['compose', 'mounted'])) { - router.push('/statuses/new'); + routerHistory.push('/statuses/new'); } }; }; -export function submitCompose() { +export function submitCompose(routerHistory) { return function (dispatch, getState) { const status = getState().getIn(['compose', 'text'], ''); const media = getState().getIn(['compose', 'media_attachments']); @@ -133,21 +133,22 @@ export function submitCompose() { dispatch(insertIntoTagHistory(response.data.tags, status)); dispatch(submitComposeSuccess({ ...response.data })); - // To make the app more responsive, immediately get the status into the columns + // To make the app more responsive, immediately push the status + // into the columns - const insertIfOnline = (timelineId) => { + const insertIfOnline = timelineId => { if (getState().getIn(['timelines', timelineId, 'items', 0]) !== null) { dispatch(updateTimeline(timelineId, { ...response.data })); } }; - insertIfOnline('home'); - - if (response.data.in_reply_to_id === null && response.data.visibility === 'public') { + if (response.data.visibility === 'direct' && getState().getIn(['conversations', 'mounted']) <= 0) { + routerHistory.push('/timelines/direct'); + } else if (response.data.visibility !== 'direct') { + insertIfOnline('home'); + } else if (response.data.in_reply_to_id === null && response.data.visibility === 'public') { insertIfOnline('community'); insertIfOnline('public'); - } else if (response.data.visibility === 'direct') { - insertIfOnline('direct'); } }).catch(function (error) { dispatch(submitComposeFail(error)); diff --git a/app/javascript/mastodon/actions/conversations.js b/app/javascript/mastodon/actions/conversations.js index 3840d23caf..cab05c1bab 100644 --- a/app/javascript/mastodon/actions/conversations.js +++ b/app/javascript/mastodon/actions/conversations.js @@ -5,11 +5,22 @@ import { importFetchedStatus, } from './importer'; +export const CONVERSATIONS_MOUNT = 'CONVERSATIONS_MOUNT'; +export const CONVERSATIONS_UNMOUNT = 'CONVERSATIONS_UNMOUNT'; + export const CONVERSATIONS_FETCH_REQUEST = 'CONVERSATIONS_FETCH_REQUEST'; export const CONVERSATIONS_FETCH_SUCCESS = 'CONVERSATIONS_FETCH_SUCCESS'; export const CONVERSATIONS_FETCH_FAIL = 'CONVERSATIONS_FETCH_FAIL'; export const CONVERSATIONS_UPDATE = 'CONVERSATIONS_UPDATE'; +export const mountConversations = () => ({ + type: CONVERSATIONS_MOUNT, +}); + +export const unmountConversations = () => ({ + type: CONVERSATIONS_UNMOUNT, +}); + export const expandConversations = ({ maxId } = {}) => (dispatch, getState) => { dispatch(expandConversationsRequest()); diff --git a/app/javascript/mastodon/features/compose/components/compose_form.js b/app/javascript/mastodon/features/compose/components/compose_form.js index 365114b931..27178fe198 100644 --- a/app/javascript/mastodon/features/compose/components/compose_form.js +++ b/app/javascript/mastodon/features/compose/components/compose_form.js @@ -30,6 +30,10 @@ const messages = defineMessages({ export default @injectIntl class ComposeForm extends ImmutablePureComponent { + static contextTypes = { + router: PropTypes.object, + }; + static propTypes = { intl: PropTypes.object.isRequired, text: PropTypes.string.isRequired, @@ -84,7 +88,7 @@ class ComposeForm extends ImmutablePureComponent { return; } - this.props.onSubmit(); + this.props.onSubmit(this.context.router.history); } onSuggestionsClearRequested = () => { diff --git a/app/javascript/mastodon/features/compose/components/upload.js b/app/javascript/mastodon/features/compose/components/upload.js index e377da90c0..66c93452ce 100644 --- a/app/javascript/mastodon/features/compose/components/upload.js +++ b/app/javascript/mastodon/features/compose/components/upload.js @@ -14,6 +14,10 @@ const messages = defineMessages({ export default @injectIntl class Upload extends ImmutablePureComponent { + static contextTypes = { + router: PropTypes.object, + }; + static propTypes = { media: ImmutablePropTypes.map.isRequired, intl: PropTypes.object.isRequired, @@ -37,7 +41,7 @@ class Upload extends ImmutablePureComponent { handleSubmit = () => { this.handleInputBlur(); - this.props.onSubmit(); + this.props.onSubmit(this.context.router.history); } handleUndoClick = () => { diff --git a/app/javascript/mastodon/features/compose/containers/compose_form_container.js b/app/javascript/mastodon/features/compose/containers/compose_form_container.js index 3822dd711f..5d7fb8852b 100644 --- a/app/javascript/mastodon/features/compose/containers/compose_form_container.js +++ b/app/javascript/mastodon/features/compose/containers/compose_form_container.js @@ -33,8 +33,8 @@ const mapDispatchToProps = (dispatch) => ({ dispatch(changeCompose(text)); }, - onSubmit () { - dispatch(submitCompose()); + onSubmit (router) { + dispatch(submitCompose(router)); }, onClearSuggestions () { diff --git a/app/javascript/mastodon/features/compose/containers/upload_container.js b/app/javascript/mastodon/features/compose/containers/upload_container.js index 9f3aab4bcd..b6d81f03ac 100644 --- a/app/javascript/mastodon/features/compose/containers/upload_container.js +++ b/app/javascript/mastodon/features/compose/containers/upload_container.js @@ -22,8 +22,8 @@ const mapDispatchToProps = dispatch => ({ dispatch(openModal('FOCAL_POINT', { id })); }, - onSubmit () { - dispatch(submitCompose()); + onSubmit (router) { + dispatch(submitCompose(router)); }, }); diff --git a/app/javascript/mastodon/features/direct_timeline/index.js b/app/javascript/mastodon/features/direct_timeline/index.js index 41ec73d98f..d202f3bfd9 100644 --- a/app/javascript/mastodon/features/direct_timeline/index.js +++ b/app/javascript/mastodon/features/direct_timeline/index.js @@ -3,7 +3,7 @@ import { connect } from 'react-redux'; import PropTypes from 'prop-types'; import Column from '../../components/column'; import ColumnHeader from '../../components/column_header'; -import { expandConversations } from '../../actions/conversations'; +import { mountConversations, unmountConversations, expandConversations } from '../../actions/conversations'; import { addColumn, removeColumn, moveColumn } from '../../actions/columns'; import { defineMessages, injectIntl, FormattedMessage } from 'react-intl'; import { connectDirectStream } from '../../actions/streaming'; @@ -48,11 +48,14 @@ class DirectTimeline extends React.PureComponent { componentDidMount () { const { dispatch } = this.props; + dispatch(mountConversations()); dispatch(expandConversations()); this.disconnect = dispatch(connectDirectStream()); } componentWillUnmount () { + this.props.dispatch(unmountConversations()); + if (this.disconnect) { this.disconnect(); this.disconnect = null; diff --git a/app/javascript/mastodon/reducers/conversations.js b/app/javascript/mastodon/reducers/conversations.js index f339abf56e..6b3f22d25b 100644 --- a/app/javascript/mastodon/reducers/conversations.js +++ b/app/javascript/mastodon/reducers/conversations.js @@ -1,5 +1,7 @@ import { Map as ImmutableMap, List as ImmutableList } from 'immutable'; import { + CONVERSATIONS_MOUNT, + CONVERSATIONS_UNMOUNT, CONVERSATIONS_FETCH_REQUEST, CONVERSATIONS_FETCH_SUCCESS, CONVERSATIONS_FETCH_FAIL, @@ -11,6 +13,7 @@ const initialState = ImmutableMap({ items: ImmutableList(), isLoading: false, hasMore: true, + mounted: false, }); const conversationToMap = item => ImmutableMap({ @@ -73,6 +76,10 @@ export default function conversations(state = initialState, action) { return expandNormalizedConversations(state, action.conversations, action.next); case CONVERSATIONS_UPDATE: return updateConversation(state, action.conversation); + case CONVERSATIONS_MOUNT: + return state.update('mounted', count => count + 1); + case CONVERSATIONS_UNMOUNT: + return state.update('mounted', count => count - 1); default: return state; } diff --git a/app/services/batched_remove_status_service.rb b/app/services/batched_remove_status_service.rb index ebb4034aaf..2fcb3cc66b 100644 --- a/app/services/batched_remove_status_service.rb +++ b/app/services/batched_remove_status_service.rb @@ -39,7 +39,6 @@ class BatchedRemoveStatusService < BaseService # Cannot be batched statuses.each do |status| unpush_from_public_timelines(status) - unpush_from_direct_timelines(status) if status.direct_visibility? batch_salmon_slaps(status) if status.local? end @@ -96,16 +95,6 @@ class BatchedRemoveStatusService < BaseService end end - def unpush_from_direct_timelines(status) - payload = @json_payloads[status.id] - redis.pipelined do - @mentions[status.id].each do |mention| - redis.publish("timeline:direct:#{mention.account.id}", payload) if mention.account.local? - end - redis.publish("timeline:direct:#{status.account.id}", payload) if status.account.local? - end - end - def batch_salmon_slaps(status) return if @mentions[status.id].empty? diff --git a/app/services/fan_out_on_write_service.rb b/app/services/fan_out_on_write_service.rb index ab520276b2..5ddddf3a90 100644 --- a/app/services/fan_out_on_write_service.rb +++ b/app/services/fan_out_on_write_service.rb @@ -6,15 +6,12 @@ class FanOutOnWriteService < BaseService def call(status) raise Mastodon::RaceConditionError if status.visibility.nil? - deliver_to_self(status) if status.account.local? - render_anonymous_payload(status) if status.direct_visibility? - deliver_to_mentioned_followers(status) - deliver_to_direct_timelines(status) deliver_to_own_conversation(status) else + deliver_to_self(status) if status.account.local? deliver_to_followers(status) deliver_to_lists(status) end @@ -56,16 +53,6 @@ class FanOutOnWriteService < BaseService end end - def deliver_to_mentioned_followers(status) - Rails.logger.debug "Delivering status #{status.id} to mentioned followers" - - status.mentions.includes(:account).each do |mention| - mentioned_account = mention.account - next if !mentioned_account.local? || !mentioned_account.following?(status.account) || FeedManager.instance.filter?(:home, status, mention.account_id) - FeedManager.instance.push_to_home(mentioned_account, status) - end - end - def render_anonymous_payload(status) @payload = InlineRenderer.render(status, nil, :status) @payload = Oj.dump(event: :update, payload: @payload) @@ -94,16 +81,6 @@ class FanOutOnWriteService < BaseService Redis.current.publish('timeline:public:local:media', @payload) if status.local? end - def deliver_to_direct_timelines(status) - Rails.logger.debug "Delivering status #{status.id} to direct timelines" - - status.mentions.includes(:account).each do |mention| - Redis.current.publish("timeline:direct:#{mention.account.id}", @payload) if mention.account.local? - end - - Redis.current.publish("timeline:direct:#{status.account.id}", @payload) if status.account.local? - end - def deliver_to_own_conversation(status) AccountConversation.add_status(status.account, status) end diff --git a/app/services/remove_status_service.rb b/app/services/remove_status_service.rb index 1a53093b89..1ee645e6d8 100644 --- a/app/services/remove_status_service.rb +++ b/app/services/remove_status_service.rb @@ -21,7 +21,6 @@ class RemoveStatusService < BaseService remove_from_hashtags remove_from_public remove_from_media if status.media_attachments.any? - remove_from_direct if status.direct_visibility? @status.destroy! @@ -153,13 +152,6 @@ class RemoveStatusService < BaseService Redis.current.publish('timeline:public:local:media', @payload) if @status.local? end - def remove_from_direct - @mentions.each do |mention| - Redis.current.publish("timeline:direct:#{mention.account.id}", @payload) if mention.account.local? - end - Redis.current.publish("timeline:direct:#{@account.id}", @payload) if @account.local? - end - def redis Redis.current end From 61d44dd11ffbe965319680cbfb9e787811c11b94 Mon Sep 17 00:00:00 2001 From: Eugen Rochko Date: Thu, 11 Oct 2018 02:10:15 +0200 Subject: [PATCH 03/87] Fix typo in ActivityPub Create handler (#8952) Regression from #8951 --- app/lib/activitypub/activity/create.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/lib/activitypub/activity/create.rb b/app/lib/activitypub/activity/create.rb index b889461cb0..73475bf029 100644 --- a/app/lib/activitypub/activity/create.rb +++ b/app/lib/activitypub/activity/create.rb @@ -69,7 +69,7 @@ class ActivityPub::Activity::Create < ActivityPub::Activity def attach_tags(status) @tags.each do |tag| status.tags << tag - TrendingTags.record_use!(hashtag, status.account, status.created_at) if status.public_visibility? + TrendingTags.record_use!(tag, status.account, status.created_at) if status.public_visibility? end @mentions.each do |mention| From e6c01171dee34896b9409448c8fce8759bbaf27b Mon Sep 17 00:00:00 2001 From: Eugen Rochko Date: Thu, 11 Oct 2018 02:29:32 +0200 Subject: [PATCH 04/87] Bump version to 2.5.1 (#8953) --- CHANGELOG.md | 10 ++++++++++ lib/mastodon/version.rb | 2 +- 2 files changed, 11 insertions(+), 1 deletion(-) create mode 100644 CHANGELOG.md diff --git a/CHANGELOG.md b/CHANGELOG.md new file mode 100644 index 0000000000..220cb65915 --- /dev/null +++ b/CHANGELOG.md @@ -0,0 +1,10 @@ +## 2.5.1 + +- Fix some local images not having their EXIF metadata stripped on upload (#8714) +- Fix class autoloading issue in ActivityPub Create handler (#8820) +- Fix cache statistics not being sent via statsd when statsd enabled (#8831) +- Fix being able to enable a disabled relay via ActivityPub Accept handler (#8864) +- Bump nokogiri from 1.8.4 to 1.8.5 (#8881) +- Bump puma from 3.11.4 to 3.12.0 (#8883) +- Fix database migrations for PostgreSQL below 9.5 (#8903) +- Fix being able to report statuses not belonging to the reported account (#8916) diff --git a/lib/mastodon/version.rb b/lib/mastodon/version.rb index 0e41a9a6d9..e6d3af35db 100644 --- a/lib/mastodon/version.rb +++ b/lib/mastodon/version.rb @@ -13,7 +13,7 @@ module Mastodon end def patch - 0 + 1 end def pre From 18e7ef6edabf85020f04fe6582ad5cdaae253d8a Mon Sep 17 00:00:00 2001 From: Eugen Rochko Date: Thu, 11 Oct 2018 19:24:43 +0200 Subject: [PATCH 05/87] Add check for missing tag param in streaming API (#8955) * Add check for missing tag param in streaming API Fixes error: ``` TypeError: Cannot read property 'toLowerCase' of undefined at app.get (.../streaming/index.js:493:50) ``` * Fix code style issues --- streaming/index.js | 36 ++++++++++++++++++++++++++++++++---- 1 file changed, 32 insertions(+), 4 deletions(-) diff --git a/streaming/index.js b/streaming/index.js index debf7c8bf7..3a01be66a5 100644 --- a/streaming/index.js +++ b/streaming/index.js @@ -449,6 +449,11 @@ const startWorker = (workerId) => { }); }; + const httpNotFound = res => { + res.writeHead(404, { 'Content-Type': 'application/json' }); + res.end(JSON.stringify({ error: 'Not found' })); + }; + app.use(setRequestId); app.use(setRemoteAddress); app.use(allowCrossDomain); @@ -490,11 +495,25 @@ const startWorker = (workerId) => { }); app.get('/api/v1/streaming/hashtag', (req, res) => { - streamFrom(`timeline:hashtag:${req.query.tag.toLowerCase()}`, req, streamToHttp(req, res), streamHttpEnd(req), true); + const { tag } = req.query; + + if (!tag || tag.length === 0) { + httpNotFound(res); + return; + } + + streamFrom(`timeline:hashtag:${tag.toLowerCase()}`, req, streamToHttp(req, res), streamHttpEnd(req), true); }); app.get('/api/v1/streaming/hashtag/local', (req, res) => { - streamFrom(`timeline:hashtag:${req.query.tag.toLowerCase()}:local`, req, streamToHttp(req, res), streamHttpEnd(req), true); + const { tag } = req.query; + + if (!tag || tag.length === 0) { + httpNotFound(res); + return; + } + + streamFrom(`timeline:hashtag:${tag.toLowerCase()}:local`, req, streamToHttp(req, res), streamHttpEnd(req), true); }); app.get('/api/v1/streaming/list', (req, res) => { @@ -502,8 +521,7 @@ const startWorker = (workerId) => { authorizeListAccess(listId, req, authorized => { if (!authorized) { - res.writeHead(404, { 'Content-Type': 'application/json' }); - res.end(JSON.stringify({ error: 'Not found' })); + httpNotFound(res); return; } @@ -553,9 +571,19 @@ const startWorker = (workerId) => { streamFrom(channel, req, streamToWs(req, ws), streamWsEnd(req, ws, subscriptionHeartbeat(channel)), true); break; case 'hashtag': + if (!location.query.tag || location.query.tag.length === 0) { + ws.close(); + return; + } + streamFrom(`timeline:hashtag:${location.query.tag.toLowerCase()}`, req, streamToWs(req, ws), streamWsEnd(req, ws), true); break; case 'hashtag:local': + if (!location.query.tag || location.query.tag.length === 0) { + ws.close(); + return; + } + streamFrom(`timeline:hashtag:${location.query.tag.toLowerCase()}:local`, req, streamToWs(req, ws), streamWsEnd(req, ws), true); break; case 'list': From 9ece873d62a483abd86221fb9780ed4f65243e96 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" Date: Thu, 11 Oct 2018 19:26:39 +0200 Subject: [PATCH 06/87] Bump doorkeeper from 5.0.0 to 5.0.1 (#8954) Bumps [doorkeeper](https://github.com/doorkeeper-gem/doorkeeper) from 5.0.0 to 5.0.1. - [Release notes](https://github.com/doorkeeper-gem/doorkeeper/releases) - [Changelog](https://github.com/doorkeeper-gem/doorkeeper/blob/master/NEWS.md) - [Commits](https://github.com/doorkeeper-gem/doorkeeper/compare/v5.0.0...v5.0.1) Signed-off-by: dependabot[bot] --- Gemfile.lock | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Gemfile.lock b/Gemfile.lock index 8e016adc8b..3245c2d286 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -182,7 +182,7 @@ GEM docile (1.3.0) domain_name (0.5.20180417) unf (>= 0.0.5, < 1.0.0) - doorkeeper (5.0.0) + doorkeeper (5.0.1) railties (>= 4.2) dotenv (2.5.0) dotenv-rails (2.5.0) From 2d27c110610a848d30fe150c58bbd60ebf6fab7c Mon Sep 17 00:00:00 2001 From: ThibG Date: Thu, 11 Oct 2018 20:35:46 +0200 Subject: [PATCH 07/87] Set Content-Security-Policy rules through RoR's config (#8957) * Set CSP rules in RoR's configuration * Override CSP setting in the embed controller to allow frames --- app/controllers/statuses_controller.rb | 4 +++ .../initializers/{ostatus.rb => 1_hosts.rb} | 0 .../initializers/content_security_policy.rb | 25 +++++++++++-------- 3 files changed, 18 insertions(+), 11 deletions(-) rename config/initializers/{ostatus.rb => 1_hosts.rb} (100%) diff --git a/app/controllers/statuses_controller.rb b/app/controllers/statuses_controller.rb index d4ad3df601..0f3fe198f4 100644 --- a/app/controllers/statuses_controller.rb +++ b/app/controllers/statuses_controller.rb @@ -19,6 +19,10 @@ class StatusesController < ApplicationController before_action :set_referrer_policy_header, only: [:show] before_action :set_cache_headers + content_security_policy only: :embed do |p| + p.frame_ancestors(false) + end + def show respond_to do |format| format.html do diff --git a/config/initializers/ostatus.rb b/config/initializers/1_hosts.rb similarity index 100% rename from config/initializers/ostatus.rb rename to config/initializers/1_hosts.rb diff --git a/config/initializers/content_security_policy.rb b/config/initializers/content_security_policy.rb index 37f2c0d450..f84116d73a 100644 --- a/config/initializers/content_security_policy.rb +++ b/config/initializers/content_security_policy.rb @@ -2,17 +2,20 @@ # For further information see the following documentation # https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Content-Security-Policy -# Rails.application.config.content_security_policy do |p| -# p.default_src :self, :https -# p.font_src :self, :https, :data -# p.img_src :self, :https, :data -# p.object_src :none -# p.script_src :self, :https -# p.style_src :self, :https, :unsafe_inline -# -# # Specify URI for violation reports -# # p.report_uri "/csp-violation-report-endpoint" -# end +assets_host = Rails.configuration.action_controller.asset_host || "https://#{ENV['WEB_DOMAIN'] || ENV['LOCAL_DOMAIN']}" + +Rails.application.config.content_security_policy do |p| + p.base_uri :none + p.default_src :none + p.frame_ancestors :none + p.script_src :self, assets_host + p.font_src :self, assets_host + p.img_src :self, :https, :data, :blob + p.style_src :self, :unsafe_inline, assets_host + p.media_src :self, :data, assets_host + p.frame_src :self, :https + p.connect_src :self, assets_host, Rails.configuration.x.streaming_api_base_url +end # Report CSP violations to a specified URI # For further information see the following documentation: From 21ad21cb507d7a5f48ef8ee726b2f9308052aa9d Mon Sep 17 00:00:00 2001 From: Eugen Rochko Date: Fri, 12 Oct 2018 00:15:55 +0200 Subject: [PATCH 08/87] Improve signature verification safeguards (#8959) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Downcase signed_headers string before building the signed string The HTTP Signatures draft does not mandate the “headers” field to be downcased, but mandates the header field names to be downcased in the signed string, which means that prior to this patch, Mastodon could fail to process signatures from some compliant clients. It also means that it would not actually check the Digest of non-compliant clients that wouldn't use a lowercased Digest field name. Thankfully, I don't know of any such client. * Revert "Remove dead code (#8919)" This reverts commit a00ce8c92c06f42109aad5cfe65d46862cf037bb. * Restore time window checking, change it to 12 hours By checking the Date header, we can prevent replaying old vulnerable signatures. The focus is to prevent replaying old vulnerable requests from software that has been fixed in the meantime, so a somewhat long window should be fine and accounts for timezone misconfiguration. * Escape users' URLs when formatting them Fixes possible HTML injection * Escape all string interpolations in Formatter class Slightly improve performance by reducing class allocations from repeated Formatter#encode calls * Fix code style issues --- .../concerns/signature_verification.rb | 18 +++++++++++++- app/lib/formatter.rb | 16 ++++++++----- .../concerns/signature_verification_spec.rb | 24 +++++++++++++++++++ 3 files changed, 51 insertions(+), 7 deletions(-) diff --git a/app/controllers/concerns/signature_verification.rb b/app/controllers/concerns/signature_verification.rb index 5f95fa3461..e5d5e2ca61 100644 --- a/app/controllers/concerns/signature_verification.rb +++ b/app/controllers/concerns/signature_verification.rb @@ -22,6 +22,12 @@ module SignatureVerification return end + if request.headers['Date'].present? && !matches_time_window? + @signature_verification_failure_reason = 'Signed request date outside acceptable time window' + @signed_request_account = nil + return + end + raw_signature = request.headers['Signature'] signature_params = {} @@ -76,7 +82,7 @@ module SignatureVerification def build_signed_string(signed_headers) signed_headers = 'date' if signed_headers.blank? - signed_headers.split(' ').map do |signed_header| + signed_headers.downcase.split(' ').map do |signed_header| if signed_header == Request::REQUEST_TARGET "#{Request::REQUEST_TARGET}: #{request.method.downcase} #{request.path}" elsif signed_header == 'digest' @@ -87,6 +93,16 @@ module SignatureVerification end.join("\n") end + def matches_time_window? + begin + time_sent = Time.httpdate(request.headers['Date']) + rescue ArgumentError + return false + end + + (Time.now.utc - time_sent).abs <= 12.hours + end + def body_digest "SHA-256=#{Digest::SHA256.base64digest(request_body)}" end diff --git a/app/lib/formatter.rb b/app/lib/formatter.rb index 8b694536c2..35d5a09b76 100644 --- a/app/lib/formatter.rb +++ b/app/lib/formatter.rb @@ -90,8 +90,12 @@ class Formatter private + def html_entities + @html_entities ||= HTMLEntities.new + end + def encode(html) - HTMLEntities.new.encode(html) + html_entities.encode(html) end def encode_and_link_urls(html, accounts = nil, options = {}) @@ -143,7 +147,7 @@ class Formatter emoji = emoji_map[shortcode] if emoji - replacement = "\":#{shortcode}:\"" + replacement = "\":#{encode(shortcode)}:\"" before_html = shortname_start_index.positive? ? html[0..shortname_start_index - 1] : '' html = before_html + replacement + html[i + 1..-1] i += replacement.size - (shortcode.size + 2) - 1 @@ -212,7 +216,7 @@ class Formatter return link_to_account(acct) unless linkable_accounts account = linkable_accounts.find { |item| TagManager.instance.same_acct?(item.acct, acct) } - account ? mention_html(account) : "@#{acct}" + account ? mention_html(account) : "@#{encode(acct)}" end def link_to_account(acct) @@ -221,7 +225,7 @@ class Formatter domain = nil if TagManager.instance.local_domain?(domain) account = EntityCache.instance.mention(username, domain) - account ? mention_html(account) : "@#{acct}" + account ? mention_html(account) : "@#{encode(acct)}" end def link_to_hashtag(entity) @@ -239,10 +243,10 @@ class Formatter end def hashtag_html(tag) - "##{tag}" + "##{encode(tag)}" end def mention_html(account) - "@#{account.username}" + "@#{encode(account.username)}" end end diff --git a/spec/controllers/concerns/signature_verification_spec.rb b/spec/controllers/concerns/signature_verification_spec.rb index 3daf1fc4e8..7206900971 100644 --- a/spec/controllers/concerns/signature_verification_spec.rb +++ b/spec/controllers/concerns/signature_verification_spec.rb @@ -73,6 +73,30 @@ describe ApplicationController, type: :controller do end end + context 'with request older than a day' do + before do + get :success + + fake_request = Request.new(:get, request.url) + fake_request.add_headers({ 'Date' => 2.days.ago.utc.httpdate }) + fake_request.on_behalf_of(author) + + request.headers.merge!(fake_request.headers) + end + + describe '#signed_request?' do + it 'returns true' do + expect(controller.signed_request?).to be true + end + end + + describe '#signed_request_account' do + it 'returns nil' do + expect(controller.signed_request_account).to be_nil + end + end + end + context 'with body' do before do post :success, body: 'Hello world' From ef43f1d2caf874ecc6d82f44e9f2bab5a6e64144 Mon Sep 17 00:00:00 2001 From: Eugen Rochko Date: Fri, 12 Oct 2018 00:24:09 +0200 Subject: [PATCH 09/87] Bump version to 2.5.2 (#8960) --- CHANGELOG.md | 4 ++++ lib/mastodon/version.rb | 2 +- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 220cb65915..75a51fc7c6 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,7 @@ +## 2.5.2 + +- Fix XSS vulnerability (#8959) + ## 2.5.1 - Fix some local images not having their EXIF metadata stripped on upload (#8714) diff --git a/lib/mastodon/version.rb b/lib/mastodon/version.rb index e6d3af35db..a49e7f102f 100644 --- a/lib/mastodon/version.rb +++ b/lib/mastodon/version.rb @@ -13,7 +13,7 @@ module Mastodon end def patch - 1 + 2 end def pre From 8fd2cc54c19fa69a6bfcd06d61d7ab7774215100 Mon Sep 17 00:00:00 2001 From: Eugen Rochko Date: Fri, 12 Oct 2018 01:36:51 +0200 Subject: [PATCH 10/87] Fix type of conversation ID in conversations API (#8961) --- app/serializers/rest/conversation_serializer.rb | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/app/serializers/rest/conversation_serializer.rb b/app/serializers/rest/conversation_serializer.rb index 08cea47d22..884253f893 100644 --- a/app/serializers/rest/conversation_serializer.rb +++ b/app/serializers/rest/conversation_serializer.rb @@ -4,4 +4,8 @@ class REST::ConversationSerializer < ActiveModel::Serializer attribute :id has_many :participant_accounts, key: :accounts, serializer: REST::AccountSerializer has_one :last_status, serializer: REST::StatusSerializer + + def id + object.id.to_s + end end From edc7f895beb80ea00b5c2c933975b210a19eb017 Mon Sep 17 00:00:00 2001 From: Eugen Rochko Date: Fri, 12 Oct 2018 01:43:09 +0200 Subject: [PATCH 11/87] Fix CSP headers blocking media and development environment (#8962) Regression from #8957 --- .../initializers/content_security_policy.rb | 20 ++++++++++++++----- 1 file changed, 15 insertions(+), 5 deletions(-) diff --git a/config/initializers/content_security_policy.rb b/config/initializers/content_security_policy.rb index f84116d73a..962b871a2a 100644 --- a/config/initializers/content_security_policy.rb +++ b/config/initializers/content_security_policy.rb @@ -2,19 +2,29 @@ # For further information see the following documentation # https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Content-Security-Policy -assets_host = Rails.configuration.action_controller.asset_host || "https://#{ENV['WEB_DOMAIN'] || ENV['LOCAL_DOMAIN']}" +base_host = Rails.configuration.x.web_domain +assets_host = Rails.configuration.action_controller.asset_host +assets_host ||= "http#{Rails.configuration.x.use_https ? 's' : ''}://#{base_host}" Rails.application.config.content_security_policy do |p| p.base_uri :none p.default_src :none p.frame_ancestors :none - p.script_src :self, assets_host p.font_src :self, assets_host - p.img_src :self, :https, :data, :blob + p.img_src :self, :https, :data, :blob, assets_host p.style_src :self, :unsafe_inline, assets_host - p.media_src :self, :data, assets_host + p.media_src :self, :https, :data, assets_host p.frame_src :self, :https - p.connect_src :self, assets_host, Rails.configuration.x.streaming_api_base_url + + if Rails.env.development? + webpacker_urls = %w(ws http).map { |protocol| "#{protocol}#{Webpacker.dev_server.https? ? 's' : ''}://#{Webpacker.dev_server.host_with_port}" } + + p.connect_src :self, assets_host, Rails.configuration.x.streaming_api_base_url, *webpacker_urls + p.script_src :self, :unsafe_inline, :unsafe_eval, assets_host + else + p.connect_src :self, assets_host, Rails.configuration.x.streaming_api_base_url + p.script_src :self, assets_host + end end # Report CSP violations to a specified URI From 5cbbd2c3b5b1298dc0ed5a0110c20a49bdb7d84e Mon Sep 17 00:00:00 2001 From: Eugen Rochko Date: Fri, 12 Oct 2018 02:04:07 +0200 Subject: [PATCH 12/87] Fix microformats on statuses according to updated spec (#8958) --- .../stream_entries/_detailed_status.html.haml | 25 ++++++++--------- .../stream_entries/_simple_status.html.haml | 27 ++++++++++--------- 2 files changed, 27 insertions(+), 25 deletions(-) diff --git a/app/views/stream_entries/_detailed_status.html.haml b/app/views/stream_entries/_detailed_status.html.haml index 6cedfb337d..0b204d4374 100644 --- a/app/views/stream_entries/_detailed_status.html.haml +++ b/app/views/stream_entries/_detailed_status.html.haml @@ -1,16 +1,17 @@ .detailed-status.detailed-status--flex - = link_to TagManager.instance.url_for(status.account), class: 'detailed-status__display-name p-author h-card', target: stream_link_target, rel: 'noopener' do - .detailed-status__display-avatar - - if current_account&.user&.setting_auto_play_gif || autoplay - = image_tag status.account.avatar_original_url, width: 48, height: 48, alt: '', class: 'account__avatar u-photo' - - else - = image_tag status.account.avatar_static_url, width: 48, height: 48, alt: '', class: 'account__avatar u-photo' - %span.display-name - %bdi - %strong.display-name__html.p-name.emojify= display_name(status.account, custom_emojify: true, autoplay: autoplay) - %span.display-name__account - = acct(status.account) - = fa_icon('lock') if status.account.locked? + .p-author.h-card + = link_to TagManager.instance.url_for(status.account), class: 'detailed-status__display-name u-url', target: stream_link_target, rel: 'noopener' do + .detailed-status__display-avatar + - if current_account&.user&.setting_auto_play_gif || autoplay + = image_tag status.account.avatar_original_url, width: 48, height: 48, alt: '', class: 'account__avatar u-photo' + - else + = image_tag status.account.avatar_static_url, width: 48, height: 48, alt: '', class: 'account__avatar u-photo' + %span.display-name + %bdi + %strong.display-name__html.p-name.emojify= display_name(status.account, custom_emojify: true, autoplay: autoplay) + %span.display-name__account + = acct(status.account) + = fa_icon('lock') if status.account.locked? = account_action_button(status.account) diff --git a/app/views/stream_entries/_simple_status.html.haml b/app/views/stream_entries/_simple_status.html.haml index 7401f82c2a..1b00388b1f 100644 --- a/app/views/stream_entries/_simple_status.html.haml +++ b/app/views/stream_entries/_simple_status.html.haml @@ -4,19 +4,20 @@ %time.time-ago{ datetime: status.created_at.iso8601, title: l(status.created_at) }= l(status.created_at) %data.dt-published{ value: status.created_at.to_time.iso8601 } - = link_to TagManager.instance.url_for(status.account), class: 'status__display-name p-author h-card', target: stream_link_target, rel: 'noopener' do - .status__avatar - %div - - if current_account&.user&.setting_auto_play_gif || autoplay - = image_tag status.account.avatar_original_url, width: 48, height: 48, alt: '', class: 'u-photo account__avatar' - - else - = image_tag status.account.avatar_static_url, width: 48, height: 48, alt: '', class: 'u-photo account__avatar' - %span.display-name - %bdi - %strong.display-name__html.p-name.emojify= display_name(status.account, custom_emojify: true, autoplay: autoplay) - %span.display-name__account - = acct(status.account) - = fa_icon('lock') if status.account.locked? + .p-author.h-card + = link_to TagManager.instance.url_for(status.account), class: 'status__display-name u-url', target: stream_link_target, rel: 'noopener' do + .status__avatar + %div + - if current_account&.user&.setting_auto_play_gif || autoplay + = image_tag status.account.avatar_original_url, width: 48, height: 48, alt: '', class: 'u-photo account__avatar' + - else + = image_tag status.account.avatar_static_url, width: 48, height: 48, alt: '', class: 'u-photo account__avatar' + %span.display-name + %bdi + %strong.display-name__html.p-name.emojify= display_name(status.account, custom_emojify: true, autoplay: autoplay) + %span.display-name__account + = acct(status.account) + = fa_icon('lock') if status.account.locked? .status__content.emojify< - if status.spoiler_text? %p{ :style => ('margin-bottom: 0' unless current_account&.user&.setting_expand_spoilers) }< From 22de24b8ca707d8eac26eab6615377a290ff1f4e Mon Sep 17 00:00:00 2001 From: Eugen Rochko Date: Fri, 12 Oct 2018 02:19:10 +0200 Subject: [PATCH 13/87] Fix missing protocol in dns-prefetch, improve code style (#8963) Regression from #8942 --- app/helpers/application_helper.rb | 6 +++--- app/views/layouts/embedded.html.haml | 6 ++++++ config/environments/production.rb | 2 +- 3 files changed, 10 insertions(+), 4 deletions(-) diff --git a/app/helpers/application_helper.rb b/app/helpers/application_helper.rb index 8533b398a4..c33975cace 100644 --- a/app/helpers/application_helper.rb +++ b/app/helpers/application_helper.rb @@ -83,7 +83,7 @@ module ApplicationHelper end def cdn_host - ENV['CDN_HOST'].presence + Rails.configuration.action_controller.asset_host end def cdn_host? @@ -91,10 +91,10 @@ module ApplicationHelper end def storage_host - ENV['S3_ALIAS_HOST'].presence || ENV['S3_CLOUDFRONT_HOST'].presence + "https://#{ENV['S3_ALIAS_HOST'].presence || ENV['S3_CLOUDFRONT_HOST']}" end def storage_host? - storage_host.present? + ENV['S3_ALIAS_HOST'].present? || ENV['S3_CLOUDFRONT_HOST'].present? end end diff --git a/app/views/layouts/embedded.html.haml b/app/views/layouts/embedded.html.haml index ac11cfbe72..0503dcdc10 100644 --- a/app/views/layouts/embedded.html.haml +++ b/app/views/layouts/embedded.html.haml @@ -4,6 +4,12 @@ %meta{ charset: 'utf-8' }/ %meta{ name: 'robots', content: 'noindex' }/ + - if cdn_host? + %link{ rel: 'dns-prefetch', href: cdn_host }/ + + - if storage_host? + %link{ rel: 'dns-prefetch', href: storage_host }/ + = stylesheet_pack_tag 'common', media: 'all' = stylesheet_pack_tag Setting.default_settings['theme'], media: 'all' = javascript_pack_tag 'common', integrity: true, crossorigin: 'anonymous' diff --git a/config/environments/production.rb b/config/environments/production.rb index ed2d885b06..70baa6ad1a 100644 --- a/config/environments/production.rb +++ b/config/environments/production.rb @@ -13,7 +13,7 @@ Rails.application.configure do # Full error reports are disabled and caching is turned on. config.consider_all_requests_local = false config.action_controller.perform_caching = true - config.action_controller.asset_host = ENV['CDN_HOST'] if ENV.key?('CDN_HOST') + config.action_controller.asset_host = ENV['CDN_HOST'] if ENV['CDN_HOST'].present? # Ensures that a master key has been made available in either ENV["RAILS_MASTER_KEY"] # or in config/master.key. This key is used to decrypt credentials (and other encrypted files). From 9d4541c612b506889675c4c19ced5cd17ad3710f Mon Sep 17 00:00:00 2001 From: Eugen Rochko Date: Fri, 12 Oct 2018 04:04:08 +0200 Subject: [PATCH 14/87] Display customized mascot in web UI and fix admin form for it (#8964) Follow-up to #8766 --- app/javascript/mastodon/features/compose/index.js | 3 ++- app/javascript/mastodon/initial_state.js | 1 + app/serializers/initial_state_serializer.rb | 7 +++++++ app/views/admin/settings/edit.html.haml | 2 ++ 4 files changed, 12 insertions(+), 1 deletion(-) diff --git a/app/javascript/mastodon/features/compose/index.js b/app/javascript/mastodon/features/compose/index.js index cf1714b71b..d76cd76e61 100644 --- a/app/javascript/mastodon/features/compose/index.js +++ b/app/javascript/mastodon/features/compose/index.js @@ -13,6 +13,7 @@ import spring from 'react-motion/lib/spring'; import SearchResultsContainer from './containers/search_results_container'; import { changeComposing } from '../../actions/compose'; import elephantUIPlane from '../../../images/elephant_ui_plane.svg'; +import { mascot } from '../../initial_state'; const messages = defineMessages({ start: { id: 'getting_started.heading', defaultMessage: 'Getting started' }, @@ -107,7 +108,7 @@ class Compose extends React.PureComponent { {multiColumn && (
- +
)} } diff --git a/app/javascript/mastodon/initial_state.js b/app/javascript/mastodon/initial_state.js index 262c931950..6e9e3ddd84 100644 --- a/app/javascript/mastodon/initial_state.js +++ b/app/javascript/mastodon/initial_state.js @@ -14,5 +14,6 @@ export const me = getMeta('me'); export const searchEnabled = getMeta('search_enabled'); export const invitesEnabled = getMeta('invites_enabled'); export const version = getMeta('version'); +export const mascot = getMeta('mascot'); export default initialState; diff --git a/app/serializers/initial_state_serializer.rb b/app/serializers/initial_state_serializer.rb index cdc4708312..57f1e00984 100644 --- a/app/serializers/initial_state_serializer.rb +++ b/app/serializers/initial_state_serializer.rb @@ -16,6 +16,7 @@ class InitialStateSerializer < ActiveModel::Serializer search_enabled: Chewy.enabled?, version: Mastodon::Version.to_s, invites_enabled: Setting.min_invite_role == 'user', + mascot: instance_presenter.mascot&.file&.url, } if object.current_account @@ -56,4 +57,10 @@ class InitialStateSerializer < ActiveModel::Serializer def media_attachments { accept_content_types: MediaAttachment::IMAGE_FILE_EXTENSIONS + MediaAttachment::VIDEO_FILE_EXTENSIONS + MediaAttachment::IMAGE_MIME_TYPES + MediaAttachment::VIDEO_MIME_TYPES } end + + private + + def instance_presenter + @instance_presenter ||= InstancePresenter.new + end end diff --git a/app/views/admin/settings/edit.html.haml b/app/views/admin/settings/edit.html.haml index f3f9bdaf06..04b1a67540 100644 --- a/app/views/admin/settings/edit.html.haml +++ b/app/views/admin/settings/edit.html.haml @@ -26,6 +26,8 @@ = f.input :thumbnail, as: :file, wrapper: :with_block_label, label: t('admin.settings.thumbnail.title'), hint: t('admin.settings.thumbnail.desc_html') .fields-row__column.fields-row__column-6.fields-group = f.input :hero, as: :file, wrapper: :with_block_label, label: t('admin.settings.hero.title'), hint: t('admin.settings.hero.desc_html') + + .fields-row .fields-row__column.fields-row__column-6.fields-group = f.input :mascot, as: :file, wrapper: :with_block_label, label: t('admin.settings.mascot.title'), hint: t('admin.settings.mascot.desc_html') From 8ab081ec3245e70acb7878b7842cfa07ca050464 Mon Sep 17 00:00:00 2001 From: ThibG Date: Fri, 12 Oct 2018 19:07:30 +0200 Subject: [PATCH 15/87] Add manifest_src to CSP, add blob to connect_src (#8967) --- config/initializers/content_security_policy.rb | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/config/initializers/content_security_policy.rb b/config/initializers/content_security_policy.rb index 962b871a2a..59cfbba173 100644 --- a/config/initializers/content_security_policy.rb +++ b/config/initializers/content_security_policy.rb @@ -15,14 +15,15 @@ Rails.application.config.content_security_policy do |p| p.style_src :self, :unsafe_inline, assets_host p.media_src :self, :https, :data, assets_host p.frame_src :self, :https + p.manifest_src :self, assets_host if Rails.env.development? webpacker_urls = %w(ws http).map { |protocol| "#{protocol}#{Webpacker.dev_server.https? ? 's' : ''}://#{Webpacker.dev_server.host_with_port}" } - p.connect_src :self, assets_host, Rails.configuration.x.streaming_api_base_url, *webpacker_urls + p.connect_src :self, :blob, assets_host, Rails.configuration.x.streaming_api_base_url, *webpacker_urls p.script_src :self, :unsafe_inline, :unsafe_eval, assets_host else - p.connect_src :self, assets_host, Rails.configuration.x.streaming_api_base_url + p.connect_src :self, :blob, assets_host, Rails.configuration.x.streaming_api_base_url p.script_src :self, assets_host end end From 734d55c3cfbebb554c20e41ea8411a8195cd88bd Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" Date: Fri, 12 Oct 2018 22:48:16 +0200 Subject: [PATCH 16/87] Bump pundit from 1.1.0 to 2.0.0 (#8873) Bumps [pundit](https://github.com/varvet/pundit) from 1.1.0 to 2.0.0. - [Release notes](https://github.com/varvet/pundit/releases) - [Changelog](https://github.com/varvet/pundit/blob/master/CHANGELOG.md) - [Commits](https://github.com/varvet/pundit/compare/v1.1.0...v2.0.0) Signed-off-by: dependabot[bot] --- Gemfile | 2 +- Gemfile.lock | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/Gemfile b/Gemfile index 9cee35e4a5..0e50dce218 100644 --- a/Gemfile +++ b/Gemfile @@ -63,7 +63,7 @@ gem 'oj', '~> 3.6' gem 'ostatus2', '~> 2.0' gem 'ox', '~> 2.10' gem 'posix-spawn', git: 'https://github.com/rtomayko/posix-spawn', ref: '58465d2e213991f8afb13b984854a49fcdcc980c' -gem 'pundit', '~> 1.1' +gem 'pundit', '~> 2.0' gem 'premailer-rails' gem 'rack-attack', '~> 5.4' gem 'rack-cors', '~> 1.0', require: 'rack/cors' diff --git a/Gemfile.lock b/Gemfile.lock index 3245c2d286..024d3c6871 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -415,7 +415,7 @@ GEM pry (>= 0.10.4) public_suffix (3.0.3) puma (3.12.0) - pundit (1.1.0) + pundit (2.0.0) activesupport (>= 3.0.0) raabro (1.1.6) rack (2.0.5) @@ -724,7 +724,7 @@ DEPENDENCIES pry-byebug (~> 3.6) pry-rails (~> 0.3) puma (~> 3.12) - pundit (~> 1.1) + pundit (~> 2.0) rack-attack (~> 5.4) rack-cors (~> 1.0) rails (~> 5.2.1) From 7d182442a77e2b383998818d079684a148f4c1e4 Mon Sep 17 00:00:00 2001 From: Eugen Rochko Date: Sat, 13 Oct 2018 01:51:14 +0200 Subject: [PATCH 17/87] Weblate translations (2018-10-12) (#8972) * Translated using Weblate (Welsh) Currently translated at 64.4% (448 of 696 strings) Translation: Mastodon/Backend Translate-URL: https://weblate.joinmastodon.org/projects/mastodon/backend/cy/ * Translated using Weblate (Arabic) Currently translated at 98.0% (682 of 696 strings) Translation: Mastodon/Backend Translate-URL: https://weblate.joinmastodon.org/projects/mastodon/backend/ar/ * Translated using Weblate (French) Currently translated at 99.9% (695 of 696 strings) Translation: Mastodon/Backend Translate-URL: https://weblate.joinmastodon.org/projects/mastodon/backend/fr/ * Translated using Weblate (Arabic) Currently translated at 94.3% (82 of 87 strings) Translation: Mastodon/Preferences Translate-URL: https://weblate.joinmastodon.org/projects/mastodon/simple_form/ar/ * Translated using Weblate (Welsh) Currently translated at 88.7% (297 of 335 strings) Translation: Mastodon/React Translate-URL: https://weblate.joinmastodon.org/projects/mastodon/frontend/cy/ * Translated using Weblate (French) Currently translated at 100.0% (335 of 335 strings) Translation: Mastodon/React Translate-URL: https://weblate.joinmastodon.org/projects/mastodon/frontend/fr/ * Translated using Weblate (French) Currently translated at 100,0% (87 of 87 strings) Translation: Mastodon/Preferences Translate-URL: https://weblate.joinmastodon.org/projects/mastodon/simple_form/fr/ * Translated using Weblate (Czech) Currently translated at 100.0% (335 of 335 strings) Translation: Mastodon/React Translate-URL: https://weblate.joinmastodon.org/projects/mastodon/frontend/cs/ * Translated using Weblate (Czech) Currently translated at 100.0% (87 of 87 strings) Translation: Mastodon/Preferences Translate-URL: https://weblate.joinmastodon.org/projects/mastodon/simple_form/cs/ * Translated using Weblate (Czech) Currently translated at 99.9% (695 of 696 strings) Translation: Mastodon/Backend Translate-URL: https://weblate.joinmastodon.org/projects/mastodon/backend/cs/ * Translated using Weblate (Persian) Currently translated at 100.0% (335 of 335 strings) Translation: Mastodon/React Translate-URL: https://weblate.joinmastodon.org/projects/mastodon/frontend/fa/ * Translated using Weblate (Arabic) Currently translated at 94.6% (88 of 93 strings) Translation: Mastodon/Preferences Translate-URL: https://weblate.joinmastodon.org/projects/mastodon/simple_form/ar/ * Translated using Weblate (Arabic) Currently translated at 100.0% (335 of 335 strings) Translation: Mastodon/React Translate-URL: https://weblate.joinmastodon.org/projects/mastodon/frontend/ar/ * Translated using Weblate (Czech) Currently translated at 100.0% (93 of 93 strings) Translation: Mastodon/Preferences Translate-URL: https://weblate.joinmastodon.org/projects/mastodon/simple_form/cs/ * Translated using Weblate (Galician) Currently translated at 100,0% (93 of 93 strings) Translation: Mastodon/Preferences Translate-URL: https://weblate.joinmastodon.org/projects/mastodon/simple_form/gl/ * Translated using Weblate (Galician) Currently translated at 100,0% (696 of 696 strings) Translation: Mastodon/Backend Translate-URL: https://weblate.joinmastodon.org/projects/mastodon/backend/gl/ * Translated using Weblate (Greek) Currently translated at 100.0% (93 of 93 strings) Translation: Mastodon/Preferences Translate-URL: https://weblate.joinmastodon.org/projects/mastodon/simple_form/el/ * Translated using Weblate (Greek) Currently translated at 98.8% (331 of 335 strings) Translation: Mastodon/React Translate-URL: https://weblate.joinmastodon.org/projects/mastodon/frontend/el/ * Translated using Weblate (Greek) Currently translated at 99.7% (694 of 696 strings) Translation: Mastodon/Backend Translate-URL: https://weblate.joinmastodon.org/projects/mastodon/backend/el/ * Translated using Weblate (Persian) Currently translated at 100.0% (93 of 93 strings) Translation: Mastodon/Preferences Translate-URL: https://weblate.joinmastodon.org/projects/mastodon/simple_form/fa/ * Translated using Weblate (Czech) Currently translated at 99.9% (695 of 696 strings) Translation: Mastodon/Backend Translate-URL: https://weblate.joinmastodon.org/projects/mastodon/backend/cs/ * Translated using Weblate (French) Currently translated at 100,0% (93 of 93 strings) Translation: Mastodon/Preferences Translate-URL: https://weblate.joinmastodon.org/projects/mastodon/simple_form/fr/ * Translated using Weblate (French) Currently translated at 99.9% (695 of 696 strings) Translation: Mastodon/Backend Translate-URL: https://weblate.joinmastodon.org/projects/mastodon/backend/fr/ * Translated using Weblate (Japanese) Currently translated at 99.4% (692 of 696 strings) Translation: Mastodon/Backend Translate-URL: https://weblate.joinmastodon.org/projects/mastodon/backend/ja/ * Translated using Weblate (Corsican) Currently translated at 100.0% (93 of 93 strings) Translation: Mastodon/Preferences Translate-URL: https://weblate.joinmastodon.org/projects/mastodon/simple_form/co/ * Translated using Weblate (Corsican) Currently translated at 99.9% (695 of 696 strings) Translation: Mastodon/Backend Translate-URL: https://weblate.joinmastodon.org/projects/mastodon/backend/co/ * Translated using Weblate (German) Currently translated at 99.6% (693 of 696 strings) Translation: Mastodon/Backend Translate-URL: https://weblate.joinmastodon.org/projects/mastodon/backend/de/ * Translated using Weblate (German) Currently translated at 100,0% (93 of 93 strings) Translation: Mastodon/Preferences Translate-URL: https://weblate.joinmastodon.org/projects/mastodon/simple_form/de/ * Translated using Weblate (Japanese) Currently translated at 99.4% (692 of 696 strings) Translation: Mastodon/Backend Translate-URL: https://weblate.joinmastodon.org/projects/mastodon/backend/ja/ * Translated using Weblate (Japanese) Currently translated at 99.9% (695 of 696 strings) Translation: Mastodon/Backend Translate-URL: https://weblate.joinmastodon.org/projects/mastodon/backend/ja/ * Translated using Weblate (Japanese) Currently translated at 100.0% (335 of 335 strings) Translation: Mastodon/React Translate-URL: https://weblate.joinmastodon.org/projects/mastodon/frontend/ja/ * Translated using Weblate (Japanese) Currently translated at 94.6% (88 of 93 strings) Translation: Mastodon/Preferences Translate-URL: https://weblate.joinmastodon.org/projects/mastodon/simple_form/ja/ * i18n-tasks normalize * yarn manage:translations --- app/javascript/mastodon/locales/ar.json | 16 +- app/javascript/mastodon/locales/ast.json | 4 + app/javascript/mastodon/locales/bg.json | 4 + app/javascript/mastodon/locales/ca.json | 4 + app/javascript/mastodon/locales/co.json | 4 + app/javascript/mastodon/locales/cs.json | 8 +- app/javascript/mastodon/locales/cy.json | 671 +++++++++--------- app/javascript/mastodon/locales/da.json | 4 + app/javascript/mastodon/locales/de.json | 4 + .../mastodon/locales/defaultMessages.json | 9 + app/javascript/mastodon/locales/el.json | 6 +- app/javascript/mastodon/locales/en.json | 1 + app/javascript/mastodon/locales/eo.json | 4 + app/javascript/mastodon/locales/es.json | 4 + app/javascript/mastodon/locales/eu.json | 4 + app/javascript/mastodon/locales/fa.json | 6 +- app/javascript/mastodon/locales/fi.json | 4 + app/javascript/mastodon/locales/fr.json | 6 +- app/javascript/mastodon/locales/gl.json | 4 + app/javascript/mastodon/locales/he.json | 4 + app/javascript/mastodon/locales/hr.json | 4 + app/javascript/mastodon/locales/hu.json | 4 + app/javascript/mastodon/locales/hy.json | 4 + app/javascript/mastodon/locales/id.json | 4 + app/javascript/mastodon/locales/io.json | 4 + app/javascript/mastodon/locales/it.json | 4 + app/javascript/mastodon/locales/ja.json | 9 +- app/javascript/mastodon/locales/ka.json | 4 + app/javascript/mastodon/locales/ko.json | 4 + app/javascript/mastodon/locales/nl.json | 4 + app/javascript/mastodon/locales/no.json | 4 + app/javascript/mastodon/locales/oc.json | 4 + app/javascript/mastodon/locales/pl.json | 1 + app/javascript/mastodon/locales/pt-BR.json | 4 + app/javascript/mastodon/locales/pt.json | 4 + app/javascript/mastodon/locales/ro.json | 4 + app/javascript/mastodon/locales/ru.json | 4 + app/javascript/mastodon/locales/sk.json | 4 + app/javascript/mastodon/locales/sl.json | 4 + app/javascript/mastodon/locales/sr-Latn.json | 4 + app/javascript/mastodon/locales/sr.json | 4 + app/javascript/mastodon/locales/sv.json | 4 + app/javascript/mastodon/locales/ta.json | 4 + app/javascript/mastodon/locales/te.json | 4 + app/javascript/mastodon/locales/th.json | 4 + app/javascript/mastodon/locales/tr.json | 4 + app/javascript/mastodon/locales/uk.json | 4 + app/javascript/mastodon/locales/zh-CN.json | 4 + app/javascript/mastodon/locales/zh-HK.json | 4 + app/javascript/mastodon/locales/zh-TW.json | 4 + config/locales/ar.yml | 11 +- config/locales/co.yml | 14 +- config/locales/cs.yml | 28 +- config/locales/cy.yml | 30 +- config/locales/de.yml | 40 +- config/locales/el.yml | 12 + config/locales/fr.yml | 16 +- config/locales/gl.yml | 14 +- config/locales/ja.yml | 6 +- config/locales/simple_form.ar.yml | 11 + config/locales/simple_form.co.yml | 11 + config/locales/simple_form.cs.yml | 11 + config/locales/simple_form.de.yml | 11 + config/locales/simple_form.el.yml | 11 + config/locales/simple_form.fa.yml | 11 + config/locales/simple_form.fr.yml | 11 + config/locales/simple_form.gl.yml | 11 + config/locales/simple_form.ja.yml | 3 + 68 files changed, 775 insertions(+), 380 deletions(-) diff --git a/app/javascript/mastodon/locales/ar.json b/app/javascript/mastodon/locales/ar.json index a74207db6f..da79b62d25 100644 --- a/app/javascript/mastodon/locales/ar.json +++ b/app/javascript/mastodon/locales/ar.json @@ -15,7 +15,7 @@ "account.follows.empty": "هذا المستخدِم لا يتبع أحدًا بعد.", "account.follows_you": "يتابعك", "account.hide_reblogs": "إخفاء ترقيات @{name}", - "account.link_verified_on": "Ownership of this link was checked on {date}", + "account.link_verified_on": "تم التحقق مِن مالك هذا الرابط بتاريخ {date}", "account.media": "وسائط", "account.mention": "أُذكُر @{name}", "account.moved_to": "{name} إنتقل إلى :", @@ -91,8 +91,11 @@ "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.unfollow.confirm": "إلغاء المتابعة", "confirmations.unfollow.message": "متأكد من أنك تريد إلغاء متابعة {name} ؟", + "conversation.last_message": "Last message:", "embed.instructions": "يمكنكم إدماج هذا المنشور على موقعكم الإلكتروني عن طريق نسخ الشفرة أدناه.", "embed.preview": "هكذا ما سوف يبدو عليه :", "emoji_button.activity": "الأنشطة", @@ -113,9 +116,9 @@ "empty_column.community": "الخط الزمني المحلي فارغ. أكتب شيئا ما للعامة كبداية !", "empty_column.direct": "لم تتلق أية رسالة خاصة مباشِرة بعد. سوف يتم عرض الرسائل المباشرة هنا إن قمت بإرسال واحدة أو تلقيت البعض منها.", "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.favourited_statuses": "ليس لديك أية تبويقات مفضلة بعد. عندما ستقوم بالإعجاب بواحد، سيظهر هنا.", + "empty_column.favourites": "لم يقم أي أحد بالإعجاب بهذا التبويق بعد. عندما يقوم أحدهم بذلك سوف يظهر هنا.", + "empty_column.follow_requests": "ليس عندك أي طلب للمتابعة بعد. سوف تظهر طلباتك هنا إن قمت بتلقي البعض منها.", "empty_column.hashtag": "ليس هناك بعدُ أي محتوى ذو علاقة بهذا الوسم.", "empty_column.home": "إنّ الخيط الزمني لصفحتك الرئيسية فارغ. قم بزيارة {public} أو استخدم حقل البحث لكي تكتشف مستخدمين آخرين.", "empty_column.home.public_timeline": "الخيط العام", @@ -163,7 +166,7 @@ "keyboard_shortcuts.reply": "للردّ", "keyboard_shortcuts.requests": "لفتح قائمة طلبات المتابعة", "keyboard_shortcuts.search": "للتركيز على البحث", - "keyboard_shortcuts.start": "to open \"get started\" column", + "keyboard_shortcuts.start": "لفتح عمود \"هيا نبدأ\"", "keyboard_shortcuts.toggle_hidden": "لعرض أو إخفاء النص مِن وراء التحذير", "keyboard_shortcuts.toot": "لتحرير تبويق جديد", "keyboard_shortcuts.unfocus": "لإلغاء التركيز على حقل النص أو نافذة البحث", @@ -280,7 +283,7 @@ "status.cancel_reblog_private": "إلغاء الترقية", "status.cannot_reblog": "تعذرت ترقية هذا المنشور", "status.delete": "إحذف", - "status.detailed_status": "Detailed conversation view", + "status.detailed_status": "تفاصيل المحادثة", "status.direct": "رسالة خاصة إلى @{name}", "status.embed": "إدماج", "status.favourite": "أضف إلى المفضلة", @@ -294,6 +297,7 @@ "status.open": "وسع هذه المشاركة", "status.pin": "تدبيس على الملف الشخصي", "status.pinned": "تبويق مثبَّت", + "status.read_more": "Read more", "status.reblog": "رَقِّي", "status.reblog_private": "القيام بالترقية إلى الجمهور الأصلي", "status.reblogged_by": "رقّاه {name}", diff --git a/app/javascript/mastodon/locales/ast.json b/app/javascript/mastodon/locales/ast.json index 147c5ad2a0..5e258c58cc 100644 --- a/app/javascript/mastodon/locales/ast.json +++ b/app/javascript/mastodon/locales/ast.json @@ -91,8 +91,11 @@ "confirmations.mute.message": "¿De xuru que quies silenciar a {name}?", "confirmations.redraft.confirm": "Delete & redraft", "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.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}?", + "conversation.last_message": "Last message:", "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": "Actividá", @@ -294,6 +297,7 @@ "status.open": "Espander esti estáu", "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", diff --git a/app/javascript/mastodon/locales/bg.json b/app/javascript/mastodon/locales/bg.json index 756c333935..5daf5d6395 100644 --- a/app/javascript/mastodon/locales/bg.json +++ b/app/javascript/mastodon/locales/bg.json @@ -91,8 +91,11 @@ "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? You will lose all replies, boosts and favourites to it.", + "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}?", + "conversation.last_message": "Last message:", "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", @@ -294,6 +297,7 @@ "status.open": "Expand this status", "status.pin": "Pin on profile", "status.pinned": "Pinned toot", + "status.read_more": "Read more", "status.reblog": "Споделяне", "status.reblog_private": "Boost to original audience", "status.reblogged_by": "{name} сподели", diff --git a/app/javascript/mastodon/locales/ca.json b/app/javascript/mastodon/locales/ca.json index 4701c93168..f2235b1902 100644 --- a/app/javascript/mastodon/locales/ca.json +++ b/app/javascript/mastodon/locales/ca.json @@ -91,8 +91,11 @@ "confirmations.mute.message": "Estàs segur que vols silenciar {name}?", "confirmations.redraft.confirm": "Esborrar i refer", "confirmations.redraft.message": "Estàs segur que vols esborrar aquesta publicació i tornar a redactar-la? Perderàs totes els impulsos i favorits, i les respostes a la publicació original es quedaran orfes.", + "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": "Deixa de seguir", "confirmations.unfollow.message": "Estàs segur que vols deixar de seguir {name}?", + "conversation.last_message": "Last message:", "embed.instructions": "Incrusta aquest estat al lloc web copiant el codi a continuació.", "embed.preview": "Aquí tenim quin aspecte tindrá:", "emoji_button.activity": "Activitat", @@ -294,6 +297,7 @@ "status.open": "Ampliar aquest estat", "status.pin": "Fixat en el perfil", "status.pinned": "Toot fixat", + "status.read_more": "Read more", "status.reblog": "Impuls", "status.reblog_private": "Impulsar a l'audiència original", "status.reblogged_by": "{name} ha retootejat", diff --git a/app/javascript/mastodon/locales/co.json b/app/javascript/mastodon/locales/co.json index 62976c98e4..4507deddbc 100644 --- a/app/javascript/mastodon/locales/co.json +++ b/app/javascript/mastodon/locales/co.json @@ -91,8 +91,11 @@ "confirmations.mute.message": "Site sicuru·a che vulete piattà @{name}?", "confirmations.redraft.confirm": "Sguassà è riscrive", "confirmations.redraft.message": "Site sicuru·a chè vulete sguassà stu statutu è riscrivelu? I favuriti è spartere saranu persi, è e risposte diventeranu orfane.", + "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": "Disabbunassi", "confirmations.unfollow.message": "Site sicuru·a ch'ùn vulete più siguità @{name}?", + "conversation.last_message": "Last message:", "embed.instructions": "Integrà stu statutu à u vostru situ cù u codice quì sottu.", "embed.preview": "Assumiglierà à qualcosa cusì:", "emoji_button.activity": "Attività", @@ -294,6 +297,7 @@ "status.open": "Apre stu statutu", "status.pin": "Puntarulà à u prufile", "status.pinned": "Statutu puntarulatu", + "status.read_more": "Read more", "status.reblog": "Sparte", "status.reblog_private": "Sparte à l'audienza uriginale", "status.reblogged_by": "{name} hà spartutu", diff --git a/app/javascript/mastodon/locales/cs.json b/app/javascript/mastodon/locales/cs.json index 2c34fd34ce..116a65468b 100644 --- a/app/javascript/mastodon/locales/cs.json +++ b/app/javascript/mastodon/locales/cs.json @@ -8,14 +8,14 @@ "account.domain_blocked": "Doména skryta", "account.edit_profile": "Upravit profil", "account.endorse": "Představit na profilu", - "account.follow": "Sleduj", + "account.follow": "Sledovat", "account.followers": "Sledovatelé", "account.followers.empty": "Tohoto uživatele ještě nikdo nesleduje.", "account.follows": "Sleduje", "account.follows.empty": "Tento uživatel ještě nikoho nesleduje.", "account.follows_you": "Sleduje vás", "account.hide_reblogs": "Skrýt boosty od uživatele @{name}", - "account.link_verified_on": "Ownership of this link was checked on {date}", + "account.link_verified_on": "Vlastnictví tohoto odkazu bylo zkontrolováno {date}", "account.media": "Média", "account.mention": "Zmínit uživatele @{name}", "account.moved_to": "{name} se přesunul/a na:", @@ -91,8 +91,11 @@ "confirmations.mute.message": "Jste si jistý/á, že chcete ignorovat uživatele {name}?", "confirmations.redraft.confirm": "Vymazat a přepsat", "confirmations.redraft.message": "Jste si jistý/á, že chcete vymazat a přepsat tento příspěvek? Oblíbení a boosty budou ztraceny a odpovědi na původní příspěvek budou opuštěny.", + "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": "Přestat sledovat", "confirmations.unfollow.message": "jste si jistý/á, že chcete přestat sledovat uživatele {name}?", + "conversation.last_message": "Last message:", "embed.instructions": "Pro přidání příspěvku na vaši webovou stránku zkopírujte níže uvedený kód.", "embed.preview": "Takhle to bude vypadat:", "emoji_button.activity": "Aktivita", @@ -294,6 +297,7 @@ "status.open": "Rozbalit tento příspěvek", "status.pin": "Připnout na profil", "status.pinned": "Připnutý toot", + "status.read_more": "Read more", "status.reblog": "Boostnout", "status.reblog_private": "Boostnout původnímu publiku", "status.reblogged_by": "{name} boostnul/a", diff --git a/app/javascript/mastodon/locales/cy.json b/app/javascript/mastodon/locales/cy.json index 90f3f8e301..4816a0e350 100644 --- a/app/javascript/mastodon/locales/cy.json +++ b/app/javascript/mastodon/locales/cy.json @@ -1,335 +1,340 @@ { - "account.badges.bot": "Bot", - "account.block": "Blociwch @{name}", - "account.block_domain": "Cuddiwch bopeth 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", - "account.follow": "Dilyn", - "account.followers": "Dilynwyr", - "account.followers.empty": "Nid oes neb yn dilyn y defnyddiwr hwn eto.", - "account.follows": "Yn dilyn", - "account.follows.empty": "Nid yw'r defnyddiwr hwn yn dilyn unrhyw un eto.", - "account.follows_you": "Yn eich dilyn chi", - "account.hide_reblogs": "Cuddio bwstiau o @{name}", - "account.media": "Cyfryngau", - "account.mention": "Crybwyll @{name}", - "account.moved_to": "Mae @{name} wedi symud i:", - "account.mute": "Tawelu @{name}", - "account.mute_notifications": "Cuddio hysbysiadau o @{name}", - "account.muted": "Distewyd", - "account.posts": "Tŵtiau", - "account.posts_with_replies": "Tŵtiau ac atebion", - "account.report": "Adroddwch @{name}", - "account.requested": "Aros am gymeradwyaeth. Cliciwch er mwyn canslo cais dilyn", - "account.share": "Rhannwch broffil @{name}", - "account.show_reblogs": "Dangoswch bwstiau o @{name}", - "account.unblock": "Dadflociwch @{name}", - "account.unblock_domain": "Dadguddiwch {domain}", - "account.unendorse": "Peidwch a'i arddangos ar fy mhroffil", - "account.unfollow": "Daddilynwch", - "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", - "bundle_column_error.body": "Aeth rhywbeth o'i le tra'n llwytho'r elfen hon.", - "bundle_column_error.retry": "Ceisiwch eto", - "bundle_column_error.title": "Gwall rhwydwaith", - "bundle_modal_error.close": "Cau", - "bundle_modal_error.message": "Aeth rhywbeth o'i le tra'n llwytho'r elfen hon.", - "bundle_modal_error.retry": "Ceiswich eto", - "column.blocks": "Defnyddwyr a flociwyd", - "column.community": "Llinell amser lleol", - "column.direct": "Negeseuon preifat", - "column.domain_blocks": "Parthau cuddiedig", - "column.favourites": "Ffefrynnau", - "column.follow_requests": "Ceisiadau dilyn", - "column.home": "Hafan", - "column.lists": "Rhestrau", - "column.mutes": "Defnyddwyr a ddistewyd", - "column.notifications": "Hysbysiadau", - "column.pins": "Tŵtiau wedi eu pinio", - "column.public": "", - "column_back_button.label": "Nôl", - "column_header.hide_settings": "Cuddiwch dewisiadau", - "column_header.moveLeft_settings": "Symudwch y golofn i'r chwith", - "column_header.moveRight_settings": "Symudwch y golofn i'r dde", - "column_header.pin": "Piniwch", - "column_header.show_settings": "Dangos gosodiadau", - "column_header.unpin": "Dadbiniwch", - "column_subheading.settings": "Gosodiadau", - "community.column_settings.media_only": "Cyfryngau yn unig", - "compose_form.direct_message_warning": "Mi fydd y tŵt hwn ond yn cael ei anfon at y defnyddwyr sy'n cael eu crybwyll.", - "compose_form.direct_message_warning_learn_more": "Dysgwch fwy", - "compose_form.hashtag_warning": "Ni fydd y tŵt hwn wedi ei restru o dan unrhyw hashnod gan ei fod heb ei restru. Dim ond tŵtiau cyhoeddus gellid chwilota amdanynt drwy hashnod.", - "compose_form.lock_disclaimer": "Nid yw eich cyfri wedi'i {locked}. Gall unrhyw un eich dilyn i weld eich POSTS dilynwyr-yn-unig.", - "compose_form.lock_disclaimer.lock": "wedi ei gloi", - "compose_form.placeholder": "Be syd ar eich meddwl?", - "compose_form.publish": "Tŵt", - "compose_form.publish_loud": "{publish}!", - "compose_form.sensitive.marked": "", - "compose_form.sensitive.unmarked": "", - "compose_form.spoiler.marked": "Testun wedi ei guddio gan rybudd", - "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.confirm": "Blociwch", - "confirmations.block.message": "Ydych chi'n sicr eich bod eisiau blocio {name}?", - "confirmations.delete.confirm": "Dileu", - "confirmations.delete.message": "Ydych chi'n sicr eich bod eisiau dileu y statws hwn?", - "confirmations.delete_list.confirm": "Dileu", - "confirmations.delete_list.message": "Ydych chi'n sicr eich bod eisiau dileu y rhestr hwn am byth?", - "confirmations.domain_block.confirm": "", - "confirmations.domain_block.message": "", - "confirmations.mute.confirm": "Tawelu", - "confirmations.mute.message": "Ydych chi'n sicr eich bod am ddistewi {name}?", - "confirmations.redraft.confirm": "Dilëwch & ailddrafftio", - "confirmations.redraft.message": "Ydych chi'n siwr eich bod eisiau dileu y statws hwn a'i ailddrafftio? Bydd ffefrynnau a bwstiau'n cael ei colli, a bydd ymatebion i'r statws gwreiddiol yn cael eu hamddifadu.", - "confirmations.unfollow.confirm": "Dad-ddilynwch", - "confirmations.unfollow.message": "Ydych chi'n sicr eich bod am ddad-ddilyn {name}?", - "embed.instructions": "Mewnblannwch y statws hwn ar eich gwefan drwy gopïo'r côd isod.", - "embed.preview": "Dyma sut olwg fydd arno:", - "emoji_button.activity": "Gweithgarwch", - "emoji_button.custom": "", - "emoji_button.flags": "Baneri", - "emoji_button.food": "Bwyd a Diod", - "emoji_button.label": "Mewnosodwch emoji", - "emoji_button.nature": "Natur", - "emoji_button.not_found": "Dim emojos!! (╯°□°)╯︵ ┻━┻", - "emoji_button.objects": "Gwrthrychau", - "emoji_button.people": "Pobl", - "emoji_button.recent": "Defnyddir yn aml", - "emoji_button.search": "Chwilio...", - "emoji_button.search_results": "Canlyniadau chwilio", - "emoji_button.symbols": "Symbolau", - "emoji_button.travel": "Teithio & Llefydd", - "empty_column.blocks": "Nid ydych wedi blocio unrhyw ddefnyddwyr eto.", - "empty_column.community": "", - "empty_column.direct": "Nid oes gennych unrhyw negeseuon preifat eto. Pan y byddwch yn anfon neu derbyn un, mi fydd yn ymddangos yma.", - "empty_column.domain_blocks": "Nid oes yna unrhyw barthau cuddiedig eto.", - "empty_column.favourited_statuses": "Nid oes gennych unrhyw hoff dwtiau eto. Pan y byddwch yn hoffi un, mi fydd yn ymddangos yma.", - "empty_column.favourites": "Nid oes neb wedi hoffi'r tŵt yma eto. Pan bydd rhywun yn ei hoffi, mi fyddent yn ymddangos yma.", - "empty_column.follow_requests": "Nid oes gennych unrhyw geisiadau dilyn eto. Pan dderbyniwch chi un, bydd yn ymddangos yma.", - "empty_column.hashtag": "Nid oes dim ar yr hashnod hwn eto.", - "empty_column.home": "", - "empty_column.home.public_timeline": "y ffrwd cyhoeddus", - "empty_column.list": "Nid oes dim yn y rhestr yma eto. Pan y bydd aelodau'r rhestr yn cyhoeddi statws newydd, mi fydd yn ymddangos yma.", - "empty_column.lists": "Nid oes gennych unrhyw restrau eto. Pan grëwch chi un, mi fydd yn ymddangos yma.", - "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 INSTANCES eraill i'w lenwi", - "follow_request.authorize": "Caniatau", - "follow_request.reject": "Gwrthod", - "getting_started.developers": "Datblygwyr", - "getting_started.documentation": "Dogfennaeth", - "getting_started.find_friends": "Canfod ffrindiau o Twitter", - "getting_started.heading": "Dechrau", - "getting_started.invite": "Gwahoddwch bobl", - "getting_started.open_source_notice": "Mae Mastodon yn feddalwedd côd agored. Mae modd cyfrannu neu adrodd materion ar GitHUb ar {github}.", - "getting_started.security": "Diogelwch", - "getting_started.terms": "Telerau Gwasanaeth", - "home.column_settings.basic": "Syml", - "home.column_settings.show_reblogs": "", - "home.column_settings.show_replies": "Dangoswch ymatebion", - "keyboard_shortcuts.back": "", - "keyboard_shortcuts.blocked": "i agor rhestr defnyddwyr a flociwyd", - "keyboard_shortcuts.boost": "", - "keyboard_shortcuts.column": "", - "keyboard_shortcuts.compose": "", - "keyboard_shortcuts.description": "Disgrifiad", - "keyboard_shortcuts.direct": "i agor colofn negeseuon preifat", - "keyboard_shortcuts.down": "i symud lawr yn y rhestr", - "keyboard_shortcuts.enter": "i agor statws", - "keyboard_shortcuts.favourite": "i hoffi", - "keyboard_shortcuts.favourites": "i agor rhestr hoffi", - "keyboard_shortcuts.federated": "", - "keyboard_shortcuts.heading": "", - "keyboard_shortcuts.home": "i agor ffrwd cartref", - "keyboard_shortcuts.hotkey": "Hotkey", - "keyboard_shortcuts.legend": "", - "keyboard_shortcuts.local": "i agor ffrwd lleol", - "keyboard_shortcuts.mention": "i grybwyll yr awdur", - "keyboard_shortcuts.muted": "i agor rhestr defnyddwyr a dawelwyd", - "keyboard_shortcuts.my_profile": "i agor eich proffil", - "keyboard_shortcuts.notifications": "i agor colofn hysbysiadau", - "keyboard_shortcuts.pinned": "", - "keyboard_shortcuts.profile": "i agor proffil yr awdur", - "keyboard_shortcuts.reply": "i ateb", - "keyboard_shortcuts.requests": "i agor rhestr ceisiadau dilyn", - "keyboard_shortcuts.search": "", - "keyboard_shortcuts.start": "", - "keyboard_shortcuts.toggle_hidden": "", - "keyboard_shortcuts.toot": "i ddechrau tŵt newydd sbon", - "keyboard_shortcuts.unfocus": "", - "keyboard_shortcuts.up": "i symud yn uwch yn y rhestr", - "lightbox.close": "Cau", - "lightbox.next": "Nesaf", - "lightbox.previous": "", - "lists.account.add": "Ychwanegwch at restr", - "lists.account.remove": "", - "lists.delete": "Dileu rhestr", - "lists.edit": "Golygwch restr", - "lists.new.create": "Ychwanegwch restr", - "lists.new.title_placeholder": "Teitl rhestr newydd", - "lists.search": "", - "lists.subheading": "Eich rhestrau", - "loading_indicator.label": "Llwytho...", - "media_gallery.toggle_visible": "", - "missing_indicator.label": "Heb ei ganfod", - "missing_indicator.sublabel": "Ni ellid canfod yr adnodd hwn", - "mute_modal.hide_notifications": "Cuddiwch hysbysiadau rhag y defnyddiwr hwn?", - "navigation_bar.apps": "Apiau symudol", - "navigation_bar.blocks": "Defnyddwyr wedi eu blocio", - "navigation_bar.community_timeline": "", - "navigation_bar.compose": "Cyfansoddwch dŵt newydd", - "navigation_bar.direct": "Negeseuon preifat", - "navigation_bar.discover": "Darganfyddwch", - "navigation_bar.domain_blocks": "Parthau cuddiedig", - "navigation_bar.edit_profile": "Golygu proffil", - "navigation_bar.favourites": "Ffefrynnau", - "navigation_bar.filters": "Geiriau a dawelwyd", - "navigation_bar.follow_requests": "Ceisiadau dilyn", - "navigation_bar.info": "", - "navigation_bar.keyboard_shortcuts": "", - "navigation_bar.lists": "Rhestrau", - "navigation_bar.logout": "Allgofnodi", - "navigation_bar.mutes": "Defnyddwyr a dawelwyd", - "navigation_bar.personal": "Personol", - "navigation_bar.pins": "Tŵtiau wedi eu pinio", - "navigation_bar.preferences": "Dewisiadau", - "navigation_bar.public_timeline": "", - "navigation_bar.security": "Diogelwch", - "notification.favourite": "hoffodd {name} eich statws", - "notification.follow": "dilynodd {name} chi", - "notification.mention": "Soniodd {name} amdanoch chi", - "notification.reblog": "", - "notifications.clear": "Clirio hysbysiadau", - "notifications.clear_confirmation": "", - "notifications.column_settings.alert": "", - "notifications.column_settings.favourite": "Ffefrynnau:", - "notifications.column_settings.follow": "Dilynwyr newydd:", - "notifications.column_settings.mention": "", - "notifications.column_settings.push": "Hysbysiadau push", - "notifications.column_settings.reblog": "", - "notifications.column_settings.show": "", - "notifications.column_settings.sound": "Chwarae sain", - "notifications.group": "{count} o hysbysiadau", - "onboarding.done": "Wedi'i wneud", - "onboarding.next": "Nesaf", - "onboarding.page_five.public_timelines": "", - "onboarding.page_four.home": "Mae'r ffrwd gartref yn dangos twtiau o bobl yr ydych yn dilyn.", - "onboarding.page_four.notifications": "", - "onboarding.page_one.federation": "", - "onboarding.page_one.full_handle": "", - "onboarding.page_one.handle_hint": "", - "onboarding.page_one.welcome": "Croeso i Mastodon!", - "onboarding.page_six.admin": "", - "onboarding.page_six.almost_done": "Bron a gorffen...", - "onboarding.page_six.appetoot": "Bon Apetŵt!", - "onboarding.page_six.apps_available": "Mae yna {apps} ar gael i iOS, Android a platfformau eraill.", - "onboarding.page_six.github": "Mae Mastodon yn feddalwedd côd agored rhad ac am ddim. Mae modd adrodd bygiau, gwneud ceisiadau am nodweddion penodol, neu gyfrannu i'r côd ar {github}.", - "onboarding.page_six.guidelines": "canllawiau cymunedol", - "onboarding.page_six.read_guidelines": "Darllenwch {guidelines} y {domain} os gwelwch yn dda!", - "onboarding.page_six.various_app": "apiau symudol", - "onboarding.page_three.profile": "", - "onboarding.page_three.search": "", - "onboarding.page_two.compose": "", - "onboarding.skip": "Sgipiwch", - "privacy.change": "", - "privacy.direct.long": "", - "privacy.direct.short": "Uniongyrchol", - "privacy.private.long": "Cyhoeddi i ddilynwyr yn unig", - "privacy.private.short": "Dilynwyr-yn-unig", - "privacy.public.long": "Cyhoeddi i ffrydiau cyhoeddus", - "privacy.public.short": "Cyhoeddus", - "privacy.unlisted.long": "Peidio a cyhoeddi i ffrydiau cyhoeddus", - "privacy.unlisted.short": "Heb ei restru", - "regeneration_indicator.label": "Llwytho…", - "regeneration_indicator.sublabel": "Mae eich ffrwd cartref yn cael ei baratoi!", - "relative_time.days": "{number}d", - "relative_time.hours": "{number}h", - "relative_time.just_now": "nawr", - "relative_time.minutes": "{number}m", - "relative_time.seconds": "{number}s", - "reply_indicator.cancel": "Canslo", - "report.forward": "", - "report.forward_hint": "", - "report.hint": "", - "report.placeholder": "Sylwadau ychwanegol", - "report.submit": "Cyflwyno", - "report.target": "", - "search.placeholder": "Chwilio", - "search_popout.search_format": "Fformat chwilio uwch", - "search_popout.tips.full_text": "", - "search_popout.tips.hashtag": "hashnod", - "search_popout.tips.status": "statws", - "search_popout.tips.text": "", - "search_popout.tips.user": "defnyddiwr", - "search_results.accounts": "Pobl", - "search_results.hashtags": "Hanshnodau", - "search_results.statuses": "Twtiau", - "search_results.total": "", - "standalone.public_title": "Golwg tu fewn...", - "status.block": "Blociwch @{name}", - "status.cancel_reblog_private": "", - "status.cannot_reblog": "", - "status.delete": "Dileu", - "status.detailed_status": "", - "status.direct": "Neges breifat @{name}", - "status.embed": "Plannu", - "status.favourite": "", - "status.filtered": "", - "status.load_more": "Llwythwch mwy", - "status.media_hidden": "", - "status.mention": "", - "status.more": "Mwy", - "status.mute": "Tawelu @{name}", - "status.mute_conversation": "", - "status.open": "", - "status.pin": "", - "status.pinned": "", - "status.reblog": "", - "status.reblog_private": "", - "status.reblogged_by": "", - "status.reblogs.empty": "", - "status.redraft": "Dilëwh & ailddrafftio", - "status.reply": "Ateb", - "status.replyAll": "Ateb i edefyn", - "status.report": "", - "status.sensitive_toggle": "", - "status.sensitive_warning": "Cynnwys sensitif", - "status.share": "Rhannwch", - "status.show_less": "Dangoswch lai", - "status.show_less_all": "Dangoswch lai i bawb", - "status.show_more": "Dangoswch fwy", - "status.show_more_all": "", - "status.unmute_conversation": "Dad-dawelu sgwrs", - "status.unpin": "", - "tabs_bar.federated_timeline": "", - "tabs_bar.home": "Hafan", - "tabs_bar.local_timeline": "Lleol", - "tabs_bar.notifications": "Hysbysiadau", - "tabs_bar.search": "Chwilio", - "trends.count_by_accounts": "{count} {rawCount, plural, one {person} other {people}} yn siarad", - "ui.beforeunload": "Mi fyddwch yn colli eich drafft os gadewch Mastodon.", - "upload_area.title": "Llusgwch & gollwing i uwchlwytho", - "upload_button.label": "Ychwanegwch gyfryngau (JPEG, PNG, GIF, WebM, MP4, MOV)", - "upload_form.description": "", - "upload_form.focus": "", - "upload_form.undo": "Dileu", - "upload_progress.label": "Uwchlwytho...", - "video.close": "Cau fideo", - "video.exit_fullscreen": "Gadael sgrîn llawn", - "video.expand": "Ymestyn fideo", - "video.fullscreen": "Sgrîn llawn", - "video.hide": "Cuddio fideo", - "video.mute": "Tawelu sain", - "video.pause": "Oedi", - "video.play": "Chwarae", - "video.unmute": "Dad-dawelu sain" + "account.badges.bot": "Bot", + "account.block": "Blociwch @{name}", + "account.block_domain": "Cuddiwch bopeth 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", + "account.follow": "Dilyn", + "account.followers": "Dilynwyr", + "account.followers.empty": "Nid oes neb yn dilyn y defnyddiwr hwn eto.", + "account.follows": "Yn dilyn", + "account.follows.empty": "Nid yw'r defnyddiwr hwn yn dilyn unrhyw un eto.", + "account.follows_you": "Yn eich dilyn chi", + "account.hide_reblogs": "Cuddio bwstiau o @{name}", + "account.link_verified_on": "Gwiriwyd perchnogaeth y ddolen yma ar {date}", + "account.media": "Cyfryngau", + "account.mention": "Crybwyll @{name}", + "account.moved_to": "Mae @{name} wedi symud i:", + "account.mute": "Tawelu @{name}", + "account.mute_notifications": "Cuddio hysbysiadau o @{name}", + "account.muted": "Distewyd", + "account.posts": "Tŵtiau", + "account.posts_with_replies": "Tŵtiau ac atebion", + "account.report": "Adroddwch @{name}", + "account.requested": "Aros am gymeradwyaeth. Cliciwch er mwyn canslo cais dilyn", + "account.share": "Rhannwch broffil @{name}", + "account.show_reblogs": "Dangoswch bwstiau o @{name}", + "account.unblock": "Dadflociwch @{name}", + "account.unblock_domain": "Dadguddiwch {domain}", + "account.unendorse": "Peidwch a'i arddangos ar fy mhroffil", + "account.unfollow": "Daddilynwch", + "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", + "bundle_column_error.body": "Aeth rhywbeth o'i le tra'n llwytho'r elfen hon.", + "bundle_column_error.retry": "Ceisiwch eto", + "bundle_column_error.title": "Gwall rhwydwaith", + "bundle_modal_error.close": "Cau", + "bundle_modal_error.message": "Aeth rhywbeth o'i le tra'n llwytho'r elfen hon.", + "bundle_modal_error.retry": "Ceiswich eto", + "column.blocks": "Defnyddwyr a flociwyd", + "column.community": "Llinell amser lleol", + "column.direct": "Negeseuon preifat", + "column.domain_blocks": "Parthau cuddiedig", + "column.favourites": "Ffefrynnau", + "column.follow_requests": "Ceisiadau dilyn", + "column.home": "Hafan", + "column.lists": "Rhestrau", + "column.mutes": "Defnyddwyr a ddistewyd", + "column.notifications": "Hysbysiadau", + "column.pins": "Tŵtiau wedi eu pinio", + "column.public": "Ffrwd y ffederasiwn", + "column_back_button.label": "Nôl", + "column_header.hide_settings": "Cuddiwch dewisiadau", + "column_header.moveLeft_settings": "Symudwch y golofn i'r chwith", + "column_header.moveRight_settings": "Symudwch y golofn i'r dde", + "column_header.pin": "Piniwch", + "column_header.show_settings": "Dangos gosodiadau", + "column_header.unpin": "Dadbiniwch", + "column_subheading.settings": "Gosodiadau", + "community.column_settings.media_only": "Cyfryngau yn unig", + "compose_form.direct_message_warning": "Mi fydd y tŵt hwn ond yn cael ei anfon at y defnyddwyr sy'n cael eu crybwyll.", + "compose_form.direct_message_warning_learn_more": "Dysgwch fwy", + "compose_form.hashtag_warning": "Ni fydd y tŵt hwn wedi ei restru o dan unrhyw hashnod gan ei fod heb ei restru. Dim ond tŵtiau cyhoeddus gellid chwilota amdanynt drwy hashnod.", + "compose_form.lock_disclaimer": "Nid yw eich cyfri wedi'i {locked}. Gall unrhyw un eich dilyn i weld eich POSTS dilynwyr-yn-unig.", + "compose_form.lock_disclaimer.lock": "wedi ei gloi", + "compose_form.placeholder": "Be syd ar eich meddwl?", + "compose_form.publish": "Tŵt", + "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": "Testun wedi ei guddio gan rybudd", + "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.confirm": "Blociwch", + "confirmations.block.message": "Ydych chi'n sicr eich bod eisiau blocio {name}?", + "confirmations.delete.confirm": "Dileu", + "confirmations.delete.message": "Ydych chi'n sicr eich bod eisiau dileu y statws hwn?", + "confirmations.delete_list.confirm": "Dileu", + "confirmations.delete_list.message": "Ydych chi'n sicr eich bod eisiau dileu y rhestr hwn am byth?", + "confirmations.domain_block.confirm": "Cuddio parth cyfan", + "confirmations.domain_block.message": "A ydych yn hollol, hollol sicr eich bod am flocio y {domain} cyfan? Yn y nifer helaeth o achosion mae blocio neu tawelu ambell gyfrif yn ddigonol ac yn well. Ni fyddwch yn gweld cynnwyr o'r parth hwnnw mewn unrhyw ffrydiau cyhoeddus na chwaith eich hysbysiadau. Bydd hyn yn cael gwared o'ch dilynwyr o'r parth hwnnw.", + "confirmations.mute.confirm": "Tawelu", + "confirmations.mute.message": "Ydych chi'n sicr eich bod am ddistewi {name}?", + "confirmations.redraft.confirm": "Dilëwch & ailddrafftio", + "confirmations.redraft.message": "Ydych chi'n siwr eich bod eisiau dileu y statws hwn a'i ailddrafftio? Bydd ffefrynnau a bwstiau'n cael ei colli, a bydd ymatebion i'r statws gwreiddiol yn cael eu hamddifadu.", + "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": "Dad-ddilynwch", + "confirmations.unfollow.message": "Ydych chi'n sicr eich bod am ddad-ddilyn {name}?", + "conversation.last_message": "Last message:", + "embed.instructions": "Mewnblannwch y statws hwn ar eich gwefan drwy gopïo'r côd isod.", + "embed.preview": "Dyma sut olwg fydd arno:", + "emoji_button.activity": "Gweithgarwch", + "emoji_button.custom": "Custom", + "emoji_button.flags": "Baneri", + "emoji_button.food": "Bwyd a Diod", + "emoji_button.label": "Mewnosodwch emoji", + "emoji_button.nature": "Natur", + "emoji_button.not_found": "Dim emojos!! (╯°□°)╯︵ ┻━┻", + "emoji_button.objects": "Gwrthrychau", + "emoji_button.people": "Pobl", + "emoji_button.recent": "Defnyddir yn aml", + "emoji_button.search": "Chwilio...", + "emoji_button.search_results": "Canlyniadau chwilio", + "emoji_button.symbols": "Symbolau", + "emoji_button.travel": "Teithio & Llefydd", + "empty_column.blocks": "Nid ydych wedi blocio unrhyw ddefnyddwyr eto.", + "empty_column.community": "Mae'r ffrwd lleol yn wag. Ysgrifenwch rhywbeth yn gyhoeddus i gael dechrau arni!", + "empty_column.direct": "Nid oes gennych unrhyw negeseuon preifat eto. Pan y byddwch yn anfon neu derbyn un, mi fydd yn ymddangos yma.", + "empty_column.domain_blocks": "Nid oes yna unrhyw barthau cuddiedig eto.", + "empty_column.favourited_statuses": "Nid oes gennych unrhyw hoff dwtiau eto. Pan y byddwch yn hoffi un, mi fydd yn ymddangos yma.", + "empty_column.favourites": "Nid oes neb wedi hoffi'r tŵt yma eto. Pan bydd rhywun yn ei hoffi, mi fyddent yn ymddangos yma.", + "empty_column.follow_requests": "Nid oes gennych unrhyw geisiadau dilyn eto. Pan dderbyniwch chi un, bydd yn ymddangos yma.", + "empty_column.hashtag": "Nid oes dim ar yr hashnod hwn eto.", + "empty_column.home": "Mae eich ffrwd gartref yn wag! Ymwelwch a {public} neu defnyddiwch y chwilotwr i ddechrau arni ac i gwrdd a defnyddwyr eraill.", + "empty_column.home.public_timeline": "y ffrwd cyhoeddus", + "empty_column.list": "Nid oes dim yn y rhestr yma eto. Pan y bydd aelodau'r rhestr yn cyhoeddi statws newydd, mi fydd yn ymddangos yma.", + "empty_column.lists": "Nid oes gennych unrhyw restrau eto. Pan grëwch chi un, mi fydd yn ymddangos yma.", + "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 INSTANCES eraill i'w lenwi", + "follow_request.authorize": "Caniatau", + "follow_request.reject": "Gwrthod", + "getting_started.developers": "Datblygwyr", + "getting_started.documentation": "Dogfennaeth", + "getting_started.find_friends": "Canfod ffrindiau o Twitter", + "getting_started.heading": "Dechrau", + "getting_started.invite": "Gwahoddwch bobl", + "getting_started.open_source_notice": "Mae Mastodon yn feddalwedd côd agored. Mae modd cyfrannu neu adrodd materion ar GitHUb ar {github}.", + "getting_started.security": "Diogelwch", + "getting_started.terms": "Telerau Gwasanaeth", + "home.column_settings.basic": "Syml", + "home.column_settings.show_reblogs": "Show boosts", + "home.column_settings.show_replies": "Dangoswch ymatebion", + "keyboard_shortcuts.back": "i lywio nôl", + "keyboard_shortcuts.blocked": "i agor rhestr defnyddwyr a flociwyd", + "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": "Disgrifiad", + "keyboard_shortcuts.direct": "i agor colofn negeseuon preifat", + "keyboard_shortcuts.down": "i symud lawr yn y rhestr", + "keyboard_shortcuts.enter": "i agor statws", + "keyboard_shortcuts.favourite": "i hoffi", + "keyboard_shortcuts.favourites": "i agor rhestr hoffi", + "keyboard_shortcuts.federated": "i agor ffrwd y ffederasiwn", + "keyboard_shortcuts.heading": "Llwybrau byr allweddell", + "keyboard_shortcuts.home": "i agor ffrwd cartref", + "keyboard_shortcuts.hotkey": "Hotkey", + "keyboard_shortcuts.legend": "i ddangos yr arwr yma", + "keyboard_shortcuts.local": "i agor ffrwd lleol", + "keyboard_shortcuts.mention": "i grybwyll yr awdur", + "keyboard_shortcuts.muted": "i agor rhestr defnyddwyr a dawelwyd", + "keyboard_shortcuts.my_profile": "i agor eich proffil", + "keyboard_shortcuts.notifications": "i agor colofn hysbysiadau", + "keyboard_shortcuts.pinned": "i agor rhestr tŵtiau wedi'i pinio", + "keyboard_shortcuts.profile": "i agor proffil yr awdur", + "keyboard_shortcuts.reply": "i ateb", + "keyboard_shortcuts.requests": "i agor rhestr ceisiadau dilyn", + "keyboard_shortcuts.search": "i ffocysu chwilio", + "keyboard_shortcuts.start": "i agor colofn \"dechrau arni\"", + "keyboard_shortcuts.toggle_hidden": "i ddangos/cuddio testun tu ôl i CW", + "keyboard_shortcuts.toot": "i ddechrau tŵt newydd sbon", + "keyboard_shortcuts.unfocus": "i ddad-ffocysu ardal cyfansoddi testun/chwilio", + "keyboard_shortcuts.up": "i symud yn uwch yn y rhestr", + "lightbox.close": "Cau", + "lightbox.next": "Nesaf", + "lightbox.previous": "Blaenorol", + "lists.account.add": "Ychwanegwch at restr", + "lists.account.remove": "Remove from list", + "lists.delete": "Dileu rhestr", + "lists.edit": "Golygwch restr", + "lists.new.create": "Ychwanegwch restr", + "lists.new.title_placeholder": "Teitl rhestr newydd", + "lists.search": "Chwiliwch ymysg pobl yr ydych yn ei ddilyn", + "lists.subheading": "Eich rhestrau", + "loading_indicator.label": "Llwytho...", + "media_gallery.toggle_visible": "Toglo gwelededd", + "missing_indicator.label": "Heb ei ganfod", + "missing_indicator.sublabel": "Ni ellid canfod yr adnodd hwn", + "mute_modal.hide_notifications": "Cuddiwch hysbysiadau rhag y defnyddiwr hwn?", + "navigation_bar.apps": "Apiau symudol", + "navigation_bar.blocks": "Defnyddwyr wedi eu blocio", + "navigation_bar.community_timeline": "Ffrwd leol", + "navigation_bar.compose": "Cyfansoddwch dŵt newydd", + "navigation_bar.direct": "Negeseuon preifat", + "navigation_bar.discover": "Darganfyddwch", + "navigation_bar.domain_blocks": "Parthau cuddiedig", + "navigation_bar.edit_profile": "Golygu proffil", + "navigation_bar.favourites": "Ffefrynnau", + "navigation_bar.filters": "Geiriau a dawelwyd", + "navigation_bar.follow_requests": "Ceisiadau dilyn", + "navigation_bar.info": "Ynghylch yr achos hwn", + "navigation_bar.keyboard_shortcuts": "Bysellau brys", + "navigation_bar.lists": "Rhestrau", + "navigation_bar.logout": "Allgofnodi", + "navigation_bar.mutes": "Defnyddwyr a dawelwyd", + "navigation_bar.personal": "Personol", + "navigation_bar.pins": "Tŵtiau wedi eu pinio", + "navigation_bar.preferences": "Dewisiadau", + "navigation_bar.public_timeline": "Ffrwd y fferasiwn", + "navigation_bar.security": "Diogelwch", + "notification.favourite": "hoffodd {name} eich statws", + "notification.follow": "dilynodd {name} chi", + "notification.mention": "Soniodd {name} amdanoch chi", + "notification.reblog": "{name} boosted your status", + "notifications.clear": "Clirio hysbysiadau", + "notifications.clear_confirmation": "Ydych chi'n sicr eich bod am glirio'ch holl hysbysiadau am byth?", + "notifications.column_settings.alert": "Hysbysiadau bwrdd gwaith", + "notifications.column_settings.favourite": "Ffefrynnau:", + "notifications.column_settings.follow": "Dilynwyr newydd:", + "notifications.column_settings.mention": "Crybwylliadau:", + "notifications.column_settings.push": "Hysbysiadau push", + "notifications.column_settings.reblog": "Boosts:", + "notifications.column_settings.show": "Dangos yn y golofn", + "notifications.column_settings.sound": "Chwarae sain", + "notifications.group": "{count} o hysbysiadau", + "onboarding.done": "Wedi'i wneud", + "onboarding.next": "Nesaf", + "onboarding.page_five.public_timelines": "Mae'r ffrwd lleol yn dangos tŵtiau cyhoeddus o bawb ar y {domain}. Mae ffrwd y ffederasiwn yn dangos tŵtiau cyhoeddus o bawb y mae pobl ar y {domain} yn dilyn. Mae rhain yn Ffrydiau Cyhoeddus, ffordd wych o ddarganfod pobl newydd.", + "onboarding.page_four.home": "Mae'r ffrwd gartref yn dangos twtiau o bobl yr ydych yn dilyn.", + "onboarding.page_four.notifications": "Mae'r golofn hysbysiadau yn dangos pan mae rhywun yn ymwneud a chi.", + "onboarding.page_one.federation": "Mae mastodon yn rwydwaith o weinyddwyr anibynnol sy'n uno i greu un rhwydwaith gymdeithasol mwy. Yr ydym yn galw'r gweinyddwyr yma yn achosion.", + "onboarding.page_one.full_handle": "Your full handle", + "onboarding.page_one.handle_hint": "Dyma beth y bysech chi'n dweud wrth eich ffrindiau i chwilota amdano.", + "onboarding.page_one.welcome": "Croeso i Mastodon!", + "onboarding.page_six.admin": "Your instance's admin is {admin}.", + "onboarding.page_six.almost_done": "Bron a gorffen...", + "onboarding.page_six.appetoot": "Bon Apetŵt!", + "onboarding.page_six.apps_available": "Mae yna {apps} ar gael i iOS, Android a platfformau eraill.", + "onboarding.page_six.github": "Mae Mastodon yn feddalwedd côd agored rhad ac am ddim. Mae modd adrodd bygiau, gwneud ceisiadau am nodweddion penodol, neu gyfrannu i'r côd ar {github}.", + "onboarding.page_six.guidelines": "canllawiau cymunedol", + "onboarding.page_six.read_guidelines": "Darllenwch {guidelines} y {domain} os gwelwch yn dda!", + "onboarding.page_six.various_app": "apiau symudol", + "onboarding.page_three.profile": "Golygwch eich proffil i newid eich afatar, bywgraffiad, ac enw arddangos. Yno fe fyddwch hefyd yn canfod gosodiadau eraill.", + "onboarding.page_three.search": "Defnyddiwch y bar chwilio i ganfod pobl ac i edrych ar eu hashnodau, megis {illustration} ac {introductions}. I chwilio am rhywun nad ydynt ar yr achos hwn, defnyddiwch eu HANDLE llawn.", + "onboarding.page_two.compose": "Write posts from the compose column. You can upload images, change privacy settings, and add content warnings with the icons below.", + "onboarding.skip": "Sgipiwch", + "privacy.change": "Addasu preifatrwdd y statws", + "privacy.direct.long": "Cyhoeddi i'r defnyddwyr sy'n cael eu crybwyll yn unig", + "privacy.direct.short": "Uniongyrchol", + "privacy.private.long": "Cyhoeddi i ddilynwyr yn unig", + "privacy.private.short": "Dilynwyr-yn-unig", + "privacy.public.long": "Cyhoeddi i ffrydiau cyhoeddus", + "privacy.public.short": "Cyhoeddus", + "privacy.unlisted.long": "Peidio a cyhoeddi i ffrydiau cyhoeddus", + "privacy.unlisted.short": "Heb ei restru", + "regeneration_indicator.label": "Llwytho…", + "regeneration_indicator.sublabel": "Mae eich ffrwd cartref yn cael ei baratoi!", + "relative_time.days": "{number}d", + "relative_time.hours": "{number}h", + "relative_time.just_now": "nawr", + "relative_time.minutes": "{number}m", + "relative_time.seconds": "{number}s", + "reply_indicator.cancel": "Canslo", + "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": "Bydd yr adroddiad yn cael ei anfon i arolygydd eich achos. Mae modd darparu esboniad o pam yr ydych yn cwyno am y cyfrif hwn isod:", + "report.placeholder": "Sylwadau ychwanegol", + "report.submit": "Cyflwyno", + "report.target": "Cwyno am {target}", + "search.placeholder": "Chwilio", + "search_popout.search_format": "Fformat chwilio uwch", + "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": "hashnod", + "search_popout.tips.status": "statws", + "search_popout.tips.text": "Mae testun syml yn dychwelyd enwau arddangos, enwau defnyddwyr a hashnodau sy'n cyfateb", + "search_popout.tips.user": "defnyddiwr", + "search_results.accounts": "Pobl", + "search_results.hashtags": "Hanshnodau", + "search_results.statuses": "Twtiau", + "search_results.total": "{count, number} {count, plural, one {result} other {results}}", + "standalone.public_title": "Golwg tu fewn...", + "status.block": "Blociwch @{name}", + "status.cancel_reblog_private": "Unboost", + "status.cannot_reblog": "Ni ellir sbarduno'r tŵt hwn", + "status.delete": "Dileu", + "status.detailed_status": "Golwg manwl o'r sgwrs", + "status.direct": "Neges breifat @{name}", + "status.embed": "Plannu", + "status.favourite": "Favourite", + "status.filtered": "Filtered", + "status.load_more": "Llwythwch mwy", + "status.media_hidden": "Media hidden", + "status.mention": "Mention @{name}", + "status.more": "Mwy", + "status.mute": "Tawelu @{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": "Dilëwh & ailddrafftio", + "status.reply": "Ateb", + "status.replyAll": "Ateb i edefyn", + "status.report": "Report @{name}", + "status.sensitive_toggle": "Click to view", + "status.sensitive_warning": "Cynnwys sensitif", + "status.share": "Rhannwch", + "status.show_less": "Dangoswch lai", + "status.show_less_all": "Dangoswch lai i bawb", + "status.show_more": "Dangoswch fwy", + "status.show_more_all": "Show more for all", + "status.unmute_conversation": "Dad-dawelu sgwrs", + "status.unpin": "Unpin from profile", + "tabs_bar.federated_timeline": "Federated", + "tabs_bar.home": "Hafan", + "tabs_bar.local_timeline": "Lleol", + "tabs_bar.notifications": "Hysbysiadau", + "tabs_bar.search": "Chwilio", + "trends.count_by_accounts": "{count} {rawCount, plural, one {person} other {people}} yn siarad", + "ui.beforeunload": "Mi fyddwch yn colli eich drafft os gadewch Mastodon.", + "upload_area.title": "Llusgwch & gollwing i uwchlwytho", + "upload_button.label": "Ychwanegwch gyfryngau (JPEG, PNG, GIF, WebM, MP4, MOV)", + "upload_form.description": "Describe for the visually impaired", + "upload_form.focus": "Crop", + "upload_form.undo": "Dileu", + "upload_progress.label": "Uwchlwytho...", + "video.close": "Cau fideo", + "video.exit_fullscreen": "Gadael sgrîn llawn", + "video.expand": "Ymestyn fideo", + "video.fullscreen": "Sgrîn llawn", + "video.hide": "Cuddio fideo", + "video.mute": "Tawelu sain", + "video.pause": "Oedi", + "video.play": "Chwarae", + "video.unmute": "Dad-dawelu sain" } diff --git a/app/javascript/mastodon/locales/da.json b/app/javascript/mastodon/locales/da.json index e3d040ea8e..2848c187ff 100644 --- a/app/javascript/mastodon/locales/da.json +++ b/app/javascript/mastodon/locales/da.json @@ -91,8 +91,11 @@ "confirmations.mute.message": "Er du sikker på, du vil dæmpe {name}?", "confirmations.redraft.confirm": "Slet & omskriv", "confirmations.redraft.message": "Er du sikker på, du vil slette denne status og omskrive den? Favoritter og fremhævelser vil gå tabt og svar til det oprindelige opslag vil blive forældreløse.", + "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": "Følg ikke længere", "confirmations.unfollow.message": "Er du sikker på, du ikke længere vil følge {name}?", + "conversation.last_message": "Last message:", "embed.instructions": "Indlejre denne status på din side ved at kopiere nedenstående kode.", "embed.preview": "Det kommer til at se således ud:", "emoji_button.activity": "Aktivitet", @@ -294,6 +297,7 @@ "status.open": "Udvid denne status", "status.pin": "Fastgør til profil", "status.pinned": "Fastgjort trut", + "status.read_more": "Read more", "status.reblog": "Fremhæv", "status.reblog_private": "Fremhæv til oprindeligt publikum", "status.reblogged_by": "{name} fremhævede", diff --git a/app/javascript/mastodon/locales/de.json b/app/javascript/mastodon/locales/de.json index d798878fb1..a263e2309b 100644 --- a/app/javascript/mastodon/locales/de.json +++ b/app/javascript/mastodon/locales/de.json @@ -91,8 +91,11 @@ "confirmations.mute.message": "Bist du dir sicher, dass du {name} stummschalten möchtest?", "confirmations.redraft.confirm": "Löschen und neu erstellen", "confirmations.redraft.message": "Bist du dir sicher, dass du diesen Status löschen und neu machen möchtest? Favoriten und Boosts werden verloren gehen und Antworten zu diesem Post werden verwaist sein.", + "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": "Entfolgen", "confirmations.unfollow.message": "Bist du dir sicher, dass du {name} entfolgen möchtest?", + "conversation.last_message": "Last message:", "embed.instructions": "Du kannst diesen Beitrag auf deiner Webseite einbetten, indem du den folgenden Code einfügst.", "embed.preview": "So wird es aussehen:", "emoji_button.activity": "Aktivitäten", @@ -294,6 +297,7 @@ "status.open": "Diesen Beitrag öffnen", "status.pin": "Im Profil anheften", "status.pinned": "Angehefteter Beitrag", + "status.read_more": "Read more", "status.reblog": "Teilen", "status.reblog_private": "An das eigentliche Publikum teilen", "status.reblogged_by": "{name} teilte", diff --git a/app/javascript/mastodon/locales/defaultMessages.json b/app/javascript/mastodon/locales/defaultMessages.json index 436d9a5815..8ad5495714 100644 --- a/app/javascript/mastodon/locales/defaultMessages.json +++ b/app/javascript/mastodon/locales/defaultMessages.json @@ -1047,6 +1047,15 @@ ], "path": "app/javascript/mastodon/features/compose/index.json" }, + { + "descriptors": [ + { + "defaultMessage": "Last message:", + "id": "conversation.last_message" + } + ], + "path": "app/javascript/mastodon/features/direct_timeline/components/conversation.json" + }, { "descriptors": [ { diff --git a/app/javascript/mastodon/locales/el.json b/app/javascript/mastodon/locales/el.json index 4e4b733ece..5ef160955f 100644 --- a/app/javascript/mastodon/locales/el.json +++ b/app/javascript/mastodon/locales/el.json @@ -91,8 +91,11 @@ "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.unfollow.confirm": "Διακοπή παρακολούθησης", "confirmations.unfollow.message": "Σίγουρα θες να πάψεις να ακολουθείς τον/την {name};", + "conversation.last_message": "Last message:", "embed.instructions": "Ενσωματώστε αυτή την κατάσταση στην ιστοσελίδα σας αντιγράφοντας τον παρακάτω κώδικα.", "embed.preview": "Ορίστε πως θα φαίνεται:", "emoji_button.activity": "Δραστηριότητα", @@ -274,7 +277,7 @@ "search_results.accounts": "Άνθρωποι", "search_results.hashtags": "Ταμπέλες", "search_results.statuses": "Τουτ", - "search_results.total": "{count, number} {count, plural, one {result} other {results}}", + "search_results.total": "{count, number} {count, plural, ένα {result} υπόλοιπα {results}}", "standalone.public_title": "Μια πρώτη γεύση...", "status.block": "Block @{name}", "status.cancel_reblog_private": "Ακύρωσε την προώθηση", @@ -294,6 +297,7 @@ "status.open": "Διεύρυνε αυτή την κατάσταση", "status.pin": "Καρφίτσωσε στο προφίλ", "status.pinned": "Καρφιτσωμένο τουτ", + "status.read_more": "Read more", "status.reblog": "Προώθησε", "status.reblog_private": "Προώθησε στους αρχικούς παραλήπτες", "status.reblogged_by": "{name} προώθησε", diff --git a/app/javascript/mastodon/locales/en.json b/app/javascript/mastodon/locales/en.json index 9aee4c1f69..949ce6da70 100644 --- a/app/javascript/mastodon/locales/en.json +++ b/app/javascript/mastodon/locales/en.json @@ -95,6 +95,7 @@ "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}?", + "conversation.last_message": "Last message:", "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", diff --git a/app/javascript/mastodon/locales/eo.json b/app/javascript/mastodon/locales/eo.json index 86bee46b16..19e7a21e5c 100644 --- a/app/javascript/mastodon/locales/eo.json +++ b/app/javascript/mastodon/locales/eo.json @@ -91,8 +91,11 @@ "confirmations.mute.message": "Ĉu vi certas, ke vi volas silentigi {name}?", "confirmations.redraft.confirm": "Forigi kaj reskribi", "confirmations.redraft.message": "Ĉu vi certas, ke vi volas forigi tiun mesaĝon kaj reskribi ĝin? Vi perdos ĉiujn respondojn, diskonigojn kaj stelumojn ligitajn al ĝi.", + "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": "Ne plu sekvi", "confirmations.unfollow.message": "Ĉu vi certas, ke vi volas ĉesi sekvi {name}?", + "conversation.last_message": "Last message:", "embed.instructions": "Enkorpigu ĉi tiun mesaĝon en vian retejon per kopio de la suba kodo.", "embed.preview": "Ĝi aperos tiel:", "emoji_button.activity": "Agadoj", @@ -294,6 +297,7 @@ "status.open": "Grandigi", "status.pin": "Alpingli profile", "status.pinned": "Alpinglita mesaĝo", + "status.read_more": "Read more", "status.reblog": "Diskonigi", "status.reblog_private": "Diskonigi al la originala atentaro", "status.reblogged_by": "{name} diskonigis", diff --git a/app/javascript/mastodon/locales/es.json b/app/javascript/mastodon/locales/es.json index 63f197c284..1a71a10239 100644 --- a/app/javascript/mastodon/locales/es.json +++ b/app/javascript/mastodon/locales/es.json @@ -91,8 +91,11 @@ "confirmations.mute.message": "¿Estás seguro de que quieres silenciar a {name}?", "confirmations.redraft.confirm": "Borrar y volver a borrador", "confirmations.redraft.message": "Estás seguro de que quieres borrar este estado y volverlo a borrador? Perderás todas las respuestas, impulsos y favoritos asociados a él, y las respuestas a la publicación original quedarán huérfanos.", + "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": "Dejar de seguir", "confirmations.unfollow.message": "¿Estás seguro de que quieres dejar de seguir a {name}?", + "conversation.last_message": "Last message:", "embed.instructions": "Añade este toot a tu sitio web con el siguiente código.", "embed.preview": "Así es como se verá:", "emoji_button.activity": "Actividad", @@ -294,6 +297,7 @@ "status.open": "Expandir estado", "status.pin": "Fijar", "status.pinned": "Toot fijado", + "status.read_more": "Read more", "status.reblog": "Retootear", "status.reblog_private": "Implusar a la audiencia original", "status.reblogged_by": "Retooteado por {name}", diff --git a/app/javascript/mastodon/locales/eu.json b/app/javascript/mastodon/locales/eu.json index e4b1154b70..f088c07a8d 100644 --- a/app/javascript/mastodon/locales/eu.json +++ b/app/javascript/mastodon/locales/eu.json @@ -91,8 +91,11 @@ "confirmations.mute.message": "Ziur {name} mututu nahi duzula?", "confirmations.redraft.confirm": "Ezabatu eta berridatzi", "confirmations.redraft.message": "Ziur mezu hau ezabatu eta berridatzi nahi duzula? Gogokoak eta bultzadak galduko dira eta jaso dituen erantzunak umezurtz geratuko dira.", + "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": "Utzi jarraitzeari", "confirmations.unfollow.message": "Ziur {name} jarraitzeari utzi nahi diozula?", + "conversation.last_message": "Last message:", "embed.instructions": "Txertatu mezu hau zure webgunean beheko kodea kopatuz.", "embed.preview": "Hau da izango duen itxura:", "emoji_button.activity": "Jarduera", @@ -294,6 +297,7 @@ "status.open": "Hedatu mezu hau", "status.pin": "Finkatu profilean", "status.pinned": "Finkatutako toot-a", + "status.read_more": "Read more", "status.reblog": "Bultzada", "status.reblog_private": "Bultzada jatorrizko hartzaileei", "status.reblogged_by": "{name}(r)en bultzada", diff --git a/app/javascript/mastodon/locales/fa.json b/app/javascript/mastodon/locales/fa.json index fb4ded11c6..6a7964606d 100644 --- a/app/javascript/mastodon/locales/fa.json +++ b/app/javascript/mastodon/locales/fa.json @@ -15,7 +15,7 @@ "account.follows.empty": "این کاربر هنوز هیچ کسی را پی نمی‌گیرد.", "account.follows_you": "پیگیر شماست", "account.hide_reblogs": "پنهان کردن بازبوق‌های @{name}", - "account.link_verified_on": "Ownership of this link was checked on {date}", + "account.link_verified_on": "مالکیت این نشانی در تایخ {date} بررسی شد", "account.media": "عکس و ویدیو", "account.mention": "نام‌بردن از @{name}", "account.moved_to": "{name} منتقل شده است به:", @@ -91,8 +91,11 @@ "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.unfollow.confirm": "لغو پیگیری", "confirmations.unfollow.message": "آیا واقعاً می‌خواهید به پیگیری از {name} پایان دهید؟", + "conversation.last_message": "Last message:", "embed.instructions": "برای جاگذاری این نوشته در سایت خودتان، کد زیر را کپی کنید.", "embed.preview": "نوشتهٔ جاگذاری‌شده این گونه به نظر خواهد رسید:", "emoji_button.activity": "فعالیت", @@ -294,6 +297,7 @@ "status.open": "این نوشته را باز کن", "status.pin": "نوشتهٔ ثابت نمایه", "status.pinned": "بوق ثابت", + "status.read_more": "Read more", "status.reblog": "بازبوقیدن", "status.reblog_private": "بازبوق به مخاطبان اولیه", "status.reblogged_by": "‫{name}‬ بازبوقید", diff --git a/app/javascript/mastodon/locales/fi.json b/app/javascript/mastodon/locales/fi.json index caf949e8c4..5a6752ce1f 100644 --- a/app/javascript/mastodon/locales/fi.json +++ b/app/javascript/mastodon/locales/fi.json @@ -91,8 +91,11 @@ "confirmations.mute.message": "Haluatko varmasti mykistää käyttäjän {name}?", "confirmations.redraft.confirm": "Delete & redraft", "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.message": "Replying now will overwrite the message you are currently composing. Are you sure you want to proceed?", "confirmations.unfollow.confirm": "Lakkaa seuraamasta", "confirmations.unfollow.message": "Haluatko varmasti lakata seuraamasta käyttäjää {name}?", + "conversation.last_message": "Last message:", "embed.instructions": "Upota statuspäivitys sivullesi kopioimalla alla oleva koodi.", "embed.preview": "Se tulee näyttämään tältä:", "emoji_button.activity": "Aktiviteetit", @@ -294,6 +297,7 @@ "status.open": "Laajenna tilapäivitys", "status.pin": "Kiinnitä profiiliin", "status.pinned": "Kiinnitetty tuuttaus", + "status.read_more": "Read more", "status.reblog": "Buustaa", "status.reblog_private": "Buustaa alkuperäiselle yleisölle", "status.reblogged_by": "{name} buustasi", diff --git a/app/javascript/mastodon/locales/fr.json b/app/javascript/mastodon/locales/fr.json index ff09a14024..4371e166c5 100644 --- a/app/javascript/mastodon/locales/fr.json +++ b/app/javascript/mastodon/locales/fr.json @@ -15,7 +15,7 @@ "account.follows.empty": "Cet utilisateur ne suit personne pour l'instant.", "account.follows_you": "Vous suit", "account.hide_reblogs": "Masquer les partages de @{name}", - "account.link_verified_on": "Ownership of this link was checked on {date}", + "account.link_verified_on": "La propriété de ce lien a été vérifiée le {date}", "account.media": "Média", "account.mention": "Mentionner", "account.moved_to": "{name} a déménagé vers :", @@ -91,8 +91,11 @@ "confirmations.mute.message": "Confirmez-vous le masquage de {name} ?", "confirmations.redraft.confirm": "Effacer et ré-écrire", "confirmations.redraft.message": "Êtes-vous sûr·e de vouloir effacer ce statut pour le ré-écrire ? Ses partages ainsi que ses mises en favori seront perdu·e·s et ses réponses seront orphelines.", + "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": "Ne plus suivre", "confirmations.unfollow.message": "Voulez-vous arrêter de suivre {name} ?", + "conversation.last_message": "Last message:", "embed.instructions": "Intégrez ce statut à votre site en copiant le code ci-dessous.", "embed.preview": "Il apparaîtra comme cela :", "emoji_button.activity": "Activités", @@ -294,6 +297,7 @@ "status.open": "Déplier ce statut", "status.pin": "Épingler sur le profil", "status.pinned": "Pouet épinglé", + "status.read_more": "Read more", "status.reblog": "Partager", "status.reblog_private": "Booster vers l’audience originale", "status.reblogged_by": "{name} a partagé :", diff --git a/app/javascript/mastodon/locales/gl.json b/app/javascript/mastodon/locales/gl.json index 6afa21c9fb..f3b1a533b6 100644 --- a/app/javascript/mastodon/locales/gl.json +++ b/app/javascript/mastodon/locales/gl.json @@ -91,8 +91,11 @@ "confirmations.mute.message": "Está segura de que quere acalar a {name}?", "confirmations.redraft.confirm": "Eliminar e reescribir", "confirmations.redraft.message": "Está segura de querer eliminar este estado e voltalo a escribir? Perderá réplicas e favoritas, e as respostas ao orixinal quedarán orfas.", + "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": "Deixar de seguir", "confirmations.unfollow.message": "Quere deixar de seguir a {name}?", + "conversation.last_message": "Last message:", "embed.instructions": "Copie o código inferior para incrustar no seu sitio web este estado.", "embed.preview": "Así será mostrado:", "emoji_button.activity": "Actividade", @@ -294,6 +297,7 @@ "status.open": "Expandir este estado", "status.pin": "Fixar no perfil", "status.pinned": "Toot fixado", + "status.read_more": "Read more", "status.reblog": "Promover", "status.reblog_private": "Promover a audiencia orixinal", "status.reblogged_by": "{name} promoveu", diff --git a/app/javascript/mastodon/locales/he.json b/app/javascript/mastodon/locales/he.json index d670d8a55a..e20d4cd9a9 100644 --- a/app/javascript/mastodon/locales/he.json +++ b/app/javascript/mastodon/locales/he.json @@ -91,8 +91,11 @@ "confirmations.mute.message": "להשתיק את {name}?", "confirmations.redraft.confirm": "Delete & redraft", "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.message": "Replying now will overwrite the message you are currently composing. Are you sure you want to proceed?", "confirmations.unfollow.confirm": "להפסיק מעקב", "confirmations.unfollow.message": "להפסיק מעקב אחרי {name}?", + "conversation.last_message": "Last message:", "embed.instructions": "ניתן להטמיע את ההודעה באתרך ע\"י העתקת הקוד שלהלן.", "embed.preview": "דוגמא כיצד זה יראה:", "emoji_button.activity": "פעילות", @@ -294,6 +297,7 @@ "status.open": "הרחבת הודעה", "status.pin": "לקבע באודות", "status.pinned": "Pinned toot", + "status.read_more": "Read more", "status.reblog": "הדהוד", "status.reblog_private": "Boost to original audience", "status.reblogged_by": "הודהד על ידי {name}", diff --git a/app/javascript/mastodon/locales/hr.json b/app/javascript/mastodon/locales/hr.json index b76b82e1bd..f3808d061d 100644 --- a/app/javascript/mastodon/locales/hr.json +++ b/app/javascript/mastodon/locales/hr.json @@ -91,8 +91,11 @@ "confirmations.mute.message": "Jesi li siguran da želiš utišati {name}?", "confirmations.redraft.confirm": "Delete & redraft", "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.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}?", + "conversation.last_message": "Last message:", "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": "Aktivnost", @@ -294,6 +297,7 @@ "status.open": "Proširi ovaj status", "status.pin": "Pin on profile", "status.pinned": "Pinned toot", + "status.read_more": "Read more", "status.reblog": "Podigni", "status.reblog_private": "Boost to original audience", "status.reblogged_by": "{name} je podigao", diff --git a/app/javascript/mastodon/locales/hu.json b/app/javascript/mastodon/locales/hu.json index 57a8b7cfa3..0ffb071733 100644 --- a/app/javascript/mastodon/locales/hu.json +++ b/app/javascript/mastodon/locales/hu.json @@ -91,8 +91,11 @@ "confirmations.mute.message": "Biztos benne, hogy némítani szeretné {name}?", "confirmations.redraft.confirm": "Delete & redraft", "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.message": "Replying now will overwrite the message you are currently composing. Are you sure you want to proceed?", "confirmations.unfollow.confirm": "Követés visszavonása", "confirmations.unfollow.message": "Biztos benne, hogy vissza szeretné vonni {name} követését?", + "conversation.last_message": "Last message:", "embed.instructions": "Ágyazza be ezen státuszt weboldalába az alábbi kód másolásával.", "embed.preview": "Így fog kinézni:", "emoji_button.activity": "Aktivitás", @@ -294,6 +297,7 @@ "status.open": "Státusz kinagyítása", "status.pin": "Kitűzés a profilra", "status.pinned": "Pinned toot", + "status.read_more": "Read more", "status.reblog": "Reblog", "status.reblog_private": "Boost to original audience", "status.reblogged_by": "{name} reblogolta", diff --git a/app/javascript/mastodon/locales/hy.json b/app/javascript/mastodon/locales/hy.json index 077748a0a7..b4f19c697a 100644 --- a/app/javascript/mastodon/locales/hy.json +++ b/app/javascript/mastodon/locales/hy.json @@ -91,8 +91,11 @@ "confirmations.mute.message": "Վստա՞հ ես, որ ուզում ես {name}֊ին լռեցնել։", "confirmations.redraft.confirm": "Delete & redraft", "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.message": "Replying now will overwrite the message you are currently composing. Are you sure you want to proceed?", "confirmations.unfollow.confirm": "Ապահետեւել", "confirmations.unfollow.message": "Վստա՞հ ես, որ ուզում ես այլեւս չհետեւել {name}֊ին։", + "conversation.last_message": "Last message:", "embed.instructions": "Այս թութը քո կայքում ներդնելու համար կարող ես պատճենել ներքոհիշյալ կոդը։", "embed.preview": "Ահա, թե ինչ տեսք կունենա այն՝", "emoji_button.activity": "Զբաղմունքներ", @@ -294,6 +297,7 @@ "status.open": "Ընդարձակել այս թութը", "status.pin": "Ամրացնել անձնական էջում", "status.pinned": "Pinned toot", + "status.read_more": "Read more", "status.reblog": "Տարածել", "status.reblog_private": "Boost to original audience", "status.reblogged_by": "{name} տարածել է", diff --git a/app/javascript/mastodon/locales/id.json b/app/javascript/mastodon/locales/id.json index 3d80c09496..6d82269f49 100644 --- a/app/javascript/mastodon/locales/id.json +++ b/app/javascript/mastodon/locales/id.json @@ -91,8 +91,11 @@ "confirmations.mute.message": "Apa anda yakin ingin membisukan {name}?", "confirmations.redraft.confirm": "Delete & redraft", "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.message": "Replying now will overwrite the message you are currently composing. Are you sure you want to proceed?", "confirmations.unfollow.confirm": "Berhenti mengikuti", "confirmations.unfollow.message": "Apakah anda ingin berhenti mengikuti {name}?", + "conversation.last_message": "Last message:", "embed.instructions": "Sematkan status ini di website anda dengan menyalin kode di bawah ini.", "embed.preview": "Seperti ini nantinya:", "emoji_button.activity": "Aktivitas", @@ -294,6 +297,7 @@ "status.open": "Tampilkan status ini", "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": "di-boost {name}", diff --git a/app/javascript/mastodon/locales/io.json b/app/javascript/mastodon/locales/io.json index 9059b3a2b2..3df7e05ad4 100644 --- a/app/javascript/mastodon/locales/io.json +++ b/app/javascript/mastodon/locales/io.json @@ -91,8 +91,11 @@ "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? You will lose all replies, boosts and favourites to it.", + "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}?", + "conversation.last_message": "Last message:", "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", @@ -294,6 +297,7 @@ "status.open": "Detaligar ca mesajo", "status.pin": "Pin on profile", "status.pinned": "Pinned toot", + "status.read_more": "Read more", "status.reblog": "Repetar", "status.reblog_private": "Boost to original audience", "status.reblogged_by": "{name} repetita", diff --git a/app/javascript/mastodon/locales/it.json b/app/javascript/mastodon/locales/it.json index 5d8e3fe4ab..10d71c1732 100644 --- a/app/javascript/mastodon/locales/it.json +++ b/app/javascript/mastodon/locales/it.json @@ -91,8 +91,11 @@ "confirmations.mute.message": "Sei sicuro di voler silenziare {name}?", "confirmations.redraft.confirm": "Cancella e riscrivi", "confirmations.redraft.message": "Sei sicuro di voler cancellare questo stato e riscriverlo? Perderai tutte le risposte, condivisioni e preferiti.", + "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": "Smetti di seguire", "confirmations.unfollow.message": "Sei sicuro che non vuoi più seguire {name}?", + "conversation.last_message": "Last message:", "embed.instructions": "Inserisci questo status nel tuo sito copiando il codice qui sotto.", "embed.preview": "Ecco come apparirà:", "emoji_button.activity": "Attività", @@ -294,6 +297,7 @@ "status.open": "Espandi questo post", "status.pin": "Fissa in cima sul profilo", "status.pinned": "Toot fissato in cima", + "status.read_more": "Read more", "status.reblog": "Condividi", "status.reblog_private": "Condividi con i destinatari iniziali", "status.reblogged_by": "{name} ha condiviso", diff --git a/app/javascript/mastodon/locales/ja.json b/app/javascript/mastodon/locales/ja.json index 8228ef302b..e6f050cc64 100644 --- a/app/javascript/mastodon/locales/ja.json +++ b/app/javascript/mastodon/locales/ja.json @@ -15,7 +15,7 @@ "account.follows.empty": "まだ誰もフォローしていません。", "account.follows_you": "フォローされています", "account.hide_reblogs": "@{name}さんからのブーストを非表示", - "account.link_verified_on": "Ownership of this link was checked on {date}", + "account.link_verified_on": "このリンクの所有権は{date}に確認されました", "account.media": "メディア", "account.mention": "@{name}さんにトゥート", "account.moved_to": "{name}さんは引っ越しました:", @@ -91,10 +91,11 @@ "confirmations.mute.message": "本当に{name}さんをミュートしますか?", "confirmations.redraft.confirm": "削除して下書きに戻す", "confirmations.redraft.message": "本当にこのトゥートを削除して下書きに戻しますか? このトゥートへのお気に入り登録やブーストは失われ、返信は孤立することになります。", - "confirmations.reply.confirm": "返信", - "confirmations.reply.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.unfollow.confirm": "フォロー解除", "confirmations.unfollow.message": "本当に{name}さんのフォローを解除しますか?", + "conversation.last_message": "Last message:", "embed.instructions": "下記のコードをコピーしてウェブサイトに埋め込みます。", "embed.preview": "表示例:", "emoji_button.activity": "活動", @@ -296,7 +297,7 @@ "status.open": "詳細を表示", "status.pin": "プロフィールに固定表示", "status.pinned": "固定されたトゥート", - "status.read_more": "もっと見る", + "status.read_more": "Read more", "status.reblog": "ブースト", "status.reblog_private": "ブースト", "status.reblogged_by": "{name}さんがブースト", diff --git a/app/javascript/mastodon/locales/ka.json b/app/javascript/mastodon/locales/ka.json index 21cd7d6446..d093717053 100644 --- a/app/javascript/mastodon/locales/ka.json +++ b/app/javascript/mastodon/locales/ka.json @@ -91,8 +91,11 @@ "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.unfollow.confirm": "ნუღარ მიჰყვები", "confirmations.unfollow.message": "დარწმუნებული ხართ, აღარ გსურთ მიჰყვებოდეთ {name}-ს?", + "conversation.last_message": "Last message:", "embed.instructions": "ეს სტატუსი ჩასვით თქვენს ვებ-საიტზე შემდეგი კოდის კოპირებით.", "embed.preview": "ესაა თუ როგორც გამოჩნდება:", "emoji_button.activity": "აქტივობა", @@ -294,6 +297,7 @@ "status.open": "ამ სტატუსის გაფართოება", "status.pin": "აპინე პროფილზე", "status.pinned": "აპინული ტუტი", + "status.read_more": "Read more", "status.reblog": "ბუსტი", "status.reblog_private": "დაიბუსტოს საწყის აუდიტორიაზე", "status.reblogged_by": "{name} დაიბუსტა", diff --git a/app/javascript/mastodon/locales/ko.json b/app/javascript/mastodon/locales/ko.json index 8e0f9f59f7..678433ff6d 100644 --- a/app/javascript/mastodon/locales/ko.json +++ b/app/javascript/mastodon/locales/ko.json @@ -91,8 +91,11 @@ "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.unfollow.confirm": "언팔로우", "confirmations.unfollow.message": "정말로 {name}를 언팔로우하시겠습니까?", + "conversation.last_message": "Last message:", "embed.instructions": "아래의 코드를 복사하여 대화를 원하는 곳으로 공유하세요.", "embed.preview": "다음과 같이 표시됩니다:", "emoji_button.activity": "활동", @@ -294,6 +297,7 @@ "status.open": "상세 정보 표시", "status.pin": "고정", "status.pinned": "고정 된 툿", + "status.read_more": "Read more", "status.reblog": "부스트", "status.reblog_private": "원래의 수신자들에게 부스트", "status.reblogged_by": "{name}님이 부스트 했습니다", diff --git a/app/javascript/mastodon/locales/nl.json b/app/javascript/mastodon/locales/nl.json index e6b85692c9..6433f6211c 100644 --- a/app/javascript/mastodon/locales/nl.json +++ b/app/javascript/mastodon/locales/nl.json @@ -91,8 +91,11 @@ "confirmations.mute.message": "Weet je het zeker dat je {name} wilt negeren?", "confirmations.redraft.confirm": "Verwijderen en herschrijven", "confirmations.redraft.message": "Weet je zeker dat je deze toot wilt verwijderen en herschrijven? Je verliest wel de boosts en favorieten, en reacties op de originele toot zitten niet meer aan de nieuwe toot vast.", + "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": "Ontvolgen", "confirmations.unfollow.message": "Weet je het zeker dat je {name} wilt ontvolgen?", + "conversation.last_message": "Last message:", "embed.instructions": "Embed deze toot op jouw website, door de onderstaande code te kopiëren.", "embed.preview": "Zo komt het eruit te zien:", "emoji_button.activity": "Activiteiten", @@ -294,6 +297,7 @@ "status.open": "Toot volledig tonen", "status.pin": "Aan profielpagina vastmaken", "status.pinned": "Vastgemaakte toot", + "status.read_more": "Read more", "status.reblog": "Boost", "status.reblog_private": "Boost naar oorspronkelijke ontvangers", "status.reblogged_by": "{name} boostte", diff --git a/app/javascript/mastodon/locales/no.json b/app/javascript/mastodon/locales/no.json index 4a8176e82b..1105f23511 100644 --- a/app/javascript/mastodon/locales/no.json +++ b/app/javascript/mastodon/locales/no.json @@ -91,8 +91,11 @@ "confirmations.mute.message": "Er du sikker på at du vil dempe {name}?", "confirmations.redraft.confirm": "Delete & redraft", "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.message": "Replying now will overwrite the message you are currently composing. Are you sure you want to proceed?", "confirmations.unfollow.confirm": "Slutt å følge", "confirmations.unfollow.message": "Er du sikker på at du vil slutte å følge {name}?", + "conversation.last_message": "Last message:", "embed.instructions": "Kopier koden under for å bygge inn denne statusen på hjemmesiden din.", "embed.preview": "Slik kommer det til å se ut:", "emoji_button.activity": "Aktivitet", @@ -294,6 +297,7 @@ "status.open": "Utvid denne statusen", "status.pin": "Fest på profilen", "status.pinned": "Pinned toot", + "status.read_more": "Read more", "status.reblog": "Fremhev", "status.reblog_private": "Boost to original audience", "status.reblogged_by": "Fremhevd av {name}", diff --git a/app/javascript/mastodon/locales/oc.json b/app/javascript/mastodon/locales/oc.json index 64cbaef554..d95beb2b54 100644 --- a/app/javascript/mastodon/locales/oc.json +++ b/app/javascript/mastodon/locales/oc.json @@ -91,8 +91,11 @@ "confirmations.mute.message": "Volètz vertadièrament rescondre {name} ?", "confirmations.redraft.confirm": "Escafar & tornar formular", "confirmations.redraft.message": "Volètz vertadièrament escafar aqueste estatut e lo reformular ? Tote sos partiments e favorits seràn perduts, e sas responsas seràn orfanèlas.", + "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": "Quitar de sègre", "confirmations.unfollow.message": "Volètz vertadièrament quitar de sègre {name} ?", + "conversation.last_message": "Last message:", "embed.instructions": "Embarcar aqueste estatut per lo far veire sus un site Internet en copiar lo còdi çai-jos.", "embed.preview": "Semblarà aquò :", "emoji_button.activity": "Activitats", @@ -294,6 +297,7 @@ "status.open": "Desplegar aqueste estatut", "status.pin": "Penjar al perfil", "status.pinned": "Tut penjat", + "status.read_more": "Read more", "status.reblog": "Partejar", "status.reblog_private": "Partejar a l’audiéncia d’origina", "status.reblogged_by": "{name} a partejat", diff --git a/app/javascript/mastodon/locales/pl.json b/app/javascript/mastodon/locales/pl.json index dc3f3c976f..770932abfb 100644 --- a/app/javascript/mastodon/locales/pl.json +++ b/app/javascript/mastodon/locales/pl.json @@ -95,6 +95,7 @@ "confirmations.reply.message": "W ten sposób utracisz wpis który obecnie tworzysz. Czy na pewno chcesz to zrobić?", "confirmations.unfollow.confirm": "Przestań śledzić", "confirmations.unfollow.message": "Czy na pewno zamierzasz przestać śledzić {name}?", + "conversation.last_message": "Last message:", "embed.instructions": "Osadź ten wpis na swojej stronie wklejając poniższy kod.", "embed.preview": "Tak będzie to wyglądać:", "emoji_button.activity": "Aktywność", diff --git a/app/javascript/mastodon/locales/pt-BR.json b/app/javascript/mastodon/locales/pt-BR.json index 3e5b5da8e1..ac67a770f6 100644 --- a/app/javascript/mastodon/locales/pt-BR.json +++ b/app/javascript/mastodon/locales/pt-BR.json @@ -91,8 +91,11 @@ "confirmations.mute.message": "Você tem certeza de que quer silenciar {name}?", "confirmations.redraft.confirm": "Apagar & usar como rascunho", "confirmations.redraft.message": "Você tem certeza que deseja apagar esse status e usá-lo como rascunho? Você vai perder todas as respostas, compartilhamentos e favoritos relacionados a ele.", + "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": "Deixar de seguir", "confirmations.unfollow.message": "Você tem certeza de que quer deixar de seguir {name}?", + "conversation.last_message": "Last message:", "embed.instructions": "Incorpore esta postagem em seu site copiando o código abaixo.", "embed.preview": "Aqui está uma previsão de como ficará:", "emoji_button.activity": "Atividades", @@ -294,6 +297,7 @@ "status.open": "Expandir", "status.pin": "Fixar no perfil", "status.pinned": "Toot fixado", + "status.read_more": "Read more", "status.reblog": "Compartilhar", "status.reblog_private": "Compartilhar com a audiência original", "status.reblogged_by": "{name} compartilhou", diff --git a/app/javascript/mastodon/locales/pt.json b/app/javascript/mastodon/locales/pt.json index e9d91f631d..b2bf0f01dd 100644 --- a/app/javascript/mastodon/locales/pt.json +++ b/app/javascript/mastodon/locales/pt.json @@ -91,8 +91,11 @@ "confirmations.mute.message": "De certeza que queres silenciar {name}?", "confirmations.redraft.confirm": "Delete & redraft", "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.message": "Replying now will overwrite the message you are currently composing. Are you sure you want to proceed?", "confirmations.unfollow.confirm": "Deixar de seguir", "confirmations.unfollow.message": "De certeza que queres deixar de seguir {name}?", + "conversation.last_message": "Last message:", "embed.instructions": "Publicar este post num outro site copiando o código abaixo.", "embed.preview": "Podes ver aqui como irá ficar:", "emoji_button.activity": "Actividade", @@ -294,6 +297,7 @@ "status.open": "Expandir", "status.pin": "Fixar no perfil", "status.pinned": "Pinned toot", + "status.read_more": "Read more", "status.reblog": "Partilhar", "status.reblog_private": "Boost to original audience", "status.reblogged_by": "{name} partilhou", diff --git a/app/javascript/mastodon/locales/ro.json b/app/javascript/mastodon/locales/ro.json index 1d6e73bfdd..c5f2c7607b 100644 --- a/app/javascript/mastodon/locales/ro.json +++ b/app/javascript/mastodon/locales/ro.json @@ -91,8 +91,11 @@ "confirmations.mute.message": "Ești sigur că vrei să oprești {name}?", "confirmations.redraft.confirm": "Șterge și salvează ca ciornă", "confirmations.redraft.message": "Ești sigur că vrei să faci asta? Tot ce ține de această postare, inclusiv răspunsurile vor fi deconectate.", + "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": "Nu mai urmări", "confirmations.unfollow.message": "Ești sigur că nu mai vrei să îl urmărești pe {name}?", + "conversation.last_message": "Last message:", "embed.instructions": "Inserează această postare pe site-ul tău adăugând codul de mai jos.", "embed.preview": "Cam așa va arăta:", "emoji_button.activity": "Activitate", @@ -294,6 +297,7 @@ "status.open": "Extinde acest status", "status.pin": "Fixează pe profil", "status.pinned": "Postare fixată", + "status.read_more": "Read more", "status.reblog": "Redistribuie", "status.reblog_private": "Redistribuie către audiența originală", "status.reblogged_by": "{name} redistribuit", diff --git a/app/javascript/mastodon/locales/ru.json b/app/javascript/mastodon/locales/ru.json index 15fbfac3f8..b283b0976e 100644 --- a/app/javascript/mastodon/locales/ru.json +++ b/app/javascript/mastodon/locales/ru.json @@ -91,8 +91,11 @@ "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.unfollow.confirm": "Отписаться", "confirmations.unfollow.message": "Вы уверены, что хотите отписаться от {name}?", + "conversation.last_message": "Last message:", "embed.instructions": "Встройте этот статус на Вашем сайте, скопировав код внизу.", "embed.preview": "Так это будет выглядеть:", "emoji_button.activity": "Занятия", @@ -294,6 +297,7 @@ "status.open": "Развернуть статус", "status.pin": "Закрепить в профиле", "status.pinned": "Закреплённый статус", + "status.read_more": "Read more", "status.reblog": "Продвинуть", "status.reblog_private": "Продвинуть для своей аудитории", "status.reblogged_by": "{name} продвинул(а)", diff --git a/app/javascript/mastodon/locales/sk.json b/app/javascript/mastodon/locales/sk.json index 11a6b76c1b..c89922de84 100644 --- a/app/javascript/mastodon/locales/sk.json +++ b/app/javascript/mastodon/locales/sk.json @@ -91,8 +91,11 @@ "confirmations.mute.message": "Naozaj chcete ignorovať {name}?", "confirmations.redraft.confirm": "Vyčistiť a prepísať", "confirmations.redraft.message": "Si si istý/á, že chceš premazať a prepísať tento príspevok? Jeho nadobudnuté odpovede, povýšenia a obľúbenia, ale i odpovede na pôvodný príspevok budú odlúčené.", + "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": "Nesledovať", "confirmations.unfollow.message": "Naozaj chcete prestať sledovať {name}?", + "conversation.last_message": "Last message:", "embed.instructions": "Umiestni kód uvedený nižšie pre pridanie tohto statusu na tvoju web stránku.", "embed.preview": "Tu je ako to bude vyzerať:", "emoji_button.activity": "Aktivita", @@ -294,6 +297,7 @@ "status.open": "Otvoriť tento status", "status.pin": "Pripni na profil", "status.pinned": "Pripnutý príspevok", + "status.read_more": "Read more", "status.reblog": "Povýšiť", "status.reblog_private": "Povýš k pôvodnému publiku", "status.reblogged_by": "{name} povýšil/a", diff --git a/app/javascript/mastodon/locales/sl.json b/app/javascript/mastodon/locales/sl.json index f715abe85f..cb03849c2c 100644 --- a/app/javascript/mastodon/locales/sl.json +++ b/app/javascript/mastodon/locales/sl.json @@ -91,8 +91,11 @@ "confirmations.mute.message": "Ali ste prepričani, da želite utišati {name}?", "confirmations.redraft.confirm": "Delete & redraft", "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.message": "Replying now will overwrite the message you are currently composing. Are you sure you want to proceed?", "confirmations.unfollow.confirm": "Prenehaj slediti", "confirmations.unfollow.message": "Ali ste prepričani, da ne želite več slediti {name}?", + "conversation.last_message": "Last message:", "embed.instructions": "Vstavi ta status na svojo spletno stran tako, da kopirate spodnjo kodo.", "embed.preview": "Tukaj je, kako bo izgledalo:", "emoji_button.activity": "Dejavnost", @@ -294,6 +297,7 @@ "status.open": "Expand this status", "status.pin": "Pin on profile", "status.pinned": "Pripeti tut", + "status.read_more": "Read more", "status.reblog": "Suni", "status.reblog_private": "Suni v prvotno občinstvo", "status.reblogged_by": "{name} sunjen", diff --git a/app/javascript/mastodon/locales/sr-Latn.json b/app/javascript/mastodon/locales/sr-Latn.json index 7131d30443..4eab0a4ab8 100644 --- a/app/javascript/mastodon/locales/sr-Latn.json +++ b/app/javascript/mastodon/locales/sr-Latn.json @@ -91,8 +91,11 @@ "confirmations.mute.message": "Da li stvarno želite da ućutkate korisnika {name}?", "confirmations.redraft.confirm": "Delete & redraft", "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.message": "Replying now will overwrite the message you are currently composing. Are you sure you want to proceed?", "confirmations.unfollow.confirm": "Otprati", "confirmations.unfollow.message": "Da li ste sigurni da želite da otpratite korisnika {name}?", + "conversation.last_message": "Last message:", "embed.instructions": "Ugradi ovaj status na Vaš veb sajt kopiranjem koda ispod.", "embed.preview": "Ovako će da izgleda:", "emoji_button.activity": "Aktivnost", @@ -294,6 +297,7 @@ "status.open": "Proširi ovaj status", "status.pin": "Prikači na profil", "status.pinned": "Pinned toot", + "status.read_more": "Read more", "status.reblog": "Podrži", "status.reblog_private": "Boost to original audience", "status.reblogged_by": "{name} podržao(la)", diff --git a/app/javascript/mastodon/locales/sr.json b/app/javascript/mastodon/locales/sr.json index 806c0acb3f..c5c33fb0c4 100644 --- a/app/javascript/mastodon/locales/sr.json +++ b/app/javascript/mastodon/locales/sr.json @@ -91,8 +91,11 @@ "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.unfollow.confirm": "Отпрати", "confirmations.unfollow.message": "Да ли сте сигурни да желите да отпратите корисника {name}?", + "conversation.last_message": "Last message:", "embed.instructions": "Угради овај статус на Ваш веб сајт копирањем кода испод.", "embed.preview": "Овако ће да изгледа:", "emoji_button.activity": "Активност", @@ -294,6 +297,7 @@ "status.open": "Прошири овај статус", "status.pin": "Закачи на профил", "status.pinned": "Закачена труба", + "status.read_more": "Read more", "status.reblog": "Подржи", "status.reblog_private": "Подржи да види првобитна публика", "status.reblogged_by": "{name} подржао/ла", diff --git a/app/javascript/mastodon/locales/sv.json b/app/javascript/mastodon/locales/sv.json index f9129d3687..68fdf8d4e0 100644 --- a/app/javascript/mastodon/locales/sv.json +++ b/app/javascript/mastodon/locales/sv.json @@ -91,8 +91,11 @@ "confirmations.mute.message": "Är du säker du vill tysta ner {name}?", "confirmations.redraft.confirm": "Radera och gör om", "confirmations.redraft.message": "Är du säker på att du vill radera meddelandet och göra om det? Du kommer förlora alla svar, knuffar och favoriter som hänvisar till meddelandet.", + "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": "Sluta följa", "confirmations.unfollow.message": "Är du säker på att du vill sluta följa {name}?", + "conversation.last_message": "Last message:", "embed.instructions": "Bädda in den här statusen på din webbplats genom att kopiera koden nedan.", "embed.preview": "Här ser du hur det kommer att se ut:", "emoji_button.activity": "Aktivitet", @@ -294,6 +297,7 @@ "status.open": "Utvidga denna status", "status.pin": "Fäst i profil", "status.pinned": "Fäst toot", + "status.read_more": "Read more", "status.reblog": "Knuff", "status.reblog_private": "Knuffa till de ursprungliga åhörarna", "status.reblogged_by": "{name} knuffade", diff --git a/app/javascript/mastodon/locales/ta.json b/app/javascript/mastodon/locales/ta.json index 427e9a3dc6..38cf67e182 100644 --- a/app/javascript/mastodon/locales/ta.json +++ b/app/javascript/mastodon/locales/ta.json @@ -91,8 +91,11 @@ "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}?", + "conversation.last_message": "Last message:", "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", @@ -294,6 +297,7 @@ "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", diff --git a/app/javascript/mastodon/locales/te.json b/app/javascript/mastodon/locales/te.json index bc13b02f16..eead75ff55 100644 --- a/app/javascript/mastodon/locales/te.json +++ b/app/javascript/mastodon/locales/te.json @@ -91,8 +91,11 @@ "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.unfollow.confirm": "అనుసరించవద్దు", "confirmations.unfollow.message": "{name}ను మీరు ఖచ్చితంగా అనుసరించవద్దనుకుంటున్నారా?", + "conversation.last_message": "Last message:", "embed.instructions": "దిగువ కోడ్ను కాపీ చేయడం ద్వారా మీ వెబ్సైట్లో ఈ స్టేటస్ ని పొందుపరచండి.", "embed.preview": "అది ఈ క్రింది విధంగా కనిపిస్తుంది:", "emoji_button.activity": "కార్యకలాపాలు", @@ -294,6 +297,7 @@ "status.open": "ఈ స్టేటస్ ను విస్తరించు", "status.pin": "ప్రొఫైల్లో అతికించు", "status.pinned": "అతికించిన టూట్", + "status.read_more": "Read more", "status.reblog": "బూస్ట్", "status.reblog_private": "అసలు ప్రేక్షకులకు బూస్ట్ చేయి", "status.reblogged_by": "{name} బూస్ట్ చేసారు", diff --git a/app/javascript/mastodon/locales/th.json b/app/javascript/mastodon/locales/th.json index 3114bca60b..052f6b16ab 100644 --- a/app/javascript/mastodon/locales/th.json +++ b/app/javascript/mastodon/locales/th.json @@ -91,8 +91,11 @@ "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? You will lose all replies, boosts and favourites to it.", + "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}?", + "conversation.last_message": "Last message:", "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", @@ -294,6 +297,7 @@ "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", diff --git a/app/javascript/mastodon/locales/tr.json b/app/javascript/mastodon/locales/tr.json index a661b022b2..fccbc55ec1 100644 --- a/app/javascript/mastodon/locales/tr.json +++ b/app/javascript/mastodon/locales/tr.json @@ -91,8 +91,11 @@ "confirmations.mute.message": "{name} kullanıcısını sessize almak istiyor musunuz?", "confirmations.redraft.confirm": "Delete & redraft", "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.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}?", + "conversation.last_message": "Last message:", "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": "Aktivite", @@ -294,6 +297,7 @@ "status.open": "Bu gönderiyi genişlet", "status.pin": "Pin on profile", "status.pinned": "Pinned toot", + "status.read_more": "Read more", "status.reblog": "Boost'la", "status.reblog_private": "Boost to original audience", "status.reblogged_by": "{name} boost etti", diff --git a/app/javascript/mastodon/locales/uk.json b/app/javascript/mastodon/locales/uk.json index 116dfc489f..6c2e8380b4 100644 --- a/app/javascript/mastodon/locales/uk.json +++ b/app/javascript/mastodon/locales/uk.json @@ -91,8 +91,11 @@ "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.unfollow.confirm": "Відписатися", "confirmations.unfollow.message": "Ви впевнені, що хочете відписатися від {name}?", + "conversation.last_message": "Last message:", "embed.instructions": "Інтегруйте цей статус на вашому вебсайті, скопіювавши код нижче.", "embed.preview": "Ось як він виглядатиме:", "emoji_button.activity": "Заняття", @@ -294,6 +297,7 @@ "status.open": "Розгорнути допис", "status.pin": "Pin on profile", "status.pinned": "Pinned toot", + "status.read_more": "Read more", "status.reblog": "Передмухнути", "status.reblog_private": "Boost to original audience", "status.reblogged_by": "{name} передмухнув(-ла)", diff --git a/app/javascript/mastodon/locales/zh-CN.json b/app/javascript/mastodon/locales/zh-CN.json index 69ecd94312..b7937fc00d 100644 --- a/app/javascript/mastodon/locales/zh-CN.json +++ b/app/javascript/mastodon/locales/zh-CN.json @@ -91,8 +91,11 @@ "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.unfollow.confirm": "取消关注", "confirmations.unfollow.message": "你确定要取消关注 {name} 吗?", + "conversation.last_message": "Last message:", "embed.instructions": "要在你的网站上嵌入这条嘟文,请复制以下代码。", "embed.preview": "它会像这样显示出来:", "emoji_button.activity": "活动", @@ -294,6 +297,7 @@ "status.open": "展开嘟文", "status.pin": "在个人资料页面置顶", "status.pinned": "置顶嘟文", + "status.read_more": "Read more", "status.reblog": "转嘟", "status.reblog_private": "转嘟给原有关注者", "status.reblogged_by": "{name} 转嘟了", diff --git a/app/javascript/mastodon/locales/zh-HK.json b/app/javascript/mastodon/locales/zh-HK.json index fc5376699d..af106312ff 100644 --- a/app/javascript/mastodon/locales/zh-HK.json +++ b/app/javascript/mastodon/locales/zh-HK.json @@ -91,8 +91,11 @@ "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.unfollow.confirm": "取消關注", "confirmations.unfollow.message": "真的不要繼續關注 {name} 了嗎?", + "conversation.last_message": "Last message:", "embed.instructions": "要內嵌此文章,請將以下代碼貼進你的網站。", "embed.preview": "看上去會是這樣:", "emoji_button.activity": "活動", @@ -294,6 +297,7 @@ "status.open": "展開文章", "status.pin": "置頂到資料頁", "status.pinned": "置頂文章", + "status.read_more": "Read more", "status.reblog": "轉推", "status.reblog_private": "轉推到原讀者", "status.reblogged_by": "{name} 轉推", diff --git a/app/javascript/mastodon/locales/zh-TW.json b/app/javascript/mastodon/locales/zh-TW.json index 458af6b956..454fd80db6 100644 --- a/app/javascript/mastodon/locales/zh-TW.json +++ b/app/javascript/mastodon/locales/zh-TW.json @@ -91,8 +91,11 @@ "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.unfollow.confirm": "取消關注", "confirmations.unfollow.message": "真的不要繼續關注 {name} 了嗎?", + "conversation.last_message": "Last message:", "embed.instructions": "要內嵌此嘟文,請將以下代碼貼進你的網站。", "embed.preview": "看上去會變成這樣:", "emoji_button.activity": "活動", @@ -294,6 +297,7 @@ "status.open": "展開嘟文", "status.pin": "置頂到個人資訊頁", "status.pinned": "置頂嘟文", + "status.read_more": "Read more", "status.reblog": "轉嘟", "status.reblog_private": "轉嘟給原有關注者", "status.reblogged_by": "{name} 轉嘟了", diff --git a/config/locales/ar.yml b/config/locales/ar.yml index dd434c373a..0a8d3fdd4b 100644 --- a/config/locales/ar.yml +++ b/config/locales/ar.yml @@ -48,6 +48,7 @@ ar: other: مُتابِعون following: مُتابَع joined: انضم·ت في %{date} + link_verified_on: تم التحقق مِن مالك هذا الرابط بتاريخ %{date} media: الوسائط moved_html: "%{name} إنتقلَ إلى %{new_profile_link} :" network_hidden: إنّ المعطيات غير متوفرة @@ -120,6 +121,7 @@ ar: moderation_notes: ملاحظات الإشراف most_recent_activity: آخر نشاط حديث most_recent_ip: أحدث عنوان إيبي + no_limits_imposed: مِن دون حدود مشروطة not_subscribed: غير مشترك order: alphabetic: أبجديًا @@ -155,8 +157,10 @@ ar: report: التقرير targeted_reports: التقريرات التي أُنشِأت ضد هذا الحساب silence: سكتهم + silenced: تم كتمه statuses: المنشورات subscribe: اشترك + suspended: تم تعليقه title: الحسابات unconfirmed_email: البريد الإلكتروني غير المؤكد undo_silenced: رفع الصمت @@ -300,7 +304,12 @@ ar: title: الدعوات relays: add_new: إضافة مُرحّل جديد + delete: حذف + disable: تعطيل + disabled: مُعطَّل + enable: تشغيل enable_hint: عندما تقوم بتنشيط هذه الميزة، سوف يشترك خادومك في جميع التبويقات القادمة مِن هذا المُرحِّل و سيشرع كذلك بإرسال كافة التبويقات العمومية إليه. + enabled: مُشغَّل inbox_url: رابط المُرحّل pending: في انتظار تسريح المُرحِّل save_and_enable: حفظ وتشغيل @@ -452,7 +461,7 @@ ar: warning: كن حذرا مع هذه البيانات. لا تقم أبدا بمشاركتها مع الآخَرين ! your_token: رمز نفاذك auth: - agreement_html: بقبولك التسجيل فإنك تُصرِّح قبول قواعد مثيل الخادوم و شروط الخدمة التي نوفرها لك. + agreement_html: بمجرد النقر على "التسجيل" أسفله، فإنك تُصرِّح قبول قواعد مثيل الخادوم و شروط الخدمة التي نوفرها لك. change_password: الكلمة السرية confirm_email: تأكيد عنوان البريد الإلكتروني delete_account: حذف حساب diff --git a/config/locales/co.yml b/config/locales/co.yml index 0172fba8d5..0eac457e8b 100644 --- a/config/locales/co.yml +++ b/config/locales/co.yml @@ -48,6 +48,7 @@ co: other: Abbunati following: Abbunamenti joined: Quì dapoi %{date} + link_verified_on: A pruprietà d'issu ligame hè stata verificata u %{date} media: Media moved_html: "%{name} hà cambiatu di contu, avà hè nant’à %{new_profile_link}:" network_hidden: St'infurmazione ùn hè micca dispunibule @@ -120,6 +121,7 @@ co: moderation_notes: Note di muderazione most_recent_activity: Attività più ricente most_recent_ip: IP più ricente + no_limits_imposed: Nisuna limita imposta not_subscribed: Micca abbunatu order: alphabetic: Alfabeticu @@ -155,8 +157,10 @@ co: report: Signalamentu targeted_reports: Signalamenti creati contr’à stu contu silence: Silenzà + silenced: Silenzatu statuses: Statuti subscribe: Abbunassi + suspended: Suspesu title: Conti unconfirmed_email: E-mail micca cunfirmatu undo_silenced: Ùn silenzà più @@ -300,8 +304,13 @@ co: title: Invitazione relays: add_new: Aghjustà un ripetitore + delete: Sguassà description_html: Un ripetitore di federazione ghjè un servore intermediariu chì manda statuti pubblichi trà l'istanze abbunate. Pò aiutà l'istanze chjuche è mezane à scuprì u cuntinutu di u fediverse senza chì l'utilizatori appianu bisognu di seguità tutti i conti di l'altri servori. + disable: Disattivà + disabled: Disattivatu + enable: Attivà enable_hint: Quandu sarà attivatu, u vostru servore hà da seguità i statuti pubblichi di u ripetitore, è mandarà i so statuti pubblichi quallà. + enabled: Attivatu inbox_url: URL di u ripetitore pending: In attesa di l'apprubazione di u ripetitore save_and_enable: Salvà è attivà @@ -452,7 +461,7 @@ co: warning: Abbadate à quessi dati. Ùn i date à nisunu! your_token: Rigenerà a fiscia d’accessu auth: - agreement_html: Arregistrassi vole dì chì site d’accunsentu per siguità e regule di l’istanza è e cundizione d’usu. + agreement_html: Cliccà "Arregistrassi" quì sottu vole dì chì site d’accunsentu per siguità e regule di l’istanza è e cundizione d’usu. change_password: Chjave d’accessu confirm_email: Cunfirmà l’e-mail delete_account: Sguassà u contu @@ -913,3 +922,6 @@ co: otp_lost_help_html: S’è voi avete persu i dui, pudete cuntattà %{email} seamless_external_login: Site cunnettatu·a dapoi un serviziu esternu, allora i parametri di chjave d’accessu è d’indirizzu e-mail ùn so micca dispunibili. signed_in_as: 'Cunnettatu·a cum’è:' + verification: + explanation_html: 'Pudete verificavi cum''è u pruprietariu di i ligami in i metadati di u vostru prufile. Per quessa, u vostru situ deve avè un ligame versu a vostra pagina Mastodon. U ligame deve avè un''attributu rel="me". U cuntenutu di u testu di u ligame ùn hè micca impurtante. Eccu un''esempiu:' + verification: Verificazione diff --git a/config/locales/cs.yml b/config/locales/cs.yml index 5408c2472d..2ab2beec58 100644 --- a/config/locales/cs.yml +++ b/config/locales/cs.yml @@ -1,13 +1,13 @@ --- cs: about: - about_hashtag_html: Toto jsou veřejné tooty označené hashtagem #%{hashtag}. Pokud máte účet kdekoliv na fediverse, můžete s nimi interagovat. + about_hashtag_html: Tohle jsou veřejné tooty označené hashtagem #%{hashtag}. Pokud máte účet kdekoliv na fediverse, můžete s nimi interagovat. about_mastodon_html: Mastodon je sociální síť založená na otevřených webových protokolech a svobodném, otevřeném softwaru. Je decentrovalizovaná jako e-mail. about_this: O této instanci - administered_by: 'Server spravuje:' + administered_by: 'Instanci spravuje:' api: API apps: Mobilní aplikace - closed_registrations: Registrace na této instanci jsou momentálně uzavřené. Můžete si však najít jinou instanci, vytvořit si na ní účet a získat z ní přístup do naprosto stejné sítě. + closed_registrations: Registrace na této instanci jsou momentálně uzavřené. Ale pozor! Můžete si najít jinou instanci, vytvořit si na ní účet a získat z ní přístup do naprosto stejné sítě. contact: Kontakt contact_missing: Nenastaveno contact_unavailable: Neuvedeno @@ -46,8 +46,9 @@ cs: followers: one: Sledovatel other: Sledovatelé - following: Sleduje + following: Sledovaní joined: Připojil/a se v %{date} + link_verified_on: Vlastnictví tohoto odkazu bylo zkontrolováno %{date} media: Média moved_html: 'Účet %{name} byl přesunut na %{new_profile_link}:' network_hidden: Tato informace není k dispozici @@ -114,12 +115,13 @@ cs: memorialize: Změnit na "in memoriam" moderation: all: Vše - silenced: Utišen - suspended: Suspendován + silenced: Utišen/a + suspended: Suspendován/a title: Moderace moderation_notes: Moderační poznámky most_recent_activity: Nejnovější aktivita most_recent_ip: Nejnovější IP + no_limits_imposed: Nejsou nastavena žádná omezení not_subscribed: Neodebírá order: alphabetic: Abecedně @@ -155,8 +157,10 @@ cs: report: nahlášení targeted_reports: Nahlášení vytvořena o tomto účtu silence: Utišit + silenced: Utišen/a statuses: Příspěvky subscribe: Odebírat + suspended: Suspendován/a title: Účty unconfirmed_email: Nepotvrzený e-mail undo_silenced: Zrušit utišení @@ -300,8 +304,13 @@ cs: title: Pozvánky relays: add_new: Přidat nový most + delete: Smazat description_html: "Federovací most je přechodný server, který vyměňuje velká množství veřejných tootů mezi servery, které z něj odebírají a poblikují na něj. Může pomoci malým a středně velkým serverům objevovat obsah z fediverse, což by jinak vyžadovalo, aby místní uživatelé manuálně sledovali jiné lidi na vzdálených serverech." + disable: Zakázat + disabled: Zakázáno + enable: Povolit enable_hint: Je-li tohle povoleno, začne váš server odebírat všechny veřejné tooty z tohoto mostu a odesílat na něj své vlastní veřejné tooty. + enabled: Povoleno inbox_url: URL mostu pending: Čekám na souhlas mostu save_and_enable: Uložit a povolit @@ -452,7 +461,7 @@ cs: warning: Buďte s těmito daty velmi opatrní. Nikdy je s nikým nesdílejte! your_token: Váš přístupový token auth: - agreement_html: Registrací souhlasíte s následováním pravidel této instance a našich podmínek používání. + agreement_html: Kliknutím na tlačítko „Registrovat“ souhlasíte s následováním pravidel této instance a našich podmínek používání. change_password: Heslo confirm_email: Potvrdit e-mail delete_account: Odstranit účet @@ -759,7 +768,7 @@ cs: over_character_limit: limit %{max} znaků byl překročen pin_errors: limit: Už jste si připnul/a maximální počet tootů - ownership: Nelže připnout toot někoho jiného + ownership: Nelze připnout toot někoho jiného private: Nelze připnout neveřejné tooty reblog: Nelze připnout boostnutí show_more: Zobrazit více @@ -912,3 +921,6 @@ cs: otp_lost_help_html: Pokud jste ztratil/a přístup k oběma, můžete se spojit %{email} seamless_external_login: Jste přihlášen/a přes externí službu, nastavení hesla a e-mailu proto nejsou dostupná. signed_in_as: 'Přihlášen/a jako:' + verification: + explanation_html: 'Můžete se ověřit jako vlastník odkazů v metadatech profilu. Pro tento účel musí stránka v odkazu obsahovat odkaz zpět na váš profil na Mastodonu. Odkaz zpět musí mít atribut rel="me". Na textu odkazu nezáleží. Zde je příklad:' + verification: Ověření diff --git a/config/locales/cy.yml b/config/locales/cy.yml index 8b923ec873..893f7cf6f2 100644 --- a/config/locales/cy.yml +++ b/config/locales/cy.yml @@ -7,7 +7,7 @@ cy: administered_by: 'Gweinyddir gan:' api: API apps: Apiau symudol - closed_registrations: Mae Mastodon yn rwydwaith cymdeithasol sy'n seiliedig ar brotocolau gwe a meddalwedd cod agored rhad ac am ddim. Mae'n ddatganoledig fel e-bost. + closed_registrations: '' contact: Cyswllt contact_missing: Heb ei osod contact_unavailable: Ddim yn berthnasol @@ -155,7 +155,7 @@ cy: report: adrodd targeted_reports: Adroddiadau am y cyfri hwn silence: Tawelu - statuses: '' + statuses: Statysau subscribe: Tanysgrifio title: Cyfrifon unconfirmed_email: E-bost heb ei gadarnhau @@ -287,7 +287,7 @@ cy: domain_name: Parth reset: Ailosod search: Chwilio - title: INSTANCES hysbys + title: Achosion hysbys invites: filter: all: Pob @@ -311,6 +311,8 @@ cy: report: adroddiad action_taken_by: Gwnathpwyd hyn gan are_you_sure: Ydych chi'n sicr? + assign_to_self: Aseinio i mi + assigned: Cymedrolwr wedi'i aseinio comment: none: Dim created_at: Adroddwyd @@ -336,10 +338,19 @@ cy: settings: activity_api_enabled: title: Cyhoeddwch ystatedgau agregau am weithgaredd defnyddwyr + bootstrap_timeline_accounts: + title: Dilyn diofyn i ddefnyddwyr newydd contact_information: email: E-bost busnes + username: Enw defnyddiwr cyswllt + custom_css: + desc_html: Addaswch wedd gyda CSS wedi lwytho ar bob tudalen hero: + desc_html: Yn cael ei arddangos ar y dudadlen flaen. Awgrymir 600x100px oleia. Pan nad yw wedi ei osod, mae'n ymddangos fel mân-lun yr achos title: Delwedd arwr + peers_api_enabled: + desc_html: Enwau parth y mae'r achos hwn wedi dod ar ei draws yn y ffedysawd + title: Cyhoeddi rhestr o achosion dargynfyddiedig registrations: deletion: desc_html: Caniatewch i unrhywun i ddileu eu cyfrif @@ -351,6 +362,15 @@ cy: title: Agorwch cofrestru show_staff_badge: title: Dangos bathodyn staff + site_description: + title: Disgrifiad achos + site_description_extended: + desc_html: Lle da ar gyfer eich côd ymddygiad, rheolau, canllawiau a phethau eraill sy'n gwneud eich achos yn whanol. Mae modd i chi ddefnyddio tagiau HTML + site_short_description: + title: Disgrifiad byr o'r achos + site_title: Enw'r achos + thumbnail: + title: Mân-lun yr achos timeline_preview: title: Rhagolwg o'r ffrwd title: Gosodiadau'r wefan @@ -493,6 +513,8 @@ cy: one: Mae rhywbeth o'i le o hyd! Edrychwch ar y gwall isod os gwelwch yn dda other: Mae rhywbeth o'i le o hyd! Edrychwch ar y %{count} gwall isod os gwelwch yn dda imports: + preface: Mae modd mewnforio data yr ydych wedi allforio o achos arall, megis rhestr o bobl yr ydych yn ei ddilyn neu yn blocio. + success: Uwchlwyddwyd eich data yn llwyddiannus ac fe fydd yn cael ei brosesu mewn da bryd types: blocking: Rhestr blocio following: Rhestr dilyn @@ -504,9 +526,11 @@ cy: expires_in: '86400': 1 dydd max_uses_prompt: Dim terfyn + prompt: Cynhyrchwch a rhannwch ddolenni gyda eraill i ganiatau mynediad i'r achos hwn table: uses: Defnyddiau migrations: + currently_redirecting: '' proceed: Cadw moderation: title: Cymedroli diff --git a/config/locales/de.yml b/config/locales/de.yml index a93a25b5ed..eb2d8ebc71 100644 --- a/config/locales/de.yml +++ b/config/locales/de.yml @@ -36,8 +36,8 @@ de: status_count_before: mit terms: Nutzungsbedingungen user_count_after: - one: Benutzer - other: Benutzer + one: Benutzer:innen + other: Benutzer:innen user_count_before: Zuhause für what_is_mastodon: Was ist Mastodon? accounts: @@ -48,6 +48,7 @@ de: other: Follower following: Folgt joined: Beigetreten am %{date} + link_verified_on: Besitz des Links wurde überprüft am %{date} media: Medien moved_html: "%{name} ist auf %{new_profile_link} umgezogen:" network_hidden: Diese Informationen sind nicht verfügbar @@ -135,7 +136,7 @@ de: redownload: Avatar neu laden remove_avatar: Profilbild entfernen resend_confirmation: - already_confirmed: Dieser Benutzer wurde bereits bestätigt + already_confirmed: Diese:r Benutzer:in wurde bereits bestätigt send: Bestätigungsmail erneut senden success: Bestätigungs-E-Mail erfolgreich gesendet! reset: Zurücksetzen @@ -144,7 +145,7 @@ de: role: Berechtigungen roles: admin: Administrator - moderator: Moderator + moderator: Moderator:in staff: Mitarbeiter user: Nutzer salmon_url: Salmon-URL @@ -155,8 +156,10 @@ de: report: Meldung targeted_reports: Meldungen über dieses Konto silence: Stummschalten + silenced: Stummgeschaltet statuses: Beiträge subscribe: Abonnieren + suspended: Gesperrt title: Konten unconfirmed_email: Unbestätigte E-Mail-Adresse undo_silenced: Stummschaltung zurücknehmen @@ -172,20 +175,20 @@ de: create_custom_emoji: "%{name} hat neues Emoji %{target} hochgeladen" create_domain_block: "%{name} hat die Domain %{target} blockiert" create_email_domain_block: "%{name} hat die E-Mail-Domain %{target} geblacklistet" - demote_user: "%{name} stufte Benutzer %{target} herunter" + demote_user: "%{name} stufte Benutzer:in %{target} herunter" destroy_domain_block: "%{name} hat die Domain %{target} entblockt" destroy_email_domain_block: "%{name} hat die E-Mail-Domain %{target} gewhitelistet" destroy_status: "%{name} hat Status von %{target} entfernt" - disable_2fa_user: "%{name} hat Zwei-Faktor-Anforderung für Benutzer %{target} deaktiviert" + disable_2fa_user: "%{name} hat Zwei-Faktor-Anforderung für Benutzer:in %{target} deaktiviert" disable_custom_emoji: "%{name} hat das %{target} Emoji deaktiviert" - disable_user: "%{name} hat den Login für Benutzer %{target} deaktiviert" + disable_user: "%{name} hat den Login für Benutzer:in %{target} deaktiviert" enable_custom_emoji: "%{name} hat das %{target} Emoji aktiviert" - enable_user: "%{name} hat die Anmeldung für den Benutzer %{target} aktiviert" + enable_user: "%{name} hat die Anmeldung für di:en Benutzer:in %{target} aktiviert" memorialize_account: "%{name} hat %{target}s Profil in eine Gedenkseite umgewandelt" promote_user: "%{name} hat %{target} befördert" remove_avatar_user: "%{name} hat das Profilbild von %{target} entfernt" reopen_report: "%{name} hat die Meldung %{target} wieder geöffnet" - reset_password_user: "%{name} hat das Passwort für den Benutzer %{target} zurückgesetzt" + reset_password_user: "%{name} hat das Passwort für di:en Benutzer:in %{target} zurückgesetzt" resolve_report: "%{name} hat die Meldung %{target} bearbeitet" silence_account: "%{name} hat %{target}s Account stummgeschaltet" suspend_account: "%{name} hat %{target}s Account gesperrt" @@ -237,11 +240,11 @@ de: software: Software space: Speicherverbrauch title: Übersicht - total_users: Benutzer Insgesamt + total_users: Benutzer:innen insgesamt trends: Trends week_interactions: Interaktionen diese Woche week_users_active: Aktiv diese Woche - week_users_new: Benutzer diese Woche + week_users_new: Benutzer:innen diese Woche domain_blocks: add_new: Neu hinzufügen created_msg: Die Domain-Blockade wird nun durchgeführt @@ -300,8 +303,13 @@ de: title: Einladungen relays: add_new: Neues Relay hinzufügen + delete: Löschen description_html: Ein Föderierungsrelay ist ein vermittelnder Server, der eine große Anzahl öffentlicher Beiträge zwischen Servern austauscht, die es abonnieren und zu ihm veröffentlichen. Es kann kleinen und mittleren Servern dabei helfen, Inhalte des Fediverse zu entdecken, was andernfalls das manuelle Folgen anderer Leute auf entfernten Servern durch lokale Nutzer erfordern würde. + disable: Ausschalten + disabled: Ausgeschaltet + enable: Einschalten enable_hint: Sobald aktiviert wird dein Server alle öffentlichen Beiträge dieses Relays abonnieren und wird alle öffentlichen Beiträge dieses Servers an es senden. + enabled: Eingeschaltet inbox_url: Relay-URL pending: Warte auf Zustimmung des Relays save_and_enable: Speichern und aktivieren @@ -452,7 +460,7 @@ de: warning: Sei mit diesen Daten sehr vorsichtig. Teile sie mit niemandem! your_token: Dein Zugangs-Token auth: - agreement_html: Indem du dich registrierst, erklärst du dich mit den Regeln, die auf dieser Instanz gelten und der Datenschutzerklärung einverstanden. + agreement_html: Indem du dich registrierst, erklärst du dich mit den untenstehenden Regeln dieser Instanz und der Datenschutzerklärung einverstanden. change_password: Passwort confirm_email: E-Mail bestätigen delete_account: Konto löschen @@ -783,9 +791,9 @@ de:

Welche Informationen sammeln wir?

    -
  • Grundlegende Kontoinformationen: Wenn du dich auf diesem Server registrierst, wirst du darum gebeten, einen Benutzernamen, eine E-Mail-Adresse und ein Passwort einzugeben. Du kannst auch zusätzliche Profilinformationen wie etwa einen Anzeigenamen oder eine Biografie eingeben und ein Profilbild oder ein Headerbild hochladen. Der Benutzername, der Anzeigename, die Biografie, das Profilbild und das Headerbild werden immer öffentlich angezeigt.
  • +
  • Grundlegende Kontoinformationen: Wenn du dich auf diesem Server registrierst, wirst du darum gebeten, einen Benutzer:innen-Namen, eine E-Mail-Adresse und ein Passwort einzugeben. Du kannst auch zusätzliche Profilinformationen wie etwa einen Anzeigenamen oder eine Biografie eingeben und ein Profilbild oder ein Headerbild hochladen. Der Benutzer:innen-Name, der Anzeigename, die Biografie, das Profilbild und das Headerbild werden immer öffentlich angezeigt.
  • Beiträge, Folge- und andere öffentliche Informationen: Die Liste der Leute, denen du folgst, wird öffentlich gezeigt, das gleiche gilt für deine Folgenden (Follower). Sobald du eine Nachricht übermittelst, wird das Datum und die Uhrzeit gemeinsam mit der Information, welche Anwendung du dafür verwendet hast, gespeichert. Nachricht können Medienanhänge enthalten, etwa Bilder und Videos. Öffentliche und ungelistete Beiträge sind öffentlich verfügbar. Sobald du einen Beitrag auf deinem Profil featurest, sind dies auch öffentlich verfügbare Informationen. Deine Beiträge werden an deine Folgenden ausgeliefert, was in manchen Fällen bedeutet, dass sie an andere Server ausgeliefert werden und dort Kopien gespeichert werden. Sobald du Beiträge löschst, wird dies ebenso an deine Follower ausgeliefert. Die Handlungen des Teilens und Favorisieren eines anderen Beitrages ist immer öffentlich.
  • -
  • Direkte und "Nur Folgende"-Beiträge: Alle Beiträge werden auf dem Server gespeichert und verarbeitet. "Nur Folgende"-Beiträge werden an deine Folgenden und an Benutzer, die du in ihnen erwähnst, ausgeliefert, direkte Beiträge nur an in ihnen erwähnte Benutzer. In manchen Fällen bedeutet dass, dass sie an andere Server ausgeliefert werden und dort Kopien gespeichert werden. Wir bemühen uns nach bestem Wissen und Gewissen, den Zugriff auf diese Beiträge auf nur autorisierte Personen einzuschränken, jedoch könnten andere Server dabei scheitern. Deswegen ist es wichtig, die Server, zu denen deine Folgenden gehören, zu überprüfen. Du kannst eine Option in den Einstellungen umschalten, um neue Folgenden manuell anzunehmen oder abzuweisen. Bitte beachte, dass die Betreiber des Server und jedes empfangenden Servers solche Nachrichten anschauen könnten und dass Empfänger von diesen eine Bildschirmkopie erstellen könnten, sie kopieren oder anderweitig weiterverteilen könnten. Teile nicht irgendwelche gefährlichen Informationen über Mastodon.
  • +
  • Direkte und "Nur Folgende"-Beiträge: Alle Beiträge werden auf dem Server gespeichert und verarbeitet. "Nur Folgende"-Beiträge werden an deine Folgenden und an Benutzer:innen, die du in ihnen erwähnst, ausgeliefert, direkte Beiträge nur an in ihnen erwähnte Benutzer:innen. In manchen Fällen bedeutet dass, dass sie an andere Server ausgeliefert werden und dort Kopien gespeichert werden. Wir bemühen uns nach bestem Wissen und Gewissen, den Zugriff auf diese Beiträge auf nur autorisierte Personen einzuschränken, jedoch könnten andere Server dabei scheitern. Deswegen ist es wichtig, die Server, zu denen deine Folgenden gehören, zu überprüfen. Du kannst eine Option in den Einstellungen umschalten, um neue Folgenden manuell anzunehmen oder abzuweisen. Bitte beachte, dass die Betreiber des Server und jedes empfangenden Servers solche Nachrichten anschauen könnten und dass Empfänger von diesen eine Bildschirmkopie erstellen könnten, sie kopieren oder anderweitig weiterverteilen könnten. Teile nicht irgendwelche gefährlichen Informationen über Mastodon.
  • Internet Protocol-Adressen (IP-Adressen) und andere Metadaten: Sobald du dich anmeldest, erfassen wir sowohl die IP-Adresse, von der aus du dich anmeldest, als auch den Namen deine Browseranwendung. Alle angemeldeten Sitzungen (Sessions) sind für deine Überprüfung und Widerruf in den Einstellungen verfügbar. Die letzte verwendete IP-Adresse wird bis zu 12 Monate lang gespeichert. Wir könnten auch Serverprotokoll behalten, welche die IP-Adresse von jeder Anfrage an unseren Server enthalten.
@@ -815,7 +823,7 @@ de:
  • Serverprotokolle, die IP-Adressen von allen deinen Anfragen an diesen Server, falls solche Protokolle behalten werden, für nicht mehr als 90 Tage behalten.
  • -
  • registrierten Benutzern zu geordnete IP-Adressen nicht länger als 12 Monate behalten.
  • +
  • registrierten Benutzer:innen zugeordnete IP-Adressen nicht länger als 12 Monate behalten.

Du kannst ein Archiv deines Inhalts anfordern und herunterladen, inkludierend deiner Beiträge, Medienanhänge, Profilbilder und Headerbilder.

@@ -915,3 +923,5 @@ de: otp_lost_help_html: Wenn Du beides nicht mehr weißt, melde Dich bei uns unter der E-Mailadresse %{email} seamless_external_login: Du bist angemeldet über einen Drittanbieter-Dienst, weswegen Passwort- und E-Maileinstellungen nicht verfügbar sind. signed_in_as: 'Angemeldet als:' + verification: + explanation_html: 'Du kannst bestätigen, dass die Links in deinen Profil-Metadaten dir gehören. Dafür muss die verlinkte Website einen Link zurück auf dein Mastodon-Profil enthalten. Dieser Link muss ein rel="me"-Attribut enthalten. Der Linktext is dabei egal. Hier ist ein Beispiel:' diff --git a/config/locales/el.yml b/config/locales/el.yml index fc14d62cdb..63c438a938 100644 --- a/config/locales/el.yml +++ b/config/locales/el.yml @@ -48,6 +48,7 @@ el: other: Ακόλουθοι following: Ακολουθεί joined: Εγγράφηκε στις %{date} + link_verified_on: Η κυριότητα αυτού του συνδέσμου ελέγχθηκε στις %{date} media: Πολυμέσα moved_html: 'Ο/Η %{name} μετακόμισε στο %{new_profile_link}:' network_hidden: Αυτή η πληροφορία δεν είναι διαθέσιμη @@ -120,6 +121,7 @@ el: moderation_notes: Σημειώσεις μεσολάβησης most_recent_activity: Πιο πρόσφατη δραστηριότητα most_recent_ip: Πιο πρόσφατη IP + no_limits_imposed: Χωρίς όρια not_subscribed: Άνευ συνδρομής order: alphabetic: Αλφαβητικά @@ -155,8 +157,10 @@ el: report: καταγγελία targeted_reports: Αναφορές για αυτόν το λογαριασμό silence: Αποσιώπησε + silenced: Αποσιωπημένοι statuses: Καταστάσεις subscribe: Εγγραφή + suspended: Σε αναστολή title: Λογαριασμοί unconfirmed_email: Ανεπιβεβαίωτο email undo_silenced: Αναίρεση αποσιώπησης @@ -300,8 +304,13 @@ el: title: Προσκλήσεις relays: add_new: Πρόσθεσε νέο ανταποκριτή (relay) + delete: Διαγραφή description_html: Ο ομοσπονδιακός ανταποκριτής είναι ένας ενδιάμεσος εξυπηρετητής (server) που ανταλλάσσει μεγάλους όγκους δημόσιων τουτ μεταξύ εξυπηρετητών που εγγράφονται και δημοσιεύουν σε αυτόν. Βοηθάει μικρούς και μεσαίους εξυπηρετητές να ανακαλύψουν περιεχόμενο στο fediverse, που υπό άλλες συνθήκες θα χρειαζόταν κάποιους τοπικούς χρήστες που να ακολουθούν χρήστες σε απομακρυσμένους εξυπηρετητές. + disable: Απενεργοποίηση + disabled: Απενεργοποιημένο + enable: Ενεργοποίηση enable_hint: Μόλις ενεργοποιηθεί, ο εξυπηρετητής (server) σου θα εγγραφεί σε όλα τα δημόσια τουτ αυτού του ανταποκριτή (relay) και θα αρχίσει να προωθεί τα δικά του δημόσια τουτ σε αυτόν. + enabled: Ενεργοποιημένο inbox_url: URL ανταποκριτή pending: Περιμένοντας την έγκριση του ανταποκριτή save_and_enable: Αποθήκευση και ενεργοποίηση @@ -912,3 +921,6 @@ el: otp_lost_help_html: Αν χάσεις και τα δύο, μπορείς να επικοινωνήσεις με τον/την %{email} seamless_external_login: Επειδή έχεις συνδεθεί μέσω τρίτης υπηρεσίας, οι ρυθμίσεις συνθηματικού και email δεν είναι διαθέσιμες. signed_in_as: 'Έχεις συνδεθεί ως:' + verification: + explanation_html: 'Μπορείς να πιστοποιήσεις τον εαυτό σου ως ιδιοκτήτη των συνδέσμων που εμφανίζεις στα μεταδεδομένα του προφίλ σου. Για να συμβεί αυτό, ο συνδεδεμένος ιστότοπος πρέπει να περιέχει ένα σύνδεσμο που να επιστρέφει προς το προφίλ σου στο Mastodon. Ο σύνδεσμος επιστροφής πρέπει περιέχει την ιδιότητα (attribute) rel="me". Το κείμενο κειμένου δεν έχει σημασία. Για παράδειγμα:' + verification: Πιστοποίηση diff --git a/config/locales/fr.yml b/config/locales/fr.yml index ba3c90195c..51a3085537 100644 --- a/config/locales/fr.yml +++ b/config/locales/fr.yml @@ -48,6 +48,7 @@ fr: other: Abonné⋅e⋅s following: Abonnements joined: Inscrit·e en %{date} + link_verified_on: La propriété de ce lien a été vérifiée le %{date} media: Médias moved_html: "%{name} a changé de compte pour %{new_profile_link} :" network_hidden: Cette information n’est pas disponible @@ -120,6 +121,7 @@ fr: moderation_notes: Notes de modération most_recent_activity: Dernière activité most_recent_ip: Adresse IP la plus récente + no_limits_imposed: Aucune limite imposée not_subscribed: Non abonné order: alphabetic: Alphabétique @@ -155,8 +157,10 @@ fr: report: signalement targeted_reports: Signalements créés visant ce compte silence: Masquer + silenced: Silencié statuses: Statuts subscribe: S’abonner + suspended: Suspendu title: Comptes unconfirmed_email: Courriel non-confirmé undo_silenced: Démasquer @@ -300,8 +304,13 @@ fr: title: Invitations relays: add_new: Ajouter un nouveau relais + delete: Effacer description_html: Un relai de fédération est un serveur intermédiaire qui échange de grandes quantités de pouets entre les serveurs qui publient dessus et ceux qui y sont abonnés. Il peut aider les petites et moyennes instances à découvrir du contenu sur le fediverse, ce qui normalement nécessiterait que les membres locaux suivent des gens inscrits sur des serveurs distants. + disable: Désactiver + disabled: Désactivé + enable: Activé enable_hint: Une fois activé, votre serveur souscrira à tous les pouets publics présents sur ce relais et y enverra ses propres pouets publics. + enabled: Activé inbox_url: URL de relais pending: En attente de l'approbation du relai save_and_enable: Sauvegarder et activer @@ -452,7 +461,7 @@ fr: warning: Soyez prudent⋅e avec ces données. Ne les partagez pas ! your_token: Votre jeton d’accès auth: - agreement_html: En vous inscrivant, vous souscrivez aux règles de l’instance et à nos conditions d’utilisation. + agreement_html: En cliquant sur "S'inscrire" ci-dessous, vous souscrivez aux règles de l’instance et à nos conditions d’utilisation. change_password: Mot de passe confirm_email: Confirmer mon adresse mail delete_account: Supprimer le compte @@ -619,7 +628,7 @@ fr: notification_mailer: digest: action: Voir toutes les notifications - body: 'Voici ce que vous avez raté sur ${instance} depuis votre dernière visite le %{since} :' + body: Voici un bref résumé des messages que vous auriez raté depuis votre dernière visite le %{since} mention: "%{name} vous a mentionné⋅e dans :" new_followers_summary: one: Vous avez un⋅e nouvel⋅le abonné⋅e ! Youpi ! @@ -913,3 +922,6 @@ fr: otp_lost_help_html: Si vous perdez accès aux deux, vous pouvez contacter %{email} seamless_external_login: Vous êtes connecté via un service externe, donc les paramètres concernant le mot de passe et le courriel ne sont pas disponibles. signed_in_as: 'Connecté·e en tant que :' + verification: + explanation_html: 'Vous pouvez vérifier vous-même que vous êtes le propriétaire des liens dans les métadonnées de votre profil. Pour cela, le site Web lié doit contenir un lien vers votre profil Mastodon. Le lien de retour doitavoir un attribut rel="me". Le contenu textuel du lien n''a pas d''importance. En voici un exemple :' + verification: Vérification diff --git a/config/locales/gl.yml b/config/locales/gl.yml index bf046a622b..49cc94f302 100644 --- a/config/locales/gl.yml +++ b/config/locales/gl.yml @@ -48,6 +48,7 @@ gl: other: Seguidoras following: Seguindo joined: Uneuse %{date} + link_verified_on: A propiedade de esta ligazón foi comprobada en %{date} media: Medios moved_html: "%{name} mudouse a %{new_profile_link}:" network_hidden: A información non está dispoñible @@ -120,6 +121,7 @@ gl: moderation_notes: Notas de moderación most_recent_activity: Actividade máis recente most_recent_ip: IP máis recente + no_limits_imposed: Sen límites impostos not_subscribed: Non suscrita order: alphabetic: Alfabética @@ -155,8 +157,10 @@ gl: report: informar targeted_reports: Informes feitos sobre esta conta silence: Acalar + silenced: Acalada statuses: Estados subscribe: Subscribir + suspended: Suspendida title: Contas unconfirmed_email: Correo-e non confirmado undo_silenced: Desfacer acalar @@ -300,8 +304,13 @@ gl: title: Convida relays: add_new: Engadir un novo repetidor + delete: Eliminar description_html: Un repetidor da federación é un servidor intermedio que intercambia grandes volumes de toots públicos entre servidores que se suscriban e publiquen nel. Pode axudar a servidores pequenos e medios a descubrir contido no fediverso, o que de outro xeito precisaría que as usuarias locais seguisen a outra xente en servidores remotos. + disable: Desactivar + disabled: Desactivada + enable: Activar enable_hint: Unha vez activado, o seu servidor suscribirase a todos os toots públicos de este servidor, e tamén comezará a eviar a el os toots públicos do servidor. + enabled: Activada inbox_url: URL do repetidor pending: Agardando polo permiso do repetidor save_and_enable: Gardar e activar @@ -452,7 +461,7 @@ gl: warning: Teña moito tino con estos datos. Nunca os comparta con ninguén! your_token: O seu testemuño de acceso auth: - agreement_html: Rexistrándose acorda seguir as normas da instancia e os termos do servizo. + agreement_html: Ao pulsar "Rexistrar" vostede acorda seguir as normas da instancia e os termos do servizo. change_password: Contrasinal confirm_email: Confirmar correo-e delete_account: Eliminar conta @@ -913,3 +922,6 @@ gl: otp_lost_help_html: Si perde o acceso a ambos, pode contactar con %{email} seamless_external_login: Está conectado a través de un servizo externo, polo que os axustes de contrasinal e correo-e non están dispoñibles. signed_in_as: 'Rexistrada como:' + verification: + explanation_html: 'Pode validarse a vostede mesma como a dona das ligazóns nos metadatos do seu perfil. Para esto, o sitio web ligado debe conter unha ligazón de retorno ao perfil de Mastodon. Esta ligazón de retorno ten que ter un atributo rel="me". O texto da ligazón non importa. Aquí ten un exemplo:' + verification: Validación diff --git a/config/locales/ja.yml b/config/locales/ja.yml index 64182ae602..d199fe715d 100644 --- a/config/locales/ja.yml +++ b/config/locales/ja.yml @@ -48,6 +48,7 @@ ja: other: フォロワー following: フォロー中 joined: "%{date} に登録" + link_verified_on: このリンクの所有権は %{date} に確認されました media: メディア moved_html: "%{name} さんは引っ越しました %{new_profile_link}:" network_hidden: この情報は利用できません @@ -463,7 +464,7 @@ ja: warning: このデータは気をつけて取り扱ってください。他の人と共有しないでください! your_token: アクセストークン auth: - agreement_html: 登録すると インスタンスのルールプライバシーポリシー に従うことに同意したことになります。 + agreement_html: 登録するをクリックすると インスタンスのルールプライバシーポリシー に従うことに同意したことになります。 change_password: パスワード confirm_email: メールアドレスの確認 delete_account: アカウントの削除 @@ -925,3 +926,6 @@ ja: otp_lost_help_html: どちらも使用できない場合、%{email} に連絡を取ると解決できるかもしれません seamless_external_login: あなたは外部サービスを介してログインしているため、パスワードとメールアドレスの設定は利用できません。 signed_in_as: '下記でログイン中:' + verification: + explanation_html: プロフィール内のリンクの所有者であることを認証することができます。そのためにはリンクされたウェブサイトにMastodonプロフィールへのリンクが含まれている必要があります。リンクにはrel="me"属性を必ず与えなければなりません。リンクのテキストについては重要ではありません。以下は例です: + verification: 認証 diff --git a/config/locales/simple_form.ar.yml b/config/locales/simple_form.ar.yml index 783e545e11..dcdc1ffc19 100644 --- a/config/locales/simple_form.ar.yml +++ b/config/locales/simple_form.ar.yml @@ -9,6 +9,7 @@ ar: context: واحد أو أكثر من السياقات التي يجب أن ينطبق عليها عامل التصفية digest: تُرسَل إليك بعد مُضيّ مدة مِن خمول نشاطك و فقط إذا ما تلقيت رسائل شخصية مباشِرة أثناء فترة غيابك مِن الشبكة display_name: %{count} حرف باق + email: سوف تتلقى رسالة إلكترونية للتأكيد fields: يُمكنك عرض 4 عناصر على شكل جدول في ملفك الشخصي header: ملف PNG أو GIF أو JPG. حجمه على أقصى تصدير %{size}. سيتم تصغيره إلى %{dimensions}px inbox_url: نسخ العنوان الذي تريد استخدامه مِن صفحة الإستقبال للمُرحَّل @@ -16,12 +17,17 @@ ar: locale: لغة واجهة المستخدم و الرسائل الإلكترونية و الإشعارات locked: يتطلب منك الموافقة يدويا على طلبات المتابعة note: %{count} حرف باق + password: يُنصح باستخدام 8 أحرف على الأقل phrase: سوف يتم العثور عليه مهما كان نوع النص أو حتى و إن كان داخل الويب فيه تحذير عن المحتوى scopes: ما هي المجالات المسموح بها في التطبيق ؟ إن قمت باختيار أعلى المجالات فيمكنك الإستغناء عن الخَيار اليدوي. setting_default_language: يمكن الكشف التلقائي للّغة اللتي استخدمتها في تحرير تبويقاتك ، غيرَ أنّ العملية ليست دائما دقيقة + setting_display_media_default: إخفاء الوسائط المُعيَّنة كحساسة + setting_display_media_hide_all: إخفاء كافة الوسائط دائمًا + setting_display_media_show_all: دائمًا عرض الوسائط المُعيَّنة كحساسة setting_hide_network: الحسابات التي تُتابعها و التي تُتابِعك على حد سواء لن تُعرَض على صفحتك الشخصية setting_noindex: ذلك يؤثر على حالة ملفك الشخصي و صفحاتك setting_theme: ذلك يؤثر على الشكل الذي سيبدو عليه ماستدون عندما تقوم بالدخول مِن أي جهاز. + username: اسم المستخدم الخاص بك سوف يكون فريدا مِن نوعه على %{domain} imports: data: ملف CSV تم تصديره مِن مثيل خادوم ماستدون آخر sessions: @@ -64,6 +70,11 @@ ar: setting_default_privacy: خصوصية المنشور setting_default_sensitive: إعتبر الوسائط دائما كمحتوى حساس setting_delete_modal: إظهار مربع حوار للتأكيد قبل حذف أي تبويق + setting_display_media: عرض الوسائط + setting_display_media_default: افتراضي + setting_display_media_hide_all: اخفاء الكل + setting_display_media_show_all: عرض الكل + setting_expand_spoilers: توسيع التبويقات التي تحتوي على تحذيرات عن المحتوى تلقائيا setting_hide_network: إخفِ شبكتك setting_noindex: عدم السماح لمحركات البحث بفهرسة ملفك الشخصي setting_reduce_motion: تخفيض عدد الصور في الوسائط المتحركة diff --git a/config/locales/simple_form.co.yml b/config/locales/simple_form.co.yml index 6f1630e6a3..c4a6bd1698 100644 --- a/config/locales/simple_form.co.yml +++ b/config/locales/simple_form.co.yml @@ -11,6 +11,7 @@ co: display_name: one: Ci ferma 1 caratteru other: Ci fermanu %{count} caratteri + email: Avete da riceve un'e-mail di cunfirmazione fields: Pudete avè fin’à 4 elementi mustrati cum’un tavulone nant’à u vostru prufile header: Furmatu PNG, GIF o JPG. 2Mo o menu. Sarà ridottu à %{dimensions}px inbox_url: Cupiate l'URL di a pagina d'accolta di u ripetitore chì vulete utilizà @@ -20,12 +21,17 @@ co: note: one: Ci ferma 1 caratteru other: Ci fermanu %{count} caratteri + password: Ci volenu almenu 8 caratteri phrase: Sarà trovu senza primura di e maiuscule o di l'avertimenti scopes: L'API à quelle l'applicazione averà accessu. S'è voi selezziunate un parametru d'altu livellu, un c'hè micca bisognu di selezziunà quell'individuali. setting_default_language: A lingua di i vostri statuti pò esse induvinata autumaticamente, mà ùn marchja micca sempre bè + setting_display_media_default: Piattà i media marcati cum'è sensibili + setting_display_media_hide_all: Sempre piattà tutti i media + setting_display_media_show_all: Sempre affissà i media marcati cum'è sensibili setting_hide_network: I vostri abbunati è abbunamenti ùn saranu micca mustrati nant’à u vostru prufile setting_noindex: Tocca à u vostru prufile pubblicu è i vostri statuti setting_theme: Tocca à l’apparenza di Mastodon quandu site cunnettatu·a da qualch’apparechju. + username: U vostru cugnome sarà unicu nant'à %{domain} whole_word: Quandu a parolla o a frasa sana hè alfanumerica, sarà applicata solu s'ella currisponde à a parolla sana imports: data: Un fugliale CSV da un’altr’istanza di Mastodon @@ -69,6 +75,11 @@ co: setting_default_privacy: Cunfidenzialità di i statuti setting_default_sensitive: Sempre cunsiderà media cum’è sensibili setting_delete_modal: Mustrà une cunfirmazione per toglie un statutu + setting_display_media: Affissera di i media + setting_display_media_default: Predefinitu + setting_display_media_hide_all: Piattà tuttu + setting_display_media_show_all: Affissà tuttu + setting_expand_spoilers: Sempre slibrà i statutu marcati cù un'avertimentu CW setting_hide_network: Piattà a vostra rete setting_noindex: Dumandà à i motori di ricerca internet d’un pudè micca esse truvatu·a cusì setting_reduce_motion: Fà chì l’animazione vanu più pianu diff --git a/config/locales/simple_form.cs.yml b/config/locales/simple_form.cs.yml index dbff526448..ed50e13ffe 100644 --- a/config/locales/simple_form.cs.yml +++ b/config/locales/simple_form.cs.yml @@ -11,6 +11,7 @@ cs: display_name: one: Zbývá 1 znak other: Zbývá vám %{count} znaků + email: Bude vám poslán potvrzovací e-mail fields: Na profilu můžete mít až 4 položky zobrazené jako tabulka header: PNG, GIF či JPG. Maximálně %{size}. Bude zmenšena na %{dimensions} px inbox_url: Zkopírujte URL z hlavní stránky mostu, který chcete použít @@ -20,12 +21,17 @@ cs: note: one: Zbývá 1znak other: Zbývá %{count} znaků + password: Použijte alespoň 8 znaků phrase: Shoda bude nalezena bez ohledu na velikost písmen v těle tootu či varování o obsahu scopes: Které API bude aplikace povolena používat. Pokud vyberete rozsah nejvyššího stupně, nebudete je muset vybírat po jednom. setting_default_language: Jazyk vašich tootů může být detekován automaticky, není to však vždy přesné + setting_display_media_default: Skrývat média označená jako citlivá + setting_display_media_hide_all: Vždy skrývat všechna média + setting_display_media_show_all: Vždy zobrazovat média označená jako citlivá setting_hide_network: Koho sledujete a kdo sleduje vás nebude zobrazeno na vašem profilu setting_noindex: Ovlivňuje váš veřejný profil a stránky příspěvků setting_theme: Ovlivňuje jak Mastodon vypadá, jste-li přihlášen na libovolném zařízení. + username: Vaše uživatelské jméno bude na %{domain} unikátní whole_word: Je-li klíčové slovo či fráze pouze alfanumerická, bude aplikována pouze, pokud se shoduje s celým slovem imports: data: Soubor CSV exportován z jiné instance Mastodon @@ -69,6 +75,11 @@ cs: setting_default_privacy: Soukromí příspěvků setting_default_sensitive: Vždy označovat média jako citlivá setting_delete_modal: Zobrazovat před smazáním tootu potvrzovací okno + setting_display_media: Zobrazování médií + setting_display_media_default: Výchozí + setting_display_media_hide_all: Skrýt vše + setting_display_media_show_all: Zobrazit vše + setting_expand_spoilers: Vždy rozbalit tooty označené varováními o obsahu setting_hide_network: Skrýt svou síť setting_noindex: Neindexovat svůj profil vyhledávači setting_reduce_motion: Redukovat pohyb v animacích diff --git a/config/locales/simple_form.de.yml b/config/locales/simple_form.de.yml index e13eece794..cca9361e43 100644 --- a/config/locales/simple_form.de.yml +++ b/config/locales/simple_form.de.yml @@ -11,6 +11,7 @@ de: display_name: one: 1 Zeichen verbleibt other: %{count} Zeichen verbleiben + email: Du wirst ein Bestätigungs-E-Mail erhalten fields: Du kannst bis zu 4 Elemente als Tabelle dargestellt auf deinem Profil anzeigen lassen header: PNG, GIF oder JPG. Maximal %{size}. Wird auf 700×335 px herunterskaliert inbox_url: Kopiere die URL von der Startseite des gewünschten Relays @@ -20,12 +21,17 @@ de: note: one: 1 Zeichen verbleibt other: %{count} Zeichen verbleiben + password: Verwende mindestens 8 Zeichen phrase: Wird unabhängig vom umgebenen Text oder Inhaltswarnung eines Beitrags verglichen scopes: Welche Schnittstellen der Applikation erlaubt sind. Wenn du einen Top-Level-Scope auswählst, dann musst du nicht jeden einzelnen darunter auswählen. setting_default_language: Die Sprache der Beiträge kann automatisch erkannt werden, aber dies ist nicht immer genau + setting_display_media_default: Verstecke Medien, die als sensibel markiert sind + setting_display_media_hide_all: Alle Medien immer verstecken + setting_display_media_show_all: Medien, die als sensibel markiert sind, immer anzeigen setting_hide_network: Wem du folgst und wer dir folgt wird in deinem Profil nicht angezeigt setting_noindex: Betrifft dein öffentliches Profil und deine Beiträge setting_theme: Wirkt sich darauf aus, wie Mastodon aussieht, egal auf welchem Gerät du eingeloggt bist. + username: Dein Benutzer:innen-Name wird auf %{domain} nur einmal vorkommen whole_word: Wenn das Schlüsselwort oder -phrase nur Buchstaben und Zahlen enthält, wird es nur angewendet werden, wenn es dem ganzen Wort entspricht imports: data: CSV-Datei, die aus einer anderen Mastodon-Instanz exportiert wurde @@ -69,6 +75,11 @@ de: setting_default_privacy: Beitragssichtbarkeit setting_default_sensitive: Medien immer als heikel markieren setting_delete_modal: Bestätigungsdialog anzeigen, bevor ein Beitrag gelöscht wird + setting_display_media: Medien-Anzeige + setting_display_media_default: Standard + setting_display_media_hide_all: Alle verstecken + setting_display_media_show_all: Alle anzeigen + setting_expand_spoilers: Toots mit Inhaltswarnungen immer ausklappen setting_hide_network: Blende dein Netzwerk aus setting_noindex: Suchmaschinen-Indexierung verhindern setting_reduce_motion: Bewegung in Animationen verringern diff --git a/config/locales/simple_form.el.yml b/config/locales/simple_form.el.yml index 96a7547e48..823f253307 100644 --- a/config/locales/simple_form.el.yml +++ b/config/locales/simple_form.el.yml @@ -11,6 +11,7 @@ el: display_name: one: απομένει 1 χαρακτήρας other: απομένουν %{count} χαρακτήρες + email: Θα σου σταλεί email επιβεβαίωσης fields: Μπορείς να έχεις έως 4 σημειώσεις σε μορφή πίνακα στο προφίλ σου header: PNG, GIF ή JPG. Έως %{size}. Θα περιοριστεί σε διάσταση %{dimensions}px inbox_url: Αντέγραψε το URL της αρχικής σελίδας του ανταποκριτή (relay) που θέλεις να χρησιμοποιήσεις @@ -20,12 +21,17 @@ el: note: one: απομένει 1 χαρακτήρας other: απομένουν %{count} χαρακτήρες + password: Χρησιμοποίησε τουλάχιστον 8 χαρακτήρες phrase: Θα ταιριάζει ανεξαρτήτως πεζών/κεφαλαίων ή προειδοποίησης περιεχομένου του τουτ scopes: Ποια API θα επιτρέπεται στην εφαρμογή να χρησιμοποιήσεις. Αν επιλέξεις κάποιο υψηλό εύρος εφαρμογής, δε χρειάζεται να επιλέξεις και εξειδικευμένα. setting_default_language: Η γλώσσα των τουτ σου μπορεί να ανιχνευτεί αυτόματα αλλά δεν είναι πάντα ακριβές + setting_display_media_default: Απόκρυψη ευαίσθητων πολυμέσων + setting_display_media_hide_all: Μόνιμη απόκρυψη όλων των πολυμέσων + setting_display_media_show_all: Μόνιμη εμφάνιση ευαίσθητων πολυμέσων setting_hide_network: Δε θα εμφανίζεται στο προφίλ σου ποιους ακολουθείς και ποιοι σε ακολουθούν setting_noindex: Επηρεάζει το δημόσιο προφίλ και τις δημοσιεύσεις σου setting_theme: Επηρεάζει την εμφάνιση του Mastodon όταν συνδέεται από οποιαδήποτε συσκευή. + username: Το όνομα χρήστη σου θα είναι μοναδικό στο %{domain} whole_word: Όταν η λέξη ή η φράση κλειδί είναι μόνο αλφαριθμητική, θα εφαρμοστεί μόνο αν ταιριάζει με ολόκληρη τη λέξη imports: data: Αρχείο CSV που έχει εξαχθεί από διαφορετικό κόμβο Mastodon @@ -69,6 +75,11 @@ el: setting_default_privacy: Ιδιωτικότητα δημοσιεύσεων setting_default_sensitive: Σημείωνε πάντα τα πολυμέσα ως ευαίσθητου περιεχομένου setting_delete_modal: Εμφάνιση ερώτησης επιβεβαίωσης πριν διαγράψεις ένα τουτ + setting_display_media: Εμφάνιση πολυμέσων + setting_display_media_default: Προκαθορισμένο + setting_display_media_hide_all: Απόκρυψη όλων + setting_display_media_show_all: Εμφάνιση όλων + setting_expand_spoilers: Μόνιμη ανάπτυξη των τουτ με προειδοποίηση περιεχομένου setting_hide_network: Κρύψε τις διασυνδέσεις σου setting_noindex: Επέλεξε να μην συμμετέχεις στα αποτελέσματα μηχανών αναζήτησης setting_reduce_motion: Μείωση κίνησης κινουμένων στοιχείων diff --git a/config/locales/simple_form.fa.yml b/config/locales/simple_form.fa.yml index 418b308b11..3e2398d557 100644 --- a/config/locales/simple_form.fa.yml +++ b/config/locales/simple_form.fa.yml @@ -11,6 +11,7 @@ fa: display_name: one: 1 حرف باقی مانده other: %{count} حرف باقی مانده + email: به شما ایمیل تأییدی فرستاده خواهد شد fields: شما می‌توانید تا چهار مورد را در یک جدول در نمایهٔ خود نمایش دهید header: یکی از قالب‌های PNG یا GIF یا JPG. بیشترین اندازه %{size}. تصویر به اندازهٔ %{dimensions} پیکسل تبدیل خواهد شد inbox_url: نشانی صفحهٔ اصلی رله‌ای را که می‌خواهید به کار ببرید کپی کنید @@ -20,12 +21,17 @@ fa: note: one: 1 حرف باقی مانده other: %{count} حرف باقی مانده + password: دست‌کم باید ۸ نویسه داشته باشد phrase: مستقل از کوچکی و بزرگی حروف، با متن اصلی یا هشدار محتوای بوق‌ها مقایسه می‌شود scopes: واسط‌های برنامه‌نویسی که این برنامه به آن دسترسی دارد. اگر بالاترین سطح دسترسی را انتخاب کنید، دیگر نیازی به انتخاب سطح‌های پایینی ندارید. setting_default_language: زبان نوشته‌های شما به طور خودکار تشخیص داده می‌شود، ولی این تشخصی همیشه دقیق نیست + setting_display_media_default: تصویرهایی را که به عنوان حساس علامت زده شده‌اند پنهان کن + setting_display_media_hide_all: همیشه همهٔ عکس‌ها و ویدیوها را پنهان کن + setting_display_media_show_all: همیشه تصویرهایی را که به عنوان حساس علامت زده شده‌اند را نشان بده setting_hide_network: فهرست پیگیران شما و فهرست کسانی که شما پی می‌گیرید روی نمایهٔ شما دیده نخواهد شد setting_noindex: روی نمایهٔ عمومی و صفحهٔ نوشته‌های شما تأثیر می‌گذارد setting_theme: ظاهر ماستدون را وقتی که از هر دستگاهی به آن وارد می‌شوید تعیین می‌کند. + username: نام کاربری شما روی %{domain} یکتا خواهد بود whole_word: اگر کلیدواژه فقط دارای حروف و اعداد باشد، تنها وقتی پیدا می‌شود که با کل یک واژه در متن منطبق باشد، نه با بخشی از یک واژه imports: data: پروندهٔ CSV که از سرور ماستدون دیگری برون‌سپاری شده @@ -69,6 +75,11 @@ fa: setting_default_privacy: حریم خصوصی نوشته‌ها setting_default_sensitive: همیشه تصاویر را به عنوان حساس علامت بزن setting_delete_modal: نمایش پیغام تأیید پیش از پاک کردن یک نوشته + setting_display_media: نمایش عکس و ویدیو + setting_display_media_default: پیش‌فرض + setting_display_media_hide_all: نهفتن همه + setting_display_media_show_all: نمایش همه + setting_expand_spoilers: همیشه بوق‌هایی را که هشدار محتوا دارند کامل نشان بده setting_hide_network: نهفتن شبکهٔ ارتباطی setting_noindex: درخواست از موتورهای جستجوگر برای ظاهر نشدن در نتایج جستجو setting_reduce_motion: کاستن از حرکت در پویانمایی‌ها diff --git a/config/locales/simple_form.fr.yml b/config/locales/simple_form.fr.yml index 1e0c4d3e67..6403bced3b 100644 --- a/config/locales/simple_form.fr.yml +++ b/config/locales/simple_form.fr.yml @@ -11,6 +11,7 @@ fr: display_name: one: 1 caractère restant other: %{count} caractères restants + email: Vous recevrez un courriel de confirmation fields: Vous pouvez avoir jusqu’à 4 éléments affichés en tant que tableau sur votre profil header: Au format PNG, GIF ou JPG. 2 Mo maximum. Sera réduit à %{dimensions}px inbox_url: Copiez l’URL depuis la page d’accueil du relais que vous souhaitez utiliser @@ -20,12 +21,17 @@ fr: note: one: 1 caractère restant other: %{count} caractères restants + password: Utilisez au moins 8 caractères phrase: Sera trouvé sans que la case ou l’avertissement de contenu du pouet soit pris en compte scopes: À quelles APIs l’application sera autorisée à accéder. Si vous sélectionnez un périmètre de haut-niveau, vous n’avez pas besoin de sélectionner les individuels. setting_default_language: La langue de vos pouets peut être détectée automatiquement, mais ça n’est pas toujours pertinent + setting_display_media_default: Masquer les supports marqués comme sensibles + setting_display_media_hide_all: Toujours masquer tous les médias + setting_display_media_show_all: Toujours afficher les médias marqués comme sensibles setting_hide_network: Ceux que vous suivez et ceux qui vous suivent ne seront pas affichés sur votre profil setting_noindex: Affecte votre profil public ainsi que vos statuts setting_theme: Affecte l’apparence de Mastodon quand vous êtes connecté·e depuis n’importe quel appareil. + username: Votre nom d'utilisateur sera unique sur %{domain} whole_word: Lorsque le mot-clef ou la phrase-clef est uniquement alphanumérique, ça sera uniquement appliqué s’il correspond au mot entier imports: data: Un fichier CSV généré par une autre instance de Mastodon @@ -69,6 +75,11 @@ fr: setting_default_privacy: Confidentialité des statuts setting_default_sensitive: Toujours marquer les médias comme sensibles setting_delete_modal: Afficher une fenêtre de confirmation avant de supprimer un pouet + setting_display_media: Affichage des médias + setting_display_media_default: Défaut + setting_display_media_hide_all: Masquer tout + setting_display_media_show_all: Montrer tout + setting_expand_spoilers: Toujours développer les pouëts marqués d'un avertissement de contenu setting_hide_network: Cacher votre réseau setting_noindex: Demander aux moteurs de recherche de ne pas indexer vos informations personnelles setting_reduce_motion: Réduire la vitesse des animations diff --git a/config/locales/simple_form.gl.yml b/config/locales/simple_form.gl.yml index 935545b0ea..f81d346108 100644 --- a/config/locales/simple_form.gl.yml +++ b/config/locales/simple_form.gl.yml @@ -11,6 +11,7 @@ gl: display_name: one: 1 caracter restante other: %{count} caracteres restantes + email: Enviaráselle un correo-e de confirmación fields: Pode ter ate 4 elementos no seu perfil mostrados como unha táboa header: PNG, GIF ou JPG. Máximo %{size}. Será reducida a %{dimensions}px inbox_url: Copiar o URL desde a páxina de inicio do repetidor que quere utilizar @@ -20,12 +21,17 @@ gl: note: one: 1 caracter restante other: %{count} caracteres restantes + password: Utilice 8 caracteres ao menos phrase: Concordará independentemente das maiúsculas ou avisos de contido no toot scopes: A que APIs terá acceso a aplicación. Si selecciona un ámbito de alto nivel, non precisa seleccionar elementos individuais. setting_default_language: Pódese detectar automáticamente o idioma dos seus toots, mais non sempre é preciso + setting_display_media_default: Ocultar medios marcados como sensibles + setting_display_media_hide_all: Ocultar sempre os medios + setting_display_media_show_all: Mostrar sempre os medios marcados como sensibles setting_hide_network: Non se mostrará no seu perfil quen a segue e quen a está a seguir setting_noindex: Afecta ao seu perfil público e páxinas de estado setting_theme: Afecta ao aspecto de Mastodon en calquer dispositivo cando está conectada. + username: O seu nome de usuaria será único en %{domain} whole_word: Si a chave ou frase de paso é só alfanumérica, só se aplicará si concorda a palabra completa imports: data: Ficheiro CSV exportado desde outra instancia Mastodon @@ -69,6 +75,11 @@ gl: setting_default_privacy: Intimidade da publicación setting_default_sensitive: Marcar sempre multimedia como sensible setting_delete_modal: Solicitar confirmación antes de eliminar unha mensaxe + setting_display_media: Mostrar medios + setting_display_media_default: Por omisión + setting_display_media_hide_all: Ocultar todo + setting_display_media_show_all: Mostrar todo + setting_expand_spoilers: Despregar sempre as mensaxes marcadas con avisos de contido setting_hide_network: Agochar a súa rede setting_noindex: Pedir non aparecer nas buscas dos motores de busca setting_reduce_motion: Reducir o movemento nas animacións diff --git a/config/locales/simple_form.ja.yml b/config/locales/simple_form.ja.yml index 3d9c507590..2ef459040f 100644 --- a/config/locales/simple_form.ja.yml +++ b/config/locales/simple_form.ja.yml @@ -9,6 +9,7 @@ ja: context: フィルターを適用する対象 (複数選択可) digest: 長期間使用していない場合と不在時に返信を受けた場合のみ送信されます display_name: あと%{count}文字入力できます。 + email: 確認のメールが送信されます fields: プロフィールに表として4つまでの項目を表示することができます header: "%{size}までのPNG、GIF、JPGが利用可能です。 %{dimensions}pxまで縮小されます" inbox_url: 使用したいリレーサーバーのトップページからURLをコピーします @@ -16,6 +17,7 @@ ja: locale: ユーザーインターフェース、メールやプッシュ通知の言語 locked: フォロワーを手動で承認する必要があります note: あと%{count}文字入力できます。 + password: 少なくとも8文字は入力してください phrase: トゥートの大文字小文字や閲覧注意に関係なく一致 scopes: アプリの API に許可するアクセス権を選択してください。最上位のスコープを選択する場合、個々のスコープを選択する必要はありません。 setting_default_language: トゥートの言語は自動的に検出されますが、必ずしも正確とは限りません @@ -25,6 +27,7 @@ ja: setting_hide_network: フォローとフォロワーの情報がプロフィールページで見られないようにします setting_noindex: 公開プロフィールおよび各投稿ページに影響します setting_theme: ログインしている全てのデバイスで適用されるデザインです。 + username: あなたのユーザー名は %{domain} の中で重複していない必要があります whole_word: キーワードまたはフレーズが英数字のみの場合、単語全体と一致する場合のみ適用されるようになります imports: data: 他の Mastodon インスタンスからエクスポートしたCSVファイルを選択して下さい From b972478812316da2f5c0d24c60386d408e027424 Mon Sep 17 00:00:00 2001 From: Eugen Rochko Date: Sat, 13 Oct 2018 01:51:30 +0200 Subject: [PATCH 18/87] Improve style of notice/alert messages (#8973) --- app/javascript/styles/mastodon-light/diff.scss | 14 -------------- app/javascript/styles/mastodon/forms.scss | 13 ++++++++++++- 2 files changed, 12 insertions(+), 15 deletions(-) diff --git a/app/javascript/styles/mastodon-light/diff.scss b/app/javascript/styles/mastodon-light/diff.scss index ac161a0042..78bc2dbb6d 100644 --- a/app/javascript/styles/mastodon-light/diff.scss +++ b/app/javascript/styles/mastodon-light/diff.scss @@ -286,20 +286,6 @@ } } -.flash-message { - box-shadow: none; - - &.notice { - background: rgba($success-green, 0.5); - color: lighten($success-green, 12%); - } - - &.alert { - background: rgba($error-red, 0.5); - color: lighten($error-red, 12%); - } -} - .simple_form, .table-form { .warning { diff --git a/app/javascript/styles/mastodon/forms.scss b/app/javascript/styles/mastodon/forms.scss index be2bf7cead..eb94f2273b 100644 --- a/app/javascript/styles/mastodon/forms.scss +++ b/app/javascript/styles/mastodon/forms.scss @@ -460,9 +460,20 @@ code { border-radius: 4px; padding: 15px 10px; margin-bottom: 30px; - box-shadow: 0 0 5px rgba($base-shadow-color, 0.2); text-align: center; + &.notice { + border: 1px solid rgba($valid-value-color, 0.5); + background: rgba($valid-value-color, 0.25); + color: $valid-value-color; + } + + &.alert { + border: 1px solid rgba($error-value-color, 0.5); + background: rgba($error-value-color, 0.25); + color: $error-value-color; + } + p { margin-bottom: 15px; } From 47bca3394590b59fb818d16bc05b9ad08cdc64dd Mon Sep 17 00:00:00 2001 From: mayaeh Date: Sun, 14 Oct 2018 00:00:15 +0900 Subject: [PATCH 19/87] Fix description about custom mascot. (#8974) --- config/locales/en.yml | 2 +- config/locales/ja.yml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/config/locales/en.yml b/config/locales/en.yml index 8c70f9ed68..f4a0111d30 100644 --- a/config/locales/en.yml +++ b/config/locales/en.yml @@ -369,7 +369,7 @@ en: desc_html: Displayed on the frontpage. At least 600x100px recommended. When not set, falls back to instance thumbnail title: Hero image mascot: - desc_html: Displayed on multiple pages. At least 293×205px recommended. When not set, falls back to instance thumbnail + desc_html: Displayed on multiple pages. At least 293×205px recommended. When not set, falls back to default mascot title: Mascot image peers_api_enabled: desc_html: Domain names this instance has encountered in the fediverse diff --git a/config/locales/ja.yml b/config/locales/ja.yml index d199fe715d..ecd6e82d4e 100644 --- a/config/locales/ja.yml +++ b/config/locales/ja.yml @@ -369,7 +369,7 @@ ja: desc_html: フロントページに表示されます。サイズは600x100px以上推奨です。未設定の場合、インスタンスのサムネイルが使用されます title: ヒーローイメージ mascot: - desc_html: 複数のページに表示されます。サイズは293x205px以上推奨です。未設定の場合、インスタンスのサムネイルが使用されます + desc_html: 複数のページに表示されます。サイズは293x205px以上推奨です。未設定の場合、標準のマスコットが使用されます title: マスコットイメージ peers_api_enabled: desc_html: 連合内でこのインスタンスが遭遇したドメインの名前 From 57063bd17d323764c503c6dd91bdf3dab0004020 Mon Sep 17 00:00:00 2001 From: jooops Date: Mon, 15 Oct 2018 04:38:41 +0200 Subject: [PATCH 20/87] fix invites in italian language (#8982) * fix invites in italian language * fix invites in italian language --- config/locales/it.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/config/locales/it.yml b/config/locales/it.yml index 5780f1e0c6..5182e33729 100644 --- a/config/locales/it.yml +++ b/config/locales/it.yml @@ -535,6 +535,7 @@ it: generate: Genera invited_by: 'Sei stato invitato da:' max_uses: + one: un uso other: "%{count} utilizzi" max_uses_prompt: Nessun limite prompt: Genera e condividi dei link ad altri per garantire l'accesso a questa istanza From efd09e2ebba7e9f0135bd47c44a77e2fc421aa67 Mon Sep 17 00:00:00 2001 From: Masoud Abkenar Date: Mon, 15 Oct 2018 04:39:20 +0200 Subject: [PATCH 21/87] undo part of PR 8202 to fix RTL (#8979) --- app/javascript/styles/mastodon/stream_entries.scss | 1 - 1 file changed, 1 deletion(-) diff --git a/app/javascript/styles/mastodon/stream_entries.scss b/app/javascript/styles/mastodon/stream_entries.scss index 14306c8bdf..d8bd303772 100644 --- a/app/javascript/styles/mastodon/stream_entries.scss +++ b/app/javascript/styles/mastodon/stream_entries.scss @@ -3,7 +3,6 @@ border-radius: 4px; overflow: hidden; margin-bottom: 10px; - text-align: left; @media screen and (max-width: $no-gap-breakpoint) { margin-bottom: 0; From d35801aaa2ad9d06345efa45cf524113469fdd02 Mon Sep 17 00:00:00 2001 From: Masoud Abkenar Date: Mon, 15 Oct 2018 16:09:08 +0200 Subject: [PATCH 22/87] Fixes 8987 broken alignment at "Remote interaction dialog" (#8988) --- app/javascript/styles/mastodon/forms.scss | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/javascript/styles/mastodon/forms.scss b/app/javascript/styles/mastodon/forms.scss index eb94f2273b..337941a080 100644 --- a/app/javascript/styles/mastodon/forms.scss +++ b/app/javascript/styles/mastodon/forms.scss @@ -562,12 +562,12 @@ code { .oauth-prompt, .follow-prompt { margin-bottom: 30px; - text-align: center; color: $darker-text-color; h2 { font-size: 16px; margin-bottom: 30px; + text-align: center; } strong { From 528ba4861d51376d8c7a157a2e2297cf1e5bde42 Mon Sep 17 00:00:00 2001 From: Eugen Rochko Date: Tue, 16 Oct 2018 03:01:07 +0200 Subject: [PATCH 23/87] Update issue templates (#8989) * Update issue templates * Update bug_report.md * Update feature_request.md * Update support.md * Update feature_request.md --- .github/ISSUE_TEMPLATE/bug_report.md | 25 ++++++++++++++++++----- .github/ISSUE_TEMPLATE/feature_request.md | 16 ++++++++++----- .github/ISSUE_TEMPLATE/support.md | 10 +++++++++ 3 files changed, 41 insertions(+), 10 deletions(-) create mode 100644 .github/ISSUE_TEMPLATE/support.md diff --git a/.github/ISSUE_TEMPLATE/bug_report.md b/.github/ISSUE_TEMPLATE/bug_report.md index 602530db0e..f49964bd9f 100644 --- a/.github/ISSUE_TEMPLATE/bug_report.md +++ b/.github/ISSUE_TEMPLATE/bug_report.md @@ -1,12 +1,27 @@ --- name: Bug Report -about: Create a report to help us improve +about: If something isn't working as expected --- -[Issue text goes here]. + -* * * * + -- [ ] I searched or browsed the repo’s other issues to ensure this is not a duplicate. -- [ ] This bug happens on a [tagged release](https://github.com/tootsuite/mastodon/releases) and not on `master` (If you're a user, don't worry about this). +### Expected behaviour + + + +### Actual behaviour + + + +### Steps to reproduce the problem + + + +### Specifications + + + + diff --git a/.github/ISSUE_TEMPLATE/feature_request.md b/.github/ISSUE_TEMPLATE/feature_request.md index 46602fd2c0..f61a262ca7 100644 --- a/.github/ISSUE_TEMPLATE/feature_request.md +++ b/.github/ISSUE_TEMPLATE/feature_request.md @@ -1,11 +1,17 @@ ---- +-- name: Feature Request -about: Suggest an idea for this project +about: I have a suggestion --- -[Issue text goes here]. + -* * * * + -- [ ] I searched or browsed the repo’s other issues to ensure this is not a duplicate. +### Pitch + + + +### Motivation + + diff --git a/.github/ISSUE_TEMPLATE/support.md b/.github/ISSUE_TEMPLATE/support.md new file mode 100644 index 0000000000..7fbc86ff14 --- /dev/null +++ b/.github/ISSUE_TEMPLATE/support.md @@ -0,0 +1,10 @@ +--- +name: Support +about: Ask for help with your deployment + +--- + +We primarily use GitHub as a bug and feature tracker. For usage questions, troubleshooting of deployments and other individual technical assistance, please use one of the resources below: + +- https://discourse.joinmastodon.org +- #mastodon on irc.freenode.net From 85334d136241b3f621b554d8bdf5fe64a096437d Mon Sep 17 00:00:00 2001 From: Eugen Rochko Date: Tue, 16 Oct 2018 03:02:01 +0200 Subject: [PATCH 24/87] Fix feature request issue template --- .github/ISSUE_TEMPLATE/feature_request.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/ISSUE_TEMPLATE/feature_request.md b/.github/ISSUE_TEMPLATE/feature_request.md index f61a262ca7..3890729e22 100644 --- a/.github/ISSUE_TEMPLATE/feature_request.md +++ b/.github/ISSUE_TEMPLATE/feature_request.md @@ -1,4 +1,4 @@ --- +--- name: Feature Request about: I have a suggestion From 8b0a980e288d3345a731047f638a4619b999fd3a Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" Date: Tue, 16 Oct 2018 07:50:09 +0200 Subject: [PATCH 25/87] Bump strong_migrations from 0.2.3 to 0.3.0 (#8991) Bumps [strong_migrations](https://github.com/ankane/strong_migrations) from 0.2.3 to 0.3.0. - [Release notes](https://github.com/ankane/strong_migrations/releases) - [Changelog](https://github.com/ankane/strong_migrations/blob/master/CHANGELOG.md) - [Commits](https://github.com/ankane/strong_migrations/compare/v0.2.3...v0.3.0) Signed-off-by: dependabot[bot] --- Gemfile | 2 +- Gemfile.lock | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/Gemfile b/Gemfile index 0e50dce218..c5e8253358 100644 --- a/Gemfile +++ b/Gemfile @@ -81,7 +81,7 @@ gem 'simple-navigation', '~> 4.0' gem 'simple_form', '~> 4.0' gem 'sprockets-rails', '~> 3.2', require: 'sprockets/railtie' gem 'stoplight', '~> 2.1.3' -gem 'strong_migrations', '~> 0.2' +gem 'strong_migrations', '~> 0.3' gem 'tty-command', '~> 0.8', require: false gem 'tty-prompt', '~> 0.17', require: false gem 'twitter-text', '~> 1.14' diff --git a/Gemfile.lock b/Gemfile.lock index 024d3c6871..0d436484cc 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -269,7 +269,7 @@ GEM httplog (1.1.1) rack (>= 1.0) rainbow (>= 2.0.0) - i18n (1.1.0) + i18n (1.1.1) concurrent-ruby (~> 1.0) i18n-tasks (0.9.25) activesupport (>= 4.0.2) @@ -585,7 +585,7 @@ GEM stoplight (2.1.3) streamio-ffmpeg (3.0.2) multi_json (~> 1.8) - strong_migrations (0.2.3) + strong_migrations (0.3.0) activerecord (>= 3.2.0) temple (0.8.0) terminal-table (1.8.0) @@ -752,7 +752,7 @@ DEPENDENCIES stackprof stoplight (~> 2.1.3) streamio-ffmpeg (~> 3.0) - strong_migrations (~> 0.2) + strong_migrations (~> 0.3) thor (~> 0.20) tty-command (~> 0.8) tty-prompt (~> 0.17) From 35b576dbecfd9e980206189b61efe58fba9269b9 Mon Sep 17 00:00:00 2001 From: Eugen Rochko Date: Tue, 16 Oct 2018 14:07:54 +0200 Subject: [PATCH 26/87] Improve form for selecting media display preference (#8965) Regression from #8569 --- app/views/settings/preferences/show.html.haml | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/app/views/settings/preferences/show.html.haml b/app/views/settings/preferences/show.html.haml index 608a290e76..d889702fec 100644 --- a/app/views/settings/preferences/show.html.haml +++ b/app/views/settings/preferences/show.html.haml @@ -36,9 +36,11 @@ %hr#settings_web/ - - if Themes.instance.names.size > 1 - .fields-group - = f.input :setting_theme, collection: Themes.instance.names, label_method: lambda { |theme| I18n.t("themes.#{theme}", default: theme) }, wrapper: :with_block_label, include_blank: false + .fields-row + .fields-group.fields-row__column.fields-row__column-6 + = f.input :setting_theme, collection: Themes.instance.names, label_method: lambda { |theme| I18n.t("themes.#{theme}", default: theme) }, wrapper: :with_label, include_blank: false, hint: false + .fields-group.fields-row__column.fields-row__column-6 + = f.input :setting_display_media, collection: ['default', 'show_all', 'hide_all'], wrapper: :with_label, include_blank: false, label_method: lambda { |item| t("simple_form.hints.defaults.setting_display_media_#{item}") }, hint: false .fields-group = f.input :setting_unfollow_modal, as: :boolean, wrapper: :with_label @@ -47,7 +49,6 @@ .fields-group = f.input :setting_auto_play_gif, as: :boolean, wrapper: :with_label - = f.input :setting_display_media, collection: ['default', 'show_all', 'hide_all'], wrapper: :with_label, include_blank: false, label_method: lambda { |item| safe_join([t("simple_form.labels.defaults.setting_display_media_#{item}"), content_tag(:span, t("simple_form.hints.defaults.setting_display_media_#{item}"), class: 'hint')]) }, required: false, as: :radio_buttons, collection_wrapper_tag: 'ul', item_wrapper_tag: 'li' = f.input :setting_expand_spoilers, as: :boolean, wrapper: :with_label = f.input :setting_reduce_motion, as: :boolean, wrapper: :with_label = f.input :setting_system_font_ui, as: :boolean, wrapper: :with_label From fe9815a462cecbc25397bc0b22231e80a3d7846a Mon Sep 17 00:00:00 2001 From: Julian Date: Tue, 16 Oct 2018 14:09:03 +0200 Subject: [PATCH 27/87] one user i18n (#8992) In german one female user is "Benutzerin" not "Benutzerinnen" --- config/locales/de.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/config/locales/de.yml b/config/locales/de.yml index eb2d8ebc71..fb0235e0ce 100644 --- a/config/locales/de.yml +++ b/config/locales/de.yml @@ -36,7 +36,7 @@ de: status_count_before: mit terms: Nutzungsbedingungen user_count_after: - one: Benutzer:innen + one: Benutzer:in other: Benutzer:innen user_count_before: Zuhause für what_is_mastodon: Was ist Mastodon? From f5e2e96e958e3f9011da932b84af00ae7cefd561 Mon Sep 17 00:00:00 2001 From: Quint Guvernator Date: Tue, 16 Oct 2018 13:55:05 -0400 Subject: [PATCH 28/87] always allow DMs from staff (#8993) --- app/services/notify_service.rb | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/app/services/notify_service.rb b/app/services/notify_service.rb index 63bf8f17ab..49022a844e 100644 --- a/app/services/notify_service.rb +++ b/app/services/notify_service.rb @@ -59,9 +59,14 @@ class NotifyService < BaseService @notification.target_status.in_reply_to_account_id == @recipient.id && @notification.target_status.thread&.direct_visibility? end + def from_staff? + @notification.from_account.local? && @notification.from_account.user.present? && @notification.from_account.user.staff? + end + def optional_non_following_and_direct? direct_message? && @recipient.user.settings.interactions['must_be_following_dm'] && + !from_staff? && !following_sender? && !response_to_recipient? end From 926451152e810603f305b60a8746ecca706df4ca Mon Sep 17 00:00:00 2001 From: Quint Guvernator Date: Tue, 16 Oct 2018 17:42:55 -0400 Subject: [PATCH 29/87] Fix some bad localization strings (#8994) * fix finnish locale variable issue * fix broken welsh localized string --- config/locales/cy.yml | 2 +- config/locales/fi.yml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/config/locales/cy.yml b/config/locales/cy.yml index 893f7cf6f2..88aa3ee562 100644 --- a/config/locales/cy.yml +++ b/config/locales/cy.yml @@ -192,7 +192,7 @@ cy: unsilence_account: Terfynodd %{name} dawelu cyfrif %{target} unsuspend_account: Terfynodd %{name} yr ataliad ar gyfrif %{target} update_custom_emoji: Diweddarodd %{name} emoji %{target} - update_status: Diweddarodd %{name} statws gan %{taget} + update_status: Diweddarodd %{name} statws gan %{target} deleted_status: "(statws wedi ei ddileu)" title: Log archwilio custom_emojis: diff --git a/config/locales/fi.yml b/config/locales/fi.yml index c2552b5399..c4d1dd8713 100644 --- a/config/locales/fi.yml +++ b/config/locales/fi.yml @@ -609,7 +609,7 @@ fi: uc_browser: UCBrowser weibo: Weibo current_session: Nykyinen istunto - description: "%{selain}, %{platform}" + description: "%{browser}, %{platform}" explanation: Nämä verkkoselaimet ovat tällä hetkellä kirjautuneet Mastodon-tilillesi. ip: IP platforms: From 7085b21f70ee0640e034c5884a93da9b015b4ab5 Mon Sep 17 00:00:00 2001 From: Gomasy Date: Wed, 17 Oct 2018 23:54:59 +0900 Subject: [PATCH 30/87] Add destroy_custom_emoji translation (#8997) Includes Japanese and English --- config/locales/en.yml | 1 + config/locales/ja.yml | 1 + 2 files changed, 2 insertions(+) diff --git a/config/locales/en.yml b/config/locales/en.yml index f4a0111d30..26fe0080de 100644 --- a/config/locales/en.yml +++ b/config/locales/en.yml @@ -177,6 +177,7 @@ en: create_domain_block: "%{name} blocked domain %{target}" create_email_domain_block: "%{name} blacklisted e-mail domain %{target}" demote_user: "%{name} demoted user %{target}" + destroy_custom_emoji: "%{name} destroyed emoji %{target}" destroy_domain_block: "%{name} unblocked domain %{target}" destroy_email_domain_block: "%{name} whitelisted e-mail domain %{target}" destroy_status: "%{name} removed status by %{target}" diff --git a/config/locales/ja.yml b/config/locales/ja.yml index ecd6e82d4e..84426f84eb 100644 --- a/config/locales/ja.yml +++ b/config/locales/ja.yml @@ -177,6 +177,7 @@ ja: create_domain_block: "%{name} さんがドメイン %{target} をブロックしました" create_email_domain_block: "%{name} さんがドメイン %{target} をメールアドレス用ブラックリストに追加しました" demote_user: "%{name} さんが %{target} さんを降格しました" + destroy_custom_emoji: "%{name} さんがカスタム絵文字 %{target} を削除しました" destroy_domain_block: "%{name} さんがドメイン %{target} のブロックを外しました" destroy_email_domain_block: "%{name} さんがドメイン %{target} をメールアドレス用ブラックリストから外しました" destroy_status: "%{name} さんが %{target} さんの投稿を削除しました" From adb06baef6d7cb1e3c051c621ba454aec82edeef Mon Sep 17 00:00:00 2001 From: ThibG Date: Wed, 17 Oct 2018 16:56:16 +0200 Subject: [PATCH 31/87] Handle global hotkeys even when no element has focus (#8998) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This fixes hotkeys not working when pressing the column “back” button, for instance. --- app/javascript/mastodon/features/ui/index.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/javascript/mastodon/features/ui/index.js b/app/javascript/mastodon/features/ui/index.js index fb6f675f4c..662375a769 100644 --- a/app/javascript/mastodon/features/ui/index.js +++ b/app/javascript/mastodon/features/ui/index.js @@ -460,7 +460,7 @@ class UI extends React.PureComponent { }; return ( - +
From 00387be2898cab016fa730d4f5683202cc540442 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" Date: Wed, 17 Oct 2018 16:56:26 +0200 Subject: [PATCH 32/87] Bump oj from 3.6.11 to 3.6.12 (#8996) Bumps [oj](https://github.com/ohler55/oj) from 3.6.11 to 3.6.12. - [Release notes](https://github.com/ohler55/oj/releases) - [Changelog](https://github.com/ohler55/oj/blob/master/CHANGELOG.md) - [Commits](https://github.com/ohler55/oj/compare/v3.6.11...v3.6.12) Signed-off-by: dependabot[bot] --- Gemfile.lock | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Gemfile.lock b/Gemfile.lock index 0d436484cc..ce88fe6e22 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -358,7 +358,7 @@ GEM concurrent-ruby (~> 1.0.0) sidekiq (>= 3.5.0) statsd-ruby (~> 1.2.0) - oj (3.6.11) + oj (3.6.12) omniauth (1.8.1) hashie (>= 3.4.6, < 3.6.0) rack (>= 1.6.2, < 3) From ddd30f331c7a2af38176d72d9ce2265068984bed Mon Sep 17 00:00:00 2001 From: Eugen Rochko Date: Wed, 17 Oct 2018 17:13:04 +0200 Subject: [PATCH 33/87] Improve support for aspects/circles (#8950) * Add silent column to mentions * Save silent mentions in ActivityPub Create handler and optimize it Move networking calls out of the database transaction * Add "limited" visibility level masked as "private" in the API Unlike DMs, limited statuses are pushed into home feeds. The access control rules between direct and limited statuses is almost the same, except for counter and conversation logic * Ensure silent column is non-null, add spec * Ensure filters don't check silent mentions for blocks/mutes As those are "this person is also allowed to see" rather than "this person is involved", therefore does not warrant filtering * Clean up code * Use Status#active_mentions to limit returned mentions * Fix code style issues * Use Status#active_mentions in Notification And remove stream_entry eager-loading from Notification --- app/lib/activitypub/activity.rb | 2 +- app/lib/activitypub/activity/create.rb | 24 ++++++++++++++- app/lib/activitypub/tag_manager.rb | 6 ++-- app/lib/feed_manager.rb | 8 ++--- app/lib/formatter.rb | 2 +- app/lib/ostatus/atom_serializer.rb | 2 +- app/models/account_conversation.rb | 2 +- app/models/mention.rb | 8 +++++ app/models/notification.rb | 2 +- app/models/status.rb | 15 ++++++---- app/models/stream_entry.rb | 2 +- app/policies/status_policy.rb | 8 ++--- .../activitypub/note_serializer.rb | 2 +- app/serializers/rest/status_serializer.rb | 13 ++++++++- app/services/batched_remove_status_service.rb | 2 +- app/services/fan_out_on_write_service.rb | 12 ++++++++ app/services/remove_status_service.rb | 2 +- .../stream_entries/_detailed_status.html.haml | 2 +- .../activitypub/distribution_worker.rb | 2 +- .../activitypub/reply_distribution_worker.rb | 6 +--- .../20181010141500_add_silent_to_mentions.rb | 23 +++++++++++++++ db/schema.rb | 3 +- spec/lib/activitypub/activity/create_spec.rb | 29 +++++++++++++++++++ 23 files changed, 142 insertions(+), 35 deletions(-) create mode 100644 db/migrate/20181010141500_add_silent_to_mentions.rb diff --git a/app/lib/activitypub/activity.rb b/app/lib/activitypub/activity.rb index 3a39b723ed..999954cb5b 100644 --- a/app/lib/activitypub/activity.rb +++ b/app/lib/activitypub/activity.rb @@ -96,7 +96,7 @@ class ActivityPub::Activity end def notify_about_mentions(status) - status.mentions.includes(:account).each do |mention| + status.active_mentions.includes(:account).each do |mention| next unless mention.account.local? && audience_includes?(mention.account) NotifyService.new.call(mention.account, mention) end diff --git a/app/lib/activitypub/activity/create.rb b/app/lib/activitypub/activity/create.rb index 73475bf029..7e6702a634 100644 --- a/app/lib/activitypub/activity/create.rb +++ b/app/lib/activitypub/activity/create.rb @@ -28,6 +28,7 @@ class ActivityPub::Activity::Create < ActivityPub::Activity process_status_params process_tags + process_audience ApplicationRecord.transaction do @status = Status.create!(@params) @@ -66,6 +67,27 @@ class ActivityPub::Activity::Create < ActivityPub::Activity end end + def process_audience + (as_array(@object['to']) + as_array(@object['cc'])).uniq.each do |audience| + next if audience == ActivityPub::TagManager::COLLECTIONS[:public] + + # Unlike with tags, there is no point in resolving accounts we don't already + # know here, because silent mentions would only be used for local access + # control anyway + account = account_from_uri(audience) + + next if account.nil? || @mentions.any? { |mention| mention.account_id == account.id } + + @mentions << Mention.new(account: account, silent: true) + + # If there is at least one silent mention, then the status can be considered + # as a limited-audience status, and not strictly a direct message + next unless @params[:visibility] == :direct + + @params[:visibility] = :limited + end + end + def attach_tags(status) @tags.each do |tag| status.tags << tag @@ -113,7 +135,7 @@ class ActivityPub::Activity::Create < ActivityPub::Activity return if account.nil? - @mentions << Mention.new(account: account) + @mentions << Mention.new(account: account, silent: false) end def process_emoji(tag) diff --git a/app/lib/activitypub/tag_manager.rb b/app/lib/activitypub/tag_manager.rb index 95d1cf9f35..be3a562d00 100644 --- a/app/lib/activitypub/tag_manager.rb +++ b/app/lib/activitypub/tag_manager.rb @@ -58,8 +58,8 @@ class ActivityPub::TagManager [COLLECTIONS[:public]] when 'unlisted', 'private' [account_followers_url(status.account)] - when 'direct' - status.mentions.map { |mention| uri_for(mention.account) } + when 'direct', 'limited' + status.active_mentions.map { |mention| uri_for(mention.account) } end end @@ -80,7 +80,7 @@ class ActivityPub::TagManager cc << COLLECTIONS[:public] end - cc.concat(status.mentions.map { |mention| uri_for(mention.account) }) unless status.direct_visibility? + cc.concat(status.active_mentions.map { |mention| uri_for(mention.account) }) unless status.direct_visibility? || status.limited_visibility? cc end diff --git a/app/lib/feed_manager.rb b/app/lib/feed_manager.rb index b10e5dd244..3d7db27211 100644 --- a/app/lib/feed_manager.rb +++ b/app/lib/feed_manager.rb @@ -88,7 +88,7 @@ class FeedManager end query.each do |status| - next if status.direct_visibility? || filter?(:home, status, into_account) + next if status.direct_visibility? || status.limited_visibility? || filter?(:home, status, into_account) add_to_feed(:home, into_account.id, status) end @@ -156,12 +156,12 @@ class FeedManager return true if status.reply? && (status.in_reply_to_id.nil? || status.in_reply_to_account_id.nil?) return true if phrase_filtered?(status, receiver_id, :home) - check_for_blocks = status.mentions.pluck(:account_id) + check_for_blocks = status.active_mentions.pluck(:account_id) check_for_blocks.concat([status.account_id]) if status.reblog? check_for_blocks.concat([status.reblog.account_id]) - check_for_blocks.concat(status.reblog.mentions.pluck(:account_id)) + check_for_blocks.concat(status.reblog.active_mentions.pluck(:account_id)) end return true if blocks_or_mutes?(receiver_id, check_for_blocks, :home) @@ -188,7 +188,7 @@ class FeedManager # This filter is called from NotifyService, but already after the sender of # the notification has been checked for mute/block. Therefore, it's not # necessary to check the author of the toot for mute/block again - check_for_blocks = status.mentions.pluck(:account_id) + check_for_blocks = status.active_mentions.pluck(:account_id) check_for_blocks.concat([status.in_reply_to_account]) if status.reply? && !status.in_reply_to_account_id.nil? should_filter = blocks_or_mutes?(receiver_id, check_for_blocks, :mentions) # Filter if it's from someone I blocked, in reply to someone I blocked, or mentioning someone I blocked (or muted) diff --git a/app/lib/formatter.rb b/app/lib/formatter.rb index 35d5a09b76..d13884ec81 100644 --- a/app/lib/formatter.rb +++ b/app/lib/formatter.rb @@ -27,7 +27,7 @@ class Formatter return html.html_safe # rubocop:disable Rails/OutputSafety end - linkable_accounts = status.mentions.map(&:account) + linkable_accounts = status.active_mentions.map(&:account) linkable_accounts << status.account html = raw_content diff --git a/app/lib/ostatus/atom_serializer.rb b/app/lib/ostatus/atom_serializer.rb index 1a0a635b3d..7a181fb404 100644 --- a/app/lib/ostatus/atom_serializer.rb +++ b/app/lib/ostatus/atom_serializer.rb @@ -354,7 +354,7 @@ class OStatus::AtomSerializer append_element(entry, 'summary', status.spoiler_text, 'xml:lang': status.language) if status.spoiler_text? append_element(entry, 'content', Formatter.instance.format(status).to_str || '.', type: 'html', 'xml:lang': status.language) - status.mentions.sort_by(&:id).each do |mentioned| + status.active_mentions.sort_by(&:id).each do |mentioned| append_element(entry, 'link', nil, rel: :mentioned, 'ostatus:object-type': OStatus::TagManager::TYPES[:person], href: OStatus::TagManager.instance.uri_for(mentioned.account)) end diff --git a/app/models/account_conversation.rb b/app/models/account_conversation.rb index a7205ec1a8..c12c8d233f 100644 --- a/app/models/account_conversation.rb +++ b/app/models/account_conversation.rb @@ -85,7 +85,7 @@ class AccountConversation < ApplicationRecord private def participants_from_status(recipient, status) - ((status.mentions.pluck(:account_id) + [status.account_id]).uniq - [recipient.id]).sort + ((status.active_mentions.pluck(:account_id) + [status.account_id]).uniq - [recipient.id]).sort end end diff --git a/app/models/mention.rb b/app/models/mention.rb index 8ab886b184..d01a88e32e 100644 --- a/app/models/mention.rb +++ b/app/models/mention.rb @@ -8,6 +8,7 @@ # created_at :datetime not null # updated_at :datetime not null # account_id :bigint(8) +# silent :boolean default(FALSE), not null # class Mention < ApplicationRecord @@ -18,10 +19,17 @@ class Mention < ApplicationRecord validates :account, uniqueness: { scope: :status } + scope :active, -> { where(silent: false) } + scope :silent, -> { where(silent: true) } + delegate( :username, :acct, to: :account, prefix: true ) + + def active? + !silent? + end end diff --git a/app/models/notification.rb b/app/models/notification.rb index b9bec08086..78b180301a 100644 --- a/app/models/notification.rb +++ b/app/models/notification.rb @@ -24,7 +24,7 @@ class Notification < ApplicationRecord favourite: 'Favourite', }.freeze - STATUS_INCLUDES = [:account, :application, :stream_entry, :media_attachments, :tags, mentions: :account, reblog: [:stream_entry, :account, :application, :media_attachments, :tags, mentions: :account]].freeze + STATUS_INCLUDES = [:account, :application, :media_attachments, :tags, active_mentions: :account, reblog: [:account, :application, :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 f61bd0fee4..b18cb56b21 100644 --- a/app/models/status.rb +++ b/app/models/status.rb @@ -37,7 +37,7 @@ class Status < ApplicationRecord update_index('statuses#status', :proper) if Chewy.enabled? - enum visibility: [:public, :unlisted, :private, :direct], _suffix: :visibility + enum visibility: [:public, :unlisted, :private, :direct, :limited], _suffix: :visibility belongs_to :application, class_name: 'Doorkeeper::Application', optional: true @@ -51,7 +51,8 @@ class Status < ApplicationRecord has_many :favourites, inverse_of: :status, dependent: :destroy has_many :reblogs, foreign_key: 'reblog_of_id', class_name: 'Status', inverse_of: :reblog, dependent: :destroy has_many :replies, foreign_key: 'in_reply_to_id', class_name: 'Status', inverse_of: :thread - has_many :mentions, dependent: :destroy + has_many :mentions, dependent: :destroy, inverse_of: :status + has_many :active_mentions, -> { active }, class_name: 'Mention', inverse_of: :status has_many :media_attachments, dependent: :nullify has_and_belongs_to_many :tags @@ -89,7 +90,7 @@ class Status < ApplicationRecord :status_stat, :tags, :stream_entry, - mentions: :account, + active_mentions: :account, reblog: [ :account, :application, @@ -98,7 +99,7 @@ class Status < ApplicationRecord :media_attachments, :conversation, :status_stat, - mentions: :account, + active_mentions: :account, ], thread: :account @@ -171,7 +172,11 @@ class Status < ApplicationRecord end def hidden? - private_visibility? || direct_visibility? + private_visibility? || direct_visibility? || limited_visibility? + end + + def distributable? + public_visibility? || unlisted_visibility? end def with_media? diff --git a/app/models/stream_entry.rb b/app/models/stream_entry.rb index a2f273281b..1a9afc5c7b 100644 --- a/app/models/stream_entry.rb +++ b/app/models/stream_entry.rb @@ -48,7 +48,7 @@ class StreamEntry < ApplicationRecord end def mentions - orphaned? ? [] : status.mentions.map(&:account) + orphaned? ? [] : status.active_mentions.map(&:account) end private diff --git a/app/policies/status_policy.rb b/app/policies/status_policy.rb index 6addc8a8a8..64a5111fc8 100644 --- a/app/policies/status_policy.rb +++ b/app/policies/status_policy.rb @@ -12,7 +12,7 @@ class StatusPolicy < ApplicationPolicy end def show? - if direct? + if requires_mention? owned? || mention_exists? elsif private? owned? || following_author? || mention_exists? @@ -22,7 +22,7 @@ class StatusPolicy < ApplicationPolicy end def reblog? - !direct? && (!private? || owned?) && show? && !blocking_author? + !requires_mention? && (!private? || owned?) && show? && !blocking_author? end def favourite? @@ -41,8 +41,8 @@ class StatusPolicy < ApplicationPolicy private - def direct? - record.direct_visibility? + def requires_mention? + record.direct_visibility? || record.limited_visibility? end def owned? diff --git a/app/serializers/activitypub/note_serializer.rb b/app/serializers/activitypub/note_serializer.rb index 82b7ffe95c..c9d23e25fa 100644 --- a/app/serializers/activitypub/note_serializer.rb +++ b/app/serializers/activitypub/note_serializer.rb @@ -68,7 +68,7 @@ class ActivityPub::NoteSerializer < ActiveModel::Serializer end def virtual_tags - object.mentions.to_a.sort_by(&:id) + object.tags + object.emojis + object.active_mentions.to_a.sort_by(&:id) + object.tags + object.emojis end def atom_uri diff --git a/app/serializers/rest/status_serializer.rb b/app/serializers/rest/status_serializer.rb index 61423f9615..1f2f46b7e6 100644 --- a/app/serializers/rest/status_serializer.rb +++ b/app/serializers/rest/status_serializer.rb @@ -36,6 +36,17 @@ class REST::StatusSerializer < ActiveModel::Serializer !current_user.nil? end + def visibility + # This visibility is masked behind "private" + # to avoid API changes because there are no + # UX differences + if object.limited_visibility? + 'private' + else + object.visibility + end + end + def uri OStatus::TagManager.instance.uri_for(object) end @@ -88,7 +99,7 @@ class REST::StatusSerializer < ActiveModel::Serializer end def ordered_mentions - object.mentions.to_a.sort_by(&:id) + object.active_mentions.to_a.sort_by(&:id) end class ApplicationSerializer < ActiveModel::Serializer diff --git a/app/services/batched_remove_status_service.rb b/app/services/batched_remove_status_service.rb index 2fcb3cc66b..b8ab58938d 100644 --- a/app/services/batched_remove_status_service.rb +++ b/app/services/batched_remove_status_service.rb @@ -12,7 +12,7 @@ class BatchedRemoveStatusService < BaseService def call(statuses) statuses = Status.where(id: statuses.map(&:id)).includes(:account, :stream_entry).flat_map { |status| [status] + status.reblogs.includes(:account, :stream_entry).to_a } - @mentions = statuses.map { |s| [s.id, s.mentions.includes(:account).to_a] }.to_h + @mentions = statuses.map { |s| [s.id, s.active_mentions.includes(:account).to_a] }.to_h @tags = statuses.map { |s| [s.id, s.tags.pluck(:name)] }.to_h @stream_entry_batches = [] diff --git a/app/services/fan_out_on_write_service.rb b/app/services/fan_out_on_write_service.rb index 5ddddf3a90..7f2a917754 100644 --- a/app/services/fan_out_on_write_service.rb +++ b/app/services/fan_out_on_write_service.rb @@ -10,6 +10,8 @@ class FanOutOnWriteService < BaseService if status.direct_visibility? deliver_to_own_conversation(status) + elsif status.limited_visibility? + deliver_to_mentioned_followers(status) else deliver_to_self(status) if status.account.local? deliver_to_followers(status) @@ -53,6 +55,16 @@ class FanOutOnWriteService < BaseService end end + def deliver_to_mentioned_followers(status) + Rails.logger.debug "Delivering status #{status.id} to limited followers" + + status.mentions.includes(:account).each do |mention| + mentioned_account = mention.account + next if !mentioned_account.local? || !mentioned_account.following?(status.account) || FeedManager.instance.filter?(:home, status, mention.account_id) + FeedManager.instance.push_to_home(mentioned_account, status) + end + end + def render_anonymous_payload(status) @payload = InlineRenderer.render(status, nil, :status) @payload = Oj.dump(event: :update, payload: @payload) diff --git a/app/services/remove_status_service.rb b/app/services/remove_status_service.rb index 1ee645e6d8..11d28e783d 100644 --- a/app/services/remove_status_service.rb +++ b/app/services/remove_status_service.rb @@ -8,7 +8,7 @@ class RemoveStatusService < BaseService @status = status @account = status.account @tags = status.tags.pluck(:name).to_a - @mentions = status.mentions.includes(:account).to_a + @mentions = status.active_mentions.includes(:account).to_a @reblogs = status.reblogs.to_a @stream_entry = status.stream_entry @options = options diff --git a/app/views/stream_entries/_detailed_status.html.haml b/app/views/stream_entries/_detailed_status.html.haml index 0b204d4374..6e6d0eda85 100644 --- a/app/views/stream_entries/_detailed_status.html.haml +++ b/app/views/stream_entries/_detailed_status.html.haml @@ -51,7 +51,7 @@ - if status.direct_visibility? %span.detailed-status__link< = fa_icon('envelope') - - elsif status.private_visibility? + - elsif status.private_visibility? || status.limited_visibility? %span.detailed-status__link< = fa_icon('lock') - else diff --git a/app/workers/activitypub/distribution_worker.rb b/app/workers/activitypub/distribution_worker.rb index c2bfd4f2f1..17c1ef7fff 100644 --- a/app/workers/activitypub/distribution_worker.rb +++ b/app/workers/activitypub/distribution_worker.rb @@ -23,7 +23,7 @@ class ActivityPub::DistributionWorker private def skip_distribution? - @status.direct_visibility? + @status.direct_visibility? || @status.limited_visibility? end def relayable? diff --git a/app/workers/activitypub/reply_distribution_worker.rb b/app/workers/activitypub/reply_distribution_worker.rb index fe99fc05f2..c0ed3a1f40 100644 --- a/app/workers/activitypub/reply_distribution_worker.rb +++ b/app/workers/activitypub/reply_distribution_worker.rb @@ -9,7 +9,7 @@ class ActivityPub::ReplyDistributionWorker @status = Status.find(status_id) @account = @status.thread&.account - return if @account.nil? || skip_distribution? + return unless @account.present? && @status.distributable? ActivityPub::DeliveryWorker.push_bulk(inboxes) do |inbox_url| [signed_payload, @status.account_id, inbox_url] @@ -20,10 +20,6 @@ class ActivityPub::ReplyDistributionWorker private - def skip_distribution? - @status.private_visibility? || @status.direct_visibility? - end - def inboxes @inboxes ||= @account.followers.inboxes end diff --git a/db/migrate/20181010141500_add_silent_to_mentions.rb b/db/migrate/20181010141500_add_silent_to_mentions.rb new file mode 100644 index 0000000000..dbb4fba263 --- /dev/null +++ b/db/migrate/20181010141500_add_silent_to_mentions.rb @@ -0,0 +1,23 @@ +require Rails.root.join('lib', 'mastodon', 'migration_helpers') + +class AddSilentToMentions < ActiveRecord::Migration[5.2] + include Mastodon::MigrationHelpers + + disable_ddl_transaction! + + def up + safety_assured do + add_column_with_default( + :mentions, + :silent, + :boolean, + allow_null: false, + default: false + ) + end + end + + def down + remove_column :mentions, :silent + end +end diff --git a/db/schema.rb b/db/schema.rb index bf6ab4e68c..f79f26f16e 100644 --- a/db/schema.rb +++ b/db/schema.rb @@ -10,7 +10,7 @@ # # It's strongly recommended that you check this file into your version control system. -ActiveRecord::Schema.define(version: 2018_10_07_025445) do +ActiveRecord::Schema.define(version: 2018_10_10_141500) do # These are extensions that must be enabled in order to support this database enable_extension "plpgsql" @@ -301,6 +301,7 @@ ActiveRecord::Schema.define(version: 2018_10_07_025445) do t.datetime "created_at", null: false t.datetime "updated_at", null: false t.bigint "account_id" + t.boolean "silent", default: false, null: false t.index ["account_id", "status_id"], name: "index_mentions_on_account_id_and_status_id", unique: true t.index ["status_id"], name: "index_mentions_on_status_id" end diff --git a/spec/lib/activitypub/activity/create_spec.rb b/spec/lib/activitypub/activity/create_spec.rb index 62b9db8c24..cd20b7c7cb 100644 --- a/spec/lib/activitypub/activity/create_spec.rb +++ b/spec/lib/activitypub/activity/create_spec.rb @@ -105,6 +105,31 @@ RSpec.describe ActivityPub::Activity::Create do end end + context 'limited' do + let(:recipient) { Fabricate(:account) } + + let(:object_json) do + { + id: [ActivityPub::TagManager.instance.uri_for(sender), '#bar'].join, + type: 'Note', + content: 'Lorem ipsum', + to: ActivityPub::TagManager.instance.uri_for(recipient), + } + end + + it 'creates status' do + status = sender.statuses.first + + expect(status).to_not be_nil + expect(status.visibility).to eq 'limited' + end + + it 'creates silent mention' do + status = sender.statuses.first + expect(status.mentions.first).to be_silent + end + end + context 'direct' do let(:recipient) { Fabricate(:account) } @@ -114,6 +139,10 @@ RSpec.describe ActivityPub::Activity::Create do type: 'Note', content: 'Lorem ipsum', to: ActivityPub::TagManager.instance.uri_for(recipient), + tag: { + type: 'Mention', + href: ActivityPub::TagManager.instance.uri_for(recipient), + }, } end From 72d7d3003b1e21ef8a6f5112f1e8cb32c72e8992 Mon Sep 17 00:00:00 2001 From: Eugen Rochko Date: Wed, 17 Oct 2018 22:04:40 +0200 Subject: [PATCH 34/87] Do not show "limited" visibility in default visibility preference (#8999) * Do not show "limited" visibility in default visibility preference Fix regression from #8950 * Fix code style issue --- app/models/status.rb | 4 ++++ app/views/settings/preferences/show.html.haml | 2 +- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/app/models/status.rb b/app/models/status.rb index b18cb56b21..bcb7dd373f 100644 --- a/app/models/status.rb +++ b/app/models/status.rb @@ -238,6 +238,10 @@ class Status < ApplicationRecord left_outer_joins(:status_stat).select('statuses.id, greatest(statuses.updated_at, status_stats.updated_at) AS updated_at') end + def selectable_visibilities + visibilities.keys - %w(direct limited) + end + def in_chosen_languages(account) where(language: nil).or where(language: account.chosen_languages) end diff --git a/app/views/settings/preferences/show.html.haml b/app/views/settings/preferences/show.html.haml index d889702fec..ecb789f93c 100644 --- a/app/views/settings/preferences/show.html.haml +++ b/app/views/settings/preferences/show.html.haml @@ -22,7 +22,7 @@ %hr#settings_publishing/ .fields-group - = f.input :setting_default_privacy, collection: Status.visibilities.keys - ['direct'], wrapper: :with_floating_label, include_blank: false, label_method: lambda { |visibility| safe_join([I18n.t("statuses.visibilities.#{visibility}"), content_tag(:span, I18n.t("statuses.visibilities.#{visibility}_long"), class: 'hint')]) }, required: false, as: :radio_buttons, collection_wrapper_tag: 'ul', item_wrapper_tag: 'li' + = f.input :setting_default_privacy, collection: Status.selectable_visibilities, wrapper: :with_floating_label, include_blank: false, label_method: lambda { |visibility| safe_join([I18n.t("statuses.visibilities.#{visibility}"), content_tag(:span, I18n.t("statuses.visibilities.#{visibility}_long"), class: 'hint')]) }, required: false, as: :radio_buttons, collection_wrapper_tag: 'ul', item_wrapper_tag: 'li' = f.input :setting_default_sensitive, as: :boolean, wrapper: :with_label From f8c1b325410369806eb77a5c8d259971a87a6852 Mon Sep 17 00:00:00 2001 From: Masoud Abkenar Date: Thu, 18 Oct 2018 14:35:49 +0200 Subject: [PATCH 35/87] RTL: fix admin account margins in about page (#9005) --- app/javascript/styles/mastodon/rtl.scss | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/app/javascript/styles/mastodon/rtl.scss b/app/javascript/styles/mastodon/rtl.scss index 9644f8e029..61a20013e9 100644 --- a/app/javascript/styles/mastodon/rtl.scss +++ b/app/javascript/styles/mastodon/rtl.scss @@ -309,3 +309,15 @@ body.rtl { } } } + +.landing-page__information { + .account__display-name { + margin-right: 0; + margin-left: 5px; + } + + .account__avatar-wrapper { + margin-left: 12px; + margin-right: 0; + } +} From 007f7690fad96e9923bf0a73d85ab102ebc0addb Mon Sep 17 00:00:00 2001 From: ThibG Date: Thu, 18 Oct 2018 19:52:00 +0200 Subject: [PATCH 36/87] Fix fav/boosts hotkeys not working on detailed statuses (#9006) --- app/javascript/mastodon/features/status/index.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/javascript/mastodon/features/status/index.js b/app/javascript/mastodon/features/status/index.js index 2cd17b8051..b36d828650 100644 --- a/app/javascript/mastodon/features/status/index.js +++ b/app/javascript/mastodon/features/status/index.js @@ -181,7 +181,7 @@ class Status extends ImmutablePureComponent { if (status.get('reblogged')) { this.props.dispatch(unreblog(status)); } else { - if (e.shiftKey || !boostModal) { + if ((e && e.shiftKey) || !boostModal) { this.handleModalReblog(status); } else { this.props.dispatch(openModal('BOOST', { status, onReblog: this.handleModalReblog })); From 65b3804a6ccd40d359616b6157682ff88f85462f Mon Sep 17 00:00:00 2001 From: Masoud Abkenar Date: Thu, 18 Oct 2018 21:19:31 +0200 Subject: [PATCH 37/87] RTL: fix domain append at signup form (#9007) --- app/javascript/styles/mastodon/rtl.scss | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/javascript/styles/mastodon/rtl.scss b/app/javascript/styles/mastodon/rtl.scss index 61a20013e9..49d9765a81 100644 --- a/app/javascript/styles/mastodon/rtl.scss +++ b/app/javascript/styles/mastodon/rtl.scss @@ -219,7 +219,7 @@ body.rtl { padding-right: 0; } - .simple_form .input-with-append .append { + .simple_form .label_input__append { right: auto; left: 0; From e5762875a47c63243717187fb79148ccc6bd94c7 Mon Sep 17 00:00:00 2001 From: Daigo 3 Dango Date: Thu, 18 Oct 2018 10:32:47 -1000 Subject: [PATCH 38/87] Use Ruby ==2.5.2== 2.5.3 (#9003) * Use Ruby 2.5.2 * Specify 2.5.2p104 as RUBY VERSION Heorku refers to RUBY VERSION in Gemfile.lock * Use ruby-2.5.3 --- .ruby-version | 2 +- Gemfile.lock | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.ruby-version b/.ruby-version index 73462a5a13..aedc15bb0c 100644 --- a/.ruby-version +++ b/.ruby-version @@ -1 +1 @@ -2.5.1 +2.5.3 diff --git a/Gemfile.lock b/Gemfile.lock index ce88fe6e22..4b47b25ed3 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -763,7 +763,7 @@ DEPENDENCIES webpush RUBY VERSION - ruby 2.5.0p0 + ruby 2.5.3p105 BUNDLED WITH 1.16.5 From bebe8ec887ba67c51353e09d7758819b117bf62d Mon Sep 17 00:00:00 2001 From: takayamaki Date: Fri, 19 Oct 2018 07:00:19 +0900 Subject: [PATCH 39/87] fix: initial state of PrivacyDropdown is should not be null (#9008) --- .../mastodon/features/compose/components/privacy_dropdown.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/javascript/mastodon/features/compose/components/privacy_dropdown.js b/app/javascript/mastodon/features/compose/components/privacy_dropdown.js index 7b5482f05b..5698765d94 100644 --- a/app/javascript/mastodon/features/compose/components/privacy_dropdown.js +++ b/app/javascript/mastodon/features/compose/components/privacy_dropdown.js @@ -164,7 +164,7 @@ class PrivacyDropdown extends React.PureComponent { state = { open: false, - placement: null, + placement: 'bottom', }; handleToggle = ({ target }) => { From a38a452481d0f5207bb27ba7a2707c0028d2ac18 Mon Sep 17 00:00:00 2001 From: Eugen Rochko Date: Fri, 19 Oct 2018 01:47:29 +0200 Subject: [PATCH 40/87] Add unread indicator to conversations (#9009) --- .../api/v1/conversations_controller.rb | 20 ++++++++++++++-- app/controllers/api/v1/reports_controller.rb | 1 - .../mastodon/actions/conversations.js | 11 +++++++++ .../components/conversation.js | 14 ++++++++--- .../containers/conversation_container.js | 8 ++++++- .../mastodon/reducers/conversations.js | 10 ++++++++ .../styles/mastodon/components.scss | 5 ++++ app/models/account_conversation.rb | 2 ++ .../rest/conversation_serializer.rb | 3 ++- config/initializers/doorkeeper.rb | 2 +- config/routes.rb | 7 +++++- ...649_add_unread_to_account_conversations.rb | 23 +++++++++++++++++++ db/schema.rb | 3 ++- 13 files changed, 98 insertions(+), 11 deletions(-) create mode 100644 db/migrate/20181018205649_add_unread_to_account_conversations.rb diff --git a/app/controllers/api/v1/conversations_controller.rb b/app/controllers/api/v1/conversations_controller.rb index 736cb21cac..b19f27ebfb 100644 --- a/app/controllers/api/v1/conversations_controller.rb +++ b/app/controllers/api/v1/conversations_controller.rb @@ -3,9 +3,11 @@ class Api::V1::ConversationsController < Api::BaseController LIMIT = 20 - before_action -> { doorkeeper_authorize! :read, :'read:statuses' } + before_action -> { doorkeeper_authorize! :read, :'read:statuses' }, only: :index + before_action -> { doorkeeper_authorize! :write, :'write:conversations' }, except: :index before_action :require_user! - after_action :insert_pagination_headers + before_action :set_conversation, except: :index + after_action :insert_pagination_headers, only: :index respond_to :json @@ -14,8 +16,22 @@ class Api::V1::ConversationsController < Api::BaseController render json: @conversations, each_serializer: REST::ConversationSerializer end + def read + @conversation.update!(unread: false) + render json: @conversation, serializer: REST::ConversationSerializer + end + + def destroy + @conversation.destroy! + render_empty + end + private + def set_conversation + @conversation = AccountConversation.where(account: current_account).find(params[:id]) + end + def paginated_conversations AccountConversation.where(account: current_account) .paginate_by_id(limit_param(LIMIT), params_slice(:max_id, :since_id, :min_id)) diff --git a/app/controllers/api/v1/reports_controller.rb b/app/controllers/api/v1/reports_controller.rb index 726817927e..e182a9c6cf 100644 --- a/app/controllers/api/v1/reports_controller.rb +++ b/app/controllers/api/v1/reports_controller.rb @@ -1,7 +1,6 @@ # frozen_string_literal: true class Api::V1::ReportsController < Api::BaseController - before_action -> { doorkeeper_authorize! :read, :'read:reports' }, except: [:create] before_action -> { doorkeeper_authorize! :write, :'write:reports' }, only: [:create] before_action :require_user! diff --git a/app/javascript/mastodon/actions/conversations.js b/app/javascript/mastodon/actions/conversations.js index cab05c1bab..aefd2fef76 100644 --- a/app/javascript/mastodon/actions/conversations.js +++ b/app/javascript/mastodon/actions/conversations.js @@ -13,6 +13,8 @@ export const CONVERSATIONS_FETCH_SUCCESS = 'CONVERSATIONS_FETCH_SUCCESS'; export const CONVERSATIONS_FETCH_FAIL = 'CONVERSATIONS_FETCH_FAIL'; export const CONVERSATIONS_UPDATE = 'CONVERSATIONS_UPDATE'; +export const CONVERSATIONS_READ = 'CONVERSATIONS_READ'; + export const mountConversations = () => ({ type: CONVERSATIONS_MOUNT, }); @@ -21,6 +23,15 @@ export const unmountConversations = () => ({ type: CONVERSATIONS_UNMOUNT, }); +export const markConversationRead = conversationId => (dispatch, getState) => { + dispatch({ + type: CONVERSATIONS_READ, + id: conversationId, + }); + + api(getState).post(`/api/v1/conversations/${conversationId}/read`); +}; + export const expandConversations = ({ maxId } = {}) => (dispatch, getState) => { dispatch(expandConversationsRequest()); diff --git a/app/javascript/mastodon/features/direct_timeline/components/conversation.js b/app/javascript/mastodon/features/direct_timeline/components/conversation.js index f9a8d4f72a..52e33c3c85 100644 --- a/app/javascript/mastodon/features/direct_timeline/components/conversation.js +++ b/app/javascript/mastodon/features/direct_timeline/components/conversation.js @@ -8,6 +8,7 @@ import DisplayName from '../../../components/display_name'; import Avatar from '../../../components/avatar'; import AttachmentList from '../../../components/attachment_list'; import { HotKeys } from 'react-hotkeys'; +import classNames from 'classnames'; export default class Conversation extends ImmutablePureComponent { @@ -19,8 +20,10 @@ export default class Conversation extends ImmutablePureComponent { conversationId: PropTypes.string.isRequired, accounts: ImmutablePropTypes.list.isRequired, lastStatus: ImmutablePropTypes.map.isRequired, + unread:PropTypes.bool.isRequired, onMoveUp: PropTypes.func, onMoveDown: PropTypes.func, + markRead: PropTypes.func.isRequired, }; handleClick = () => { @@ -28,7 +31,12 @@ export default class Conversation extends ImmutablePureComponent { return; } - const { lastStatus } = this.props; + const { lastStatus, unread, markRead } = this.props; + + if (unread) { + markRead(); + } + this.context.router.history.push(`/statuses/${lastStatus.get('id')}`); } @@ -41,7 +49,7 @@ export default class Conversation extends ImmutablePureComponent { } render () { - const { accounts, lastStatus, lastAccount } = this.props; + const { accounts, lastStatus, lastAccount, unread } = this.props; if (lastStatus === null) { return null; @@ -61,7 +69,7 @@ export default class Conversation extends ImmutablePureComponent { return ( -
+
{accounts.map(account => )}
diff --git a/app/javascript/mastodon/features/direct_timeline/containers/conversation_container.js b/app/javascript/mastodon/features/direct_timeline/containers/conversation_container.js index 4166ee2acb..e2e2e3afb5 100644 --- a/app/javascript/mastodon/features/direct_timeline/containers/conversation_container.js +++ b/app/javascript/mastodon/features/direct_timeline/containers/conversation_container.js @@ -1,5 +1,6 @@ import { connect } from 'react-redux'; import Conversation from '../components/conversation'; +import { markConversationRead } from '../../../actions/conversations'; const mapStateToProps = (state, { conversationId }) => { const conversation = state.getIn(['conversations', 'items']).find(x => x.get('id') === conversationId); @@ -7,9 +8,14 @@ const mapStateToProps = (state, { conversationId }) => { return { accounts: conversation.get('accounts').map(accountId => state.getIn(['accounts', accountId], null)), + unread: conversation.get('unread'), lastStatus, lastAccount: lastStatus === null ? null : state.getIn(['accounts', lastStatus.get('account')], null), }; }; -export default connect(mapStateToProps)(Conversation); +const mapDispatchToProps = (dispatch, { conversationId }) => ({ + markRead: () => dispatch(markConversationRead(conversationId)), +}); + +export default connect(mapStateToProps, mapDispatchToProps)(Conversation); diff --git a/app/javascript/mastodon/reducers/conversations.js b/app/javascript/mastodon/reducers/conversations.js index 6b3f22d25b..ea39fcceeb 100644 --- a/app/javascript/mastodon/reducers/conversations.js +++ b/app/javascript/mastodon/reducers/conversations.js @@ -6,6 +6,7 @@ import { CONVERSATIONS_FETCH_SUCCESS, CONVERSATIONS_FETCH_FAIL, CONVERSATIONS_UPDATE, + CONVERSATIONS_READ, } from '../actions/conversations'; import compareId from '../compare_id'; @@ -18,6 +19,7 @@ const initialState = ImmutableMap({ const conversationToMap = item => ImmutableMap({ id: item.id, + unread: item.unread, accounts: ImmutableList(item.accounts.map(a => a.id)), last_status: item.last_status.id, }); @@ -80,6 +82,14 @@ export default function conversations(state = initialState, action) { return state.update('mounted', count => count + 1); case CONVERSATIONS_UNMOUNT: return state.update('mounted', count => count - 1); + case CONVERSATIONS_READ: + return state.update('items', list => list.map(item => { + if (item.get('id') === action.id) { + return item.set('unread', false); + } + + return item; + })); default: return state; } diff --git a/app/javascript/styles/mastodon/components.scss b/app/javascript/styles/mastodon/components.scss index 129bde8568..24b614a37f 100644 --- a/app/javascript/styles/mastodon/components.scss +++ b/app/javascript/styles/mastodon/components.scss @@ -5503,6 +5503,11 @@ noscript { border-bottom: 1px solid lighten($ui-base-color, 8%); cursor: pointer; + &--unread { + background: lighten($ui-base-color, 8%); + border-bottom-color: lighten($ui-base-color, 12%); + } + &__header { display: flex; margin-bottom: 15px; diff --git a/app/models/account_conversation.rb b/app/models/account_conversation.rb index c12c8d233f..b7447d8058 100644 --- a/app/models/account_conversation.rb +++ b/app/models/account_conversation.rb @@ -10,6 +10,7 @@ # status_ids :bigint(8) default([]), not null, is an Array # last_status_id :bigint(8) # lock_version :integer default(0), not null +# unread :boolean default(FALSE), not null # class AccountConversation < ApplicationRecord @@ -58,6 +59,7 @@ class AccountConversation < ApplicationRecord def add_status(recipient, status) conversation = find_or_initialize_by(account: recipient, conversation_id: status.conversation_id, participant_account_ids: participants_from_status(recipient, status)) conversation.status_ids << status.id + conversation.unread = status.account_id != recipient.id conversation.save conversation rescue ActiveRecord::StaleObjectError diff --git a/app/serializers/rest/conversation_serializer.rb b/app/serializers/rest/conversation_serializer.rb index 884253f893..b09ca63419 100644 --- a/app/serializers/rest/conversation_serializer.rb +++ b/app/serializers/rest/conversation_serializer.rb @@ -1,7 +1,8 @@ # frozen_string_literal: true class REST::ConversationSerializer < ActiveModel::Serializer - attribute :id + attributes :id, :unread + has_many :participant_accounts, key: :accounts, serializer: REST::AccountSerializer has_one :last_status, serializer: REST::StatusSerializer diff --git a/config/initializers/doorkeeper.rb b/config/initializers/doorkeeper.rb index fe2490b326..367eead6a4 100644 --- a/config/initializers/doorkeeper.rb +++ b/config/initializers/doorkeeper.rb @@ -58,6 +58,7 @@ Doorkeeper.configure do optional_scopes :write, :'write:accounts', :'write:blocks', + :'write:conversations', :'write:favourites', :'write:filters', :'write:follows', @@ -76,7 +77,6 @@ Doorkeeper.configure do :'read:lists', :'read:mutes', :'read:notifications', - :'read:reports', :'read:search', :'read:statuses', :follow, diff --git a/config/routes.rb b/config/routes.rb index a2468c9bdb..b203e13294 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -261,7 +261,12 @@ Rails.application.routes.draw do resources :streaming, only: [:index] resources :custom_emojis, only: [:index] resources :suggestions, only: [:index, :destroy] - resources :conversations, only: [:index] + + resources :conversations, only: [:index, :destroy] do + member do + post :read + end + end get '/search', to: 'search#index', as: :search diff --git a/db/migrate/20181018205649_add_unread_to_account_conversations.rb b/db/migrate/20181018205649_add_unread_to_account_conversations.rb new file mode 100644 index 0000000000..3c28b9a641 --- /dev/null +++ b/db/migrate/20181018205649_add_unread_to_account_conversations.rb @@ -0,0 +1,23 @@ +require Rails.root.join('lib', 'mastodon', 'migration_helpers') + +class AddUnreadToAccountConversations < ActiveRecord::Migration[5.2] + include Mastodon::MigrationHelpers + + disable_ddl_transaction! + + def up + safety_assured do + add_column_with_default( + :account_conversations, + :unread, + :boolean, + allow_null: false, + default: false + ) + end + end + + def down + remove_column :account_conversations, :unread, :boolean + end +end diff --git a/db/schema.rb b/db/schema.rb index f79f26f16e..046975ac99 100644 --- a/db/schema.rb +++ b/db/schema.rb @@ -10,7 +10,7 @@ # # It's strongly recommended that you check this file into your version control system. -ActiveRecord::Schema.define(version: 2018_10_10_141500) do +ActiveRecord::Schema.define(version: 2018_10_18_205649) do # These are extensions that must be enabled in order to support this database enable_extension "plpgsql" @@ -22,6 +22,7 @@ ActiveRecord::Schema.define(version: 2018_10_10_141500) do t.bigint "status_ids", default: [], null: false, array: true t.bigint "last_status_id" t.integer "lock_version", default: 0, null: false + t.boolean "unread", default: false, null: false t.index ["account_id", "conversation_id", "participant_account_ids"], name: "index_unique_conversations", unique: true t.index ["account_id"], name: "index_account_conversations_on_account_id" t.index ["conversation_id"], name: "index_account_conversations_on_conversation_id" From 301cbcc9802ed85c519e67a01133968bc074c8af Mon Sep 17 00:00:00 2001 From: Masoud Abkenar Date: Fri, 19 Oct 2018 13:16:13 +0200 Subject: [PATCH 41/87] RTL: fix user stats in about page (#9018) --- app/javascript/styles/mastodon/rtl.scss | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/app/javascript/styles/mastodon/rtl.scss b/app/javascript/styles/mastodon/rtl.scss index 49d9765a81..2bfd0de3af 100644 --- a/app/javascript/styles/mastodon/rtl.scss +++ b/app/javascript/styles/mastodon/rtl.scss @@ -245,6 +245,10 @@ body.rtl { left: auto; } + .landing-page__call-to-action .row__information-board { + direction: rtl; + } + .landing-page .header .hero .floats .float-1 { left: -120px; right: auto; From c7b9e6f47952263d2e0b4dff42a18ebdd3fc0010 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" Date: Fri, 19 Oct 2018 20:20:07 +0900 Subject: [PATCH 42/87] Bump tzinfo-data from 1.2018.5 to 1.2018.6 (#9016) Bumps [tzinfo-data](https://github.com/tzinfo/tzinfo-data) from 1.2018.5 to 1.2018.6. - [Release notes](https://github.com/tzinfo/tzinfo-data/releases) - [Commits](https://github.com/tzinfo/tzinfo-data/compare/v1.2018.5...v1.2018.6) Signed-off-by: dependabot[bot] --- Gemfile.lock | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Gemfile.lock b/Gemfile.lock index 4b47b25ed3..b64c054159 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -616,7 +616,7 @@ GEM unf (~> 0.1.0) tzinfo (1.2.5) thread_safe (~> 0.1) - tzinfo-data (1.2018.5) + tzinfo-data (1.2018.6) tzinfo (>= 1.0.0) unf (0.1.4) unf_ext From 890968603b7b631ba4bfb4d5d85fff5ccbef07c2 Mon Sep 17 00:00:00 2001 From: Eugen Rochko Date: Fri, 19 Oct 2018 16:41:25 +0200 Subject: [PATCH 43/87] Update CONTRIBUTING.md (#9014) * Update CONTRIBUTING.md * Update CONTRIBUTING.md * Update CONTRIBUTING.md * Update CONTRIBUTING.md --- CONTRIBUTING.md | 73 ++++++++++++++++++------------------------------- 1 file changed, 27 insertions(+), 46 deletions(-) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index d0f75f2e45..b55729a9ba 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -1,56 +1,37 @@ -CONTRIBUTING +Contributing ============ -There are three ways in which you can contribute to this repository: +Thank you for considering contributing to Mastodon 🐘 -1. By improving the documentation -2. By working on the back-end application -3. By working on the front-end application +You can contribute in the following ways: -Choosing what to work on in a large open source project is not easy. The list of [GitHub issues](https://github.com/tootsuite/mastodon/issues) may provide some ideas, but not every feature request has been greenlit. Likewise, not every change or feature that resolves a personal itch will be merged into the main repository. Some communication ahead of time may be wise. If your addition creates a new feature or setting, or otherwise changes how things work in some substantial way, please remember to submit a correlating pull request to document your changes in the [documentation](http://github.com/tootsuite/documentation). +- Finding and reporting bugs +- Translating the Mastodon interface into various languages +- Contributing code to Mastodon by fixing bugs or implementing features +- Improving the documentation -Below are the guidelines for working on pull requests: +## Bug reports -## General +Bug reports and feature suggestions can be submitted to [GitHub Issues](https://github.com/tootsuite/mastodon/issues). Please make sure that you are not submitting duplicates, and that a similar report or request has not already been resolved or rejected in the past using the search function. Please also use descriptive, concise titles. -- 2 spaces indentation +## Translations + +You can submit translations via [Weblate](https://weblate.joinmastodon.org/). They are periodically merged into the codebase. + +[![Mastodon translation statistics by language](https://weblate.joinmastodon.org/widgets/mastodon/-/multi-auto.svg)](https://weblate.joinmastodon.org/) + +## Pull requests + +Please use clean, concise titles for your pull requests. We use commit squashing, so the final commit in the master branch will carry the title of the pull request. + +The smaller the set of changes in the pull request is, the quicker it can be reviewed and merged. Splitting tasks into multiple smaller pull requests is often preferable. + +**Pull requests that do not pass automated checks may not be reviewed**. In particular, you need to keep in mind: + +- Unit and integration tests (rspec, jest) +- Code style rules (rubocop, eslint) +- Normalization of locale files (i18n-tasks) ## Documentation -- No spelling mistakes -- No orthographic mistakes -- No Markdown syntax errors - -## Requirements - -- Ruby -- Node.js -- PostgreSQL -- Redis -- Nginx (optional) - -## Back-end application - -It is expected that you have a working development environment set up. The development environment includes [rubocop](https://github.com/bbatsov/rubocop), which checks your Ruby code for compliance with our style guide and best practices. Sublime Text, likely like other editors, has a [Rubocop plugin](https://github.com/pderichs/sublime_rubocop) that runs checks on files as you edit them. The codebase also has a test suite. - -* The codebase is not perfect, at the time of writing, but it is expected that you do not introduce new code style violations -* The rspec test suite must pass -* To the extent that it is possible, verify your changes. In the best case, by adding new tests to the test suite. At the very least, by running the server or console and checking it manually -* If you are introducing new strings to the user interface, they must be using localization methods - -If your code has syntax errors that won't let it run, it's a good sign that the pull request isn't ready for submission yet. - -## Front-end application - -It is expected that you have a working development environment set up (see back-end application section). This project includes an ESLint configuration file, with which you can lint your changes. - -* Avoid grave ESLint violations -* Verify that your changes work -* If you are introducing new strings, they must be using localization methods - -If the JavaScript or CSS assets won't compile due to a syntax error, it's a good sign that the pull request isn't ready for submission yet. - -## Translate - -You can contribute to translating Mastodon via Weblate at [weblate.joinmastodon.org](https://weblate.joinmastodon.org/). -[![Mastodon translation statistics by language](https://weblate.joinmastodon.org/widgets/mastodon/-/multi-auto.svg)](https://weblate.joinmastodon.org/) +The [Mastodon documentation](https://docs.joinmastodon.org) is a statically generated site. You can [submit merge requests to mastodon/docs](https://source.joinmastodon.org/mastodon/docs). From 3abab56650d388638af59c09a18683f796f9e992 Mon Sep 17 00:00:00 2001 From: Eugen Rochko Date: Fri, 19 Oct 2018 18:49:35 +0200 Subject: [PATCH 44/87] Improve README (#9012) * Improve README * Update README.md * Update README.md * Update README.md * Update README.md --- README.md | 91 +++++++++++++++++++++++++++---------------------------- 1 file changed, 44 insertions(+), 47 deletions(-) diff --git a/README.md b/README.md index c6496ec5fd..6c4918e6f2 100644 --- a/README.md +++ b/README.md @@ -1,98 +1,95 @@ ![Mastodon](https://i.imgur.com/NhZc40l.png) ======== +[![GitHub release](https://img.shields.io/github/release/tootsuite/mastodon.svg)][releases] [![Build Status](https://img.shields.io/circleci/project/github/tootsuite/mastodon.svg)][circleci] [![Code Climate](https://img.shields.io/codeclimate/maintainability/tootsuite/mastodon.svg)][code_climate] [![Translation status](https://weblate.joinmastodon.org/widgets/mastodon/-/svg-badge.svg)][weblate] +[![Docker Pulls](https://img.shields.io/docker/pulls/tootsuite/mastodon.svg)][docker] +[releases]: https://github.com/tootsuite/mastodon/releases [circleci]: https://circleci.com/gh/tootsuite/mastodon [code_climate]: https://codeclimate.com/github/tootsuite/mastodon [weblate]: https://weblate.joinmastodon.org/engage/mastodon/ +[docker]: https://hub.docker.com/r/tootsuite/mastodon/ -Mastodon is a **free, open-source social network server** based on **open web protocols** like ActivityPub and OStatus. The social focus of the project is a viable decentralized alternative to commercial social media silos that returns the control of the content distribution channels to the people. The technical focus of the project is a good user interface, a clean REST API for 3rd party apps and robust anti-abuse tools. +Mastodon is a **free, open-source social network server** based on ActivityPub. Follow friends and discover new ones. Publish anything you want: links, pictures, text, video. All servers of Mastodon are interoperable as a federated network, i.e. users on one server can seamlessly communicate with users from another one. This includes non-Mastodon software that also implements ActivityPub! -Click on the screenshot below to watch a demo of the UI: +Click below to **learn more** in a video: -[![Screenshot](https://i.imgur.com/qrNOiSp.png)][youtube_demo] +[![Screenshot](https://blog.joinmastodon.org/2018/06/why-activitypub-is-the-future/ezgif-2-60f1b00403.gif)][youtube_demo] [youtube_demo]: https://www.youtube.com/watch?v=IPSbNdBmWKE -**Ruby on Rails** is used for the back-end, while **React.js** and Redux are used for the dynamic front-end. A static front-end for public resources (profiles and statuses) is also provided. +## Navigation -If you would like, you can [support the development of this project on Patreon][patreon]. +- [Project homepage 🐘](https://joinmastodon.org) +- [Support the development via Patreon][patreon] +- [View sponsors](https://joinmastodon.org/sponsors) +- [Blog](https://blog.joinmastodon.org) +- [Documentation](https://docs.joinmastodon.org) +- [Browse Mastodon servers](https://joinmastodon.org/#getting-started) +- [Browse Mastodon apps](https://joinmastodon.org/apps) [patreon]: https://www.patreon.com/mastodon ---- - -## Resources - -- [Quick start guide](https://blog.joinmastodon.org/2018/08/mastodon-quick-start-guide/) -- [Find Twitter friends on Mastodon](https://bridge.joinmastodon.org) -- [API overview](https://github.com/tootsuite/documentation/blob/master/Using-the-API/API.md) -- [Documentation](https://github.com/tootsuite/documentation) -- [List of servers](https://joinmastodon.org/#getting-started) -- [List of apps](https://joinmastodon.org/apps) -- [List of sponsors](https://joinmastodon.org/sponsors) - ## Features + + **No vendor lock-in: Fully interoperable with any conforming platform** -It doesn't have to be Mastodon, whatever implements ActivityPub or OStatus is part of the social network! +It doesn't have to be Mastodon, whatever implements ActivityPub is part of the social network! [Learn more](https://blog.joinmastodon.org/2018/06/why-activitypub-is-the-future/) -**Real-time timeline updates** +**Real-time, chronological timeline updates** See the updates of people you're following appear in real-time in the UI via WebSockets. There's a firehose view as well! -**Federated thread resolving** - -If someone you follow replies to a user unknown to the server, the server fetches the full thread so you can view it without leaving the UI - **Media attachments like images and short videos** Upload and view images and WebM/MP4 videos attached to the updates. Videos with no audio track are treated like GIFs; normal videos are looped - like vines! +**Safety and moderation tools** + +Private posts, locked accounts, phrase filtering, muting, blocking and all sorts of other features, along with a reporting and moderation system. [Learn more](https://blog.joinmastodon.org/2018/07/cage-the-mastodon/) + **OAuth2 and a straightforward REST API** -Mastodon acts as an OAuth2 provider so 3rd party apps can use the API - -**Fast response times** - -Mastodon tries to be as fast and responsive as possible, so all long-running tasks are delegated to background processing - -**Deployable via Docker** - -You don't need to mess with dependencies and configuration if you want to try Mastodon, if you have Docker and Docker Compose the deployment is extremely easy - ---- - -## Development - -Please follow the [development guide](https://github.com/tootsuite/documentation/blob/master/Running-Mastodon/Development-guide.md) from the documentation repository. +Mastodon acts as an OAuth2 provider so 3rd party apps can use the REST and Streaming APIs, resulting in a rich app ecosystem with a lot of choice! ## Deployment -There are guides in the documentation repository for [deploying on various platforms](https://github.com/tootsuite/documentation#running-mastodon). +**Tech stack:** + +- **Ruby on Rails** powers the REST API and other web pages +- **React.js** and Redux are used for the dynamic parts of the interface +- **Node.js** powers the streaming API + +**Requirements:** + +- **PostgreSQL** 9.5+ +- **Redis** +- **Ruby** 2.4+ +- **Node.js** 8+ + +The repository includes deployment configurations for **Docker and docker-compose**, but also a few specific platforms like **Heroku**, **Scalingo**, and **Nanobox**. The [**stand-alone** installation guide](https://docs.joinmastodon.org/administration/installation/) is available in the documentation. + +A **Vagrant** configuration is included for development purposes. ## Contributing -You can open issues for bugs you've found or features you think are missing. You can also submit pull requests to this repository. [Here are the guidelines for code contributions](CONTRIBUTING.md) +Mastodon is **free, open source software** licensed under **AGPLv3**. + +You can open issues for bugs you've found or features you think are missing. You can also submit pull requests to this repository, or submit translations using Weblate. To get started, take a look at [CONTRIBUTING.md](CONTRIBUTING.md) **IRC channel**: #mastodon on irc.freenode.net ## License -Copyright (C) 2016-2018 Eugen Rochko & other Mastodon contributors (see AUTHORS.md) +Copyright (C) 2016-2018 Eugen Rochko & other Mastodon contributors (see [AUTHORS.md](AUTHORS.md)) This program is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for more details. You should have received a copy of the GNU Affero General Public License along with this program. If not, see . - ---- - -## Extra credits - -The elephant friend illustrations are created by [Dopatwo](https://mastodon.social/@dopatwo) From 6c91f1a5b3cd79441211b07e1718e77b2728e5b0 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" Date: Fri, 19 Oct 2018 18:51:40 +0200 Subject: [PATCH 45/87] Bump strong_migrations from 0.3.0 to 0.3.1 (#9015) Bumps [strong_migrations](https://github.com/ankane/strong_migrations) from 0.3.0 to 0.3.1. - [Release notes](https://github.com/ankane/strong_migrations/releases) - [Changelog](https://github.com/ankane/strong_migrations/blob/master/CHANGELOG.md) - [Commits](https://github.com/ankane/strong_migrations/compare/v0.3.0...v0.3.1) Signed-off-by: dependabot[bot] --- Gemfile.lock | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Gemfile.lock b/Gemfile.lock index b64c054159..fa36d4cbe8 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -585,7 +585,7 @@ GEM stoplight (2.1.3) streamio-ffmpeg (3.0.2) multi_json (~> 1.8) - strong_migrations (0.3.0) + strong_migrations (0.3.1) activerecord (>= 3.2.0) temple (0.8.0) terminal-table (1.8.0) From 065b39e7a460e088fd5afcd48dfc425d0006fee9 Mon Sep 17 00:00:00 2001 From: bsky Date: Sat, 20 Oct 2018 03:35:42 +0900 Subject: [PATCH 46/87] Fix admin account avatar margin (#9020) --- app/javascript/styles/mastodon/rtl.scss | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/app/javascript/styles/mastodon/rtl.scss b/app/javascript/styles/mastodon/rtl.scss index 2bfd0de3af..0381e2e02d 100644 --- a/app/javascript/styles/mastodon/rtl.scss +++ b/app/javascript/styles/mastodon/rtl.scss @@ -317,11 +317,9 @@ body.rtl { .landing-page__information { .account__display-name { margin-right: 0; - margin-left: 5px; } .account__avatar-wrapper { - margin-left: 12px; - margin-right: 0; + margin-left: 0; } } From 029943d59b222e96a2f7839390a5628888249bf6 Mon Sep 17 00:00:00 2001 From: Masoud Abkenar Date: Sat, 20 Oct 2018 01:05:17 +0200 Subject: [PATCH 47/87] RTL: fix preferences layout (#9021) --- app/javascript/styles/mastodon/rtl.scss | 29 +++++++++++++++++++++++++ 1 file changed, 29 insertions(+) diff --git a/app/javascript/styles/mastodon/rtl.scss b/app/javascript/styles/mastodon/rtl.scss index 0381e2e02d..448534b3c7 100644 --- a/app/javascript/styles/mastodon/rtl.scss +++ b/app/javascript/styles/mastodon/rtl.scss @@ -196,6 +196,10 @@ body.rtl { right: -2.14285714em; } + .admin-wrapper { + direction: rtl; + } + .admin-wrapper .sidebar ul a i.fa, a.table-action-link i.fa { margin-right: 0; @@ -214,11 +218,32 @@ body.rtl { right: 0; } + .simple_form .input.radio_buttons .radio { + left: auto; + right: 0; + } + + .simple_form .input.radio_buttons .radio > label { + padding-right: 28px; + padding-left: 0; + } + .simple_form .input-with-append .input input { padding-left: 142px; padding-right: 0; } + .simple_form .input.boolean label.checkbox { + left: auto; + right: 0; + } + + .simple_form .input.boolean .label_input, + .simple_form .input.boolean .hint { + padding-left: 0; + padding-right: 28px; + } + .simple_form .label_input__append { right: auto; left: 0; @@ -230,6 +255,10 @@ body.rtl { } } + .simple_form select { + background: darken($ui-base-color, 10%) url("data:image/svg+xml;utf8,") no-repeat left 8px center / auto 16px; + } + .table th, .table td { text-align: right; From eb1b9903a6f60d024d71bffd635e6fec7edc59a9 Mon Sep 17 00:00:00 2001 From: Eugen Rochko Date: Sat, 20 Oct 2018 02:23:58 +0200 Subject: [PATCH 48/87] Redesign direct messages column (#9022) --- .../mastodon/components/avatar_composite.js | 96 +++++++++++++++++++ .../mastodon/components/display_name.js | 19 ++-- app/javascript/mastodon/components/status.js | 23 +++-- .../components/conversation.js | 56 +++-------- .../containers/conversation_container.js | 4 +- .../styles/mastodon/components.scss | 62 +++--------- 6 files changed, 152 insertions(+), 108 deletions(-) create mode 100644 app/javascript/mastodon/components/avatar_composite.js diff --git a/app/javascript/mastodon/components/avatar_composite.js b/app/javascript/mastodon/components/avatar_composite.js new file mode 100644 index 0000000000..4a9a73c512 --- /dev/null +++ b/app/javascript/mastodon/components/avatar_composite.js @@ -0,0 +1,96 @@ +import React from 'react'; +import PropTypes from 'prop-types'; +import ImmutablePropTypes from 'react-immutable-proptypes'; +import { autoPlayGif } from '../initial_state'; + +export default class AvatarComposite extends React.PureComponent { + + static propTypes = { + accounts: ImmutablePropTypes.list.isRequired, + animate: PropTypes.bool, + size: PropTypes.number.isRequired, + }; + + static defaultProps = { + animate: autoPlayGif, + }; + + renderItem (account, size, index) { + const { animate } = this.props; + + let width = 50; + let height = 100; + let top = 'auto'; + let left = 'auto'; + let bottom = 'auto'; + let right = 'auto'; + + if (size === 1) { + width = 100; + } + + if (size === 4 || (size === 3 && index > 0)) { + height = 50; + } + + if (size === 2) { + if (index === 0) { + right = '2px'; + } else { + left = '2px'; + } + } else if (size === 3) { + if (index === 0) { + right = '2px'; + } else if (index > 0) { + left = '2px'; + } + + if (index === 1) { + bottom = '2px'; + } else if (index > 1) { + top = '2px'; + } + } else if (size === 4) { + if (index === 0 || index === 2) { + right = '2px'; + } + + if (index === 1 || index === 3) { + left = '2px'; + } + + if (index < 2) { + bottom = '2px'; + } else { + top = '2px'; + } + } + + const style = { + left: left, + top: top, + right: right, + bottom: bottom, + width: `${width}%`, + height: `${height}%`, + backgroundSize: 'cover', + backgroundImage: `url(${account.get(animate ? 'avatar' : 'avatar_static')})`, + }; + + return ( +
+ ); + } + + render() { + const { accounts, size } = this.props; + + return ( +
+ {accounts.take(4).map((account, i) => this.renderItem(account, accounts.size, i))} +
+ ); + } + +} diff --git a/app/javascript/mastodon/components/display_name.js b/app/javascript/mastodon/components/display_name.js index c3a9ab9211..c2c40cb3f5 100644 --- a/app/javascript/mastodon/components/display_name.js +++ b/app/javascript/mastodon/components/display_name.js @@ -1,25 +1,28 @@ import React from 'react'; import ImmutablePropTypes from 'react-immutable-proptypes'; -import PropTypes from 'prop-types'; export default class DisplayName extends React.PureComponent { static propTypes = { account: ImmutablePropTypes.map.isRequired, - withAcct: PropTypes.bool, - }; - - static defaultProps = { - withAcct: true, + others: ImmutablePropTypes.list, }; render () { - const { account, withAcct } = this.props; + const { account, others } = this.props; const displayNameHtml = { __html: account.get('display_name_html') }; + let suffix; + + if (others && others.size > 1) { + suffix = `+${others.size}`; + } else { + suffix = @{account.get('acct')}; + } + return ( - {withAcct && @{account.get('acct')}} + {suffix} ); } diff --git a/app/javascript/mastodon/components/status.js b/app/javascript/mastodon/components/status.js index 90c689a75a..0b23e51f8a 100644 --- a/app/javascript/mastodon/components/status.js +++ b/app/javascript/mastodon/components/status.js @@ -3,6 +3,7 @@ import ImmutablePropTypes from 'react-immutable-proptypes'; import PropTypes from 'prop-types'; import Avatar from './avatar'; import AvatarOverlay from './avatar_overlay'; +import AvatarComposite from './avatar_composite'; import RelativeTimestamp from './relative_timestamp'; import DisplayName from './display_name'; import StatusContent from './status_content'; @@ -45,6 +46,8 @@ class Status extends ImmutablePureComponent { static propTypes = { status: ImmutablePropTypes.map, account: ImmutablePropTypes.map, + otherAccounts: ImmutablePropTypes.list, + onClick: PropTypes.func, onReply: PropTypes.func, onFavourite: PropTypes.func, onReblog: PropTypes.func, @@ -60,6 +63,7 @@ class Status extends ImmutablePureComponent { onToggleHidden: PropTypes.func, muted: PropTypes.bool, hidden: PropTypes.bool, + unread: PropTypes.bool, onMoveUp: PropTypes.func, onMoveDown: PropTypes.func, }; @@ -74,6 +78,11 @@ class Status extends ImmutablePureComponent { ] handleClick = () => { + if (this.props.onClick) { + this.props.onClick(); + return; + } + if (!this.context.router) { return; } @@ -158,7 +167,7 @@ class Status extends ImmutablePureComponent { let media = null; let statusAvatar, prepend, rebloggedByText; - const { intl, hidden, featured } = this.props; + const { intl, hidden, featured, otherAccounts, unread } = this.props; let { status, account, ...other } = this.props; @@ -249,9 +258,11 @@ class Status extends ImmutablePureComponent { } } - if (account === undefined || account === null) { + if (otherAccounts) { + statusAvatar = ; + } else if (account === undefined || account === null) { statusAvatar = ; - }else{ + } else { statusAvatar = ; } @@ -269,10 +280,10 @@ class Status extends ImmutablePureComponent { return ( -
+
{prepend} -
+
@@ -281,7 +292,7 @@ class Status extends ImmutablePureComponent { {statusAvatar}
- +
diff --git a/app/javascript/mastodon/features/direct_timeline/components/conversation.js b/app/javascript/mastodon/features/direct_timeline/components/conversation.js index 52e33c3c85..7277b7f0fc 100644 --- a/app/javascript/mastodon/features/direct_timeline/components/conversation.js +++ b/app/javascript/mastodon/features/direct_timeline/components/conversation.js @@ -2,13 +2,7 @@ import React from 'react'; import PropTypes from 'prop-types'; import ImmutablePropTypes from 'react-immutable-proptypes'; import ImmutablePureComponent from 'react-immutable-pure-component'; -import StatusContent from '../../../components/status_content'; -import RelativeTimestamp from '../../../components/relative_timestamp'; -import DisplayName from '../../../components/display_name'; -import Avatar from '../../../components/avatar'; -import AttachmentList from '../../../components/attachment_list'; -import { HotKeys } from 'react-hotkeys'; -import classNames from 'classnames'; +import StatusContainer from '../../../containers/status_container'; export default class Conversation extends ImmutablePureComponent { @@ -19,7 +13,7 @@ export default class Conversation extends ImmutablePureComponent { static propTypes = { conversationId: PropTypes.string.isRequired, accounts: ImmutablePropTypes.list.isRequired, - lastStatus: ImmutablePropTypes.map.isRequired, + lastStatusId: PropTypes.string, unread:PropTypes.bool.isRequired, onMoveUp: PropTypes.func, onMoveDown: PropTypes.func, @@ -31,13 +25,13 @@ export default class Conversation extends ImmutablePureComponent { return; } - const { lastStatus, unread, markRead } = this.props; + const { lastStatusId, unread, markRead } = this.props; if (unread) { markRead(); } - this.context.router.history.push(`/statuses/${lastStatus.get('id')}`); + this.context.router.history.push(`/statuses/${lastStatusId}`); } handleHotkeyMoveUp = () => { @@ -49,44 +43,20 @@ export default class Conversation extends ImmutablePureComponent { } render () { - const { accounts, lastStatus, lastAccount, unread } = this.props; + const { accounts, lastStatusId, unread } = this.props; - if (lastStatus === null) { + if (lastStatusId === null) { return null; } - const handlers = { - moveDown: this.handleHotkeyMoveDown, - moveUp: this.handleHotkeyMoveUp, - open: this.handleClick, - }; - - let media; - - if (lastStatus.get('media_attachments').size > 0) { - media = ; - } - return ( - -
-
-
-
{accounts.map(account => )}
-
- -
- -
- -
-
- - - - {media} -
-
+ ); } diff --git a/app/javascript/mastodon/features/direct_timeline/containers/conversation_container.js b/app/javascript/mastodon/features/direct_timeline/containers/conversation_container.js index e2e2e3afb5..bd6f6bfb01 100644 --- a/app/javascript/mastodon/features/direct_timeline/containers/conversation_container.js +++ b/app/javascript/mastodon/features/direct_timeline/containers/conversation_container.js @@ -4,13 +4,11 @@ import { markConversationRead } from '../../../actions/conversations'; const mapStateToProps = (state, { conversationId }) => { const conversation = state.getIn(['conversations', 'items']).find(x => x.get('id') === conversationId); - const lastStatus = state.getIn(['statuses', conversation.get('last_status')], null); return { accounts: conversation.get('accounts').map(accountId => state.getIn(['accounts', accountId], null)), unread: conversation.get('unread'), - lastStatus, - lastAccount: lastStatus === null ? null : state.getIn(['accounts', lastStatus.get('account')], null), + lastStatusId: conversation.get('last_status', null), }; }; diff --git a/app/javascript/styles/mastodon/components.scss b/app/javascript/styles/mastodon/components.scss index 24b614a37f..f77dc405c5 100644 --- a/app/javascript/styles/mastodon/components.scss +++ b/app/javascript/styles/mastodon/components.scss @@ -801,7 +801,7 @@ padding: 8px 10px; padding-left: 68px; position: relative; - min-height: 48px; + min-height: 54px; border-bottom: 1px solid lighten($ui-base-color, 8%); cursor: default; @@ -823,7 +823,7 @@ margin-top: 8px; } - &.status-direct { + &.status-direct:not(.read) { background: lighten($ui-base-color, 8%); border-bottom-color: lighten($ui-base-color, 12%); } @@ -1133,6 +1133,18 @@ vertical-align: middle; margin-right: 5px; } + + &-composite { + @include avatar-radius(); + overflow: hidden; + + & > div { + @include avatar-radius(); + float: left; + position: relative; + box-sizing: border-box; + } + } } a .account__avatar { @@ -5497,49 +5509,3 @@ noscript { } } } - -.conversation { - padding: 14px 10px; - border-bottom: 1px solid lighten($ui-base-color, 8%); - cursor: pointer; - - &--unread { - background: lighten($ui-base-color, 8%); - border-bottom-color: lighten($ui-base-color, 12%); - } - - &__header { - display: flex; - margin-bottom: 15px; - } - - &__avatars { - overflow: hidden; - flex: 1 1 auto; - - & > div { - display: flex; - flex-wrap: none; - width: 900px; - } - - .account__avatar { - margin-right: 10px; - } - } - - &__time { - flex: 0 0 auto; - font-size: 14px; - color: $darker-text-color; - text-align: right; - - .display-name { - color: $secondary-text-color; - } - } - - .attachment-list.compact { - margin-top: 15px; - } -} From 369cc5f555821d823d4daf7aab3142cdac896a69 Mon Sep 17 00:00:00 2001 From: Eugen Rochko Date: Sat, 20 Oct 2018 02:25:25 +0200 Subject: [PATCH 49/87] Check if port/socket is available before forking in Streaming API (#9023) Previously, the server would attempt taking port/socket in worker process, and if it was taken, fail, which made the master process create a new worker. This led to really high CPU usage if the streaming API was started when the port or socket were not available. Now, before clustering (forking) into worker processes, a test server is created and then removed to check if it can be done. --- streaming/index.js | 64 +++++++++++++++++++++++++++++++++++----------- 1 file changed, 49 insertions(+), 15 deletions(-) diff --git a/streaming/index.js b/streaming/index.js index 3a01be66a5..dd1a8d5462 100644 --- a/streaming/index.js +++ b/streaming/index.js @@ -74,6 +74,7 @@ const startMaster = () => { if (!process.env.SOCKET && process.env.PORT && isNaN(+process.env.PORT)) { log.warn('UNIX domain socket is now supported by using SOCKET. Please migrate from PORT hack.'); } + log.info(`Starting streaming API server master with ${numWorkers} workers`); }; @@ -616,16 +617,9 @@ const startWorker = (workerId) => { }); }, 30000); - if (process.env.SOCKET || process.env.PORT && isNaN(+process.env.PORT)) { - server.listen(process.env.SOCKET || process.env.PORT, () => { - fs.chmodSync(server.address(), 0o666); - log.info(`Worker ${workerId} now listening on ${server.address()}`); - }); - } else { - server.listen(+process.env.PORT || 4000, process.env.BIND || '0.0.0.0', () => { - log.info(`Worker ${workerId} now listening on ${server.address().address}:${server.address().port}`); - }); - } + attachServerWithConfig(server, address => { + log.info(`Worker ${workerId} now listening on ${address}`); + }); const onExit = () => { log.info(`Worker ${workerId} exiting, bye bye`); @@ -645,9 +639,49 @@ const startWorker = (workerId) => { process.on('uncaughtException', onError); }; -throng({ - workers: numWorkers, - lifetime: Infinity, - start: startWorker, - master: startMaster, +const attachServerWithConfig = (server, onSuccess) => { + if (process.env.SOCKET || process.env.PORT && isNaN(+process.env.PORT)) { + server.listen(process.env.SOCKET || process.env.PORT, () => { + fs.chmodSync(server.address(), 0o666); + + if (onSuccess) { + onSuccess(server.address()); + } + }); + } else { + server.listen(+process.env.PORT || 4000, process.env.BIND || '0.0.0.0', () => { + if (onSuccess) { + onSuccess(`${server.address().address}:${server.address().port}`); + } + }); + } +}; + +const onPortAvailable = onSuccess => { + const testServer = http.createServer(); + + testServer.once('error', err => { + onSuccess(err); + }); + + testServer.once('listening', () => { + testServer.once('close', () => onSuccess()); + testServer.close(); + }); + + attachServerWithConfig(testServer); +}; + +onPortAvailable(err => { + if (err) { + log.error('Could not start server, the port or socket is in use'); + return; + } + + throng({ + workers: numWorkers, + lifetime: Infinity, + start: startWorker, + master: startMaster, + }); }); From 9486f0ca7774a148845a45db74ae8527cc963e85 Mon Sep 17 00:00:00 2001 From: Eugen Rochko Date: Sat, 20 Oct 2018 02:39:39 +0200 Subject: [PATCH 50/87] Add "disable" button to report screen (#9024) * Add "disable" button to report screen * i18n-tasks remove-unused --- app/controllers/admin/reports_controller.rb | 9 +++++++++ app/views/admin/accounts/show.html.haml | 6 +++--- app/views/admin/reports/show.html.haml | 6 ++++-- config/locales/ar.yml | 2 -- config/locales/ca.yml | 2 -- config/locales/co.yml | 2 -- config/locales/cs.yml | 2 -- config/locales/cy.yml | 1 - config/locales/da.yml | 2 -- config/locales/de.yml | 2 -- config/locales/el.yml | 2 -- config/locales/en.yml | 4 +--- config/locales/eo.yml | 2 -- config/locales/es.yml | 2 -- config/locales/eu.yml | 2 -- config/locales/fa.yml | 2 -- config/locales/fi.yml | 2 -- config/locales/fr.yml | 2 -- config/locales/gl.yml | 2 -- config/locales/he.yml | 2 -- config/locales/hu.yml | 2 -- config/locales/id.yml | 2 -- config/locales/io.yml | 2 -- config/locales/it.yml | 2 -- config/locales/ja.yml | 2 -- config/locales/ka.yml | 2 -- config/locales/ko.yml | 2 -- config/locales/nl.yml | 2 -- config/locales/no.yml | 2 -- config/locales/oc.yml | 3 --- config/locales/pl.yml | 2 -- config/locales/pt-BR.yml | 2 -- config/locales/pt.yml | 2 -- config/locales/ru.yml | 2 -- config/locales/sk.yml | 2 -- config/locales/sr-Latn.yml | 2 -- config/locales/sr.yml | 2 -- config/locales/sv.yml | 2 -- config/locales/th.yml | 2 -- config/locales/tr.yml | 2 -- config/locales/uk.yml | 2 -- config/locales/zh-CN.yml | 2 -- config/locales/zh-HK.yml | 2 -- config/locales/zh-TW.yml | 2 -- 44 files changed, 17 insertions(+), 88 deletions(-) diff --git a/app/controllers/admin/reports_controller.rb b/app/controllers/admin/reports_controller.rb index 5d7f43e005..e97ddb9b64 100644 --- a/app/controllers/admin/reports_controller.rb +++ b/app/controllers/admin/reports_controller.rb @@ -44,6 +44,14 @@ module Admin when 'resolve' @report.resolve!(current_account) log_action :resolve, @report + when 'disable' + @report.resolve!(current_account) + @report.target_account.user.disable! + + log_action :resolve, @report + log_action :disable, @report.target_account.user + + resolve_all_target_account_reports when 'silence' @report.resolve!(current_account) @report.target_account.update!(silenced: true) @@ -55,6 +63,7 @@ module Admin else raise ActiveRecord::RecordNotFound end + @report.reload end diff --git a/app/views/admin/accounts/show.html.haml b/app/views/admin/accounts/show.html.haml index f2c53e3fe3..17f1f224d4 100644 --- a/app/views/admin/accounts/show.html.haml +++ b/app/views/admin/accounts/show.html.haml @@ -106,7 +106,7 @@ - if @account.user&.otp_required_for_login? = link_to t('admin.accounts.disable_two_factor_authentication'), admin_user_two_factor_authentication_path(@account.user.id), method: :delete, class: 'button' if can?(:disable_2fa, @account.user) - unless @account.memorial? - = link_to t('admin.accounts.memorialize'), memorialize_admin_account_path(@account.id), method: :post, data: { confirm: t('admin.accounts.are_you_sure') }, class: 'button' if can?(:memorialize, @account) + = link_to t('admin.accounts.memorialize'), memorialize_admin_account_path(@account.id), method: :post, data: { confirm: t('admin.accounts.are_you_sure') }, class: 'button button--destructive' if can?(:memorialize, @account) - else = link_to t('admin.accounts.redownload'), redownload_admin_account_path(@account.id), method: :post, class: 'button' if can?(:redownload, @account) @@ -114,7 +114,7 @@ - if @account.silenced? = link_to t('admin.accounts.undo_silenced'), admin_account_silence_path(@account.id), method: :delete, class: 'button' if can?(:unsilence, @account) - else - = link_to t('admin.accounts.silence'), admin_account_silence_path(@account.id), method: :post, class: 'button' if can?(:silence, @account) + = link_to t('admin.accounts.silence'), admin_account_silence_path(@account.id), method: :post, class: 'button button--destructive' if can?(:silence, @account) - if @account.local? - unless @account.user_confirmed? @@ -123,7 +123,7 @@ - if @account.suspended? = link_to t('admin.accounts.undo_suspension'), admin_account_suspension_path(@account.id), method: :delete, class: 'button' if can?(:unsuspend, @account) - else - = link_to t('admin.accounts.perform_full_suspension'), new_admin_account_suspension_path(@account.id), class: 'button' if can?(:suspend, @account) + = link_to t('admin.accounts.perform_full_suspension'), new_admin_account_suspension_path(@account.id), class: 'button button--destructive' if can?(:suspend, @account) - if !@account.local? && @account.hub_url.present? %hr.spacer/ diff --git a/app/views/admin/reports/show.html.haml b/app/views/admin/reports/show.html.haml index ef0e4aa415..3588d151d2 100644 --- a/app/views/admin/reports/show.html.haml +++ b/app/views/admin/reports/show.html.haml @@ -7,8 +7,10 @@ %div{ style: 'overflow: hidden; margin-bottom: 20px' } - if @report.unresolved? %div{ style: 'float: right' } - = link_to t('admin.reports.silence_account'), admin_report_path(@report, outcome: 'silence'), method: :put, class: 'button' - = link_to t('admin.reports.suspend_account'), new_admin_account_suspension_path(@report.target_account_id, report_id: @report.id), class: 'button' + - if @report.target_account.local? + = link_to t('admin.accounts.disable'), admin_report_path(@report, outcome: 'disable'), method: :put, class: 'button button--destructive' + = link_to t('admin.accounts.silence'), admin_report_path(@report, outcome: 'silence'), method: :put, class: 'button button--destructive' + = link_to t('admin.accounts.perform_full_suspension'), new_admin_account_suspension_path(@report.target_account_id, report_id: @report.id), class: 'button button--destructive' %div{ style: 'float: left' } = link_to t('admin.reports.mark_as_resolved'), admin_report_path(@report, outcome: 'resolve'), method: :put, class: 'button' - else diff --git a/config/locales/ar.yml b/config/locales/ar.yml index 0a8d3fdd4b..4499830f95 100644 --- a/config/locales/ar.yml +++ b/config/locales/ar.yml @@ -346,9 +346,7 @@ ar: reported_by: أبلغ عنه من طرف resolved: معالجة resolved_msg: تم حل تقرير بنجاح! - silence_account: كتم و إخفاء الحساب status: الحالة - suspend_account: فرض تعليق على الحساب title: التقارير unassign: إلغاء تعيين unresolved: غير معالجة diff --git a/config/locales/ca.yml b/config/locales/ca.yml index 354d45713b..d7211f654d 100644 --- a/config/locales/ca.yml +++ b/config/locales/ca.yml @@ -336,9 +336,7 @@ ca: reported_by: Reportat per resolved: Resolt resolved_msg: Informe resolt amb èxit! - silence_account: Silencia el compte status: Estat - suspend_account: Suspèn el compte title: Informes unassign: Treure assignació unresolved: No resolt diff --git a/config/locales/co.yml b/config/locales/co.yml index 0eac457e8b..7b810e2ede 100644 --- a/config/locales/co.yml +++ b/config/locales/co.yml @@ -345,9 +345,7 @@ co: reported_by: Palisatu da resolved: Scioltu è chjosu resolved_msg: Signalamentu scioltu! - silence_account: Silenzà u contu status: Statutu - suspend_account: Suspende u contu title: Signalamenti unassign: Disassignà unresolved: Micca sciolti diff --git a/config/locales/cs.yml b/config/locales/cs.yml index 2ab2beec58..67bda70f19 100644 --- a/config/locales/cs.yml +++ b/config/locales/cs.yml @@ -345,9 +345,7 @@ cs: reported_by: Nahlášeno uživatelem resolved: Vyřešeno resolved_msg: Nahlášení úspěšně vyřešeno! - silence_account: Utišit účet status: Stav - suspend_account: Suspendovat účet title: Nahlášení unassign: Odebrat unresolved: Nevyřešeno diff --git a/config/locales/cy.yml b/config/locales/cy.yml index 88aa3ee562..8b16949a55 100644 --- a/config/locales/cy.yml +++ b/config/locales/cy.yml @@ -329,7 +329,6 @@ cy: reported_by: Adroddwyd gan resolved: Wedi ei ddatrys resolved_msg: Llwyddwyd i ddatrys yr adroddiad! - silence_account: Tawelwch y cyfrif status: Statws title: Adroddiadau unassign: Dadneilltuo diff --git a/config/locales/da.yml b/config/locales/da.yml index 7cda5cbca2..0cd3e78f72 100644 --- a/config/locales/da.yml +++ b/config/locales/da.yml @@ -336,9 +336,7 @@ da: reported_by: Anmeldt af resolved: Løst resolved_msg: Anmeldelse er sat til at være løst! - silence_account: Dæmp konto status: Status - suspend_account: Udeluk konto title: Anmeldelser unassign: Utildel unresolved: Uløst diff --git a/config/locales/de.yml b/config/locales/de.yml index fb0235e0ce..12e0152264 100644 --- a/config/locales/de.yml +++ b/config/locales/de.yml @@ -344,9 +344,7 @@ de: reported_by: Gemeldet von resolved: Gelöst resolved_msg: Meldung erfolgreich gelöst! - silence_account: Konto stummschalten status: Status - suspend_account: Konto sperren title: Meldungen unassign: Zuweisung entfernen unresolved: Ungelöst diff --git a/config/locales/el.yml b/config/locales/el.yml index 63c438a938..fbd8a6461d 100644 --- a/config/locales/el.yml +++ b/config/locales/el.yml @@ -345,9 +345,7 @@ el: reported_by: Αναφέρθηκε από resolved: Επιλύθηκε resolved_msg: Η καταγγελία επιλύθηκε επιτυχώς! - silence_account: Αποσιώπηση λογαριασμού status: Κατάσταση - suspend_account: Ανέστειλε λογαριασμό title: Αναφορές unassign: Αποσύνδεση unresolved: Άλυτη diff --git a/config/locales/en.yml b/config/locales/en.yml index 26fe0080de..0360e719ef 100644 --- a/config/locales/en.yml +++ b/config/locales/en.yml @@ -128,7 +128,7 @@ en: most_recent: Most recent title: Order outbox_url: Outbox URL - perform_full_suspension: Perform full suspension + perform_full_suspension: Suspend profile_url: Profile URL promote: Promote protocol: Protocol @@ -346,9 +346,7 @@ en: reported_by: Reported by resolved: Resolved resolved_msg: Report successfully resolved! - silence_account: Silence account status: Status - suspend_account: Suspend account title: Reports unassign: Unassign unresolved: Unresolved diff --git a/config/locales/eo.yml b/config/locales/eo.yml index 454eeae9d3..72628a9440 100644 --- a/config/locales/eo.yml +++ b/config/locales/eo.yml @@ -325,9 +325,7 @@ eo: reported_by: Signalita de resolved: Solvita resolved_msg: Signalo sukcese solvita! - silence_account: Kaŝi konton status: Mesaĝoj - suspend_account: Haltigi konton title: Signaloj unassign: Malasigni unresolved: Nesolvita diff --git a/config/locales/es.yml b/config/locales/es.yml index 5adfafeca9..ccb7439ae6 100644 --- a/config/locales/es.yml +++ b/config/locales/es.yml @@ -336,9 +336,7 @@ es: reported_by: Reportado por resolved: Resuelto resolved_msg: "¡La denuncia se ha resuelto correctamente!" - silence_account: Silenciar cuenta status: Estado - suspend_account: Suspender cuenta title: Reportes unassign: Desasignar unresolved: No resuelto diff --git a/config/locales/eu.yml b/config/locales/eu.yml index 1a6558d9f5..f0ddb6adbd 100644 --- a/config/locales/eu.yml +++ b/config/locales/eu.yml @@ -336,9 +336,7 @@ eu: reported_by: Salatzailea resolved: Konponduta resolved_msg: Salaketa ongi konpondu da! - silence_account: Isilarazi kontua status: Mezua - suspend_account: Kanporatu kontua title: Salaketak unassign: Kendu esleipena unresolved: Konpondu gabea diff --git a/config/locales/fa.yml b/config/locales/fa.yml index d620dcf4b3..a9cf5868fc 100644 --- a/config/locales/fa.yml +++ b/config/locales/fa.yml @@ -336,9 +336,7 @@ fa: reported_by: گزارش از طرف resolved: حل‌شده resolved_msg: گزارش با موفقیت حل شد! - silence_account: بی‌صدا کردن حساب status: نوشته - suspend_account: معلق‌کردن حساب title: گزارش‌ها unassign: پس‌گرفتن مسئولیت unresolved: حل‌نشده diff --git a/config/locales/fi.yml b/config/locales/fi.yml index c4d1dd8713..e629311291 100644 --- a/config/locales/fi.yml +++ b/config/locales/fi.yml @@ -282,9 +282,7 @@ fi: reported_by: Raportoija resolved: Ratkaistut resolved_msg: Raportti onnistuneesti ratkaistu! - silence_account: Hiljennä tili status: Tila - suspend_account: Siirrä tili jäähylle title: Raportit unresolved: Ratkaisemattomat updated_at: Päivitetty diff --git a/config/locales/fr.yml b/config/locales/fr.yml index 51a3085537..f0eaf8d3f1 100644 --- a/config/locales/fr.yml +++ b/config/locales/fr.yml @@ -345,9 +345,7 @@ fr: reported_by: Signalé par resolved: Résolus resolved_msg: Signalement résolu avec succès ! - silence_account: Masquer le compte status: Statut - suspend_account: Suspendre le compte title: Signalements unassign: Dés-assigner unresolved: Non résolus diff --git a/config/locales/gl.yml b/config/locales/gl.yml index 49cc94f302..090796413d 100644 --- a/config/locales/gl.yml +++ b/config/locales/gl.yml @@ -345,9 +345,7 @@ gl: reported_by: Reportada por resolved: Resolto resolved_msg: Resolveuse con éxito o informe! - silence_account: Acalar conta status: Estado - suspend_account: Suspender conta title: Informes unassign: Non asignar unresolved: Non resolto diff --git a/config/locales/he.yml b/config/locales/he.yml index 3d24f22d20..09d57da3b9 100644 --- a/config/locales/he.yml +++ b/config/locales/he.yml @@ -189,9 +189,7 @@ he: reported_account: חשבון מדווח reported_by: דווח על ידי resolved: פתור - silence_account: השתקת חשבון status: הודעה - suspend_account: השעיית חשבון title: דיווחים unresolved: לא פתור settings: diff --git a/config/locales/hu.yml b/config/locales/hu.yml index 0c4046785e..92d11f0d8a 100644 --- a/config/locales/hu.yml +++ b/config/locales/hu.yml @@ -249,9 +249,7 @@ hu: reported_account: Bejelentett fiók reported_by: 'Jelentette:' resolved: Megoldott - silence_account: Felhasználó némítása status: Állapot - suspend_account: Felhasználó felfüggesztése title: Jelentések unresolved: Megoldatlan settings: diff --git a/config/locales/id.yml b/config/locales/id.yml index b186b7652f..3da3583f69 100644 --- a/config/locales/id.yml +++ b/config/locales/id.yml @@ -114,9 +114,7 @@ id: reported_account: Akun yang dilaporkan reported_by: Dilaporkan oleh resolved: Terseleseikan - silence_account: Akun yang didiamkan status: Status - suspend_account: Akun yang disuspen title: Laporan unresolved: Belum Terseleseikan settings: diff --git a/config/locales/io.yml b/config/locales/io.yml index be8a87acd0..b739df3af0 100644 --- a/config/locales/io.yml +++ b/config/locales/io.yml @@ -107,9 +107,7 @@ io: reported_account: Reported account reported_by: Reported by resolved: Resolved - silence_account: Silence account status: Status - suspend_account: Suspend account title: Reports unresolved: Unresolved settings: diff --git a/config/locales/it.yml b/config/locales/it.yml index 5182e33729..6a831ab2c5 100644 --- a/config/locales/it.yml +++ b/config/locales/it.yml @@ -324,9 +324,7 @@ it: report: 'Rapporto #%{id}' reported_by: Inviato da resolved: Risolto - silence_account: Silenzia account status: Stato - suspend_account: Sospendi account title: Rapporti unassign: Non assegnare unresolved: Non risolto diff --git a/config/locales/ja.yml b/config/locales/ja.yml index 84426f84eb..ea1d665daf 100644 --- a/config/locales/ja.yml +++ b/config/locales/ja.yml @@ -346,9 +346,7 @@ ja: reported_by: 報告者 resolved: 解決済み resolved_msg: レポートを解決済みにしました! - silence_account: アカウントをサイレンス status: ステータス - suspend_account: アカウントを停止 title: レポート unassign: 担当を外す unresolved: 未解決 diff --git a/config/locales/ka.yml b/config/locales/ka.yml index f782db09b1..5ac254df48 100644 --- a/config/locales/ka.yml +++ b/config/locales/ka.yml @@ -325,9 +325,7 @@ ka: reported_by: დაარეპორტა resolved: გადაწყვეტილი resolved_msg: რეპორტი წარმატებით გადაწყდა! - silence_account: ანგარიშის გაჩუმება status: სტატუსი - suspend_account: ანგარიშის შეჩერება title: რეპორტები unassign: გადაყენება unresolved: გადაუწყვეტელი diff --git a/config/locales/ko.yml b/config/locales/ko.yml index 6f281a3029..9f9875a16a 100644 --- a/config/locales/ko.yml +++ b/config/locales/ko.yml @@ -338,9 +338,7 @@ ko: reported_by: 신고자 resolved: 해결됨 resolved_msg: 리포트가 성공적으로 해결되었습니다! - silence_account: 계정을 침묵 처리 status: 상태 - suspend_account: 계정을 정지 title: 신고 unassign: 할당 해제 unresolved: 미해결 diff --git a/config/locales/nl.yml b/config/locales/nl.yml index 7e206d9389..997df01645 100644 --- a/config/locales/nl.yml +++ b/config/locales/nl.yml @@ -336,9 +336,7 @@ nl: reported_by: Gerapporteerd door resolved: Opgelost resolved_msg: Rapportage succesvol opgelost! - silence_account: Account negeren status: Toot - suspend_account: Account opschorten title: Rapportages unassign: Niet langer toewijzen unresolved: Onopgelost diff --git a/config/locales/no.yml b/config/locales/no.yml index bbfa9b5da0..61466fa20e 100644 --- a/config/locales/no.yml +++ b/config/locales/no.yml @@ -249,9 +249,7 @@ reported_account: Rapportert konto reported_by: Rapportert av resolved: Løst - silence_account: Målbind konto status: Status - suspend_account: Utvis konto title: Rapporter unresolved: Uløst settings: diff --git a/config/locales/oc.yml b/config/locales/oc.yml index af11d18e44..01063ab57f 100644 --- a/config/locales/oc.yml +++ b/config/locales/oc.yml @@ -144,7 +144,6 @@ oc: role: Permissions roles: admin: Administrator - bot: Robòt moderator: Moderador staff: Personnal user: Uitlizaire @@ -337,9 +336,7 @@ oc: reported_by: Senhalat per resolved: Resolgut resolved_msg: Rapòrt corrèctament resolgut  ! - silence_account: Metre lo compte en silenci status: Estatut - suspend_account: Suspendre lo compte title: Senhalament unassign: Levar unresolved: Pas resolgut diff --git a/config/locales/pl.yml b/config/locales/pl.yml index dfebe25bdd..4921055e3f 100644 --- a/config/locales/pl.yml +++ b/config/locales/pl.yml @@ -354,9 +354,7 @@ pl: reported_by: Zgłaszający resolved: Rozwiązane resolved_msg: Pomyślnie rozwiązano zgłoszenie. - silence_account: Wycisz konto status: Stan - suspend_account: Zawieś konto title: Zgłoszenia unassign: Cofnij przypisanie unresolved: Nierozwiązane diff --git a/config/locales/pt-BR.yml b/config/locales/pt-BR.yml index 3e56f0731e..1ec00f85f2 100644 --- a/config/locales/pt-BR.yml +++ b/config/locales/pt-BR.yml @@ -334,9 +334,7 @@ pt-BR: reported_by: Denunciada por resolved: Resolvido resolved_msg: Denúncia resolvida com sucesso! - silence_account: Silenciar conta status: Status - suspend_account: Suspender conta title: Denúncias unassign: Desatribuir unresolved: Não resolvido diff --git a/config/locales/pt.yml b/config/locales/pt.yml index 2bada74fe6..5f532ea377 100644 --- a/config/locales/pt.yml +++ b/config/locales/pt.yml @@ -249,9 +249,7 @@ pt: reported_account: Conta denunciada reported_by: Denúnciada por resolved: Resolvido - silence_account: Conta silenciada status: Estado - suspend_account: Conta suspensa title: Denúncias unresolved: Por resolver settings: diff --git a/config/locales/ru.yml b/config/locales/ru.yml index e8bbb94ca1..2eef001704 100644 --- a/config/locales/ru.yml +++ b/config/locales/ru.yml @@ -345,9 +345,7 @@ ru: reported_by: Отправитель жалобы resolved: Разрешено resolved_msg: Жалоба успешно обработана! - silence_account: Заглушить аккаунт status: Статус - suspend_account: Блокировать аккаунт title: Жалобы unassign: Снять назначение unresolved: Неразрешенные diff --git a/config/locales/sk.yml b/config/locales/sk.yml index 3e337fa428..2bdd3afa66 100644 --- a/config/locales/sk.yml +++ b/config/locales/sk.yml @@ -337,9 +337,7 @@ sk: reported_by: Nahlásené užívateľom resolved: Vyriešené resolved_msg: Hlásenie úspešne vyriešené! - silence_account: Zamĺčať účet status: Stav - suspend_account: Pozastaviť účet title: Reporty unassign: Odobrať unresolved: Nevyriešené diff --git a/config/locales/sr-Latn.yml b/config/locales/sr-Latn.yml index d6800a8fb2..ff31203c85 100644 --- a/config/locales/sr-Latn.yml +++ b/config/locales/sr-Latn.yml @@ -251,9 +251,7 @@ sr-Latn: reported_account: Prijavljeni nalog reported_by: Prijavio resolved: Rešeni - silence_account: Ućutkaj nalog status: Status - suspend_account: Suspenduj nalog title: Prijave unresolved: Nerešeni settings: diff --git a/config/locales/sr.yml b/config/locales/sr.yml index 53981b0f0a..36d81886eb 100644 --- a/config/locales/sr.yml +++ b/config/locales/sr.yml @@ -338,9 +338,7 @@ sr: reported_by: Пријавио resolved: Решена resolved_msg: Пријава успешно разрешена! - silence_account: Ућуткај налог status: Статус - suspend_account: Суспендуј налог title: Пријаве unassign: Уклони доделу unresolved: Нерешене diff --git a/config/locales/sv.yml b/config/locales/sv.yml index b7229aebe6..4f80a46f1a 100644 --- a/config/locales/sv.yml +++ b/config/locales/sv.yml @@ -285,9 +285,7 @@ sv: reported_by: Anmäld av resolved: Löst resolved_msg: Anmälan har lösts framgångsrikt! - silence_account: Tysta ner konto status: Status - suspend_account: Suspendera konto title: Anmälningar unassign: Otilldela unresolved: Olösta diff --git a/config/locales/th.yml b/config/locales/th.yml index 8c411f2524..3ed73c7f50 100644 --- a/config/locales/th.yml +++ b/config/locales/th.yml @@ -116,9 +116,7 @@ th: reported_account: รายงานแอคเคาท์ reported_by: รายงานโดย resolved: จัดการแล้ว - silence_account: แอคเค๊าท์ที่ปิดเสียง status: สถานะ - suspend_account: แอคเค๊าท์ที่หยุดไว้ title: รายงาน unresolved: Unresolved settings: diff --git a/config/locales/tr.yml b/config/locales/tr.yml index d7ecb480f0..99ba893979 100644 --- a/config/locales/tr.yml +++ b/config/locales/tr.yml @@ -115,9 +115,7 @@ tr: reported_account: Şikayet edilen hesap reported_by: Şikayet eden resolved: Giderildi - silence_account: Hesabı sustur status: Durum - suspend_account: Hesabı uzaklaştır title: Şikayetler unresolved: Giderilmedi settings: diff --git a/config/locales/uk.yml b/config/locales/uk.yml index 22d5e98df1..83a315a379 100644 --- a/config/locales/uk.yml +++ b/config/locales/uk.yml @@ -313,9 +313,7 @@ uk: reported_by: Відправник скарги resolved: Вирішено resolved_msg: Скаргу успішно вирішено! - silence_account: Заглушити акаунт status: Статус - suspend_account: Заблокувати акаунт title: Скарги unassign: Зняти призначення unresolved: Невирішені diff --git a/config/locales/zh-CN.yml b/config/locales/zh-CN.yml index 9a1b47fdbb..0ce1a0ed7e 100644 --- a/config/locales/zh-CN.yml +++ b/config/locales/zh-CN.yml @@ -332,9 +332,7 @@ zh-CN: reported_by: 举报人 resolved: 已处理 resolved_msg: 举报处理成功! - silence_account: 隐藏用户 status: 状态 - suspend_account: 封禁用户 title: 举报 unassign: 取消接管 unresolved: 未处理 diff --git a/config/locales/zh-HK.yml b/config/locales/zh-HK.yml index abbb1b8093..db7c0c47cf 100644 --- a/config/locales/zh-HK.yml +++ b/config/locales/zh-HK.yml @@ -285,9 +285,7 @@ zh-HK: reported_by: 舉報者 resolved: 已處理 resolved_msg: 舉報已處理。 - silence_account: 將用戶靜音 status: 狀態 - suspend_account: 將用戶停權 title: 舉報 unassign: 取消指派 unresolved: 未處理 diff --git a/config/locales/zh-TW.yml b/config/locales/zh-TW.yml index 338c40d095..d1b7633f33 100644 --- a/config/locales/zh-TW.yml +++ b/config/locales/zh-TW.yml @@ -295,9 +295,7 @@ zh-TW: reported_by: 檢舉人 resolved: 已解決 resolved_msg: 檢舉已處理! - silence_account: 靜音使用者 status: 狀態 - suspend_account: 停權使用者 title: 檢舉 unassign: 取消指派 unresolved: 未解決 From d5bfba3262cf531d767f583a79fc2fbe8bff93b4 Mon Sep 17 00:00:00 2001 From: Eugen Rochko Date: Sat, 20 Oct 2018 07:32:26 +0200 Subject: [PATCH 51/87] Do not test PAM authentication by default (#9027) * Do not test PAM authentication by default * Disable PAM tests if PAM is not enabled --- .env.test | 4 - .../auth/sessions_controller_spec.rb | 82 ++++++++++--------- 2 files changed, 42 insertions(+), 44 deletions(-) diff --git a/.env.test b/.env.test index 726351c5e3..fa4e1d91fa 100644 --- a/.env.test +++ b/.env.test @@ -3,7 +3,3 @@ NODE_ENV=test # Federation LOCAL_DOMAIN=cb6e6126.ngrok.io LOCAL_HTTPS=true -# test pam authentication -PAM_ENABLED=true -PAM_DEFAULT_SERVICE=pam_test -PAM_CONTROLLED_SERVICE=pam_test_controlled diff --git a/spec/controllers/auth/sessions_controller_spec.rb b/spec/controllers/auth/sessions_controller_spec.rb index b4f912717b..86fed7b8bb 100644 --- a/spec/controllers/auth/sessions_controller_spec.rb +++ b/spec/controllers/auth/sessions_controller_spec.rb @@ -55,53 +55,55 @@ RSpec.describe Auth::SessionsController, type: :controller do request.env['devise.mapping'] = Devise.mappings[:user] end - context 'using PAM authentication' do - context 'using a valid password' do - before do - post :create, params: { user: { email: "pam_user1", password: '123456' } } + if ENV['PAM_ENABLED'] == 'true' + context 'using PAM authentication' do + context 'using a valid password' do + before do + post :create, params: { user: { email: "pam_user1", password: '123456' } } + end + + it 'redirects to home' do + expect(response).to redirect_to(root_path) + end + + it 'logs the user in' do + expect(controller.current_user).to be_instance_of(User) + end end - it 'redirects to home' do - expect(response).to redirect_to(root_path) + context 'using an invalid password' do + before do + post :create, params: { user: { email: "pam_user1", password: 'WRONGPW' } } + end + + it 'shows a login error' do + expect(flash[:alert]).to match I18n.t('devise.failure.invalid', authentication_keys: 'Email') + end + + it "doesn't log the user in" do + expect(controller.current_user).to be_nil + end end - it 'logs the user in' do - expect(controller.current_user).to be_instance_of(User) - end - end + context 'using a valid email and existing user' do + let(:user) do + account = Fabricate.build(:account, username: 'pam_user1') + account.save!(validate: false) + user = Fabricate(:user, email: 'pam@example.com', password: nil, account: account) + user + end - context 'using an invalid password' do - before do - post :create, params: { user: { email: "pam_user1", password: 'WRONGPW' } } - end + before do + post :create, params: { user: { email: user.email, password: '123456' } } + end - it 'shows a login error' do - expect(flash[:alert]).to match I18n.t('devise.failure.invalid', authentication_keys: 'Email') - end + it 'redirects to home' do + expect(response).to redirect_to(root_path) + end - it "doesn't log the user in" do - expect(controller.current_user).to be_nil - end - end - - context 'using a valid email and existing user' do - let(:user) do - account = Fabricate.build(:account, username: 'pam_user1') - account.save!(validate: false) - user = Fabricate(:user, email: 'pam@example.com', password: nil, account: account) - user - end - - before do - post :create, params: { user: { email: user.email, password: '123456' } } - end - - it 'redirects to home' do - expect(response).to redirect_to(root_path) - end - - it 'logs the user in' do - expect(controller.current_user).to eq user + it 'logs the user in' do + expect(controller.current_user).to eq user + end end end end From fd5285658f477c5b6a9c7af0935b5c889729b2e0 Mon Sep 17 00:00:00 2001 From: Eugen Rochko Date: Sat, 20 Oct 2018 08:02:44 +0200 Subject: [PATCH 52/87] Add option to block reports from domain (#8830) --- .../admin/domain_blocks_controller.rb | 2 +- app/javascript/packs/admin.js | 21 +++++++------------ app/lib/activitypub/activity/flag.rb | 8 +++++++ app/models/domain_block.rb | 13 ++++++------ .../domain_blocks/_domain_block.html.haml | 5 ++++- app/views/admin/domain_blocks/index.html.haml | 1 + app/views/admin/domain_blocks/new.html.haml | 3 +++ .../_email_domain_block.html.haml | 2 +- app/views/admin/instances/_instance.html.haml | 2 +- config/locales/en.yml | 2 ++ ...937_add_reject_reports_to_domain_blocks.rb | 17 +++++++++++++++ db/schema.rb | 1 + 12 files changed, 54 insertions(+), 23 deletions(-) create mode 100644 db/migrate/20181017170937_add_reject_reports_to_domain_blocks.rb diff --git a/app/controllers/admin/domain_blocks_controller.rb b/app/controllers/admin/domain_blocks_controller.rb index 64de2cbf0c..90c70275a2 100644 --- a/app/controllers/admin/domain_blocks_controller.rb +++ b/app/controllers/admin/domain_blocks_controller.rb @@ -46,7 +46,7 @@ module Admin end def resource_params - params.require(:domain_block).permit(:domain, :severity, :reject_media, :retroactive) + params.require(:domain_block).permit(:domain, :severity, :reject_media, :reject_reports, :retroactive) end def retroactive_unblock? diff --git a/app/javascript/packs/admin.js b/app/javascript/packs/admin.js index ce5f70ee78..f0c0ee0b74 100644 --- a/app/javascript/packs/admin.js +++ b/app/javascript/packs/admin.js @@ -1,17 +1,5 @@ import { delegate } from 'rails-ujs'; -function handleDeleteStatus(event) { - const [data] = event.detail; - const element = document.querySelector(`[data-id="${data.id}"]`); - if (element) { - element.parentNode.removeChild(element); - } -} - -[].forEach.call(document.querySelectorAll('.trash-button'), (content) => { - content.addEventListener('ajax:success', handleDeleteStatus); -}); - const batchCheckboxClassName = '.batch-checkbox input[type="checkbox"]'; delegate(document, '#batch_checkbox_all', 'change', ({ target }) => { @@ -22,6 +10,7 @@ delegate(document, '#batch_checkbox_all', 'change', ({ target }) => { delegate(document, batchCheckboxClassName, 'change', () => { const checkAllElement = document.querySelector('#batch_checkbox_all'); + if (checkAllElement) { checkAllElement.checked = [].every.call(document.querySelectorAll(batchCheckboxClassName), (content) => content.checked); checkAllElement.indeterminate = !checkAllElement.checked && [].some.call(document.querySelectorAll(batchCheckboxClassName), (content) => content.checked); @@ -41,8 +30,14 @@ delegate(document, '.media-spoiler-hide-button', 'click', () => { }); delegate(document, '#domain_block_severity', 'change', ({ target }) => { - const rejectMediaDiv = document.querySelector('.input.with_label.domain_block_reject_media'); + const rejectMediaDiv = document.querySelector('.input.with_label.domain_block_reject_media'); + const rejectReportsDiv = document.querySelector('.input.with_label.domain_block_reject_reports'); + if (rejectMediaDiv) { rejectMediaDiv.style.display = (target.value === 'suspend') ? 'none' : 'block'; } + + if (rejectReportsDiv) { + rejectReportsDiv.style.display = (target.value === 'suspend') ? 'none' : 'block'; + } }); diff --git a/app/lib/activitypub/activity/flag.rb b/app/lib/activitypub/activity/flag.rb index 36d3c57300..92e59bb81a 100644 --- a/app/lib/activitypub/activity/flag.rb +++ b/app/lib/activitypub/activity/flag.rb @@ -2,6 +2,8 @@ class ActivityPub::Activity::Flag < ActivityPub::Activity def perform + return if skip_reports? + target_accounts = object_uris.map { |uri| account_from_uri(uri) }.compact.select(&:local?) target_statuses_by_account = object_uris.map { |uri| status_from_uri(uri) }.compact.select(&:local?).group_by(&:account_id) @@ -19,6 +21,12 @@ class ActivityPub::Activity::Flag < ActivityPub::Activity end end + private + + def skip_reports? + DomainBlock.find_by(domain: @account.domain)&.reject_reports? + end + def object_uris @object_uris ||= Array(@object.is_a?(Array) ? @object.map { |item| value_or_id(item) } : value_or_id(@object)) end diff --git a/app/models/domain_block.rb b/app/models/domain_block.rb index 93658793bd..b828a9d71c 100644 --- a/app/models/domain_block.rb +++ b/app/models/domain_block.rb @@ -3,12 +3,13 @@ # # Table name: domain_blocks # -# id :bigint(8) not null, primary key -# domain :string default(""), not null -# created_at :datetime not null -# updated_at :datetime not null -# severity :integer default("silence") -# reject_media :boolean default(FALSE), not null +# id :bigint(8) not null, primary key +# domain :string default(""), not null +# created_at :datetime not null +# updated_at :datetime not null +# severity :integer default("silence") +# reject_media :boolean default(FALSE), not null +# reject_reports :boolean default(FALSE), not null # class DomainBlock < ApplicationRecord diff --git a/app/views/admin/domain_blocks/_domain_block.html.haml b/app/views/admin/domain_blocks/_domain_block.html.haml index 17a3de81c6..7bfea35743 100644 --- a/app/views/admin/domain_blocks/_domain_block.html.haml +++ b/app/views/admin/domain_blocks/_domain_block.html.haml @@ -1,10 +1,13 @@ %tr - %td.domain + %td %samp= domain_block.domain %td.severity = t("admin.domain_blocks.severities.#{domain_block.severity}") %td.reject_media - if domain_block.reject_media? || domain_block.suspend? %i.fa.fa-check + %td.reject_reports + - if domain_block.reject_reports? || domain_block.suspend? + %i.fa.fa-check %td = table_link_to 'undo', t('admin.domain_blocks.undo'), admin_domain_block_path(domain_block) diff --git a/app/views/admin/domain_blocks/index.html.haml b/app/views/admin/domain_blocks/index.html.haml index 42b8ca53f4..4c5221c423 100644 --- a/app/views/admin/domain_blocks/index.html.haml +++ b/app/views/admin/domain_blocks/index.html.haml @@ -8,6 +8,7 @@ %th= t('admin.domain_blocks.domain') %th= t('admin.domain_blocks.severity') %th= t('admin.domain_blocks.reject_media') + %th= t('admin.domain_blocks.reject_reports') %th %tbody = render @domain_blocks diff --git a/app/views/admin/domain_blocks/new.html.haml b/app/views/admin/domain_blocks/new.html.haml index f0eb217ebe..055d2fbd7e 100644 --- a/app/views/admin/domain_blocks/new.html.haml +++ b/app/views/admin/domain_blocks/new.html.haml @@ -17,5 +17,8 @@ .fields-group = f.input :reject_media, as: :boolean, wrapper: :with_label, label: I18n.t('admin.domain_blocks.reject_media'), hint: I18n.t('admin.domain_blocks.reject_media_hint') + .fields-group + = f.input :reject_reports, as: :boolean, wrapper: :with_label, label: I18n.t('admin.domain_blocks.reject_reports'), hint: I18n.t('admin.domain_blocks.reject_reports_hint') + .actions = f.button :button, t('.create'), type: :submit diff --git a/app/views/admin/email_domain_blocks/_email_domain_block.html.haml b/app/views/admin/email_domain_blocks/_email_domain_block.html.haml index 61cff93955..bf66c9001d 100644 --- a/app/views/admin/email_domain_blocks/_email_domain_block.html.haml +++ b/app/views/admin/email_domain_blocks/_email_domain_block.html.haml @@ -1,5 +1,5 @@ %tr - %td.domain + %td %samp= email_domain_block.domain %td = table_link_to 'trash', t('admin.email_domain_blocks.delete'), admin_email_domain_block_path(email_domain_block), method: :delete diff --git a/app/views/admin/instances/_instance.html.haml b/app/views/admin/instances/_instance.html.haml index 6efbbbe60a..e36ebae472 100644 --- a/app/views/admin/instances/_instance.html.haml +++ b/app/views/admin/instances/_instance.html.haml @@ -1,5 +1,5 @@ %tr - %td.domain + %td = link_to instance.domain, admin_accounts_path(by_domain: instance.domain) %td.count = instance.accounts_count diff --git a/config/locales/en.yml b/config/locales/en.yml index 0360e719ef..a2859aa5d8 100644 --- a/config/locales/en.yml +++ b/config/locales/en.yml @@ -263,6 +263,8 @@ en: title: New domain block reject_media: Reject media files reject_media_hint: Removes locally stored media files and refuses to download any in the future. Irrelevant for suspensions + reject_reports: Reject reports + reject_reports_hint: Ignore all reports coming from this domain. Irrelevant for suspensions severities: noop: None silence: Silence diff --git a/db/migrate/20181017170937_add_reject_reports_to_domain_blocks.rb b/db/migrate/20181017170937_add_reject_reports_to_domain_blocks.rb new file mode 100644 index 0000000000..f05d50fcd9 --- /dev/null +++ b/db/migrate/20181017170937_add_reject_reports_to_domain_blocks.rb @@ -0,0 +1,17 @@ +require Rails.root.join('lib', 'mastodon', 'migration_helpers') + +class AddRejectReportsToDomainBlocks < ActiveRecord::Migration[5.2] + include Mastodon::MigrationHelpers + + disable_ddl_transaction! + + def up + safety_assured do + add_column_with_default :domain_blocks, :reject_reports, :boolean, default: false, allow_null: false + end + end + + def down + remove_column :domain_blocks, :reject_reports + end +end diff --git a/db/schema.rb b/db/schema.rb index 046975ac99..8facfa2595 100644 --- a/db/schema.rb +++ b/db/schema.rb @@ -186,6 +186,7 @@ ActiveRecord::Schema.define(version: 2018_10_18_205649) do t.datetime "updated_at", null: false t.integer "severity", default: 0 t.boolean "reject_media", default: false, null: false + t.boolean "reject_reports", default: false, null: false t.index ["domain"], name: "index_domain_blocks_on_domain", unique: true end From 33976c8ecc6bd5e75b918737b224c9d4388f6516 Mon Sep 17 00:00:00 2001 From: takayamaki Date: Sun, 21 Oct 2018 00:28:04 +0900 Subject: [PATCH 53/87] fix: Execute PAM authentication tests on CircleCI (#9029) and use 'if' option of context block --- .circleci/config.yml | 3 + .../auth/sessions_controller_spec.rb | 82 +++++++++---------- 2 files changed, 43 insertions(+), 42 deletions(-) diff --git a/.circleci/config.yml b/.circleci/config.yml index 20688b8e9a..674d1b02dc 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -13,6 +13,9 @@ aliases: ALLOW_NOPAM: true CONTINUOUS_INTEGRATION: true DISABLE_SIMPLECOV: true + PAM_ENABLED: true + PAM_DEFAULT_SERVICE: pam_test + PAM_CONTROLLED_SERVICE: pam_test_controlled working_directory: ~/projects/mastodon/ - &attach_workspace diff --git a/spec/controllers/auth/sessions_controller_spec.rb b/spec/controllers/auth/sessions_controller_spec.rb index 86fed7b8bb..71fcc1a6e3 100644 --- a/spec/controllers/auth/sessions_controller_spec.rb +++ b/spec/controllers/auth/sessions_controller_spec.rb @@ -55,55 +55,53 @@ RSpec.describe Auth::SessionsController, type: :controller do request.env['devise.mapping'] = Devise.mappings[:user] end - if ENV['PAM_ENABLED'] == 'true' - context 'using PAM authentication' do - context 'using a valid password' do - before do - post :create, params: { user: { email: "pam_user1", password: '123456' } } - end - - it 'redirects to home' do - expect(response).to redirect_to(root_path) - end - - it 'logs the user in' do - expect(controller.current_user).to be_instance_of(User) - end + context 'using PAM authentication', if: ENV['PAM_ENABLED'] == 'true' do + context 'using a valid password' do + before do + post :create, params: { user: { email: "pam_user1", password: '123456' } } end - context 'using an invalid password' do - before do - post :create, params: { user: { email: "pam_user1", password: 'WRONGPW' } } - end - - it 'shows a login error' do - expect(flash[:alert]).to match I18n.t('devise.failure.invalid', authentication_keys: 'Email') - end - - it "doesn't log the user in" do - expect(controller.current_user).to be_nil - end + it 'redirects to home' do + expect(response).to redirect_to(root_path) end - context 'using a valid email and existing user' do - let(:user) do - account = Fabricate.build(:account, username: 'pam_user1') - account.save!(validate: false) - user = Fabricate(:user, email: 'pam@example.com', password: nil, account: account) - user - end + it 'logs the user in' do + expect(controller.current_user).to be_instance_of(User) + end + end - before do - post :create, params: { user: { email: user.email, password: '123456' } } - end + context 'using an invalid password' do + before do + post :create, params: { user: { email: "pam_user1", password: 'WRONGPW' } } + end - it 'redirects to home' do - expect(response).to redirect_to(root_path) - end + it 'shows a login error' do + expect(flash[:alert]).to match I18n.t('devise.failure.invalid', authentication_keys: 'Email') + end - it 'logs the user in' do - expect(controller.current_user).to eq user - end + it "doesn't log the user in" do + expect(controller.current_user).to be_nil + end + end + + context 'using a valid email and existing user' do + let(:user) do + account = Fabricate.build(:account, username: 'pam_user1') + account.save!(validate: false) + user = Fabricate(:user, email: 'pam@example.com', password: nil, account: account) + user + end + + before do + post :create, params: { user: { email: user.email, password: '123456' } } + end + + it 'redirects to home' do + expect(response).to redirect_to(root_path) + end + + it 'logs the user in' do + expect(controller.current_user).to eq user end end end From f468bfb83004bf9b688cdcec5da41453e0390a3f Mon Sep 17 00:00:00 2001 From: Eugen Rochko Date: Sun, 21 Oct 2018 00:49:36 +0200 Subject: [PATCH 54/87] Bump version to 2.6.0rc1 (#9025) * Bump version to 2.6.0rc1 * Update AUTHORS.md * Update CHANGELOG.md --- AUTHORS.md | 83 ++++++++++++++++++++------------ CHANGELOG.md | 103 ++++++++++++++++++++++++++++++++++++++-- lib/mastodon/version.rb | 6 +-- 3 files changed, 153 insertions(+), 39 deletions(-) diff --git a/AUTHORS.md b/AUTHORS.md index abcc243849..277683a008 100644 --- a/AUTHORS.md +++ b/AUTHORS.md @@ -5,44 +5,46 @@ and provided thanks to the work of the following contributors: * [ykzts](https://github.com/ykzts) * [akihikodaki](https://github.com/akihikodaki) * [mjankowski](https://github.com/mjankowski) -* [unarist](https://github.com/unarist) * [ThibG](https://github.com/ThibG) +* [unarist](https://github.com/unarist) * [m4sk1n](https://github.com/m4sk1n) * [yiskah](https://github.com/yiskah) * [nolanlawson](https://github.com/nolanlawson) * [sorin-davidoi](https://github.com/sorin-davidoi) * [abcang](https://github.com/abcang) * [lynlynlynx](https://github.com/lynlynlynx) +* [dependabot[bot]](https://github.com/apps/dependabot) * [alpaca-tc](https://github.com/alpaca-tc) * [nclm](https://github.com/nclm) * [ineffyble](https://github.com/ineffyble) * [renatolond](https://github.com/renatolond) * [jeroenpraat](https://github.com/jeroenpraat) +* [mayaeh](https://github.com/mayaeh) * [blackle](https://github.com/blackle) * [Quent-in](https://github.com/Quent-in) * [JantsoP](https://github.com/JantsoP) * [nullkal](https://github.com/nullkal) * [yookoala](https://github.com/yookoala) -* [mayaeh](https://github.com/mayaeh) * [ysksn](https://github.com/ysksn) * [shuheiktgw](https://github.com/shuheiktgw) * [ashfurrow](https://github.com/ashfurrow) +* [mabkenar](https://github.com/mabkenar) * [zunda](https://github.com/zunda) -* [eramdam](https://github.com/eramdam) * [Kjwon15](https://github.com/Kjwon15) +* [eramdam](https://github.com/eramdam) * [masarakki](https://github.com/masarakki) * [ticky](https://github.com/ticky) +* [takayamaki](https://github.com/takayamaki) * [Quenty31](https://github.com/Quenty31) * [danhunsaker](https://github.com/danhunsaker) * [ThisIsMissEm](https://github.com/ThisIsMissEm) * [hcmiya](https://github.com/hcmiya) * [stephenburgess8](https://github.com/stephenburgess8) * [Wonderfall](https://github.com/Wonderfall) -* [takayamaki](https://github.com/takayamaki) * [matteoaquila](https://github.com/matteoaquila) * [rkarabut](https://github.com/rkarabut) -* [Artoria2e5](https://github.com/Artoria2e5) * [yukimochi](https://github.com/yukimochi) +* [Artoria2e5](https://github.com/Artoria2e5) * [marrus-sh](https://github.com/marrus-sh) * [krainboltgreene](https://github.com/krainboltgreene) * [patf](https://github.com/patf) @@ -56,7 +58,7 @@ and provided thanks to the work of the following contributors: * [MasterGroosha](https://github.com/MasterGroosha) * [JeanGauthier](https://github.com/JeanGauthier) * [kschaper](https://github.com/kschaper) -* [mabkenar](https://github.com/mabkenar) +* [MaciekBaron](https://github.com/MaciekBaron) * [MitarashiDango](mailto:mitarashidango@users.noreply.github.com) * [beatrix-bitrot](https://github.com/beatrix-bitrot) * [adbelle](https://github.com/adbelle) @@ -64,9 +66,9 @@ and provided thanks to the work of the following contributors: * [MightyPork](https://github.com/MightyPork) * [yhirano55](https://github.com/yhirano55) * [camponez](https://github.com/camponez) -* [MaciekBaron](https://github.com/MaciekBaron) * [SerCom-KC](https://github.com/SerCom-KC) * [aschmitz](https://github.com/aschmitz) +* [devkral](https://github.com/devkral) * [fpiesche](https://github.com/fpiesche) * [gandaro](https://github.com/gandaro) * [johnsudaar](https://github.com/johnsudaar) @@ -75,8 +77,6 @@ and provided thanks to the work of the following contributors: * [lindwurm](https://github.com/lindwurm) * [victorhck](mailto:victorhck@geeko.site) * [voidsatisfaction](https://github.com/voidsatisfaction) -* [valentin2105](https://github.com/valentin2105) -* [devkral](https://github.com/devkral) * [hikari-no-yume](https://github.com/hikari-no-yume) * [angristan](https://github.com/angristan) * [seefood](https://github.com/seefood) @@ -93,6 +93,7 @@ and provided thanks to the work of the following contributors: * [tsuwatch](https://github.com/tsuwatch) * [victorhck](https://github.com/victorhck) * [puckipedia](https://github.com/puckipedia) +* [fvh-P](https://github.com/fvh-P) * [contraexemplo](https://github.com/contraexemplo) * [hugogameiro](https://github.com/hugogameiro) * [kazu9su](https://github.com/kazu9su) @@ -102,11 +103,11 @@ and provided thanks to the work of the following contributors: * [Neetshin](mailto:neetshin@neetsh.in) * [rainyday](https://github.com/rainyday) * [ProgVal](https://github.com/ProgVal) +* [valentin2105](https://github.com/valentin2105) * [yuntan](https://github.com/yuntan) * [goofy-bz](mailto:goofy@babelzilla.org) * [kadiix](https://github.com/kadiix) * [kodacs](https://github.com/kodacs) -* [fvh-P](https://github.com/fvh-P) * [rtucker](https://github.com/rtucker) * [KScl](https://github.com/KScl) * [sterdev](https://github.com/sterdev) @@ -116,6 +117,7 @@ and provided thanks to the work of the following contributors: * [cpytel](https://github.com/cpytel) * [northerner](https://github.com/northerner) * [fhemberger](https://github.com/fhemberger) +* [greysteil](https://github.com/greysteil) * [hnrysmth](https://github.com/hnrysmth) * [d6rkaiz](https://github.com/d6rkaiz) * [JMendyk](https://github.com/JMendyk) @@ -125,12 +127,14 @@ and provided thanks to the work of the following contributors: * [reneklacan](https://github.com/reneklacan) * [ekiru](https://github.com/ekiru) * [tcitworld](https://github.com/tcitworld) +* [ashleyhull-versent](https://github.com/ashleyhull-versent) * [geta6](https://github.com/geta6) * [happycoloredbanana](https://github.com/happycoloredbanana) * [leopku](https://github.com/leopku) * [SansPseudoFix](https://github.com/SansPseudoFix) * [tomfhowe](https://github.com/tomfhowe) * [noraworld](https://github.com/noraworld) +* [theboss](https://github.com/theboss) * [178inaba](https://github.com/178inaba) * [alyssais](https://github.com/alyssais) * [kodnaplakal](https://github.com/kodnaplakal) @@ -140,6 +144,7 @@ and provided thanks to the work of the following contributors: * [halkeye](https://github.com/halkeye) * [hinaloe](https://github.com/hinaloe) * [treby](https://github.com/treby) +* [Reverite](https://github.com/Reverite) * [jpdevries](https://github.com/jpdevries) * [00x9d](https://github.com/00x9d) * [Kurtis Rainbolt-Greene](mailto:me@kurtisrainboltgreene.name) @@ -147,15 +152,16 @@ and provided thanks to the work of the following contributors: * [nevillepark](https://github.com/nevillepark) * [ornithocoder](https://github.com/ornithocoder) * [pierreozoux](https://github.com/pierreozoux) +* [qguv](https://github.com/qguv) * [Ram Lmn](mailto:ramlmn@users.noreply.github.com) * [harukasan](https://github.com/harukasan) * [stamak](https://github.com/stamak) -* [theboss](https://github.com/theboss) * [Technowix](mailto:technowix@users.noreply.github.com) * [Eychics](https://github.com/Eychics) * [Thor Harald Johansen](mailto:thj@thj.no) * [0x70b1a5](https://github.com/0x70b1a5) * [gled-rs](https://github.com/gled-rs) +* [Valentin_NC](mailto:valentin.ouvrard@nautile.sarl) * [R0ckweb](https://github.com/R0ckweb) * [caasi](https://github.com/caasi) * [esetomo](https://github.com/esetomo) @@ -168,6 +174,7 @@ and provided thanks to the work of the following contributors: * [vahnj](https://github.com/vahnj) * [ikuradon](https://github.com/ikuradon) * [AndreLewin](https://github.com/AndreLewin) +* [rinsuki](https://github.com/rinsuki) * [redtachyons](https://github.com/redtachyons) * [thurloat](https://github.com/thurloat) * [aaribaud](https://github.com/aaribaud) @@ -188,14 +195,12 @@ and provided thanks to the work of the following contributors: * [Fjoerfoks](https://github.com/Fjoerfoks) * [fmauNeko](https://github.com/fmauNeko) * [gloaec](https://github.com/gloaec) -* [greysteil](https://github.com/greysteil) * [unstabler](https://github.com/unstabler) * [potato4d](https://github.com/potato4d) * [h-izumi](https://github.com/h-izumi) * [ErikXXon](https://github.com/ErikXXon) * [ian-kelling](https://github.com/ian-kelling) * [immae](https://github.com/immae) -* [Reverite](https://github.com/Reverite) * [foozmeat](https://github.com/foozmeat) * [jasonrhodes](https://github.com/jasonrhodes) * [Jason Snell](mailto:jason@newrelic.com) @@ -232,6 +237,8 @@ and provided thanks to the work of the following contributors: * [zacanger](https://github.com/zacanger) * [amazedkoumei](https://github.com/amazedkoumei) * [anon5r](https://github.com/anon5r) +* [aus-social](https://github.com/aus-social) +* [imbsky](https://github.com/imbsky) * [bsky](mailto:me@imbsky.net) * [chr-1x](https://github.com/chr-1x) * [codl](https://github.com/codl) @@ -249,12 +256,12 @@ and provided thanks to the work of the following contributors: * [oliverkeeble](https://github.com/oliverkeeble) * [pinfort](https://github.com/pinfort) * [rbaumert](https://github.com/rbaumert) +* [rhoio](https://github.com/rhoio) * [trwnh](https://github.com/trwnh) * [usagi-f](https://github.com/usagi-f) * [vidarlee](https://github.com/vidarlee) * [vjackson725](https://github.com/vjackson725) * [wxcafe](https://github.com/wxcafe) -* [rinsuki](https://github.com/rinsuki) * [新都心(Neet Shin)](mailto:nucx@dio-vox.com) * [cygnan](https://github.com/cygnan) * [Awea](https://github.com/Awea) @@ -282,6 +289,7 @@ and provided thanks to the work of the following contributors: * [ameliavoncat](https://github.com/ameliavoncat) * [ilpianista](https://github.com/ilpianista) * [Andreas Drop](mailto:andy@remline.de) +* [andi1984](https://github.com/andi1984) * [schas002](https://github.com/schas002) * [abackstrom](https://github.com/abackstrom) * [jumbosushi](https://github.com/jumbosushi) @@ -303,8 +311,9 @@ and provided thanks to the work of the following contributors: * [chriswk](https://github.com/chriswk) * [csu](https://github.com/csu) * [kklleemm](https://github.com/kklleemm) +* [colindean](https://github.com/colindean) * [dachinat](https://github.com/dachinat) -* [monsterpit-daggertooth](https://github.com/monsterpit-daggertooth) +* [multiple-creatures](https://github.com/multiple-creatures) * [watilde](https://github.com/watilde) * [daprice](https://github.com/daprice) * [dar5hak](https://github.com/dar5hak) @@ -328,14 +337,17 @@ and provided thanks to the work of the following contributors: * [espenronnevik](https://github.com/espenronnevik) * [Finariel](https://github.com/Finariel) * [siuying](https://github.com/siuying) +* [GenbuHase](https://github.com/GenbuHase) * [hattori6789](https://github.com/hattori6789) * [algernon](https://github.com/algernon) * [Fastbyte01](https://github.com/Fastbyte01) +* [Gomasy](https://github.com/Gomasy) * [myfreeweb](https://github.com/myfreeweb) * [gfaivre](https://github.com/gfaivre) * [Fiaxhs](https://github.com/Fiaxhs) * [reedcourty](https://github.com/reedcourty) * [anneau](https://github.com/anneau) +* [lanodan](https://github.com/lanodan) * [Harmon758](https://github.com/Harmon758) * [HellPie](https://github.com/HellPie) * [Habu-Kagumba](https://github.com/Habu-Kagumba) @@ -360,6 +372,7 @@ and provided thanks to the work of the following contributors: * [jguerder](https://github.com/jguerder) * [Jehops](https://github.com/Jehops) * [joshuap](https://github.com/joshuap) +* [YuleZ](https://github.com/YuleZ) * [Tiwy57](https://github.com/Tiwy57) * [xuv](https://github.com/xuv) * [Jnsll](https://github.com/Jnsll) @@ -388,6 +401,7 @@ and provided thanks to the work of the following contributors: * [otsune](https://github.com/otsune) * [Mathias B](mailto:10813340+mathias-b@users.noreply.github.com) * [matt-auckland](https://github.com/matt-auckland) +* [webroo](https://github.com/webroo) * [matthiasbeyer](https://github.com/matthiasbeyer) * [mattjmattj](https://github.com/mattjmattj) * [mtparet](https://github.com/mtparet) @@ -400,6 +414,7 @@ and provided thanks to the work of the following contributors: * [mike-burns](https://github.com/mike-burns) * [verymilan](https://github.com/verymilan) * [milmazz](https://github.com/milmazz) +* [premist](https://github.com/premist) * [Mnkai](https://github.com/Mnkai) * [mitchhentges](https://github.com/mitchhentges) * [moritzheiber](https://github.com/moritzheiber) @@ -413,7 +428,7 @@ and provided thanks to the work of the following contributors: * [vonneudeck](https://github.com/vonneudeck) * [Ninetailed](https://github.com/Ninetailed) * [k24](https://github.com/k24) -* [Noiob](mailto:noiob@users.noreply.github.com) +* [noiob](https://github.com/noiob) * [kwaio](https://github.com/kwaio) * [norayr](https://github.com/norayr) * [joyeusenoelle](https://github.com/joyeusenoelle) @@ -425,7 +440,6 @@ and provided thanks to the work of the following contributors: * [Pangoraw](https://github.com/Pangoraw) * [peterkeen](https://github.com/peterkeen) * [pgate](https://github.com/pgate) -* [qguv](https://github.com/qguv) * [remram44](https://github.com/remram44) * [retokromer](https://github.com/retokromer) * [rfwatson](https://github.com/rfwatson) @@ -436,6 +450,7 @@ and provided thanks to the work of the following contributors: * [staticsafe](https://github.com/staticsafe) * [snwh](https://github.com/snwh) * [sts10](https://github.com/sts10) +* [sascha-sl](https://github.com/sascha-sl) * [skoji](https://github.com/skoji) * [ScienJus](https://github.com/ScienJus) * [larkinscott](https://github.com/larkinscott) @@ -450,20 +465,20 @@ and provided thanks to the work of the following contributors: * [Sina Mashek](mailto:sina@mashek.xyz) * [sossii](https://github.com/sossii) * [SpankyWorks](https://github.com/SpankyWorks) -* [StefOfficiel](https://github.com/StefOfficiel) -* [svetlik](https://github.com/svetlik) -* [dereckson](https://github.com/dereckson) -* [phaedryx](https://github.com/phaedryx) -* [takp](https://github.com/takp) -* [tkusano](https://github.com/tkusano) -* [TakesxiSximada](https://github.com/TakesxiSximada) -* [TheInventrix](https://github.com/TheInventrix) -* [shug0](https://github.com/shug0) -* [Fortyseven](https://github.com/Fortyseven) -* [tobypinder](https://github.com/tobypinder) -* [tomosm](https://github.com/tomosm) -* [TomoyaShibata](https://github.com/TomoyaShibata) -* [treyssatvincent](https://github.com/treyssatvincent) +* [StefOfficiel](mailto:pichard.stephane@free.fr) +* [Svetlozar Todorov](mailto:svetlik@users.noreply.github.com) +* [Sébastien Santoro](mailto:dereckson@espace-win.org) +* [Tad Thorley](mailto:phaedryx@users.noreply.github.com) +* [Takayoshi Nishida](mailto:takayoshi.nishida@gmail.com) +* [Takayuki KUSANO](mailto:github@tkusano.jp) +* [TakesxiSximada](mailto:takesxi.sximada@gmail.com) +* [TheInventrix](mailto:theinventrix@users.noreply.github.com) +* [Thomas Alberola](mailto:thomas@needacoffee.fr) +* [Toby Deshane](mailto:fortyseven@users.noreply.github.com) +* [Toby Pinder](mailto:gigitrix@gmail.com) +* [Tomonori Murakami](mailto:crosslife777@gmail.com) +* [TomoyaShibata](mailto:wind.of.hometown@gmail.com) +* [Treyssat-Vincent Nino](mailto:treyssatvincent@users.noreply.github.com) * [Udo Kramer](mailto:optik@fluffel.io) * [Una](mailto:una@unascribed.com) * [Ushitora Anqou](mailto:ushitora_anqou@yahoo.co.jp) @@ -489,6 +504,7 @@ and provided thanks to the work of the following contributors: * [benklop](mailto:benklop@gmail.com) * [bsky](mailto:git@imbsky.net) * [caesarologia](mailto:lopesgemelli.1@gmail.com) +* [cbayerlein](mailto:c.bayerlein@gmail.com) * [chrolis](mailto:chrolis@users.noreply.github.com) * [cormo](mailto:cormorant2+github@gmail.com) * [d0p1](mailto:dopi-sama@hush.com) @@ -500,19 +516,23 @@ and provided thanks to the work of the following contributors: * [hakoai](mailto:hk--76@qa2.so-net.ne.jp) * [haosbvnker](mailto:github@chaosbunker.com) * [isati](mailto:phil@juchnowi.cz) +* [jacob](mailto:jacobherringtondeveloper@gmail.com) * [jenn kaplan](mailto:me@jkap.io) * [jirayudech](mailto:jirayudech@gmail.com) +* [jooops](mailto:joops@autistici.org) * [jukper](mailto:jukkaperanto@gmail.com) * [jumoru](mailto:jumoru@mailbox.org) * [karlyeurl](mailto:karl.yeurl@gmail.com) * [kedama](mailto:32974885+kedamadq@users.noreply.github.com) * [kuro5hin](mailto:rusty@kuro5hin.org) +* [luzpaz](mailto:luzpaz@users.noreply.github.com) * [maxypy](mailto:maxime@mpigou.fr) * [mhe](mailto:mail@marcus-herrmann.com) * [mimikun](mailto:dzdzble_effort_311@outlook.jp) * [mshrtkch](mailto:mshrtkch@users.noreply.github.com) * [muan](mailto:muan@github.com) * [neetshin](mailto:neetshin@neetsh.in) +* [nightpool](mailto:nightpool@users.noreply.github.com) * [rch850](mailto:rich850@gmail.com) * [roikale](mailto:roikale@users.noreply.github.com) * [rysiekpl](mailto:rysiek@hackerspace.pl) @@ -524,6 +544,7 @@ and provided thanks to the work of the following contributors: * [tackeyy](mailto:mailto.takita.yusuke@gmail.com) * [tateisu](mailto:tateisu@gmail.com) * [tmyt](mailto:shigure@refy.net) +* [trevDev()](mailto:trev@trevdev.ca) * [utam0k](mailto:k0ma@utam0k.jp) * [vpzomtrrfrt](mailto:vpzomtrrfrt@gmail.com) * [walfie](mailto:walfington@gmail.com) diff --git a/CHANGELOG.md b/CHANGELOG.md index 75a51fc7c6..666ccd14b2 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,14 +1,107 @@ -## 2.5.2 +Changelog +========= + +All notable changes to this project will be documented in this file. + +## [Unreleased] +### Added + +- Add link ownership verification (#8703) +- Add conversations API (#8832) +- Add limit for the number of people that can be followed from one account (#8807) +- Add admin setting to customize mascot (#8766) +- Add support for more granular ActivityPub audiences from other software, i.e. circles (#8950) +- Add option to block all reports from a domain (#8830) +- Add user preference to always expand toots marked with content warnings (#8762) +- Add user preference to always hide all media (#8569) +- Add `force_login` param to OAuth authorize page (#8655) +- Add `tootctl accounts backup` (#8642, #8811) +- Add `tootctl accounts create` (#8642, #8811) +- Add `tootctl accounts cull` (#8642, #8811) +- Add `tootctl accounts delete` (#8642, #8811) +- Add `tootctl accounts modify` (#8642, #8811) +- Add `tootctl accounts refresh` (#8642, #8811) +- Add `tootctl feeds build` (#8642, #8811) +- Add `tootctl feeds clear` (#8642, #8811) +- Add `tootctl settings registrations open` (#8642, #8811) +- Add `tootctl settings registrations close` (#8642, #8811) +- Add `min_id` param to REST API to support backwards pagination (#8736) +- Add a confirmation dialog when hitting reply and the compose box isn't empty (#8893) +- Add PostgreSQL disk space growth tracking in PGHero (#8906) +- Add button for disabling local account to report quick actions bar (#9024) +- Add Czech language (#8594) +- Add `Clear-Site-Data` header when logging out (#8627) +- Add `same-site` (`lax`) attribute to cookies (#8626) +- Add support for styled scrollbars in Firefox Nightly (#8653) +- Add highlight to the active tab in web UI profiles (#8673) +- Add auto-focus for comment textarea in report modal (#8689) +- Add auto-focus for emoji picker's search field (#8688) +- Add nginx and systemd templates to `dist/` directory (#8770) +- Add support for `/.well-known/change-password` (#8828) +- Add option to override FFMPEG binary path (#8855) +- Add `dns-prefetch` tag when using different host for assets or uploads (#8942) +- Add `description` meta tag (#8941) +- Add `Content-Security-Policy` header (#8957) +- Add cache for the instance info API (#8765) + +### Changed + +- Change forms design (#8703) +- Change reports overview to group by target account (#8674) +- Change web UI to show "read more" link on overly long in-stream statuses (#8205) +- Change design of direct messages column (#8832, #9022) +- Change home timelines to exclude DMs (#8940) +- Change list timelines to exclude all replies (#8683) +- Change admin accounts UI default sort to most recent (#8813) +- Change documentation URL in the UI (#8898) +- Change style of success and failure messages (#8973) +- Change DM filtering to always allow DMs from staff (#8993) +- Change recommended Ruby version to 2.5.3 (#9003) + +### Deprecated + +- `GET /api/v1/timelines/direct` → `GET /api/v1/conversations` (#8832) +- `POST /api/v1/notifications/dismiss` → `POST /api/v1/notifications/:id/dismiss` (#8905) + +### Removed + +- Remove "on this device" label in column push settings (#8704) +- Remove rake tasks in favour of tootctl commands (#8675) + +### Fixed + +- Fix remote statuses using instance's default locale if no language given (#8861) +- Fix streaming API not exiting when port or socket is unavailable (#9023) +- Fix network calls being performed in database transaction in ActivityPub handler (#8951) +- Fix dropdown arrow position (#8637) +- Fix first element of dropdowns being focused even if not using keyboard (#8679) +- Fix tootctl requiring `bundle exec` invocation (#8619) +- Fix public pages not using animation preference for avatars (#8614) +- Fix OEmbed/OpenGraph cards not understanding relative URLs (#8669) +- Fix some dark emojis not having a white outline (#8597) +- Fix media description not being displayed in various media modals (#8678) +- Fix generated URLs of desktop notifications missing base URL (#8758) +- Fix RTL styles (#8764, #8767, #8823, #8897, #9005, #9007, #9018, #9021) +- Fix crash in streaming API when tag param missing (#8955) +- Fix hotkeys not working when no element is focused (#8998) +- Fix some hotkeys not working on detailed status view (#9006) + +## [2.5.2] - 2018-10-12 +### Security - Fix XSS vulnerability (#8959) -## 2.5.1 +## [2.5.1] - 2018-10-07 +### Fixed -- Fix some local images not having their EXIF metadata stripped on upload (#8714) +- Fix database migrations for PostgreSQL below 9.5 (#8903) - Fix class autoloading issue in ActivityPub Create handler (#8820) - Fix cache statistics not being sent via statsd when statsd enabled (#8831) +- Bump puma from 3.11.4 to 3.12.0 (#8883) + +### Security + +- Fix some local images not having their EXIF metadata stripped on upload (#8714) - Fix being able to enable a disabled relay via ActivityPub Accept handler (#8864) - Bump nokogiri from 1.8.4 to 1.8.5 (#8881) -- Bump puma from 3.11.4 to 3.12.0 (#8883) -- Fix database migrations for PostgreSQL below 9.5 (#8903) - Fix being able to report statuses not belonging to the reported account (#8916) diff --git a/lib/mastodon/version.rb b/lib/mastodon/version.rb index a49e7f102f..d0a1542ddd 100644 --- a/lib/mastodon/version.rb +++ b/lib/mastodon/version.rb @@ -9,11 +9,11 @@ module Mastodon end def minor - 5 + 6 end def patch - 2 + 0 end def pre @@ -21,7 +21,7 @@ module Mastodon end def flags - '' + 'rc1' end def to_a From 25f9ead041a3087993059a1398f37dfa21a62610 Mon Sep 17 00:00:00 2001 From: kedama Date: Sun, 21 Oct 2018 14:35:25 +0900 Subject: [PATCH 55/87] Fix domain label position and color (#9033) * Fix position of the domain label * Fix position of the domain label for RTL - Fix color mismatch of linear gradient which assigned to "::after" pseudo class --- app/javascript/styles/mastodon/forms.scss | 2 +- app/javascript/styles/mastodon/rtl.scss | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/app/javascript/styles/mastodon/forms.scss b/app/javascript/styles/mastodon/forms.scss index 337941a080..8c4c934ea4 100644 --- a/app/javascript/styles/mastodon/forms.scss +++ b/app/javascript/styles/mastodon/forms.scss @@ -427,7 +427,7 @@ code { &__append { position: absolute; - right: 1px; + right: 3px; top: 1px; padding: 10px; padding-bottom: 9px; diff --git a/app/javascript/styles/mastodon/rtl.scss b/app/javascript/styles/mastodon/rtl.scss index 448534b3c7..e3f4af825c 100644 --- a/app/javascript/styles/mastodon/rtl.scss +++ b/app/javascript/styles/mastodon/rtl.scss @@ -246,12 +246,12 @@ body.rtl { .simple_form .label_input__append { right: auto; - left: 0; + left: 3px; &::after { right: auto; left: 0; - background-image: linear-gradient(to left, rgba($ui-base-color, 0), $ui-base-color); + background-image: linear-gradient(to left, rgba(darken($ui-base-color, 10%), 0), darken($ui-base-color, 10%)); } } From bf58461d365b5cee0d8a80a019a64e84c841f32f Mon Sep 17 00:00:00 2001 From: Masoud Abkenar Date: Sun, 21 Oct 2018 13:31:40 +0200 Subject: [PATCH 56/87] RTL: fix column settings toggle label (#9037) --- app/javascript/styles/mastodon/rtl.scss | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/javascript/styles/mastodon/rtl.scss b/app/javascript/styles/mastodon/rtl.scss index e3f4af825c..a2dfbf74b7 100644 --- a/app/javascript/styles/mastodon/rtl.scss +++ b/app/javascript/styles/mastodon/rtl.scss @@ -73,7 +73,7 @@ body.rtl { float: left; } - .setting-toggle { + .setting-toggle__label { margin-left: 0; margin-right: 8px; } From 8d70d3de3842cd079484b8e683516ff291de7e24 Mon Sep 17 00:00:00 2001 From: Gomasy Date: Sun, 21 Oct 2018 23:41:33 +0900 Subject: [PATCH 57/87] Fix crash when using UNIX socket (#9036) --- streaming/index.js | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/streaming/index.js b/streaming/index.js index dd1a8d5462..b4d09d0ad2 100644 --- a/streaming/index.js +++ b/streaming/index.js @@ -642,9 +642,8 @@ const startWorker = (workerId) => { const attachServerWithConfig = (server, onSuccess) => { if (process.env.SOCKET || process.env.PORT && isNaN(+process.env.PORT)) { server.listen(process.env.SOCKET || process.env.PORT, () => { - fs.chmodSync(server.address(), 0o666); - if (onSuccess) { + fs.chmodSync(server.address(), 0o666); onSuccess(server.address()); } }); From 68f0e4d54e452fd71fee1f1eeeb09a6cc0f56a67 Mon Sep 17 00:00:00 2001 From: Jeong Arm Date: Sun, 21 Oct 2018 23:42:22 +0900 Subject: [PATCH 58/87] Handle if username is not found on tootctl feeds build (#9040) --- lib/mastodon/feeds_cli.rb | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/lib/mastodon/feeds_cli.rb b/lib/mastodon/feeds_cli.rb index c3fca723ec..cca65cf878 100644 --- a/lib/mastodon/feeds_cli.rb +++ b/lib/mastodon/feeds_cli.rb @@ -54,6 +54,11 @@ module Mastodon elsif username.present? account = Account.find_local(username) + if account.nil? + say("Account #{username} is not found", :red) + exit(1) + end + if options[:background] RegenerationWorker.perform_async(account.id) unless options[:dry_run] else From 3a157210c87e6fe034f70d922cf7fc70fb533ad1 Mon Sep 17 00:00:00 2001 From: Masoud Abkenar Date: Sun, 21 Oct 2018 16:45:08 +0200 Subject: [PATCH 59/87] RTL: fix admin account avatar margin in about page (#9039) * RTL: fix admin account avatar margin in about page * fix code style --- app/javascript/styles/mastodon/rtl.scss | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) diff --git a/app/javascript/styles/mastodon/rtl.scss b/app/javascript/styles/mastodon/rtl.scss index a2dfbf74b7..e5213b5555 100644 --- a/app/javascript/styles/mastodon/rtl.scss +++ b/app/javascript/styles/mastodon/rtl.scss @@ -341,14 +341,16 @@ body.rtl { margin-right: 20px; } } -} -.landing-page__information { - .account__display-name { - margin-right: 0; - } + .landing-page__information { + .account__display-name { + margin-right: 0; + margin-left: 5px; + } - .account__avatar-wrapper { - margin-left: 0; + .account__avatar-wrapper { + margin-left: 12px; + margin-right: 0; + } } } From c73864c1373330f2ef75006d639f90a1debcce6d Mon Sep 17 00:00:00 2001 From: Masoud Abkenar Date: Sun, 21 Oct 2018 18:37:57 +0200 Subject: [PATCH 60/87] RTL: fix cardbar margins and alignment (#9044) --- app/javascript/styles/mastodon/rtl.scss | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/app/javascript/styles/mastodon/rtl.scss b/app/javascript/styles/mastodon/rtl.scss index e5213b5555..a86e3e632f 100644 --- a/app/javascript/styles/mastodon/rtl.scss +++ b/app/javascript/styles/mastodon/rtl.scss @@ -353,4 +353,10 @@ body.rtl { margin-right: 0; } } + + .card__bar .display-name { + margin-left: 0; + margin-right: 15px; + text-align: right; + } } From 84cf78da8ad80d8a4128451d8d96ae74acbac318 Mon Sep 17 00:00:00 2001 From: ThibG Date: Sun, 21 Oct 2018 22:52:10 +0200 Subject: [PATCH 61/87] Fix og:url on toots' public view (#9047) Fixes #9045 --- app/views/stream_entries/show.html.haml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/views/stream_entries/show.html.haml b/app/views/stream_entries/show.html.haml index 2edc155bf3..0e81c4f685 100644 --- a/app/views/stream_entries/show.html.haml +++ b/app/views/stream_entries/show.html.haml @@ -12,7 +12,7 @@ = opengraph 'og:site_name', site_title = opengraph 'og:type', 'article' = opengraph 'og:title', "#{display_name(@account)} (@#{@account.local_username_and_domain})" - = opengraph 'og:url', short_account_status_url(@account, @stream_entry) + = opengraph 'og:url', short_account_status_url(@account, @stream_entry.activity) = render 'stream_entries/og_description', activity: @stream_entry.activity = render 'stream_entries/og_image', activity: @stream_entry.activity, account: @account From 2e18ad74dcffb2e1aeec9f265becd3308c110a67 Mon Sep 17 00:00:00 2001 From: Jeong Arm Date: Mon, 22 Oct 2018 05:52:27 +0900 Subject: [PATCH 62/87] Fix tootctl cull on dead servers (#9041) * Delete first 9 accounts on dead servers * Clean up code by moving dead server culling to the end --- lib/mastodon/accounts_cli.rb | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/lib/mastodon/accounts_cli.rb b/lib/mastodon/accounts_cli.rb index 704cf474b5..829fab19eb 100644 --- a/lib/mastodon/accounts_cli.rb +++ b/lib/mastodon/accounts_cli.rb @@ -239,7 +239,7 @@ module Mastodon end end - if [404, 410].include?(code) || dead_servers.include?(account.domain) + if [404, 410].include?(code) unless options[:dry_run] SuspendAccountService.new.call(account) account.destroy @@ -252,6 +252,18 @@ module Mastodon end end + # Remove dead servers + unless dead_servers.empty? || options[:dry_run] + dead_servers.each do |domain| + Account.where(domain: domain).find_each do |account| + SuspendAccountService.new.call(account) + account.destroy + culled += 1 + say('.', :green, false) + end + end + end + say say("Removed #{culled} accounts (#{dead_servers.size} dead servers)#{dry_run}", :green) From c7e9f9ff1ed1def7f14f6ca4ac2836005eeefa47 Mon Sep 17 00:00:00 2001 From: Masoud Abkenar Date: Mon, 22 Oct 2018 01:04:32 +0200 Subject: [PATCH 63/87] RTL: remove blank character inside bdi (#9038) * RTL: remove blank character inside bdi * Update app/javascript/mastodon/components/display_name.js Co-Authored-By: mabkenar --- app/javascript/mastodon/components/display_name.js | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/app/javascript/mastodon/components/display_name.js b/app/javascript/mastodon/components/display_name.js index c2c40cb3f5..31efab80a2 100644 --- a/app/javascript/mastodon/components/display_name.js +++ b/app/javascript/mastodon/components/display_name.js @@ -22,7 +22,8 @@ export default class DisplayName extends React.PureComponent { return ( - {suffix} + + {suffix} ); } From f5b8bd4392d7955c84de187e56def191dcf7de51 Mon Sep 17 00:00:00 2001 From: Eugen Rochko Date: Mon, 22 Oct 2018 16:58:08 +0200 Subject: [PATCH 64/87] Fix cull tripping on nil in last_webfingered_at (#9051) Fix #8741 --- lib/mastodon/accounts_cli.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/mastodon/accounts_cli.rb b/lib/mastodon/accounts_cli.rb index 829fab19eb..a32bc95332 100644 --- a/lib/mastodon/accounts_cli.rb +++ b/lib/mastodon/accounts_cli.rb @@ -223,7 +223,7 @@ module Mastodon dry_run = options[:dry_run] ? ' (DRY RUN)' : '' Account.remote.where(protocol: :activitypub).partitioned.find_each do |account| - next if account.updated_at >= skip_threshold || account.last_webfingered_at >= skip_threshold + next if account.updated_at >= skip_threshold || (account.last_webfingered_at.present? && account.last_webfingered_at >= skip_threshold) unless dead_servers.include?(account.domain) begin From 4f0bdbaaaf6828d7ee6fd6e6023375b727c0afe5 Mon Sep 17 00:00:00 2001 From: Eugen Rochko Date: Mon, 22 Oct 2018 16:58:36 +0200 Subject: [PATCH 65/87] Downgrade fog-openstack to 0.3.7 and fog-core to 2.1.0 (#9049) Fix #8889 --- Gemfile | 4 ++-- Gemfile.lock | 12 ++++++------ 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/Gemfile b/Gemfile index c5e8253358..6a0d331981 100644 --- a/Gemfile +++ b/Gemfile @@ -16,8 +16,8 @@ gem 'pghero', '~> 2.2' gem 'dotenv-rails', '~> 2.5' gem 'aws-sdk-s3', '~> 1.21', require: false -gem 'fog-core', '~> 2.1' -gem 'fog-openstack', '~> 1.0', require: false +gem 'fog-core', '<= 2.1.0' +gem 'fog-openstack', '~> 0.3', require: false gem 'paperclip', '~> 6.0' gem 'paperclip-av-transcoder', '~> 0.6' gem 'streamio-ffmpeg', '~> 3.0' diff --git a/Gemfile.lock b/Gemfile.lock index fa36d4cbe8..373ebbaf75 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -211,7 +211,7 @@ GEM fast_blank (1.0.0) fastimage (2.1.4) ffi (1.9.25) - fog-core (2.1.2) + fog-core (2.1.0) builder excon (~> 0.58) formatador (~> 0.2) @@ -219,8 +219,8 @@ GEM fog-json (1.2.0) fog-core multi_json (~> 1.10) - fog-openstack (1.0.3) - fog-core (~> 2.1) + fog-openstack (0.3.7) + fog-core (>= 1.45, <= 2.1.0) fog-json (>= 1.0) ipaddress (>= 0.8) formatador (0.2.5) @@ -678,8 +678,8 @@ DEPENDENCIES faker (~> 1.9) fast_blank (~> 1.0) fastimage - fog-core (~> 2.1) - fog-openstack (~> 1.0) + fog-core (<= 2.1.0) + fog-openstack (~> 0.3) fuubar (~> 2.3) goldfinger (~> 2.1) hamlit-rails (~> 0.2) @@ -766,4 +766,4 @@ RUBY VERSION ruby 2.5.3p105 BUNDLED WITH - 1.16.5 + 1.16.6 From e45a6edd6574c86409333cc64f9fb87e1b0a196e Mon Sep 17 00:00:00 2001 From: Thibaut Girka Date: Mon, 22 Oct 2018 18:15:51 +0200 Subject: [PATCH 66/87] Keep new DMs in home feeds and in the old DM timeline Revert server-side part of 87fdd139b890e60f752bf71e3b09d79eaefcf7b5 --- app/services/batched_remove_status_service.rb | 11 +++++++++++ app/services/fan_out_on_write_service.rb | 12 ++++++++++++ app/services/remove_status_service.rb | 8 ++++++++ 3 files changed, 31 insertions(+) diff --git a/app/services/batched_remove_status_service.rb b/app/services/batched_remove_status_service.rb index b8ab58938d..b7296cf7ca 100644 --- a/app/services/batched_remove_status_service.rb +++ b/app/services/batched_remove_status_service.rb @@ -39,6 +39,7 @@ class BatchedRemoveStatusService < BaseService # Cannot be batched statuses.each do |status| unpush_from_public_timelines(status) + unpush_from_direct_timelines(status) if status.direct_visibility? batch_salmon_slaps(status) if status.local? end @@ -95,6 +96,16 @@ class BatchedRemoveStatusService < BaseService end end + def unpush_from_direct_timelines(status) + payload = @json_payloads[status.id] + redis.pipelined do + @mentions[status.id].each do |mention| + redis.publish("timeline:direct:#{mention.account.id}", payload) if mention.account.local? + end + redis.publish("timeline:direct:#{status.account.id}", payload) if status.account.local? + end + end + def batch_salmon_slaps(status) return if @mentions[status.id].empty? diff --git a/app/services/fan_out_on_write_service.rb b/app/services/fan_out_on_write_service.rb index 7f2a917754..0e9465d483 100644 --- a/app/services/fan_out_on_write_service.rb +++ b/app/services/fan_out_on_write_service.rb @@ -9,6 +9,8 @@ class FanOutOnWriteService < BaseService render_anonymous_payload(status) if status.direct_visibility? + deliver_to_mentioned_followers(status) + deliver_to_direct_timelines(status) deliver_to_own_conversation(status) elsif status.limited_visibility? deliver_to_mentioned_followers(status) @@ -93,6 +95,16 @@ class FanOutOnWriteService < BaseService Redis.current.publish('timeline:public:local:media', @payload) if status.local? end + def deliver_to_direct_timelines(status) + Rails.logger.debug "Delivering status #{status.id} to direct timelines" + + status.mentions.includes(:account).each do |mention| + Redis.current.publish("timeline:direct:#{mention.account.id}", @payload) if mention.account.local? + end + + Redis.current.publish("timeline:direct:#{status.account.id}", @payload) if status.account.local? + end + def deliver_to_own_conversation(status) AccountConversation.add_status(status.account, status) end diff --git a/app/services/remove_status_service.rb b/app/services/remove_status_service.rb index 11d28e783d..4bee86c8a1 100644 --- a/app/services/remove_status_service.rb +++ b/app/services/remove_status_service.rb @@ -21,6 +21,7 @@ class RemoveStatusService < BaseService remove_from_hashtags remove_from_public remove_from_media if status.media_attachments.any? + remove_from_direct if status.direct_visibility? @status.destroy! @@ -152,6 +153,13 @@ class RemoveStatusService < BaseService Redis.current.publish('timeline:public:local:media', @payload) if @status.local? end + def remove_from_direct + @mentions.each do |mention| + Redis.current.publish("timeline:direct:#{mention.account.id}", @payload) if mention.account.local? + end + Redis.current.publish("timeline:direct:#{@account.id}", @payload) if @account.local? + end + def redis Redis.current end From 9f1c9b6135717535a48be0584dd777c9c8c34d76 Mon Sep 17 00:00:00 2001 From: Thibaut Girka Date: Mon, 22 Oct 2018 18:20:43 +0200 Subject: [PATCH 67/87] [Glitch] Improve style of notice/alert messages Port b972478812316da2f5c0d24c60386d408e027424 to glitch-soc --- app/javascript/flavours/glitch/styles/forms.scss | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/app/javascript/flavours/glitch/styles/forms.scss b/app/javascript/flavours/glitch/styles/forms.scss index be2bf7cead..eb94f2273b 100644 --- a/app/javascript/flavours/glitch/styles/forms.scss +++ b/app/javascript/flavours/glitch/styles/forms.scss @@ -460,9 +460,20 @@ code { border-radius: 4px; padding: 15px 10px; margin-bottom: 30px; - box-shadow: 0 0 5px rgba($base-shadow-color, 0.2); text-align: center; + &.notice { + border: 1px solid rgba($valid-value-color, 0.5); + background: rgba($valid-value-color, 0.25); + color: $valid-value-color; + } + + &.alert { + border: 1px solid rgba($error-value-color, 0.5); + background: rgba($error-value-color, 0.25); + color: $error-value-color; + } + p { margin-bottom: 15px; } From bf9c4b6d98628dacdf5617d86611d4aafbc14921 Mon Sep 17 00:00:00 2001 From: Thibaut Girka Date: Mon, 22 Oct 2018 18:22:01 +0200 Subject: [PATCH 68/87] [Glitch] undo part of PR 8202 to fix RTL Port efd09e2ebba7e9f0135bd47c44a77e2fc421aa67 to glitch-soc --- app/javascript/flavours/glitch/styles/stream_entries.scss | 1 - 1 file changed, 1 deletion(-) diff --git a/app/javascript/flavours/glitch/styles/stream_entries.scss b/app/javascript/flavours/glitch/styles/stream_entries.scss index c458fcb792..80e2d0ca0e 100644 --- a/app/javascript/flavours/glitch/styles/stream_entries.scss +++ b/app/javascript/flavours/glitch/styles/stream_entries.scss @@ -3,7 +3,6 @@ border-radius: 4px; overflow: hidden; margin-bottom: 10px; - text-align: left; @media screen and (max-width: $no-gap-breakpoint) { margin-bottom: 0; From 1139b758c5c9ef5526c045da59d2ce6e39d6e1c8 Mon Sep 17 00:00:00 2001 From: Thibaut Girka Date: Mon, 22 Oct 2018 18:30:11 +0200 Subject: [PATCH 69/87] [Glitch] RTL: fix admin account margins in about page Port f8c1b325410369806eb77a5c8d259971a87a6852 to glitch-soc --- app/javascript/flavours/glitch/styles/rtl.scss | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/app/javascript/flavours/glitch/styles/rtl.scss b/app/javascript/flavours/glitch/styles/rtl.scss index 70aaa5bb10..654d5e27c7 100644 --- a/app/javascript/flavours/glitch/styles/rtl.scss +++ b/app/javascript/flavours/glitch/styles/rtl.scss @@ -313,3 +313,15 @@ body.rtl { } } } + +.landing-page__information { + .account__display-name { + margin-right: 0; + margin-left: 5px; + } + + .account__avatar-wrapper { + margin-left: 12px; + margin-right: 0; + } +} From e18724363d84f887b797134d1a2ccc7ec26f77c0 Mon Sep 17 00:00:00 2001 From: Thibaut Girka Date: Mon, 22 Oct 2018 18:22:49 +0200 Subject: [PATCH 70/87] [Glitch] Fixes 8987 broken alignment at "Remote interaction dialog" Port d35801aaa2ad9d06345efa45cf524113469fdd02 to glitch-soc --- app/javascript/flavours/glitch/styles/forms.scss | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/javascript/flavours/glitch/styles/forms.scss b/app/javascript/flavours/glitch/styles/forms.scss index eb94f2273b..337941a080 100644 --- a/app/javascript/flavours/glitch/styles/forms.scss +++ b/app/javascript/flavours/glitch/styles/forms.scss @@ -562,12 +562,12 @@ code { .oauth-prompt, .follow-prompt { margin-bottom: 30px; - text-align: center; color: $darker-text-color; h2 { font-size: 16px; margin-bottom: 30px; + text-align: center; } strong { From ef9c11e050073dfa6a77f179f5931ab249b73e49 Mon Sep 17 00:00:00 2001 From: Thibaut Girka Date: Mon, 22 Oct 2018 18:24:18 +0200 Subject: [PATCH 71/87] [Glitch] RTL: fix domain append at signup form Port 65b3804a6ccd40d359616b6157682ff88f85462f to glitch-soc --- app/javascript/flavours/glitch/styles/rtl.scss | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/javascript/flavours/glitch/styles/rtl.scss b/app/javascript/flavours/glitch/styles/rtl.scss index 654d5e27c7..7ccec08b30 100644 --- a/app/javascript/flavours/glitch/styles/rtl.scss +++ b/app/javascript/flavours/glitch/styles/rtl.scss @@ -223,7 +223,7 @@ body.rtl { padding-right: 0; } - .simple_form .input-with-append .append { + .simple_form .label_input__append { right: auto; left: 0; From aa277ab5fbf078b80e8ab4497cbbf826f20a4b24 Mon Sep 17 00:00:00 2001 From: Thibaut Girka Date: Mon, 22 Oct 2018 18:25:21 +0200 Subject: [PATCH 72/87] [Glitch] RTL: fix user stats in about page Port 301cbcc9802ed85c519e67a01133968bc074c8af to glitch-soc --- app/javascript/flavours/glitch/styles/rtl.scss | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/app/javascript/flavours/glitch/styles/rtl.scss b/app/javascript/flavours/glitch/styles/rtl.scss index 7ccec08b30..a0c92b751a 100644 --- a/app/javascript/flavours/glitch/styles/rtl.scss +++ b/app/javascript/flavours/glitch/styles/rtl.scss @@ -249,6 +249,10 @@ body.rtl { left: auto; } + .landing-page__call-to-action .row__information-board { + direction: rtl; + } + .landing-page .header .hero .floats .float-1 { left: -120px; right: auto; From 076f0a0eb67f77a10326376bba70bcd66a4065f2 Mon Sep 17 00:00:00 2001 From: Thibaut Girka Date: Mon, 22 Oct 2018 18:33:35 +0200 Subject: [PATCH 73/87] [Glitch] Fix admin account avatar margin Port 065b39e7a460e088fd5afcd48dfc425d0006fee9 to glitch-soc --- app/javascript/flavours/glitch/styles/rtl.scss | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/app/javascript/flavours/glitch/styles/rtl.scss b/app/javascript/flavours/glitch/styles/rtl.scss index a0c92b751a..7ff8bdf6ef 100644 --- a/app/javascript/flavours/glitch/styles/rtl.scss +++ b/app/javascript/flavours/glitch/styles/rtl.scss @@ -321,11 +321,9 @@ body.rtl { .landing-page__information { .account__display-name { margin-right: 0; - margin-left: 5px; } .account__avatar-wrapper { - margin-left: 12px; - margin-right: 0; + margin-left: 0; } } From 9950db2e1cf1c06011b25bde2f2f3f9b98ce8941 Mon Sep 17 00:00:00 2001 From: Thibaut Girka Date: Mon, 22 Oct 2018 18:34:48 +0200 Subject: [PATCH 74/87] [Glitch] RTL: fix preferences layout Port 029943d59b222e96a2f7839390a5628888249bf6 to glitch-soc --- .../flavours/glitch/styles/rtl.scss | 29 +++++++++++++++++++ 1 file changed, 29 insertions(+) diff --git a/app/javascript/flavours/glitch/styles/rtl.scss b/app/javascript/flavours/glitch/styles/rtl.scss index 7ff8bdf6ef..c66fb5b6d8 100644 --- a/app/javascript/flavours/glitch/styles/rtl.scss +++ b/app/javascript/flavours/glitch/styles/rtl.scss @@ -200,6 +200,10 @@ body.rtl { right: -2.14285714em; } + .admin-wrapper { + direction: rtl; + } + .admin-wrapper .sidebar ul a i.fa, a.table-action-link i.fa { margin-right: 0; @@ -218,11 +222,32 @@ body.rtl { right: 0; } + .simple_form .input.radio_buttons .radio { + left: auto; + right: 0; + } + + .simple_form .input.radio_buttons .radio > label { + padding-right: 28px; + padding-left: 0; + } + .simple_form .input-with-append .input input { padding-left: 142px; padding-right: 0; } + .simple_form .input.boolean label.checkbox { + left: auto; + right: 0; + } + + .simple_form .input.boolean .label_input, + .simple_form .input.boolean .hint { + padding-left: 0; + padding-right: 28px; + } + .simple_form .label_input__append { right: auto; left: 0; @@ -234,6 +259,10 @@ body.rtl { } } + .simple_form select { + background: darken($ui-base-color, 10%) url("data:image/svg+xml;utf8,") no-repeat left 8px center / auto 16px; + } + .table th, .table td { text-align: right; From a1f512f18bd683d93d1a3dca6ad712fb978ec1f1 Mon Sep 17 00:00:00 2001 From: Thibaut Girka Date: Mon, 22 Oct 2018 18:37:17 +0200 Subject: [PATCH 75/87] [Glitch] Fix domain label position and color Port 25f9ead041a3087993059a1398f37dfa21a62610 to glitch-soc --- app/javascript/flavours/glitch/styles/forms.scss | 2 +- app/javascript/flavours/glitch/styles/rtl.scss | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/app/javascript/flavours/glitch/styles/forms.scss b/app/javascript/flavours/glitch/styles/forms.scss index 337941a080..8c4c934ea4 100644 --- a/app/javascript/flavours/glitch/styles/forms.scss +++ b/app/javascript/flavours/glitch/styles/forms.scss @@ -427,7 +427,7 @@ code { &__append { position: absolute; - right: 1px; + right: 3px; top: 1px; padding: 10px; padding-bottom: 9px; diff --git a/app/javascript/flavours/glitch/styles/rtl.scss b/app/javascript/flavours/glitch/styles/rtl.scss index c66fb5b6d8..b60bdd2567 100644 --- a/app/javascript/flavours/glitch/styles/rtl.scss +++ b/app/javascript/flavours/glitch/styles/rtl.scss @@ -250,12 +250,12 @@ body.rtl { .simple_form .label_input__append { right: auto; - left: 0; + left: 3px; &::after { right: auto; left: 0; - background-image: linear-gradient(to left, rgba($ui-base-color, 0), $ui-base-color); + background-image: linear-gradient(to left, rgba(darken($ui-base-color, 10%), 0), darken($ui-base-color, 10%)); } } From c14be538a6ee785ba633c2e2dab89f5eefe21a00 Mon Sep 17 00:00:00 2001 From: Thibaut Girka Date: Mon, 22 Oct 2018 18:38:11 +0200 Subject: [PATCH 76/87] [Glitch] RTL: fix column settings toggle label Port bf58461d365b5cee0d8a80a019a64e84c841f32f to glitch-soc --- app/javascript/flavours/glitch/styles/rtl.scss | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/javascript/flavours/glitch/styles/rtl.scss b/app/javascript/flavours/glitch/styles/rtl.scss index b60bdd2567..e0fc2a2911 100644 --- a/app/javascript/flavours/glitch/styles/rtl.scss +++ b/app/javascript/flavours/glitch/styles/rtl.scss @@ -73,7 +73,7 @@ body.rtl { float: left; } - .setting-toggle { + .setting-toggle__label { margin-left: 0; margin-right: 8px; } From c9b19e05e2365fc453a8f9eaafcfe6ba95623d5b Mon Sep 17 00:00:00 2001 From: Thibaut Girka Date: Mon, 22 Oct 2018 18:38:52 +0200 Subject: [PATCH 77/87] [Glitch] RTL: fix admin account avatar margin in about page Port 3a157210c87e6fe034f70d922cf7fc70fb533ad1 to glitch-soc --- app/javascript/flavours/glitch/styles/rtl.scss | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) diff --git a/app/javascript/flavours/glitch/styles/rtl.scss b/app/javascript/flavours/glitch/styles/rtl.scss index e0fc2a2911..fd17e9e725 100644 --- a/app/javascript/flavours/glitch/styles/rtl.scss +++ b/app/javascript/flavours/glitch/styles/rtl.scss @@ -345,14 +345,16 @@ body.rtl { margin-right: 20px; } } -} -.landing-page__information { - .account__display-name { - margin-right: 0; - } + .landing-page__information { + .account__display-name { + margin-right: 0; + margin-left: 5px; + } - .account__avatar-wrapper { - margin-left: 0; + .account__avatar-wrapper { + margin-left: 12px; + margin-right: 0; + } } } From 1bb23d0407d8fbe35729e3095a6ad6f1a909dc38 Mon Sep 17 00:00:00 2001 From: Thibaut Girka Date: Mon, 22 Oct 2018 18:39:37 +0200 Subject: [PATCH 78/87] [Glitch] RTL: fix cardbar margins and alignment Port c73864c1373330f2ef75006d639f90a1debcce6d to glitch-soc --- app/javascript/flavours/glitch/styles/rtl.scss | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/app/javascript/flavours/glitch/styles/rtl.scss b/app/javascript/flavours/glitch/styles/rtl.scss index fd17e9e725..3c775618e8 100644 --- a/app/javascript/flavours/glitch/styles/rtl.scss +++ b/app/javascript/flavours/glitch/styles/rtl.scss @@ -357,4 +357,10 @@ body.rtl { margin-right: 0; } } + + .card__bar .display-name { + margin-left: 0; + margin-right: 15px; + text-align: right; + } } From 323ae1403a7aef884d617decac36963afcc7fc70 Mon Sep 17 00:00:00 2001 From: Thibaut Girka Date: Mon, 22 Oct 2018 18:41:34 +0200 Subject: [PATCH 79/87] [Glitch] fix: initial state of PrivacyDropdown is should not be null Port bebe8ec887ba67c51353e09d7758819b117bf62d to glitch-soc --- .../flavours/glitch/features/composer/options/dropdown/index.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/javascript/flavours/glitch/features/composer/options/dropdown/index.js b/app/javascript/flavours/glitch/features/composer/options/dropdown/index.js index 8cfbac1bb6..7817cc9642 100644 --- a/app/javascript/flavours/glitch/features/composer/options/dropdown/index.js +++ b/app/javascript/flavours/glitch/features/composer/options/dropdown/index.js @@ -131,7 +131,7 @@ export default class ComposerOptionsDropdown extends React.PureComponent { this.state = { needsModalUpdate: false, open: false, - placement: null, + placement: 'bottom', }; } From 0c7f710be1208397f2d803270a503c1224f19831 Mon Sep 17 00:00:00 2001 From: Thibaut Girka Date: Mon, 22 Oct 2018 18:52:59 +0200 Subject: [PATCH 80/87] [Glitch] Surround mid-text display names with bdi tags Port 7861c5f108a8f8cb0450f3b1ef865b1177c706fc to glitch-soc --- app/javascript/flavours/glitch/components/display_name.js | 2 +- .../glitch/features/account_timeline/components/moved_note.js | 2 +- .../glitch/features/notifications/components/follow.js | 4 ++-- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/app/javascript/flavours/glitch/components/display_name.js b/app/javascript/flavours/glitch/components/display_name.js index 4c65aaefac..d6ac4907d6 100644 --- a/app/javascript/flavours/glitch/components/display_name.js +++ b/app/javascript/flavours/glitch/components/display_name.js @@ -15,7 +15,7 @@ export default function DisplayName ({ // The result. return account ? ( - + {inline ? ' ' : null} @{account.get('acct')} diff --git a/app/javascript/flavours/glitch/features/account_timeline/components/moved_note.js b/app/javascript/flavours/glitch/features/account_timeline/components/moved_note.js index 1c0e081cc4..280389bba9 100644 --- a/app/javascript/flavours/glitch/features/account_timeline/components/moved_note.js +++ b/app/javascript/flavours/glitch/features/account_timeline/components/moved_note.js @@ -34,7 +34,7 @@ export default class MovedNote extends ImmutablePureComponent {
- }} /> + }} />
diff --git a/app/javascript/flavours/glitch/features/notifications/components/follow.js b/app/javascript/flavours/glitch/features/notifications/components/follow.js index 54506f67c4..ea81d9ab49 100644 --- a/app/javascript/flavours/glitch/features/notifications/components/follow.js +++ b/app/javascript/flavours/glitch/features/notifications/components/follow.js @@ -63,13 +63,13 @@ export default class NotificationFollow extends ImmutablePureComponent { // Links to the display name. const displayName = account.get('display_name_html') || account.get('username'); const link = ( - + /> ); // Renders. From 81017eaea7ce08a951274a6a8dbc11dca38bc27e Mon Sep 17 00:00:00 2001 From: Eugen Rochko Date: Mon, 22 Oct 2018 23:23:00 +0200 Subject: [PATCH 81/87] Revert "RTL: remove blank character inside bdi (#9038)" (#9056) This reverts commit c7e9f9ff1ed1def7f14f6ca4ac2836005eeefa47. --- app/javascript/mastodon/components/display_name.js | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/app/javascript/mastodon/components/display_name.js b/app/javascript/mastodon/components/display_name.js index 31efab80a2..c2c40cb3f5 100644 --- a/app/javascript/mastodon/components/display_name.js +++ b/app/javascript/mastodon/components/display_name.js @@ -22,8 +22,7 @@ export default class DisplayName extends React.PureComponent { return ( - - {suffix} + {suffix} ); } From 969a10a5d1c0c8354acf133947460be7bee31d7f Mon Sep 17 00:00:00 2001 From: Eugen Rochko Date: Tue, 23 Oct 2018 00:08:25 +0200 Subject: [PATCH 82/87] Persist volumes by default in docker-compose (#9055) Too many databases were lost to this --- docker-compose.yml | 17 +++++++---------- 1 file changed, 7 insertions(+), 10 deletions(-) diff --git a/docker-compose.yml b/docker-compose.yml index 064d5a2604..d9f80a38a4 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -6,18 +6,16 @@ services: image: postgres:9.6-alpine networks: - internal_network -### Uncomment to enable DB persistence -# volumes: -# - ./postgres:/var/lib/postgresql/data + volumes: + - ./postgres:/var/lib/postgresql/data redis: restart: always image: redis:4.0-alpine networks: - internal_network -### Uncomment to enable REDIS persistence -# volumes: -# - ./redis:/data + volumes: + - ./redis:/data # es: # restart: always @@ -26,9 +24,8 @@ services: # - "ES_JAVA_OPTS=-Xms512m -Xmx512m" # networks: # - internal_network -#### Uncomment to enable ES persistence -## volumes: -## - ./elasticsearch:/usr/share/elasticsearch/data +# volumes: +# - ./elasticsearch:/usr/share/elasticsearch/data web: build: . @@ -68,7 +65,7 @@ services: image: tootsuite/mastodon restart: always env_file: .env.production - command: bundle exec sidekiq -q default -q push -q mailers -q pull + command: bundle exec sidekiq depends_on: - db - redis From ad510db3a19640267f94062756d558a45472af14 Mon Sep 17 00:00:00 2001 From: Eugen Rochko Date: Tue, 23 Oct 2018 00:08:39 +0200 Subject: [PATCH 83/87] Show suggested follows on search screen in mobile layout (#9010) Reminder: Suggestions were added in #7918 and are based on who you interact with who you do not follow. E.g. if you boost someone a lot from seeing other people's boosts of that person, it makes sense you might be interested in following the original source; or if you reply to someone a lot, maybe you'd want to follow them Each suggestion can be dismissed --- .../mastodon/actions/suggestions.js | 52 +++++++++++++++++++ app/javascript/mastodon/components/account.js | 13 ++++- .../compose/components/search_results.js | 43 +++++++++++++-- .../containers/search_results_container.js | 9 +++- app/javascript/mastodon/reducers/index.js | 2 + .../mastodon/reducers/suggestions.js | 30 +++++++++++ 6 files changed, 143 insertions(+), 6 deletions(-) create mode 100644 app/javascript/mastodon/actions/suggestions.js create mode 100644 app/javascript/mastodon/reducers/suggestions.js diff --git a/app/javascript/mastodon/actions/suggestions.js b/app/javascript/mastodon/actions/suggestions.js new file mode 100644 index 0000000000..b15bd916ba --- /dev/null +++ b/app/javascript/mastodon/actions/suggestions.js @@ -0,0 +1,52 @@ +import api from '../api'; +import { importFetchedAccounts } from './importer'; + +export const SUGGESTIONS_FETCH_REQUEST = 'SUGGESTIONS_FETCH_REQUEST'; +export const SUGGESTIONS_FETCH_SUCCESS = 'SUGGESTIONS_FETCH_SUCCESS'; +export const SUGGESTIONS_FETCH_FAIL = 'SUGGESTIONS_FETCH_FAIL'; + +export const SUGGESTIONS_DISMISS = 'SUGGESTIONS_DISMISS'; + +export function fetchSuggestions() { + return (dispatch, getState) => { + dispatch(fetchSuggestionsRequest()); + + api(getState).get('/api/v1/suggestions').then(response => { + dispatch(importFetchedAccounts(response.data)); + dispatch(fetchSuggestionsSuccess(response.data)); + }).catch(error => dispatch(fetchSuggestionsFail(error))); + }; +}; + +export function fetchSuggestionsRequest() { + return { + type: SUGGESTIONS_FETCH_REQUEST, + skipLoading: true, + }; +}; + +export function fetchSuggestionsSuccess(accounts) { + return { + type: SUGGESTIONS_FETCH_SUCCESS, + accounts, + skipLoading: true, + }; +}; + +export function fetchSuggestionsFail(error) { + return { + type: SUGGESTIONS_FETCH_FAIL, + error, + skipLoading: true, + skipAlert: true, + }; +}; + +export const dismissSuggestion = accountId => (dispatch, getState) => { + dispatch({ + type: SUGGESTIONS_DISMISS, + id: accountId, + }); + + api(getState).delete(`/api/v1/suggestions/${accountId}`); +}; diff --git a/app/javascript/mastodon/components/account.js b/app/javascript/mastodon/components/account.js index c021e32676..2bcea8b675 100644 --- a/app/javascript/mastodon/components/account.js +++ b/app/javascript/mastodon/components/account.js @@ -30,6 +30,9 @@ class Account extends ImmutablePureComponent { onMuteNotifications: PropTypes.func.isRequired, intl: PropTypes.object.isRequired, hidden: PropTypes.bool, + actionIcon: PropTypes.string, + actionTitle: PropTypes.string, + onActionClick: PropTypes.func, }; handleFollow = () => { @@ -52,8 +55,12 @@ class Account extends ImmutablePureComponent { this.props.onMuteNotifications(this.props.account, false); } + handleAction = () => { + this.props.onActionClick(this.props.account); + } + render () { - const { account, intl, hidden } = this.props; + const { account, intl, hidden, onActionClick, actionIcon, actionTitle } = this.props; if (!account) { return
; @@ -70,7 +77,9 @@ class Account extends ImmutablePureComponent { let buttons; - if (account.get('id') !== me && account.get('relationship', null) !== null) { + if (onActionClick && actionIcon) { + buttons = ; + } else if (account.get('id') !== me && account.get('relationship', null) !== null) { const following = account.getIn(['relationship', 'following']); const requested = account.getIn(['relationship', 'requested']); const blocking = account.getIn(['relationship', 'blocking']); diff --git a/app/javascript/mastodon/features/compose/components/search_results.js b/app/javascript/mastodon/features/compose/components/search_results.js index c351b84bb3..f0ddf6d714 100644 --- a/app/javascript/mastodon/features/compose/components/search_results.js +++ b/app/javascript/mastodon/features/compose/components/search_results.js @@ -1,19 +1,56 @@ import React from 'react'; +import PropTypes from 'prop-types'; import ImmutablePropTypes from 'react-immutable-proptypes'; -import { FormattedMessage } from 'react-intl'; +import { FormattedMessage, defineMessages, injectIntl } from 'react-intl'; import AccountContainer from '../../../containers/account_container'; import StatusContainer from '../../../containers/status_container'; import ImmutablePureComponent from 'react-immutable-pure-component'; import Hashtag from '../../../components/hashtag'; -export default class SearchResults extends ImmutablePureComponent { +const messages = defineMessages({ + dismissSuggestion: { id: 'suggestions.dismiss', defaultMessage: 'Dismiss suggestion' }, +}); + +export default @injectIntl +class SearchResults extends ImmutablePureComponent { static propTypes = { results: ImmutablePropTypes.map.isRequired, + suggestions: ImmutablePropTypes.list.isRequired, + fetchSuggestions: PropTypes.func.isRequired, + dismissSuggestion: PropTypes.func.isRequired, + intl: PropTypes.object.isRequired, }; + componentDidMount () { + this.props.fetchSuggestions(); + } + render () { - const { results } = this.props; + const { intl, results, suggestions, dismissSuggestion } = this.props; + + if (results.isEmpty() && !suggestions.isEmpty()) { + return ( +
+
+
+ + +
+ + {suggestions && suggestions.map(accountId => ( + + ))} +
+
+ ); + } let accounts, statuses, hashtags; let count = 0; diff --git a/app/javascript/mastodon/features/compose/containers/search_results_container.js b/app/javascript/mastodon/features/compose/containers/search_results_container.js index 16d95d417e..f9637861ae 100644 --- a/app/javascript/mastodon/features/compose/containers/search_results_container.js +++ b/app/javascript/mastodon/features/compose/containers/search_results_container.js @@ -1,8 +1,15 @@ import { connect } from 'react-redux'; import SearchResults from '../components/search_results'; +import { fetchSuggestions, dismissSuggestion } from '../../../actions/suggestions'; const mapStateToProps = state => ({ results: state.getIn(['search', 'results']), + suggestions: state.getIn(['suggestions', 'items']), }); -export default connect(mapStateToProps)(SearchResults); +const mapDispatchToProps = dispatch => ({ + fetchSuggestions: () => dispatch(fetchSuggestions()), + dismissSuggestion: account => dispatch(dismissSuggestion(account.get('id'))), +}); + +export default connect(mapStateToProps, mapDispatchToProps)(SearchResults); diff --git a/app/javascript/mastodon/reducers/index.js b/app/javascript/mastodon/reducers/index.js index d3b98d4f6f..e98566e260 100644 --- a/app/javascript/mastodon/reducers/index.js +++ b/app/javascript/mastodon/reducers/index.js @@ -28,6 +28,7 @@ import lists from './lists'; import listEditor from './list_editor'; import filters from './filters'; import conversations from './conversations'; +import suggestions from './suggestions'; const reducers = { dropdown_menu, @@ -59,6 +60,7 @@ const reducers = { listEditor, filters, conversations, + suggestions, }; export default combineReducers(reducers); diff --git a/app/javascript/mastodon/reducers/suggestions.js b/app/javascript/mastodon/reducers/suggestions.js new file mode 100644 index 0000000000..9f4b89d586 --- /dev/null +++ b/app/javascript/mastodon/reducers/suggestions.js @@ -0,0 +1,30 @@ +import { + SUGGESTIONS_FETCH_REQUEST, + SUGGESTIONS_FETCH_SUCCESS, + SUGGESTIONS_FETCH_FAIL, + SUGGESTIONS_DISMISS, +} from '../actions/suggestions'; +import { Map as ImmutableMap, List as ImmutableList, fromJS } from 'immutable'; + +const initialState = ImmutableMap({ + items: ImmutableList(), + isLoading: false, +}); + +export default function suggestionsReducer(state = initialState, action) { + switch(action.type) { + case SUGGESTIONS_FETCH_REQUEST: + return state.set('isLoading', true); + case SUGGESTIONS_FETCH_SUCCESS: + return state.withMutations(map => { + map.set('items', fromJS(action.accounts.map(x => x.id))); + map.set('isLoading', false); + }); + case SUGGESTIONS_FETCH_FAIL: + return state.set('isLoading', false); + case SUGGESTIONS_DISMISS: + return state.update('items', list => list.filterNot(id => id === action.id)); + default: + return state; + } +}; From 39abec4d25db02e7d1e6a2d137d96d07dffac02c Mon Sep 17 00:00:00 2001 From: Eugen Rochko Date: Tue, 23 Oct 2018 00:43:18 +0200 Subject: [PATCH 84/87] Fix public timelines not instantly updating on compose (#9050) Fix #9034 --- app/javascript/mastodon/actions/compose.js | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/app/javascript/mastodon/actions/compose.js b/app/javascript/mastodon/actions/compose.js index f726712283..fac8d32a12 100644 --- a/app/javascript/mastodon/actions/compose.js +++ b/app/javascript/mastodon/actions/compose.js @@ -146,7 +146,9 @@ export function submitCompose(routerHistory) { routerHistory.push('/timelines/direct'); } else if (response.data.visibility !== 'direct') { insertIfOnline('home'); - } else if (response.data.in_reply_to_id === null && response.data.visibility === 'public') { + } + + if (response.data.in_reply_to_id === null && response.data.visibility === 'public') { insertIfOnline('community'); insertIfOnline('public'); } From 51677ff070e8738c190e712e45229d0e2190472f Mon Sep 17 00:00:00 2001 From: ashleyhull-versent Date: Tue, 23 Oct 2018 14:21:28 +1100 Subject: [PATCH 85/87] Update Dockerfile (#9026) --- Dockerfile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Dockerfile b/Dockerfile index 6a1e8776cc..9c53b4145e 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,5 +1,5 @@ FROM node:8.12.0-alpine as node -FROM ruby:2.4.4-alpine3.7 +FROM ruby:2.4.5-alpine3.8 LABEL maintainer="https://github.com/tootsuite/mastodon" \ description="Your self-hosted, globally interconnected microblogging community" From 65867b6e6170ab6bc4db6d94b46cd3ddd6b82113 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" Date: Tue, 23 Oct 2018 08:17:26 +0200 Subject: [PATCH 86/87] Bump parallel_tests from 2.23.0 to 2.24.0 (#9064) Bumps [parallel_tests](https://github.com/grosser/parallel_tests) from 2.23.0 to 2.24.0. - [Release notes](https://github.com/grosser/parallel_tests/releases) - [Commits](https://github.com/grosser/parallel_tests/compare/v2.23.0...v2.24.0) Signed-off-by: dependabot[bot] --- Gemfile | 2 +- Gemfile.lock | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/Gemfile b/Gemfile index 6a0d331981..ca38f033a1 100644 --- a/Gemfile +++ b/Gemfile @@ -114,7 +114,7 @@ group :test do gem 'rspec-sidekiq', '~> 3.0' gem 'simplecov', '~> 0.16', require: false gem 'webmock', '~> 3.4' - gem 'parallel_tests', '~> 2.23' + gem 'parallel_tests', '~> 2.24' end group :development do diff --git a/Gemfile.lock b/Gemfile.lock index 373ebbaf75..c43f3673ff 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -385,7 +385,7 @@ GEM av (~> 0.9.0) paperclip (>= 2.5.2) parallel (1.12.1) - parallel_tests (2.23.0) + parallel_tests (2.24.0) parallel parser (2.5.1.2) ast (~> 2.4.0) @@ -714,7 +714,7 @@ DEPENDENCIES ox (~> 2.10) paperclip (~> 6.0) paperclip-av-transcoder (~> 0.6) - parallel_tests (~> 2.23) + parallel_tests (~> 2.24) pg (~> 1.1) pghero (~> 2.2) pkg-config (~> 1.3) From ed8d06212f439b9fe2f170a6f43d6be6d586ff80 Mon Sep 17 00:00:00 2001 From: Thibaut Girka Date: Tue, 23 Oct 2018 20:03:35 +0200 Subject: [PATCH 87/87] Keep back own DMs in Home timeline Follow-up to e45a6edd6574c86409333cc64f9fb87e1b0a196e, fixes inconsistencies in glitch-soc behavior. --- app/services/fan_out_on_write_service.rb | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/app/services/fan_out_on_write_service.rb b/app/services/fan_out_on_write_service.rb index 0e9465d483..63cab84035 100644 --- a/app/services/fan_out_on_write_service.rb +++ b/app/services/fan_out_on_write_service.rb @@ -6,6 +6,8 @@ class FanOutOnWriteService < BaseService def call(status) raise Mastodon::RaceConditionError if status.visibility.nil? + deliver_to_self(status) if status.account.local? + render_anonymous_payload(status) if status.direct_visibility? @@ -15,7 +17,6 @@ class FanOutOnWriteService < BaseService elsif status.limited_visibility? deliver_to_mentioned_followers(status) else - deliver_to_self(status) if status.account.local? deliver_to_followers(status) deliver_to_lists(status) end