about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--.github/workflows/build-image.yml2
-rw-r--r--app/controllers/api/web/push_subscriptions_controller.rb23
-rw-r--r--app/javascript/flavours/glitch/actions/notifications.js3
-rw-r--r--app/javascript/flavours/glitch/features/notifications/components/admin_signup.js101
-rw-r--r--app/javascript/flavours/glitch/features/notifications/components/column_settings.js16
-rw-r--r--app/javascript/flavours/glitch/features/notifications/components/notification.js14
-rw-r--r--app/javascript/flavours/glitch/reducers/settings.js3
-rw-r--r--app/javascript/mastodon/actions/notifications.js3
-rw-r--r--app/javascript/mastodon/components/loading_indicator.js2
-rw-r--r--app/javascript/mastodon/features/emoji/emoji_compressed.js2
-rw-r--r--app/javascript/mastodon/features/notifications/components/column_settings.js16
-rw-r--r--app/javascript/mastodon/features/notifications/components/notification.js25
-rw-r--r--app/javascript/mastodon/locales/ca.json4
-rw-r--r--app/javascript/mastodon/locales/da.json4
-rw-r--r--app/javascript/mastodon/locales/el.json4
-rw-r--r--app/javascript/mastodon/locales/es-AR.json4
-rw-r--r--app/javascript/mastodon/locales/es.json4
-rw-r--r--app/javascript/mastodon/locales/eu.json34
-rw-r--r--app/javascript/mastodon/locales/fi.json4
-rw-r--r--app/javascript/mastodon/locales/fr.json12
-rw-r--r--app/javascript/mastodon/locales/gl.json4
-rw-r--r--app/javascript/mastodon/locales/he.json4
-rw-r--r--app/javascript/mastodon/locales/hu.json4
-rw-r--r--app/javascript/mastodon/locales/id.json4
-rw-r--r--app/javascript/mastodon/locales/is.json4
-rw-r--r--app/javascript/mastodon/locales/it.json4
-rw-r--r--app/javascript/mastodon/locales/ja.json2
-rw-r--r--app/javascript/mastodon/locales/kmr.json4
-rw-r--r--app/javascript/mastodon/locales/ko.json4
-rw-r--r--app/javascript/mastodon/locales/lv.json4
-rw-r--r--app/javascript/mastodon/locales/pl.json4
-rw-r--r--app/javascript/mastodon/locales/pt-PT.json4
-rw-r--r--app/javascript/mastodon/locales/ru.json4
-rw-r--r--app/javascript/mastodon/locales/sq.json4
-rw-r--r--app/javascript/mastodon/locales/sv.json2
-rw-r--r--app/javascript/mastodon/locales/th.json4
-rw-r--r--app/javascript/mastodon/locales/tr.json4
-rw-r--r--app/javascript/mastodon/locales/uk.json4
-rw-r--r--app/javascript/mastodon/locales/vi.json4
-rw-r--r--app/javascript/mastodon/locales/zh-CN.json2
-rw-r--r--app/javascript/mastodon/locales/zh-TW.json14
-rw-r--r--app/javascript/mastodon/reducers/settings.js3
-rw-r--r--app/javascript/mastodon/service_worker/web_push_locales.js1
-rw-r--r--app/lib/feed_manager.rb2
-rw-r--r--app/models/notification.rb14
-rw-r--r--app/services/bootstrap_timeline_service.rb7
-rw-r--r--app/services/fetch_link_card_service.rb2
-rw-r--r--app/services/notify_service.rb44
-rw-r--r--app/views/admin_mailer/new_trending_tags.text.erb2
-rw-r--r--config/i18n-tasks.yml1
-rw-r--r--config/initializers/preload_link_headers.rb2
-rw-r--r--config/locales/activerecord.lv.yml2
-rw-r--r--config/locales/devise.th.yml2
-rw-r--r--config/locales/en.yml3
-rw-r--r--config/locales/eu.yml47
-rw-r--r--config/locales/fi.yml52
-rw-r--r--config/locales/fr.yml95
-rw-r--r--config/locales/he.yml15
-rw-r--r--config/locales/id.yml21
-rw-r--r--config/locales/ja.yml32
-rw-r--r--config/locales/ru.yml8
-rw-r--r--config/locales/simple_form.fi.yml37
-rw-r--r--config/locales/simple_form.fr.yml7
-rw-r--r--config/locales/simple_form.gl.yml2
-rw-r--r--config/locales/simple_form.id.yml7
-rw-r--r--config/locales/simple_form.ru.yml2
-rw-r--r--config/locales/simple_form.th.yml2
-rw-r--r--config/locales/th.yml37
-rw-r--r--db/migrate/20170920032311_fix_reblogs_in_feeds.rb2
-rw-r--r--lib/mastodon/statuses_cli.rb2
-rw-r--r--spec/controllers/settings/two_factor_authentication/otp_authentication_controller_spec.rb2
-rw-r--r--spec/models/web/push_subscription_spec.rb2
-rw-r--r--spec/services/block_domain_service_spec.rb2
-rw-r--r--spec/services/clear_domain_media_service_spec.rb2
-rw-r--r--spec/services/delete_account_service_spec.rb2
-rw-r--r--spec/validators/unreserved_username_validator_spec.rb4
76 files changed, 657 insertions, 178 deletions
diff --git a/.github/workflows/build-image.yml b/.github/workflows/build-image.yml
index 2d1df7211..281fa33b7 100644
--- a/.github/workflows/build-image.yml
+++ b/.github/workflows/build-image.yml
@@ -22,6 +22,7 @@ jobs:
           registry: ghcr.io
           username: ${{ github.repository_owner }}
           password: ${{ secrets.GITHUB_TOKEN }}
+        if: github.event_name != 'pull_request'
       - uses: docker/metadata-action@v3
         id: meta
         with:
@@ -31,6 +32,7 @@ jobs:
           tags: |
             type=edge,branch=main
             type=semver,pattern={{ raw }}
+            type=ref,event=pr
       - uses: docker/build-push-action@v2
         with:
           context: .
diff --git a/app/controllers/api/web/push_subscriptions_controller.rb b/app/controllers/api/web/push_subscriptions_controller.rb
index db2512e5f..5167928e9 100644
--- a/app/controllers/api/web/push_subscriptions_controller.rb
+++ b/app/controllers/api/web/push_subscriptions_controller.rb
@@ -17,17 +17,7 @@ class Api::Web::PushSubscriptionsController < Api::Web::BaseController
 
     data = {
       policy: 'all',
-
-      alerts: {
-        follow: alerts_enabled,
-        follow_request: alerts_enabled,
-        favourite: alerts_enabled,
-        reblog: alerts_enabled,
-        mention: alerts_enabled,
-        poll: alerts_enabled,
-        status: alerts_enabled,
-        update: alerts_enabled,
-      },
+      alerts: Notification::TYPES.index_with { alerts_enabled },
     }
 
     data.deep_merge!(data_params) if params[:data]
@@ -62,15 +52,6 @@ class Api::Web::PushSubscriptionsController < Api::Web::BaseController
   end
 
   def data_params
-    @data_params ||= params.require(:data).permit(:policy, alerts: [
-      :follow,
-      :follow_request,
-      :favourite,
-      :reblog,
-      :mention,
-      :poll,
-      :status,
-      :update,
-    ])
+    @data_params ||= params.require(:data).permit(:policy, alerts: Notification::TYPES)
   end
 end
diff --git a/app/javascript/flavours/glitch/actions/notifications.js b/app/javascript/flavours/glitch/actions/notifications.js
index 40430102c..42ad39efa 100644
--- a/app/javascript/flavours/glitch/actions/notifications.js
+++ b/app/javascript/flavours/glitch/actions/notifications.js
@@ -57,7 +57,7 @@ defineMessages({
 });
 
 const fetchRelatedRelationships = (dispatch, notifications) => {
-  const accountIds = notifications.filter(item => item.type === 'follow').map(item => item.account.id);
+  const accountIds = notifications.filter(item => ['follow', 'follow_request', 'admin.sign_up'].indexOf(item.type) !== -1).map(item => item.account.id);
 
   if (accountIds > 0) {
     dispatch(fetchRelationships(accountIds));
@@ -144,6 +144,7 @@ const excludeTypesFromFilter = filter => {
     'poll',
     'status',
     'update',
+    'admin.sign_up',
   ]);
 
   return allTypes.filterNot(item => item === filter).toJS();
diff --git a/app/javascript/flavours/glitch/features/notifications/components/admin_signup.js b/app/javascript/flavours/glitch/features/notifications/components/admin_signup.js
new file mode 100644
index 000000000..355ebef94
--- /dev/null
+++ b/app/javascript/flavours/glitch/features/notifications/components/admin_signup.js
@@ -0,0 +1,101 @@
+//  Package imports.
+import React from 'react';
+import ImmutablePropTypes from 'react-immutable-proptypes';
+import PropTypes from 'prop-types';
+import { FormattedMessage } from 'react-intl';
+import ImmutablePureComponent from 'react-immutable-pure-component';
+import { HotKeys } from 'react-hotkeys';
+import classNames from 'classnames';
+
+// Our imports.
+import Permalink from 'flavours/glitch/components/permalink';
+import AccountContainer from 'flavours/glitch/containers/account_container';
+import NotificationOverlayContainer from '../containers/overlay_container';
+import Icon from 'flavours/glitch/components/icon';
+
+export default class NotificationFollow extends ImmutablePureComponent {
+
+  static propTypes = {
+    hidden: PropTypes.bool,
+    id: PropTypes.string.isRequired,
+    account: ImmutablePropTypes.map.isRequired,
+    notification: ImmutablePropTypes.map.isRequired,
+    unread: PropTypes.bool,
+  };
+
+  handleMoveUp = () => {
+    const { notification, onMoveUp } = this.props;
+    onMoveUp(notification.get('id'));
+  }
+
+  handleMoveDown = () => {
+    const { notification, onMoveDown } = this.props;
+    onMoveDown(notification.get('id'));
+  }
+
+  handleOpen = () => {
+    this.handleOpenProfile();
+  }
+
+  handleOpenProfile = () => {
+    const { notification } = this.props;
+    this.context.router.history.push(`/@${notification.getIn(['account', 'acct'])}`);
+  }
+
+  handleMention = e => {
+    e.preventDefault();
+
+    const { notification, onMention } = this.props;
+    onMention(notification.get('account'), this.context.router.history);
+  }
+
+  getHandlers () {
+    return {
+      moveUp: this.handleMoveUp,
+      moveDown: this.handleMoveDown,
+      open: this.handleOpen,
+      openProfile: this.handleOpenProfile,
+      mention: this.handleMention,
+      reply: this.handleMention,
+    };
+  }
+
+  render () {
+    const { account, notification, hidden, unread } = this.props;
+
+    //  Links to the display name.
+    const displayName = account.get('display_name_html') || account.get('username');
+    const link = (
+      <bdi><Permalink
+        className='notification__display-name'
+        href={account.get('url')}
+        title={account.get('acct')}
+        to={`/@${account.get('acct')}`}
+        dangerouslySetInnerHTML={{ __html: displayName }}
+      /></bdi>
+    );
+
+    //  Renders.
+    return (
+      <HotKeys handlers={this.getHandlers()}>
+        <div className={classNames('notification notification-admin-sign-up focusable', { unread })} tabIndex='0'>
+          <div className='notification__message'>
+            <div className='notification__favourite-icon-wrapper'>
+              <Icon fixedWidth id='user-plus' />
+            </div>
+
+            <FormattedMessage
+              id='notification.admin.sign_up'
+              defaultMessage='{name} signed up'
+              values={{ name: link }}
+            />
+          </div>
+
+          <AccountContainer hidden={hidden} id={account.get('id')} withNote={false} />
+          <NotificationOverlayContainer notification={notification} />
+        </div>
+      </HotKeys>
+    );
+  }
+
+}
diff --git a/app/javascript/flavours/glitch/features/notifications/components/column_settings.js b/app/javascript/flavours/glitch/features/notifications/components/column_settings.js
index 569ba4db0..0dad079ad 100644
--- a/app/javascript/flavours/glitch/features/notifications/components/column_settings.js
+++ b/app/javascript/flavours/glitch/features/notifications/components/column_settings.js
@@ -6,6 +6,7 @@ import ClearColumnButton from './clear_column_button';
 import GrantPermissionButton from './grant_permission_button';
 import SettingToggle from './setting_toggle';
 import PillBarButton from './pill_bar_button';
+import { isStaff } from 'flavours/glitch/util/initial_state';
 
 export default class ColumnSettings extends React.PureComponent {
 
@@ -156,7 +157,7 @@ export default class ColumnSettings extends React.PureComponent {
         </div>
 
         <div role='group' aria-labelledby='notifications-update'>
-          <span id='notifications-status' className='column-settings__section'><FormattedMessage id='notifications.column_settings.update' defaultMessage='Edits:' /></span>
+          <span id='notifications-update' className='column-settings__section'><FormattedMessage id='notifications.column_settings.update' defaultMessage='Edits:' /></span>
 
           <div className='column-settings__pillbar'>
             <PillBarButton disabled={browserPermission === 'denied'} prefix='notifications_desktop' settings={settings} settingPath={['alerts', 'update']} onChange={onChange} label={alertStr} />
@@ -165,6 +166,19 @@ export default class ColumnSettings extends React.PureComponent {
             <PillBarButton prefix='notifications' settings={settings} settingPath={['sounds', 'update']} onChange={onChange} label={soundStr} />
           </div>
         </div>
+
+        {isStaff && (
+          <div role='group' aria-labelledby='notifications-admin-sign-up'>
+            <span id='notifications-status' className='column-settings__section'><FormattedMessage id='notifications.column_settings.admin.sign_up' defaultMessage='New sign-ups:' /></span>
+
+            <div className='column-settings__pillbar'>
+              <PillBarButton disabled={browserPermission === 'denied'} prefix='notifications_desktop' settings={settings} settingPath={['alerts', 'admin.sign_up']} onChange={onChange} label={alertStr} />
+              {showPushSettings && <PillBarButton prefix='notifications_push' settings={pushSettings} settingPath={['alerts', 'admin.sign_up']} onChange={this.onPushChange} label={pushStr} />}
+              <PillBarButton prefix='notifications' settings={settings} settingPath={['shows', 'admin.sign_up']} onChange={onChange} label={showStr} />
+              <PillBarButton prefix='notifications' settings={settings} settingPath={['sounds', 'admin.sign_up']} onChange={onChange} label={soundStr} />
+            </div>
+          </div>
+        )}
       </div>
     );
   }
diff --git a/app/javascript/flavours/glitch/features/notifications/components/notification.js b/app/javascript/flavours/glitch/features/notifications/components/notification.js
index 1cf205898..e0cd3c7a6 100644
--- a/app/javascript/flavours/glitch/features/notifications/components/notification.js
+++ b/app/javascript/flavours/glitch/features/notifications/components/notification.js
@@ -8,6 +8,7 @@ import ImmutablePureComponent from 'react-immutable-pure-component';
 import StatusContainer from 'flavours/glitch/containers/status_container';
 import NotificationFollow from './follow';
 import NotificationFollowRequestContainer from '../containers/follow_request_container';
+import NotificationAdminSignup from './admin_signup';
 
 export default class Notification extends ImmutablePureComponent {
 
@@ -63,6 +64,19 @@ export default class Notification extends ImmutablePureComponent {
           unread={this.props.unread}
         />
       );
+    case 'admin.sign_up':
+      return (
+        <NotificationAdminSignup
+          hidden={hidden}
+          id={notification.get('id')}
+          account={notification.get('account')}
+          notification={notification}
+          onMoveDown={onMoveDown}
+          onMoveUp={onMoveUp}
+          onMention={onMention}
+          unread={this.props.unread}
+        />
+      );
     case 'mention':
       return (
         <StatusContainer
diff --git a/app/javascript/flavours/glitch/reducers/settings.js b/app/javascript/flavours/glitch/reducers/settings.js
index 48587ce64..676a1ccc1 100644
--- a/app/javascript/flavours/glitch/reducers/settings.js
+++ b/app/javascript/flavours/glitch/reducers/settings.js
@@ -41,6 +41,7 @@ const initialState = ImmutableMap({
       poll: false,
       status: false,
       update: false,
+      'admin.sign_up': false,
     }),
 
     quickFilter: ImmutableMap({
@@ -61,6 +62,7 @@ const initialState = ImmutableMap({
       poll: true,
       status: true,
       update: true,
+      'admin.sign_up': true,
     }),
 
     sounds: ImmutableMap({
@@ -72,6 +74,7 @@ const initialState = ImmutableMap({
       poll: true,
       status: true,
       update: true,
+      'admin.sign_up': true,
     }),
   }),
 
diff --git a/app/javascript/mastodon/actions/notifications.js b/app/javascript/mastodon/actions/notifications.js
index 9370811e0..00e8d74d7 100644
--- a/app/javascript/mastodon/actions/notifications.js
+++ b/app/javascript/mastodon/actions/notifications.js
@@ -45,7 +45,7 @@ defineMessages({
 });
 
 const fetchRelatedRelationships = (dispatch, notifications) => {
-  const accountIds = notifications.filter(item => item.type === 'follow').map(item => item.account.id);
+  const accountIds = notifications.filter(item => ['follow', 'follow_request', 'admin.sign_up'].indexOf(item.type) !== -1).map(item => item.account.id);
 
   if (accountIds.length > 0) {
     dispatch(fetchRelationships(accountIds));
@@ -132,6 +132,7 @@ const excludeTypesFromFilter = filter => {
     'poll',
     'status',
     'update',
+    'admin.sign_up',
   ]);
 
   return allTypes.filterNot(item => item === filter).toJS();
diff --git a/app/javascript/mastodon/components/loading_indicator.js b/app/javascript/mastodon/components/loading_indicator.js
index 59f721c50..33c59d94c 100644
--- a/app/javascript/mastodon/components/loading_indicator.js
+++ b/app/javascript/mastodon/components/loading_indicator.js
@@ -6,7 +6,7 @@ export const CircularProgress = ({ size, strokeWidth }) => {
   const radius  = (size - strokeWidth) / 2;
 
   return (
-    <svg width={size} heigh={size} viewBox={viewBox} className='circular-progress' role='progressbar'>
+    <svg width={size} height={size} viewBox={viewBox} className='circular-progress' role='progressbar'>
       <circle
         fill='none'
         cx={size / 2}
diff --git a/app/javascript/mastodon/features/emoji/emoji_compressed.js b/app/javascript/mastodon/features/emoji/emoji_compressed.js
index 74b53ce5c..6a402f2d4 100644
--- a/app/javascript/mastodon/features/emoji/emoji_compressed.js
+++ b/app/javascript/mastodon/features/emoji/emoji_compressed.js
@@ -90,7 +90,7 @@ Object.keys(emojiIndex.emojis).forEach(key => {
   let { short_names, search, unified } = emojiMartData.emojis[key];
 
   if (short_names[0] !== key) {
-    throw new Error('The compresser expects the first short_code to be the ' +
+    throw new Error('The compressor expects the first short_code to be the ' +
       'key. It may need to be rewritten if the emoji change such that this ' +
       'is no longer the case.');
   }
diff --git a/app/javascript/mastodon/features/notifications/components/column_settings.js b/app/javascript/mastodon/features/notifications/components/column_settings.js
index ada8b6e4a..84db04430 100644
--- a/app/javascript/mastodon/features/notifications/components/column_settings.js
+++ b/app/javascript/mastodon/features/notifications/components/column_settings.js
@@ -5,6 +5,7 @@ import { FormattedMessage } from 'react-intl';
 import ClearColumnButton from './clear_column_button';
 import GrantPermissionButton from './grant_permission_button';
 import SettingToggle from './setting_toggle';
+import { isStaff } from 'mastodon/initial_state';
 
 export default class ColumnSettings extends React.PureComponent {
 
@@ -155,7 +156,7 @@ export default class ColumnSettings extends React.PureComponent {
         </div>
 
         <div role='group' aria-labelledby='notifications-update'>
-          <span id='notifications-status' className='column-settings__section'><FormattedMessage id='notifications.column_settings.update' defaultMessage='Edits:' /></span>
+          <span id='notifications-update' className='column-settings__section'><FormattedMessage id='notifications.column_settings.update' defaultMessage='Edits:' /></span>
 
           <div className='column-settings__row'>
             <SettingToggle disabled={browserPermission === 'denied'} prefix='notifications_desktop' settings={settings} settingPath={['alerts', 'update']} onChange={onChange} label={alertStr} />
@@ -164,6 +165,19 @@ export default class ColumnSettings extends React.PureComponent {
             <SettingToggle prefix='notifications' settings={settings} settingPath={['sounds', 'update']} onChange={onChange} label={soundStr} />
           </div>
         </div>
+
+        {isStaff && (
+          <div role='group' aria-labelledby='notifications-admin-sign-up'>
+            <span id='notifications-status' className='column-settings__section'><FormattedMessage id='notifications.column_settings.admin.sign_up' defaultMessage='New sign-ups:' /></span>
+
+            <div className='column-settings__row'>
+              <SettingToggle disabled={browserPermission === 'denied'} prefix='notifications_desktop' settings={settings} settingPath={['alerts', 'admin.sign_up']} onChange={onChange} label={alertStr} />
+              {showPushSettings && <SettingToggle prefix='notifications_push' settings={pushSettings} settingPath={['alerts', 'admin.sign_up']} onChange={this.onPushChange} label={pushStr} />}
+              <SettingToggle prefix='notifications' settings={settings} settingPath={['shows', 'admin.sign_up']} onChange={onChange} label={showStr} />
+              <SettingToggle prefix='notifications' settings={settings} settingPath={['sounds', 'admin.sign_up']} onChange={onChange} label={soundStr} />
+            </div>
+          </div>
+        )}
       </div>
     );
   }
diff --git a/app/javascript/mastodon/features/notifications/components/notification.js b/app/javascript/mastodon/features/notifications/components/notification.js
index cd471852b..9198e9c9d 100644
--- a/app/javascript/mastodon/features/notifications/components/notification.js
+++ b/app/javascript/mastodon/features/notifications/components/notification.js
@@ -20,6 +20,7 @@ const messages = defineMessages({
   reblog: { id: 'notification.reblog', defaultMessage: '{name} boosted your status' },
   status: { id: 'notification.status', defaultMessage: '{name} just posted' },
   update: { id: 'notification.update', defaultMessage: '{name} edited a post' },
+  adminSignUp: { id: 'notification.admin.sign_up', defaultMessage: '{name} signed up' },
 });
 
 const notificationForScreenReader = (intl, message, timestamp) => {
@@ -344,6 +345,28 @@ class Notification extends ImmutablePureComponent {
     );
   }
 
+  renderAdminSignUp (notification, account, link) {
+    const { intl, unread } = this.props;
+
+    return (
+      <HotKeys handlers={this.getHandlers()}>
+        <div className={classNames('notification notification-admin-sign-up focusable', { unread })} tabIndex='0' aria-label={notificationForScreenReader(intl, intl.formatMessage(messages.adminSignUp, { name: account.get('acct') }), notification.get('created_at'))}>
+          <div className='notification__message'>
+            <div className='notification__favourite-icon-wrapper'>
+              <Icon id='user-plus' fixedWidth />
+            </div>
+
+            <span title={notification.get('created_at')}>
+              <FormattedMessage id='notification.admin.sign_up' defaultMessage='{name} signed up' values={{ name: link }} />
+            </span>
+          </div>
+
+          <AccountContainer id={account.get('id')} hidden={this.props.hidden} />
+        </div>
+      </HotKeys>
+    );
+  }
+
   render () {
     const { notification } = this.props;
     const account          = notification.get('account');
@@ -367,6 +390,8 @@ class Notification extends ImmutablePureComponent {
       return this.renderUpdate(notification, link);
     case 'poll':
       return this.renderPoll(notification, account);
+    case 'admin.sign_up':
+      return this.renderAdminSignUp(notification, account, link);
     }
 
     return null;
diff --git a/app/javascript/mastodon/locales/ca.json b/app/javascript/mastodon/locales/ca.json
index 77fe32d85..15036eef9 100644
--- a/app/javascript/mastodon/locales/ca.json
+++ b/app/javascript/mastodon/locales/ca.json
@@ -308,7 +308,7 @@
   "notification.poll": "Ha finalitzat una enquesta en la que has votat",
   "notification.reblog": "{name} ha impulsat el teu estat",
   "notification.status": "ha publicat {name}",
-  "notification.update": "{name} edited a post",
+  "notification.update": "{name} ha editat una publicació",
   "notifications.clear": "Netejar notificacions",
   "notifications.clear_confirmation": "Estàs segur que vols esborrar permanentment totes les teves notificacions?",
   "notifications.column_settings.alert": "Notificacions d'escriptori",
@@ -327,7 +327,7 @@
   "notifications.column_settings.status": "Nous tuts:",
   "notifications.column_settings.unread_notifications.category": "Notificacions no llegides",
   "notifications.column_settings.unread_notifications.highlight": "Destaca notificacions no llegides",
-  "notifications.column_settings.update": "Edits:",
+  "notifications.column_settings.update": "Edicions:",
   "notifications.filter.all": "Tots",
   "notifications.filter.boosts": "Impulsos",
   "notifications.filter.favourites": "Favorits",
diff --git a/app/javascript/mastodon/locales/da.json b/app/javascript/mastodon/locales/da.json
index 0e7b308a2..4e1832fd3 100644
--- a/app/javascript/mastodon/locales/da.json
+++ b/app/javascript/mastodon/locales/da.json
@@ -308,7 +308,7 @@
   "notification.poll": "En afstemning, du deltog i, er færdig",
   "notification.reblog": "{name} fremhævede dit indlæg",
   "notification.status": "{name} har netop udgivet",
-  "notification.update": "{name} edited a post",
+  "notification.update": "{name} redigerede et indlæg",
   "notifications.clear": "Ryd notifikationer",
   "notifications.clear_confirmation": "Er du sikker på, du vil rydde alle dine notifikationer permanent?",
   "notifications.column_settings.alert": "Skrivebordsnotifikationer",
@@ -327,7 +327,7 @@
   "notifications.column_settings.status": "Nye indlæg:",
   "notifications.column_settings.unread_notifications.category": "Ulæste notifikationer",
   "notifications.column_settings.unread_notifications.highlight": "Fremhæv ulæste notifikationer",
-  "notifications.column_settings.update": "Edits:",
+  "notifications.column_settings.update": "Redigeringer:",
   "notifications.filter.all": "Alle",
   "notifications.filter.boosts": "Fremhævelser",
   "notifications.filter.favourites": "Favoritter",
diff --git a/app/javascript/mastodon/locales/el.json b/app/javascript/mastodon/locales/el.json
index 1ce6fcdd8..450b3aff8 100644
--- a/app/javascript/mastodon/locales/el.json
+++ b/app/javascript/mastodon/locales/el.json
@@ -308,7 +308,7 @@
   "notification.poll": "Τελείωσε μια από τις ψηφοφορίες που συμμετείχες",
   "notification.reblog": "Ο/Η {name} προώθησε την κατάστασή σου",
   "notification.status": "Ο/Η {name} μόλις έγραψε κάτι",
-  "notification.update": "{name} edited a post",
+  "notification.update": "{name} επεξεργάστηκε μια δημοσίευση",
   "notifications.clear": "Καθαρισμός ειδοποιήσεων",
   "notifications.clear_confirmation": "Σίγουρα θέλεις να καθαρίσεις όλες τις ειδοποιήσεις σου;",
   "notifications.column_settings.alert": "Ειδοποιήσεις επιφάνειας εργασίας",
@@ -327,7 +327,7 @@
   "notifications.column_settings.status": "Νέα τουτ:",
   "notifications.column_settings.unread_notifications.category": "Μη αναγνωσμένες ειδοποιήσεις",
   "notifications.column_settings.unread_notifications.highlight": "Επισήμανση μη αναγνωσμένων ειδοποιήσεων",
-  "notifications.column_settings.update": "Edits:",
+  "notifications.column_settings.update": "Επεξεργασίες:",
   "notifications.filter.all": "Όλες",
   "notifications.filter.boosts": "Προωθήσεις",
   "notifications.filter.favourites": "Αγαπημένα",
diff --git a/app/javascript/mastodon/locales/es-AR.json b/app/javascript/mastodon/locales/es-AR.json
index b84914d87..24902a058 100644
--- a/app/javascript/mastodon/locales/es-AR.json
+++ b/app/javascript/mastodon/locales/es-AR.json
@@ -308,7 +308,7 @@
   "notification.poll": "Finalizó una encuesta en la que votaste",
   "notification.reblog": "{name} adhirió a tu mensaje",
   "notification.status": "{name} acaba de enviar un mensaje",
-  "notification.update": "{name} edited a post",
+  "notification.update": "{name} editó un mensaje",
   "notifications.clear": "Limpiar notificaciones",
   "notifications.clear_confirmation": "¿Estás seguro que querés limpiar todas tus notificaciones permanentemente?",
   "notifications.column_settings.alert": "Notificaciones de escritorio",
@@ -327,7 +327,7 @@
   "notifications.column_settings.status": "Nuevos mensajes:",
   "notifications.column_settings.unread_notifications.category": "Notificaciones sin leer",
   "notifications.column_settings.unread_notifications.highlight": "Resaltar notificaciones no leídas",
-  "notifications.column_settings.update": "Edits:",
+  "notifications.column_settings.update": "Ediciones:",
   "notifications.filter.all": "Todas",
   "notifications.filter.boosts": "Adhesiones",
   "notifications.filter.favourites": "Favoritos",
diff --git a/app/javascript/mastodon/locales/es.json b/app/javascript/mastodon/locales/es.json
index fad2dc698..c4d1a9d59 100644
--- a/app/javascript/mastodon/locales/es.json
+++ b/app/javascript/mastodon/locales/es.json
@@ -308,7 +308,7 @@
   "notification.poll": "Una encuesta en la que has votado ha terminado",
   "notification.reblog": "{name} ha retooteado tu publicación",
   "notification.status": "{name} acaba de publicar",
-  "notification.update": "{name} edited a post",
+  "notification.update": "{name} editó una publicación",
   "notifications.clear": "Limpiar notificaciones",
   "notifications.clear_confirmation": "¿Seguro que quieres limpiar permanentemente todas tus notificaciones?",
   "notifications.column_settings.alert": "Notificaciones de escritorio",
@@ -327,7 +327,7 @@
   "notifications.column_settings.status": "Nuevas publicaciones:",
   "notifications.column_settings.unread_notifications.category": "Notificaciones sin leer",
   "notifications.column_settings.unread_notifications.highlight": "Destacar notificaciones no leídas",
-  "notifications.column_settings.update": "Edits:",
+  "notifications.column_settings.update": "Ediciones:",
   "notifications.filter.all": "Todos",
   "notifications.filter.boosts": "Retoots",
   "notifications.filter.favourites": "Favoritos",
diff --git a/app/javascript/mastodon/locales/eu.json b/app/javascript/mastodon/locales/eu.json
index b46d29e80..da3d66a9a 100644
--- a/app/javascript/mastodon/locales/eu.json
+++ b/app/javascript/mastodon/locales/eu.json
@@ -47,8 +47,8 @@
   "account.unmute": "Desmututu @{name}",
   "account.unmute_notifications": "Desmututu @{name}(r)en jakinarazpenak",
   "account_note.placeholder": "Click to add a note",
-  "admin.dashboard.daily_retention": "User retention rate by day after sign-up",
-  "admin.dashboard.monthly_retention": "User retention rate by month after sign-up",
+  "admin.dashboard.daily_retention": "Erabiltzaile atxikitze-tasa izena eman ondorengo eguneko",
+  "admin.dashboard.monthly_retention": "Erabiltzaile atxikitze-tasa izena eman ondorengo hilabeteko",
   "admin.dashboard.retention.average": "Batezbestekoa",
   "admin.dashboard.retention.cohort": "Izen emate hilean",
   "admin.dashboard.retention.cohort_size": "Erabiltzaile berriak",
@@ -105,7 +105,7 @@
   "compose_form.poll.switch_to_single": "Aldatu inkesta aukera bakarra onartzeko",
   "compose_form.publish": "Toot",
   "compose_form.publish_loud": "{publish}!",
-  "compose_form.save_changes": "Save changes",
+  "compose_form.save_changes": "Gorde aldaketak",
   "compose_form.sensitive.hide": "Markatu multimedia hunkigarri gisa",
   "compose_form.sensitive.marked": "Multimedia edukia hunkigarri gisa markatu da",
   "compose_form.sensitive.unmarked": "Multimedia edukia ez da hunkigarri gisa markatu",
@@ -308,7 +308,7 @@
   "notification.poll": "Zuk erantzun duzun inkesta bat bukatu da",
   "notification.reblog": "{name}(e)k bultzada eman dio zure bidalketari",
   "notification.status": "{name} erabiltzaileak bidalketa egin berri du",
-  "notification.update": "{name} edited a post",
+  "notification.update": "{name} erabiltzaileak bidalketa bat editatu du",
   "notifications.clear": "Garbitu jakinarazpenak",
   "notifications.clear_confirmation": "Ziur zure jakinarazpen guztiak behin betirako garbitu nahi dituzula?",
   "notifications.column_settings.alert": "Mahaigaineko jakinarazpenak",
@@ -327,7 +327,7 @@
   "notifications.column_settings.status": "Bidalketa berriak:",
   "notifications.column_settings.unread_notifications.category": "Irakurri gabeko jakinarazpenak",
   "notifications.column_settings.unread_notifications.highlight": "Nabarmendu irakurri gabeko jakinarazpenak",
-  "notifications.column_settings.update": "Edits:",
+  "notifications.column_settings.update": "Edizioak:",
   "notifications.filter.all": "Denak",
   "notifications.filter.boosts": "Bultzadak",
   "notifications.filter.favourites": "Gogokoak",
@@ -367,20 +367,20 @@
   "regeneration_indicator.label": "Kargatzen…",
   "regeneration_indicator.sublabel": "Zure hasiera-jarioa prestatzen ari da!",
   "relative_time.days": "{number}e",
-  "relative_time.full.days": "{number, plural, one {# day} other {# days}} ago",
-  "relative_time.full.hours": "{number, plural, one {# hour} other {# hours}} ago",
-  "relative_time.full.just_now": "just now",
-  "relative_time.full.minutes": "{number, plural, one {# minute} other {# minutes}} ago",
-  "relative_time.full.seconds": "{number, plural, one {# second} other {# seconds}} ago",
+  "relative_time.full.days": "Duela {number, plural, one {egun #} other {# egun}}",
+  "relative_time.full.hours": "Duela {number, plural, one {ordu #} other {# ordu}}",
+  "relative_time.full.just_now": "oraintxe",
+  "relative_time.full.minutes": "Duela {number, plural, one {minutu #} other {# minutu}}",
+  "relative_time.full.seconds": "Duela {number, plural, one {segundo #} other {# segundo}}",
   "relative_time.hours": "{number}h",
   "relative_time.just_now": "orain",
   "relative_time.minutes": "{number}m",
   "relative_time.seconds": "{number}s",
   "relative_time.today": "gaur",
   "reply_indicator.cancel": "Utzi",
-  "report.categories.other": "Other",
+  "report.categories.other": "Bestelakoak",
   "report.categories.spam": "Spam",
-  "report.categories.violation": "Content violates one or more server rules",
+  "report.categories.violation": "Edukiak zerbitzariko arau bat edo gehiago urratzen ditu",
   "report.forward": "Birbidali hona: {target}",
   "report.forward_hint": "Kontu hau beste zerbitzari batekoa da. Bidali txostenaren kopia anonimo hara ere?",
   "report.hint": "Txostena zure zerbitzariaren moderatzaileei bidaliko zaie. Kontu hau zergatik salatzen duzun behean azaldu dezakezu:",
@@ -409,14 +409,14 @@
   "status.delete": "Ezabatu",
   "status.detailed_status": "Elkarrizketaren ikuspegi xehetsua",
   "status.direct": "Mezu zuzena @{name}(r)i",
-  "status.edit": "Edit",
-  "status.edited": "Edited {date}",
-  "status.edited_x_times": "Edited {count, plural, one {{count} time} other {{count} times}}",
+  "status.edit": "Editatu",
+  "status.edited": "Editatua {date}",
+  "status.edited_x_times": "{count, plural, one {behin} other {{count} aldiz}} editatua",
   "status.embed": "Txertatu",
   "status.favourite": "Gogokoa",
   "status.filtered": "Iragazita",
-  "status.history.created": "{name} created {date}",
-  "status.history.edited": "{name} edited {date}",
+  "status.history.created": "{name} erabiltzaileak sortua {date}",
+  "status.history.edited": "{name} erabiltzaileak editatua {date}",
   "status.load_more": "Kargatu gehiago",
   "status.media_hidden": "Multimedia ezkutatua",
   "status.mention": "Aipatu @{name}",
diff --git a/app/javascript/mastodon/locales/fi.json b/app/javascript/mastodon/locales/fi.json
index 97e0488eb..e3436ac84 100644
--- a/app/javascript/mastodon/locales/fi.json
+++ b/app/javascript/mastodon/locales/fi.json
@@ -308,7 +308,7 @@
   "notification.poll": "Kysely, johon osallistuit, on päättynyt",
   "notification.reblog": "{name} buustasi julkaisusi",
   "notification.status": "{name} julkaisi juuri",
-  "notification.update": "{name} edited a post",
+  "notification.update": "{name} muokkasi viestiä",
   "notifications.clear": "Tyhjennä ilmoitukset",
   "notifications.clear_confirmation": "Haluatko varmasti poistaa kaikki ilmoitukset pysyvästi?",
   "notifications.column_settings.alert": "Työpöytäilmoitukset",
@@ -327,7 +327,7 @@
   "notifications.column_settings.status": "Uudet julkaisut:",
   "notifications.column_settings.unread_notifications.category": "Lukemattomat ilmoitukset",
   "notifications.column_settings.unread_notifications.highlight": "Korosta lukemattomat ilmoitukset",
-  "notifications.column_settings.update": "Edits:",
+  "notifications.column_settings.update": "Muokkaukset:",
   "notifications.filter.all": "Kaikki",
   "notifications.filter.boosts": "Buustit",
   "notifications.filter.favourites": "Suosikit",
diff --git a/app/javascript/mastodon/locales/fr.json b/app/javascript/mastodon/locales/fr.json
index 44389cf08..8d10a7149 100644
--- a/app/javascript/mastodon/locales/fr.json
+++ b/app/javascript/mastodon/locales/fr.json
@@ -13,7 +13,7 @@
   "account.domain_blocked": "Domaine bloqué",
   "account.edit_profile": "Modifier le profil",
   "account.enable_notifications": "Me notifier quand @{name} publie",
-  "account.endorse": "Recommander sur le profil",
+  "account.endorse": "Recommander sur votre profil",
   "account.follow": "Suivre",
   "account.followers": "Abonnés",
   "account.followers.empty": "Personne ne suit cet·te utilisateur·rice pour l’instant.",
@@ -47,7 +47,7 @@
   "account.unmute": "Ne plus masquer @{name}",
   "account.unmute_notifications": "Ne plus masquer les notifications de @{name}",
   "account_note.placeholder": "Cliquez pour ajouter une note",
-  "admin.dashboard.daily_retention": "User retention rate by day after sign-up",
+  "admin.dashboard.daily_retention": "Taux de maintien des utilisateur·rice·s par jour après inscription",
   "admin.dashboard.monthly_retention": "Brugerfastholdelsesrate efter måned efter tilmelding",
   "admin.dashboard.retention.average": "Moyenne",
   "admin.dashboard.retention.cohort": "Mois d'inscription",
@@ -308,7 +308,7 @@
   "notification.poll": "Un sondage auquel vous avez participé vient de se terminer",
   "notification.reblog": "{name} a partagé votre message",
   "notification.status": "{name} vient de publier",
-  "notification.update": "{name} edited a post",
+  "notification.update": "{name} a modifié un message",
   "notifications.clear": "Effacer les notifications",
   "notifications.clear_confirmation": "Voulez-vous vraiment effacer toutes vos notifications ?",
   "notifications.column_settings.alert": "Notifications du navigateur",
@@ -327,7 +327,7 @@
   "notifications.column_settings.status": "Nouveaux messages :",
   "notifications.column_settings.unread_notifications.category": "Notifications non lues",
   "notifications.column_settings.unread_notifications.highlight": "Surligner les notifications non lues",
-  "notifications.column_settings.update": "Edits:",
+  "notifications.column_settings.update": "Modifications :",
   "notifications.filter.all": "Tout",
   "notifications.filter.boosts": "Partages",
   "notifications.filter.favourites": "Favoris",
@@ -415,8 +415,8 @@
   "status.embed": "Intégrer",
   "status.favourite": "Ajouter aux favoris",
   "status.filtered": "Filtré",
-  "status.history.created": "{name} created {date}",
-  "status.history.edited": "{name} edited {date}",
+  "status.history.created": "créé par {name} {date}",
+  "status.history.edited": "édité par {name} {date}",
   "status.load_more": "Charger plus",
   "status.media_hidden": "Média caché",
   "status.mention": "Mentionner @{name}",
diff --git a/app/javascript/mastodon/locales/gl.json b/app/javascript/mastodon/locales/gl.json
index d735b423d..39f121065 100644
--- a/app/javascript/mastodon/locales/gl.json
+++ b/app/javascript/mastodon/locales/gl.json
@@ -308,7 +308,7 @@
   "notification.poll": "Unha enquisa na que votaches rematou",
   "notification.reblog": "{name} compartiu a túa publicación",
   "notification.status": "{name} publicou",
-  "notification.update": "{name} edited a post",
+  "notification.update": "{name} editou unha publicación",
   "notifications.clear": "Limpar notificacións",
   "notifications.clear_confirmation": "Tes a certeza de querer limpar de xeito permanente todas as túas notificacións?",
   "notifications.column_settings.alert": "Notificacións de escritorio",
@@ -327,7 +327,7 @@
   "notifications.column_settings.status": "Novas publicacións:",
   "notifications.column_settings.unread_notifications.category": "Notificacións non lidas",
   "notifications.column_settings.unread_notifications.highlight": "Resaltar notificacións non lidas",
-  "notifications.column_settings.update": "Edits:",
+  "notifications.column_settings.update": "Edicións:",
   "notifications.filter.all": "Todo",
   "notifications.filter.boosts": "Compartidos",
   "notifications.filter.favourites": "Favoritos",
diff --git a/app/javascript/mastodon/locales/he.json b/app/javascript/mastodon/locales/he.json
index 0c80222d1..c163812ac 100644
--- a/app/javascript/mastodon/locales/he.json
+++ b/app/javascript/mastodon/locales/he.json
@@ -308,7 +308,7 @@
   "notification.poll": "A poll you have voted in has ended",
   "notification.reblog": "חצרוצך הודהד על ידי {name}",
   "notification.status": "{name} just posted",
-  "notification.update": "{name} edited a post",
+  "notification.update": "{name} ערכו פוסט",
   "notifications.clear": "הסרת התראות",
   "notifications.clear_confirmation": "להסיר את כל ההתראות? בטוח?",
   "notifications.column_settings.alert": "התראות לשולחן העבודה",
@@ -327,7 +327,7 @@
   "notifications.column_settings.status": "New toots:",
   "notifications.column_settings.unread_notifications.category": "Unread notifications",
   "notifications.column_settings.unread_notifications.highlight": "Highlight unread notifications",
-  "notifications.column_settings.update": "Edits:",
+  "notifications.column_settings.update": "שינויים:",
   "notifications.filter.all": "All",
   "notifications.filter.boosts": "Boosts",
   "notifications.filter.favourites": "Favourites",
diff --git a/app/javascript/mastodon/locales/hu.json b/app/javascript/mastodon/locales/hu.json
index 3d63d77a1..97b985d95 100644
--- a/app/javascript/mastodon/locales/hu.json
+++ b/app/javascript/mastodon/locales/hu.json
@@ -308,7 +308,7 @@
   "notification.poll": "Egy szavazás, melyben részt vettél, véget ért",
   "notification.reblog": "{name} megtolta a bejegyzésedet",
   "notification.status": "{name} bejegyzést tett közzé",
-  "notification.update": "{name} edited a post",
+  "notification.update": "{name} szerkesztett egy bejegyzést",
   "notifications.clear": "Értesítések törlése",
   "notifications.clear_confirmation": "Biztos, hogy véglegesen törölni akarod az összes értesítésed?",
   "notifications.column_settings.alert": "Asztali értesítések",
@@ -327,7 +327,7 @@
   "notifications.column_settings.status": "Új bejegyzések:",
   "notifications.column_settings.unread_notifications.category": "Olvasatlan értesítések",
   "notifications.column_settings.unread_notifications.highlight": "Olvasatlan értesítések kiemelése",
-  "notifications.column_settings.update": "Edits:",
+  "notifications.column_settings.update": "Szerkesztések:",
   "notifications.filter.all": "Mind",
   "notifications.filter.boosts": "Megtolások",
   "notifications.filter.favourites": "Kedvencnek jelölések",
diff --git a/app/javascript/mastodon/locales/id.json b/app/javascript/mastodon/locales/id.json
index a596752b1..e8e81cfde 100644
--- a/app/javascript/mastodon/locales/id.json
+++ b/app/javascript/mastodon/locales/id.json
@@ -308,7 +308,7 @@
   "notification.poll": "Japat yang Anda ikuti telah berakhir",
   "notification.reblog": "{name} mem-boost status anda",
   "notification.status": "{name} baru saja memposting",
-  "notification.update": "{name} edited a post",
+  "notification.update": "{name} mengedit kiriman",
   "notifications.clear": "Hapus notifikasi",
   "notifications.clear_confirmation": "Apa anda yakin hendak menghapus semua notifikasi anda?",
   "notifications.column_settings.alert": "Notifikasi desktop",
@@ -327,7 +327,7 @@
   "notifications.column_settings.status": "Toot baru:",
   "notifications.column_settings.unread_notifications.category": "Notifikasi yang belum dibaca",
   "notifications.column_settings.unread_notifications.highlight": "Sorot notifikasi yang belum dibaca",
-  "notifications.column_settings.update": "Edits:",
+  "notifications.column_settings.update": "Edit:",
   "notifications.filter.all": "Semua",
   "notifications.filter.boosts": "Boost",
   "notifications.filter.favourites": "Favorit",
diff --git a/app/javascript/mastodon/locales/is.json b/app/javascript/mastodon/locales/is.json
index 679bb4710..a5164fa24 100644
--- a/app/javascript/mastodon/locales/is.json
+++ b/app/javascript/mastodon/locales/is.json
@@ -308,7 +308,7 @@
   "notification.poll": "Könnun sem þú tókst þátt í er lokið",
   "notification.reblog": "{name} endurbirti færsluna þína",
   "notification.status": "{name} sendi inn rétt í þessu",
-  "notification.update": "{name} edited a post",
+  "notification.update": "{name} breytti færslu",
   "notifications.clear": "Hreinsa tilkynningar",
   "notifications.clear_confirmation": "Ertu viss um að þú viljir endanlega eyða öllum tilkynningunum þínum?",
   "notifications.column_settings.alert": "Tilkynningar á skjáborði",
@@ -327,7 +327,7 @@
   "notifications.column_settings.status": "Nýjar færslur:",
   "notifications.column_settings.unread_notifications.category": "Ólesnar tilkynningar",
   "notifications.column_settings.unread_notifications.highlight": "Áherslulita ólesnar tilkynningar",
-  "notifications.column_settings.update": "Edits:",
+  "notifications.column_settings.update": "Breytingar:",
   "notifications.filter.all": "Allt",
   "notifications.filter.boosts": "Endurbirtingar",
   "notifications.filter.favourites": "Eftirlæti",
diff --git a/app/javascript/mastodon/locales/it.json b/app/javascript/mastodon/locales/it.json
index ac462f0d6..a4847b77b 100644
--- a/app/javascript/mastodon/locales/it.json
+++ b/app/javascript/mastodon/locales/it.json
@@ -308,7 +308,7 @@
   "notification.poll": "Un sondaggio in cui hai votato è terminato",
   "notification.reblog": "{name} ha condiviso il tuo post",
   "notification.status": "{name} ha appena pubblicato un post",
-  "notification.update": "{name} edited a post",
+  "notification.update": "{name} ha modificato un post",
   "notifications.clear": "Cancella notifiche",
   "notifications.clear_confirmation": "Vuoi davvero cancellare tutte le notifiche?",
   "notifications.column_settings.alert": "Notifiche desktop",
@@ -327,7 +327,7 @@
   "notifications.column_settings.status": "Nuovi post:",
   "notifications.column_settings.unread_notifications.category": "Notifiche non lette",
   "notifications.column_settings.unread_notifications.highlight": "Evidenzia notifiche non lette",
-  "notifications.column_settings.update": "Edits:",
+  "notifications.column_settings.update": "Modifiche:",
   "notifications.filter.all": "Tutti",
   "notifications.filter.boosts": "Condivisioni",
   "notifications.filter.favourites": "Apprezzati",
diff --git a/app/javascript/mastodon/locales/ja.json b/app/javascript/mastodon/locales/ja.json
index d008f1e79..934857ed4 100644
--- a/app/javascript/mastodon/locales/ja.json
+++ b/app/javascript/mastodon/locales/ja.json
@@ -313,7 +313,7 @@
   "notification.poll": "アンケートが終了しました",
   "notification.reblog": "{name}さんがあなたの投稿をブーストしました",
   "notification.status": "{name}さんが投稿しました",
-  "notification.update": "{name} edited a post",
+  "notification.update": "{name} が投稿を編集しました",
   "notifications.clear": "通知を消去",
   "notifications.clear_confirmation": "本当に通知を消去しますか?",
   "notifications.column_settings.alert": "デスクトップ通知",
diff --git a/app/javascript/mastodon/locales/kmr.json b/app/javascript/mastodon/locales/kmr.json
index 2ef4da0a4..2ae288581 100644
--- a/app/javascript/mastodon/locales/kmr.json
+++ b/app/javascript/mastodon/locales/kmr.json
@@ -308,7 +308,7 @@
   "notification.poll": "Rapirsiyeke ku te deng daye qediya",
   "notification.reblog": "{name} şandiya te bilind kir",
   "notification.status": "{name} niha şand",
-  "notification.update": "{name} edited a post",
+  "notification.update": "{name} şandiyek serrast kir",
   "notifications.clear": "Agahdariyan pak bike",
   "notifications.clear_confirmation": "Bi rastî tu dixwazî bi awayekî dawî hemû agahdariyên xwe pak bikî?",
   "notifications.column_settings.alert": "Agahdariyên sermaseyê",
@@ -327,7 +327,7 @@
   "notifications.column_settings.status": "Şandiyên nû:",
   "notifications.column_settings.unread_notifications.category": "Agahdariyên nexwendî",
   "notifications.column_settings.unread_notifications.highlight": "Agahiyên nexwendî nîşan bike",
-  "notifications.column_settings.update": "Edits:",
+  "notifications.column_settings.update": "Serrastkirin:",
   "notifications.filter.all": "Hemû",
   "notifications.filter.boosts": "Bilindkirî",
   "notifications.filter.favourites": "Bijarte",
diff --git a/app/javascript/mastodon/locales/ko.json b/app/javascript/mastodon/locales/ko.json
index 375abd7c3..b3aa2e6ab 100644
--- a/app/javascript/mastodon/locales/ko.json
+++ b/app/javascript/mastodon/locales/ko.json
@@ -308,7 +308,7 @@
   "notification.poll": "당신이 참여 한 투표가 종료되었습니다",
   "notification.reblog": "{name} 님이 부스트 했습니다",
   "notification.status": "{name} 님이 방금 게시물을 올렸습니다",
-  "notification.update": "{name} edited a post",
+  "notification.update": "{name} 님이 게시물을 수정했습니다",
   "notifications.clear": "알림 지우기",
   "notifications.clear_confirmation": "정말로 알림을 삭제하시겠습니까?",
   "notifications.column_settings.alert": "데스크탑 알림",
@@ -327,7 +327,7 @@
   "notifications.column_settings.status": "새 게시물:",
   "notifications.column_settings.unread_notifications.category": "읽지 않은 알림",
   "notifications.column_settings.unread_notifications.highlight": "읽지 않은 알림 강조",
-  "notifications.column_settings.update": "Edits:",
+  "notifications.column_settings.update": "수정내역:",
   "notifications.filter.all": "모두",
   "notifications.filter.boosts": "부스트",
   "notifications.filter.favourites": "즐겨찾기",
diff --git a/app/javascript/mastodon/locales/lv.json b/app/javascript/mastodon/locales/lv.json
index 53681915c..955d2afa3 100644
--- a/app/javascript/mastodon/locales/lv.json
+++ b/app/javascript/mastodon/locales/lv.json
@@ -308,7 +308,7 @@
   "notification.poll": "Aprauja, kurā tu piedalījies, ir pabeigta",
   "notification.reblog": "{name} paaugstināja tavu ziņu",
   "notification.status": "{name} tikko publicēja",
-  "notification.update": "{name} edited a post",
+  "notification.update": "{name} ir rediģējis rakstu",
   "notifications.clear": "Notīrīt paziņojumus",
   "notifications.clear_confirmation": "Vai tiešām vēlies neatgriezeniski notīrīt visus savus paziņojumus?",
   "notifications.column_settings.alert": "Darbvirsmas paziņojumi",
@@ -327,7 +327,7 @@
   "notifications.column_settings.status": "Jaunas ziņas:",
   "notifications.column_settings.unread_notifications.category": "Nelasītie paziņojumi",
   "notifications.column_settings.unread_notifications.highlight": "Iezīmēt nelasītos paziņojumus",
-  "notifications.column_settings.update": "Edits:",
+  "notifications.column_settings.update": "Labojumi:",
   "notifications.filter.all": "Visi",
   "notifications.filter.boosts": "Palielinājumi",
   "notifications.filter.favourites": "Izlases",
diff --git a/app/javascript/mastodon/locales/pl.json b/app/javascript/mastodon/locales/pl.json
index df7c595cd..e77def41e 100644
--- a/app/javascript/mastodon/locales/pl.json
+++ b/app/javascript/mastodon/locales/pl.json
@@ -313,7 +313,7 @@
   "notification.poll": "Głosowanie w którym brałeś(-aś) udział zakończyło się",
   "notification.reblog": "{name} podbił(a) Twój wpis",
   "notification.status": "{name} właśnie utworzył(a) wpis",
-  "notification.update": "{name} edited a post",
+  "notification.update": "{name} edytował post",
   "notifications.clear": "Wyczyść powiadomienia",
   "notifications.clear_confirmation": "Czy na pewno chcesz bezpowrotnie usunąć wszystkie powiadomienia?",
   "notifications.column_settings.alert": "Powiadomienia na pulpicie",
@@ -332,7 +332,7 @@
   "notifications.column_settings.status": "Nowe wpisy:",
   "notifications.column_settings.unread_notifications.category": "Nieprzeczytane powiadomienia",
   "notifications.column_settings.unread_notifications.highlight": "Podświetl nieprzeczytane powiadomienia",
-  "notifications.column_settings.update": "Edits:",
+  "notifications.column_settings.update": "Edycje:",
   "notifications.filter.all": "Wszystkie",
   "notifications.filter.boosts": "Podbicia",
   "notifications.filter.favourites": "Ulubione",
diff --git a/app/javascript/mastodon/locales/pt-PT.json b/app/javascript/mastodon/locales/pt-PT.json
index 360bb3532..531265706 100644
--- a/app/javascript/mastodon/locales/pt-PT.json
+++ b/app/javascript/mastodon/locales/pt-PT.json
@@ -308,7 +308,7 @@
   "notification.poll": "Uma votação em que participaste chegou ao fim",
   "notification.reblog": "{name} partilhou a tua publicação",
   "notification.status": "{name} acabou de publicar",
-  "notification.update": "{name} edited a post",
+  "notification.update": "{name} editou uma publicação",
   "notifications.clear": "Limpar notificações",
   "notifications.clear_confirmation": "Queres mesmo limpar todas as notificações?",
   "notifications.column_settings.alert": "Notificações no ambiente de trabalho",
@@ -327,7 +327,7 @@
   "notifications.column_settings.status": "Novos toots:",
   "notifications.column_settings.unread_notifications.category": "Notificações não lidas",
   "notifications.column_settings.unread_notifications.highlight": "Destacar notificações não lidas",
-  "notifications.column_settings.update": "Edits:",
+  "notifications.column_settings.update": "Edições:",
   "notifications.filter.all": "Todas",
   "notifications.filter.boosts": "Boosts",
   "notifications.filter.favourites": "Favoritos",
diff --git a/app/javascript/mastodon/locales/ru.json b/app/javascript/mastodon/locales/ru.json
index 482219fa8..82e57821b 100644
--- a/app/javascript/mastodon/locales/ru.json
+++ b/app/javascript/mastodon/locales/ru.json
@@ -35,7 +35,7 @@
   "account.never_active": "Никогда",
   "account.posts": "Посты",
   "account.posts_with_replies": "Посты и ответы",
-  "account.report": "Жалоба №{name}",
+  "account.report": "Пожаловаться на @{name}",
   "account.requested": "Ожидает подтверждения. Нажмите для отмены запроса",
   "account.share": "Поделиться профилем @{name}",
   "account.show_reblogs": "Показывать продвижения от @{name}",
@@ -327,7 +327,7 @@
   "notifications.column_settings.status": "Новые посты:",
   "notifications.column_settings.unread_notifications.category": "Непрочитанные уведомления",
   "notifications.column_settings.unread_notifications.highlight": "Выделять непрочитанные уведомления",
-  "notifications.column_settings.update": "Edits:",
+  "notifications.column_settings.update": "Изменения:",
   "notifications.filter.all": "Все",
   "notifications.filter.boosts": "Продвижения",
   "notifications.filter.favourites": "Отметки «избранного»",
diff --git a/app/javascript/mastodon/locales/sq.json b/app/javascript/mastodon/locales/sq.json
index facfa324b..fb6bbac75 100644
--- a/app/javascript/mastodon/locales/sq.json
+++ b/app/javascript/mastodon/locales/sq.json
@@ -308,7 +308,7 @@
   "notification.poll": "Ka përfunduar një pyetësor ku keni votuar",
   "notification.reblog": "{name} përforcoi mesazhin tuaj",
   "notification.status": "{name} sapo postoi",
-  "notification.update": "{name} edited a post",
+  "notification.update": "{name} përpunoi një postim",
   "notifications.clear": "Spastroji njoftimet",
   "notifications.clear_confirmation": "Jeni i sigurt se doni të spastrohen përgjithmonë krejt njoftimet tuaja?",
   "notifications.column_settings.alert": "Njoftime desktopi",
@@ -327,7 +327,7 @@
   "notifications.column_settings.status": "Mesazhe të rinj:",
   "notifications.column_settings.unread_notifications.category": "Njoftime të palexuara",
   "notifications.column_settings.unread_notifications.highlight": "Theksoji njoftimet e palexuara",
-  "notifications.column_settings.update": "Edits:",
+  "notifications.column_settings.update": "Përpunime:",
   "notifications.filter.all": "Krejt",
   "notifications.filter.boosts": "Përforcime",
   "notifications.filter.favourites": "Të parapëlqyer",
diff --git a/app/javascript/mastodon/locales/sv.json b/app/javascript/mastodon/locales/sv.json
index 4f627a013..798d1f8e4 100644
--- a/app/javascript/mastodon/locales/sv.json
+++ b/app/javascript/mastodon/locales/sv.json
@@ -308,7 +308,7 @@
   "notification.poll": "En omröstning du röstat i har avslutats",
   "notification.reblog": "{name} knuffade din status",
   "notification.status": "{name} skrev just",
-  "notification.update": "{name} edited a post",
+  "notification.update": "{name} redigerade ett inlägg",
   "notifications.clear": "Rensa aviseringar",
   "notifications.clear_confirmation": "Är du säker på att du vill rensa alla dina aviseringar permanent?",
   "notifications.column_settings.alert": "Skrivbordsaviseringar",
diff --git a/app/javascript/mastodon/locales/th.json b/app/javascript/mastodon/locales/th.json
index b4828b79a..bef3af46f 100644
--- a/app/javascript/mastodon/locales/th.json
+++ b/app/javascript/mastodon/locales/th.json
@@ -308,7 +308,7 @@
   "notification.poll": "การสำรวจความคิดเห็นที่คุณได้ลงคะแนนได้สิ้นสุดแล้ว",
   "notification.reblog": "{name} ได้ดันโพสต์ของคุณ",
   "notification.status": "{name} เพิ่งโพสต์",
-  "notification.update": "{name} edited a post",
+  "notification.update": "{name} ได้แก้ไขโพสต์",
   "notifications.clear": "ล้างการแจ้งเตือน",
   "notifications.clear_confirmation": "คุณแน่ใจหรือไม่ว่าต้องการล้างการแจ้งเตือนทั้งหมดของคุณอย่างถาวร?",
   "notifications.column_settings.alert": "การแจ้งเตือนบนเดสก์ท็อป",
@@ -327,7 +327,7 @@
   "notifications.column_settings.status": "โพสต์ใหม่:",
   "notifications.column_settings.unread_notifications.category": "การแจ้งเตือนที่ยังไม่ได้อ่าน",
   "notifications.column_settings.unread_notifications.highlight": "เน้นการแจ้งเตือนที่ยังไม่ได้อ่าน",
-  "notifications.column_settings.update": "Edits:",
+  "notifications.column_settings.update": "การแก้ไข:",
   "notifications.filter.all": "ทั้งหมด",
   "notifications.filter.boosts": "การดัน",
   "notifications.filter.favourites": "รายการโปรด",
diff --git a/app/javascript/mastodon/locales/tr.json b/app/javascript/mastodon/locales/tr.json
index 2516bb8da..3d67b62e9 100644
--- a/app/javascript/mastodon/locales/tr.json
+++ b/app/javascript/mastodon/locales/tr.json
@@ -308,7 +308,7 @@
   "notification.poll": "Oy verdiğiniz bir anket sona erdi",
   "notification.reblog": "{name} gönderini teşvik etti",
   "notification.status": "{name} az önce gönderdi",
-  "notification.update": "{name} edited a post",
+  "notification.update": "{name} bir gönderiyi düzenledi",
   "notifications.clear": "Bildirimleri temizle",
   "notifications.clear_confirmation": "Tüm bildirimlerinizi kalıcı olarak temizlemek ister misiniz?",
   "notifications.column_settings.alert": "Masaüstü bildirimleri",
@@ -327,7 +327,7 @@
   "notifications.column_settings.status": "Yeni gönderiler:",
   "notifications.column_settings.unread_notifications.category": "Okunmamış bildirimler",
   "notifications.column_settings.unread_notifications.highlight": "Okunmamış bildirimleri öne çıkar",
-  "notifications.column_settings.update": "Edits:",
+  "notifications.column_settings.update": "Düzenlemeler:",
   "notifications.filter.all": "Tümü",
   "notifications.filter.boosts": "Boostlar",
   "notifications.filter.favourites": "Beğeniler",
diff --git a/app/javascript/mastodon/locales/uk.json b/app/javascript/mastodon/locales/uk.json
index cd7b3c97a..4414d6741 100644
--- a/app/javascript/mastodon/locales/uk.json
+++ b/app/javascript/mastodon/locales/uk.json
@@ -308,7 +308,7 @@
   "notification.poll": "Опитування, у якому ви голосували, закінчилося",
   "notification.reblog": "{name} передмухнув(-ла) Ваш допис",
   "notification.status": "{name} щойно дописує",
-  "notification.update": "{name} edited a post",
+  "notification.update": "{name} змінює допис",
   "notifications.clear": "Очистити сповіщення",
   "notifications.clear_confirmation": "Ви впевнені, що хочете назавжди видалити всі сповіщеня?",
   "notifications.column_settings.alert": "Сповіщення на комп'ютері",
@@ -327,7 +327,7 @@
   "notifications.column_settings.status": "Нові дмухи:",
   "notifications.column_settings.unread_notifications.category": "Непрочитані сповіщення",
   "notifications.column_settings.unread_notifications.highlight": "Виділити непрочитані сповіщення",
-  "notifications.column_settings.update": "Edits:",
+  "notifications.column_settings.update": "Зміни:",
   "notifications.filter.all": "Усі",
   "notifications.filter.boosts": "Передмухи",
   "notifications.filter.favourites": "Улюблені",
diff --git a/app/javascript/mastodon/locales/vi.json b/app/javascript/mastodon/locales/vi.json
index 6c3c6936d..588721073 100644
--- a/app/javascript/mastodon/locales/vi.json
+++ b/app/javascript/mastodon/locales/vi.json
@@ -308,7 +308,7 @@
   "notification.poll": "Cuộc bình chọn đã kết thúc",
   "notification.reblog": "{name} chia sẻ tút của bạn",
   "notification.status": "{name} vừa đăng",
-  "notification.update": "{name} edited a post",
+  "notification.update": "{name} đã viết lại một tút",
   "notifications.clear": "Xóa hết thông báo",
   "notifications.clear_confirmation": "Bạn thật sự muốn xóa vĩnh viễn tất cả thông báo của mình?",
   "notifications.column_settings.alert": "Thông báo trên máy tính",
@@ -327,7 +327,7 @@
   "notifications.column_settings.status": "Tút mới:",
   "notifications.column_settings.unread_notifications.category": "Thông báo chưa đọc",
   "notifications.column_settings.unread_notifications.highlight": "Nổi bật thông báo chưa đọc",
-  "notifications.column_settings.update": "Edits:",
+  "notifications.column_settings.update": "Lượt sửa:",
   "notifications.filter.all": "Toàn bộ",
   "notifications.filter.boosts": "Chia sẻ",
   "notifications.filter.favourites": "Thích",
diff --git a/app/javascript/mastodon/locales/zh-CN.json b/app/javascript/mastodon/locales/zh-CN.json
index 53504c5ae..56dca56a6 100644
--- a/app/javascript/mastodon/locales/zh-CN.json
+++ b/app/javascript/mastodon/locales/zh-CN.json
@@ -308,7 +308,7 @@
   "notification.poll": "你参与的一个投票已经结束",
   "notification.reblog": "{name} 转嘟了你的嘟文",
   "notification.status": "{name} 刚刚发嘟",
-  "notification.update": "{name} edited a post",
+  "notification.update": "{name} 编辑了嘟文",
   "notifications.clear": "清空通知列表",
   "notifications.clear_confirmation": "你确定要永久清空通知列表吗?",
   "notifications.column_settings.alert": "桌面通知",
diff --git a/app/javascript/mastodon/locales/zh-TW.json b/app/javascript/mastodon/locales/zh-TW.json
index 609e79878..3f89737d4 100644
--- a/app/javascript/mastodon/locales/zh-TW.json
+++ b/app/javascript/mastodon/locales/zh-TW.json
@@ -308,7 +308,7 @@
   "notification.poll": "您曾投過的投票已經結束",
   "notification.reblog": "{name} 轉嘟了您的嘟文",
   "notification.status": "{name} 剛剛嘟文",
-  "notification.update": "{name} edited a post",
+  "notification.update": "{name} 編輯了嘟文",
   "notifications.clear": "清除通知",
   "notifications.clear_confirmation": "確定要永久清除您的通知嗎?",
   "notifications.column_settings.alert": "桌面通知",
@@ -327,7 +327,7 @@
   "notifications.column_settings.status": "新嘟文:",
   "notifications.column_settings.unread_notifications.category": "未讀通知",
   "notifications.column_settings.unread_notifications.highlight": "突顯未讀通知",
-  "notifications.column_settings.update": "Edits:",
+  "notifications.column_settings.update": "編輯:",
   "notifications.filter.all": "全部",
   "notifications.filter.boosts": "轉嘟",
   "notifications.filter.favourites": "最愛",
@@ -367,11 +367,11 @@
   "regeneration_indicator.label": "載入中…",
   "regeneration_indicator.sublabel": "您的主頁時間軸正在準備中!",
   "relative_time.days": "{number} 天",
-  "relative_time.full.days": "{number, plural, one {# 天} other {# 天}} 前",
-  "relative_time.full.hours": "{number, plural, one {# 小時} other {# 小時}} 前",
+  "relative_time.full.days": "{number, plural, one {# 天} other {# 天}}前",
+  "relative_time.full.hours": "{number, plural, one {# 小時} other {# 小時}}前",
   "relative_time.full.just_now": "剛剛",
-  "relative_time.full.minutes": "{number, plural, one {# 分鐘} other {# 分鐘}} 前",
-  "relative_time.full.seconds": "{number, plural, one {# 秒} other {# 秒}} 前",
+  "relative_time.full.minutes": "{number, plural, one {# 分鐘} other {# 分鐘}}前",
+  "relative_time.full.seconds": "{number, plural, one {# 秒} other {# 秒}}前",
   "relative_time.hours": "{number}小時前",
   "relative_time.just_now": "剛剛",
   "relative_time.minutes": "{number} 分前",
@@ -410,7 +410,7 @@
   "status.detailed_status": "詳細的對話內容",
   "status.direct": "發送私訊給 @{name}",
   "status.edit": "編輯",
-  "status.edited": "已編輯:{date}",
+  "status.edited": "編輯於 {date}",
   "status.edited_x_times": "已編輯 {count, plural, one {{count} 次} other {{count} 次}}",
   "status.embed": "內嵌",
   "status.favourite": "最愛",
diff --git a/app/javascript/mastodon/reducers/settings.js b/app/javascript/mastodon/reducers/settings.js
index 5146abe98..39639f3dc 100644
--- a/app/javascript/mastodon/reducers/settings.js
+++ b/app/javascript/mastodon/reducers/settings.js
@@ -37,6 +37,7 @@ const initialState = ImmutableMap({
       poll: false,
       status: false,
       update: false,
+      'admin.sign_up': false,
     }),
 
     quickFilter: ImmutableMap({
@@ -57,6 +58,7 @@ const initialState = ImmutableMap({
       poll: true,
       status: true,
       update: true,
+      'admin.sign_up': true,
     }),
 
     sounds: ImmutableMap({
@@ -68,6 +70,7 @@ const initialState = ImmutableMap({
       poll: true,
       status: true,
       update: true,
+      'admin.sign_up': true,
     }),
   }),
 
diff --git a/app/javascript/mastodon/service_worker/web_push_locales.js b/app/javascript/mastodon/service_worker/web_push_locales.js
index 807a1bcb9..7d713cd37 100644
--- a/app/javascript/mastodon/service_worker/web_push_locales.js
+++ b/app/javascript/mastodon/service_worker/web_push_locales.js
@@ -22,6 +22,7 @@ filenames.forEach(filename => {
     'notification.poll': full['notification.poll'] || '',
     'notification.status': full['notification.status'] || '',
     'notification.update': full['notification.update'] || '',
+    'notification.admin.sign_up': full['notification.admin.sign_up'] || '',
 
     'status.show_more': full['status.show_more'] || '',
     'status.reblog': full['status.reblog'] || '',
diff --git a/app/lib/feed_manager.rb b/app/lib/feed_manager.rb
index 7f2bc42d3..2c16689bd 100644
--- a/app/lib/feed_manager.rb
+++ b/app/lib/feed_manager.rb
@@ -549,7 +549,7 @@ class FeedManager
       end
     else
       # A reblog may reach earlier than the original status because of the
-      # delay of the worker deliverying the original status, the late addition
+      # delay of the worker delivering the original status, the late addition
       # by merging timelines, and other reasons.
       # If such a reblog already exists, just do not re-insert it into the feed.
       return false unless redis.zscore(reblog_key, status.id).nil?
diff --git a/app/models/notification.rb b/app/models/notification.rb
index c14eb8a7e..9bf296386 100644
--- a/app/models/notification.rb
+++ b/app/models/notification.rb
@@ -36,6 +36,7 @@ class Notification < ApplicationRecord
     favourite
     poll
     update
+    admin.sign_up
   ).freeze
 
   TARGET_STATUS_INCLUDES_BY_TYPE = {
@@ -63,13 +64,10 @@ class Notification < ApplicationRecord
   scope :without_suspended, -> { joins(:from_account).merge(Account.without_suspended) }
 
   scope :browserable, ->(exclude_types = [], account_id = nil) {
-    types = TYPES - exclude_types.map(&:to_sym)
-
-    if account_id.nil?
-      where(type: types)
-    else
-      where(type: types, from_account_id: account_id)
-    end
+    scope = all
+    scope = where(from_account_id: account_id) if account_id.present?
+    scope = scope.where(type: TYPES - exclude_types.map(&:to_sym)) unless exclude_types.empty?
+    scope
   }
 
   def type
@@ -142,6 +140,8 @@ class Notification < ApplicationRecord
       self.from_account_id = activity&.account_id
     when 'Mention'
       self.from_account_id = activity&.status&.account_id
+    when 'Account'
+      self.from_account_id = activity&.id
     end
   end
 end
diff --git a/app/services/bootstrap_timeline_service.rb b/app/services/bootstrap_timeline_service.rb
index e1a1b98c3..312c163e4 100644
--- a/app/services/bootstrap_timeline_service.rb
+++ b/app/services/bootstrap_timeline_service.rb
@@ -5,6 +5,7 @@ class BootstrapTimelineService < BaseService
     @source_account = source_account
 
     autofollow_inviter!
+    notify_staff!
   end
 
   private
@@ -14,4 +15,10 @@ class BootstrapTimelineService < BaseService
 
     FollowService.new.call(@source_account, @source_account.user.invite.user.account)
   end
+
+  def notify_staff!
+    User.staff.includes(:account).find_each do |user|
+      NotifyService.new.call(user.account, :'admin.sign_up', @source_account)
+    end
+  end
 end
diff --git a/app/services/fetch_link_card_service.rb b/app/services/fetch_link_card_service.rb
index 94dc6389f..239ab9b93 100644
--- a/app/services/fetch_link_card_service.rb
+++ b/app/services/fetch_link_card_service.rb
@@ -2,7 +2,7 @@
 
 class FetchLinkCardService < BaseService
   URL_PATTERN = %r{
-    (#{Twitter::TwitterText::Regex[:valid_url_preceding_chars]})                                                                #   $1 preceeding chars
+    (#{Twitter::TwitterText::Regex[:valid_url_preceding_chars]})                                                                #   $1 preceding chars
     (                                                                                                                           #   $2 URL
       (https?:\/\/)                                                                                                             #   $3 Protocol (required)
       (#{Twitter::TwitterText::Regex[:valid_domain]})                                                                           #   $4 Domain(s)
diff --git a/app/services/notify_service.rb b/app/services/notify_service.rb
index 039e007f5..b1f9fd755 100644
--- a/app/services/notify_service.rb
+++ b/app/services/notify_service.rb
@@ -22,34 +22,6 @@ class NotifyService < BaseService
     FeedManager.instance.filter?(:mentions, @notification.mention.status, @recipient)
   end
 
-  def blocked_status?
-    false
-  end
-
-  def blocked_favourite?
-    false
-  end
-
-  def blocked_follow?
-    false
-  end
-
-  def blocked_reblog?
-    false
-  end
-
-  def blocked_follow_request?
-    false
-  end
-
-  def blocked_poll?
-    false
-  end
-
-  def blocked_update?
-    false
-  end
-
   def following_sender?
     return @following_sender if defined?(@following_sender)
     @following_sender = @recipient.following?(@notification.from_account) || @recipient.requested?(@notification.from_account)
@@ -71,7 +43,7 @@ class NotifyService < BaseService
     message? && @notification.target_status.direct_visibility?
   end
 
-  # Returns true if the sender has been mentionned by the recipient up the thread
+  # Returns true if the sender has been mentioned by the recipient up the thread
   def response_to_recipient?
     return false if @notification.target_status.in_reply_to_id.nil?
 
@@ -149,15 +121,15 @@ class NotifyService < BaseService
 
     return blocked if message? && from_staff?
 
-    blocked ||= domain_blocking?                                 # Skip for domain blocked accounts
-    blocked ||= @recipient.blocking?(@notification.from_account) # Skip for blocked accounts
+    blocked ||= domain_blocking?
+    blocked ||= @recipient.blocking?(@notification.from_account)
     blocked ||= @recipient.muting_notifications?(@notification.from_account)
-    blocked ||= hellbanned?                                      # Hellban
-    blocked ||= optional_non_follower?                           # Options
-    blocked ||= optional_non_following?                          # Options
-    blocked ||= optional_non_following_and_direct?               # Options
+    blocked ||= hellbanned?
+    blocked ||= optional_non_follower?
+    blocked ||= optional_non_following?
+    blocked ||= optional_non_following_and_direct?
     blocked ||= conversation_muted?
-    blocked ||= send("blocked_#{@notification.type}?")           # Type-dependent filters
+    blocked ||= blocked_mention? if @notification.type == :mention
     blocked
   end
 
diff --git a/app/views/admin_mailer/new_trending_tags.text.erb b/app/views/admin_mailer/new_trending_tags.text.erb
index 5051e8a96..9ea31fa7c 100644
--- a/app/views/admin_mailer/new_trending_tags.text.erb
+++ b/app/views/admin_mailer/new_trending_tags.text.erb
@@ -13,4 +13,4 @@
 <%= t('admin_mailer.new_trending_tags.no_approved_tags') %>
 <% end %>
 
-<%= raw t('application_mailer.view')%> <%= admin_trends_tags_url(pending_review: '1') %>
+<%= raw t('application_mailer.view')%> <%= admin_trends_tags_url(status: 'pending_review') %>
diff --git a/config/i18n-tasks.yml b/config/i18n-tasks.yml
index e09f4262b..a3d7baecd 100644
--- a/config/i18n-tasks.yml
+++ b/config/i18n-tasks.yml
@@ -62,6 +62,7 @@ ignore_unused:
   - 'themes.*'
   - 'statuses.attached.*'
   - 'move_handler.carry_{mutes,blocks}_over_text'
+  - 'notification_mailer.*'
 
 ignore_inconsistent_interpolations:
   - '*.one'
diff --git a/config/initializers/preload_link_headers.rb b/config/initializers/preload_link_headers.rb
index 9f21c45ec..364a7cc1b 100644
--- a/config/initializers/preload_link_headers.rb
+++ b/config/initializers/preload_link_headers.rb
@@ -2,7 +2,7 @@
 # in the Links header per default.
 
 # In our case, that will bloat headers too much and potentially cause
-# issues with reverse proxies. Furhermore, we don't need those links,
+# issues with reverse proxies. Furthermore, we don't need those links,
 # as we already output them as HTML link tags.
 
 Rails.application.config.action_view.preload_links_header = false
diff --git a/config/locales/activerecord.lv.yml b/config/locales/activerecord.lv.yml
index f3524811b..ad9fa6604 100644
--- a/config/locales/activerecord.lv.yml
+++ b/config/locales/activerecord.lv.yml
@@ -3,7 +3,7 @@ lv:
   activerecord:
     attributes:
       poll:
-        expires_at: Gala termiņš
+        expires_at: Deadline
         options: Izvēles
       user:
         agreement: Pakalpojuma līgums
diff --git a/config/locales/devise.th.yml b/config/locales/devise.th.yml
index e53c0f895..14f99f2c3 100644
--- a/config/locales/devise.th.yml
+++ b/config/locales/devise.th.yml
@@ -55,7 +55,7 @@ th:
         subject: 'Mastodon: เปิดใช้งานการรับรองความถูกต้องด้วยสองปัจจัยแล้ว'
         title: เปิดใช้งาน 2FA แล้ว
       two_factor_recovery_codes_changed:
-        explanation: ยกเลิกรหัสกู้คืนก่อนหน้าและสร้างรหัสใหม่แล้ว
+        explanation: ยกเลิกรหัสกู้คืนก่อนหน้านี้และสร้างรหัสใหม่แล้ว
         subject: 'Mastodon: สร้างรหัสกู้คืนสองปัจจัยใหม่แล้ว'
         title: เปลี่ยนรหัสกู้คืน 2FA แล้ว
       unlock_instructions:
diff --git a/config/locales/en.yml b/config/locales/en.yml
index cf4c2cc37..c206c893b 100644
--- a/config/locales/en.yml
+++ b/config/locales/en.yml
@@ -1176,6 +1176,9 @@ en:
     carry_mutes_over_text: This user moved from %{acct}, which you had muted.
     copy_account_note_text: 'This user moved from %{acct}, here were your previous notes about them:'
   notification_mailer:
+    admin:
+      sign_up:
+        subject: "%{name} signed up"
     digest:
       action: View all notifications
       body: Here is a brief summary of the messages you missed since your last visit on %{since}
diff --git a/config/locales/eu.yml b/config/locales/eu.yml
index 3de853d47..785cf14d2 100644
--- a/config/locales/eu.yml
+++ b/config/locales/eu.yml
@@ -110,6 +110,7 @@ eu:
       confirm: Berretsi
       confirmed: Berretsita
       confirming: Berresten
+      custom: Pertsonalizatua
       delete: Ezabatu datuak
       deleted: Ezabatua
       demote: Jaitsi mailaz
@@ -201,6 +202,7 @@ eu:
       silenced: Isilarazita
       statuses: Bidalketa
       subscribe: Harpidetu
+      suspend: Kanporatu
       suspended: Kanporatuta
       suspension_irreversible: Kontu honen datuak behin betiko ezabatu dira. Kontua kanporatzea atzera bota dezakezu, berriz erabilgarri izan dadin, baina datuak ezingo dira berreskuratu.
       suspension_reversible_hint_html: Kontu hau kanporatua izan da eta bere datuak %{date}(e)an behin betiko ezabatuko dira. Ordura arte kontua kalterik gabe leheneratu daiteke. Kontuaren datu guztiak oraintxe bertan ezabatu nahi badituzu, jarraian egin dezakezu.
@@ -221,6 +223,7 @@ eu:
       whitelisted: Zerrenda zurian
     action_logs:
       action_types:
+        approve_appeal: Onartu apelazioa
         approve_user: Onartu erabiltzailea
         assigned_to_self_report: Esleitu salaketa
         change_email_user: Aldatu erabiltzailearen e-maila
@@ -252,6 +255,7 @@ eu:
         enable_user: Gaitu erabiltzailea
         memorialize_account: Bihurtu kontua oroigarri
         promote_user: Igo erabiltzailea mailaz
+        reject_appeal: Baztertu apelazioa
         reject_user: Baztertu erabiltzailea
         remove_avatar_user: Kendu abatarra
         reopen_report: Berrireki txostena
@@ -270,6 +274,7 @@ eu:
         update_domain_block: Eguneratu domeinu-blokeoa
         update_status: Eguneratu bidalketa
       actions:
+        approve_appeal_html: "%{name} erabiltzaileak %{target} erabiltzailearen moderazio erabakiaren apelazioa onartu du"
         approve_user_html: "%{name} erabiltzaileak %{target} erabiltzailearen izen-ematea onartu du"
         assigned_to_self_report_html: "%{name} erabiltzaileak %{target} salaketa bere buruari esleitu dio"
         change_email_user_html: "%{name} erabiltzaileak %{target} erabiltzailearen e-posta helbidea aldatu du"
@@ -301,6 +306,7 @@ eu:
         enable_user_html: "%{name} erabiltzaileak %{target} erabiltzailearen saioa gaitu du"
         memorialize_account_html: "%{name} erabiltzaileak %{target} kontua memoriala bihurtu du"
         promote_user_html: "%{name} erabiltzaileak %{target} erabiltzailea mailaz igo du"
+        reject_appeal_html: "%{name} erabiltzaileak %{target} erabiltzailearen moderazio erabakiaren apelazioa baztertu du"
         reject_user_html: "%{name} erabiltzaileak %{target} erabiltzailearen izen-ematea baztertu du"
         remove_avatar_user_html: "%{name} erabiltzaileak %{target} erabiltzailearen abatarra kendu du"
         reopen_report_html: "%{name} erabiltzaileak %{target} txostena berrireki du"
@@ -387,6 +393,10 @@ eu:
       top_languages: Hizkuntza aktiboenak
       top_servers: Zerbitzari aktiboenak
       website: Webgunea
+    disputes:
+      appeals:
+        empty: Ez da apelaziorik aurkitu.
+        title: Apelazioak
     domain_allows:
       add_new: Sartu domeinua zerrenda zurian
       created_msg: Domeinua ongi sartu da zerrenda zurian
@@ -424,6 +434,10 @@ eu:
         silence: isilarazia
         suspend: kanporatua
       show:
+        affected_accounts:
+          one: Datu-baseko kontu bati eragiten dio
+          other: Datu-baseko %{count} konturi eragiten die
+          zero: Ez die eragiten datu-baseko kontuei
         retroactive:
           silence: Kendu isilarazteko agindua domeinu honetako kontu guztiei
           suspend: Kendu kanporatzeko agindua domeinu honetako kontu guztiei
@@ -474,6 +488,10 @@ eu:
       delivery_error_hint: Banaketa ezin bada %{count} egunean egin, banaezin bezala markatuko da automatikoki.
       destroyed_msg: "%{domain} domeinuko datuak berehala ezabatzeko ilaran daude orain."
       empty: Ez da domeinurik aurkitu.
+      known_accounts:
+        one: Kontu ezagun %{count}
+        other: "%{count} kontu ezagun"
+        zero: Kontu ezagunik ez
       moderation:
         all: Denak
         limited: Mugatua
@@ -531,41 +549,61 @@ eu:
     report_notes:
       created_msg: Salaketa oharra ongi sortu da!
       destroyed_msg: Salaketa oharra ongi ezabatu da!
+      today_at: Gaur %{time}(e)tan
     reports:
       account:
         notes:
           one: Ohar %{count}
           other: "%{count} ohar"
+      action_log: Auditoria-egunkaria
       action_taken_by: Neurrien hartzailea
+      actions:
+        other_description_html: Ikusi kontuaren portaera kontrolatzeko eta salatutako kontuarekin komunikazioa pertsonalizatzeko aukera gehiago.
+        silence_description_html: Profila dagoeneko jarraitzen dutenei edo eskuz bilatzen dutenei bakarrik agertuko zaie, bere irismena asko mugatuz. Beti bota daiteke atzera.
+        suspend_description_html: Profila eta bere eduki guztiak iritsiezinak bihurtuko dira, ezabatzen den arte. Kontuarekin ezin da interakziorik eduki. Atzera bota daiteke 30 eguneko epean.
+      actions_description_html: Erabaki txosten hau konpontzeko ze ekintza hartu. Salatutako kontuaren aurka zigor ekintza bat hartzen baduzu, eposta jakinarazpen bat bidaliko zaie, <strong>Spam</strong> kategoria hautatzean ezik.
+      add_to_report: Gehitu gehiago txostenera
       are_you_sure: Ziur zaude?
       assign_to_self: Esleitu niri
       assigned: Esleitutako moderatzailea
       by_target_domain: Jakinarazitako kontuaren domeinua
+      category: Kategoria
+      category_description_html: Kontu edo/eta eduki hau salatu izanaren arrazoia salatutako kontuarekiko komunikazioan aipatuko da
       comment:
         none: Bat ere ez
+      comment_description_html: 'Informazio gehiago emateko, %{name} idatzi:'
       created_at: Salatua
+      delete_and_resolve: Ezabatu bidalketak
       forwarded: Birbidalia
       forwarded_to: 'Hona birbidalia: %{domain}'
       mark_as_resolved: Markatu konpondutako gisa
       mark_as_unresolved: Markatu konpondu gabeko gisa
+      no_one_assigned: Inor ez
       notes:
         create: Gehitu oharra
         create_and_resolve: Konpondu ohar batekin
         create_and_unresolve: Berrireki ohar batekin
         delete: Ezabatu
         placeholder: Azaldu hartutako neurriak, edo erlazioa duten bestelako berriak...
+        title: Oharrak
+      notes_description_html: Ikusi eta idatzi oharrak beste moderatzaileentzat eta zuretzat etorkizunerako
+      quick_actions_description_html: 'Hartu ekintza azkar bat edo korritu behera salatutako edukia ikusteko:'
       reopen: Berrireki salaketa
       report: 'Salaketa #%{id}'
       reported_account: Salatutako kontua
       reported_by: Salatzailea
       resolved: Konponduta
       resolved_msg: Salaketa ongi konpondu da!
+      skip_to_actions: Salto ekintzetara
       status: Mezua
+      statuses: Salatutako edukia
+      statuses_description_html: Salatutako edukia salatutako kontuarekiko komunikazioan aipatuko da
       target_origin: Salatutako kontuaren jatorria
       title: Salaketak
       unassign: Kendu esleipena
       unresolved: Konpondu gabea
       updated_at: Eguneratua
+      view_profile: Ikusi profila
     rules:
       add_new: Gehitu araua
       delete: Ezabatu
@@ -667,12 +705,21 @@ eu:
       destroyed_msg: Guneko igoera ongi ezabatu da!
     statuses:
       back_to_account: Atzera kontuaren orrira
+      back_to_report: Atzera txostenaren orrira
+      batch:
+        remove_from_report: Kendu txostenetik
+        report: Salatu
       deleted: Ezabatuta
       media:
         title: Multimedia
       no_status_selected: Ez da bidalketarik aldatu ez delako bidalketarik aukeratu
       title: Kontuaren bidalketak
       with_media: Multimediarekin
+    strikes:
+      actions:
+        delete_statuses: "%{name} erabiltzaileak %{target} erabiltzailearen bidalketak ezabatu ditu"
+        disable: "%{name} erabiltzailea %{target} erabiltzailearen kontua izoztu du"
+        none: "%{name} erabiltzaileak abisua bidali dio %{target} erabiltzaileari"
     system_checks:
       database_schema_check:
         message_html: Aplikatu gabeko datu-basearen migrazioak daude. Exekutatu aplikazioak esperotako portaera izan dezan
diff --git a/config/locales/fi.yml b/config/locales/fi.yml
index ebbd417ae..f438552ce 100644
--- a/config/locales/fi.yml
+++ b/config/locales/fi.yml
@@ -162,6 +162,11 @@ fi:
       not_subscribed: Ei tilaaja
       pending: Odottaa tarkistusta
       perform_full_suspension: Siirrä kokonaan jäähylle
+      previous_strikes: Aiemmat varoitukset
+      previous_strikes_description_html:
+        one: Tällä tilillä on <strong>yksi</strong> varoitus.
+        other: Tällä tilillä on <strong>%{count}</strong> varoitusta.
+        zero: Tämä tili on <strong>hyvässä kunnossa</strong>.
       promote: Ylennä
       protocol: Protokolla
       public: Julkinen
@@ -226,6 +231,7 @@ fi:
       whitelisted: Sallittu liittämiselle
     action_logs:
       action_types:
+        approve_appeal: Hyväksy valitus
         approve_user: Hyväksy käyttäjä
         assigned_to_self_report: Määritä raportti
         change_email_user: Vaihda sähköposti käyttäjälle
@@ -257,6 +263,7 @@ fi:
         enable_user: Tili otettu käyttöön
         memorialize_account: Muuta muistotiliksi
         promote_user: Käyttäjä ylennetty
+        reject_appeal: Hylkää valitus
         reject_user: Hylkää käyttäjä
         remove_avatar_user: Profiilikuvan poisto
         reopen_report: Uudelleenavaa raportti
@@ -275,6 +282,7 @@ fi:
         update_domain_block: Päivitä verkkotunnuksen esto
         update_status: Päivitä viesti
       actions:
+        approve_appeal_html: "%{name} hyväksyi moderointipäätöksen muutoksenhaun lähettäjältä %{target}"
         approve_user_html: "%{name} hyväksyi käyttäjän rekisteröitymisen kohteesta %{target}"
         assigned_to_self_report_html: "%{name} otti raportin %{target} tehtäväkseen"
         change_email_user_html: "%{name} vaihtoi käyttäjän %{target} sähköpostiosoitteen"
@@ -306,6 +314,7 @@ fi:
         enable_user_html: "%{name} salli kirjautumisen käyttäjälle %{target}"
         memorialize_account_html: "%{name} muutti käyttäjän %{target} tilin muistosivuksi"
         promote_user_html: "%{name} ylensi käyttäjän %{target}"
+        reject_appeal_html: "%{name} hylkäsi moderointipäätöksen muutoksenhaun %{target}"
         reject_user_html: "%{name} hylkäsi käyttäjän rekisteröitymisen kohteesta %{target}"
         remove_avatar_user_html: "%{name} poisti käyttäjän %{target} profiilikuvan"
         reopen_report_html: "%{name} avasi uudelleen raportin %{target}"
@@ -384,6 +393,18 @@ fi:
       media_storage: Median tallennustila
       new_users: uudet käyttäjät
       opened_reports: raportit avattu
+      pending_appeals_html:
+        one: "<strong>%{count}</strong> vireillä oleva valitus"
+        other: "<strong>%{count}</strong> vireillä olevat valitukset"
+      pending_reports_html:
+        one: "<strong>%{count}</strong> odottava raportti"
+        other: "<strong>%{count}</strong> odottavat raportit"
+      pending_tags_html:
+        one: "<strong>%{count}</strong> odottava hashtagi"
+        other: "<strong>%{count}</strong> odottavat hashtagit"
+      pending_users_html:
+        one: "<strong>%{count}</strong> odottava käyttäjä"
+        other: "<strong>%{count}</strong> odottavat käyttäjät"
       resolved_reports: raportit ratkaistu
       software: Ohjelmisto
       sources: Kirjautumisen lähteet
@@ -392,6 +413,10 @@ fi:
       top_languages: Aktiiviset kielet
       top_servers: Aktiiviset palvelimet
       website: Sivusto
+    disputes:
+      appeals:
+        empty: Valituksia ei löytynyt.
+        title: Valitukset
     domain_allows:
       add_new: Salli liitto verkkotunnuksella
       created_msg: Verkkotunnus on onnistuneesti sallittu federaatiolle
@@ -429,6 +454,10 @@ fi:
         silence: hiljennetty
         suspend: jäähyllä
       show:
+        affected_accounts:
+          one: Tämä vaikuttaa yhteen tiliin tietokannassa
+          other: Vaikuttaa %{count} tiliin tietokannassa
+          zero: Tämä ei vaikuta mihinkään tietokannan tiliin
         retroactive:
           silence: Peru kaikkien tässä verkkotunnuksessa jo olemassa olevien tilien hiljennys
           suspend: Peru kaikkien tässä verkkotunnuksessa jo olemassa olevien tilien jäähy
@@ -471,11 +500,18 @@ fi:
         unavailable: Ei saatavilla
         unavailable_message: Toimitus ei käytettävissä
         warning: Varoitus
+        warning_message:
+          one: Toimitusvirhe %{count} päivä
+          other: Toimitushäiriö %{count} päivää
       delivery_available: Toimitus on saatavilla
       delivery_error_days: Toimitusvirheen päivät
       delivery_error_hint: Jos toimitus ei ole mahdollista %{count} päivän aikana, se merkitään automaattisesti toimittamattomaksi.
       destroyed_msg: Tiedot %{domain} on nyt jonossa välitöntä poistoa varten.
       empty: Verkkotunnuksia ei löytynyt.
+      known_accounts:
+        one: "%{count} tunnettu tili"
+        other: "%{count} tunnettua tiliä"
+        zero: Ei tunnettua tiliä
       moderation:
         all: Kaikki
         limited: Rajoitettu
@@ -535,6 +571,10 @@ fi:
       destroyed_msg: Muistiinpano onnistuneesti poistettu raportista!
       today_at: Tänään klo %{time}
     reports:
+      account:
+        notes:
+          one: "%{count} ilmoitus"
+          other: "%{count} ilmoitusta"
       action_log: Tarkastusloki
       action_taken_by: Toimenpiteen tekijä
       actions:
@@ -901,6 +941,12 @@ fi:
     directory: Profiilihakemisto
     explanation: Löydä käyttäjiä heidän kiinnostustensa mukaan
     explore_mastodon: Tutki %{title}ia
+  disputes:
+    strikes:
+      created_at: Päivätty
+      recipient: Osoitettu
+      status: 'Viesti #%{id}'
+      status_removed: Viesti on jo poistettu järjestelmästä
   domain_validator:
     invalid_domain: ei ole kelvollinen toimialueen nimi
   errors:
@@ -1359,6 +1405,7 @@ fi:
     formats:
       default: "%d.%m.%Y klo %H.%M"
       month: "%b %Y"
+      time: "%H:%M"
   two_factor_authentication:
     add: Lisää
     disable: Poista käytöstä
@@ -1385,12 +1432,17 @@ fi:
       subject: Ole hyvä ja vahvista sisäänkirjautumisyritys
       title: Sisäänkirjautumisyritys
     warning:
+      categories:
+        spam: Roskaposti
+      reason: 'Syy:'
       subject:
         disable: Tilisi %{acct} on jäädytetty
         none: Varoitus %{acct}
       title:
+        delete_statuses: Viestit poistettu
         disable: Tili jäädytetty
         none: Varoitus
+        sensitive: Media piilotettu
         silence: Rajoitettu tili
         suspend: Tilin käyttäminen keskeytetty
     welcome:
diff --git a/config/locales/fr.yml b/config/locales/fr.yml
index bcde82bde..2673b25cb 100644
--- a/config/locales/fr.yml
+++ b/config/locales/fr.yml
@@ -16,11 +16,11 @@ fr:
     contact: Contact
     contact_missing: Non défini
     contact_unavailable: Non disponible
-    discover_users: Découvrez des utilisateurs
+    discover_users: Découvrez des utilisateur·rice·s
     documentation: Documentation
-    federation_hint_html: Avec un compte sur %{instance}, vous pourrez suivre les gens sur n’importe quel serveur Mastodon et au-delà.
+    federation_hint_html: Avec un compte sur %{instance}, vous pourrez suivre des gens sur n’importe quel serveur Mastodon et au-delà.
     get_apps: Essayez une application mobile
-    hosted_on: Serveur Mastodon hébergé par %{domain}
+    hosted_on: Serveur Mastodon hébergé sur %{domain}
     instance_actor_flash: |
       Ce compte est un acteur virtuel utilisé pour représenter le serveur lui-même et non un·e utilisateur·rice individuel·le.
       Il est utilisé à des fins de fédération et ne doit pas être bloqué à moins que vous ne vouliez bloquer l’instance entière, auquel cas vous devriez utiliser un blocage de domaine.
@@ -35,7 +35,7 @@ fr:
       one: message
       other: messages
     status_count_before: Ayant publié
-    tagline: Suivez vos amis et découvrez-en de nouveaux
+    tagline: Suivez vos ami·e·s et découvrez-en de nouveaux·elles
     terms: Conditions d’utilisation
     unavailable_content: Serveurs modérés
     unavailable_content_description:
@@ -162,6 +162,11 @@ fr:
       not_subscribed: Non abonné
       pending: En attente d’approbation
       perform_full_suspension: Suspendre
+      previous_strikes: Sanctions précédentes
+      previous_strikes_description_html:
+        one: Ce compte a reçu <strong>une</strong> sanction.
+        other: Ce compte a reçu <strong>%{count}</strong> sanctions.
+        zero: Ce compte est <strong>en règle</strong>.
       promote: Promouvoir
       protocol: Protocole
       public: Publique
@@ -226,6 +231,7 @@ fr:
       whitelisted: Sur liste blanche
     action_logs:
       action_types:
+        approve_appeal: Approuver l'appel
         approve_user: Approuver l’utilisateur
         assigned_to_self_report: Affecter le signalement
         change_email_user: Modifier le courriel pour
@@ -257,6 +263,7 @@ fr:
         enable_user: Activer l’utilisateur
         memorialize_account: Ériger en mémorial
         promote_user: Promouvoir l’utilisateur
+        reject_appeal: Rejeter l'appel
         reject_user: Rejeter l’utilisateur
         remove_avatar_user: Supprimer l’avatar
         reopen_report: Rouvrir le signalement
@@ -275,6 +282,7 @@ fr:
         update_domain_block: Mettre à jour le blocage de domaine
         update_status: Mettre à jour le message
       actions:
+        approve_appeal_html: "%{name} a approuvé l'appel de la décision de modération émis par %{target}"
         approve_user_html: "%{name} a approuvé l’inscription de %{target}"
         assigned_to_self_report_html: "%{name} s’est assigné·e le signalement de %{target}"
         change_email_user_html: "%{name} a modifié l'adresse de courriel de l'utilisateur·rice %{target}"
@@ -306,6 +314,7 @@ fr:
         enable_user_html: "%{name} a activé la connexion de l'utilisateur·rice %{target}"
         memorialize_account_html: "%{name} a converti le compte de %{target} en un mémorial"
         promote_user_html: "%{name} a promu l'utilisateur·rice %{target}"
+        reject_appeal_html: "%{name} a rejeté l'appel de la décision de modération émis par %{target}"
         reject_user_html: "%{name} a rejeté l’inscription de %{target}"
         remove_avatar_user_html: "%{name} a supprimé l'avatar de %{target}"
         reopen_report_html: "%{name} a rouvert le signalement %{target}"
@@ -384,6 +393,9 @@ fr:
       media_storage: Stockage des médias
       new_users: nouveaux utilisateurs
       opened_reports: rapports ouverts
+      pending_appeals_html:
+        one: "<strong>%{count}</strong> appel en attente"
+        other: "<strong>%{count}</strong> appels en attente"
       pending_reports_html:
         one: "<strong>%{count}</strong> rapport en attente"
         other: "<strong>%{count}</strong> rapports en attente"
@@ -401,6 +413,10 @@ fr:
       top_languages: Langues les plus actives
       top_servers: Serveurs les plus actifs
       website: Site Web
+    disputes:
+      appeals:
+        empty: Aucun appel trouvé.
+        title: Appels
     domain_allows:
       add_new: Mettre le domaine sur liste sur blanche
       created_msg: Ce domaine a été ajouté à la liste blanche avec succès
@@ -562,9 +578,12 @@ fr:
       action_log: Journal d’audit
       action_taken_by: Intervention de
       actions:
+        delete_description_html: Les messages signalés seront supprimés et une sanction sera enregistrée pour vous aider à prendre les mesures appropriées en cas d'infractions futures par le même compte.
         other_description_html: Voir plus d'options pour contrôler le comportement du compte et personnaliser la communication vers le compte signalé.
+        resolve_description_html: Aucune mesure ne sera prise contre le compte signalé, aucune sanction ne sera enregistrée et le sigalement sera clôturé.
         silence_description_html: Le profil ne sera visible que pour ceux qui le suivent déjà ou le consultent manuellement, ce qui limite considérablement sa portée. Peut toujours être restauré.
         suspend_description_html: Le profil et tout son contenu deviendront inaccessibles jusqu'à ce qu'il soit éventuellement supprimé. Interagir avec le compte sera impossible. Réversible dans les 30 jours.
+      actions_description_html: Décidez des mesures à prendre pour résoudre ce signalement. Si vous prenez des mesures punitives contre le compte signalé, une notification sera envoyée par e-mail, sauf si la catégorie <strong>Spam</strong> est sélectionnée.
       add_to_report: Ajouter davantage au rapport
       are_you_sure: Voulez-vous vraiment faire ça ?
       assign_to_self: Me l’assigner
@@ -718,6 +737,16 @@ fr:
       no_status_selected: Aucun statut n’a été modifié car aucun n’a été sélectionné
       title: Messages du compte
       with_media: Avec médias
+    strikes:
+      actions:
+        delete_statuses: "%{name} a supprimé les messages de %{target}"
+        disable: "%{name} a bloqué le compte de %{target}"
+        none: "%{name} a envoyé un avertissement à %{target}"
+        sensitive: "%{name} a marqué le compte de %{target} comme sensible"
+        silence: "%{name} a limité le compte de %{target}"
+        suspend: "%{name} a suspendu le compte de %{target}"
+      appeal_approved: Appel soumis
+      appeal_pending: Appel en attente
     system_checks:
       database_schema_check:
         message_html: Vous avez des migrations de base de données en attente. Veuillez les exécuter pour vous assurer que l'application se comporte comme prévu
@@ -739,6 +768,10 @@ fr:
         allow_provider: Autoriser l'éditeur
         disallow: Interdire le lien
         disallow_provider: Interdire l'éditeur
+        shared_by_over_week:
+          one: Partagé par une personne au cours de la semaine dernière
+          other: Partagé par %{count} personnes au cours de la semaine dernière
+          zero: Non partagé au cours de la semaine dernière
         title: Liens tendances
         usage_comparison: Partagé %{today} fois aujourd'hui, comparé à %{yesterday} hier
       pending_review: En attente de révision
@@ -765,6 +798,10 @@ fr:
         trending_rank: 'Tendance #%{rank}'
         usable: Peut être utilisé
         usage_comparison: Utilisé %{today} fois aujourd'hui, comparé à %{yesterday} hier
+        used_by_over_week:
+          one: Utilisé par une personne au cours de la semaine dernière
+          other: Utilisé par %{count} personnes au cours de la semaine dernière
+          zero: Non utilisé au cours de la semaine dernière
       title: Tendances
     warning_presets:
       add_new: Ajouter un nouveau
@@ -773,6 +810,17 @@ fr:
       empty: Vous n'avez pas encore créé de paramètres prédéfinis pour les avertissements.
       title: Gérer les avertissements prédéfinis
   admin_mailer:
+    new_appeal:
+      actions:
+        delete_statuses: effacer les messages
+        disable: bloquer le compte
+        none: un avertissement
+        sensitive: marquer le compte comme sensible
+        silence: limiter le compte
+        suspend: suspendre le compte
+      body: "%{target} fait appel de la décision de modération émise par %{action_taken_by} le %{date} et qui était : %{type}. Cette personne a écrit :"
+      next_steps: Vous pouvez approuver l'appel pour annuler la décision de modération, ou l'ignorer.
+      subject: "%{username} fait appel d'une décision de modération sur %{instance}"
     new_pending_account:
       body: Les détails du nouveau compte se trouvent ci-dessous. Vous pouvez approuver ou rejeter cette demande.
       subject: Nouveau compte à examiner sur %{instance} (%{username})
@@ -928,6 +976,31 @@ fr:
     directory: Annuaire des profils
     explanation: Découvrir des utilisateur·rice·s en fonction de leurs centres d’intérêt
     explore_mastodon: Explorer %{title}
+  disputes:
+    strikes:
+      action_taken: Mesure prise
+      appeal_approved: Cette sanction a été annulée en appel et n'est plus valide
+      appeal_rejected: L'appel a été rejeté
+      appeal_submitted_at: Appel soumis le
+      appealed_msg: Votre demande d'appel a été soumise. Si elle est approuvée, vous en serez informé·e.
+      appeals:
+        submit: Faire appel
+      associated_report: Rapport associé
+      created_at: En date du
+      recipient: Adressé à
+      status: 'Message #%{id}'
+      status_removed: Message déjà supprimé du système
+      title: "%{action} du %{date}"
+      title_actions:
+        delete_statuses: Suppression de message
+        disable: Suspension de compte
+        none: Avertissement
+        sensitive: Marquage d'un compte comme sensible
+        silence: Limitation du compte
+        suspend: Suspension de compte
+      your_appeal_approved: Votre appel a été approuvé
+      your_appeal_pending: Vous avez soumis un appel
+      your_appeal_rejected: Votre appel a été rejeté
   domain_validator:
     invalid_domain: n’est pas un nom de domaine valide
   errors:
@@ -1222,6 +1295,9 @@ fr:
     reply:
       proceed: Confirmer la réponse
       prompt: 'Vous souhaitez répondre à ce message :'
+  reports:
+    errors:
+      invalid_rules: ne fait pas référence à des règles valides
   scheduled_statuses:
     over_daily_limit: Vous avez dépassé la limite de %{limit} messages planifiés par jour
     over_total_limit: Vous avez dépassé la limite de %{limit} messages planifiés
@@ -1488,6 +1564,15 @@ fr:
     recovery_instructions_html: Si vous perdez l’accès à votre téléphone, vous pouvez utiliser un des codes de récupération ci-dessous pour retrouver l’accès à votre compte. <strong>Conservez les codes de récupération en sécurité</strong>. Par exemple, en les imprimant et en les stockant avec vos autres documents importants.
     webauthn: Clés de sécurité
   user_mailer:
+    appeal_approved:
+      action: Aller à votre compte
+      explanation: L'appel de la sanction contre votre compte mise en place le %{strike_date} que vous avez soumis le %{appeal_date} a été approuvé. Votre compte est de nouveau en règle.
+      subject: Votre appel du %{date} a été approuvé
+      title: Appel approuvé
+    appeal_rejected:
+      explanation: L'appel de la sanction contre votre compte mise en place le %{strike_date} que vous avez soumis le %{appeal_date} a été rejeté.
+      subject: Votre appel du %{date} a été rejeté
+      title: Appel rejeté
     backup_ready:
       explanation: Vous avez demandé une sauvegarde complète de votre compte Mastodon. Elle est maintenant prête à être téléchargée !
       subject: Votre archive est prête à être téléchargée
@@ -1499,6 +1584,8 @@ fr:
       subject: Veuillez confirmer la tentative de connexion
       title: Tentative de connexion
     warning:
+      appeal: Faire appel
+      appeal_description: Si vous pensez qu'il s'agit d'une erreur, vous pouvez faire appel auprès de l'équipe de %{instance}.
       categories:
         spam: Indésirable
         violation: Le contenu viole les directives de la communauté suivantes
diff --git a/config/locales/he.yml b/config/locales/he.yml
index fab6e3b89..454a48e09 100644
--- a/config/locales/he.yml
+++ b/config/locales/he.yml
@@ -120,6 +120,10 @@ he:
       reject_media: חסימת קבצי מדיה
       reject_media_hint: מסירה קבצי מדיה השמורים מקומית ומונעת מהורדת קבצים נוספים בעתיד. לא רלוונטי להשעיות
       show:
+        affected_accounts:
+          one: חשבון אחד במסד נתונים מושפע
+          other: "%{count} חשבונות במסד נתונים מושפעים"
+          zero: אף חשבון במסד נתונים מושפע
         retroactive:
           silence: הסרת השתקה מכל החשבונות על שרת זה
           suspend: הסרת השעייה מכל החשבונות על שרת זה
@@ -175,6 +179,17 @@ he:
         remove_from_report: הסרה מהדיווח
         report: דווח
     title: ניהול
+    trends:
+      links:
+        shared_by_over_week:
+          one: שותף ע"י משתמש\ת אחד\ת בשבוע האחרון
+          other: שותף ע"י %{count} משתמשים בשבוע האחרון
+          zero: לא שותף בכלל בשבוע האחרון
+      tags:
+        used_by_over_week:
+          one: היה בשימוש משתמש\ת אחד\ת בשבוע האחרון
+          other: היה בשימוש ע"י %{count} משתמשים בשבוע האחרון
+          zero: לא היה בשימוש בכלל בשבוע האחרון
   application_mailer:
     settings: 'שינוי הגדרות דוא"ל: %{link}'
     view: 'תצוגה:'
diff --git a/config/locales/id.yml b/config/locales/id.yml
index ccd8d6479..76e91c9d2 100644
--- a/config/locales/id.yml
+++ b/config/locales/id.yml
@@ -786,6 +786,10 @@ id:
         trending_rank: 'Sedang tren #%{rank}'
         usable: Dapat digunakan
         usage_comparison: Digunakan %{today} kali hari ini, dibandingkan %{yesterday} kemarin
+        used_by_over_week:
+          one: Dipakai oleh satu orang lebih dari seminggu lalu
+          other: Dipakai oleh %{count} orang selama seminggu terakhir
+          zero: Tidak dipakai siapapun lebih dari seminggu lalu
       title: Tren
     warning_presets:
       add_new: Tambah baru
@@ -980,6 +984,12 @@ id:
         delete_statuses: Penghapusan kiriman
         disable: Pembekuan akun
         none: Peringatan
+        sensitive: Tandai akun sebagai sensitif
+        silence: Pembatasan akun
+        suspend: Penangguhan akun
+      your_appeal_approved: Banding Anda disetujui
+      your_appeal_pending: Anda telah mengirim banding
+      your_appeal_rejected: Banding Anda ditolak
   domain_validator:
     invalid_domain: bukan nama domain yang valid
   errors:
@@ -1533,6 +1543,15 @@ id:
     recovery_instructions_html: Jika anda kehilangan akses pada handphone anda, anda bisa menggunakan kode pemulihan dibawah ini untuk mendapatkan kembali akses pada akun anda. Simpan kode pemulihan anda baik-baik, misalnya dengan mencetaknya atau menyimpannya bersama dokumen penting lainnya.
     webauthn: Kunci keamanan
   user_mailer:
+    appeal_approved:
+      action: Ke akun Anda
+      explanation: Banding peringatan terhadap akun Anda pada %{strike_date} yang Anda kirim pada %{appeal_date} telah disetujui. Akun Anda akan kembali ditandai sebagai akun bagus.
+      subject: Banding Anda dari %{date} telah disetujui
+      title: Banding disetujui
+    appeal_rejected:
+      explanation: Banding terhadap akun Anda pada %{strike_date} yang Anda ajukan %{appeal_date} telah ditolak.
+      subject: Banding Anda dari %{date} telah ditolak
+      title: Banding ditolak
     backup_ready:
       explanation: Cadangan penuh akun Mastodon Anda sudah dapat diunduh!
       subject: Arsip Anda sudah siap diunduh
@@ -1544,6 +1563,8 @@ id:
       subject: Harap konfirmasi usaha masuk akun
       title: Usaha masuk akun
     warning:
+      appeal: Ajukan banding
+      appeal_description: Jika Anda yakin ini galat, Anda dapat mengajukan banding ke staf %{instance}.
       categories:
         spam: Spam
         violation: Konten melanggar panduan komunitas berikut
diff --git a/config/locales/ja.yml b/config/locales/ja.yml
index f07659549..1b79cd7f9 100644
--- a/config/locales/ja.yml
+++ b/config/locales/ja.yml
@@ -198,6 +198,7 @@ ja:
       silenced: サイレンス済み
       statuses: 投稿数
       subscribe: 購読する
+      suspend: サスペンド
       suspended: 停止済み
       suspension_irreversible: このアカウントのデータは削除され元に戻せなくなります。後日アカウントの凍結を解除することはできますがデータは元に戻せません。
       suspension_reversible_hint_html: アカウントは停止されており、データは %{date} に完全に削除されます。それまではアカウントを元に戻すことができます。今すぐ完全に削除したい場合は以下から行うことができます。
@@ -218,6 +219,7 @@ ja:
       whitelisted: 連合許可済み
     action_logs:
       action_types:
+        approve_appeal: 抗議を承認
         approve_user: ユーザーの承認
         assigned_to_self_report: 通報の担当者に設定
         change_email_user: ユーザーのメールアドレスを変更
@@ -249,6 +251,7 @@ ja:
         enable_user: ユーザーを有効化
         memorialize_account: 追悼アカウント化
         promote_user: ユーザーを昇格
+        reject_appeal: 抗議を却下
         reject_user: ユーザーを拒否
         remove_avatar_user: アイコンを削除
         reopen_report: 未解決に戻す
@@ -267,6 +270,7 @@ ja:
         update_domain_block: ドメインブロックを更新
         update_status: 投稿を更新
       actions:
+        approve_appeal_html: "%{name} さんが %{target} からの抗議を承認しました"
         approve_user_html: "%{target} から登録された %{name} さんを承認しました"
         assigned_to_self_report_html: "%{name} さんが通報 %{target} を自身の担当に割り当てました"
         change_email_user_html: "%{name} さんが %{target} さんのメールアドレスを変更しました"
@@ -298,6 +302,7 @@ ja:
         enable_user_html: "%{name} さんが %{target} さんのログインを有効化しました"
         memorialize_account_html: "%{name} さんが %{target} さんを追悼アカウントページに登録しました"
         promote_user_html: "%{name} さんが %{target} さんを昇格しました"
+        reject_appeal_html: "%{name} さんが %{target} からの抗議を却下しました"
         reject_user_html: "%{target} から登録された %{name} さんを拒否しました"
         remove_avatar_user_html: "%{name} さんが %{target} さんのアイコンを削除しました"
         reopen_report_html: "%{name} さんが通報 %{target} を未解決に戻しました"
@@ -376,6 +381,14 @@ ja:
       media_storage: メディアストレージ
       new_users: 新規ユーザー
       opened_reports: 新規通報
+      pending_appeals_html:
+        other: 保留中の抗議 <strong>%{count}</strong> 件
+      pending_reports_html:
+        other: 保留中の通報 <strong>%{count}</strong> 件
+      pending_tags_html:
+        other: 保留中のハッシュタグ <strong>%{count}</strong> 件
+      pending_users_html:
+        other: 保留中のユーザー <strong>%{count}</strong> 件
       resolved_reports: 解決済みの通報
       software: ソフトウェア
       sources: サインアップソース
@@ -384,6 +397,10 @@ ja:
       top_languages: トップのアクティブ言語
       top_servers: トップアクティブサーバー
       website: ウェブサイト
+    disputes:
+      appeals:
+        empty: 抗議はありません。
+        title: 抗議
     domain_allows:
       add_new: 連合を許可
       created_msg: 連合を許可しました
@@ -893,6 +910,9 @@ ja:
     directory: ディレクトリ
     explanation: 関心を軸にユーザーを発見しよう
     explore_mastodon: "%{title}を探索"
+  disputes:
+    strikes:
+      appeal: 抗議
   domain_validator:
     invalid_domain: は無効なドメイン名です
   errors:
@@ -1300,8 +1320,8 @@ ja:
     enabled_hint: 設定した期間を過ぎた投稿は、以下の例外に該当しない限り、自動的に削除されます
     exceptions: 例外
     explanation: 投稿の削除はサーバーに負荷がかかるため、サーバーが混み合っていないときに時間をかけて行われます。
-    ignore_favs: お気に入りされた数を無視
-    ignore_reblogs: ブーストされた数を無視
+    ignore_favs: 設定しない
+    ignore_reblogs: 設定しない
     interaction_exceptions: インタラクションに基づく例外
     interaction_exceptions_explanation: お気に入りやブーストの基準値を一度超えてしまった投稿は、基準値を下回った後であっても、削除される保証はありません。
     keep_direct: ダイレクトメッセージを保持
@@ -1325,10 +1345,10 @@ ja:
       '63113904': 2年
       '7889238': 3ヶ月
     min_age_label: 投稿を保持する期間
-    min_favs: これ以上お気に入りに登録された投稿を無視する
-    min_favs_hint: この数以上、お気に入りに登録された投稿を削除しません。空白にしておくと、お気に入りに登録された数に関わらず投稿を削除します。
-    min_reblogs: これ以上ブーストされた投稿を無視する
-    min_reblogs_hint: この数以上、ブーストされた投稿を削除しません。空白にしておくと、ブーストされた数に関わらず投稿を削除します。
+    min_favs: お気に入りの基準値
+    min_favs_hint: この数以上、お気に入りされた投稿を削除せずに残します。空白にしておくと、お気に入りに登録された数に関わらず投稿を削除します。
+    min_reblogs: ブーストの基準値
+    min_reblogs_hint: この数以上、ブーストされた投稿を削除せずに残します。空白にしておくと、ブーストされた数に関わらず投稿を削除します。
   stream_entries:
     pinned: 固定された投稿
     reblogged: さんがブースト
diff --git a/config/locales/ru.yml b/config/locales/ru.yml
index cf49e396b..f99d8962a 100644
--- a/config/locales/ru.yml
+++ b/config/locales/ru.yml
@@ -929,7 +929,12 @@ ru:
     explore_mastodon: Изучайте %{title}
   disputes:
     strikes:
+      action_taken: Предпринятые меры
       appeal_approved: Это замечание было успешно обжаловано и более не действительно
+      appeals:
+        submit: Подать обжалование
+      created_at: Дата
+      recipient: Адресовано
       status: 'Пост #%{id}'
       title: "%{action} от %{date}"
       your_appeal_approved: Ваша апелляция одобрена
@@ -1293,7 +1298,7 @@ ru:
     authorized_apps: Приложения
     back: Назад в Mastodon
     delete: Удаление учётной записи
-    development: Разработка
+    development: Разработчикам
     edit_profile: Изменить профиль
     export: Экспорт данных
     featured_tags: Особенные хэштеги
@@ -1514,6 +1519,7 @@ ru:
     webauthn: Ключи безопасности
   user_mailer:
     appeal_approved:
+      action: Перейти к своему профилю
       subject: Ваша апелляция от %{date} была одобрена
       title: Апелляция одобрена
     appeal_rejected:
diff --git a/config/locales/simple_form.fi.yml b/config/locales/simple_form.fi.yml
index 87adfe1cc..25ff3a162 100644
--- a/config/locales/simple_form.fi.yml
+++ b/config/locales/simple_form.fi.yml
@@ -77,16 +77,35 @@ fi:
       ip_block:
         comment: Valinnainen. Muista miksi lisäsit tämän säännön.
         expires_in: IP-osoitteet ovat rajallinen resurssi, joskus niitä jaetaan ja vaihtavat usein omistajaa. Tästä syystä epämääräisiä IP-lohkoja ei suositella.
+        ip: Kirjoita IPv4- tai IPv6-osoite. Voit estää kokonaisia alueita käyttämällä CIDR-syntaksia. Varo, että et lukitse itseäsi!
+        severities:
+          no_access: Estä pääsy kaikkiin resursseihin
+          sign_up_requires_approval: Uudet rekisteröitymiset edellyttävät hyväksyntääsi
+        severity: Valitse, mitä tapahtuu tämän IP-osoitteen pyynnöille
+      rule:
+        text: Kuvaile sääntöä tai vaatimusta tämän palvelimen käyttäjille. Yritä pitää se lyhyenä ja yksinkertaisena
       sessions:
         otp: Syötä puhelimeen saamasi kaksivaiheisen tunnistautumisen koodi tai käytä palautuskoodia.
+        webauthn: Jos kyseessä on USB-avain, muista laittaa se paikalleen ja tarvittaessa napauttaa sitä.
+      tag:
+        name: Voit muuttaa esimerkiksi kirjaimia paremmin luettavaksi
+      user:
+        chosen_languages: Kun valittu, vain valituilla kielillä julkaistut viestit näkyvät julkisilla aikajanoilla
     labels:
       account:
         fields:
           name: Nimike
           value: Sisältö
+      account_alias:
+        acct: Vanhan tilin käsittely
+      account_migration:
+        acct: Uuden tilin käsittely
       account_warning_preset:
+        text: Esiasetettu teksti
         title: Otsikko
       admin_account_action:
+        include_statuses: Sisällytä raportoidut viestit sähköpostiin
+        send_email_notification: Ilmoita käyttäjälle sähköpostitse
         text: Mukautettu varoitus
         type: Toimenpide
         types:
@@ -99,8 +118,11 @@ fi:
       announcement:
         all_day: Koko päivän kestävä tapahtuma
         ends_at: Tapahtuman loppu
+        scheduled_at: Ajasta julkaisu
         starts_at: Tapahtuman alku
         text: Ilmoitus
+      appeal:
+        text: Perustele, miksi tämä päätös olisi kumottava
       defaults:
         autofollow: Kutsu seuraamaan tiliäsi
         avatar: Profiilikuva
@@ -117,6 +139,9 @@ fi:
         expires_in: Vanhenee
         fields: Profiilin metadata
         header: Otsakekuva
+        honeypot: "%{label} (älä täytä)"
+        inbox_url: Välityspostilaatikon URL-osoite
+        irreversible: Pudota piilottamisen sijaan
         locale: Kieli
         locked: Lukitse tili
         max_uses: Käyttökertoja enintään
@@ -134,10 +159,12 @@ fi:
         setting_default_privacy: Julkaisun näkyvyys
         setting_default_sensitive: Merkitse media aina arkaluontoiseksi
         setting_delete_modal: Kysy vahvistusta ennen viestin poistamista
+        setting_disable_swiping: Poista pyyhkäisyt käytöstä
         setting_display_media: Median näyttäminen
         setting_display_media_default: Oletus
         setting_display_media_hide_all: Piilota kaikki
         setting_display_media_show_all: Näytä kaikki
+        setting_expand_spoilers: Laajenna aina sisältövaroituksilla merkityt viestit
         setting_hide_network: Piilota verkkosi
         setting_noindex: Jättäydy pois hakukoneindeksoinnista
         setting_reduce_motion: Vähennä animaatioiden liikettä
@@ -146,6 +173,7 @@ fi:
         setting_theme: Sivuston teema
         setting_trends: Näytä päivän trendit
         setting_unfollow_modal: Kysy vahvistusta, ennen kuin lopetat seuraamisen
+        setting_use_blurhash: Näytä värikkäät liukuvärit piilotetulle medialle
         setting_use_pending_items: Hidastila
         severity: Vakavuus
         sign_in_token_attempt: Turvakoodi
@@ -166,12 +194,14 @@ fi:
       invite_request:
         text: Miksi haluat liittyä?
       ip_block:
+        comment: Kommentti
         ip: IP
         severities:
           no_access: Estä pääsy
           sign_up_requires_approval: Rajoita rekisteröitymisiä
         severity: Sääntö
       notification_emails:
+        appeal: Joku valittaa valvojan päätöksestä
         digest: Lähetä koosteviestejä sähköpostitse
         favourite: Lähetä sähköposti, kun joku tykkää tilastasi
         follow: Lähetä sähköposti, kun joku seuraa sinua
@@ -179,14 +209,21 @@ fi:
         mention: Lähetä sähköposti, kun sinut mainitaan
         pending_account: Uusi tili tarvitsee tarkastusta
         reblog: Lähetä sähköposti, kun joku buustaa julkaisusi
+        report: Uusi raportti on lähetetty
+        trending_tag: Uusi trendi vaatii tarkastelua
       rule:
         text: Sääntö
       tag:
+        listable: Salli tämän hashtagin näkyä hauissa ja ehdotuksissa
         name: Aihetunniste
         trendable: Salli tämän aihetunnisteen näkyä trendeissä
         usable: Salli postauksien käyttää tätä aihetunnistetta
     'no': Ei
     recommended: Suositeltu
     required:
+      mark: "*"
       text: pakollinen tieto
+    title:
+      sessions:
+        webauthn: Käytä jotakin suojausavainta kirjautuaksesi sisään
     'yes': Kyllä
diff --git a/config/locales/simple_form.fr.yml b/config/locales/simple_form.fr.yml
index 6794d1677..8aa4af15e 100644
--- a/config/locales/simple_form.fr.yml
+++ b/config/locales/simple_form.fr.yml
@@ -27,6 +27,8 @@ fr:
         scheduled_at: Laisser vide pour publier l’annonce immédiatement
         starts_at: Optionnel. Si votre annonce est liée à une période spécifique
         text: Vous pouvez utiliser la syntaxe des messages. Veuillez prendre en compte l’espace que l'annonce prendra sur l’écran de l'utilisateur·rice
+      appeal:
+        text: Vous ne pouvez faire appel d'une sanction qu'une seule fois
       defaults:
         autofollow: Les personnes qui s’inscrivent grâce à l’invitation vous suivront automatiquement
         avatar: Au format PNG, GIF ou JPG. %{size} maximum. Sera réduit à %{dimensions}px
@@ -119,6 +121,8 @@ fr:
         scheduled_at: Planifier la publication
         starts_at: Début de l’événement
         text: Annonce
+      appeal:
+        text: Expliquez pourquoi cette décision devrait être annulée
       defaults:
         autofollow: Invitation à suivre votre compte
         avatar: Image de profil
@@ -197,6 +201,7 @@ fr:
           sign_up_requires_approval: Limite des inscriptions
         severity: Règle
       notification_emails:
+        appeal: Une personne fait appel d'une décision des modérateur·rice·s
         digest: Envoyer des courriels récapitulatifs
         favourite: Quelqu’un a ajouté mon message à ses favoris
         follow: Quelqu’un vient de me suivre
@@ -204,6 +209,8 @@ fr:
         mention: Quelqu’un me mentionne
         pending_account: Nouveau compte en attente d’approbation
         reblog: Quelqu’un a partagé mon message
+        report: Nouveau signalement soumis
+        trending_tag: Nouvelle tendance nécessitant supervision
       rule:
         text: Règle
       tag:
diff --git a/config/locales/simple_form.gl.yml b/config/locales/simple_form.gl.yml
index 83cd6f516..58945edbb 100644
--- a/config/locales/simple_form.gl.yml
+++ b/config/locales/simple_form.gl.yml
@@ -141,7 +141,7 @@ gl:
         header: Cabeceira
         honeypot: "%{label} (non completar)"
         inbox_url: URL da caixa de entrada do repetidor
-        irreversible: Soltar en lugar de agochar
+        irreversible: Desbotar en lugar de agochar
         locale: Idioma da interface
         locked: Requerir aprobar seguimento
         max_uses: Número máximo de usos
diff --git a/config/locales/simple_form.id.yml b/config/locales/simple_form.id.yml
index 5f168d4c2..025472551 100644
--- a/config/locales/simple_form.id.yml
+++ b/config/locales/simple_form.id.yml
@@ -27,6 +27,8 @@ id:
         scheduled_at: Biarkan kosong jika ingin menerbitkan pengumuman secara langsung
         starts_at: Opsional. Persiapan jika pengumuman Anda terikat pada rentang waktu tertentu
         text: Anda dapat menggunakan sintaks toot. Mohon perhatikan ruang pengumuman yang mungkin akan memenuhi layar pengguna
+      appeal:
+        text: Anda hanya dapat mengajukan banding peringatan sekali
       defaults:
         autofollow: Orang yang ingin mendaftar lewat undangan, otomatis mengikuti Anda
         avatar: PNG, GIF atau JPG. Maksimal %{size}. Ukuran dikecilkan menjadi %{dimensions}px
@@ -119,6 +121,8 @@ id:
         scheduled_at: Jadwal publikasi
         starts_at: Awal mulai event
         text: Pengumuman
+      appeal:
+        text: Jelaskan mengapa keputusan ini perlu dibatalkan
       defaults:
         autofollow: Undang untuk mengikuti Anda
         avatar: Avatar
@@ -197,6 +201,7 @@ id:
           sign_up_requires_approval: Batasi pendaftaran
         severity: Aturan
       notification_emails:
+        appeal: Seseorang mengajukan banding tehadap keputusan moderator
         digest: Kirim email berisi rangkuman
         favourite: Kirim email saat seseorang menyukai status anda
         follow: Kirim email saat seseorang mengikuti anda
@@ -204,6 +209,8 @@ id:
         mention: Kirim email saat seseorang menyebut anda
         pending_account: Kirim email ketika akun baru perlu ditinjau
         reblog: Kirim email saat seseorang mem-boost status anda
+        report: Laporan baru dikirim
+        trending_tag: Tren baru harus ditinjau
       rule:
         text: Aturan
       tag:
diff --git a/config/locales/simple_form.ru.yml b/config/locales/simple_form.ru.yml
index 98ab1eb3d..c71dd5b39 100644
--- a/config/locales/simple_form.ru.yml
+++ b/config/locales/simple_form.ru.yml
@@ -27,6 +27,8 @@ ru:
         scheduled_at: Оставьте поля незаполненными, чтобы опубликовать объявление сразу
         starts_at: Необязательно. На случай, если ваше объявление привязано к какому-то временному интервалу
         text: Вы можете использовать тот же синтаксис, что и в постах. Будьте предусмотрительны насчёт места, которое займёт объявление на экране пользователей
+      appeal:
+        text: Вы можете обжаловать замечание только один раз
       defaults:
         autofollow: Люди, пришедшие по этому приглашению, автоматически будут подписаны на вас.
         avatar: Поддерживается PNG, GIF и JPG. Максимальный размер — %{size}. Будет уменьшен до %{dimensions}px.
diff --git a/config/locales/simple_form.th.yml b/config/locales/simple_form.th.yml
index 94e84861f..8bfe5ba88 100644
--- a/config/locales/simple_form.th.yml
+++ b/config/locales/simple_form.th.yml
@@ -27,6 +27,8 @@ th:
         scheduled_at: เว้นว่างไว้เพื่อเผยแพร่ประกาศทันที
         starts_at: ไม่จำเป็น ในกรณีที่ประกาศของคุณผูกไว้กับช่วงเวลาที่เฉพาะเจาะจง
         text: คุณสามารถใช้ไวยากรณ์โพสต์ โปรดระวังพื้นที่ที่ประกาศจะใช้ในหน้าจอของผู้ใช้
+      appeal:
+        text: คุณสามารถอุทธรณ์การลงโทษได้เพียงครั้งเดียวเท่านั้น
       defaults:
         autofollow: ผู้คนที่ลงทะเบียนผ่านคำเชิญจะติดตามคุณโดยอัตโนมัติ
         avatar: PNG, GIF หรือ JPG สูงสุด %{size} จะถูกย่อขนาดเป็น %{dimensions}px
diff --git a/config/locales/th.yml b/config/locales/th.yml
index 0494f5d85..ec92cfd2d 100644
--- a/config/locales/th.yml
+++ b/config/locales/th.yml
@@ -150,6 +150,10 @@ th:
       not_subscribed: ไม่ได้บอกรับ
       pending: การตรวจทานที่รอดำเนินการ
       perform_full_suspension: ระงับ
+      previous_strikes: การลงโทษก่อนหน้านี้
+      previous_strikes_description_html:
+        one: บัญชีนี้มี <strong>หนึ่ง</strong> การลงโทษ
+        other: บัญชีนี้มี <strong>%{count}</strong> การลงโทษ
       promote: เลื่อนขั้น
       protocol: โปรโตคอล
       public: สาธารณะ
@@ -190,6 +194,7 @@ th:
       silence: จำกัด
       silenced: จำกัดอยู่
       statuses: โพสต์
+      strikes: การลงโทษก่อนหน้านี้
       subscribe: บอกรับ
       suspend: ระงับ
       suspended: ระงับอยู่
@@ -369,6 +374,14 @@ th:
       media_storage: ที่เก็บข้อมูลสื่อ
       new_users: ผู้ใช้ใหม่
       opened_reports: รายงานที่เปิด
+      pending_appeals_html:
+        other: "<strong>%{count}</strong> การอุทธรณ์ที่รอดำเนินการ"
+      pending_reports_html:
+        other: "<strong>%{count}</strong> รายงานที่รอดำเนินการ"
+      pending_tags_html:
+        other: "<strong>%{count}</strong> แฮชแท็กที่รอดำเนินการ"
+      pending_users_html:
+        other: "<strong>%{count}</strong> ผู้ใช้ที่รอดำเนินการ"
       resolved_reports: รายงานที่แก้ปัญหาแล้ว
       software: ซอฟต์แวร์
       sources: แหล่งที่มาการลงทะเบียน
@@ -413,6 +426,10 @@ th:
         silence: จำกัดอยู่
         suspend: ระงับอยู่
       show:
+        affected_accounts:
+          one: หนึ่งบัญชีในฐานข้อมูลที่ได้รับผลกระทบ
+          other: "%{count} บัญชีในฐานข้อมูลที่ได้รับผลกระทบ"
+          zero: ไม่มีบัญชีในฐานข้อมูลที่ได้รับผลกระทบ
         retroactive:
           silence: เลิกทำการจำกัดบัญชีที่มีผลที่มีอยู่จากโดเมนนี้
           suspend: เลิกระงับบัญชีที่มีผลที่มีอยู่จากโดเมนนี้
@@ -457,6 +474,10 @@ th:
       delivery_available: มีการจัดส่ง
       delivery_error_days: วันที่มีข้อผิดพลาดการจัดส่ง
       empty: ไม่พบโดเมน
+      known_accounts:
+        one: "%{count} บัญชีที่รู้จัก"
+        other: "%{count} บัญชีที่รู้จัก"
+        zero: ไม่มีบัญชีที่รู้จัก
       moderation:
         all: ทั้งหมด
         limited: จำกัดอยู่
@@ -518,6 +539,7 @@ th:
         notes:
           other: "%{count} หมายเหตุ"
       action_log: รายการบันทึกการตรวจสอบ
+      action_taken_by: ใช้การกระทำโดย
       are_you_sure: คุณแน่ใจหรือไม่?
       assign_to_self: มอบหมายให้ฉัน
       assigned: ผู้ควบคุมที่ได้รับมอบหมาย
@@ -691,6 +713,10 @@ th:
         allow_provider: อนุญาตผู้เผยแพร่
         disallow: ไม่อนุญาตลิงก์
         disallow_provider: ไม่อนุญาตผู้เผยแพร่
+        shared_by_over_week:
+          one: แบ่งปันโดยหนึ่งคนในช่วงสัปดาห์ที่ผ่านมา
+          other: แบ่งปันโดย %{count} คนในช่วงสัปดาห์ที่ผ่านมา
+          zero: ไม่มีใครแบ่งปันในช่วงสัปดาห์ที่ผ่านมา
         title: ลิงก์ที่กำลังนิยม
         usage_comparison: แบ่งปัน %{today} ครั้งวันนี้ เทียบกับ %{yesterday} เมื่อวานนี้
       pending_review: การตรวจทานที่รอดำเนินการ
@@ -717,6 +743,10 @@ th:
         trending_rank: 'กำลังนิยม #%{rank}'
         usable: สามารถใช้
         usage_comparison: ใช้ %{today} ครั้งวันนี้ เทียบกับ %{yesterday} เมื่อวานนี้
+        used_by_over_week:
+          one: ใช้โดยหนึ่งคนในช่วงสัปดาห์ที่ผ่านมา
+          other: ใช้โดย %{count} คนในช่วงสัปดาห์ที่ผ่านมา
+          zero: ไม่มีใครใช้ในช่วงสัปดาห์ที่ผ่านมา
       title: แนวโน้ม
     warning_presets:
       add_new: เพิ่มใหม่
@@ -878,10 +908,13 @@ th:
     explore_mastodon: สำรวจ %{title}
   disputes:
     strikes:
+      action_taken: การกระทำที่ใช้
       appeal_submitted_at: ส่งการอุทธรณ์แล้ว
       appeals:
         submit: ส่งการอุทธรณ์
       associated_report: รายงานที่เกี่ยวข้อง
+      created_at: ลงวันที่
+      recipient: ส่งถึง
       status: 'โพสต์ #%{id}'
       title_actions:
         delete_statuses: การเอาโพสต์ออก
@@ -1039,7 +1072,7 @@ th:
   move_handler:
     carry_blocks_over_text: ผู้ใช้นี้ได้ย้ายจาก %{acct} ซึ่งคุณได้ปิดกั้น
     carry_mutes_over_text: ผู้ใช้นี้ได้ย้ายจาก %{acct} ซึ่งคุณได้ซ่อน
-    copy_account_note_text: 'ผู้ใช้นี้ได้ย้ายจาก %{acct} นี่คือหมายเหตุก่อนหน้าของคุณเกี่ยวกับผู้ใช้:'
+    copy_account_note_text: 'ผู้ใช้นี้ได้ย้ายจาก %{acct} นี่คือหมายเหตุก่อนหน้านี้ของคุณเกี่ยวกับผู้ใช้:'
   notification_mailer:
     digest:
       action: ดูการแจ้งเตือนทั้งหมด
@@ -1292,7 +1325,7 @@ th:
     reblogged: ดันแล้ว
     sensitive_content: เนื้อหาที่ละเอียดอ่อน
   tags:
-    does_not_match_previous_name: ไม่ตรงกับชื่อก่อนหน้า
+    does_not_match_previous_name: ไม่ตรงกับชื่อก่อนหน้านี้
   terms:
     title: เงื่อนไขการให้บริการและนโยบายความเป็นส่วนตัวของ %{instance}
   themes:
diff --git a/db/migrate/20170920032311_fix_reblogs_in_feeds.rb b/db/migrate/20170920032311_fix_reblogs_in_feeds.rb
index 5654bf6f8..bcd4b9137 100644
--- a/db/migrate/20170920032311_fix_reblogs_in_feeds.rb
+++ b/db/migrate/20170920032311_fix_reblogs_in_feeds.rb
@@ -15,7 +15,7 @@ class FixReblogsInFeeds < ActiveRecord::Migration[5.1]
     # feed, with an entry in a reblog tracking zset (where the score
     # is once again set to the reblogging status' ID, and the value
     # is set to the reblogged status' ID). This is safe for Redis'
-    # float coersion because in this reblog tracking zset, we only
+    # float conversion because in this reblog tracking zset, we only
     # need the rebloggging status' ID to be able to stop tracking
     # entries after they have gotten too far down the feed, which
     # does not require an exact value.
diff --git a/lib/mastodon/statuses_cli.rb b/lib/mastodon/statuses_cli.rb
index e273e2614..91b08813b 100644
--- a/lib/mastodon/statuses_cli.rb
+++ b/lib/mastodon/statuses_cli.rb
@@ -54,7 +54,7 @@ module Mastodon
 
       ActiveRecord::Base.connection.add_index(:media_attachments, :remote_url, name: :index_media_attachments_remote_url, where: 'remote_url is not null', algorithm: :concurrently, if_not_exists: true)
 
-      max_id   = Mastodon::Snowflake.id_at(options[:days].days.ago)
+      max_id   = Mastodon::Snowflake.id_at(options[:days].days.ago, with_random: false)
       start_at = Time.now.to_f
 
       unless options[:continue] && ActiveRecord::Base.connection.table_exists?('statuses_to_be_deleted')
diff --git a/spec/controllers/settings/two_factor_authentication/otp_authentication_controller_spec.rb b/spec/controllers/settings/two_factor_authentication/otp_authentication_controller_spec.rb
index 17e8fa9b8..c8ba6f9a8 100644
--- a/spec/controllers/settings/two_factor_authentication/otp_authentication_controller_spec.rb
+++ b/spec/controllers/settings/two_factor_authentication/otp_authentication_controller_spec.rb
@@ -18,7 +18,7 @@ describe Settings::TwoFactorAuthentication::OtpAuthenticationController do
           user.update(otp_required_for_login: true)
         end
 
-        it 'redirects to two factor authentciation methods list page' do
+        it 'redirects to two factor authentication methods list page' do
           get :show
 
           expect(response).to redirect_to settings_two_factor_authentication_methods_path
diff --git a/spec/models/web/push_subscription_spec.rb b/spec/models/web/push_subscription_spec.rb
index b44904369..bd5719593 100644
--- a/spec/models/web/push_subscription_spec.rb
+++ b/spec/models/web/push_subscription_spec.rb
@@ -29,7 +29,7 @@ RSpec.describe Web::PushSubscription, type: :model do
       context "when notification is a #{type}" do
         let(:notification_type) { type }
 
-        it "returns boolean corresonding to alert setting" do
+        it "returns boolean corresponding to alert setting" do
           expect(subject.pushable?(notification)).to eq data[:alerts][type]
         end
       end
diff --git a/spec/services/block_domain_service_spec.rb b/spec/services/block_domain_service_spec.rb
index c689b57e3..242b02fff 100644
--- a/spec/services/block_domain_service_spec.rb
+++ b/spec/services/block_domain_service_spec.rb
@@ -66,7 +66,7 @@ RSpec.describe BlockDomainService, type: :service do
       expect(Account.find_remote('badguy', 'evil.org').silenced_at).to_not eq DomainBlock.find_by(domain: 'evil.org').created_at
     end
 
-    it 'leaves the domains status and attachements, but clears media' do
+    it 'leaves the domains status and attachments, but clears media' do
       expect { bad_status1.reload }.not_to raise_error
       expect { bad_status2.reload }.not_to raise_error
       expect { bad_attachment.reload }.not_to raise_error
diff --git a/spec/services/clear_domain_media_service_spec.rb b/spec/services/clear_domain_media_service_spec.rb
index 8e58c6039..45b92e2c9 100644
--- a/spec/services/clear_domain_media_service_spec.rb
+++ b/spec/services/clear_domain_media_service_spec.rb
@@ -13,7 +13,7 @@ RSpec.describe ClearDomainMediaService, type: :service do
       subject.call(DomainBlock.create!(domain: 'evil.org', severity: :silence, reject_media: true))
     end
 
-    it 'leaves the domains status and attachements, but clears media' do
+    it 'leaves the domains status and attachments, but clears media' do
       expect { bad_status1.reload }.not_to raise_error
       expect { bad_status2.reload }.not_to raise_error
       expect { bad_attachment.reload }.not_to raise_error
diff --git a/spec/services/delete_account_service_spec.rb b/spec/services/delete_account_service_spec.rb
index b1da97036..9c785fc17 100644
--- a/spec/services/delete_account_service_spec.rb
+++ b/spec/services/delete_account_service_spec.rb
@@ -90,7 +90,7 @@ RSpec.describe DeleteAccountService, type: :service do
       let!(:account) { Fabricate(:account, inbox_url: 'https://bob.com/inbox', protocol: :activitypub) }
       let!(:local_follower) { Fabricate(:account) }
 
-      it 'sends a reject follow to follwer inboxes' do
+      it 'sends a reject follow to follower inboxes' do
         subject.call
         expect(a_request(:post, account.inbox_url)).to have_been_made.once
       end
diff --git a/spec/validators/unreserved_username_validator_spec.rb b/spec/validators/unreserved_username_validator_spec.rb
index cabd6d386..746b3866c 100644
--- a/spec/validators/unreserved_username_validator_spec.rb
+++ b/spec/validators/unreserved_username_validator_spec.rb
@@ -27,7 +27,7 @@ RSpec.describe UnreservedUsernameValidator, type: :validator do
       context 'reserved_username?' do
         let(:reserved_username) { true }
 
-        it 'calls erros.add' do
+        it 'calls errors.add' do
           expect(errors).to have_received(:add).with(:username, :reserved)
         end
       end
@@ -35,7 +35,7 @@ RSpec.describe UnreservedUsernameValidator, type: :validator do
       context '!reserved_username?' do
         let(:reserved_username) { false }
 
-        it 'not calls erros.add' do
+        it 'not calls errors.add' do
           expect(errors).not_to have_received(:add).with(:username, any_args)
         end
       end