about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--app/controllers/about_controller.rb2
-rw-r--r--app/controllers/accounts_controller.rb1
-rw-r--r--app/controllers/auth/confirmations_controller.rb5
-rw-r--r--app/controllers/auth/passwords_controller.rb5
-rw-r--r--app/controllers/auth/registrations_controller.rb5
-rw-r--r--app/controllers/auth/sessions_controller.rb5
-rw-r--r--app/controllers/concerns/account_controller_concern.rb5
-rw-r--r--app/controllers/invites_controller.rb2
-rw-r--r--app/controllers/statuses_controller.rb7
-rw-r--r--app/controllers/tags_controller.rb2
-rw-r--r--app/helpers/stream_entries_helper.rb46
-rw-r--r--app/javascript/core/public.js1
-rw-r--r--app/javascript/core/settings.js27
-rw-r--r--app/javascript/mastodon/components/relative_timestamp.js50
-rw-r--r--app/javascript/mastodon/components/status_list.js6
-rw-r--r--app/javascript/mastodon/containers/media_container.js6
-rw-r--r--app/javascript/mastodon/features/account/components/action_bar.js6
-rw-r--r--app/javascript/mastodon/features/account_gallery/index.js5
-rw-r--r--app/javascript/mastodon/features/account_timeline/index.js4
-rw-r--r--app/javascript/mastodon/features/blocks/index.js9
-rw-r--r--app/javascript/mastodon/features/community_timeline/index.js4
-rw-r--r--app/javascript/mastodon/features/direct_timeline/index.js4
-rw-r--r--app/javascript/mastodon/features/domain_blocks/index.js13
-rw-r--r--app/javascript/mastodon/features/favourited_statuses/index.js4
-rw-r--r--app/javascript/mastodon/features/favourites/index.js7
-rw-r--r--app/javascript/mastodon/features/follow_requests/index.js9
-rw-r--r--app/javascript/mastodon/features/followers/index.js7
-rw-r--r--app/javascript/mastodon/features/following/index.js7
-rw-r--r--app/javascript/mastodon/features/hashtag_timeline/index.js4
-rw-r--r--app/javascript/mastodon/features/home_timeline/index.js4
-rw-r--r--app/javascript/mastodon/features/list_timeline/index.js4
-rw-r--r--app/javascript/mastodon/features/mutes/index.js9
-rw-r--r--app/javascript/mastodon/features/pinned_statuses/index.js4
-rw-r--r--app/javascript/mastodon/features/public_timeline/index.js4
-rw-r--r--app/javascript/mastodon/features/reblogs/index.js7
-rw-r--r--app/javascript/mastodon/features/status/index.js6
-rw-r--r--app/javascript/mastodon/features/ui/components/media_modal.js2
-rw-r--r--app/javascript/mastodon/features/ui/components/modal_root.js13
-rw-r--r--app/javascript/mastodon/features/ui/index.js67
-rw-r--r--app/javascript/mastodon/locales/cs.json432
-rw-r--r--app/javascript/mastodon/locales/ko.json2
-rw-r--r--app/javascript/mastodon/locales/pt-BR.json6
-rw-r--r--app/javascript/mastodon/locales/te.json8
-rw-r--r--app/javascript/packs/public.js22
-rw-r--r--app/javascript/styles/application.scss2
-rw-r--r--app/javascript/styles/mastodon/about.scss30
-rw-r--r--app/javascript/styles/mastodon/accounts.scss559
-rw-r--r--app/javascript/styles/mastodon/basics.scss27
-rw-r--r--app/javascript/styles/mastodon/components.scss17
-rw-r--r--app/javascript/styles/mastodon/containers.scss577
-rw-r--r--app/javascript/styles/mastodon/footer.scss157
-rw-r--r--app/javascript/styles/mastodon/landing_strip.scss111
-rw-r--r--app/javascript/styles/mastodon/stream_entries.scss390
-rw-r--r--app/javascript/styles/mastodon/variables.scss2
-rw-r--r--app/javascript/styles/mastodon/widgets.scss161
-rw-r--r--app/lib/activitypub/adapter.rb4
-rw-r--r--app/models/account.rb1
-rw-r--r--app/models/concerns/account_header.rb5
-rw-r--r--app/models/media_attachment.rb58
-rw-r--r--app/services/activitypub/fetch_remote_account_service.rb4
-rw-r--r--app/services/activitypub/process_account_service.rb2
-rw-r--r--app/views/accounts/_bio.html.haml15
-rw-r--r--app/views/accounts/_follow_button.html.haml28
-rw-r--r--app/views/accounts/_follow_grid.html.haml8
-rw-r--r--app/views/accounts/_follow_grid_hidden.html.haml3
-rw-r--r--app/views/accounts/_grid_card.html.haml12
-rw-r--r--app/views/accounts/_header.html.haml82
-rw-r--r--app/views/accounts/_moved.html.haml (renamed from app/views/accounts/_moved_strip.html.haml)11
-rw-r--r--app/views/accounts/_nothing_here.html.haml1
-rw-r--r--app/views/accounts/show.html.haml69
-rw-r--r--app/views/application/_card.html.haml16
-rw-r--r--app/views/application/_sidebar.html.haml6
-rw-r--r--app/views/auth/registrations/new.html.haml2
-rw-r--r--app/views/authorize_follows/_card.html.haml23
-rw-r--r--app/views/authorize_follows/show.html.haml2
-rw-r--r--app/views/authorize_follows/success.html.haml2
-rw-r--r--app/views/follower_accounts/index.html.haml9
-rw-r--r--app/views/following_accounts/index.html.haml9
-rw-r--r--app/views/layouts/public.html.haml55
-rw-r--r--app/views/remote_follow/new.html.haml2
-rw-r--r--app/views/remote_unfollows/success.html.haml2
-rw-r--r--app/views/settings/migrations/show.html.haml2
-rw-r--r--app/views/settings/profiles/show.html.haml7
-rw-r--r--app/views/shared/_landing_strip.html.haml6
-rw-r--r--app/views/stream_entries/_content_spoiler.html.haml7
-rw-r--r--app/views/stream_entries/_detailed_status.html.haml34
-rw-r--r--app/views/stream_entries/_media.html.haml4
-rw-r--r--app/views/stream_entries/_more.html.haml2
-rw-r--r--app/views/stream_entries/_simple_status.html.haml34
-rw-r--r--app/views/stream_entries/_status.html.haml23
-rw-r--r--app/views/stream_entries/embed.html.haml2
-rw-r--r--app/views/stream_entries/show.html.haml11
-rw-r--r--config/locales/activerecord.ast.yml3
-rw-r--r--config/locales/ar.yml5
-rw-r--r--config/locales/ast.yml3
-rw-r--r--config/locales/bg.yml5
-rw-r--r--config/locales/ca.yml5
-rw-r--r--config/locales/co.yml5
-rw-r--r--config/locales/cs.yml839
-rw-r--r--config/locales/da.yml12
-rw-r--r--config/locales/de.yml5
-rw-r--r--config/locales/devise.ast.yml3
-rw-r--r--config/locales/devise.cs.yml32
-rw-r--r--config/locales/devise.tr.yml51
-rw-r--r--config/locales/doorkeeper.ast.yml3
-rw-r--r--config/locales/el.yml5
-rw-r--r--config/locales/en.yml24
-rw-r--r--config/locales/eo.yml5
-rw-r--r--config/locales/es.yml5
-rw-r--r--config/locales/eu.yml5
-rw-r--r--config/locales/fa.yml5
-rw-r--r--config/locales/fi.yml5
-rw-r--r--config/locales/fr.yml5
-rw-r--r--config/locales/gl.yml5
-rw-r--r--config/locales/he.yml5
-rw-r--r--config/locales/hr.yml5
-rw-r--r--config/locales/hu.yml5
-rw-r--r--config/locales/id.yml5
-rw-r--r--config/locales/io.yml5
-rw-r--r--config/locales/it.yml5
-rw-r--r--config/locales/ja.yml14
-rw-r--r--config/locales/ko.yml34
-rw-r--r--config/locales/nl.yml5
-rw-r--r--config/locales/no.yml5
-rw-r--r--config/locales/oc.yml5
-rw-r--r--config/locales/pl.yml13
-rw-r--r--config/locales/pt-BR.yml5
-rw-r--r--config/locales/pt.yml5
-rw-r--r--config/locales/ru.yml5
-rw-r--r--config/locales/simple_form.ar.yml4
-rw-r--r--config/locales/simple_form.ast.yml3
-rw-r--r--config/locales/simple_form.bg.yml4
-rw-r--r--config/locales/simple_form.ca.yml4
-rw-r--r--config/locales/simple_form.co.yml4
-rw-r--r--config/locales/simple_form.cs.yml4
-rw-r--r--config/locales/simple_form.da.yml4
-rw-r--r--config/locales/simple_form.de.yml4
-rw-r--r--config/locales/simple_form.el.yml4
-rw-r--r--config/locales/simple_form.en.yml4
-rw-r--r--config/locales/simple_form.eo.yml4
-rw-r--r--config/locales/simple_form.es.yml4
-rw-r--r--config/locales/simple_form.eu.yml4
-rw-r--r--config/locales/simple_form.fr.yml4
-rw-r--r--config/locales/simple_form.gl.yml4
-rw-r--r--config/locales/simple_form.he.yml4
-rw-r--r--config/locales/simple_form.hr.yml4
-rw-r--r--config/locales/simple_form.hu.yml4
-rw-r--r--config/locales/simple_form.id.yml4
-rw-r--r--config/locales/simple_form.io.yml4
-rw-r--r--config/locales/simple_form.it.yml4
-rw-r--r--config/locales/simple_form.ja.yml4
-rw-r--r--config/locales/simple_form.ko.yml6
-rw-r--r--config/locales/simple_form.nl.yml4
-rw-r--r--config/locales/simple_form.no.yml4
-rw-r--r--config/locales/simple_form.oc.yml4
-rw-r--r--config/locales/simple_form.pl.yml4
-rw-r--r--config/locales/simple_form.pt-BR.yml4
-rw-r--r--config/locales/simple_form.pt.yml4
-rw-r--r--config/locales/simple_form.ru.yml4
-rw-r--r--config/locales/simple_form.sk.yml4
-rw-r--r--config/locales/simple_form.sl.yml4
-rw-r--r--config/locales/simple_form.sr-Latn.yml4
-rw-r--r--config/locales/simple_form.sr.yml4
-rw-r--r--config/locales/simple_form.sv.yml4
-rw-r--r--config/locales/simple_form.th.yml4
-rw-r--r--config/locales/simple_form.tr.yml4
-rw-r--r--config/locales/simple_form.uk.yml4
-rw-r--r--config/locales/simple_form.zh-CN.yml4
-rw-r--r--config/locales/simple_form.zh-HK.yml4
-rw-r--r--config/locales/simple_form.zh-TW.yml4
-rw-r--r--config/locales/sk.yml5
-rw-r--r--config/locales/sl.yml1
-rw-r--r--config/locales/sr-Latn.yml5
-rw-r--r--config/locales/sr.yml5
-rw-r--r--config/locales/sv.yml5
-rw-r--r--config/locales/th.yml5
-rw-r--r--config/locales/tr.yml5
-rw-r--r--config/locales/uk.yml518
-rw-r--r--config/locales/zh-CN.yml5
-rw-r--r--config/locales/zh-HK.yml5
-rw-r--r--config/locales/zh-TW.yml5
-rw-r--r--lib/mastodon/version.rb6
-rw-r--r--package.json1
-rw-r--r--spec/controllers/about_controller_spec.rb12
-rw-r--r--spec/models/account_spec.rb4
-rw-r--r--spec/views/stream_entries/show.html.haml_spec.rb1
-rw-r--r--yarn.lock4
187 files changed, 3352 insertions, 2005 deletions
diff --git a/app/controllers/about_controller.rb b/app/controllers/about_controller.rb
index 7b46b2228..a620d7c5f 100644
--- a/app/controllers/about_controller.rb
+++ b/app/controllers/about_controller.rb
@@ -31,7 +31,7 @@ class AboutController < ApplicationController
   end
 
   def set_body_classes
-    @body_classes = 'about-body'
+    @body_classes = 'with-modals'
   end
 
   def initial_state_params
diff --git a/app/controllers/accounts_controller.rb b/app/controllers/accounts_controller.rb
index 50f5d0b11..723da665e 100644
--- a/app/controllers/accounts_controller.rb
+++ b/app/controllers/accounts_controller.rb
@@ -11,6 +11,7 @@ class AccountsController < ApplicationController
     respond_to do |format|
       format.html do
         use_pack 'public'
+        @body_classes    = 'with-modals'
         @pinned_statuses = []
 
         if current_account && @account.blocking?(current_account)
diff --git a/app/controllers/auth/confirmations_controller.rb b/app/controllers/auth/confirmations_controller.rb
index de0fcd3e3..2954c34da 100644
--- a/app/controllers/auth/confirmations_controller.rb
+++ b/app/controllers/auth/confirmations_controller.rb
@@ -3,6 +3,7 @@
 class Auth::ConfirmationsController < Devise::ConfirmationsController
   layout 'auth'
 
+  before_action :set_body_classes
   before_action :set_user, only: [:finish_signup]
   before_action :set_pack
 
@@ -28,6 +29,10 @@ class Auth::ConfirmationsController < Devise::ConfirmationsController
     @user = current_user
   end
 
+  def set_body_classes
+    @body_classes = 'lighter'
+  end
+
   def user_params
     params.require(:user).permit(:email)
   end
diff --git a/app/controllers/auth/passwords_controller.rb b/app/controllers/auth/passwords_controller.rb
index e0400aa3d..a59806f0d 100644
--- a/app/controllers/auth/passwords_controller.rb
+++ b/app/controllers/auth/passwords_controller.rb
@@ -3,6 +3,7 @@
 class Auth::PasswordsController < Devise::PasswordsController
   before_action :check_validity_of_reset_password_token, only: :edit
   before_action :set_pack
+  before_action :set_body_classes
 
   layout 'auth'
 
@@ -15,6 +16,10 @@ class Auth::PasswordsController < Devise::PasswordsController
     end
   end
 
+  def set_body_classes
+    @body_classes = 'lighter'
+  end
+
   def reset_password_token_is_valid?
     resource_class.with_reset_password_token(params[:reset_password_token]).present?
   end
diff --git a/app/controllers/auth/registrations_controller.rb b/app/controllers/auth/registrations_controller.rb
index 8df8af4c7..fcfd1830a 100644
--- a/app/controllers/auth/registrations_controller.rb
+++ b/app/controllers/auth/registrations_controller.rb
@@ -9,6 +9,7 @@ class Auth::RegistrationsController < Devise::RegistrationsController
   before_action :set_pack
   before_action :set_sessions, only: [:edit, :update]
   before_action :set_instance_presenter, only: [:new, :create, :update]
+  before_action :set_body_classes, only: [:new, :create]
 
   def destroy
     not_found
@@ -84,6 +85,10 @@ class Auth::RegistrationsController < Devise::RegistrationsController
     @instance_presenter = InstancePresenter.new
   end
 
+  def set_body_classes
+    @body_classes = 'lighter'
+  end
+
   def set_invite
     @invite = invite_code.present? ? Invite.find_by(code: invite_code) : nil
   end
diff --git a/app/controllers/auth/sessions_controller.rb b/app/controllers/auth/sessions_controller.rb
index 62f3b2eb6..4c0d93f5d 100644
--- a/app/controllers/auth/sessions_controller.rb
+++ b/app/controllers/auth/sessions_controller.rb
@@ -10,6 +10,7 @@ class Auth::SessionsController < Devise::SessionsController
   prepend_before_action :authenticate_with_two_factor, if: :two_factor_enabled?, only: [:create]
   prepend_before_action :set_pack
   before_action :set_instance_presenter, only: [:new]
+  before_action :set_body_classes
 
   def new
     Devise.omniauth_configs.each do |provider, config|
@@ -114,6 +115,10 @@ class Auth::SessionsController < Devise::SessionsController
     @instance_presenter = InstancePresenter.new
   end
 
+  def set_body_classes
+    @body_classes = 'lighter'
+  end
+
   def home_paths(resource)
     paths = [about_path]
     if single_user_mode? && resource.is_a?(User)
diff --git a/app/controllers/concerns/account_controller_concern.rb b/app/controllers/concerns/account_controller_concern.rb
index 5b9981aa2..6c27ef330 100644
--- a/app/controllers/concerns/account_controller_concern.rb
+++ b/app/controllers/concerns/account_controller_concern.rb
@@ -8,6 +8,7 @@ module AccountControllerConcern
   included do
     layout 'public'
     before_action :set_account
+    before_action :set_instance_presenter
     before_action :set_link_headers
     before_action :check_account_suspension
   end
@@ -18,6 +19,10 @@ module AccountControllerConcern
     @account = Account.find_local!(params[:account_username])
   end
 
+  def set_instance_presenter
+    @instance_presenter = InstancePresenter.new
+  end
+
   def set_link_headers
     response.headers['Link'] = LinkHeader.new(
       [
diff --git a/app/controllers/invites_controller.rb b/app/controllers/invites_controller.rb
index 1053e9c42..3dc934761 100644
--- a/app/controllers/invites_controller.rb
+++ b/app/controllers/invites_controller.rb
@@ -43,7 +43,7 @@ class InvitesController < ApplicationController
   end
 
   def invites
-    Invite.where(user: current_user)
+    Invite.where(user: current_user).order(id: :desc)
   end
 
   def resource_params
diff --git a/app/controllers/statuses_controller.rb b/app/controllers/statuses_controller.rb
index f4ac1d03b..1940aaa1b 100644
--- a/app/controllers/statuses_controller.rb
+++ b/app/controllers/statuses_controller.rb
@@ -12,6 +12,7 @@ class StatusesController < ApplicationController
 
   before_action :set_account
   before_action :set_status
+  before_action :set_instance_presenter
   before_action :set_link_headers
   before_action :check_account_suspension
   before_action :redirect_to_original, only: [:show]
@@ -22,6 +23,8 @@ class StatusesController < ApplicationController
     respond_to do |format|
       format.html do
         use_pack 'public'
+        @body_classes = 'with-modals'
+
         set_ancestors
         set_descendants
 
@@ -150,6 +153,10 @@ class StatusesController < ApplicationController
     raise ActiveRecord::RecordNotFound
   end
 
+  def set_instance_presenter
+    @instance_presenter = InstancePresenter.new
+  end
+
   def check_account_suspension
     gone if @account.suspended?
   end
diff --git a/app/controllers/tags_controller.rb b/app/controllers/tags_controller.rb
index a76be26e5..a48fdb9f8 100644
--- a/app/controllers/tags_controller.rb
+++ b/app/controllers/tags_controller.rb
@@ -38,7 +38,7 @@ class TagsController < ApplicationController
   private
 
   def set_body_classes
-    @body_classes = 'tag-body'
+    @body_classes = 'with-modals'
   end
 
   def set_instance_presenter
diff --git a/app/helpers/stream_entries_helper.rb b/app/helpers/stream_entries_helper.rb
index 05cea73d7..121644263 100644
--- a/app/helpers/stream_entries_helper.rb
+++ b/app/helpers/stream_entries_helper.rb
@@ -12,6 +12,52 @@ module StreamEntriesHelper
     end
   end
 
+  def account_action_button(account)
+    if user_signed_in?
+      if account.id == current_user.account_id
+        link_to settings_profile_url, class: 'button logo-button' do
+          safe_join([render(file: Rails.root.join('app', 'javascript', 'images', 'logo.svg')), t('settings.edit_profile')])
+        end
+      elsif current_account.following?(account) || current_account.requested?(account)
+        link_to account_unfollow_path(account), class: 'button logo-button', data: { method: :post } do
+          safe_join([render(file: Rails.root.join('app', 'javascript', 'images', 'logo.svg')), t('accounts.unfollow')])
+        end
+      else
+        link_to account_follow_path(account), class: 'button logo-button', data: { method: :post } do
+          safe_join([render(file: Rails.root.join('app', 'javascript', 'images', 'logo.svg')), t('accounts.follow')])
+        end
+      end
+    else
+      link_to account_remote_follow_path(account), class: 'button logo-button modal-button', target: '_new' do
+        safe_join([render(file: Rails.root.join('app', 'javascript', 'images', 'logo.svg')), t('accounts.follow')])
+      end
+    end
+  end
+
+  def account_badge(account)
+    if account.bot?
+      content_tag(:div, content_tag(:div, t('accounts.roles.bot'), class: 'account-role bot'), class: 'roles')
+    elsif Setting.show_staff_badge && account.user_staff?
+      content_tag(:div, class: 'roles') do
+        if account.user_admin?
+          content_tag(:div, t('accounts.roles.admin'), class: 'account-role admin')
+        elsif account.user_moderator?
+          content_tag(:div, t('accounts.roles.moderator'), class: 'account-role moderator')
+        end
+      end
+    end
+  end
+
+  def link_to_more(url)
+    link_to t('statuses.show_more'), url, class: 'load-more load-gap'
+  end
+
+  def nothing_here(extra_classes = '')
+    content_tag(:div, class: "nothing-here #{extra_classes}") do
+      t('accounts.nothing_here')
+    end
+  end
+
   def account_description(account)
     prepend_str = [
       [
diff --git a/app/javascript/core/public.js b/app/javascript/core/public.js
index 47c34a259..d3d80019f 100644
--- a/app/javascript/core/public.js
+++ b/app/javascript/core/public.js
@@ -1,6 +1,7 @@
 //  This file will be loaded on public pages, regardless of theme.
 
 const { delegate } = require('rails-ujs');
+const { length } = require('stringz');
 
 delegate(document, '.webapp-btn', 'click', ({ target, button }) => {
   if (button !== 0) {
diff --git a/app/javascript/core/settings.js b/app/javascript/core/settings.js
index 1add0314d..175a1758f 100644
--- a/app/javascript/core/settings.js
+++ b/app/javascript/core/settings.js
@@ -3,24 +3,29 @@
 const { length } = require('stringz');
 const { delegate } = require('rails-ujs');
 
-delegate(document, '.account_display_name', 'input', ({ target }) => {
+delegate(document, '#account_display_name', 'input', ({ target }) => {
   const nameCounter = document.querySelector('.name-counter');
+  const name        = document.querySelector('.card .display-name strong');
 
   if (nameCounter) {
     nameCounter.textContent = 30 - length(target.value);
   }
+
+  if (name) {
+    name.innerHTML = emojify(target.value);
+  }
 });
 
-delegate(document, '.account_note', 'input', ({ target }) => {
+delegate(document, '#account_note', 'input', ({ target }) => {
   const noteCounter = document.querySelector('.note-counter');
 
   if (noteCounter) {
-    noteCounter.textContent = 500 - length(target.value);
+    noteCounter.textContent = 160 - length(target.value);
   }
 });
 
 delegate(document, '#account_avatar', 'change', ({ target }) => {
-  const avatar = document.querySelector('.card.compact .avatar img');
+  const avatar = document.querySelector('.card .avatar img');
   const [file] = target.files || [];
   const url = file ? URL.createObjectURL(file) : avatar.dataset.originalSrc;
 
@@ -28,9 +33,19 @@ delegate(document, '#account_avatar', 'change', ({ target }) => {
 });
 
 delegate(document, '#account_header', 'change', ({ target }) => {
-  const header = document.querySelector('.card.compact');
+  const header = document.querySelector('.card .card__img img');
   const [file] = target.files || [];
   const url = file ? URL.createObjectURL(file) : header.dataset.originalSrc;
 
-  header.style.backgroundImage = `url(${url})`;
+  header.src = url;
+});
+
+delegate(document, '#account_locked', 'change', ({ target }) => {
+  const lock = document.querySelector('.card .display-name i');
+
+  if (target.checked) {
+    lock.style.display = 'inline';
+  } else {
+    lock.style.display = 'none';
+  }
 });
diff --git a/app/javascript/mastodon/components/relative_timestamp.js b/app/javascript/mastodon/components/relative_timestamp.js
index 3c8db7092..9609714a1 100644
--- a/app/javascript/mastodon/components/relative_timestamp.js
+++ b/app/javascript/mastodon/components/relative_timestamp.js
@@ -60,6 +60,32 @@ const getUnitDelay = units => {
   }
 };
 
+export const timeAgoString = (intl, date, now, year) => {
+  const delta = now - date.getTime();
+
+  let relativeTime;
+
+  if (delta < 10 * SECOND) {
+    relativeTime = intl.formatMessage(messages.just_now);
+  } else if (delta < 7 * DAY) {
+    if (delta < MINUTE) {
+      relativeTime = intl.formatMessage(messages.seconds, { number: Math.floor(delta / SECOND) });
+    } else if (delta < HOUR) {
+      relativeTime = intl.formatMessage(messages.minutes, { number: Math.floor(delta / MINUTE) });
+    } else if (delta < DAY) {
+      relativeTime = intl.formatMessage(messages.hours, { number: Math.floor(delta / HOUR) });
+    } else {
+      relativeTime = intl.formatMessage(messages.days, { number: Math.floor(delta / DAY) });
+    }
+  } else if (date.getFullYear() === year) {
+    relativeTime = intl.formatDate(date, shortDateFormatOptions);
+  } else {
+    relativeTime = intl.formatDate(date, { ...shortDateFormatOptions, year: 'numeric' });
+  }
+
+  return relativeTime;
+};
+
 @injectIntl
 export default class RelativeTimestamp extends React.Component {
 
@@ -121,28 +147,8 @@ export default class RelativeTimestamp extends React.Component {
   render () {
     const { timestamp, intl, year } = this.props;
 
-    const date  = new Date(timestamp);
-    const delta = this.state.now - date.getTime();
-
-    let relativeTime;
-
-    if (delta < 10 * SECOND) {
-      relativeTime = intl.formatMessage(messages.just_now);
-    } else if (delta < 7 * DAY) {
-      if (delta < MINUTE) {
-        relativeTime = intl.formatMessage(messages.seconds, { number: Math.floor(delta / SECOND) });
-      } else if (delta < HOUR) {
-        relativeTime = intl.formatMessage(messages.minutes, { number: Math.floor(delta / MINUTE) });
-      } else if (delta < DAY) {
-        relativeTime = intl.formatMessage(messages.hours, { number: Math.floor(delta / HOUR) });
-      } else {
-        relativeTime = intl.formatMessage(messages.days, { number: Math.floor(delta / DAY) });
-      }
-    } else if (date.getFullYear() === year) {
-      relativeTime = intl.formatDate(date, shortDateFormatOptions);
-    } else {
-      relativeTime = intl.formatDate(date, { ...shortDateFormatOptions, year: 'numeric' });
-    }
+    const date         = new Date(timestamp);
+    const relativeTime = timeAgoString(intl, date, this.state.now, year);
 
     return (
       <time dateTime={timestamp} title={intl.formatDate(date, dateFormatOptions)}>
diff --git a/app/javascript/mastodon/components/status_list.js b/app/javascript/mastodon/components/status_list.js
index 68c9eef54..37f21fb44 100644
--- a/app/javascript/mastodon/components/status_list.js
+++ b/app/javascript/mastodon/components/status_list.js
@@ -1,12 +1,12 @@
 import { debounce } from 'lodash';
 import React from 'react';
+import { FormattedMessage } from 'react-intl';
 import ImmutablePropTypes from 'react-immutable-proptypes';
 import PropTypes from 'prop-types';
 import StatusContainer from '../containers/status_container';
 import ImmutablePureComponent from 'react-immutable-pure-component';
 import LoadGap from './load_gap';
 import ScrollableList from './scrollable_list';
-import { FormattedMessage } from 'react-intl';
 
 export default class StatusList extends ImmutablePureComponent {
 
@@ -71,7 +71,7 @@ export default class StatusList extends ImmutablePureComponent {
   }
 
   render () {
-    const { statusIds, featuredStatusIds, onLoadMore, timelineId, ...other }  = this.props;
+    const { statusIds, featuredStatusIds, shouldUpdateScroll, onLoadMore, timelineId, ...other }  = this.props;
     const { isLoading, isPartial } = other;
 
     if (isPartial) {
@@ -122,7 +122,7 @@ export default class StatusList extends ImmutablePureComponent {
     }
 
     return (
-      <ScrollableList {...other} onLoadMore={onLoadMore && this.handleLoadOlder} ref={this.setRef}>
+      <ScrollableList {...other} onLoadMore={onLoadMore && this.handleLoadOlder} shouldUpdateScroll={shouldUpdateScroll} ref={this.setRef}>
         {scrollableContent}
       </ScrollableList>
     );
diff --git a/app/javascript/mastodon/containers/media_container.js b/app/javascript/mastodon/containers/media_container.js
index 1700fba05..43bb39403 100644
--- a/app/javascript/mastodon/containers/media_container.js
+++ b/app/javascript/mastodon/containers/media_container.js
@@ -29,19 +29,19 @@ export default class MediaContainer extends PureComponent {
   };
 
   handleOpenMedia = (media, index) => {
-    document.body.classList.add('media-standalone__body');
+    document.body.classList.add('with-modals--active');
     this.setState({ media, index });
   }
 
   handleOpenVideo = (video, time) => {
     const media = ImmutableList([video]);
 
-    document.body.classList.add('media-standalone__body');
+    document.body.classList.add('with-modals--active');
     this.setState({ media, time });
   }
 
   handleCloseMedia = () => {
-    document.body.classList.remove('media-standalone__body');
+    document.body.classList.remove('with-modals--active');
     this.setState({ media: null, index: null, time: null });
   }
 
diff --git a/app/javascript/mastodon/features/account/components/action_bar.js b/app/javascript/mastodon/features/account/components/action_bar.js
index 69726a416..e3f2d0f55 100644
--- a/app/javascript/mastodon/features/account/components/action_bar.js
+++ b/app/javascript/mastodon/features/account/components/action_bar.js
@@ -142,17 +142,17 @@ export default class ActionBar extends React.PureComponent {
         <div className='account__action-bar'>
           <div className='account__action-bar-links'>
             <Link className='account__action-bar__tab' to={`/accounts/${account.get('id')}`}>
-              <span><FormattedMessage id='account.posts' defaultMessage='Toots' /></span>
+              <FormattedMessage id='account.posts' defaultMessage='Toots' />
               <strong>{shortNumberFormat(account.get('statuses_count'))}</strong>
             </Link>
 
             <Link className='account__action-bar__tab' to={`/accounts/${account.get('id')}/following`}>
-              <span><FormattedMessage id='account.follows' defaultMessage='Follows' /></span>
+              <FormattedMessage id='account.follows' defaultMessage='Follows' />
               <strong>{shortNumberFormat(account.get('following_count'))}</strong>
             </Link>
 
             <Link className='account__action-bar__tab' to={`/accounts/${account.get('id')}/followers`}>
-              <span><FormattedMessage id='account.followers' defaultMessage='Followers' /></span>
+              <FormattedMessage id='account.followers' defaultMessage='Followers' />
               <strong>{shortNumberFormat(account.get('followers_count'))}</strong>
             </Link>
           </div>
diff --git a/app/javascript/mastodon/features/account_gallery/index.js b/app/javascript/mastodon/features/account_gallery/index.js
index 5f564d3a9..a6c464aff 100644
--- a/app/javascript/mastodon/features/account_gallery/index.js
+++ b/app/javascript/mastodon/features/account_gallery/index.js
@@ -23,6 +23,7 @@ const mapStateToProps = (state, props) => ({
 class LoadMoreMedia extends ImmutablePureComponent {
 
   static propTypes = {
+    shouldUpdateScroll: PropTypes.func,
     maxId: PropTypes.string,
     onLoadMore: PropTypes.func.isRequired,
   };
@@ -90,7 +91,7 @@ export default class AccountGallery extends ImmutablePureComponent {
   }
 
   render () {
-    const { medias, isLoading, hasMore } = this.props;
+    const { medias, shouldUpdateScroll, isLoading, hasMore } = this.props;
 
     let loadOlder = null;
 
@@ -110,7 +111,7 @@ export default class AccountGallery extends ImmutablePureComponent {
       <Column>
         <ColumnBackButton />
 
-        <ScrollContainer scrollKey='account_gallery'>
+        <ScrollContainer scrollKey='account_gallery' shouldUpdateScroll={shouldUpdateScroll}>
           <div className='scrollable' onScroll={this.handleScroll}>
             <HeaderContainer accountId={this.props.params.accountId} />
 
diff --git a/app/javascript/mastodon/features/account_timeline/index.js b/app/javascript/mastodon/features/account_timeline/index.js
index d329bac5c..934513cd7 100644
--- a/app/javascript/mastodon/features/account_timeline/index.js
+++ b/app/javascript/mastodon/features/account_timeline/index.js
@@ -29,6 +29,7 @@ export default class AccountTimeline extends ImmutablePureComponent {
   static propTypes = {
     params: PropTypes.object.isRequired,
     dispatch: PropTypes.func.isRequired,
+    shouldUpdateScroll: PropTypes.func,
     statusIds: ImmutablePropTypes.list,
     featuredStatusIds: ImmutablePropTypes.list,
     isLoading: PropTypes.bool,
@@ -61,7 +62,7 @@ export default class AccountTimeline extends ImmutablePureComponent {
   }
 
   render () {
-    const { statusIds, featuredStatusIds, isLoading, hasMore } = this.props;
+    const { shouldUpdateScroll, statusIds, featuredStatusIds, isLoading, hasMore } = this.props;
 
     if (!statusIds && isLoading) {
       return (
@@ -83,6 +84,7 @@ export default class AccountTimeline extends ImmutablePureComponent {
           isLoading={isLoading}
           hasMore={hasMore}
           onLoadMore={this.handleLoadMore}
+          shouldUpdateScroll={shouldUpdateScroll}
         />
       </Column>
     );
diff --git a/app/javascript/mastodon/features/blocks/index.js b/app/javascript/mastodon/features/blocks/index.js
index 14a512ae8..0b88e50ae 100644
--- a/app/javascript/mastodon/features/blocks/index.js
+++ b/app/javascript/mastodon/features/blocks/index.js
@@ -1,5 +1,7 @@
 import React from 'react';
 import { connect } from 'react-redux';
+import { defineMessages, injectIntl } from 'react-intl';
+import ImmutablePureComponent from 'react-immutable-pure-component';
 import ImmutablePropTypes from 'react-immutable-proptypes';
 import PropTypes from 'prop-types';
 import LoadingIndicator from '../../components/loading_indicator';
@@ -8,8 +10,6 @@ import Column from '../ui/components/column';
 import ColumnBackButtonSlim from '../../components/column_back_button_slim';
 import AccountContainer from '../../containers/account_container';
 import { fetchBlocks, expandBlocks } from '../../actions/blocks';
-import { defineMessages, injectIntl } from 'react-intl';
-import ImmutablePureComponent from 'react-immutable-pure-component';
 
 const messages = defineMessages({
   heading: { id: 'column.blocks', defaultMessage: 'Blocked users' },
@@ -26,6 +26,7 @@ export default class Blocks extends ImmutablePureComponent {
   static propTypes = {
     params: PropTypes.object.isRequired,
     dispatch: PropTypes.func.isRequired,
+    shouldUpdateScroll: PropTypes.func,
     accountIds: ImmutablePropTypes.list,
     intl: PropTypes.object.isRequired,
   };
@@ -43,7 +44,7 @@ export default class Blocks extends ImmutablePureComponent {
   }
 
   render () {
-    const { intl, accountIds } = this.props;
+    const { intl, accountIds, shouldUpdateScroll } = this.props;
 
     if (!accountIds) {
       return (
@@ -56,7 +57,7 @@ export default class Blocks extends ImmutablePureComponent {
     return (
       <Column icon='ban' heading={intl.formatMessage(messages.heading)}>
         <ColumnBackButtonSlim />
-        <ScrollContainer scrollKey='blocks'>
+        <ScrollContainer scrollKey='blocks' shouldUpdateScroll={shouldUpdateScroll}>
           <div className='scrollable' onScroll={this.handleScroll}>
             {accountIds.map(id =>
               <AccountContainer key={id} id={id} />
diff --git a/app/javascript/mastodon/features/community_timeline/index.js b/app/javascript/mastodon/features/community_timeline/index.js
index eb9ad97a2..1cd5cf157 100644
--- a/app/javascript/mastodon/features/community_timeline/index.js
+++ b/app/javascript/mastodon/features/community_timeline/index.js
@@ -39,6 +39,7 @@ export default class CommunityTimeline extends React.PureComponent {
 
   static propTypes = {
     dispatch: PropTypes.func.isRequired,
+    shouldUpdateScroll: PropTypes.func,
     columnId: PropTypes.string,
     intl: PropTypes.object.isRequired,
     hasUnread: PropTypes.bool,
@@ -100,7 +101,7 @@ export default class CommunityTimeline extends React.PureComponent {
   }
 
   render () {
-    const { intl, hasUnread, columnId, multiColumn, onlyMedia } = this.props;
+    const { intl, shouldUpdateScroll, hasUnread, columnId, multiColumn, onlyMedia } = this.props;
     const pinned = !!columnId;
 
     return (
@@ -124,6 +125,7 @@ export default class CommunityTimeline extends React.PureComponent {
           timelineId={`community${onlyMedia ? ':media' : ''}`}
           onLoadMore={this.handleLoadMore}
           emptyMessage={<FormattedMessage id='empty_column.community' defaultMessage='The local timeline is empty. Write something publicly to get the ball rolling!' />}
+          shouldUpdateScroll={shouldUpdateScroll}
         />
       </Column>
     );
diff --git a/app/javascript/mastodon/features/direct_timeline/index.js b/app/javascript/mastodon/features/direct_timeline/index.js
index 63dc41d9e..2181c75b6 100644
--- a/app/javascript/mastodon/features/direct_timeline/index.js
+++ b/app/javascript/mastodon/features/direct_timeline/index.js
@@ -23,6 +23,7 @@ export default class DirectTimeline extends React.PureComponent {
 
   static propTypes = {
     dispatch: PropTypes.func.isRequired,
+    shouldUpdateScroll: PropTypes.func,
     columnId: PropTypes.string,
     intl: PropTypes.object.isRequired,
     hasUnread: PropTypes.bool,
@@ -71,7 +72,7 @@ export default class DirectTimeline extends React.PureComponent {
   }
 
   render () {
-    const { intl, hasUnread, columnId, multiColumn } = this.props;
+    const { intl, shouldUpdateScroll, hasUnread, columnId, multiColumn } = this.props;
     const pinned = !!columnId;
 
     return (
@@ -93,6 +94,7 @@ export default class DirectTimeline extends React.PureComponent {
           timelineId='direct'
           onLoadMore={this.handleLoadMore}
           emptyMessage={<FormattedMessage id='empty_column.direct' defaultMessage="You don't have any direct messages yet. When you send or receive one, it will show up here." />}
+          shouldUpdateScroll={shouldUpdateScroll}
         />
       </Column>
     );
diff --git a/app/javascript/mastodon/features/domain_blocks/index.js b/app/javascript/mastodon/features/domain_blocks/index.js
index b8a942d6c..e4e2b5239 100644
--- a/app/javascript/mastodon/features/domain_blocks/index.js
+++ b/app/javascript/mastodon/features/domain_blocks/index.js
@@ -1,15 +1,15 @@
 import React from 'react';
 import { connect } from 'react-redux';
-import ImmutablePropTypes from 'react-immutable-proptypes';
+import { defineMessages, injectIntl } from 'react-intl';
+import ImmutablePureComponent from 'react-immutable-pure-component';
 import PropTypes from 'prop-types';
+import ImmutablePropTypes from 'react-immutable-proptypes';
+import { debounce } from 'lodash';
 import LoadingIndicator from '../../components/loading_indicator';
 import Column from '../ui/components/column';
 import ColumnBackButtonSlim from '../../components/column_back_button_slim';
 import DomainContainer from '../../containers/domain_container';
 import { fetchDomainBlocks, expandDomainBlocks } from '../../actions/domain_blocks';
-import { defineMessages, injectIntl } from 'react-intl';
-import ImmutablePureComponent from 'react-immutable-pure-component';
-import { debounce } from 'lodash';
 import ScrollableList from '../../components/scrollable_list';
 
 const messages = defineMessages({
@@ -28,6 +28,7 @@ export default class Blocks extends ImmutablePureComponent {
   static propTypes = {
     params: PropTypes.object.isRequired,
     dispatch: PropTypes.func.isRequired,
+    shouldUpdateScroll: PropTypes.func,
     domains: ImmutablePropTypes.orderedSet,
     intl: PropTypes.object.isRequired,
   };
@@ -41,7 +42,7 @@ export default class Blocks extends ImmutablePureComponent {
   }, 300, { leading: true });
 
   render () {
-    const { intl, domains } = this.props;
+    const { intl, domains, shouldUpdateScroll } = this.props;
 
     if (!domains) {
       return (
@@ -54,7 +55,7 @@ export default class Blocks extends ImmutablePureComponent {
     return (
       <Column icon='minus-circle' heading={intl.formatMessage(messages.heading)}>
         <ColumnBackButtonSlim />
-        <ScrollableList scrollKey='domain_blocks' onLoadMore={this.handleLoadMore}>
+        <ScrollableList scrollKey='domain_blocks' onLoadMore={this.handleLoadMore} shouldUpdateScroll={shouldUpdateScroll}>
           {domains.map(domain =>
             <DomainContainer key={domain} domain={domain} />
           )}
diff --git a/app/javascript/mastodon/features/favourited_statuses/index.js b/app/javascript/mastodon/features/favourited_statuses/index.js
index 6f1c863b4..3973ed3cb 100644
--- a/app/javascript/mastodon/features/favourited_statuses/index.js
+++ b/app/javascript/mastodon/features/favourited_statuses/index.js
@@ -27,6 +27,7 @@ export default class Favourites extends ImmutablePureComponent {
 
   static propTypes = {
     dispatch: PropTypes.func.isRequired,
+    shouldUpdateScroll: PropTypes.func,
     statusIds: ImmutablePropTypes.list.isRequired,
     intl: PropTypes.object.isRequired,
     columnId: PropTypes.string,
@@ -67,7 +68,7 @@ export default class Favourites extends ImmutablePureComponent {
   }, 300, { leading: true })
 
   render () {
-    const { intl, statusIds, columnId, multiColumn, hasMore, isLoading } = this.props;
+    const { intl, shouldUpdateScroll, statusIds, columnId, multiColumn, hasMore, isLoading } = this.props;
     const pinned = !!columnId;
 
     return (
@@ -90,6 +91,7 @@ export default class Favourites extends ImmutablePureComponent {
           hasMore={hasMore}
           isLoading={isLoading}
           onLoadMore={this.handleLoadMore}
+          shouldUpdateScroll={shouldUpdateScroll}
         />
       </Column>
     );
diff --git a/app/javascript/mastodon/features/favourites/index.js b/app/javascript/mastodon/features/favourites/index.js
index 6f113beb4..40fe6c9a8 100644
--- a/app/javascript/mastodon/features/favourites/index.js
+++ b/app/javascript/mastodon/features/favourites/index.js
@@ -1,5 +1,6 @@
 import React from 'react';
 import { connect } from 'react-redux';
+import ImmutablePureComponent from 'react-immutable-pure-component';
 import PropTypes from 'prop-types';
 import ImmutablePropTypes from 'react-immutable-proptypes';
 import LoadingIndicator from '../../components/loading_indicator';
@@ -8,7 +9,6 @@ import { ScrollContainer } from 'react-router-scroll-4';
 import AccountContainer from '../../containers/account_container';
 import Column from '../ui/components/column';
 import ColumnBackButton from '../../components/column_back_button';
-import ImmutablePureComponent from 'react-immutable-pure-component';
 
 const mapStateToProps = (state, props) => ({
   accountIds: state.getIn(['user_lists', 'favourited_by', props.params.statusId]),
@@ -20,6 +20,7 @@ export default class Favourites extends ImmutablePureComponent {
   static propTypes = {
     params: PropTypes.object.isRequired,
     dispatch: PropTypes.func.isRequired,
+    shouldUpdateScroll: PropTypes.func,
     accountIds: ImmutablePropTypes.list,
   };
 
@@ -34,7 +35,7 @@ export default class Favourites extends ImmutablePureComponent {
   }
 
   render () {
-    const { accountIds } = this.props;
+    const { shouldUpdateScroll, accountIds } = this.props;
 
     if (!accountIds) {
       return (
@@ -48,7 +49,7 @@ export default class Favourites extends ImmutablePureComponent {
       <Column>
         <ColumnBackButton />
 
-        <ScrollContainer scrollKey='favourites'>
+        <ScrollContainer scrollKey='favourites' shouldUpdateScroll={shouldUpdateScroll}>
           <div className='scrollable'>
             {accountIds.map(id => <AccountContainer key={id} id={id} withNote={false} />)}
           </div>
diff --git a/app/javascript/mastodon/features/follow_requests/index.js b/app/javascript/mastodon/features/follow_requests/index.js
index eae821f92..53a394cbc 100644
--- a/app/javascript/mastodon/features/follow_requests/index.js
+++ b/app/javascript/mastodon/features/follow_requests/index.js
@@ -1,5 +1,7 @@
 import React from 'react';
 import { connect } from 'react-redux';
+import { defineMessages, injectIntl } from 'react-intl';
+import ImmutablePureComponent from 'react-immutable-pure-component';
 import PropTypes from 'prop-types';
 import ImmutablePropTypes from 'react-immutable-proptypes';
 import LoadingIndicator from '../../components/loading_indicator';
@@ -8,8 +10,6 @@ import Column from '../ui/components/column';
 import ColumnBackButtonSlim from '../../components/column_back_button_slim';
 import AccountAuthorizeContainer from './containers/account_authorize_container';
 import { fetchFollowRequests, expandFollowRequests } from '../../actions/accounts';
-import { defineMessages, injectIntl } from 'react-intl';
-import ImmutablePureComponent from 'react-immutable-pure-component';
 
 const messages = defineMessages({
   heading: { id: 'column.follow_requests', defaultMessage: 'Follow requests' },
@@ -26,6 +26,7 @@ export default class FollowRequests extends ImmutablePureComponent {
   static propTypes = {
     params: PropTypes.object.isRequired,
     dispatch: PropTypes.func.isRequired,
+    shouldUpdateScroll: PropTypes.func,
     accountIds: ImmutablePropTypes.list,
     intl: PropTypes.object.isRequired,
   };
@@ -43,7 +44,7 @@ export default class FollowRequests extends ImmutablePureComponent {
   }
 
   render () {
-    const { intl, accountIds } = this.props;
+    const { intl, shouldUpdateScroll, accountIds } = this.props;
 
     if (!accountIds) {
       return (
@@ -57,7 +58,7 @@ export default class FollowRequests extends ImmutablePureComponent {
       <Column icon='users' heading={intl.formatMessage(messages.heading)}>
         <ColumnBackButtonSlim />
 
-        <ScrollContainer scrollKey='follow_requests'>
+        <ScrollContainer scrollKey='follow_requests' shouldUpdateScroll={shouldUpdateScroll}>
           <div className='scrollable' onScroll={this.handleScroll}>
             {accountIds.map(id =>
               <AccountAuthorizeContainer key={id} id={id} />
diff --git a/app/javascript/mastodon/features/followers/index.js b/app/javascript/mastodon/features/followers/index.js
index 919a89332..5bb8fdd6a 100644
--- a/app/javascript/mastodon/features/followers/index.js
+++ b/app/javascript/mastodon/features/followers/index.js
@@ -1,5 +1,6 @@
 import React from 'react';
 import { connect } from 'react-redux';
+import ImmutablePureComponent from 'react-immutable-pure-component';
 import PropTypes from 'prop-types';
 import ImmutablePropTypes from 'react-immutable-proptypes';
 import LoadingIndicator from '../../components/loading_indicator';
@@ -14,7 +15,6 @@ import Column from '../ui/components/column';
 import HeaderContainer from '../account_timeline/containers/header_container';
 import LoadMore from '../../components/load_more';
 import ColumnBackButton from '../../components/column_back_button';
-import ImmutablePureComponent from 'react-immutable-pure-component';
 
 const mapStateToProps = (state, props) => ({
   accountIds: state.getIn(['user_lists', 'followers', props.params.accountId, 'items']),
@@ -27,6 +27,7 @@ export default class Followers extends ImmutablePureComponent {
   static propTypes = {
     params: PropTypes.object.isRequired,
     dispatch: PropTypes.func.isRequired,
+    shouldUpdateScroll: PropTypes.func,
     accountIds: ImmutablePropTypes.list,
     hasMore: PropTypes.bool,
   };
@@ -57,7 +58,7 @@ export default class Followers extends ImmutablePureComponent {
   }
 
   render () {
-    const { accountIds, hasMore } = this.props;
+    const { shouldUpdateScroll, accountIds, hasMore } = this.props;
 
     let loadMore = null;
 
@@ -77,7 +78,7 @@ export default class Followers extends ImmutablePureComponent {
       <Column>
         <ColumnBackButton />
 
-        <ScrollContainer scrollKey='followers'>
+        <ScrollContainer scrollKey='followers' shouldUpdateScroll={shouldUpdateScroll}>
           <div className='scrollable' onScroll={this.handleScroll}>
             <div className='followers'>
               <HeaderContainer accountId={this.props.params.accountId} hideTabs />
diff --git a/app/javascript/mastodon/features/following/index.js b/app/javascript/mastodon/features/following/index.js
index 5719259d1..97b0a8964 100644
--- a/app/javascript/mastodon/features/following/index.js
+++ b/app/javascript/mastodon/features/following/index.js
@@ -1,5 +1,6 @@
 import React from 'react';
 import { connect } from 'react-redux';
+import ImmutablePureComponent from 'react-immutable-pure-component';
 import PropTypes from 'prop-types';
 import ImmutablePropTypes from 'react-immutable-proptypes';
 import LoadingIndicator from '../../components/loading_indicator';
@@ -14,7 +15,6 @@ import Column from '../ui/components/column';
 import HeaderContainer from '../account_timeline/containers/header_container';
 import LoadMore from '../../components/load_more';
 import ColumnBackButton from '../../components/column_back_button';
-import ImmutablePureComponent from 'react-immutable-pure-component';
 
 const mapStateToProps = (state, props) => ({
   accountIds: state.getIn(['user_lists', 'following', props.params.accountId, 'items']),
@@ -27,6 +27,7 @@ export default class Following extends ImmutablePureComponent {
   static propTypes = {
     params: PropTypes.object.isRequired,
     dispatch: PropTypes.func.isRequired,
+    shouldUpdateScroll: PropTypes.func,
     accountIds: ImmutablePropTypes.list,
     hasMore: PropTypes.bool,
   };
@@ -57,7 +58,7 @@ export default class Following extends ImmutablePureComponent {
   }
 
   render () {
-    const { accountIds, hasMore } = this.props;
+    const { shouldUpdateScroll, accountIds, hasMore } = this.props;
 
     let loadMore = null;
 
@@ -77,7 +78,7 @@ export default class Following extends ImmutablePureComponent {
       <Column>
         <ColumnBackButton />
 
-        <ScrollContainer scrollKey='following'>
+        <ScrollContainer scrollKey='following' shouldUpdateScroll={shouldUpdateScroll}>
           <div className='scrollable' onScroll={this.handleScroll}>
             <div className='following'>
               <HeaderContainer accountId={this.props.params.accountId} hideTabs />
diff --git a/app/javascript/mastodon/features/hashtag_timeline/index.js b/app/javascript/mastodon/features/hashtag_timeline/index.js
index 374615ac7..15fca9ab4 100644
--- a/app/javascript/mastodon/features/hashtag_timeline/index.js
+++ b/app/javascript/mastodon/features/hashtag_timeline/index.js
@@ -20,6 +20,7 @@ export default class HashtagTimeline extends React.PureComponent {
     params: PropTypes.object.isRequired,
     columnId: PropTypes.string,
     dispatch: PropTypes.func.isRequired,
+    shouldUpdateScroll: PropTypes.func,
     hasUnread: PropTypes.bool,
     multiColumn: PropTypes.bool,
   };
@@ -83,7 +84,7 @@ export default class HashtagTimeline extends React.PureComponent {
   }
 
   render () {
-    const { hasUnread, columnId, multiColumn } = this.props;
+    const { shouldUpdateScroll, hasUnread, columnId, multiColumn } = this.props;
     const { id } = this.props.params;
     const pinned = !!columnId;
 
@@ -107,6 +108,7 @@ export default class HashtagTimeline extends React.PureComponent {
           timelineId={`hashtag:${id}`}
           onLoadMore={this.handleLoadMore}
           emptyMessage={<FormattedMessage id='empty_column.hashtag' defaultMessage='There is nothing in this hashtag yet.' />}
+          shouldUpdateScroll={shouldUpdateScroll}
         />
       </Column>
     );
diff --git a/app/javascript/mastodon/features/home_timeline/index.js b/app/javascript/mastodon/features/home_timeline/index.js
index db6bbdec1..4e6853c5b 100644
--- a/app/javascript/mastodon/features/home_timeline/index.js
+++ b/app/javascript/mastodon/features/home_timeline/index.js
@@ -25,6 +25,7 @@ export default class HomeTimeline extends React.PureComponent {
 
   static propTypes = {
     dispatch: PropTypes.func.isRequired,
+    shouldUpdateScroll: PropTypes.func,
     intl: PropTypes.object.isRequired,
     hasUnread: PropTypes.bool,
     isPartial: PropTypes.bool,
@@ -93,7 +94,7 @@ export default class HomeTimeline extends React.PureComponent {
   }
 
   render () {
-    const { intl, hasUnread, columnId, multiColumn } = this.props;
+    const { intl, shouldUpdateScroll, hasUnread, columnId, multiColumn } = this.props;
     const pinned = !!columnId;
 
     return (
@@ -117,6 +118,7 @@ export default class HomeTimeline extends React.PureComponent {
           onLoadMore={this.handleLoadMore}
           timelineId='home'
           emptyMessage={<FormattedMessage id='empty_column.home' defaultMessage='Your home timeline is empty! Visit {public} or use search to get started and meet other users.' values={{ public: <Link to='/timelines/public'><FormattedMessage id='empty_column.home.public_timeline' defaultMessage='the public timeline' /></Link> }} />}
+          shouldUpdateScroll={shouldUpdateScroll}
         />
       </Column>
     );
diff --git a/app/javascript/mastodon/features/list_timeline/index.js b/app/javascript/mastodon/features/list_timeline/index.js
index f08e77b7a..5c40fb758 100644
--- a/app/javascript/mastodon/features/list_timeline/index.js
+++ b/app/javascript/mastodon/features/list_timeline/index.js
@@ -35,6 +35,7 @@ export default class ListTimeline extends React.PureComponent {
   static propTypes = {
     params: PropTypes.object.isRequired,
     dispatch: PropTypes.func.isRequired,
+    shouldUpdateScroll: PropTypes.func,
     columnId: PropTypes.string,
     hasUnread: PropTypes.bool,
     multiColumn: PropTypes.bool,
@@ -112,7 +113,7 @@ export default class ListTimeline extends React.PureComponent {
   }
 
   render () {
-    const { hasUnread, columnId, multiColumn, list } = this.props;
+    const { shouldUpdateScroll, hasUnread, columnId, multiColumn, list } = this.props;
     const { id } = this.props.params;
     const pinned = !!columnId;
     const title  = list ? list.get('title') : id;
@@ -166,6 +167,7 @@ export default class ListTimeline extends React.PureComponent {
           timelineId={`list:${id}`}
           onLoadMore={this.handleLoadMore}
           emptyMessage={<FormattedMessage id='empty_column.list' defaultMessage='There is nothing in this list yet. When members of this list post new statuses, they will appear here.' />}
+          shouldUpdateScroll={shouldUpdateScroll}
         />
       </Column>
     );
diff --git a/app/javascript/mastodon/features/mutes/index.js b/app/javascript/mastodon/features/mutes/index.js
index bb351ece2..66fd3796d 100644
--- a/app/javascript/mastodon/features/mutes/index.js
+++ b/app/javascript/mastodon/features/mutes/index.js
@@ -1,5 +1,7 @@
 import React from 'react';
 import { connect } from 'react-redux';
+import { defineMessages, injectIntl } from 'react-intl';
+import ImmutablePureComponent from 'react-immutable-pure-component';
 import PropTypes from 'prop-types';
 import ImmutablePropTypes from 'react-immutable-proptypes';
 import LoadingIndicator from '../../components/loading_indicator';
@@ -8,8 +10,6 @@ import Column from '../ui/components/column';
 import ColumnBackButtonSlim from '../../components/column_back_button_slim';
 import AccountContainer from '../../containers/account_container';
 import { fetchMutes, expandMutes } from '../../actions/mutes';
-import { defineMessages, injectIntl } from 'react-intl';
-import ImmutablePureComponent from 'react-immutable-pure-component';
 
 const messages = defineMessages({
   heading: { id: 'column.mutes', defaultMessage: 'Muted users' },
@@ -26,6 +26,7 @@ export default class Mutes extends ImmutablePureComponent {
   static propTypes = {
     params: PropTypes.object.isRequired,
     dispatch: PropTypes.func.isRequired,
+    shouldUpdateScroll: PropTypes.func,
     accountIds: ImmutablePropTypes.list,
     intl: PropTypes.object.isRequired,
   };
@@ -43,7 +44,7 @@ export default class Mutes extends ImmutablePureComponent {
   }
 
   render () {
-    const { intl, accountIds } = this.props;
+    const { intl, shouldUpdateScroll, accountIds } = this.props;
 
     if (!accountIds) {
       return (
@@ -56,7 +57,7 @@ export default class Mutes extends ImmutablePureComponent {
     return (
       <Column icon='volume-off' heading={intl.formatMessage(messages.heading)}>
         <ColumnBackButtonSlim />
-        <ScrollContainer scrollKey='mutes'>
+        <ScrollContainer scrollKey='mutes' shouldUpdateScroll={shouldUpdateScroll}>
           <div className='scrollable mutes' onScroll={this.handleScroll}>
             {accountIds.map(id =>
               <AccountContainer key={id} id={id} />
diff --git a/app/javascript/mastodon/features/pinned_statuses/index.js b/app/javascript/mastodon/features/pinned_statuses/index.js
index b4a6c1e52..c6eb689d2 100644
--- a/app/javascript/mastodon/features/pinned_statuses/index.js
+++ b/app/javascript/mastodon/features/pinned_statuses/index.js
@@ -24,6 +24,7 @@ export default class PinnedStatuses extends ImmutablePureComponent {
 
   static propTypes = {
     dispatch: PropTypes.func.isRequired,
+    shouldUpdateScroll: PropTypes.func,
     statusIds: ImmutablePropTypes.list.isRequired,
     intl: PropTypes.object.isRequired,
     hasMore: PropTypes.bool.isRequired,
@@ -42,7 +43,7 @@ export default class PinnedStatuses extends ImmutablePureComponent {
   }
 
   render () {
-    const { intl, statusIds, hasMore } = this.props;
+    const { intl, shouldUpdateScroll, statusIds, hasMore } = this.props;
 
     return (
       <Column icon='thumb-tack' heading={intl.formatMessage(messages.heading)} ref={this.setRef}>
@@ -51,6 +52,7 @@ export default class PinnedStatuses extends ImmutablePureComponent {
           statusIds={statusIds}
           scrollKey='pinned_statuses'
           hasMore={hasMore}
+          shouldUpdateScroll={shouldUpdateScroll}
         />
       </Column>
     );
diff --git a/app/javascript/mastodon/features/public_timeline/index.js b/app/javascript/mastodon/features/public_timeline/index.js
index 2d5bb3baf..5f7ac5fc7 100644
--- a/app/javascript/mastodon/features/public_timeline/index.js
+++ b/app/javascript/mastodon/features/public_timeline/index.js
@@ -39,6 +39,7 @@ export default class PublicTimeline extends React.PureComponent {
 
   static propTypes = {
     dispatch: PropTypes.func.isRequired,
+    shouldUpdateScroll: PropTypes.func,
     intl: PropTypes.object.isRequired,
     columnId: PropTypes.string,
     multiColumn: PropTypes.bool,
@@ -107,7 +108,7 @@ export default class PublicTimeline extends React.PureComponent {
   }
 
   render () {
-    const { intl, columnId, hasUnread, multiColumn, onlyMedia } = this.props;
+    const { intl, shouldUpdateScroll, columnId, hasUnread, multiColumn, onlyMedia } = this.props;
     const pinned = !!columnId;
 
     return (
@@ -131,6 +132,7 @@ export default class PublicTimeline extends React.PureComponent {
           trackScroll={!pinned}
           scrollKey={`public_timeline-${columnId}`}
           emptyMessage={<FormattedMessage id='empty_column.public' defaultMessage='There is nothing here! Write something publicly, or manually follow users from other instances to fill it up' />}
+          shouldUpdateScroll={shouldUpdateScroll}
         />
       </Column>
     );
diff --git a/app/javascript/mastodon/features/reblogs/index.js b/app/javascript/mastodon/features/reblogs/index.js
index 579d6aaa0..367739636 100644
--- a/app/javascript/mastodon/features/reblogs/index.js
+++ b/app/javascript/mastodon/features/reblogs/index.js
@@ -1,5 +1,6 @@
 import React from 'react';
 import { connect } from 'react-redux';
+import ImmutablePureComponent from 'react-immutable-pure-component';
 import PropTypes from 'prop-types';
 import ImmutablePropTypes from 'react-immutable-proptypes';
 import LoadingIndicator from '../../components/loading_indicator';
@@ -8,7 +9,6 @@ import { ScrollContainer } from 'react-router-scroll-4';
 import AccountContainer from '../../containers/account_container';
 import Column from '../ui/components/column';
 import ColumnBackButton from '../../components/column_back_button';
-import ImmutablePureComponent from 'react-immutable-pure-component';
 
 const mapStateToProps = (state, props) => ({
   accountIds: state.getIn(['user_lists', 'reblogged_by', props.params.statusId]),
@@ -20,6 +20,7 @@ export default class Reblogs extends ImmutablePureComponent {
   static propTypes = {
     params: PropTypes.object.isRequired,
     dispatch: PropTypes.func.isRequired,
+    shouldUpdateScroll: PropTypes.func,
     accountIds: ImmutablePropTypes.list,
   };
 
@@ -34,7 +35,7 @@ export default class Reblogs extends ImmutablePureComponent {
   }
 
   render () {
-    const { accountIds } = this.props;
+    const { shouldUpdateScroll, accountIds } = this.props;
 
     if (!accountIds) {
       return (
@@ -48,7 +49,7 @@ export default class Reblogs extends ImmutablePureComponent {
       <Column>
         <ColumnBackButton />
 
-        <ScrollContainer scrollKey='reblogs'>
+        <ScrollContainer scrollKey='reblogs' shouldUpdateScroll={shouldUpdateScroll}>
           <div className='scrollable reblogs'>
             {accountIds.map(id => <AccountContainer key={id} id={id} withNote={false} />)}
           </div>
diff --git a/app/javascript/mastodon/features/status/index.js b/app/javascript/mastodon/features/status/index.js
index d7b50786c..89387ca43 100644
--- a/app/javascript/mastodon/features/status/index.js
+++ b/app/javascript/mastodon/features/status/index.js
@@ -42,7 +42,7 @@ import { defineMessages, injectIntl, FormattedMessage } from 'react-intl';
 import ImmutablePureComponent from 'react-immutable-pure-component';
 import { HotKeys } from 'react-hotkeys';
 import { boostModal, deleteModal } from '../../initial_state';
-import { attachFullscreenListener, detachFullscreenListener, isFullscreen } from '../../features/ui/util/fullscreen';
+import { attachFullscreenListener, detachFullscreenListener, isFullscreen } from '../ui/util/fullscreen';
 
 const messages = defineMessages({
   deleteConfirm: { id: 'confirmations.delete.confirm', defaultMessage: 'Delete' },
@@ -370,7 +370,7 @@ export default class Status extends ImmutablePureComponent {
 
   render () {
     let ancestors, descendants;
-    const { status, ancestorsIds, descendantsIds, intl } = this.props;
+    const { shouldUpdateScroll, status, ancestorsIds, descendantsIds, intl } = this.props;
     const { fullscreen } = this.state;
 
     if (status === null) {
@@ -410,7 +410,7 @@ export default class Status extends ImmutablePureComponent {
           )}
         />
 
-        <ScrollContainer scrollKey='thread'>
+        <ScrollContainer scrollKey='thread' shouldUpdateScroll={shouldUpdateScroll}>
           <div className={classNames('scrollable', 'detailed-status__wrapper', { fullscreen })} ref={this.setRef}>
             {ancestors}
 
diff --git a/app/javascript/mastodon/features/ui/components/media_modal.js b/app/javascript/mastodon/features/ui/components/media_modal.js
index 12db95326..83b9e1b50 100644
--- a/app/javascript/mastodon/features/ui/components/media_modal.js
+++ b/app/javascript/mastodon/features/ui/components/media_modal.js
@@ -16,7 +16,7 @@ const messages = defineMessages({
   next: { id: 'lightbox.next', defaultMessage: 'Next' },
 });
 
-const previewState = 'previewMediaModal';
+export const previewState = 'previewMediaModal';
 
 @injectIntl
 export default class MediaModal extends ImmutablePureComponent {
diff --git a/app/javascript/mastodon/features/ui/components/modal_root.js b/app/javascript/mastodon/features/ui/components/modal_root.js
index a334318ce..d8e034554 100644
--- a/app/javascript/mastodon/features/ui/components/modal_root.js
+++ b/app/javascript/mastodon/features/ui/components/modal_root.js
@@ -41,14 +41,15 @@ export default class ModalRoot extends React.PureComponent {
   };
 
   getSnapshotBeforeUpdate () {
-    const visible = !!this.props.type;
-    return {
-      overflowY: visible ? 'hidden' : null,
-    };
+    return { visible: !!this.props.type };
   }
 
-  componentDidUpdate (prevProps, prevState, { overflowY }) {
-    document.body.style.overflowY = overflowY;
+  componentDidUpdate (prevProps, prevState, { visible }) {
+    if (visible) {
+      document.body.classList.add('with-modals--active');
+    } else {
+      document.body.classList.remove('with-modals--active');
+    }
   }
 
   renderLoading = modalId => () => {
diff --git a/app/javascript/mastodon/features/ui/index.js b/app/javascript/mastodon/features/ui/index.js
index 56a856230..67484fc63 100644
--- a/app/javascript/mastodon/features/ui/index.js
+++ b/app/javascript/mastodon/features/ui/index.js
@@ -1,12 +1,14 @@
 import classNames from 'classnames';
 import React from 'react';
-import NotificationsContainer from './containers/notifications_container';
+import { HotKeys } from 'react-hotkeys';
+import { defineMessages, injectIntl } from 'react-intl';
+import { connect } from 'react-redux';
+import { Redirect, withRouter } from 'react-router-dom';
 import PropTypes from 'prop-types';
+import NotificationsContainer from './containers/notifications_container';
 import LoadingBarContainer from './containers/loading_bar_container';
 import TabsBar from './components/tabs_bar';
 import ModalContainer from './containers/modal_container';
-import { connect } from 'react-redux';
-import { Redirect, withRouter } from 'react-router-dom';
 import { isMobile } from '../../is_mobile';
 import { debounce } from 'lodash';
 import { uploadCompose, resetCompose } from '../../actions/compose';
@@ -44,9 +46,8 @@ import {
   PinnedStatuses,
   Lists,
 } from './util/async-components';
-import { HotKeys } from 'react-hotkeys';
 import { me } from '../../initial_state';
-import { defineMessages, injectIntl } from 'react-intl';
+import { previewState } from './components/media_modal';
 
 // Dummy import, to make sure that <Status /> ends up in the application bundle.
 // Without this it ends up in ~8 very commonly used bundles.
@@ -117,6 +118,10 @@ class SwitchingColumnsArea extends React.PureComponent {
     window.removeEventListener('resize', this.handleResize);
   }
 
+  shouldUpdateScroll (_, { location }) {
+    return location.state !== previewState;
+  }
+
   handleResize = debounce(() => {
     // The cached heights are no longer accurate, invalidate
     this.props.onLayoutChange();
@@ -141,36 +146,36 @@ class SwitchingColumnsArea extends React.PureComponent {
           {redirect}
           <WrappedRoute path='/getting-started' component={GettingStarted} content={children} />
           <WrappedRoute path='/keyboard-shortcuts' component={KeyboardShortcuts} content={children} />
-          <WrappedRoute path='/timelines/home' component={HomeTimeline} content={children} />
-          <WrappedRoute path='/timelines/public' exact component={PublicTimeline} content={children} />
-          <WrappedRoute path='/timelines/public/media' component={PublicTimeline} content={children} componentParams={{ onlyMedia: true }} />
-          <WrappedRoute path='/timelines/public/local' exact component={CommunityTimeline} content={children} />
-          <WrappedRoute path='/timelines/public/local/media' component={CommunityTimeline} content={children} componentParams={{ onlyMedia: true }} />
-          <WrappedRoute path='/timelines/direct' component={DirectTimeline} content={children} />
-          <WrappedRoute path='/timelines/tag/:id' component={HashtagTimeline} content={children} />
-          <WrappedRoute path='/timelines/list/:id' component={ListTimeline} content={children} />
-
-          <WrappedRoute path='/notifications' component={Notifications} content={children} />
-          <WrappedRoute path='/favourites' component={FavouritedStatuses} content={children} />
-          <WrappedRoute path='/pinned' component={PinnedStatuses} content={children} />
+          <WrappedRoute path='/timelines/home' component={HomeTimeline} content={children} componentParams={{ shouldUpdateScroll: this.shouldUpdateScroll }} />
+          <WrappedRoute path='/timelines/public' exact component={PublicTimeline} content={children} componentParams={{ shouldUpdateScroll: this.shouldUpdateScroll }} />
+          <WrappedRoute path='/timelines/public/media' component={PublicTimeline} content={children} componentParams={{ shouldUpdateScroll: this.shouldUpdateScroll, onlyMedia: true }} />
+          <WrappedRoute path='/timelines/public/local' exact component={CommunityTimeline} content={children} componentParams={{ shouldUpdateScroll: this.shouldUpdateScroll }} />
+          <WrappedRoute path='/timelines/public/local/media' component={CommunityTimeline} content={children} componentParams={{ shouldUpdateScroll: this.shouldUpdateScroll, onlyMedia: true }} />
+          <WrappedRoute path='/timelines/direct' component={DirectTimeline} content={children} componentParams={{ shouldUpdateScroll: this.shouldUpdateScroll }} />
+          <WrappedRoute path='/timelines/tag/:id' component={HashtagTimeline} content={children} componentParams={{ shouldUpdateScroll: this.shouldUpdateScroll }} />
+          <WrappedRoute path='/timelines/list/:id' component={ListTimeline} content={children} componentParams={{ shouldUpdateScroll: this.shouldUpdateScroll }} />
+
+          <WrappedRoute path='/notifications' component={Notifications} content={children} componentParams={{ shouldUpdateScroll: this.shouldUpdateScroll }} />
+          <WrappedRoute path='/favourites' component={FavouritedStatuses} content={children} componentParams={{ shouldUpdateScroll: this.shouldUpdateScroll }} />
+          <WrappedRoute path='/pinned' component={PinnedStatuses} content={children} componentParams={{ shouldUpdateScroll: this.shouldUpdateScroll }} />
 
           <WrappedRoute path='/search' component={Compose} content={children} componentParams={{ isSearchPage: true }} />
 
           <WrappedRoute path='/statuses/new' component={Compose} content={children} />
-          <WrappedRoute path='/statuses/:statusId' exact component={Status} content={children} />
-          <WrappedRoute path='/statuses/:statusId/reblogs' component={Reblogs} content={children} />
-          <WrappedRoute path='/statuses/:statusId/favourites' component={Favourites} content={children} />
-
-          <WrappedRoute path='/accounts/:accountId' exact component={AccountTimeline} content={children} />
-          <WrappedRoute path='/accounts/:accountId/with_replies' component={AccountTimeline} content={children} componentParams={{ withReplies: true }} />
-          <WrappedRoute path='/accounts/:accountId/followers' component={Followers} content={children} />
-          <WrappedRoute path='/accounts/:accountId/following' component={Following} content={children} />
-          <WrappedRoute path='/accounts/:accountId/media' component={AccountGallery} content={children} />
-
-          <WrappedRoute path='/follow_requests' component={FollowRequests} content={children} />
-          <WrappedRoute path='/blocks' component={Blocks} content={children} />
-          <WrappedRoute path='/domain_blocks' component={DomainBlocks} content={children} />
-          <WrappedRoute path='/mutes' component={Mutes} content={children} />
+          <WrappedRoute path='/statuses/:statusId' exact component={Status} content={children} componentParams={{ shouldUpdateScroll: this.shouldUpdateScroll }} />
+          <WrappedRoute path='/statuses/:statusId/reblogs' component={Reblogs} content={children} componentParams={{ shouldUpdateScroll: this.shouldUpdateScroll }} />
+          <WrappedRoute path='/statuses/:statusId/favourites' component={Favourites} content={children} componentParams={{ shouldUpdateScroll: this.shouldUpdateScroll }} />
+
+          <WrappedRoute path='/accounts/:accountId' exact component={AccountTimeline} content={children} componentParams={{ shouldUpdateScroll: this.shouldUpdateScroll }} />
+          <WrappedRoute path='/accounts/:accountId/with_replies' component={AccountTimeline} content={children} componentParams={{ shouldUpdateScroll: this.shouldUpdateScroll, withReplies: true }} />
+          <WrappedRoute path='/accounts/:accountId/followers' component={Followers} content={children} componentParams={{ shouldUpdateScroll: this.shouldUpdateScroll }} />
+          <WrappedRoute path='/accounts/:accountId/following' component={Following} content={children} componentParams={{ shouldUpdateScroll: this.shouldUpdateScroll }} />
+          <WrappedRoute path='/accounts/:accountId/media' component={AccountGallery} content={children} componentParams={{ shouldUpdateScroll: this.shouldUpdateScroll }} />
+
+          <WrappedRoute path='/follow_requests' component={FollowRequests} content={children} componentParams={{ shouldUpdateScroll: this.shouldUpdateScroll }} />
+          <WrappedRoute path='/blocks' component={Blocks} content={children} componentParams={{ shouldUpdateScroll: this.shouldUpdateScroll }} />
+          <WrappedRoute path='/domain_blocks' component={DomainBlocks} content={children} componentParams={{ shouldUpdateScroll: this.shouldUpdateScroll }} />
+          <WrappedRoute path='/mutes' component={Mutes} content={children} componentParams={{ shouldUpdateScroll: this.shouldUpdateScroll }} />
           <WrappedRoute path='/lists' component={Lists} content={children} />
 
           <WrappedRoute component={GenericNotFound} content={children} />
diff --git a/app/javascript/mastodon/locales/cs.json b/app/javascript/mastodon/locales/cs.json
index e0dd0ab23..d276c4651 100644
--- a/app/javascript/mastodon/locales/cs.json
+++ b/app/javascript/mastodon/locales/cs.json
@@ -1,17 +1,17 @@
 {
   "account.badges.bot": "Robot",
-  "account.block": "Blokovat @{name}",
+  "account.block": "Zablokovat uživatele @{name}",
   "account.block_domain": "Skrýt vše z {domain}",
   "account.blocked": "Blokován/a",
   "account.direct": "Přímá zpráva pro uživatele @{name}",
   "account.disclaimer_full": "Níže uvedené informace nemusejí zcela odrážet profil uživatele.",
   "account.domain_blocked": "Doména skryta",
-  "account.edit_profile": "Uprav profil",
+  "account.edit_profile": "Upravit profil",
   "account.follow": "Sleduj",
   "account.followers": "Sledovatelé",
   "account.follows": "Sleduje",
   "account.follows_you": "Sleduje vás",
-  "account.hide_reblogs": "Skrýt povýšení od uživatele @{name}",
+  "account.hide_reblogs": "Skrýt boosty od uživatele @{name}",
   "account.media": "Média",
   "account.mention": "Zmínit uživatele @{name}",
   "account.moved_to": "{name} se přesunul/a na:",
@@ -23,7 +23,7 @@
   "account.report": "Nahlásit uživatele @{name}",
   "account.requested": "Požadavek čeká na schválení. Kliknutím zrušíte požadavek o sledování",
   "account.share": "Sdílet profil uživatele @{name}",
-  "account.show_reblogs": "Zobrazit povýšení od uživatele @{name}",
+  "account.show_reblogs": "Zobrazit boosty od uživatele @{name}",
   "account.unblock": "Odblokovat uživatele @{name}",
   "account.unblock_domain": "Odkrýt doménu {domain}",
   "account.unfollow": "Přestat sledovat",
@@ -64,7 +64,7 @@
   "compose_form.direct_message_warning_learn_more": "Zjistit více",
   "compose_form.hashtag_warning": "Tento toot nebude zobrazen pod žádným hashtagem, neboť je neuvedený. Pouze veřejné tooty mohou být vyhledány podle hashtagu.",
   "compose_form.lock_disclaimer": "Váš účet není {locked}. Kdokoliv vás může sledovat a vidět vaše příspěvky pouze pro sledovatele.",
-  "compose_form.lock_disclaimer.lock": "zamknutý",
+  "compose_form.lock_disclaimer.lock": "zamčený",
   "compose_form.placeholder": "Co máte na mysli?",
   "compose_form.publish": "Tootnout",
   "compose_form.publish_loud": "{publish}!",
@@ -85,225 +85,225 @@
   "confirmations.mute.confirm": "Ignorovat",
   "confirmations.mute.message": "Jste si jistý/á, že chcete ignorovat uživatele {name}?",
   "confirmations.redraft.confirm": "Vymazat a přepsat",
-  "confirmations.redraft.message": "Are you sure you want to delete this status and re-draft it? You will lose all replies, boosts and favourites to it.",
-  "confirmations.unfollow.confirm": "Unfollow",
-  "confirmations.unfollow.message": "Are you sure you want to unfollow {name}?",
-  "embed.instructions": "Embed this status on your website by copying the code below.",
-  "embed.preview": "Here is what it will look like:",
-  "emoji_button.activity": "Activity",
-  "emoji_button.custom": "Custom",
-  "emoji_button.flags": "Flags",
-  "emoji_button.food": "Food & Drink",
-  "emoji_button.label": "Insert emoji",
-  "emoji_button.nature": "Nature",
-  "emoji_button.not_found": "No emojos!! (╯°□°)╯︵ ┻━┻",
-  "emoji_button.objects": "Objects",
-  "emoji_button.people": "People",
-  "emoji_button.recent": "Frequently used",
-  "emoji_button.search": "Search...",
-  "emoji_button.search_results": "Search results",
-  "emoji_button.symbols": "Symbols",
-  "emoji_button.travel": "Travel & Places",
-  "empty_column.community": "The local timeline is empty. Write something publicly to get the ball rolling!",
-  "empty_column.direct": "You don't have any direct messages yet. When you send or receive one, it will show up here.",
-  "empty_column.hashtag": "There is nothing in this hashtag yet.",
-  "empty_column.home": "Your home timeline is empty! Visit {public} or use search to get started and meet other users.",
-  "empty_column.home.public_timeline": "the public timeline",
-  "empty_column.list": "There is nothing in this list yet. When members of this list post new statuses, they will appear here.",
-  "empty_column.notifications": "You don't have any notifications yet. Interact with others to start the conversation.",
-  "empty_column.public": "There is nothing here! Write something publicly, or manually follow users from other instances to fill it up",
-  "follow_request.authorize": "Authorize",
-  "follow_request.reject": "Reject",
-  "getting_started.developers": "Developers",
+  "confirmations.redraft.message": "Jste si jistý/á, že chcete vymazat a přepsat tento status? Ztratíte všechny jeho odpovědi, boosty a oblíbení.",
+  "confirmations.unfollow.confirm": "Přestat sledovat",
+  "confirmations.unfollow.message": "jste si jistý/á, že chcete přestat sledovat uživatele {name}?",
+  "embed.instructions": "Pro přidání statusu na vaši webovou stránku zkopírujte níže uvedený kód.",
+  "embed.preview": "Takhle to bude vypadat:",
+  "emoji_button.activity": "Aktivita",
+  "emoji_button.custom": "Vlastní",
+  "emoji_button.flags": "Vlajky",
+  "emoji_button.food": "Jídla a nápoje",
+  "emoji_button.label": "Vložit emoji",
+  "emoji_button.nature": "Příroda",
+  "emoji_button.not_found": "Žádné emoji!! (╯°□°)╯︵ ┻━┻",
+  "emoji_button.objects": "Předměty",
+  "emoji_button.people": "Lidé",
+  "emoji_button.recent": "Často používané",
+  "emoji_button.search": "Hledat...",
+  "emoji_button.search_results": "Výsledky hledání",
+  "emoji_button.symbols": "Symboly",
+  "emoji_button.travel": "Cestování a místa",
+  "empty_column.community": "Místní časová osa je prázdná. Napište něco veřejně a rozhýbejte to tu!",
+  "empty_column.direct": "Ještě nemáte žádné přímé zprávy. Pokud nějakou pošlete nebo dostanete, zobrazí se zde.",
+  "empty_column.hashtag": "Pod tímto hashtagem ještě nic není.",
+  "empty_column.home": "Vaše domovská časová osa je prázdná! Začněte navštívením {public} nebo použijte hledání a seznamte se s dalšími uživateli.",
+  "empty_column.home.public_timeline": "veřejné časové osy",
+  "empty_column.list": "V tomto seznamu ještě nic není. Pokud budou členové tohoto seznamu psát nové statusy, objeví se zde.",
+  "empty_column.notifications": "Ještě nemáte žádná oznámení. Začněte konverzaci komunikováním s ostatními.",
+  "empty_column.public": "Tady nic není! Napište něco veřejně, nebo manuálně začněte sledovat uživatele z jiných instancí, aby tu něco přibylo",
+  "follow_request.authorize": "Autorizovat",
+  "follow_request.reject": "Odmítnout",
+  "getting_started.developers": "Vývojáři",
   "getting_started.documentation": "Documentation",
-  "getting_started.find_friends": "Find friends from Twitter",
-  "getting_started.heading": "Getting started",
-  "getting_started.invite": "Invite people",
-  "getting_started.open_source_notice": "Mastodon is open source software. You can contribute or report issues on GitHub at {github}.",
-  "getting_started.security": "Security",
-  "getting_started.terms": "Terms of service",
-  "home.column_settings.basic": "Basic",
-  "home.column_settings.show_reblogs": "Show boosts",
-  "home.column_settings.show_replies": "Show replies",
-  "keyboard_shortcuts.back": "to navigate back",
-  "keyboard_shortcuts.boost": "to boost",
-  "keyboard_shortcuts.column": "to focus a status in one of the columns",
-  "keyboard_shortcuts.compose": "to focus the compose textarea",
-  "keyboard_shortcuts.description": "Description",
-  "keyboard_shortcuts.down": "to move down in the list",
-  "keyboard_shortcuts.enter": "to open status",
-  "keyboard_shortcuts.favourite": "to favourite",
-  "keyboard_shortcuts.heading": "Keyboard Shortcuts",
-  "keyboard_shortcuts.hotkey": "Hotkey",
-  "keyboard_shortcuts.legend": "to display this legend",
-  "keyboard_shortcuts.mention": "to mention author",
+  "getting_started.find_friends": "Najděte si přátele z Twitteru",
+  "getting_started.heading": "Začínáme",
+  "getting_started.invite": "Pozvat lidi",
+  "getting_started.open_source_notice": "Mastodon je otevřený software. Na GitHubu k němu můžete přispět nebo nahlásit chyby: {github}.",
+  "getting_started.security": "Zabezpečení",
+  "getting_started.terms": "Podmínky používání",
+  "home.column_settings.basic": "Základní",
+  "home.column_settings.show_reblogs": "Zobrazit boosty",
+  "home.column_settings.show_replies": "Zobrazit odpovědi",
+  "keyboard_shortcuts.back": "k návratu zpět",
+  "keyboard_shortcuts.boost": "k boostnutí",
+  "keyboard_shortcuts.column": "k zaměření na status v jednom ze sloupců",
+  "keyboard_shortcuts.compose": "k zaměření na psací prostor",
+  "keyboard_shortcuts.description": "Popis",
+  "keyboard_shortcuts.down": "k přesunutí dolů v seznamu",
+  "keyboard_shortcuts.enter": "k otevření statusu",
+  "keyboard_shortcuts.favourite": "k oblíbení",
+  "keyboard_shortcuts.heading": "Klávesové zkratky",
+  "keyboard_shortcuts.hotkey": "Horká klávesa",
+  "keyboard_shortcuts.legend": "k zobrazení této legendy",
+  "keyboard_shortcuts.mention": "ke zmínění autora",
   "keyboard_shortcuts.profile": "to open author's profile",
-  "keyboard_shortcuts.reply": "to reply",
-  "keyboard_shortcuts.search": "to focus search",
-  "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",
-  "lightbox.close": "Close",
-  "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.new.create": "Add list",
-  "lists.new.title_placeholder": "New list title",
-  "lists.search": "Search among people you follow",
-  "lists.subheading": "Your lists",
-  "loading_indicator.label": "Loading...",
-  "media_gallery.toggle_visible": "Toggle visibility",
-  "missing_indicator.label": "Not found",
-  "missing_indicator.sublabel": "This resource could not be found",
-  "mute_modal.hide_notifications": "Hide notifications from this user?",
-  "navigation_bar.blocks": "Blocked users",
-  "navigation_bar.community_timeline": "Local timeline",
-  "navigation_bar.direct": "Direct messages",
-  "navigation_bar.discover": "Discover",
-  "navigation_bar.domain_blocks": "Hidden domains",
-  "navigation_bar.edit_profile": "Edit profile",
-  "navigation_bar.favourites": "Favourites",
-  "navigation_bar.filters": "Muted words",
-  "navigation_bar.follow_requests": "Follow requests",
-  "navigation_bar.info": "About this instance",
-  "navigation_bar.keyboard_shortcuts": "Hotkeys",
-  "navigation_bar.lists": "Lists",
-  "navigation_bar.logout": "Logout",
-  "navigation_bar.mutes": "Muted users",
-  "navigation_bar.personal": "Personal",
-  "navigation_bar.pins": "Pinned toots",
-  "navigation_bar.preferences": "Preferences",
-  "navigation_bar.public_timeline": "Federated timeline",
-  "navigation_bar.security": "Security",
-  "notification.favourite": "{name} favourited your status",
-  "notification.follow": "{name} followed you",
-  "notification.mention": "{name} mentioned you",
-  "notification.reblog": "{name} boosted your status",
-  "notifications.clear": "Clear notifications",
-  "notifications.clear_confirmation": "Are you sure you want to permanently clear all your notifications?",
-  "notifications.column_settings.alert": "Desktop notifications",
-  "notifications.column_settings.favourite": "Favourites:",
-  "notifications.column_settings.follow": "New followers:",
-  "notifications.column_settings.mention": "Mentions:",
-  "notifications.column_settings.push": "Push notifications",
-  "notifications.column_settings.push_meta": "This device",
-  "notifications.column_settings.reblog": "Boosts:",
-  "notifications.column_settings.show": "Show in column",
-  "notifications.column_settings.sound": "Play sound",
-  "notifications.group": "{count} notifications",
-  "onboarding.done": "Done",
-  "onboarding.next": "Next",
-  "onboarding.page_five.public_timelines": "The local timeline shows public posts from everyone on {domain}. The federated timeline shows public posts from everyone who people on {domain} follow. These are the Public Timelines, a great way to discover new people.",
-  "onboarding.page_four.home": "The home timeline shows posts from people you follow.",
-  "onboarding.page_four.notifications": "The notifications column shows when someone interacts with you.",
-  "onboarding.page_one.federation": "Mastodon is a network of independent servers joining up to make one larger social network. We call these servers instances.",
-  "onboarding.page_one.full_handle": "Your full handle",
-  "onboarding.page_one.handle_hint": "This is what you would tell your friends to search for.",
-  "onboarding.page_one.welcome": "Welcome to Mastodon!",
-  "onboarding.page_six.admin": "Your instance's admin is {admin}.",
-  "onboarding.page_six.almost_done": "Almost done...",
-  "onboarding.page_six.appetoot": "Bon Appetoot!",
-  "onboarding.page_six.apps_available": "There are {apps} available for iOS, Android and other platforms.",
-  "onboarding.page_six.github": "Mastodon is free open-source software. You can report bugs, request features, or contribute to the code on {github}.",
-  "onboarding.page_six.guidelines": "community guidelines",
-  "onboarding.page_six.read_guidelines": "Please read {domain}'s {guidelines}!",
-  "onboarding.page_six.various_app": "mobile apps",
-  "onboarding.page_three.profile": "Edit your profile to change your avatar, bio, and display name. There, you will also find other preferences.",
-  "onboarding.page_three.search": "Use the search bar to find people and look at hashtags, such as {illustration} and {introductions}. To look for a person who is not on this instance, use their full handle.",
-  "onboarding.page_two.compose": "Write posts from the compose column. You can upload images, change privacy settings, and add content warnings with the icons below.",
-  "onboarding.skip": "Skip",
-  "privacy.change": "Adjust status privacy",
-  "privacy.direct.long": "Post to mentioned users only",
-  "privacy.direct.short": "Direct",
-  "privacy.private.long": "Post to followers only",
-  "privacy.private.short": "Followers-only",
-  "privacy.public.long": "Post to public timelines",
-  "privacy.public.short": "Public",
+  "keyboard_shortcuts.reply": "k odpovězení",
+  "keyboard_shortcuts.search": "k zaměření na vyhledávání",
+  "keyboard_shortcuts.toggle_hidden": "k zobrazení/skrytí textu za CW",
+  "keyboard_shortcuts.toot": "k napsání úplně nového tootu",
+  "keyboard_shortcuts.unfocus": "ke zrušení soustředění na psací prostor/hledání",
+  "keyboard_shortcuts.up": "k posunutí nahoru v seznamu",
+  "lightbox.close": "Zavřít",
+  "lightbox.next": "Další",
+  "lightbox.previous": "Předchozí",
+  "lists.account.add": "Přidat do seznamu",
+  "lists.account.remove": "Odebrat ze seznamu",
+  "lists.delete": "Smazat seznam",
+  "lists.edit": "Upravit seznam",
+  "lists.new.create": "Přidat seznam",
+  "lists.new.title_placeholder": "Název nového seznamu",
+  "lists.search": "Hledejte mezi uživateli, které sledujete",
+  "lists.subheading": "Vaše seznamy",
+  "loading_indicator.label": "Načítám...",
+  "media_gallery.toggle_visible": "Přepínat viditelnost",
+  "missing_indicator.label": "Nenalezeno",
+  "missing_indicator.sublabel": "Tento zdroj se nepodažilo najít",
+  "mute_modal.hide_notifications": "Skrýt oznámení před tímto uživatelem?",
+  "navigation_bar.blocks": "Blokovaní uživatelé",
+  "navigation_bar.community_timeline": "Místní časová osa",
+  "navigation_bar.direct": "Přímé zprávy",
+  "navigation_bar.discover": "Objevujte",
+  "navigation_bar.domain_blocks": "Skryté domény",
+  "navigation_bar.edit_profile": "Upravit profil",
+  "navigation_bar.favourites": "Oblíbené",
+  "navigation_bar.filters": "Skrytá slova",
+  "navigation_bar.follow_requests": "Žádosti o sledování",
+  "navigation_bar.info": "O této instanci",
+  "navigation_bar.keyboard_shortcuts": "Klávesové zkratky",
+  "navigation_bar.lists": "Seznamy",
+  "navigation_bar.logout": "Odhlásit se",
+  "navigation_bar.mutes": "Ignorovaní uživatelé",
+  "navigation_bar.personal": "Osobní",
+  "navigation_bar.pins": "Připnuté tooty",
+  "navigation_bar.preferences": "Předvolby",
+  "navigation_bar.public_timeline": "Federovaná časová osa",
+  "navigation_bar.security": "Zabezpečení",
+  "notification.favourite": "{name} označil/a váš status jako oblíbený",
+  "notification.follow": "{name} vás začal/a sledovat",
+  "notification.mention": "{name} vás zmínil/a",
+  "notification.reblog": "{name} vám boostnul/a status",
+  "notifications.clear": "Vymazat oznámení",
+  "notifications.clear_confirmation": "Jste si jistý/á, že chcete trvale vymazat všechna vaše oznámení?",
+  "notifications.column_settings.alert": "Desktopová oznámení",
+  "notifications.column_settings.favourite": "Oblíbené:",
+  "notifications.column_settings.follow": "Noví sledovatelé:",
+  "notifications.column_settings.mention": "Zmínky:",
+  "notifications.column_settings.push": "Push oznámení",
+  "notifications.column_settings.push_meta": "Toto zařízení",
+  "notifications.column_settings.reblog": "Boosty:",
+  "notifications.column_settings.show": "Zobrazit ve sloupci",
+  "notifications.column_settings.sound": "Přehrát zvuk",
+  "notifications.group": "{count} oznámení",
+  "onboarding.done": "Hotovo",
+  "onboarding.next": "Další",
+  "onboarding.page_five.public_timelines": "Místní časová osa zobrazuje veřejné příspěvky od všech lidí na {domain}. Federovaná časová osa zobrazuje veřejné příspěvky ode všech, které lidé na {domain} sledují. Toto jsou veřejné časové osy, výborný způsob, jak objevovat nové lidi.",
+  "onboarding.page_four.home": "Domovská časová osa zobrazuje příspěvky od lidí, které sledujete.",
+  "onboarding.page_four.notifications": "Sloupec oznámení se zobrazí, když s vámi někdo bude komunikovat.",
+  "onboarding.page_one.federation": "Mastodon je síť nezávislých serverů, jejichž propojením vzniká jedna velká sociální síť. Těmto serverům říkáme instance.",
+  "onboarding.page_one.full_handle": "Vaše celá adresa profilu",
+  "onboarding.page_one.handle_hint": "Tohle je, co byste řekl/a svým přátelům, aby hledali.",
+  "onboarding.page_one.welcome": "Vítejte na Mastodonu!",
+  "onboarding.page_six.admin": "Administrátorem vaší instance je {admin}.",
+  "onboarding.page_six.almost_done": "Skoro hotovo...",
+  "onboarding.page_six.appetoot": "Bon appetoot!",
+  "onboarding.page_six.apps_available": "Jsou dostupné {apps} pro iOS, Android a jiné platformy.",
+  "onboarding.page_six.github": "Mastodon je svobodný a otevřený software. Na {github} můžete nahlásit chyby, požádat o nové funkce, nebo přispívat ke kódu.",
+  "onboarding.page_six.guidelines": "komunitní pravidla",
+  "onboarding.page_six.read_guidelines": "Prosím přečtěte si {guidelines} {domain}!",
+  "onboarding.page_six.various_app": "mobilní aplikace",
+  "onboarding.page_three.profile": "Upravte si svůj profil a změňte si svůj avatar, popis profilu a zobrazované jméno. V nastaveních najdete i další možnosti.",
+  "onboarding.page_three.search": "Pomocí vyhledávacího řádku najděte lidi a podívejte se na hashtagy jako {illustration} a {introductions}. Chcete-li najít někoho, kdo není na této instanci, použijte jeho celou adresu profilu.",
+  "onboarding.page_two.compose": "Příspěvky pište z pole na komponování. Ikonami níže můžete nahrávat obrázky, změnit nastavení soukromí a přidat varování o obsahu.",
+  "onboarding.skip": "Přeskočit",
+  "privacy.change": "Změnit viditelnost statusu",
+  "privacy.direct.long": "Odeslat pouze zmíněným uživatelům",
+  "privacy.direct.short": "Přímé",
+  "privacy.private.long": "Odeslat pouze sledovatelům",
+  "privacy.private.short": "Pouze pro sledovatele",
+  "privacy.public.long": "Odeslat na veřejné časové osy",
+  "privacy.public.short": "Veřejné",
   "privacy.unlisted.long": "Do not show in public timelines",
-  "privacy.unlisted.short": "Unlisted",
-  "regeneration_indicator.label": "Loading…",
-  "regeneration_indicator.sublabel": "Your home feed is being prepared!",
+  "privacy.unlisted.short": "Nezobrazované",
+  "regeneration_indicator.label": "Načítám…",
+  "regeneration_indicator.sublabel": "Váš domovský proud se připravuje!",
   "relative_time.days": "{number}d",
   "relative_time.hours": "{number}h",
-  "relative_time.just_now": "now",
+  "relative_time.just_now": "teď",
   "relative_time.minutes": "{number}m",
   "relative_time.seconds": "{number}s",
-  "reply_indicator.cancel": "Cancel",
-  "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.placeholder": "Additional comments",
-  "report.submit": "Submit",
-  "report.target": "Report {target}",
-  "search.placeholder": "Search",
-  "search_popout.search_format": "Advanced search 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.",
+  "reply_indicator.cancel": "Zrušit",
+  "report.forward": "Přeposlat k {target}",
+  "report.forward_hint": "Tento účet je z jiného serveru. Chcete na něj také poslat anonymizovanou kopii?",
+  "report.hint": "Toto nahlášení bude zasláno moderátorům vaší instance. Níže můžete uvést, proč tento účet nahlašujete:",
+  "report.placeholder": "Další komentáře",
+  "report.submit": "Odeslat",
+  "report.target": "Nahlásit {target}",
+  "search.placeholder": "Hledat",
+  "search_popout.search_format": "Pokročilé vyhledávání",
+  "search_popout.tips.full_text": "Jednoduchý textový výpis statusů, které jste napsal/a, oblíbil/a si, povýšil/a, nebo v nich byl/a zmíněn/a, včetně odpovídajících přezdívek, jmen a hashtagů.",
   "search_popout.tips.hashtag": "hashtag",
   "search_popout.tips.status": "status",
-  "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_results.total": "{count, number} {count, plural, one {result} other {results}}",
-  "standalone.public_title": "A look inside...",
-  "status.block": "Block @{name}",
-  "status.cancel_reblog_private": "Unboost",
-  "status.cannot_reblog": "This post cannot be boosted",
+  "search_popout.tips.text": "Jednoduchý textový výpis odpovídajících jmen, přezdívek a hashtagů",
+  "search_popout.tips.user": "uživatel",
+  "search_results.accounts": "Lidé",
+  "search_results.hashtags": "Hashtagy",
+  "search_results.statuses": "Tooty",
+  "search_results.total": "{count, number} {count, plural, one {výsledek} other {výsledků}}",
+  "standalone.public_title": "Nahlédnout dovnitř...",
+  "status.block": "Zablokovat uživatele @{name}",
+  "status.cancel_reblog_private": "Zrušit boost",
+  "status.cannot_reblog": "Tento příspěvek nemůže být boostnutý",
   "status.delete": "Delete",
-  "status.direct": "Direct message @{name}",
-  "status.embed": "Embed",
-  "status.favourite": "Favourite",
-  "status.filtered": "Filtered",
-  "status.load_more": "Load more",
-  "status.media_hidden": "Media hidden",
-  "status.mention": "Mention @{name}",
-  "status.more": "More",
-  "status.mute": "Mute @{name}",
-  "status.mute_conversation": "Mute conversation",
-  "status.open": "Expand this status",
-  "status.pin": "Pin on profile",
-  "status.pinned": "Pinned toot",
-  "status.reblog": "Boost",
-  "status.reblog_private": "Boost to original audience",
-  "status.reblogged_by": "{name} boosted",
-  "status.redraft": "Delete & re-draft",
-  "status.reply": "Reply",
-  "status.replyAll": "Reply to thread",
-  "status.report": "Report @{name}",
-  "status.sensitive_toggle": "Click to view",
-  "status.sensitive_warning": "Sensitive content",
-  "status.share": "Share",
-  "status.show_less": "Show less",
-  "status.show_less_all": "Show less for all",
-  "status.show_more": "Show more",
-  "status.show_more_all": "Show more for all",
-  "status.unmute_conversation": "Unmute conversation",
-  "status.unpin": "Unpin from profile",
-  "tabs_bar.federated_timeline": "Federated",
-  "tabs_bar.home": "Home",
-  "tabs_bar.local_timeline": "Local",
-  "tabs_bar.notifications": "Notifications",
-  "tabs_bar.search": "Search",
-  "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": "Drag & drop to upload",
-  "upload_button.label": "Add media",
-  "upload_form.description": "Describe for the visually impaired",
-  "upload_form.focus": "Crop",
-  "upload_form.undo": "Delete",
-  "upload_progress.label": "Uploading...",
-  "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"
+  "status.direct": "Poslat přímou zprávu uživateli @{name}",
+  "status.embed": "Vložit",
+  "status.favourite": "Oblíbit",
+  "status.filtered": "Filtrováno",
+  "status.load_more": "Zobrazit více",
+  "status.media_hidden": "Média skryta",
+  "status.mention": "Zmínit uživatele @{name}",
+  "status.more": "Více",
+  "status.mute": "Ignorovat uživatele @{name}",
+  "status.mute_conversation": "Ignorovat konverzaci",
+  "status.open": "Otevřít tento status",
+  "status.pin": "Připnout na profil",
+  "status.pinned": "Připnutý toot",
+  "status.reblog": "Boostnout",
+  "status.reblog_private": "Boostnout původnímu publiku",
+  "status.reblogged_by": "{name} boostnul/a",
+  "status.redraft": "Vymazat a přepsat",
+  "status.reply": "Odpovědět",
+  "status.replyAll": "Odpovědět na vlákno",
+  "status.report": "Nahlásit uživatele @{name}",
+  "status.sensitive_toggle": "Klikněte pro zobrazení",
+  "status.sensitive_warning": "Citlivý obsah",
+  "status.share": "Sdílet",
+  "status.show_less": "Zobrazit méně",
+  "status.show_less_all": "Zobrazit méně pro všechny",
+  "status.show_more": "Zobrazit více",
+  "status.show_more_all": "Zobrazit více pro všechny",
+  "status.unmute_conversation": "Přestat ignorovat konverzaci",
+  "status.unpin": "Odepnout z profilu",
+  "tabs_bar.federated_timeline": "Federovaná",
+  "tabs_bar.home": "Domů",
+  "tabs_bar.local_timeline": "Místní",
+  "tabs_bar.notifications": "Oznámení",
+  "tabs_bar.search": "Hledat",
+  "trends.count_by_accounts": "{count} {rawCount, plural, one {člověk} other {lidí}} diskutuje",
+  "ui.beforeunload": "Váš koncept se ztratí, pokud Mastodon opustíte.",
+  "upload_area.title": "Přetažením nahrajete",
+  "upload_button.label": "Přidat média",
+  "upload_form.description": "Popis pro zrakově postižené",
+  "upload_form.focus": "Vystřihnout",
+  "upload_form.undo": "Smazat",
+  "upload_progress.label": "Nahrávám...",
+  "video.close": "Zavřít video",
+  "video.exit_fullscreen": "Ukončit celou obrazovku",
+  "video.expand": "Otevřít video",
+  "video.fullscreen": "Celá obrazovka",
+  "video.hide": "Skrýt video",
+  "video.mute": "Vypnout zvuk",
+  "video.pause": "Pauza",
+  "video.play": "Přehrát",
+  "video.unmute": "Zapnout zvuk"
 }
diff --git a/app/javascript/mastodon/locales/ko.json b/app/javascript/mastodon/locales/ko.json
index 206ebeefd..9e630520d 100644
--- a/app/javascript/mastodon/locales/ko.json
+++ b/app/javascript/mastodon/locales/ko.json
@@ -167,7 +167,7 @@
   "navigation_bar.domain_blocks": "숨겨진 도메인",
   "navigation_bar.edit_profile": "프로필 편집",
   "navigation_bar.favourites": "즐겨찾기",
-  "navigation_bar.filters": "Muted words",
+  "navigation_bar.filters": "뮤트",
   "navigation_bar.follow_requests": "팔로우 요청",
   "navigation_bar.info": "이 인스턴스에 대해서",
   "navigation_bar.keyboard_shortcuts": "단축키",
diff --git a/app/javascript/mastodon/locales/pt-BR.json b/app/javascript/mastodon/locales/pt-BR.json
index fa56e52fb..69db735dd 100644
--- a/app/javascript/mastodon/locales/pt-BR.json
+++ b/app/javascript/mastodon/locales/pt-BR.json
@@ -129,11 +129,11 @@
   "keyboard_shortcuts.boost": "para compartilhar",
   "keyboard_shortcuts.column": "Focar um status em uma das colunas",
   "keyboard_shortcuts.compose": "para focar a área de redação",
-  "keyboard_shortcuts.description": "Description",
+  "keyboard_shortcuts.description": "Descrição",
   "keyboard_shortcuts.down": "para mover para baixo na lista",
-  "keyboard_shortcuts.enter": "to open status",
+  "keyboard_shortcuts.enter": "para expandir um status",
   "keyboard_shortcuts.favourite": "para adicionar aos favoritos",
-  "keyboard_shortcuts.heading": "Keyboard Shortcuts",
+  "keyboard_shortcuts.heading": "Atalhos de teclado",
   "keyboard_shortcuts.hotkey": "Atalho",
   "keyboard_shortcuts.legend": "para mostrar essa legenda",
   "keyboard_shortcuts.mention": "para mencionar o autor",
diff --git a/app/javascript/mastodon/locales/te.json b/app/javascript/mastodon/locales/te.json
index 48a648622..635647355 100644
--- a/app/javascript/mastodon/locales/te.json
+++ b/app/javascript/mastodon/locales/te.json
@@ -65,7 +65,7 @@
   "compose_form.hashtag_warning": "ఈ టూట్ అన్లిస్టెడ్ కాబట్టి ఏ హాష్ ట్యాగ్ క్రిందకూ రాదు. పబ్లిక్ టూట్ లను మాత్రమే హాష్ ట్యాగ్ ద్వారా శోధించవచ్చు.",
   "compose_form.lock_disclaimer": "మీ ఖాతా {locked} చేయబడలేదు. ఎవరైనా మిమ్మల్ని అనుసరించి మీ అనుచరులకు-మాత్రమే పోస్ట్లను వీక్షించవచ్చు.",
   "compose_form.lock_disclaimer.lock": "బిగించబడినది",
-  "compose_form.placeholder": "మీ మనస్సులో ఏమి ఉంది?",
+  "compose_form.placeholder": "మీ మనస్సులో ఏముంది?",
   "compose_form.publish": "టూట్",
   "compose_form.publish_loud": "{publish}!",
   "compose_form.sensitive.marked": "మీడియా సున్నితమైనదిగా గుర్తించబడింది",
@@ -115,7 +115,7 @@
   "follow_request.authorize": "అనుమతించు",
   "follow_request.reject": "తిరస్కరించు",
   "getting_started.developers": "డెవలపర్లు",
-  "getting_started.documentation": "Documentation",
+  "getting_started.documentation": "డాక్యుమెంటేషన్",
   "getting_started.find_friends": "ట్విట్టర్ నుండి స్నేహితులను కనుగొనండి",
   "getting_started.heading": "మొదలుపెడదాం",
   "getting_started.invite": "వ్యక్తులను ఆహ్వానించండి",
@@ -167,7 +167,7 @@
   "navigation_bar.domain_blocks": "దాచిన డొమైన్లు",
   "navigation_bar.edit_profile": "ప్రొఫైల్ని సవరించండి",
   "navigation_bar.favourites": "ఇష్టపడినవి",
-  "navigation_bar.filters": "Muted words",
+  "navigation_bar.filters": "మ్యూట్ చేయబడిన పదాలు",
   "navigation_bar.follow_requests": "అనుసరించడానికి అభ్యర్ధనలు",
   "navigation_bar.info": "ఈ దృష్టాంతం గురించి",
   "navigation_bar.keyboard_shortcuts": "హాట్ కీలు",
@@ -258,7 +258,7 @@
   "status.direct": "@{name}కు నేరుగా సందేశం పంపు",
   "status.embed": "ఎంబెడ్",
   "status.favourite": "ఇష్టపడు",
-  "status.filtered": "Filtered",
+  "status.filtered": "వడకట్టబడిన",
   "status.load_more": "మరిన్ని లోడ్ చేయి",
   "status.media_hidden": "మీడియా దాచబడింది",
   "status.mention": "@{name}ను ప్రస్తావించు",
diff --git a/app/javascript/packs/public.js b/app/javascript/packs/public.js
index 0d37c34c8..3a1ca1a7b 100644
--- a/app/javascript/packs/public.js
+++ b/app/javascript/packs/public.js
@@ -5,14 +5,16 @@ import { start } from '../mastodon/common';
 start();
 
 function main() {
-  const IntlRelativeFormat = require('intl-relativeformat').default;
+  const { length } = require('stringz');
+  const IntlMessageFormat = require('intl-messageformat').default;
+  const { timeAgoString } = require('../mastodon/components/relative_timestamp');
+  const { delegate } = require('rails-ujs');
   const emojify = require('../mastodon/features/emoji/emoji').default;
   const { getLocale } = require('../mastodon/locales');
-  const { localeData } = getLocale();
+  const { messages } = getLocale();
   const React = require('react');
   const ReactDOM = require('react-dom');
-
-  localeData.forEach(IntlRelativeFormat.__addLocaleData);
+  const Rellax = require('rellax');
 
   ready(() => {
     const locale = document.documentElement.lang;
@@ -25,8 +27,6 @@ function main() {
       minute: 'numeric',
     });
 
-    const relativeFormat = new IntlRelativeFormat(locale);
-
     [].forEach.call(document.querySelectorAll('.emojify'), (content) => {
       content.innerHTML = emojify(content.innerHTML);
     });
@@ -41,12 +41,16 @@ function main() {
 
     [].forEach.call(document.querySelectorAll('time.time-ago'), (content) => {
       const datetime = new Date(content.getAttribute('datetime'));
+      const now      = new Date();
 
       content.title = dateTimeFormat.format(datetime);
-      content.textContent = relativeFormat.format(datetime);
+      content.textContent = timeAgoString({
+        formatMessage: ({ id, defaultMessage }, values) => (new IntlMessageFormat(messages[id] || defaultMessage, locale)).format(values),
+        formatDate: (date, options) => (new Intl.DateTimeFormat(locale, options)).format(date),
+      }, datetime, now, datetime.getFullYear());
     });
 
-    [].forEach.call(document.querySelectorAll('.logo-button'), (content) => {
+    [].forEach.call(document.querySelectorAll('.modal-button'), (content) => {
       content.addEventListener('click', (e) => {
         e.preventDefault();
         window.open(e.target.href, 'mastodon-intent', 'width=445,height=600,resizable=no,menubar=no,status=no,scrollbars=yes');
@@ -64,6 +68,8 @@ function main() {
         })
         .catch(error => console.error(error));
     }
+
+    new Rellax('.parallax', { speed: -1 });
   });
 }
 
diff --git a/app/javascript/styles/application.scss b/app/javascript/styles/application.scss
index 7b3b10dfe..0990a4f25 100644
--- a/app/javascript/styles/application.scss
+++ b/app/javascript/styles/application.scss
@@ -10,7 +10,7 @@
 @import 'mastodon/lists';
 @import 'mastodon/footer';
 @import 'mastodon/compact_header';
-@import 'mastodon/landing_strip';
+@import 'mastodon/widgets';
 @import 'mastodon/forms';
 @import 'mastodon/accounts';
 @import 'mastodon/stream_entries';
diff --git a/app/javascript/styles/mastodon/about.scss b/app/javascript/styles/mastodon/about.scss
index fefb03407..b9544bb33 100644
--- a/app/javascript/styles/mastodon/about.scss
+++ b/app/javascript/styles/mastodon/about.scss
@@ -1115,6 +1115,21 @@ $small-breakpoint: 960px;
   }
 
   &.tag-page {
+    @media screen and (max-width: $column-breakpoint) {
+      padding: 0;
+
+      .container {
+        padding: 0;
+      }
+
+      #mastodon-timeline {
+        display: block;
+        width: 100vw;
+        height: 100vh;
+        border-radius: 0;
+      }
+    }
+
     .grid {
       @media screen and (min-width: $small-breakpoint) {
         grid-template-columns: 33% 67%;
@@ -1146,24 +1161,17 @@ $small-breakpoint: 960px;
 
     @media screen and (max-width: $column-breakpoint) {
       .grid {
+        grid-gap: 0;
+
         .column-1 {
           grid-column: 1;
-          grid-row: 2;
+          grid-row: 1;
         }
 
         .column-2 {
-          grid-column: 1;
-          grid-row: 1;
+          display: none;
         }
       }
-
-      .brand {
-        margin: 0;
-      }
-
-      .landing-page__features {
-        display: none;
-      }
     }
   }
 }
diff --git a/app/javascript/styles/mastodon/accounts.scss b/app/javascript/styles/mastodon/accounts.scss
index b4612b063..c27bc0df3 100644
--- a/app/javascript/styles/mastodon/accounts.scss
+++ b/app/javascript/styles/mastodon/accounts.scss
@@ -1,243 +1,100 @@
 .card {
-  background-color: $base-shadow-color;
-  background-size: cover;
-  background-position: center;
-  border-radius: 4px 4px 0 0;
-  box-shadow: 0 0 15px rgba($base-shadow-color, 0.2);
-  overflow: hidden;
-  position: relative;
-  display: flex;
-
-  &::after {
-    background: rgba(darken($ui-base-color, 8%), 0.5);
+  & > a {
     display: block;
-    content: "";
-    position: absolute;
-    left: 0;
-    top: 0;
-    width: 100%;
-    height: 100%;
-    z-index: 1;
-  }
-
-  @media screen and (max-width: 740px) {
-    border-radius: 0;
-    box-shadow: none;
-  }
-
-  .card__illustration {
-    padding: 60px 0;
-    position: relative;
-    flex: 1 1 auto;
-    display: flex;
-    justify-content: center;
-    align-items: center;
-  }
-
-  .card__bio {
-    max-width: 260px;
-    flex: 1 1 auto;
-    display: flex;
-    flex-direction: column;
-    justify-content: space-between;
-    background: rgba(darken($ui-base-color, 8%), 0.8);
-    position: relative;
-    z-index: 2;
-  }
-
-  &.compact {
-    padding: 30px 0;
-    border-radius: 4px;
-
-    .avatar {
-      margin-bottom: 0;
+    text-decoration: none;
+    color: inherit;
+    box-shadow: 0 0 15px rgba($base-shadow-color, 0.2);
 
-      img {
-        object-fit: cover;
-      }
+    @media screen and (max-width: $no-gap-breakpoint) {
+      box-shadow: none;
     }
-  }
-
-  .name {
-    display: block;
-    font-size: 20px;
-    line-height: 18px * 1.5;
-    color: $primary-text-color;
-    padding: 10px 15px;
-    padding-bottom: 0;
-    font-weight: 500;
-    position: relative;
-    z-index: 2;
-    margin-bottom: 30px;
-    overflow: hidden;
-    text-overflow: ellipsis;
 
-    small {
-      display: block;
-      font-size: 14px;
-      color: $highlight-text-color;
-      font-weight: 400;
-      overflow: hidden;
-      text-overflow: ellipsis;
-
-      .fa {
-        margin-left: 3px;
+    &:hover,
+    &:active,
+    &:focus {
+      .card__bar {
+        background: lighten($ui-base-color, 8%);
       }
     }
   }
 
-  .avatar {
-    width: 120px;
-    margin: 0 auto;
+  &__img {
+    height: 130px;
     position: relative;
-    z-index: 2;
+    background: darken($ui-base-color, 12%);
+    border-radius: 4px 4px 0 0;
 
     img {
-      width: 120px;
-      height: 120px;
-      display: block;
-      border-radius: 120px;
-      box-shadow: 0 0 15px rgba($base-shadow-color, 0.2);
-    }
-  }
-
-  .roles {
-    margin-bottom: 30px;
-    padding: 0 15px;
-  }
-
-  .details-counters {
-    margin-top: 30px;
-    display: flex;
-    flex-direction: row;
-    width: 100%;
-  }
-
-  .counter {
-    width: 33.3%;
-    box-sizing: border-box;
-    flex: 0 0 auto;
-    color: $darker-text-color;
-    padding: 5px 10px 0;
-    margin-bottom: 10px;
-    border-right: 1px solid lighten($ui-base-color, 4%);
-    cursor: default;
-    text-align: center;
-    position: relative;
-
-    a {
-      display: block;
-    }
-
-    &:last-child {
-      border-right: 0;
-    }
-
-    &::after {
       display: block;
-      content: "";
-      position: absolute;
-      bottom: -10px;
-      left: 0;
       width: 100%;
-      border-bottom: 4px solid $ui-primary-color;
-      opacity: 0.5;
-      transition: all 400ms ease;
-    }
-
-    &.active {
-      &::after {
-        border-bottom: 4px solid $highlight-text-color;
-        opacity: 1;
-      }
-    }
-
-    &:hover {
-      &::after {
-        opacity: 1;
-        transition-duration: 100ms;
-      }
+      height: 100%;
+      margin: 0;
+      object-fit: cover;
+      border-radius: 4px 4px 0 0;
     }
 
-    a {
-      text-decoration: none;
-      color: inherit;
+    @media screen and (max-width: 600px) {
+      height: 200px;
     }
 
-    .counter-label {
-      font-size: 12px;
-      display: block;
-      margin-bottom: 5px;
-    }
-
-    .counter-number {
-      font-weight: 500;
-      font-size: 18px;
-      color: $primary-text-color;
-      font-family: 'mastodon-font-display', sans-serif;
+    @media screen and (max-width: $no-gap-breakpoint) {
+      display: none;
     }
   }
 
-  .bio {
-    font-size: 14px;
-    line-height: 18px;
-    padding: 0 15px;
-    color: $secondary-text-color;
-  }
-
-  @media screen and (max-width: 480px) {
-    display: block;
+  &__bar {
+    position: relative;
+    padding: 15px;
+    display: flex;
+    justify-content: flex-start;
+    align-items: center;
+    background: lighten($ui-base-color, 4%);
+    border-radius: 0 0 4px 4px;
 
-    .card__bio {
-      max-width: none;
+    @media screen and (max-width: $no-gap-breakpoint) {
+      border-radius: 0;
     }
 
-    .name,
-    .roles {
-      text-align: center;
-      margin-bottom: 15px;
-    }
+    .avatar {
+      flex: 0 0 auto;
+      width: 48px;
+      height: 48px;
+      padding-top: 2px;
 
-    .bio {
-      margin-bottom: 15px;
+      img {
+        width: 100%;
+        height: 100%;
+        display: block;
+        margin: 0;
+        border-radius: 4px;
+        background: darken($ui-base-color, 8%);
+      }
     }
-  }
-}
 
-.card,
-.account-grid-card {
-  .controls {
-    position: absolute;
-    top: 15px;
-    left: 15px;
-    z-index: 2;
-
-    .icon-button {
-      color: rgba($white, 0.8);
-      text-decoration: none;
-      font-size: 13px;
-      line-height: 13px;
-      font-weight: 500;
-
-      .fa {
-        font-weight: 400;
-        margin-right: 5px;
+    .display-name {
+      margin-left: 15px;
+      text-align: left;
+
+      strong {
+        font-size: 15px;
+        color: $primary-text-color;
+        font-weight: 500;
+        overflow: hidden;
+        text-overflow: ellipsis;
       }
 
-      &:hover,
-      &:active,
-      &:focus {
-        color: $white;
+      span {
+        display: block;
+        font-size: 14px;
+        color: $darker-text-color;
+        font-weight: 400;
+        overflow: hidden;
+        text-overflow: ellipsis;
       }
     }
   }
 }
 
-.account-grid-card .controls {
-  left: auto;
-  right: 15px;
-}
-
 .pagination {
   padding: 30px 0;
   text-align: center;
@@ -314,289 +171,23 @@
   }
 }
 
-.accounts-grid {
-  box-shadow: 0 0 15px rgba($base-shadow-color, 0.2);
-  background: darken($simple-background-color, 8%);
-  border-radius: 0 0 4px 4px;
-  padding: 20px 5px;
-  padding-bottom: 10px;
-  overflow: hidden;
-  display: flex;
-  flex-wrap: wrap;
-  z-index: 2;
-  position: relative;
-
-  &.empty img {
-    position: absolute;
-    opacity: 0.2;
-    height: 200px;
-    left: 0;
-    bottom: 0;
-    pointer-events: none;
-  }
-
-  @media screen and (max-width: 740px) {
-    border-radius: 0;
-    box-shadow: none;
-  }
-
-  .account-grid-card {
-    box-sizing: border-box;
-    width: 335px;
-    background: $simple-background-color;
-    border-radius: 4px;
-    color: $inverted-text-color;
-    margin: 0 5px 10px;
-    position: relative;
-
-    @media screen and (max-width: 740px) {
-      width: calc(100% - 10px);
-    }
-
-    .account-grid-card__header {
-      overflow: hidden;
-      height: 100px;
-      border-radius: 4px 4px 0 0;
-      background-color: lighten($inverted-text-color, 4%);
-      background-size: cover;
-      background-position: center;
-      position: relative;
-
-      &::after {
-        background: rgba(darken($ui-base-color, 8%), 0.5);
-        display: block;
-        content: "";
-        position: absolute;
-        left: 0;
-        top: 0;
-        width: 100%;
-        height: 100%;
-        z-index: 1;
-      }
-    }
-
-    .account-grid-card__avatar {
-      box-sizing: border-box;
-      padding: 15px;
-      position: absolute;
-      z-index: 2;
-      top: 100px - (40px + 2px);
-      left: -2px;
-    }
-
-    .avatar {
-      width: 80px;
-      height: 80px;
-
-      img {
-        display: block;
-        width: 80px;
-        height: 80px;
-        border-radius: 80px;
-        border: 2px solid $simple-background-color;
-        background: $simple-background-color;
-      }
-    }
-
-    .name {
-      padding: 15px;
-      padding-top: 10px;
-      padding-left: 15px + 80px + 15px;
-
-      a {
-        display: block;
-        color: $inverted-text-color;
-        text-decoration: none;
-        text-overflow: ellipsis;
-        overflow: hidden;
-        font-weight: 500;
-
-        &:hover {
-          .display_name {
-            text-decoration: underline;
-          }
-        }
-      }
-    }
-
-    .display_name {
-      font-size: 16px;
-      display: block;
-      text-overflow: ellipsis;
-      overflow: hidden;
-    }
-
-    .username {
-      color: $lighter-text-color;
-      font-size: 14px;
-      font-weight: 400;
-    }
-
-    .account__header__content {
-      padding: 10px 15px;
-      padding-top: 15px;
-      color: $lighter-text-color;
-      word-wrap: break-word;
-      overflow: hidden;
-      text-overflow: ellipsis;
-      height: 5.5em;
-      position: relative;
-
-      &::after {
-        display: block;
-        content: "";
-        width: 100%;
-        height: 100px;
-        position: absolute;
-        bottom: 0;
-        background: linear-gradient(to bottom, rgba($simple-background-color, 0.01) 0%, rgba($simple-background-color, 1) 100%);
-        left: 0;
-        border-radius: 0 0 4px 4px;
-        pointer-events: none;
-      }
-    }
-  }
-}
-
 .nothing-here {
-  width: 100%;
-  display: block;
+  background: $ui-base-color;
+  box-shadow: 0 0 15px rgba($base-shadow-color, 0.2);
   color: $light-text-color;
   font-size: 14px;
   font-weight: 500;
   text-align: center;
-  padding: 130px 0;
-  padding-top: 125px;
-  margin: 0 auto;
+  display: flex;
+  justify-content: center;
+  align-items: center;
   cursor: default;
-}
-
-.account-card {
   border-radius: 4px;
-  text-align: left;
-  box-shadow: 0 0 15px rgba($base-shadow-color, 0.2);
-  background: $simple-background-color;
-
-  &__header {
-    background: $base-shadow-color;
-    background-size: cover;
-    background-position: center center;
-    height: 90px;
-    border-radius: 4px 4px 0 0;
-  }
+  padding: 20px;
+  min-height: 30vh;
 
-  & > .detailed-status__display-name {
-    display: block;
-    overflow: hidden;
-    display: flex;
-    align-items: center;
-    padding: 10px;
-
-    &:last-child {
-      margin-bottom: 0;
-    }
-
-    & > div:first-child {
-      flex: 0 0 auto;
-      margin-right: 10px;
-      width: 48px;
-      height: 48px;
-    }
-
-    .avatar {
-      display: block;
-      border-radius: 4px;
-      margin: 0;
-    }
-
-    .display-name {
-      flex: 1 0 auto;
-      display: block;
-      max-width: 100%;
-      overflow: hidden;
-      white-space: nowrap;
-      text-overflow: ellipsis;
-      cursor: default;
-
-      & > .detailed-status__display-name {
-        margin-bottom: 0;
-      }
-
-      strong {
-        font-weight: 500;
-        color: $ui-base-color;
-
-        @each $lang in $cjk-langs {
-          &:lang(#{$lang}) {
-            font-weight: 700;
-          }
-        }
-      }
-
-      span {
-        font-size: 14px;
-        color: $light-text-color;
-      }
-    }
-
-    &:hover {
-      .display-name {
-        strong {
-          text-decoration: none;
-        }
-      }
-    }
-  }
-
-  .counter {
-    box-sizing: border-box;
-    flex: 0 0 auto;
-    color: $light-text-color;
-    padding: 0 10px;
-    cursor: default;
-    text-align: center;
-    position: relative;
-    line-height: 24px;
-
-    .counter-label {
-      font-size: 12px;
-      display: block;
-      text-transform: uppercase;
-    }
-
-    .counter-number {
-      font-weight: 500;
-      font-size: 16px;
-      color: $inverted-text-color;
-      font-family: 'mastodon-font-display', sans-serif;
-    }
-  }
-}
-
-.activity-stream-tabs {
-  background: $simple-background-color;
-  border-bottom: 1px solid $ui-secondary-color;
-  position: relative;
-  z-index: 2;
-
-  a {
-    display: inline-block;
-    padding: 15px;
-    text-decoration: none;
-    color: $highlight-text-color;
-    text-transform: uppercase;
-    font-weight: 500;
-
-    &:hover,
-    &:active,
-    &:focus {
-      color: lighten($highlight-text-color, 8%);
-    }
-
-    &.active {
-      color: $inverted-text-color;
-      cursor: default;
-    }
+  &--under-tabs {
+    border-radius: 0 0 4px 4px;
   }
 }
 
@@ -629,14 +220,14 @@
   padding: 0;
   margin: 15px -15px -15px;
   border: 0 none;
-  border-top: 1px solid lighten($ui-base-color, 4%);
-  border-bottom: 1px solid lighten($ui-base-color, 4%);
+  border-top: 1px solid lighten($ui-base-color, 12%);
+  border-bottom: 1px solid lighten($ui-base-color, 12%);
   font-size: 14px;
   line-height: 20px;
 
   dl {
     display: flex;
-    border-bottom: 1px solid lighten($ui-base-color, 4%);
+    border-bottom: 1px solid lighten($ui-base-color, 12%);
   }
 
   dt,
diff --git a/app/javascript/styles/mastodon/basics.scss b/app/javascript/styles/mastodon/basics.scss
index c52e069be..7a6a1c490 100644
--- a/app/javascript/styles/mastodon/basics.scss
+++ b/app/javascript/styles/mastodon/basics.scss
@@ -1,13 +1,10 @@
 body {
   font-family: 'mastodon-font-sans-serif', sans-serif;
-  background: $ui-base-color;
-  background-size: cover;
-  background-attachment: fixed;
+  background: darken($ui-base-color, 8%);
   font-size: 13px;
   line-height: 18px;
   font-weight: 400;
   color: $primary-text-color;
-  padding-bottom: 20px;
   text-rendering: optimizelegibility;
   font-feature-settings: "kern";
   text-size-adjust: none;
@@ -35,16 +32,24 @@ body {
     height: 100%;
     padding: 0;
     background: $ui-base-color;
+
+    &.with-modals--active {
+      overflow-y: hidden;
+    }
   }
 
-  &.about-body {
-    background: darken($ui-base-color, 8%);
-    padding-bottom: 0;
+  &.lighter {
+    background: $ui-base-color;
   }
 
-  &.tag-body {
-    background: darken($ui-base-color, 8%);
-    padding-bottom: 0;
+  &.with-modals {
+    overflow-x: hidden;
+    overflow-y: scroll;
+
+    &--active {
+      overflow-y: hidden;
+      margin-right: 13px;
+    }
   }
 
   &.player {
@@ -52,7 +57,7 @@ body {
   }
 
   &.embed {
-    background: transparent;
+    background: lighten($ui-base-color, 4%);
     margin: 0;
     padding-bottom: 0;
 
diff --git a/app/javascript/styles/mastodon/components.scss b/app/javascript/styles/mastodon/components.scss
index 48460d760..8067b80bb 100644
--- a/app/javascript/styles/mastodon/components.scss
+++ b/app/javascript/styles/mastodon/components.scss
@@ -946,6 +946,18 @@
   background: lighten($ui-base-color, 4%);
   padding: 14px 10px;
 
+  &--flex {
+    display: flex;
+    flex-wrap: wrap;
+    justify-content: space-between;
+    align-items: flex-start;
+
+    .status__content,
+    .detailed-status__meta {
+      flex: 100%;
+    }
+  }
+
   .status__content {
     font-size: 19px;
     line-height: 24px;
@@ -1224,7 +1236,6 @@ a .account__avatar {
 }
 
 .account__action-bar-dropdown {
-  flex: 0 1 calc(50% - 140px);
   padding: 10px;
 
   .icon-button {
@@ -1256,9 +1267,9 @@ a .account__avatar {
 .account__action-bar__tab {
   text-decoration: none;
   overflow: hidden;
-  flex: 0 1 80px;
+  flex: 0 1 100%;
   border-right: 1px solid lighten($ui-base-color, 8%);
-  padding: 10px 5px;
+  padding: 10px 0;
 
   & > span {
     display: block;
diff --git a/app/javascript/styles/mastodon/containers.scss b/app/javascript/styles/mastodon/containers.scss
index ac648c868..7b339277f 100644
--- a/app/javascript/styles/mastodon/containers.scss
+++ b/app/javascript/styles/mastodon/containers.scss
@@ -60,10 +60,6 @@
   }
 }
 
-.media-standalone__body {
-  overflow: hidden;
-}
-
 .account-header {
   width: 400px;
   margin: 0 auto;
@@ -118,3 +114,576 @@
     margin-left: 8px;
   }
 }
+
+.public-layout {
+  @media screen and (max-width: $no-gap-breakpoint) {
+    padding-top: 48px;
+  }
+
+  .container {
+    max-width: 960px;
+
+    @media screen and (max-width: $no-gap-breakpoint) {
+      padding: 0;
+    }
+  }
+
+  .header {
+    background: lighten($ui-base-color, 8%);
+    box-shadow: 0 0 15px rgba($base-shadow-color, 0.2);
+    border-radius: 4px;
+    height: 48px;
+    margin: 10px 0;
+    display: flex;
+    align-items: stretch;
+    justify-content: center;
+    flex-wrap: nowrap;
+    overflow: hidden;
+
+    @media screen and (max-width: $no-gap-breakpoint) {
+      position: fixed;
+      width: 100%;
+      top: 0;
+      left: 0;
+      margin: 0;
+      border-radius: 0;
+      box-shadow: none;
+      z-index: 110;
+    }
+
+    & > div {
+      flex: 1 1 33.3%;
+      min-height: 1px;
+    }
+
+    .nav-left {
+      display: flex;
+      align-items: stretch;
+      justify-content: flex-start;
+      flex-wrap: nowrap;
+    }
+
+    .nav-center {
+      display: flex;
+      align-items: stretch;
+      justify-content: center;
+      flex-wrap: nowrap;
+    }
+
+    .nav-right {
+      display: flex;
+      align-items: stretch;
+      justify-content: flex-end;
+      flex-wrap: nowrap;
+    }
+
+    .brand {
+      display: block;
+      padding: 15px;
+
+      img {
+        display: block;
+        height: 18px;
+        width: auto;
+        position: relative;
+        bottom: -2px;
+
+        @media screen and (max-width: $no-gap-breakpoint) {
+          height: 20px;
+        }
+      }
+
+      &:hover,
+      &:focus,
+      &:active {
+        background: lighten($ui-base-color, 12%);
+      }
+    }
+
+    .nav-link {
+      display: flex;
+      align-items: center;
+      padding: 0 1rem;
+      font-size: 12px;
+      font-weight: 500;
+      text-decoration: none;
+      color: $darker-text-color;
+      white-space: nowrap;
+      text-align: center;
+
+      &:hover,
+      &:focus,
+      &:active {
+        text-decoration: underline;
+        color: $primary-text-color;
+      }
+    }
+
+    .nav-button {
+      background: lighten($ui-base-color, 16%);
+      margin: 8px;
+      margin-left: 0;
+      border-radius: 4px;
+
+      &:hover,
+      &:focus,
+      &:active {
+        text-decoration: none;
+        background: lighten($ui-base-color, 20%);
+      }
+    }
+  }
+
+  $no-columns-breakpoint: 600px;
+
+  .grid {
+    display: grid;
+    grid-gap: 10px;
+    grid-template-columns: minmax(300px, 3fr) minmax(298px, 1fr);
+    grid-auto-columns: 25%;
+    grid-auto-rows: max-content;
+
+    .column-0 {
+      grid-row: 1;
+      grid-column: 1;
+    }
+
+    .column-1 {
+      grid-row: 1;
+      grid-column: 2;
+    }
+
+    @media screen and (max-width: $no-columns-breakpoint) {
+      grid-template-columns: 100%;
+      grid-gap: 0;
+
+      .column-1 {
+        display: none;
+      }
+    }
+  }
+
+  .public-account-header {
+    overflow: hidden;
+    margin-bottom: 10px;
+    box-shadow: 0 0 15px rgba($base-shadow-color, 0.2);
+
+    &__image {
+      border-radius: 4px 4px 0 0;
+      overflow: hidden;
+      height: 300px;
+      position: relative;
+      background: darken($ui-base-color, 12%);
+
+      &::after {
+        content: "";
+        display: block;
+        position: absolute;
+        width: 100%;
+        height: 100%;
+        box-shadow: inset 0 -1px 1px 1px rgba($base-shadow-color, 0.15);
+        top: 0;
+        left: 0;
+      }
+
+      img {
+        object-fit: cover;
+        display: block;
+        width: 100%;
+        height: 100%;
+        margin: 0;
+        border-radius: 4px 4px 0 0;
+      }
+
+      @media screen and (max-width: 600px) {
+        height: 200px;
+      }
+    }
+
+    @media screen and (max-width: $no-gap-breakpoint) {
+      margin-bottom: 0;
+      box-shadow: none;
+
+      &__image::after {
+        display: none;
+      }
+
+      &__image,
+      &__image img {
+        border-radius: 0;
+      }
+    }
+
+    &__bar {
+      position: relative;
+      margin-top: -80px;
+      display: flex;
+      justify-content: flex-start;
+
+      &::before {
+        content: "";
+        display: block;
+        background: lighten($ui-base-color, 4%);
+        position: absolute;
+        bottom: 0;
+        left: 0;
+        right: 0;
+        height: 60px;
+        border-radius: 0 0 4px 4px;
+        z-index: -1;
+      }
+
+      .avatar {
+        display: block;
+        width: 120px;
+        height: 120px;
+        padding-left: 20px - 4px;
+        flex: 0 0 auto;
+
+        img {
+          display: block;
+          width: 100%;
+          height: 100%;
+          margin: 0;
+          border-radius: 50%;
+          border: 4px solid lighten($ui-base-color, 4%);
+          background: darken($ui-base-color, 8%);
+        }
+      }
+
+      @media screen and (max-width: 600px) {
+        margin-top: 0;
+        background: lighten($ui-base-color, 4%);
+        border-radius: 0 0 4px 4px;
+        padding: 5px;
+
+        &::before {
+          display: none;
+        }
+
+        .avatar {
+          width: 48px;
+          height: 48px;
+          padding: 7px 0;
+          padding-left: 10px;
+
+          img {
+            border: 0;
+            border-radius: 4px;
+          }
+
+          @media screen and (max-width: 360px) {
+            display: none;
+          }
+        }
+      }
+
+      @media screen and (max-width: $no-gap-breakpoint) {
+        border-radius: 0;
+      }
+
+      @media screen and (max-width: $no-columns-breakpoint) {
+        flex-wrap: wrap;
+      }
+    }
+
+    &__tabs {
+      flex: 1 1 auto;
+      margin-left: 20px;
+
+      &__name {
+        padding-top: 20px;
+        padding-bottom: 8px;
+
+        h1 {
+          font-size: 20px;
+          line-height: 18px * 1.5;
+          color: $primary-text-color;
+          font-weight: 500;
+          overflow: hidden;
+          white-space: nowrap;
+          text-overflow: ellipsis;
+          text-shadow: 1px 1px 1px $base-shadow-color;
+
+          small {
+            display: block;
+            font-size: 14px;
+            color: $primary-text-color;
+            font-weight: 400;
+            overflow: hidden;
+            text-overflow: ellipsis;
+          }
+        }
+      }
+
+      @media screen and (max-width: 600px) {
+        margin-left: 15px;
+        display: flex;
+        justify-content: space-between;
+        align-items: center;
+
+        &__name {
+          padding-top: 0;
+          padding-bottom: 0;
+
+          h1 {
+            font-size: 16px;
+            line-height: 24px;
+            text-shadow: none;
+
+            small {
+              color: $darker-text-color;
+            }
+          }
+        }
+      }
+
+      &__tabs {
+        display: flex;
+        justify-content: flex-start;
+        align-items: stretch;
+        height: 58px;
+
+        .details-counters {
+          display: flex;
+          flex-direction: row;
+          min-width: 300px;
+        }
+
+        @media screen and (max-width: $no-columns-breakpoint) {
+          .details-counters {
+            display: none;
+          }
+        }
+
+        .counter {
+          width: 33.3%;
+          box-sizing: border-box;
+          flex: 0 0 auto;
+          color: $darker-text-color;
+          padding: 10px;
+          border-right: 1px solid lighten($ui-base-color, 4%);
+          cursor: default;
+          text-align: center;
+          position: relative;
+
+          a {
+            display: block;
+          }
+
+          &:last-child {
+            border-right: 0;
+          }
+
+          &::after {
+            display: block;
+            content: "";
+            position: absolute;
+            bottom: 0;
+            left: 0;
+            width: 100%;
+            border-bottom: 4px solid $ui-primary-color;
+            opacity: 0.5;
+            transition: all 400ms ease;
+          }
+
+          &.active {
+            &::after {
+              border-bottom: 4px solid $highlight-text-color;
+              opacity: 1;
+            }
+          }
+
+          &:hover {
+            &::after {
+              opacity: 1;
+              transition-duration: 100ms;
+            }
+          }
+
+          a {
+            text-decoration: none;
+            color: inherit;
+          }
+
+          .counter-label {
+            font-size: 12px;
+            display: block;
+          }
+
+          .counter-number {
+            font-weight: 500;
+            font-size: 18px;
+            margin-bottom: 5px;
+            color: $primary-text-color;
+            font-family: 'mastodon-font-display', sans-serif;
+          }
+        }
+
+        .spacer {
+          flex: 1 1 auto;
+          height: 1px;
+        }
+
+        &__buttons {
+          padding: 7px 8px;
+        }
+      }
+    }
+
+    &__extra {
+      display: none;
+      margin-top: 4px;
+
+      .public-account-bio {
+        border-radius: 0;
+        box-shadow: none;
+        background: transparent;
+        margin: 0 -5px;
+
+        .account__header__fields {
+          border-top: 1px solid lighten($ui-base-color, 12%);
+        }
+
+        .roles {
+          display: none;
+        }
+      }
+
+      &__links {
+        margin-top: -15px;
+        font-size: 14px;
+        color: $darker-text-color;
+
+        a {
+          display: inline-block;
+          color: $darker-text-color;
+          text-decoration: none;
+          padding: 15px;
+
+          strong {
+            font-weight: 700;
+            color: $primary-text-color;
+          }
+        }
+      }
+
+      @media screen and (max-width: $no-columns-breakpoint) {
+        display: block;
+        flex: 100%;
+      }
+    }
+  }
+
+  .account__section-headline {
+    border-radius: 4px 4px 0 0;
+
+    @media screen and (max-width: $no-gap-breakpoint) {
+      border-radius: 0;
+    }
+  }
+
+  .detailed-status__meta {
+    margin-top: 25px;
+  }
+
+  .public-account-bio {
+    background: lighten($ui-base-color, 8%);
+    box-shadow: 0 0 15px rgba($base-shadow-color, 0.2);
+    border-radius: 4px;
+    overflow: hidden;
+    margin-bottom: 10px;
+
+    @media screen and (max-width: $no-gap-breakpoint) {
+      box-shadow: none;
+      margin-bottom: 0;
+      border-radius: 0;
+    }
+
+    .account__header__fields {
+      margin: 0;
+      border-top: 0;
+
+      a {
+        color: lighten($ui-highlight-color, 8%);
+      }
+    }
+
+    .account__header__content {
+      padding: 20px;
+      padding-bottom: 0;
+      color: $primary-text-color;
+    }
+
+    &__extra,
+    .roles {
+      padding: 20px;
+      font-size: 14px;
+      color: $darker-text-color;
+    }
+
+    .roles {
+      padding-bottom: 0;
+    }
+  }
+
+  .static-icon-button {
+    color: $action-button-color;
+    font-size: 18px;
+
+    & > span {
+      font-size: 14px;
+      font-weight: 500;
+    }
+  }
+
+  .card-grid {
+    display: flex;
+    flex-wrap: wrap;
+    min-width: 100%;
+    margin: 0 -5px;
+
+    & > div {
+      box-sizing: border-box;
+      flex: 1 0 auto;
+      width: 300px;
+      padding: 0 5px;
+      margin-bottom: 10px;
+      max-width: 33.333%;
+
+      @media screen and (max-width: 900px) {
+        max-width: 50%;
+      }
+
+      @media screen and (max-width: 600px) {
+        max-width: 100%;
+      }
+    }
+
+    @media screen and (max-width: $no-gap-breakpoint) {
+      margin: 0;
+      border-top: 1px solid lighten($ui-base-color, 8%);
+
+      & > div {
+        width: 100%;
+        padding: 0;
+        margin-bottom: 0;
+        border-bottom: 1px solid lighten($ui-base-color, 8%);
+
+        &:last-child {
+          border-bottom: 0;
+        }
+
+        .card__bar {
+          background: $ui-base-color;
+
+          &:hover,
+          &:active,
+          &:focus {
+            background: lighten($ui-base-color, 4%);
+          }
+        }
+      }
+    }
+  }
+}
diff --git a/app/javascript/styles/mastodon/footer.scss b/app/javascript/styles/mastodon/footer.scss
index 81eb1ce2d..4d75477e0 100644
--- a/app/javascript/styles/mastodon/footer.scss
+++ b/app/javascript/styles/mastodon/footer.scss
@@ -1,39 +1,140 @@
-.footer {
-  text-align: center;
-  margin-top: 30px;
-  padding-bottom: 60px;
-  font-size: 12px;
-  color: $darker-text-color;
-
-  .footer__domain {
-    font-weight: 500;
-
-    a {
-      color: inherit;
-      text-decoration: none;
+.public-layout {
+  .footer {
+    text-align: left;
+    padding-top: 20px;
+    padding-bottom: 60px;
+    font-size: 12px;
+    color: lighten($ui-base-color, 34%);
+
+    @media screen and (max-width: $no-gap-breakpoint) {
+      padding-left: 20px;
+      padding-right: 20px;
     }
-  }
 
-  .powered-by,
-  .single-user-login {
-    font-weight: 400;
+    .grid {
+      display: grid;
+      grid-gap: 10px;
+      grid-template-columns: 1fr 1fr 2fr 1fr 1fr;
+
+      .column-0 {
+        grid-column: 1;
+        grid-row: 1;
+        min-width: 0;
+      }
+
+      .column-1 {
+        grid-column: 2;
+        grid-row: 1;
+        min-width: 0;
+      }
+
+      .column-2 {
+        grid-column: 3;
+        grid-row: 1;
+        min-width: 0;
+        text-align: center;
+
+        h4 a {
+          color: lighten($ui-base-color, 34%);
+        }
+      }
+
+      .column-3 {
+        grid-column: 4;
+        grid-row: 1;
+        min-width: 0;
+      }
+
+      .column-4 {
+        grid-column: 5;
+        grid-row: 1;
+        min-width: 0;
+      }
+
+      @media screen and (max-width: 690px) {
+        grid-template-columns: 1fr 2fr 1fr;
+
+        .column-0,
+        .column-1 {
+          grid-column: 1;
+        }
+
+        .column-1 {
+          grid-row: 2;
+        }
+
+        .column-2 {
+          grid-column: 2;
+        }
 
-    a {
-      color: inherit;
-      text-decoration: underline;
-      font-weight: 500;
+        .column-3,
+        .column-4 {
+          grid-column: 3;
+        }
 
-      &:hover {
+        .column-4 {
+          grid-row: 2;
+        }
+      }
+
+      @media screen and (max-width: 600px) {
+        .column-1 {
+          display: block;
+        }
+      }
+
+      @media screen and (max-width: $no-gap-breakpoint) {
+        .column-0,
+        .column-1,
+        .column-3,
+        .column-4 {
+          display: none;
+        }
+      }
+    }
+
+    h4 {
+      text-transform: uppercase;
+      font-weight: 700;
+      margin-bottom: 8px;
+      color: $darker-text-color;
+
+      a {
+        color: inherit;
         text-decoration: none;
       }
     }
 
-    img {
-      margin: 0 4px;
-      position: relative;
-      bottom: -1px;
-      height: 18px;
-      vertical-align: top;
+    ul a {
+      text-decoration: none;
+      color: lighten($ui-base-color, 34%);
+
+      &:hover,
+      &:active,
+      &:focus {
+        text-decoration: underline;
+      }
+    }
+
+    .brand {
+      svg {
+        display: block;
+        height: 36px;
+        width: auto;
+        margin: 0 auto;
+
+        path {
+          fill: lighten($ui-base-color, 34%);
+        }
+      }
+
+      &:hover,
+      &:focus,
+      &:active {
+        svg path {
+          fill: lighten($ui-base-color, 38%);
+        }
+      }
     }
   }
 }
diff --git a/app/javascript/styles/mastodon/landing_strip.scss b/app/javascript/styles/mastodon/landing_strip.scss
deleted file mode 100644
index 86614b89b..000000000
--- a/app/javascript/styles/mastodon/landing_strip.scss
+++ /dev/null
@@ -1,111 +0,0 @@
-.landing-strip,
-.memoriam-strip {
-  background: rgba(darken($ui-base-color, 7%), 0.8);
-  color: $darker-text-color;
-  font-weight: 400;
-  padding: 14px;
-  border-radius: 4px;
-  margin-bottom: 20px;
-  display: flex;
-  align-items: center;
-
-  strong,
-  a {
-    font-weight: 500;
-
-    @each $lang in $cjk-langs {
-      &:lang(#{$lang}) {
-        font-weight: 700;
-      }
-    }
-  }
-
-  a {
-    color: inherit;
-    text-decoration: underline;
-  }
-
-  .logo {
-    width: 30px;
-    height: 30px;
-    flex: 0 0 auto;
-    margin-right: 15px;
-  }
-
-  @media screen and (max-width: 740px) {
-    margin-bottom: 0;
-  }
-}
-
-.memoriam-strip {
-  background: rgba($base-shadow-color, 0.7);
-}
-
-.moved-strip {
-  padding: 14px;
-  border-radius: 4px;
-  background: rgba(darken($ui-base-color, 7%), 0.8);
-  color: $secondary-text-color;
-  font-weight: 400;
-  margin-bottom: 20px;
-
-  strong,
-  a {
-    font-weight: 500;
-
-    @each $lang in $cjk-langs {
-      &:lang(#{$lang}) {
-        font-weight: 700;
-      }
-    }
-  }
-
-  a {
-    color: inherit;
-    text-decoration: underline;
-
-    &.mention {
-      text-decoration: none;
-
-      span {
-        text-decoration: none;
-      }
-
-      &:focus,
-      &:hover,
-      &:active {
-        text-decoration: none;
-
-        span {
-          text-decoration: underline;
-        }
-      }
-    }
-  }
-
-  &__message {
-    margin-bottom: 15px;
-
-    .fa {
-      margin-right: 5px;
-      color: $darker-text-color;
-    }
-  }
-
-  &__card {
-    .detailed-status__display-avatar {
-      position: relative;
-      cursor: pointer;
-    }
-
-    .detailed-status__display-name {
-      margin-bottom: 0;
-      text-decoration: none;
-
-      span {
-        color: $highlight-text-color;
-        font-weight: 400;
-      }
-    }
-  }
-}
diff --git a/app/javascript/styles/mastodon/stream_entries.scss b/app/javascript/styles/mastodon/stream_entries.scss
index f4d6e237f..9e2aa720c 100644
--- a/app/javascript/styles/mastodon/stream_entries.scss
+++ b/app/javascript/styles/mastodon/stream_entries.scss
@@ -1,367 +1,145 @@
 .activity-stream {
-  clear: both;
   box-shadow: 0 0 15px rgba($base-shadow-color, 0.2);
+  border-radius: 4px;
+  overflow: hidden;
+  margin-bottom: 10px;
+
+  @media screen and (max-width: $no-gap-breakpoint) {
+    margin-bottom: 0;
+    border-radius: 0;
+    box-shadow: none;
+  }
+
+  &--headless {
+    border-radius: 0;
+    margin: 0;
+    box-shadow: none;
+
+    .detailed-status,
+    .status {
+      border-radius: 0 !important;
+    }
+  }
 
   div[data-component] {
     width: 100%;
   }
 
   .entry {
-    background: $simple-background-color;
+    background: $ui-base-color;
 
-    .detailed-status.light,
-    .status.light,
-    .more.light {
-      border-bottom: 1px solid $ui-secondary-color;
+    .detailed-status,
+    .status,
+    .load-more {
       animation: none;
     }
 
     &:last-child {
-      &,
-      .detailed-status.light,
-      .status.light {
+      .detailed-status,
+      .status {
         border-bottom: 0;
         border-radius: 0 0 4px 4px;
       }
     }
 
     &:first-child {
-      &,
-      .detailed-status.light,
-      .status.light {
+      .detailed-status,
+      .status {
         border-radius: 4px 4px 0 0;
       }
 
       &:last-child {
-        &,
-        .detailed-status.light,
-        .status.light {
+        .detailed-status,
+        .status {
           border-radius: 4px;
         }
       }
     }
 
     @media screen and (max-width: 740px) {
-      &,
-      .detailed-status.light,
-      .status.light {
+      .detailed-status,
+      .status {
         border-radius: 0 !important;
       }
     }
   }
+}
 
-  &.with-header {
-    .entry {
-      &:first-child {
-        &,
-        .detailed-status.light,
-        .status.light {
-          border-radius: 0;
-        }
-
-        &:last-child {
-          &,
-          .detailed-status.light,
-          .status.light {
-            border-radius: 0 0 4px 4px;
-          }
-        }
-      }
-    }
-  }
-
-  .media-gallery__gifv__label {
-    bottom: 9px;
-  }
-
-  .status.light {
-    padding: 14px 14px 14px (48px + 14px * 2);
-    position: relative;
-    min-height: 48px;
-    cursor: default;
-
-    .status__header {
-      font-size: 15px;
-
-      .status__meta {
-        float: right;
-        font-size: 14px;
-
-        .status__relative-time {
-          color: $lighter-text-color;
-        }
-      }
-    }
-
-    .status__display-name {
-      display: block;
-      max-width: 100%;
-      padding-right: 25px;
-      color: $inverted-text-color;
-    }
-
-    .status__avatar {
-      position: absolute;
-      left: 14px;
-      top: 14px;
-      width: 48px;
-      height: 48px;
-
-      & > div {
-        width: 48px;
-        height: 48px;
-      }
-
-      img {
-        display: block;
-        border-radius: 4px;
-      }
-    }
-
-    .display-name {
-      display: block;
-      max-width: 100%;
-      overflow: hidden;
-      white-space: nowrap;
-      text-overflow: ellipsis;
-
-      strong {
-        font-weight: 500;
-        color: $inverted-text-color;
-
-        @each $lang in $cjk-langs {
-          &:lang(#{$lang}) {
-            font-weight: 700;
-          }
-        }
-      }
-
-      span {
-        font-size: 14px;
-        color: $light-text-color;
-      }
-    }
-
-    .status__content {
-      color: $inverted-text-color;
-
-      a {
-        color: $highlight-text-color;
-      }
-
-      a.status__content__spoiler-link {
-        color: $primary-text-color;
-        background: $ui-base-color;
-
-        &:hover {
-          background: lighten($ui-base-color, 8%);
-        }
-      }
-    }
-  }
-
-  .detailed-status.light {
-    padding: 14px;
-    background: $simple-background-color;
-    cursor: default;
-
-    .detailed-status__display-name {
-      display: block;
-      overflow: hidden;
-      margin-bottom: 15px;
-
-      & > div {
-        float: left;
-        margin-right: 10px;
-      }
-
-      .display-name {
-        display: block;
-        max-width: 100%;
-        overflow: hidden;
-        white-space: nowrap;
-        text-overflow: ellipsis;
-
-        strong {
-          font-weight: 500;
-          color: $inverted-text-color;
-
-          @each $lang in $cjk-langs {
-            &:lang(#{$lang}) {
-              font-weight: 700;
-            }
-          }
-        }
-
-        span {
-          font-size: 14px;
-          color: $light-text-color;
-        }
-      }
-    }
-
-    .avatar {
-      width: 48px;
-      height: 48px;
-
-      img {
-        display: block;
-        border-radius: 4px;
-      }
-    }
-
-    .status__content {
-      color: $inverted-text-color;
-
-      a {
-        color: $highlight-text-color;
-      }
-
-      a.status__content__spoiler-link {
-        color: $primary-text-color;
-        background: $ui-base-color;
-
-        &:hover {
-          background: lighten($ui-base-color, 8%);
-        }
-      }
-    }
-
-    .detailed-status__meta {
-      margin-top: 15px;
-      color: $light-text-color;
-      font-size: 14px;
-      line-height: 18px;
-
-      a {
-        color: inherit;
-      }
-
-      span > span {
-        font-weight: 500;
-        font-size: 12px;
-        margin-left: 6px;
-        display: inline-block;
-      }
-    }
-
-    .status-card {
-      border-color: lighten($ui-secondary-color, 4%);
-      color: $lighter-text-color;
-
-      &:hover {
-        background: lighten($ui-secondary-color, 4%);
-      }
-    }
-
-    .status-card__title,
-    .status-card__description {
-      color: $inverted-text-color;
-    }
-
-    .status-card__image {
-      background: $ui-secondary-color;
-    }
-  }
-
-  .media-spoiler {
-    background: $ui-base-color;
-    color: $darker-text-color;
-  }
+.button.logo-button {
+  flex: 0 auto;
+  font-size: 14px;
+  background: $ui-highlight-color;
+  color: $primary-text-color;
+  text-transform: none;
+  line-height: 36px;
+  height: auto;
+  padding: 3px 15px;
+  border: 0;
 
-  .pre-header {
-    padding: 14px 0;
-    padding-left: (48px + 14px * 2);
-    padding-bottom: 0;
-    margin-bottom: -4px;
-    color: $light-text-color;
-    font-size: 14px;
-    position: relative;
+  svg {
+    width: 20px;
+    height: auto;
+    vertical-align: middle;
+    margin-right: 5px;
 
-    .pre-header__icon {
-      position: absolute;
-      left: (48px + 14px * 2 - 30px);
+    path:first-child {
+      fill: $primary-text-color;
     }
 
-    .status__display-name.muted strong {
-      color: $light-text-color;
+    path:last-child {
+      fill: $ui-highlight-color;
     }
   }
 
-  .open-in-web-link {
-    text-decoration: none;
+  &:active,
+  &:focus,
+  &:hover {
+    background: lighten($ui-highlight-color, 10%);
 
-    &:hover {
-      text-decoration: underline;
+    svg path:last-child {
+      fill: lighten($ui-highlight-color, 10%);
     }
   }
 
-  .more {
-    color: $darker-text-color;
-    display: block;
-    padding: 14px;
-    text-align: center;
-
-    &:not(:hover) {
-      text-decoration: none;
+  @media screen and (max-width: $no-gap-breakpoint) {
+    svg {
+      display: none;
     }
   }
 }
 
-.embed {
-  .activity-stream {
-    box-shadow: none;
+.embed,
+.public-layout {
+  .detailed-status {
+    padding: 15px;
   }
-}
 
-.entry {
-  .detailed-status.light {
-    display: flex;
-    flex-wrap: wrap;
-    justify-content: space-between;
-    align-items: flex-start;
+  .status {
+    padding: 15px 15px 15px (48px + 15px * 2);
+    min-height: 48px + 2px;
 
-    .detailed-status__display-name {
-      flex: 1;
-      margin: 0 5px 15px 0;
+    &__avatar {
+      left: 15px;
+      top: 17px;
     }
 
-    .button.button-secondary.logo-button {
-      flex: 0 auto;
-      font-size: 14px;
-      background: $ui-highlight-color;
-      color: $primary-text-color;
-      border: 0;
-
-      svg {
-        width: 20px;
-        height: auto;
-        vertical-align: middle;
-        margin-right: 5px;
-
-        path:first-child {
-          fill: $primary-text-color;
-        }
-
-        path:last-child {
-          fill: $ui-highlight-color;
-        }
-      }
+    &__content {
+      padding-top: 5px;
+    }
 
-      &:active,
-      &:focus,
-      &:hover {
-        background: lighten($ui-highlight-color, 10%);
+    &__prepend {
+      margin-left: 48px + 15px * 2;
+      padding-top: 15px;
+    }
 
-        svg path:last-child {
-          fill: lighten($ui-highlight-color, 10%);
-        }
-      }
+    &__prepend-icon-wrapper {
+      left: -32px;
     }
 
-    .status__content,
-    .detailed-status__meta {
-      flex: 100%;
+    .media-gallery,
+    &__action-bar,
+    .video-player {
+      margin-top: 10px;
     }
   }
 }
diff --git a/app/javascript/styles/mastodon/variables.scss b/app/javascript/styles/mastodon/variables.scss
index 40aeb4afc..009f0a3c9 100644
--- a/app/javascript/styles/mastodon/variables.scss
+++ b/app/javascript/styles/mastodon/variables.scss
@@ -46,3 +46,5 @@ $cjk-langs: ja, ko, zh-CN, zh-HK, zh-TW;
 $media-modal-media-max-width: 100%;
 // put margins on top and bottom of image to avoid the screen covered by image.
 $media-modal-media-max-height: 80%;
+
+$no-gap-breakpoint: 415px;
diff --git a/app/javascript/styles/mastodon/widgets.scss b/app/javascript/styles/mastodon/widgets.scss
new file mode 100644
index 000000000..d37a6f458
--- /dev/null
+++ b/app/javascript/styles/mastodon/widgets.scss
@@ -0,0 +1,161 @@
+.hero-widget {
+  margin-bottom: 10px;
+  box-shadow: 0 0 15px rgba($base-shadow-color, 0.2);
+
+  &__img {
+    width: 100%;
+    height: 167px;
+    position: relative;
+    overflow: hidden;
+    border-radius: 4px 4px 0 0;
+    background: $base-shadow-color;
+
+    img {
+      object-fit: cover;
+      display: block;
+      width: 100%;
+      height: 100%;
+      margin: 0;
+      border-radius: 4px 4px 0 0;
+    }
+  }
+
+  &__text {
+    background: $ui-base-color;
+    padding: 20px;
+    border-radius: 0 0 4px 4px;
+    font-size: 15px;
+    color: $darker-text-color;
+    line-height: 20px;
+    word-wrap: break-word;
+    font-weight: 400;
+
+    .emojione {
+      width: 20px;
+      height: 20px;
+      margin: -3px 0 0;
+    }
+
+    p {
+      margin-bottom: 20px;
+
+      &:last-child {
+        margin-bottom: 0;
+      }
+    }
+
+    em {
+      display: inline;
+      margin: 0;
+      padding: 0;
+      font-weight: 700;
+      background: transparent;
+      font-family: inherit;
+      font-size: inherit;
+      line-height: inherit;
+      color: lighten($darker-text-color, 10%);
+    }
+
+    a {
+      color: $secondary-text-color;
+      text-decoration: none;
+
+      &:hover {
+        text-decoration: underline;
+      }
+    }
+  }
+
+  @media screen and (max-width: $no-gap-breakpoint) {
+    display: none;
+  }
+}
+
+.moved-account-widget {
+  padding: 15px;
+  padding-bottom: 20px;
+  border-radius: 4px;
+  background: $ui-base-color;
+  box-shadow: 0 0 15px rgba($base-shadow-color, 0.2);
+  color: $secondary-text-color;
+  font-weight: 400;
+  margin-bottom: 10px;
+
+  strong,
+  a {
+    font-weight: 500;
+
+    @each $lang in $cjk-langs {
+      &:lang(#{$lang}) {
+        font-weight: 700;
+      }
+    }
+  }
+
+  a {
+    color: inherit;
+    text-decoration: underline;
+
+    &.mention {
+      text-decoration: none;
+
+      span {
+        text-decoration: none;
+      }
+
+      &:focus,
+      &:hover,
+      &:active {
+        text-decoration: none;
+
+        span {
+          text-decoration: underline;
+        }
+      }
+    }
+  }
+
+  &__message {
+    margin-bottom: 15px;
+
+    .fa {
+      margin-right: 5px;
+      color: $darker-text-color;
+    }
+  }
+
+  &__card {
+    .detailed-status__display-avatar {
+      position: relative;
+      cursor: pointer;
+    }
+
+    .detailed-status__display-name {
+      margin-bottom: 0;
+      text-decoration: none;
+
+      span {
+        font-weight: 400;
+      }
+    }
+  }
+}
+
+.memoriam-widget {
+  padding: 20px;
+  border-radius: 4px;
+  background: $base-shadow-color;
+  box-shadow: 0 0 15px rgba($base-shadow-color, 0.2);
+  font-size: 14px;
+  color: $darker-text-color;
+  margin-bottom: 10px;
+}
+
+.moved-account-widget,
+.memoriam-widget {
+  @media screen and (max-width: $no-gap-breakpoint) {
+    margin-bottom: 0;
+    box-shadow: none;
+    border-radius: 0;
+  }
+}
diff --git a/app/lib/activitypub/adapter.rb b/app/lib/activitypub/adapter.rb
index e880499f1..d35cae889 100644
--- a/app/lib/activitypub/adapter.rb
+++ b/app/lib/activitypub/adapter.rb
@@ -9,7 +9,7 @@ class ActivityPub::Adapter < ActiveModelSerializers::Adapter::Base
       {
         'manuallyApprovesFollowers' => 'as:manuallyApprovesFollowers',
         'sensitive'                 => 'as:sensitive',
-        'movedTo'                   => 'as:movedTo',
+        'movedTo'                   => { '@id' => 'as:movedTo', '@type' => '@id' },
         'Hashtag'                   => 'as:Hashtag',
         'ostatus'                   => 'http://ostatus.org#',
         'atomUri'                   => 'ostatus:atomUri',
@@ -18,7 +18,7 @@ class ActivityPub::Adapter < ActiveModelSerializers::Adapter::Base
         'toot'                      => 'http://joinmastodon.org/ns#',
         'Emoji'                     => 'toot:Emoji',
         'focalPoint'                => { '@container' => '@list', '@id' => 'toot:focalPoint' },
-        'featured'                  => 'toot:featured',
+        'featured'                  => { '@id' => 'toot:featured', '@type' => '@id' },
         'schema'                    => 'http://schema.org#',
         'PropertyValue'             => 'schema:PropertyValue',
         'value'                     => 'schema:value',
diff --git a/app/models/account.rb b/app/models/account.rb
index 4abcd438a..041eda6f4 100644
--- a/app/models/account.rb
+++ b/app/models/account.rb
@@ -70,6 +70,7 @@ class Account < ApplicationRecord
 
   # Remote user validations
   validates :username, uniqueness: { scope: :domain, case_sensitive: true }, if: -> { !local? && will_save_change_to_username? }
+  validates :username, format: { with: /\A#{USERNAME_RE}\z/i }, if: -> { !local? && will_save_change_to_username? }
 
   # Local user validations
   validates :username, format: { with: /\A[a-z0-9_]+\z/i }, length: { maximum: 30 }, if: -> { local? && will_save_change_to_username? }
diff --git a/app/models/concerns/account_header.rb b/app/models/concerns/account_header.rb
index ef40b8126..067e166eb 100644
--- a/app/models/concerns/account_header.rb
+++ b/app/models/concerns/account_header.rb
@@ -5,11 +5,12 @@ module AccountHeader
 
   IMAGE_MIME_TYPES = ['image/jpeg', 'image/png', 'image/gif'].freeze
   LIMIT = 2.megabytes
+  MAX_PIXELS = 750_000 # 1500x500px
 
   class_methods do
     def header_styles(file)
-      styles = { original: { geometry: '700x335#', file_geometry_parser: FastGeometryParser } }
-      styles[:static] = { geometry: '700x335#', format: 'png', convert_options: '-coalesce', file_geometry_parser: FastGeometryParser } if file.content_type == 'image/gif'
+      styles = { original: { pixels: MAX_PIXELS, file_geometry_parser: FastGeometryParser } }
+      styles[:static] = { format: 'png', convert_options: '-coalesce', file_geometry_parser: FastGeometryParser } if file.content_type == 'image/gif'
       styles
     end
 
diff --git a/app/models/media_attachment.rb b/app/models/media_attachment.rb
index 07c08d63a..3e3cbdaed 100644
--- a/app/models/media_attachment.rb
+++ b/app/models/media_attachment.rb
@@ -25,12 +25,13 @@ class MediaAttachment < ApplicationRecord
   enum type: [:image, :gifv, :video, :audio, :unknown]
 
   IMAGE_FILE_EXTENSIONS = ['.jpg', '.jpeg', '.png', '.gif'].freeze
-  VIDEO_FILE_EXTENSIONS = ['.webm', '.mp4', '.m4v'].freeze
+  VIDEO_FILE_EXTENSIONS = ['.webm', '.mp4', '.m4v', '.mov'].freeze
   AUDIO_FILE_EXTENSIONS = ['.mp3', '.m4a', '.wav', '.ogg'].freeze
 
-  IMAGE_MIME_TYPES = ['image/jpeg', 'image/png', 'image/gif'].freeze
-  VIDEO_MIME_TYPES = ['video/webm', 'video/mp4'].freeze
-  AUDIO_MIME_TYPES = ['audio/mpeg', 'audio/mp4', 'audio/vnd.wav', 'audio/wav', 'audio/x-wav', 'audio/x-wave', 'audio/ogg',].freeze
+  IMAGE_MIME_TYPES             = ['image/jpeg', 'image/png', 'image/gif'].freeze
+  VIDEO_MIME_TYPES             = ['video/webm', 'video/mp4', 'video/quicktime'].freeze
+  VIDEO_CONVERTIBLE_MIME_TYPES = ['video/webm', 'video/quicktime'].freeze
+  AUDIO_MIME_TYPES             = ['audio/mpeg', 'audio/mp4', 'audio/vnd.wav', 'audio/wav', 'audio/x-wav', 'audio/x-wave', 'audio/ogg',].freeze
 
   IMAGE_STYLES = {
     original: {
@@ -72,7 +73,25 @@ class MediaAttachment < ApplicationRecord
     },
   }.freeze
 
-  LIMIT = 8.megabytes
+  VIDEO_FORMAT = {
+    format: 'mp4',
+    convert_options: {
+      output: {
+        'movflags' => 'faststart',
+        'pix_fmt'  => 'yuv420p',
+        'vf'       => 'scale=\'trunc(iw/2)*2:trunc(ih/2)*2\'',
+        'vsync'    => 'cfr',
+        'c:v'      => 'h264',
+        'b:v'      => '500K',
+        'maxrate'  => '1300K',
+        'bufsize'  => '1300K',
+        'crf'      => 18,
+      },
+    },
+  }.freeze
+
+  IMAGE_LIMIT = 8.megabytes
+  VIDEO_LIMIT = 40.megabytes
 
   belongs_to :account, inverse_of: :media_attachments, optional: true
   belongs_to :status,  inverse_of: :media_attachments, optional: true
@@ -82,11 +101,10 @@ class MediaAttachment < ApplicationRecord
                     processors: ->(f) { file_processors f },
                     convert_options: { all: '-quality 90 -strip' }
 
-  include Remotable
-
   validates_attachment_content_type :file, content_type: IMAGE_MIME_TYPES + VIDEO_MIME_TYPES + AUDIO_MIME_TYPES
-  validates_attachment_size :file, less_than: LIMIT
-  remotable_attachment :file, LIMIT
+  validates_attachment_size :file, less_than: IMAGE_LIMIT, unless: :video?
+  validates_attachment_size :file, less_than: VIDEO_LIMIT, if: :video?
+  remotable_attachment :file, VIDEO_LIMIT
 
   include Attachmentable
 
@@ -142,27 +160,17 @@ class MediaAttachment < ApplicationRecord
       if f.instance.file_content_type == 'image/gif'
         {
           small: IMAGE_STYLES[:small],
-          original: {
-            format: 'mp4',
-            convert_options: {
-              output: {
-                'movflags' => 'faststart',
-                'pix_fmt'  => 'yuv420p',
-                'vf'       => 'scale=\'trunc(iw/2)*2:trunc(ih/2)*2\'',
-                'vsync'    => 'cfr',
-                'c:v'      => 'h264',
-                'b:v'      => '500K',
-                'maxrate'  => '1300K',
-                'bufsize'  => '1300K',
-                'crf'      => 18,
-              },
-            },
-          },
+          original: VIDEO_FORMAT,
         }
       elsif IMAGE_MIME_TYPES.include? f.instance.file_content_type
         IMAGE_STYLES
       elsif AUDIO_MIME_TYPES.include? f.instance.file_content_type
         AUDIO_STYLES
+      elsif VIDEO_CONVERTIBLE_MIME_TYPES.include?(f.instance.file_content_type)
+        {
+          small: VIDEO_STYLES[:small],
+          original: VIDEO_FORMAT,
+        }
       else
         VIDEO_STYLES
       end
diff --git a/app/services/activitypub/fetch_remote_account_service.rb b/app/services/activitypub/fetch_remote_account_service.rb
index 867e70876..41fec9170 100644
--- a/app/services/activitypub/fetch_remote_account_service.rb
+++ b/app/services/activitypub/fetch_remote_account_service.rb
@@ -7,14 +7,14 @@ class ActivityPub::FetchRemoteAccountService < BaseService
 
   # Should be called when uri has already been checked for locality
   # Does a WebFinger roundtrip on each call
-  def call(uri, id: true, prefetched_body: nil)
+  def call(uri, id: true, prefetched_body: nil, break_on_redirect: false)
     @json = if prefetched_body.nil?
               fetch_resource(uri, id)
             else
               body_to_json(prefetched_body)
             end
 
-    return unless supported_context? && expected_type?
+    return if !supported_context? || !expected_type? || (break_on_redirect && @json['movedTo'].present?)
 
     @uri      = @json['id']
     @username = @json['preferredUsername']
diff --git a/app/services/activitypub/process_account_service.rb b/app/services/activitypub/process_account_service.rb
index 453253db4..7f95678b0 100644
--- a/app/services/activitypub/process_account_service.rb
+++ b/app/services/activitypub/process_account_service.rb
@@ -175,7 +175,7 @@ class ActivityPub::ProcessAccountService < BaseService
 
   def moved_account
     account   = ActivityPub::TagManager.instance.uri_to_resource(@json['movedTo'], Account)
-    account ||= ActivityPub::FetchRemoteAccountService.new.call(@json['movedTo'], id: true)
+    account ||= ActivityPub::FetchRemoteAccountService.new.call(@json['movedTo'], id: true, break_on_redirect: true)
     account
   end
 
diff --git a/app/views/accounts/_bio.html.haml b/app/views/accounts/_bio.html.haml
new file mode 100644
index 000000000..c9a4d8f1b
--- /dev/null
+++ b/app/views/accounts/_bio.html.haml
@@ -0,0 +1,15 @@
+.public-account-bio
+  - unless account.fields.empty?
+    .account__header__fields
+      - account.fields.each do |field|
+        %dl
+          %dt.emojify{ title: field.name }= field.name
+          %dd.emojify{ title: field.value }= Formatter.instance.format_field(account, field.value, custom_emojify: true)
+
+  = account_badge(account)
+
+  - if account.note.present?
+    .account__header__content.emojify= Formatter.instance.simplified_format(account, custom_emojify: true)
+
+  .public-account-bio__extra
+    = t 'accounts.joined', date: l(account.created_at, format: :month)
diff --git a/app/views/accounts/_follow_button.html.haml b/app/views/accounts/_follow_button.html.haml
deleted file mode 100644
index 558ced010..000000000
--- a/app/views/accounts/_follow_button.html.haml
+++ /dev/null
@@ -1,28 +0,0 @@
-- relationships ||= nil
-
-- unless account.memorial? || account.moved?
-  - if user_signed_in?
-    - requested = relationships ? relationships.requested[account.id].present? : current_account.requested?(account)
-    - following = relationships ? relationships.following[account.id].present? : current_account.following?(account)
-
-  - if user_signed_in? && current_account.id != account.id && !requested
-    .controls
-      - if following
-        = link_to (account.local? ? account_unfollow_path(account) : remote_unfollow_path(acct: account.acct)), data: { method: :post }, class: 'icon-button' do
-          = fa_icon 'user-times'
-          = t('accounts.unfollow')
-      - else
-        = link_to (account.local? ? account_follow_path(account) : authorize_follow_path(acct: account.acct)), data: { method: :post }, class: 'icon-button' do
-          = fa_icon 'user-plus'
-          = t('accounts.follow')
-  - elsif user_signed_in? && current_account.id == account.id
-    .controls
-      = link_to settings_profile_url, class: 'icon-button' do
-        = fa_icon 'pencil'
-        = t('settings.edit_profile')
-  - elsif !user_signed_in?
-    .controls
-      .remote-follow
-        = link_to (account.local? ? account_remote_follow_path(account) : "web+mastodon://follow?uri=#{account.uri}"), class: 'icon-button' do
-          = fa_icon 'user-plus'
-          = t('accounts.remote_follow')
diff --git a/app/views/accounts/_follow_grid.html.haml b/app/views/accounts/_follow_grid.html.haml
deleted file mode 100644
index fdcef84be..000000000
--- a/app/views/accounts/_follow_grid.html.haml
+++ /dev/null
@@ -1,8 +0,0 @@
-.accounts-grid{ class: accounts.empty? ? 'empty' : '' }
-  - if accounts.empty?
-    = image_tag asset_pack_path('elephant_ui_greeting.svg'), alt: '', role: 'presentational'
-    = render partial: 'accounts/nothing_here'
-  - else
-    = render partial: 'accounts/grid_card', collection: accounts, as: :account, cached: !user_signed_in?
-
-= paginate follows
diff --git a/app/views/accounts/_follow_grid_hidden.html.haml b/app/views/accounts/_follow_grid_hidden.html.haml
deleted file mode 100644
index e970350e6..000000000
--- a/app/views/accounts/_follow_grid_hidden.html.haml
+++ /dev/null
@@ -1,3 +0,0 @@
-.accounts-grid.empty
-  = image_tag asset_pack_path('elephant_ui_greeting.svg'), alt: '', role: 'presentational'
-  %p.nothing-here= t('accounts.network_hidden')
diff --git a/app/views/accounts/_grid_card.html.haml b/app/views/accounts/_grid_card.html.haml
deleted file mode 100644
index a59ed128e..000000000
--- a/app/views/accounts/_grid_card.html.haml
+++ /dev/null
@@ -1,12 +0,0 @@
-.account-grid-card
-  .account-grid-card__header{ style: "background-image: url(#{account.header.url(:original)})" }
-    = render 'accounts/follow_button', account: account, relationships: @relationships
-  .account-grid-card__avatar
-    .avatar= image_tag account.avatar.url(:original)
-  .name
-    = link_to TagManager.instance.url_for(account) do
-      %span.display_name.emojify= display_name(account, custom_emojify: true)
-      %span.username
-        @#{account.local? ? account.local_username_and_domain : account.acct}
-        = fa_icon('lock') if account.locked?
-  .account__header__content.p-note.emojify= Formatter.instance.simplified_format(account)
diff --git a/app/views/accounts/_header.html.haml b/app/views/accounts/_header.html.haml
index 4098d6778..e343be820 100644
--- a/app/views/accounts/_header.html.haml
+++ b/app/views/accounts/_header.html.haml
@@ -1,51 +1,43 @@
-.card.h-card.p-author{ style: "background-image: url(#{account.header.url(:original)})" }
-  .card__illustration
-    = render 'accounts/follow_button', account: account
-    .avatar= image_tag account.avatar.url(:original), class: 'u-photo'
+.public-account-header
+  .public-account-header__image
+    = image_tag account.header.url, class: 'parallax'
+  .public-account-header__bar
+    = link_to short_account_url(account), class: 'avatar' do
+      = image_tag account.avatar.url
+    .public-account-header__tabs
+      .public-account-header__tabs__name
+        %h1
+          = display_name(account)
+          %small
+            = acct(account)
+            = fa_icon('lock') if account.locked?
+      .public-account-header__tabs__tabs
+        .details-counters
+          .counter{ class: active_nav_class(short_account_url(account)) }
+            = link_to short_account_url(account), class: 'u-url u-uid' do
+              %span.counter-number= number_to_human account.statuses_count, strip_insignificant_zeros: true
+              %span.counter-label= t('accounts.posts')
 
-  .card__bio
-    %h1.name
-      %span.p-name.emojify= display_name(account, custom_emojify: true)
-      %small<
-        %span>< @#{account.local_username_and_domain}
-        = fa_icon('lock') if account.locked?
+          .counter{ class: active_nav_class(account_following_index_url(account)) }
+            = link_to account_following_index_url(account) do
+              %span.counter-number= number_to_human account.following_count, strip_insignificant_zeros: true
+              %span.counter-label= t('accounts.following')
 
-    - if account.bot?
-      .roles
-        .account-role.bot
-          = t 'accounts.roles.bot'
-    - elsif Setting.show_staff_badge
-      - if account.user_admin?
-        .roles
-          .account-role.admin
-            = t 'accounts.roles.admin'
-      - elsif account.user_moderator?
-        .roles
-          .account-role.moderator
-            = t 'accounts.roles.moderator'
+          .counter{ class: active_nav_class(account_followers_url(account)) }
+            = link_to account_followers_url(account) do
+              %span.counter-number= number_to_human account.followers_count, strip_insignificant_zeros: true
+              %span.counter-label= t('accounts.followers')
+        .spacer
+        .public-account-header__tabs__tabs__buttons
+          = account_action_button(account)
 
-    .bio
-      .account__header__content.p-note.emojify= Formatter.instance.simplified_format(account, custom_emojify: true)
+    .public-account-header__extra
+      = render 'accounts/bio', account: account
 
-      - unless account.fields.empty?
-        .account__header__fields
-          - account.fields.each do |field|
-            %dl
-              %dt.emojify{ title: field.name }= field.name
-              %dd.emojify{ title: field.value }= Formatter.instance.format_field(account, field.value, custom_emojify: true)
-
-    .details-counters
-      .counter{ class: active_nav_class(short_account_url(account)) }
-        = link_to short_account_url(account), class: 'u-url u-uid' do
-          %span.counter-number= number_to_human account.statuses_count, strip_insignificant_zeros: true
-          %span.counter-label= t('accounts.posts')
-
-      .counter{ class: active_nav_class(account_following_index_url(account)) }
+      .public-account-header__extra__links
         = link_to account_following_index_url(account) do
-          %span.counter-number= number_to_human account.following_count, strip_insignificant_zeros: true
-          %span.counter-label= t('accounts.following')
-
-      .counter{ class: active_nav_class(account_followers_url(account)) }
+          %strong= number_to_human account.following_count, strip_insignificant_zeros: true
+          = t('accounts.following')
         = link_to account_followers_url(account) do
-          %span.counter-number= number_to_human account.followers_count, strip_insignificant_zeros: true
-          %span.counter-label= t('accounts.followers')
+          %strong= number_to_human account.followers_count, strip_insignificant_zeros: true
+          = t('accounts.followers')
diff --git a/app/views/accounts/_moved_strip.html.haml b/app/views/accounts/_moved.html.haml
index ae18c6dc7..f99328dbd 100644
--- a/app/views/accounts/_moved_strip.html.haml
+++ b/app/views/accounts/_moved.html.haml
@@ -1,11 +1,11 @@
 - moved_to_account = account.moved_to_account
 
-.moved-strip
-  .moved-strip__message
+.moved-account-widget
+  .moved-account-widget__message
     = fa_icon 'suitcase'
-    = t('accounts.moved_html', name: content_tag(:strong, display_name(account, custom_emojify: true), class: :emojify), new_profile_link: link_to(content_tag(:strong, safe_join(['@', content_tag(:span, moved_to_account.acct)])), TagManager.instance.url_for(moved_to_account), class: 'mention'))
+    = t('accounts.moved_html', name: content_tag(:bdi, content_tag(:strong, display_name(account, custom_emojify: true), class: :emojify)), new_profile_link: link_to(content_tag(:strong, safe_join(['@', content_tag(:span, moved_to_account.acct)])), TagManager.instance.url_for(moved_to_account), class: 'mention'))
 
-  .moved-strip__card
+  .moved-account-widget__card
     = link_to TagManager.instance.url_for(moved_to_account), class: 'detailed-status__display-name p-author h-card', target: '_blank', rel: 'noopener' do
       .detailed-status__display-avatar
         .account__avatar-overlay
@@ -13,5 +13,6 @@
           .account__avatar-overlay-overlay{ style: "background-image: url('#{account.avatar.url(:original)}')" }
 
       %span.display-name
-        %strong.emojify= display_name(moved_to_account, custom_emojify: true)
+        %bdi
+          %strong.emojify= display_name(moved_to_account, custom_emojify: true)
         %span @#{moved_to_account.acct}
diff --git a/app/views/accounts/_nothing_here.html.haml b/app/views/accounts/_nothing_here.html.haml
deleted file mode 100644
index 0c6dc1168..000000000
--- a/app/views/accounts/_nothing_here.html.haml
+++ /dev/null
@@ -1 +0,0 @@
-%p.nothing-here= t('accounts.nothing_here')
diff --git a/app/views/accounts/show.html.haml b/app/views/accounts/show.html.haml
index cfdd3a945..b30755d94 100644
--- a/app/views/accounts/show.html.haml
+++ b/app/views/accounts/show.html.haml
@@ -20,36 +20,39 @@
   = opengraph 'og:type', 'profile'
   = render 'og', account: @account, url: short_account_url(@account, only_path: false)
 
-- if @account.memorial?
-  .memoriam-strip= t('in_memoriam_html')
-- elsif @account.moved?
-  = render partial: 'moved_strip', locals: { account: @account }
-- elsif show_landing_strip?
-  = render partial: 'shared/landing_strip', locals: { account: @account }
-
-.h-feed
-  %data.p-name{ value: "#{@account.username} on #{site_hostname}" }/
-
-  = render 'header', account: @account
-
-  .activity-stream-tabs
-    = active_link_to t('accounts.posts'), short_account_url(@account)
-    = active_link_to t('accounts.posts_with_replies'), short_account_with_replies_url(@account)
-    = active_link_to t('accounts.media'), short_account_media_url(@account)
-
-  - if @statuses.empty?
-    .accounts-grid
-      = render 'nothing_here'
-  - else
-    .activity-stream.with-header
-      - if params[:page].to_i.zero?
-        = render partial: 'stream_entries/status', collection: @pinned_statuses, as: :status, locals: { pinned: true }
-
-      = render partial: 'stream_entries/status', collection: @statuses, as: :status
-
-  - if @newer_url || @older_url
-    .pagination
-      - if @older_url
-        = link_to safe_join([fa_icon('chevron-left'), t('pagination.older')], ' '), @older_url, class: 'older', rel: 'next'
-      - if @newer_url
-        = link_to safe_join([t('pagination.newer'), fa_icon('chevron-right')], ' '), @newer_url, class: 'newer', rel: 'prev'
+
+= render 'header', account: @account, with_bio: true
+
+.grid
+  .column-0
+    .h-feed
+      %data.p-name{ value: "#{@account.username} on #{site_hostname}" }/
+
+      .account__section-headline
+        = active_link_to t('accounts.posts'), short_account_url(@account)
+        = active_link_to t('accounts.posts_with_replies'), short_account_with_replies_url(@account)
+        = active_link_to t('accounts.media'), short_account_media_url(@account)
+
+      - if @statuses.empty?
+        = nothing_here 'nothing-here--under-tabs'
+      - else
+        .activity-stream
+          - if params[:page].to_i.zero?
+            = render partial: 'stream_entries/status', collection: @pinned_statuses, as: :status, locals: { pinned: true }
+
+          - if @newer_url
+            .entry= link_to_more @newer_url
+
+          = render partial: 'stream_entries/status', collection: @statuses, as: :status
+
+          - if @older_url
+            .entry= link_to_more @older_url
+
+  .column-1
+    - if @account.memorial?
+      .memoriam-widget= t('in_memoriam_html')
+    - elsif @account.moved?
+      = render 'moved', account: @account
+
+    = render 'bio', account: @account
+    = render 'application/sidebar'
diff --git a/app/views/application/_card.html.haml b/app/views/application/_card.html.haml
new file mode 100644
index 000000000..9cf8f8ff2
--- /dev/null
+++ b/app/views/application/_card.html.haml
@@ -0,0 +1,16 @@
+- account_url = local_assigns[:admin] ? admin_account_path(account.id) : TagManager.instance.url_for(account)
+
+.card.h-card
+  = link_to account_url, target: '_blank', rel: 'noopener' do
+    .card__img
+      = image_tag account.header.url, alt: ''
+    .card__bar
+      .avatar
+        = image_tag account.avatar.url, alt: '', width: 48, height: 48, class: 'u-photo'
+
+      .display-name
+        %bdi
+          %strong.emojify.p-name= display_name(account, custom_emojify: true)
+        %span
+          = acct(account)
+          = fa_icon('lock') if account.locked?
diff --git a/app/views/application/_sidebar.html.haml b/app/views/application/_sidebar.html.haml
new file mode 100644
index 000000000..3d8832bb4
--- /dev/null
+++ b/app/views/application/_sidebar.html.haml
@@ -0,0 +1,6 @@
+.hero-widget
+  .hero-widget__img
+    = image_tag @instance_presenter.hero&.file&.url || @instance_presenter.thumbnail&.file&.url || asset_pack_path('preview.jpg'), alt: @instance_presenter.site_title
+
+  .hero-widget__text
+    %p= @instance_presenter.site_description.html_safe.presence || t('about.generic_description', domain: site_hostname)
diff --git a/app/views/auth/registrations/new.html.haml b/app/views/auth/registrations/new.html.haml
index 0fac8e10d..200ed42de 100644
--- a/app/views/auth/registrations/new.html.haml
+++ b/app/views/auth/registrations/new.html.haml
@@ -10,7 +10,7 @@
   - if @invite.present? && @invite.autofollow?
     .fields-group{ style: 'margin-bottom: 30px' }
       %p.hint{ style: 'text-align: center' }= t('invites.invited_by')
-      = render 'authorize_follows/card', account: @invite.user.account
+      = render 'application/card', account: @invite.user.account
 
   = f.simple_fields_for :account do |ff|
     .input-with-append
diff --git a/app/views/authorize_follows/_card.html.haml b/app/views/authorize_follows/_card.html.haml
deleted file mode 100644
index edc03131f..000000000
--- a/app/views/authorize_follows/_card.html.haml
+++ /dev/null
@@ -1,23 +0,0 @@
-.account-card
-  .account-card__header{ style: "background-image: url(#{account.header.url(:original)})" }
-  .detailed-status__display-name
-    %div
-      = image_tag account.avatar.url(:original), alt: '', width: 48, height: 48, class: 'avatar'
-
-    %span.display-name
-      - account_url = local_assigns[:admin] ? admin_account_path(account.id) : TagManager.instance.url_for(account)
-      = link_to account_url, class: 'detailed-status__display-name p-author h-card', target: '_blank', rel: 'noopener' do
-        %strong.emojify= display_name(account, custom_emojify: true)
-        %span @#{account.acct}
-
-    .counter
-      %span.counter-number= number_to_human account.statuses_count, strip_insignificant_zeros: true
-      %span.counter-label= t('accounts.posts')
-
-    .counter
-      %span.counter-number= number_to_human account.following_count, strip_insignificant_zeros: true
-      %span.counter-label= t('accounts.following')
-
-    .counter
-      %span.counter-number= number_to_human account.followers_count, strip_insignificant_zeros: true
-      %span.counter-label= t('accounts.followers')
diff --git a/app/views/authorize_follows/show.html.haml b/app/views/authorize_follows/show.html.haml
index a1fd01dd6..90e65b34f 100644
--- a/app/views/authorize_follows/show.html.haml
+++ b/app/views/authorize_follows/show.html.haml
@@ -3,7 +3,7 @@
 
 .form-container
   .follow-prompt
-    = render 'card', account: @account
+    = render 'application/card', account: @account
 
   - if current_account.following?(@account)
     .flash-message
diff --git a/app/views/authorize_follows/success.html.haml b/app/views/authorize_follows/success.html.haml
index fa59b24b8..cf9cb50ea 100644
--- a/app/views/authorize_follows/success.html.haml
+++ b/app/views/authorize_follows/success.html.haml
@@ -8,6 +8,6 @@
     - else
       %h2= t('authorize_follow.following')
 
-    = render 'card', account: @account
+    = render 'application/card', account: @account
 
   = render 'post_follow_actions'
diff --git a/app/views/follower_accounts/index.html.haml b/app/views/follower_accounts/index.html.haml
index 65af81a5b..31dab68bf 100644
--- a/app/views/follower_accounts/index.html.haml
+++ b/app/views/follower_accounts/index.html.haml
@@ -8,6 +8,11 @@
 = render 'accounts/header', account: @account
 
 - if @account.user_hides_network?
-  = render 'accounts/follow_grid_hidden'
+  .nothing-here= t('accounts.network_hidden')
+- elsif @follows.empty?
+  = nothing_here
 - else
-  = render 'accounts/follow_grid', follows: @follows, accounts: @follows.map(&:account)
+  .card-grid
+    = render partial: 'application/card', collection: @follows.map(&:account), as: :account
+
+  = paginate @follows
diff --git a/app/views/following_accounts/index.html.haml b/app/views/following_accounts/index.html.haml
index 8fd95a0b4..8b49b529b 100644
--- a/app/views/following_accounts/index.html.haml
+++ b/app/views/following_accounts/index.html.haml
@@ -8,6 +8,11 @@
 = render 'accounts/header', account: @account
 
 - if @account.user_hides_network?
-  = render 'accounts/follow_grid_hidden'
+  .nothing-here= t('accounts.network_hidden')
+- elsif @follows.empty?
+  = nothing_here
 - else
-  = render 'accounts/follow_grid', follows: @follows, accounts: @follows.map(&:target_account)
+  .card-grid
+    = render partial: 'application/card', collection: @follows.map(&:target_account), as: :account
+
+  = paginate @follows
diff --git a/app/views/layouts/public.html.haml b/app/views/layouts/public.html.haml
index 8bbd184bb..098262b2e 100644
--- a/app/views/layouts/public.html.haml
+++ b/app/views/layouts/public.html.haml
@@ -1,14 +1,47 @@
 - content_for :content do
-  .container-alt= yield
-  .footer
-    - if !user_signed_in? && single_user_mode?
-      %span.single-user-login
-        = link_to t('auth.login'), new_user_session_path
-        &mdash;
-      %span.footer__domain= link_to site_hostname, about_path
-    - else
-      %span.footer__domain= link_to site_hostname, root_path
-    %span.powered-by
-      != t('generic.powered_by', link: link_to('https://joinmastodon.org') { image_tag asset_pack_path('logo_full.svg'), alt: 'Mastodon' })
+  .public-layout
+    .container
+      %nav.header
+        .nav-left
+          = link_to root_url, class: 'brand' do
+            = image_tag asset_pack_path('logo_full.svg'), alt: 'Mastodon'
+        .nav-center
+        .nav-right
+          - if user_signed_in?
+            = link_to t('settings.back'), root_url, class: 'nav-link nav-button webapp-btn'
+          - else
+            = link_to t('auth.login'), new_user_session_path, class: 'webapp-btn nav-link nav-button'
+            = link_to t('auth.register'), new_user_registration_path, class: 'webapp-btn nav-link nav-button'
+
+    .container= yield
+
+    .container
+      .footer
+        .grid
+          .column-0
+            %h4= t 'footer.resources'
+            %ul
+              %li= link_to t('about.terms'), terms_path
+              %li= link_to t('about.privacy_policy'), terms_path
+          .column-1
+            %h4= t 'footer.developers'
+            %ul
+              %li= link_to t('about.documentation'), 'https://github.com/tootsuite/documentation'
+              %li= link_to t('about.api'), 'https://github.com/tootsuite/documentation/blob/master/Using-the-API/API.md'
+          .column-2
+            %h4= link_to t('about.what_is_mastodon'), 'https://joinmastodon.org/'
+
+            = link_to root_url, class: 'brand' do
+              = render file: Rails.root.join('app', 'javascript', 'images', 'logo_transparent.svg')
+          .column-3
+            %h4= site_hostname
+            %ul
+              %li= link_to t('about.about_this'), about_more_path
+              %li= "v#{Mastodon::Version.to_s}"
+          .column-4
+            %h4= t 'footer.more'
+            %ul
+              %li= link_to t('about.source_code'), Mastodon::Version.source_url
+              %li= link_to 'joinmastodon.org', 'https://joinmastodon.org'
 
 = render template: 'layouts/application'
diff --git a/app/views/remote_follow/new.html.haml b/app/views/remote_follow/new.html.haml
index 9b22fda5f..9b679015f 100644
--- a/app/views/remote_follow/new.html.haml
+++ b/app/views/remote_follow/new.html.haml
@@ -6,7 +6,7 @@
   .follow-prompt
     %h2= t('remote_follow.prompt')
 
-    = render partial: 'authorize_follows/card', locals: { account: @account }
+    = render partial: 'application/card', locals: { account: @account }
 
   = simple_form_for @remote_follow, as: :remote_follow, url: account_remote_follow_path(@account) do |f|
     = render 'shared/error_messages', object: @remote_follow
diff --git a/app/views/remote_unfollows/success.html.haml b/app/views/remote_unfollows/success.html.haml
index aa3c838a0..b007eedc7 100644
--- a/app/views/remote_unfollows/success.html.haml
+++ b/app/views/remote_unfollows/success.html.haml
@@ -5,6 +5,6 @@
   .follow-prompt
     %h2= t('remote_unfollow.unfollowed')
 
-    = render 'card', account: @account
+    = render 'application/card', account: @account
 
   = render 'post_follow_actions'
diff --git a/app/views/settings/migrations/show.html.haml b/app/views/settings/migrations/show.html.haml
index b7c34761f..c69061d50 100644
--- a/app/views/settings/migrations/show.html.haml
+++ b/app/views/settings/migrations/show.html.haml
@@ -6,7 +6,7 @@
     %p.hint= t('migrations.currently_redirecting')
 
     .fields-group
-      = render partial: 'authorize_follows/card', locals: { account: @migration.account }
+      = render partial: 'application/card', locals: { account: @migration.account }
 
   = render 'shared/error_messages', object: @migration
 
diff --git a/app/views/settings/profiles/show.html.haml b/app/views/settings/profiles/show.html.haml
index d65a7f36f..1acbb9b8a 100644
--- a/app/views/settings/profiles/show.html.haml
+++ b/app/views/settings/profiles/show.html.haml
@@ -8,13 +8,12 @@
     = f.input :display_name, placeholder: t('simple_form.labels.defaults.display_name'), hint: t('simple_form.hints.defaults.display_name', count: 30 - @account.display_name.size).html_safe
     = f.input :note, placeholder: t('simple_form.labels.defaults.note'), hint: t('simple_form.hints.defaults.note', count: 500 - @account.note.size).html_safe
 
-  .card.compact{ style: "background-image: url(#{@account.header.url(:original)})", data: { original_src: @account.header.url(:original) } }
-    .avatar= image_tag @account.avatar.url(:original), data: { original_src: @account.avatar.url(:original) }
+  = render 'application/card', account: @account
 
   .fields-group
-    = f.input :avatar, wrapper: :with_label, input_html: { accept: AccountAvatar::IMAGE_MIME_TYPES.join(',') }, hint: t('simple_form.hints.defaults.avatar')
+    = f.input :avatar, wrapper: :with_label, input_html: { accept: AccountAvatar::IMAGE_MIME_TYPES.join(',') }, hint: t('simple_form.hints.defaults.avatar', dimensions: '400x400', size: number_to_human_size(AccountAvatar::LIMIT))
 
-    = f.input :header, wrapper: :with_label, input_html: { accept: AccountHeader::IMAGE_MIME_TYPES.join(',') }, hint: t('simple_form.hints.defaults.header')
+    = f.input :header, wrapper: :with_label, input_html: { accept: AccountHeader::IMAGE_MIME_TYPES.join(',') }, hint: t('simple_form.hints.defaults.header', dimensions: '1500x500', size: number_to_human_size(AccountHeader::LIMIT))
 
   .fields-group
     = f.input :locked, as: :boolean, wrapper: :with_label, hint: t('simple_form.hints.defaults.locked')
diff --git a/app/views/shared/_landing_strip.html.haml b/app/views/shared/_landing_strip.html.haml
deleted file mode 100644
index 9a4144723..000000000
--- a/app/views/shared/_landing_strip.html.haml
+++ /dev/null
@@ -1,6 +0,0 @@
-.landing-strip
-  = image_tag asset_pack_path('logo.svg'), class: 'logo'
-
-  %div
-    = t('landing_strip_html', name: content_tag(:span, display_name(account, custom_emojify: true), class: :emojify), link_to_root_path: link_to(content_tag(:strong, site_hostname), root_path))
-    = t('landing_strip_signup_html', sign_up_path: open_registrations? ? new_user_registration_path : 'https://joinmastodon.org/#getting-started')
diff --git a/app/views/stream_entries/_content_spoiler.html.haml b/app/views/stream_entries/_content_spoiler.html.haml
deleted file mode 100644
index fb42d3f57..000000000
--- a/app/views/stream_entries/_content_spoiler.html.haml
+++ /dev/null
@@ -1,7 +0,0 @@
-.media-spoiler-wrapper{ class: sensitive == false && 'media-spoiler-wrapper__visible' }><
-  .spoiler-button
-    .icon-button.overlayed
-      %i.fa.fa-fw.fa-eye
-  .media-spoiler
-    %span= t('stream_entries.sensitive_content')
-    %span= t('stream_entries.click_to_show')
diff --git a/app/views/stream_entries/_detailed_status.html.haml b/app/views/stream_entries/_detailed_status.html.haml
index 85e90a237..aa160b979 100644
--- a/app/views/stream_entries/_detailed_status.html.haml
+++ b/app/views/stream_entries/_detailed_status.html.haml
@@ -1,16 +1,15 @@
-.detailed-status.light
+.detailed-status.detailed-status--flex
   = link_to TagManager.instance.url_for(status.account), class: 'detailed-status__display-name p-author h-card', target: stream_link_target, rel: 'noopener' do
-    %div
-      .avatar
-        = image_tag status.account.avatar.url(:original), width: 48, height: 48, alt: '', class: 'u-photo'
+    .detailed-status__display-avatar
+      = image_tag status.account.avatar.url(:original), width: 48, height: 48, alt: '', class: 'account__avatar u-photo'
     %span.display-name
-      %strong.p-name.emojify= display_name(status.account, custom_emojify: true)
-      %span= acct(status.account)
+      %bdi
+        %strong.display-name__html.p-name.emojify= display_name(status.account, custom_emojify: true)
+      %span.display-name__account
+        = acct(status.account)
+        = fa_icon('lock') if status.account.locked?
 
-  - if !user_signed_in? || embedded_view?
-    = link_to account_remote_follow_path(status.account), class: 'button button-secondary logo-button', target: '_new' do
-      = render file: Rails.root.join('app', 'javascript', 'images', 'logo.svg')
-      = t('accounts.follow')
+  = account_action_button(status.account)
 
   .status__content.emojify<
     - if status.spoiler_text?
@@ -30,6 +29,7 @@
 
   .detailed-status__meta
     %data.dt-published{ value: status.created_at.to_time.iso8601 }
+
     = link_to TagManager.instance.url_for(status), class: 'detailed-status__datetime u-url u-uid', target: stream_link_target, rel: 'noopener' do
       %time.formatted{ datetime: status.created_at.iso8601, title: l(status.created_at) }= l(status.created_at)
     ·
@@ -40,20 +40,20 @@
         = link_to status.application.name, status.application.website, class: 'detailed-status__application', target: '_blank', rel: 'noopener'
       ·
     - if status.direct_visibility?
-      %span<
+      %span.detailed-status__link<
         = fa_icon('envelope')
     - elsif status.private_visibility?
-      %span<
+      %span.detailed-status__link<
         = fa_icon('lock')
     - else
-      %span<
+      %span.detailed-status__link<
         = fa_icon('retweet')
-        %span= status.reblogs_count
+        %span.detailed-status__reblogs= number_to_human status.reblogs_count, strip_insignificant_zeros: true
     ·
-    %span<
+    %span.detailed-status__link<
       = fa_icon('star')
-      %span= status.favourites_count
+      %span.detailed-status__favorites= number_to_human status.favourites_count, strip_insignificant_zeros: true
 
     - if user_signed_in?
       ·
-      = link_to t('statuses.open_in_web'), web_url("statuses/#{status.id}"), class: 'open-in-web-link', target: '_blank'
+      = link_to t('statuses.open_in_web'), web_url("statuses/#{status.id}"), class: 'detailed-status__application', target: '_blank'
diff --git a/app/views/stream_entries/_media.html.haml b/app/views/stream_entries/_media.html.haml
deleted file mode 100644
index 32d024cf6..000000000
--- a/app/views/stream_entries/_media.html.haml
+++ /dev/null
@@ -1,4 +0,0 @@
-.media-item><
-  = link_to media.remote_url.blank? ? media.file.url(:original) : media.remote_url, style: media.image? ? "background-image: url(#{media.file.url(:original)})" : '', target: '_blank', rel: 'noopener', class: "u-#{media.video? || media.gifv? ? 'video' : 'photo'}" do
-    - unless media.image?
-      %video{ src: media.file.url(:original), autoplay: true, loop: true }/
diff --git a/app/views/stream_entries/_more.html.haml b/app/views/stream_entries/_more.html.haml
deleted file mode 100644
index 9b1dfe4a7..000000000
--- a/app/views/stream_entries/_more.html.haml
+++ /dev/null
@@ -1,2 +0,0 @@
-= link_to url, class: 'more light'  do
-  = t('statuses.show_more')
diff --git a/app/views/stream_entries/_simple_status.html.haml b/app/views/stream_entries/_simple_status.html.haml
index 397b8dca3..bdbb6f387 100644
--- a/app/views/stream_entries/_simple_status.html.haml
+++ b/app/views/stream_entries/_simple_status.html.haml
@@ -1,18 +1,19 @@
-.status.light
-  .status__header
-    .status__meta
-      = link_to TagManager.instance.url_for(status), class: 'status__relative-time u-url u-uid', target: stream_link_target, rel: 'noopener' do
-        %time.time-ago{ datetime: status.created_at.iso8601, title: l(status.created_at) }= l(status.created_at)
-      %data.dt-published{ value: status.created_at.to_time.iso8601 }
+.status
+  .status__info
+    = link_to TagManager.instance.url_for(status), class: 'status__relative-time u-url u-uid', target: stream_link_target, rel: 'noopener' do
+      %time.time-ago{ datetime: status.created_at.iso8601, title: l(status.created_at) }= l(status.created_at)
+    %data.dt-published{ value: status.created_at.to_time.iso8601 }
 
     = link_to TagManager.instance.url_for(status.account), class: 'status__display-name p-author h-card', target: stream_link_target, rel: 'noopener' do
       .status__avatar
         %div
-          = image_tag status.account.avatar(:original), width: 48, height: 48, alt: '', class: 'u-photo'
+          = image_tag status.account.avatar(:original), width: 48, height: 48, alt: '', class: 'u-photo account__avatar'
       %span.display-name
-        %strong.p-name.emojify= display_name(status.account, custom_emojify: true)
-        %span= acct(status.account)
-
+        %bdi
+          %strong.display-name__html.p-name.emojify= display_name(status.account, custom_emojify: true)
+        %span.display-name__account
+          = acct(status.account)
+          = fa_icon('lock') if status.account.locked?
   .status__content.emojify<
     - if status.spoiler_text?
       %p{ style: 'margin-bottom: 0' }<
@@ -27,3 +28,16 @@
       = react_component :video, src: video.file.url(:original), preview: video.file.url(:small), sensitive: status.sensitive? && !current_account&.user&.setting_display_sensitive_media, width: 610, height: 343, inline: true
     - else
       = react_component :media_gallery, height: 343, sensitive: status.sensitive? && !current_account&.user&.setting_display_sensitive_media, 'autoPlayGif': current_account&.user&.setting_auto_play_gif, media: status.media_attachments.map { |a| ActiveModelSerializers::SerializableResource.new(a, serializer: REST::MediaAttachmentSerializer).as_json }
+
+  .status__action-bar
+    .status__action-bar-button.static-icon-button<
+      - if status.public_visibility? || status.unlisted_visibility?
+        = fa_icon 'retweet fw'
+        %span.detailed-status__reblogs= number_to_human status.reblogs_count, strip_insignificant_zeros: true
+      - elsif status.private_visibility?
+        = fa_icon 'lock fw'
+      - else
+        = fa_icon 'envelope fw'
+    .status__action-bar-button.static-icon-button<
+      = fa_icon 'star fw'
+      %span.detailed-status__favorites= number_to_human status.favourites_count, strip_insignificant_zeros: true
diff --git a/app/views/stream_entries/_status.html.haml b/app/views/stream_entries/_status.html.haml
index b87ca2177..320c9bc4f 100644
--- a/app/views/stream_entries/_status.html.haml
+++ b/app/views/stream_entries/_status.html.haml
@@ -16,24 +16,25 @@
 - if status.reply? && include_threads
   - if @next_ancestor
     .entry{ class: entry_classes }
-      = render 'stream_entries/more', url: TagManager.instance.url_for(@next_ancestor)
+      = link_to_more TagManager.instance.url_for(@next_ancestor)
 
   = render partial: 'stream_entries/status', collection: @ancestors, as: :status, locals: { is_predecessor: true, direct_reply_id: status.in_reply_to_id }
 
 .entry{ class: entry_classes }
 
   - if status.reblog?
-    .pre-header
-      .pre-header__icon
-        = fa_icon('retweet fw')
+    .status__prepend
+      .status__prepend-icon-wrapper
+        %i.status__prepend-icon.fa.fa-fw.fa-retweet
       %span
         = link_to TagManager.instance.url_for(status.account), class: 'status__display-name muted' do
-          %strong.emojify= display_name(status.account, custom_emojify: true)
+          %bdi
+            %strong.emojify= display_name(status.account, custom_emojify: true)
         = t('stream_entries.reblogged')
   - elsif pinned
-    .pre-header
-      .pre-header__icon
-        = fa_icon('thumb-tack fw')
+    .status__prepend
+      .status__prepend-icon-wrapper
+        %i.status__prepend-icon.fa.fa-fw.fa-thumb-tack
       %span
         = t('stream_entries.pinned')
 
@@ -42,13 +43,13 @@
 - if include_threads
   - if @since_descendant_thread_id
     .entry{ class: entry_classes }
-      = render 'stream_entries/more', url: short_account_status_url(status.account.username, status, max_descendant_thread_id: @since_descendant_thread_id + 1)
+      = link_to_more short_account_status_url(status.account.username, status, max_descendant_thread_id: @since_descendant_thread_id + 1)
   - @descendant_threads.each do |thread|
     = render partial: 'stream_entries/status', collection: thread[:statuses], as: :status, locals: { is_successor: true, parent_id: status.id }
 
     - if thread[:next_status]
       .entry{ class: entry_classes }
-        = render 'stream_entries/more', url: TagManager.instance.url_for(thread[:next_status])
+        = link_to_more TagManager.instance.url_for(thread[:next_status])
   - if @next_descendant_thread
     .entry{ class: entry_classes }
-      = render 'stream_entries/more', url: short_account_status_url(status.account.username, status, since_descendant_thread_id: @max_descendant_thread_id - 1)
+      = link_to_more short_account_status_url(status.account.username, status, since_descendant_thread_id: @max_descendant_thread_id - 1)
diff --git a/app/views/stream_entries/embed.html.haml b/app/views/stream_entries/embed.html.haml
index b703c15d2..d20c1e93e 100644
--- a/app/views/stream_entries/embed.html.haml
+++ b/app/views/stream_entries/embed.html.haml
@@ -1,3 +1,3 @@
 - cache @stream_entry.activity do
-  .activity-stream.activity-stream-headless
+  .activity-stream.activity-stream--headless
     = render "stream_entries/#{@type}", @type.to_sym => @stream_entry.activity, centered: true
diff --git a/app/views/stream_entries/show.html.haml b/app/views/stream_entries/show.html.haml
index dfb83e747..9da6245dc 100644
--- a/app/views/stream_entries/show.html.haml
+++ b/app/views/stream_entries/show.html.haml
@@ -17,8 +17,9 @@
   = render 'stream_entries/og_description', activity: @stream_entry.activity
   = render 'stream_entries/og_image', activity: @stream_entry.activity, account: @account
 
-- if show_landing_strip?
-  = render partial: 'shared/landing_strip', locals: { account: @stream_entry.account }
-
-.activity-stream.activity-stream-headless.h-entry
-  = render partial: "stream_entries/#{@type}", locals: { @type.to_sym => @stream_entry.activity, include_threads: true }
+.grid
+  .column-0
+    .activity-stream.activity-stream-headless.h-entry
+      = render partial: "stream_entries/#{@type}", locals: { @type.to_sym => @stream_entry.activity, include_threads: true }
+  .column-1
+    = render 'application/sidebar'
diff --git a/config/locales/activerecord.ast.yml b/config/locales/activerecord.ast.yml
index 0967ef424..0b77eecf2 100644
--- a/config/locales/activerecord.ast.yml
+++ b/config/locales/activerecord.ast.yml
@@ -1 +1,2 @@
-{}
+---
+ast:
diff --git a/config/locales/ar.yml b/config/locales/ar.yml
index 013bc7004..d40ae0f72 100644
--- a/config/locales/ar.yml
+++ b/config/locales/ar.yml
@@ -46,7 +46,6 @@ ar:
     people_who_follow: الأشخاص الذين يتبعون %{name}
     posts: منشورات
     posts_with_replies: التبويقات و الردود
-    remote_follow: إتبع عن بعد
     reserved_username: إسم المستخدم محجوز
     roles:
       admin: المدير
@@ -516,7 +515,6 @@ ar:
     unlocked_warning_title: إنّ حسابك غير مقفل
   generic:
     changes_saved_msg: تم حفظ التعديلات بنجاح !
-    powered_by: مدعوم بـ %{link}
     save_changes: حفظ التغييرات
     validation_errors:
       one: لا يزال هناك خلل ما إلى حد الآن. يُرجى إعادة النظر في الخطأ أسفله
@@ -551,8 +549,6 @@ ar:
       expires_at: تنتهي مدة صلاحيتها في
       uses: يستخدِم
     title: دعوة أشخاص
-  landing_strip_html: "<strong>%{name}</strong> هو أحد مُستخدِمي %{link_to_root_path}. بإمكانك متابعته أو التواصل معه إن كنت تملك حسابًا أيا كان على البيئة الموحَّدة فيديفرس."
-  landing_strip_signup_html: إن كنت لا تملك واحدا، يمكنك <a href="%{sign_up_path}">التسجيل مِن هنا</a>.
   lists:
     errors:
       limit: لقد بلغت الحد الأقصى للقوائم
@@ -720,7 +716,6 @@ ar:
       unlisted: غير مُدرَج
       unlisted_long: يُمكن لأيٍ كان رُؤيتَه و لكن لن يُعرَض على الخيوط العامة
   stream_entries:
-    click_to_show: إضغط للعرض
     pinned: تبويق مثبّت
     reblogged: رقى
     sensitive_content: محتوى حساس
diff --git a/config/locales/ast.yml b/config/locales/ast.yml
index 4436c2d88..3dae9cc1a 100644
--- a/config/locales/ast.yml
+++ b/config/locales/ast.yml
@@ -96,8 +96,6 @@ ast:
   followers:
     domain: Dominiu
     followers_count: Númberu de siguidores
-  generic:
-    powered_by: cola potencia de %{link}
   invites:
     expires_in:
       '1800': 30 minutos
@@ -183,7 +181,6 @@ ast:
         other: "%{count} vídeos"
     title: "%{name}: «%{quote}»"
   stream_entries:
-    click_to_show: Primi p'amosar
     sensitive_content: Conteníu sensible
   themes:
     default: Mastodon
diff --git a/config/locales/bg.yml b/config/locales/bg.yml
index cb3ed2244..f101101e2 100644
--- a/config/locales/bg.yml
+++ b/config/locales/bg.yml
@@ -22,7 +22,6 @@ bg:
     people_followed_by: Хора, които %{name} следва
     people_who_follow: Хора, които следват %{name}
     posts: Публикации
-    remote_follow: Последвай
     unfollow: Не следвай
   application_mailer:
     settings: 'Промяна на предпочитанията за e-mail: %{link}'
@@ -64,7 +63,6 @@ bg:
     storage: Съхранение на мултимедия
   generic:
     changes_saved_msg: Успешно запазване на промените!
-    powered_by: поддържано от %{link}
     save_changes: Запази промените
     validation_errors:
       one: Нещо все още не е наред! Моля, прегледай грешката по-долу
@@ -76,8 +74,6 @@ bg:
       blocking: Списък на блокираните
       following: Списък на последователите
     upload: Качване
-  landing_strip_html: "<strong>%{name}</strong> е потребител от %{link_to_root_path}. Можеш да ги следваш, или да контактуваш с тях, ако имаш акаунт където и да е из федерираната вселена на Mastodon."
-  landing_strip_signup_html: Ако нямаш акаунт, можеш да си <a href="%{sign_up_path}">създадеш ето тук</a>.
   media_attachments:
     validations:
       images_and_video: Не мога да прикача видеоклип към публикация, която вече съдържа изображения
@@ -144,7 +140,6 @@ bg:
       public: Публично
       unlisted: Публично, но не показвай в публичния канал
   stream_entries:
-    click_to_show: Покажи
     reblogged: споделено
     sensitive_content: Деликатно съдържание
   time:
diff --git a/config/locales/ca.yml b/config/locales/ca.yml
index 7133019d1..e4a62ffb1 100644
--- a/config/locales/ca.yml
+++ b/config/locales/ca.yml
@@ -46,7 +46,6 @@ ca:
     people_who_follow: Usuaris que segueixen %{name}
     posts: Toots
     posts_with_replies: Toots i respostes
-    remote_follow: Seguiment remot
     reserved_username: El nom d'usuari està reservat
     roles:
       admin: Administrador
@@ -504,7 +503,6 @@ ca:
     unlocked_warning_title: El teu compte no està blocat
   generic:
     changes_saved_msg: Els canvis s'han desat correctament!
-    powered_by: amb tecnologia %{link}
     save_changes: Desa els canvis
     validation_errors:
       one: Alguna cosa no va bé! Si us plau, revisa l'error
@@ -540,8 +538,6 @@ ca:
       expires_at: Caduca
       uses: Usos
     title: Convida persones
-  landing_strip_html: "<strong>%{name}</strong> és un usuari/a de %{link_to_root_path}. Pots seguir-lo/la o interactuar amb ell/a si tens un compte a qualsevol node del fediverse."
-  landing_strip_signup_html: Si no en tens, pots <a href="%{sign_up_path}">registrar-te aquí</a>.
   lists:
     errors:
       limit: Has assolit la quantitat màxima de llistes
@@ -710,7 +706,6 @@ ca:
       unlisted: No llistat
       unlisted_long: Tothom ho pot veure, però no es mostra en la història federada
   stream_entries:
-    click_to_show: Clic per mostrar
     pinned: Toot fixat
     reblogged: ha impulsat
     sensitive_content: Contingut sensible
diff --git a/config/locales/co.yml b/config/locales/co.yml
index 6608f05a9..4326dde67 100644
--- a/config/locales/co.yml
+++ b/config/locales/co.yml
@@ -46,7 +46,6 @@ co:
     people_who_follow: Seguitanu %{name}
     posts: Statuti
     posts_with_replies: Statuti è risposte
-    remote_follow: Siguità d’altrò
     reserved_username: Stu cugnome hè riservatu
     roles:
       admin: Amministratore
@@ -488,7 +487,6 @@ co:
     unlocked_warning_title: U vostru contu hè pubblicu
   generic:
     changes_saved_msg: Cambiamenti salvati!
-    powered_by: mossu da %{link}
     save_changes: Salvà e mudificazione
     validation_errors:
       one: Qualcosa ùn và bè! Verificate u prublemu quì sottu
@@ -523,8 +521,6 @@ co:
       expires_at: Spira
       uses: Utiliza
     title: Invità ghjente
-  landing_strip_html: "<strong>%{name}</strong> hè nant’à %{link_to_root_path}. Pudete seguitallu·a o cumunicà cù ellu·a cù un contu in qualche parte di u fediverse."
-  landing_strip_signup_html: Pudete ancu <a href="%{sign_up_path}">arrigistravi quì</a>.
   lists:
     errors:
       limit: Ùn pudete più creà altre liste
@@ -691,7 +687,6 @@ co:
       unlisted: Micca listatu
       unlisted_long: Tuttu u mondu pò vede, mà micca indè e linee pubbliche
   stream_entries:
-    click_to_show: Cliccà per vede
     pinned: Statutu puntarulatu
     reblogged: spartutu
     sensitive_content: Cuntenutu sensibile
diff --git a/config/locales/cs.yml b/config/locales/cs.yml
index 135ecda31..6529992dc 100644
--- a/config/locales/cs.yml
+++ b/config/locales/cs.yml
@@ -1,7 +1,7 @@
 ---
 cs:
   about:
-    about_hashtag_html: Toto jsou veřejné tooty označené jako <strong>#%{hashtag}</strong>. Pokud máte účet kdekoliv na fediverse, můžete s nimi interagovat.
+    about_hashtag_html: Toto jsou veřejné tooty označené hashtagem<strong>#%{hashtag}</strong>. Pokud máte účet kdekoliv na fediverse, můžete s nimi interagovat.
     about_mastodon_html: Mastodon je sociální síť založená na otevřených webových protokolech a svobodném, otevřeném softwaru. Je decentrovalizovaná jako e-mail.
     about_this: O této instanci
     administered_by: 'Server spravuje:'
@@ -18,14 +18,21 @@ cs:
     features:
       humane_approach_body: Mastodon, poučen z chyb jiných sociálních sítí, se snaží bojovat se zneužíváním sociálních sítí vytvářením etických možností.
       humane_approach_title: Lidštější přístup
+      not_a_product_body: Mastodon není komerční síť. Žádné reklamy, žádné dolování dat, žádné hranice. Žádná centrální autorita.
       not_a_product_title: Jste osoba, ne produkt
+      real_conversation_body: S 500 znaky k vaší dispozici a podporou pro varování o obsahu a médiích se můžete vyjadřovat tak, jak chcete.
+      real_conversation_title: Vytvořen pro opravdovou konverzaci
+      within_reach_body: Několik aplikací pro iOS, Android a jiné platformy vám díky jednoduchému API ekosystému dovolují držet krok s vašimi přáteli, ať už jste kdekoliv.
+      within_reach_title: Vždy v dosahu
     generic_description: "%{domain} je jedním serverem v síti"
+    hosted_on: Mastodon hostovaný na %{domain}
     learn_more: Zjistit více
+    other_instances: Seznam instancí
     source_code: Zdrojový kód
     status_count_after: příspěvků
-    status_count_before: Kdo je autorem
+    status_count_before: Kteří napsali
     user_count_after: uživatelů
-    user_count_before: Domov pro
+    user_count_before: Domov
     what_is_mastodon: Co je Mastodon?
   accounts:
     follow: Sledovat
@@ -35,10 +42,836 @@ cs:
     moved_html: 'Účet %{name} byl přesunut na %{new_profile_link}:'
     network_hidden: Tato informace není k dispozici
     nothing_here: Tady nic není!
+    people_followed_by: Lidé, které %{name} sleduje
+    people_who_follow: Lidé, kteří sledují uživatele %{name}
+    posts: Tooty
+    posts_with_replies: Tooty s odpověďmi
+    reserved_username: Toto uživatelské jméno je rezervováno
+    roles:
+      admin: Administrátor
+      bot: Robot
+      moderator: Moderátor
+    unfollow: Přestat sledovat
+  admin:
+    account_moderation_notes:
+      create: Zanechat poznámku
+      created_msg: Poznámka moderátora byla úspěšně vytvořena!
+      delete: Smazat
+      destroyed_msg: Poznámka moderátora byla úspěšně zničena!
+    accounts:
+      are_you_sure: Jste si jistý/á?
+      avatar: Avatar
+      by_domain: Doména
+      change_email:
+        changed_msg: E-mail k tomuto účtu byl úspěšně změněn!
+        current_email: Současný e-mail
+        label: Změnit e-mail
+        new_email: Nový e-mail
+        submit: Změnit e-mail
+        title: Změnit e-mail pro uživatele %{username}
+      confirm: Potvrdit
+      confirmed: Potvrzeno
+      confirming: Potvrzující
+      demote: Degradovat
+      disable: Zablokovat
+      disable_two_factor_authentication: Zakázat 2FA
+      disabled: Blokováno
+      display_name: Zobrazované jméno
+      domain: Doména
+      edit: Upravit
+      email: E-mail
+      email_status: Stav e-mailu
+      enable: Povolit
+      enabled: Povoleno
+      feed_url: URL proudu
+      followers: Sledovatelé
+      followers_url: URL sledovatelů
+      follows: Sleduje
+      inbox_url: URL přijatých zpráv
+      ip: IP
+      location:
+        all: Vše
+        local: Místní
+        remote: Vzdálené
+        title: Umístění
+      login_status: Stav přihlášení
+      media_attachments: Mediální přílohy
+      memorialize: Změnit na "in memoriam"
+      moderation:
+        all: Vše
+        silenced: Utišen
+        suspended: Suspendován
+        title: Moderace
+      moderation_notes: Moderační poznámky
+      most_recent_activity: Nejnovější aktivita
+      most_recent_ip: Nejnovější IP
+      not_subscribed: Neodebírá
+      order:
+        alphabetic: Abecedně
+        most_recent: Nejnovější
+        title: Pořadí
+      outbox_url: URL odchozích zpráv
+      perform_full_suspension: Provést plnou suspenzaci
+      profile_url: URL profilu
+      promote: Povýšit
+      protocol: Protokol
+      public: Veřejný
+      push_subscription_expires: Odebírání PuSH expiruje
+      redownload: Obnovit avatar
+      remove_avatar: Odstranit avatar
+      resend_confirmation:
+        already_confirmed: Tento uživatel je již potvrzen
+        send: Znovu odeslat potvrzovací e-mail
+        success: Potvrzovací e-mail byl úspěšně odeslán!
+      reset: Resetovat
+      reset_password: Obnovit heslo
+      resubscribe: Znovu odebírat
+      role: Oprávnění
+      roles:
+        admin: Administrátor
+        moderator: Moderátor
+        staff: Personál
+        user: Uživatel
+      salmon_url: URL Salmon
+      search: Hledat
+      shared_inbox_url: URL sdílené schránky
+      show:
+        created_reports: Nahlášení vytvořené z tohoto účtu
+        report: nahlášení
+        targeted_reports: Nahlášení vytvořena o tomto účtu
+      silence: Utišit
+      statuses: Statusy
+      subscribe: Odebírat
+      title: Účty
+      unconfirmed_email: Nepotvrzený e-mail
+      undo_silenced: Zrušit utišení
+      undo_suspension: Zrušit suspenzaci
+      unsubscribe: Přestat odebírat
+      username: Uživatelské jméno
+      web: Web
+    action_logs:
+      actions:
+        assigned_to_self_report: "%{name} přidělil/a hlášení %{target} sobě"
+        change_email_user: "%{name} změnil/a e-mailovou adresu uživatele %{target}"
+        confirm_user: "%{name} potvrdil/a e-mailovou adresu uživatele %{target}"
+        create_custom_emoji: "%{name} nahrál/a nové emoji %{target}"
+        create_domain_block: "%{name} zablokoval/a doménu %{target}"
+        create_email_domain_block: "%{name} přidal/a e-mailovou doménu %{target} na černou listinu"
+        demote_user: "%{name} degradoval/a uživatele %{target}"
+        destroy_domain_block: "%{name} odblokoval/a doménu %{target}"
+        destroy_email_domain_block: "%{name} odebral/a e-mailovou doménu %{target} z černé listiny"
+        destroy_status: "%{name} odstranil/a status uživatele %{target}"
+        disable_2fa_user: "%{name} vypnul/a požadavek pro dvoufaktorovou autentikaci pro uživatele %{target}"
+        disable_custom_emoji: "%{name} zakázal/a emoji %{target}"
+        disable_user: "%{name} zakázal/a přihlašování pro uživatele %{target}"
+        enable_custom_emoji: "%{name} povolil/a emoji %{target}"
+        enable_user: "%{name} povolil/a přihlašování pro uživatele %{target}"
+        memorialize_account: '%{name} změnil/a účet %{target} na stránku "in memoriam"'
+        promote_user: "%{name} povýšil/a uživatele %{target}"
+        remove_avatar_user: "%{name} odstranil/a avatar uživatele %{target}"
+        reopen_report: "%{name} znovuotevřel/a nahlášení %{target}"
+        reset_password_user: "%{name} resetoval/a heslo uživatele %{target}"
+        resolve_report: "%{name} vyřešil/a nahlášení %{target}"
+        silence_account: "%{name} utišil/a účet uživatele %{target}"
+        suspend_account: "%{name} suspendoval/a účet uživatele %{target}"
+        unassigned_report: "%{name} odebral/a nahlášení %{target}"
+        unsilence_account: "%{name} odtišil/a účet uživatele %{target}"
+        unsuspend_account: "%{name} zrušil/a suspenzaci účtu uživatele %{target}"
+        update_custom_emoji: "%{name} aktualizoval/a emoji %{target}"
+        update_status: "%{name} aktualizoval/a status uživatele %{target}"
+      title: Záznam auditu
+    custom_emojis:
+      by_domain: Doména
+      copied_msg: Místní kopie emoji byla úspěšně vytvořena
+      copy: Kopírovat
+      copy_failed_msg: Nebylo možné vytvořit místní kopii tohoto emoji
+      created_msg: Emoji úspěšně vytvořeno!
+      delete: Smazat
+      destroyed_msg: Emoji úspěšně zničeno!
+      disable: Zakázat
+      disabled_msg: Emoji bylo úspěšně zakázáno
+      emoji: Emoji
+      enable: Povolit
+      enabled_msg: Emoji bylo úspěšně povoleno
+      image_hint: PNG až do 50KB
+      listed: Uvedené
+      new:
+        title: Přidat nové vlastní emoji
+      overwrite: Přepsat
+      shortcode: Zkratka
+      shortcode_hint: Alespoň 2 znaky, pouze alfanumerické znaky a podtržítka
+      title: Vlastní emoji
+      unlisted: Neuvedené
+      update_failed_msg: Nebylo možné aktualizovat toto emoji
+      updated_msg: Emoji úspěšně aktualizováno!
+      upload: Nahrát
+    dashboard:
+      backlog: opožděné úlohy
+      config: Konfigurace
+      feature_deletions: Smazání účtů
+      feature_invites: Pozvánky
+      feature_registrations: Registrace
+      feature_relay: Federovací most
+      features: Vlastnosti
+      hidden_service: Federace se skrytými službami
+      open_reports: otevřená hlášení
+      recent_users: Nedávní uživatelé
+      search: Fulltextové vyhledávání
+      single_user_mode: Režim jednoho uživatele
+      software: Software
+      space: Využití prostoru
+      title: Přehled
+      total_users: uživatelů celkem
+      trends: Trendy
+      week_interactions: interakcí tento týden
+      week_users_active: aktivních tento týden
+      week_users_new: uživatelů tento týden
+    domain_blocks:
+      add_new: Přidat nové
+      created_msg: Blokace domény se právě vyřizuje
+      destroyed_msg: Blokace domény byla zrušena
+      domain: Doména
+      new:
+        create: Vytvořit blokaci
+        hint: Blokace domény nezakáže vytváření účtových záznamů v databázi, ale bude na tyto účty zpětně a automaticky aplikovat specifické metody moderace.
+        severity:
+          desc_html: Funkce <strong>Utišit</strong> zneviditelní příspěvky z účtu komukoliv, kdo jej nesleduje. Funkce <strong>Suspendovat</strong> odstraní všechen obsah, média a profilová data účtu. Pro pouhé odmítnutí mediálních souborů použijte funkci <strong>Žádné</strong>.
+          noop: Žádné
+          silence: Utišit
+          suspend: Suspendovat
+        title: Nová doménová blokace
+      reject_media: Odmítat mediální soubory
+      reject_media_hint: Odstraní lokálně uložené soubory a odmítne jejich stažení v budoucnosti. Irelevantní pro suspenzace
+      severities:
+        noop: Žádné
+        silence: Utišit
+        suspend: Suspendovat
+      severity: Přísnost
+      show:
+        affected_accounts:
+          one: Jeden účet v databázi byl ovlivněn
+          other: "%{count} účtů v databázi byl ovlivněn"
+        retroactive:
+          silence: Odtišit všechny existující účty z této domény
+          suspend: Zrušit suspenzaci všech existujících účtů z této domény
+        title: Zrušit blokaci domény %{domain}
+        undo: Odvolat
+      title: Doménové blokace
+      undo: Odvolat
+    email_domain_blocks:
+      add_new: Přidat nový
+      created_msg: E-mailová doména úspěšně přidána na černou listinu
+      delete: Smazat
+      destroyed_msg: E-mailová doména úspěšně odstraněna z černé listiny
+      domain: Doména
+      new:
+        create: Přidat doménu
+        title: Nový e-mail pro zablokování
+      title: Černá listina e-mailů
+    instances:
+      account_count: Známé účty
+      domain_name: Doména
+      reset: Resetovat
+      search: Hledat
+      title: Známé instance
+    invites:
+      filter:
+        all: Vše
+        available: Dostupné
+        expired: Vypršelé
+        title: Filtrovat
+      title: Pozvánky
+    relays:
+      add_new: Přidat nový most
+      description_html: "<strong>Federovací most</strong> je přechodný server, který vyměňuje velká množství veřejných tootů mezi servery, které z něj odebírají a poblikují na něj. <strong>Může pomoci malým a středně velkým serverům objevovat obsah z fediverse</strong>, což by jinak vyžadovalo, aby místní uživatelé manuálně sledovali jiné lidi na vzdálených serverech."
+      enable_hint: Je-li tohle povoleno, začne váš server odebírat všechny veřejné tooty z tohoto mostu a odesílat na něj své vlastní veřejné tooty.
+      inbox_url: URL mostu
+      setup: Nastavit připojení k mostu
+      status: Stav
+      title: Mosty
+    report_notes:
+      created_msg: Poznámka o nahlášení úspěšně vytvořena!
+      destroyed_msg: Poznámka o nahlášení úspěšně smazána!
+    reports:
+      account:
+        note: poznámka
+        report: nahlášení
+      action_taken_by: Akci vykonal/a
+      are_you_sure: Jste si jistý/á?
+      assign_to_self: Přidělit ke mně
+      assigned: Přiřazený moderátor
+      comment:
+        none: Žádné
+      created_at: Nahlášené
+      id: ID
+      mark_as_resolved: Označit jako vyřešené
+      mark_as_unresolved: Označit jako nevyřešené
+      notes:
+        create: Přidat poznámku
+        create_and_resolve: Vyřešit s poznámkou
+        create_and_unresolve: Znovu otevřít s poznámkou
+        delete: Smazat
+        placeholder: Popište, jaké akce byly vykonány, nebo jakékoliv jiné související aktuality...
+      reopen: Znovu otevřít nahlášení
+      report: 'Nahlásit #%{id}'
+      report_contents: Obsah
+      reported_account: Nahlášený účet
+      reported_by: Nahlášeno uživatelem
+      resolved: Vyřešeno
+      resolved_msg: Nahlášení úspěšně vyřešeno!
+      silence_account: Utišit účet
+      status: Stav
+      suspend_account: Suspendovat účet
+      target: Cíl
+      title: Nahlášení
+      unassign: Odebrat
+      unresolved: Nevyřešeno
+      updated_at: Aktualizováno
+      view: Zobrazit
+    settings:
+      activity_api_enabled:
+        desc_html: Počty lokálně publikovaných statusů, aktivních uživatelů a nových registrací, v týdenních intervalech
+        title: Publikovat hromadné statistiky o uživatelské aktivitě
+      bootstrap_timeline_accounts:
+        desc_html: Je-li uživatelskch jmen více, oddělujte je čárkami. Lze zadat pouze místní a odemknuté účty. Je-li tohle prázdné, jsou výchozí hodnotou všichni místní administrátoři.
+        title: Výchozí sledování pro nové uživatele
+      contact_information:
+        email: Pracovní e-mail
+        username: Uživatelské jméno kontaktu
+      hero:
+        desc_html: Zobrazuje se na hlavní stránce. Doporučuje se rozlišení alespoň 600x100px. Pokud toto není nastavené, bude zobrazena miniatura instance
+        title: Hlavní obrázek
+      peers_api_enabled:
+        desc_html: Domény, na které tato instanve narazila ve fediverse
+        title: Zveřejnit seznam objevených instancí
+      preview_sensitive_media:
+        desc_html: Náhledy odkazů na jiných stránkách budou zobrazeny i pokud jsou media označena jako citlivá
+        title: Zobrazovat v náhledech OpenGraph i citlivá média
+      registrations:
+        closed_message:
+          desc_html: Zobrazí se na hlavní stránce, jsou-li registrace uzavřeny. Můžete použít i HTML značky
+          title: Zpráva o uzavřených registracích
+        deletion:
+          desc_html: Dovolit každému smazání svého účtu
+          title: Zpřístupnit smazání účtu
+        min_invite_role:
+          disabled: Nikdo
+          title: Povolit pozvánky od
+        open:
+          desc_html: Povolit každému vytvořit si účet
+          title: Zpřístupnit registraci
+      show_known_fediverse_at_about_page:
+        desc_html: Je-li toto zapnuto, zobrazí se v náhledu tooty ze všech známých serverů na fediverse. Jinak budou zobrazeny pouze místní tooty.
+        title: Zobrazit celou známou fediverse na náhledu časové osy
+      show_staff_badge:
+        desc_html: Zobrazit na stránce uživatele odznak člena personálu
+        title: Zobrazit odznak personálu
+      site_description:
+        desc_html: Úvodní odstavec na hlavní straně a v meta značkách. Můžete zde používat HTML značky, hlavně <code>&lt;a&gt;</code> a <code>&lt;em&gt;</code>.
+        title: Popis instance
+      site_description_extended:
+        desc_html: Dobré místo pro vaše pravidla, pokyny a jiné věci, které vaši instanci odlišují od ostatních. Lze použít HTML značky
+        title: Vlastní doplňujísí informace
+      site_terms:
+        desc_html: Můžete si napsat vlastní zásady soukromí, podmínky používání či jiné legality. Můžete použít HTML značky
+        title: Vlastní podmínky používání
+      site_title: Název instance
+      thumbnail:
+        desc_html: Používáno pro náhledy přes OpenGraph a API. Doporučuje se rozlišení 1200x630px
+        title: Miniatura instance
+      timeline_preview:
+        desc_html: Zobrazit na hlavní straně veřejnou časovou osu
+        title: Náhled časové osy
+      title: Nastavení stránky
+    statuses:
+      back_to_account: Zpět na stránku účtu
+      batch:
+        delete: Vymazat
+        nsfw_off: Označit, že není citlivý
+        nsfw_on: Označit jako citlivý
+      failed_to_execute: Nepodařilo se vykonat
+      media:
+        title: Média
+      no_media: Žádná média
+      title: Statusy účtů
+      with_media: S médii
+    subscriptions:
+      callback_url: Zpáteční URL
+      confirmed: Potvrzeno
+      expires_in: Vyprší v
+      last_delivery: Poslední doručení
+      title: WebSub
+      topic: Téma
+    title: Administrace
+  admin_mailer:
+    new_report:
+      body: "%{reporter} nahlásil/a uživatele %{target}"
+      body_remote: Někdo z %{domain} nahlásil uživatele %{target}
+      subject: Nové nahlášení pro %{instance} (#%{id})
+  application_mailer:
+    notification_preferences: Změnit volby e-mailu
+    salutation: "%{name},"
+    settings: 'Změnit volby e-mailu: %{link}'
+    view: 'Zobrazit:'
+    view_profile: Zobrazit profil
+    view_status: Zobrazit status
+  applications:
+    created: Aplikace úspěšně vytvořena
+    destroyed: Aplikace úspěšně smazána
+    invalid_url: Zadaná adresa URL je neplatná
+    regenerate_token: Znovu vygenerovat přístupový token
+    token_regenerated: Přístupový token byl úspěšně vygenerován
+    warning: Buďte s těmito daty velmi opatrní. Nikdy je s nikým nesdílejte!
+    your_token: Váš přístupový token
+  auth:
+    agreement_html: Registrací souhlasíte s následováním <a href="%{rules_path}">pravidel této instance</a> a <a href="%{terms_path}">našich podmínek používání</a>.
+    change_password: Heslo
+    confirm_email: Potvrdit e-mail
+    delete_account: Odstranit účet
+    delete_account_html: Chcete-li odstranit svůj účet, <a href="%{path}">pokračujte zde</a>. Budete požádán/a o potvrzení.
+    didnt_get_confirmation: Neobdržel/a jste pokyny pro potvrzení?
+    forgot_password: Zapomněl/a jste heslo?
+    invalid_reset_password_token: Token na obnovu hesla je buď neplatný, nebo vypršel. Prosím vyžádejte si nový.
+    login: Přihlásit
+    logout: Odhlásit
+    migrate_account: Přesunout se na jiný účet
+    migrate_account_html: Chcete-li přesměrovat tento účet na jiný, můžete to <a href="%{path}">nastavit zde</a>.
+    or: nebo
+    or_log_in_with: Nebo se přihlaste pomocí
+    providers:
+      cas: CAS
+      saml: SAML
+    register: Registrovat
+    register_elsewhere: Registrovat na jiném serveru
+    resend_confirmation: Znovu odeslat pokyny pro potvrzení
+    reset_password: Obnovit heslo
+    security: Zabezpečení
+    set_new_password: Nastavit nové heslo
+  authorize_follow:
+    already_following: Tento účet již sledujete
+    error: Při hledání vzdáleného účtu bohužel nastala chyba
+    follow: Sledovat
+    follow_request: 'Poslal/a jste žádost o sledování uživateli:'
+    following: 'Podařilo se! Nyní sledujete uživatele:'
+    post_follow:
+      close: Nebo můžete toto okno klidně zavřít.
+      return: Zobrazit profil uživatele
+      web: Přejít na web
+    title: Sledovat uživatele %{acct}
+  datetime:
+    distance_in_words:
+      about_x_hours: "%{count} hod"
+      about_x_months: "%{count} měsíců"
+      about_x_years: "%{count} let"
+      almost_x_years: "%{count} let"
+      half_a_minute: Právě teď
+      less_than_x_minutes: "%{count} min"
+      less_than_x_seconds: Právě teď
+      over_x_years: "%{count} let"
+      x_days: "%{count} dní"
+      x_minutes: "%{count} min"
+      x_months: "%{count} mesíců"
+      x_seconds: "%{count} s"
+  deletes:
+    bad_password_msg: Dobrý pokus, hackeři! Nesprávné heslo
+    confirm_password: Zadejte svoje současné heslo pro ověření vaší identity
+    description_html: Tímto <strong>trvale a nenávratně</strong> odstraníte obsah z vašeho účtu a deaktivuje ho. Vaše uživatelské jméno zůstane rezervované pro zabránění budoucím napodobováním.
+    proceed: Odstranit účet
+    success_msg: Váš účet byl úspěšně odstraněn
+    warning_html: Pouze vymazání obsahu z této konkrétní instance je zaručeno. Obsah, který byl široce sdílen, po sobě pravděpodobně zanechá stopy. U offline serverů a serverů, které vaše aktualizace již neodebírají, nebudou databáze aktualizovány.
+    warning_title: Dostupnost rozšířeného obsahu
+  errors:
+    '403': Nemáte povolení zobrazit tuto stránku.
+    '404': Stránka, kterou hledáte, neexistuje.
+    '410': Stránka, kterou hledáte, již neexistuje.
+    '422':
+      content: Bezpečnostní ověření selhalo. Neblokujete cookoes?
+      title: Bezpečnostní ověření selhalo
+    '429': Příliš mnoho požadavků
+    '500':
+      content: Omlouváme se, ale něco se pokazilo u nás.
+      title: Tato stránka není správná
+    noscript_html: Pro použití webové aplikace Mastodon prosím povolte JavaScript. Nebo zkuste jednu z <a href="https://github.com/tootsuite/documentation/blob/master/Using-Mastodon/Apps.md">nativních aplikací</a> pro Mastodon pro vaši platformu.
+  exports:
+    archive_takeout:
+      date: Datum
+      download: Stáhnout svůj archiv
+      hint_html: Můžete si vyžádat archiv vašich <strong>tootů a nahraných médií</strong>. Exportovaná data budou ve formátu ActivityPub a budou čitelné kterýmkoliv kompatibilním softwarem. Archiv si můžete vyžádat každých 7 dní.
+      in_progress: Kompiluji váš archiv...
+      request: Vyžádat svůj archiv
+      size: Velikost
+    blocks: Blokujete
+    csv: CSV
+    follows: Sledujete
+    mutes: Ignorujete
+    storage: Úložisko médií
+  filters:
+    contexts:
+      home: Domovská časová osa
+      notifications: Oznámení
+      public: Veřejný časové osy
+      thread: Konverzace
+    edit:
+      title: Upravit filtr
+    errors:
+      invalid_context: Nebylo poskytnuto nic, nebo má neplatný kontext
+      invalid_irreversible: Nezvratné filtrování funguje pouze v souvislosti s domovskou osou či oznámeními
+    index:
+      delete: Smazat
+      title: Filtry
+    new:
+      title: Přidat nový filtr
+  followers:
+    domain: Doména
+    explanation_html: Chcete-li zaručit soukromí vašich statusů, musíte mít na vědomí, kdo vás sleduje. <strong>Vaše soukromé statusy jsou doručeny na všechny instance, kde máte sledovatele</strong>. Nejspíš si je budete chtít zkontrolovat a odstranit sledovatele na instancích, jejichž personálu či softwaru nedůvěřujete s respektováním vašeho soukromí.
+    followers_count: Počet sledovatelů
+    lock_link: Zamkněte svůj účet
+    purge: Odstranit ze sledovatelů
+    success:
+      one: V průběhu utišování sledovatelů z jedné domény...
+      other: V průběhu utišování sledovatelů z %{count} domén...
+    true_privacy_html: Berte prosím na vědomí, že <strong>skutečného soukromí se dá dosáhnout pouze za pomoci end-to-end šifrování</strong>.
+    unlocked_warning_html: Kdokoliv vás může sledovat a okamžitě vidět vaše soukromé statusy. %{lock_link}, abyste mohl/a zkontrolovat a odmítnout sledovatele.
+    unlocked_warning_title: Váš účet není zamknutý
+  generic:
+    changes_saved_msg: Změny byly úspěšně uloženy!
+    save_changes: Uložit změny
+    validation_errors:
+      one: Něco ještě není úplně v pořádku! Prosím zkontrolujte chybu níže
+      other: Něco ještě není úplně v pořádku! Prosím zkontrolujte %{count} chyb níže
+  imports:
+    preface: Můžete importovat data, která jste exportoval/a z jiné instance, jako například seznam lidí, které sledujete či blokujete.
+    success: Vaše data byla úspěšně nahrána a nyní budou zpracována v daný čas
+    types:
+      blocking: Seznam blokovaných
+      following: Seznam sledovaných
+      muting: Seznam ignorovaných
+    upload: Nahrát
+  in_memoriam_html: Navždy budeme vzpomínat.
+  invites:
+    delete: Deaktivovat
+    expired: Vypršelé
+    expires_in:
+      '1800': 30 minut
+      '21600': 6 hodin
+      '3600': 1 hodina
+      '43200': 12 hodin
+      '604800': 1 týden
+      '86400': 1 den
+    expires_in_prompt: Nikdy
+    generate: Vygenerovat
+    invited_by: 'Byl/a jste pozván/a uživatelem:'
+    max_uses:
+      one: 1 použití
+      other: "%{count} použití"
+    max_uses_prompt: Bez limitu
+    prompt: Vygenerujte a sdílejte s ostatními odkazy a umožněte jim přístup na tuto instanci
+    table:
+      expires_at: Vyprší
+      uses: Použití
+    title: Pozvěte lidi
+  lists:
+    errors:
+      limit: Dosáhl/a jste maximálního počtu seznamů
+  media_attachments:
+    validations:
+      images_and_video: Ke statusu, který již obsahuje obrázky, nelze připojit video
+      too_many: Nelze připojit více než 4 soubory
+  migrations:
+    acct: přezdívka@doména nového účtu
+    currently_redirecting: 'Váš profil má nastaveno přesměrování na:'
+    proceed: Uložit
+    updated_msg: Vaše nastavení migrace účtu bylo úspěšně aktualizováno!
+  moderation:
+    title: Moderace
+  notification_mailer:
+    digest:
+      action: Zobrazit všechna oznámení
+      body: Zde najdete stručný souhrn zpráv, které jste zmeškal/a od vaší poslední návštěvy %{since}
+      mention: "%{name} vás zmínil/a v:"
+      new_followers_summary:
+        one: Navíc jste získal/a jednoho nového sledovatele, zatímco jste byl/a pryč! Hurá!
+        other: Navíc jste získal/a %{count} nových sledovatelů, zatímco jste byl/a pryč! Hurá!
+      subject:
+        one: "Jedno nové oznámení od vaší poslední návštěvy \U0001F418"
+        other: "%{count} nových oznámení od vaší poslední návštěvy \U0001F418"
+      title: Ve vaší absenci...
+    favourite:
+      body: 'Váš status si oblíbil/a %{name}:'
+      subject: "%{name} si oblíbil/a váš status"
+      title: Nové oblíbení
+    follow:
+      body: "%{name} vás nyní sleduje!"
+      subject: "%{name} vás nyní sleduje"
+      title: Nový sledovatel
+    follow_request:
+      action: Spravovat žádosti o sledování
+      body: "%{name} žádá o povolení vás následovat"
+      subject: 'Čekající sledovatel: %{name}'
+      title: Nová žádost o sledování
+    mention:
+      action: Odpovědět
+      body: 'Byl/a jste zmíněn/a uživatelem %{name} v:'
+      subject: Byl/a jste zmíněn/a uživatelem %{name}
+      title: Nová zmínka
+    reblog:
+      body: 'Váš status byl boostnutý uživatelem %{name}:'
+      subject: "%{name} boostnul/a váš status"
+      title: Nové boostnutí
+  number:
+    human:
+      decimal_units:
+        format: "%n %u"
+        units:
+          billion: mld
+          million: mil
+          quadrillion: bld
+          thousand: tis
+          trillion: T
+  pagination:
+    newer: Novější
+    next: Starší
+    older: Starší
+    prev: Před
+    truncate: "&hellip;"
+  preferences:
+    languages: Jazyky
+    other: Ostatní
+    publishing: Publikování
+    web: Web
+  remote_follow:
+    acct: Napište svou přezdívku@doménu, ze které chcete sledovat
+    missing_resource: Nemůžeme najít požadované přesměrovací URL pro váš účet
+    no_account_html: Ještě nemáte účet? Můžete se <a href='%{sign_up_path}' target='_blank'>registrovat zde</a>
+    proceed: Pokračujte pro sledování
+    prompt: 'Budete sledovat:'
+  remote_unfollow:
+    error: Chyba
+    title: Nadpis
+    unfollowed: Už nesledujete
+  sessions:
+    activity: Nejnovější aktivita
+    browser: Prohlížeč
+    browsers:
+      alipay: Alipay
+      blackberry: Blackberry
+      chrome: Chrome
+      edge: Microsoft Edge
+      electron: Electron
+      firefox: Firefox
+      generic: Neznámý prohlížeč
+      ie: Internet Explorer
+      micro_messenger: MicroMessenger
+      nokia: Nokia S40 Ovi Browser
+      opera: Opera
+      otter: Otter
+      phantom_js: PhantomJS
+      qq: QQ Browser
+      safari: Safari
+      uc_browser: UCBrowser
+      weibo: Weibo
+    current_session: Aktuální relace
+    description: "%{browser} na %{platform}"
+    explanation: Toto jsou webové prohlížeče aktuálně přihlášené na váš účet Mastodon.
+    ip: IP
+    platforms:
+      adobe_air: Adobe Air
+      android: Android
+      blackberry: Blackberry
+      chrome_os: Chrome OS
+      firefox_os: Firefox OS
+      ios: iOS
+      linux: Linux
+      mac: Mac
+      other: neznámé platformě
+      windows: Windows
+      windows_mobile: Windows Mobile
+      windows_phone: Windows Phone
+    revoke: Zamítnout
+    revoke_success: Relace úspěšně zamítnuta
+    title: Relace
+  settings:
+    authorized_apps: Autorizované aplikace
+    back: Zpět na Mastodon
+    delete: Smazání účtu
+    development: Vývoj
+    edit_profile: Upravit profil
+    export: Export dat
+    followers: Autorizovaní sledovatelé
+    import: Import
+    migrate: Přesunutí účtu
+    notifications: Oznámení
+    preferences: Předvolby
+    settings: Nastavení
+    two_factor_authentication: Dvoufaktorové ověřování
+    your_apps: Vaše aplikace
+  statuses:
+    attached:
+      description: 'Přiloženo: %{attached}'
+      image:
+        one: "%{count} obrázek"
+        other: "%{count} obrázků"
+      video:
+        one: "%{count} video"
+        other: "%{count} videí"
+    boosted_from_html: Boostnuto z %{acct_link}
+    content_warning: 'Varování o obsahu: %{warning}'
+    disallowed_hashtags:
+      one: 'obsahuje nepovolený hashtag: %{tags}'
+      other: 'obsahuje nepovolené hashtagy: %{tags}'
+    language_detection: Zjistit jazyk automaticky
+    open_in_web: Otevřít na webu
+    over_character_limit: limit %{max} znaků byl překročen
+    pin_errors:
+      limit: Už jste si připnul/a maximální počet tootů
+      ownership: Nelže připnout toot někoho jiného
+      private: Nelze připnout neveřejné tooty
+      reblog: Nelze připnout boostnutí
+    show_more: Zobrazit více
+    title: '%{name}: "%{quote}"'
+    visibilities:
+      private: Pouze pro sledovatele
+      private_long: Zobrazit pouze sledovatelům
+      public: Veřejné
+      public_long: Všichni mohou vidět
+      unlisted: Neuvedené
+      unlisted_long: Všichni mohou vidět, ale není zahrnut ve veřejných časových osách
+  stream_entries:
+    pinned: Připnutý toot
+    reblogged: boostnutý
+    sensitive_content: CItlivý obsah
+  terms:
+    body_html: |
+      <h2>Zásady soukromí</h2>
+      <h3 id="collect">Jaké informace sbíráme?</h3>
+
+      <ul>
+        <li><em>Základní informace o účtu</em>: Pokud se na tomto serveru zaregistrujete, můžeme vás požádat o zadání uživatelského jména, e-mailové adresy a hesla. Můžete také zadat dodatečné profilové informace, jako například zobrazované jméno a krátký životopis, a nahrát si profilovou fotografii a hlavičkový obrázek. Uživatelské i zobrazované jméno, životopis, profilová fotografie a hlavičkový obrázek jsou vždy uvedeny veřejně.</li>
+        <li><em>Příspěvky, sledovatelé a další veřejné informace</em>: Seznam lidí, které sledujete, je uveden veřejně, totéž platí i pro vaše sledovatele. Když sem nahrajete zprávu, bude uloženo datum a čas, společně s aplikací, ze které jste zprávu odeslali. Zprávy mohou obsahovat mediální přílohy, jako jsou obrázky a videa. Veřejné a nezobrazované příspěvky jsou dostupné veřejně. Pokud na vašem profilu uvedete příspěvek, je to také veřejně dostupná informace. Vaše příspěvky jsou doručeny vašim sledovatelům, což v některých případech znamená, že budou doručeny na různé servery, na kterých budou ukládány kopie. Pokud příspěvky smažete, bude tohle taktéž doručeno vašim sledovatelům. Akce znovusdílení nebo oblíbení jiného příspěvku je vždy veřejná.</li>
+        <li><em>Příspěvky přímé a pouze pro sledovatele</em>: Všechny příspěvky jsou uloženy a zpracovány na serveru. Příspěvky pouze pro sledovatele jsou doručeny vašim sledovatelům a uživateům v nich zmíněných a přímé příspěvky jsou doručeny pouze uživatelům v nich zmíněných. V některých případech tohle znamená, že budou doručeny na různé servery, na kterých budou ukládány kopie. Snažíme se omezit přístup k těmto příspěvkům pouze na autorizované uživatele, ovšem jiné servery tak nemusejí učinit. Proto je důležité posoudit servery, ke kterým vaši sledovatelé patří. V nastavení si můžete zapnout volbu pro manuální schvalování či odmítnutí nových sledovatelů. <em>Prosím mějte na paměti, že operátoři tohoto serveru a kteréhokoliv přijímacího serveru mohou tyto zprávy vidět</em> a příjemci mohou vytvořit jejich snímek, zkopírovat je, nebo je jinak sdílet. <em>Nesdílejte přes Mastodon jakékoliv nebezpečné informace.</em></li>
+        <li><em>IP adresy a další metadata</em>: Když se přihlásíte, zaznamenáváme IP adresu, ze které se přihlašujete, jakožto i název vašeho webového prohlížeče. Všechny vaše webové relace jsou v nastavení přístupné k vašemu posouzení a odvolání. Nejpozdější IP adresa použita je uložena maximálně do 12 měsíců. Můžeme také uchovávat serverové záznamy, které obsahují IP adresy každého požadavku odeslaného na náš server.</li>
+      </ul>
+
+      <hr class="spacer" />
+
+      <h3 id="use">Na co používáme vaše informace?</h3>
+
+      <p>Jakékoliv informace, které sbíráme, mohou být použity následujícími způsoby:</p>
+
+      <ul>
+        <li>K poskytnutí základních funkcí Mastodonu. Interagovat s obsahem od jiných lidí a přispívat svým vlastním obsahem můžete pouze, pokud jste přihlášeni. Můžete například sledovat jiné lidi a zobrazit si jejich kombinované příspěvky ve vaší vlastní personalizované časové ose.</li>
+        <li>Pro pomoc moderaci komunity, například porovnáním vaší IP adresy s dalšími známými adresami pro určení vyhýbání se zákazům či jiných přestupků.</li>
+        <li>E-mailová adresa, kterou nám poskytnete, může být použita pro zasílání informací, oznámení o interakcích jiných uživatelů s vaším obsahem nebo přijatých zprávách a k odpovědím na dotazy a/nebo další požadavky či otázky.</li>
+      </ul>
+
+      <hr class="spacer" />
+
+      <h3 id="protect">Jak vaše informace chráníme?</h3>
+
+      <p>Implenentujeme různá bezpečnostní opatření pro udržování bezpečnosti vašich osobních dat, když zadáváte, odesíláte, či přistupujete k vašim osobním datům. Mimo jiné je vaše relace v prohlížeči, jakož i provoz mezi vašimi aplikacemi a API, zabezpečena pomocí SSL, a vaše heslo je hashováno pomocí silného jednosměrného algoritmu. Pro větší zabezpečení vašeho účtu můžete povolit dvoufaktorovou autentikaci.</p>
+
+      <hr class="spacer" />
+
+      <h3 id="data-retention">Jaké jsou naše zásady o uchovávání údajů?</h3>
+
+      <p>Budeme se snažit:</p>
+
+      <ul>
+        <li>Uchovávat serverové záznamy obsahující IP adresy všech požadavků pro tento server, pokud se takové záznamy uchovávají, maximálně 90 dní.</li>
+        <li>Uchovávat IP adresy související s registrovanými uživateli maximálně 12 měsíců.</li>
+      </ul>
+
+      <p>Kdykoliv si můžete vyžádat a stáhnout archiv vašeho obsahu, včetně vašich příspěvků, mediálních příloh, profilové fotografie a hlavičkového obrázku.</p>
+
+      <p>Kdykoliv můžete nenávratně smazat váš účet.</p>
+
+      <hr class="spacer"/>
+
+      <h3 id="cookies">Používáme cookies?</h3>
+
+      <p>Ano. Cookies jsou malé soubory, které stránka nebo její poskytovatel uloží na pevný disk vašeho počítače (pokud to dovolíte). Tyto cookies umožňují stránce rozpoznat váš prohlížeč a, pokud máte registrovaný účet, přidružit ho s vaším registrovaným účtem.</p>
+
+      <p>POužíváme cookies pro pochopení a ukládání vašich předvoleb pro budoucí návštěvy.</p>
+
+      <hr class="spacer" />
+
+      <h3 id="disclose">Zveřejňujeme jakékoliv informace třetím stranám?</h3>
+
+      <p>Vaše osobně identifikovatelné informace neprodáváme, neobchodujeme s nimi, ani je nijak nepřenášíme vnějším stranám. Do tohoto se nepočítají důvěryhodné třetí strany, které nám pomáhají provozovat naši stránku, podnikat, nebo vás obsluhovat, pokud tyto strany souhlasí se zachováním důvěrnosti těchto informací. Můžeme také uvolnit vaše informace, pokud věříme, že je to nutné pro soulad se zákonem, prosazování našich zásad, nebo ochranu práv, majetku, či bezpečnost nás či ostatních.</p>
+
+      <p>Váš veřejný obsah může být stažen jinými servery na síti. Vaše příspěvky veřejné a pouze pro sledovatele budou doručeny na servery vašich sledovatelů a přímé zprávy budou doručeny na servery příjemců, pokud jsou tito sledovatelé nebo příjemci zaregistrováni na jiném serveru, než je tento.</p>
+
+      <p>Když autorizujete aplikaci, aby používala váš účet, může, v závislosti na rozsahu oprávnění, které jí udělíte, přistupovat k vašim veřejným profilovým informacím, seznamu lidí, které sledujete, vašim sledovatelům, vašim seznamům, všem vašim příspěvkům a příspěvkům, které jste si oblíbili. Aplikace nikdy nemohou získat vaši e-mailovou adresu či heslo.</p>
+
+      <hr class="spacer" />
+
+      <h3 id="children">Používání stránky dětmi</h3>
+
+      <p>Pokud se tento server nachází v EU nebo EHP: Naše stránka, produkty a služby jsou všechny směřovány na lidi, kterým je alespoň 16 let. Pokud je vám méně než 16, dle požadavků nařízení GDPR (<a href="https://cs.wikipedia.org/wiki/Obecn%C3%A9_na%C5%99%C3%ADzen%C3%AD_o_ochran%C4%9B_osobn%C3%ADch_%C3%BAdaj%C5%AF">Obecné nařízení o ochě sobních údajů</a>) </p>
+
+      <p>Pokud se tento server nachází v USA: Naše stránka, produkty a služby jsou všechny směřovány na lidi, kterým je alespoň 13 let. Pokud je vám méně než 13, dle požadavků zákona COPPA (<a href="https://cs.wikipedia.org/wiki/Children%27s_online_privacy_protection_act">Children's Online Privacy Protection Act</a>) tuto stránku nepoužívejte.</p>
+
+      <p>Právní požadavky mohou být jiné, pokud se tento server nachází v jiné jurisdikci.</p>
+
+      <hr class="spacer" />
+
+      <h3 id="changes">Změny v našich zásadách soukromí</h3>
+
+      <p>Rozhodneme-li se naše zásady soukromí změnit, zveřejníme tyto změny na této stránce.</p>
+
+      <p>Tento dokument je dostupný pod licencí CC-BY-SA. Byl naposledy aktualizován 7 března 2018.</p>
+
+      <p>Původně adaptováno ze <a href="https://github.com/discourse/discourse">zásad soukromí Discourse</a>.</p>
+    title: Podmínky používání a zásady soukromí %{instance}
+  themes:
+    contrast: Vysoký kontrast
+    default: Mastodon
+    mastodon-light: Mastodon (světlý)
+  time:
+    formats:
+      default: "%d. %b %Y, %H:%M"
+  two_factor_authentication:
+    code_hint: Pro potvrzení zadejte kód vygenerovaný vaší autentikační aplikací
+    description_html: Povolíte-li <strong>dvoufaktorové ověřování</strong>, budete při přihlášení potřebovat telefon, který vám vygeneruje přístupové tokeny, které musíte zadat.
+    disable: Zakázat
+    enable: Povolit
+    enabled: Dvoufaktorové ověřování je povoleno
+    enabled_success: Dvoufaktorové ověřování bylo úspěšně povoleno
+    generate_recovery_codes: Vygenerovat záložní kódy
+    instructions_html: "<strong>Naskenujte tento QR kód Google Authenticatorem nebo jinou TOTP aplikací na vašem telefonu</strong>. Od teď bude tato aplikace generovat tokeny, které budete muset zadat při přihlášení."
+    lost_recovery_codes: Záložní kódy vám dovolí dostat se k vašemu účtu, pokud ztratíte telefon. Ztratíte-li záložní kódy, můžete je zde znovu vygenerovat. Vaše staré záložní kódy budou zneplatněny.
+    manual_instructions: 'Nemůžete-li oskenovat QR kód a je potřebovat ho zadat ručně, zde je tajemství v prostém textu:'
+    recovery_codes: Záložní kódy pro obnovu
+    recovery_codes_regenerated: Záložní kódy byly úspěšně znovu vygenerované
+    recovery_instructions_html: Ztratíte-li někdy přístup k vašemu telefonu, můžete k získání přístupu k účtu použít jeden ze záložních kódů. <strong>Uchovávejte tyto kódy v bezpečí</strong>. Můžete si je například vytisknout a uložit je mezi jiné důležité dokumenty.
+    setup: Nastavit
+    wrong_code: Zadaný kód byl neplatný! Je serverový čas a čas na zařízení správný?
   user_mailer:
+    backup_ready:
+      explanation: Vyžádal/a jste si úplnou zálohu svého účtu Mastodon. Nyní je připravena ke stažení!
+      subject: Váš archiv je připraven ke stažení
+      title: Stažení archivu
     welcome:
+      edit_profile_action: Nastavit profil
+      edit_profile_step: Můžete si přizpůsobit svůj profil nahráním avataru a obrázku na hlavičce, změnou zobrazovaného jména a dalších. Chcete-li posoudit nové sledovatele předtím, než vás mohou sledovat, můžete svůj účet uzamknout.
+      explanation: Zde je pár tipů na začátek
+      final_action: Začněte přispívat
+      final_step: 'Začněte psát! I když nemáte sledovatele, mohou vaše zprávy vidět jiní lidé, například na místní časové ose a mezi hashtagy. Můžete se ostatním představit pomocí hashtagu #introductions.'
+      full_handle: Vaše celá adresa profilu
+      full_handle_hint: Tohle je, co byste řekl/a svým přátelům, aby vám mohli posílat zprávy nebo vás sledovat z jiné instance.
+      review_preferences_action: Změnit nastavení
+      review_preferences_step: Nezapomeňte si nastavit své volby, například jaké e-maily chcete přijímat či jak soukromé mají být vaše příspěvky ve výchozím stavu. Nemáte-li epilepsii, můžete si nastavit automatické přehrávání obrázků GIF.
+      subject: Vítejte na Mastodonu
+      tip_bridge_html: Pokud přicházíte z Twitteru, můžete najít vaše přátele na Mastodonu pomocí <a href="%{bridge_url}">mostové aplikace</a>. Funguje ovšem pouze, pokud ji oni někdy také použili!
+      tip_federated_timeline: Federovaná časová osa je náhled celé sítě Mastodon. Zahrnuje ovšem pouze lidi, které sledují vaši sousedé, takže není úplná.
+      tip_following: Administrátora/y serveru sledujete automaticky. Chcete-li najít další zajímavé lidi, podívejte se na místní a federované časové osy.
+      tip_local_timeline: Místní časová osa je náhled lidí na %{instance}. Toto jsou vaši nejbližší sousedé!
+      tip_mobile_webapp: Pokud vám váš mobilní prohlížeč nabídne přidat si Mastodon na vaši domovskou obrazovku, můžete dostávat oznámení. V mnoha ohledech to funguje jako nativní aplikace!
       tips: Tipy
       title: Vítejte na palubě, %{name}!
   users:
     invalid_email: E-mailová adresa je neplatná
+    invalid_otp_token: Neplatný kód pro dvoufaktorovou autentikaci
+    otp_lost_help_html: Pokud jste ztratil/a přístup k oběma, můžete se spojit %{email}
+    seamless_external_login: Jste přihlášen/a přes externí službu, nastavení hesla a e-mailu proto nejsou dostupná.
     signed_in_as: 'Přihlášen/a jako:'
diff --git a/config/locales/da.yml b/config/locales/da.yml
index 7f9cd1e1e..4c7f0f550 100644
--- a/config/locales/da.yml
+++ b/config/locales/da.yml
@@ -46,7 +46,6 @@ da:
     people_who_follow: Folk der følger %{name}
     posts: Dyt
     posts_with_replies: Toots og svar
-    remote_follow: Følg fra andre instanser
     reserved_username: Brugernavnet er reserveret
     roles:
       admin: Administrator
@@ -464,7 +463,6 @@ da:
     unlocked_warning_title: Din konto er ikke låst
   generic:
     changes_saved_msg: Ændringerne blev gemt!
-    powered_by: drevet af %{link}
     save_changes: Gem ændringer
   imports:
     types:
@@ -511,6 +509,9 @@ da:
       action: Se alle notifikationer
       mention: "%{name} nævnte dig i:"
       title: Mens du var væk...
+    favourite:
+      body: 'Din status blev favoriseret af %{name}:'
+      subject: "%{name} favoriserede din status"
     follow:
       body: "%{name} følger dig nu!"
       subject: "%{name} følger dig nu"
@@ -538,18 +539,22 @@ da:
   preferences:
     languages: Sprog
     other: Andet
+    publishing: Offentligører
     web: Web
   remote_unfollow:
     error: Fejl
     title: Titel
     unfollowed: Følger ikke længere
   sessions:
+    activity: Sidste aktivitet
+    browser: Browser
     browsers:
       blackberry: Blackberry OS
       chrome: Google Chrome
       firefox: Mozilla Firefox
       generic: Ukendt browser
       ie: IE
+      safari: Apple Safari
     description: "%{browser} på %{platform}"
     ip: IP
     platforms:
@@ -583,7 +588,9 @@ da:
     content_warning: 'Advarsel om indhold: %{warning}'
     language_detection: Opfang automatisk sprog
     pin_errors:
+      limit: Du har allerede fastgjort det maksimale antal trut
       ownership: Dun kan ikke fastgøre en anden persons toot
+      private: Ikke offentlige trut kan ikke blive fastgjort
     show_more: Vis mere
     title: '%{name}: "%{quote}"'
     visibilities:
@@ -593,7 +600,6 @@ da:
       public_long: Alle kan se
       unlisted: Ikke listet
   stream_entries:
-    click_to_show: Tryk for at vise
     pinned: Fastgjort toot
     sensitive_content: Følsomt indhold
   themes:
diff --git a/config/locales/de.yml b/config/locales/de.yml
index bab45223d..dbd04e2ba 100644
--- a/config/locales/de.yml
+++ b/config/locales/de.yml
@@ -46,7 +46,6 @@ de:
     people_who_follow: Profile, die %{name} folgen
     posts: Beiträge
     posts_with_replies: Beiträge mit Antworten
-    remote_follow: Folgen
     reserved_username: Dieser Profilname ist belegt
     roles:
       admin: Admin
@@ -517,7 +516,6 @@ de:
     unlocked_warning_title: Dein Konto ist nicht gesperrt
   generic:
     changes_saved_msg: Änderungen gespeichert!
-    powered_by: angetrieben von %{link}
     save_changes: Änderungen speichern
     validation_errors:
       one: Etwas ist noch nicht ganz richtig! Bitte korrigiere den Fehler
@@ -553,8 +551,6 @@ de:
       expires_at: Läuft ab
       uses: Verwendungen
     title: Leute Einladen
-  landing_strip_html: "<strong>%{name}</strong> hat ein Profil auf %{link_to_root_path}. Du kannst folgen oder interagieren, sofern du ein Konto irgendwo im Fediversum hast."
-  landing_strip_signup_html: Wenn nicht, kannst du dich <a href="%{sign_up_path}">hier anmelden</a>.
   lists:
     errors:
       limit: Du hast die maximale Anzahl an Listen erreicht
@@ -723,7 +719,6 @@ de:
       unlisted: Nicht gelistet
       unlisted_long: Für alle sichtbar, aber nicht in öffentlichen Zeitleisten aufgelistet
   stream_entries:
-    click_to_show: Klicken, um zu zeigen
     pinned: Angehefteter Beitrag
     reblogged: teilte
     sensitive_content: Heikle Inhalte
diff --git a/config/locales/devise.ast.yml b/config/locales/devise.ast.yml
index 0967ef424..0b77eecf2 100644
--- a/config/locales/devise.ast.yml
+++ b/config/locales/devise.ast.yml
@@ -1 +1,2 @@
-{}
+---
+ast:
diff --git a/config/locales/devise.cs.yml b/config/locales/devise.cs.yml
index adaa40835..19593cbac 100644
--- a/config/locales/devise.cs.yml
+++ b/config/locales/devise.cs.yml
@@ -8,3 +8,35 @@ cs:
     failure:
       already_authenticated: Již jste přihlášen/a.
       inactive: Váš účet ještě není aktivován.
+      invalid: Neplatné %{authentication_keys} nebo heslo.
+      last_attempt: Máte ještě jeden pokus, než bude váš účet uzamčen.
+      locked: Váš účet je uzamčen.
+      not_found_in_database: Neplatné %{authentication_keys} nebo heslo.
+      timeout: Vaše relace vypršela. Pro pokračování se prosím přihlaste znovu.
+      unauthenticated: Před pokračováním se musíte přihlásit nebo registrovat.
+      unconfirmed: Před pokračováním musíte potvrdit svůj e-mail.
+    mailer:
+      confirmation_instructions:
+        action: Potvrdit e-mailovou adresu
+        explanation: S touto e-mailovou adresou jste si vytvořil/a účet na %{host}. K jeho aktivaci vám zbývá jedno kliknutí. Pokud jste to nebyl/a vy, ignorujte této e-mail.
+        extra_html: Prosím podívejte se také na <a href="%{terms_path}">pravidla této instance</a> a <a href="%{policy_path}">naše podmínky používání</a>.
+        subject: 'Mastodon: Potvrzovací instrukce pro %{instance}'
+        title: Potvrďte e-mailovou adresu
+      email_changed:
+        explanation: 'E-mailová adresa vašeho účtu byla změněna na:'
+        extra: Pokud jste si e-mail nezměnil/a, je pravděpodobné, že někdo jiný získal přístup k vašemu účtu. Prosím změňte si okamžitě heslo, nebo, pokud se nemůžete na účet přihlásit, kontaktujte administrátora instance.
+        subject: 'Mastodon: E-mail byl změněn'
+        title: Nová e-mailová adresa
+      password_change:
+        explanation: Heslo k vašemu účtu bylo změněno.
+        extra: Pokud jste si heslo nezměnil/a, je pravděpodobné, že někdo jiný získal přístup k vašemu účtu. Prosím změňte si okamžitě heslo, nebo, pokud se nemůžete na účet přihlásit, kontaktujte administrátora instance.
+        subject: 'Mastodon: Heslo bylo změněno'
+        title: Heslo bylo změněno
+      reconfirmation_instructions:
+        explanation: Potvrďte novou adresu pro změnu e-mailu.
+        extra: Pokud jste tuto akci nevyžádal/a vy, prosím ignorujte tento e-mail. E-mailová adresa nebude změněna, dokud nepřejdete na výše uvedenou adresu.
+        subject: 'Mastodon: Potvrďte e-mail pro %{instance}'
+        title: Ověřit e-mailovou adresu
+      reset_password_instructions:
+        action: Změnit heslo
+        explanation: Vyžádal/a jste si pro svůj účet nové heslo.
diff --git a/config/locales/devise.tr.yml b/config/locales/devise.tr.yml
deleted file mode 100644
index fb819978f..000000000
--- a/config/locales/devise.tr.yml
+++ /dev/null
@@ -1,51 +0,0 @@
----
-tr:
-  simple_form:
-    hints:
-      defaults:
-        avatar: En fazla 2MB olacak şekilde PNG, GIF veya JPG formatında yükleyiniz. 400x400px büyüklüğüne indirgenecektir
-        display_name: "%{count} karakter kaldı"
-        header: En fazla 2MB olacak şekilde PNG, GIF veya JPG formatında yükleyiniz. 700x335px büyüklüğüne indirgenecektir.
-        locked: Takipçilerinizi manuel olarak kabul etmenizi ve gönderilerinizi varsayılan olarak sadece takipçilerinizin göreceği şekilde paylaşmanızı sağlar.
-        note: "%{count} karakter kaldı"
-      imports:
-        data: Diğer Mastodon sunucusundan dışarı aktardığınız CSV dosyası
-      sessions:
-        otp: Telefonunuzdaki two-factor kodunuzu giriniz veya kurtarma kodlarınızdan birini giriniz.
-    labels:
-      defaults:
-        avatar: Profil resmi
-        confirm_new_password: Yeni parolanız (tekrar)
-        confirm_password: Parolanız (tekrar)
-        current_password: Mevcut parolanız
-        data: Dosya
-        display_name: Görünen adınız
-        email: E-posta adresiniz
-        header: Kapak resmi
-        locale: Dil
-        locked: Hesabımı kilitle
-        new_password: Yeni parolanız
-        note: Kişisel bilgiler
-        otp_attempt: İki-faktörlü kod
-        password: Parolanız
-        setting_auto_play_gif: GIF'leri otomatik oynatt
-        setting_boost_modal: Boost etmeden önce onay diyaloğu göster
-        setting_default_privacy: Gönderi gizliliği
-        severity: Zorluk
-        type: Dosya türü
-        username: Kullanıcı adınız
-      interactions:
-        must_be_follower: Takipçim olmayan kişilerden gelen bildirimleri engelle
-        must_be_following: Takip etmediğim kişilerden gelen bildirimleri engelle
-      notification_emails:
-        digest: Özet e-postaları gönder
-        favourite: Biri durumumu favorilerine eklediginde bana e-posta gönder
-        follow: Biri beni takip ettiğinde bana e-posta gönder
-        follow_request: Biri bana takip isteği gönderdiğinde, bana e-posta gönder
-        mention: Biri benden bahsettiğinde, bana e-posta gönder
-        reblog: Biri durumumu paylaştığında, bana e-posta gönder
-    'no': Hayır
-    required:
-      mark: "*"
-      text: gerekli
-    'yes': Evet
diff --git a/config/locales/doorkeeper.ast.yml b/config/locales/doorkeeper.ast.yml
index 0967ef424..0b77eecf2 100644
--- a/config/locales/doorkeeper.ast.yml
+++ b/config/locales/doorkeeper.ast.yml
@@ -1 +1,2 @@
-{}
+---
+ast:
diff --git a/config/locales/el.yml b/config/locales/el.yml
index 7fd48b7d2..905564317 100644
--- a/config/locales/el.yml
+++ b/config/locales/el.yml
@@ -46,7 +46,6 @@ el:
     people_who_follow: Χρήστες που ακολουθούν τον/την %{name}
     posts: Τουτ
     posts_with_replies: Τουτ και απαντήσεις
-    remote_follow: Απομακρυσμένη παρακολούθηση
     reserved_username: Το όνομα χρήστη είναι κατειλημμένο
     roles:
       admin: Διαχειριστής
@@ -536,7 +535,6 @@ el:
     unlocked_warning_title: Ο λογαριασμός σου δεν είναι κλειδωμένος
   generic:
     changes_saved_msg: Οι αλλαγές αποθηκεύτηκαν!
-    powered_by: παρέχεται από %{link}
     save_changes: Αποθήκευσε αλλαγές
     validation_errors:
       one: Κάτι δεν είναι εντάξει ακόμα! Για κοίταξε το παρακάτω σφάλμα
@@ -572,8 +570,6 @@ el:
       expires_at: Λήγει
       uses: Χρήσεις
     title: Προσκάλεσε άτομα
-  landing_strip_html: Ο/Η <strong>%{name}</strong> είναι χρήστης στο %{link_to_root_path}. Μπορείς να ακολουθήσεις ή να αλληλεπιδράσεις μαζί τους αν έχεις λογαριασμό οπουδήποτε στο fediverse.
-  landing_strip_signup_html: Αν όχι, μπορείς να <a href="%{sign_up_path}">γραφτείς εδώ</a>.
   lists:
     errors:
       limit: Έχεις φτάσει το μέγιστο πλήθος επιτρεπτών λιστών
@@ -741,7 +737,6 @@ el:
       unlisted: Ακαταχώριστο
       unlisted_long: Βλέπει οποιοσδήποτε, αλλά δεν καταχωρείται στις δημόσιες ροές
   stream_entries:
-    click_to_show: Κλικ για εμφάνιση
     pinned: Καρφιτσωμένο τουτ
     reblogged: προωθημένο
     sensitive_content: Ευαίσθητο περιεχόμενο
diff --git a/config/locales/en.yml b/config/locales/en.yml
index f933dc53b..ae4da9c7f 100644
--- a/config/locales/en.yml
+++ b/config/locales/en.yml
@@ -5,11 +5,13 @@ en:
     about_mastodon_html: Mastodon is a social network based on open web protocols and free, open-source software. It is decentralized like e-mail.
     about_this: About
     administered_by: 'Administered by:'
+    api: API
     closed_registrations: Registrations are currently closed on this instance. However! You can find a different instance to make an account on and get access to the very same network from there.
     contact: Contact
     contact_missing: Not set
     contact_unavailable: N/A
     description_headline: What is %{domain}?
+    documentation: Documentation
     domain_count_after: other instances
     domain_count_before: Connected to
     extended_description_html: |
@@ -28,9 +30,11 @@ en:
     hosted_on: Mastodon hosted on %{domain}
     learn_more: Learn more
     other_instances: Instance list
+    privacy_policy: Privacy policy
     source_code: Source code
     status_count_after: statuses
     status_count_before: Who authored
+    terms: Terms of service
     user_count_after: users
     user_count_before: Home to
     what_is_mastodon: What is Mastodon?
@@ -38,6 +42,7 @@ en:
     follow: Follow
     followers: Followers
     following: Following
+    joined: Joined %{date}
     media: Media
     moved_html: "%{name} has moved to %{new_profile_link}:"
     network_hidden: This information is not available
@@ -46,7 +51,6 @@ en:
     people_who_follow: People who follow %{name}
     posts: Toots
     posts_with_replies: Toots and replies
-    remote_follow: Remote follow
     reserved_username: The username is reserved
     roles:
       admin: Admin
@@ -534,9 +538,12 @@ en:
     true_privacy_html: Please mind that <strong>true privacy can only be achieved with end-to-end encryption</strong>.
     unlocked_warning_html: Anyone can follow you to immediately view your private statuses. %{lock_link} to be able to review and reject followers.
     unlocked_warning_title: Your account is not locked
+  footer:
+    developers: Developers
+    more: More…
+    resources: Resources
   generic:
     changes_saved_msg: Changes successfully saved!
-    powered_by: powered by %{link}
     save_changes: Save changes
     use_this: Use this
     validation_errors:
@@ -573,17 +580,6 @@ en:
       expires_at: Expires
       uses: Uses
     title: Invite people
-  keyword_mutes:
-    add_keyword: Add keyword
-    apply_to_mentions: Apply to mentions
-    edit: Edit
-    edit_keyword: Edit keyword
-    keyword: Keyword
-    match_whole_word: Match whole word
-    remove: Remove
-    remove_all: Remove all
-  landing_strip_html: "<strong>%{name}</strong> is a user on %{link_to_root_path}. You can follow them or interact with them if you have an account anywhere in the fediverse."
-  landing_strip_signup_html: If you don't, you can <a href="%{sign_up_path}">sign up here</a>.
   lists:
     errors:
       limit: You have reached the maximum amount of lists
@@ -754,7 +750,6 @@ en:
       unlisted: Unlisted
       unlisted_long: Everyone can see, but not listed on public timelines
   stream_entries:
-    click_to_show: Click to show
     pinned: Pinned toot
     reblogged: boosted
     sensitive_content: Sensitive content
@@ -848,6 +843,7 @@ en:
   time:
     formats:
       default: "%b %d, %Y, %H:%M"
+      month: "%b %Y"
   two_factor_authentication:
     code_hint: Enter the code generated by your authenticator app to confirm
     description_html: If you enable <strong>two-factor authentication</strong>, logging in will require you to be in possession of your phone, which will generate tokens for you to enter.
diff --git a/config/locales/eo.yml b/config/locales/eo.yml
index 156088af9..72010a085 100644
--- a/config/locales/eo.yml
+++ b/config/locales/eo.yml
@@ -46,7 +46,6 @@ eo:
     people_who_follow: Sekvantoj de %{name}
     posts: Mesaĝoj
     posts_with_replies: Mesaĝoj kaj respondoj
-    remote_follow: Fore sekvi
     reserved_username: La uzantnomo estas rezervita
     roles:
       admin: Administranto
@@ -517,7 +516,6 @@ eo:
     unlocked_warning_title: Via konto ne estas ŝlosita
   generic:
     changes_saved_msg: Ŝanĝoj sukcese konservitaj!
-    powered_by: povigita de %{link}
     save_changes: Konservi ŝanĝojn
     validation_errors:
       one: Io mise okazis! Bonvolu konsulti la suban erar-raporton
@@ -553,8 +551,6 @@ eo:
       expires_at: Eksvalidiĝas je
       uses: Uzoj
     title: Inviti homojn
-  landing_strip_html: "<strong>%{name}</strong> estas uzanto en %{link_to_root_path}. Vi povas sekvi tiun aŭ interagi kun tiu, se vi havas konton ie ajn en la fediverse."
-  landing_strip_signup_html: Se vi ne havas, vi povas <a href="%{sign_up_path}">registriĝi ĉi tie</a>.
   lists:
     errors:
       limit: Vi atingis la maksimuman kvanton de listoj
@@ -723,7 +719,6 @@ eo:
       unlisted: Nelistigita
       unlisted_long: Ĉiuj povas vidi, sed nelistigita en publikaj tempolinioj
   stream_entries:
-    click_to_show: Alklaki por montri
     pinned: Alpinglita
     reblogged: diskonigita
     sensitive_content: Tikla enhavo
diff --git a/config/locales/es.yml b/config/locales/es.yml
index 9a7cb62fe..53dde4f71 100644
--- a/config/locales/es.yml
+++ b/config/locales/es.yml
@@ -45,7 +45,6 @@ es:
     people_who_follow: Usuarios que siguen a %{name}
     posts: Toots
     posts_with_replies: Toots con respuestas
-    remote_follow: Seguir
     reserved_username: El nombre de usuario está reservado
     roles:
       admin: Administrador
@@ -486,7 +485,6 @@ es:
     unlocked_warning_title: Tu cuenta no está bloqueada
   generic:
     changes_saved_msg: "¡Cambios guardados con éxito!"
-    powered_by: gracias a %{link}
     save_changes: Guardar cambios
     validation_errors:
       one: "¡Algo no está bien! Por favor, revisa el error"
@@ -521,8 +519,6 @@ es:
       expires_at: Expira
       uses: Usos
     title: Invitar a gente
-  landing_strip_html: "<strong>%{name}</strong> es un usuario en %{link_to_root_path}. Puedes seguirlo(a) o interactuar con el o ella si tienes una cuenta en cualquier parte del fediverse."
-  landing_strip_signup_html: Si no tienes una, puedes <a href="%{sign_up_path}">registrarte aquí</a>.
   lists:
     errors:
       limit: Has alcanzado la cantidad máxima de listas
@@ -688,7 +684,6 @@ es:
       unlisted: Público, pero no mostrar en la historia federada
       unlisted_long: Todos pueden ver, pero no está listado en las líneas de tiempo públicas
   stream_entries:
-    click_to_show: Click para mostrar
     pinned: Toot fijado
     reblogged: retooteado
     sensitive_content: Contenido sensible
diff --git a/config/locales/eu.yml b/config/locales/eu.yml
index e141f27ee..c11e05908 100644
--- a/config/locales/eu.yml
+++ b/config/locales/eu.yml
@@ -46,7 +46,6 @@ eu:
     people_who_follow: "%{name} jarraitzen dutenak"
     posts: Toot-ak
     posts_with_replies: Toot eta erantzunak
-    remote_follow: Jarraitu urrunetik
     reserved_username: Erabiltzaile-izena erreserbatuta dago
     roles:
       admin: Administratzailea
@@ -488,7 +487,6 @@ eu:
     unlocked_warning_title: Zure kontua ez dago giltzapetuta
   generic:
     changes_saved_msg: Aldaketak ongi gorde dira!
-    powered_by: "(e)k %{link} darabil"
     save_changes: Gorde aldaketak
     validation_errors:
       one: Zerbait ez dabil ongi! Egiaztatu beheko errorea mesedez
@@ -524,8 +522,6 @@ eu:
       expires_at: Iraungitzea
       uses: Erabilerak
     title: Gonbidatu jendea
-  landing_strip_html: "<strong>%{name}</strong> %{link_to_root_path} instantziako erabiltzailea da. Fedibertsoko edozein tokitan kontua baduzu jarraitu dezakezu eta harremanetan jarri."
-  landing_strip_signup_html: Ez baduzu, <a href="%{sign_up_path}">hemen izena eman</a> dezakezu.
   lists:
     errors:
       limit: Gehieneko zerrenda kopurura heldu zara
@@ -693,7 +689,6 @@ eu:
       unlisted: Zerrendatu gabea
       unlisted_long: Edonork ikusi dezake, baina ez da denbora-lerro publikoetan agertzen
   stream_entries:
-    click_to_show: Klik erakusteko
     pinned: Finkatutako toot-a
     reblogged: "(r)en bultzada"
     sensitive_content: Eduki hunkigarria
diff --git a/config/locales/fa.yml b/config/locales/fa.yml
index cfd4a9838..b4dc3fd8a 100644
--- a/config/locales/fa.yml
+++ b/config/locales/fa.yml
@@ -46,7 +46,6 @@ fa:
     people_who_follow: کسانی که %{name} را پی می‌گیرند
     posts: نوشته‌ها
     posts_with_replies: نوشته‌ها و پاسخ‌ها
-    remote_follow: پیگیری غیرمستقیم
     reserved_username: این نام کاربری در دسترس نیست
     roles:
       admin: مدیر
@@ -536,7 +535,6 @@ fa:
     unlocked_warning_title: حساب شما خصوصی نیست
   generic:
     changes_saved_msg: تغییرات با موفقیت ذخیره شدند!
-    powered_by: نیرو گرفته از %{link}
     save_changes: ذخیرهٔ تغییرات
     validation_errors:
       one: یک چیزی هنوز درست نیست! لطفاً خطاهای زیر را ببینید
@@ -572,8 +570,6 @@ fa:
       expires_at: تاریخ انقضا
       uses: استفاده‌ها
     title: دعوت دیگران
-  landing_strip_html: "<strong>%{name}</strong> کاربری روی %{link_to_root_path} است. شما با داشتن حساب روی هر سروری می‌توانید نوشته‌های او را پیگیری کرده یا با او ارتباط داشته باشید."
-  landing_strip_signup_html: اگر هنوز حسابی ندارید <a href="%{sign_up_path}">این‌جا حساب باز کنید</a>.
   lists:
     errors:
       limit: از این بیشتر نمی‌شود فهرست داشت
@@ -742,7 +738,6 @@ fa:
       unlisted: فهرست‌نشده
       unlisted_long: عمومی، ولی در فهرست نوشته‌ها نمایش نمی‌یابد
   stream_entries:
-    click_to_show: برای نمایش کلیک کنید
     pinned: نوشته‌های ثابت
     reblogged: بازبوقید
     sensitive_content: محتوای حساس
diff --git a/config/locales/fi.yml b/config/locales/fi.yml
index 6c9076919..2c534f071 100644
--- a/config/locales/fi.yml
+++ b/config/locales/fi.yml
@@ -46,7 +46,6 @@ fi:
     people_who_follow: Käyttäjän %{name} seuraajat
     posts: Tuuttaukset
     posts_with_replies: Tuuttaukset ja vastaukset
-    remote_follow: Etäseuranta
     reserved_username: Käyttäjänimi on varattu
     roles:
       admin: Ylläpitäjä
@@ -484,7 +483,6 @@ fi:
     unlocked_warning_title: Tiliäsi ei ole lukittu
   generic:
     changes_saved_msg: Muutosten tallennus onnistui!
-    powered_by: voimanlähteenä %{link}
     save_changes: Tallenna muutokset
     validation_errors:
       one: Kaikki ei ole aivan oikein! Tarkasta alla oleva virhe
@@ -519,8 +517,6 @@ fi:
       expires_at: Vanhenee
       uses: Käytetty
     title: Kutsu ihmisiä
-  landing_strip_html: "<strong>%{name}</strong> on käyttäjänä palvelimella %{link_to_root_path}. Voit seurata heitä tai pitää heihin yhteyttä, jos sinulla on tili missä tahansa fediversumin kolkassa."
-  landing_strip_signup_html: Jos sinulla ei ole tiliä, voit <a href="%{sign_up_path}">rekisteröityä tätä kautta</a>.
   lists:
     errors:
       limit: Sinulla on jo suurin sallittu määrä listoja
@@ -684,7 +680,6 @@ fi:
       unlisted: Listaamaton julkinen
       unlisted_long: Kaikki voivat nähdä, mutta ei näytetä julkisilla aikajanoilla
   stream_entries:
-    click_to_show: Katso napsauttamalla
     pinned: Kiinnitetty tuuttaus
     reblogged: buustasi
     sensitive_content: Arkaluontoista sisältöä
diff --git a/config/locales/fr.yml b/config/locales/fr.yml
index 07d900cfa..bc2c7b387 100644
--- a/config/locales/fr.yml
+++ b/config/locales/fr.yml
@@ -46,7 +46,6 @@ fr:
     people_who_follow: Personnes qui suivent %{name}
     posts: Statuts
     posts_with_replies: Statuts & réponses
-    remote_follow: Suivre à distance
     reserved_username: Ce nom d’utilisateur⋅ice est réservé
     roles:
       admin: Admin
@@ -488,7 +487,6 @@ fr:
     unlocked_warning_title: Votre compte n’est pas privé
   generic:
     changes_saved_msg: Les modifications ont été enregistrées avec succès !
-    powered_by: propulsé par %{link}
     save_changes: Enregistrer les modifications
     validation_errors:
       one: Quelque chose ne va pas ! Vérifiez l’erreur ci-dessous
@@ -523,8 +521,6 @@ fr:
       expires_at: Expire
       uses: Utilise
     title: Inviter des gens
-  landing_strip_html: <strong>%{name}</strong> utilise %{link_to_root_path}. Vous pouvez læ suivre et interagir si vous possédez un compte quelque part dans le "fediverse".
-  landing_strip_signup_html: Si ce n’est pas le cas, vous pouvez <a href="%{sign_up_path}">en créer un ici</a>.
   lists:
     errors:
       limit: Vous avez atteint le nombre maximum de listes
@@ -691,7 +687,6 @@ fr:
       unlisted: Public sans être affiché sur le fil public
       unlisted_long: Tout le monde peut voir vos statuts mais ils ne seront pas sur listés sur les fils publics
   stream_entries:
-    click_to_show: Cliquer pour afficher
     pinned: Pouet épinglé
     reblogged: a partagé
     sensitive_content: Contenu sensible
diff --git a/config/locales/gl.yml b/config/locales/gl.yml
index d20e1559d..f38f65e5a 100644
--- a/config/locales/gl.yml
+++ b/config/locales/gl.yml
@@ -46,7 +46,6 @@ gl:
     people_who_follow: Personas que seguen a %{name}
     posts: Mensaxes
     posts_with_replies: Toots e respostas
-    remote_follow: Seguimento remoto
     reserved_username: O nome de usuaria está reservado
     roles:
       admin: Admin
@@ -535,7 +534,6 @@ gl:
     unlocked_warning_title: A súa conta non está pechada
   generic:
     changes_saved_msg: Cambios gardados correctamente!!
-    powered_by: grazas a %{link}
     save_changes: Gardar cambios
     validation_errors:
       one: Algo non está ben de todo! Por favor revise abaixo o erro
@@ -571,8 +569,6 @@ gl:
       expires_at: Caduca
       uses: Usos
     title: Convidar xente
-  landing_strip_html: "<strong>%{name}</strong> é unha usuaria en %{link_to_root_path}.  Pode seguila ou interactuar con ela si ten unha conta en algún lugar do fediverso."
-  landing_strip_signup_html: Si non, pode <a href="%{sign_up_path}">rexistrarse aquí</a>.
   lists:
     errors:
       limit: Acadou o número máximo de listas
@@ -741,7 +737,6 @@ gl:
       unlisted: Non listado
       unlisted_long: Visible para calquera, pero non listado en liñas de tempo públicas
   stream_entries:
-    click_to_show: Pulse para mostrar
     pinned: Mensaxe fixada
     reblogged: promovida
     sensitive_content: Contido sensible
diff --git a/config/locales/he.yml b/config/locales/he.yml
index c127db385..b03f184ca 100644
--- a/config/locales/he.yml
+++ b/config/locales/he.yml
@@ -44,7 +44,6 @@ he:
     people_who_follow: העוקבים של %{name}
     posts: הודעות
     posts_with_replies: חצרוצים ותגובות
-    remote_follow: מעקב מרחוק
     reserved_username: שם המשתמש שמור
     roles:
       admin: מנהל
@@ -286,7 +285,6 @@ he:
     unlocked_warning_title: חשבונך אינו נעול
   generic:
     changes_saved_msg: השינויים נשמרו בהצלחה!
-    powered_by: רץ על %{link}
     save_changes: שמור שינויים
     validation_errors:
       one: משהו לא לגמרי בסדר עדיין! אנא הציצו על השגיאה מטה
@@ -299,8 +297,6 @@ he:
       following: רשימת נעקבים
       muting: רשימת השתקות
     upload: יבוא
-  landing_strip_html: "<strong>%{name}</strong> מזהה משתמש(ת) מהקהילה %{link_to_root_path}. ניתן לעקוב אחריהם או לדבר איתם בעזרת חשבון על כל שרת קהילה ברחבי הפדרציה."
-  landing_strip_signup_html: לחלופין , ניתן <a href="%{sign_up_path}">להרשם מקומית כאן</a>.
   media_attachments:
     validations:
       images_and_video: לא ניתן להוסיף וידאו לחצרוץ שכבר מכיל תמונות
@@ -372,7 +368,6 @@ he:
       unlisted: מוסתר
       unlisted_long: פומבי, אבל לא להצגה בפיד הציבורי
   stream_entries:
-    click_to_show: ללחוץ להצגה
     reblogged: הודהד
     sensitive_content: תוכן רגיש
   time:
diff --git a/config/locales/hr.yml b/config/locales/hr.yml
index 2d2eddc08..07373d19d 100644
--- a/config/locales/hr.yml
+++ b/config/locales/hr.yml
@@ -22,7 +22,6 @@ hr:
     people_followed_by: Ljudi koje %{name} slijedi
     people_who_follow: Ljudi koji slijede %{name}
     posts: Postovi
-    remote_follow: Remote follow
     unfollow: Prestani slijediti
   application_mailer:
     settings: 'Promijeni e-mail postavke: %{link}'
@@ -64,7 +63,6 @@ hr:
     storage: Pohrana media zapisa
   generic:
     changes_saved_msg: Izmjene su uspješno sačuvane!
-    powered_by: omogućuje %{link}
     save_changes: Sačuvaj izmjene
     validation_errors:
       one: Nešto ne štima! Vidi grešku ispod
@@ -77,8 +75,6 @@ hr:
       following: Lista onih koje slijedim
       muting: Lista utišanih
     upload: Upload
-  landing_strip_html: "<strong>%{name}</strong> je korisnik na %{link_to_root_path}. Možeš ih slijediti ili komunicirati s njima ako imaš račun igdje u fediversu."
-  landing_strip_signup_html: Ako nemaš, možeš se <a href="%{sign_up_path}">registrirati ovdje</a>.
   notification_mailer:
     digest:
       body: 'Ovo je kratak sažetak propuštenog %{instance} od tvog prošlog posjeta %{since}:'
@@ -141,7 +137,6 @@ hr:
       public: Javno
       unlisted: Javno, no nemoj prikazati na javnom timelineu
   stream_entries:
-    click_to_show: Klikni da bi prikazao
     reblogged: potaknut
     sensitive_content: Osjetljivi sadržaj
   time:
diff --git a/config/locales/hu.yml b/config/locales/hu.yml
index 41093aa43..af10dfd80 100644
--- a/config/locales/hu.yml
+++ b/config/locales/hu.yml
@@ -44,7 +44,6 @@ hu:
     people_who_follow: "%{name} követői"
     posts: Tülkök
     posts_with_replies: Tülkök és válaszok
-    remote_follow: Követés más hálózaton
     reserved_username: Ez egy már lefoglalt felhasználónév
     roles:
       admin: Adminisztrátor
@@ -427,7 +426,6 @@ hu:
     unlocked_warning_title: A fiókod jelenleg nem privát
   generic:
     changes_saved_msg: Változások sikeresen elmentve!
-    powered_by: működteti a %{link}
     save_changes: Változások mentése
     validation_errors:
       one: Valami nincs rendjén! Kérlek tekintsd meg a hibát alant
@@ -461,8 +459,6 @@ hu:
       expires_at: Lejárat
       uses: Használat
     title: Meghívások
-  landing_strip_html: "<strong>%{name}</strong> az alábbi instancia használója: %{link_to_root_path}. Követheted vagy kapcsolatba léphetsz vele, ha már van felhasználói fiókod a föderációban."
-  landing_strip_signup_html: Ha még nincs fiókod, <a href="%{sign_up_path}">itt regisztrálhatsz</a>.
   lists:
     errors:
       limit: Elérted a hozzáadható listák maximális számát
@@ -610,7 +606,6 @@ hu:
       unlisted: Listázatlan
       unlisted_long: Mindenki látja, de a nyilvános időfolyamokban nem jelenik meg
   stream_entries:
-    click_to_show: Megtekintéshez kattints
     pinned: Kitűzött tülk
     reblogged: reblogolt
     sensitive_content: Szenzitív tartalom
diff --git a/config/locales/id.yml b/config/locales/id.yml
index 4fb75f2b0..c391a6b4e 100644
--- a/config/locales/id.yml
+++ b/config/locales/id.yml
@@ -22,7 +22,6 @@ id:
     people_followed_by: Orang yang diikuti %{name}
     people_who_follow: Orang-orang yang mengikuti %{name}
     posts: Postingan
-    remote_follow: Mengikuti
     unfollow: Berhenti mengikuti
   admin:
     accounts:
@@ -213,7 +212,6 @@ id:
     unlocked_warning_title: Akun anda tidak dikunci
   generic:
     changes_saved_msg: Perubahan berhasil disimpan!
-    powered_by: didukung oleh %{link}
     save_changes: Simpan perubahan
     validation_errors:
       one: Ada yang tidak beres! Mohon tinjau error dibawah ini
@@ -226,8 +224,6 @@ id:
       following: Daftar diikuti
       muting: Daftar didiamkan
     upload: Unggah
-  landing_strip_html: "<strong>%{name}</strong> adalah pengguna di %{link_to_root_path}.Anda dapat mengikuti mereka atau berinteraksi dengan mereka jika anda memiliki akun di fediverse."
-  landing_strip_signup_html: Jika anda tidak punya, anda bisa <a href="%{sign_up_path}">daftar disini</a>.
   media_attachments:
     validations:
       images_and_video: Tidak bisa melampirkan video pada status yang telah memiliki gambar
@@ -298,7 +294,6 @@ id:
       public_long: Bisa dilihat semua orang
       unlisted: Bisa dilihat semua orang, tapi tidak ditampilkan di linimasa publik
   stream_entries:
-    click_to_show: Klik untuk menampilkan
     reblogged: di-boost-kan
     sensitive_content: Konten sensitif
   time:
diff --git a/config/locales/io.yml b/config/locales/io.yml
index bf15de488..71a7f2d94 100644
--- a/config/locales/io.yml
+++ b/config/locales/io.yml
@@ -22,7 +22,6 @@ io:
     people_followed_by: Sequati da %{name}
     people_who_follow: Sequanti di %{name}
     posts: Mesaji
-    remote_follow: Fore sequar
     unfollow: Dessequar
   admin:
     accounts:
@@ -192,7 +191,6 @@ io:
     storage: Konservado di kontenajo
   generic:
     changes_saved_msg: Chanji senprobleme konservita!
-    powered_by: povigita da %{link}
     save_changes: Konservar la chanji
     validation_errors:
       one: Ulo ne eventis senprobleme! Voluntez konsultar la suba eror-raporto.
@@ -205,8 +203,6 @@ io:
       following: Listo de sequati
       muting: Muting list
     upload: Kargar
-  landing_strip_html: "<strong>%{name}</strong> esas uzero en %{link_to_root_path}. Tu povas sequar lu o komunikar kun lu, se tu havas konto irgaloke en la Fediverse."
-  landing_strip_signup_html: Se tu ne havas, tu povas <a href="%{sign_up_path}">membreskar hike</a>.
   media_attachments:
     validations:
       images_and_video: Cannot attach a video to a status that already contains images
@@ -274,7 +270,6 @@ io:
       public: Publika
       unlisted: Publika, ma ne aperos en publika tempolinei
   stream_entries:
-    click_to_show: Kliktar por montrar
     reblogged: diskonocigita
     sensitive_content: Titiliva kontenajo
   time:
diff --git a/config/locales/it.yml b/config/locales/it.yml
index 0110a488e..e985d1f10 100644
--- a/config/locales/it.yml
+++ b/config/locales/it.yml
@@ -46,7 +46,6 @@ it:
     people_who_follow: Persone che seguono %{name}
     posts: Posts
     posts_with_replies: Toot e risposte
-    remote_follow: Segui da remoto
     reserved_username: Il nome utente è riservato
     roles:
       admin: Amministratore
@@ -433,7 +432,6 @@ it:
     unlocked_warning_html: Chiunque può seguirti per vedere immediatamente i tuoi status privati. %{lock_link} per poter esaminare e respingere gli utenti che vogliono seguirti.
   generic:
     changes_saved_msg: Modifiche effettuate con successo!
-    powered_by: offerto da %{link}
     save_changes: Salva modifiche
     validation_errors:
       one: Qualcosa ancora non va bene! Per favore, controlla l'errore qui sotto
@@ -467,8 +465,6 @@ it:
       expires_at: Scade
       uses: Utilizzi
     title: Invita persone
-  landing_strip_html: "<strong>%{name}</strong> è un utente su %{link_to_root_path}. Puoi seguirlo o interagire con lui se possiedi un account ovunque nel fediverse."
-  landing_strip_signup_html: Se non possiedi un account, puoi <a href="%{sign_up_path}">iscriverti qui</a>.
   lists:
     errors:
       limit: Hai raggiunto il numero massimo di liste
@@ -605,7 +601,6 @@ it:
       unlisted: Pubblico, ma non visibile sulla timeline pubblica
       unlisted_long: Tutti lo possono vedere, ma non compare nelle timeline pubbliche
   stream_entries:
-    click_to_show: Clicca per mostrare
     pinned: Toot fissato in cima
     reblogged: condiviso
     sensitive_content: Materiale sensibile
diff --git a/config/locales/ja.yml b/config/locales/ja.yml
index 5a85fac93..8ebff6a8f 100644
--- a/config/locales/ja.yml
+++ b/config/locales/ja.yml
@@ -46,7 +46,6 @@ ja:
     people_who_follow: "%{name} さんをフォロー中のアカウント"
     posts: トゥート
     posts_with_replies: トゥートと返信
-    remote_follow: リモートフォロー
     reserved_username: このユーザー名は予約されています
     roles:
       admin: Admin
@@ -207,6 +206,7 @@ ja:
       updated_msg: 絵文字の更新に成功しました!
       upload: アップロード
     dashboard:
+      backlog: 未処理のジョブ
       config: 構成
       feature_deletions: アカウント削除
       feature_invites: 招待リンク
@@ -535,7 +535,6 @@ ja:
     unlocked_warning_title: このアカウントは承認制アカウントに設定されていません
   generic:
     changes_saved_msg: 正常に変更されました!
-    powered_by: powered by %{link}
     save_changes: 変更を保存
     use_this: これを使う
     validation_errors:
@@ -572,16 +571,6 @@ ja:
       expires_at: 有効期限
       uses: 使用
     title: 新規ユーザーの招待
-  keyword_mutes:
-    add_keyword: キーワードを追加
-    edit: 編集
-    edit_keyword: キーワードを編集
-    keyword: キーワード
-    match_whole_word: 単語全体が一致
-    remove: 削除
-    remove_all: すべて削除
-  landing_strip_html: "<strong>%{name}</strong> さんはインスタンス %{link_to_root_path} のユーザーです。アカウントさえ持っていればフォローしたり会話したりできます。"
-  landing_strip_signup_html: もしお持ちでないなら <a href="%{sign_up_path}">こちら</a> からサインアップできます。
   lists:
     errors:
       limit: リストの上限に達しました
@@ -752,7 +741,6 @@ ja:
       unlisted: 未収載
       unlisted_long: 誰でも見ることができますが、公開タイムラインには表示されません
   stream_entries:
-    click_to_show: クリックして表示
     pinned: 固定されたトゥート
     reblogged: さんがブースト
     sensitive_content: 閲覧注意
diff --git a/config/locales/ko.yml b/config/locales/ko.yml
index 9b742d18b..00b3b249d 100644
--- a/config/locales/ko.yml
+++ b/config/locales/ko.yml
@@ -46,7 +46,6 @@ ko:
     people_who_follow: "%{name} 님을 팔로우 중인 계정"
     posts: 툿
     posts_with_replies: 툿과 답장
-    remote_follow: 리모트 팔로우
     reserved_username: 이 아이디는 예약되어 있습니다
     roles:
       admin: 관리자
@@ -206,6 +205,27 @@ ko:
       update_failed_msg: 에모지를 업데이트 할 수 없습니다
       updated_msg: 에모지가 성공적으로 업데이트 되었습니다!
       upload: 업로드
+    dashboard:
+      backlog: 미처리 된 작업
+      config: 설정
+      feature_deletions: 계정 삭제
+      feature_invites: 초대 링크
+      feature_registrations: 가입
+      feature_relay: 연합 릴레이
+      features: 기능
+      hidden_service: 히든 서비스와의 연합
+      open_reports: 미해결 신고
+      recent_users: 최근 가입 한 유저
+      search: 전문 검색
+      single_user_mode: 싱글 유저 모드
+      software: 소프트웨어
+      space: 디스크 사용량
+      title: 대시보드
+      total_users: 총 유저 수
+      trends: 트렌드
+      week_interactions: 이번 주의 상호작용
+      week_users_active: 이번 주의 활성 사용자
+      week_users_new: 이번 주의 신규 유저
     domain_blocks:
       add_new: 추가하기
       created_msg: 도메인 차단 처리를 완료했습니다
@@ -263,6 +283,14 @@ ko:
         expired: 만료됨
         title: 필터
       title: 초대
+    relays:
+      add_new: 릴레이 추가
+      description_html: "<strong>연합 릴레이</strong>는 서버들 사이에서 많은 양의 공개 툿을 구독하고 중개하는 서버입니다. <strong>이것은 중소 규모의 서버에서 연합우주를 발견하는 데에 도움을 줄 수 있습니다</strong>, 이제 로컬 유저들이 다른 서버의 유저들을 수동으로 팔로우 하지 않아도 됩니다."
+      enable_hint: 활성화 되면, 이 릴레이의 모든 공개 툿을 구독하고 이 서버의 공개 툿을 전송하게 됩니다.
+      inbox_url: 릴레이 URL
+      setup: 릴레이 연결 설정
+      status: 상태
+      title: 릴레이
     report_notes:
       created_msg: 리포트 노트가 성공적으로 작성되었습니다!
       destroyed_msg: 리포트 노트가 성공적으로 삭제되었습니다!
@@ -509,7 +537,6 @@ ko:
     unlocked_warning_title: 이 계정은 비공개로 설정되어 있지 않습니다
   generic:
     changes_saved_msg: 정상적으로 변경되었습니다!
-    powered_by: "%{link}에 의해 제공"
     save_changes: 변경 사항을 저장
     validation_errors:
       one: 오류가 발생했습니다. 아래 오류를 확인해 주십시오
@@ -545,8 +572,6 @@ ko:
       expires_at: 만료
       uses: 사용됨
     title: 초대
-  landing_strip_html: "<strong>%{name}</strong> 님은 %{link_to_root_path} 인스턴스의 사용자입니다. 계정을 가지고 있다면 팔로우 하거나 대화할 수 있습니다."
-  landing_strip_signup_html: 아직 계정이 없다면 <a href="%{sign_up_path}">여기서</a> 등록할 수 있습니다.
   lists:
     errors:
       limit: 리스트 최대치에 도달했습니다
@@ -715,7 +740,6 @@ ko:
       unlisted: 공개 타임라인 비공개
       unlisted_long: 누구나 볼 수 있지만, 공개 타임라인에는 표시되지 않습니다
   stream_entries:
-    click_to_show: 클릭해서 표시
     pinned: 고정된 툿
     reblogged: 님이 부스트 했습니다
     sensitive_content: 민감한 컨텐츠
diff --git a/config/locales/nl.yml b/config/locales/nl.yml
index 3f4342d8e..f4fc22108 100644
--- a/config/locales/nl.yml
+++ b/config/locales/nl.yml
@@ -46,7 +46,6 @@ nl:
     people_who_follow: Mensen die %{name} volgen
     posts: Toots
     posts_with_replies: Toots en reacties
-    remote_follow: Extern volgen
     reserved_username: Deze gebruikersnaam is gereserveerd
     roles:
       admin: Beheerder
@@ -536,7 +535,6 @@ nl:
     unlocked_warning_title: Jouw account is niet besloten
   generic:
     changes_saved_msg: Wijzigingen succesvol opgeslagen!
-    powered_by: wordt mogelijk gemaakt door %{link}
     save_changes: Wijzigingen opslaan
     validation_errors:
       one: Er is iets niet helemaal goed! Bekijk onderstaande fout
@@ -572,8 +570,6 @@ nl:
       expires_at: Verloopt op
       uses: Aantal keer te gebruiken
     title: Mensen uitnodigen
-  landing_strip_html: "<strong>%{name}</strong> is een gebruiker op %{link_to_root_path}. Je kunt deze volgen en ermee communiceren als je op Mastodon (of ergens anders in de fediverse) een account hebt."
-  landing_strip_signup_html: Als je dat niet hebt, kun je je <a href="%{sign_up_path}">hier registreren</a>.
   lists:
     errors:
       limit: Je hebt het maximaal aantal lijsten bereikt
@@ -742,7 +738,6 @@ nl:
       unlisted: Minder openbaar
       unlisted_long: Aan iedereen tonen, maar niet op openbare tijdlijnen
   stream_entries:
-    click_to_show: Klik om te tonen
     pinned: Vastgemaakte toot
     reblogged: boostte
     sensitive_content: Gevoelige inhoud
diff --git a/config/locales/no.yml b/config/locales/no.yml
index eb1d27a19..c17ea3e86 100644
--- a/config/locales/no.yml
+++ b/config/locales/no.yml
@@ -44,7 +44,6 @@
     people_who_follow: Folk som følger %{name}
     posts: Poster
     posts_with_replies: Tuter med svar
-    remote_follow: Følg fra andre instanser
     reserved_username: Brukernavnet er reservert
     roles:
       admin: Admin
@@ -427,7 +426,6 @@
     unlocked_warning_title: Din konto er ikke låst
   generic:
     changes_saved_msg: Vellykket lagring av endringer!
-    powered_by: drevet av %{link}
     save_changes: Lagre endringer
     validation_errors:
       one: Noe er ikke helt riktig ennå. Vennligst se etter en gang til
@@ -461,8 +459,6 @@
       expires_at: Utløper
       uses: Bruk
     title: Inviter personer
-  landing_strip_html: "<strong>%{name}</strong> er en bruker på %{link_to_root_path}. Du kan følge dem eller kommunisere med dem hvis du har en konto hvor som helst i fediverset."
-  landing_strip_signup_html: Hvis du ikke har en konto så kan du <a href="%{sign_up_path}">registrere deg her</a>.
   lists:
     errors:
       limit: Du har nådd det maksimale antall lister
@@ -610,7 +606,6 @@
       unlisted: Uoppført
       unlisted_long: Synlig for alle, men ikke på offentlige tidslinjer
   stream_entries:
-    click_to_show: Klikk for å vise
     pinned: Festet tut
     reblogged: fremhevde
     sensitive_content: Følsomt innhold
diff --git a/config/locales/oc.yml b/config/locales/oc.yml
index f853d6cd4..2cbc8a8fb 100644
--- a/config/locales/oc.yml
+++ b/config/locales/oc.yml
@@ -46,7 +46,6 @@ oc:
     people_who_follow: Lo monde que sègon %{name}
     posts: Tuts
     posts_with_replies: Tuts e responsas
-    remote_follow: Sègre a distància
     reserved_username: Aqueste nom d’utilizaire es reservat
     roles:
       admin: Admin
@@ -593,7 +592,6 @@ oc:
     unlocked_warning_title: Vòstre compte es pas clavat
   generic:
     changes_saved_msg: Cambiaments ben realizats !
-    powered_by: propulsat per %{link}
     save_changes: Salvar los cambiaments
     validation_errors:
       one: I a quicòm que truca ! Mercés de corregir l’error çai-jos
@@ -629,8 +627,6 @@ oc:
       expires_at: Expirats
       uses: Usatges
     title: Convidar de mond
-  landing_strip_html: "<strong>%{name}</strong> utiliza %{link_to_root_path}. Podètz lo/la sègre o interagir amb el o ela s’avètz un compte ont que siasque sul fediverse."
-  landing_strip_signup_html: S’es pas lo cas, podètz <a href="%{sign_up_path}">vos marcar aquí</a>.
   lists:
     errors:
       limit: Avètz atengut lo maximum de listas
@@ -799,7 +795,6 @@ oc:
       unlisted: Pas listat
       unlisted_long: Tot lo monde pòt veire mai serà pas visible sul flux public
   stream_entries:
-    click_to_show: Clicatz per veire
     pinned: Tut penjat
     reblogged: a partejat
     sensitive_content: Contengut sensible
diff --git a/config/locales/pl.yml b/config/locales/pl.yml
index d79bfd0a8..d3a2b62c1 100644
--- a/config/locales/pl.yml
+++ b/config/locales/pl.yml
@@ -46,7 +46,6 @@ pl:
     people_who_follow: Osoby, które śledzą konto %{name}
     posts: Wpisy
     posts_with_replies: Wpisy z odpowiedziami
-    remote_follow: Śledź zdalnie
     reserved_username: Ta nazwa użytkownika jest zarezerwowana
     roles:
       admin: Administrator
@@ -537,7 +536,6 @@ pl:
     unlocked_warning_title: Twoje konto nie jest zablokowane
   generic:
     changes_saved_msg: Ustawienia zapisane!
-    powered_by: uruchomione na %{link}
     save_changes: Zapisz zmiany
     use_this: Użyj tego
     validation_errors:
@@ -578,16 +576,6 @@ pl:
       expires_at: Wygaśnie po
       uses: Użycia
     title: Zaproś użytkowników
-  keyword_mutes:
-    add_keyword: Dodaj słowo kluczowe
-    edit: Edytuj
-    edit_keyword: Edytuj słowo kluczowe
-    keyword: Słowo kluczowe
-    match_whole_word: Uwzględniaj całe słowo
-    remove: Usuń
-    remove_all: Usuń wszystkie
-  landing_strip_html: "<strong>%{name}</strong> ma konto na %{link_to_root_path}. Możesz je śledzić i wejść z nim w interakcję jeśli masz konto gdziekolwiek w Fediwersum."
-  landing_strip_signup_html: Jeśli jeszcze go nie masz, możesz <a href="%{sign_up_path}">stworzyć konto</a>.
   lists:
     errors:
       limit: Przekroczyłeś maksymalną liczbę utworzonych list
@@ -766,7 +754,6 @@ pl:
       unlisted: Niewypisane
       unlisted_long: Widoczne dla wszystkich, ale nie wyświetlane na publicznych osiach czasu
   stream_entries:
-    click_to_show: Naciśnij aby wyświetlić
     pinned: Przypięty wpis
     reblogged: podbił
     sensitive_content: Wrażliwa zawartość
diff --git a/config/locales/pt-BR.yml b/config/locales/pt-BR.yml
index 12314a050..d2e4d226c 100644
--- a/config/locales/pt-BR.yml
+++ b/config/locales/pt-BR.yml
@@ -46,7 +46,6 @@ pt-BR:
     people_who_follow: Pessoas que seguem %{name}
     posts: Toots
     posts_with_replies: Toots e respostas
-    remote_follow: Siga remotamente
     reserved_username: Este usuário está reservado
     roles:
       admin: Administrador
@@ -536,7 +535,6 @@ pt-BR:
     unlocked_warning_title: A sua conta não está trancada
   generic:
     changes_saved_msg: Mudanças salvas com sucesso!
-    powered_by: graças a tecnologia de %{link}
     save_changes: Salvar mudanças
     validation_errors:
       one: Algo não está certo! Por favor, reveja o erro abaixo
@@ -572,8 +570,6 @@ pt-BR:
       expires_at: Expira em
       uses: Usos
     title: Convidar pessoas
-  landing_strip_html: "<strong>%{name}</strong> é um usuário no %{link_to_root_path}. Você pode segui-lo ou interagir com ele se você tiver uma conta em qualquer lugar no fediverso."
-  landing_strip_signup_html: Se não, você pode <a href="%{sign_up_path}">se cadastrar aqui</a>.
   lists:
     errors:
       limit: Você alcançou o número máximo de listas
@@ -742,7 +738,6 @@ pt-BR:
       unlisted: Não listado
       unlisted_long: Todos podem ver, porém não será postado nas timelines públicas
   stream_entries:
-    click_to_show: Clique para mostrar
     pinned: Toot fixado
     reblogged: compartilhou
     sensitive_content: Conteúdo sensível
diff --git a/config/locales/pt.yml b/config/locales/pt.yml
index 3a6f2c993..33b6b0acb 100644
--- a/config/locales/pt.yml
+++ b/config/locales/pt.yml
@@ -44,7 +44,6 @@ pt:
     people_who_follow: Pessoas que seguem %{name}
     posts: Posts
     posts_with_replies: Posts e Respostas
-    remote_follow: Seguir remotamente
     reserved_username: Este nome de utilizadores é reservado
     roles:
       admin: Administrador
@@ -430,7 +429,6 @@ pt:
     unlocked_warning_title: A tua conta não está bloqueada
   generic:
     changes_saved_msg: Alterações guardadas!
-    powered_by: fornecido por %{link}
     save_changes: Guardar alterações
     validation_errors:
       one: Algo não está correcto. Por favor vê o erro abaixo
@@ -464,8 +462,6 @@ pt:
       expires_at: Expira
       uses: Usos
     title: Convidar pessoas
-  landing_strip_html: "<strong>%{name}</strong> é um utilizador em %{link_to_root_path}. Podes segui-lo ou interagir com ele se tiveres uma conta em qualquer lugar no fediverso."
-  landing_strip_signup_html: If you don't, you can <a href="%{sign_up_path}">sign up here</a>.
   lists:
     errors:
       limit: Número máximo de listas alcançado
@@ -612,7 +608,6 @@ pt:
       unlisted: Público, mas não mostre no timeline público
       unlisted_long: Todos podem ver, porém não será postado nas timelines públicas
   stream_entries:
-    click_to_show: Clique pra mostrar
     pinned: Toot fixado
     reblogged: boosted
     sensitive_content: Conteúdo sensível
diff --git a/config/locales/ru.yml b/config/locales/ru.yml
index 89aefc1cd..5fc511d2e 100644
--- a/config/locales/ru.yml
+++ b/config/locales/ru.yml
@@ -46,7 +46,6 @@ ru:
     people_who_follow: Подписчики %{name}
     posts: Посты
     posts_with_replies: Посты с ответами
-    remote_follow: Подписаться на удаленном узле
     reserved_username: Имя пользователя зарезервировано
     roles:
       admin: Администратор
@@ -492,7 +491,6 @@ ru:
     unlocked_warning_title: Ваш аккаунт не закрыт для подписки
   generic:
     changes_saved_msg: Изменения успешно сохранены!
-    powered_by: работает на %{link}
     save_changes: Сохранить изменения
     validation_errors:
       few: Что-то здесь не так! Пожалуйста, прочитайте о %{count} ошибках ниже
@@ -531,8 +529,6 @@ ru:
       expires_at: Истекает
       uses: Исп.
     title: Пригласить людей
-  landing_strip_html: "<strong>%{name}</strong> - пользователь на %{link_to_root_path}. Вы можете подписаться на него/нее и общаться с ним/ней, если у Вас есть аккаунт на любом узле общей сети."
-  landing_strip_signup_html: Если у Вас его нет, вы можете <a href="%{sign_up_path}">зарегистрироваться здесь</a>.
   lists:
     errors:
       limit: Вы достигли максимального числа списков
@@ -709,7 +705,6 @@ ru:
       unlisted: Скрывать из лент
       unlisted_long: Показывать всем, но не отображать в публичных лентах
   stream_entries:
-    click_to_show: Показать
     pinned: Закреплённое сообщение
     reblogged: продвинул(а)
     sensitive_content: Чувствительный контент
diff --git a/config/locales/simple_form.ar.yml b/config/locales/simple_form.ar.yml
index 8f3e685a6..0474e1ef2 100644
--- a/config/locales/simple_form.ar.yml
+++ b/config/locales/simple_form.ar.yml
@@ -4,7 +4,7 @@ ar:
     hints:
       defaults:
         autofollow: سوف يتابعك تلقائيًا الأشخاص الذين يقومون بالتسجيل من خلال الدعوة
-        avatar: ملف PNG أو GIF أو JPG. حجمه على أقصى تصدير 2MB. سيتم تصغيره إلى 400x400px
+        avatar: ملف PNG أو GIF أو JPG. حجمه على أقصى تصدير %{size}. سيتم تصغيره إلى %{dimensions}px
         bot: يُعلِم أنّ هذا الحساب لا يمثل شخصًا
         context: واحد أو أكثر من السياقات التي يجب أن ينطبق عليها عامل التصفية
         digest: تُرسَل إليك بعد مُضيّ مدة مِن خمول نشاطك و فقط إذا ما تلقيت رسائل شخصية مباشِرة أثناء فترة غيابك مِن الشبكة
@@ -12,7 +12,7 @@ ar:
           one: <span class="name-counter">1</span> حرف باق
           other: <span class="name-counter">%{count}</span> حرف باق
         fields: يُمكنك عرض 4 عناصر على شكل جدول في ملفك الشخصي
-        header: ملف PNG أو GIF أو JPG. حجمه على أقصى تصدير 2MB. سيتم تصغيره إلى 700x335px
+        header: ملف PNG أو GIF أو JPG. حجمه على أقصى تصدير %{size}. سيتم تصغيره إلى %{dimensions}px
         irreversible: التبويقات التي تم تصفيتها ستختفي لا محالة حتى و إن تمت إزالة عامِل التصفية لاحقًا
         locale: لغة واجهة المستخدم و الرسائل الإلكترونية و الإشعارات
         locked: يتطلب منك الموافقة يدويا على طلبات المتابعة
diff --git a/config/locales/simple_form.ast.yml b/config/locales/simple_form.ast.yml
index 0967ef424..0b77eecf2 100644
--- a/config/locales/simple_form.ast.yml
+++ b/config/locales/simple_form.ast.yml
@@ -1 +1,2 @@
-{}
+---
+ast:
diff --git a/config/locales/simple_form.bg.yml b/config/locales/simple_form.bg.yml
index 720a8391d..938dacc95 100644
--- a/config/locales/simple_form.bg.yml
+++ b/config/locales/simple_form.bg.yml
@@ -3,9 +3,9 @@ bg:
   simple_form:
     hints:
       defaults:
-        avatar: PNG, GIF или JPG. До 2MB. Ще бъде смалена до 400x400 пиксела
+        avatar: PNG, GIF или JPG. До %{size}. Ще бъде смалена до %{dimensions} пиксела
         display_name: До 30 символа
-        header: PNG, GIF или JPG. До 2MB. Ще бъде смалена до 700x335 пиксела
+        header: PNG, GIF или JPG. До %{size}. Ще бъде смалена до %{dimensions} пиксела
         locked: Изисква ръчно одобрение на последователите. По подразбиране, публикациите са достъпни само до последователи.
         note: До 160 символа
       imports:
diff --git a/config/locales/simple_form.ca.yml b/config/locales/simple_form.ca.yml
index 482ddd7be..d45b84971 100644
--- a/config/locales/simple_form.ca.yml
+++ b/config/locales/simple_form.ca.yml
@@ -4,7 +4,7 @@ ca:
     hints:
       defaults:
         autofollow: Les persones que es registrin a través de la invitació et seguiran automàticament
-        avatar: PNG, GIF o JPG. Màxim 2MB. S'escalarà a 400x400px
+        avatar: PNG, GIF o JPG. Màxim %{size}. S'escalarà a %{dimensions}px
         bot: Aquest compte realitza principalment accions automatitzades i pot no estar controlat per cap persona
         context: Un o diversos contextos on s'ha d'aplicar el filtre
         digest: Només s'envia després d'un llarg període d'inactivitat amb un resum de les mencions que has rebut en la teva absència
@@ -12,7 +12,7 @@ ca:
           one: <span class="name-counter">1</span> càracter restant
           other: <span class="name-counter">%{count}</span> càracters restans
         fields: Pots tenir fins a 4 elements que es mostren com a taula al teu perfil
-        header: PNG, GIF o JPG. Màxim 2MB. S'escalarà a 700x335px
+        header: PNG, GIF o JPG. Màxim %{size}. S'escalarà a %{dimensions}px
         irreversible: Els nodes filtrats desapareixeran de manera irreversible, fins i tot si el filtre es retira més tard
         locale: El llenguatge de l’interfície d’usuari, els correus i les notificacions push
         locked: Requereix que aprovis manualment els seguidors
diff --git a/config/locales/simple_form.co.yml b/config/locales/simple_form.co.yml
index ac8b89a7b..85a98a3f6 100644
--- a/config/locales/simple_form.co.yml
+++ b/config/locales/simple_form.co.yml
@@ -3,14 +3,14 @@ co:
   simple_form:
     hints:
       defaults:
-        avatar: Furmatu PNG, GIF o JPG. 2Mo o menu. Sarà ridottu à 400x400px
+        avatar: Furmatu PNG, GIF o JPG. 2Mo o menu. Sarà ridottu à %{dimensions}px
         bot: Stu contu hè autumatizatu è ùn hè forse micca survegliatu
         digest: Solu mandatu dopu à una longa perioda d’inattività, è solu s’elli ci sò novi missaghji diretti
         display_name:
           one: Ci ferma <span class="name-counter">1</span> caratteru
           other: Ci fermanu <span class="name-counter">%{count}</span> caratteri
         fields: Pudete avè fin’à 4 elementi mustrati cum’un tavulone nant’à u vostru prufile
-        header: Furmatu PNG, GIF o JPG. 2Mo o menu. Sarà ridottu à 700x335px
+        header: Furmatu PNG, GIF o JPG. 2Mo o menu. Sarà ridottu à %{dimensions}px
         locked: Duvarete appruvà e dumande d’abbunamentu
         note:
           one: Ci ferma <span class="name-counter">1</span> caratteru
diff --git a/config/locales/simple_form.cs.yml b/config/locales/simple_form.cs.yml
index e8e7628f3..48ab9cdac 100644
--- a/config/locales/simple_form.cs.yml
+++ b/config/locales/simple_form.cs.yml
@@ -3,8 +3,8 @@ cs:
   simple_form:
     hints:
       defaults:
-        avatar: PNG, GIF či JPG. Maximálně 2 MB. Bude zmenšena na 400x400px
-        bot: Tento účet provádí hlavně automatizované akce a nemusí být spravován.
+        avatar: PNG, GIF či JPG. Maximálně %{size}. Bude zmenšena na %{dimensions}px
+        bot: Tento účet provádí hlavně automatizované akce a nemusí být spravován
         display_name:
           one: Zbývá <span class="name-counter">1</span> znak
           other: Zbývá <span class="name-counter">%{count}</span> znaků
diff --git a/config/locales/simple_form.da.yml b/config/locales/simple_form.da.yml
index 716ee7e1c..fc3258993 100644
--- a/config/locales/simple_form.da.yml
+++ b/config/locales/simple_form.da.yml
@@ -4,7 +4,7 @@ da:
     hints:
       defaults:
         autofollow: Folk der har oprettet sig gennem invitationen vil automatisk følge dig
-        avatar: PNG, GIF eller JPG. Højest 2MB. Vil blive skaleret ned til 400x400px
+        avatar: PNG, GIF eller JPG. Højest %{size}. Vil blive skaleret ned til %{dimensions}px
         bot: Denne konto udfører hovedsageligt automatiserede handlinger og bliver muligvis ikke overvåget
         context: En eller flere sammenhænge hvor filteret skal være gældende
         digest: Sendes kun efter en lang periode med inaktivitet og kun hvis du har modtaget nogle personlige beskeder mens du er væk
@@ -12,7 +12,7 @@ da:
           one: <span class="name-counter">1</span> tegn tilbage
           other: <span class="name-counter">%{count}</span>tegn tilbage
         fields: Du kan have op til 4 ting vist som en tabel på din profil
-        header: PNG, GIF eller JPG. Højest 2MB. Vil blive skaleret ned til 700x335px
+        header: PNG, GIF eller JPG. Højest %{size}. Vil blive skaleret ned til %{dimensions}px
         inbox_url: Kopiere linket fra forsiden af den relay som du ønsker at bruge
         irreversible: Filtrerede toots vil forsvinde fulstændigt, selv hvis filteret senere skulle blive fjernet
         locale: Sproget på interfacet, emails og push beskeder
diff --git a/config/locales/simple_form.de.yml b/config/locales/simple_form.de.yml
index 0c0679605..e9e795bf4 100644
--- a/config/locales/simple_form.de.yml
+++ b/config/locales/simple_form.de.yml
@@ -4,7 +4,7 @@ de:
     hints:
       defaults:
         autofollow: Leute die sich über deine Einladung registrieren werden dir automatisch folgen
-        avatar: PNG, GIF oder JPG. Maximal 2 MB. Wird auf 400×400 px herunterskaliert
+        avatar: PNG, GIF oder JPG. Maximal %{size}. Wird auf 400×400 px herunterskaliert
         bot: Dieses Konto führt lediglich automatisierte Aktionen durch und wird möglicherweise nicht überwacht
         context: Ein oder mehrere Aspekte, wo der Filter greifen soll
         digest: Wenn du lange Zeit inaktiv bist, wird dir eine Zusammenfassung von Erwähnungen in deiner Abwesenheit zugeschickt
@@ -12,7 +12,7 @@ de:
           one: <span class="name-counter">1</span> Zeichen verbleibt
           other: <span class="name-counter">%{count}</span> Zeichen verbleiben
         fields: Du kannst bis zu 4 Elemente als Tabelle dargestellt auf deinem Profil anzeigen lassen
-        header: PNG, GIF oder JPG. Maximal 2 MB. Wird auf 700×335 px herunterskaliert
+        header: PNG, GIF oder JPG. Maximal %{size}. Wird auf 700×335 px herunterskaliert
         irreversible: Gefilterte Beiträge werden unwiderruflich gefiltert, selbst wenn der Filter später entfernt wurde
         locale: Die Sprache der Oberfläche, E-Mails und Push-Benachrichtigungen
         locked: Wer dir folgen möchte, muss um deine Erlaubnis bitten
diff --git a/config/locales/simple_form.el.yml b/config/locales/simple_form.el.yml
index 58bae8dc1..75d97dcd0 100644
--- a/config/locales/simple_form.el.yml
+++ b/config/locales/simple_form.el.yml
@@ -4,7 +4,7 @@ el:
     hints:
       defaults:
         autofollow: Όσοι εγγραφούν μέσω της πρόσκλησης θα σε ακολουθούν αυτόματα
-        avatar: PNG, GIF ή JPG. Έως 2MB. Θα περιοριστεί σε διάσταση 400x400px
+        avatar: PNG, GIF ή JPG. Έως %{size}. Θα περιοριστεί σε διάσταση %{dimensions}px
         bot: Ο λογαριασμός αυτός εκτελεί κυρίως αυτοματοποιημένες ενέργειες και ίσως να μην παρακολουθείται
         context: Ένα ή περισσότερα πλαίσια στα οποία μπορεί να εφαρμόζεται αυτό το φίλτρο
         digest: Αποστέλλεται μόνο μετά από μακρά περίοδο αδράνειας και μόνο αν έχεις λάβει προσωπικά μηνύματα κατά την απουσία σου
@@ -12,7 +12,7 @@ el:
           one: απομένει <span class="name-counter">1</span> χαρακτήρας
           other: απομένουν <span class="name-counter">%{count}</span> χαρακτήρες
         fields: Μπορείς να έχεις έως 4 σημειώσεις σε μορφή πίνακα στο προφίλ σου
-        header: PNG, GIF ή JPG. Έως 2MB. Θα περιοριστεί σε διάσταση 700x335px
+        header: PNG, GIF ή JPG. Έως %{size}. Θα περιοριστεί σε διάσταση %{dimensions}px
         inbox_url: Αντέγραψε το URL της αρχικής σελίδας του ανταποκριτή (relay) που θέλεις να χρησιμοποιήσεις
         irreversible: Τα φιλτραρισμένα τουτ θα εξαφανιστούν αμετάκλητα, ακόμα και αν το φίλτρο αργότερα αφαιρεθεί
         locale: Η γλώσσα του περιβάλλοντος χρήσης, των email και των ειδοποιήσεων ώθησης
diff --git a/config/locales/simple_form.en.yml b/config/locales/simple_form.en.yml
index cd99160e5..2f0e40f66 100644
--- a/config/locales/simple_form.en.yml
+++ b/config/locales/simple_form.en.yml
@@ -4,7 +4,7 @@ en:
     hints:
       defaults:
         autofollow: People who sign up through the invite will automatically follow you
-        avatar: PNG, GIF or JPG. At most 2MB. Will be downscaled to 400x400px
+        avatar: PNG, GIF or JPG. At most %{size}. Will be downscaled to %{dimensions}px
         bot: This account mainly performs automated actions and might not be monitored
         context: One or multiple contexts where the filter should apply
         digest: Only sent after a long period of inactivity and only if you have received any personal messages in your absence
@@ -12,7 +12,7 @@ en:
           one: <span class="name-counter">1</span> character left
           other: <span class="name-counter">%{count}</span> characters left
         fields: You can have up to 4 items displayed as a table on your profile
-        header: PNG, GIF or JPG. At most 2MB. Will be downscaled to 700x335px
+        header: PNG, GIF or JPG. At most %{size}. Will be downscaled to %{dimensions}px
         inbox_url: Copy the URL from the frontpage of the relay you want to use
         irreversible: Filtered toots will disappear irreversibly, even if filter is later removed
         locale: The language of the user interface, e-mails and push notifications
diff --git a/config/locales/simple_form.eo.yml b/config/locales/simple_form.eo.yml
index 7d73f2553..9b6e7cd9e 100644
--- a/config/locales/simple_form.eo.yml
+++ b/config/locales/simple_form.eo.yml
@@ -4,7 +4,7 @@ eo:
     hints:
       defaults:
         autofollow: Homoj, kiuj registriĝos per la invito aŭtomate sekvos vin
-        avatar: Formato PNG, GIF aŭ JPG. Ĝis 2MB. Estos malgrandigita al 400x400px
+        avatar: Formato PNG, GIF aŭ JPG. Ĝis %{size}. Estos malgrandigita al %{dimensions}px
         bot: Tiu konto ĉefe faras aŭtomatajn agojn, kaj povas esti ne kontrolata
         context: Unu ol pluraj kuntekstoj kie la filtrilo devus agi
         digest: Sendita nur post longa tempo de neaktiveco, kaj nur se vi ricevis personan mesaĝon en via foresto
@@ -12,7 +12,7 @@ eo:
           one: <span class="name-counter">1</span> signo restas
           other: <span class="name-counter">%{count}</span> signoj restas
         fields: Vi povas havi ĝis 4 tabelajn elementojn en via profilo
-        header: Formato PNG, GIF aŭ JPG. Ĝis 2MB. Estos malgrandigita al 700x335px
+        header: Formato PNG, GIF aŭ JPG. Ĝis %{size}. Estos malgrandigita al %{dimensions}px
         inbox_url: Kopiu la URL de la ĉefpaĝo de la ripetilo, kiun vi volas uzi
         irreversible: Elfiltritaj mesaĝoj malaperos por ĉiam, eĉ se la filtrilo estas poste forigita
         locale: La lingvo de la uzant-interfaco, retmesaĝoj kaj puŝ-sciigoj
diff --git a/config/locales/simple_form.es.yml b/config/locales/simple_form.es.yml
index 000a33edc..483f79058 100644
--- a/config/locales/simple_form.es.yml
+++ b/config/locales/simple_form.es.yml
@@ -3,12 +3,12 @@ es:
   simple_form:
     hints:
       defaults:
-        avatar: PNG, GIF o JPG. Máximo 2MB. Será escalado a 400x400px
+        avatar: PNG, GIF o JPG. Máximo %{size}. Será escalado a %{dimensions}px
         digest: Solo enviado tras un largo periodo de inactividad y solo si has recibido mensajes personales durante tu ausencia
         display_name:
           one: <span class="name-counter">1</span> caracter restante
           other: <span class="name-counter">%{count}</span> caracteres restantes
-        header: PNG, GIF o JPG. Máximo 2MB. Será escalado a 700x335px
+        header: PNG, GIF o JPG. Máximo %{size}. Será escalado a %{dimensions}px
         locked: Requiere que manualmente apruebes seguidores y las publicaciones serán mostradas solamente a tus seguidores
         note:
           one: <span class="name-counter">1</span> carácter restante
diff --git a/config/locales/simple_form.eu.yml b/config/locales/simple_form.eu.yml
index 2d60030ec..481e95e39 100644
--- a/config/locales/simple_form.eu.yml
+++ b/config/locales/simple_form.eu.yml
@@ -4,14 +4,14 @@ eu:
     hints:
       defaults:
         autofollow: Gonbidapena erabiliz izena ematen dutenek automatikoki jarraituko zaituzte
-        avatar: PNG, GIF edo JPG. Gehienez 2MB. 400x400px neurrira eskalatuko da
+        avatar: PNG, GIF edo JPG. Gehienez %{size}. %{dimensions}px neurrira eskalatuko da
         bot: Kontu honek nagusiki automatizatutako ekintzak burutzen ditu eta agian ez du inork monitorizatzen
         digest: Soilik jarduerarik gabeko epe luze bat eta gero, eta soilik ez zeudela mezu pertsonalen bat jaso baduzu
         display_name:
           one: Karaktere <span class="name-counter">1</span> geratzen da
           other: <span class="name-counter">%{count}</span> karaktere geratzen dira
         fields: 4 elementu bistaratu ditzakezu taula batean zure profilean
-        header: PNG, GIF edo JPG. Gehienez 2MB. 700x335px eskalara txikituko da
+        header: PNG, GIF edo JPG. Gehienez %{size}. %{dimensions}px eskalara txikituko da
         locale: Erabiltzaile-interfazea, e-mail mezuen eta jakinarazpenen hizkuntza
         locked: Jarraitzaileak eskuz onartu behar dituzu
         note:
diff --git a/config/locales/simple_form.fr.yml b/config/locales/simple_form.fr.yml
index e510bd155..1a5bb3494 100644
--- a/config/locales/simple_form.fr.yml
+++ b/config/locales/simple_form.fr.yml
@@ -4,7 +4,7 @@ fr:
     hints:
       defaults:
         autofollow: Les personnes qui s'inscrivent grâce à l'invitation vous suivront automatiquement
-        avatar: Au format PNG, GIF ou JPG. 2 Mo maximum. Sera réduit à 400x400px
+        avatar: Au format PNG, GIF ou JPG. 2 Mo maximum. Sera réduit à %{dimensions}px
         bot: Ce compte exécute principalement des actions automatisées et pourrait ne pas être surveillé
         context: Un ou plusieurs contextes où le filtre devrait s'appliquer
         digest: Uniquement envoyé après une longue période d’inactivité et uniquement si vous avez reçu des messages personnels pendant votre absence
@@ -12,7 +12,7 @@ fr:
           one: <span class="name-counter">1</span> caractère restant
           other: <span class="name-counter">%{count}</span> caractères restants
         fields: Vous pouvez avoir jusqu'à 4 éléments affichés en tant que tableau sur votre profil
-        header: Au format PNG, GIF ou JPG. 2 Mo maximum. Sera réduit à 700x335px
+        header: Au format PNG, GIF ou JPG. 2 Mo maximum. Sera réduit à %{dimensions}px
         irreversible: Les pouets filtrés disparaîtront irrémédiablement, même si le filtre est supprimé plus tard
         locale: La langue de l'interface-utilisateur, des courriels, et des notifications
         locked: Vous devrez approuver chaque abonné⋅e et vos statuts ne s’afficheront qu’à vos abonné⋅es
diff --git a/config/locales/simple_form.gl.yml b/config/locales/simple_form.gl.yml
index 84990a66f..b84a95826 100644
--- a/config/locales/simple_form.gl.yml
+++ b/config/locales/simple_form.gl.yml
@@ -4,7 +4,7 @@ gl:
     hints:
       defaults:
         autofollow: As persoas que se conectaron a través de un convite seguirana automáticamente a vostede
-        avatar: PNG, GIF ou JPG.  Máximo 2MB. Será reducida a 400x400px
+        avatar: PNG, GIF ou JPG.  Máximo %{size}. Será reducida a %{dimensions}px
         bot: Esta conta realiza principalmente accións automatizadas e podería non estar monitorizada
         context: Un ou varios contextos onde se debería aplicar o filtro
         digest: Enviar só tras un longo período de inactividade e só si recibeu algunha mensaxe personal na súa ausencia
@@ -12,7 +12,7 @@ gl:
           one: <span class="name-counter">1</span> caracter restante
           other: <span class="name-counter">%{count}</span> caracteres restantes
         fields: Pode ter ate 4 elementos no seu perfil mostrados como unha táboa
-        header: PNG, GIF ou JPG. Máximo 2MB. Será reducida a 700x335px
+        header: PNG, GIF ou JPG. Máximo %{size}. Será reducida a %{dimensions}px
         inbox_url: Copiar o URL desde a páxina de inicio do repetidor que quere utilizar
         irreversible: Os toots filtrados desaparecerán de xeito irreversible, incluso si despois se elimina o filtro
         locale: O idioma da interface de usuaria, correos e notificacións
diff --git a/config/locales/simple_form.he.yml b/config/locales/simple_form.he.yml
index 96cdccd2b..aa5c7e827 100644
--- a/config/locales/simple_form.he.yml
+++ b/config/locales/simple_form.he.yml
@@ -3,12 +3,12 @@ he:
   simple_form:
     hints:
       defaults:
-        avatar: PNG, GIF או JPG. מקסימום 2MB. גודל התמונה יוקטן ל-400x400px
+        avatar: PNG, GIF או JPG. מקסימום %{size}. גודל התמונה יוקטן ל-%{dimensions}px
         digest: נשלח לאחר תקופה ארוכה של אי-פעילות עם סיכום איזכורים שקיבלת בהעדרך
         display_name:
           one: נותרה אות<span class="name-counter">אחת</span>
           other: נותרו<span class="name-counter">%{count}</span> אותיות
-        header: PNG, GIF או JPG. מקסימום 2MB. גודל התמונה יוקטן 700x335px
+        header: PNG, GIF או JPG. מקסימום %{size}. גודל התמונה יוקטן %{dimensions}px
         locked: מחייב אישור עוקבים באופן ידני. פרטיות ההודעות תהיה עוקבים-בלבד אלא אם יצוין אחרת
         note:
           one: נותרה אות<span class="note-counter">אחת</span>
diff --git a/config/locales/simple_form.hr.yml b/config/locales/simple_form.hr.yml
index 2506c8d92..2b3ebf91e 100644
--- a/config/locales/simple_form.hr.yml
+++ b/config/locales/simple_form.hr.yml
@@ -3,9 +3,9 @@ hr:
   simple_form:
     hints:
       defaults:
-        avatar: PNG, GIF ili JPG. Najviše 2MB. Bit će smanjen na 400x400px
+        avatar: PNG, GIF ili JPG. Najviše %{size}. Bit će smanjen na %{dimensions}px
         display_name: Najviše 30 znakova
-        header: PNG, GIF ili JPG. Najviše 2MB. Bit će smanjen na 700x335px
+        header: PNG, GIF ili JPG. Najviše %{size}. Bit će smanjen na %{dimensions}px
         locked: traži te da ručno odobriš sljedbenike i postavlja privatnost postova na dostupnu samo sljedbenicima
         note: Najviše 160 znakova
       imports:
diff --git a/config/locales/simple_form.hu.yml b/config/locales/simple_form.hu.yml
index 2b36dc85b..ef915dec5 100644
--- a/config/locales/simple_form.hu.yml
+++ b/config/locales/simple_form.hu.yml
@@ -3,12 +3,12 @@ hu:
   simple_form:
     hints:
       defaults:
-        avatar: PNG, GIF vagy JPG. Maximum 2MB. Át lesz méretezve 400x400 pixelre
+        avatar: PNG, GIF vagy JPG. Maximum %{size}. Át lesz méretezve %{dimensions} pixelre
         digest: Csak hosszú távollét esetén küldve és csak ha személyes üzenetet kaptál távollétedben
         display_name:
           one: <span class="name-counter">1</span>karakter maradt
           other: <span class="name-counter">%{count}</span>karakter maradt
-        header: PNG, GIF vagy JPG. Maximum 2MB. Át lesz méretezve 700x335 pixelre
+        header: PNG, GIF vagy JPG. Maximum %{size}. Át lesz méretezve %{dimensions} pixelre
         locked: Egyenként engedélyezned kell a követőidet
         note:
           one: <span class="note-counter">1</span>karakter maradt
diff --git a/config/locales/simple_form.id.yml b/config/locales/simple_form.id.yml
index 6b2868e02..fcd9d862c 100644
--- a/config/locales/simple_form.id.yml
+++ b/config/locales/simple_form.id.yml
@@ -3,9 +3,9 @@ id:
   simple_form:
     hints:
       defaults:
-        avatar: PNG, GIF atau JPG. Maksimal 2MB. Ukuran dikecilkan menjadi 400x400px
+        avatar: PNG, GIF atau JPG. Maksimal %{size}. Ukuran dikecilkan menjadi %{dimensions}px
         display_name: Maksimal 30 karakter
-        header: PNG, GIF atau JPG. Maksimal 2MB. Ukuran dikecilkan menjadi 700x335px
+        header: PNG, GIF atau JPG. Maksimal %{size}. Ukuran dikecilkan menjadi %{dimensions}px
         locked: Anda harus menerima permintaan pengikut secara manual dan setting privasi postingan akan diubah khusus untuk pengikut
         note: Maksimum 160 karakter
       imports:
diff --git a/config/locales/simple_form.io.yml b/config/locales/simple_form.io.yml
index 60b578a12..cf87aa6d9 100644
--- a/config/locales/simple_form.io.yml
+++ b/config/locales/simple_form.io.yml
@@ -3,9 +3,9 @@ io:
   simple_form:
     hints:
       defaults:
-        avatar: En la formato PNG, GIF o JPG. Til 2Mo. Esos mikrigita a 400x400px
+        avatar: En la formato PNG, GIF o JPG. Til 2Mo. Esos mikrigita a %{dimensions}px
         display_name: 30 signi maxime
-        header: En la formato PNG, GIF o JPG. Til 2Mo. Esos mikrigita a 700x335px
+        header: En la formato PNG, GIF o JPG. Til 2Mo. Esos mikrigita a %{dimensions}px
         locked: Tu devos aprobar omna demandi di sequado, e tua mesaji esos senchanje nur por tua sequanti.
         note: 160 signi maxime
       imports:
diff --git a/config/locales/simple_form.it.yml b/config/locales/simple_form.it.yml
index 16de1efd2..810ac813e 100644
--- a/config/locales/simple_form.it.yml
+++ b/config/locales/simple_form.it.yml
@@ -4,7 +4,7 @@ it:
     hints:
       defaults:
         autofollow: Le persone che si iscrivono attraverso l'invito ti seguiranno automaticamente
-        avatar: PNG, GIF o JPG. Al massimo 2MB. Verranno scalate a 400x400px
+        avatar: PNG, GIF o JPG. Al massimo %{size}. Verranno scalate a %{dimensions}px
         bot: Questo account esegue principalmente operazioni automatiche e potrebbe non essere tenuto sotto controllo da una persona
         context: Uno o più contesti nei quali il filtro dovrebbe essere applicato
         digest: Inviata solo dopo un lungo periodo di inattività e solo se hai ricevuto qualche messaggio personale in tua assenza
@@ -12,7 +12,7 @@ it:
           one: <span class="name-counter">1</span> carattere rimanente
           other: <span class="name-counter">%{count}</span> caratteri rimanenti
         fields: Puoi avere fino a 4 voci visualizzate come una tabella sul tuo profilo
-        header: PNG, GIF o JPG. Al massimo 2MB. Verranno scalate a 700x335px
+        header: PNG, GIF o JPG. Al massimo %{size}. Verranno scalate a %{dimensions}px
         inbox_url: Copia la URL dalla pagina iniziale del ripetitore che vuoi usare
         irreversible: I toot filtrati scompariranno in modo irreversibile, anche se il filtro viene eliminato
         locale: La lingua dell'interfaccia utente, di email e notifiche push
diff --git a/config/locales/simple_form.ja.yml b/config/locales/simple_form.ja.yml
index ec1b71871..99c7b7cf9 100644
--- a/config/locales/simple_form.ja.yml
+++ b/config/locales/simple_form.ja.yml
@@ -4,13 +4,13 @@ ja:
     hints:
       defaults:
         autofollow: 招待から登録した人が自動的にあなたをフォローするようになります
-        avatar: 2MBまでのPNG、GIF、JPGが利用可能です。400x400pxまで縮小されます
+        avatar: "%{size}までのPNG、GIF、JPGが利用可能です。%{dimensions}pxまで縮小されます"
         bot: このアカウントは主に自動で動作し、人が見ていない可能性があります
         context: フィルターを適用する対象 (複数選択可)
         digest: 長期間使用していない場合と不在時に返信を受けた場合のみ送信されます
         display_name: あと<span class="name-counter">%{count}</span>文字入力できます。
         fields: プロフィールに表として4つまでの項目を表示することができます
-        header: 2MBまでのPNG、GIF、JPGが利用可能です。 700x335pxまで縮小されます
+        header: "%{size}までのPNG、GIF、JPGが利用可能です。 %{dimensions}pxまで縮小されます"
         inbox_url: 使用したいリレーサーバーのトップページからURLをコピーします
         irreversible: フィルターが後で削除されても、除外されたトゥートは元に戻せなくなります
         locale: ユーザーインターフェース、メールやプッシュ通知の言語
diff --git a/config/locales/simple_form.ko.yml b/config/locales/simple_form.ko.yml
index 392c24e82..73751fc99 100644
--- a/config/locales/simple_form.ko.yml
+++ b/config/locales/simple_form.ko.yml
@@ -4,7 +4,7 @@ ko:
     hints:
       defaults:
         autofollow: 이 초대를 통해 가입하는 사람은 당신을 자동으로 팔로우 하게 됩니다
-        avatar: PNG, GIF 혹은 JPG. 최대 2MB. 400x400px로 다운스케일 될 것임
+        avatar: PNG, GIF 혹은 JPG. 최대 %{size}. %{dimensions}px로 다운스케일 될 것임
         bot: 사람들에게 계정이 사람이 아님을 알립니다
         context: 필터를 적용 할 한 개 이상의 컨텍스트
         digest: 오랫동안 활동하지 않았을 때 받은 멘션들에 대한 요약 받기
@@ -12,7 +12,8 @@ ko:
           one: <span class="name-counter">1</span> 글자 남음
           other: <span class="name-counter">%{count}</span> 글자 남음
         fields: 당신의 프로파일에 최대 4개까지 표 형식으로 나타낼 수 있습니다
-        header: PNG, GIF 혹은 JPG. 최대 2MB. 700x335px로 다운스케일 됨
+        header: PNG, GIF 혹은 JPG. 최대 %{size}. %{dimensions}px로 다운스케일 됨
+        inbox_url: 사용 할 릴레이 서버의 프론트페이지에서 URL을 복사합니다
         irreversible: 필터링 된 툿은 나중에 필터가 사라지더라도 돌아오지 않게 됩니다
         locale: 유저 인터페이스, 이메일, 푸시 알림 언어
         locked: 수동으로 팔로워를 승인하고, 기본 툿 프라이버시 설정을 팔로워 전용으로 변경
@@ -52,6 +53,7 @@ ko:
         expires_in: 만료시각
         fields: 프로필 메타데이터
         header: 헤더
+        inbox_url: 릴레이 서버의 inbox URL
         irreversible: 숨기는 대신 삭제
         locale: 인터페이스 언어
         locked: 계정 잠금
diff --git a/config/locales/simple_form.nl.yml b/config/locales/simple_form.nl.yml
index 47520a55b..ddbc58978 100644
--- a/config/locales/simple_form.nl.yml
+++ b/config/locales/simple_form.nl.yml
@@ -4,7 +4,7 @@ nl:
     hints:
       defaults:
         autofollow: Mensen die zich via de uitnodiging hebben geregistreerd, volgen jou automatisch
-        avatar: PNG, GIF of JPG. Maximaal 2MB. Wordt teruggeschaald naar 400x400px
+        avatar: PNG, GIF of JPG. Maximaal %{size}. Wordt teruggeschaald naar %{dimensions}px
         bot: Dit is een geautomatiseerd account en wordt mogelijk niet gemonitord
         context: Een of meerdere locaties waar de filter actief moet zijn
         digest: Wordt alleen na een lange periode van inactiviteit verzonden en alleen wanneer je tijdens jouw afwezigheid persoonlijke berichten hebt ontvangen
@@ -12,7 +12,7 @@ nl:
           one: <span class="name-counter">1</span> teken over
           other: <span class="name-counter">%{count}</span> tekens over
         fields: Je kan maximaal 4 items als een tabel op je profiel weergeven
-        header: PNG, GIF of JPG. Maximaal 2MB. Wordt teruggeschaald naar 700x335px
+        header: PNG, GIF of JPG. Maximaal %{size}. Wordt teruggeschaald naar %{dimensions}px
         inbox_url: Kopieer de URL van de voorpagina van de relayserver die je wil gebruiken
         irreversible: Gefilterde toots verdwijnen onomkeerbaar, zelfs als de filter later wordt verwijderd
         locale: De taal van de gebruikersomgeving, e-mails en pushmeldingen
diff --git a/config/locales/simple_form.no.yml b/config/locales/simple_form.no.yml
index aba8feeb6..98c6b82fe 100644
--- a/config/locales/simple_form.no.yml
+++ b/config/locales/simple_form.no.yml
@@ -3,12 +3,12 @@
   simple_form:
     hints:
       defaults:
-        avatar: PNG, GIF eller JPG. Maksimalt 2 MB. Vil bli nedskalert til 400x400px
+        avatar: PNG, GIF eller JPG. Maksimalt %{size}. Vil bli nedskalert til %{dimensions}px
         digest: Kun sendt etter en lang periode med inaktivitet og bare dersom du har mottatt noen personlige meldinger mens du var borte
         display_name:
           one: <span class="name-counter">1</span> tegn igjen
           other: <span class="name-counter">%{count}</span> tegn igjen
-        header: PNG, GIF eller JPG. Maksimalt 2MB. Vil bli nedskalert til 700x335px
+        header: PNG, GIF eller JPG. Maksimalt %{size}. Vil bli nedskalert til %{dimensions}px
         locked: Krever at du manuelt godkjenner følgere
         note:
           one: <span class="note-counter">1</span> tegn igjen
diff --git a/config/locales/simple_form.oc.yml b/config/locales/simple_form.oc.yml
index 293ad964a..4842e5c4e 100644
--- a/config/locales/simple_form.oc.yml
+++ b/config/locales/simple_form.oc.yml
@@ -4,7 +4,7 @@ oc:
     hints:
       defaults:
         autofollow: Lo monde que se marcan gràcia a l’invitacion vos segràn automaticament
-        avatar: PNG, GIF o JPG. Maximum 2 Mo. Serà retalhat en 400x400px
+        avatar: PNG, GIF o JPG. Maximum 2 Mo. Serà retalhat en %{dimensions}px
         bot: Avisar lo monde qu’aqueste compte es pas d’una persona
         context: Un o mai de contèxtes ont lo filtre deuriá s’aplicar
         digest: Solament enviat aprèp un long moment d’inactivitat e solament s’avètz recebut de messatges personals pendent vòstra abséncia
@@ -12,7 +12,7 @@ oc:
           one: Demòra encara <span class="name-counter">1</span> caractèr
           other: Demòran encara <span class="name-counter">%{count}</span> caractèrs
         fields: Podètz far veire cap a 4 elements sus vòstre perfil
-        header: PNG, GIF o JPG. Maximum 2 Mo. Serà retalhada en 700x335px
+        header: PNG, GIF o JPG. Maximum 2 Mo. Serà retalhada en %{dimensions}px
         inbox_url: Copiatz l’URL de la pagina màger del relai que volètz utilizar
         irreversible: Los tuts filtrats desapareisseràn irreversiblament, encara que lo filtre siá suprimit mai tard
         locale: La lenga de l’interfàcia d’utilizacion, los messatges e las notificacions
diff --git a/config/locales/simple_form.pl.yml b/config/locales/simple_form.pl.yml
index 6e09814bd..9008d2338 100644
--- a/config/locales/simple_form.pl.yml
+++ b/config/locales/simple_form.pl.yml
@@ -4,7 +4,7 @@ pl:
     hints:
       defaults:
         autofollow: Osoby, które zarejestrują się z Twojego zaproszenia automatycznie zaczną Cię śledzić
-        avatar: PNG, GIF lub JPG. Maksymalnie 2MB. Zostanie zmniejszony do 400x400px
+        avatar: PNG, GIF lub JPG. Maksymalnie %{size}. Zostanie zmniejszony do %{dimensions}px
         bot: To konto wykonuje głównie zautomatyzowane działania i może nie być monitorowane
         context: Jedno lub wiele miejsc, w których filtr zostanie zastosowany
         digest: Wysyłane tylko po długiej nieaktywności, jeżeli w tym czasie otrzymaleś jakąś wiadomość bezpośrednią
@@ -14,7 +14,7 @@ pl:
           one: Pozostał <span class="name-counter">1</span> znak
           other: Pozostało <span class="name-counter">%{count}</span> znaków
         fields: Możesz ustawić maksymalnie 4 niestandardowe pola wyświetlane jako tabela na Twoim profilu
-        header: PNG, GIF lub JPG. Maksymalnie 2MB. Zostanie zmniejszony do 700x335px
+        header: PNG, GIF lub JPG. Maksymalnie %{size}. Zostanie zmniejszony do %{dimensions}px
         irreversible: Filtrowane wpisy znikną bezpowrotnie, nawet gdy filtr zostanie usunięty
         locale: Język interfejsu, wiadomości e-mail i powiadomieniach push
         locked: Musisz akceptować prośby o śledzenie
diff --git a/config/locales/simple_form.pt-BR.yml b/config/locales/simple_form.pt-BR.yml
index f6738b73f..013b26066 100644
--- a/config/locales/simple_form.pt-BR.yml
+++ b/config/locales/simple_form.pt-BR.yml
@@ -4,7 +4,7 @@ pt-BR:
     hints:
       defaults:
         autofollow: Pessoas que se cadastrarem através de seu convite te seguirão automaticamente
-        avatar: PNG, GIF or JPG. Arquivos de até 2MB. Eles serão diminuídos para 400x400px
+        avatar: PNG, GIF or JPG. Arquivos de até %{size}. Eles serão diminuídos para %{dimensions}px
         bot: Essa conta executa principalmente ações automatizadas e pode não ser monitorada
         context: Um ou mais contextos onde o filtro deve ser aplicado
         digest: Enviado após um longo período de inatividade com um resumo das menções que você recebeu em sua ausência
@@ -12,7 +12,7 @@ pt-BR:
           one: <span class="name-counter">1</span> caracter restante
           other: <span class="name-counter">%{count}</span> caracteres restantes
         fields: Você pode ter até 4 itens exibidos em forma de tabela no seu perfil
-        header: PNG, GIF or JPG. Arquivos de até 2MB. Eles serão diminuídos para 700x335px
+        header: PNG, GIF or JPG. Arquivos de até %{size}. Eles serão diminuídos para %{dimensions}px
         inbox_url: Copie a URL da página inicial do repetidor que você quer usar
         irreversible: Os toots filtrados vão desaparecer irreversivelmente, mesmo se o filtro for removido depois
         locale: O idioma das telas de usuário, e-mails e notificações push
diff --git a/config/locales/simple_form.pt.yml b/config/locales/simple_form.pt.yml
index 5b79bd29f..8c515c1de 100644
--- a/config/locales/simple_form.pt.yml
+++ b/config/locales/simple_form.pt.yml
@@ -3,12 +3,12 @@ pt:
   simple_form:
     hints:
       defaults:
-        avatar: PNG, GIF or JPG. Arquivos até 2MB. Vão ser reduzidos para 400x400px
+        avatar: PNG, GIF or JPG. Arquivos até %{size}. Vão ser reduzidos para %{dimensions}px
         digest: Enviado após um longo período de inatividade e apenas se foste mencionado na tua ausência
         display_name:
           one: <span class="name-counter">1</span> caracter restante
           other: <span class="name-counter">%{count}</span> caracteres restantes
-        header: PNG, GIF or JPG. Arquivos até 2MB. Vão ser reduzidos para 700x335px
+        header: PNG, GIF or JPG. Arquivos até %{size}. Vão ser reduzidos para %{dimensions}px
         locked: Requer aprovação manual de seguidores
         note:
           one: <span class="note-counter">1</span> caracter restante
diff --git a/config/locales/simple_form.ru.yml b/config/locales/simple_form.ru.yml
index 6bb95b13f..9174237bc 100644
--- a/config/locales/simple_form.ru.yml
+++ b/config/locales/simple_form.ru.yml
@@ -3,7 +3,7 @@ ru:
   simple_form:
     hints:
       defaults:
-        avatar: PNG, GIF или JPG. Максимально 2MB. Будет уменьшено до 400x400px
+        avatar: PNG, GIF или JPG. Максимально %{size}. Будет уменьшено до %{dimensions}px
         bot: Этот аккаунт обычно выполяет автоматизированные действия и может не просматриваться владельцем
         digest: Отсылается лишь после длительной неактивности, если Вы в это время получали личные сообщения
         display_name:
@@ -12,7 +12,7 @@ ru:
           one: Остался <span class="name-counter">1</span> символ
           other: Осталось <span class="name-counter">%{count}</span> символов
         fields: В профиле можно отобразить до 4 пунктов как таблицу
-        header: PNG, GIF или JPG. Максимально 2MB. Будет уменьшено до 700x335px
+        header: PNG, GIF или JPG. Максимально %{size}. Будет уменьшено до %{dimensions}px
         locked: Потребует от Вас ручного подтверждения подписчиков, изменит приватность постов по умолчанию на "только для подписчиков"
         note:
           few: Осталось <span class="name-counter">%{count}</span> символа
diff --git a/config/locales/simple_form.sk.yml b/config/locales/simple_form.sk.yml
index 8064dbdae..c9ec7fb20 100644
--- a/config/locales/simple_form.sk.yml
+++ b/config/locales/simple_form.sk.yml
@@ -4,7 +4,7 @@ sk:
     hints:
       defaults:
         autofollow: Ľudia ktorí sa zaregistrujú prostredníctvom pozvánky, ťa budú inheď následovať
-        avatar: PNG, GIF alebo JPG. Maximálne 2MB. Bude zmenšený na 400x400px
+        avatar: PNG, GIF alebo JPG. Maximálne %{size}. Bude zmenšený na %{dimensions}px
         bot: Tento účet vykonáva hlavne automatizované akcie, a je pravdepodobne nespravovaný
         context: Jedno, alebo viac kritérií, v ktorých má byť filtrovanie uplatnené
         digest: Odoslané iba v prípade dlhodobej neprítomnosti, a len ak si obdŕžal/a nejaké osobné správy kým si bol/a preč
@@ -13,7 +13,7 @@ sk:
           one: Ostáva ti <span class="name-counter">1</span> znak
           other: Ostáva ti <span class="name-counter">%{count}</span> znakov
         fields: Môžeš mať 4 položky na svojom profile zobrazené vo forme tabuľky
-        header: PNG, GIF alebo JPG. Maximálne 2MB. Bude zmenšený na 700x335px
+        header: PNG, GIF alebo JPG. Maximálne %{size}. Bude zmenšený na %{dimensions}px
         inbox_url: Skopíruj adresu z hlavnej stránky mostíka, ktorý chceš používať
         irreversible: Vytriedené príspevky zmiznú nenávratne, aj keď triedenie neskôr zrušíš
         locale: Jazyk užívateľského rozhrania, emailových a nástenkových oboznámení
diff --git a/config/locales/simple_form.sl.yml b/config/locales/simple_form.sl.yml
index 31d1e1170..0f86841d3 100644
--- a/config/locales/simple_form.sl.yml
+++ b/config/locales/simple_form.sl.yml
@@ -3,13 +3,13 @@ sl:
   simple_form:
     hints:
       defaults:
-        avatar: PNG, GIF ali JPG. Največ 2MB. Zmanjšana bo na 400x400px
+        avatar: PNG, GIF ali JPG. Največ %{size}. Zmanjšana bo na %{dimensions}px
         bot: Opozarja ljudi, da račun ne predstavlja osebe
         digest: Pošlje se le po dolgem obdobju nedejavnosti in samo, če ste prejeli osebna sporočila v vaši odsotnosti
         display_name:
           one: <span class="name-counter">1</span> znak ostane
           other: <span class="name-counter">%{count}</span> znakov ostane
         fields: Na svojem profilu lahko imate do 4 predmete prikazane kot tabelo.
-        header: PNG, GIF ali JPG. Največ 2MB. Zmanjšana bo na 700x335px
+        header: PNG, GIF ali JPG. Največ %{size}. Zmanjšana bo na %{dimensions}px
       imports:
         data: Izvožena CSV datoteka iz drugega Mastodon vozlišča
diff --git a/config/locales/simple_form.sr-Latn.yml b/config/locales/simple_form.sr-Latn.yml
index 608630c0c..259ac0046 100644
--- a/config/locales/simple_form.sr-Latn.yml
+++ b/config/locales/simple_form.sr-Latn.yml
@@ -3,14 +3,14 @@ sr-Latn:
   simple_form:
     hints:
       defaults:
-        avatar: PNG, GIF ili JPG. Najviše 2MB. Biće smanjena na 400x400px
+        avatar: PNG, GIF ili JPG. Najviše %{size}. Biće smanjena na %{dimensions}px
         digest: Poslato posle dužeg perioda neaktivnosti sa pregledom svih bitnih stvari koje ste dobili dok ste bili odsutni
         display_name:
           few: <span class="name-counter">%{count}</span> karaktera preostala
           many: <span class="name-counter">%{count}</span> karaktera preostalo
           one: <span class="name-counter">1</span> karakter preostao
           other: <span class="name-counter">%{count}</span> karaktera preostalo
-        header: PNG, GIF ili JPG. Najviše 2MB. Biće smanjena na 700x335px
+        header: PNG, GIF ili JPG. Najviše %{size}. Biće smanjena na %{dimensions}px
         locked: Zahteva da pojedinačno odobrite pratioce
         note:
           few: <span class="note-counter">%{count}</span> karaktera preostal
diff --git a/config/locales/simple_form.sr.yml b/config/locales/simple_form.sr.yml
index ab9ef0f49..d84052c66 100644
--- a/config/locales/simple_form.sr.yml
+++ b/config/locales/simple_form.sr.yml
@@ -3,14 +3,14 @@ sr:
   simple_form:
     hints:
       defaults:
-        avatar: PNG, GIF или JPG. Највише 2MB. Биће смањена на 400x400px
+        avatar: PNG, GIF или JPG. Највише %{size}. Биће смањена на %{dimensions}px
         digest: Послато после дужег периода неактивности са прегледом свих битних ствари које сте добили док сте били одсутни
         display_name:
           few: <span class="name-counter">%{count}</span> карактера преостала
           many: <span class="name-counter">%{count}</span> карактера преостало
           one: <span class="name-counter">1</span> карактер преостао
           other: <span class="name-counter">%{count}</span> карактера преостало
-        header: PNG, GIF или JPG. Највише 2MB. Биће смањена на 700x335px
+        header: PNG, GIF или JPG. Највише %{size}. Биће смањена на %{dimensions}px
         locked: Захтева да појединачно одобрите пратиоце
         note:
           few: <span class="note-counter">%{count}</span> карактера преостал
diff --git a/config/locales/simple_form.sv.yml b/config/locales/simple_form.sv.yml
index e761f3d99..7a10aa1e2 100644
--- a/config/locales/simple_form.sv.yml
+++ b/config/locales/simple_form.sv.yml
@@ -4,14 +4,14 @@ sv:
     hints:
       defaults:
         autofollow: Användarkonton som skapas genom din inbjudan kommer automatiskt följa dig
-        avatar: Högst 2 MB. Kommer att skalas ner till 400x400px
+        avatar: Högst %{size}. Kommer att skalas ner till %{dimensions}px
         bot: Detta konto utför huvudsakligen automatiserade åtgärder och kanske inte övervakas
         digest: Skickas endast efter en lång period av inaktivitet och endast om du har fått några personliga meddelanden i din frånvaro
         display_name:
           one: <span class="name-counter">1</span> tecken kvar
           other: <span class="name-counter">%{count}</span> tecken kvar
         fields: Du kan ha upp till 4 objekt visade som en tabell på din profil
-        header: NG, GIF eller JPG. Högst 2 MB. Kommer nedskalas till 700x335px
+        header: NG, GIF eller JPG. Högst %{size}. Kommer nedskalas till %{dimensions}px
         locale: Användargränssnittets språk, e-post och push aviseringar
         locked: Kräver att du manuellt godkänner följare
         note:
diff --git a/config/locales/simple_form.th.yml b/config/locales/simple_form.th.yml
index 575b6a9f4..29491de0b 100644
--- a/config/locales/simple_form.th.yml
+++ b/config/locales/simple_form.th.yml
@@ -3,11 +3,11 @@ th:
   simple_form:
     hints:
       defaults:
-        avatar: PNG, GIF or JPG. At most 2MB. Will be downscaled to 400x400px
+        avatar: PNG, GIF or JPG. At most %{size}. Will be downscaled to %{dimensions}px
         display_name:
           one: <span class="name-counter">1</span> character left
           other: <span class="name-counter">%{count}</span> characters left
-        header: PNG, GIF or JPG. At most 2MB. Will be downscaled to 700x335px
+        header: PNG, GIF or JPG. At most %{size}. Will be downscaled to %{dimensions}px
         locked: Requires you to manually approve followers and defaults post privacy to followers-only
         note:
           one: <span class="name-counter">1</span> character left
diff --git a/config/locales/simple_form.tr.yml b/config/locales/simple_form.tr.yml
index c827aac46..bd5c65d83 100644
--- a/config/locales/simple_form.tr.yml
+++ b/config/locales/simple_form.tr.yml
@@ -3,9 +3,9 @@ tr:
   simple_form:
     hints:
       defaults:
-        avatar: En fazla 2MB olacak şekilde PNG, GIF veya JPG formatında yükleyiniz. 400x400px büyüklüğüne indirgenecektir
+        avatar: En fazla %{size} olacak şekilde PNG, GIF veya JPG formatında yükleyiniz. %{dimensions}px büyüklüğüne indirgenecektir
         display_name: <span class="name-counter">%{count}</span> karakter kaldı
-        header: En fazla 2MB olacak şekilde PNG, GIF veya JPG formatında yükleyiniz. 700x335px büyüklüğüne indirgenecektir.
+        header: En fazla %{size} olacak şekilde PNG, GIF veya JPG formatında yükleyiniz. %{dimensions}px büyüklüğüne indirgenecektir.
         locked: Takipçilerinizi manuel olarak kabul etmenizi ve gönderilerinizi varsayılan olarak sadece takipçilerinizin göreceği şekilde paylaşmanızı sağlar.
         note: <span class="note-counter">%{count}</span> karakter kaldı
       imports:
diff --git a/config/locales/simple_form.uk.yml b/config/locales/simple_form.uk.yml
index 7bc3ee4b8..b4d2d6a80 100644
--- a/config/locales/simple_form.uk.yml
+++ b/config/locales/simple_form.uk.yml
@@ -3,9 +3,9 @@ uk:
   simple_form:
     hints:
       defaults:
-        avatar: PNG, GIF, або JPG. Максимум - 2МБ. Буде зменшено до 400x400px
+        avatar: PNG, GIF, або JPG. Максимум - 2МБ. Буде зменшено до %{dimensions}px
         display_name: 'Залишилося символів: <span class="name-counter">%{count}</span>'
-        header: PNG, GIF, або JPG. Максимум - 2МБ. Буде зменшено до 700x335px
+        header: PNG, GIF, або JPG. Максимум - 2МБ. Буде зменшено до %{dimensions}px
         locked: Буде вимагати від Вас самостійного підтверждення підписників, змінить приватність постів за замовчуванням на "тільки для підписників"
         note: 'Осталось символов: <span class="note-counter">%{count}</span>'
       imports:
diff --git a/config/locales/simple_form.zh-CN.yml b/config/locales/simple_form.zh-CN.yml
index ce990d692..b84f7107d 100644
--- a/config/locales/simple_form.zh-CN.yml
+++ b/config/locales/simple_form.zh-CN.yml
@@ -4,12 +4,12 @@ zh-CN:
     hints:
       defaults:
         autofollow: 通过邀请链接注册的用户将会自动关注你
-        avatar: 文件大小限制 2MB,只支持 PNG、GIF 或 JPG 格式。图片分辨率将会压缩至 400×400px
+        avatar: 文件大小限制 %{size},只支持 PNG、GIF 或 JPG 格式。图片分辨率将会压缩至 400×400px
         bot: 来自这个帐户的绝大多数操作都是自动进行的,并且可能无人监控
         digest: 仅在你长时间未登录,且收到了私信时发送
         display_name: 还能输入 <span class="name-counter">%{count}</span> 个字符
         fields: 这将会在个人资料页上以表格的形式展示,最多 4 个项目
-        header: 文件大小限制 2MB,只支持 PNG、GIF 或 JPG 格式。图片分辨率将会压缩至 700×335px
+        header: 文件大小限制 %{size},只支持 PNG、GIF 或 JPG 格式。图片分辨率将会压缩至 700×335px
         locale: 用户界面、电子邮件和推送通知中使用的语言
         locked: 你需要手动审核所有关注请求
         note: 还能输入 <span class="note-counter">%{count}</span> 个字符
diff --git a/config/locales/simple_form.zh-HK.yml b/config/locales/simple_form.zh-HK.yml
index 0575c09f8..abe6b7e06 100644
--- a/config/locales/simple_form.zh-HK.yml
+++ b/config/locales/simple_form.zh-HK.yml
@@ -4,14 +4,14 @@ zh-HK:
     hints:
       defaults:
         autofollow: 通過邀請網址註冊的用戶將會自動關注你
-        avatar: 支援 PNG, GIF 或 JPG 圖片,檔案最大為 2MB,會縮裁成 400x400px
+        avatar: 支援 PNG, GIF 或 JPG 圖片,檔案最大為 %{size},會縮裁成 %{dimensions}px
         bot: 提醒用戶本帳號是機械人
         digest: 僅在你長時間未登錄,且收到了私信時發送
         display_name:
           one: 尚餘 <span class="name-counter">1</span> 個字
           other: 尚餘 <span class="name-counter">%{count}</span> 個字
         fields: 個人資料頁可顯示多至 4 個項目
-        header: 支援 PNG, GIF 或 JPG 圖片,檔案最大為 2MB,會縮裁成 700x335px
+        header: 支援 PNG, GIF 或 JPG 圖片,檔案最大為 %{size},會縮裁成 %{dimensions}px
         locale: 使用者介面、電郵和通知的語言
         locked: 你必須人手核准每個用戶對你的關注請求,而你的文章私隱會被預設為「只有關注你的人能看」
         note:
diff --git a/config/locales/simple_form.zh-TW.yml b/config/locales/simple_form.zh-TW.yml
index 6b1dbae91..3763fc747 100644
--- a/config/locales/simple_form.zh-TW.yml
+++ b/config/locales/simple_form.zh-TW.yml
@@ -4,14 +4,14 @@ zh-TW:
     hints:
       defaults:
         autofollow: 通過邀請網址註冊的使用者將會自動關注你
-        avatar: 支援 PNG, GIF 或 JPG 圖片,檔案最大為 2MB,會縮裁成 400x400px
+        avatar: 支援 PNG, GIF 或 JPG 圖片,檔案最大為 %{size},會縮裁成 %{dimensions}px
         bot: 這個帳號由程式進行自動式操作
         digest: 僅在你長時間未登入,並且收到了私訊時發送
         display_name:
           one: 尚餘 <span class="name-counter">1</span> 個字
           other: 尚餘 <span class="name-counter">%{count}</span> 個字
         fields: 個人資訊頁至多可顯示 4 個項目
-        header: 支援 PNG, GIF 或 JPG 圖片,檔案最大為 2MB,會縮裁成 700x335px
+        header: 支援 PNG, GIF 或 JPG 圖片,檔案最大為 %{size},會縮裁成 %{dimensions}px
         locale: 使用者介面、 E-mail 與通知的語言
         locked: 你必須手動核准每個使用者對你的關注請求,而你的貼文隱私將會被設定為「只有關注你的人能看」
         note:
diff --git a/config/locales/sk.yml b/config/locales/sk.yml
index 3be28dd4c..4a409de5b 100644
--- a/config/locales/sk.yml
+++ b/config/locales/sk.yml
@@ -46,7 +46,6 @@ sk:
     people_who_follow: Ľudia sledujúci %{name}
     posts: Príspevky
     posts_with_replies: Príspevky s odpoveďami
-    remote_follow: Sleduj vzdialeného
     reserved_username: Prihlasovacie meno je rezervované
     roles:
       admin: Administrátor
@@ -526,7 +525,6 @@ sk:
     unlocked_warning_title: Tvoj účet nieje zamknutý
   generic:
     changes_saved_msg: Zmeny boli úspešne uložené!
-    powered_by: poháňané vďaka %{link}
     save_changes: Uložiť zmeny
     validation_errors:
       few: Niečo ešte stále nieje v poriadku! Prosím skontroluj všetky %{count} chyby
@@ -564,8 +562,6 @@ sk:
       expires_at: Vyprší
       uses: Používa
     title: Pozvi ľudí
-  landing_strip_html: "<strong>%{name}</strong> je užívateľ na serveri %{link_to_root_path}. Ty ich môžeš následovať a môžeš s nimi interaktovať pokiaľ máš účet kdekoľvek v rámci fediversa."
-  landing_strip_signup_html: Pokiaľ ešte nemáš, môžeš <a href="%{sign_up_path}">si tu vytvoriť účet</a>.
   lists:
     errors:
       limit: Dosiahli ste maximálny možný počet zoznamov
@@ -725,7 +721,6 @@ sk:
       unlisted: Nezaradené
       unlisted_long: Všetci môžu vidieť, ale nieje zaradené do verejnej osi
   stream_entries:
-    click_to_show: Klikni pre zobrazenie
     pinned: Pripnutý toot
     reblogged: vyzdvihnutý
     sensitive_content: Senzitívny obsah
diff --git a/config/locales/sl.yml b/config/locales/sl.yml
index 6f581f838..16ace08d3 100644
--- a/config/locales/sl.yml
+++ b/config/locales/sl.yml
@@ -42,7 +42,6 @@ sl:
     people_who_follow: Ljudje, ki sledijo %{name}
     posts: Tuti
     posts_with_replies: Tuti in odgovori
-    remote_follow: Oddaljeno sledenje
     reserved_username: Uporabniško ime je zasedeno
     roles:
       admin: Skrbnik
diff --git a/config/locales/sr-Latn.yml b/config/locales/sr-Latn.yml
index 15c6b00ac..d7dd574c7 100644
--- a/config/locales/sr-Latn.yml
+++ b/config/locales/sr-Latn.yml
@@ -44,7 +44,6 @@ sr-Latn:
     people_who_follow: Ljudi koji prate %{name}
     posts: Tutovi
     posts_with_replies: Tutovi i odgovori
-    remote_follow: Udaljena praćenja
     reserved_username: Korisničko ime je rezervisano
     roles:
       admin: Administrator
@@ -422,7 +421,6 @@ sr-Latn:
     unlocked_warning_title: Vaš nalog nije zaključan
   generic:
     changes_saved_msg: Izmene uspešno sačuvane!
-    powered_by: omogućio %{link}
     save_changes: Snimi izmene
     validation_errors:
       few: Nešto nije baš kako treba! Pregledajte %{count} greške ispod
@@ -460,8 +458,6 @@ sr-Latn:
       expires_at: Ističe
       uses: Korišćenja
     title: Pozovi ljude
-  landing_strip_html: "<strong>%{name}</strong> je korisnik na %{link_to_root_path}. Možete ga zapratiti ili komunicirati sa njim ako imte nalog bilo gde u fediversu."
-  landing_strip_signup_html: Ako nemate, možete se <a href="%{sign_up_path}">registrovati ovde</a>.
   lists:
     errors:
       limit: Dostigli ste limit broja listi
@@ -602,7 +598,6 @@ sr-Latn:
       unlisted: Neizlistano
       unlisted_long: Svako može da vidi, ali nije izlistano na javnim lajnama
   stream_entries:
-    click_to_show: Klikni da vidiš
     pinned: Prikačeni tut
     reblogged: podržano
     sensitive_content: Osetljiv sadržaj
diff --git a/config/locales/sr.yml b/config/locales/sr.yml
index 040090932..63c42f62f 100644
--- a/config/locales/sr.yml
+++ b/config/locales/sr.yml
@@ -45,7 +45,6 @@ sr:
     people_who_follow: Људи који прате %{name}
     posts: Тутови
     posts_with_replies: Тутови и одговори
-    remote_follow: Удаљена праћења
     reserved_username: Корисничко име је резервисано
     roles:
       admin: Администратор
@@ -423,7 +422,6 @@ sr:
     unlocked_warning_title: Ваш налог није закључан
   generic:
     changes_saved_msg: Измене успешно сачуване!
-    powered_by: омогућио %{link}
     save_changes: Сними измене
     validation_errors:
       few: Нешто није баш како треба! Прегледајте %{count} грешке испод
@@ -461,8 +459,6 @@ sr:
       expires_at: Истиче
       uses: Коришћења
     title: Позови људе
-  landing_strip_html: "<strong>%{name}</strong> је корисник на %{link_to_root_path}. Можете га запратити или комуницирати са њим ако имте налог било где у федиверсу."
-  landing_strip_signup_html: Ако немате, можете се <a href="%{sign_up_path}">регистровати овде</a>.
   lists:
     errors:
       limit: Достигли сте лимит броја листи
@@ -603,7 +599,6 @@ sr:
       unlisted: Неизлистано
       unlisted_long: Свако може да види, али није излистано на јавним лајнама
   stream_entries:
-    click_to_show: Кликни да видиш
     pinned: Прикачени тут
     reblogged: подржано
     sensitive_content: Осетљив садржај
diff --git a/config/locales/sv.yml b/config/locales/sv.yml
index 76b26c24f..cf1ab582f 100644
--- a/config/locales/sv.yml
+++ b/config/locales/sv.yml
@@ -46,7 +46,6 @@ sv:
     people_who_follow: Personer som följer %{name}
     posts: Toots
     posts_with_replies: Toots med svar
-    remote_follow: Avlägsen följare
     reserved_username: Användarnamnet är reserverat
     roles:
       admin: Admin
@@ -488,7 +487,6 @@ sv:
     unlocked_warning_title: Ditt konto är inte låst
   generic:
     changes_saved_msg: Ändringar sparades framgångsrikt!
-    powered_by: drivs av %{link}
     save_changes: Spara ändringar
     validation_errors:
       one: Något är inte riktigt rätt ännu! Kontrollera felet nedan
@@ -524,8 +522,6 @@ sv:
       expires_at: Utgår
       uses: Användningar
     title: Bjud in andra
-  landing_strip_html: "<strong>%{name}</strong> är en användare på %{link_to_root_path}. Du kan följa dem eller interagera med dem om du har ett konto någonstans i federationen."
-  landing_strip_signup_html: Om du inte gör det, så kan du <a href="%{sign_up_path}">registrera dig här</a>.
   lists:
     errors:
       limit: Du har nått det maximala antalet listor
@@ -693,7 +689,6 @@ sv:
       unlisted: Olistade
       unlisted_long: Alla kan se, men listas inte på offentliga tidslinjer
   stream_entries:
-    click_to_show: Klicka för att visa
     pinned: Fäst toot
     reblogged: boostad
     sensitive_content: Känsligt innehåll
diff --git a/config/locales/th.yml b/config/locales/th.yml
index 6804dbd13..182bde388 100644
--- a/config/locales/th.yml
+++ b/config/locales/th.yml
@@ -22,7 +22,6 @@ th:
     people_followed_by: ถูกติดตามโดย %{name}
     people_who_follow: คนที่ติดตาม %{name}
     posts: โพสต์
-    remote_follow: Remote follow
     unfollow: เลิกติดตาม
   admin:
     accounts:
@@ -216,7 +215,6 @@ th:
     unlocked_warning_title: แอคเค๊าท์ของคุณไม่ได้ล๊อค
   generic:
     changes_saved_msg: บันทึกการแก้ไขแล้ว!
-    powered_by: powered by %{link}
     save_changes: บันทึกการเปลี่ยนแปลง
     validation_errors:
       one: Something isn't quite right yet! Please review the error below
@@ -229,8 +227,6 @@ th:
       following: Following list
       muting: Muting list
     upload: Upload
-  landing_strip_html: "<strong>%{name}</strong> is a user on %{link_to_root_path}. You can follow them or interact with them if you have an account anywhere in the fediverse."
-  landing_strip_signup_html: If you don't, you can <a href="%{sign_up_path}">sign up here</a>.
   media_attachments:
     validations:
       images_and_video: Cannot attach a video to a status that already contains images
@@ -302,7 +298,6 @@ th:
       unlisted: Unlisted
       unlisted_long: Everyone can see, but not listed on public timelines
   stream_entries:
-    click_to_show: คลิกเพื่อแสดง
     reblogged: boosted
     sensitive_content: Sensitive content
   time:
diff --git a/config/locales/tr.yml b/config/locales/tr.yml
index 8bafbface..3609261ed 100644
--- a/config/locales/tr.yml
+++ b/config/locales/tr.yml
@@ -22,7 +22,6 @@ tr:
     people_followed_by: Kullanıcı %{name}'in takip ettikleri
     people_who_follow: Kullanıcı %{name}'i takip edenler
     posts: Gönderiler
-    remote_follow: Uzaktan takip et
     unfollow: Takibi bırak
   admin:
     accounts:
@@ -214,7 +213,6 @@ tr:
     unlocked_warning_title: Hesabınız kilitlendi
   generic:
     changes_saved_msg: Değişiklikler başarıyla kaydedildi!
-    powered_by: powered by %{link}
     save_changes: Değişiklikleri kaydet
     validation_errors:
       one: Bir şeyler ters gitti! Lütfen aşağıdaki hatayı gözden geçiriniz
@@ -227,8 +225,6 @@ tr:
       following: Takip edilenler listesi
       muting: Susturulanlar listesi
     upload: Yükle
-  landing_strip_html: "<strong>%{name}</strong>, %{link_to_root_path} sunucusundaki bir kullanıcıdır. Onu takip edebilir, veya Mastodon ağındaki bir hesabınızı kullanarak etkileşime geçebilirsiniz."
-  landing_strip_signup_html: Eğer hesabınız yoksa <a href="%{sign_up_path}">buradan kaydolabilirsiniz</a>.
   media_attachments:
     validations:
       images_and_video: Halihazırda görsel içeren bir gönderiye video ekleyemezsiniz.
@@ -300,7 +296,6 @@ tr:
       unlisted: Listelenmemiş
       unlisted_long: Herkes görebilir fakat herkese açık zaman tünellerinde listelenmez.
   stream_entries:
-    click_to_show: Görüntülemek için tıklayınız
     reblogged: boost edildi
     sensitive_content: Hassas içerik
   time:
diff --git a/config/locales/uk.yml b/config/locales/uk.yml
index 6fe46b4d9..266c878f1 100644
--- a/config/locales/uk.yml
+++ b/config/locales/uk.yml
@@ -1,39 +1,73 @@
 ---
 uk:
   about:
+    about_hashtag_html: Немає публічних постів з хештегом<strong>#%{hashtag}</strong>. Ви можете  You can interact with them if you have an account anywhere in the fediverse.
     about_mastodon_html: Mastodon - це <em>вільна</em> соціальна мережа з <em>відкритим вихідним кодом</em>. Вона є <em>децентралізованою</em> альтернативою комерційним платформам, що дозволяє уникнути ризиків монополізації вашого спілкування однією компанією. Виберіть сервер, якому ви довіряєте &mdash; що б ви не вибрали, Ви зможете спілкуватись з усіма іншими. Будь-який користувач може запустити власну інстанцію Mastodon та без проблем брати участь в <em>соціальній мережі</em>.
     about_this: Про цю інстанцію
     closed_registrations: На даний момент реєстрація на цій інстанції закрита.
     contact: Зв'язатися
+    contact_missing: Не зазначено
     description_headline: Що таке %{domain}?
     domain_count_after: іншими інстанціями
     domain_count_before: Зв'язаний з
+    features:
+      humane_approach_title: Більш людський підхід
+      real_conversation_title: Побудований для справжньої розмови
+      within_reach_title: Завжди на звязку
+    generic_description: "%{domain} є одним сервером у мережі"
+    hosted_on: Мастодон розміщено на %{domain}
+    learn_more: Дізнатися більше
     other_instances: Інші інстанції
     source_code: Вихідний код
     status_count_after: статусів
     status_count_before: Опубліковано
     user_count_after: користувачів
     user_count_before: Тут живе
+    what_is_mastodon: Що таке Мастодон?
   accounts:
     follow: Підписатися
     followers: Підписники
     following: Підписаний(-а)
+    media: Медіа
+    moved_html: "%{name} переїхав на %{new_profile_link}:"
     nothing_here: Тут нічого немає!
     people_followed_by: Люди, на яких підписаний(-а) %{name}
     people_who_follow: Підписники %{name}
     posts: Пости
-    remote_follow: Підписатися на іншій інстанції
+    posts_with_replies: Пости і відповіді
+    reserved_username: Це ім'я користувача зарезервоване
+    roles:
+      admin: Адміністратор
+      bot: Бот
+      moderator: Мод
     unfollow: Відписатися
   admin:
+    account_moderation_notes:
+      create: Залишити примітки
+      created_msg: Примітку модератора успішно створено!
+      delete: Видалити
+      destroyed_msg: Примітку модератора успішно видалено!
     accounts:
       are_you_sure: Ви впевнені?
+      avatar: Аватар
+      change_email:
+        changed_msg: Поштова адреса аккаунту успішно змінена!
+        current_email: Поточна поштова адреса
+        label: Змінити поштову адресу
+        submit: Змінити поштову адресу
+        title: Змінити поштову адресу для %{username}
+      confirm: Зберегти
+      confirmed: Збережено
+      confirming: Зберігається
       display_name: Відображуване ім'я
       domain: Домен
       edit: Змінити
       email: Email
       feed_url: URL фіду
       followers: Підписники
+      followers_url: URL підписників
       follows: Підписки
+      ip: IP
       location:
         all: Усі
         local: Локальні
@@ -45,6 +79,7 @@ uk:
         silenced: Заглушені
         suspended: Заблоковані
         title: Модерація
+      moderation_notes: Примітки модераторів
       most_recent_activity: Остання активність
       most_recent_ip: Останній IP
       not_subscribed: Не підписані
@@ -52,19 +87,105 @@ uk:
         alphabetic: За алфавітом
         most_recent: За датою
         title: Порядок
+      outbox_url: Вихідний URL
       perform_full_suspension: Повне блокування
       profile_url: URL профілю
+      protocol: Протокол
       public: Публічний
       push_subscription_expires: Підписка PuSH спливає
+      redownload: Оновити аватар
+      remove_avatar: Видалити аватар
+      reset: Скинути
       reset_password: Зкинути пароль
+      resubscribe: Перепідписатися
+      role: Дозволи
+      roles:
+        admin: Адміністратор
+        moderator: Модератор
+        staff: Персонал
+        user: Користувач
       salmon_url: Salmon URL
+      search: Пошук
+      shared_inbox_url: URL спільного вхідного кошика
+      show:
+        report: скарга
       silence: Глушення
       statuses: Статуси
+      subscribe: Підписатися
       title: Акаунти
       undo_silenced: Зняти глушення
       undo_suspension: Зняти блокування
+      unsubscribe: Відписатися
       username: Ім'я користувача
       web: WWW
+    action_logs:
+      actions:
+        assigned_to_self_report: "%{name} призначив(-ла) скаргу %{target} на себе"
+        change_email_user: "%{name} змінив(-ла) поштову адресу користувача %{target}"
+        confirm_user: "%{name} підтвердив(-ла) статус поштової адреси користувача %{target}"
+        create_custom_emoji: "%{name} вивантажив(-ла) нове емодзі %{target}"
+        create_domain_block: "%{name} заблокував(-ла) домен %{target}"
+        create_email_domain_block: "%{name} додав(-ла) поштовий домен %{target} до чорного списку"
+        destroy_domain_block: "%{name} розблокував(-ла) домен %{target}"
+        destroy_email_domain_block: "%{name} додав(-ла) поштовий домен %{target} до білого списку"
+        destroy_status: "%{name} видалив(-ла) статус користувача %{target}"
+        disable_2fa_user: "%{name} вимкнув(-ла) двофакторну авторизацію для користувача %{target}"
+        disable_custom_emoji: "%{name} вимкнув(-ла) емодзі %{target}"
+        disable_user: "%{name} заборонив(-ла) авторизацію користувачу %{target}"
+        enable_custom_emoji: "%{name} увімкнув(-ла) емодзі %{target}"
+        enable_user: "%{name} увімкнув(-ла) авторизацію користувачу %{target}"
+        promote_user: "%{name} підвищив(-ла) користувача %{target}"
+        remove_avatar_user: "%{name} прибрав(-ла) аватар користувача %{target}"
+        reopen_report: "%{name} перевідкрив(-ла) скаргу %{target}"
+        reset_password_user: "%{name} скинув(-ла) пароль користувача %{target}"
+        suspend_account: "%{name} заблокував аккаунт користувача %{target}"
+        unsuspend_account: "%{name} розблокував аккаунт користувача %{target}"
+        update_custom_emoji: "%{name} оновив(-ла) емодзі %{target}"
+        update_status: "%{name} змінив(-ла) статус користуача %{target}"
+      title: Журнал подій
+    custom_emojis:
+      by_domain: Домен
+      copied_msg: Локальна копія емодзі успішно створена
+      copy: Копіювати
+      copy_failed_msg: Не вийшло створити локальну копію емодзі
+      created_msg: Емодзі успішно створене!
+      delete: Видалити
+      destroyed_msg: Емодзі усіпішно видалене!
+      disable: Вимкнути
+      disabled_msg: Емодзі успішно вимкнено
+      emoji: Емодзі
+      enable: Увімкнути
+      enabled_msg: Емодзі успішно увімкнене
+      image_hint: PNG розміром до 50 КБ
+      listed: У списку
+      new:
+        title: Додати новий емодзі
+      overwrite: Переписати
+      shortcode: Шорткод
+      shortcode_hint: Мінімум два символи, тільки цифрові й латинські символи або нижні підкреслення
+      title: Особливі емодзі
+      unlisted: Не у списку
+      update_failed_msg: Не вийшло оновити емозді
+      updated_msg: Емодзі успішно оновлене!
+      upload: Вивантажити
+    dashboard:
+      config: Налаштування
+      feature_invites: Посилання-запрошення
+      feature_registrations: Реєстрації
+      features: Можливості
+      hidden_service: Федерація з прихованими сервісами
+      open_reports: відкриті скарги
+      recent_users: Останні користувачі
+      search: Повнотекстовий пошук
+      single_user_mode: Режим одного користувача
+      software: Програмне забезпечення
+      space: Використання дискового простору
+      title: Дашборд
+      total_users: користувачів загалом
+      trends: Тренди
+      week_interactions: дій за цей тиждень
+      week_users_active: активно протягом тижня
+      week_users_new: користувачів цього тижня
     domain_blocks:
       add_new: Додати нове
       created_msg: Блокування домену оброблюється
@@ -72,15 +193,17 @@ uk:
       domain: Домен
       new:
         create: Створити блокування
-        hint: Блокування домену не запобіжить створенню нових акаунтів у базі даних, але ретроактивно та автоматично застосує указані методи модерації для цих акаунтів.
+        hint: Блокування домену не завадить створенню нових акаунтів у базі даних, але ретроактивно та автоматично застосує вказані методи модерації для цих акаунтів.
         severity:
-          desc_html: "<strong>Глушення</strong> зробить статуси акаунту невидимими для всіх, крім їхніх підписників. <strong>Блокування</strong> видалить увесь контент акаунту, включаючи мультимедійні вкладення та дані профілю."
+          desc_html: "<strong>Глушення</strong> зробить статуси акаунту невидимими для всіх, окрім їхніх підписників. <strong>Блокування</strong> видалить увесь контент акаунту, включаючи мультимедійні вкладення та дані профілю."
+          noop: Нічого
           silence: Глушення
           suspend: Блокування
-        title: Нове доменне блокування
+        title: Нове блокування домену
       reject_media: Заборонити медіаконтент
       reject_media_hint: Видаляє медіаконтент, збережений локально, і забороняє його завантаження у майбутньому. Не має значення у випадку блокування.
       severities:
+        noop: Нічого
         silence: Глушення
         suspend: Блокування
       severity: Суворість
@@ -97,40 +220,137 @@ uk:
         undo: Відмінити
       title: Доменні блокування
       undo: Відмінити
+    email_domain_blocks:
+      add_new: Додати
+      created_msg: Успішно додано поштовий домен до чорного списку
+      delete: Видалити
+      destroyed_msg: Успішно видалено поштовий домен з чорного списку
+      domain: Домен
+      new:
+        create: Додати домен
+        title: Нове доменне блокування домену email
+      title: Чорний список поштових доменів
+    instances:
+      account_count: Відомі аккаунти
+      domain_name: Домен
+      reset: Скинути
+      search: Пошук
+      title: Відомі інстанції
+    invites:
+      filter:
+        all: Все
+        available: Доступно
+        expired: Просрочено
+        title: Фільтр
+      title: Запрошення
+    relays:
+      status: Статус
+    report_notes:
+      created_msg: Скарга успішно створена!
+      destroyed_msg: Скарга успішно видалена!
     reports:
+      account:
+        note: примітка
+        report: скарга
+      action_taken_by: Дія виконана
+      are_you_sure: Ви впевнені?
+      assign_to_self: Призначити мені
+      assigned: Призначений модератор
       comment:
         none: Немає
+      created_at: Створено
       id: ID
       mark_as_resolved: Відмітити як вирішену
+      mark_as_unresolved: Відмітити як невирішену
+      notes:
+        create: Додати примітку
+        create_and_unresolve: Перевідкрити з приміткою
+        delete: Видалити
+        placeholder: Опишіть, які дії були виконані, або інші зміни, що стосуються справи...
+      reopen: Перевідкрити скаргу
       report: 'Скарга #%{id}'
+      report_contents: Зміст
       reported_account: Акаунт порушника
       reported_by: Відправник скарги
       resolved: Вирішено
+      resolved_msg: Скаргу успішно вирішено!
       silence_account: Заглушити акаунт
       status: Статус
-      suspend_account: Блокувати акаунт
+      suspend_account: Заблокувати акаунт
       target: Ціль
       title: Скарги
+      unassign: Зняти призначення
       unresolved: Невирішені
+      updated_at: Оновлені
       view: Подивитися
     settings:
+      activity_api_enabled:
+        desc_html: Кількість локальних постів, активних та нових користувачів у тижневих розрізах
+        title: Публікація агрегованої статистики про активність користувачів
+      bootstrap_timeline_accounts:
+        title: Підписки за замовчуванням для нових користувачів
       contact_information:
         email: Введіть публічний email
         username: Введіть ім'я користувача
+      hero:
+        desc_html: Відображається на головній сторінці. Рекомендована як мінімум 600x100 пікселів. Якщо не вказано, буде використано передпоказ інстанції
+        title: Банер інстанції
+      peers_api_enabled:
+        desc_html: Доменні ім'я, помічені цією інстанцією федисвіту
+        title: Опублікувати список знайдених інстанцій
+      preview_sensitive_media:
+        desc_html: Передпоказ посилання на інших сайтах буде відображати мініатюру навіть якщо медіа відмічене як вразливе
+        title: Показувати вразливе медія у перепоказі OpenGraph
       registrations:
         closed_message:
           desc_html: Відображається на титульній сторінці, коли реєстрація закрита <br>Можна використовувати HTML-теги
           title: Повідомлення про закриту реєстрацію
+        deletion:
+          desc_html: Дозволити будь-кому видаляти свій аккаунт
+          title: Дозволити видалення аккаунтів
+        min_invite_role:
+          disabled: Ніхто
+          title: Дозволити запрошення від
         open:
+          desc_html: Дозволити будь-ком створювати аккаунт
           title: Відкрити реєстрацію
+      show_known_fediverse_at_about_page:
+        desc_html: Коли увімкнено, будуть показані пости з усього відомого федисвіту у передпоказі. Інакше будуть показані локальні пости
+        title: Показувати доступний федисвіт у передпоказі фіду
+      show_staff_badge:
+        desc_html: Відмічати персонал на сторінці користувачів
+        title: Показувати персонал
       site_description:
         desc_html: Відображається у якості параграфа на титульній сторінці та використовується у якості мета-тега.<br>Можна використовувати HTML-теги, особливо <code>&lt;a&gt;</code> і <code>&lt;em&gt;</code>.
-        title: Опис сайту
+        title: Опис інстанції
       site_description_extended:
         desc_html: Відображається на сторінці додаткової информації<br>Можна використовувати HTML-теги
         title: Розширений опис сайту
+      site_terms:
+        desc_html: |-
+          Ви можене написати власну політику приватності, умови використанні та інші законні штуки<br>
+          Можете використовувати HTML теги
+        title: Особливі умови використання
       site_title: Назва сайту
+      thumbnail:
+        desc_html: Використовується для передпоказів через OpenGraph та API. Бажано розміром 1200х640 пікселів.
+        title: Мініатюра інстанції
+      timeline_preview:
+        desc_html: Показувати публічний фід на головній сторінці
+        title: Передпоказ фіду
       title: Налаштування сайту
+    statuses:
+      back_to_account: Назад на сторінку профілю
+      batch:
+        delete: Видалити
+        nsfw_off: Відмітити сприйнятливим
+        nsfw_on: Відмітити несприйнятливим
+      failed_to_execute: Не вийшло
+      media:
+        title: Медіа
+      no_media: Немає медіа
+      title: Статуси аккаунтів
+      with_media: З медіа
     subscriptions:
       callback_url: Callback URL
       confirmed: Підтверджено
@@ -139,24 +359,60 @@ uk:
       title: WebSub
       topic: Тема
     title: Адміністрування
+  admin_mailer:
+    new_report:
+      body: "%{reporter} поскаржився(-лася) %{target}"
+      body_remote: Хтось з домену %{domain} поскаржився(-лася) %{target}
+      subject: Нова скарга до %{instance} (#%{id})
   application_mailer:
-    settings: 'Змінити налаштування email: %{link}'
+    notification_preferences: Змінити налаштування e-mail
+    salutation: "%{name},"
+    settings: 'Змінити налаштування e-mail: %{link}'
     view: 'Перегляд:'
+    view_profile: Показати профіль
+    view_status: Показати статус
   applications:
+    created: Застосунок успішно створений
+    destroyed: Застосунок успішно видалений
     invalid_url: Введена URL неправильна
+    regenerate_token: Перегенерувати токен доступу
+    token_regenerated: Токен доступу успішне перегенеровано
+    warning: Будьте дуже обережні з цими даними. Ніколи не діліться ними ні з ким!
+    your_token: Ваш токен доступу
   auth:
+    agreement_html: Реєструючись, ви погоджуєтеся виконувати <a href="%{rules_path}">правила інстанції</a> та <a href="%{terms_path}">наші умови використання</a>.
+    change_password: Пароль
+    confirm_email: Підтвердьте e-mail адресу
+    delete_account: Видалити аккаунт
+    delete_account_html: Якщо ви хочете видалити аккаунт, ви можете <a href="%{path}">перейти сюди</a>. Вас попросять підтвердити дію.
     didnt_get_confirmation: Ви не отримали інструкції з підтвердження?
     forgot_password: Забули свій пароль?
+    invalid_reset_password_token: Токен скидання паролю неправильний або просрочений. Спробуйте попросити новий.
     login: Увійти
     logout: Вийти
+    migrate_account: Переїхати до іншого аккаунту
+    migrate_account_html: Якщо ви бажаєте, щоб відвідувачі цього акканту були перенаправлені до іншого, ви можете <a href="%{path}">налаштувати це тут</a>.
+    or: або
+    or_log_in_with: Або увійдіть з
+    providers:
+      cas: CAS
+      saml: SAML
     register: Зареєструватися
+    register_elsewhere: Зареєструватися на іншому сервері
     resend_confirmation: Повторно відправити інструкції з підтвердження
     reset_password: Скинути пароль
     security: Зміна паролю
     set_new_password: Встановити новий пароль
   authorize_follow:
+    already_following: Ви вже підписані на цей аккаунт
     error: На жаль, при пошуку віддаленого аккаунту виникла помилка
     follow: Підписатися
+    follow_request: 'Вам надіслали запит на підписку:'
+    following: 'Ура! Ви тепер підписані на:'
+    post_follow:
+      close: Або, ви можете просто закрити вікно.
+      return: Перейти до профілю користувача
+      web: Перейти до вебу
     title: Підписатися на %{acct}
   datetime:
     distance_in_words:
@@ -164,14 +420,22 @@ uk:
       about_x_months: "%{count}міс"
       about_x_years: "%{count}р"
       almost_x_years: "%{count}р"
-      half_a_minute: Тільки що
+      half_a_minute: Щойно
       less_than_x_minutes: "%{count}хв"
-      less_than_x_seconds: Тільки що
+      less_than_x_seconds: Щойно
       over_x_years: "%{count}р"
       x_days: "%{count}д"
       x_minutes: "%{count}хв"
       x_months: "%{count}міс"
       x_seconds: "%{count}сек"
+  deletes:
+    bad_password_msg: Гарна спроба, гакери! Неправильний пароль
+    confirm_password: Введіть актуальний пароль щоб перевірити що ви це ви
+    description_html: Це <strong>безвідворотно і назавжди</strong> видалить контент з вашого аккаунту та деактивує його. Ваше ім'я користувача буде залишатися зарезервованим для уникнення вашої деперсоналізації.
+    proceed: Видалити аккаунт
+    success_msg: Ваш аккаунт було успішно видалено
+    warning_html: Ми можемо гарантувати видалення контенти <b>лише з цього сайту</b>. Контент, що був поширений залишає сліди. Сервери, що є офлайн та ті, що відписалися від наших оновлень не запишуть змін до своїх баз даних.
+    warning_title: Про доступність поширеного контенту
   errors:
     '403': У Вас немає доступу до перегляду даної сторінки.
     '404': Сторінка, яку Ви шукали, не існує.
@@ -179,15 +443,43 @@ uk:
     '422':
       content: Перевірка безпеки не вдалася. Можливо, Ви блокуєте cookies?
       title: Перевірка безпеки не вдалася.
+    '429': Забагато запитів
+    '500':
+      content: Пробачте, та щось пішло не так з нашого боку.
+      title: Ця сторінка неправильна
+    noscript_html: Для використання веб-застосунку Мастодон, будь-ласка увімкніть JavaScript. Якщо у вас немає такої можливості, скористайтесь одним із <a href="https://github.com/tootsuite/documentation/blob/master/Using-Mastodon/Apps.md">нативних застосунків</a> для Мастодон для вашої платформи.
   exports:
+    archive_takeout:
+      date: Дата
+      download: Завантажити ваш архів
+      hint_html: Ви можете зробити запит на архів ваших <strong>постів та вивантаженого медіа контенту</strong>. Завантажені дані будуть у форматі ActivityPub, доступні для читання будь-яким сумісним програмним забезпеченням. Ви можете робити запит на архів кожні 7 днів.
+      in_progress: Збираємо ваш архів...
+      request: Зробити запит на архів
+      size: Розмір
     blocks: Список блокувань
     csv: CSV
     follows: Підписки
     mutes: Список глушення
     storage: Ваш медіаконтент
+  filters:
+    contexts:
+      home: Ваш фід
+      notifications: Сповіщення
+      public: Публічний фід
+      thread: Повідомлення
+    edit:
+      title: Редагувати фільтр
+    errors:
+      invalid_context: Контекст неправильний або не був наданий
+      invalid_irreversible: Незворотне фільтрування працює тільки в контексті свого фіду або сповіщень
+    index:
+      delete: Видалити
+      title: Фільтри
+    new:
+      title: Додати фільтр
   followers:
     domain: Домен
-    explanation_html: Якщо Ви хочете бути впевнені в приватності Ваших статусів, Ви повинні мати чітке уявлення про те, хто на Вас підписаний. <strong>Ваші приватні статусі відправляються усім інстанціям, на яких у Вас є підписники</strong>. Рекомендуємо видалити з підписників користувачів інстанцій, адміністрації чи програмному забезпеченню яких Ви не довіряєте.
+    explanation_html: Якщо Ви хочете бути впевнені в приватності Ваших статусів, Ви повинні мати чітке уявлення про те, хто на Вас підписаний. <strong>Ваші приватні статусі відправляються усім сайтам, на яких у Вас є підписники</strong>. Рекомендуємо видалити з підписників користувачів інстанцій, адміністрації чи програмному забезпеченню яких Ви не довіряєте.
     followers_count: Кількість підписників
     lock_link: Закрийте акаунт
     purge: Видалити з підписників
@@ -199,7 +491,6 @@ uk:
     unlocked_warning_title: Ваш аккаунт не закритий для підписки
   generic:
     changes_saved_msg: Зміни успішно збережені!
-    powered_by: працює на %{link}
     save_changes: Зберегти зміни
     validation_errors:
       one: Щось тут не так! Будь ласка, ознайомтеся з помилкою нижче
@@ -212,103 +503,252 @@ uk:
       following: Підписки
       muting: Список глушення
     upload: Завантажити
-  landing_strip_html: "<strong>%{name}</strong> - користувач на %{link_to_root_path}. Ви можете підписатися на нього/неї та спілкуватися з ним/нею, якщо у Вас є акаунт на будь-якій інстанції загальної мережі."
-  landing_strip_signup_html: Якщо його у Вас немає, Ви можете <a href="%{sign_up_path}">зареєструватися тут</a>.
+  in_memoriam_html: Пам'ятник.
+  invites:
+    delete: Деактивувати
+    expired: Вийшов
+    expires_in:
+      '1800': 30 хвилин
+      '21600': 6 годин
+      '3600': 1 година
+      '43200': 12 годин
+      '604800': 1 тиждень
+      '86400': 1 день
+    expires_in_prompt: Ніколи
+    generate: Згенерувати
+    invited_by: 'Вас запросив(-ла):'
+    max_uses:
+      one: 1 використання
+      other: "%{count} використань"
+    max_uses_prompt: Без обмеження
+    prompt: Генеруйте та діліться посиланням з іншими для надання доступу до сайту
+    table:
+      expires_at: Час роботи
+      uses: Використання
+    title: Запросити людей
+  lists:
+    errors:
+      limit: Ви досягнули максимальної кількості списків
   media_attachments:
     validations:
       images_and_video: Не можна додати відео до статусу з зображеннями
       too_many: Не можна додати більше 4 файлів
+  migrations:
+    acct: username@domain нового аккаунту
+    currently_redirecting: 'Ваш профіль налаштований перенаправляти на:'
+    proceed: Зберегти
+    updated_msg: Переїзд вашого аккаунту успішно оновлений!
+  moderation:
+    title: Модерація
   notification_mailer:
     digest:
-      body: 'Коротко про пропущене Вами на %{instance} з Вашого останнього входу %{since}:'
+      action: Показати усі сповіщення
+      body: Коротко про пропущене вами з Вашого останнього входу %{since}
       mention: "%{name} згадав(-ла) Вас в:"
       new_followers_summary:
         few: У Вас з'явилось %{count} нових підписники! Чудово!
         many: У Вас з'явилось %{count} нових підписників! Чудово!
-        one: У Вас з'явився новий підписник! Ура!
-        other: У Вас з'явилось %{count} нових підписників! Чудово!
+        one: Також, у Вас з'явився новий підписник, коли ви були відсутні! Ура!
+        other: Також, у Вас з'явилось %{count} нових підписників, поки ви були відсутні! Чудово!
       subject:
         few: "%{count} нові сповіщення з Вашого останнього входу \U0001F418"
         many: "%{count} нових сповіщень з Вашого останнього входу \U0001F418"
         one: "1 нове сповіщення з Вашого останнього входу \U0001F418"
         other: "%{count} нових сповіщень з Вашого останнього входу \U0001F418"
+      title: Поки ви були відсутні...
     favourite:
       body: 'Ваш статус подобається %{name}:'
       subject: Користувачу %{name} сподобався ваш статус
+      title: Нове вподобання
     follow:
       body: "%{name} тепер підписаний на вас!"
       subject: "%{name} тепер підписаний(-а) на вас"
+      title: Новий підписник
     follow_request:
+      action: Керувати запитами на підписку
       body: "%{name} запитав Вас про підписку"
       subject: "%{name} хоче підписатися на Вас"
+      title: Новий запит на підписку
     mention:
-      body: 'Ви були згадані %{name} в:'
-      subject: Ви були згадані %{name}
+      action: Відповісти
+      body: 'Вас згадав(-ла) %{name} в:'
+      subject: Вас згадав(-ла) %{name}
+      title: Нова згадка
     reblog:
       body: 'Ваш статус було передмухнуто %{name}:'
       subject: "%{name} передмухнув ваш статус"
+      title: Нове передмухування
   number:
     human:
       decimal_units:
         format: "%n%u"
         units:
-          billion: B
-          million: M
-          quadrillion: Q
-          thousand: K
-          trillion: T
+          billion: млрд
+          million: млн
+          quadrillion: квдрл
+          thousand: тис
+          trillion: трлн
           unit: ''
   pagination:
+    newer: Новіше
     next: Далі
     prev: Назад
     truncate: "&hellip;"
+  preferences:
+    languages: Мови
+    other: Інше
+    publishing: Публікація
+    web: Веб
   remote_follow:
-    acct: Введіть username@domain, звідки ви хочете підписатися
-    missing_resource: Пошук потрібного перенаправлення URL для Вашого аккаунта закінчився неудачою
-    proceed: Продовжити підписку
+    acct: Введіть username@domain, яким ви хочете підписатися
+    missing_resource: Пошук потрібного перенаправлення URL для Вашого аккаунта закінчився невдачею
+    no_account_html: Не маєте аккаунту? Не біда, ви можете <a href='%{sign_up_path}' target='_blank'>зареєструватися</a>
+    proceed: Перейти до підписки
     prompt: 'Ви хочете підписатися на:'
+  remote_unfollow:
+    error: Помилка
+    title: Заголовок
+    unfollowed: Відписані
+  sessions:
+    activity: Остання активність
+    browser: Браузер
+    browsers:
+      alipay: Alipay
+      blackberry: Blackberry
+      chrome: Chrome
+      edge: Microsoft Edge
+      electron: Electron
+      firefox: Firefox
+      generic: Невідомий браузер
+      ie: Internet Explorer
+      micro_messenger: MicroMessenger
+      nokia: Nokia S40 Ovi Browser
+      opera: Opera
+      otter: Otter
+      phantom_js: PhantomJS
+      qq: QQ Browser
+      safari: Safari
+      uc_browser: UCBrowser
+      weibo: Weibo
+    current_session: Активна сесія
+    description: "%{browser} на %{platform}"
+    explanation: Це веб-браузери, нині авторизовані до вашого аккаунту Мастодон.
+    ip: IP
+    platforms:
+      adobe_air: Adobe Air
+      android: Android
+      blackberry: Blackberry
+      chrome_os: ChromeOS
+      firefox_os: Firefox OS
+      ios: iOS
+      linux: Linux
+      mac: Mac
+      other: невідома платформа
+      windows: Windows
+      windows_mobile: Windows Mobile
+      windows_phone: Windows Phone
+    revoke: Закінчити
+    revoke_success: Сесія успішно закінчена
+    title: Сесії
   settings:
-    authorized_apps: Авторизованные приложения
-    back: Назад в Mastodon
+    authorized_apps: Авторизовані застосунки
+    back: Назад у Мастодон
+    delete: Видалення аккаунту
+    development: Розробка
     edit_profile: Редагувати профіль
     export: Експорт даних
     followers: Авторизовані підписники
     import: Імпорт
+    migrate: Міграція акаунту
+    notifications: Сповіщення
     preferences: Налаштування
     settings: Опції
     two_factor_authentication: Двофакторна аутентифікація
+    your_apps: Ваші затосунки
   statuses:
-    open_in_web: Відкрити в WWW
+    attached:
+      description: 'Прикріплено: %{attached}'
+      image:
+        one: "%{count} картинка"
+        other: "%{count} картинки"
+      video:
+        one: "%{count} відео"
+        other: "%{count} відео"
+    boosted_from_html: Просунуто від %{acct_link}
+    content_warning: 'Попередження про контент: %{warning}'
+    disallowed_hashtags:
+      one: 'містив заборонений хештеґ: %{tags}'
+      other: 'містив заборонені хештеґи: %{tags}'
+    language_detection: Автоматично визначати мову
+    open_in_web: Відкрити у вебі
     over_character_limit: перевищено ліміт символів (%{max})
+    pin_errors:
+      limit: Ви вже закріпили максимальну кількість постів
+      ownership: Не можна закріпити чужий пост
+      private: Не можна закріпити непублічний пост
+      reblog: Не можна закріпити просунутий пост
     show_more: Детальніше
+    title: '%{name}: "%{quote}"'
     visibilities:
       private: Для підписників
-      private_long: Показувати тількои підписникам
+      private_long: Показувати тільки підписникам
       public: Для всіх
       public_long: Показувати всім
-      unlisted: Приховувати зі стріок
+      unlisted: Приховувати зі стрічок
       unlisted_long: Показувати всім, але не відображати в публічних стрічках
   stream_entries:
-    click_to_show: Показати
+    pinned: Закріплений пост
     reblogged: передмухнув(-ла)
-    sensitive_content: Непристойний контент
+    sensitive_content: Несприйнятливий контент
+  terms:
+    title: Умови використання та Політика приватності %{instance}
+  themes:
+    contrast: Висока контрасність
+    default: Mastodon
+    mastodon-light: Mastodon (світла)
   time:
     formats:
       default: "%b %d, %Y, %H:%M"
   two_factor_authentication:
-    code_hint: Для підтверждення введіть код, згенерований додатком аутентифікатора
+    code_hint: Для підтверждення введіть код, згенерований застосунком аутентифікатора
     description_html: При увімкненні <strong>двофакторної аутентифікації</strong>, вхід буде вимагати від Вас використовування Вашого телефона, який згенерує вхідний код.
     disable: Вимкнути
     enable: Увімкнути
+    enabled: Двофакторна аутентифікація увімкнена
     enabled_success: Двофакторна аутентифікація успішно увімкнена
     generate_recovery_codes: Згенерувати коди відновлення
-    instructions_html: "<strong>Відскануйте цей QR-код за допомогою Google Authenticator чи іншого TOTP-додатка на Вашому телефоні</strong>. Від цього моменту додаток буде генерувати коди, які буде необхідно ввести для входу."
-    lost_recovery_codes: Коди відновлення дозволяють повернути доступ до акаунту у випадку втрати телефону. Якщо Ви втратили Ваші коди відновлення, Ви можете знову згенерувати їх тут. Ваші старі коди відновлення будуть анульовані.
+    instructions_html: "<strong>Відскануйте цей QR-код за допомогою Google Authenticator чи іншого TOTP-застосунку на Вашому телефоні</strong>. З цього моменту він буде генерувати коди, які буде необхідно ввести для входу."
+    lost_recovery_codes: Коди відновлення дозволяють повернути доступ до акаунту у випадку втрати телефону. Якщо Ви втратили Ваші коди відновлення, Ви можете знову згенерувати їх тут. Тоді ваші старі коди відновлення будуть анульовані.
     manual_instructions: 'Якщо Ви не можете відсканувати QR-код та хочете ввести його вручну, секрет представлений тут відкритим текстом:'
+    recovery_codes: Запасні коди відновлення
     recovery_codes_regenerated: Коди відновлення успішно згенеровані
-    recovery_instructions_html: У випадку втрати доступу до Вашого телефона Ви можете використати один з кодів відновлення, вказаних нижче, щоб повернути доступ до акаунту. Тримайте коди відновлення у безпеці, наприклад, роздрукувавши їх та тримаючи їх з іншими важливими документами.
+    recovery_instructions_html: У випадку втрати доступу до вашого телефону ви можете використати один з кодів відновлення, вказаних нижче, щоб повернути доступ до акаунту. Тримайте коди відновлення у безпеці, наприклад, роздруйте їх та зберігайте їх з іншими важливими документами.
     setup: Налаштувати
-    wrong_code: Введений код неправильний! Чи правильно встановлені серверний час та час пристрою?
+    wrong_code: Введений код неправильний! Чи правильно встановлений час на сервері та пристрої?
+  user_mailer:
+    backup_ready:
+      explanation: Ви зробили запит на повний архів вашого аккаунту Mastodon. Він вже готовий для завантаження!
+      subject: Ваш архів готовий до завантаження
+      title: Винесення архіву
+    welcome:
+      edit_profile_action: Налаштувати профіль
+      edit_profile_step: Ви можете налаштувати профіль під себе завантаживши аватар, шпалери, змінивши відображуване ім'я тощо. Якщо ви захочете переглядати нових підписників до того, як вони зможуть підписатися на вас, ви можете заблокувати свій аккаунт.
+      explanation: Ось декілька порад для початку
+      final_action: Почати постити
+      final_step: 'Почність постити! Навіть не підписавшись на вас, інші зможуть побачити ваші пости, наприкоал, у локальному фіді та у хештеґах. Якщо ви хочете представитися, можете скористатися хештеґом #introductions.'
+      full_handle: Ваше звернення
+      full_handle_hint: Те, що ви хочете сказати друзям, щоб вони могли написати вам або підписатися з інших сайтів.
+      review_preferences_action: Змінити налаштування
+      review_preferences_step: Переконайтеся у тому, що ви налаштували все необхідне, як от які e-mail повідомлення ви хочете отримувати, або який рівень приватності ви хочете встановити вашим постам за замовчуванням. Якщо хочете, ви можете увімкнути автоматичне програвання GIF анімацій.
+      subject: Ласкаво просимо до Mastodon
+      tip_bridge_html: Якщо ви прийшли до нас із Twitter, ви можете знайти ваших друзів на Mastodon, скориставшись <a href="%{bridge_url}">проміжним застосунком</a>. Проте він працює тільки, якщо вони теж користуються проміжним застосунком!
+      tip_federated_timeline: Федерований фід є широким поглядом на мережу Mastodon. Але він включає лише людей, на яких підписані ваші сусіди по сайту, тому він не є повним.
+      tip_following: Ви автоматично підписані на адміністратора(-ів) сервера. Для того, щоб знайти ще цікавих людей, дослідіть локальний та федерований фіди.
+      tip_local_timeline: Локальний фід - це погляд згори на людей на %{instance}. Це ваші прямі сусіди!
+      tip_mobile_webapp: Якщо ваш мобільний браузер пропонує вам додати Mastodon на робочий стіл, ви можете отримувати push-сповіщення. Все може виглядати як нативний застосунок у багатьох речах.
+      tips: Поради
+      title: Ласкаво просимо, %{name}!
   users:
-    invalid_email: Введений email неправильний
+    invalid_email: Введена адреса e-mail неправильна
     invalid_otp_token: Введено неправильний код
+    otp_lost_help_html: Якщо ви втратили доступ до обох, ви можете отримати доступ з %{email}
diff --git a/config/locales/zh-CN.yml b/config/locales/zh-CN.yml
index 1b741a7d6..6e64aff5a 100644
--- a/config/locales/zh-CN.yml
+++ b/config/locales/zh-CN.yml
@@ -46,7 +46,6 @@ zh-CN:
     people_who_follow: 关注 %{name} 的人
     posts: 嘟文
     posts_with_replies: 嘟文和回复
-    remote_follow: 跨站关注
     reserved_username: 此用户名已被保留
     roles:
       admin: 管理员
@@ -484,7 +483,6 @@ zh-CN:
     unlocked_warning_title: 你的帐户未受到保护
   generic:
     changes_saved_msg: 更改保存成功!
-    powered_by: 基于 %{link} 构建
     save_changes: 保存更改
     validation_errors:
       one: 出错啦!检查一下下面出错的地方吧
@@ -518,8 +516,6 @@ zh-CN:
       expires_at: 失效时间
       uses: 已使用次数
     title: 邀请用户
-  landing_strip_html: "<strong>%{name}</strong> 是一位来自 %{link_to_root_path} 的用户。如果你想关注他们或者与他们互动,你需要在任意一个 Mastodon 实例或与其兼容的网站上拥有一个帐户。"
-  landing_strip_signup_html: 还没有这种帐户?你可以<a href="%{sign_up_path}">在本站注册一个</a>。
   lists:
     errors:
       limit: 你所建立的列表数量已经达到上限
@@ -681,7 +677,6 @@ zh-CN:
       unlisted: 不公开
       unlisted_long: 所有人可见,但不会出现在公共时间轴上
   stream_entries:
-    click_to_show: 点击显示
     pinned: 置顶嘟文
     reblogged: 转嘟
     sensitive_content: 敏感内容
diff --git a/config/locales/zh-HK.yml b/config/locales/zh-HK.yml
index a5e997536..7ff0d7ae6 100644
--- a/config/locales/zh-HK.yml
+++ b/config/locales/zh-HK.yml
@@ -46,7 +46,6 @@ zh-HK:
     people_who_follow: 關注 %{name} 的人
     posts: 文章
     posts_with_replies: 文章和回覆
-    remote_follow: 跨站關注
     reserved_username: 此用戶名已被保留
     roles:
       admin: 管理員
@@ -488,7 +487,6 @@ zh-HK:
     unlocked_warning_title: 你的用戶目前為「公共」
   generic:
     changes_saved_msg: 已成功儲存修改。
-    powered_by: 網站由 %{link} 開發
     save_changes: 儲存修改
     validation_errors:
       one: 提交的資料有問題
@@ -524,8 +522,6 @@ zh-HK:
       expires_at: 失效時間
       uses: 已使用次數
     title: 邀請用戶
-  landing_strip_html: "<strong>%{name}</strong> 是一個在 %{link_to_root_path} 的用戶。只要你有任何 Mastodon 服務站、或者聯盟網站的用戶,便可以跨站關注此站用戶,或者與他們互動。"
-  landing_strip_signup_html: 如果你沒有這類用戶,歡迎在<a href="%{sign_up_path}">此處登記</a>。
   lists:
     errors:
       limit: 你所建立的列表數量已經達到上限
@@ -692,7 +688,6 @@ zh-HK:
       unlisted: 公開,但不在公共時間軸顯示
       unlisted_long: 所有人都能看到,但不在公共時間軸(本站時間軸、跨站時間軸)顯示
   stream_entries:
-    click_to_show: 點擊顯示
     pinned: 置頂文章
     reblogged: 轉推
     sensitive_content: 敏感內容
diff --git a/config/locales/zh-TW.yml b/config/locales/zh-TW.yml
index e2b376a3f..483cffe8e 100644
--- a/config/locales/zh-TW.yml
+++ b/config/locales/zh-TW.yml
@@ -46,7 +46,6 @@ zh-TW:
     people_who_follow: 關注 %{name} 的人
     posts: 嘟文
     posts_with_replies: 嘟文與回覆
-    remote_follow: 跨站關注
     reserved_username: 此用戶名已被保留
     roles:
       admin: 管理員
@@ -488,7 +487,6 @@ zh-TW:
     unlocked_warning_title: 你的帳戶是公開的
   generic:
     changes_saved_msg: 已成功儲存修改!
-    powered_by: 網站由 %{link} 開發
     save_changes: 儲存修改
     validation_errors:
       one: 送出的資料有問題
@@ -524,8 +522,6 @@ zh-TW:
       expires_at: 失效時間
       uses: 已使用次數
     title: 邀請使用者
-  landing_strip_html: "<strong>%{name}</strong> 是一個在 %{link_to_root_path} 的使用者。只要您有任何 Mastodon 站點、或者聯盟站點的帳戶,便可以跨站關注此站使用者,或者與他們互動。"
-  landing_strip_signup_html: 如果您沒有這些帳戶,歡迎在<a href="%{sign_up_path}">這裡註冊</a>。
   lists:
     errors:
       limit: 你所建立的列表數量已經達到上限
@@ -685,7 +681,6 @@ zh-TW:
       unlisted: 公開,但不在公共時間軸顯示
       unlisted_long: 所有人都能看到,但不會出現在公共時間軸上
   stream_entries:
-    click_to_show: 點選顯示
     pinned: 置頂嘟文
     reblogged: 轉嘟
     sensitive_content: 敏感內容
diff --git a/lib/mastodon/version.rb b/lib/mastodon/version.rb
index 62e55d32d..1aa9b413e 100644
--- a/lib/mastodon/version.rb
+++ b/lib/mastodon/version.rb
@@ -32,8 +32,12 @@ module Mastodon
       [to_a.join('.'), flags].join
     end
 
+    def repository
+      'glitch-soc/mastodon'
+    end
+
     def source_base_url
-      'https://github.com/glitch-soc/mastodon'
+      "https://github.com/#{repository}"
     end
 
     # specify git tag or commit hash here
diff --git a/package.json b/package.json
index aeec3c72c..3f6f4c7fd 100644
--- a/package.json
+++ b/package.json
@@ -106,6 +106,7 @@
     "redux": "^3.7.1",
     "redux-immutable": "^4.0.0",
     "redux-thunk": "^2.2.0",
+    "rellax": "^1.6.2",
     "requestidlecallback": "^0.3.0",
     "reselect": "^3.0.1",
     "rimraf": "^2.6.1",
diff --git a/spec/controllers/about_controller_spec.rb b/spec/controllers/about_controller_spec.rb
index 2089b3b16..03dddd8c1 100644
--- a/spec/controllers/about_controller_spec.rb
+++ b/spec/controllers/about_controller_spec.rb
@@ -8,10 +8,6 @@ RSpec.describe AboutController, type: :controller do
       get :show
     end
 
-    it 'assigns @body_classes' do
-      expect(assigns(:body_classes)).to eq 'about-body'
-    end
-
     it 'assigns @instance_presenter' do
       expect(assigns(:instance_presenter)).to be_kind_of InstancePresenter
     end
@@ -26,10 +22,6 @@ RSpec.describe AboutController, type: :controller do
       get :more
     end
 
-    it 'assigns @body_classes' do
-      expect(assigns(:body_classes)).to eq 'about-body'
-    end
-
     it 'assigns @instance_presenter' do
       expect(assigns(:instance_presenter)).to be_kind_of InstancePresenter
     end
@@ -44,10 +36,6 @@ RSpec.describe AboutController, type: :controller do
       get :terms
     end
 
-    it 'assigns @body_classes' do
-      expect(assigns(:body_classes)).to eq 'about-body'
-    end
-
     it 'returns http success' do
       expect(response).to have_http_status(200)
     end
diff --git a/spec/models/account_spec.rb b/spec/models/account_spec.rb
index da1ae4888..8fb5bbddf 100644
--- a/spec/models/account_spec.rb
+++ b/spec/models/account_spec.rb
@@ -618,10 +618,10 @@ RSpec.describe Account, type: :model do
         expect(account).not_to model_have_error_on_field(:username)
       end
 
-      it 'is valid even if the username doesn\'t only contains letters, numbers and underscores' do
+      it 'is invalid if the username doesn\'t only contains letters, numbers and underscores' do
         account = Fabricate.build(:account, domain: 'domain', username: 'the-doctor')
         account.valid?
-        expect(account).not_to model_have_error_on_field(:username)
+        expect(account).to model_have_error_on_field(:username)
       end
 
       it 'is valid even if the username is longer then 30 characters' do
diff --git a/spec/views/stream_entries/show.html.haml_spec.rb b/spec/views/stream_entries/show.html.haml_spec.rb
index e0681b125..34207aa6b 100644
--- a/spec/views/stream_entries/show.html.haml_spec.rb
+++ b/spec/views/stream_entries/show.html.haml_spec.rb
@@ -12,6 +12,7 @@ describe 'stream_entries/show.html.haml', without_verify_partial_doubles: true d
     allow(view).to receive(:full_asset_url).and_return('//asset.host/image.svg')
     allow(view).to receive(:local_time)
     allow(view).to receive(:local_time_ago)
+    assign(:instance_presenter, InstancePresenter.new)
   end
 
   it 'has valid author h-card and basic data for a detailed_status' do
diff --git a/yarn.lock b/yarn.lock
index 3d0917ce1..e8c41786d 100644
--- a/yarn.lock
+++ b/yarn.lock
@@ -7200,6 +7200,10 @@ regjsparser@^0.1.4:
   dependencies:
     jsesc "~0.5.0"
 
+rellax@^1.6.2:
+  version "1.6.2"
+  resolved "https://registry.yarnpkg.com/rellax/-/rellax-1.6.2.tgz#b22c8715f56324fa8b396465d3dca9953b711f30"
+
 remove-trailing-separator@^1.0.1:
   version "1.1.0"
   resolved "https://registry.yarnpkg.com/remove-trailing-separator/-/remove-trailing-separator-1.1.0.tgz#c24bce2a283adad5bc3f58e0d48249b92379d8ef"