From b4e739ff0f64c601973762ac986c0e63092d2d7e Mon Sep 17 00:00:00 2001
From: Claire <claire.github-309c@sitedethib.com>
Date: Thu, 27 Jul 2023 16:11:17 +0200
Subject: [PATCH] Change interaction modal in web UI (#26075)

Co-authored-by: Eugen Rochko <eugen@zeonfederated.com>
---
 app/chewy/instances_index.rb                  |  12 +
 .../api/v1/instances/peers_controller.rb      |   2 +-
 .../api/v1/peers/search_controller.rb         |  45 +++
 .../authorize_interactions_controller.rb      |  21 +-
 .../remote_interaction_helper_controller.rb   |  43 +++
 .../well_known/webfinger_controller.rb        |   1 +
 .../mastodon/containers/status_container.jsx  |   2 +-
 .../containers/header_container.jsx           |   2 +-
 .../features/compose/components/search.jsx    |   4 -
 .../features/interaction_modal/index.jsx      | 300 ++++++++++++++----
 .../picture_in_picture/components/footer.jsx  |   6 +-
 .../mastodon/features/status/index.jsx        |   6 +-
 app/javascript/mastodon/locales/en.json       |   8 +-
 .../packs/remote_interaction_helper.ts        | 172 ++++++++++
 .../styles/mastodon/components.scss           | 115 ++++---
 app/javascript/styles/mastodon/variables.scss |   2 +
 app/javascript/types/resources.ts             |   1 +
 app/lib/importer/instances_index_importer.rb  |  26 ++
 app/lib/webfinger_resource.rb                 |   9 +
 app/models/instance.rb                        |   1 +
 app/serializers/rest/account_serializer.rb    |   6 +-
 app/serializers/webfinger_serializer.rb       |   1 +
 .../_post_follow_actions.html.haml            |   4 -
 .../authorize_interactions/error.html.haml    |   3 -
 .../authorize_interactions/show.html.haml     |  24 --
 .../authorize_interactions/success.html.haml  |  13 -
 app/views/layouts/helper_frame.html.haml      |   8 +
 .../remote_interaction_helper/index.html.haml |   4 +
 .../scheduler/instance_refresh_scheduler.rb   |   1 +
 config/locales/an.yml                         |  12 -
 config/locales/ar.yml                         |  12 -
 config/locales/ast.yml                        |   9 -
 config/locales/be.yml                         |  12 -
 config/locales/bg.yml                         |  12 -
 config/locales/br.yml                         |   5 -
 config/locales/ca.yml                         |  12 -
 config/locales/ckb.yml                        |  12 -
 config/locales/co.yml                         |  12 -
 config/locales/cs.yml                         |  12 -
 config/locales/cy.yml                         |  12 -
 config/locales/da.yml                         |  12 -
 config/locales/de.yml                         |  12 -
 config/locales/el.yml                         |  12 -
 config/locales/en-GB.yml                      |  12 -
 config/locales/en.yml                         |  12 -
 config/locales/eo.yml                         |  12 -
 config/locales/es-AR.yml                      |  12 -
 config/locales/es-MX.yml                      |  12 -
 config/locales/es.yml                         |  12 -
 config/locales/et.yml                         |  12 -
 config/locales/eu.yml                         |  12 -
 config/locales/fa.yml                         |  12 -
 config/locales/fi.yml                         |  12 -
 config/locales/fo.yml                         |  12 -
 config/locales/fr-QC.yml                      |  12 -
 config/locales/fr.yml                         |  12 -
 config/locales/fy.yml                         |  12 -
 config/locales/ga.yml                         |   5 -
 config/locales/gd.yml                         |  12 -
 config/locales/gl.yml                         |  12 -
 config/locales/he.yml                         |  12 -
 config/locales/hr.yml                         |   4 -
 config/locales/hu.yml                         |  12 -
 config/locales/hy.yml                         |  11 -
 config/locales/id.yml                         |  12 -
 config/locales/io.yml                         |  12 -
 config/locales/is.yml                         |  12 -
 config/locales/it.yml                         |  12 -
 config/locales/ja.yml                         |  12 -
 config/locales/ka.yml                         |  11 -
 config/locales/kab.yml                        |   8 -
 config/locales/kk.yml                         |  11 -
 config/locales/ko.yml                         |  12 -
 config/locales/ku.yml                         |  12 -
 config/locales/lt.yml                         |  11 -
 config/locales/lv.yml                         |  12 -
 config/locales/ml.yml                         |  10 -
 config/locales/ms.yml                         |   8 -
 config/locales/my.yml                         |  12 -
 config/locales/nl.yml                         |  12 -
 config/locales/nn.yml                         |  12 -
 config/locales/no.yml                         |  12 -
 config/locales/oc.yml                         |  11 -
 config/locales/pl.yml                         |  12 -
 config/locales/pt-BR.yml                      |  12 -
 config/locales/pt-PT.yml                      |  12 -
 config/locales/ro.yml                         |  12 -
 config/locales/ru.yml                         |  12 -
 config/locales/sc.yml                         |  12 -
 config/locales/sco.yml                        |  12 -
 config/locales/si.yml                         |  12 -
 config/locales/sk.yml                         |  11 -
 config/locales/sl.yml                         |  12 -
 config/locales/sq.yml                         |  12 -
 config/locales/sr-Latn.yml                    |  12 -
 config/locales/sr.yml                         |  12 -
 config/locales/sv.yml                         |  12 -
 config/locales/ta.yml                         |   2 -
 config/locales/th.yml                         |  12 -
 config/locales/tr.yml                         |  12 -
 config/locales/tt.yml                         |   6 -
 config/locales/uk.yml                         |  12 -
 config/locales/vi.yml                         |  12 -
 config/locales/zgh.yml                        |   3 -
 config/locales/zh-CN.yml                      |  12 -
 config/locales/zh-HK.yml                      |  12 -
 config/locales/zh-TW.yml                      |  12 -
 config/routes.rb                              |   5 +-
 config/routes/api.rb                          |   4 +
 lib/mastodon/cli/search.rb                    |   1 +
 .../authorize_interactions_controller_spec.rb |  51 +--
 111 files changed, 682 insertions(+), 1091 deletions(-)
 create mode 100644 app/chewy/instances_index.rb
 create mode 100644 app/controllers/api/v1/peers/search_controller.rb
 create mode 100644 app/controllers/remote_interaction_helper_controller.rb
 create mode 100644 app/javascript/packs/remote_interaction_helper.ts
 create mode 100644 app/lib/importer/instances_index_importer.rb
 delete mode 100644 app/views/authorize_interactions/_post_follow_actions.html.haml
 delete mode 100644 app/views/authorize_interactions/error.html.haml
 delete mode 100644 app/views/authorize_interactions/show.html.haml
 delete mode 100644 app/views/authorize_interactions/success.html.haml
 create mode 100644 app/views/layouts/helper_frame.html.haml
 create mode 100644 app/views/remote_interaction_helper/index.html.haml

diff --git a/app/chewy/instances_index.rb b/app/chewy/instances_index.rb
new file mode 100644
index 000000000..2bce4043c
--- /dev/null
+++ b/app/chewy/instances_index.rb
@@ -0,0 +1,12 @@
+# frozen_string_literal: true
+
+class InstancesIndex < Chewy::Index
+  settings index: { refresh_interval: '30s' }
+
+  index_scope ::Instance.searchable
+
+  root date_detection: false do
+    field :domain, type: 'text', index_prefixes: { min_chars: 1 }
+    field :accounts_count, type: 'long'
+  end
+end
diff --git a/app/controllers/api/v1/instances/peers_controller.rb b/app/controllers/api/v1/instances/peers_controller.rb
index 70281362a..23096650e 100644
--- a/app/controllers/api/v1/instances/peers_controller.rb
+++ b/app/controllers/api/v1/instances/peers_controller.rb
@@ -15,7 +15,7 @@ class Api::V1::Instances::PeersController < Api::BaseController
 
   def index
     cache_even_if_authenticated!
-    render_with_cache(expires_in: 1.day) { Instance.where.not(domain: DomainBlock.select(:domain)).pluck(:domain) }
+    render_with_cache(expires_in: 1.day) { Instance.searchable.pluck(:domain) }
   end
 
   private
diff --git a/app/controllers/api/v1/peers/search_controller.rb b/app/controllers/api/v1/peers/search_controller.rb
new file mode 100644
index 000000000..50a342cde
--- /dev/null
+++ b/app/controllers/api/v1/peers/search_controller.rb
@@ -0,0 +1,45 @@
+# frozen_string_literal: true
+
+class Api::V1::Peers::SearchController < Api::BaseController
+  before_action :require_enabled_api!
+  before_action :set_domains
+
+  skip_before_action :require_authenticated_user!, unless: :whitelist_mode?
+  skip_around_action :set_locale
+
+  vary_by ''
+
+  def index
+    cache_even_if_authenticated!
+    render json: @domains
+  end
+
+  private
+
+  def require_enabled_api!
+    head 404 unless Setting.peers_api_enabled && !whitelist_mode?
+  end
+
+  def set_domains
+    return if params[:q].blank?
+
+    if Chewy.enabled?
+      @domains = InstancesIndex.query(function_score: {
+        query: {
+          prefix: {
+            domain: params[:q],
+          },
+        },
+
+        field_value_factor: {
+          field: 'accounts_count',
+          modifier: 'log2p',
+        },
+      }).limit(10).pluck(:domain)
+    else
+      domain = params[:q].strip
+      domain = TagManager.instance.normalize_domain(domain)
+      @domains = Instance.searchable.where(Instance.arel_table[:domain].matches("#{Instance.sanitize_sql_like(domain)}%", false, true)).limit(10).pluck(:domain)
+    end
+  end
+end
diff --git a/app/controllers/authorize_interactions_controller.rb b/app/controllers/authorize_interactions_controller.rb
index bf28d1842..99eed018b 100644
--- a/app/controllers/authorize_interactions_controller.rb
+++ b/app/controllers/authorize_interactions_controller.rb
@@ -3,32 +3,19 @@
 class AuthorizeInteractionsController < ApplicationController
   include Authorization
 
-  layout 'modal'
-
   before_action :authenticate_user!
-  before_action :set_body_classes
   before_action :set_resource
 
   def show
     if @resource.is_a?(Account)
-      render :show
+      redirect_to web_url("@#{@resource.pretty_acct}")
     elsif @resource.is_a?(Status)
       redirect_to web_url("@#{@resource.account.pretty_acct}/#{@resource.id}")
     else
-      render :error
+      not_found
     end
   end
 
-  def create
-    if @resource.is_a?(Account) && FollowService.new.call(current_account, @resource, with_rate_limit: true)
-      render :success
-    else
-      render :error
-    end
-  rescue ActiveRecord::RecordNotFound
-    render :error
-  end
-
   private
 
   def set_resource
@@ -61,8 +48,4 @@ class AuthorizeInteractionsController < ApplicationController
   def uri_param
     params[:uri] || params.fetch(:acct, '').delete_prefix('acct:')
   end
-
-  def set_body_classes
-    @body_classes = 'modal-layout'
-  end
 end
diff --git a/app/controllers/remote_interaction_helper_controller.rb b/app/controllers/remote_interaction_helper_controller.rb
new file mode 100644
index 000000000..90c853f47
--- /dev/null
+++ b/app/controllers/remote_interaction_helper_controller.rb
@@ -0,0 +1,43 @@
+# frozen_string_literal: true
+
+class RemoteInteractionHelperController < ApplicationController
+  vary_by ''
+
+  skip_before_action :require_functional!
+  skip_around_action :set_locale
+  skip_before_action :update_user_sign_in
+
+  content_security_policy do |p|
+    # We inherit the normal `script-src`
+
+    # Set every directive that does not have a fallback
+    p.default_src :none
+    p.form_action :none
+    p.base_uri :none
+
+    # Disable every directive with a fallback to cut on response size
+    p.base_uri false
+    p.font_src false
+    p.img_src false
+    p.style_src false
+    p.media_src false
+    p.frame_src false
+    p.manifest_src false
+    p.connect_src false
+    p.child_src false
+    p.worker_src false
+
+    # Widen the directives that we do need
+    p.frame_ancestors :self
+    p.connect_src :https
+  end
+
+  def index
+    expires_in(5.minutes, public: true, stale_while_revalidate: 30.seconds, stale_if_error: 1.day)
+
+    response.headers['X-Frame-Options'] = 'SAMEORIGIN'
+    response.headers['Referrer-Policy'] = 'no-referrer'
+
+    render layout: 'helper_frame'
+  end
+end
diff --git a/app/controllers/well_known/webfinger_controller.rb b/app/controllers/well_known/webfinger_controller.rb
index 0d897e8e2..4748940f7 100644
--- a/app/controllers/well_known/webfinger_controller.rb
+++ b/app/controllers/well_known/webfinger_controller.rb
@@ -19,6 +19,7 @@ module WellKnown
 
     def set_account
       username = username_from_resource
+
       @account = begin
         if username == Rails.configuration.x.local_domain
           Account.representative
diff --git a/app/javascript/mastodon/containers/status_container.jsx b/app/javascript/mastodon/containers/status_container.jsx
index 536765e13..7a7cd9880 100644
--- a/app/javascript/mastodon/containers/status_container.jsx
+++ b/app/javascript/mastodon/containers/status_container.jsx
@@ -278,7 +278,7 @@ const mapDispatchToProps = (dispatch, { intl, contextType }) => ({
       modalProps: {
         type,
         accountId: status.getIn(['account', 'id']),
-        url: status.get('url'),
+        url: status.get('uri'),
       },
     }));
   },
diff --git a/app/javascript/mastodon/features/account_timeline/containers/header_container.jsx b/app/javascript/mastodon/features/account_timeline/containers/header_container.jsx
index 2b3a66c55..df5427c30 100644
--- a/app/javascript/mastodon/features/account_timeline/containers/header_container.jsx
+++ b/app/javascript/mastodon/features/account_timeline/containers/header_container.jsx
@@ -83,7 +83,7 @@ const mapDispatchToProps = (dispatch, { intl }) => ({
       modalProps: {
         type: 'follow',
         accountId: account.get('id'),
-        url: account.get('url'),
+        url: account.get('uri'),
       },
     }));
   },
diff --git a/app/javascript/mastodon/features/compose/components/search.jsx b/app/javascript/mastodon/features/compose/components/search.jsx
index 7badb0774..682f8d3c8 100644
--- a/app/javascript/mastodon/features/compose/components/search.jsx
+++ b/app/javascript/mastodon/features/compose/components/search.jsx
@@ -139,10 +139,6 @@ class Search extends PureComponent {
     this.setState({ expanded: false, selectedOption: -1 });
   };
 
-  findTarget = () => {
-    return this.searchForm;
-  };
-
   handleHashtagClick = () => {
     const { router } = this.context;
     const { value, onClickSearchResult } = this.props;
diff --git a/app/javascript/mastodon/features/interaction_modal/index.jsx b/app/javascript/mastodon/features/interaction_modal/index.jsx
index 4722c130e..6e17ab019 100644
--- a/app/javascript/mastodon/features/interaction_modal/index.jsx
+++ b/app/javascript/mastodon/features/interaction_modal/index.jsx
@@ -1,95 +1,296 @@
 import PropTypes from 'prop-types';
-import { PureComponent } from 'react';
+import React from 'react';
 
-import { FormattedMessage } from 'react-intl';
+import { FormattedMessage, defineMessages, injectIntl } from 'react-intl';
 
 import classNames from 'classnames';
 
 import { connect } from 'react-redux';
 
+import { throttle, escapeRegExp } from 'lodash';
+
 import { openModal, closeModal } from 'mastodon/actions/modal';
+import api from 'mastodon/api';
+import Button from 'mastodon/components/button';
 import { Icon }  from 'mastodon/components/icon';
 import { registrationsOpen } from 'mastodon/initial_state';
 
+const messages = defineMessages({
+  loginPrompt: { id: 'interaction_modal.login.prompt', defaultMessage: 'Domain of your home server, e.g. mastodon.social' },
+});
+
 const mapStateToProps = (state, { accountId }) => ({
   displayNameHtml: state.getIn(['accounts', accountId, 'display_name_html']),
-  signupUrl: state.getIn(['server', 'server', 'registrations', 'url'], null) || '/auth/sign_up',
 });
 
 const mapDispatchToProps = (dispatch) => ({
   onSignupClick() {
-    dispatch(closeModal({
-      modalType: undefined,
-      ignoreFocus: false,
-    }));
-    dispatch(openModal({ modalType: 'CLOSED_REGISTRATIONS' }));
+    dispatch(closeModal());
+    dispatch(openModal('CLOSED_REGISTRATIONS'));
   },
 });
 
-class Copypaste extends PureComponent {
+const PERSISTENCE_KEY = 'mastodon_home';
+
+const isValidDomain = value => {
+  const url = new URL('https:///path');
+  url.hostname = value;
+  return url.hostname === value;
+};
+
+const valueToDomain = value => {
+  // If the user starts typing an URL
+  if (/^https?:\/\//.test(value)) {
+    try {
+      const url = new URL(value);
+
+      // Consider that if there is a path, the URL is more meaningful than a bare domain
+      if (url.pathname.length > 1) {
+        return '';
+      }
+
+      return url.host;
+    } catch {
+      return undefined;
+    }
+  // If the user writes their full handle including username
+  } else if (value.includes('@')) {
+    if (value.replace(/^@/, '').split('@').length > 2) {
+      return undefined;
+    }
+    return '';
+  }
+
+  return value;
+};
+
+const addInputToOptions = (value, options) => {
+  value = value.trim();
+
+  if (value.includes('.') && isValidDomain(value)) {
+    return [value].concat(options.filter((x) => x !== value));
+  }
+
+  return options;
+};
+
+class LoginForm extends React.PureComponent {
 
   static propTypes = {
-    value: PropTypes.string,
+    resourceUrl: PropTypes.string,
+    intl: PropTypes.object.isRequired,
   };
 
   state = {
-    copied: false,
+    value: localStorage ? (localStorage.getItem(PERSISTENCE_KEY) || '') : '',
+    expanded: false,
+    selectedOption: -1,
+    isLoading: false,
+    isSubmitting: false,
+    error: false,
+    options: [],
+    networkOptions: [],
   };
 
   setRef = c => {
     this.input = c;
   };
 
-  handleInputClick = () => {
-    this.setState({ copied: false });
-    this.input.focus();
-    this.input.select();
-    this.input.setSelectionRange(0, this.input.value.length);
+  handleChange = ({ target }) => {
+    this.setState(state => ({ value: target.value, isLoading: true, error: false, options: addInputToOptions(target.value, state.networkOptions) }), () => this._loadOptions());
   };
 
-  handleButtonClick = () => {
-    const { value } = this.props;
-    navigator.clipboard.writeText(value);
-    this.input.blur();
-    this.setState({ copied: true });
-    this.timeout = setTimeout(() => this.setState({ copied: false }), 700);
+  handleMessage = (event) => {
+    const { resourceUrl } = this.props;
+
+    if (event.origin !== window.origin || event.source !== this.iframeRef.contentWindow) {
+      return;
+    }
+
+    if (event.data?.type === 'fetchInteractionURL-failure') {
+      this.setState({ isSubmitting: false, error: true });
+    } else if (event.data?.type === 'fetchInteractionURL-success') {
+      if (/^https?:\/\//.test(event.data.template)) {
+        if (localStorage) {
+          localStorage.setItem(PERSISTENCE_KEY, event.data.uri_or_domain);
+        }
+
+        window.location.href = event.data.template.replace('{uri}', encodeURIComponent(resourceUrl));
+      } else {
+        this.setState({ isSubmitting: false, error: true });
+      }
+    }
   };
 
-  componentWillUnmount () {
-    if (this.timeout) clearTimeout(this.timeout);
+  componentDidMount () {
+    window.addEventListener('message', this.handleMessage);
   }
 
+  componentWillUnmount () {
+    window.removeEventListener('message', this.handleMessage);
+  }
+
+  handleSubmit = () => {
+    const { value } = this.state;
+
+    this.setState({ isSubmitting: true });
+
+    this.iframeRef.contentWindow.postMessage({
+      type: 'fetchInteractionURL',
+      uri_or_domain: value.trim(),
+    }, window.origin);
+  };
+
+  setIFrameRef = (iframe) => {
+    this.iframeRef = iframe;
+  }
+
+  handleFocus = () => {
+    this.setState({ expanded: true });
+  };
+
+  handleBlur = () => {
+    this.setState({ expanded: false });
+  };
+
+  handleKeyDown = (e) => {
+    const { options, selectedOption } = this.state;
+
+    switch(e.key) {
+    case 'ArrowDown':
+      e.preventDefault();
+
+      if (options.length > 0) {
+        this.setState({ selectedOption: Math.min(selectedOption + 1, options.length - 1) });
+      }
+
+      break;
+    case 'ArrowUp':
+      e.preventDefault();
+
+      if (options.length > 0) {
+        this.setState({ selectedOption: Math.max(selectedOption - 1, -1) });
+      }
+
+      break;
+    case 'Enter':
+      e.preventDefault();
+
+      if (selectedOption === -1) {
+        this.handleSubmit();
+      } else if (options.length > 0) {
+        this.setState({ value: options[selectedOption], error: false }, () => this.handleSubmit());
+      }
+
+      break;
+    }
+  };
+
+  handleOptionClick = e => {
+    const index  = Number(e.currentTarget.getAttribute('data-index'));
+    const option = this.state.options[index];
+
+    e.preventDefault();
+    this.setState({ selectedOption: index, value: option, error: false }, () => this.handleSubmit());
+  };
+
+  _loadOptions = throttle(() => {
+    const { value } = this.state;
+
+    const domain = valueToDomain(value.trim());
+
+    if (typeof domain === 'undefined') {
+      this.setState({ options: [], networkOptions: [], isLoading: false, error: true });
+      return;
+    }
+
+    if (domain.length === 0) {
+      this.setState({ options: [], networkOptions: [], isLoading: false });
+      return;
+    }
+
+    api().get('/api/v1/peers/search', { params: { q: domain } }).then(({ data }) => {
+      if (!data) {
+        data = [];
+      }
+
+      this.setState((state) => ({ networkOptions: data, options: addInputToOptions(state.value, data), isLoading: false }));
+    }).catch(() => {
+      this.setState({ isLoading: false });
+    });
+  }, 200, { leading: true, trailing: true });
+
   render () {
-    const { value } = this.props;
-    const { copied } = this.state;
+    const { intl } = this.props;
+    const { value, expanded, options, selectedOption, error, isSubmitting } = this.state;
+    const domain = (valueToDomain(value) || '').trim();
+    const domainRegExp = new RegExp(`(${escapeRegExp(domain)})`, 'gi');
+    const hasPopOut = domain.length > 0 && options.length > 0;
 
     return (
-      <div className={classNames('copypaste', { copied })}>
-        <input
-          type='text'
-          ref={this.setRef}
-          value={value}
-          readOnly
-          onClick={this.handleInputClick}
+      <div className={classNames('interaction-modal__login', { focused: expanded, expanded: hasPopOut, invalid: error })}>
+
+        <iframe
+          ref={this.setIFrameRef}
+          style={{display: 'none'}}
+          src='/remote_interaction_helper'
+          sandbox='allow-scripts allow-same-origin'
+          title='remote interaction helper'
         />
 
-        <button className='button' onClick={this.handleButtonClick}>
-          {copied ? <FormattedMessage id='copypaste.copied' defaultMessage='Copied' /> : <FormattedMessage id='copypaste.copy' defaultMessage='Copy' />}
-        </button>
+        <div className='interaction-modal__login__input'>
+          <input
+            ref={this.setRef}
+            type='text'
+            value={value}
+            placeholder={intl.formatMessage(messages.loginPrompt)}
+            aria-label={intl.formatMessage(messages.loginPrompt)}
+            autoFocus
+            onChange={this.handleChange}
+            onFocus={this.handleFocus}
+            onBlur={this.handleBlur}
+            onKeyDown={this.handleKeyDown}
+          />
+
+          <Button onClick={this.handleSubmit} disabled={isSubmitting}><FormattedMessage id='interaction_modal.login.action' defaultMessage='Take me home' /></Button>
+        </div>
+
+        {hasPopOut && (
+          <div className='search__popout'>
+            <div className='search__popout__menu'>
+              {options.map((option, i) => (
+                <button key={option} onMouseDown={this.handleOptionClick} data-index={i} className={classNames('search__popout__menu__item', { selected: selectedOption === i })}>
+                  {option.split(domainRegExp).map((part, i) => (
+                    part.toLowerCase() === domain.toLowerCase() ? (
+                      <mark key={i}>
+                        {part}
+                      </mark>
+                    ) : (
+                      <span key={i}>
+                        {part}
+                      </span>
+                    )
+                  ))}
+                </button>
+              ))}
+            </div>
+          </div>
+        )}
       </div>
     );
   }
 
 }
 
-class InteractionModal extends PureComponent {
+const IntlLoginForm = injectIntl(LoginForm);
+
+class InteractionModal extends React.PureComponent {
 
   static propTypes = {
     displayNameHtml: PropTypes.string,
     url: PropTypes.string,
     type: PropTypes.oneOf(['reply', 'reblog', 'favourite', 'follow']),
     onSignupClick: PropTypes.func.isRequired,
-    signupUrl: PropTypes.string.isRequired,
   };
 
   handleSignupClick = () => {
@@ -97,7 +298,7 @@ class InteractionModal extends PureComponent {
   };
 
   render () {
-    const { url, type, displayNameHtml, signupUrl } = this.props;
+    const { url, type, displayNameHtml } = this.props;
 
     const name = <bdi dangerouslySetInnerHTML={{ __html: displayNameHtml }} />;
 
@@ -130,13 +331,13 @@ class InteractionModal extends PureComponent {
 
     if (registrationsOpen) {
       signupButton = (
-        <a href={signupUrl} className='button button--block button-tertiary'>
+        <a href='/auth/sign_up' className='link-button'>
           <FormattedMessage id='sign_in_banner.create_account' defaultMessage='Create account' />
         </a>
       );
     } else {
       signupButton = (
-        <button className='button button--block button-tertiary' onClick={this.handleSignupClick}>
+        <button className='link-button' onClick={this.handleSignupClick}>
           <FormattedMessage id='sign_in_banner.create_account' defaultMessage='Create account' />
         </button>
       );
@@ -146,22 +347,13 @@ class InteractionModal extends PureComponent {
       <div className='modal-root__modal interaction-modal'>
         <div className='interaction-modal__lead'>
           <h3><span className='interaction-modal__icon'>{icon}</span> {title}</h3>
-          <p>{actionDescription} <FormattedMessage id='interaction_modal.preamble' defaultMessage="Since Mastodon is decentralized, you can use your existing account hosted by another Mastodon server or compatible platform if you don't have an account on this one." /></p>
+          <p>{actionDescription} <strong><FormattedMessage id='interaction_modal.sign_in' defaultMessage='You are not logged in to this server. Where is your account hosted?' /></strong></p>
         </div>
 
-        <div className='interaction-modal__choices'>
-          <div className='interaction-modal__choices__choice'>
-            <h3><FormattedMessage id='interaction_modal.on_this_server' defaultMessage='On this server' /></h3>
-            <a href='/auth/sign_in' className='button button--block'><FormattedMessage id='sign_in_banner.sign_in' defaultMessage='Login' /></a>
-            {signupButton}
-          </div>
+        <IntlLoginForm resourceUrl={url} />
 
-          <div className='interaction-modal__choices__choice'>
-            <h3><FormattedMessage id='interaction_modal.on_another_server' defaultMessage='On a different server' /></h3>
-            <p><FormattedMessage id='interaction_modal.other_server_instructions' defaultMessage='Copy and paste this URL into the search field of your favorite Mastodon app or the web interface of your Mastodon server.' /></p>
-            <Copypaste value={url} />
-          </div>
-        </div>
+        <p className='hint'><FormattedMessage id='interaction_modal.sign_in_hint' defaultMessage="Tip: That's the website where you signed up. If you don't remember, look for the welcome e-mail in your inbox. You can also enter your full username! (e.g. @Mastodon@mastodon.social)" /></p>
+        <p><FormattedMessage id='interaction_modal.no_account_yet' defaultMessage='Not on Mastodon?' /> {signupButton}</p>
       </div>
     );
   }
diff --git a/app/javascript/mastodon/features/picture_in_picture/components/footer.jsx b/app/javascript/mastodon/features/picture_in_picture/components/footer.jsx
index a368962b9..0f3244b9c 100644
--- a/app/javascript/mastodon/features/picture_in_picture/components/footer.jsx
+++ b/app/javascript/mastodon/features/picture_in_picture/components/footer.jsx
@@ -91,7 +91,7 @@ class Footer extends ImmutablePureComponent {
         modalProps: {
           type: 'reply',
           accountId: status.getIn(['account', 'id']),
-          url: status.get('url'),
+          url: status.get('uri'),
         },
       }));
     }
@@ -113,7 +113,7 @@ class Footer extends ImmutablePureComponent {
         modalProps: {
           type: 'favourite',
           accountId: status.getIn(['account', 'id']),
-          url: status.get('url'),
+          url: status.get('uri'),
         },
       }));
     }
@@ -142,7 +142,7 @@ class Footer extends ImmutablePureComponent {
         modalProps: {
           type: 'reblog',
           accountId: status.getIn(['account', 'id']),
-          url: status.get('url'),
+          url: status.get('uri'),
         },
       }));
     }
diff --git a/app/javascript/mastodon/features/status/index.jsx b/app/javascript/mastodon/features/status/index.jsx
index 1713d94eb..f1d591c73 100644
--- a/app/javascript/mastodon/features/status/index.jsx
+++ b/app/javascript/mastodon/features/status/index.jsx
@@ -252,7 +252,7 @@ class Status extends ImmutablePureComponent {
         modalProps: {
           type: 'favourite',
           accountId: status.getIn(['account', 'id']),
-          url: status.get('url'),
+          url: status.get('uri'),
         },
       }));
     }
@@ -289,7 +289,7 @@ class Status extends ImmutablePureComponent {
         modalProps: {
           type: 'reply',
           accountId: status.getIn(['account', 'id']),
-          url: status.get('url'),
+          url: status.get('uri'),
         },
       }));
     }
@@ -319,7 +319,7 @@ class Status extends ImmutablePureComponent {
         modalProps: {
           type: 'reblog',
           accountId: status.getIn(['account', 'id']),
-          url: status.get('url'),
+          url: status.get('uri'),
         },
       }));
     }
diff --git a/app/javascript/mastodon/locales/en.json b/app/javascript/mastodon/locales/en.json
index cc9bffd80..c87f8f508 100644
--- a/app/javascript/mastodon/locales/en.json
+++ b/app/javascript/mastodon/locales/en.json
@@ -191,7 +191,6 @@
   "conversation.open": "View conversation",
   "conversation.with": "With {names}",
   "copypaste.copied": "Copied",
-  "copypaste.copy": "Copy",
   "copypaste.copy_to_clipboard": "Copy to clipboard",
   "directory.federated": "From known fediverse",
   "directory.local": "From {domain} only",
@@ -311,10 +310,13 @@
   "interaction_modal.description.follow": "With an account on Mastodon, you can follow {name} to receive their posts in your home feed.",
   "interaction_modal.description.reblog": "With an account on Mastodon, you can boost this post to share it with your own followers.",
   "interaction_modal.description.reply": "With an account on Mastodon, you can respond to this post.",
+  "interaction_modal.login.action": "Take me home",
+  "interaction_modal.login.prompt": "Domain of your home server, e.g. mastodon.social",
+  "interaction_modal.no_account_yet": "Not on Mastodon?",
   "interaction_modal.on_another_server": "On a different server",
   "interaction_modal.on_this_server": "On this server",
-  "interaction_modal.other_server_instructions": "Copy and paste this URL into the search field of your favorite Mastodon app or the web interface of your Mastodon server.",
-  "interaction_modal.preamble": "Since Mastodon is decentralized, you can use your existing account hosted by another Mastodon server or compatible platform if you don't have an account on this one.",
+  "interaction_modal.sign_in": "You are not logged in to this server. Where is your account hosted?",
+  "interaction_modal.sign_in_hint": "Tip: That's the website where you signed up. If you don't remember, look for the welcome e-mail in your inbox. You can also enter your full username! (e.g. @Mastodon@mastodon.social)",
   "interaction_modal.title.favourite": "Favorite {name}'s post",
   "interaction_modal.title.follow": "Follow {name}",
   "interaction_modal.title.reblog": "Boost {name}'s post",
diff --git a/app/javascript/packs/remote_interaction_helper.ts b/app/javascript/packs/remote_interaction_helper.ts
new file mode 100644
index 000000000..76528ff38
--- /dev/null
+++ b/app/javascript/packs/remote_interaction_helper.ts
@@ -0,0 +1,172 @@
+/*
+
+This script is meant to to be used in an `iframe` with the sole purpose of doing webfinger queries
+client-side without being restricted by a strict `connect-src` Content-Security-Policy directive.
+
+It communicates with the parent window through message events that are authenticated by origin,
+and performs no other task.
+
+*/
+
+import './public-path';
+
+import axios from 'axios';
+
+interface JRDLink {
+  rel: string;
+  template?: string;
+  href?: string;
+}
+
+const isJRDLink = (link: unknown): link is JRDLink =>
+  typeof link === 'object' &&
+  link !== null &&
+  'rel' in link &&
+  typeof link.rel === 'string' &&
+  (!('template' in link) || typeof link.template === 'string') &&
+  (!('href' in link) || typeof link.href === 'string');
+
+const findLink = (rel: string, data: unknown): JRDLink | undefined => {
+  if (
+    typeof data === 'object' &&
+    data !== null &&
+    'links' in data &&
+    data.links instanceof Array
+  ) {
+    return data.links.find(
+      (link): link is JRDLink => isJRDLink(link) && link.rel === rel,
+    );
+  } else {
+    return undefined;
+  }
+};
+
+const findTemplateLink = (data: unknown) =>
+  findLink('http://ostatus.org/schema/1.0/subscribe', data)?.template;
+
+const fetchInteractionURLSuccess = (
+  uri_or_domain: string,
+  template: string,
+) => {
+  window.parent.postMessage(
+    {
+      type: 'fetchInteractionURL-success',
+      uri_or_domain,
+      template,
+    },
+    window.origin,
+  );
+};
+
+const fetchInteractionURLFailure = () => {
+  window.parent.postMessage(
+    {
+      type: 'fetchInteractionURL-failure',
+    },
+    window.origin,
+  );
+};
+
+const isValidDomain = (value: string) => {
+  const url = new URL('https:///path');
+  url.hostname = value;
+  return url.hostname === value;
+};
+
+// Attempt to find a remote interaction URL from a domain
+const fromDomain = (domain: string) => {
+  const fallbackTemplate = `https://${domain}/authorize_interaction?uri={uri}`;
+
+  axios
+    .get(`https://${domain}/.well-known/webfinger`, {
+      params: { resource: `https://${domain}` },
+    })
+    .then(({ data }) => {
+      const template = findTemplateLink(data);
+      fetchInteractionURLSuccess(domain, template ?? fallbackTemplate);
+      return;
+    })
+    .catch(() => {
+      fetchInteractionURLSuccess(domain, fallbackTemplate);
+    });
+};
+
+// Attempt to find a remote interaction URL from an arbitrary URL
+const fromURL = (url: string) => {
+  const domain = new URL(url).host;
+  const fallbackTemplate = `https://${domain}/authorize_interaction?uri={uri}`;
+
+  axios
+    .get(`https://${domain}/.well-known/webfinger`, {
+      params: { resource: url },
+    })
+    .then(({ data }) => {
+      const template = findTemplateLink(data);
+      fetchInteractionURLSuccess(url, template ?? fallbackTemplate);
+      return;
+    })
+    .catch(() => {
+      fromDomain(domain);
+    });
+};
+
+// Attempt to find a remote interaction URL from a `user@domain` string
+const fromAcct = (acct: string) => {
+  acct = acct.replace(/^@/, '');
+
+  const segments = acct.split('@');
+
+  if (segments.length !== 2 || !segments[0] || !isValidDomain(segments[1])) {
+    fetchInteractionURLFailure();
+    return;
+  }
+
+  const domain = segments[1];
+  const fallbackTemplate = `https://${domain}/authorize_interaction?uri={uri}`;
+
+  axios
+    .get(`https://${domain}/.well-known/webfinger`, {
+      params: { resource: `acct:${acct}` },
+    })
+    .then(({ data }) => {
+      const template = findTemplateLink(data);
+      fetchInteractionURLSuccess(acct, template ?? fallbackTemplate);
+      return;
+    })
+    .catch(() => {
+      // TODO: handle host-meta?
+      fromDomain(domain);
+    });
+};
+
+const fetchInteractionURL = (uri_or_domain: string) => {
+  if (/^https?:\/\//.test(uri_or_domain)) {
+    fromURL(uri_or_domain);
+  } else if (uri_or_domain.includes('@')) {
+    fromAcct(uri_or_domain);
+  } else {
+    fromDomain(uri_or_domain);
+  }
+};
+
+window.addEventListener('message', (event: MessageEvent<unknown>) => {
+  // Check message origin
+  if (
+    !window.origin ||
+    window.parent !== event.source ||
+    event.origin !== window.origin
+  ) {
+    return;
+  }
+
+  if (
+    event.data &&
+    typeof event.data === 'object' &&
+    'type' in event.data &&
+    event.data.type === 'fetchInteractionURL' &&
+    'uri_or_domain' in event.data &&
+    typeof event.data.uri_or_domain === 'string'
+  ) {
+    fetchInteractionURL(event.data.uri_or_domain);
+  }
+});
diff --git a/app/javascript/styles/mastodon/components.scss b/app/javascript/styles/mastodon/components.scss
index 4c9a2cfdd..24ba0c6e9 100644
--- a/app/javascript/styles/mastodon/components.scss
+++ b/app/javascript/styles/mastodon/components.scss
@@ -8356,13 +8356,13 @@ noscript {
 .interaction-modal {
   max-width: 90vw;
   width: 600px;
-  background: $ui-base-color;
+  background: var(--modal-background-color);
+  border: 1px solid var(--modal-border-color);
   border-radius: 8px;
-  overflow-x: hidden;
-  overflow-y: auto;
+  overflow: visible;
   position: relative;
   display: block;
-  padding: 20px;
+  padding: 40px;
 
   h3 {
     font-size: 22px;
@@ -8371,63 +8371,100 @@ noscript {
     text-align: center;
   }
 
+  p {
+    font-size: 17px;
+    line-height: 22px;
+    color: $darker-text-color;
+
+    strong {
+      color: $primary-text-color;
+      font-weight: 700;
+    }
+  }
+
+  p.hint {
+    margin-bottom: 14px;
+    font-size: 14px;
+  }
+
   &__icon {
     color: $highlight-text-color;
     margin: 0 5px;
   }
 
   &__lead {
-    padding: 20px;
-    text-align: center;
+    margin-bottom: 20px;
 
     h3 {
       margin-bottom: 15px;
     }
-
-    p {
-      font-size: 17px;
-      line-height: 22px;
-      color: $darker-text-color;
-    }
   }
 
-  &__choices {
-    display: flex;
+  &__login {
+    position: relative;
+    margin-bottom: 20px;
 
-    &__choice {
-      flex: 0 0 auto;
-      width: 50%;
-      box-sizing: border-box;
-      padding: 20px;
+    &__input {
+      @include search-input;
 
-      h3 {
-        margin-bottom: 20px;
-      }
+      border: 1px solid lighten($ui-base-color, 8%);
+      padding: 4px 6px;
+      color: $primary-text-color;
+      font-size: 16px;
+      line-height: 18px;
+      display: flex;
+      align-items: center;
 
-      p {
-        color: $darker-text-color;
-        margin-bottom: 20px;
+      input {
+        background: transparent;
+        color: inherit;
+        font: inherit;
+        border: 0;
+        padding: 15px - 4px 15px - 6px;
+        flex: 1 1 auto;
+
+        &::placeholder {
+          color: lighten($darker-text-color, 4%);
+        }
+
+        &:focus {
+          outline: 0;
+        }
       }
 
       .button {
-        margin-bottom: 10px;
-
-        &:last-child {
-          margin-bottom: 0;
-        }
+        flex: 0 0 auto;
       }
     }
+
+    .search__popout {
+      margin-top: -1px;
+      padding-top: 5px;
+      padding-bottom: 5px;
+      border: 1px solid lighten($ui-base-color, 8%);
+    }
+
+    &.focused &__input {
+      border-color: $highlight-text-color;
+      background: lighten($ui-base-color, 4%);
+    }
+
+    &.invalid &__input {
+      border-color: $error-red;
+    }
+
+    &.expanded .search__popout {
+      display: block;
+    }
+
+    &.expanded &__input {
+      border-radius: 4px 4px 0 0;
+    }
   }
 
-  @media screen and (max-width: $no-gap-breakpoint - 1px) {
-    &__choices {
-      display: block;
-
-      &__choice {
-        width: auto;
-        margin-bottom: 20px;
-      }
-    }
+  .link-button {
+    font-size: inherit;
+    display: inline;
   }
 }
 
diff --git a/app/javascript/styles/mastodon/variables.scss b/app/javascript/styles/mastodon/variables.scss
index e89dd5d3a..073bb16e5 100644
--- a/app/javascript/styles/mastodon/variables.scss
+++ b/app/javascript/styles/mastodon/variables.scss
@@ -96,4 +96,6 @@ $font-monospace: 'mastodon-font-monospace' !default;
   --dropdown-background-color: #{lighten($ui-base-color, 4%)};
   --dropdown-shadow: 0 20px 25px -5px #{rgba($base-shadow-color, 0.25)},
     0 8px 10px -6px #{rgba($base-shadow-color, 0.25)};
+  --modal-background-color: #{darken($ui-base-color, 4%)};
+  --modal-border-color: #{lighten($ui-base-color, 4%)};
 }
diff --git a/app/javascript/types/resources.ts b/app/javascript/types/resources.ts
index 63ec2993b..f3901ad15 100644
--- a/app/javascript/types/resources.ts
+++ b/app/javascript/types/resources.ts
@@ -33,6 +33,7 @@ interface AccountApiResponseValues {
   note: string;
   statuses_count: number;
   url: string;
+  uri: string;
   username: string;
 }
 
diff --git a/app/lib/importer/instances_index_importer.rb b/app/lib/importer/instances_index_importer.rb
new file mode 100644
index 000000000..7318b51b5
--- /dev/null
+++ b/app/lib/importer/instances_index_importer.rb
@@ -0,0 +1,26 @@
+# frozen_string_literal: true
+
+class Importer::InstancesIndexImporter < Importer::BaseImporter
+  def import!
+    index.adapter.default_scope.find_in_batches(batch_size: @batch_size) do |tmp|
+      in_work_unit(tmp) do |instances|
+        bulk = Chewy::Index::Import::BulkBuilder.new(index, to_index: instances).bulk_body
+
+        indexed = bulk.count { |entry| entry[:index] }
+        deleted = bulk.count { |entry| entry[:delete] }
+
+        Chewy::Index::Import::BulkRequest.new(index).perform(bulk)
+
+        [indexed, deleted]
+      end
+    end
+
+    wait!
+  end
+
+  private
+
+  def index
+    InstancesIndex
+  end
+end
diff --git a/app/lib/webfinger_resource.rb b/app/lib/webfinger_resource.rb
index e28723ff8..e2027e164 100644
--- a/app/lib/webfinger_resource.rb
+++ b/app/lib/webfinger_resource.rb
@@ -11,6 +11,8 @@ class WebfingerResource
 
   def username
     case resource
+    when %r{\A(https?://)?#{instance_actor_regexp}/?\Z}
+      Rails.configuration.x.local_domain
     when /\Ahttps?/i
       username_from_url
     when /@/
@@ -22,6 +24,13 @@ class WebfingerResource
 
   private
 
+  def instance_actor_regexp
+    hosts = [Rails.configuration.x.local_domain, Rails.configuration.x.web_domain]
+    hosts.concat(Rails.configuration.x.alternate_domains) if Rails.configuration.x.alternate_domains.present?
+
+    Regexp.union(hosts)
+  end
+
   def username_from_url
     if account_show_page?
       path_params[:username]
diff --git a/app/models/instance.rb b/app/models/instance.rb
index 5e6a93f64..17ee0cbb1 100644
--- a/app/models/instance.rb
+++ b/app/models/instance.rb
@@ -21,6 +21,7 @@ class Instance < ApplicationRecord
     belongs_to :unavailable_domain # skipcq: RB-RL1031
   end
 
+  scope :searchable, -> { where.not(domain: DomainBlock.select(:domain)) }
   scope :matches_domain, ->(value) { where(arel_table[:domain].matches("%#{value}%")) }
   scope :by_domain_and_subdomains, ->(domain) { where("reverse('.' || domain) LIKE reverse(?)", "%.#{domain}") }
 
diff --git a/app/serializers/rest/account_serializer.rb b/app/serializers/rest/account_serializer.rb
index 2845470be..310cf1b1e 100644
--- a/app/serializers/rest/account_serializer.rb
+++ b/app/serializers/rest/account_serializer.rb
@@ -5,7 +5,7 @@ class REST::AccountSerializer < ActiveModel::Serializer
   include FormattingHelper
 
   attributes :id, :username, :acct, :display_name, :locked, :bot, :discoverable, :group, :created_at,
-             :note, :url, :avatar, :avatar_static, :header, :header_static,
+             :note, :url, :uri, :avatar, :avatar_static, :header, :header_static,
              :followers_count, :following_count, :statuses_count, :last_status_at
 
   has_one :moved_to_account, key: :moved, serializer: REST::AccountSerializer, if: :moved_and_not_nested?
@@ -66,6 +66,10 @@ class REST::AccountSerializer < ActiveModel::Serializer
     ActivityPub::TagManager.instance.url_for(object)
   end
 
+  def uri
+    ActivityPub::TagManager.instance.uri_for(object)
+  end
+
   def avatar
     full_asset_url(object.suspended? ? object.avatar.default_url : object.avatar_original_url)
   end
diff --git a/app/serializers/webfinger_serializer.rb b/app/serializers/webfinger_serializer.rb
index c67363b8f..3ca344116 100644
--- a/app/serializers/webfinger_serializer.rb
+++ b/app/serializers/webfinger_serializer.rb
@@ -22,6 +22,7 @@ class WebfingerSerializer < ActiveModel::Serializer
       [
         { rel: 'http://webfinger.net/rel/profile-page', type: 'text/html', href: about_more_url(instance_actor: true) },
         { rel: 'self', type: 'application/activity+json', href: instance_actor_url },
+        { rel: 'http://ostatus.org/schema/1.0/subscribe', template: "#{authorize_interaction_url}?uri={uri}" },
       ]
     else
       [
diff --git a/app/views/authorize_interactions/_post_follow_actions.html.haml b/app/views/authorize_interactions/_post_follow_actions.html.haml
deleted file mode 100644
index e30097964..000000000
--- a/app/views/authorize_interactions/_post_follow_actions.html.haml
+++ /dev/null
@@ -1,4 +0,0 @@
-.post-follow-actions
-  %div= link_to t('authorize_follow.post_follow.web'), web_url("@#{@resource.pretty_acct}"), class: 'button button--block'
-  %div= link_to t('authorize_follow.post_follow.return'), ActivityPub::TagManager.instance.url_for(@resource), class: 'button button--block'
-  %div= t('authorize_follow.post_follow.close')
diff --git a/app/views/authorize_interactions/error.html.haml b/app/views/authorize_interactions/error.html.haml
deleted file mode 100644
index 88d33b68d..000000000
--- a/app/views/authorize_interactions/error.html.haml
+++ /dev/null
@@ -1,3 +0,0 @@
-.form-container
-  .flash-message#error_explanation
-    = t('authorize_follow.error')
diff --git a/app/views/authorize_interactions/show.html.haml b/app/views/authorize_interactions/show.html.haml
deleted file mode 100644
index 2b4d2ed62..000000000
--- a/app/views/authorize_interactions/show.html.haml
+++ /dev/null
@@ -1,24 +0,0 @@
-- content_for :page_title do
-  = t('authorize_follow.title', acct: @resource.pretty_acct)
-
-.form-container
-  .follow-prompt
-    = render 'application/card', account: @resource
-
-  - if current_account.following?(@resource)
-    .flash-message
-      %strong
-        = t('authorize_follow.already_following')
-
-    = render 'post_follow_actions'
-  - elsif current_account.requested?(@resource)
-    .flash-message
-      %strong
-        = t('authorize_follow.already_requested')
-
-    = render 'post_follow_actions'
-  - else
-    = form_tag authorize_interaction_path, method: :post, class: 'simple_form' do
-      = hidden_field_tag :action, :follow
-      = hidden_field_tag :acct, @resource.acct
-      = button_tag t('authorize_follow.follow'), type: :submit
diff --git a/app/views/authorize_interactions/success.html.haml b/app/views/authorize_interactions/success.html.haml
deleted file mode 100644
index 86fa55eac..000000000
--- a/app/views/authorize_interactions/success.html.haml
+++ /dev/null
@@ -1,13 +0,0 @@
-- content_for :page_title do
-  = t('authorize_follow.title', acct: @resource.pretty_acct)
-
-.form-container
-  .follow-prompt
-    - if @resource.locked?
-      %h2= t('authorize_follow.follow_request')
-    - else
-      %h2= t('authorize_follow.following')
-
-    = render 'application/card', account: @resource
-
-  = render 'post_follow_actions'
diff --git a/app/views/layouts/helper_frame.html.haml b/app/views/layouts/helper_frame.html.haml
new file mode 100644
index 000000000..289738919
--- /dev/null
+++ b/app/views/layouts/helper_frame.html.haml
@@ -0,0 +1,8 @@
+!!! 5
+%html
+  %head
+    %meta{ charset: 'utf-8' }/
+
+    = javascript_pack_tag 'common', crossorigin: 'anonymous'
+
+    = yield :header_tags
diff --git a/app/views/remote_interaction_helper/index.html.haml b/app/views/remote_interaction_helper/index.html.haml
new file mode 100644
index 000000000..08db7075b
--- /dev/null
+++ b/app/views/remote_interaction_helper/index.html.haml
@@ -0,0 +1,4 @@
+- content_for :header_tags do
+  %meta{ name: 'robots', content: 'noindex' }/
+
+  = javascript_pack_tag 'remote_interaction_helper', crossorigin: 'anonymous'
diff --git a/app/workers/scheduler/instance_refresh_scheduler.rb b/app/workers/scheduler/instance_refresh_scheduler.rb
index 2af5f3855..59f91dc62 100644
--- a/app/workers/scheduler/instance_refresh_scheduler.rb
+++ b/app/workers/scheduler/instance_refresh_scheduler.rb
@@ -7,5 +7,6 @@ class Scheduler::InstanceRefreshScheduler
 
   def perform
     Instance.refresh
+    InstancesIndex.import if Chewy.enabled?
   end
 end
diff --git a/config/locales/an.yml b/config/locales/an.yml
index b8f53bf83..7922ccf58 100644
--- a/config/locales/an.yml
+++ b/config/locales/an.yml
@@ -982,18 +982,6 @@ an:
       view_strikes: Veyer amonestacions pasadas contra la tuya cuenta
     too_fast: Formulario ninviau masiau rapido, lo intente de nuevo.
     use_security_key: Usar la clau de seguranza
-  authorize_follow:
-    already_following: Ya yes seguindo a esta cuenta
-    already_requested: Ya has ninviau una solicitut de seguimiento a ixa cuenta
-    error: Desafortunadament, ha ocurriu una error buscando la cuenta remota
-    follow: Seguir
-    follow_request: 'Tiens una solicitut de seguimiento de:'
-    following: 'Exito! Agora yes seguindo a:'
-    post_follow:
-      close: U, puetz simplament zarrar esta finestra.
-      return: Tornar ta lo perfil de l'usuario
-      web: Ir ta lo puesto web
-    title: Seguir a %{acct}
   challenge:
     confirm: Continar
     hint_html: "<strong>Tip:</strong> No tornaremos a preguntar-te per la clau entre la siguient hora."
diff --git a/config/locales/ar.yml b/config/locales/ar.yml
index d8be015f2..e69f3d708 100644
--- a/config/locales/ar.yml
+++ b/config/locales/ar.yml
@@ -1065,18 +1065,6 @@ ar:
       view_strikes: عرض السجلات السابقة ضد حسابك
     too_fast: تم إرسال النموذج بسرعة كبيرة، حاول مرة أخرى.
     use_security_key: استخدام مفتاح الأمان
-  authorize_follow:
-    already_following: أنت تتابع بالفعل هذا الحساب
-    already_requested: لقد قُمتَ بإرسال طلب متابَعة إلى هذا الحساب مِن قَبل
-    error: يا للأسف، وقع هناك خطأ إثر عملية البحث عن الحساب عن بعد
-    follow: اتبع
-    follow_request: 'لقد قمت بإرسال طلب متابعة إلى:'
-    following: 'مرحى! أنت الآن تتبع:'
-    post_follow:
-      close: أو يمكنك إغلاق هذه النافذة.
-      return: اظهر الملف التعريفي للمستخدم
-      web: واصل إلى الويب
-    title: إتباع %{acct}
   challenge:
     confirm: واصل
     hint_html: "<strong>توصية:</strong> لن نطلب منك ثانية كلمتك السرية في غضون الساعة اللاحقة."
diff --git a/config/locales/ast.yml b/config/locales/ast.yml
index d52678170..4bcbd554c 100644
--- a/config/locales/ast.yml
+++ b/config/locales/ast.yml
@@ -481,15 +481,6 @@ ast:
       functional: La cuenta ta completamente operativa.
       pending: La to solicitú ta pendiente de que la revise'l nuesu personal ya ye posible que tarde tiempu. Vas recibir un mensaxe si s'aprueba.
     too_fast: El formulariu xubióse mui rápido, volvi tentalo.
-  authorize_follow:
-    already_following: Xá tas siguiendo a esta cuenta
-    already_requested: Yá unviesti una solicitú de siguimientu a esa cuenta
-    error: Desafortunadamente, hebo un error al buscar la cuenta remota
-    follow_request: 'Unviesti una solicitú de siguimientu a:'
-    post_follow:
-      close: O pues zarrar esta ventana.
-      return: Amosar el perfil de la cuenta
-      web: Dir a la web
   challenge:
     confirm: Siguir
     hint_html: "<strong>Conseyu:</strong> nun vamos volver pidite la contraseña hasta dientro d'una hora."
diff --git a/config/locales/be.yml b/config/locales/be.yml
index 5a22953aa..bb08532ba 100644
--- a/config/locales/be.yml
+++ b/config/locales/be.yml
@@ -1095,18 +1095,6 @@ be:
       view_strikes: Праглядзець мінулыя папярэджанні для вашага ўліковага запісу
     too_fast: Форма адпраўлена занадта хутка, паспрабуйце яшчэ раз.
     use_security_key: Выкарыстаеце ключ бяспекі
-  authorize_follow:
-    already_following: Вы ўжо падпісаныя на гэты ўліковы запіс
-    already_requested: Вы ўжо адправілі запыт на гэты ўліковы запіс
-    error: На жаль, падчас пошуку аддаленага ўліковага запісу здарылася памылка
-    follow: Падпісацца
-    follow_request: 'Вы адправілі запыт на падпіску:'
-    following: 'Поспех! Цяпер вы падпісаны на:'
-    post_follow:
-      close: Або, вы можаце проста закрыць гэтае акно.
-      return: Паказаць профіль карыстальніка
-      web: Перайсці ў вэб-версію
-    title: Падпісацца на %{acct}
   challenge:
     confirm: Працягнуць
     hint_html: "<strong>Парада:</strong> Мы не будзем запытваць ваш пароль зноўку на працягу наступнай гадзіны."
diff --git a/config/locales/bg.yml b/config/locales/bg.yml
index 1b14e5d12..f16758498 100644
--- a/config/locales/bg.yml
+++ b/config/locales/bg.yml
@@ -1059,18 +1059,6 @@ bg:
       view_strikes: Преглед на предишните предупреждения против акаунта ви
     too_fast: Образецът подаден пребързо, опитайте пак.
     use_security_key: Употреба на ключ за сигурност
-  authorize_follow:
-    already_following: Вече следвате този акаунт
-    already_requested: Вече сте изпратили заявка за последване до този акаунт
-    error: Възникна грешка, търсейки отдалечения акаунт
-    follow: Последвай
-    follow_request: 'Изпратихте следната заявка до:'
-    following: 'Успешно! Сега сте последвали:'
-    post_follow:
-      close: Или просто затворете този прозорец.
-      return: Показване на профила на потребителя
-      web: Към мрежата
-    title: Последвай %{acct}
   challenge:
     confirm: Продължаване
     hint_html: "<strong>Съвет</strong>: няма да ви питаме пак за паролата през следващия час."
diff --git a/config/locales/br.yml b/config/locales/br.yml
index f1d9d1190..d2c24cb38 100644
--- a/config/locales/br.yml
+++ b/config/locales/br.yml
@@ -299,11 +299,6 @@ br:
     security: Diogelroez
     status:
       account_status: Statud ar gont
-  authorize_follow:
-    follow: Heuliañ
-    post_follow:
-      web: Distreiñ d'an etrefas web
-    title: Heuliañ %{acct}
   challenge:
     confirm: Kenderc' hel
     invalid_password: Ger-tremen diwiriek
diff --git a/config/locales/ca.yml b/config/locales/ca.yml
index 62208d4d8..519670864 100644
--- a/config/locales/ca.yml
+++ b/config/locales/ca.yml
@@ -1060,18 +1060,6 @@ ca:
       view_strikes: Veure accions del passat contra el teu compte
     too_fast: Formulari enviat massa ràpid, torna a provar-ho.
     use_security_key: Usa clau de seguretat
-  authorize_follow:
-    already_following: Ja estàs seguint aquest compte
-    already_requested: Ja has enviat una sol·licitud de seguiment a aquest usuari
-    error: Malauradament, ha ocorregut un error cercant el compte remot
-    follow: Segueix
-    follow_request: 'Has enviat una sol·licitud de seguiment a:'
-    following: 'Perfecte! Ara segueixes:'
-    post_follow:
-      close: O bé, pots tancar aquesta finestra.
-      return: Mostra el perfil de l'usuari
-      web: Vés a la web
-    title: Segueix %{acct}
   challenge:
     confirm: Continua
     hint_html: "<strong>Pista:</strong> No et preguntarem un altre cop la teva contrasenya en la pròxima hora."
diff --git a/config/locales/ckb.yml b/config/locales/ckb.yml
index a9020a84e..9a974b9ed 100644
--- a/config/locales/ckb.yml
+++ b/config/locales/ckb.yml
@@ -620,18 +620,6 @@ ckb:
       view_strikes: بینینی لێدانەکانی ڕابردوو لە دژی ئەکاونتەکەت
     too_fast: فۆڕم زۆر خێرا پێشکەش کراوە، دووبارە هەوڵبدەرەوە.
     use_security_key: کلیلی ئاسایش بەکاربهێنە
-  authorize_follow:
-    already_following: ئێوە ئێستا شوێن کەوتووی ئەم هەژمارەیەی
-    already_requested: تۆ پێشتر داواکاری بەدواداچوت ناردوە بۆ ئەو هەژمارە
-    error: بەداخەوە هەڵەیەک هەبوو لە کاتی گەڕان بەدوای ئەو هەژمارەیە
-    follow: شوێن کەوە
-    follow_request: 'تۆ داواکاری شوێنکەوتنت ناردووە بۆ:'
-    following: 'ئەنجام بوو! تۆ ئێستا بەدوای ئەم بەکارهێنەرە دەکەویت:'
-    post_follow:
-      close: یان، دەتوانیت ئەم پەنجەرەیە دابخەیت.
-      return: پرۆفایلی بەکارهێنەر نیشان بدە
-      web: بڕۆ بۆ وێب
-    title: دوای %{acct} بکەوە
   challenge:
     confirm: بەردەوام بە
     hint_html: "<strong>خاڵ:</strong> ئیمە لە کاتژمێری داهاتوو تێپەروشەت لێداوا ناکەین."
diff --git a/config/locales/co.yml b/config/locales/co.yml
index 26907ca7b..0493bfd33 100644
--- a/config/locales/co.yml
+++ b/config/locales/co.yml
@@ -583,18 +583,6 @@ co:
       redirecting_to: U vostru contu hè inattivu perchè riindirizza versu %{acct}.
     too_fast: Furmulariu mandatu troppu prestu, ripruvate.
     use_security_key: Utilizà a chjave di sicurità
-  authorize_follow:
-    already_following: Site digià abbunatu·a à stu contu
-    already_requested: Avete digià mandatu una dumanda d'abbunamentu à stu contu
-    error: Peccatu, c’hè statu un prublemu ricercandu u contu
-    follow: Siguità
-    follow_request: 'Avete dumandatu di siguità:'
-    following: 'Eccu! Avà seguitate:'
-    post_follow:
-      close: O pudete ancu chjude sta finestra.
-      return: Vede u prufile di l’utilizatore
-      web: Andà à l’interfaccia web
-    title: Siguità %{acct}
   challenge:
     confirm: Cuntinuvà
     hint_html: "<strong>Astuzia:</strong> Ùn avemu micca da dumandavvi stu codice per l'ore chì vene."
diff --git a/config/locales/cs.yml b/config/locales/cs.yml
index 8d031c910..95c980a6d 100644
--- a/config/locales/cs.yml
+++ b/config/locales/cs.yml
@@ -1075,18 +1075,6 @@ cs:
       view_strikes: Zobrazit minulé prohřešky vašeho účtu
     too_fast: Formulář byl odeslán příliš rychle, zkuste to znovu.
     use_security_key: Použít bezpečnostní klíč
-  authorize_follow:
-    already_following: Tento účet již sledujete
-    already_requested: Tomuto účtu už jste žádost o sledování zaslali
-    error: Při hledání vzdáleného účtu bohužel nastala chyba
-    follow: Sledovat
-    follow_request: 'Poslali jste žádost o sledování uživateli:'
-    following: 'Podařilo se! Nyní sledujete uživatele:'
-    post_follow:
-      close: Nebo můžete toto okno klidně zavřít.
-      return: Zobrazit profil uživatele
-      web: Přejít na web
-    title: Sledovat %{acct}
   challenge:
     confirm: Pokračovat
     hint_html: "<strong>Tip:</strong> Po dobu jedné hodiny vás o heslo nebudeme znovu žádat."
diff --git a/config/locales/cy.yml b/config/locales/cy.yml
index 24d544bd6..7cb2ba222 100644
--- a/config/locales/cy.yml
+++ b/config/locales/cy.yml
@@ -1132,18 +1132,6 @@ cy:
       view_strikes: Gweld rybuddion y gorffennol yn erbyn eich cyfrif
     too_fast: Cafodd y ffurflen ei chyflwyno'n rhy gyflym, ceisiwch eto.
     use_security_key: Defnyddiwch allwedd diogelwch
-  authorize_follow:
-    already_following: Rydych yn dilyn y cyfrif hwn yn barod
-    already_requested: Rydych chi eisoes wedi anfon cais i ddilyn y cyfrif hwnnw
-    error: Yn anffodus, roedd gwall tra'n edrych am y cyfrif pell
-    follow: Dilyn
-    follow_request: 'Rydych wedi anfon cais dilyn at:'
-    following: 'Llwyddiant! Rydych nawr yn dilyn:'
-    post_follow:
-      close: Neu, gallwch gau'r ffenest hon.
-      return: Dangos proffil y defnyddiwr
-      web: Ewch i'r we
-    title: Dilyn %{acct}
   challenge:
     confirm: Parhau
     hint_html: "<strong>Awgrym:</strong> Fyddwn ni ddim yn gofyn i chi am eich cyfrinair eto am yr awr nesaf."
diff --git a/config/locales/da.yml b/config/locales/da.yml
index 3cf7d5166..0ffc3a51a 100644
--- a/config/locales/da.yml
+++ b/config/locales/da.yml
@@ -1060,18 +1060,6 @@ da:
       view_strikes: Se tidligere anmeldelser af din konto
     too_fast: Formularen indsendt for hurtigt, forsøg igen.
     use_security_key: Brug sikkerhedsnøgle
-  authorize_follow:
-    already_following: Du følger allerede denne konto
-    already_requested: Du har allerede sendt en følgeanmodning til den konto
-    error: Desværre opstod en fejl under søgning af fjernkontoen
-    follow: Følg
-    follow_request: 'Du har sendt en følgeanmodning til:'
-    following: 'Accepteret! Du følger nu:'
-    post_follow:
-      close: Du kan også bare lukke dette vindue.
-      return: Vis brugerens profil
-      web: Gå til web
-    title: Følg %{acct}
   challenge:
     confirm: Fortsæt
     hint_html: "<strong>Tip:</strong> Du bliver ikke anmodet om din adgangskode igen den næste time."
diff --git a/config/locales/de.yml b/config/locales/de.yml
index 71959fc86..9b9d9eea6 100644
--- a/config/locales/de.yml
+++ b/config/locales/de.yml
@@ -1060,18 +1060,6 @@ de:
       view_strikes: Vorherige Verstöße deines Kontos ansehen
     too_fast: Formular zu schnell übermittelt. Bitte versuche es erneut.
     use_security_key: Sicherheitsschlüssel verwenden
-  authorize_follow:
-    already_following: Du folgst diesem Konto bereits
-    already_requested: Du hast bereits eine Anfrage zum Folgen an dieses Konto gestellt
-    error: Bedauerlicherweise konnte das externe Konto nicht geladen werden
-    follow: Folgen
-    follow_request: 'Du hast eine Anfrage zum Folgen gestellt an:'
-    following: 'Erfolg! Du folgst nun:'
-    post_follow:
-      close: Oder du schließt einfach dieses Fenster.
-      return: Profil anzeigen
-      web: Im Webinterface öffnen
-    title: "%{acct} folgen"
   challenge:
     confirm: Fortfahren
     hint_html: "<strong>Hinweis:</strong> Wir werden dich für die nächste Stunde nicht erneut nach deinem Passwort fragen."
diff --git a/config/locales/el.yml b/config/locales/el.yml
index e6f30aa10..c4c3d3939 100644
--- a/config/locales/el.yml
+++ b/config/locales/el.yml
@@ -1039,18 +1039,6 @@ el:
       view_strikes: Προβολή προηγούμενων ποινών εναντίον του λογαριασμού σας
     too_fast: Η φόρμα υποβλήθηκε πολύ γρήγορα, προσπαθήστε ξανά.
     use_security_key: Χρήση κλειδιού ασφαλείας
-  authorize_follow:
-    already_following: Ήδη ακολουθείς αυτό το λογαριασμό
-    already_requested: Έχετε ήδη στείλει ένα αίτημα ακολούθησης σε αυτόν τον λογαριασμό
-    error: Δυστυχώς παρουσιάστηκε ένα σφάλμα κατά την αναζήτηση του απομακρυσμένου λογαριασμού
-    follow: Ακολούθησε
-    follow_request: 'Έστειλες αίτημα παρακολούθησης προς:'
-    following: 'Επιτυχία! Πλέον ακολουθείς τον/την:'
-    post_follow:
-      close: Ή, μπορείς απλά να κλείσεις αυτό το παράθυρο.
-      return: Δείξε το προφίλ του χρήστη
-      web: Πήγαινε στο δίκτυο
-    title: Ακολούθησε %{acct}
   challenge:
     confirm: Συνέχεια
     hint_html: "<strong>Συμβουλή:</strong> Δεν θα σου ζητήσουμε τον κωδικό ασφαλείας σου ξανά για την επόμενη ώρα."
diff --git a/config/locales/en-GB.yml b/config/locales/en-GB.yml
index 1df3dc3a9..9ae8e8540 100644
--- a/config/locales/en-GB.yml
+++ b/config/locales/en-GB.yml
@@ -1060,18 +1060,6 @@ en-GB:
       view_strikes: View past strikes against your account
     too_fast: Form submitted too fast, try again.
     use_security_key: Use security key
-  authorize_follow:
-    already_following: You are already following this account
-    already_requested: You have already sent a follow request to that account
-    error: Unfortunately, there was an error looking up the remote account
-    follow: Follow
-    follow_request: 'You have sent a follow request to:'
-    following: 'Success! You are now following:'
-    post_follow:
-      close: Or, you can just close this window.
-      return: Show the user's profile
-      web: Go to web
-    title: Follow %{acct}
   challenge:
     confirm: Continue
     hint_html: "<strong>Tip:</strong> We won't ask you for your password again for the next hour."
diff --git a/config/locales/en.yml b/config/locales/en.yml
index 10b6867af..7c14b89b9 100644
--- a/config/locales/en.yml
+++ b/config/locales/en.yml
@@ -1060,18 +1060,6 @@ en:
       view_strikes: View past strikes against your account
     too_fast: Form submitted too fast, try again.
     use_security_key: Use security key
-  authorize_follow:
-    already_following: You are already following this account
-    already_requested: You have already sent a follow request to that account
-    error: Unfortunately, there was an error looking up the remote account
-    follow: Follow
-    follow_request: 'You have sent a follow request to:'
-    following: 'Success! You are now following:'
-    post_follow:
-      close: Or, you can just close this window.
-      return: Show the user's profile
-      web: Go to web
-    title: Follow %{acct}
   challenge:
     confirm: Continue
     hint_html: "<strong>Tip:</strong> We won't ask you for your password again for the next hour."
diff --git a/config/locales/eo.yml b/config/locales/eo.yml
index b513bcc00..245771b8e 100644
--- a/config/locales/eo.yml
+++ b/config/locales/eo.yml
@@ -1056,18 +1056,6 @@ eo:
       view_strikes: Vidi antauaj admonoj kontra via konto
     too_fast: Formularo sendita tro rapide, klopodu denove.
     use_security_key: Uzi sekurecan ŝlosilon
-  authorize_follow:
-    already_following: Vi jam sekvas tiun konton
-    already_requested: Vi jam sendis peton de sekvado al ĉi tiu konto
-    error: Bedaŭrinde, estis eraro en la serĉado de la fora konto
-    follow: Sekvi
-    follow_request: 'Vi sendis peton de sekvado al:'
-    following: 'Sukceson! Vi nun sekvas:'
-    post_follow:
-      close: Aŭ, vi povas simple fermi ĉi tiun fenestron.
-      return: Montri la profilon de la uzanto
-      web: Iri al reto
-    title: Sekvi %{acct}
   challenge:
     confirm: Daŭrigi
     hint_html: "<strong>Konsileto:</strong> Ni ne demandos pri via pasvorto ĝis 1 horo."
diff --git a/config/locales/es-AR.yml b/config/locales/es-AR.yml
index 1cf60173e..bcbde8f65 100644
--- a/config/locales/es-AR.yml
+++ b/config/locales/es-AR.yml
@@ -1060,18 +1060,6 @@ es-AR:
       view_strikes: Ver incumplimientos pasados contra tu cuenta
     too_fast: Formulario enviado demasiado rápido, probá de nuevo.
     use_security_key: Usar la llave de seguridad
-  authorize_follow:
-    already_following: Ya estás siguiendo a esta cuenta
-    already_requested: Ya enviaste una solicitud de seguimiento a esa cuenta
-    error: Lamentablemente, ocurrió un error buscando la cuenta remota
-    follow: Seguir
-    follow_request: 'Enviaste una solicitud de seguimiento a:'
-    following: "¡Listo! Ahora estás siguiendo a:"
-    post_follow:
-      close: O simplemente podés cerrar esta ventana.
-      return: Mostrar el perfil del usuario
-      web: Ir a la web
-    title: Seguir a %{acct}
   challenge:
     confirm: Continuar
     hint_html: "<strong>Dato:</strong> No volveremos a preguntarte por la contraseña durante la siguiente hora."
diff --git a/config/locales/es-MX.yml b/config/locales/es-MX.yml
index 21079be0b..c05d4d242 100644
--- a/config/locales/es-MX.yml
+++ b/config/locales/es-MX.yml
@@ -1060,18 +1060,6 @@ es-MX:
       view_strikes: Ver amonestaciones pasadas contra tu cuenta
     too_fast: Formulario enviado demasiado rápido, inténtelo de nuevo.
     use_security_key: Usar la clave de seguridad
-  authorize_follow:
-    already_following: Ya estás siguiendo a esta cuenta
-    already_requested: Ya has enviado una solicitud de seguimiento a esa cuenta
-    error: Desafortunadamente, ha ocurrido un error buscando la cuenta remota
-    follow: Seguir
-    follow_request: 'Tienes una solicitud de seguimiento de:'
-    following: "¡Éxito! Ahora estás siguiendo a:"
-    post_follow:
-      close: O, puedes simplemente cerrar esta ventana.
-      return: Regresar al perfil del usuario
-      web: Ir al sitio web
-    title: Seguir a %{acct}
   challenge:
     confirm: Continuar
     hint_html: "<strong>Tip:</strong> No volveremos a preguntarte por la contraseña durante la siguiente hora."
diff --git a/config/locales/es.yml b/config/locales/es.yml
index f782f8fba..8bb99c42e 100644
--- a/config/locales/es.yml
+++ b/config/locales/es.yml
@@ -1060,18 +1060,6 @@ es:
       view_strikes: Ver amonestaciones pasadas contra tu cuenta
     too_fast: Formulario enviado demasiado rápido, inténtelo de nuevo.
     use_security_key: Usar la clave de seguridad
-  authorize_follow:
-    already_following: Ya estás siguiendo a esta cuenta
-    already_requested: Ya has enviado una solicitud de seguimiento a esa cuenta
-    error: Desafortunadamente, ha ocurrido un error buscando la cuenta remota
-    follow: Seguir
-    follow_request: 'Tienes una solicitud de seguimiento de:'
-    following: "¡Éxito! Ahora estás siguiendo a:"
-    post_follow:
-      close: O, puedes simplemente cerrar esta ventana.
-      return: Regresar al perfil del usuario
-      web: Ir al sitio web
-    title: Seguir a %{acct}
   challenge:
     confirm: Continuar
     hint_html: "<strong>Tip:</strong> No volveremos a preguntarte por la contraseña durante la siguiente hora."
diff --git a/config/locales/et.yml b/config/locales/et.yml
index d4ba300e7..9d9fa45c4 100644
--- a/config/locales/et.yml
+++ b/config/locales/et.yml
@@ -1060,18 +1060,6 @@ et:
       view_strikes: Vaata enda eelnevaid juhtumeid
     too_fast: Vorm esitatud liiga kiirelt, proovi uuesti.
     use_security_key: Kasuta turvavõtit
-  authorize_follow:
-    already_following: Juba jälgid seda kontot
-    already_requested: Saatsid juba sellele kontole jälgimistaotluse
-    error: Kahjuks ilmus viga kasutaja kaugserverist otsimisel
-    follow: Jälgi
-    follow_request: 'Oled saatnud jälgimistaotluse kasutajale:'
-    following: 'Õnnestus! Jälgid nüüd kasutajat:'
-    post_follow:
-      close: Või sulge lihtsalt see aken.
-      return: Näita kasutaja profiili
-      web: Mine veebi
-    title: Jälgi %{acct}
   challenge:
     confirm: Jätka
     hint_html: "<strong>Nõuanne:</strong> Me ei küsi salasõna uuesti järgmise tunni jooksul."
diff --git a/config/locales/eu.yml b/config/locales/eu.yml
index 13563f80a..0fe1a8d3d 100644
--- a/config/locales/eu.yml
+++ b/config/locales/eu.yml
@@ -1051,18 +1051,6 @@ eu:
       view_strikes: Ikusi zure kontuaren aurkako neurriak
     too_fast: Formularioa azkarregi bidali duzu, saiatu berriro.
     use_security_key: Erabili segurtasun gakoa
-  authorize_follow:
-    already_following: Kontu hau aurretik jarraitzen duzu
-    already_requested: Bidali duzu dagoeneko kontu hori jarraitzeko eskaera bat
-    error: Zoritxarrez, urruneko kontua bilatzean errore bat gertatu da
-    follow: Jarraitu
-    follow_request: 'Jarraitzeko eskari bat bidali duzu hona:'
-    following: 'Ongi! Orain jarraitzen duzu:'
-    post_follow:
-      close: Edo, leiho hau besterik gabe itxi dezakezu.
-      return: Erakutsi erabiltzailearen profila
-      web: Joan webera
-    title: Jarraitu %{acct}
   challenge:
     confirm: Jarraitu
     hint_html: "<strong>Oharra:</strong> Ez dizugu pasahitza berriro eskatuko ordu batez."
diff --git a/config/locales/fa.yml b/config/locales/fa.yml
index 9f1c83b4e..f5ba91e1f 100644
--- a/config/locales/fa.yml
+++ b/config/locales/fa.yml
@@ -889,18 +889,6 @@ fa:
       view_strikes: دیدن شکایت‌های گذشته از حسابتان
     too_fast: فرم با سرعت بسیار زیادی فرستاده شد، دوباره تلاش کنید.
     use_security_key: استفاده از کلید امنیتی
-  authorize_follow:
-    already_following: شما همین الان هم این حساب را پی‌می‌گیرید
-    already_requested: درخواست پی‌گیری‌ای برای آن حساب فرستاده‌ بودید
-    error: متأسفانه حین یافتن آن حساب خطایی رخ داد
-    follow: پی بگیرید
-    follow_request: 'شما درخواست پیگیری فرستاده‌اید به:'
-    following: 'انجام شد! شما هم‌اینک پیگیر این کاربر هستید:'
-    post_follow:
-      close: یا این پنجره را ببندید.
-      return: نمایهٔ این کاربر را نشان بده
-      web: رفتن به وب
-    title: پیگیری %{acct}
   challenge:
     confirm: ادامه
     hint_html: "<strong>نکته:</strong> ما در یک ساعت آینده گذرواژه‌تان را از شما نخواهیم پرسید."
diff --git a/config/locales/fi.yml b/config/locales/fi.yml
index 67627ec69..9fa0d51d7 100644
--- a/config/locales/fi.yml
+++ b/config/locales/fi.yml
@@ -1060,18 +1060,6 @@ fi:
       view_strikes: Näytä tiliäsi koskevia aiempia varoituksia
     too_fast: Lomake lähetettiin liian nopeasti, yritä uudelleen.
     use_security_key: Käytä suojausavainta
-  authorize_follow:
-    already_following: Sinä seuraat jo tätä tiliä
-    already_requested: Olet jo lähettänyt seurantapyynnön tälle tilille
-    error: Valitettavasti etätilin haussa tapahtui virhe
-    follow: Seuraa
-    follow_request: 'Olet lähettänyt seuraamispyynnön käyttäjälle:'
-    following: 'Onnistui! Seuraat käyttäjää:'
-    post_follow:
-      close: Tai voit sulkea tämän ikkunan.
-      return: Palaa käyttäjän profiiliin
-      web: Siirry verkkosivulle
-    title: Seuraa käyttäjää %{acct}
   challenge:
     confirm: Jatka
     hint_html: "<strong>Vihje:</strong> Emme pyydä sinulta salasanaa uudelleen seuraavan tunnin aikana."
diff --git a/config/locales/fo.yml b/config/locales/fo.yml
index d2567feeb..872c25824 100644
--- a/config/locales/fo.yml
+++ b/config/locales/fo.yml
@@ -1060,18 +1060,6 @@ fo:
       view_strikes: Vís eldri atsóknir móti tíni kontu
     too_fast: Oyðublaðið innsent ov skjótt, royn aftur.
     use_security_key: Brúka trygdarlykil
-  authorize_follow:
-    already_following: Tú fylgir longu hesi kontuni
-    already_requested: Tú hevur longu sent eina fylgiumbøn til hasa kontuna
-    error: Tíverri kom ein feilur, tá vit royndu at finna fjarkontuna
-    follow: Fylg
-    follow_request: 'Tú hevur sent eina fylgjaraumbøn til:'
-    following: 'Góðkent! Tú fylgir nú:'
-    post_follow:
-      close: Ella kanst tú bara lata hetta vindeygað aftur.
-      return: Vís vangan hjá brúkaranum
-      web: Far á vevið
-    title: Fylg %{acct}
   challenge:
     confirm: Hald á
     hint_html: "<strong>Góð ráð:</strong> vit spyrja teg ikki aftur um loyniorðið næsta tíman."
diff --git a/config/locales/fr-QC.yml b/config/locales/fr-QC.yml
index 7ebb4406e..c7e69ca96 100644
--- a/config/locales/fr-QC.yml
+++ b/config/locales/fr-QC.yml
@@ -1060,18 +1060,6 @@ fr-QC:
       view_strikes: Voir les sanctions précédemment appliquées à votre compte
     too_fast: Formulaire envoyé trop rapidement, veuillez réessayer.
     use_security_key: Utiliser la clé de sécurité
-  authorize_follow:
-    already_following: Vous suivez déjà ce compte
-    already_requested: Vous avez déjà envoyé une demande d’abonnement à ce compte
-    error: Malheureusement, une erreur s'est produite lors de la recherche du compte distant
-    follow: Suivre
-    follow_request: 'Vous avez demandé à suivre :'
-    following: 'Youpi ! Vous suivez maintenant  :'
-    post_follow:
-      close: Ou bien, vous pouvez fermer cette fenêtre.
-      return: Afficher le profil de l’utilisateur·ice
-      web: Retour à l’interface web
-    title: Suivre %{acct}
   challenge:
     confirm: Continuer
     hint_html: "<strong>Astuce :</strong> Nous ne vous demanderons plus votre mot de passe pour la prochaine heure."
diff --git a/config/locales/fr.yml b/config/locales/fr.yml
index 7631140d1..61f641046 100644
--- a/config/locales/fr.yml
+++ b/config/locales/fr.yml
@@ -1060,18 +1060,6 @@ fr:
       view_strikes: Voir les sanctions précédemment appliquées à votre compte
     too_fast: Formulaire envoyé trop rapidement, veuillez réessayer.
     use_security_key: Utiliser la clé de sécurité
-  authorize_follow:
-    already_following: Vous suivez déjà ce compte
-    already_requested: Vous avez déjà envoyé une demande d’abonnement à ce compte
-    error: Malheureusement, une erreur s'est produite lors de la recherche du compte distant
-    follow: Suivre
-    follow_request: 'Vous avez demandé à suivre :'
-    following: 'Youpi ! Vous suivez maintenant  :'
-    post_follow:
-      close: Ou bien, vous pouvez fermer cette fenêtre.
-      return: Afficher le profil de l’utilisateur·ice
-      web: Retour à l’interface web
-    title: Suivre %{acct}
   challenge:
     confirm: Continuer
     hint_html: "<strong>Astuce :</strong> Nous ne vous demanderons plus votre mot de passe pour la prochaine heure."
diff --git a/config/locales/fy.yml b/config/locales/fy.yml
index 62d41663f..d3279a65b 100644
--- a/config/locales/fy.yml
+++ b/config/locales/fy.yml
@@ -1060,18 +1060,6 @@ fy:
       view_strikes: Besjoch de earder troch moderatoaren fêststelde skeiningen dy’t jo makke hawwe
     too_fast: Formulier is te fluch yntsjinne. Probearje it nochris.
     use_security_key: Befeiligingskaai brûke
-  authorize_follow:
-    already_following: Jo folgje dizze account al
-    already_requested: Jo hawwe al in folchfersyk nei dat account ferstjoerd
-    error: Spitiger, der is in flater bard by it opsykjen fan de eksterne account
-    follow: Folgje
-    follow_request: 'Jo hawwe in folchfersyk yntsjinne by:'
-    following: 'Slagge! Jo folgje no:'
-    post_follow:
-      close: Of jo kinne dit finster gewoan slute.
-      return: Profyl fan dizze brûker toane
-      web: Gean nei de webapp
-    title: "%{acct} folgje"
   challenge:
     confirm: Trochgean
     hint_html: "<strong>Tip:</strong> Wy freegje jo it kommende oere net mear nei jo wachtwurd."
diff --git a/config/locales/ga.yml b/config/locales/ga.yml
index acb0868cf..f1861d69d 100644
--- a/config/locales/ga.yml
+++ b/config/locales/ga.yml
@@ -331,11 +331,6 @@ ga:
     status:
       account_status: Stádas cuntais
     too_fast: Cuireadh an fhoirm isteach róthapa, triail arís.
-  authorize_follow:
-    follow: Lean
-    post_follow:
-      return: Taispeáin próifíl an úsáideora
-    title: Lean %{acct}
   challenge:
     confirm: Lean ar aghaidh
   datetime:
diff --git a/config/locales/gd.yml b/config/locales/gd.yml
index fe25bf518..0ce2c4c30 100644
--- a/config/locales/gd.yml
+++ b/config/locales/gd.yml
@@ -1095,18 +1095,6 @@ gd:
       view_strikes: Seall na rabhaidhean a fhuair an cunntas agad roimhe
     too_fast: Chaidh am foirm a chur a-null ro luath, feuch ris a-rithist.
     use_security_key: Cleachd iuchair tèarainteachd
-  authorize_follow:
-    already_following: Tha thu a’ leantainn a’ chunntais seo mu thràth
-    already_requested: Chuir thu iarrtas leantainn dhan chunntas seo mu thràth
-    error: Gu mì-fhortanach, thachair mearachd le lorg a’ chunntais chèin
-    follow: Lean
-    follow_request: 'Chuir thu iarrtas leantainn gu:'
-    following: 'Taghta! Chaidh leat a’ leantainn:'
-    post_follow:
-      close: Air neo dùin an uinneag seo.
-      return: Seall pròifil a’ chleachdaiche
-      web: Tadhail air an duilleag-lìn
-    title: Lean %{acct}
   challenge:
     confirm: Lean air adhart
     hint_html: "<strong>Gliocas:</strong> Chan iarr sinn am facal-faire agad ort a-rithist fad uair a thìde."
diff --git a/config/locales/gl.yml b/config/locales/gl.yml
index 08de22b1b..f3a4647cf 100644
--- a/config/locales/gl.yml
+++ b/config/locales/gl.yml
@@ -1060,18 +1060,6 @@ gl:
       view_strikes: Ver avisos anteriores respecto da túa conta
     too_fast: Formulario enviado demasiado rápido, inténtao outra vez.
     use_security_key: Usa chave de seguridade
-  authorize_follow:
-    already_following: Xa está a seguir esta conta
-    already_requested: Xa tes enviada unha solicitude de seguimento a esa conta
-    error: Desgraciadamente, algo fallou ao buscar a conta remota
-    follow: Seguir
-    follow_request: 'Enviaches unha petición de seguimento a:'
-    following: 'Parabéns! Agora segues a:'
-    post_follow:
-      close: Ou, podes pechar esta ventá.
-      return: Mostrar o perfil da usuaria
-      web: Ir á web
-    title: Seguir %{acct}
   challenge:
     confirm: Continuar
     hint_html: "<strong>Nota:</strong> Non che pediremos o contrasinal na seguinte hora."
diff --git a/config/locales/he.yml b/config/locales/he.yml
index b29f2ab26..ef3345335 100644
--- a/config/locales/he.yml
+++ b/config/locales/he.yml
@@ -1096,18 +1096,6 @@ he:
       view_strikes: צפיה בעברות קודמות שנרשמו נגד חשבונך
     too_fast: הטופס הוגש מהר מדי, נסה/י שוב.
     use_security_key: שימוש במפתח אבטחה
-  authorize_follow:
-    already_following: את/ה כבר עוקב/ת אחרי חשבון זה
-    already_requested: כבר נשלחה בקשת מעקב לחשבון זה
-    error: למרבה הצער, היתה שגיאה בחיפוש החשבון המרוחק
-    follow: לעקוב
-    follow_request: 'שלחת בקשת מעקב ל:'
-    following: 'הצלחה! הינך עוקב עכשיו אחרי:'
-    post_follow:
-      close: או, פשוט לסגור חלון זה.
-      return: הצג את פרופיל המשתמש
-      web: מעבר לווב
-    title: לעקוב אחרי %{acct}
   challenge:
     confirm: המשך
     hint_html: "<strong>טיפ:</strong> לא נבקש את סיסמתך שוב בשעה הקרובה."
diff --git a/config/locales/hr.yml b/config/locales/hr.yml
index a35c8efc6..4c300c204 100644
--- a/config/locales/hr.yml
+++ b/config/locales/hr.yml
@@ -64,10 +64,6 @@ hr:
     reset_password: Ponovno postavi lozinku
     security: Sigurnost
     set_new_password: Postavi novu lozinku
-  authorize_follow:
-    error: Nažalost, došlo je do greške tijekom traženja udaljenog računa
-    follow: Prati
-    title: Prati %{acct}
   datetime:
     distance_in_words:
       about_x_months: "%{count}mj"
diff --git a/config/locales/hu.yml b/config/locales/hu.yml
index a629508fb..b4cfde590 100644
--- a/config/locales/hu.yml
+++ b/config/locales/hu.yml
@@ -1060,18 +1060,6 @@ hu:
       view_strikes: Fiókod ellen felrótt korábbi vétségek megtekintése
     too_fast: Túl gyorsan küldted el az űrlapot, próbáld később.
     use_security_key: Biztonsági kulcs használata
-  authorize_follow:
-    already_following: Már követed ezt a felhasználót
-    already_requested: Már küldtél követési kérelmet ennek a fióknak
-    error: Hiba történt a távoli felhasználó keresésekor
-    follow: Követés
-    follow_request: 'Engedélyt kértél az alábbi felhasználó követésére:'
-    following: 'Siker! Mostantól követed az alábbi felhasználót:'
-    post_follow:
-      close: Akár be is zárhatod ezt az ablakot.
-      return: A felhasználó profiljának mutatása
-      web: Megtekintés a weben
-    title: "%{acct} követése"
   challenge:
     confirm: Folytatás
     hint_html: "<strong>Hasznos:</strong> Nem fogjuk megint a jelszavadat kérdezni a következő órában."
diff --git a/config/locales/hy.yml b/config/locales/hy.yml
index fdbba50e9..a3854671e 100644
--- a/config/locales/hy.yml
+++ b/config/locales/hy.yml
@@ -481,17 +481,6 @@ hy:
       account_status: Հաշուի կարգավիճակ
       pending: Դիմումը պէտք է քննուի մեր անձնակազմի կողմից, ինչը կարող է մի փոքր ժամանակ խլել։ Դիմումի հաստատուելու դէպքում, կտեղեկացնենք նամակով։
     use_security_key: Օգտագործել անվտանգութեան բանալի
-  authorize_follow:
-    already_following: Դու արդէն հետեւում ես այս հաշուին
-    already_requested: Դու արդէն ուղարկել ես հետեւմանն յայտ այս հաշուին
-    follow: Հետևել
-    follow_request: Դու ուղարկել ես հետեւելու հայց՝
-    following: Յաջողութի՜ւն։ Դու այժմ հետեւում ես․
-    post_follow:
-      close: Կամ, կարող ես պարզապէս փակել այս պատուհանը։
-      return: Ցուցադրել օգտատիրոջ էջը
-      web: Անցնել վէբին
-    title: Հետեւել %{acct}
   challenge:
     confirm: Շարունակել
     invalid_password: Անվաւեր ծածկագիր
diff --git a/config/locales/id.yml b/config/locales/id.yml
index df8be30af..0e8f2b9b0 100644
--- a/config/locales/id.yml
+++ b/config/locales/id.yml
@@ -959,18 +959,6 @@ id:
       view_strikes: Lihat hukuman lalu yang pernah terjadi kepada akun Anda
     too_fast: Formulir dikirim terlalu cepat, coba lagi.
     use_security_key: Gunakan kunci keamanan
-  authorize_follow:
-    already_following: Anda sudah mengikuti akun ini
-    already_requested: Anda sudah mengirimkan permintaan untuk mengikuti akun tersebut
-    error: Sayangnya, ada error saat melihat akun remote
-    follow: Ikuti
-    follow_request: 'Anda telah mengirim permintaan untuk mengikuti ke:'
-    following: 'Berhasil! Anda sekarang mengikuti:'
-    post_follow:
-      close: Atau Anda dapat menutup jendela ini.
-      return: Tampilkan profil pengguna
-      web: Ke web
-    title: Mengikuti %{acct}
   challenge:
     confirm: Lanjut
     hint_html: "<strong>Tip:</strong> Kami tidak akan meminta kata sandi Anda lagi untuk beberapa jam ke depan."
diff --git a/config/locales/io.yml b/config/locales/io.yml
index 805ecffe1..d09dfed70 100644
--- a/config/locales/io.yml
+++ b/config/locales/io.yml
@@ -935,18 +935,6 @@ io:
       view_strikes: Videz antea streki kontre vua konto
     too_fast: Formulario sendesis tro rapide, probez itere.
     use_security_key: Uzes sekuresklefo
-  authorize_follow:
-    already_following: Vu ja sequis ca konto
-    already_requested: Vu ja sendis sequodemando a ta konto
-    error: Regretinde, eventis eraro probante konsultar la fora konto
-    follow: Sequar
-    follow_request: 'Vu sendis sequodemando a:'
-    following: 'Suceso! Vu nun sequas:'
-    post_follow:
-      close: O, vu volas jus klozar ca panelo.
-      return: Montrez priflo de uzanti
-      web: Irez a interreto
-    title: Sequar %{acct}
   challenge:
     confirm: Durez
     hint_html: "<strong>Guidilo:</strong> Ni ne demandos vua pasvorto itere til 1 horo."
diff --git a/config/locales/is.yml b/config/locales/is.yml
index 625453c94..346eeeb56 100644
--- a/config/locales/is.yml
+++ b/config/locales/is.yml
@@ -1064,18 +1064,6 @@ is:
       view_strikes: Skoða fyrri bönn notandaaðgangsins þíns
     too_fast: Innfyllingarform sent inn of hratt, prófaðu aftur.
     use_security_key: Nota öryggislykil
-  authorize_follow:
-    already_following: Þú ert að þegar fylgjast með þessum aðgangi
-    already_requested: Þú ert þegar búin/n að senda fylgjendabeiðni á þennan notanda
-    error: Því miður, það kom upp villa við að fletta upp fjartengda notandaaðgangnum
-    follow: Fylgjast með
-    follow_request: 'Þú sendir beiðni um að fylgjast með til:'
-    following: 'Tókst! Þú ert núna að fylgjast með:'
-    post_follow:
-      close: Eða að þú getur lokað þessum glugga.
-      return: Birta notandasnið notandans
-      web: Fara á vefinn
-    title: Fylgjast með %{acct}
   challenge:
     confirm: Halda áfram
     hint_html: "<strong>Ábending:</strong> Við munum ekki spyrja þig um lykilorðið aftur næstu klukkustundina."
diff --git a/config/locales/it.yml b/config/locales/it.yml
index c678741fd..950e5eca3 100644
--- a/config/locales/it.yml
+++ b/config/locales/it.yml
@@ -1062,18 +1062,6 @@ it:
       view_strikes: Visualizza le sanzioni precedenti prese nei confronti del tuo account
     too_fast: Modulo inviato troppo velocemente, riprova.
     use_security_key: Usa la chiave di sicurezza
-  authorize_follow:
-    already_following: Stai già seguendo questo account
-    already_requested: Hai già mandato una richiesta di seguire questo account
-    error: Sfortunatamente c'è stato un errore nel consultare l'account remoto
-    follow: Segui
-    follow_request: 'Hai mandato una richiesta di seguire:'
-    following: 'Accettato! Ora stai seguendo:'
-    post_follow:
-      close: Oppure puoi chiudere questa finestra.
-      return: Mostra il profilo dell'utente
-      web: Vai al web
-    title: Segui %{acct}
   challenge:
     confirm: Continua
     hint_html: "<strong>Suggerimento:</strong> Non ti chiederemo di nuovo la tua password per la prossima ora."
diff --git a/config/locales/ja.yml b/config/locales/ja.yml
index 38f675470..e56e131e7 100644
--- a/config/locales/ja.yml
+++ b/config/locales/ja.yml
@@ -1042,18 +1042,6 @@ ja:
       view_strikes: 過去のストライクを表示
     too_fast: フォームの送信が速すぎます。もう一度やり直してください。
     use_security_key: セキュリティキーを使用
-  authorize_follow:
-    already_following: あなたは既にこのアカウントをフォローしています
-    already_requested: 既にこのアカウントへフォローリクエストを送信しています
-    error: 残念ながら、リモートアカウント情報の取得中にエラーが発生しました
-    follow: フォロー
-    follow_request: 'あなたは以下のアカウントにフォローリクエストを送信しました:'
-    following: '成功! あなたは現在以下のアカウントをフォローしています:'
-    post_follow:
-      close: またはこのウィンドウを閉じます。
-      return: ユーザーのプロフィールを見る
-      web: Webを開く
-    title: "%{acct}さんをフォロー"
   challenge:
     confirm: 続ける
     hint_html: 以後1時間はパスワードの再入力を求めません
diff --git a/config/locales/ka.yml b/config/locales/ka.yml
index 59e412b90..9d7b5ddf0 100644
--- a/config/locales/ka.yml
+++ b/config/locales/ka.yml
@@ -232,17 +232,6 @@ ka:
     reset_password: პაროლის გადატვირთვა
     security: უსაფრთხოება
     set_new_password: ახალი პაროლის დაყენება
-  authorize_follow:
-    already_following: უკვე მიჰყვებით ამ ანგარიშს
-    error: სამწუხაროთ, დისტანციური სერვერის წაკითხვამ გამოიწვია შეცდომა
-    follow: გაყევი
-    follow_request: 'დადევნების მოთხონვა გაეგზავნა:'
-    following: 'წარმატება! ახლა მიჰყვებით:'
-    post_follow:
-      close: ან შეგიძლიათ დახუროთ ეს ფანჯარა.
-      return: მომხმარებლის პროფილის ჩვენება
-      web: ვებზე გადასვლა
-    title: გაყევი %{acct}-ს
   datetime:
     distance_in_words:
       about_x_hours: "%{count}სთ"
diff --git a/config/locales/kab.yml b/config/locales/kab.yml
index f9884e4e7..422346703 100644
--- a/config/locales/kab.yml
+++ b/config/locales/kab.yml
@@ -461,14 +461,6 @@ kab:
     status:
       account_status: Addad n umiḍan
     use_security_key: Seqdec tasarut n teɣlist
-  authorize_follow:
-    already_following: Teṭafareḍ ya kan amiḍan-a
-    follow: Ḍfeṛ
-    following: 'Igerrez! Aqlik teṭafareḍ tura:'
-    post_follow:
-      return: Ssken-d amaɣnu n useqdac
-      web: Ddu γer Web
-    title: Ḍfeṛ %{acct}
   challenge:
     confirm: Kemmel
     invalid_password: Yir awal uffir
diff --git a/config/locales/kk.yml b/config/locales/kk.yml
index d891dfa37..98fe37f29 100644
--- a/config/locales/kk.yml
+++ b/config/locales/kk.yml
@@ -360,17 +360,6 @@ kk:
       confirming: Электрондық поштаны растау аяқталуын күтуде.
       pending: Сіздің өтінішіңіз біздің қызметкерлеріміздің қарауында. Бұл біраз уақыт алуы мүмкін. Өтінішіңіз мақұлданса, сізге электрондық пошта хабарламасы келеді.
       redirecting_to: Сіздің есептік жазбаңыз белсенді емес, себебі ол %{acct} жүйесіне қайта бағытталуда.
-  authorize_follow:
-    already_following: Бұл аккаунтқа жазылғансыз
-    error: Өкінішке орай, қашықтағы тіркелгіні іздеуде қате пайда болды
-    follow: Жазылу
-    follow_request: 'Сіз жазылуға өтініш жібердіңіз:'
-    following: 'Керемет! Сіз енді жазылдыңыз:'
-    post_follow:
-      close: Немесе терезені жаба салыңыз.
-      return: Қолданушы профилін көрсет
-      web: Вебте ашу
-    title: Жазылу %{acct}
   challenge:
     confirm: Жалғастыру
     hint_html: "<strong> Кеңес: </strong> біз келесі сағат ішінде сізден құпия сөзді қайта сұрамаймыз."
diff --git a/config/locales/ko.yml b/config/locales/ko.yml
index 9386ff901..fe195ee09 100644
--- a/config/locales/ko.yml
+++ b/config/locales/ko.yml
@@ -1044,18 +1044,6 @@ ko:
       view_strikes: 내 계정에 대한 과거 중재 기록 보기
     too_fast: 너무 빠르게 양식이 제출되었습니다, 다시 시도하세요.
     use_security_key: 보안 키 사용
-  authorize_follow:
-    already_following: 이미 이 계정을 팔로우 하고 있습니다
-    already_requested: 이미 이 계정에게 팔로우 요청을 보냈습니다
-    error: 리모트 계정을 확인하는 도중 오류가 발생했습니다
-    follow: 팔로우
-    follow_request: '팔로우 요청을 보냄:'
-    following: '성공! 당신은 다음 계정을 팔로우 하고 있습니다:'
-    post_follow:
-      close: 혹은, 그저 이 창을 닫을 수도 있습니다.
-      return: 사용자 프로필 보기
-      web: 웹으로 가기
-    title: "%{acct} 를 팔로우"
   challenge:
     confirm: 계속
     hint_html: "<strong>팁:</strong> 한 시간 동안 다시 암호를 묻지 않을 것입니다."
diff --git a/config/locales/ku.yml b/config/locales/ku.yml
index d35d0de27..58c1885df 100644
--- a/config/locales/ku.yml
+++ b/config/locales/ku.yml
@@ -979,18 +979,6 @@ ku:
       view_strikes: Binpêkirinên berê yên dijî ajimêrê xwe bibîne
     too_fast: Form pir zû hat şandin, dîsa biceribîne.
     use_security_key: Kilîteke ewlehiyê bi kar bîne
-  authorize_follow:
-    already_following: Jixwe tu vê ajimêrê dişopînî
-    already_requested: Jixwe te ji vê ajimêrê re daxwazîya şopandinê şandi bû
-    error: Mixabin, dema ajimêr hat gerandin çewtiyek çêbû
-    follow: Bişopîne
-    follow_request: 'Te ji vê kesê re daxwazîya şopandinê şand:'
-    following: 'Serkeftin! Tu êdî dikarî bişopînî:'
-    post_follow:
-      close: An jî, tu dikarî tenê ev çarçoveyê bigirî.
-      return: Profîla vê bikarhênerê nîşan bike
-      web: Biçe tevneyê
-    title: "%{acct} bişopîne"
   challenge:
     confirm: Bidomîne
     hint_html: "<strong>Nîşe:</strong>Ji bo demjimêreke din em ê borînpeyva te careke din ji te nexwazin."
diff --git a/config/locales/lt.yml b/config/locales/lt.yml
index 8732d3f2b..74b5f51ee 100644
--- a/config/locales/lt.yml
+++ b/config/locales/lt.yml
@@ -267,17 +267,6 @@ lt:
     reset_password: Atstatyti slaptažodį
     security: Apsauga
     set_new_password: Nustatyti naują slaptažodį
-  authorize_follow:
-    already_following: Jūs jau sekate šią paskyrą
-    error: Dėja, aptikta klaida ieškant tolimosios paskyros
-    follow: Sekti
-    follow_request: 'Jūs išsiuntėte sekimo prašymą:'
-    following: 'Puiku! Jūs pradėjote sekti:'
-    post_follow:
-      close: Arba, Jūs galite uždaryti šį langą.
-      return: Rodyti vartotojo paskyrą
-      web: Eiti į
-    title: Sekti %{acct}
   datetime:
     distance_in_words:
       about_x_hours: "%{count} val"
diff --git a/config/locales/lv.yml b/config/locales/lv.yml
index e184e2171..9d83d5abd 100644
--- a/config/locales/lv.yml
+++ b/config/locales/lv.yml
@@ -1057,18 +1057,6 @@ lv:
       view_strikes: Skati iepriekšējos brīdinājumus par savu kontu
     too_fast: Veidlapa ir iesniegta pārāk ātri, mēģini vēlreiz.
     use_security_key: Lietot drošības atslēgu
-  authorize_follow:
-    already_following: Tu jau seko šim kontam
-    already_requested: Tu jau esi nosūtījis sekošanas pieteikumu šim kontam
-    error: Diemžēl, meklējot attālināto kontu, radās kļūda
-    follow: Sekot
-    follow_request: 'Tu esi nosūtījis sekošanas pieteikumu:'
-    following: 'Veiksmīgi! Tu tagad seko:'
-    post_follow:
-      close: Vai vienkārši aizver šo logu.
-      return: Parādīt lietotāja profilu
-      web: Doties uz tīmekli
-    title: Sekot %{acct}
   challenge:
     confirm: Turpināt
     hint_html: "<strong>Padoms:</strong> Nākamās stundas laikā mēs tev vairs neprasīsim paroli."
diff --git a/config/locales/ml.yml b/config/locales/ml.yml
index 6db786ad9..5f8de5298 100644
--- a/config/locales/ml.yml
+++ b/config/locales/ml.yml
@@ -76,16 +76,6 @@ ml:
     invites:
       filter:
         all: എല്ലാം
-  authorize_follow:
-    following: 'വിജയകരം! നിങ്ങൾ ഇപ്പോൾ പിന്തുടരുന്നു:'
-  errors:
-    '400': The request you submitted was invalid or malformed.
-    '403': You don't have permission to view this page.
-    '404': The page you are looking for isn't here.
-    '406': This page is not available in the requested format.
-    '410': The page you were looking for doesn't exist here anymore.
-    '429': Too many requests
-    '503': The page could not be served due to a temporary server failure.
   filters:
     contexts:
       notifications: അറിയിപ്പുകൾ
diff --git a/config/locales/ms.yml b/config/locales/ms.yml
index 963ee644c..678dbcd76 100644
--- a/config/locales/ms.yml
+++ b/config/locales/ms.yml
@@ -767,14 +767,6 @@ ms:
       account_status: Status akaun
       view_strikes: Lihat pelanggaran yang lepas terhadap akaun anda
     use_security_key: Gunakan kunci keselamatan
-  authorize_follow:
-    follow: Ikut
-    follow_request: 'Anda telah menghantar permintaan mengikut kepada:'
-    post_follow:
-      close: Atau anda boleh tutup tetingkap ini.
-      return: Tunjukkan profil pengguna
-      web: Pergi ke web
-    title: Ikuti %{acct}
   challenge:
     confirm: Teruskan
     invalid_password: Kata laluan tidak sah
diff --git a/config/locales/my.yml b/config/locales/my.yml
index 0d11c30ba..2ce63d272 100644
--- a/config/locales/my.yml
+++ b/config/locales/my.yml
@@ -1042,18 +1042,6 @@ my:
       view_strikes: သင့်အကောင့်ကို ဆန့်ကျင်သည့် ယခင်ကလုပ်ဆောင်ချက်များကို ကြည့်ပါ
     too_fast: ဖောင်တင်သည်မှာ မြန်နေပါသည်။ ထပ်စမ်းကြည့်ပါ။
     use_security_key: လုံခြုံရေးကီးကို သုံးပါ
-  authorize_follow:
-    already_following: သင်သည် ဤအကောင့်ကို စောင့်ကြည့်နေပြီဖြစ်ပါသည်
-    already_requested: သင်သည် ထိုအကောင့်စောင့်ကြည့်ရန် တောင်းဆိုမှုတစ်ခု ပေးပို့ခဲ့ပြီးပါပြီ
-    error: ကံမကောင်းစွာဖြင့် အဝေးမှထိန်းချုပ်သောအကောင့်ရှာဖွေရာတွင် အမှားအယွင်းတစ်ခုရှိခဲ့သည်
-    follow: စောင့်ကြည့်မယ်
-    follow_request: သင်သည် စောင့်ကြည့်မည် တောင်းဆိုချက်တစ်ခု ပေးပို့ထားသည်-
-    following: သင် ယခု အောက်ပါအတိုင်း လုပ်ဆောင်နေပါသည် -
-    post_follow:
-      close: သို့မဟုတ် သင်သည် ဤဝင်းဒိုးကို ပိတ်နိုင်သည်
-      return: အသုံးပြုသူ၏ ပရိုဖိုင်ကိုပြရန်
-      web: ဝဘ်သို့ သွားပါ
-    title: "%{acct} ကို စောင့်ကြည့်မယ်"
   challenge:
     confirm: ဆက်လုပ်မည်
     hint_html: "<strong>အကြံပြုချက် -</strong> နောက်နာရီများတွင် သင့်စကားဝှက်ကို ထပ်မံတောင်းဆိုမည်မဟုတ်ပါ။"
diff --git a/config/locales/nl.yml b/config/locales/nl.yml
index ff562c97c..ab3bcfac6 100644
--- a/config/locales/nl.yml
+++ b/config/locales/nl.yml
@@ -1060,18 +1060,6 @@ nl:
       view_strikes: Bekijk de eerder door moderatoren vastgestelde overtredingen die je hebt gemaakt
     too_fast: Formulier is te snel ingediend. Probeer het nogmaals.
     use_security_key: Beveiligingssleutel gebruiken
-  authorize_follow:
-    already_following: Je volgt dit account al
-    already_requested: Je hebt al een volgverzoek naar dat account verstuurd
-    error: Helaas, er is een fout opgetreden bij het opzoeken van de externe account
-    follow: Volgen
-    follow_request: 'Jij hebt een volgverzoek ingediend bij:'
-    following: 'Succes! Jij volgt nu:'
-    post_follow:
-      close: Of je kunt dit venster gewoon sluiten.
-      return: Profiel van deze gebruiker tonen
-      web: Ga naar de webapp
-    title: Volg %{acct}
   challenge:
     confirm: Doorgaan
     hint_html: "<strong>Tip:</strong> We vragen jou het komende uur niet meer naar jouw wachtwoord."
diff --git a/config/locales/nn.yml b/config/locales/nn.yml
index 78292744b..90616bf86 100644
--- a/config/locales/nn.yml
+++ b/config/locales/nn.yml
@@ -1049,18 +1049,6 @@ nn:
       view_strikes: Vis tidligere advarsler mot kontoen din
     too_fast: Skjemaet ble sendt inn for raskt, prøv på nytt.
     use_security_key: Bruk sikkerhetsnøkkel
-  authorize_follow:
-    already_following: Du fylgjer allereie denne kontoen
-    already_requested: Du har allereie sendt ein fylgjespurnad til den kontoen
-    error: Uheldigvis skjedde det en feil da vi prøvde å få tak i en bruker fra en annen instans
-    follow: Fylg
-    follow_request: 'Du har sendt ein fylgjeførespurnad til:'
-    following: 'Suksess! No fylgjer du:'
-    post_follow:
-      close: Eller så kan du berre lukka att dette vindauget.
-      return: Vis brukarprofilen
-      web: Gå til nettet
-    title: Fylg %{acct}
   challenge:
     confirm: Hald fram
     hint_html: "<strong>Tips:</strong> Vi skal ikkje spørja deg om passordet ditt igjen i laupet av den neste timen."
diff --git a/config/locales/no.yml b/config/locales/no.yml
index 04b5bce72..336c19e3d 100644
--- a/config/locales/no.yml
+++ b/config/locales/no.yml
@@ -988,18 +988,6 @@
       view_strikes: Vis tidligere advarsler mot kontoen din
     too_fast: Skjemaet ble sendt inn for raskt, prøv på nytt.
     use_security_key: Bruk sikkerhetsnøkkel
-  authorize_follow:
-    already_following: Du følger allerede denne kontoen
-    already_requested: Du har allerede sendt en følgeforespørsel til denne kontoen
-    error: Dessverre oppstod det en feil da vi prøvde å få tak i brukeren fra tjeneren
-    follow: Følg
-    follow_request: 'Du har sendt en følgeforespørsel til:'
-    following: 'Suksess! Nå følger du:'
-    post_follow:
-      close: Eller så kan du lukke dette vinduet.
-      return: Gå tilbake til brukerens profil
-      web: Gå til nettsiden
-    title: Følg %{acct}
   challenge:
     confirm: Fortsett
     hint_html: "<strong>Tips:</strong> Vi ber deg ikke om passordet ditt igjen i løpet av neste time."
diff --git a/config/locales/oc.yml b/config/locales/oc.yml
index 5dcbb0c57..e8dce6126 100644
--- a/config/locales/oc.yml
+++ b/config/locales/oc.yml
@@ -502,17 +502,6 @@ oc:
       account_status: Estat del compte
       functional: Vòstre compte es complètament foncional.
     use_security_key: Utilizar clau de seguretat
-  authorize_follow:
-    already_following: Seguètz ja aqueste compte
-    error: O planhèm, i a agut una error al moment de cercar lo compte
-    follow: Sègre
-    follow_request: 'Avètz demandat de sègre :'
-    following: 'Felicitacion ! Seguètz ara :'
-    post_follow:
-      close: O podètz tampar aquesta fenèstra.
-      return: Veire lo perfil a la persona
-      web: Tornar a l’interfàcia Web
-    title: Sègre %{acct}
   challenge:
     confirm: Contunhar
     hint_html: "<strong>Asutúcia :</strong> vos demandarem pas vòstre senhal de nòu d’aquí unas oras."
diff --git a/config/locales/pl.yml b/config/locales/pl.yml
index 4af888513..c1b34ee96 100644
--- a/config/locales/pl.yml
+++ b/config/locales/pl.yml
@@ -1096,18 +1096,6 @@ pl:
       view_strikes: Zobacz dawne ostrzeżenia nałożone na twoje konto
     too_fast: Zbyt szybko przesłano formularz, spróbuj ponownie.
     use_security_key: Użyj klucza bezpieczeństwa
-  authorize_follow:
-    already_following: Już obserwujesz to konto
-    already_requested: Już wysłałeś(-aś) prośbę o możliwość obserwowania tego konta
-    error: Niestety, podczas sprawdzania zdalnego konta wystąpił błąd
-    follow: Obserwuj
-    follow_request: 'Wysłano prośbę o możliwość obserwowania:'
-    following: 'Pomyślnie! Od teraz obserwujesz:'
-    post_follow:
-      close: Ewentualnie, możesz po prostu zamknąć tę stronę.
-      return: Pokaż stronę użytkownika
-      web: Przejdź do sieci
-    title: Obserwuj %{acct}
   challenge:
     confirm: Kontynuuj
     hint_html: "<strong>Informacja:</strong> Nie będziemy prosić Cię o ponowne podanie hasła przez następną godzinę."
diff --git a/config/locales/pt-BR.yml b/config/locales/pt-BR.yml
index d9594a150..d47b94627 100644
--- a/config/locales/pt-BR.yml
+++ b/config/locales/pt-BR.yml
@@ -1059,18 +1059,6 @@ pt-BR:
       view_strikes: Veja os avisos anteriores em relação à sua conta
     too_fast: O formulário foi enviado muito rapidamente, tente novamente.
     use_security_key: Usar chave de segurança
-  authorize_follow:
-    already_following: Você já segue
-    already_requested: Você já enviou uma solicitação para seguir esta conta
-    error: Infelizmente, ocorreu um erro ao buscar a conta remota
-    follow: Seguir
-    follow_request: 'Você mandou solicitação para seguir para:'
-    following: 'Sucesso! Agora você está seguindo:'
-    post_follow:
-      close: Ou você pode simplesmente fechar esta janela.
-      return: Mostrar o perfil do usuário
-      web: Voltar à página inicial
-    title: Seguir %{acct}
   challenge:
     confirm: Continuar
     hint_html: "<strong>Dica:</strong> Não pediremos novamente sua senha pela próxima hora."
diff --git a/config/locales/pt-PT.yml b/config/locales/pt-PT.yml
index 4b1b7a1b7..4c4aaa415 100644
--- a/config/locales/pt-PT.yml
+++ b/config/locales/pt-PT.yml
@@ -1060,18 +1060,6 @@ pt-PT:
       view_strikes: Veja as reprimendas anteriores sobre a sua conta
     too_fast: Formulário enviado demasiado rapidamente, tente novamente.
     use_security_key: Usar chave de segurança
-  authorize_follow:
-    already_following: Tu já estás a seguir esta conta
-    already_requested: Já enviou anteriormente um pedido para seguir esta conta
-    error: Infelizmente, ocorreu um erro ao buscar a conta remota
-    follow: Seguir
-    follow_request: 'Enviaste uma solicitação de seguidor para:'
-    following: 'Sucesso! Agora estás a seguir a:'
-    post_follow:
-      close: Ou podes simplesmente fechar esta janela.
-      return: Mostrar perfil do utilizador
-      web: Ir para a página na teia
-    title: Seguir %{acct}
   challenge:
     confirm: Continuar
     hint_html: "<strong>Dica:</strong> Não vamos pedir novamente a sua palavra-passe durante a próxima hora."
diff --git a/config/locales/ro.yml b/config/locales/ro.yml
index ae32b1177..036e78edb 100644
--- a/config/locales/ro.yml
+++ b/config/locales/ro.yml
@@ -445,18 +445,6 @@ ro:
       confirming: Se așteaptă finalizarea confirmării prin e-mail.
       pending: Cererea dvs. este în curs de revizuire de către personalul nostru. Este posibil să dureze ceva timp. Veți primi un e-mail dacă cererea dvs. este aprobată.
       redirecting_to: Contul dvs. este inactiv deoarece în prezent se redirecționează către %{acct}.
-  authorize_follow:
-    already_following: Urmărești deja acest cont
-    already_requested: Ați trimis deja o cerere de urmărire către acel cont
-    error: Din păcate a apărut o eroare
-    follow: Urmărește
-    follow_request: 'Ai trimis o cerere de urmărire către:'
-    following: 'Gata! De acum urmărești:'
-    post_follow:
-      close: Sau, poți închide această fereastră.
-      return: Arată profilul utilizatorului
-      web: Mergi la web
-    title: Urmărește %{acct}
   challenge:
     confirm: Continuă
     hint_html: "<strong>Sfat:</strong> Nu vă vom mai cere parola pentru următoarea oră."
diff --git a/config/locales/ru.yml b/config/locales/ru.yml
index d90a93e3c..c6fdff9aa 100644
--- a/config/locales/ru.yml
+++ b/config/locales/ru.yml
@@ -1094,18 +1094,6 @@ ru:
       view_strikes: Просмотр предыдущих замечаний в адрес вашей учетной записи
     too_fast: Форма отправлена слишком быстро, попробуйте еще раз.
     use_security_key: Использовать ключ безопасности
-  authorize_follow:
-    already_following: Вы уже подписаны на эту учётную запись
-    already_requested: Вы уже отправили запрос на подписку на эту учётную запись
-    error: К сожалению, при поиске удалённой учётной записи возникла ошибка
-    follow: Подписаться
-    follow_request: 'Вы отправили запрос на подписку:'
-    following: 'Готово! Вы подписались на:'
-    post_follow:
-      close: Или просто закройте это окно.
-      return: Вернуться к профилю пользователя
-      web: Открыть в веб-версии
-    title: Подписаться на %{acct}
   challenge:
     confirm: Продолжить
     hint_html: "<strong>Подсказка</strong>: мы не будем спрашивать пароль повторно в течение часа."
diff --git a/config/locales/sc.yml b/config/locales/sc.yml
index b67d67391..b6754021e 100644
--- a/config/locales/sc.yml
+++ b/config/locales/sc.yml
@@ -537,18 +537,6 @@ sc:
       redirecting_to: Su contu tuo est inativu pro ite in die de oe est torrende a indiritzare a %{acct}.
     too_fast: Formulàriu imbiadu tropu a lestru, torra a proare.
     use_security_key: Imprea una crae de seguresa
-  authorize_follow:
-    already_following: Ses giai sighende custu contu
-    already_requested: As giai imbiadu una dimanda de sighidura a custa persone
-    error: Faddina in sa chirca de su contu remotu
-    follow: Sighi
-    follow_request: 'As imbiadu una dimanda de sighidura a:'
-    following: 'Fatu! Immoe ses sighende a:'
-    post_follow:
-      close: O, podes serrare custa ventana.
-      return: Ammustra su profilu de custa persone
-      web: Bae a su situ web
-    title: Sighi a %{acct}
   challenge:
     confirm: Sighi
     hint_html: "<strong>Cussìgiu:</strong> No t'amus a torrare a dimandare sa crae in s'ora imbeniente."
diff --git a/config/locales/sco.yml b/config/locales/sco.yml
index 37c8b0b43..2199c5dbf 100644
--- a/config/locales/sco.yml
+++ b/config/locales/sco.yml
@@ -969,18 +969,6 @@ sco:
       view_strikes: Luik at past strikes aginst yer accoont
     too_fast: Form submittit ower fast, try again.
     use_security_key: Uise security key
-  authorize_follow:
-    already_following: Ye'r awriddy follaein this accoont
-    already_requested: Ye'v awriddy sent a follae request tae that accoont
-    error: Unfortunately, there wis a error luikin up the remote accoont
-    follow: Follae
-    follow_request: 'Ye hae sent a follae request tae:'
-    following: 'Success! Ye''r noo follaein:'
-    post_follow:
-      close: Or, ye kin juist shut this windae.
-      return: Shaw the uiser's profile
-      web: Gang tae the wab
-    title: Follae %{acct}
   challenge:
     confirm: Continue
     hint_html: "<strong>wee tip:</strong> We wullnae ask ye fir yer passwird again fir the neist oor."
diff --git a/config/locales/si.yml b/config/locales/si.yml
index 11804ef09..45be8b76f 100644
--- a/config/locales/si.yml
+++ b/config/locales/si.yml
@@ -803,18 +803,6 @@ si:
       view_strikes: ඔබගේ ගිණුමට එරෙහිව පසුගිය වර්ජන බලන්න
     too_fast: පෝරමය ඉතා වේගයෙන් ඉදිරිපත් කර ඇත, නැවත උත්සාහ කරන්න.
     use_security_key: ආරක්ෂක යතුර භාවිතා කරන්න
-  authorize_follow:
-    already_following: ඔබ දැනටමත් මෙම ගිණුම අනුගමනය කරයි
-    already_requested: ඔබ දැනටමත් එම ගිණුමට අනුගමනය ඉල්ලීමක් යවා ඇත
-    error: අවාසනාවකට, දුරස්ථ ගිණුම සෙවීමේදී දෝෂයක් ඇති විය
-    follow: අනුගමනය
-    follow_request: 'ඔබ පහත ඉල්ලීමක් යවා ඇත:'
-    following: 'සාර්ථකත්වය! ඔබ දැන් පහත දැක්වේ:'
-    post_follow:
-      close: හෝ ඔබට මෙම කවුළුව වසාදැමිය හැකිය.
-      return: පරිශීලකගේ පැතිකඩ පෙන්වන්න
-      web: වියමන ට යන්න
-    title: "%{acct} අනුගමනය"
   challenge:
     confirm: ඉදිරියට
     hint_html: "<strong>ඉඟිය:</strong> අපි ඉදිරි පැය සඳහා නැවත ඔබගේ මුරපදය ඔබෙන් නොඉල්ලමු."
diff --git a/config/locales/sk.yml b/config/locales/sk.yml
index 0cf03d7e3..adc4e8b59 100644
--- a/config/locales/sk.yml
+++ b/config/locales/sk.yml
@@ -737,17 +737,6 @@ sk:
       pending: Tvoja žiadosť čaká na schvílenie od nášho týmu. Môže to chviľu potrvať. Ak bude tvoja žiadosť schválená, dostaneš o tom email.
       redirecting_to: Tvoj účet je neaktívny, lebo v súčasnosti presmerováva na %{acct}.
     use_security_key: Použi bezpečnostný kľúč
-  authorize_follow:
-    already_following: Tento účet už nasleduješ
-    error: Naneštastie nastala chyba pri hľadaní vzdialeného účtu
-    follow: Nasleduj
-    follow_request: 'Poslal/a si žiadosť nasledovať užívateľa:'
-    following: 'Podarilo sa! Teraz nasleduješ užívateľa:'
-    post_follow:
-      close: Alebo môžeš iba zatvoriť toto okno.
-      return: Ukáž užívateľov profil
-      web: Prejdi do siete
-    title: Nasleduj %{acct}
   challenge:
     confirm: Pokračuj
     hint_html: "<strong>Tip:</strong> Hodinu nebudeme znovu vyžadovať tvoje heslo."
diff --git a/config/locales/sl.yml b/config/locales/sl.yml
index 057abc2b8..b963c6467 100644
--- a/config/locales/sl.yml
+++ b/config/locales/sl.yml
@@ -1084,18 +1084,6 @@ sl:
       view_strikes: Pokaži pretekle ukrepe proti mojemu računu
     too_fast: Obrazec oddan prehitro, poskusite znova.
     use_security_key: Uporabi varnostni ključ
-  authorize_follow:
-    already_following: Temu računu že sledite
-    already_requested: Temu računu ste že poslali zahtevo po sledenju
-    error: Na žalost je prišlo do napake pri iskanju oddaljenega računa
-    follow: Sledi
-    follow_request: 'Prošnjo za sledenje se poslali:'
-    following: 'Uspeh! Zdaj sledite:'
-    post_follow:
-      close: Lahko pa tudi zaprete to okno.
-      return: Prikaži uporabnikov profil
-      web: Pojdi na splet
-    title: Sledi %{acct}
   challenge:
     confirm: Nadaljuj
     hint_html: "<strong>Namig:</strong> naslednjo uro vas ne bomo več vprašali po vašem geslu."
diff --git a/config/locales/sq.yml b/config/locales/sq.yml
index 4e27e218e..51bf810ad 100644
--- a/config/locales/sq.yml
+++ b/config/locales/sq.yml
@@ -1052,18 +1052,6 @@ sq:
       view_strikes: Shihni paralajmërime të dikurshme kundër llogarisë tuaj
     too_fast: Formulari u parashtrua shumë shpejt, riprovoni.
     use_security_key: Përdor kyç sigurie
-  authorize_follow:
-    already_following: E ndiqni tashmë këtë llogari
-    already_requested: Keni dërguar tashmë një kërkesë ndjekjeje te ajo llogari
-    error: Mjerisht, pati një gabim gjatë kërkimit të llogarisë së largët
-    follow: Ndiqeni
-    follow_request: 'Keni dërguar një kërkesë ndjekjeje te:'
-    following: 'Sukses! Tani e ndiqni:'
-    post_follow:
-      close: Ose, thjesht mund të mbyllni këtë dritare.
-      return: Shfaq profilin e përdoruesit
-      web: Kalo në web
-    title: Ndiq %{acct}
   challenge:
     confirm: Vazhdo
     hint_html: "<strong>Ndihmëz:</strong> S’do t’ju pyesim për fjalëkalimin tuaj sërish, për një orë."
diff --git a/config/locales/sr-Latn.yml b/config/locales/sr-Latn.yml
index 0de22a2f9..cbd60dc5b 100644
--- a/config/locales/sr-Latn.yml
+++ b/config/locales/sr-Latn.yml
@@ -1078,18 +1078,6 @@ sr-Latn:
       view_strikes: Pogledajte prethodne prestupe upisane na Vaše ime
     too_fast: Formular je podnet prebrzo, pokušajte ponovo.
     use_security_key: Koristite sigurnosni ključ
-  authorize_follow:
-    already_following: Već pratite ovaj nalog
-    already_requested: Već ste poslali zahtev za praćenje tom nalogu
-    error: Nažalost, desila se greška pri traženju udaljenog naloga
-    follow: Zaprati
-    follow_request: 'Poslali ste zahtev za praćenjen za:'
-    following: 'Sjajno! Sada pratite:'
-    post_follow:
-      close: Ili možete zatvoriti ovaj prozor.
-      return: Vrati se na nalog ovog korisnika
-      web: Idi na veb
-    title: Zaprati %{acct}
   challenge:
     confirm: Nastavi
     hint_html: "<strong>Savet:</strong> Nećemo Vas pitati za lozinku ponovo u narednih sat vremena."
diff --git a/config/locales/sr.yml b/config/locales/sr.yml
index 5806b4696..8b4954d16 100644
--- a/config/locales/sr.yml
+++ b/config/locales/sr.yml
@@ -1078,18 +1078,6 @@ sr:
       view_strikes: Погледајте претходне преступе уписане на Ваше име
     too_fast: Формулар је поднет пребрзо, покушајте поново.
     use_security_key: Користите сигурносни кључ
-  authorize_follow:
-    already_following: Већ пратите овај налог
-    already_requested: Већ сте послали захтев за праћење том налогу
-    error: Нажалост, десила се грешка при тражењу удаљеног налога
-    follow: Запрати
-    follow_request: 'Послали сте захтев за праћењен за:'
-    following: 'Сјајно! Сада пратите:'
-    post_follow:
-      close: Или можете затворити овај прозор.
-      return: Врати се на налог овог корисника
-      web: Иди на веб
-    title: Запрати %{acct}
   challenge:
     confirm: Настави
     hint_html: "<strong>Савет:</strong> Нећемо Вас питати за лозинку поново у наредних сат времена."
diff --git a/config/locales/sv.yml b/config/locales/sv.yml
index 81ef482f5..340058afe 100644
--- a/config/locales/sv.yml
+++ b/config/locales/sv.yml
@@ -1042,18 +1042,6 @@ sv:
       view_strikes: Visa tidigare prickar på ditt konto
     too_fast: Formuläret har skickats för snabbt, försök igen.
     use_security_key: Använd säkerhetsnyckel
-  authorize_follow:
-    already_following: Du följer redan detta konto
-    already_requested: Du har redan skickat en vänförfrågan till det kontot
-    error: Tyvärr inträffade ett fel när vi kontrollerade fjärrkontot
-    follow: Följ
-    follow_request: 'Du har skickat en följaförfrågan till:'
-    following: 'Succé! Du följer nu:'
-    post_follow:
-      close: Eller så kan du stänga detta fönster.
-      return: Visa användarens profil
-      web: Gå till webb
-    title: Följ %{acct}
   challenge:
     confirm: Fortsätt
     hint_html: "<strong>Tips:</strong> Vi frågar dig inte efter ditt lösenord igen under nästkommande timme."
diff --git a/config/locales/ta.yml b/config/locales/ta.yml
index 2d2bce86a..80cafff1e 100644
--- a/config/locales/ta.yml
+++ b/config/locales/ta.yml
@@ -191,8 +191,6 @@ ta:
     localization:
       body: மாஸ்டோடான் தன்னார்வலர்களால் மொழிபெயர்க்கப்படுகிறது.
       guide_link_text: அனைவரும் பங்களிக்கலாம்.
-  authorize_follow:
-    already_requested: இக்கணக்கைப் பின்தொடரும் கோரிக்கையை நீங்கள் ஏற்கனவே அனுப்பிவிட்டீர்கள்
   crypto:
     errors:
       invalid_key: ஒரு முறையான Ed25519 அல்லது Curve25519 key அல்ல
diff --git a/config/locales/th.yml b/config/locales/th.yml
index 0d55abbe5..264beffaf 100644
--- a/config/locales/th.yml
+++ b/config/locales/th.yml
@@ -1042,18 +1042,6 @@ th:
       view_strikes: ดูการดำเนินการที่ผ่านมาต่อบัญชีของคุณ
     too_fast: ส่งแบบฟอร์มเร็วเกินไป ลองอีกครั้ง
     use_security_key: ใช้กุญแจความปลอดภัย
-  authorize_follow:
-    already_following: คุณกำลังติดตามบัญชีนี้อยู่แล้ว
-    already_requested: คุณได้ส่งคำขอติดตามไปยังบัญชีนั้นไปแล้ว
-    error: น่าเสียดาย มีข้อผิดพลาดในการมองหาบัญชีระยะไกล
-    follow: ติดตาม
-    follow_request: 'คุณได้ส่งคำขอติดตามไปยัง:'
-    following: 'สำเร็จ! ตอนนี้คุณกำลังติดตาม:'
-    post_follow:
-      close: หรือคุณสามารถปิดหน้าต่างนี้
-      return: แสดงโปรไฟล์ของผู้ใช้
-      web: ไปยังเว็บ
-    title: ติดตาม %{acct}
   challenge:
     confirm: ดำเนินการต่อ
     hint_html: "<strong>เคล็ดลับ:</strong> เราจะไม่ถามรหัสผ่านของคุณกับคุณสำหรับชั่วโมงถัดไป"
diff --git a/config/locales/tr.yml b/config/locales/tr.yml
index 3b60a4cd5..8923e730a 100644
--- a/config/locales/tr.yml
+++ b/config/locales/tr.yml
@@ -1060,18 +1060,6 @@ tr:
       view_strikes: Hesabınıza yönelik eski eylemleri görüntüleyin
     too_fast: Form çok hızlı gönderildi, tekrar deneyin.
     use_security_key: Güvenlik anahtarını kullan
-  authorize_follow:
-    already_following: Bu hesabı zaten takip ediyorsunuz
-    already_requested: Bu hesaba zaten takip isteği gönderdiniz
-    error: Uzak hesap aranırken bir hata oluştu
-    follow: Takip et
-    follow_request: 'Şuna takip isteği gönderdiniz:'
-    following: 'Başarılı! Artık şunu takip ediyorsunuz:'
-    post_follow:
-      close: Ya da, sadece bu pencereyi kapatabilirsiniz.
-      return: Kullanıcının profilini göster
-      web: Web'e git
-    title: "%{acct} takip et"
   challenge:
     confirm: Devam et
     hint_html: "<strong>İpucu:</strong> Önümüzdeki saat boyunca sana parolanı sormayacağız."
diff --git a/config/locales/tt.yml b/config/locales/tt.yml
index 7999de2ff..4006aac62 100644
--- a/config/locales/tt.yml
+++ b/config/locales/tt.yml
@@ -337,12 +337,6 @@ tt:
       accept: Кабул итү
       back: Кире
     security: Хәвефсезлек
-    status:
-      account_status: Хисап халәте
-  authorize_follow:
-    follow: Язылу
-    post_follow:
-      web: Вебга күчү
   challenge:
     confirm: Дәвам итү
   date:
diff --git a/config/locales/uk.yml b/config/locales/uk.yml
index d3d92f9f7..3fed715de 100644
--- a/config/locales/uk.yml
+++ b/config/locales/uk.yml
@@ -1096,18 +1096,6 @@ uk:
       view_strikes: Переглянути попередні попередження вашому обліковому запису
     too_fast: Форму подано занадто швидко, спробуйте ще раз.
     use_security_key: Використовувати ключ безпеки
-  authorize_follow:
-    already_following: Ви вже слідкуєте за цим обліковим записом
-    already_requested: Ви вже надіслали запит на підписку до цього облікового запису
-    error: На жаль, під час пошуку віддаленого облікового запису сталася помилка
-    follow: Підписатися
-    follow_request: 'Вам надіслали запит на підписку:'
-    following: 'Ура! Ви тепер підписані на:'
-    post_follow:
-      close: Або, ви можете просто закрити вікно.
-      return: Перейти до профілю користувача
-      web: Перейти до вебу
-    title: Підписатися на %{acct}
   challenge:
     confirm: Далі
     hint_html: "<strong>Підказка:</strong> ми не будемо запитувати ваш пароль впродовж наступної години."
diff --git a/config/locales/vi.yml b/config/locales/vi.yml
index a95f5f764..08e0eeb17 100644
--- a/config/locales/vi.yml
+++ b/config/locales/vi.yml
@@ -1042,18 +1042,6 @@ vi:
       view_strikes: Xem những lần cảnh cáo cũ
     too_fast: Nghi vấn đăng ký spam, xin thử lại.
     use_security_key: Dùng khóa bảo mật
-  authorize_follow:
-    already_following: Bạn đang theo dõi người này
-    already_requested: Bạn vừa gửi một yêu cầu theo dõi tới người này
-    error: Rất tiếc, đã xảy ra lỗi khi tìm kiếm tài khoản từ nơi khác
-    follow: Theo dõi
-    follow_request: Bạn đã gửi yêu cầu theo dõi tới
-    following: Chúc mừng! Bạn đã trở thành người theo dõi
-    post_follow:
-      close: Bạn có thể đóng cửa sổ này rồi.
-      return: Xem trang hồ sơ
-      web: Mở trong Mastodon
-    title: Theo dõi %{acct}
   challenge:
     confirm: Tiếp tục
     hint_html: "<strong>Mẹo:</strong> Chúng tôi sẽ không hỏi lại mật khẩu của bạn sau này."
diff --git a/config/locales/zgh.yml b/config/locales/zgh.yml
index ee25ed142..31c5fc20b 100644
--- a/config/locales/zgh.yml
+++ b/config/locales/zgh.yml
@@ -77,9 +77,6 @@ zgh:
     register: ⵣⵎⵎⴻⵎ
     status:
       account_status: ⴰⴷⴷⴰⴷ ⵏ ⵓⵎⵉⴹⴰⵏ
-  authorize_follow:
-    follow: ⴹⴼⵕ
-    title: ⴹⴼⵕ %{acct}
   deletes:
     proceed: ⴽⴽⵙ ⴰⵎⵉⴹⴰⵏ
   errors:
diff --git a/config/locales/zh-CN.yml b/config/locales/zh-CN.yml
index 0ba154d62..bed748d81 100644
--- a/config/locales/zh-CN.yml
+++ b/config/locales/zh-CN.yml
@@ -1042,18 +1042,6 @@ zh-CN:
       view_strikes: 查看针对你账号的记录
     too_fast: 表单提交过快,请重试。
     use_security_key: 使用安全密钥
-  authorize_follow:
-    already_following: 你已经在关注此用户了
-    already_requested: 你已经向那个账户发送过关注请求了
-    error: 对不起,寻找这个跨站用户时出错
-    follow: 关注
-    follow_request: 关注请求已发送给:
-    following: 成功!你正在关注:
-    post_follow:
-      close: 你也可以直接关闭这个窗口。
-      return: 查看用户个人资料
-      web: 返回本站
-    title: 关注 %{acct}
   challenge:
     confirm: 继续
     hint_html: "<strong>注意:</strong>接下来一小时内我们不会再次要求你输入密码。"
diff --git a/config/locales/zh-HK.yml b/config/locales/zh-HK.yml
index 25a989754..eec900c86 100644
--- a/config/locales/zh-HK.yml
+++ b/config/locales/zh-HK.yml
@@ -1005,18 +1005,6 @@ zh-HK:
       view_strikes: 查看針對你的帳戶的過往警告
     too_fast: 你太快遞交了,請再試一次。
     use_security_key: 使用安全密鑰裝置
-  authorize_follow:
-    already_following: 你已經關注了這個帳號
-    already_requested: 你先前已向該帳號發送關注請求
-    error: 對不起,尋找這個跨站用戶的過程發生錯誤
-    follow: 關注
-    follow_request: 關注請求已發送给:
-    following: 成功!你正在關注:
-    post_follow:
-      close: 你也可以直接關閉這個頁面。
-      return: 顯示個人資料頁
-      web: 返回本站
-    title: 關注 %{acct}
   challenge:
     confirm: 繼續
     hint_html: "<strong>温馨提示</strong> 我們在未來一小時內不會再要求你填寫密碼。"
diff --git a/config/locales/zh-TW.yml b/config/locales/zh-TW.yml
index 80addbf49..7ec003135 100644
--- a/config/locales/zh-TW.yml
+++ b/config/locales/zh-TW.yml
@@ -1046,18 +1046,6 @@ zh-TW:
       view_strikes: 檢視針對您帳號過去的警示
     too_fast: 送出表單的速度太快跟不上,請稍後再試。
     use_security_key: 使用安全金鑰
-  authorize_follow:
-    already_following: 您已經跟隨這個使用者
-    already_requested: 您早已向該帳號寄送跟隨請求
-    error: 對不起,搜尋其他站點使用者出現錯誤
-    follow: 跟隨
-    follow_request: 跟隨請求已發送給:
-    following: 成功!您正在跟隨:
-    post_follow:
-      close: 您可以直接關閉此頁面。
-      return: 顯示個人檔案
-      web: 返回本站
-    title: 跟隨 %{acct}
   challenge:
     confirm: 繼續
     hint_html: "<strong>温馨小提醒:</strong> 我們在接下來一小時內不會再要求您輸入密碼。"
diff --git a/config/routes.rb b/config/routes.rb
index 87ee815f4..5de8562a8 100644
--- a/config/routes.rb
+++ b/config/routes.rb
@@ -54,6 +54,7 @@ Rails.application.routes.draw do
   get '.well-known/nodeinfo', to: 'well_known/nodeinfo#index', as: :nodeinfo, defaults: { format: 'json' }
   get '.well-known/webfinger', to: 'well_known/webfinger#show', as: :webfinger
   get '.well-known/change-password', to: redirect('/auth/edit')
+  get '.well-known/proxy', to: redirect { |_, request| "/authorize_interaction?#{request.params.to_query}" }
 
   get '/nodeinfo/2.0', to: 'well_known/nodeinfo#show', as: :nodeinfo_schema
 
@@ -61,6 +62,8 @@ Rails.application.routes.draw do
   get 'intent', to: 'intents#show'
   get 'custom.css', to: 'custom_css#show', as: :custom_css
 
+  get 'remote_interaction_helper', to: 'remote_interaction_helper#index'
+
   resource :instance_actor, path: 'actor', only: [:show] do
     resource :inbox, only: [:create], module: :activitypub
     resource :outbox, only: [:show], module: :activitypub
@@ -163,7 +166,7 @@ Rails.application.routes.draw do
   get '/media_proxy/:id/(*any)', to: 'media_proxy#show', as: :media_proxy, format: false
   get '/backups/:id/download', to: 'backups#download', as: :download_backup, format: false
 
-  resource :authorize_interaction, only: [:show, :create]
+  resource :authorize_interaction, only: [:show]
   resource :share, only: [:show]
 
   draw(:admin)
diff --git a/config/routes/api.rb b/config/routes/api.rb
index 2fc84ace2..6db03147b 100644
--- a/config/routes/api.rb
+++ b/config/routes/api.rb
@@ -123,6 +123,10 @@ namespace :api, format: false do
       resource :activity, only: [:show], controller: 'instances/activity'
     end
 
+    namespace :peers do
+      get :search, to: 'search#index'
+    end
+
     resource :domain_blocks, only: [:show, :create, :destroy]
 
     resource :directory, only: [:show]
diff --git a/lib/mastodon/cli/search.rb b/lib/mastodon/cli/search.rb
index 8d7b7202f..33bcad5fe 100644
--- a/lib/mastodon/cli/search.rb
+++ b/lib/mastodon/cli/search.rb
@@ -7,6 +7,7 @@ module Mastodon::CLI
     # Indices are sorted by amount of data to be expected in each, so that
     # smaller indices can go online sooner
     INDICES = [
+      InstancesIndex,
       AccountsIndex,
       TagsIndex,
       StatusesIndex,
diff --git a/spec/controllers/authorize_interactions_controller_spec.rb b/spec/controllers/authorize_interactions_controller_spec.rb
index 098c25ba3..5282a196a 100644
--- a/spec/controllers/authorize_interactions_controller_spec.rb
+++ b/spec/controllers/authorize_interactions_controller_spec.rb
@@ -24,7 +24,7 @@ describe AuthorizeInteractionsController do
       it 'renders error without acct param' do
         get :show
 
-        expect(response).to render_template(:error)
+        expect(response).to have_http_status(404)
       end
 
       it 'renders error when account cant be found' do
@@ -34,7 +34,7 @@ describe AuthorizeInteractionsController do
 
         get :show, params: { acct: 'acct:missing@hostname' }
 
-        expect(response).to render_template(:error)
+        expect(response).to have_http_status(404)
         expect(service).to have_received(:call).with('missing@hostname')
       end
 
@@ -46,7 +46,7 @@ describe AuthorizeInteractionsController do
 
         get :show, params: { acct: 'http://example.com' }
 
-        expect(response).to have_http_status(200)
+        expect(response).to have_http_status(302)
         expect(assigns(:resource)).to eq account
       end
 
@@ -58,52 +58,9 @@ describe AuthorizeInteractionsController do
 
         get :show, params: { acct: 'acct:found@hostname' }
 
-        expect(response).to have_http_status(200)
+        expect(response).to have_http_status(302)
         expect(assigns(:resource)).to eq account
       end
     end
   end
-
-  describe 'POST #create' do
-    describe 'when signed out' do
-      it 'redirects to sign in page' do
-        post :create
-
-        expect(response).to redirect_to(new_user_session_path)
-      end
-    end
-
-    describe 'when signed in' do
-      let!(:user) { Fabricate(:user) }
-      let(:account) { user.account }
-
-      before do
-        sign_in(user)
-      end
-
-      it 'shows error when account not found' do
-        service = instance_double(ResolveAccountService)
-
-        allow(ResolveAccountService).to receive(:new).and_return(service)
-        allow(service).to receive(:call).with('user@hostname').and_return(nil)
-
-        post :create, params: { acct: 'acct:user@hostname' }
-
-        expect(response).to render_template(:error)
-      end
-
-      it 'follows account when found' do
-        target_account = Fabricate(:account)
-        service = instance_double(ResolveAccountService)
-
-        allow(ResolveAccountService).to receive(:new).and_return(service)
-        allow(service).to receive(:call).with('user@hostname').and_return(target_account)
-
-        post :create, params: { acct: 'acct:user@hostname' }
-
-        expect(account.following?(target_account)).to be true
-        expect(response).to render_template(:success)
-      end
-    end
-  end
 end