From 5247ea4efd3683154d52efe4385bdbb63f476943 Mon Sep 17 00:00:00 2001
From: ThibG <thib@sitedethib.com>
Date: Mon, 8 Apr 2019 18:35:41 +0200
Subject: [PATCH 01/16] Fix batch actions not working on pending accounts
 (#10508)

---
 app/controllers/admin/pending_accounts_controller.rb | 4 ++--
 app/views/admin/pending_accounts/index.html.haml     | 2 +-
 config/locales/en.yml                                | 1 +
 config/routes.rb                                     | 3 ++-
 4 files changed, 6 insertions(+), 4 deletions(-)

diff --git a/app/controllers/admin/pending_accounts_controller.rb b/app/controllers/admin/pending_accounts_controller.rb
index 8429d35855..f145108b34 100644
--- a/app/controllers/admin/pending_accounts_controller.rb
+++ b/app/controllers/admin/pending_accounts_controller.rb
@@ -8,11 +8,11 @@ module Admin
       @form = Form::AccountBatch.new
     end
 
-    def update
+    def batch
       @form = Form::AccountBatch.new(form_account_batch_params.merge(current_account: current_account, action: action_from_button))
       @form.save
     rescue ActionController::ParameterMissing
-      # Do nothing
+      flash[:alert] = I18n.t('admin.accounts.no_account_selected')
     ensure
       redirect_to admin_pending_accounts_path(current_params)
     end
diff --git a/app/views/admin/pending_accounts/index.html.haml b/app/views/admin/pending_accounts/index.html.haml
index 77b96cbca0..7ce5b8213a 100644
--- a/app/views/admin/pending_accounts/index.html.haml
+++ b/app/views/admin/pending_accounts/index.html.haml
@@ -4,7 +4,7 @@
 - content_for :header_tags do
   = javascript_pack_tag 'admin', integrity: true, async: true, crossorigin: 'anonymous'
 
-= form_for(@form, url: admin_pending_accounts_path, method: :patch) do |f|
+= form_for(@form, url: batch_admin_pending_accounts_path) do |f|
   = hidden_field_tag :page, params[:page] || 1
 
   .batch-table
diff --git a/config/locales/en.yml b/config/locales/en.yml
index e56008a89b..139803affb 100644
--- a/config/locales/en.yml
+++ b/config/locales/en.yml
@@ -134,6 +134,7 @@ en:
       moderation_notes: Moderation notes
       most_recent_activity: Most recent activity
       most_recent_ip: Most recent IP
+      no_account_selected: No accounts were changed as none were selected
       no_limits_imposed: No limits imposed
       not_subscribed: Not subscribed
       outbox_url: Outbox URL
diff --git a/config/routes.rb b/config/routes.rb
index 1ea6490b0d..34d0081e77 100644
--- a/config/routes.rb
+++ b/config/routes.rb
@@ -214,10 +214,11 @@ Rails.application.routes.draw do
       end
     end
 
-    resources :pending_accounts, only: [:index, :update] do
+    resources :pending_accounts, only: [:index] do
       collection do
         post :approve_all
         post :reject_all
+        post :batch
       end
     end
 

From 2a168a002c971014093d89bd45486dca9db0b14d Mon Sep 17 00:00:00 2001
From: Alix Rossi <alixrossics@gmail.com>
Date: Mon, 8 Apr 2019 19:01:41 +0200
Subject: [PATCH 02/16] i18n: Update Corsican translations (#10510)

* i18n: Update Corsican translations

* i18n: Update Corsican translations
---
 config/locales/co.yml | 1 +
 1 file changed, 1 insertion(+)

diff --git a/config/locales/co.yml b/config/locales/co.yml
index 7fcb087cfd..c751c80f0e 100644
--- a/config/locales/co.yml
+++ b/config/locales/co.yml
@@ -134,6 +134,7 @@ co:
       moderation_notes: Note di muderazione
       most_recent_activity: Attività più ricente
       most_recent_ip: IP più ricente
+      no_account_selected: Nisun contu hè statu cambiatu postu ch'ùn c'eranu micca selezziunati
       no_limits_imposed: Nisuna limita imposta
       not_subscribed: Micca abbunatu
       outbox_url: URL di l’outbox

From ba1a78d1687a8e5bd1e969af41852a28192e5231 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Quent=C3=AD?= <33203663+Quenty31@users.noreply.github.com>
Date: Tue, 9 Apr 2019 00:39:50 +0200
Subject: [PATCH 03/16] [i18n] Update and correction (#10511)

* [i18n] Update and correction

* Update oc.json

* Update oc.json
---
 app/javascript/mastodon/locales/oc.json | 6 ++++--
 1 file changed, 4 insertions(+), 2 deletions(-)

diff --git a/app/javascript/mastodon/locales/oc.json b/app/javascript/mastodon/locales/oc.json
index 8fc8762a48..c9d896f5b3 100644
--- a/app/javascript/mastodon/locales/oc.json
+++ b/app/javascript/mastodon/locales/oc.json
@@ -83,7 +83,7 @@
   "compose_form.spoiler.unmarked": "Lo tèxte es pas rescondut",
   "compose_form.spoiler_placeholder": "Escrivètz l’avertiment aquí",
   "confirmation_modal.cancel": "Anullar",
-  "confirmations.block.block_and_report": "Block & Report",
+  "confirmations.block.block_and_report": "Blocar e senhalar",
   "confirmations.block.confirm": "Blocar",
   "confirmations.block.message": "Volètz vertadièrament blocar {name} ?",
   "confirmations.delete.confirm": "Escafar",
@@ -117,6 +117,8 @@
   "emoji_button.symbols": "Simbòls",
   "emoji_button.travel": "Viatges & lòcs",
   "empty_column.account_timeline": "Cap de tuts aquí !",
+  "empty_column.account_timeline_blocked": "Sètz blocat",
+  "empty_column.account_unavailable": "Perfil pas disponible",
   "empty_column.blocks": "Avètz pas blocat degun pel moment.",
   "empty_column.community": "Lo flux public local es void. Escrivètz quicòm per lo garnir !",
   "empty_column.direct": "Avètz pas encara cap de messatges. Quand ne mandatz un o que ne recebètz un, serà mostrat aquí.",
@@ -358,7 +360,7 @@
   "tabs_bar.search": "Recèrcas",
   "time_remaining.days": "demòra{number, plural, one  { # jorn} other {n # jorns}}",
   "time_remaining.hours": "demòra{number, plural, one { # ora} other {n # oras}}",
-  "time_remaining.minutes": "demòr{number, plural, one { # minuta} other {nn # minutas}}",
+  "time_remaining.minutes": "demòra{number, plural, one { # minuta} other {n # minutas}}",
   "time_remaining.moments": "Moments restants",
   "time_remaining.seconds": "demòra{number, plural, one { # segonda} other {n # segondas}}",
   "trends.count_by_accounts": "{count} {rawCount, plural, one {person} ne charra other {people}} ne charran",

From 56f29c38b603a98e7b9715c48de022106d8da073 Mon Sep 17 00:00:00 2001
From: Eugen Rochko <eugen@zeonfederated.com>
Date: Tue, 9 Apr 2019 05:02:48 +0200
Subject: [PATCH 04/16] Fix glitched out "not found" message for non-existing
 profiles in web UI (#10517)

---
 app/javascript/mastodon/actions/alerts.js           |  5 +++++
 .../mastodon/features/account_gallery/index.js      | 13 ++++++++++++-
 .../features/account_timeline/components/header.js  |  3 +--
 .../mastodon/features/account_timeline/index.js     | 13 ++++++++++++-
 app/javascript/mastodon/features/followers/index.js | 13 ++++++++++++-
 app/javascript/mastodon/features/following/index.js | 13 ++++++++++++-
 6 files changed, 54 insertions(+), 6 deletions(-)

diff --git a/app/javascript/mastodon/actions/alerts.js b/app/javascript/mastodon/actions/alerts.js
index 50cd48a9ed..b2c7ab76aa 100644
--- a/app/javascript/mastodon/actions/alerts.js
+++ b/app/javascript/mastodon/actions/alerts.js
@@ -34,6 +34,11 @@ export function showAlertForError(error) {
   if (error.response) {
     const { data, status, statusText } = error.response;
 
+    if (status === 404 || status === 410) {
+      // Skip these errors as they are reflected in the UI
+      return {};
+    }
+
     let message = statusText;
     let title   = `${status}`;
 
diff --git a/app/javascript/mastodon/features/account_gallery/index.js b/app/javascript/mastodon/features/account_gallery/index.js
index 96051818b8..73be58d6a3 100644
--- a/app/javascript/mastodon/features/account_gallery/index.js
+++ b/app/javascript/mastodon/features/account_gallery/index.js
@@ -13,8 +13,10 @@ import MediaItem from './components/media_item';
 import HeaderContainer from '../account_timeline/containers/header_container';
 import { ScrollContainer } from 'react-router-scroll-4';
 import LoadMore from '../../components/load_more';
+import MissingIndicator from 'mastodon/components/missing_indicator';
 
 const mapStateToProps = (state, props) => ({
+  isAccount: !!state.getIn(['accounts', props.params.accountId]),
   medias: getAccountGallery(state, props.params.accountId),
   isLoading: state.getIn(['timelines', `account:${props.params.accountId}:media`, 'isLoading']),
   hasMore:   state.getIn(['timelines', `account:${props.params.accountId}:media`, 'hasMore']),
@@ -52,6 +54,7 @@ class AccountGallery extends ImmutablePureComponent {
     medias: ImmutablePropTypes.list.isRequired,
     isLoading: PropTypes.bool,
     hasMore: PropTypes.bool,
+    isAccount: PropTypes.bool,
   };
 
   componentDidMount () {
@@ -91,7 +94,15 @@ class AccountGallery extends ImmutablePureComponent {
   }
 
   render () {
-    const { medias, shouldUpdateScroll, isLoading, hasMore } = this.props;
+    const { medias, shouldUpdateScroll, isLoading, hasMore, isAccount } = this.props;
+
+    if (!isAccount) {
+      return (
+        <Column>
+          <MissingIndicator />
+        </Column>
+      );
+    }
 
     let loadOlder = null;
 
diff --git a/app/javascript/mastodon/features/account_timeline/components/header.js b/app/javascript/mastodon/features/account_timeline/components/header.js
index 27dfcc516a..844b8a236a 100644
--- a/app/javascript/mastodon/features/account_timeline/components/header.js
+++ b/app/javascript/mastodon/features/account_timeline/components/header.js
@@ -2,7 +2,6 @@ import React from 'react';
 import ImmutablePropTypes from 'react-immutable-proptypes';
 import PropTypes from 'prop-types';
 import InnerHeader from '../../account/components/header';
-import MissingIndicator from '../../../components/missing_indicator';
 import ImmutablePureComponent from 'react-immutable-pure-component';
 import MovedNote from './moved_note';
 import { FormattedMessage } from 'react-intl';
@@ -88,7 +87,7 @@ export default class Header extends ImmutablePureComponent {
     const { account, hideTabs, identity_proofs } = this.props;
 
     if (account === null) {
-      return <MissingIndicator />;
+      return null;
     }
 
     return (
diff --git a/app/javascript/mastodon/features/account_timeline/index.js b/app/javascript/mastodon/features/account_timeline/index.js
index a01f1dd9ae..27581bfdc8 100644
--- a/app/javascript/mastodon/features/account_timeline/index.js
+++ b/app/javascript/mastodon/features/account_timeline/index.js
@@ -13,6 +13,7 @@ import { List as ImmutableList } from 'immutable';
 import ImmutablePureComponent from 'react-immutable-pure-component';
 import { FormattedMessage } from 'react-intl';
 import { fetchAccountIdentityProofs } from '../../actions/identity_proofs';
+import MissingIndicator from 'mastodon/components/missing_indicator';
 
 const emptyList = ImmutableList();
 
@@ -20,6 +21,7 @@ const mapStateToProps = (state, { params: { accountId }, withReplies = false })
   const path = withReplies ? `${accountId}:with_replies` : accountId;
 
   return {
+    isAccount: !!state.getIn(['accounts', accountId]),
     statusIds: state.getIn(['timelines', `account:${path}`, 'items'], emptyList),
     featuredStatusIds: withReplies ? ImmutableList() : state.getIn(['timelines', `account:${accountId}:pinned`, 'items'], emptyList),
     isLoading: state.getIn(['timelines', `account:${path}`, 'isLoading']),
@@ -41,6 +43,7 @@ class AccountTimeline extends ImmutablePureComponent {
     hasMore: PropTypes.bool,
     withReplies: PropTypes.bool,
     blockedBy: PropTypes.bool,
+    isAccount: PropTypes.bool,
   };
 
   componentWillMount () {
@@ -74,7 +77,15 @@ class AccountTimeline extends ImmutablePureComponent {
   }
 
   render () {
-    const { shouldUpdateScroll, statusIds, featuredStatusIds, isLoading, hasMore, blockedBy } = this.props;
+    const { shouldUpdateScroll, statusIds, featuredStatusIds, isLoading, hasMore, blockedBy, isAccount } = this.props;
+
+    if (!isAccount) {
+      return (
+        <Column>
+          <MissingIndicator />
+        </Column>
+      );
+    }
 
     if (!statusIds && isLoading) {
       return (
diff --git a/app/javascript/mastodon/features/followers/index.js b/app/javascript/mastodon/features/followers/index.js
index ce6357c4cc..e3387e1be8 100644
--- a/app/javascript/mastodon/features/followers/index.js
+++ b/app/javascript/mastodon/features/followers/index.js
@@ -16,8 +16,10 @@ import Column from '../ui/components/column';
 import HeaderContainer from '../account_timeline/containers/header_container';
 import ColumnBackButton from '../../components/column_back_button';
 import ScrollableList from '../../components/scrollable_list';
+import MissingIndicator from 'mastodon/components/missing_indicator';
 
 const mapStateToProps = (state, props) => ({
+  isAccount: !!state.getIn(['accounts', props.params.accountId]),
   accountIds: state.getIn(['user_lists', 'followers', props.params.accountId, 'items']),
   hasMore: !!state.getIn(['user_lists', 'followers', props.params.accountId, 'next']),
   blockedBy: state.getIn(['relationships', props.params.accountId, 'blocked_by'], false),
@@ -33,6 +35,7 @@ class Followers extends ImmutablePureComponent {
     accountIds: ImmutablePropTypes.list,
     hasMore: PropTypes.bool,
     blockedBy: PropTypes.bool,
+    isAccount: PropTypes.bool,
   };
 
   componentWillMount () {
@@ -52,7 +55,15 @@ class Followers extends ImmutablePureComponent {
   }, 300, { leading: true });
 
   render () {
-    const { shouldUpdateScroll, accountIds, hasMore, blockedBy } = this.props;
+    const { shouldUpdateScroll, accountIds, hasMore, blockedBy, isAccount } = this.props;
+
+    if (!isAccount) {
+      return (
+        <Column>
+          <MissingIndicator />
+        </Column>
+      );
+    }
 
     if (!accountIds) {
       return (
diff --git a/app/javascript/mastodon/features/following/index.js b/app/javascript/mastodon/features/following/index.js
index 70e7fde06a..3bf89fb2ba 100644
--- a/app/javascript/mastodon/features/following/index.js
+++ b/app/javascript/mastodon/features/following/index.js
@@ -16,8 +16,10 @@ import Column from '../ui/components/column';
 import HeaderContainer from '../account_timeline/containers/header_container';
 import ColumnBackButton from '../../components/column_back_button';
 import ScrollableList from '../../components/scrollable_list';
+import MissingIndicator from 'mastodon/components/missing_indicator';
 
 const mapStateToProps = (state, props) => ({
+  isAccount: !!state.getIn(['accounts', props.params.accountId]),
   accountIds: state.getIn(['user_lists', 'following', props.params.accountId, 'items']),
   hasMore: !!state.getIn(['user_lists', 'following', props.params.accountId, 'next']),
   blockedBy: state.getIn(['relationships', props.params.accountId, 'blocked_by'], false),
@@ -33,6 +35,7 @@ class Following extends ImmutablePureComponent {
     accountIds: ImmutablePropTypes.list,
     hasMore: PropTypes.bool,
     blockedBy: PropTypes.bool,
+    isAccount: PropTypes.bool,
   };
 
   componentWillMount () {
@@ -52,7 +55,15 @@ class Following extends ImmutablePureComponent {
   }, 300, { leading: true });
 
   render () {
-    const { shouldUpdateScroll, accountIds, hasMore, blockedBy } = this.props;
+    const { shouldUpdateScroll, accountIds, hasMore, blockedBy, isAccount } = this.props;
+
+    if (!isAccount) {
+      return (
+        <Column>
+          <MissingIndicator />
+        </Column>
+      );
+    }
 
     if (!accountIds) {
       return (

From c03f926cf373d68922ea3d3324263d38355befd9 Mon Sep 17 00:00:00 2001
From: Eugen Rochko <eugen@zeonfederated.com>
Date: Tue, 9 Apr 2019 05:04:11 +0200
Subject: [PATCH 05/16] Bump version to 2.8.0rc2 (#10501)

---
 CHANGELOG.md            | 11 +++++++++--
 lib/mastodon/version.rb |  2 +-
 2 files changed, 10 insertions(+), 3 deletions(-)

diff --git a/CHANGELOG.md b/CHANGELOG.md
index 8670c26583..6e163bee29 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -11,14 +11,14 @@ All notable changes to this project will be documented in this file.
 - Add identity proof integration with Keybase ([Gargron](https://github.com/tootsuite/mastodon/pull/10297), [xgess](https://github.com/tootsuite/mastodon/pull/10375), [Gargron](https://github.com/tootsuite/mastodon/pull/10338), [Gargron](https://github.com/tootsuite/mastodon/pull/10350), [Gargron](https://github.com/tootsuite/mastodon/pull/10414))
 - Add option to overwrite imported data instead of merging ([Gargron](https://github.com/tootsuite/mastodon/pull/9962))
 - Add featured hashtags to profiles ([Gargron](https://github.com/tootsuite/mastodon/pull/9755), [Gargron](https://github.com/tootsuite/mastodon/pull/10167), [Gargron](https://github.com/tootsuite/mastodon/pull/10249), [ThibG](https://github.com/tootsuite/mastodon/pull/10034))
-- Add admission-based registrations mode ([Gargron](https://github.com/tootsuite/mastodon/pull/10250), [ThibG](https://github.com/tootsuite/mastodon/pull/10269), [Gargron](https://github.com/tootsuite/mastodon/pull/10264), [ThibG](https://github.com/tootsuite/mastodon/pull/10321), [Gargron](https://github.com/tootsuite/mastodon/pull/10349))
+- Add admission-based registrations mode ([Gargron](https://github.com/tootsuite/mastodon/pull/10250), [ThibG](https://github.com/tootsuite/mastodon/pull/10269), [Gargron](https://github.com/tootsuite/mastodon/pull/10264), [ThibG](https://github.com/tootsuite/mastodon/pull/10321), [Gargron](https://github.com/tootsuite/mastodon/pull/10349), [Gargron](https://github.com/tootsuite/mastodon/pull/10469))
 - Add support for WebP uploads ([acid-chicken](https://github.com/tootsuite/mastodon/pull/9879))
 - Add "copy link" item to status action bars in web UI ([Gargron](https://github.com/tootsuite/mastodon/pull/9983))
 - Add list title editing in web UI ([ThibG](https://github.com/tootsuite/mastodon/pull/9748))
 - Add a "Block & Report" button to the block confirmation dialog in web UI ([ThibG](https://github.com/tootsuite/mastodon/pull/10360))
 - Add disappointed elephant when the page crashes in web UI ([Gargron](https://github.com/tootsuite/mastodon/pull/10275))
 - Add ability to upload multiple files at once in web UI ([tmm576](https://github.com/tootsuite/mastodon/pull/9856))
-- Add indication that you have been blocked when viewing profiles in web UI ([Gargron](https://github.com/tootsuite/mastodon/pull/10420))
+- Add indication when you are not allowed to follow an account in web UI ([Gargron](https://github.com/tootsuite/mastodon/pull/10420), [Gargron](https://github.com/tootsuite/mastodon/pull/10491))
 - Add validations to admin settings to catch common mistakes ([Gargron](https://github.com/tootsuite/mastodon/pull/10348), [ThibG](https://github.com/tootsuite/mastodon/pull/10354))
 - Add `type`, `limit`, `offset`, `min_id`, `max_id`, `account_id` to search API ([Gargron](https://github.com/tootsuite/mastodon/pull/10091))
 - Add a preferences API so apps can share basic behaviours ([Gargron](https://github.com/tootsuite/mastodon/pull/10109))
@@ -32,6 +32,10 @@ All notable changes to this project will be documented in this file.
 - Add `DB_SSLMODE` configuration variable ([sascha-sl](https://github.com/tootsuite/mastodon/pull/10210))
 - Add click-to-copy UI to invites page ([Gargron](https://github.com/tootsuite/mastodon/pull/10259))
 - Add self-replies fetching ([ThibG](https://github.com/tootsuite/mastodon/pull/10106), [ThibG](https://github.com/tootsuite/mastodon/pull/10128), [ThibG](https://github.com/tootsuite/mastodon/pull/10175), [ThibG](https://github.com/tootsuite/mastodon/pull/10201))
+- Add rate limit for media proxy requests ([Gargron](https://github.com/tootsuite/mastodon/pull/10490))
+- Add `tootctl emoji purge` ([Gargron](https://github.com/tootsuite/mastodon/pull/10481))
+- Add `tootctl accounts approve` ([Gargron](https://github.com/tootsuite/mastodon/pull/10480))
+- Add `tootctl accounts reset-relationships` ([noellabo](https://github.com/tootsuite/mastodon/pull/10483))
 
 ### Changed
 
@@ -51,6 +55,9 @@ All notable changes to this project will be documented in this file.
 - Change web UI to use new Web Share Target API ([gol-cha](https://github.com/tootsuite/mastodon/pull/9963))
 - Change ActivityPub reports to have persistent URIs ([ThibG](https://github.com/tootsuite/mastodon/pull/10303))
 - Change `tootctl accounts cull --dry-run` to list accounts that would be deleted ([BenLubar](https://github.com/tootsuite/mastodon/pull/10460))
+- Change format of CSV exports of follows and mutes to include extra settings ([ThibG](https://github.com/tootsuite/mastodon/pull/10495), [ThibG](https://github.com/tootsuite/mastodon/pull/10335))
+- Change ActivityPub collections to be cacheable by proxies ([ThibG](https://github.com/tootsuite/mastodon/pull/10467))
+- Change REST API and public profiles to not return follows/followers for users that have blocked you ([Gargron](https://github.com/tootsuite/mastodon/pull/10491))
 
 ### Removed
 
diff --git a/lib/mastodon/version.rb b/lib/mastodon/version.rb
index d6114320e5..859850d15f 100644
--- a/lib/mastodon/version.rb
+++ b/lib/mastodon/version.rb
@@ -21,7 +21,7 @@ module Mastodon
     end
 
     def flags
-      'rc1'
+      'rc2'
     end
 
     def to_a

From 654f79d2b1f70324a756a1d981e48fcaa8245531 Mon Sep 17 00:00:00 2001
From: Eugen Rochko <eugen@zeonfederated.com>
Date: Tue, 9 Apr 2019 07:19:52 +0200
Subject: [PATCH 06/16] Fix permission denied bug on approve all/reject all
 pending accounts (#10519)

---
 app/controllers/admin/pending_accounts_controller.rb | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/app/controllers/admin/pending_accounts_controller.rb b/app/controllers/admin/pending_accounts_controller.rb
index f145108b34..2ea7785fc0 100644
--- a/app/controllers/admin/pending_accounts_controller.rb
+++ b/app/controllers/admin/pending_accounts_controller.rb
@@ -18,12 +18,12 @@ module Admin
     end
 
     def approve_all
-      Form::AccountBatch.new(account_ids: User.pending.pluck(:account_id), action: 'approve').save
+      Form::AccountBatch.new(current_account: current_account, account_ids: User.pending.pluck(:account_id), action: 'approve').save
       redirect_to admin_pending_accounts_path(current_params)
     end
 
     def reject_all
-      Form::AccountBatch.new(account_ids: User.pending.pluck(:account_id), action: 'reject').save
+      Form::AccountBatch.new(current_account: current_account, account_ids: User.pending.pluck(:account_id), action: 'reject').save
       redirect_to admin_pending_accounts_path(current_params)
     end
 

From 819d053be8fa3546b7f6dfb21adecf76ed8ed5e9 Mon Sep 17 00:00:00 2001
From: "dependabot[bot]" <dependabot[bot]@users.noreply.github.com>
Date: Tue, 9 Apr 2019 17:23:18 +0900
Subject: [PATCH 07/16] Bump bootsnap from 1.4.2 to 1.4.3 (#10523)

Bumps [bootsnap](https://github.com/Shopify/bootsnap) from 1.4.2 to 1.4.3.
- [Release notes](https://github.com/Shopify/bootsnap/releases)
- [Changelog](https://github.com/Shopify/bootsnap/blob/master/CHANGELOG.md)
- [Commits](https://github.com/Shopify/bootsnap/compare/v1.4.2...v1.4.3)

Signed-off-by: dependabot[bot] <support@dependabot.com>
---
 Gemfile.lock | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/Gemfile.lock b/Gemfile.lock
index ee7e58dd00..c0cf991f6c 100644
--- a/Gemfile.lock
+++ b/Gemfile.lock
@@ -99,7 +99,7 @@ GEM
       rack (>= 0.9.0)
     binding_of_caller (0.8.0)
       debug_inspector (>= 0.0.1)
-    bootsnap (1.4.2)
+    bootsnap (1.4.3)
       msgpack (~> 1.0)
     brakeman (4.5.0)
     browser (2.5.3)

From 0f3719f16fb5a2704416fa3afae00ba767ad2b2c Mon Sep 17 00:00:00 2001
From: "dependabot[bot]" <dependabot[bot]@users.noreply.github.com>
Date: Tue, 9 Apr 2019 17:23:52 +0900
Subject: [PATCH 08/16] Bump hamlit-rails from 0.2.2 to 0.2.3 (#10522)

Bumps [hamlit-rails](https://github.com/mfung/hamlit-rails) from 0.2.2 to 0.2.3.
- [Release notes](https://github.com/mfung/hamlit-rails/releases)
- [Commits](https://github.com/mfung/hamlit-rails/compare/v0.2.2...v0.2.3)

Signed-off-by: dependabot[bot] <support@dependabot.com>
---
 Gemfile.lock | 8 ++++----
 1 file changed, 4 insertions(+), 4 deletions(-)

diff --git a/Gemfile.lock b/Gemfile.lock
index c0cf991f6c..afe403dec5 100644
--- a/Gemfile.lock
+++ b/Gemfile.lock
@@ -240,11 +240,11 @@ GEM
       http (~> 3.0)
       nokogiri (~> 1.8)
       oj (~> 3.0)
-    hamlit (2.9.2)
+    hamlit (2.9.3)
       temple (>= 0.8.0)
       thor
       tilt
-    hamlit-rails (0.2.2)
+    hamlit-rails (0.2.3)
       actionpack (>= 4.0.1)
       activesupport (>= 4.0.1)
       hamlit (>= 1.2.0)
@@ -424,7 +424,7 @@ GEM
     pundit (2.0.1)
       activesupport (>= 3.0.0)
     raabro (1.1.6)
-    rack (2.0.6)
+    rack (2.0.7)
     rack-attack (5.4.2)
       rack (>= 1.0, < 3)
     rack-cors (1.0.3)
@@ -595,7 +595,7 @@ GEM
       multi_json (~> 1.8)
     strong_migrations (0.3.1)
       activerecord (>= 3.2.0)
-    temple (0.8.0)
+    temple (0.8.1)
     terminal-table (1.8.0)
       unicode-display_width (~> 1.1, >= 1.1.1)
     terrapin (0.6.0)

From 8b69a66380bbe32127e717ca2d79244392b7d2b6 Mon Sep 17 00:00:00 2001
From: Eugen Rochko <eugen@zeonfederated.com>
Date: Tue, 9 Apr 2019 16:06:30 +0200
Subject: [PATCH 09/16] Add "why do you want to join" field to invite requests
 (#10524)

* Add "why do you want to join" field to invite requests

Fix #10512

* Remove unused translations

* Fix broken registrations when no invite request text is submitted
---
 app/controllers/about_controller.rb           |  5 +++-
 .../admin/pending_accounts_controller.rb      |  2 +-
 .../auth/registrations_controller.rb          | 14 ++++++----
 app/javascript/styles/mastodon/accounts.scss  | 26 +++++++++++++++++++
 app/javascript/styles/mastodon/widgets.scss   |  9 +++++++
 app/models/user.rb                            |  3 +++
 app/models/user_invite_request.rb             | 17 ++++++++++++
 app/views/about/_registration.html.haml       |  5 ++++
 .../admin/pending_accounts/_account.html.haml | 22 ++++++++--------
 app/views/auth/registrations/new.html.haml    |  9 ++++++-
 config/locales/ar.yml                         |  1 -
 config/locales/ast.yml                        |  1 -
 config/locales/ca.yml                         |  1 -
 config/locales/co.yml                         |  1 -
 config/locales/cs.yml                         |  1 -
 config/locales/cy.yml                         |  1 -
 config/locales/da.yml                         |  1 -
 config/locales/de.yml                         |  1 -
 config/locales/el.yml                         |  1 -
 config/locales/en.yml                         |  1 -
 config/locales/en_GB.yml                      |  1 -
 config/locales/eo.yml                         |  1 -
 config/locales/es.yml                         |  1 -
 config/locales/eu.yml                         |  1 -
 config/locales/fa.yml                         |  1 -
 config/locales/fi.yml                         |  1 -
 config/locales/fr.yml                         |  1 -
 config/locales/gl.yml                         |  1 -
 config/locales/hu.yml                         |  1 -
 config/locales/it.yml                         |  1 -
 config/locales/ja.yml                         |  1 -
 config/locales/ka.yml                         |  1 -
 config/locales/kk.yml                         |  1 -
 config/locales/ko.yml                         |  1 -
 config/locales/lt.yml                         |  1 -
 config/locales/nl.yml                         |  1 -
 config/locales/no.yml                         |  1 -
 config/locales/oc.yml                         |  1 -
 config/locales/pl.yml                         |  1 -
 config/locales/pt-BR.yml                      |  1 -
 config/locales/pt.yml                         |  1 -
 config/locales/ro.yml                         |  1 -
 config/locales/ru.yml                         |  1 -
 config/locales/simple_form.en.yml             |  4 +++
 config/locales/sk.yml                         |  1 -
 config/locales/sq.yml                         |  1 -
 config/locales/sr-Latn.yml                    |  1 -
 config/locales/sr.yml                         |  1 -
 config/locales/sv.yml                         |  1 -
 config/locales/uk.yml                         |  1 -
 config/locales/zh-CN.yml                      |  1 -
 config/locales/zh-HK.yml                      |  1 -
 config/locales/zh-TW.yml                      |  1 -
 ...90409054914_create_user_invite_requests.rb | 10 +++++++
 db/schema.rb                                  | 11 +++++++-
 .../user_invite_request_fabricator.rb         |  4 +++
 spec/models/user_invite_request_spec.rb       |  4 +++
 57 files changed, 125 insertions(+), 62 deletions(-)
 create mode 100644 app/models/user_invite_request.rb
 create mode 100644 db/migrate/20190409054914_create_user_invite_requests.rb
 create mode 100644 spec/fabricators/user_invite_request_fabricator.rb
 create mode 100644 spec/models/user_invite_request_spec.rb

diff --git a/app/controllers/about_controller.rb b/app/controllers/about_controller.rb
index 67bb2c87fa..52a51fd62e 100644
--- a/app/controllers/about_controller.rb
+++ b/app/controllers/about_controller.rb
@@ -16,7 +16,10 @@ class AboutController < ApplicationController
   private
 
   def new_user
-    User.new.tap(&:build_account)
+    User.new.tap do |user|
+      user.build_account
+      user.build_invite_request
+    end
   end
 
   helper_method :new_user
diff --git a/app/controllers/admin/pending_accounts_controller.rb b/app/controllers/admin/pending_accounts_controller.rb
index 2ea7785fc0..249525504b 100644
--- a/app/controllers/admin/pending_accounts_controller.rb
+++ b/app/controllers/admin/pending_accounts_controller.rb
@@ -30,7 +30,7 @@ module Admin
     private
 
     def set_accounts
-      @accounts = Account.joins(:user).merge(User.pending).page(params[:page])
+      @accounts = Account.joins(:user).merge(User.pending).includes(user: :invite_request).page(params[:page])
     end
 
     def form_account_batch_params
diff --git a/app/controllers/auth/registrations_controller.rb b/app/controllers/auth/registrations_controller.rb
index 16a3ec67ad..5c1ff769a8 100644
--- a/app/controllers/auth/registrations_controller.rb
+++ b/app/controllers/auth/registrations_controller.rb
@@ -10,6 +10,10 @@ class Auth::RegistrationsController < Devise::RegistrationsController
   before_action :set_instance_presenter, only: [:new, :create, :update]
   before_action :set_body_classes, only: [:new, :create, :edit, :update]
 
+  def new
+    super(&:build_invite_request)
+  end
+
   def destroy
     not_found
   end
@@ -24,17 +28,17 @@ class Auth::RegistrationsController < Devise::RegistrationsController
   def build_resource(hash = nil)
     super(hash)
 
-    resource.locale      = I18n.locale
-    resource.invite_code = params[:invite_code] if resource.invite_code.blank?
-    resource.agreement   = true
+    resource.locale             = I18n.locale
+    resource.invite_code        = params[:invite_code] if resource.invite_code.blank?
+    resource.agreement          = true
+    resource.current_sign_in_ip = request.remote_ip
 
-    resource.current_sign_in_ip = request.remote_ip if resource.current_sign_in_ip.nil?
     resource.build_account if resource.account.nil?
   end
 
   def configure_sign_up_params
     devise_parameter_sanitizer.permit(:sign_up) do |u|
-      u.permit({ account_attributes: [:username] }, :email, :password, :password_confirmation, :invite_code)
+      u.permit({ account_attributes: [:username], invite_request_attributes: [:text] }, :email, :password, :password_confirmation, :invite_code)
     end
   end
 
diff --git a/app/javascript/styles/mastodon/accounts.scss b/app/javascript/styles/mastodon/accounts.scss
index f4f458cf42..a790251f48 100644
--- a/app/javascript/styles/mastodon/accounts.scss
+++ b/app/javascript/styles/mastodon/accounts.scss
@@ -292,3 +292,29 @@
 .directory__tag .trends__item__current {
   width: auto;
 }
+
+.pending-account {
+  &__header {
+    color: $darker-text-color;
+
+    a {
+      color: $ui-secondary-color;
+      text-decoration: none;
+
+      &:hover,
+      &:active,
+      &:focus {
+        text-decoration: underline;
+      }
+    }
+
+    strong {
+      color: $primary-text-color;
+      font-weight: 700;
+    }
+  }
+
+  &__body {
+    margin-top: 10px;
+  }
+}
diff --git a/app/javascript/styles/mastodon/widgets.scss b/app/javascript/styles/mastodon/widgets.scss
index 307e509d59..e736d7a7ef 100644
--- a/app/javascript/styles/mastodon/widgets.scss
+++ b/app/javascript/styles/mastodon/widgets.scss
@@ -377,6 +377,10 @@
     border: 0;
   }
 
+  strong {
+    font-weight: 700;
+  }
+
   thead th {
     text-align: center;
     text-transform: uppercase;
@@ -414,6 +418,11 @@
     }
   }
 
+  &__comment {
+    width: 50%;
+    vertical-align: initial !important;
+  }
+
   @media screen and (max-width: $no-gap-breakpoint) {
     tbody td.optional {
       display: none;
diff --git a/app/models/user.rb b/app/models/user.rb
index d703f95889..c9309bc216 100644
--- a/app/models/user.rb
+++ b/app/models/user.rb
@@ -74,6 +74,9 @@ class User < ApplicationRecord
   has_many :applications, class_name: 'Doorkeeper::Application', as: :owner
   has_many :backups, inverse_of: :user
 
+  has_one :invite_request, class_name: 'UserInviteRequest', inverse_of: :user, dependent: :destroy
+  accepts_nested_attributes_for :invite_request, reject_if: ->(attributes) { attributes['text'].blank? }
+
   validates :locale, inclusion: I18n.available_locales.map(&:to_s), if: :locale?
   validates_with BlacklistedEmailValidator, if: :email_changed?
   validates_with EmailMxValidator, if: :validate_email_dns?
diff --git a/app/models/user_invite_request.rb b/app/models/user_invite_request.rb
new file mode 100644
index 0000000000..2b76c88b94
--- /dev/null
+++ b/app/models/user_invite_request.rb
@@ -0,0 +1,17 @@
+# frozen_string_literal: true
+
+# == Schema Information
+#
+# Table name: user_invite_requests
+#
+#  id         :bigint(8)        not null, primary key
+#  user_id    :bigint(8)
+#  text       :text
+#  created_at :datetime         not null
+#  updated_at :datetime         not null
+#
+
+class UserInviteRequest < ApplicationRecord
+  belongs_to :user, inverse_of: :invite_request
+  validates :text, presence: true, length: { maximum: 420 }
+end
diff --git a/app/views/about/_registration.html.haml b/app/views/about/_registration.html.haml
index 09cbe2e289..ff32ec8c46 100644
--- a/app/views/about/_registration.html.haml
+++ b/app/views/about/_registration.html.haml
@@ -10,6 +10,11 @@
       = f.input :password, placeholder: t('simple_form.labels.defaults.password'), required: true, input_html: { 'aria-label' => t('simple_form.labels.defaults.password'), :autocomplete => 'off' }, hint: false, disabled: closed_registrations?
       = f.input :password_confirmation, placeholder: t('simple_form.labels.defaults.confirm_password'), required: true, input_html: { 'aria-label' => t('simple_form.labels.defaults.confirm_password'), :autocomplete => 'off' }, hint: false, disabled: closed_registrations?
 
+    - if approved_registrations?
+      .fields-group
+        = f.simple_fields_for :invite_request do |invite_request_fields|
+          = invite_request_fields.input :text, as: :text, wrapper: :with_block_label, required: false
+
     .fields-group
       = f.input :agreement, as: :boolean, wrapper: :with_label, label: t('auth.checkbox_agreement_html', rules_path: about_more_path, terms_path: terms_path), disabled: closed_registrations?
 
diff --git a/app/views/admin/pending_accounts/_account.html.haml b/app/views/admin/pending_accounts/_account.html.haml
index c520dc065a..1ed5dafdd4 100644
--- a/app/views/admin/pending_accounts/_account.html.haml
+++ b/app/views/admin/pending_accounts/_account.html.haml
@@ -1,14 +1,14 @@
 .batch-table__row
   %label.batch-table__row__select.batch-table__row__select--aligned.batch-checkbox
     = f.check_box :account_ids, { multiple: true, include_hidden: false }, account.id
-  .batch-table__row__content.batch-table__row__content--unpadded
-    %table.accounts-table
-      %tbody
-        %tr
-          %td
-            = account.user_email
-            = "(@#{account.username})"
-            %br/
-            = account.user_current_sign_in_ip
-          %td.accounts-table__count
-            = table_link_to 'pencil', t('admin.accounts.edit'), admin_account_path(account.id)
+  .batch-table__row__content.pending-account
+    .pending-account__header
+      = link_to admin_account_path(account.id) do
+        %strong= account.user_email
+        = "(@#{account.username})"
+      %br/
+      = account.user_current_sign_in_ip
+
+    - if account.user&.invite_request&.text&.present?
+      .pending-account__body
+        %p= account.user&.invite_request&.text
diff --git a/app/views/auth/registrations/new.html.haml b/app/views/auth/registrations/new.html.haml
index 1caf2b4016..bd6e3a13f7 100644
--- a/app/views/auth/registrations/new.html.haml
+++ b/app/views/auth/registrations/new.html.haml
@@ -21,12 +21,19 @@
 
   .fields-group
     = f.input :password, wrapper: :with_label, label: t('simple_form.labels.defaults.password'), required: true, input_html: { 'aria-label' => t('simple_form.labels.defaults.password'), :autocomplete => 'off' }
+
   .fields-group
     = f.input :password_confirmation, wrapper: :with_label, label: t('simple_form.labels.defaults.confirm_password'), required: true, input_html: { 'aria-label' => t('simple_form.labels.defaults.confirm_password'), :autocomplete => 'off' }
 
+  - if approved_registrations? && !@invite.present?
+    .fields-group
+      = f.simple_fields_for :invite_request do |invite_request_fields|
+        = invite_request_fields.input :text, as: :text, wrapper: :with_block_label, required: false
+
   = f.input :invite_code, as: :hidden
 
-  %p.hint= t('auth.agreement_html', rules_path: about_more_path, terms_path: terms_path)
+  .fields-group
+    = f.input :agreement, as: :boolean, wrapper: :with_label, label: t('auth.checkbox_agreement_html', rules_path: about_more_path, terms_path: terms_path)
 
   .actions
     = f.button :button, sign_up_message, type: :submit
diff --git a/config/locales/ar.yml b/config/locales/ar.yml
index d409ad99ac..e0ccb63a94 100644
--- a/config/locales/ar.yml
+++ b/config/locales/ar.yml
@@ -498,7 +498,6 @@ ar:
     warning: كن حذرا مع هذه البيانات. لا تقم أبدا بمشاركتها مع الآخَرين !
     your_token: رمز نفاذك
   auth:
-    agreement_html: بمجرد النقر على "التسجيل" أسفله، فإنك تُصرِّح قبول <a href="%{rules_path}">قواعد مثيل الخادوم</a> و <a href="%{terms_path}">شروط الخدمة التي نوفرها لك</a>.
     change_password: الكلمة السرية
     confirm_email: تأكيد عنوان البريد الإلكتروني
     delete_account: حذف حساب
diff --git a/config/locales/ast.yml b/config/locales/ast.yml
index cbfd27b047..f6892923c1 100644
--- a/config/locales/ast.yml
+++ b/config/locales/ast.yml
@@ -123,7 +123,6 @@ ast:
     invalid_url: La URL apurrida nun ye válida
     warning: Ten curiáu con estos datos, ¡enxamás nun los compartas con naide!
   auth:
-    agreement_html: Faciendo clic en «Aniciar sesión» aceutes siguir <a href="%{rules_path}"> les regles de la instancia</a> y <a href="%{terms_path}">los nuesos términos del serviciu</a>.
     change_password: Contraseña
     delete_account: Desaniciu de la cuenta
     delete_account_html: Si deseyes desaniciar la to cuenta, pues <a href="%{path}">siguir equí</a>. Va pidísete la confirmación.
diff --git a/config/locales/ca.yml b/config/locales/ca.yml
index c6ab35cb6b..5fd2ff8234 100644
--- a/config/locales/ca.yml
+++ b/config/locales/ca.yml
@@ -507,7 +507,6 @@ ca:
     warning: Aneu amb compte amb aquestes dades. No les compartiu mai amb ningú!
     your_token: El teu identificador d'accés
   auth:
-    agreement_html: Al fer clic en "Registre" acceptes respectar <a href="%{rules_path}">les normes del servidor</a> i <a href="%{terms_path}">els nostres termes del servei</a>.
     apply_for_account: Demana una invitació
     change_password: Contrasenya
     checkbox_agreement_html: Estic d'acord amb les <a href="%{rules_path}" target="_blank">normes del servidor</a> i <a href="%{terms_path}" target="_blank"> els termes del servei</a>
diff --git a/config/locales/co.yml b/config/locales/co.yml
index c751c80f0e..c4122b6d94 100644
--- a/config/locales/co.yml
+++ b/config/locales/co.yml
@@ -513,7 +513,6 @@ co:
     warning: Abbadate à quessi dati. Ùn i date à nisunu!
     your_token: Rigenerà a fiscia d’accessu
   auth:
-    agreement_html: Cliccà "Arregistrassi" quì sottu vole dì chì site d’accunsentu per siguità <a href="%{rules_path}">e regule di u servore</a> è <a href="%{terms_path}">e cundizione d’usu</a>.
     apply_for_account: Dumandà un'invitazione
     change_password: Chjave d’accessu
     checkbox_agreement_html: Sò d'accunsentu cù e <a href="%{rules_path}" target="_blank">regule di u servore</a> è i <a href="%{terms_path}" target="_blank">termini di u serviziu</a>
diff --git a/config/locales/cs.yml b/config/locales/cs.yml
index 15cc025f23..7917166de7 100644
--- a/config/locales/cs.yml
+++ b/config/locales/cs.yml
@@ -518,7 +518,6 @@ cs:
     warning: Buďte s těmito daty velmi opatrní. Nikdy je s nikým nesdílejte!
     your_token: Váš přístupový token
   auth:
-    agreement_html: Kliknutím na tlačítko „Registrovat“ souhlasíte s následováním <a href="%{rules_path}">pravidel tohoto serveru</a> a <a href="%{terms_path}">našich podmínek používání</a>.
     apply_for_account: Vyžádat si pozvánku
     change_password: Heslo
     checkbox_agreement_html: Souhlasím s <a href="%{rules_path}" target="_blank">pravidly serveru</a> a <a href="%{terms_path}" target="_blank">podmínkami používání</a>
diff --git a/config/locales/cy.yml b/config/locales/cy.yml
index 68a445e4ca..9ab4fc394e 100644
--- a/config/locales/cy.yml
+++ b/config/locales/cy.yml
@@ -506,7 +506,6 @@ cy:
     warning: Byddwch yn ofalus a'r data hyn. Peidiwch a'i rannu byth!
     your_token: Eich tocyn mynediad
   auth:
-    agreement_html: Wrth glicio "Cofrestru" isod yr ydych yn cytuno i ddilyn <a href="%{rules_path}">y rheolau ar gyfer yr achos hwn</a> a <a href="%{terms_path}">ein termau gwasanaeth</a>.
     change_password: Cyfrinair
     confirm_email: Cadarnhau e-bost
     delete_account: Dileu cyfrif
diff --git a/config/locales/da.yml b/config/locales/da.yml
index 88bf05d172..2156acb443 100644
--- a/config/locales/da.yml
+++ b/config/locales/da.yml
@@ -432,7 +432,6 @@ da:
     warning: Vær meget forsigtig med disse data. Del dem aldrig med nogen!
     your_token: Din adgangs token
   auth:
-    agreement_html: Ved at oprette dig erklærer du dig enig i at følge <a href="%{rules_path}">serverens regler</a> og <a href="%{terms_path}">vores servicevilkår</a>.
     change_password: Kodeord
     confirm_email: Bekræft email
     delete_account: Slet konto
diff --git a/config/locales/de.yml b/config/locales/de.yml
index 5b51f9d852..cfe527b0a6 100644
--- a/config/locales/de.yml
+++ b/config/locales/de.yml
@@ -511,7 +511,6 @@ de:
     warning: Sei mit diesen Daten sehr vorsichtig. Teile sie mit niemandem!
     your_token: Dein Zugangs-Token
   auth:
-    agreement_html: Indem du dich registrierst, erklärst du dich mit den untenstehenden <a href="%{rules_path}">Regeln des Servers</a> und der <a href="%{terms_path}">Datenschutzerklärung</a> einverstanden.
     apply_for_account: Eine Einladung anfragen
     change_password: Passwort
     checkbox_agreement_html: Ich akzeptiere die <a href="%{rules_path}" target="_blank">Server-Regeln</a> und die <a href="%{terms_path}" target="_blank">Nutzungsbedingungen</a>
diff --git a/config/locales/el.yml b/config/locales/el.yml
index b8fd45a685..8ff42acbfe 100644
--- a/config/locales/el.yml
+++ b/config/locales/el.yml
@@ -506,7 +506,6 @@ el:
     warning: Μεγάλη προσοχή με αυτά τα στοιχεία. Μην τα μοιραστείς ποτέ με κανέναν!
     your_token: Το διακριτικό πρόσβασής σου (access token)
   auth:
-    agreement_html: Επιλέγοντας το "Εγγραφή", συμφωνείς πως δέχεσαι <a href="%{rules_path}">τους κανόνες αυτού του κόμβου</a> και <a href="%{terms_path}">τους όρους χρήσης του</a>.
     apply_for_account: Αίτηση πρόσκλησης
     change_password: Συνθηματικό
     checkbox_agreement_html: Συμφωνώ με τους <a href="%{rules_path}" target="_blank">κανονισμούς του κόμβου</a> και <a href="%{terms_path}" target="_blank">τους όρους χρήσης</a>
diff --git a/config/locales/en.yml b/config/locales/en.yml
index 139803affb..60540ecdce 100644
--- a/config/locales/en.yml
+++ b/config/locales/en.yml
@@ -513,7 +513,6 @@ en:
     warning: Be very careful with this data. Never share it with anyone!
     your_token: Your access token
   auth:
-    agreement_html: By clicking "Sign up" below you agree to follow <a href="%{rules_path}">the rules of the server</a> and <a href="%{terms_path}">our terms of service</a>.
     apply_for_account: Request an invite
     change_password: Password
     checkbox_agreement_html: I agree to the <a href="%{rules_path}" target="_blank">server rules</a> and <a href="%{terms_path}" target="_blank">terms of service</a>
diff --git a/config/locales/en_GB.yml b/config/locales/en_GB.yml
index 9e6eb5e949..743989879e 100644
--- a/config/locales/en_GB.yml
+++ b/config/locales/en_GB.yml
@@ -506,7 +506,6 @@ en_GB:
     warning: Be very careful with this data. Never share it with anyone!
     your_token: Your access token
   auth:
-    agreement_html: By clicking "Sign up" below you agree to follow <a href="%{rules_path}">the rules of the server</a> and <a href="%{terms_path}">our terms of service</a>.
     apply_for_account: Request an invite
     change_password: Password
     checkbox_agreement_html: I agree to the <a href="%{rules_path}" target="_blank">server rules</a> and <a href="%{terms_path}" target="_blank">terms of service</a>
diff --git a/config/locales/eo.yml b/config/locales/eo.yml
index dcbf0065b0..cce32cc561 100644
--- a/config/locales/eo.yml
+++ b/config/locales/eo.yml
@@ -507,7 +507,6 @@ eo:
     warning: Estu tre atenta kun ĉi tiu datumo. Neniam diskonigu ĝin al iu ajn!
     your_token: Via alira ĵetono
   auth:
-    agreement_html: Klakante “Registriĝi” sube, vi konsentas kun <a href="%{rules_path}">la reguloj de la servilo</a> kaj <a href="%{terms_path}">niaj uzkondiĉoj</a>.
     apply_for_account: Peti inviton
     change_password: Pasvorto
     checkbox_agreement_html: Mi samopinii al la <a href="%{rules_path}" target="_blank">Servo reguloj</a> kaj <a href="%{terms_path}" target="_blank">kondiĉo al servadon</a>
diff --git a/config/locales/es.yml b/config/locales/es.yml
index bcc3fe62ca..c0b6cfb3b5 100644
--- a/config/locales/es.yml
+++ b/config/locales/es.yml
@@ -437,7 +437,6 @@ es:
     warning: Ten mucho cuidado con estos datos. ¡No los compartas con nadie!
     your_token: Tu token de acceso
   auth:
-    agreement_html: Al hacer click en "Registrarse" acepta seguir <a href="%{rules_path}">las reglas de la instancia</a> y <a href="%{terms_path}">nuestros términos de servicio</a>.
     change_password: Contraseña
     confirm_email: Confirmar email
     delete_account: Borrar cuenta
diff --git a/config/locales/eu.yml b/config/locales/eu.yml
index 187a5325b1..50e5b66394 100644
--- a/config/locales/eu.yml
+++ b/config/locales/eu.yml
@@ -481,7 +481,6 @@ eu:
     warning: Kontuz datu hauekin, ez partekatu inoiz inorekin!
     your_token: Zure sarbide token-a
   auth:
-    agreement_html: '"Izena eman" botoia sakatzean <a href="%{rules_path}">zerbitzariaren arauak</a> eta <a href="%{terms_path}">erabilera baldintzak</a> onartzen dituzu.'
     change_password: Pasahitza
     confirm_email: Berretsi e-mail helbidea
     delete_account: Ezabatu kontua
diff --git a/config/locales/fa.yml b/config/locales/fa.yml
index d4ec320cbf..0cf3809218 100644
--- a/config/locales/fa.yml
+++ b/config/locales/fa.yml
@@ -506,7 +506,6 @@ fa:
     warning: خیلی مواظب این اطلاعات باشید و آن را به هیچ کس ندهید!
     your_token: کد دسترسی شما
   auth:
-    agreement_html: با کلیک روی دکمهٔ عضو شدن، شما <a href="%{rules_path}">قوانین این سرور</a> و <a href="%{terms_path}">شرایط استفادهٔ</a> ما را می‌پذیرید.
     apply_for_account: درخواست دعوت‌نامه
     change_password: رمز
     checkbox_agreement_html: من <a href="%{rules_path}" target="_blank">قانون‌های این سرور</a> و <a href="%{terms_path}" target="_blank">شرایط کاربری</a> را می‌پذیرم
diff --git a/config/locales/fi.yml b/config/locales/fi.yml
index 029696f7de..47ff00434e 100644
--- a/config/locales/fi.yml
+++ b/config/locales/fi.yml
@@ -370,7 +370,6 @@ fi:
     warning: Säilytä tietoa hyvin. Älä milloinkaan jaa sitä muille!
     your_token: Pääsytunnus
   auth:
-    agreement_html: Rekisteröityessäsi sitoudut noudattamaan <a href="%{rules_path}">instanssin sääntöjä</a> ja <a href="%{terms_path}">käyttöehtoja</a>.
     change_password: Salasana
     confirm_email: Vahvista sähköpostiosoite
     delete_account: Poista tili
diff --git a/config/locales/fr.yml b/config/locales/fr.yml
index 421ba1da9f..f1d81acf02 100644
--- a/config/locales/fr.yml
+++ b/config/locales/fr.yml
@@ -482,7 +482,6 @@ fr:
     warning: Soyez prudent⋅e avec ces données. Ne les partagez pas !
     your_token: Votre jeton d’accès
   auth:
-    agreement_html: En cliquant sur "S'inscrire" ci-dessous, vous souscrivez <a href="%{rules_path}">aux règles du serveur</a> et à <a href="%{terms_path}">nos conditions d’utilisation</a>.
     change_password: Mot de passe
     confirm_email: Confirmer mon adresse mail
     delete_account: Supprimer le compte
diff --git a/config/locales/gl.yml b/config/locales/gl.yml
index 32f642e16c..0ee3a329ca 100644
--- a/config/locales/gl.yml
+++ b/config/locales/gl.yml
@@ -506,7 +506,6 @@ gl:
     warning: Teña moito tino con estos datos. Nunca os comparta con ninguén!
     your_token: O seu testemuño de acceso
   auth:
-    agreement_html: Ao pulsar "Rexistrar" vostede acorda seguir <a href="%{rules_path}">as normas do servidor</a> e <a href="%{terms_path}">os termos do servizo</a>.
     apply_for_account: Solicite un convite
     change_password: Contrasinal
     checkbox_agreement_html: Acepto as <a href="%{rules_path}" target="_blank">regras do servidor</a> e os <a href="%{terms_path}" target="_blank">termos do servizo</a>
diff --git a/config/locales/hu.yml b/config/locales/hu.yml
index 04318f5e44..f32f6f4079 100644
--- a/config/locales/hu.yml
+++ b/config/locales/hu.yml
@@ -309,7 +309,6 @@ hu:
     warning: Ez érzékeny adat. Soha ne oszd meg másokkal!
     your_token: Hozzáférési kulcsod
   auth:
-    agreement_html: A feliratkozással elfogatod az <a href="%{rules_path}">instancia szabályzatát</a> és a <a href="%{terms_path}">felhasználási feltételeket</a>.
     delete_account: Felhasználói fiók törlése
     delete_account_html: Felhasználói fiókod törléséhez <a href="%{path}">kattints ide</a>. A rendszer újbóli megerősítést fog kérni.
     didnt_get_confirmation: Nem kaptad meg a megerősítési lépéseket?
diff --git a/config/locales/it.yml b/config/locales/it.yml
index 384ba918bd..bb170bc4a2 100644
--- a/config/locales/it.yml
+++ b/config/locales/it.yml
@@ -467,7 +467,6 @@ it:
     token_regenerated: Token di accesso rigenerato
     warning: Fa' molta attenzione con questi dati. Non fornirli mai a nessun altro!
   auth:
-    agreement_html: Iscrivendoti, accetti di seguire <a href="%{rules_path}">le regole del server</a> e <a href="%{terms_path}"> le nostre condizioni di servizio</a>.
     change_password: Password
     confirm_email: Conferma email
     delete_account: Elimina account
diff --git a/config/locales/ja.yml b/config/locales/ja.yml
index f68df97106..85e97580e8 100644
--- a/config/locales/ja.yml
+++ b/config/locales/ja.yml
@@ -512,7 +512,6 @@ ja:
     warning: このデータは気をつけて取り扱ってください。他の人と共有しないでください!
     your_token: アクセストークン
   auth:
-    agreement_html: 登録するをクリックすると <a href="%{rules_path}">サーバーのルール</a> と <a href="%{terms_path}">プライバシーポリシー</a> に従うことに同意したことになります。
     apply_for_account: 登録を申請する
     change_password: パスワード
     checkbox_agreement_html: <a href="%{rules_path}" target="_blank">サーバーのルール</a> と <a href="%{terms_path}" target="_blank">プライバシーポリシー</a> に同意します
diff --git a/config/locales/ka.yml b/config/locales/ka.yml
index 8e537c745a..758a0429e3 100644
--- a/config/locales/ka.yml
+++ b/config/locales/ka.yml
@@ -401,7 +401,6 @@ ka:
     warning: იყავით ძალიან ფრთხილად ამ მონაცემთან. არასდროს გააზიაროთ ეს!
     your_token: თქვენი წვდომის ტოკენი
   auth:
-    agreement_html: რეგისტრაციით თქვენ ეთანხმებით <a href="%{rules_path}">ინსტანციის წესებს</a> და <a href="%{terms_path}">ჩვენ მომსახურების პირობებს</a>.
     change_password: პაროლი
     confirm_email: ელ-ფოსტის დამოწმება
     delete_account: ანგარიშის გაუქმება
diff --git a/config/locales/kk.yml b/config/locales/kk.yml
index 4ac4c08b99..da91ca9c47 100644
--- a/config/locales/kk.yml
+++ b/config/locales/kk.yml
@@ -482,7 +482,6 @@ kk:
     warning: Be very carеful with this data. Never share it with anyone!
     your_token: Your access tokеn
   auth:
-    agreement_html: '"Тіркелу" батырмасын басу арқылы <a href="%{rules_path}">сервер ережелері</a> мен <a href="%{terms_path}">қолдану шарттарына</a> келісесіз.'
     change_password: Құпиясөз
     confirm_email: Еmаil құптау
     delete_account: Аккаунт өшіру
diff --git a/config/locales/ko.yml b/config/locales/ko.yml
index 90996b4661..c97fd82092 100644
--- a/config/locales/ko.yml
+++ b/config/locales/ko.yml
@@ -514,7 +514,6 @@ ko:
     warning: 이 데이터를 조심히 다뤄 주세요. 다른 사람들과 절대로 공유하지 마세요!
     your_token: 액세스 토큰
   auth:
-    agreement_html: 이 등록으로 이 서버의 <a href="%{rules_path}">이용규약</a> 과 <a href="%{terms_path}">약관</a>에 동의하는 것으로 간주됩니다.
     apply_for_account: 가입 요청하기
     change_password: 패스워드
     checkbox_agreement_html: <a href="%{rules_path}" target="_blank">서버 규칙</a>과 <a href="%{terms_path}" target="_blank">이용약관</a>에 동의합니다
diff --git a/config/locales/lt.yml b/config/locales/lt.yml
index 0f5ca3091f..97994c3627 100644
--- a/config/locales/lt.yml
+++ b/config/locales/lt.yml
@@ -490,7 +490,6 @@ lt:
     warning: Būkite atsargūs su šia informacija. Niekada jos nesidalinkite!
     your_token: Jūsų prieigos žetonas
   auth:
-    agreement_html: Paspaudus "Sign up" Jūs sutinkate sekti <a href="%{rules_path}">serverio taisykles</a> bei <a href="%{terms_path}">naudojimo sąlygas</a>.
     change_password: Slaptažodis
     confirm_email: Patvirtinti el paštą
     delete_account: Ištrinti paskyrą
diff --git a/config/locales/nl.yml b/config/locales/nl.yml
index 2bfab24543..ca0f57ae0b 100644
--- a/config/locales/nl.yml
+++ b/config/locales/nl.yml
@@ -506,7 +506,6 @@ nl:
     warning: Wees voorzichtig met deze gegevens. Deel het nooit met iemand anders!
     your_token: Jouw toegangscode
   auth:
-    agreement_html: Wanneer je op registreren klikt ga je akkoord met het opvolgen van <a href="%{rules_path}">de regels van deze server</a> en <a href="%{terms_path}">onze gebruiksvoorwaarden</a>.
     apply_for_account: Een uitnodiging aanvragen
     change_password: Wachtwoord
     checkbox_agreement_html: Ik ga akkoord met de <a href="%{rules_path}" target="_blank">regels van deze server</a> en de <a href="%{terms_path}" target="_blank">gebruiksvoorwaarden</a>
diff --git a/config/locales/no.yml b/config/locales/no.yml
index 773f2d0603..d6475afd6a 100644
--- a/config/locales/no.yml
+++ b/config/locales/no.yml
@@ -309,7 +309,6 @@
     warning: Vær veldig forsiktig med denne data. Aldri del den med noen!
     your_token: Din tilgangsnøkkel
   auth:
-    agreement_html: Ved å registrere deg godtar du å følge <a href="%{rules_path}">instansens regler</a> og <a href="%{terms_path}">våre brukervilkår</a>.
     delete_account: Slett konto
     delete_account_html: Hvis du ønsker å slette din konto kan du <a href="%{path}">fortsette her</a>. Du vil bli spurt om bekreftelse.
     didnt_get_confirmation: Mottok du ikke instruksjoner om bekreftelse?
diff --git a/config/locales/oc.yml b/config/locales/oc.yml
index 85df11cf6e..d1c6d11d9f 100644
--- a/config/locales/oc.yml
+++ b/config/locales/oc.yml
@@ -498,7 +498,6 @@ oc:
     warning: Mèfi ! Agachatz de partejar aquela donada amb degun !
     your_token: Vòstre geton d’accès
   auth:
-    agreement_html: En vos marcar acceptatz <a href="%{rules_path}">las règlas del servidor</a> e <a href="%{terms_path}">politica de confidencialitat</a>.
     apply_for_account: Demandar una invitacion
     change_password: Senhal
     checkbox_agreement_html: Accepti las <a href="%{rules_path}" target="_blank">règlas del servidor</a> e <a href="%{terms_path}" target="_blank">los tèrmes del servici</a>
diff --git a/config/locales/pl.yml b/config/locales/pl.yml
index f3da82b1c9..192a56dcf6 100644
--- a/config/locales/pl.yml
+++ b/config/locales/pl.yml
@@ -519,7 +519,6 @@ pl:
     warning: Przechowuj te dane ostrożnie. Nie udostępniaj ich nikomu!
     your_token: Twój token dostępu
   auth:
-    agreement_html: Rejestrując się, oświadczasz, że zapoznałeś(-aś) się z <a href="%{rules_path}">informacjami o serwerze</a> i <a href="%{terms_path}">zasadami korzystania z usługi</a>.
     apply_for_account: Poproś o zaproszenie
     change_password: Hasło
     checkbox_agreement_html: Zgadzam się z <a href="%{rules_path}" target="_blank">regułami serwera</a> i <a href="%{terms_path}" target="_blank">zasadami korzystania z usługi</a>
diff --git a/config/locales/pt-BR.yml b/config/locales/pt-BR.yml
index 6a82a41b1e..4fdacf51d4 100644
--- a/config/locales/pt-BR.yml
+++ b/config/locales/pt-BR.yml
@@ -507,7 +507,6 @@ pt-BR:
     warning: Tenha cuidado com estes dados. Nunca compartilhe com alguém!
     your_token: Seu token de acesso
   auth:
-    agreement_html: Ao se cadastrar você concorda em seguir <a href="%{rules_path}">as regras da instância</a> e <a href="%{terms_path}">os nossos termos de serviço</a>.
     apply_for_account: Pedir um convite
     change_password: Senha
     checkbox_agreement_html: Eu concordo com <a href="%{rules_path}" target="_blank">as regras do servidor</a> e com <a href="%{terms_path}" target="_blank">os termos de serviço</a>
diff --git a/config/locales/pt.yml b/config/locales/pt.yml
index d943d6511a..92c8ab42f7 100644
--- a/config/locales/pt.yml
+++ b/config/locales/pt.yml
@@ -482,7 +482,6 @@ pt:
     warning: Cuidado com estes dados. Não partilhar com ninguém!
     your_token: O teu token de acesso
   auth:
-    agreement_html: Registando-te concordas em seguir <a href="%{rules_path}">as regras da instância</a> e <a href="%{terms_path}">os nossos termos de serviço</a>.
     change_password: Palavra-passe
     confirm_email: Confirmar e-mail
     delete_account: Eliminar conta
diff --git a/config/locales/ro.yml b/config/locales/ro.yml
index 0331f002f6..cdb68c72ae 100644
--- a/config/locales/ro.yml
+++ b/config/locales/ro.yml
@@ -8,7 +8,6 @@ ro:
       one: Toot
       other: Toots
   auth:
-    agreement_html: Prin apăsarea butonului Înscriere de mai jos ești deacord cu <a href="%{rules_path}">regulile acestei instanțe</a> și <a href="%{terms_path}">termenii de utilizare al acestui serviciu</a>.
     change_password: Parolă
     confirm_email: Confirmă email
     delete_account: Șterge contul
diff --git a/config/locales/ru.yml b/config/locales/ru.yml
index ffc9471cd3..e821502583 100644
--- a/config/locales/ru.yml
+++ b/config/locales/ru.yml
@@ -424,7 +424,6 @@ ru:
     warning: Будьте очень внимательны с этими данными. Не делитесь ими ни с кем!
     your_token: Ваш токен доступа
   auth:
-    agreement_html: Создавая аккаунт, вы соглашаетесь с <a href="%{rules_path}">правилами узла</a> и <a href="%{terms_path}">нашими условиями обслуживания</a>.
     change_password: Пароль
     confirm_email: Подтвердите email
     delete_account: Удалить аккаунт
diff --git a/config/locales/simple_form.en.yml b/config/locales/simple_form.en.yml
index 3faaa6ac7b..3317127f3c 100644
--- a/config/locales/simple_form.en.yml
+++ b/config/locales/simple_form.en.yml
@@ -41,6 +41,8 @@ en:
         name: 'You might want to use one of these:'
       imports:
         data: CSV file exported from another Mastodon server
+      invite_request:
+        text: This will help us review your application
       sessions:
         otp: 'Enter the two-factor code generated by your phone app or use one of your recovery codes:'
       user:
@@ -118,6 +120,8 @@ en:
         must_be_follower: Block notifications from non-followers
         must_be_following: Block notifications from people you don't follow
         must_be_following_dm: Block direct messages from people you don't follow
+      invite_request:
+        text: Why do you want to join?
       notification_emails:
         digest: Send digest e-mails
         favourite: Send e-mail when someone favourites your status
diff --git a/config/locales/sk.yml b/config/locales/sk.yml
index d1ff178fdb..9dcb3f4701 100644
--- a/config/locales/sk.yml
+++ b/config/locales/sk.yml
@@ -511,7 +511,6 @@ sk:
     warning: Na tieto údaje dávajte ohromný pozor. Nikdy ich s nikým nezďieľajte!
     your_token: Váš prístupový token
   auth:
-    agreement_html: V rámci registrácie súhlasíš, že sa budeš riadiť <a href="%{rules_path}"> pravidlami tohto servera</a>, a taktiež <a href="%{terms_path}"> našími prevádzkovými podmienkami</a>.
     change_password: Heslo
     confirm_email: Potvrdiť email
     delete_account: Vymaž účet
diff --git a/config/locales/sq.yml b/config/locales/sq.yml
index f02c994ebc..8303abea80 100644
--- a/config/locales/sq.yml
+++ b/config/locales/sq.yml
@@ -479,7 +479,6 @@ sq:
     warning: Hapni sytë me ato të dhëna. Mos ia jepni kurrë njeriu!
     your_token: Token-i juaj për hyrje
   auth:
-    agreement_html: Duke klikuar mbi "Regjistrohuni" më poshtë, pajtoheni të ndiqni <a href="%{rules_path}">rregullat e shërbyesit</a> dhe <a href="%{terms_path}">kushtet tona të shërbimit</a>.
     change_password: Fjalëkalim
     confirm_email: Ripohoni email-in
     delete_account: Fshije llogarinë
diff --git a/config/locales/sr-Latn.yml b/config/locales/sr-Latn.yml
index a2d57ce29a..468867e679 100644
--- a/config/locales/sr-Latn.yml
+++ b/config/locales/sr-Latn.yml
@@ -302,7 +302,6 @@ sr-Latn:
     warning: Oprezno sa ovim podacima. Nikad je ne delite ni sa kim!
     your_token: Vaš pristupni token
   auth:
-    agreement_html: Pristupanjem instanci se slažete sa <a href="%{rules_path}">pravilima instance</a> i <a href="%{terms_path}">uslovima korišćenja</a>.
     delete_account: Obriši nalog
     delete_account_html: Ako želite da obrišete Vaš nalog, možete <a href="%{path}">nastaviti ovde</a>. Bićete upitani da potvrdite.
     didnt_get_confirmation: Niste dobili poruku sa uputstvima za potvrdu naloga?
diff --git a/config/locales/sr.yml b/config/locales/sr.yml
index 45a59bcb1f..49252b5000 100644
--- a/config/locales/sr.yml
+++ b/config/locales/sr.yml
@@ -492,7 +492,6 @@ sr:
     warning: Опрезно са овим подацима. Никад је не делите ни са ким!
     your_token: Ваш приступни токен
   auth:
-    agreement_html: Приступањем инстанци се слажете са <a href="%{rules_path}">правилима инстанце</a> и <a href="%{terms_path}">условима коришћења</a>.
     change_password: Лозинка
     confirm_email: Потврдите адресу е-поште
     delete_account: Обриши налог
diff --git a/config/locales/sv.yml b/config/locales/sv.yml
index b0c04329a7..ef208aceae 100644
--- a/config/locales/sv.yml
+++ b/config/locales/sv.yml
@@ -354,7 +354,6 @@ sv:
     warning: Var mycket försiktig med denna data. Dela aldrig den med någon!
     your_token: Din access token
   auth:
-    agreement_html: Genom att registrera dig godkänner du att följa <a href="%{rules_path}">instansens regler</a> och <a href="%{terms_path}">våra användarvillkor</a>.
     change_password: Lösenord
     confirm_email: Bekräfta e-postadress
     delete_account: Ta bort konto
diff --git a/config/locales/uk.yml b/config/locales/uk.yml
index e72e2f4611..12f2d13a1f 100644
--- a/config/locales/uk.yml
+++ b/config/locales/uk.yml
@@ -386,7 +386,6 @@ uk:
     warning: Будьте дуже обережні з цими даними. Ніколи не діліться ними ні з ким!
     your_token: Ваш токен доступу
   auth:
-    agreement_html: Реєструючись, ви погоджуєтеся виконувати <a href="%{rules_path}">правила інстанції</a> та <a href="%{terms_path}">наші умови використання</a>.
     change_password: Пароль
     confirm_email: Підтвердьте e-mail адресу
     delete_account: Видалити аккаунт
diff --git a/config/locales/zh-CN.yml b/config/locales/zh-CN.yml
index bfacc86fc6..4eafa70f4c 100644
--- a/config/locales/zh-CN.yml
+++ b/config/locales/zh-CN.yml
@@ -410,7 +410,6 @@ zh-CN:
     warning: 一定小心,千万不要把它分享给任何人!
     your_token: 你的访问令牌
   auth:
-    agreement_html: 点击注册即表示你同意遵守<a href="%{rules_path}">本站的相关规定</a>和<a href="%{terms_path}">我们的使用条款</a>。
     change_password: 密码
     confirm_email: 确认电子邮件地址
     delete_account: 删除帐户
diff --git a/config/locales/zh-HK.yml b/config/locales/zh-HK.yml
index 7b200e91ac..9ff97805d6 100644
--- a/config/locales/zh-HK.yml
+++ b/config/locales/zh-HK.yml
@@ -352,7 +352,6 @@ zh-HK:
     warning: 警告,不要把它分享給任何人!
     your_token: token
   auth:
-    agreement_html: 登記即表示你同意遵守<a href="%{rules_path}">本服務站的規則</a>和<a href="%{terms_path}">使用條款</a>。
     change_password: 密碼
     confirm_email: 確認電郵
     delete_account: 刪除帳戶
diff --git a/config/locales/zh-TW.yml b/config/locales/zh-TW.yml
index 913442e170..9a13a602f3 100644
--- a/config/locales/zh-TW.yml
+++ b/config/locales/zh-TW.yml
@@ -436,7 +436,6 @@ zh-TW:
     warning: 警告,不要把它分享給任何人!
     your_token: 你的 token
   auth:
-    agreement_html: 按下下方的「註冊」即代表同意遵守 <a href="%{rules_path}">此伺服器的規則</a> 以及 <a href="%{terms_path}">使用條款</a>。
     change_password: 密碼
     confirm_email: 確認電子信箱位址
     delete_account: 刪除帳戶
diff --git a/db/migrate/20190409054914_create_user_invite_requests.rb b/db/migrate/20190409054914_create_user_invite_requests.rb
new file mode 100644
index 0000000000..974e0f69fe
--- /dev/null
+++ b/db/migrate/20190409054914_create_user_invite_requests.rb
@@ -0,0 +1,10 @@
+class CreateUserInviteRequests < ActiveRecord::Migration[5.2]
+  def change
+    create_table :user_invite_requests do |t|
+      t.belongs_to :user, foreign_key: { on_delete: :cascade }
+      t.text :text
+
+      t.timestamps
+    end
+  end
+end
diff --git a/db/schema.rb b/db/schema.rb
index 11535d8679..3060159d25 100644
--- a/db/schema.rb
+++ b/db/schema.rb
@@ -10,7 +10,7 @@
 #
 # It's strongly recommended that you check this file into your version control system.
 
-ActiveRecord::Schema.define(version: 2019_03_17_135723) do
+ActiveRecord::Schema.define(version: 2019_04_09_054914) do
 
   # These are extensions that must be enabled in order to support this database
   enable_extension "plpgsql"
@@ -679,6 +679,14 @@ ActiveRecord::Schema.define(version: 2019_03_17_135723) do
     t.index ["uri"], name: "index_tombstones_on_uri"
   end
 
+  create_table "user_invite_requests", force: :cascade do |t|
+    t.bigint "user_id"
+    t.text "text"
+    t.datetime "created_at", null: false
+    t.datetime "updated_at", null: false
+    t.index ["user_id"], name: "index_user_invite_requests_on_user_id"
+  end
+
   create_table "users", force: :cascade do |t|
     t.string "email", default: "", null: false
     t.datetime "created_at", null: false
@@ -816,6 +824,7 @@ ActiveRecord::Schema.define(version: 2019_03_17_135723) do
   add_foreign_key "stream_entries", "accounts", name: "fk_5659b17554", on_delete: :cascade
   add_foreign_key "subscriptions", "accounts", name: "fk_9847d1cbb5", on_delete: :cascade
   add_foreign_key "tombstones", "accounts", on_delete: :cascade
+  add_foreign_key "user_invite_requests", "users", on_delete: :cascade
   add_foreign_key "users", "accounts", name: "fk_50500f500d", on_delete: :cascade
   add_foreign_key "users", "invites", on_delete: :nullify
   add_foreign_key "users", "oauth_applications", column: "created_by_application_id", on_delete: :nullify
diff --git a/spec/fabricators/user_invite_request_fabricator.rb b/spec/fabricators/user_invite_request_fabricator.rb
new file mode 100644
index 0000000000..5cc6ae56fe
--- /dev/null
+++ b/spec/fabricators/user_invite_request_fabricator.rb
@@ -0,0 +1,4 @@
+Fabricator(:user_invite_request) do
+  user
+  text { Faker::Lorem.sentence }
+end
diff --git a/spec/models/user_invite_request_spec.rb b/spec/models/user_invite_request_spec.rb
new file mode 100644
index 0000000000..1be38d8a47
--- /dev/null
+++ b/spec/models/user_invite_request_spec.rb
@@ -0,0 +1,4 @@
+require 'rails_helper'
+
+RSpec.describe UserInviteRequest, type: :model do
+end

From 48f466daf1498173cf6ec36db58562df9a031297 Mon Sep 17 00:00:00 2001
From: Hinaloe <hina@hinaloe.net>
Date: Wed, 10 Apr 2019 00:02:12 +0900
Subject: [PATCH 10/16] Allow set the voting period to just 5 minutes (#10525)

* Add spec of PollValidator for #10190

* Raise fraction less than 1 second

* format

* simplify time initialize
---
 app/validators/poll_validator.rb       |  2 +-
 spec/validators/poll_validator_spec.rb | 28 ++++++++++++++++++++++++++
 2 files changed, 29 insertions(+), 1 deletion(-)
 create mode 100644 spec/validators/poll_validator_spec.rb

diff --git a/app/validators/poll_validator.rb b/app/validators/poll_validator.rb
index fd497c8d0b..9d7321cad6 100644
--- a/app/validators/poll_validator.rb
+++ b/app/validators/poll_validator.rb
@@ -14,6 +14,6 @@ class PollValidator < ActiveModel::Validator
     poll.errors.add(:options, I18n.t('polls.errors.over_character_limit', max: MAX_OPTION_CHARS)) if poll.options.any? { |option| option.mb_chars.grapheme_length > MAX_OPTION_CHARS }
     poll.errors.add(:options, I18n.t('polls.errors.duplicate_options')) unless poll.options.uniq.size == poll.options.size
     poll.errors.add(:expires_at, I18n.t('polls.errors.duration_too_long')) if poll.expires_at.nil? || poll.expires_at - current_time > MAX_EXPIRATION
-    poll.errors.add(:expires_at, I18n.t('polls.errors.duration_too_short')) if poll.expires_at.present? && poll.expires_at - current_time < MIN_EXPIRATION
+    poll.errors.add(:expires_at, I18n.t('polls.errors.duration_too_short')) if poll.expires_at.present? && (poll.expires_at - current_time).ceil < MIN_EXPIRATION
   end
 end
diff --git a/spec/validators/poll_validator_spec.rb b/spec/validators/poll_validator_spec.rb
new file mode 100644
index 0000000000..941b83401f
--- /dev/null
+++ b/spec/validators/poll_validator_spec.rb
@@ -0,0 +1,28 @@
+# frozen_string_literal: true
+
+require 'rails_helper'
+
+RSpec.describe PollValidator, type: :validator do
+  describe '#validate' do
+    before do
+      validator.validate(poll)
+    end
+
+    let(:validator) { described_class.new }
+    let(:poll) { double(options: options, expires_at: expires_at, errors: errors) }
+    let(:errors) { double(add: nil) }
+    let(:options) { %w(foo bar) }
+    let(:expires_at) { 1.day.from_now }
+
+    it 'have no errors' do
+      expect(errors).not_to have_received(:add)
+    end
+
+    context 'expires just 5 min ago' do
+      let(:expires_at) { 5.minutes.from_now }
+      it 'not calls errors add' do
+        expect(errors).not_to have_received(:add)
+      end
+    end
+  end
+end

From 2cb16c20a636a364b6d4d17f9588541a0d113731 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Ya=C4=9F=C4=B1zhan?=
 <35808275+yagizhan49@users.noreply.github.com>
Date: Tue, 9 Apr 2019 21:42:01 +0300
Subject: [PATCH 11/16] Fixed terrible grammar and translated the most (#10527)

The translation was written in bad Turkish grammar. I fixed those terrible phrases and translated %93 of Mastodon.

I'll come back and finish the translation.
---
 app/javascript/mastodon/locales/tr.json | 324 ++++++++++++------------
 1 file changed, 162 insertions(+), 162 deletions(-)

diff --git a/app/javascript/mastodon/locales/tr.json b/app/javascript/mastodon/locales/tr.json
index cbe1c5726b..ec2d34a264 100644
--- a/app/javascript/mastodon/locales/tr.json
+++ b/app/javascript/mastodon/locales/tr.json
@@ -4,7 +4,7 @@
   "account.block": "Engelle @{name}",
   "account.block_domain": "{domain} alanından her şeyi gizle",
   "account.blocked": "Engellenmiş",
-  "account.direct": "Direct Message @{name}",
+  "account.direct": "Mesaj gönder : @{name}",
   "account.domain_blocked": "Alan adı gizlendi",
   "account.edit_profile": "Profili düzenle",
   "account.endorse": "Profildeki özellik",
@@ -19,28 +19,28 @@
   "account.locked_info": "Bu hesabın gizlilik durumu kilitli olarak ayarlanmış. Sahibi, onu kimin takip edebileceğini elle inceler.",
   "account.media": "Medya",
   "account.mention": "@{name} kullanıcısından bahset",
-  "account.moved_to": "{name} has moved to:",
+  "account.moved_to": "{name} şuraya taşındı:",
   "account.mute": "@{name} kullanıcısını sessize al",
   "account.mute_notifications": "@{name} kullanıcısının bildirimlerini kapat",
-  "account.muted": "Sessiz",
+  "account.muted": "Sesi kısık",
   "account.posts": "Gönderiler",
   "account.posts_with_replies": "Gönderiler ve yanıtlar",
   "account.report": "@{name} kullanıcısını bildir",
   "account.requested": "Onay bekliyor. Takip isteğini iptal etmek için tıklayın",
   "account.share": "@{name} kullanıcısının profilini paylaş",
-  "account.show_reblogs": "@{name} kullanıcısından boost'ları göster",
+  "account.show_reblogs": "@{name} kullanıcısından boostları göster",
   "account.unblock": "Engeli kaldır @{name}",
   "account.unblock_domain": "{domain} göster",
   "account.unendorse": "Profilde özellik yok",
   "account.unfollow": "Takipten vazgeç",
-  "account.unmute": "Sesi aç @{name}",
+  "account.unmute": "Sesi aç : @{name}",
   "account.unmute_notifications": "@{name} kullanıcısından bildirimleri aç",
   "alert.unexpected.message": "Beklenmedik bir hata oluştu.",
   "alert.unexpected.title": "Hay aksi!",
   "boost_modal.combo": "Bir dahaki sefere {combo} tuşuna basabilirsiniz",
   "bundle_column_error.body": "Bu bileşen yüklenirken bir şeyler ters gitti.",
   "bundle_column_error.retry": "Tekrar deneyin",
-  "bundle_column_error.title": "Network error",
+  "bundle_column_error.title": "Ağ hatası",
   "bundle_modal_error.close": "Kapat",
   "bundle_modal_error.message": "Bu bileşen yüklenirken bir şeyler ters gitti.",
   "bundle_modal_error.retry": "Tekrar deneyin",
@@ -54,7 +54,7 @@
   "column.lists": "Listeler",
   "column.mutes": "Susturulmuş kullanıcılar",
   "column.notifications": "Bildirimler",
-  "column.pins": "Pinned toot",
+  "column.pins": "Sabitlenmiş gönderi",
   "column.public": "Federe zaman tüneli",
   "column_back_button.label": "Geri",
   "column_header.hide_settings": "Ayarları gizle",
@@ -66,16 +66,16 @@
   "column_subheading.settings": "Ayarlar",
   "community.column_settings.media_only": "Sadece medya",
   "compose_form.direct_message_warning": "Bu gönderi sadece belirtilen kullanıcılara gönderilecektir.",
-  "compose_form.direct_message_warning_learn_more": "Daha fazla bilgi edin",
-  "compose_form.hashtag_warning": "This toot won't be listed under any hashtag as it is unlisted. Only public toots can be searched by hashtag.",
+  "compose_form.direct_message_warning_learn_more": "Daha fazla bilgi edinin",
+  "compose_form.hashtag_warning": "Bu paylaşım liste dışı olduğu için hiç bir hashtag'de yer almayacak. Sadece herkese açık gönderiler hashtaglerde bulunabilir.",
   "compose_form.lock_disclaimer": "Hesabınız {locked} değil. Sadece takipçilerle paylaştığınız gönderileri görebilmek için sizi herhangi bir kullanıcı takip edebilir.",
   "compose_form.lock_disclaimer.lock": "kilitli",
   "compose_form.placeholder": "Aklınızdan ne geçiyor?",
-  "compose_form.poll.add_option": "Add a choice",
-  "compose_form.poll.duration": "Poll duration",
-  "compose_form.poll.option_placeholder": "Choice {number}",
-  "compose_form.poll.remove_option": "Remove this choice",
-  "compose_form.publish": "Toot",
+  "compose_form.poll.add_option": "Bir seçenek ekleyin",
+  "compose_form.poll.duration": "Anket süresi",
+  "compose_form.poll.option_placeholder": "Seçim {number}",
+  "compose_form.poll.remove_option": "Bu seçimi kaldır",
+  "compose_form.publish": "Gönder",
   "compose_form.publish_loud": "{publish}!",
   "compose_form.sensitive.marked": "Medya hassas olarak işaretlendi",
   "compose_form.sensitive.unmarked": "Medya hassas olarak işaretlenmemiş",
@@ -83,24 +83,24 @@
   "compose_form.spoiler.unmarked": "Metin gizli değil",
   "compose_form.spoiler_placeholder": "İçerik uyarısı",
   "confirmation_modal.cancel": "İptal",
-  "confirmations.block.block_and_report": "Block & Report",
+  "confirmations.block.block_and_report": "Engelle & Bildir",
   "confirmations.block.confirm": "Engelle",
   "confirmations.block.message": "{name} kullanıcısını engellemek istiyor musunuz?",
   "confirmations.delete.confirm": "Sil",
   "confirmations.delete.message": "Bu gönderiyi silmek istiyor musunuz?",
-  "confirmations.delete_list.confirm": "Delete",
+  "confirmations.delete_list.confirm": "Sil",
   "confirmations.delete_list.message": "Bu listeyi kalıcı olarak silmek istediğinize emin misiniz?",
   "confirmations.domain_block.confirm": "Alan adının tamamını gizle",
-  "confirmations.domain_block.message": "Are you really, really sure you want to block the entire {domain}? In most cases a few targeted blocks or mutes are sufficient and preferable.",
+  "confirmations.domain_block.message": "tüm {domain} alan adını engellemek istediğinizden emin misiniz? Genellikle birkaç hedefli engel ve susturma işi görür ve tercih edilir.",
   "confirmations.mute.confirm": "Sessize al",
   "confirmations.mute.message": "{name} kullanıcısını sessize almak istiyor musunuz?",
   "confirmations.redraft.confirm": "Sil ve yeniden tasarla",
-  "confirmations.redraft.message": "Are you sure you want to delete this status and re-draft it? You will lose all replies, boosts and favourites to it.",
+  "confirmations.redraft.message": "Bu durumu silip tekrar taslaklaştırmak istediğinizden emin misiniz? Tüm cevapları, boostları ve favorileri kaybedeceksiniz.",
   "confirmations.reply.confirm": "Yanıtla",
   "confirmations.reply.message": "Şimdi yanıtlarken o an oluşturduğunuz mesajın üzerine yazılır. Devam etmek istediğinize emin misiniz?",
   "confirmations.unfollow.confirm": "Takibi kaldır",
-  "confirmations.unfollow.message": "Are you sure you want to unfollow {name}?",
-  "embed.instructions": "Embed this status on your website by copying the code below.",
+  "confirmations.unfollow.message": "{name}'yi takipten çıkarmak istediğinizden emin misiniz?",
+  "embed.instructions": "Aşağıdaki kodu kopyalayarak bu durumu sitenize gömün.",
   "embed.preview": "İşte nasıl görüneceği:",
   "emoji_button.activity": "Aktivite",
   "emoji_button.custom": "Özel",
@@ -112,7 +112,7 @@
   "emoji_button.objects": "Nesneler",
   "emoji_button.people": "İnsanlar",
   "emoji_button.recent": "Sık kullanılan",
-  "emoji_button.search": "Emoji ara...",
+  "emoji_button.search": "Ara...",
   "emoji_button.search_results": "Arama sonuçları",
   "emoji_button.symbols": "Semboller",
   "emoji_button.travel": "Seyahat ve Yerler",
@@ -121,13 +121,13 @@
   "empty_column.community": "Yerel zaman çizelgesi boş. Daha fazla eğlence için herkese açık bir gönderi paylaşın!",
   "empty_column.direct": "Henüz doğrudan mesajınız yok. Bir tane gönderdiğinizde veya aldığınızda burada görünecektir.",
   "empty_column.domain_blocks": "Henüz hiçbir gizli alan adı yok.",
-  "empty_column.favourited_statuses": "You don't have any favourite toots yet. When you favourite one, it will show up here.",
-  "empty_column.favourites": "No one has favourited this toot yet. When someone does, they will show up here.",
-  "empty_column.follow_requests": "You don't have any follow requests yet. When you receive one, it will show up here.",
+  "empty_column.favourited_statuses": "Hiç favori gönderiminiz yok. Bir tane olursa burada görünecek.",
+  "empty_column.favourites": "Kimse bu gönderiyi favorilerine eklememiş. Biri eklerse burada görünecek.",
+  "empty_column.follow_requests": "Hiç takip isteğiniz yok. Bir tane aldığınızda burada görünecek.",
   "empty_column.hashtag": "Henüz bu hashtag’e sahip hiçbir gönderi yok.",
   "empty_column.home": "Henüz kimseyi takip etmiyorsunuz. {public} ziyaret edebilir veya arama kısmını kullanarak diğer kullanıcılarla iletişime geçebilirsiniz.",
   "empty_column.home.public_timeline": "herkese açık zaman tüneli",
-  "empty_column.list": "There is nothing in this list yet.",
+  "empty_column.list": "Bu listede henüz hiçbir şey yok.",
   "empty_column.lists": "Henüz hiç listeniz yok. Bir tane oluşturduğunuzda burada görünecek.",
   "empty_column.mutes": "Henüz hiçbir kullanıcıyı sessize almadınız.",
   "empty_column.notifications": "Henüz hiçbir bildiriminiz yok. Diğer insanlarla sobhet edebilmek için etkileşime geçebilirsiniz.",
@@ -136,7 +136,7 @@
   "follow_request.reject": "Reddet",
   "getting_started.developers": "Geliştiriciler",
   "getting_started.directory": "Profil dizini",
-  "getting_started.documentation": "Documentation",
+  "getting_started.documentation": "Belgeler",
   "getting_started.heading": "Başlangıç",
   "getting_started.invite": "İnsanları davet edin",
   "getting_started.open_source_notice": "Mastodon açık kaynaklı bir yazılımdır. Github {github}. {apps} üzerinden katkıda bulunabilir, hata raporlayabilirsiniz.",
@@ -145,12 +145,12 @@
   "hashtag.column_header.tag_mode.all": "ve {additional}",
   "hashtag.column_header.tag_mode.any": "ya da {additional}",
   "hashtag.column_header.tag_mode.none": "{additional} olmadan",
-  "hashtag.column_settings.select.no_options_message": "No suggestions found",
-  "hashtag.column_settings.select.placeholder": "Enter hashtags…",
+  "hashtag.column_settings.select.no_options_message": "Hiç öneri bulunamadı",
+  "hashtag.column_settings.select.placeholder": "Hashtagler girin…",
   "hashtag.column_settings.tag_mode.all": "Bunların hepsi",
   "hashtag.column_settings.tag_mode.any": "Bunların hiçbiri",
   "hashtag.column_settings.tag_mode.none": "Bunların hiçbiri",
-  "hashtag.column_settings.tag_toggle": "Include additional tags in this column",
+  "hashtag.column_settings.tag_toggle": "Bu sütundaki ek etiketleri içer",
   "home.column_settings.basic": "Temel",
   "home.column_settings.show_reblogs": "Boost edilenleri göster",
   "home.column_settings.show_replies": "Cevapları göster",
@@ -159,122 +159,122 @@
   "intervals.full.minutes": "{number, plural, one {# minute} other {# minutes}}",
   "introduction.federation.action": "İleri",
   "introduction.federation.federated.headline": "Birleşik",
-  "introduction.federation.federated.text": "Diğer dosya sunucularından gelen genel yayınlar, birleşik zaman çizelgesinde görünecektir.",
+  "introduction.federation.federated.text": "Diğer dosya sunucularından gelen genel gönderiler, birleşik zaman çizelgesinde görünecektir.",
   "introduction.federation.home.headline": "Ana sayfa",
   "introduction.federation.home.text": "Posts from people you follow will appear in your home feed. You can follow anyone on any server!",
   "introduction.federation.local.headline": "Yerel",
-  "introduction.federation.local.text": "Public posts from people on the same server as you will appear in the local timeline.",
+  "introduction.federation.local.text": "Aynı sunucudaki kişilerin gönderileri yerel zaman tünelinde gözükecektir.",
   "introduction.interactions.action": "Öğreticiyi bitirin!",
   "introduction.interactions.favourite.headline": "Favori",
-  "introduction.interactions.favourite.text": "You can save a toot for later, and let the author know that you liked it, by favouriting it.",
+  "introduction.interactions.favourite.text": "Bir gönderiyi favorilerinize alarak sonrası için saklayabilirsiniz ve yazara gönderiyi beğendiğinizi söyleyebilirsiniz.",
   "introduction.interactions.reblog.headline": "Boost",
-  "introduction.interactions.reblog.text": "You can share other people's toots with your followers by boosting them.",
+  "introduction.interactions.reblog.text": "Başkalarının gönderilerini boostlayarak kendi takipçilerinizle paylaşabillirsiniz.",
   "introduction.interactions.reply.headline": "Yanıt",
-  "introduction.interactions.reply.text": "You can reply to other people's and your own toots, which will chain them together in a conversation.",
+  "introduction.interactions.reply.text": "Başkalarının gönderilerini ve kendi gönderilerinizi yanıtlayabilirsiniz. Bir konuşmada zincirli bir şekilde olacaklardır.",
   "introduction.welcome.action": "Hadi gidelim!",
   "introduction.welcome.headline": "İlk adımlar",
-  "introduction.welcome.text": "Welcome to the fediverse! In a few moments, you'll be able to broadcast messages and talk to your friends across a wide variety of servers. But this server, {domain}, is special—it hosts your profile, so remember its name.",
-  "keyboard_shortcuts.back": "to navigate back",
-  "keyboard_shortcuts.blocked": "to open blocked users list",
-  "keyboard_shortcuts.boost": "to boost",
-  "keyboard_shortcuts.column": "to focus a status in one of the columns",
-  "keyboard_shortcuts.compose": "to focus the compose textarea",
+  "introduction.welcome.text": "Krallığa hoş geldiniz! Az sonra, geniş bir sunucu yelpazesinde mesaj gönderip arkadaşlarınızla konuşabileceksiniz. Ama bu sunucu, {domain}, özel (profilinizi barındırır, bu yüzden adresini hatırlayın).",
+  "keyboard_shortcuts.back": "geriye gitmek için",
+  "keyboard_shortcuts.blocked": "engelli kullanıcılar listesini açmak için",
+  "keyboard_shortcuts.boost": "boostlamak için",
+  "keyboard_shortcuts.column": "sütunlardan birindeki duruma odaklanmak için",
+  "keyboard_shortcuts.compose": "yazma alanına odaklanmak için",
   "keyboard_shortcuts.description": "Açıklama",
-  "keyboard_shortcuts.direct": "to open direct messages column",
-  "keyboard_shortcuts.down": "to move down in the list",
-  "keyboard_shortcuts.enter": "to open status",
-  "keyboard_shortcuts.favourite": "to favourite",
-  "keyboard_shortcuts.favourites": "to open favourites list",
-  "keyboard_shortcuts.federated": "to open federated timeline",
+  "keyboard_shortcuts.direct": "direkt mesajlar sütununu açmak için",
+  "keyboard_shortcuts.down": "listede aşağıya inmek için",
+  "keyboard_shortcuts.enter": "durumu açmak için",
+  "keyboard_shortcuts.favourite": "favorilere eklemek için",
+  "keyboard_shortcuts.favourites": "favoriler listesini açmak için",
+  "keyboard_shortcuts.federated": "federe edilmiş zaman tünelini açmak için",
   "keyboard_shortcuts.heading": "Klavye kısayolları",
-  "keyboard_shortcuts.home": "Ana sayfa zaman çizelgesini açmak için",
-  "keyboard_shortcuts.hotkey": "Hotkey",
-  "keyboard_shortcuts.legend": "to display this legend",
-  "keyboard_shortcuts.local": "to open local timeline",
-  "keyboard_shortcuts.mention": "to mention author",
-  "keyboard_shortcuts.muted": "to open muted users list",
-  "keyboard_shortcuts.my_profile": "to open your profile",
-  "keyboard_shortcuts.notifications": "to open notifications column",
-  "keyboard_shortcuts.pinned": "to open pinned toots list",
-  "keyboard_shortcuts.profile": "to open author's profile",
-  "keyboard_shortcuts.reply": "to reply",
-  "keyboard_shortcuts.requests": "to open follow requests list",
-  "keyboard_shortcuts.search": "to focus search",
-  "keyboard_shortcuts.start": "to open \"get started\" column",
-  "keyboard_shortcuts.toggle_hidden": "to show/hide text behind CW",
-  "keyboard_shortcuts.toot": "to start a brand new toot",
-  "keyboard_shortcuts.unfocus": "to un-focus compose textarea/search",
-  "keyboard_shortcuts.up": "to move up in the list",
+  "keyboard_shortcuts.home": "ana sayfa zaman çizelgesini açmak için",
+  "keyboard_shortcuts.hotkey": "Kısatuş",
+  "keyboard_shortcuts.legend": "bu efsaneyi görüntülemek için",
+  "keyboard_shortcuts.local": "yerel zaman tünelini açmak için",
+  "keyboard_shortcuts.mention": "yazardan bahsetmek için",
+  "keyboard_shortcuts.muted": "susturulmuş kullanıcı listesini açmak için",
+  "keyboard_shortcuts.my_profile": "profilinizi açmak için",
+  "keyboard_shortcuts.notifications": "bildirimler sütununu açmak için",
+  "keyboard_shortcuts.pinned": "sabitlenmiş gönderiler listesini açmak için",
+  "keyboard_shortcuts.profile": "yazarın profilini açmak için",
+  "keyboard_shortcuts.reply": "cevaplamak için",
+  "keyboard_shortcuts.requests": "takip istekleri listesini açmak için",
+  "keyboard_shortcuts.search": "aramaya odaklanmak için",
+  "keyboard_shortcuts.start": "\"başlayın\" sütununu açmak için",
+  "keyboard_shortcuts.toggle_hidden": "CW'den önceki yazıyı göstermek/gizlemek için",
+  "keyboard_shortcuts.toot": "yeni bir gönderiye başlamak için",
+  "keyboard_shortcuts.unfocus": "aramada bir gönderiye odaklanmamak için",
+  "keyboard_shortcuts.up": "listede yukarıya çıkmak için",
   "lightbox.close": "Kapat",
-  "lightbox.next": "Next",
-  "lightbox.previous": "Previous",
-  "lists.account.add": "Add to list",
-  "lists.account.remove": "Remove from list",
-  "lists.delete": "Delete list",
-  "lists.edit": "Edit list",
-  "lists.edit.submit": "Change title",
-  "lists.new.create": "Add list",
-  "lists.new.title_placeholder": "New list title",
-  "lists.search": "Search among people you follow",
-  "lists.subheading": "Your lists",
+  "lightbox.next": "Sonraki",
+  "lightbox.previous": "Önceli",
+  "lists.account.add": "Listeye ekle",
+  "lists.account.remove": "Listeden kaldır",
+  "lists.delete": "Listeyi sil",
+  "lists.edit": "listeyi düzenle",
+  "lists.edit.submit": "Başlığı değiştir",
+  "lists.new.create": "Liste ekle",
+  "lists.new.title_placeholder": "Yeni liste başlığı",
+  "lists.search": "Takip ettiğiniz kişiler arasından arayın",
+  "lists.subheading": "Listeleriniz",
   "loading_indicator.label": "Yükleniyor...",
   "media_gallery.toggle_visible": "Görünürlüğü değiştir",
   "missing_indicator.label": "Bulunamadı",
-  "missing_indicator.sublabel": "This resource could not be found",
-  "mute_modal.hide_notifications": "Hide notifications from this user?",
-  "navigation_bar.apps": "Mobile apps",
+  "missing_indicator.sublabel": "Bu kaynak bulunamadı",
+  "mute_modal.hide_notifications": "Bu kullanıcıdan bildirimler gizlensin mı?",
+  "navigation_bar.apps": "Mobil uygulamalar",
   "navigation_bar.blocks": "Engellenen kullanıcılar",
   "navigation_bar.community_timeline": "Yerel zaman tüneli",
-  "navigation_bar.compose": "Compose new toot",
-  "navigation_bar.direct": "Direct messages",
-  "navigation_bar.discover": "Discover",
-  "navigation_bar.domain_blocks": "Hidden domains",
+  "navigation_bar.compose": "Yeni bir gönderi yazın",
+  "navigation_bar.direct": "Direkt Mesajlar",
+  "navigation_bar.discover": "Keşfet",
+  "navigation_bar.domain_blocks": "Gizli alan adları",
   "navigation_bar.edit_profile": "Profili düzenle",
   "navigation_bar.favourites": "Favoriler",
-  "navigation_bar.filters": "Muted words",
+  "navigation_bar.filters": "Susturulmuş kelimeler",
   "navigation_bar.follow_requests": "Takip istekleri",
   "navigation_bar.info": "Genişletilmiş bilgi",
-  "navigation_bar.keyboard_shortcuts": "Keyboard shortcuts",
-  "navigation_bar.lists": "Lists",
+  "navigation_bar.keyboard_shortcuts": "Klavye kısayolları",
+  "navigation_bar.lists": "Listeler",
   "navigation_bar.logout": "Çıkış",
   "navigation_bar.mutes": "Sessize alınmış kullanıcılar",
-  "navigation_bar.personal": "Personal",
-  "navigation_bar.pins": "Pinned toots",
+  "navigation_bar.personal": "Kişisel",
+  "navigation_bar.pins": "Sabitlenmiş gönderiler",
   "navigation_bar.preferences": "Tercihler",
   "navigation_bar.public_timeline": "Federe zaman tüneli",
-  "navigation_bar.security": "Security",
+  "navigation_bar.security": "Güvenlik",
   "notification.favourite": "{name} senin durumunu favorilere ekledi",
   "notification.follow": "{name} seni takip ediyor",
   "notification.mention": "{name} mentioned you",
-  "notification.poll": "A poll you have voted in has ended",
+  "notification.poll": "Oy verdiğiniz bir anket bitti",
   "notification.reblog": "{name} senin durumunu boost etti",
   "notifications.clear": "Bildirimleri temizle",
   "notifications.clear_confirmation": "Tüm bildirimlerinizi kalıcı olarak temizlemek ister misiniz?",
   "notifications.column_settings.alert": "Masaüstü bildirimleri",
   "notifications.column_settings.favourite": "Favoriler:",
-  "notifications.column_settings.filter_bar.advanced": "Display all categories",
-  "notifications.column_settings.filter_bar.category": "Quick filter bar",
-  "notifications.column_settings.filter_bar.show": "Show",
+  "notifications.column_settings.filter_bar.advanced": "Tüm kategorileri göster",
+  "notifications.column_settings.filter_bar.category": "Hızlı filtre çubuğu",
+  "notifications.column_settings.filter_bar.show": "Göster",
   "notifications.column_settings.follow": "Yeni takipçiler:",
   "notifications.column_settings.mention": "Bahsedilenler:",
-  "notifications.column_settings.poll": "Poll results:",
-  "notifications.column_settings.push": "Push notifications",
-  "notifications.column_settings.reblog": "Boost’lar:",
+  "notifications.column_settings.poll": "Anket sonuçları:",
+  "notifications.column_settings.push": "Push bildirimleri",
+  "notifications.column_settings.reblog": "Boostlar:",
   "notifications.column_settings.show": "Bildirimlerde göster",
   "notifications.column_settings.sound": "Ses çal",
-  "notifications.filter.all": "All",
-  "notifications.filter.boosts": "Boosts",
-  "notifications.filter.favourites": "Favourites",
-  "notifications.filter.follows": "Follows",
-  "notifications.filter.mentions": "Mentions",
-  "notifications.filter.polls": "Poll results",
-  "notifications.group": "{count} notifications",
-  "poll.closed": "Closed",
-  "poll.refresh": "Refresh",
+  "notifications.filter.all": "Tümü",
+  "notifications.filter.boosts": "Boostlar",
+  "notifications.filter.favourites": "Favoriler",
+  "notifications.filter.follows": "Takip edilenler",
+  "notifications.filter.mentions": "Bahsetmeler",
+  "notifications.filter.polls": "Anket sonuçları",
+  "notifications.group": "{count} bildirim",
+  "poll.closed": "Kapandı",
+  "poll.refresh": "Yenile",
   "poll.total_votes": "{count, plural, one {# vote} other {# votes}}",
-  "poll.vote": "Vote",
-  "poll_button.add_poll": "Add a poll",
-  "poll_button.remove_poll": "Remove poll",
+  "poll.vote": "Oy ver",
+  "poll_button.add_poll": "Bir anket ekleyin",
+  "poll_button.remove_poll": "Anket kaldır",
   "privacy.change": "Gönderi gizliliğini ayarla",
   "privacy.direct.long": "Sadece bahsedilen kişilere gönder",
   "privacy.direct.short": "Direkt",
@@ -284,100 +284,100 @@
   "privacy.public.short": "Herkese açık",
   "privacy.unlisted.long": "Herkese açık zaman tüneline gönderme",
   "privacy.unlisted.short": "Listelenmemiş",
-  "regeneration_indicator.label": "Loading…",
-  "regeneration_indicator.sublabel": "Your home feed is being prepared!",
-  "relative_time.days": "{number}d",
-  "relative_time.hours": "{number}h",
-  "relative_time.just_now": "now",
-  "relative_time.minutes": "{number}m",
-  "relative_time.seconds": "{number}s",
+  "regeneration_indicator.label": "Yükleniyor…",
+  "regeneration_indicator.sublabel": "Ev akışınız hazırlanıyor!",
+  "relative_time.days": "{number}g",
+  "relative_time.hours": "{number}s",
+  "relative_time.just_now": "şimdi",
+  "relative_time.minutes": "{number}dk",
+  "relative_time.seconds": "{number}sn",
   "reply_indicator.cancel": "İptal",
-  "report.forward": "Forward to {target}",
-  "report.forward_hint": "The account is from another server. Send an anonymized copy of the report there as well?",
-  "report.hint": "The report will be sent to your instance moderators. You can provide an explanation of why you are reporting this account below:",
+  "report.forward": "Şu kişiye ilet : {target}",
+  "report.forward_hint": "Bu hesap başka bir sunucudan. Anonimleştirilmiş bir rapor oraya da gönderilsin mi?",
+  "report.hint": "Bu rapor sunucu moderatörlerine gönderilecek. Bu hesabı neden bildirdiğiniz hakkında bilgi verebirsiniz:",
   "report.placeholder": "Ek yorumlar",
   "report.submit": "Gönder",
   "report.target": "Raporlama",
   "search.placeholder": "Ara",
-  "search_popout.search_format": "Advanced search format",
+  "search_popout.search_format": "Gelişmiş arama formatı",
   "search_popout.tips.full_text": "Simple text returns statuses you have written, favourited, boosted, or have been mentioned in, as well as matching usernames, display names, and hashtags.",
   "search_popout.tips.hashtag": "hashtag",
-  "search_popout.tips.status": "status",
+  "search_popout.tips.status": "durum",
   "search_popout.tips.text": "Simple text returns matching display names, usernames and hashtags",
-  "search_popout.tips.user": "user",
-  "search_results.accounts": "People",
-  "search_results.hashtags": "Hashtags",
-  "search_results.statuses": "Toots",
+  "search_popout.tips.user": "kullanıcı",
+  "search_results.accounts": "İnsanlar",
+  "search_results.hashtags": "Hashtagler",
+  "search_results.statuses": "Gönderiler",
   "search_results.total": "{count, number} {count, plural, one {sonuç} other {sonuçlar}}",
   "status.admin_account": "@{name} için denetim arayüzünü açın",
   "status.admin_status": "Denetim arayüzünde bu durumu açın",
-  "status.block": "Block @{name}",
-  "status.cancel_reblog_private": "Unboost",
+  "status.block": "Engelle : @{name}",
+  "status.cancel_reblog_private": "Boost'u geri al",
   "status.cannot_reblog": "Bu gönderi boost edilemez",
   "status.copy": "Bağlantı durumunu kopyala",
   "status.delete": "Sil",
-  "status.detailed_status": "Detailed conversation view",
-  "status.direct": "Direct message @{name}",
-  "status.embed": "Embed",
+  "status.detailed_status": "Detaylı yazışma dökümü",
+  "status.direct": "@{name}'e gönder",
+  "status.embed": "Gömülü",
   "status.favourite": "Favorilere ekle",
-  "status.filtered": "Filtered",
+  "status.filtered": "Filtrelenmiş",
   "status.load_more": "Daha fazla",
   "status.media_hidden": "Gizli görsel",
-  "status.mention": "Bahset @{name}",
-  "status.more": "More",
-  "status.mute": "Mute @{name}",
-  "status.mute_conversation": "Mute conversation",
+  "status.mention": "Bahset : @{name}",
+  "status.more": "Daha fazla",
+  "status.mute": "Sustur : @{name}",
+  "status.mute_conversation": "Yazışmayı sustur",
   "status.open": "Bu gönderiyi genişlet",
-  "status.pin": "Pin on profile",
-  "status.pinned": "Pinned toot",
-  "status.read_more": "Read more",
-  "status.reblog": "Boost'la",
+  "status.pin": "Profile sabitle",
+  "status.pinned": "Sabitlenmiş gönderi",
+  "status.read_more": "Daha dazla oku",
+  "status.reblog": "Boostla",
   "status.reblog_private": "Boost to original audience",
   "status.reblogged_by": "{name} boost etti",
-  "status.reblogs.empty": "No one has boosted this toot yet. When someone does, they will show up here.",
-  "status.redraft": "Delete & re-draft",
+  "status.reblogs.empty": "Kimse bu gönderiyi boostlamadı. Biri yaptığında burada gözükecek.",
+  "status.redraft": "Sil & tekrar taslakla",
   "status.reply": "Cevapla",
   "status.replyAll": "Konuşmayı cevapla",
   "status.report": "@{name}'i raporla",
   "status.sensitive_toggle": "Görmek için tıklayınız",
   "status.sensitive_warning": "Hassas içerik",
-  "status.share": "Share",
-  "status.show_less": "Daha azı",
-  "status.show_less_all": "Show less for all",
-  "status.show_more": "Daha fazlası",
-  "status.show_more_all": "Show more for all",
-  "status.show_thread": "Show thread",
+  "status.share": "Paylaş",
+  "status.show_less": "Daha az göster",
+  "status.show_less_all": "Hepsi için daha az göster",
+  "status.show_more": "Daha fazla göster",
+  "status.show_more_all": "Hepsi için daha fazla göster",
+  "status.show_thread": "Başlığı göster",
   "status.unmute_conversation": "Unmute conversation",
-  "status.unpin": "Unpin from profile",
-  "suggestions.dismiss": "Dismiss suggestion",
-  "suggestions.header": "You might be interested in…",
+  "status.unpin": "Profilden sabitlemeyi kaldır",
+  "suggestions.dismiss": "Öneriyi görmezden gel",
+  "suggestions.header": "Şuna ilgi duyuyor olabilirsiniz…",
   "tabs_bar.federated_timeline": "Federe",
   "tabs_bar.home": "Ana sayfa",
   "tabs_bar.local_timeline": "Yerel",
   "tabs_bar.notifications": "Bildirimler",
-  "tabs_bar.search": "Search",
+  "tabs_bar.search": "Ara",
   "time_remaining.days": "{number, plural, one {# day} other {# days}} left",
   "time_remaining.hours": "{number, plural, one {# hour} other {# hours}} left",
   "time_remaining.minutes": "{number, plural, one {# minute} other {# minutes}} left",
   "time_remaining.moments": "Moments remaining",
   "time_remaining.seconds": "{number, plural, one {# second} other {# seconds}} left",
   "trends.count_by_accounts": "{count} {rawCount, plural, one {person} other {people}} talking",
-  "ui.beforeunload": "Your draft will be lost if you leave Mastodon.",
-  "upload_area.title": "Upload için sürükle bırak yapınız",
+  "ui.beforeunload": "Mastodon'dan ayrılırsanız taslağınız kaybolacak.",
+  "upload_area.title": "Karşıya yükleme için sürükle bırak yapınız",
   "upload_button.label": "Görsel ekle",
   "upload_error.limit": "Dosya yükleme sınırı aşıldı.",
-  "upload_error.poll": "File upload not allowed with polls.",
+  "upload_error.poll": "Anketlerde dosya yüklemesine izin verilmez.",
   "upload_form.description": "Describe for the visually impaired",
-  "upload_form.focus": "Crop",
+  "upload_form.focus": "Kırp",
   "upload_form.undo": "Geri al",
   "upload_progress.label": "Yükleniyor...",
-  "video.close": "Close video",
-  "video.exit_fullscreen": "Exit full screen",
-  "video.expand": "Expand video",
-  "video.fullscreen": "Full screen",
-  "video.hide": "Hide video",
-  "video.mute": "Mute sound",
-  "video.pause": "Pause",
-  "video.play": "Play",
-  "video.unmute": "Unmute sound"
+  "video.close": "Videoyu kapat",
+  "video.exit_fullscreen": "Tam ekrandan çık",
+  "video.expand": "Videoyu genişlet",
+  "video.fullscreen": "Tam ekran",
+  "video.hide": "Videoyu gizle",
+  "video.mute": "Sesi kıs",
+  "video.pause": "Duraklat",
+  "video.play": "Oynat",
+  "video.unmute": "Sesi aç"
 }

From 36b39fbac55a9b141b99b54f193ec2702f8c3c39 Mon Sep 17 00:00:00 2001
From: Eugen Rochko <eugen@zeonfederated.com>
Date: Wed, 10 Apr 2019 00:35:49 +0200
Subject: [PATCH 12/16] Add preference to disable e-mails about new pending
 accounts (#10529)

---
 app/controllers/settings/preferences_controller.rb | 2 +-
 app/models/user.rb                                 | 6 +++++-
 app/views/settings/notifications/show.html.haml    | 1 +
 config/locales/simple_form.en.yml                  | 1 +
 config/settings.yml                                | 1 +
 5 files changed, 9 insertions(+), 2 deletions(-)

diff --git a/app/controllers/settings/preferences_controller.rb b/app/controllers/settings/preferences_controller.rb
index 90967635da..5afdf0eec0 100644
--- a/app/controllers/settings/preferences_controller.rb
+++ b/app/controllers/settings/preferences_controller.rb
@@ -49,7 +49,7 @@ class Settings::PreferencesController < Settings::BaseController
       :setting_hide_network,
       :setting_aggregate_reblogs,
       :setting_show_application,
-      notification_emails: %i(follow follow_request reblog favourite mention digest report),
+      notification_emails: %i(follow follow_request reblog favourite mention digest report pending_account),
       interactions: %i(must_be_follower must_be_following)
     )
   end
diff --git a/app/models/user.rb b/app/models/user.rb
index c9309bc216..135baae122 100644
--- a/app/models/user.rb
+++ b/app/models/user.rb
@@ -191,6 +191,10 @@ class User < ApplicationRecord
     settings.notification_emails['report']
   end
 
+  def allows_pending_account_emails?
+    settings.notification_emails['pending_account']
+  end
+
   def hides_network?
     @hides_network ||= settings.hide_network
   end
@@ -295,7 +299,7 @@ class User < ApplicationRecord
 
   def notify_staff_about_pending_account!
     User.staff.includes(:account).each do |u|
-      next unless u.allows_report_emails?
+      next unless u.allows_pending_account_emails?
       AdminMailer.new_pending_account(u.account, self).deliver_later
     end
   end
diff --git a/app/views/settings/notifications/show.html.haml b/app/views/settings/notifications/show.html.haml
index 8aaac043b7..6ec57b502f 100644
--- a/app/views/settings/notifications/show.html.haml
+++ b/app/views/settings/notifications/show.html.haml
@@ -14,6 +14,7 @@
 
       - if current_user.staff?
         = ff.input :report, as: :boolean, wrapper: :with_label
+        = ff.input :pending_account, as: :boolean, wrapper: :with_label
 
   .fields-group
     = f.simple_fields_for :notification_emails, hash_to_object(current_user.settings.notification_emails) do |ff|
diff --git a/config/locales/simple_form.en.yml b/config/locales/simple_form.en.yml
index 3317127f3c..1a43e19e23 100644
--- a/config/locales/simple_form.en.yml
+++ b/config/locales/simple_form.en.yml
@@ -128,6 +128,7 @@ en:
         follow: Send e-mail when someone follows you
         follow_request: Send e-mail when someone requests to follow you
         mention: Send e-mail when someone mentions you
+        pending_account: Send e-mail when a new account needs review
         reblog: Send e-mail when someone boosts your status
         report: Send e-mail when a new report is submitted
     'no': 'No'
diff --git a/config/settings.yml b/config/settings.yml
index 4f05519a55..63f7c33803 100644
--- a/config/settings.yml
+++ b/config/settings.yml
@@ -39,6 +39,7 @@ defaults: &defaults
     follow_request: true
     digest: true
     report: true
+    pending_account: true
   interactions:
     must_be_follower: false
     must_be_following: false

From 46cb36fd2cc641ab6c125f7e91140fa1b1d77634 Mon Sep 17 00:00:00 2001
From: Eugen Rochko <eugen@zeonfederated.com>
Date: Wed, 10 Apr 2019 00:36:01 +0200
Subject: [PATCH 13/16] Add invite request to pending account notification
 e-mail (#10528)

Fix sorting of the pending accounts page
---
 app/controllers/admin/pending_accounts_controller.rb |  2 +-
 app/helpers/application_helper.rb                    |  5 +++++
 app/views/admin_mailer/new_pending_account.text.erb  | 10 +++++++---
 spec/mailers/previews/admin_mailer_preview.rb        |  8 ++++++++
 4 files changed, 21 insertions(+), 4 deletions(-)
 create mode 100644 spec/mailers/previews/admin_mailer_preview.rb

diff --git a/app/controllers/admin/pending_accounts_controller.rb b/app/controllers/admin/pending_accounts_controller.rb
index 249525504b..b62a9bc846 100644
--- a/app/controllers/admin/pending_accounts_controller.rb
+++ b/app/controllers/admin/pending_accounts_controller.rb
@@ -30,7 +30,7 @@ module Admin
     private
 
     def set_accounts
-      @accounts = Account.joins(:user).merge(User.pending).includes(user: :invite_request).page(params[:page])
+      @accounts = Account.joins(:user).merge(User.pending.recent).includes(user: :invite_request).page(params[:page])
     end
 
     def form_account_batch_params
diff --git a/app/helpers/application_helper.rb b/app/helpers/application_helper.rb
index b42b1bbdf7..9d113263df 100644
--- a/app/helpers/application_helper.rb
+++ b/app/helpers/application_helper.rb
@@ -117,4 +117,9 @@ module ApplicationHelper
   def storage_host?
     ENV['S3_ALIAS_HOST'].present? || ENV['S3_CLOUDFRONT_HOST'].present?
   end
+
+  def quote_wrap(text, line_width: 80, break_sequence: "\n")
+    text = word_wrap(text, line_width: line_width - 2, break_sequence: break_sequence)
+    text.split("\n").map { |line| '> ' + line }.join("\n")
+  end
 end
diff --git a/app/views/admin_mailer/new_pending_account.text.erb b/app/views/admin_mailer/new_pending_account.text.erb
index ed31ae2eb7..a466ee2de7 100644
--- a/app/views/admin_mailer/new_pending_account.text.erb
+++ b/app/views/admin_mailer/new_pending_account.text.erb
@@ -2,7 +2,11 @@
 
 <%= raw t('admin_mailer.new_pending_account.body') %>
 
-<%= raw t('admin.accounts.email') %>: <%= @account.user_email %>
-<%= raw t('admin.accounts.most_recent_ip') %>: <%= @account.user_current_sign_in_ip %>
+<%= @account.user_email %> (@<%= @account.username %>)
+<%= @account.user_current_sign_in_ip %>
+<% if @account.user&.invite_request&.text.present? %>
 
-<%= raw t('application_mailer.view')%> <%= admin_account_url(@account.id) %>
+<%= quote_wrap(@account.user&.invite_request&.text) %>
+<% end %>
+
+<%= raw t('application_mailer.view')%> <%= admin_pending_accounts_url %>
diff --git a/spec/mailers/previews/admin_mailer_preview.rb b/spec/mailers/previews/admin_mailer_preview.rb
new file mode 100644
index 0000000000..561a56b787
--- /dev/null
+++ b/spec/mailers/previews/admin_mailer_preview.rb
@@ -0,0 +1,8 @@
+# Preview all emails at http://localhost:3000/rails/mailers/admin_mailer
+
+class AdminMailerPreview < ActionMailer::Preview
+  # Preview this email at http://localhost:3000/rails/mailers/admin_mailer/new_pending_account
+  def new_pending_account
+    AdminMailer.new_pending_account(Account.first, User.pending.first)
+  end
+end

From 400397c0c790d7d401d14cea6a0f4c1643af45bc Mon Sep 17 00:00:00 2001
From: Eugen Rochko <eugen@zeonfederated.com>
Date: Wed, 10 Apr 2019 03:34:16 +0200
Subject: [PATCH 14/16] Change HTML validator to ignore all errors except
 unmatched tags (#10534)

---
 app/models/form/admin_settings.rb |  3 ++-
 app/validators/html_validator.rb  | 12 +++++++-----
 2 files changed, 9 insertions(+), 6 deletions(-)

diff --git a/app/models/form/admin_settings.rb b/app/models/form/admin_settings.rb
index d3af8c30f5..86a86ec666 100644
--- a/app/models/form/admin_settings.rb
+++ b/app/models/form/admin_settings.rb
@@ -49,7 +49,8 @@ class Form::AdminSettings
 
   attr_accessor(*KEYS)
 
-  validates :site_short_description, :site_description, :site_extended_description, :site_terms, :closed_registrations_message, html: true
+  validates :site_short_description, :site_description, html: { wrap_with: :p }
+  validates :site_extended_description, :site_terms, :closed_registrations_message, html: true
   validates :registrations_mode, inclusion: { in: %w(open approved none) }
   validates :min_invite_role, inclusion: { in: %w(disabled user moderator admin) }
   validates :site_contact_email, :site_contact_username, presence: true
diff --git a/app/validators/html_validator.rb b/app/validators/html_validator.rb
index b7caee5a9e..1c9cd303cf 100644
--- a/app/validators/html_validator.rb
+++ b/app/validators/html_validator.rb
@@ -1,18 +1,20 @@
 # frozen_string_literal: true
 
 class HtmlValidator < ActiveModel::EachValidator
+  ERROR_RE = /Opening and ending tag mismatch|Unexpected end tag/
+
   def validate_each(record, attribute, value)
     return if value.blank?
+
     errors = html_errors(value)
-    unless errors.empty?
-      record.errors.add(attribute, I18n.t('html_validator.invalid_markup', error: errors.first.to_s))
-    end
+
+    record.errors.add(attribute, I18n.t('html_validator.invalid_markup', error: errors.first.to_s)) unless errors.empty?
   end
 
   private
 
   def html_errors(str)
-    fragment = Nokogiri::HTML.fragment(str)
-    fragment.errors
+    fragment = Nokogiri::HTML.fragment(options[:wrap_with] ? "<#{options[:wrap_with]}>#{str}</#{options[:wrap_with]}>" : str)
+    fragment.errors.select { |error| ERROR_RE =~ error.message }
   end
 end

From 9b0d8f74cbbb04c4b1227293137774db78b67896 Mon Sep 17 00:00:00 2001
From: Eugen Rochko <eugen@zeonfederated.com>
Date: Wed, 10 Apr 2019 03:47:11 +0200
Subject: [PATCH 15/16] Change the groupings of menu items in settings
 navigation (#10533)

* Change the groupings of menu items in settings navigation

Fix #10307

* Remove unused translations
---
 app/views/settings/preferences/show.html.haml |  1 +
 config/locales/ar.yml                         |  2 -
 config/locales/ast.yml                        |  1 -
 config/locales/bg.yml                         |  1 -
 config/locales/ca.yml                         |  2 -
 config/locales/co.yml                         |  2 -
 config/locales/cs.yml                         |  2 -
 config/locales/cy.yml                         |  2 -
 config/locales/da.yml                         |  2 -
 config/locales/de.yml                         |  2 -
 config/locales/el.yml                         |  2 -
 config/locales/en.yml                         |  6 +-
 config/locales/en_GB.yml                      |  2 -
 config/locales/eo.yml                         |  2 -
 config/locales/es.yml                         |  2 -
 config/locales/eu.yml                         |  2 -
 config/locales/fa.yml                         |  2 -
 config/locales/fi.yml                         |  2 -
 config/locales/fr.yml                         |  2 -
 config/locales/gl.yml                         |  2 -
 config/locales/he.yml                         |  1 -
 config/locales/hr.yml                         |  1 -
 config/locales/hu.yml                         |  2 -
 config/locales/id.yml                         |  1 -
 config/locales/io.yml                         |  1 -
 config/locales/it.yml                         |  2 -
 config/locales/ja.yml                         |  2 -
 config/locales/ka.yml                         |  2 -
 config/locales/kk.yml                         |  2 -
 config/locales/ko.yml                         |  2 -
 config/locales/lt.yml                         |  2 -
 config/locales/nl.yml                         |  2 -
 config/locales/no.yml                         |  2 -
 config/locales/oc.yml                         |  2 -
 config/locales/pl.yml                         |  2 -
 config/locales/pt-BR.yml                      |  2 -
 config/locales/pt.yml                         |  2 -
 config/locales/ru.yml                         |  2 -
 config/locales/sk.yml                         |  2 -
 config/locales/sq.yml                         |  2 -
 config/locales/sr-Latn.yml                    |  2 -
 config/locales/sr.yml                         |  2 -
 config/locales/sv.yml                         |  2 -
 config/locales/th.yml                         |  2 -
 config/locales/tr.yml                         |  1 -
 config/locales/uk.yml                         |  2 -
 config/locales/zh-CN.yml                      |  2 -
 config/locales/zh-HK.yml                      |  2 -
 config/locales/zh-TW.yml                      |  2 -
 config/navigation.rb                          | 73 ++++++++++---------
 50 files changed, 43 insertions(+), 124 deletions(-)

diff --git a/app/views/settings/preferences/show.html.haml b/app/views/settings/preferences/show.html.haml
index 3cb91631ed..d81ee61add 100644
--- a/app/views/settings/preferences/show.html.haml
+++ b/app/views/settings/preferences/show.html.haml
@@ -6,6 +6,7 @@
   %li= link_to t('preferences.publishing'), '#settings_publishing'
   %li= link_to t('preferences.other'), '#settings_other'
   %li= link_to t('preferences.web'), '#settings_web'
+  %li= link_to t('settings.notifications'), settings_notifications_path
 
 = simple_form_for current_user, url: settings_preferences_path, html: { method: :put } do |f|
   = render 'shared/error_messages', object: current_user
diff --git a/config/locales/ar.yml b/config/locales/ar.yml
index e0ccb63a94..fe49ac7f6b 100644
--- a/config/locales/ar.yml
+++ b/config/locales/ar.yml
@@ -812,9 +812,7 @@ ar:
     migrate: تهجير الحساب
     notifications: الإخطارات
     preferences: التفضيلات
-    settings: الإعدادات
     two_factor_authentication: المُصادقة بخُطوَتَيْن
-    your_apps: تطبيقاتك
   statuses:
     attached:
       description: 'مُرفَق : %{attached}'
diff --git a/config/locales/ast.yml b/config/locales/ast.yml
index f6892923c1..7a51be7cf4 100644
--- a/config/locales/ast.yml
+++ b/config/locales/ast.yml
@@ -300,7 +300,6 @@ ast:
     import: Importación
     notifications: Avisos
     preferences: Preferencies
-    settings: Axustes
     two_factor_authentication: Autenticación en dos pasos
   statuses:
     attached:
diff --git a/config/locales/bg.yml b/config/locales/bg.yml
index 2424d93991..57aa6f87e0 100644
--- a/config/locales/bg.yml
+++ b/config/locales/bg.yml
@@ -122,7 +122,6 @@ bg:
     export: Експортиране на данни
     import: Импортиране
     preferences: Предпочитания
-    settings: Настройки
     two_factor_authentication: Двустепенно удостоверяване
   statuses:
     open_in_web: Отвори в уеб
diff --git a/config/locales/ca.yml b/config/locales/ca.yml
index 5fd2ff8234..17a5d9d0ce 100644
--- a/config/locales/ca.yml
+++ b/config/locales/ca.yml
@@ -867,9 +867,7 @@ ca:
     notifications: Notificacions
     preferences: Preferències
     relationships: Seguits i seguidors
-    settings: Configuració
     two_factor_authentication: Autenticació de dos factors
-    your_apps: Les teves aplicacions
   statuses:
     attached:
       description: 'Adjunt: %{attached}'
diff --git a/config/locales/co.yml b/config/locales/co.yml
index c4122b6d94..311e3f1427 100644
--- a/config/locales/co.yml
+++ b/config/locales/co.yml
@@ -873,9 +873,7 @@ co:
     notifications: Nutificazione
     preferences: Priferenze
     relationships: Abbunamenti è abbunati
-    settings: Parametri
     two_factor_authentication: Identificazione à dui fattori
-    your_apps: E vostre applicazione
   statuses:
     attached:
       description: 'Aghjuntu: %{attached}'
diff --git a/config/locales/cs.yml b/config/locales/cs.yml
index 7917166de7..fdb0252bd4 100644
--- a/config/locales/cs.yml
+++ b/config/locales/cs.yml
@@ -883,9 +883,7 @@ cs:
     notifications: Oznámení
     preferences: Předvolby
     relationships: Sledovaní a sledující
-    settings: Nastavení
     two_factor_authentication: Dvoufázové ověřování
-    your_apps: Vaše aplikace
   statuses:
     attached:
       description: 'Přiloženo: %{attached}'
diff --git a/config/locales/cy.yml b/config/locales/cy.yml
index 9ab4fc394e..f365f71733 100644
--- a/config/locales/cy.yml
+++ b/config/locales/cy.yml
@@ -812,9 +812,7 @@ cy:
     migrate: Mudo cyfrif
     notifications: Hysbysiadau
     preferences: Dewisiadau
-    settings: Gosodiadau
     two_factor_authentication: Awdurdodi dau-gam
-    your_apps: Eich rhaglenni
   statuses:
     attached:
       description: 'Ynghlwm: %{attached}'
diff --git a/config/locales/da.yml b/config/locales/da.yml
index 2156acb443..0787db621f 100644
--- a/config/locales/da.yml
+++ b/config/locales/da.yml
@@ -700,9 +700,7 @@ da:
     migrate: Konto migrering
     notifications: Notifikationer
     preferences: Præferencer
-    settings: Indstillinger
     two_factor_authentication: To-faktor godkendelse
-    your_apps: Dine applikationer
   statuses:
     attached:
       description: 'Vedhæftede: %{attached}'
diff --git a/config/locales/de.yml b/config/locales/de.yml
index cfe527b0a6..aaf1c30b2c 100644
--- a/config/locales/de.yml
+++ b/config/locales/de.yml
@@ -868,9 +868,7 @@ de:
     notifications: Benachrichtigungen
     preferences: Einstellungen
     relationships: Folgende und Follower
-    settings: Einstellungen
     two_factor_authentication: Zwei-Faktor-Auth
-    your_apps: Deine Anwendungen
   statuses:
     attached:
       description: 'Angehängt: %{attached}'
diff --git a/config/locales/el.yml b/config/locales/el.yml
index 8ff42acbfe..f2b6751ff6 100644
--- a/config/locales/el.yml
+++ b/config/locales/el.yml
@@ -859,9 +859,7 @@ el:
     notifications: Ειδοποιήσεις
     preferences: Προτιμήσεις
     relationships: Ακολουθεί και ακολουθείται
-    settings: Ρυθμίσεις
     two_factor_authentication: Πιστοποίηση 2 παραγόντων (2FA)
-    your_apps: Οι εφαρμογές σου
   statuses:
     attached:
       description: 'Συνημμένα: %{attached}'
diff --git a/config/locales/en.yml b/config/locales/en.yml
index 60540ecdce..838d6adc32 100644
--- a/config/locales/en.yml
+++ b/config/locales/en.yml
@@ -860,6 +860,8 @@ en:
     revoke_success: Session successfully revoked
     title: Sessions
   settings:
+    account: Account
+    account_settings: Account settings
     authorized_apps: Authorized apps
     back: Back to Mastodon
     delete: Account deletion
@@ -869,13 +871,13 @@ en:
     featured_tags: Featured hashtags
     identity_proofs: Identity proofs
     import: Import
+    import_and_export: Import and export
     migrate: Account migration
     notifications: Notifications
     preferences: Preferences
+    profile: Profile
     relationships: Follows and followers
-    settings: Settings
     two_factor_authentication: Two-factor Auth
-    your_apps: Your applications
   statuses:
     attached:
       description: 'Attached: %{attached}'
diff --git a/config/locales/en_GB.yml b/config/locales/en_GB.yml
index 743989879e..d428a95c3f 100644
--- a/config/locales/en_GB.yml
+++ b/config/locales/en_GB.yml
@@ -854,9 +854,7 @@ en_GB:
     notifications: Notifications
     preferences: Preferences
     relationships: Follows and followers
-    settings: Settings
     two_factor_authentication: Two-factor Auth
-    your_apps: Your applications
   statuses:
     attached:
       description: 'Attached: %{attached}'
diff --git a/config/locales/eo.yml b/config/locales/eo.yml
index cce32cc561..b85cb1a491 100644
--- a/config/locales/eo.yml
+++ b/config/locales/eo.yml
@@ -869,9 +869,7 @@ eo:
     notifications: Sciigoj
     preferences: Preferoj
     relationships: Follows and followers
-    settings: Agordoj
     two_factor_authentication: Dufaktora aŭtentigo
-    your_apps: Viaj aplikaĵoj
   statuses:
     attached:
       description: 'Ligita: %{attached}'
diff --git a/config/locales/es.yml b/config/locales/es.yml
index c0b6cfb3b5..3a8e8dc0b0 100644
--- a/config/locales/es.yml
+++ b/config/locales/es.yml
@@ -705,9 +705,7 @@ es:
     migrate: Migración de cuenta
     notifications: Notificaciones
     preferences: Preferencias
-    settings: Ajustes
     two_factor_authentication: Autenticación de dos factores
-    your_apps: Tus aplicaciones
   statuses:
     attached:
       description: 'Adjunto: %{attached}'
diff --git a/config/locales/eu.yml b/config/locales/eu.yml
index 50e5b66394..5ae664cadd 100644
--- a/config/locales/eu.yml
+++ b/config/locales/eu.yml
@@ -787,9 +787,7 @@ eu:
     migrate: Kontuaren migrazioa
     notifications: Jakinarazpenak
     preferences: Hobespenak
-    settings: Ezarpenak
     two_factor_authentication: Bi faktoreetako autentifikazioa
-    your_apps: Zure aplikazioak
   statuses:
     attached:
       description: 'Erantsita: %{attached}'
diff --git a/config/locales/fa.yml b/config/locales/fa.yml
index 0cf3809218..3a3455c6d1 100644
--- a/config/locales/fa.yml
+++ b/config/locales/fa.yml
@@ -860,9 +860,7 @@ fa:
     notifications: اعلان‌ها
     preferences: ترجیحات
     relationships: پیگیری‌ها و پیگیران
-    settings: تنظیمات
     two_factor_authentication: ورود دومرحله‌ای
-    your_apps: برنامهٔ شما
   statuses:
     attached:
       description: 'پیوست‌شده: %{attached}'
diff --git a/config/locales/fi.yml b/config/locales/fi.yml
index 47ff00434e..e4a0ed22cb 100644
--- a/config/locales/fi.yml
+++ b/config/locales/fi.yml
@@ -613,9 +613,7 @@ fi:
     migrate: Tilin muutto muualle
     notifications: Ilmoitukset
     preferences: Ominaisuudet
-    settings: Asetukset
     two_factor_authentication: Kaksivaiheinen todentaminen
-    your_apps: Omat sovellukset
   statuses:
     attached:
       description: 'Liitetty: %{attached}'
diff --git a/config/locales/fr.yml b/config/locales/fr.yml
index f1d81acf02..a6c806de39 100644
--- a/config/locales/fr.yml
+++ b/config/locales/fr.yml
@@ -798,9 +798,7 @@ fr:
     migrate: Migration de compte
     notifications: Notifications
     preferences: Préférences
-    settings: Réglages
     two_factor_authentication: Identification à deux facteurs
-    your_apps: Vos applications
   statuses:
     attached:
       description: 'Attaché : %{attached}'
diff --git a/config/locales/gl.yml b/config/locales/gl.yml
index 0ee3a329ca..9c4673186b 100644
--- a/config/locales/gl.yml
+++ b/config/locales/gl.yml
@@ -855,9 +855,7 @@ gl:
     notifications: Notificacións
     preferences: Preferencias
     relationships: Seguindo e seguidoras
-    settings: Axustes
     two_factor_authentication: Validar Doble Factor
-    your_apps: As súas aplicacións
   statuses:
     attached:
       description: 'Axenado: %{attached}'
diff --git a/config/locales/he.yml b/config/locales/he.yml
index 089af2bebd..e471c4d025 100644
--- a/config/locales/he.yml
+++ b/config/locales/he.yml
@@ -310,7 +310,6 @@ he:
     export: יצוא מידע
     import: יבוא
     preferences: העדפות
-    settings: הגדרות
     two_factor_authentication: אימות דו-שלבי
   statuses:
     open_in_web: פתח ברשת
diff --git a/config/locales/hr.yml b/config/locales/hr.yml
index f53515d7af..f9c552bce1 100644
--- a/config/locales/hr.yml
+++ b/config/locales/hr.yml
@@ -115,7 +115,6 @@ hr:
     export: Izvoz podataka
     import: Uvezi
     preferences: Postavke
-    settings: Podešenja
     two_factor_authentication: Dvo-faktorska Autentifikacija
   statuses:
     open_in_web: Otvori na webu
diff --git a/config/locales/hu.yml b/config/locales/hu.yml
index f32f6f4079..b6029eecab 100644
--- a/config/locales/hu.yml
+++ b/config/locales/hu.yml
@@ -533,9 +533,7 @@ hu:
     migrate: Fiók átirányítása
     notifications: Értesítések
     preferences: Általános beállítások
-    settings: Beállítások
     two_factor_authentication: Kétlépcsős azonosítás
-    your_apps: Alkalmazásaid
   statuses:
     open_in_web: Megnyitás a weben
     over_character_limit: Túllépted a maximális %{max} karakteres keretet
diff --git a/config/locales/id.yml b/config/locales/id.yml
index a27f1f0088..4323c145fc 100644
--- a/config/locales/id.yml
+++ b/config/locales/id.yml
@@ -334,7 +334,6 @@ id:
     export: Expor data
     import: Impor
     preferences: Pilihan
-    settings: Pengaturan
     two_factor_authentication: Autentikasi Two-factor
   statuses:
     open_in_web: Buka di web
diff --git a/config/locales/io.yml b/config/locales/io.yml
index b926fe6415..b5edb2aa32 100644
--- a/config/locales/io.yml
+++ b/config/locales/io.yml
@@ -235,7 +235,6 @@ io:
     export: Exportacar datumi
     import: Importacar
     preferences: Preferi
-    settings: Settings
     two_factor_authentication: Dufaktora autentikigo
   statuses:
     open_in_web: Apertar retnavigile
diff --git a/config/locales/it.yml b/config/locales/it.yml
index bb170bc4a2..508b8a0dc9 100644
--- a/config/locales/it.yml
+++ b/config/locales/it.yml
@@ -762,9 +762,7 @@ it:
     migrate: Migrazione dell'account
     notifications: Notifiche
     preferences: Preferenze
-    settings: Impostazioni
     two_factor_authentication: Autenticazione a due fattori
-    your_apps: Le tue applicazioni
   statuses:
     attached:
       description: 'Allegato: %{attached}'
diff --git a/config/locales/ja.yml b/config/locales/ja.yml
index 85e97580e8..a4026fcfc0 100644
--- a/config/locales/ja.yml
+++ b/config/locales/ja.yml
@@ -871,9 +871,7 @@ ja:
     notifications: 通知
     preferences: ユーザー設定
     relationships: フォロー・フォロワー
-    settings: 設定
     two_factor_authentication: 二段階認証
-    your_apps: アプリ
   statuses:
     attached:
       description: '添付: %{attached}'
diff --git a/config/locales/ka.yml b/config/locales/ka.yml
index 758a0429e3..9781fc5be9 100644
--- a/config/locales/ka.yml
+++ b/config/locales/ka.yml
@@ -668,9 +668,7 @@ ka:
     migrate: ანგარიშის მიგრაცია
     notifications: შეტყობინებები
     preferences: პრეფერენციები
-    settings: პარამეტრები
     two_factor_authentication: მეორე-ფაქტორის აუტენტიფიკაცია
-    your_apps: თქვენი აპლიკაციები
   statuses:
     attached:
       description: 'თან დართული: %{attached}'
diff --git a/config/locales/kk.yml b/config/locales/kk.yml
index da91ca9c47..84bd710818 100644
--- a/config/locales/kk.yml
+++ b/config/locales/kk.yml
@@ -797,9 +797,7 @@ kk:
     migrate: Аккаунт көшіру
     notifications: Ескертпелер
     preferences: Таңдаулар
-    settings: Баптаулар
     two_factor_authentication: Екі-факторлы авторизация
-    your_apps: Қосымшалар
   statuses:
     attached:
       description: 'Жүктелді: %{attached}'
diff --git a/config/locales/ko.yml b/config/locales/ko.yml
index c97fd82092..cf0a993849 100644
--- a/config/locales/ko.yml
+++ b/config/locales/ko.yml
@@ -874,9 +874,7 @@ ko:
     notifications: 알림
     preferences: 사용자 설정
     relationships: 팔로잉과 팔로워
-    settings: 설정
     two_factor_authentication: 2단계 인증
-    your_apps: 애플리케이션
   statuses:
     attached:
       description: '첨부: %{attached}'
diff --git a/config/locales/lt.yml b/config/locales/lt.yml
index 97994c3627..7ea8dc76b2 100644
--- a/config/locales/lt.yml
+++ b/config/locales/lt.yml
@@ -800,9 +800,7 @@ lt:
     migrate: Paskyros migracija
     notifications: Pranešimai
     preferences: Preferencijos
-    settings: Nustatymai
     two_factor_authentication: Dviejų veiksnių autentikacija
-    your_apps: Jūsų aplikacijos
   statuses:
     attached:
       description: 'Pridėta: %{attached}'
diff --git a/config/locales/nl.yml b/config/locales/nl.yml
index ca0f57ae0b..ae274ad702 100644
--- a/config/locales/nl.yml
+++ b/config/locales/nl.yml
@@ -856,9 +856,7 @@ nl:
     notifications: Meldingen
     preferences: Voorkeuren
     relationships: Volgers en gevolgden
-    settings: Instellingen
     two_factor_authentication: Tweestapsverificatie
-    your_apps: Jouw toepassingen
   statuses:
     attached:
       description: 'Bijlagen: %{attached}'
diff --git a/config/locales/no.yml b/config/locales/no.yml
index d6475afd6a..f16b314cb6 100644
--- a/config/locales/no.yml
+++ b/config/locales/no.yml
@@ -533,9 +533,7 @@
     migrate: Kontomigrering
     notifications: Varslinger
     preferences: Preferanser
-    settings: Innstillinger
     two_factor_authentication: Tofaktorautentisering
-    your_apps: Dine applikasjoner
   statuses:
     open_in_web: Åpne i nettleser
     over_character_limit: grense på %{max} tegn overskredet
diff --git a/config/locales/oc.yml b/config/locales/oc.yml
index d1c6d11d9f..81f17cd3dc 100644
--- a/config/locales/oc.yml
+++ b/config/locales/oc.yml
@@ -890,9 +890,7 @@ oc:
     notifications: Notificacions
     preferences: Preferéncias
     relationships: Abonaments e seguidors
-    settings: Paramètres
     two_factor_authentication: Autentificacion en dos temps
-    your_apps: Vòstras aplicacions
   statuses:
     attached:
       description: 'Ajustat : %{attached}'
diff --git a/config/locales/pl.yml b/config/locales/pl.yml
index 192a56dcf6..1b9bb614c3 100644
--- a/config/locales/pl.yml
+++ b/config/locales/pl.yml
@@ -889,9 +889,7 @@ pl:
     notifications: Powiadomienia
     preferences: Preferencje
     relationships: Śledzeni i śledzący
-    settings: Ustawienia
     two_factor_authentication: Uwierzytelnianie dwuetapowe
-    your_apps: Twoje aplikacje
   statuses:
     attached:
       description: 'Załączono: %{attached}'
diff --git a/config/locales/pt-BR.yml b/config/locales/pt-BR.yml
index 4fdacf51d4..2d11712887 100644
--- a/config/locales/pt-BR.yml
+++ b/config/locales/pt-BR.yml
@@ -867,9 +867,7 @@ pt-BR:
     notifications: Notificações
     preferences: Preferências
     relationships: Seguindo e seguidores
-    settings: Configurações
     two_factor_authentication: Autenticação em dois passos
-    your_apps: Seus aplicativos
   statuses:
     attached:
       description: 'Anexado: %{attached}'
diff --git a/config/locales/pt.yml b/config/locales/pt.yml
index 92c8ab42f7..b827184e90 100644
--- a/config/locales/pt.yml
+++ b/config/locales/pt.yml
@@ -800,9 +800,7 @@ pt:
     migrate: Migração de conta
     notifications: Notificações
     preferences: Preferências
-    settings: Configurações
     two_factor_authentication: Autenticação em dois passos
-    your_apps: As tuas aplicações
   statuses:
     attached:
       description: 'Anexadas: %{attached}'
diff --git a/config/locales/ru.yml b/config/locales/ru.yml
index e821502583..0d912d3523 100644
--- a/config/locales/ru.yml
+++ b/config/locales/ru.yml
@@ -698,9 +698,7 @@ ru:
     migrate: Перенос аккаунта
     notifications: Уведомления
     preferences: Настройки
-    settings: Опции
     two_factor_authentication: Двухфакторная аутентификация
-    your_apps: Ваши приложения
   statuses:
     attached:
       description: 'Вложение: %{attached}'
diff --git a/config/locales/sk.yml b/config/locales/sk.yml
index 9dcb3f4701..bf7898ed74 100644
--- a/config/locales/sk.yml
+++ b/config/locales/sk.yml
@@ -831,9 +831,7 @@ sk:
     migrate: Presunutie účtu
     notifications: Oznámenia
     preferences: Voľby
-    settings: Nastavenia
     two_factor_authentication: Dvoj-faktorové overenie
-    your_apps: Tvoje aplikácie
   statuses:
     attached:
       description: 'Priložené: %{attached}'
diff --git a/config/locales/sq.yml b/config/locales/sq.yml
index 8303abea80..ea36a2189f 100644
--- a/config/locales/sq.yml
+++ b/config/locales/sq.yml
@@ -784,9 +784,7 @@ sq:
     migrate: Migrim llogarie
     notifications: Njoftime
     preferences: Parapëlqime
-    settings: Rregullime
     two_factor_authentication: Mirëfilltësim Dyfaktorësh
-    your_apps: Aplikacionet tuaja
   statuses:
     attached:
       description: 'Bashkëngjitur: %{attached}'
diff --git a/config/locales/sr-Latn.yml b/config/locales/sr-Latn.yml
index 468867e679..2292b6a7f8 100644
--- a/config/locales/sr-Latn.yml
+++ b/config/locales/sr-Latn.yml
@@ -523,9 +523,7 @@ sr-Latn:
     migrate: Prebacivanje naloga
     notifications: Obaveštenja
     preferences: Podešavanja
-    settings: Postavke
     two_factor_authentication: Dvofaktorska identifikacija
-    your_apps: Vaše aplikacije
   statuses:
     open_in_web: Otvori u vebu
     over_character_limit: ograničenje od %{max} karaktera prekoračeno
diff --git a/config/locales/sr.yml b/config/locales/sr.yml
index 49252b5000..2bf9001ce5 100644
--- a/config/locales/sr.yml
+++ b/config/locales/sr.yml
@@ -792,9 +792,7 @@ sr:
     migrate: Пребацивање налога
     notifications: Обавештења
     preferences: Подешавања
-    settings: Поставке
     two_factor_authentication: Двофакторска идентификација
-    your_apps: Ваше апликације
   statuses:
     attached:
       description: 'У прилогу: %{attached}'
diff --git a/config/locales/sv.yml b/config/locales/sv.yml
index ef208aceae..91d4c2496d 100644
--- a/config/locales/sv.yml
+++ b/config/locales/sv.yml
@@ -600,9 +600,7 @@ sv:
     migrate: Kontoflytt
     notifications: Meddelanden
     preferences: Inställningar
-    settings: Inställningar
     two_factor_authentication: Tvåstegsautentisering
-    your_apps: Dina applikationer
   statuses:
     attached:
       description: 'Bifogad: %{attached}'
diff --git a/config/locales/th.yml b/config/locales/th.yml
index 729865c83c..2ebd6c7f1c 100644
--- a/config/locales/th.yml
+++ b/config/locales/th.yml
@@ -590,9 +590,7 @@ th:
     notifications: การแจ้งเตือน
     preferences: การกำหนดลักษณะ
     relationships: การติดตามและผู้ติดตาม
-    settings: การตั้งค่า
     two_factor_authentication: การรับรองความถูกต้องด้วยสองปัจจัย
-    your_apps: แอปพลิเคชันของคุณ
   statuses:
     attached:
       description: 'แนบ: %{attached}'
diff --git a/config/locales/tr.yml b/config/locales/tr.yml
index 14e7f34df5..e3e27e3ef3 100644
--- a/config/locales/tr.yml
+++ b/config/locales/tr.yml
@@ -347,7 +347,6 @@ tr:
     export: Dışa aktar
     import: İçe aktar
     preferences: Tercihler
-    settings: Ayarlar
     two_factor_authentication: İki-faktörlü doğrulama
   statuses:
     open_in_web: Web sayfasında aç
diff --git a/config/locales/uk.yml b/config/locales/uk.yml
index 12f2d13a1f..a582b23853 100644
--- a/config/locales/uk.yml
+++ b/config/locales/uk.yml
@@ -648,9 +648,7 @@ uk:
     migrate: Міграція акаунту
     notifications: Сповіщення
     preferences: Налаштування
-    settings: Опції
     two_factor_authentication: Двофакторна авторизація
-    your_apps: Ваші затосунки
   statuses:
     attached:
       description: 'Прикріплено: %{attached}'
diff --git a/config/locales/zh-CN.yml b/config/locales/zh-CN.yml
index 4eafa70f4c..ae49c05371 100644
--- a/config/locales/zh-CN.yml
+++ b/config/locales/zh-CN.yml
@@ -670,9 +670,7 @@ zh-CN:
     migrate: 帐户迁移
     notifications: 通知
     preferences: 首选项
-    settings: 设置
     two_factor_authentication: 双重认证
-    your_apps: 你的应用
   statuses:
     attached:
       description: 附加媒体:%{attached}
diff --git a/config/locales/zh-HK.yml b/config/locales/zh-HK.yml
index 9ff97805d6..aade1debb4 100644
--- a/config/locales/zh-HK.yml
+++ b/config/locales/zh-HK.yml
@@ -597,9 +597,7 @@ zh-HK:
     migrate: 帳戶遷移
     notifications: 通知
     preferences: 偏好設定
-    settings: 設定
     two_factor_authentication: 雙重認證
-    your_apps: 你的應用程式
   statuses:
     attached:
       description: 附件: %{attached}
diff --git a/config/locales/zh-TW.yml b/config/locales/zh-TW.yml
index 9a13a602f3..988357e1b1 100644
--- a/config/locales/zh-TW.yml
+++ b/config/locales/zh-TW.yml
@@ -666,9 +666,7 @@ zh-TW:
     migrate: 帳戶搬遷
     notifications: 通知
     preferences: 偏好設定
-    settings: 設定
     two_factor_authentication: 兩階段認證
-    your_apps: 你的應用程式
   statuses:
     attached:
       description: 附件: %{attached}
diff --git a/config/navigation.rb b/config/navigation.rb
index dd5825867b..c2a8e45cea 100644
--- a/config/navigation.rb
+++ b/config/navigation.rb
@@ -1,50 +1,53 @@
 # frozen_string_literal: true
 
 SimpleNavigation::Configuration.run do |navigation|
-  navigation.items do |primary|
-    primary.item :web, safe_join([fa_icon('chevron-left fw'), t('settings.back')]), root_url
+  navigation.items do |n|
+    n.item :web, safe_join([fa_icon('chevron-left fw'), t('settings.back')]), root_url
 
-    primary.item :settings, safe_join([fa_icon('cog fw'), t('settings.settings')]), settings_profile_url do |settings|
-      settings.item :profile, safe_join([fa_icon('user fw'), t('settings.edit_profile')]), settings_profile_url, highlights_on: %r{/settings/profile|/settings/migration}
-      settings.item :featured_tags, safe_join([fa_icon('hashtag fw'), t('settings.featured_tags')]), settings_featured_tags_url
-      settings.item :preferences, safe_join([fa_icon('sliders fw'), t('settings.preferences')]), settings_preferences_url
-      settings.item :notifications, safe_join([fa_icon('bell fw'), t('settings.notifications')]), settings_notifications_url
-      settings.item :password, safe_join([fa_icon('lock fw'), t('auth.security')]), edit_user_registration_url, highlights_on: %r{/auth/edit|/settings/delete}
-      settings.item :two_factor_authentication, safe_join([fa_icon('mobile fw'), t('settings.two_factor_authentication')]), settings_two_factor_authentication_url, highlights_on: %r{/settings/two_factor_authentication}
-      settings.item :import, safe_join([fa_icon('cloud-upload fw'), t('settings.import')]), settings_import_url
-      settings.item :export, safe_join([fa_icon('cloud-download fw'), t('settings.export')]), settings_export_url
-      settings.item :authorized_apps, safe_join([fa_icon('list fw'), t('settings.authorized_apps')]), oauth_authorized_applications_url
-      settings.item :identity_proofs, safe_join([fa_icon('key fw'), t('settings.identity_proofs')]), settings_identity_proofs_path, highlights_on: %r{/settings/identity_proofs*}, if: proc { current_account.identity_proofs.exists? }
+    n.item :profile, safe_join([fa_icon('user fw'), t('settings.profile')]), settings_profile_url do |s|
+      s.item :profile, safe_join([fa_icon('pencil fw'), t('settings.appearance')]), settings_profile_url, highlights_on: %r{/settings/profile|/settings/migration}
+      s.item :featured_tags, safe_join([fa_icon('hashtag fw'), t('settings.featured_tags')]), settings_featured_tags_url
+      s.item :identity_proofs, safe_join([fa_icon('key fw'), t('settings.identity_proofs')]), settings_identity_proofs_path, highlights_on: %r{/settings/identity_proofs*}, if: proc { current_account.identity_proofs.exists? }
     end
 
-    primary.item :relationships, safe_join([fa_icon('users fw'), t('settings.relationships')]), relationships_url
-    primary.item :filters, safe_join([fa_icon('filter fw'), t('filters.index.title')]), filters_path, highlights_on: %r{/filters}
-    primary.item :invites, safe_join([fa_icon('user-plus fw'), t('invites.title')]), invites_path, if: proc { Setting.min_invite_role == 'user' }
+    n.item :preferences, safe_join([fa_icon('cog fw'), t('settings.preferences')]), settings_preferences_url, highlights_on: %r{/settings/preferences|/settings/notifications}
+    n.item :relationships, safe_join([fa_icon('users fw'), t('settings.relationships')]), relationships_url
+    n.item :filters, safe_join([fa_icon('filter fw'), t('filters.index.title')]), filters_path, highlights_on: %r{/filters}
 
-    primary.item :development, safe_join([fa_icon('code fw'), t('settings.development')]), settings_applications_url do |development|
-      development.item :your_apps, safe_join([fa_icon('list fw'), t('settings.your_apps')]), settings_applications_url, highlights_on: %r{/settings/applications}
+    n.item :security, safe_join([fa_icon('lock fw'), t('settings.account')]), edit_user_registration_url do |s|
+      s.item :password, safe_join([fa_icon('lock fw'), t('settings.account_settings')]), edit_user_registration_url, highlights_on: %r{/auth/edit|/settings/delete}
+      s.item :two_factor_authentication, safe_join([fa_icon('mobile fw'), t('settings.two_factor_authentication')]), settings_two_factor_authentication_url, highlights_on: %r{/settings/two_factor_authentication}
+      s.item :authorized_apps, safe_join([fa_icon('list fw'), t('settings.authorized_apps')]), oauth_authorized_applications_url
     end
 
-    primary.item :moderation, safe_join([fa_icon('gavel fw'), t('moderation.title')]), admin_reports_url, if: proc { current_user.staff? } do |admin|
-      admin.item :action_logs, safe_join([fa_icon('bars fw'), t('admin.action_logs.title')]), admin_action_logs_url
-      admin.item :reports, safe_join([fa_icon('flag fw'), t('admin.reports.title')]), admin_reports_url, highlights_on: %r{/admin/reports}
-      admin.item :accounts, safe_join([fa_icon('users fw'), t('admin.accounts.title')]), admin_accounts_url, highlights_on: %r{/admin/accounts|/admin/pending_accounts}
-      admin.item :invites, safe_join([fa_icon('user-plus fw'), t('admin.invites.title')]), admin_invites_path
-      admin.item :tags, safe_join([fa_icon('tag fw'), t('admin.tags.title')]), admin_tags_path
-      admin.item :instances, safe_join([fa_icon('cloud fw'), t('admin.instances.title')]), admin_instances_url(limited: '1'), highlights_on: %r{/admin/instances|/admin/domain_blocks}, if: -> { current_user.admin? }
-      admin.item :email_domain_blocks, safe_join([fa_icon('envelope fw'), t('admin.email_domain_blocks.title')]), admin_email_domain_blocks_url, highlights_on: %r{/admin/email_domain_blocks}, if: -> { current_user.admin? }
+    n.item :data, safe_join([fa_icon('cloud-download fw'), t('settings.import_and_export')]), settings_export_url do |s|
+      s.item :import, safe_join([fa_icon('cloud-upload fw'), t('settings.import')]), settings_import_url
+      s.item :export, safe_join([fa_icon('cloud-download fw'), t('settings.export')]), settings_export_url
     end
 
-    primary.item :admin, safe_join([fa_icon('cogs fw'), t('admin.title')]), admin_dashboard_url, if: proc { current_user.staff? } do |admin|
-      admin.item :dashboard, safe_join([fa_icon('tachometer fw'), t('admin.dashboard.title')]), admin_dashboard_url
-      admin.item :settings, safe_join([fa_icon('cogs fw'), t('admin.settings.title')]), edit_admin_settings_url, if: -> { current_user.admin? }, highlights_on: %r{/admin/settings}
-      admin.item :custom_emojis, safe_join([fa_icon('smile-o fw'), t('admin.custom_emojis.title')]), admin_custom_emojis_url, highlights_on: %r{/admin/custom_emojis}
-      admin.item :relays, safe_join([fa_icon('exchange fw'), t('admin.relays.title')]), admin_relays_url, if: -> { current_user.admin? }, highlights_on: %r{/admin/relays}
-      admin.item :subscriptions, safe_join([fa_icon('paper-plane-o fw'), t('admin.subscriptions.title')]), admin_subscriptions_url, if: -> { current_user.admin? }
-      admin.item :sidekiq, safe_join([fa_icon('diamond fw'), 'Sidekiq']), sidekiq_url, link_html: { target: 'sidekiq' }, if: -> { current_user.admin? }
-      admin.item :pghero, safe_join([fa_icon('database fw'), 'PgHero']), pghero_url, link_html: { target: 'pghero' }, if: -> { current_user.admin? }
+    n.item :invites, safe_join([fa_icon('user-plus fw'), t('invites.title')]), invites_path, if: proc { Setting.min_invite_role == 'user' }
+    n.item :development, safe_join([fa_icon('code fw'), t('settings.development')]), settings_applications_url
+
+    n.item :moderation, safe_join([fa_icon('gavel fw'), t('moderation.title')]), admin_reports_url, if: proc { current_user.staff? } do |s|
+      s.item :action_logs, safe_join([fa_icon('bars fw'), t('admin.action_logs.title')]), admin_action_logs_url
+      s.item :reports, safe_join([fa_icon('flag fw'), t('admin.reports.title')]), admin_reports_url, highlights_on: %r{/admin/reports}
+      s.item :accounts, safe_join([fa_icon('users fw'), t('admin.accounts.title')]), admin_accounts_url, highlights_on: %r{/admin/accounts|/admin/pending_accounts}
+      s.item :invites, safe_join([fa_icon('user-plus fw'), t('admin.invites.title')]), admin_invites_path
+      s.item :tags, safe_join([fa_icon('tag fw'), t('admin.tags.title')]), admin_tags_path
+      s.item :instances, safe_join([fa_icon('cloud fw'), t('admin.instances.title')]), admin_instances_url(limited: '1'), highlights_on: %r{/admin/instances|/admin/domain_blocks}, if: -> { current_user.admin? }
+      s.item :email_domain_blocks, safe_join([fa_icon('envelope fw'), t('admin.email_domain_blocks.title')]), admin_email_domain_blocks_url, highlights_on: %r{/admin/email_domain_blocks}, if: -> { current_user.admin? }
     end
 
-    primary.item :logout, safe_join([fa_icon('sign-out fw'), t('auth.logout')]), destroy_user_session_url, link_html: { 'data-method' => 'delete' }
+    n.item :admin, safe_join([fa_icon('cogs fw'), t('admin.title')]), admin_dashboard_url, if: proc { current_user.staff? } do |s|
+      s.item :dashboard, safe_join([fa_icon('tachometer fw'), t('admin.dashboard.title')]), admin_dashboard_url
+      s.item :settings, safe_join([fa_icon('cogs fw'), t('admin.settings.title')]), edit_admin_settings_url, if: -> { current_user.admin? }, highlights_on: %r{/admin/settings}
+      s.item :custom_emojis, safe_join([fa_icon('smile-o fw'), t('admin.custom_emojis.title')]), admin_custom_emojis_url, highlights_on: %r{/admin/custom_emojis}
+      s.item :relays, safe_join([fa_icon('exchange fw'), t('admin.relays.title')]), admin_relays_url, if: -> { current_user.admin? }, highlights_on: %r{/admin/relays}
+      s.item :subscriptions, safe_join([fa_icon('paper-plane-o fw'), t('admin.subscriptions.title')]), admin_subscriptions_url, if: -> { current_user.admin? }
+      s.item :sidekiq, safe_join([fa_icon('diamond fw'), 'Sidekiq']), sidekiq_url, link_html: { target: 'sidekiq' }, if: -> { current_user.admin? }
+      s.item :pghero, safe_join([fa_icon('database fw'), 'PgHero']), pghero_url, link_html: { target: 'pghero' }, if: -> { current_user.admin? }
+    end
+
+    n.item :logout, safe_join([fa_icon('sign-out fw'), t('auth.logout')]), destroy_user_session_url, link_html: { 'data-method' => 'delete' }
   end
 end

From 830c2a9ccbe98e145640e12637ef3da56f41a7b5 Mon Sep 17 00:00:00 2001
From: Eugen Rochko <eugen@zeonfederated.com>
Date: Wed, 10 Apr 2019 04:25:09 +0200
Subject: [PATCH 16/16] Bump version to 2.8.0rc3 (#10535)

---
 CHANGELOG.md            | 1 +
 lib/mastodon/version.rb | 2 +-
 2 files changed, 2 insertions(+), 1 deletion(-)

diff --git a/CHANGELOG.md b/CHANGELOG.md
index 6e163bee29..120ec7407b 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -58,6 +58,7 @@ All notable changes to this project will be documented in this file.
 - Change format of CSV exports of follows and mutes to include extra settings ([ThibG](https://github.com/tootsuite/mastodon/pull/10495), [ThibG](https://github.com/tootsuite/mastodon/pull/10335))
 - Change ActivityPub collections to be cacheable by proxies ([ThibG](https://github.com/tootsuite/mastodon/pull/10467))
 - Change REST API and public profiles to not return follows/followers for users that have blocked you ([Gargron](https://github.com/tootsuite/mastodon/pull/10491))
+- Change the groupings of menu items in settings navigation ([Gargron](https://github.com/tootsuite/mastodon/pull/10533))
 
 ### Removed
 
diff --git a/lib/mastodon/version.rb b/lib/mastodon/version.rb
index 859850d15f..bc27d06eaf 100644
--- a/lib/mastodon/version.rb
+++ b/lib/mastodon/version.rb
@@ -21,7 +21,7 @@ module Mastodon
     end
 
     def flags
-      'rc2'
+      'rc3'
     end
 
     def to_a