about summary refs log tree commit diff
diff options
context:
space:
mode:
authorDavid Yip <yipdw@member.fsf.org>2018-06-08 00:33:09 -0500
committerGitHub <noreply@github.com>2018-06-08 00:33:09 -0500
commita9515f3186b49df63436b98d382ee6a6b755387d (patch)
treed771e65a58d3c69ba1c08c3fc145f24b5b806274
parentf8d50a40701f344ea7c2a0e5475bbcbc727ef930 (diff)
parent8142bd2553e7819722fdfc401e06cb10eeddd230 (diff)
Merge pull request #535 from glitch-soc/merge-upstream
Merge upstream
-rw-r--r--.codeclimate.yml1
-rw-r--r--.rubocop.yml5
-rw-r--r--app/javascript/mastodon/actions/statuses.js17
-rw-r--r--app/javascript/mastodon/components/hashtag.js11
-rw-r--r--app/javascript/mastodon/components/status_action_bar.js6
-rw-r--r--app/javascript/mastodon/containers/status_container.js12
-rw-r--r--app/javascript/mastodon/features/account/components/action_bar.js9
-rw-r--r--app/javascript/mastodon/features/status/components/action_bar.js6
-rw-r--r--app/javascript/mastodon/features/status/index.js19
-rw-r--r--app/javascript/mastodon/features/ui/components/report_modal.js7
-rw-r--r--app/javascript/mastodon/locales/ar.json5
-rw-r--r--app/javascript/mastodon/locales/bg.json5
-rw-r--r--app/javascript/mastodon/locales/ca.json5
-rw-r--r--app/javascript/mastodon/locales/co.json5
-rw-r--r--app/javascript/mastodon/locales/de.json5
-rw-r--r--app/javascript/mastodon/locales/defaultMessages.json58
-rw-r--r--app/javascript/mastodon/locales/el.json5
-rw-r--r--app/javascript/mastodon/locales/en.json5
-rw-r--r--app/javascript/mastodon/locales/eo.json5
-rw-r--r--app/javascript/mastodon/locales/es.json5
-rw-r--r--app/javascript/mastodon/locales/eu.json15
-rw-r--r--app/javascript/mastodon/locales/fa.json5
-rw-r--r--app/javascript/mastodon/locales/fi.json5
-rw-r--r--app/javascript/mastodon/locales/fr.json5
-rw-r--r--app/javascript/mastodon/locales/gl.json5
-rw-r--r--app/javascript/mastodon/locales/he.json5
-rw-r--r--app/javascript/mastodon/locales/hr.json5
-rw-r--r--app/javascript/mastodon/locales/hu.json5
-rw-r--r--app/javascript/mastodon/locales/hy.json5
-rw-r--r--app/javascript/mastodon/locales/id.json5
-rw-r--r--app/javascript/mastodon/locales/io.json5
-rw-r--r--app/javascript/mastodon/locales/it.json5
-rw-r--r--app/javascript/mastodon/locales/ja.json5
-rw-r--r--app/javascript/mastodon/locales/ko.json5
-rw-r--r--app/javascript/mastodon/locales/nl.json5
-rw-r--r--app/javascript/mastodon/locales/no.json5
-rw-r--r--app/javascript/mastodon/locales/oc.json5
-rw-r--r--app/javascript/mastodon/locales/pl.json5
-rw-r--r--app/javascript/mastodon/locales/pt-BR.json5
-rw-r--r--app/javascript/mastodon/locales/pt.json5
-rw-r--r--app/javascript/mastodon/locales/ru.json5
-rw-r--r--app/javascript/mastodon/locales/sk.json5
-rw-r--r--app/javascript/mastodon/locales/sl.json5
-rw-r--r--app/javascript/mastodon/locales/sr-Latn.json5
-rw-r--r--app/javascript/mastodon/locales/sr.json5
-rw-r--r--app/javascript/mastodon/locales/sv.json5
-rw-r--r--app/javascript/mastodon/locales/te.json5
-rw-r--r--app/javascript/mastodon/locales/th.json5
-rw-r--r--app/javascript/mastodon/locales/tr.json5
-rw-r--r--app/javascript/mastodon/locales/uk.json5
-rw-r--r--app/javascript/mastodon/locales/zh-CN.json5
-rw-r--r--app/javascript/mastodon/locales/zh-HK.json5
-rw-r--r--app/javascript/mastodon/locales/zh-TW.json5
-rw-r--r--app/javascript/mastodon/reducers/compose.js32
-rw-r--r--app/javascript/mastodon/utils/html.js3
-rw-r--r--app/javascript/mastodon/utils/numbers.js10
-rw-r--r--app/javascript/styles/mastodon-light/diff.scss27
-rw-r--r--app/javascript/styles/mastodon/tables.scss1
-rw-r--r--app/models/concerns/remotable.rb39
-rw-r--r--app/models/concerns/status_threading_concern.rb10
-rw-r--r--app/models/status.rb13
-rw-r--r--app/services/fetch_link_card_service.rb2
-rw-r--r--app/services/post_status_service.rb2
-rw-r--r--app/views/admin/accounts/_account.html.haml2
-rw-r--r--config/locales/doorkeeper.eu.yml2
-rw-r--r--config/locales/en.yml2
-rw-r--r--config/locales/eu.yml14
-rw-r--r--config/locales/pl.yml10
-rw-r--r--config/locales/simple_form.eu.yml10
-rw-r--r--config/locales/sk.yml1
-rw-r--r--lib/mastodon/version.rb2
-rw-r--r--lib/tasks/mastodon.rake2
-rw-r--r--spec/controllers/api/web/embeds_controller_spec.rb52
-rw-r--r--spec/controllers/settings/sessions_controller_spec.rb30
-rw-r--r--spec/lib/status_finder_spec.rb7
75 files changed, 436 insertions, 208 deletions
diff --git a/.codeclimate.yml b/.codeclimate.yml
index 21e6b33bf..58f6b3de4 100644
--- a/.codeclimate.yml
+++ b/.codeclimate.yml
@@ -30,6 +30,7 @@ plugins:
     channel: eslint-4
   rubocop:
     enabled: true
+    channel: rubocop-0-54
   scss-lint:
     enabled: true
 exclude_patterns:
diff --git a/.rubocop.yml b/.rubocop.yml
index a36aa5cae..6faeaca6f 100644
--- a/.rubocop.yml
+++ b/.rubocop.yml
@@ -107,5 +107,8 @@ Style/RegexpLiteral:
 Style/SymbolArray:
   Enabled: false
 
-Style/TrailingCommaInLiteral:
+Style/TrailingCommaInArrayLiteral:
+  EnforcedStyleForMultiline: 'comma'
+
+Style/TrailingCommaInHashLiteral:
   EnforcedStyleForMultiline: 'comma'
diff --git a/app/javascript/mastodon/actions/statuses.js b/app/javascript/mastodon/actions/statuses.js
index 849cb4f5a..3e1e5f270 100644
--- a/app/javascript/mastodon/actions/statuses.js
+++ b/app/javascript/mastodon/actions/statuses.js
@@ -29,6 +29,8 @@ export const STATUS_UNMUTE_FAIL    = 'STATUS_UNMUTE_FAIL';
 export const STATUS_REVEAL = 'STATUS_REVEAL';
 export const STATUS_HIDE   = 'STATUS_HIDE';
 
+export const REDRAFT = 'REDRAFT';
+
 export function fetchStatusRequest(id, skipLoading) {
   return {
     type: STATUS_FETCH_REQUEST,
@@ -131,14 +133,27 @@ export function fetchStatusFail(id, error, skipLoading) {
   };
 };
 
-export function deleteStatus(id) {
+export function redraft(status) {
+  return {
+    type: REDRAFT,
+    status,
+  };
+};
+
+export function deleteStatus(id, withRedraft = false) {
   return (dispatch, getState) => {
+    const status = getState().getIn(['statuses', id]);
+
     dispatch(deleteStatusRequest(id));
 
     api(getState).delete(`/api/v1/statuses/${id}`).then(() => {
       evictStatus(id);
       dispatch(deleteStatusSuccess(id));
       dispatch(deleteFromTimelines(id));
+
+      if (withRedraft) {
+        dispatch(redraft(status));
+      }
     }).catch(error => {
       dispatch(deleteStatusFail(id, error));
     });
diff --git a/app/javascript/mastodon/components/hashtag.js b/app/javascript/mastodon/components/hashtag.js
index cc37a91e2..a407df31e 100644
--- a/app/javascript/mastodon/components/hashtag.js
+++ b/app/javascript/mastodon/components/hashtag.js
@@ -1,16 +1,9 @@
 import React from 'react';
 import { Sparklines, SparklinesCurve } from 'react-sparklines';
 import { Link } from 'react-router-dom';
-import { FormattedMessage, FormattedNumber } from 'react-intl';
+import { FormattedMessage } from 'react-intl';
 import ImmutablePropTypes from 'react-immutable-proptypes';
-
-const shortNumberFormat = number => {
-  if (number < 1000) {
-    return <FormattedNumber value={number} />;
-  } else {
-    return <React.Fragment><FormattedNumber value={number / 1000} maximumFractionDigits={1} />K</React.Fragment>;
-  }
-};
+import { shortNumberFormat } from '../utils/numbers';
 
 const Hashtag = ({ hashtag }) => (
   <div className='trends__item'>
diff --git a/app/javascript/mastodon/components/status_action_bar.js b/app/javascript/mastodon/components/status_action_bar.js
index d605dbc8a..0ae21e3f0 100644
--- a/app/javascript/mastodon/components/status_action_bar.js
+++ b/app/javascript/mastodon/components/status_action_bar.js
@@ -9,6 +9,7 @@ import { me } from '../initial_state';
 
 const messages = defineMessages({
   delete: { id: 'status.delete', defaultMessage: 'Delete' },
+  redraft: { id: 'status.redraft', defaultMessage: 'Delete & re-draft' },
   direct: { id: 'status.direct', defaultMessage: 'Direct message @{name}' },
   mention: { id: 'status.mention', defaultMessage: 'Mention @{name}' },
   mute: { id: 'account.mute', defaultMessage: 'Mute @{name}' },
@@ -88,6 +89,10 @@ export default class StatusActionBar extends ImmutablePureComponent {
     this.props.onDelete(this.props.status);
   }
 
+  handleRedraftClick = () => {
+    this.props.onDelete(this.props.status, true);
+  }
+
   handlePinClick = () => {
     this.props.onPin(this.props.status);
   }
@@ -159,6 +164,7 @@ export default class StatusActionBar extends ImmutablePureComponent {
       }
 
       menu.push({ text: intl.formatMessage(messages.delete), action: this.handleDeleteClick });
+      menu.push({ text: intl.formatMessage(messages.redraft), action: this.handleRedraftClick });
     } else {
       menu.push({ text: intl.formatMessage(messages.mention, { name: status.getIn(['account', 'username']) }), action: this.handleMentionClick });
       menu.push({ text: intl.formatMessage(messages.direct, { name: status.getIn(['account', 'username']) }), action: this.handleDirectClick });
diff --git a/app/javascript/mastodon/containers/status_container.js b/app/javascript/mastodon/containers/status_container.js
index f22509edf..3e7b5215b 100644
--- a/app/javascript/mastodon/containers/status_container.js
+++ b/app/javascript/mastodon/containers/status_container.js
@@ -33,6 +33,8 @@ import { showAlertForError } from '../actions/alerts';
 const messages = defineMessages({
   deleteConfirm: { id: 'confirmations.delete.confirm', defaultMessage: 'Delete' },
   deleteMessage: { id: 'confirmations.delete.message', defaultMessage: 'Are you sure you want to delete this status?' },
+  redraftConfirm: { id: 'confirmations.redraft.confirm', defaultMessage: 'Delete & redraft' },
+  redraftMessage: { id: 'confirmations.redraft.message', defaultMessage: 'Are you sure you want to delete this status and re-draft it? You will lose all replies, boosts and favourites to it.' },
   blockConfirm: { id: 'confirmations.block.confirm', defaultMessage: 'Block' },
 });
 
@@ -91,14 +93,14 @@ const mapDispatchToProps = (dispatch, { intl }) => ({
     }));
   },
 
-  onDelete (status) {
+  onDelete (status, withRedraft = false) {
     if (!deleteModal) {
-      dispatch(deleteStatus(status.get('id')));
+      dispatch(deleteStatus(status.get('id'), withRedraft));
     } else {
       dispatch(openModal('CONFIRM', {
-        message: intl.formatMessage(messages.deleteMessage),
-        confirm: intl.formatMessage(messages.deleteConfirm),
-        onConfirm: () => dispatch(deleteStatus(status.get('id'))),
+        message: intl.formatMessage(withRedraft ? messages.redraftMessage : messages.deleteMessage),
+        confirm: intl.formatMessage(withRedraft ? messages.redraftConfirm : messages.deleteConfirm),
+        onConfirm: () => dispatch(deleteStatus(status.get('id'), withRedraft)),
       }));
     }
   },
diff --git a/app/javascript/mastodon/features/account/components/action_bar.js b/app/javascript/mastodon/features/account/components/action_bar.js
index 3a1f92811..2d0f72be2 100644
--- a/app/javascript/mastodon/features/account/components/action_bar.js
+++ b/app/javascript/mastodon/features/account/components/action_bar.js
@@ -3,8 +3,9 @@ import ImmutablePropTypes from 'react-immutable-proptypes';
 import PropTypes from 'prop-types';
 import DropdownMenuContainer from '../../../containers/dropdown_menu_container';
 import { Link } from 'react-router-dom';
-import { defineMessages, injectIntl, FormattedMessage, FormattedNumber } from 'react-intl';
+import { defineMessages, injectIntl, FormattedMessage } from 'react-intl';
 import { me } from '../../../initial_state';
+import { shortNumberFormat } from '../../../utils/numbers';
 
 const messages = defineMessages({
   mention: { id: 'account.mention', defaultMessage: 'Mention @{name}' },
@@ -146,17 +147,17 @@ export default class ActionBar extends React.PureComponent {
           <div className='account__action-bar-links'>
             <Link className='account__action-bar__tab' to={`/accounts/${account.get('id')}`}>
               <span><FormattedMessage id='account.posts' defaultMessage='Toots' /></span>
-              <strong><FormattedNumber value={account.get('statuses_count')} /></strong>
+              <strong>{shortNumberFormat(account.get('statuses_count'))}</strong>
             </Link>
 
             <Link className='account__action-bar__tab' to={`/accounts/${account.get('id')}/following`}>
               <span><FormattedMessage id='account.follows' defaultMessage='Follows' /></span>
-              <strong><FormattedNumber value={account.get('following_count')} /></strong>
+              <strong>{shortNumberFormat(account.get('following_count'))}</strong>
             </Link>
 
             <Link className='account__action-bar__tab' to={`/accounts/${account.get('id')}/followers`}>
               <span><FormattedMessage id='account.followers' defaultMessage='Followers' /></span>
-              <strong><FormattedNumber value={account.get('followers_count')} /></strong>
+              <strong>{shortNumberFormat(account.get('followers_count'))}</strong>
             </Link>
           </div>
         </div>
diff --git a/app/javascript/mastodon/features/status/components/action_bar.js b/app/javascript/mastodon/features/status/components/action_bar.js
index 9162e1326..541499668 100644
--- a/app/javascript/mastodon/features/status/components/action_bar.js
+++ b/app/javascript/mastodon/features/status/components/action_bar.js
@@ -8,6 +8,7 @@ import { me } from '../../../initial_state';
 
 const messages = defineMessages({
   delete: { id: 'status.delete', defaultMessage: 'Delete' },
+  redraft: { id: 'status.redraft', defaultMessage: 'Delete & re-draft' },
   direct: { id: 'status.direct', defaultMessage: 'Direct message @{name}' },
   mention: { id: 'status.mention', defaultMessage: 'Mention @{name}' },
   reply: { id: 'status.reply', defaultMessage: 'Reply' },
@@ -67,6 +68,10 @@ export default class ActionBar extends React.PureComponent {
     this.props.onDelete(this.props.status);
   }
 
+  handleRedraftClick = () => {
+    this.props.onDelete(this.props.status, true);
+  }
+
   handleDirectClick = () => {
     this.props.onDirect(this.props.status.get('account'), this.context.router.history);
   }
@@ -132,6 +137,7 @@ export default class ActionBar extends React.PureComponent {
       menu.push({ text: intl.formatMessage(mutingConversation ? messages.unmuteConversation : messages.muteConversation), action: this.handleConversationMuteClick });
       menu.push(null);
       menu.push({ text: intl.formatMessage(messages.delete), action: this.handleDeleteClick });
+      menu.push({ text: intl.formatMessage(messages.redraft), action: this.handleRedraftClick });
     } else {
       menu.push({ text: intl.formatMessage(messages.mention, { name: status.getIn(['account', 'username']) }), action: this.handleMentionClick });
       menu.push({ text: intl.formatMessage(messages.direct, { name: status.getIn(['account', 'username']) }), action: this.handleDirectClick });
diff --git a/app/javascript/mastodon/features/status/index.js b/app/javascript/mastodon/features/status/index.js
index 505a88a3f..ca792043f 100644
--- a/app/javascript/mastodon/features/status/index.js
+++ b/app/javascript/mastodon/features/status/index.js
@@ -47,6 +47,8 @@ import { attachFullscreenListener, detachFullscreenListener, isFullscreen } from
 const messages = defineMessages({
   deleteConfirm: { id: 'confirmations.delete.confirm', defaultMessage: 'Delete' },
   deleteMessage: { id: 'confirmations.delete.message', defaultMessage: 'Are you sure you want to delete this status?' },
+  redraftConfirm: { id: 'confirmations.redraft.confirm', defaultMessage: 'Delete & redraft' },
+  redraftMessage: { id: 'confirmations.redraft.message', defaultMessage: 'Are you sure you want to delete this status and re-draft it? You will lose all replies, boosts and favourites to it.' },
   blockConfirm: { id: 'confirmations.block.confirm', defaultMessage: 'Block' },
   revealAll: { id: 'status.show_more_all', defaultMessage: 'Show more for all' },
   hideAll: { id: 'status.show_less_all', defaultMessage: 'Show less for all' },
@@ -77,9 +79,12 @@ const makeMapStateToProps = () => {
           let id        = ids.shift();
           const replies = state.getIn(['contexts', 'replies', id]);
 
+          if (status.get('id') !== id) {
+            mutable.push(id);
+          }
+
           if (replies) {
-            replies.forEach(reply => {
-              mutable.push(reply);
+            replies.reverse().forEach(reply => {
               ids.unshift(reply);
             });
           }
@@ -169,16 +174,16 @@ export default class Status extends ImmutablePureComponent {
     }
   }
 
-  handleDeleteClick = (status) => {
+  handleDeleteClick = (status, withRedraft = false) => {
     const { dispatch, intl } = this.props;
 
     if (!deleteModal) {
-      dispatch(deleteStatus(status.get('id')));
+      dispatch(deleteStatus(status.get('id'), withRedraft));
     } else {
       dispatch(openModal('CONFIRM', {
-        message: intl.formatMessage(messages.deleteMessage),
-        confirm: intl.formatMessage(messages.deleteConfirm),
-        onConfirm: () => dispatch(deleteStatus(status.get('id'))),
+        message: intl.formatMessage(withRedraft ? messages.redraftMessage : messages.deleteMessage),
+        confirm: intl.formatMessage(withRedraft ? messages.redraftConfirm : messages.deleteConfirm),
+        onConfirm: () => dispatch(deleteStatus(status.get('id'), withRedraft)),
       }));
     }
   }
diff --git a/app/javascript/mastodon/features/ui/components/report_modal.js b/app/javascript/mastodon/features/ui/components/report_modal.js
index 8616f0315..90f001319 100644
--- a/app/javascript/mastodon/features/ui/components/report_modal.js
+++ b/app/javascript/mastodon/features/ui/components/report_modal.js
@@ -63,6 +63,12 @@ export default class ReportModal extends ImmutablePureComponent {
     this.props.dispatch(submitReport());
   }
 
+  handleKeyDown = e => {
+    if (e.keyCode === 13 && (e.ctrlKey || e.metaKey)) {
+      this.handleSubmit();
+    }
+  }
+
   componentDidMount () {
     this.props.dispatch(expandAccountTimeline(this.props.account.get('id'), { withReplies: true }));
   }
@@ -98,6 +104,7 @@ export default class ReportModal extends ImmutablePureComponent {
               placeholder={intl.formatMessage(messages.placeholder)}
               value={comment}
               onChange={this.handleCommentChange}
+              onKeyDown={this.handleKeyDown}
               disabled={isSubmitting}
             />
 
diff --git a/app/javascript/mastodon/locales/ar.json b/app/javascript/mastodon/locales/ar.json
index c007cd26f..60d4acc39 100644
--- a/app/javascript/mastodon/locales/ar.json
+++ b/app/javascript/mastodon/locales/ar.json
@@ -83,6 +83,8 @@
   "confirmations.domain_block.message": "متأكد من أنك تود حظر إسم النطاق {domain} بالكامل ؟ في غالب الأحيان يُستَحسَن كتم أو حظر بعض الحسابات بدلا من حظر نطاق بالكامل.",
   "confirmations.mute.confirm": "أكتم",
   "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.unfollow.confirm": "إلغاء المتابعة",
   "confirmations.unfollow.message": "متأكد من أنك تريد إلغاء متابعة {name} ؟",
   "embed.instructions": "يمكنكم إدماج هذه الحالة على موقعكم الإلكتروني عن طريق نسخ الشفرة أدناه.",
@@ -264,6 +266,7 @@
   "status.reblog": "رَقِّي",
   "status.reblog_private": "القيام بالترقية إلى الجمهور الأصلي",
   "status.reblogged_by": "{name} رقى",
+  "status.redraft": "Delete & re-draft",
   "status.reply": "ردّ",
   "status.replyAll": "رُد على الخيط",
   "status.report": "إبلِغ عن @{name}",
@@ -284,8 +287,6 @@
   "timeline.media": "Media",
   "timeline.posts": "Toots",
   "trends.count_by_accounts": "{count} {rawCount, plural, one {person} other {people}} talking",
-  "trends.header": "Trending now",
-  "trends.refresh": "Refresh",
   "ui.beforeunload": "سوف تفقد مسودتك إن تركت ماستدون.",
   "upload_area.title": "إسحب ثم أفلت للرفع",
   "upload_button.label": "إضافة وسائط",
diff --git a/app/javascript/mastodon/locales/bg.json b/app/javascript/mastodon/locales/bg.json
index 80c72ac98..ebee044b8 100644
--- a/app/javascript/mastodon/locales/bg.json
+++ b/app/javascript/mastodon/locales/bg.json
@@ -83,6 +83,8 @@
   "confirmations.domain_block.message": "Are you really, really sure you want to block the entire {domain}? In most cases a few targeted blocks or mutes are sufficient and preferable.",
   "confirmations.mute.confirm": "Mute",
   "confirmations.mute.message": "Are you sure you want to mute {name}?",
+  "confirmations.redraft.confirm": "Delete & redraft",
+  "confirmations.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.unfollow.confirm": "Unfollow",
   "confirmations.unfollow.message": "Are you sure you want to unfollow {name}?",
   "embed.instructions": "Embed this status on your website by copying the code below.",
@@ -264,6 +266,7 @@
   "status.reblog": "Споделяне",
   "status.reblog_private": "Boost to original audience",
   "status.reblogged_by": "{name} сподели",
+  "status.redraft": "Delete & re-draft",
   "status.reply": "Отговор",
   "status.replyAll": "Reply to thread",
   "status.report": "Report @{name}",
@@ -284,8 +287,6 @@
   "timeline.media": "Media",
   "timeline.posts": "Toots",
   "trends.count_by_accounts": "{count} {rawCount, plural, one {person} other {people}} talking",
-  "trends.header": "Trending now",
-  "trends.refresh": "Refresh",
   "ui.beforeunload": "Your draft will be lost if you leave Mastodon.",
   "upload_area.title": "Drag & drop to upload",
   "upload_button.label": "Добави медия",
diff --git a/app/javascript/mastodon/locales/ca.json b/app/javascript/mastodon/locales/ca.json
index 9598a2796..48b4d28cd 100644
--- a/app/javascript/mastodon/locales/ca.json
+++ b/app/javascript/mastodon/locales/ca.json
@@ -83,6 +83,8 @@
   "confirmations.domain_block.message": "Estàs realment, realment segur que vols blocar totalment {domain}? En la majoria dels casos blocar o silenciar uns pocs objectius és suficient i preferible.",
   "confirmations.mute.confirm": "Silencia",
   "confirmations.mute.message": "Estàs segur que vols silenciar {name}?",
+  "confirmations.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.unfollow.confirm": "Deixa de seguir",
   "confirmations.unfollow.message": "Estàs segur que vols deixar de seguir {name}?",
   "embed.instructions": "Incrusta aquest estat al lloc web copiant el codi a continuació.",
@@ -264,6 +266,7 @@
   "status.reblog": "Impuls",
   "status.reblog_private": "Impulsar a l'audiència original",
   "status.reblogged_by": "{name} ha retootejat",
+  "status.redraft": "Delete & re-draft",
   "status.reply": "Respondre",
   "status.replyAll": "Respondre al tema",
   "status.report": "Informar sobre @{name}",
@@ -284,8 +287,6 @@
   "timeline.media": "Media",
   "timeline.posts": "Toots",
   "trends.count_by_accounts": "{count} {rawCount, plural, one {person} other {people}} talking",
-  "trends.header": "Trending now",
-  "trends.refresh": "Refresh",
   "ui.beforeunload": "El vostre esborrany es perdrà si sortiu de Mastodon.",
   "upload_area.title": "Arrossega i deixa anar per carregar",
   "upload_button.label": "Afegir multimèdia",
diff --git a/app/javascript/mastodon/locales/co.json b/app/javascript/mastodon/locales/co.json
index d5e2b2ede..11bb662d8 100644
--- a/app/javascript/mastodon/locales/co.json
+++ b/app/javascript/mastodon/locales/co.json
@@ -83,6 +83,8 @@
   "confirmations.domain_block.message": "Site sicuru·a che vulete piattà tuttu à {domain}? Saria forse abbastanza di bluccà ò piattà alcuni conti da quallà.",
   "confirmations.mute.confirm": "Piattà",
   "confirmations.mute.message": "Site sicuru·a che vulete piattà @{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.unfollow.confirm": "Disabbunassi",
   "confirmations.unfollow.message": "Site sicuru·a ch'ùn vulete più siguità @{name}?",
   "embed.instructions": "Integrà stu statutu à u vostru situ cù u codice quì sottu.",
@@ -264,6 +266,7 @@
   "status.reblog": "Sparte",
   "status.reblog_private": "Sparte à l'audienza uriginale",
   "status.reblogged_by": "{name} hà spartutu",
+  "status.redraft": "Delete & re-draft",
   "status.reply": "Risponde",
   "status.replyAll": "Risponde à tutti",
   "status.report": "Palisà @{name}",
@@ -284,8 +287,6 @@
   "timeline.media": "Media",
   "timeline.posts": "Toots",
   "trends.count_by_accounts": "{count} {rawCount, plural, one {person} other {people}} talking",
-  "trends.header": "Trending now",
-  "trends.refresh": "Refresh",
   "ui.beforeunload": "A bruttacopia sarà persa s'ellu hè chjosu Mastodon.",
   "upload_area.title": "Drag & drop per caricà un fugliale",
   "upload_button.label": "Aghjunghje un media",
diff --git a/app/javascript/mastodon/locales/de.json b/app/javascript/mastodon/locales/de.json
index e770c74eb..7ccf38059 100644
--- a/app/javascript/mastodon/locales/de.json
+++ b/app/javascript/mastodon/locales/de.json
@@ -83,6 +83,8 @@
   "confirmations.domain_block.message": "Bist du dir wirklich sicher, dass du die ganze Domain {domain} verbergen willst? In den meisten Fällen reichen ein paar gezielte Blocks aus.",
   "confirmations.mute.confirm": "Stummschalten",
   "confirmations.mute.message": "Bist du dir sicher, dass du {name} stummschalten möchtest?",
+  "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.unfollow.confirm": "Entfolgen",
   "confirmations.unfollow.message": "Bist du dir sicher, dass du {name} entfolgen möchtest?",
   "embed.instructions": "Du kannst diesen Beitrag auf deiner Webseite einbetten, indem du den folgenden Code einfügst.",
@@ -264,6 +266,7 @@
   "status.reblog": "Teilen",
   "status.reblog_private": "An das eigentliche Publikum teilen",
   "status.reblogged_by": "{name} teilte",
+  "status.redraft": "Delete & re-draft",
   "status.reply": "Antworten",
   "status.replyAll": "Auf Thread antworten",
   "status.report": "@{name} melden",
@@ -284,8 +287,6 @@
   "timeline.media": "Media",
   "timeline.posts": "Toots",
   "trends.count_by_accounts": "{count} {rawCount, plural, one {person} other {people}} talking",
-  "trends.header": "Trending now",
-  "trends.refresh": "Refresh",
   "ui.beforeunload": "Dein Entwurf geht verloren, wenn du Mastodon verlässt.",
   "upload_area.title": "Zum Hochladen hereinziehen",
   "upload_button.label": "Mediendatei hinzufügen",
diff --git a/app/javascript/mastodon/locales/defaultMessages.json b/app/javascript/mastodon/locales/defaultMessages.json
index e3b749e86..464592121 100644
--- a/app/javascript/mastodon/locales/defaultMessages.json
+++ b/app/javascript/mastodon/locales/defaultMessages.json
@@ -220,6 +220,10 @@
         "id": "status.delete"
       },
       {
+        "defaultMessage": "Delete & re-draft",
+        "id": "status.redraft"
+      },
+      {
         "defaultMessage": "Direct message @{name}",
         "id": "status.direct"
       },
@@ -378,6 +382,14 @@
         "id": "confirmations.delete.message"
       },
       {
+        "defaultMessage": "Delete & redraft",
+        "id": "confirmations.redraft.confirm"
+      },
+      {
+        "defaultMessage": "Are you sure you want to delete this status and re-draft it? You will lose all replies, boosts and favourites to it.",
+        "id": "confirmations.redraft.message"
+      },
+      {
         "defaultMessage": "Block",
         "id": "confirmations.block.confirm"
       },
@@ -805,10 +817,6 @@
   {
     "descriptors": [
       {
-        "defaultMessage": "Trending now",
-        "id": "trends.header"
-      },
-      {
         "defaultMessage": "People",
         "id": "search_results.accounts"
       },
@@ -1039,23 +1047,6 @@
   {
     "descriptors": [
       {
-        "defaultMessage": "Refresh",
-        "id": "trends.refresh"
-      },
-      {
-        "defaultMessage": "Trending now",
-        "id": "trends.header"
-      },
-      {
-        "defaultMessage": "Load more",
-        "id": "status.load_more"
-      }
-    ],
-    "path": "app/javascript/mastodon/features/getting_started/components/trends.json"
-  },
-  {
-    "descriptors": [
-      {
         "defaultMessage": "Home",
         "id": "tabs_bar.home"
       },
@@ -1508,6 +1499,10 @@
         "id": "status.delete"
       },
       {
+        "defaultMessage": "Delete & re-draft",
+        "id": "status.redraft"
+      },
+      {
         "defaultMessage": "Direct message @{name}",
         "id": "status.direct"
       },
@@ -1589,6 +1584,14 @@
         "id": "confirmations.delete.message"
       },
       {
+        "defaultMessage": "Delete & redraft",
+        "id": "confirmations.redraft.confirm"
+      },
+      {
+        "defaultMessage": "Are you sure you want to delete this status and re-draft it? You will lose all replies, boosts and favourites to it.",
+        "id": "confirmations.redraft.message"
+      },
+      {
         "defaultMessage": "Block",
         "id": "confirmations.block.confirm"
       },
@@ -1610,19 +1613,6 @@
   {
     "descriptors": [
       {
-        "defaultMessage": "Trending now",
-        "id": "trends.header"
-      },
-      {
-        "defaultMessage": "Refresh trends",
-        "id": "trends.refresh"
-      }
-    ],
-    "path": "app/javascript/mastodon/features/trends/index.json"
-  },
-  {
-    "descriptors": [
-      {
         "defaultMessage": "Boost",
         "id": "status.reblog"
       },
diff --git a/app/javascript/mastodon/locales/el.json b/app/javascript/mastodon/locales/el.json
index 9efc0e1bd..64efbd31a 100644
--- a/app/javascript/mastodon/locales/el.json
+++ b/app/javascript/mastodon/locales/el.json
@@ -83,6 +83,8 @@
   "confirmations.domain_block.message": "Σίγουρα θες να μπλοκάρεις ολόκληρο το {domain}; Συνήθως μερικά εστιασμένα μπλοκ ή αποσιωπήσεις επαρκούν και προτιμούνται.",
   "confirmations.mute.confirm": "Αποσιώπηση",
   "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.unfollow.confirm": "Διακοπή παρακολούθησης",
   "confirmations.unfollow.message": "Σίγουρα θες να πάψεις να ακολουθείς τον/την {name};",
   "embed.instructions": "Ενσωματώστε αυτή την κατάσταση στην ιστοσελίδα σας αντιγράφοντας τον παρακάτω κώδικα.",
@@ -264,6 +266,7 @@
   "status.reblog": "Boost",
   "status.reblog_private": "Boost to original audience",
   "status.reblogged_by": "{name} boosted",
+  "status.redraft": "Delete & re-draft",
   "status.reply": "Reply",
   "status.replyAll": "Reply to thread",
   "status.report": "Καταγγελία @{name}",
@@ -284,8 +287,6 @@
   "timeline.media": "Media",
   "timeline.posts": "Toots",
   "trends.count_by_accounts": "{count} {rawCount, plural, one {person} other {people}} talking",
-  "trends.header": "Trending now",
-  "trends.refresh": "Refresh",
   "ui.beforeunload": "Your draft will be lost if you leave Mastodon.",
   "upload_area.title": "Drag & drop to upload",
   "upload_button.label": "Add media",
diff --git a/app/javascript/mastodon/locales/en.json b/app/javascript/mastodon/locales/en.json
index b5ce82050..ae3b96c6d 100644
--- a/app/javascript/mastodon/locales/en.json
+++ b/app/javascript/mastodon/locales/en.json
@@ -87,6 +87,8 @@
   "confirmations.domain_block.message": "Are you really, really sure you want to block the entire {domain}? In most cases a few targeted blocks or mutes are sufficient and preferable.",
   "confirmations.mute.confirm": "Mute",
   "confirmations.mute.message": "Are you sure you want to mute {name}?",
+  "confirmations.redraft.confirm": "Delete & redraft",
+  "confirmations.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.unfollow.confirm": "Unfollow",
   "confirmations.unfollow.message": "Are you sure you want to unfollow {name}?",
   "embed.instructions": "Embed this status on your website by copying the code below.",
@@ -269,6 +271,7 @@
   "status.reblog": "Boost",
   "status.reblog_private": "Boost to original audience",
   "status.reblogged_by": "{name} boosted",
+  "status.redraft": "Delete & re-draft",
   "status.reply": "Reply",
   "status.replyAll": "Reply to thread",
   "status.report": "Report @{name}",
@@ -289,8 +292,6 @@
   "timeline.media": "Media",
   "timeline.posts": "Toots",
   "trends.count_by_accounts": "{count} {rawCount, plural, one {person} other {people}} talking",
-  "trends.header": "Trending now",
-  "trends.refresh": "Refresh",
   "ui.beforeunload": "Your draft will be lost if you leave Mastodon.",
   "upload_area.title": "Drag & drop to upload",
   "upload_button.label": "Add media",
diff --git a/app/javascript/mastodon/locales/eo.json b/app/javascript/mastodon/locales/eo.json
index 8740c396e..b01237a2e 100644
--- a/app/javascript/mastodon/locales/eo.json
+++ b/app/javascript/mastodon/locales/eo.json
@@ -83,6 +83,8 @@
   "confirmations.domain_block.message": "Ĉu vi vere, vere certas, ke vi volas tute bloki {domain}? Plej ofte, trafa blokado kaj silentigado sufiĉas kaj preferindas.",
   "confirmations.mute.confirm": "Silentigi",
   "confirmations.mute.message": "Ĉu vi certas, ke vi volas silentigi {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.unfollow.confirm": "Ne plu sekvi",
   "confirmations.unfollow.message": "Ĉu vi certas, ke vi volas ĉesi sekvi {name}?",
   "embed.instructions": "Enkorpigu ĉi tiun mesaĝon en vian retejon per kopio de la suba kodo.",
@@ -264,6 +266,7 @@
   "status.reblog": "Diskonigi",
   "status.reblog_private": "Diskonigi al la originala atentaro",
   "status.reblogged_by": "{name} diskonigis",
+  "status.redraft": "Delete & re-draft",
   "status.reply": "Respondi",
   "status.replyAll": "Respondi al la fadeno",
   "status.report": "Signali @{name}",
@@ -284,8 +287,6 @@
   "timeline.media": "Aŭdovidaĵoj",
   "timeline.posts": "Mesaĝoj",
   "trends.count_by_accounts": "{count} {rawCount, pluraj, unu {person} alia(j) {people}} parolas",
-  "trends.header": "Nun furoras",
-  "trends.refresh": "Aktualigi",
   "ui.beforeunload": "Via malneto perdiĝos se vi eliras de Mastodon.",
   "upload_area.title": "Altreni kaj lasi por alŝuti",
   "upload_button.label": "Aldoni aŭdovidaĵon",
diff --git a/app/javascript/mastodon/locales/es.json b/app/javascript/mastodon/locales/es.json
index 4386786cb..ba85841f6 100644
--- a/app/javascript/mastodon/locales/es.json
+++ b/app/javascript/mastodon/locales/es.json
@@ -83,6 +83,8 @@
   "confirmations.domain_block.message": "¿Seguro de que quieres bloquear al dominio entero? En algunos casos es preferible bloquear o silenciar objetivos determinados.",
   "confirmations.mute.confirm": "Silenciar",
   "confirmations.mute.message": "¿Estás seguro de que quieres 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.unfollow.confirm": "Dejar de seguir",
   "confirmations.unfollow.message": "¿Estás seguro de que quieres dejar de seguir a {name}?",
   "embed.instructions": "Añade este toot a tu sitio web con el siguiente código.",
@@ -264,6 +266,7 @@
   "status.reblog": "Retootear",
   "status.reblog_private": "Boost to original audience",
   "status.reblogged_by": "Retooteado por {name}",
+  "status.redraft": "Delete & re-draft",
   "status.reply": "Responder",
   "status.replyAll": "Responder al hilo",
   "status.report": "Reportar",
@@ -284,8 +287,6 @@
   "timeline.media": "Media",
   "timeline.posts": "Toots",
   "trends.count_by_accounts": "{count} {rawCount, plural, one {person} other {people}} talking",
-  "trends.header": "Trending now",
-  "trends.refresh": "Refresh",
   "ui.beforeunload": "Tu borrador se perderá si sales de Mastodon.",
   "upload_area.title": "Arrastra y suelta para subir",
   "upload_button.label": "Subir multimedia",
diff --git a/app/javascript/mastodon/locales/eu.json b/app/javascript/mastodon/locales/eu.json
index 508e4d988..49be810e2 100644
--- a/app/javascript/mastodon/locales/eu.json
+++ b/app/javascript/mastodon/locales/eu.json
@@ -13,14 +13,14 @@
   "account.follows_you": "Jarraitzen dizu",
   "account.hide_reblogs": "Ezkutatu @{name}(r)en bultzadak",
   "account.media": "Media",
-  "account.mention": "@{name} aipatu",
+  "account.mention": "Aipatu @{name}",
   "account.moved_to": "{name} hona lekualdatu da:",
   "account.mute": "Mututu @{name}",
   "account.mute_notifications": "Mututu @{name}(r)en jakinarazpenak",
   "account.muted": "Mutututa",
   "account.posts": "Toot-ak",
   "account.posts_with_replies": "Toot eta erantzunak",
-  "account.report": "@{name} salatu",
+  "account.report": "Salatu @{name}",
   "account.requested": "Onarpenaren zain. Klikatu jarraitzeko eskaera ezeztatzeko",
   "account.share": "@{name}(e)ren profila elkarbanatu",
   "account.show_reblogs": "Erakutsi @{name}(r)en bultzadak",
@@ -67,8 +67,8 @@
   "compose_form.placeholder": "Zer duzu buruan?",
   "compose_form.publish": "Toot",
   "compose_form.publish_loud": "{publish}!",
-  "compose_form.sensitive.marked": "Multimedia mingarri gisa markatu da",
-  "compose_form.sensitive.unmarked": "Multimedia ez da mingarri gisa markatu",
+  "compose_form.sensitive.marked": "Multimedia edukia hunkigarri gisa markatu da",
+  "compose_form.sensitive.unmarked": "Multimedia edukia ez da hunkigarri gisa markatu",
   "compose_form.spoiler.marked": "Testua abisu batek ezkutatzen du",
   "compose_form.spoiler.unmarked": "Testua ez dago ezkutatuta",
   "compose_form.spoiler_placeholder": "Idatzi zure abisua hemen",
@@ -83,6 +83,8 @@
   "confirmations.domain_block.message": "Ziur, erabat ziur, {domain} domeinu osoa blokeatu nahi duzula? Gehienetan gutxi batzuk blokeatu edo mututzearekin nahikoa da.",
   "confirmations.mute.confirm": "Mututu",
   "confirmations.mute.message": "Ziur {name} mututu nahi duzula?",
+  "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.unfollow.confirm": "Utzi jarraitzeari",
   "confirmations.unfollow.message": "Ziur {name} jarraitzeari utzi nahi diozula?",
   "embed.instructions": "Txertatu mezu hau zure webgunean beheko kodea kopatuz.",
@@ -264,11 +266,12 @@
   "status.reblog": "Bultzada",
   "status.reblog_private": "Bultzada jatorrizko hartzaileei",
   "status.reblogged_by": "{name}(r)en bultzada",
+  "status.redraft": "Delete & re-draft",
   "status.reply": "Erantzun",
   "status.replyAll": "Erantzun harian",
   "status.report": "Salatu @{name}",
   "status.sensitive_toggle": "Egin klik ikusteko",
-  "status.sensitive_warning": "Eduki mingarria",
+  "status.sensitive_warning": "Eduki hunkigarria",
   "status.share": "Partekatu",
   "status.show_less": "Erakutsi gutxiago",
   "status.show_less_all": "Erakutsi denetarik gutxiago",
@@ -284,8 +287,6 @@
   "timeline.media": "Media",
   "timeline.posts": "Toot-ak",
   "trends.count_by_accounts": "{count} {rawCount, plural, one {person} other {people}} hitz egiten",
-  "trends.header": "Joera orain",
-  "trends.refresh": "Freskatu",
   "ui.beforeunload": "Zure zirriborroa galduko da Mastodon uzten baduzu.",
   "upload_area.title": "Arrastatu eta jaregin igotzeko",
   "upload_button.label": "Gehitu multimedia",
diff --git a/app/javascript/mastodon/locales/fa.json b/app/javascript/mastodon/locales/fa.json
index 82f3af3cd..bf7a256d6 100644
--- a/app/javascript/mastodon/locales/fa.json
+++ b/app/javascript/mastodon/locales/fa.json
@@ -83,6 +83,8 @@
   "confirmations.domain_block.message": "آیا جدی جدی می‌خواهید کل دامین {domain} را مسدود کنید؟ بیشتر وقت‌ها مسدودکردن یا بی‌صداکردن چند حساب کاربری خاص کافی است و توصیه می‌شود.",
   "confirmations.mute.confirm": "بی‌صدا کن",
   "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.unfollow.confirm": "لغو پیگیری",
   "confirmations.unfollow.message": "آیا واقعاً می‌خواهید به پیگیری از {name} پایان دهید؟",
   "embed.instructions": "برای جاگذاری این نوشته در سایت خودتان، کد زیر را کپی کنید.",
@@ -264,6 +266,7 @@
   "status.reblog": "بازبوقیدن",
   "status.reblog_private": "بازبوق به مخاطبان اولیه",
   "status.reblogged_by": "‫{name}‬ بازبوقید",
+  "status.redraft": "Delete & re-draft",
   "status.reply": "پاسخ",
   "status.replyAll": "به نوشته پاسخ دهید",
   "status.report": "گزارش دادن @{name}",
@@ -284,8 +287,6 @@
   "timeline.media": "عکس و ویدیو",
   "timeline.posts": "بوق‌ها",
   "trends.count_by_accounts": "{count} {rawCount, plural, one {نفر نوشته است} other {نفر نوشته‌اند}}",
-  "trends.header": "موضوعات داغ",
-  "trends.refresh": "به‌روزرسانی",
   "ui.beforeunload": "اگر از ماستدون خارج شوید پیش‌نویس شما پاک خواهد شد.",
   "upload_area.title": "برای بارگذاری به این‌جا بکشید",
   "upload_button.label": "افزودن تصویر",
diff --git a/app/javascript/mastodon/locales/fi.json b/app/javascript/mastodon/locales/fi.json
index fa8565431..4cdee49ee 100644
--- a/app/javascript/mastodon/locales/fi.json
+++ b/app/javascript/mastodon/locales/fi.json
@@ -83,6 +83,8 @@
   "confirmations.domain_block.message": "Haluatko aivan varmasti estää koko verkko-osoitteen {domain}? Useimmiten jokunen kohdistettu esto ja mykistys riittää, ja se on suositeltavampi tapa toimia.",
   "confirmations.mute.confirm": "Mykistä",
   "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.unfollow.confirm": "Lakkaa seuraamasta",
   "confirmations.unfollow.message": "Haluatko varmasti lakata seuraamasta käyttäjää {name}?",
   "embed.instructions": "Upota statuspäivitys sivullesi kopioimalla alla oleva koodi.",
@@ -264,6 +266,7 @@
   "status.reblog": "Buustaa",
   "status.reblog_private": "Buustaa alkuperäiselle yleisölle",
   "status.reblogged_by": "{name} buustasi",
+  "status.redraft": "Delete & re-draft",
   "status.reply": "Vastaa",
   "status.replyAll": "Vastaa ketjuun",
   "status.report": "Raportoi @{name}",
@@ -284,8 +287,6 @@
   "timeline.media": "Media",
   "timeline.posts": "Toots",
   "trends.count_by_accounts": "{count} {rawCount, plural, one {person} other {people}} talking",
-  "trends.header": "Trending now",
-  "trends.refresh": "Refresh",
   "ui.beforeunload": "Luonnos häviää, jos poistut Mastodonista.",
   "upload_area.title": "Lataa raahaamalla ja pudottamalla tähän",
   "upload_button.label": "Lisää mediaa",
diff --git a/app/javascript/mastodon/locales/fr.json b/app/javascript/mastodon/locales/fr.json
index 0190c7562..35c753091 100644
--- a/app/javascript/mastodon/locales/fr.json
+++ b/app/javascript/mastodon/locales/fr.json
@@ -83,6 +83,8 @@
   "confirmations.domain_block.message": "Êtes-vous vraiment, vraiment sûr⋅e de vouloir bloquer {domain} en entier ? Dans la plupart des cas, quelques blocages ou masquages ciblés sont suffisants et préférables.",
   "confirmations.mute.confirm": "Masquer",
   "confirmations.mute.message": "Confirmez-vous le masquage de {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.unfollow.confirm": "Ne plus suivre",
   "confirmations.unfollow.message": "Voulez-vous arrêter de suivre {name} ?",
   "embed.instructions": "Intégrez ce statut à votre site en copiant le code ci-dessous.",
@@ -264,6 +266,7 @@
   "status.reblog": "Partager",
   "status.reblog_private": "Booster vers l'audience originale",
   "status.reblogged_by": "{name} a partagé :",
+  "status.redraft": "Delete & re-draft",
   "status.reply": "Répondre",
   "status.replyAll": "Répondre au fil",
   "status.report": "Signaler @{name}",
@@ -284,8 +287,6 @@
   "timeline.media": "Media",
   "timeline.posts": "Pouets",
   "trends.count_by_accounts": "{count} {rawCount, plural, one {person} other {people}} talking",
-  "trends.header": "Trending now",
-  "trends.refresh": "Refresh",
   "ui.beforeunload": "Votre brouillon sera perdu si vous quittez Mastodon.",
   "upload_area.title": "Glissez et déposez pour envoyer",
   "upload_button.label": "Joindre un média",
diff --git a/app/javascript/mastodon/locales/gl.json b/app/javascript/mastodon/locales/gl.json
index 7af9a0426..5aab4d648 100644
--- a/app/javascript/mastodon/locales/gl.json
+++ b/app/javascript/mastodon/locales/gl.json
@@ -83,6 +83,8 @@
   "confirmations.domain_block.message": "Realmente está segura de que quere bloquear por completo o dominio {domain}? Normalmente é suficiente, e preferible, bloquear de xeito selectivo varios elementos.",
   "confirmations.mute.confirm": "Acalar",
   "confirmations.mute.message": "Está segura de que quere acalar 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.unfollow.confirm": "Deixar de seguir",
   "confirmations.unfollow.message": "Quere deixar de seguir a {name}?",
   "embed.instructions": "Copie o código inferior para incrustar no seu sitio web este estado.",
@@ -264,6 +266,7 @@
   "status.reblog": "Promover",
   "status.reblog_private": "Promover a audiencia orixinal",
   "status.reblogged_by": "{name} promoveu",
+  "status.redraft": "Delete & re-draft",
   "status.reply": "Resposta",
   "status.replyAll": "Resposta a conversa",
   "status.report": "Informar @{name}",
@@ -284,8 +287,6 @@
   "timeline.media": "Media",
   "timeline.posts": "Toots",
   "trends.count_by_accounts": "{count} {rawCount, plural, one {person} other {people}} talking",
-  "trends.header": "Trending now",
-  "trends.refresh": "Refresh",
   "ui.beforeunload": "O borrador perderase se sae de Mastodon.",
   "upload_area.title": "Arrastre e solte para subir",
   "upload_button.label": "Engadir medios",
diff --git a/app/javascript/mastodon/locales/he.json b/app/javascript/mastodon/locales/he.json
index 343edec42..188d69553 100644
--- a/app/javascript/mastodon/locales/he.json
+++ b/app/javascript/mastodon/locales/he.json
@@ -83,6 +83,8 @@
   "confirmations.domain_block.message": "באמת באמת לחסום את כל קהילת {domain}? ברב המקרים השתקות נבחרות של מספר משתמשים מסויימים צריכה להספיק.",
   "confirmations.mute.confirm": "להשתיק",
   "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.unfollow.confirm": "להפסיק מעקב",
   "confirmations.unfollow.message": "להפסיק מעקב אחרי {name}?",
   "embed.instructions": "ניתן להטמיע את ההודעה באתרך ע\"י העתקת הקוד שלהלן.",
@@ -264,6 +266,7 @@
   "status.reblog": "הדהוד",
   "status.reblog_private": "Boost to original audience",
   "status.reblogged_by": "הודהד על ידי {name}",
+  "status.redraft": "Delete & re-draft",
   "status.reply": "תגובה",
   "status.replyAll": "תגובה לכולם",
   "status.report": "דיווח על @{name}",
@@ -284,8 +287,6 @@
   "timeline.media": "Media",
   "timeline.posts": "Toots",
   "trends.count_by_accounts": "{count} {rawCount, plural, one {person} other {people}} talking",
-  "trends.header": "Trending now",
-  "trends.refresh": "Refresh",
   "ui.beforeunload": "הטיוטא תאבד אם תעזבו את מסטודון.",
   "upload_area.title": "ניתן להעלות על ידי Drag & drop",
   "upload_button.label": "הוספת מדיה",
diff --git a/app/javascript/mastodon/locales/hr.json b/app/javascript/mastodon/locales/hr.json
index d350cb6e1..fc787366d 100644
--- a/app/javascript/mastodon/locales/hr.json
+++ b/app/javascript/mastodon/locales/hr.json
@@ -83,6 +83,8 @@
   "confirmations.domain_block.message": "Jesi li zaista, zaista siguran da želiš potpuno blokirati {domain}? In most cases a few targeted blocks or mutes are sufficient and preferable.",
   "confirmations.mute.confirm": "Utišaj",
   "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.unfollow.confirm": "Unfollow",
   "confirmations.unfollow.message": "Are you sure you want to unfollow {name}?",
   "embed.instructions": "Embed this status on your website by copying the code below.",
@@ -264,6 +266,7 @@
   "status.reblog": "Podigni",
   "status.reblog_private": "Boost to original audience",
   "status.reblogged_by": "{name} je podigao",
+  "status.redraft": "Delete & re-draft",
   "status.reply": "Odgovori",
   "status.replyAll": "Odgovori na temu",
   "status.report": "Prijavi @{name}",
@@ -284,8 +287,6 @@
   "timeline.media": "Media",
   "timeline.posts": "Toots",
   "trends.count_by_accounts": "{count} {rawCount, plural, one {person} other {people}} talking",
-  "trends.header": "Trending now",
-  "trends.refresh": "Refresh",
   "ui.beforeunload": "Your draft will be lost if you leave Mastodon.",
   "upload_area.title": "Povuci i spusti kako bi uploadao",
   "upload_button.label": "Dodaj media",
diff --git a/app/javascript/mastodon/locales/hu.json b/app/javascript/mastodon/locales/hu.json
index 7164951bf..7c850b005 100644
--- a/app/javascript/mastodon/locales/hu.json
+++ b/app/javascript/mastodon/locales/hu.json
@@ -83,6 +83,8 @@
   "confirmations.domain_block.message": "Nagyon biztos abban, hogy le szeretné tiltani az egész {domain}-t? A legtöbb esetben néhány célszerű tiltás vagy némítás elegendő és kívánatosabb megoldás.",
   "confirmations.mute.confirm": "Némít",
   "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.unfollow.confirm": "Követés visszavonása",
   "confirmations.unfollow.message": "Biztos benne, hogy vissza szeretné vonni {name} követését?",
   "embed.instructions": "Ágyazza be ezen státuszt weboldalába az alábbi kód másolásával.",
@@ -264,6 +266,7 @@
   "status.reblog": "Reblog",
   "status.reblog_private": "Boost to original audience",
   "status.reblogged_by": "{name} reblogolta",
+  "status.redraft": "Delete & re-draft",
   "status.reply": "Válasz",
   "status.replyAll": "Válaszolj a beszélgetésre",
   "status.report": "Report @{name}",
@@ -284,8 +287,6 @@
   "timeline.media": "Media",
   "timeline.posts": "Toots",
   "trends.count_by_accounts": "{count} {rawCount, plural, one {person} other {people}} talking",
-  "trends.header": "Trending now",
-  "trends.refresh": "Refresh",
   "ui.beforeunload": "A piszkozata el fog vesztődni ha elhagyja Mastodon-t.",
   "upload_area.title": "Húzza ide a feltöltéshez",
   "upload_button.label": "Média hozzáadása",
diff --git a/app/javascript/mastodon/locales/hy.json b/app/javascript/mastodon/locales/hy.json
index 9f3885076..bb167998e 100644
--- a/app/javascript/mastodon/locales/hy.json
+++ b/app/javascript/mastodon/locales/hy.json
@@ -83,6 +83,8 @@
   "confirmations.domain_block.message": "Հաստատ֊հաստա՞տ վստահ ես, որ ուզում ես արգելափակել ամբողջ {domain} տիրույթը։ Սովորաբար մի երկու թիրախավորված արգելափակում կամ լռեցում բավական է ու նախընտրելի։",
   "confirmations.mute.confirm": "Լռեցնել",
   "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.unfollow.confirm": "Ապահետեւել",
   "confirmations.unfollow.message": "Վստա՞հ ես, որ ուզում ես այլեւս չհետեւել {name}֊ին։",
   "embed.instructions": "Այս թութը քո կայքում ներդնելու համար կարող ես պատճենել ներքոհիշյալ կոդը։",
@@ -264,6 +266,7 @@
   "status.reblog": "Տարածել",
   "status.reblog_private": "Boost to original audience",
   "status.reblogged_by": "{name} տարածել է",
+  "status.redraft": "Delete & re-draft",
   "status.reply": "Պատասխանել",
   "status.replyAll": "Պատասխանել թելին",
   "status.report": "Բողոքել @{name}֊ից",
@@ -284,8 +287,6 @@
   "timeline.media": "Media",
   "timeline.posts": "Toots",
   "trends.count_by_accounts": "{count} {rawCount, plural, one {person} other {people}} talking",
-  "trends.header": "Trending now",
-  "trends.refresh": "Refresh",
   "ui.beforeunload": "Քո սեւագիրը կկորի, եթե լքես Մաստոդոնը։",
   "upload_area.title": "Քաշիր ու նետիր՝ վերբեռնելու համար",
   "upload_button.label": "Ավելացնել մեդիա",
diff --git a/app/javascript/mastodon/locales/id.json b/app/javascript/mastodon/locales/id.json
index 9683e69a7..0dee97656 100644
--- a/app/javascript/mastodon/locales/id.json
+++ b/app/javascript/mastodon/locales/id.json
@@ -83,6 +83,8 @@
   "confirmations.domain_block.message": "Apakah anda benar benar yakin untuk memblokir keseluruhan {domain}? Dalam kasus tertentu beberapa pemblokiran atau penyembunyian lebih baik.",
   "confirmations.mute.confirm": "Bisukan",
   "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.unfollow.confirm": "Berhenti mengikuti",
   "confirmations.unfollow.message": "Apakah anda ingin berhenti mengikuti {name}?",
   "embed.instructions": "Sematkan status ini di website anda dengan menyalin kode di bawah ini.",
@@ -264,6 +266,7 @@
   "status.reblog": "Boost",
   "status.reblog_private": "Boost to original audience",
   "status.reblogged_by": "di-boost {name}",
+  "status.redraft": "Delete & re-draft",
   "status.reply": "Balas",
   "status.replyAll": "Balas ke semua",
   "status.report": "Laporkan @{name}",
@@ -284,8 +287,6 @@
   "timeline.media": "Media",
   "timeline.posts": "Toots",
   "trends.count_by_accounts": "{count} {rawCount, plural, one {person} other {people}} talking",
-  "trends.header": "Trending now",
-  "trends.refresh": "Refresh",
   "ui.beforeunload": "Naskah anda akan hilang jika anda keluar dari Mastodon.",
   "upload_area.title": "Seret & lepaskan untuk mengunggah",
   "upload_button.label": "Tambahkan media",
diff --git a/app/javascript/mastodon/locales/io.json b/app/javascript/mastodon/locales/io.json
index d63225783..abb81981e 100644
--- a/app/javascript/mastodon/locales/io.json
+++ b/app/javascript/mastodon/locales/io.json
@@ -83,6 +83,8 @@
   "confirmations.domain_block.message": "Are you really, really sure you want to block the entire {domain}? In most cases a few targeted blocks or mutes are sufficient and preferable.",
   "confirmations.mute.confirm": "Mute",
   "confirmations.mute.message": "Are you sure you want to mute {name}?",
+  "confirmations.redraft.confirm": "Delete & redraft",
+  "confirmations.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.unfollow.confirm": "Unfollow",
   "confirmations.unfollow.message": "Are you sure you want to unfollow {name}?",
   "embed.instructions": "Embed this status on your website by copying the code below.",
@@ -264,6 +266,7 @@
   "status.reblog": "Repetar",
   "status.reblog_private": "Boost to original audience",
   "status.reblogged_by": "{name} repetita",
+  "status.redraft": "Delete & re-draft",
   "status.reply": "Respondar",
   "status.replyAll": "Respondar a filo",
   "status.report": "Denuncar @{name}",
@@ -284,8 +287,6 @@
   "timeline.media": "Media",
   "timeline.posts": "Toots",
   "trends.count_by_accounts": "{count} {rawCount, plural, one {person} other {people}} talking",
-  "trends.header": "Trending now",
-  "trends.refresh": "Refresh",
   "ui.beforeunload": "Your draft will be lost if you leave Mastodon.",
   "upload_area.title": "Tranar faligar por kargar",
   "upload_button.label": "Adjuntar kontenajo",
diff --git a/app/javascript/mastodon/locales/it.json b/app/javascript/mastodon/locales/it.json
index 87ff78469..f0d58621d 100644
--- a/app/javascript/mastodon/locales/it.json
+++ b/app/javascript/mastodon/locales/it.json
@@ -83,6 +83,8 @@
   "confirmations.domain_block.message": "Sei davvero sicuro che vuoi bloccare l'intero {domain}? Nella maggior parte dei casi, pochi blocchi o silenziamenti mirati sono sufficienti e preferibili.",
   "confirmations.mute.confirm": "Silenzia",
   "confirmations.mute.message": "Sei sicuro di voler silenziare {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.unfollow.confirm": "Smetti di seguire",
   "confirmations.unfollow.message": "Sei sicuro che non vuoi più seguire {name}?",
   "embed.instructions": "Inserisci questo status nel tuo sito copiando il codice qui sotto.",
@@ -264,6 +266,7 @@
   "status.reblog": "Condividi",
   "status.reblog_private": "Condividi con i destinatari iniziali",
   "status.reblogged_by": "{name} ha condiviso",
+  "status.redraft": "Delete & re-draft",
   "status.reply": "Rispondi",
   "status.replyAll": "Rispondi alla conversazione",
   "status.report": "Segnala @{name}",
@@ -284,8 +287,6 @@
   "timeline.media": "Media",
   "timeline.posts": "Toots",
   "trends.count_by_accounts": "{count} {rawCount, plural, one {person} other {people}} talking",
-  "trends.header": "Trending now",
-  "trends.refresh": "Refresh",
   "ui.beforeunload": "La bozza andrà persa se esci da Mastodon.",
   "upload_area.title": "Trascina per caricare",
   "upload_button.label": "Aggiungi file multimediale",
diff --git a/app/javascript/mastodon/locales/ja.json b/app/javascript/mastodon/locales/ja.json
index fc1a314e8..9bb3fca25 100644
--- a/app/javascript/mastodon/locales/ja.json
+++ b/app/javascript/mastodon/locales/ja.json
@@ -87,6 +87,8 @@
   "confirmations.domain_block.message": "本当に{domain}全体を非表示にしますか? 多くの場合は個別にブロックやミュートするだけで充分であり、また好ましいです。",
   "confirmations.mute.confirm": "ミュート",
   "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.unfollow.confirm": "フォロー解除",
   "confirmations.unfollow.message": "本当に{name}さんのフォローを解除しますか?",
   "embed.instructions": "下記のコードをコピーしてウェブサイトに埋め込みます。",
@@ -269,6 +271,7 @@
   "status.reblog": "ブースト",
   "status.reblog_private": "ブースト",
   "status.reblogged_by": "{name}さんがブースト",
+  "status.redraft": "Delete & re-draft",
   "status.reply": "返信",
   "status.replyAll": "全員に返信",
   "status.report": "@{name}さんを通報",
@@ -289,8 +292,6 @@
   "timeline.media": "メディア",
   "timeline.posts": "投稿",
   "trends.count_by_accounts": "{count} {rawCount, plural, one {人} other {人}} がトゥート",
-  "trends.header": "トレンドタグ",
-  "trends.refresh": "更新",
   "ui.beforeunload": "Mastodonから離れると送信前の投稿は失われます。",
   "upload_area.title": "ドラッグ&ドロップでアップロード",
   "upload_button.label": "メディアを追加",
diff --git a/app/javascript/mastodon/locales/ko.json b/app/javascript/mastodon/locales/ko.json
index 65c6319b4..fef953c66 100644
--- a/app/javascript/mastodon/locales/ko.json
+++ b/app/javascript/mastodon/locales/ko.json
@@ -83,6 +83,8 @@
   "confirmations.domain_block.message": "정말로 {domain} 전체를 숨기시겠습니까? 대부분의 경우 개별 차단이나 뮤트로 충분합니다.",
   "confirmations.mute.confirm": "뮤트",
   "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.unfollow.confirm": "언팔로우",
   "confirmations.unfollow.message": "정말로 {name}를 언팔로우하시겠습니까?",
   "embed.instructions": "아래의 코드를 복사하여 대화를 원하는 곳으로 공유하세요.",
@@ -264,6 +266,7 @@
   "status.reblog": "부스트",
   "status.reblog_private": "원래의 수신자들에게 부스트",
   "status.reblogged_by": "{name}님이 부스트 했습니다",
+  "status.redraft": "Delete & re-draft",
   "status.reply": "답장",
   "status.replyAll": "전원에게 답장",
   "status.report": "신고",
@@ -284,8 +287,6 @@
   "timeline.media": "Media",
   "timeline.posts": "Toots",
   "trends.count_by_accounts": "{count} {rawCount, plural, one {person} other {people}} talking",
-  "trends.header": "Trending now",
-  "trends.refresh": "Refresh",
   "ui.beforeunload": "지금 나가면 저장되지 않은 항목을 잃게 됩니다.",
   "upload_area.title": "드래그 & 드롭으로 업로드",
   "upload_button.label": "미디어 추가",
diff --git a/app/javascript/mastodon/locales/nl.json b/app/javascript/mastodon/locales/nl.json
index 664cebac0..d744a8723 100644
--- a/app/javascript/mastodon/locales/nl.json
+++ b/app/javascript/mastodon/locales/nl.json
@@ -83,6 +83,8 @@
   "confirmations.domain_block.message": "Weet je het echt heel erg zeker dat je alles van {domain} wil negeren? In de meeste gevallen is het blokkeren of negeren van een paar specifieke personen voldoende en gepaster.",
   "confirmations.mute.confirm": "Negeren",
   "confirmations.mute.message": "Weet je het zeker dat je {name} wilt negeren?",
+  "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.unfollow.confirm": "Ontvolgen",
   "confirmations.unfollow.message": "Weet je het zeker dat je {name} wilt ontvolgen?",
   "embed.instructions": "Embed deze toot op jouw website, door de onderstaande code te kopiëren.",
@@ -264,6 +266,7 @@
   "status.reblog": "Boost",
   "status.reblog_private": "Boost naar oorspronkelijke ontvangers",
   "status.reblogged_by": "{name} boostte",
+  "status.redraft": "Delete & re-draft",
   "status.reply": "Reageren",
   "status.replyAll": "Reageer op iedereen",
   "status.report": "Rapporteer @{name}",
@@ -284,8 +287,6 @@
   "timeline.media": "Media",
   "timeline.posts": "Toots",
   "trends.count_by_accounts": "{count} {rawCount, plural, one {persoon praat} other {mensen praten}} hierover",
-  "trends.header": "Trends",
-  "trends.refresh": "Vernieuwen",
   "ui.beforeunload": "Je concept zal verloren gaan als je Mastodon verlaat.",
   "upload_area.title": "Hierin slepen om te uploaden",
   "upload_button.label": "Media toevoegen",
diff --git a/app/javascript/mastodon/locales/no.json b/app/javascript/mastodon/locales/no.json
index 8aaf4de42..d971bfcdc 100644
--- a/app/javascript/mastodon/locales/no.json
+++ b/app/javascript/mastodon/locales/no.json
@@ -83,6 +83,8 @@
   "confirmations.domain_block.message": "Er du sikker på at du vil skjule hele domenet {domain}? I de fleste tilfeller er det bedre med målrettet blokkering eller demping.",
   "confirmations.mute.confirm": "Demp",
   "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.unfollow.confirm": "Slutt å følge",
   "confirmations.unfollow.message": "Er du sikker på at du vil slutte å følge {name}?",
   "embed.instructions": "Kopier koden under for å bygge inn denne statusen på hjemmesiden din.",
@@ -264,6 +266,7 @@
   "status.reblog": "Fremhev",
   "status.reblog_private": "Boost to original audience",
   "status.reblogged_by": "Fremhevd av {name}",
+  "status.redraft": "Delete & re-draft",
   "status.reply": "Svar",
   "status.replyAll": "Svar til samtale",
   "status.report": "Rapporter @{name}",
@@ -284,8 +287,6 @@
   "timeline.media": "Media",
   "timeline.posts": "Toots",
   "trends.count_by_accounts": "{count} {rawCount, plural, one {person} other {people}} talking",
-  "trends.header": "Trending now",
-  "trends.refresh": "Refresh",
   "ui.beforeunload": "Din kladd vil bli forkastet om du forlater Mastodon.",
   "upload_area.title": "Dra og slipp for å laste opp",
   "upload_button.label": "Legg til media",
diff --git a/app/javascript/mastodon/locales/oc.json b/app/javascript/mastodon/locales/oc.json
index 4056ec2db..cfbd3a83c 100644
--- a/app/javascript/mastodon/locales/oc.json
+++ b/app/javascript/mastodon/locales/oc.json
@@ -83,6 +83,8 @@
   "confirmations.domain_block.message": "Volètz vertadièrament blocar complètament {domain} ? De còps cal pas que blocar o rescondre unas personas solament.",
   "confirmations.mute.confirm": "Rescondre",
   "confirmations.mute.message": "Sètz segur de voler rescondre {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.unfollow.confirm": "Quitar de sègre",
   "confirmations.unfollow.message": "Volètz vertadièrament quitar de sègre {name} ?",
   "embed.instructions": "Embarcar aqueste estatut per lo far veire sus un site Internet en copiar lo còdi çai-jos.",
@@ -264,6 +266,7 @@
   "status.reblog": "Partejar",
   "status.reblog_private": "Partejar a l’audiéncia d’origina",
   "status.reblogged_by": "{name} a partejat",
+  "status.redraft": "Delete & re-draft",
   "status.reply": "Respondre",
   "status.replyAll": "Respondre a la conversacion",
   "status.report": "Senhalar @{name}",
@@ -284,8 +287,6 @@
   "timeline.media": "Media",
   "timeline.posts": "Tuts",
   "trends.count_by_accounts": "{count} {rawCount, plural, one {person} ne charra other {people}} ne charran",
-  "trends.header": "Tendéncia actuala",
-  "trends.refresh": "Actualizar",
   "ui.beforeunload": "Vòstre brolhon serà perdut se quitatz Mastodon.",
   "upload_area.title": "Lisatz e depausatz per mandar",
   "upload_button.label": "Ajustar un mèdia",
diff --git a/app/javascript/mastodon/locales/pl.json b/app/javascript/mastodon/locales/pl.json
index b62d5b065..759d7c9e8 100644
--- a/app/javascript/mastodon/locales/pl.json
+++ b/app/javascript/mastodon/locales/pl.json
@@ -87,6 +87,8 @@
   "confirmations.domain_block.message": "Czy na pewno chcesz zablokować całą domenę {domain}? Zwykle lepszym rozwiązaniem jest blokada lub wyciszenie kilku użytkowników.",
   "confirmations.mute.confirm": "Wycisz",
   "confirmations.mute.message": "Czy na pewno chcesz wyciszyć {name}?",
+  "confirmations.redraft.confirm": "Usuń i przeredaguj",
+  "confirmations.redraft.message": "Czy na pewno chcesz usunąć i przeredagować ten wpis? Utracisz wszystkie odpowiedzi, podbicia i polubienia dotyczące go.",
   "confirmations.unfollow.confirm": "Przestań śledzić",
   "confirmations.unfollow.message": "Czy na pewno zamierzasz przestać śledzić {name}?",
   "embed.instructions": "Osadź ten wpis na swojej stronie wklejając poniższy kod.",
@@ -269,6 +271,7 @@
   "status.reblog": "Podbij",
   "status.reblog_private": "Podbij dla odbiorców oryginalnego wpisu",
   "status.reblogged_by": "{name} podbił",
+  "status.redraft": "Usuń i przeredaguj",
   "status.reply": "Odpowiedz",
   "status.replyAll": "Odpowiedz na wątek",
   "status.report": "Zgłoś @{name}",
@@ -289,8 +292,6 @@
   "timeline.media": "Zawartość multimedialna",
   "timeline.posts": "Wpisy",
   "trends.count_by_accounts": "{count} {rawCount, plural, one {osoba rozmawia} few {osoby rozmawiają} other {osób rozmawia}} o tym",
-  "trends.header": "Na czasie",
-  "trends.refresh": "Odśwież",
   "ui.beforeunload": "Utracisz tworzony wpis, jeżeli opuścisz Mastodona.",
   "upload_area.title": "Przeciągnij i upuść aby wysłać",
   "upload_button.label": "Dodaj zawartość multimedialną",
diff --git a/app/javascript/mastodon/locales/pt-BR.json b/app/javascript/mastodon/locales/pt-BR.json
index fc07266a8..fcb2a5686 100644
--- a/app/javascript/mastodon/locales/pt-BR.json
+++ b/app/javascript/mastodon/locales/pt-BR.json
@@ -83,6 +83,8 @@
   "confirmations.domain_block.message": "Você quer mesmo bloquear {domain} inteiro? Na maioria dos casos, silenciar ou bloquear alguns usuários é o suficiente e o recomendado.",
   "confirmations.mute.confirm": "Silenciar",
   "confirmations.mute.message": "Você tem certeza de que quer 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.unfollow.confirm": "Deixar de seguir",
   "confirmations.unfollow.message": "Você tem certeza de que quer deixar de seguir {name}?",
   "embed.instructions": "Incorpore esta postagem em seu site copiando o código abaixo.",
@@ -264,6 +266,7 @@
   "status.reblog": "Compartilhar",
   "status.reblog_private": "Compartilhar com a audiência original",
   "status.reblogged_by": "{name} compartilhou",
+  "status.redraft": "Delete & re-draft",
   "status.reply": "Responder",
   "status.replyAll": "Responder à sequência",
   "status.report": "Denunciar @{name}",
@@ -284,8 +287,6 @@
   "timeline.media": "Media",
   "timeline.posts": "Toots",
   "trends.count_by_accounts": "{count} {rawCount, plural, one {pessoa} other {pessoas}} falando sobre",
-  "trends.header": "Hashtags do momento",
-  "trends.refresh": "Atualizar",
   "ui.beforeunload": "Seu rascunho será perdido se você sair do Mastodon.",
   "upload_area.title": "Arraste e solte para enviar",
   "upload_button.label": "Adicionar mídia",
diff --git a/app/javascript/mastodon/locales/pt.json b/app/javascript/mastodon/locales/pt.json
index b1e760954..d51a47955 100644
--- a/app/javascript/mastodon/locales/pt.json
+++ b/app/javascript/mastodon/locales/pt.json
@@ -83,6 +83,8 @@
   "confirmations.domain_block.message": "De certeza que queres bloquear por completo o domínio {domain}? Na maioria dos casos, silenciar ou bloquear alguns utilizadores é o suficiente e o recomendado.",
   "confirmations.mute.confirm": "Silenciar",
   "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.unfollow.confirm": "Deixar de seguir",
   "confirmations.unfollow.message": "De certeza que queres deixar de seguir {name}?",
   "embed.instructions": "Publicar este post num outro site copiando o código abaixo.",
@@ -264,6 +266,7 @@
   "status.reblog": "Partilhar",
   "status.reblog_private": "Boost to original audience",
   "status.reblogged_by": "{name} partilhou",
+  "status.redraft": "Delete & re-draft",
   "status.reply": "Responder",
   "status.replyAll": "Responder à conversa",
   "status.report": "Denunciar @{name}",
@@ -284,8 +287,6 @@
   "timeline.media": "Media",
   "timeline.posts": "Toots",
   "trends.count_by_accounts": "{count} {rawCount, plural, one {person} other {people}} talking",
-  "trends.header": "Trending now",
-  "trends.refresh": "Refresh",
   "ui.beforeunload": "O teu rascunho vai ser perdido se abandonares o Mastodon.",
   "upload_area.title": "Arraste e solte para enviar",
   "upload_button.label": "Adicionar media",
diff --git a/app/javascript/mastodon/locales/ru.json b/app/javascript/mastodon/locales/ru.json
index 48bcbf0fb..0ef7a32bb 100644
--- a/app/javascript/mastodon/locales/ru.json
+++ b/app/javascript/mastodon/locales/ru.json
@@ -83,6 +83,8 @@
   "confirmations.domain_block.message": "Вы на самом деле уверены, что хотите блокировать весь {domain}? В большинстве случаев нескольких отдельных блокировок или глушений достаточно.",
   "confirmations.mute.confirm": "Заглушить",
   "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.unfollow.confirm": "Отписаться",
   "confirmations.unfollow.message": "Вы уверены, что хотите отписаться от {name}?",
   "embed.instructions": "Встройте этот статус на Вашем сайте, скопировав код внизу.",
@@ -264,6 +266,7 @@
   "status.reblog": "Продвинуть",
   "status.reblog_private": "Продвинуть для своей аудитории",
   "status.reblogged_by": "{name} продвинул(а)",
+  "status.redraft": "Delete & re-draft",
   "status.reply": "Ответить",
   "status.replyAll": "Ответить на тред",
   "status.report": "Пожаловаться",
@@ -284,8 +287,6 @@
   "timeline.media": "Media",
   "timeline.posts": "Toots",
   "trends.count_by_accounts": "{count} {rawCount, plural, one {person} other {people}} talking",
-  "trends.header": "Trending now",
-  "trends.refresh": "Refresh",
   "ui.beforeunload": "Ваш черновик будет утерян, если вы покинете Mastodon.",
   "upload_area.title": "Перетащите сюда, чтобы загрузить",
   "upload_button.label": "Добавить медиаконтент",
diff --git a/app/javascript/mastodon/locales/sk.json b/app/javascript/mastodon/locales/sk.json
index 416816c60..983018dd8 100644
--- a/app/javascript/mastodon/locales/sk.json
+++ b/app/javascript/mastodon/locales/sk.json
@@ -83,6 +83,8 @@
   "confirmations.domain_block.message": "Ste si naozaj istý, že chcete blokovať celú {domain}? Vo väčšine prípadov stačí blokovať alebo ignorovať daných používateľov, čiže to sa doporučuje.",
   "confirmations.mute.confirm": "Ignoruj",
   "confirmations.mute.message": "Naozaj chcete ignorovať {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.unfollow.confirm": "Nesledovať",
   "confirmations.unfollow.message": "Naozaj chcete prestať sledovať {name}?",
   "embed.instructions": "Umiestni kód uvedený nižšie pre pridanie tohto statusu na tvoju web stránku.",
@@ -264,6 +266,7 @@
   "status.reblog": "Povýšiť",
   "status.reblog_private": "Boost to original audience",
   "status.reblogged_by": "{name} povýšil/a",
+  "status.redraft": "Delete & re-draft",
   "status.reply": "Odpovedať",
   "status.replyAll": "Odpovedať na diskusiu",
   "status.report": "Nahlásiť @{name}",
@@ -284,8 +287,6 @@
   "timeline.media": "Media",
   "timeline.posts": "Príspevky",
   "trends.count_by_accounts": "{count} {rawCount, plural, one {person} other {people}} talking",
-  "trends.header": "Trending now",
-  "trends.refresh": "Refresh",
   "ui.beforeunload": "Čo máte rozpísané sa stratí, ak opustíte Mastodon.",
   "upload_area.title": "Ťahaj a pusti pre nahratie",
   "upload_button.label": "Pridať médiá",
diff --git a/app/javascript/mastodon/locales/sl.json b/app/javascript/mastodon/locales/sl.json
index 3caa26f50..2d89b63eb 100644
--- a/app/javascript/mastodon/locales/sl.json
+++ b/app/javascript/mastodon/locales/sl.json
@@ -83,6 +83,8 @@
   "confirmations.domain_block.message": "Ali ste res, res prepričani, da želite blokirati celotno {domain}? V večini primerov je nekaj ciljnih blokiranj ali utišanj dovolj in boljše.",
   "confirmations.mute.confirm": "Utišanje",
   "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.unfollow.confirm": "Prenehaj slediti",
   "confirmations.unfollow.message": "Ali ste prepričani, da ne želite več slediti {name}?",
   "embed.instructions": "Vstavi ta status na svojo spletno stran tako, da kopirate spodnjo kodo.",
@@ -264,6 +266,7 @@
   "status.reblog": "Suni",
   "status.reblog_private": "Suni v prvotno občinstvo",
   "status.reblogged_by": "{name} sunjen",
+  "status.redraft": "Delete & re-draft",
   "status.reply": "Odgovori",
   "status.replyAll": "Odgovori na objavo",
   "status.report": "Prijavi @{name}",
@@ -284,8 +287,6 @@
   "timeline.media": "Media",
   "timeline.posts": "Toots",
   "trends.count_by_accounts": "{count} {rawCount, plural, one {person} other {people}} talking",
-  "trends.header": "Trending now",
-  "trends.refresh": "Refresh",
   "ui.beforeunload": "Vaš osnutek bo izgubljen, če zapustite Mastodona.",
   "upload_area.title": "Povlecite in spustite za pošiljanje",
   "upload_button.label": "Dodaj medij",
diff --git a/app/javascript/mastodon/locales/sr-Latn.json b/app/javascript/mastodon/locales/sr-Latn.json
index 45971e9d4..c17495979 100644
--- a/app/javascript/mastodon/locales/sr-Latn.json
+++ b/app/javascript/mastodon/locales/sr-Latn.json
@@ -83,6 +83,8 @@
   "confirmations.domain_block.message": "Da li ste stvarno, stvarno sigurno da želite da blokirate ceo domen {domain}? U većini slučajeva, par dobrih blokiranja ili ućutkavanja su dovoljna i preporučljiva.",
   "confirmations.mute.confirm": "Ućutkaj",
   "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.unfollow.confirm": "Otprati",
   "confirmations.unfollow.message": "Da li ste sigurni da želite da otpratite korisnika {name}?",
   "embed.instructions": "Ugradi ovaj status na Vaš veb sajt kopiranjem koda ispod.",
@@ -264,6 +266,7 @@
   "status.reblog": "Podrži",
   "status.reblog_private": "Boost to original audience",
   "status.reblogged_by": "{name} podržao(la)",
+  "status.redraft": "Delete & re-draft",
   "status.reply": "Odgovori",
   "status.replyAll": "Odgovori na diskusiju",
   "status.report": "Prijavi korisnika @{name}",
@@ -284,8 +287,6 @@
   "timeline.media": "Media",
   "timeline.posts": "Toots",
   "trends.count_by_accounts": "{count} {rawCount, plural, one {person} other {people}} talking",
-  "trends.header": "Trending now",
-  "trends.refresh": "Refresh",
   "ui.beforeunload": "Ako napustite Mastodont, izgubićete napisani nacrt.",
   "upload_area.title": "Prevucite ovde da otpremite",
   "upload_button.label": "Dodaj multimediju",
diff --git a/app/javascript/mastodon/locales/sr.json b/app/javascript/mastodon/locales/sr.json
index a9e7aca82..f11e3935c 100644
--- a/app/javascript/mastodon/locales/sr.json
+++ b/app/javascript/mastodon/locales/sr.json
@@ -83,6 +83,8 @@
   "confirmations.domain_block.message": "Да ли сте стварно, стварно сигурно да желите да блокирате цео домен {domain}? У већини случајева, пар добрих блокирања или ућуткавања су довољна и препоручљива.",
   "confirmations.mute.confirm": "Ућуткај",
   "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.unfollow.confirm": "Отпрати",
   "confirmations.unfollow.message": "Да ли сте сигурни да желите да отпратите корисника {name}?",
   "embed.instructions": "Угради овај статус на Ваш веб сајт копирањем кода испод.",
@@ -264,6 +266,7 @@
   "status.reblog": "Подржи",
   "status.reblog_private": "Boost to original audience",
   "status.reblogged_by": "{name} подржао(ла)",
+  "status.redraft": "Delete & re-draft",
   "status.reply": "Одговори",
   "status.replyAll": "Одговори на дискусију",
   "status.report": "Пријави корисника @{name}",
@@ -284,8 +287,6 @@
   "timeline.media": "Media",
   "timeline.posts": "Toots",
   "trends.count_by_accounts": "{count} {rawCount, plural, one {person} other {people}} talking",
-  "trends.header": "Trending now",
-  "trends.refresh": "Refresh",
   "ui.beforeunload": "Ако напустите Мастодонт, изгубићете написани нацрт.",
   "upload_area.title": "Превуците овде да отпремите",
   "upload_button.label": "Додај мултимедију",
diff --git a/app/javascript/mastodon/locales/sv.json b/app/javascript/mastodon/locales/sv.json
index 11bd92a87..fd0cc3268 100644
--- a/app/javascript/mastodon/locales/sv.json
+++ b/app/javascript/mastodon/locales/sv.json
@@ -83,6 +83,8 @@
   "confirmations.domain_block.message": "Är du verkligen, verkligen säker på att du vill blockera hela {domain}? I de flesta fall är några riktade blockeringar eller nedtystade tillräckligt och föredras.",
   "confirmations.mute.confirm": "Tysta",
   "confirmations.mute.message": "Är du säker du vill tysta ner {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.unfollow.confirm": "Sluta följa",
   "confirmations.unfollow.message": "Är du säker på att du vill sluta följa {name}?",
   "embed.instructions": "Bädda in den här statusen på din webbplats genom att kopiera koden nedan.",
@@ -264,6 +266,7 @@
   "status.reblog": "Knuff",
   "status.reblog_private": "Knuffa till de ursprungliga åhörarna",
   "status.reblogged_by": "{name} knuffade",
+  "status.redraft": "Delete & re-draft",
   "status.reply": "Svara",
   "status.replyAll": "Svara på tråden",
   "status.report": "Rapportera @{name}",
@@ -284,8 +287,6 @@
   "timeline.media": "Media",
   "timeline.posts": "Toots",
   "trends.count_by_accounts": "{count} {rawCount, plural, one {person} other {people}} talking",
-  "trends.header": "Trending now",
-  "trends.refresh": "Refresh",
   "ui.beforeunload": "Ditt utkast kommer att förloras om du lämnar Mastodon.",
   "upload_area.title": "Dra & släpp för att ladda upp",
   "upload_button.label": "Lägg till media",
diff --git a/app/javascript/mastodon/locales/te.json b/app/javascript/mastodon/locales/te.json
index b82ce1f6c..22b164936 100644
--- a/app/javascript/mastodon/locales/te.json
+++ b/app/javascript/mastodon/locales/te.json
@@ -83,6 +83,8 @@
   "confirmations.domain_block.message": "Are you really, really sure you want to block the entire {domain}? In most cases a few targeted blocks or mutes are sufficient and preferable.",
   "confirmations.mute.confirm": "Mute",
   "confirmations.mute.message": "Are you sure you want to mute {name}?",
+  "confirmations.redraft.confirm": "Delete & redraft",
+  "confirmations.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.unfollow.confirm": "Unfollow",
   "confirmations.unfollow.message": "Are you sure you want to unfollow {name}?",
   "embed.instructions": "Embed this status on your website by copying the code below.",
@@ -264,6 +266,7 @@
   "status.reblog": "Boost",
   "status.reblog_private": "Boost to original audience",
   "status.reblogged_by": "{name} boosted",
+  "status.redraft": "Delete & re-draft",
   "status.reply": "Reply",
   "status.replyAll": "Reply to thread",
   "status.report": "Report @{name}",
@@ -284,8 +287,6 @@
   "timeline.media": "Media",
   "timeline.posts": "Toots",
   "trends.count_by_accounts": "{count} {rawCount, plural, one {person} other {people}} talking",
-  "trends.header": "Trending now",
-  "trends.refresh": "Refresh",
   "ui.beforeunload": "Your draft will be lost if you leave Mastodon.",
   "upload_area.title": "Drag & drop to upload",
   "upload_button.label": "Add media",
diff --git a/app/javascript/mastodon/locales/th.json b/app/javascript/mastodon/locales/th.json
index 229189b56..57fe1b5d9 100644
--- a/app/javascript/mastodon/locales/th.json
+++ b/app/javascript/mastodon/locales/th.json
@@ -83,6 +83,8 @@
   "confirmations.domain_block.message": "Are you really, really sure you want to block the entire {domain}? In most cases a few targeted blocks or mutes are sufficient and preferable.",
   "confirmations.mute.confirm": "Mute",
   "confirmations.mute.message": "Are you sure you want to mute {name}?",
+  "confirmations.redraft.confirm": "Delete & redraft",
+  "confirmations.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.unfollow.confirm": "Unfollow",
   "confirmations.unfollow.message": "Are you sure you want to unfollow {name}?",
   "embed.instructions": "Embed this status on your website by copying the code below.",
@@ -264,6 +266,7 @@
   "status.reblog": "Boost",
   "status.reblog_private": "Boost to original audience",
   "status.reblogged_by": "{name} boosted",
+  "status.redraft": "Delete & re-draft",
   "status.reply": "Reply",
   "status.replyAll": "Reply to thread",
   "status.report": "Report @{name}",
@@ -284,8 +287,6 @@
   "timeline.media": "Media",
   "timeline.posts": "Toots",
   "trends.count_by_accounts": "{count} {rawCount, plural, one {person} other {people}} talking",
-  "trends.header": "Trending now",
-  "trends.refresh": "Refresh",
   "ui.beforeunload": "Your draft will be lost if you leave Mastodon.",
   "upload_area.title": "Drag & drop to upload",
   "upload_button.label": "Add media",
diff --git a/app/javascript/mastodon/locales/tr.json b/app/javascript/mastodon/locales/tr.json
index 30409a803..9c5e89463 100644
--- a/app/javascript/mastodon/locales/tr.json
+++ b/app/javascript/mastodon/locales/tr.json
@@ -83,6 +83,8 @@
   "confirmations.domain_block.message": "Are you really, really sure you want to block the entire {domain}? In most cases a few targeted blocks or mutes are sufficient and preferable.",
   "confirmations.mute.confirm": "Sessize al",
   "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.unfollow.confirm": "Unfollow",
   "confirmations.unfollow.message": "Are you sure you want to unfollow {name}?",
   "embed.instructions": "Embed this status on your website by copying the code below.",
@@ -264,6 +266,7 @@
   "status.reblog": "Boost'la",
   "status.reblog_private": "Boost to original audience",
   "status.reblogged_by": "{name} boost etti",
+  "status.redraft": "Delete & re-draft",
   "status.reply": "Cevapla",
   "status.replyAll": "Konuşmayı cevapla",
   "status.report": "@{name}'i raporla",
@@ -284,8 +287,6 @@
   "timeline.media": "Media",
   "timeline.posts": "Toots",
   "trends.count_by_accounts": "{count} {rawCount, plural, one {person} other {people}} talking",
-  "trends.header": "Trending now",
-  "trends.refresh": "Refresh",
   "ui.beforeunload": "Your draft will be lost if you leave Mastodon.",
   "upload_area.title": "Upload için sürükle bırak yapınız",
   "upload_button.label": "Görsel ekle",
diff --git a/app/javascript/mastodon/locales/uk.json b/app/javascript/mastodon/locales/uk.json
index 5c6394b61..0f76a0045 100644
--- a/app/javascript/mastodon/locales/uk.json
+++ b/app/javascript/mastodon/locales/uk.json
@@ -83,6 +83,8 @@
   "confirmations.domain_block.message": "Ви точно, точно впевнені, що хочете заблокувати весь домен {domain}? У більшості випадків для нормальної роботи краще заблокувати/заглушити лише деяких користувачів.",
   "confirmations.mute.confirm": "Заглушити",
   "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.unfollow.confirm": "Unfollow",
   "confirmations.unfollow.message": "Are you sure you want to unfollow {name}?",
   "embed.instructions": "Embed this status on your website by copying the code below.",
@@ -264,6 +266,7 @@
   "status.reblog": "Передмухнути",
   "status.reblog_private": "Boost to original audience",
   "status.reblogged_by": "{name} передмухнув(-ла)",
+  "status.redraft": "Delete & re-draft",
   "status.reply": "Відповісти",
   "status.replyAll": "Відповісти на тред",
   "status.report": "Поскаржитися",
@@ -284,8 +287,6 @@
   "timeline.media": "Media",
   "timeline.posts": "Toots",
   "trends.count_by_accounts": "{count} {rawCount, plural, one {person} other {people}} talking",
-  "trends.header": "Trending now",
-  "trends.refresh": "Refresh",
   "ui.beforeunload": "Your draft will be lost if you leave Mastodon.",
   "upload_area.title": "Перетягніть сюди, щоб завантажити",
   "upload_button.label": "Додати медіаконтент",
diff --git a/app/javascript/mastodon/locales/zh-CN.json b/app/javascript/mastodon/locales/zh-CN.json
index 854c9fcdd..24bab6f80 100644
--- a/app/javascript/mastodon/locales/zh-CN.json
+++ b/app/javascript/mastodon/locales/zh-CN.json
@@ -83,6 +83,8 @@
   "confirmations.domain_block.message": "你真的确定要隐藏所有来自 {domain} 的内容吗?多数情况下,屏蔽或隐藏几个特定的用户应该就能满足你的需要了。",
   "confirmations.mute.confirm": "隐藏",
   "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.unfollow.confirm": "取消关注",
   "confirmations.unfollow.message": "你确定要取消关注 {name} 吗?",
   "embed.instructions": "要在你的网站上嵌入这条嘟文,请复制以下代码。",
@@ -264,6 +266,7 @@
   "status.reblog": "转嘟",
   "status.reblog_private": "转嘟给原有关注者",
   "status.reblogged_by": "{name} 转嘟了",
+  "status.redraft": "Delete & re-draft",
   "status.reply": "回复",
   "status.replyAll": "回复所有人",
   "status.report": "举报 @{name}",
@@ -284,8 +287,6 @@
   "timeline.media": "媒体",
   "timeline.posts": "嘟文",
   "trends.count_by_accounts": "{count} {rawCount, plural, one {person} other {people}} talking",
-  "trends.header": "Trending now",
-  "trends.refresh": "Refresh",
   "ui.beforeunload": "如果你现在离开 Mastodon,你的草稿内容将会被丢弃。",
   "upload_area.title": "将文件拖放到此处开始上传",
   "upload_button.label": "上传媒体文件",
diff --git a/app/javascript/mastodon/locales/zh-HK.json b/app/javascript/mastodon/locales/zh-HK.json
index 1fea2ced3..578f03842 100644
--- a/app/javascript/mastodon/locales/zh-HK.json
+++ b/app/javascript/mastodon/locales/zh-HK.json
@@ -83,6 +83,8 @@
   "confirmations.domain_block.message": "你真的真的確定要隱藏整個 {domain} ?多數情況下,比較推薦封鎖或靜音幾個特定目標就好。",
   "confirmations.mute.confirm": "靜音",
   "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.unfollow.confirm": "取消關注",
   "confirmations.unfollow.message": "真的不要繼續關注 {name} 了嗎?",
   "embed.instructions": "要內嵌此文章,請將以下代碼貼進你的網站。",
@@ -264,6 +266,7 @@
   "status.reblog": "轉推",
   "status.reblog_private": "轉推到原讀者",
   "status.reblogged_by": "{name} 轉推",
+  "status.redraft": "Delete & re-draft",
   "status.reply": "回應",
   "status.replyAll": "回應所有人",
   "status.report": "舉報 @{name}",
@@ -284,8 +287,6 @@
   "timeline.media": "Media",
   "timeline.posts": "文章",
   "trends.count_by_accounts": "{count} 位用戶在討論",
-  "trends.header": "現時趨勢",
-  "trends.refresh": "重新載入",
   "ui.beforeunload": "如果你現在離開 Mastodon,你的草稿內容將會被丟棄。",
   "upload_area.title": "將檔案拖放至此上載",
   "upload_button.label": "上載媒體檔案",
diff --git a/app/javascript/mastodon/locales/zh-TW.json b/app/javascript/mastodon/locales/zh-TW.json
index 3f1bc19be..88dd4ac6d 100644
--- a/app/javascript/mastodon/locales/zh-TW.json
+++ b/app/javascript/mastodon/locales/zh-TW.json
@@ -83,6 +83,8 @@
   "confirmations.domain_block.message": "你真的真的確定要隱藏整個 {domain} ?多數情況下,比較推薦封鎖或消音幾個特定目標就好。",
   "confirmations.mute.confirm": "消音",
   "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.unfollow.confirm": "取消關注",
   "confirmations.unfollow.message": "真的不要繼續關注 {name} 了嗎?",
   "embed.instructions": "要內嵌此貼文,請將以下代碼貼進你的網站。",
@@ -264,6 +266,7 @@
   "status.reblog": "轉推",
   "status.reblog_private": "Boost to original audience",
   "status.reblogged_by": "{name} 轉推了",
+  "status.redraft": "Delete & re-draft",
   "status.reply": "回應",
   "status.replyAll": "回應這串",
   "status.report": "通報 @{name}",
@@ -284,8 +287,6 @@
   "timeline.media": "Media",
   "timeline.posts": "Toots",
   "trends.count_by_accounts": "{count} {rawCount, plural, one {person} other {people}} talking",
-  "trends.header": "Trending now",
-  "trends.refresh": "Refresh",
   "ui.beforeunload": "如果離開 Mastodon,你的草稿將會不見。",
   "upload_area.title": "拖放來上傳",
   "upload_button.label": "增加媒體",
diff --git a/app/javascript/mastodon/reducers/compose.js b/app/javascript/mastodon/reducers/compose.js
index 62461d1a7..8524ddb8e 100644
--- a/app/javascript/mastodon/reducers/compose.js
+++ b/app/javascript/mastodon/reducers/compose.js
@@ -32,9 +32,11 @@ import {
 } from '../actions/compose';
 import { TIMELINE_DELETE } from '../actions/timelines';
 import { STORE_HYDRATE } from '../actions/store';
+import { REDRAFT } from '../actions/statuses';
 import { Map as ImmutableMap, List as ImmutableList, OrderedSet as ImmutableOrderedSet, fromJS } from 'immutable';
 import uuid from '../uuid';
 import { me } from '../initial_state';
+import { unescapeHTML } from '../utils/html';
 
 const initialState = ImmutableMap({
   mounted: 0,
@@ -170,6 +172,18 @@ const hydrate = (state, hydratedState) => {
   return state;
 };
 
+const domParser = new DOMParser();
+
+const expandMentions = status => {
+  const fragment = domParser.parseFromString(status.get('content'), 'text/html').documentElement;
+
+  status.get('mentions').forEach(mention => {
+    fragment.querySelector(`a[href="${mention.get('url')}"]`).textContent = `@${mention.get('acct')}`;
+  });
+
+  return fragment.innerHTML;
+};
+
 export default function compose(state = initialState, action) {
   switch(action.type) {
   case STORE_HYDRATE:
@@ -301,6 +315,24 @@ export default function compose(state = initialState, action) {
 
         return item;
       }));
+  case REDRAFT:
+    return state.withMutations(map => {
+      map.set('text', unescapeHTML(expandMentions(action.status)));
+      map.set('in_reply_to', action.status.get('in_reply_to_id'));
+      map.set('privacy', action.status.get('visibility'));
+      map.set('media_attachments', action.status.get('media_attachments'));
+      map.set('focusDate', new Date());
+      map.set('caretPosition', null);
+      map.set('idempotencyKey', uuid());
+
+      if (action.status.get('spoiler_text').length > 0) {
+        map.set('spoiler', true);
+        map.set('spoiler_text', action.status.get('spoiler_text'));
+      } else {
+        map.set('spoiler', false);
+        map.set('spoiler_text', '');
+      }
+    });
   default:
     return state;
   }
diff --git a/app/javascript/mastodon/utils/html.js b/app/javascript/mastodon/utils/html.js
index 0b646ce58..5159df9db 100644
--- a/app/javascript/mastodon/utils/html.js
+++ b/app/javascript/mastodon/utils/html.js
@@ -1,6 +1,5 @@
 export const unescapeHTML = (html) => {
   const wrapper = document.createElement('div');
-  html = html.replace(/<br \/>|<br>|\n/g, ' ');
-  wrapper.innerHTML = html;
+  wrapper.innerHTML = html.replace(/<br\s*\/?>/g, '\n').replace(/<\/p><p>/g, '\n\n').replace(/<[^>]*>/g, '');
   return wrapper.textContent;
 };
diff --git a/app/javascript/mastodon/utils/numbers.js b/app/javascript/mastodon/utils/numbers.js
new file mode 100644
index 000000000..fdd8269ae
--- /dev/null
+++ b/app/javascript/mastodon/utils/numbers.js
@@ -0,0 +1,10 @@
+import React, { Fragment } from 'react';
+import { FormattedNumber } from 'react-intl';
+
+export const shortNumberFormat = number => {
+  if (number < 1000) {
+    return <FormattedNumber value={number} />;
+  } else {
+    return <Fragment><FormattedNumber value={number / 1000} maximumFractionDigits={1} />K</Fragment>;
+  }
+};
diff --git a/app/javascript/styles/mastodon-light/diff.scss b/app/javascript/styles/mastodon-light/diff.scss
index fe304317d..460dc53a9 100644
--- a/app/javascript/styles/mastodon-light/diff.scss
+++ b/app/javascript/styles/mastodon-light/diff.scss
@@ -26,20 +26,20 @@
 }
 
 .compose-form .compose-form__modifiers .compose-form__upload__actions .icon-button {
-  color: $ui-base-color;
+  color: lighten($white, 7%);
 
   &:active,
   &:focus,
   &:hover {
-    color: darken($ui-base-color, 7%);
+    color: $white;
   }
 }
 
 .compose-form .compose-form__modifiers .compose-form__upload-description input {
-  color: $ui-base-color;
+  color: lighten($white, 7%);
 
   &::placeholder {
-    color: $ui-base-color;
+    color: lighten($white, 7%);
   }
 }
 
@@ -100,7 +100,7 @@
 .dropdown-menu__item {
   a {
     background: $ui-base-color;
-    color: $ui-secondary-color;
+    color: $darker-text-color;
   }
 }
 
@@ -189,17 +189,18 @@
 // Change the default colors used on some parts of the profile pages
 .activity-stream-tabs {
   background: $account-background-color;
-
-  a {
-    &.active {
-      color: $ui-primary-color;
-    }
-  }
+  border-bottom-color: lighten($ui-base-color, 8%);
 }
 
 .activity-stream {
   .entry {
     background: $account-background-color;
+
+    .detailed-status.light,
+    .more.light,
+    .status.light {
+      border-bottom-color: lighten($ui-base-color, 8%);
+    }
   }
 
   .status.light {
@@ -219,7 +220,7 @@
   .account-grid-card {
     .controls {
       .icon-button {
-        color: $ui-secondary-color;
+        color: $darker-text-color;
       }
     }
 
@@ -230,7 +231,7 @@
     }
 
     .username {
-      color: $ui-secondary-color;
+      color: $darker-text-color;
     }
 
     .account__header__content {
diff --git a/app/javascript/styles/mastodon/tables.scss b/app/javascript/styles/mastodon/tables.scss
index 982bfd990..e54c55947 100644
--- a/app/javascript/styles/mastodon/tables.scss
+++ b/app/javascript/styles/mastodon/tables.scss
@@ -195,6 +195,7 @@ a.table-action-link {
       font-weight: 700;
       background: linear-gradient(to right, orange , yellow, green, cyan, blue, violet,orange , yellow, green, cyan, blue, violet);
       background-size: 200% 100%;
+      -webkit-background-clip: text;
       background-clip: text;
       color: transparent;
       animation: Swag 2s linear 0s infinite;
diff --git a/app/models/concerns/remotable.rb b/app/models/concerns/remotable.rb
index c17f04776..c17f19a60 100644
--- a/app/models/concerns/remotable.rb
+++ b/app/models/concerns/remotable.rb
@@ -24,14 +24,17 @@ module Remotable
           Request.new(:get, url).perform do |response|
             next if response.code != 200
 
-            matches  = response.headers['content-disposition']&.match(/filename="([^"]*)"/)
-            filename = matches.nil? ? parsed_url.path.split('/').last : matches[1]
+            content_type = parse_content_type(response.headers.get('content-type').last)
+            extname      = detect_extname_from_content_type(content_type)
+
+            if extname.nil?
+              disposition = response.headers.get('content-disposition').last
+              matches     = disposition&.match(/filename="([^"]*)"/)
+              filename    = matches.nil? ? parsed_url.path.split('/').last : matches[1]
+              extname     = filename.nil? ? '' : File.extname(filename)
+            end
+
             basename = SecureRandom.hex(8)
-            extname = if filename.nil?
-                        ''
-                      else
-                        File.extname(filename)
-                      end
 
             send("#{attachment_name}=", StringIO.new(response.body_with_limit(limit)))
             send("#{attachment_name}_file_name=", basename + extname)
@@ -57,4 +60,26 @@ module Remotable
       end
     end
   end
+
+  private
+
+  def detect_extname_from_content_type(content_type)
+    return if content_type.nil?
+
+    type = MIME::Types[content_type].first
+
+    return if type.nil?
+
+    extname = type.extensions.first
+
+    return if extname.nil?
+
+    ".#{extname}"
+  end
+
+  def parse_content_type(content_type)
+    return if content_type.nil?
+
+    content_type.split(/\s*;\s*/).first
+  end
 end
diff --git a/app/models/concerns/status_threading_concern.rb b/app/models/concerns/status_threading_concern.rb
index 1ba8fc693..fa441469c 100644
--- a/app/models/concerns/status_threading_concern.rb
+++ b/app/models/concerns/status_threading_concern.rb
@@ -51,12 +51,16 @@ module StatusThreadingConcern
   end
 
   def descendant_statuses(limit, max_child_id, since_child_id, depth)
-    Status.find_by_sql([<<-SQL.squish, id: id, limit: limit, max_child_id: max_child_id, since_child_id: since_child_id, depth: depth])
+    # use limit + 1 and depth + 1 because 'self' is included
+    depth += 1 if depth.present?
+    limit += 1 if limit.present?
+
+    descendants_with_self = Status.find_by_sql([<<-SQL.squish, id: id, limit: limit, max_child_id: max_child_id, since_child_id: since_child_id, depth: depth])
       WITH RECURSIVE search_tree(id, path)
       AS (
         SELECT id, ARRAY[id]
         FROM statuses
-        WHERE in_reply_to_id = :id AND COALESCE(id < :max_child_id, TRUE) AND COALESCE(id > :since_child_id, TRUE)
+        WHERE id = :id AND COALESCE(id < :max_child_id, TRUE) AND COALESCE(id > :since_child_id, TRUE)
         UNION ALL
         SELECT statuses.id, path || statuses.id
         FROM search_tree
@@ -68,6 +72,8 @@ module StatusThreadingConcern
       ORDER BY path
       LIMIT :limit
     SQL
+
+    descendants_with_self - [self]
   end
 
   def find_statuses_from_tree_path(ids, account)
diff --git a/app/models/status.rb b/app/models/status.rb
index 69fae2eb6..c0e241ddd 100644
--- a/app/models/status.rb
+++ b/app/models/status.rb
@@ -55,7 +55,7 @@ class Status < ApplicationRecord
   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 :media_attachments, dependent: :destroy
+  has_many :media_attachments, dependent: :nullify
 
   has_and_belongs_to_many :tags
   has_and_belongs_to_many :preview_cards
@@ -194,7 +194,6 @@ class Status < ApplicationRecord
   before_validation :set_reblog
   before_validation :set_visibility
   before_validation :set_conversation
-  before_validation :set_sensitivity
   before_validation :set_local
 
   class << self
@@ -317,7 +316,11 @@ class Status < ApplicationRecord
         # non-followers can see everything that isn't private/direct, but can see stuff they are mentioned in.
         visibility.push(:private) if account.following?(target_account)
 
-        where(visibility: visibility).or(where(id: account.mentions.select(:status_id)))
+        scope = left_outer_joins(:reblog)
+
+        scope.where(visibility: visibility)
+             .or(scope.where(id: account.mentions.select(:status_id)))
+             .merge(scope.where(reblog_of_id: nil).or(scope.where.not(reblogs_statuses: { account_id: account.excluded_from_timeline_account_ids })))
       end
     end
 
@@ -388,10 +391,6 @@ class Status < ApplicationRecord
     self.sensitive  = false if sensitive.nil?
   end
 
-  def set_sensitivity
-    self.sensitive = sensitive || spoiler_text.present?
-  end
-
   def set_locality
     if account.domain.nil? && !attribute_changed?(:local_only)
       self.local_only = marked_local_only?
diff --git a/app/services/fetch_link_card_service.rb b/app/services/fetch_link_card_service.rb
index 86d0f9971..560a81768 100644
--- a/app/services/fetch_link_card_service.rb
+++ b/app/services/fetch_link_card_service.rb
@@ -40,7 +40,7 @@ class FetchLinkCardService < BaseService
     @card ||= PreviewCard.new(url: @url)
 
     failed = Request.new(:head, @url).perform do |res|
-      res.code != 405 && (res.code != 200 || res.mime_type != 'text/html')
+      res.code != 405 && res.code != 501 && (res.code != 200 || res.mime_type != 'text/html')
     end
 
     return if failed
diff --git a/app/services/post_status_service.rb b/app/services/post_status_service.rb
index b1d5bd3a7..6e982c7e6 100644
--- a/app/services/post_status_service.rb
+++ b/app/services/post_status_service.rb
@@ -28,7 +28,7 @@ class PostStatusService < BaseService
       status = account.statuses.create!(text: text,
                                         media_attachments: media || [],
                                         thread: in_reply_to,
-                                        sensitive: (options[:sensitive].nil? ? account.user&.setting_default_sensitive : options[:sensitive]),
+                                        sensitive: (options[:sensitive].nil? ? account.user&.setting_default_sensitive : options[:sensitive]) || options[:spoiler_text].present?,
                                         spoiler_text: options[:spoiler_text] || '',
                                         visibility: options[:visibility] || account.user&.setting_default_privacy,
                                         language: language_from_option(options[:language]) || LanguageDetector.instance.detect(text, account),
diff --git a/app/views/admin/accounts/_account.html.haml b/app/views/admin/accounts/_account.html.haml
index dfa7c5649..c6e63152d 100644
--- a/app/views/admin/accounts/_account.html.haml
+++ b/app/views/admin/accounts/_account.html.haml
@@ -1,7 +1,7 @@
 %tr
   %td.username
     = account.username
-  %td.domain
+  %td
     - unless account.local?
       = link_to account.domain, admin_accounts_path(by_domain: account.domain)
   %td
diff --git a/config/locales/doorkeeper.eu.yml b/config/locales/doorkeeper.eu.yml
index 9fe6ea961..aba3166ac 100644
--- a/config/locales/doorkeeper.eu.yml
+++ b/config/locales/doorkeeper.eu.yml
@@ -117,4 +117,4 @@ eu:
       follow: jarraitu kontuak, blokeatu, utzi jarraitzeari eta desblokeatu
       push: jaso zure kontuaren push jakinarazpenak
       read: irakurri zure kontuko datuak
-      write: argitaratu zure izenean
+      write: zure izenean argitaratu
diff --git a/config/locales/en.yml b/config/locales/en.yml
index 3c2a8c3db..66d181851 100644
--- a/config/locales/en.yml
+++ b/config/locales/en.yml
@@ -424,7 +424,7 @@ en:
     following: 'Success! You are now following:'
     post_follow:
       close: Or, you can just close this window.
-      return: Return to the user's profile
+      return: Show the user's profile
       web: Go to web
     title: Follow %{acct}
   datetime:
diff --git a/config/locales/eu.yml b/config/locales/eu.yml
index c0b824c9a..1f3588b30 100644
--- a/config/locales/eu.yml
+++ b/config/locales/eu.yml
@@ -153,14 +153,14 @@ eu:
     action_logs:
       actions:
         assigned_to_self_report: "%{name}(e)k %{target} salaketa bere buruari esleitu dio"
-        change_email_user: "%{name}(e)k %{target}(r)en helbide elektronikoa aldatu du"
-        confirm_user: "%{name}(e)k %{target}(r)en helbide elektronikoa berretsi du"
+        change_email_user: "%{name}(e)k %{target}(r)en e-mail helbidea aldatu du"
+        confirm_user: "%{name}(e)k %{target}(r)en e-mail helbidea berretsi du"
         create_custom_emoji: "%{name}(e)k emoji berria kargatu du %{target}"
         create_domain_block: "%{name}(e)k %{target} domeinua blokeatu du"
-        create_email_domain_block: "%{name}(e)k %{target} helbide elektronikoen domeinua zerrenda beltzean sartu du"
+        create_email_domain_block: "%{name}(e)k %{target} e-mail helbideen domeinua zerrenda beltzean sartu du"
         demote_user: "%{name}(e)k %{target} mailaz jaitsi du"
         destroy_domain_block: "%{name}(e)k %{target} domeinua desblokeatu du"
-        destroy_email_domain_block: "%{name}(e)k %{target} helbide elektronikoen domeinua zerrenda zurian sartu du"
+        destroy_email_domain_block: "%{name}(e)k %{target} e-mail helbideen domeinua zerrenda zurian sartu du"
         destroy_status: "%{name}(e)k %{target}(e)n egoera kendu du"
         disable_2fa_user: "%{name}(e)k %{target}(r)i bi faktoreetako eskaera kendu dio"
         disable_custom_emoji: "%{name}(e)k %{target} emoji-a desgaitu du"
@@ -356,8 +356,8 @@ eu:
       back_to_account: Atzera kontuaren orrira
       batch:
         delete: Ezabatu
-        nsfw_off: Markatu ez mingarri gisa
-        nsfw_on: Markatu mingarri gisa
+        nsfw_off: Markatu ez hunkigarri gisa
+        nsfw_on: Markatu hunkigarri gisa
       failed_to_execute: Ezin izan da burutu
       media:
         title: Multimedia
@@ -694,7 +694,7 @@ eu:
     click_to_show: Klik erakusteko
     pinned: Finkatutako toot-a
     reblogged: bultzatua
-    sensitive_content: Eduki mingarria
+    sensitive_content: Eduki hunkigarria
   terms:
     body_html: |
       <h2>Pribatutasun politika</h2>
diff --git a/config/locales/pl.yml b/config/locales/pl.yml
index ac585368a..15f9cc7dd 100644
--- a/config/locales/pl.yml
+++ b/config/locales/pl.yml
@@ -425,7 +425,7 @@ pl:
     following: 'Pomyślnie! Od teraz śledzisz:'
     post_follow:
       close: Ewentualnie, możesz po prostu zamknąć tę stronę.
-      return: Powróć do strony użytkownika
+      return: Pokaż stronę użytkownika
       web: Przejdź do sieci
     title: Śledź %{acct}
   datetime:
@@ -784,9 +784,13 @@ pl:
 
       <hr class="spacer" />
 
-      <h3 id="coppa">Children's Online Privacy Protection Act Compliance</h3>
+      <h3 id="children">Korzystanie ze strony przez dzieci</h3>
 
-      <p>Ta strona, produkty i usługi są przeznaczone dla osób, które ukończyły 13 lat. Jeżeli serwer znajduje się w USA, a nie ukończyłeś 13 roku życia, zgodnie z wymogami COPPA (<a href="https://pl.wikipedia.org/wiki/Children%27s_Online_Privacy_Protection_Act">Prawo o Ochronie Prywatności Dzieci w Internecie</a>), nie używaj tej strony.</p>
+      <p>Jeżeli serwer znajduje się w UE lub w EOG: Ta strona, produkty i usługi są przeznaczone dla osób, które ukończyły 16 lat. Jeżeli nie ukończyłeś 16 roku życia, zgodnie z wymogami COPPA (<a href="https://pl.wikipedia.org/wiki/Children%27s_Online_Privacy_Protection_Act">Prawo o Ochronie Prywatności Dzieci w Internecie</a>), nie używaj tej strony.</p>
+
+      <p>Jeżeli serwer znajduje się w USA: Ta strona, produkty i usługi są przeznaczone dla osób, które ukończyły 13 lat. Jeżeli nie ukończyłeś 13 roku życia, zgodnie z wymogami RODO (<a href="https://pl.wikipedia.org/wiki/Ogólne_rozporządzenie_o_ochronie_danych">Ogólne rozporządzenie o ochronie danych</a>), nie używaj tej strony.</p>
+
+      <p>Wymogi mogą być inne, jeżeli serwer znajduje się w innym kraju.</p>
 
       <hr class="spacer" />
 
diff --git a/config/locales/simple_form.eu.yml b/config/locales/simple_form.eu.yml
index a2720ac5d..364a2e118 100644
--- a/config/locales/simple_form.eu.yml
+++ b/config/locales/simple_form.eu.yml
@@ -37,7 +37,7 @@ eu:
         current_password: Oraingo pasahitza
         data: Datuak
         display_name: Pantaila-izena
-        email: Helbide elektronikoa
+        email: E-mail helbidea
         expires_in: Iraungitzea
         fields: Profilaren metadatuak
         filtered_languages: Iragazitako hizkuntzak
@@ -49,14 +49,14 @@ eu:
         note: Biografia
         otp_attempt: Bi faktoreetako kodea
         password: Pasahitza
-        setting_auto_play_gif: Automatikoki abiatu GIF animatuak
+        setting_auto_play_gif: Erreproduzitu GIF animatuak automatikoki
         setting_boost_modal: Erakutsi baieztapen elkarrizketa-koadroa bultzada eman aurretik
         setting_default_privacy: Mezuen pribatutasuna
-        setting_default_sensitive: Beti markatu edukiak mingarri gisa
+        setting_default_sensitive: Beti markatu edukiak hunkigarri gisa
         setting_delete_modal: Erakutsi baieztapen elkarrizketa-koadroa toot bat ezabatu aurretik
-        setting_display_sensitive_media: Beti erakutsi mingarri marka duen edukia
+        setting_display_sensitive_media: Beti erakutsi hunkigarri gisa markatutako edukia
         setting_hide_network: Ezkutatu zure sarea
-        setting_noindex: Atera bilaketa motorraren idexaziotik
+        setting_noindex: Atera bilaketa motorraren indexaziotik
         setting_reduce_motion: Murriztu animazioen mugimenduak
         setting_system_font_ui: Erabili sistemako tipografia lehenetsia
         setting_theme: Gunearen gaia
diff --git a/config/locales/sk.yml b/config/locales/sk.yml
index e2f6b7947..027715c04 100644
--- a/config/locales/sk.yml
+++ b/config/locales/sk.yml
@@ -50,6 +50,7 @@ sk:
     reserved_username: Prihlasovacie meno je rezervované
     roles:
       admin: Administrátor
+      bot: Automat
       moderator: Moderátor
     unfollow: Prestať sledovať
   admin:
diff --git a/lib/mastodon/version.rb b/lib/mastodon/version.rb
index 622103ea4..6ccf73f36 100644
--- a/lib/mastodon/version.rb
+++ b/lib/mastodon/version.rb
@@ -21,7 +21,7 @@ module Mastodon
     end
 
     def flags
-      'rc1'
+      'rc3'
     end
 
     def to_a
diff --git a/lib/tasks/mastodon.rake b/lib/tasks/mastodon.rake
index 8ff29ea9e..de8c0bb86 100644
--- a/lib/tasks/mastodon.rake
+++ b/lib/tasks/mastodon.rake
@@ -561,7 +561,7 @@ namespace :mastodon do
 
     desc 'Generates home timelines for users who logged in in the past two weeks'
     task build: :environment do
-      User.active.select(:account_id).find_in_batches do |users|
+      User.active.select(:id, :account_id).find_in_batches do |users|
         RegenerationWorker.push_bulk(users.map(&:account_id))
       end
     end
diff --git a/spec/controllers/api/web/embeds_controller_spec.rb b/spec/controllers/api/web/embeds_controller_spec.rb
new file mode 100644
index 000000000..6b7297189
--- /dev/null
+++ b/spec/controllers/api/web/embeds_controller_spec.rb
@@ -0,0 +1,52 @@
+# frozen_string_literal: true
+
+require 'rails_helper'
+
+describe Api::Web::EmbedsController do
+  render_views
+
+  let(:user) { Fabricate(:user) }
+  before { sign_in user }
+
+  describe 'POST #create' do
+    subject(:response) { post :create, params: { url: url } }
+    subject(:body) { JSON.parse(response.body, symbolize_names: true) }
+
+    context 'when successfully finds status' do
+      let(:status) { Fabricate(:status) }
+      let(:url) { "http://#{ Rails.configuration.x.web_domain }/@#{status.account.username}/#{status.id}" }
+
+      it 'returns a right response' do
+        expect(response).to have_http_status :ok
+        expect(body[:author_name]).to eq status.account.username
+      end
+    end
+
+    context 'when fails to find status' do
+      let(:url) { 'https://host.test/oembed.html' }
+      let(:service_instance) { double('fetch_oembed_service') }
+
+      before do
+        allow(FetchOEmbedService).to receive(:new) { service_instance }
+        allow(service_instance).to receive(:call) { call_result }
+      end
+
+      context 'when successfully fetching oembed' do
+        let(:call_result) { { result: :ok } }
+
+        it 'returns a right response' do
+          expect(response).to have_http_status :ok
+          expect(body[:result]).to eq 'ok'
+        end
+      end
+
+      context 'when fails to fetch oembed' do
+        let(:call_result) { nil }
+
+        it 'returns a right response' do
+          expect(response).to have_http_status :not_found
+        end
+      end
+    end
+  end
+end
diff --git a/spec/controllers/settings/sessions_controller_spec.rb b/spec/controllers/settings/sessions_controller_spec.rb
new file mode 100644
index 000000000..52b204a6a
--- /dev/null
+++ b/spec/controllers/settings/sessions_controller_spec.rb
@@ -0,0 +1,30 @@
+require 'rails_helper'
+
+describe Settings::SessionsController do
+  render_views
+
+  let(:user) { Fabricate(:user) }
+  let(:session_activation) { Fabricate(:session_activation, user: user) }
+  before { sign_in user, scope: :user }
+
+  describe 'DELETE #destroy' do
+    subject { delete :destroy, params: { id: id } }
+
+    context 'when session activation exists' do
+      let(:id) { session_activation.id }
+
+      it 'destroys session activation' do
+        is_expected.to redirect_to edit_user_registration_path
+        expect(SessionActivation.find_by(id: id)).to be_nil
+      end
+    end
+
+    context 'when session activation does not exist' do
+      let(:id) { session_activation.id + 1000 }
+
+      it 'destroys session activation' do
+        is_expected.to have_http_status :not_found
+      end
+    end
+  end
+end
diff --git a/spec/lib/status_finder_spec.rb b/spec/lib/status_finder_spec.rb
index 3ef086736..6b4ee434f 100644
--- a/spec/lib/status_finder_spec.rb
+++ b/spec/lib/status_finder_spec.rb
@@ -6,10 +6,11 @@ describe StatusFinder do
   include RoutingHelper
 
   describe '#status' do
+    subject { described_class.new(url) }
+
     context 'with a status url' do
       let(:status) { Fabricate(:status) }
       let(:url) { short_account_status_url(account_username: status.account.username, id: status.id) }
-      subject { described_class.new(url) }
 
       it 'finds the stream entry' do
         expect(subject.status).to eq(status)
@@ -27,7 +28,6 @@ describe StatusFinder do
     context 'with a stream entry url' do
       let(:stream_entry) { Fabricate(:stream_entry) }
       let(:url) { account_stream_entry_url(stream_entry.account, stream_entry) }
-      subject { described_class.new(url) }
 
       it 'finds the stream entry' do
         expect(subject.status).to eq(stream_entry.status)
@@ -37,7 +37,6 @@ describe StatusFinder do
     context 'with a remote url even if id exists on local' do
       let(:status) { Fabricate(:status) }
       let(:url) { "https://example.com/users/test/statuses/#{status.id}" }
-      subject { described_class.new(url) }
 
       it 'raises an error' do
         expect { subject.status }.to raise_error(ActiveRecord::RecordNotFound)
@@ -46,7 +45,6 @@ describe StatusFinder do
 
     context 'with a plausible url' do
       let(:url) { 'https://example.com/users/test/updates/123/embed' }
-      subject { described_class.new(url) }
 
       it 'raises an error' do
         expect { subject.status }.to raise_error(ActiveRecord::RecordNotFound)
@@ -55,7 +53,6 @@ describe StatusFinder do
 
     context 'with an unrecognized url' do
       let(:url) { 'https://example.com/about' }
-      subject { described_class.new(url) }
 
       it 'raises an error' do
         expect { subject.status }.to raise_error(ActiveRecord::RecordNotFound)