about summary refs log tree commit diff
path: root/app
diff options
context:
space:
mode:
authorThibaut Girka <thib@sitedethib.com>2018-09-19 21:46:01 +0200
committerThibaut Girka <thib@sitedethib.com>2018-09-19 21:46:01 +0200
commit91bef4759f40422b64d7990f9b90db0b493773b1 (patch)
tree3211b1014a6d0a88737db16c44d210ef96a070e4 /app
parent382cdd7f959480d59fee5646be320d6076cb18d8 (diff)
parent554f659f2aa1eb9c0ca64ec1c9c177538434826c (diff)
Merge branch 'master' into glitch-soc/merge-upstream
Conflicts:
	Vagrantfile
	app/javascript/packs/public.js
	app/views/admin/settings/edit.html.haml
	app/views/settings/preferences/show.html.haml
	app/views/settings/profiles/show.html.haml
	config/locales/es.yml
	config/locales/simple_form.en.yml
	config/webpack/configuration.js
	config/webpack/loaders/babel.js
	package.json
	yarn.lock

Split new additions to app/javascript/packs/public.js to
app/javascript/core/settings.js
Diffstat (limited to 'app')
-rw-r--r--app/controllers/auth/sessions_controller.rb2
-rw-r--r--app/helpers/admin/account_moderation_notes_helper.rb4
-rw-r--r--app/helpers/home_helper.rb16
-rw-r--r--app/javascript/core/settings.js24
-rw-r--r--app/javascript/mastodon/actions/dropdown_menu.js4
-rw-r--r--app/javascript/mastodon/components/__tests__/__snapshots__/button-test.js.snap6
-rw-r--r--app/javascript/mastodon/components/account.js4
-rw-r--r--app/javascript/mastodon/components/column_header.js4
-rw-r--r--app/javascript/mastodon/components/domain.js4
-rw-r--r--app/javascript/mastodon/components/dropdown_menu.js32
-rw-r--r--app/javascript/mastodon/components/load_gap.js4
-rw-r--r--app/javascript/mastodon/components/media_gallery.js4
-rw-r--r--app/javascript/mastodon/components/relative_timestamp.js4
-rw-r--r--app/javascript/mastodon/components/status.js4
-rw-r--r--app/javascript/mastodon/components/status_action_bar.js4
-rw-r--r--app/javascript/mastodon/containers/dropdown_menu_container.js5
-rw-r--r--app/javascript/mastodon/features/account/components/action_bar.js25
-rw-r--r--app/javascript/mastodon/features/account/components/header.js19
-rw-r--r--app/javascript/mastodon/features/account_gallery/index.js4
-rw-r--r--app/javascript/mastodon/features/account_timeline/index.js4
-rw-r--r--app/javascript/mastodon/features/blocks/index.js4
-rw-r--r--app/javascript/mastodon/features/community_timeline/components/column_settings.js4
-rw-r--r--app/javascript/mastodon/features/community_timeline/index.js4
-rw-r--r--app/javascript/mastodon/features/compose/components/action_bar.js4
-rw-r--r--app/javascript/mastodon/features/compose/components/compose_form.js4
-rw-r--r--app/javascript/mastodon/features/compose/components/emoji_picker_dropdown.js5
-rw-r--r--app/javascript/mastodon/features/compose/components/privacy_dropdown.js4
-rw-r--r--app/javascript/mastodon/features/compose/components/reply_indicator.js4
-rw-r--r--app/javascript/mastodon/features/compose/components/search.js4
-rw-r--r--app/javascript/mastodon/features/compose/components/upload.js4
-rw-r--r--app/javascript/mastodon/features/compose/components/upload_button.js4
-rw-r--r--app/javascript/mastodon/features/compose/index.js4
-rw-r--r--app/javascript/mastodon/features/compose/util/url_regex.js2
-rw-r--r--app/javascript/mastodon/features/direct_timeline/components/column_settings.js4
-rw-r--r--app/javascript/mastodon/features/direct_timeline/index.js4
-rw-r--r--app/javascript/mastodon/features/domain_blocks/index.js4
-rw-r--r--app/javascript/mastodon/features/favourited_statuses/index.js4
-rw-r--r--app/javascript/mastodon/features/favourites/index.js4
-rw-r--r--app/javascript/mastodon/features/follow_requests/components/account_authorize.js4
-rw-r--r--app/javascript/mastodon/features/follow_requests/index.js4
-rw-r--r--app/javascript/mastodon/features/followers/index.js4
-rw-r--r--app/javascript/mastodon/features/following/index.js4
-rw-r--r--app/javascript/mastodon/features/getting_started/index.js4
-rw-r--r--app/javascript/mastodon/features/hashtag_timeline/index.js4
-rw-r--r--app/javascript/mastodon/features/home_timeline/components/column_settings.js4
-rw-r--r--app/javascript/mastodon/features/home_timeline/index.js4
-rw-r--r--app/javascript/mastodon/features/keyboard_shortcuts/index.js4
-rw-r--r--app/javascript/mastodon/features/list_editor/components/account.js4
-rw-r--r--app/javascript/mastodon/features/list_editor/components/search.js4
-rw-r--r--app/javascript/mastodon/features/list_editor/index.js4
-rw-r--r--app/javascript/mastodon/features/list_timeline/index.js4
-rw-r--r--app/javascript/mastodon/features/lists/components/new_list_form.js4
-rw-r--r--app/javascript/mastodon/features/lists/index.js4
-rw-r--r--app/javascript/mastodon/features/mutes/index.js4
-rw-r--r--app/javascript/mastodon/features/notifications/components/notification.js4
-rw-r--r--app/javascript/mastodon/features/notifications/index.js4
-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.js4
-rw-r--r--app/javascript/mastodon/features/standalone/community_timeline/index.js4
-rw-r--r--app/javascript/mastodon/features/standalone/hashtag_timeline/index.js4
-rw-r--r--app/javascript/mastodon/features/standalone/public_timeline/index.js4
-rw-r--r--app/javascript/mastodon/features/status/components/action_bar.js4
-rw-r--r--app/javascript/mastodon/features/status/index.js4
-rw-r--r--app/javascript/mastodon/features/ui/components/boost_modal.js4
-rw-r--r--app/javascript/mastodon/features/ui/components/columns_area.js4
-rw-r--r--app/javascript/mastodon/features/ui/components/confirmation_modal.js4
-rw-r--r--app/javascript/mastodon/features/ui/components/embed_modal.js4
-rw-r--r--app/javascript/mastodon/features/ui/components/focal_point_modal.js4
-rw-r--r--app/javascript/mastodon/features/ui/components/media_modal.js6
-rw-r--r--app/javascript/mastodon/features/ui/components/mute_modal.js4
-rw-r--r--app/javascript/mastodon/features/ui/components/onboarding_modal.js4
-rw-r--r--app/javascript/mastodon/features/ui/components/report_modal.js5
-rw-r--r--app/javascript/mastodon/features/ui/components/tabs_bar.js4
-rw-r--r--app/javascript/mastodon/features/ui/components/video_modal.js2
-rw-r--r--app/javascript/mastodon/features/ui/components/zoomable_image.js1
-rw-r--r--app/javascript/mastodon/features/ui/index.js4
-rw-r--r--app/javascript/mastodon/features/ui/util/react_router_helpers.js2
-rw-r--r--app/javascript/mastodon/features/video/index.js7
-rw-r--r--app/javascript/mastodon/locales/ar.json1
-rw-r--r--app/javascript/mastodon/locales/ast.json289
-rw-r--r--app/javascript/mastodon/locales/bg.json1
-rw-r--r--app/javascript/mastodon/locales/ca.json1
-rw-r--r--app/javascript/mastodon/locales/co.json1
-rw-r--r--app/javascript/mastodon/locales/cs.json1
-rw-r--r--app/javascript/mastodon/locales/cy.json355
-rw-r--r--app/javascript/mastodon/locales/da.json5
-rw-r--r--app/javascript/mastodon/locales/de.json25
-rw-r--r--app/javascript/mastodon/locales/defaultMessages.json13
-rw-r--r--app/javascript/mastodon/locales/el.json1
-rw-r--r--app/javascript/mastodon/locales/en.json1
-rw-r--r--app/javascript/mastodon/locales/eo.json1
-rw-r--r--app/javascript/mastodon/locales/es.json121
-rw-r--r--app/javascript/mastodon/locales/eu.json1
-rw-r--r--app/javascript/mastodon/locales/fa.json1
-rw-r--r--app/javascript/mastodon/locales/fi.json1
-rw-r--r--app/javascript/mastodon/locales/fr.json11
-rw-r--r--app/javascript/mastodon/locales/gl.json1
-rw-r--r--app/javascript/mastodon/locales/he.json1
-rw-r--r--app/javascript/mastodon/locales/hr.json1
-rw-r--r--app/javascript/mastodon/locales/hu.json1
-rw-r--r--app/javascript/mastodon/locales/hy.json1
-rw-r--r--app/javascript/mastodon/locales/id.json1
-rw-r--r--app/javascript/mastodon/locales/io.json1
-rw-r--r--app/javascript/mastodon/locales/it.json55
-rw-r--r--app/javascript/mastodon/locales/ja.json1
-rw-r--r--app/javascript/mastodon/locales/ka.json1
-rw-r--r--app/javascript/mastodon/locales/ko.json1
-rw-r--r--app/javascript/mastodon/locales/nl.json1
-rw-r--r--app/javascript/mastodon/locales/no.json1
-rw-r--r--app/javascript/mastodon/locales/oc.json1
-rw-r--r--app/javascript/mastodon/locales/pl.json1
-rw-r--r--app/javascript/mastodon/locales/pt-BR.json1
-rw-r--r--app/javascript/mastodon/locales/pt.json1
-rw-r--r--app/javascript/mastodon/locales/ro.json447
-rw-r--r--app/javascript/mastodon/locales/ru.json1
-rw-r--r--app/javascript/mastodon/locales/sk.json47
-rw-r--r--app/javascript/mastodon/locales/sl.json1
-rw-r--r--app/javascript/mastodon/locales/sr-Latn.json1
-rw-r--r--app/javascript/mastodon/locales/sr.json79
-rw-r--r--app/javascript/mastodon/locales/sv.json1
-rw-r--r--app/javascript/mastodon/locales/ta.json1
-rw-r--r--app/javascript/mastodon/locales/te.json59
-rw-r--r--app/javascript/mastodon/locales/th.json1
-rw-r--r--app/javascript/mastodon/locales/tr.json1
-rw-r--r--app/javascript/mastodon/locales/uk.json1
-rw-r--r--app/javascript/mastodon/locales/zh-CN.json1
-rw-r--r--app/javascript/mastodon/locales/zh-HK.json1
-rw-r--r--app/javascript/mastodon/locales/zh-TW.json13
-rw-r--r--app/javascript/mastodon/reducers/dropdown_menu.js4
-rw-r--r--app/javascript/packs/public.js3
-rw-r--r--app/javascript/styles/mastodon/accounts.scss14
-rw-r--r--app/javascript/styles/mastodon/admin.scss183
-rw-r--r--app/javascript/styles/mastodon/basics.scss7
-rw-r--r--app/javascript/styles/mastodon/boost.scss7
-rw-r--r--app/javascript/styles/mastodon/components.scss14
-rw-r--r--app/javascript/styles/mastodon/containers.scss8
-rw-r--r--app/javascript/styles/mastodon/forms.scss361
-rw-r--r--app/lib/activitypub/activity/update.rb1
-rw-r--r--app/models/account.rb54
-rw-r--r--app/models/status.rb2
-rw-r--r--app/serializers/rest/account_serializer.rb4
-rw-r--r--app/services/activitypub/process_account_service.rb5
-rw-r--r--app/services/fetch_link_card_service.rb2
-rw-r--r--app/services/update_account_service.rb12
-rw-r--r--app/services/verify_link_service.rb32
-rw-r--r--app/views/about/_registration.html.haml11
-rw-r--r--app/views/about/more.html.haml2
-rw-r--r--app/views/about/show.html.haml4
-rw-r--r--app/views/accounts/_bio.html.haml7
-rw-r--r--app/views/accounts/_header.html.haml2
-rw-r--r--app/views/admin/change_emails/show.html.haml11
-rw-r--r--app/views/admin/custom_emojis/new.html.haml5
-rw-r--r--app/views/admin/domain_blocks/new.html.haml13
-rw-r--r--app/views/admin/email_domain_blocks/new.html.haml3
-rw-r--r--app/views/admin/reports/_account.html.haml19
-rw-r--r--app/views/admin/reports/_report.html.haml29
-rw-r--r--app/views/admin/reports/index.html.haml52
-rw-r--r--app/views/admin/settings/edit.html.haml63
-rw-r--r--app/views/auth/confirmations/finish_signup.html.haml3
-rw-r--r--app/views/auth/confirmations/new.html.haml3
-rw-r--r--app/views/auth/passwords/edit.html.haml6
-rw-r--r--app/views/auth/passwords/new.html.haml3
-rw-r--r--app/views/auth/registrations/edit.html.haml20
-rw-r--r--app/views/auth/registrations/new.html.haml22
-rw-r--r--app/views/auth/sessions/new.html.haml12
-rw-r--r--app/views/auth/sessions/two_factor.html.haml3
-rw-r--r--app/views/filters/_fields.html.haml12
-rw-r--r--app/views/invites/_form.html.haml8
-rw-r--r--app/views/invites/index.html.haml2
-rw-r--r--app/views/settings/applications/_fields.html.haml6
-rw-r--r--app/views/settings/exports/show.html.haml2
-rw-r--r--app/views/settings/imports/show.html.haml4
-rw-r--r--app/views/settings/preferences/show.html.haml27
-rw-r--r--app/views/settings/profiles/show.html.haml53
-rw-r--r--app/views/settings/two_factor_authentication/confirmations/new.html.haml3
-rw-r--r--app/views/settings/two_factor_authentications/show.html.haml2
-rw-r--r--app/workers/verify_account_links_worker.rb20
178 files changed, 1822 insertions, 1290 deletions
diff --git a/app/controllers/auth/sessions_controller.rb b/app/controllers/auth/sessions_controller.rb
index f4401b3dd..d4a659409 100644
--- a/app/controllers/auth/sessions_controller.rb
+++ b/app/controllers/auth/sessions_controller.rb
@@ -133,7 +133,7 @@ class Auth::SessionsController < Devise::SessionsController
   def clear_site_data
     return if continue_after?
 
-    # Should be '"*"' but that doen't work in Chrome (neither does '"executionContexts"')
+    # Should be '"*"' but that doesn't work in Chrome (neither does '"executionContexts"')
     # https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Clear-Site-Data
     response.headers['Clear-Site-Data'] = '"cache", "cookies"'
   end
diff --git a/app/helpers/admin/account_moderation_notes_helper.rb b/app/helpers/admin/account_moderation_notes_helper.rb
index 25586fbba..4d8f0352e 100644
--- a/app/helpers/admin/account_moderation_notes_helper.rb
+++ b/app/helpers/admin/account_moderation_notes_helper.rb
@@ -4,7 +4,7 @@ module Admin::AccountModerationNotesHelper
   def admin_account_link_to(account)
     return if account.nil?
 
-    link_to admin_account_path(account.id), class: name_tag_classes(account) do
+    link_to admin_account_path(account.id), class: name_tag_classes(account), title: account.acct do
       safe_join([
                   image_tag(account.avatar.url, width: 15, height: 15, alt: display_name(account), class: 'avatar'),
                   content_tag(:span, account.acct, class: 'username'),
@@ -15,7 +15,7 @@ module Admin::AccountModerationNotesHelper
   def admin_account_inline_link_to(account)
     return if account.nil?
 
-    link_to admin_account_path(account.id), class: name_tag_classes(account, true) do
+    link_to admin_account_path(account.id), class: name_tag_classes(account, true), title: account.acct do
       content_tag(:span, account.acct, class: 'username')
     end
   end
diff --git a/app/helpers/home_helper.rb b/app/helpers/home_helper.rb
index f5b501235..ba7c443c2 100644
--- a/app/helpers/home_helper.rb
+++ b/app/helpers/home_helper.rb
@@ -7,13 +7,13 @@ module HomeHelper
     }
   end
 
-  def account_link_to(account, button = '')
+  def account_link_to(account, button = '', size: 36, path: nil)
     content_tag(:div, class: 'account') do
       content_tag(:div, class: 'account__wrapper') do
         section = if account.nil?
                     content_tag(:div, class: 'account__display-name') do
                       content_tag(:div, class: 'account__avatar-wrapper') do
-                        content_tag(:div, '', class: 'account__avatar', style: "background-image: url(#{full_asset_url('avatars/original/missing.png', skip_pipeline: true)})")
+                        content_tag(:div, '', class: 'account__avatar', style: "width: #{size}px; height: #{size}px; background-size: #{size}px #{size}px; background-image: url(#{full_asset_url('avatars/original/missing.png', skip_pipeline: true)})")
                       end +
                         content_tag(:span, class: 'display-name') do
                           content_tag(:strong, t('about.contact_missing')) +
@@ -21,9 +21,9 @@ module HomeHelper
                         end
                     end
                   else
-                    link_to(TagManager.instance.url_for(account), class: 'account__display-name') do
+                    link_to(path || TagManager.instance.url_for(account), class: 'account__display-name') do
                       content_tag(:div, class: 'account__avatar-wrapper') do
-                        content_tag(:div, '', class: 'account__avatar', style: "background-image: url(#{account.avatar.url})")
+                        content_tag(:div, '', class: 'account__avatar', style: "width: #{size}px; height: #{size}px; background-size: #{size}px #{size}px; background-image: url(#{account.avatar.url})")
                       end +
                         content_tag(:span, class: 'display-name') do
                           content_tag(:bdi) do
@@ -48,4 +48,12 @@ module HomeHelper
       '1+'
     end
   end
+
+  def custom_field_classes(field)
+    if field.verified?
+      'verified'
+    else
+      'emojify'
+    end
+  end
 end
diff --git a/app/javascript/core/settings.js b/app/javascript/core/settings.js
index e48fcb9b1..377c899dc 100644
--- a/app/javascript/core/settings.js
+++ b/app/javascript/core/settings.js
@@ -50,3 +50,27 @@ delegate(document, '#account_locked', 'change', ({ target }) => {
     lock.style.display = 'none';
   }
 });
+
+delegate(document, '.input-copy input', 'click', ({ target }) => {
+  target.select();
+});
+
+delegate(document, '.input-copy button', 'click', ({ target }) => {
+  const input = target.parentNode.querySelector('input');
+
+  input.focus();
+  input.select();
+
+  try {
+    if (document.execCommand('copy')) {
+      input.blur();
+      target.parentNode.classList.add('copied');
+
+    setTimeout(() => {
+        target.parentNode.classList.remove('copied');
+      }, 700);
+    }
+  } catch (err) {
+    console.error(err);
+  }
+});
diff --git a/app/javascript/mastodon/actions/dropdown_menu.js b/app/javascript/mastodon/actions/dropdown_menu.js
index 217ba4e74..14f2939c7 100644
--- a/app/javascript/mastodon/actions/dropdown_menu.js
+++ b/app/javascript/mastodon/actions/dropdown_menu.js
@@ -1,8 +1,8 @@
 export const DROPDOWN_MENU_OPEN = 'DROPDOWN_MENU_OPEN';
 export const DROPDOWN_MENU_CLOSE = 'DROPDOWN_MENU_CLOSE';
 
-export function openDropdownMenu(id, placement) {
-  return { type: DROPDOWN_MENU_OPEN, id, placement };
+export function openDropdownMenu(id, placement, keyboard) {
+  return { type: DROPDOWN_MENU_OPEN, id, placement, keyboard };
 }
 
 export function closeDropdownMenu(id) {
diff --git a/app/javascript/mastodon/components/__tests__/__snapshots__/button-test.js.snap b/app/javascript/mastodon/components/__tests__/__snapshots__/button-test.js.snap
index c3f018d90..5c04e0979 100644
--- a/app/javascript/mastodon/components/__tests__/__snapshots__/button-test.js.snap
+++ b/app/javascript/mastodon/components/__tests__/__snapshots__/button-test.js.snap
@@ -3,7 +3,6 @@
 exports[`<Button /> adds class "button-secondary" if props.secondary given 1`] = `
 <button
   className="button button-secondary"
-  disabled={undefined}
   onClick={[Function]}
   style={
     Object {
@@ -18,7 +17,6 @@ exports[`<Button /> adds class "button-secondary" if props.secondary given 1`] =
 exports[`<Button /> renders a button element 1`] = `
 <button
   className="button"
-  disabled={undefined}
   onClick={[Function]}
   style={
     Object {
@@ -48,7 +46,6 @@ exports[`<Button /> renders a disabled attribute if props.disabled given 1`] = `
 exports[`<Button /> renders class="button--block" if props.block given 1`] = `
 <button
   className="button button--block"
-  disabled={undefined}
   onClick={[Function]}
   style={
     Object {
@@ -63,7 +60,6 @@ exports[`<Button /> renders class="button--block" if props.block given 1`] = `
 exports[`<Button /> renders the children 1`] = `
 <button
   className="button"
-  disabled={undefined}
   onClick={[Function]}
   style={
     Object {
@@ -82,7 +78,6 @@ exports[`<Button /> renders the children 1`] = `
 exports[`<Button /> renders the given text 1`] = `
 <button
   className="button"
-  disabled={undefined}
   onClick={[Function]}
   style={
     Object {
@@ -99,7 +94,6 @@ exports[`<Button /> renders the given text 1`] = `
 exports[`<Button /> renders the props.text instead of children 1`] = `
 <button
   className="button"
-  disabled={undefined}
   onClick={[Function]}
   style={
     Object {
diff --git a/app/javascript/mastodon/components/account.js b/app/javascript/mastodon/components/account.js
index 8e6aa9d92..c021e3267 100644
--- a/app/javascript/mastodon/components/account.js
+++ b/app/javascript/mastodon/components/account.js
@@ -19,8 +19,8 @@ const messages = defineMessages({
   unmute_notifications: { id: 'account.unmute_notifications', defaultMessage: 'Unmute notifications from @{name}' },
 });
 
-@injectIntl
-export default class Account extends ImmutablePureComponent {
+export default @injectIntl
+class Account extends ImmutablePureComponent {
 
   static propTypes = {
     account: ImmutablePropTypes.map.isRequired,
diff --git a/app/javascript/mastodon/components/column_header.js b/app/javascript/mastodon/components/column_header.js
index 56453aeac..457508d13 100644
--- a/app/javascript/mastodon/components/column_header.js
+++ b/app/javascript/mastodon/components/column_header.js
@@ -10,8 +10,8 @@ const messages = defineMessages({
   moveRight: { id: 'column_header.moveRight_settings', defaultMessage: 'Move column to the right' },
 });
 
-@injectIntl
-export default class ColumnHeader extends React.PureComponent {
+export default @injectIntl
+class ColumnHeader extends React.PureComponent {
 
   static contextTypes = {
     router: PropTypes.object,
diff --git a/app/javascript/mastodon/components/domain.js b/app/javascript/mastodon/components/domain.js
index f657cb8d2..24f80e788 100644
--- a/app/javascript/mastodon/components/domain.js
+++ b/app/javascript/mastodon/components/domain.js
@@ -8,8 +8,8 @@ const messages = defineMessages({
   unblockDomain: { id: 'account.unblock_domain', defaultMessage: 'Unhide {domain}' },
 });
 
-@injectIntl
-export default class Account extends ImmutablePureComponent {
+export default @injectIntl
+class Account extends ImmutablePureComponent {
 
   static propTypes = {
     domain: PropTypes.string,
diff --git a/app/javascript/mastodon/components/dropdown_menu.js b/app/javascript/mastodon/components/dropdown_menu.js
index a5cf6479b..91b65a02f 100644
--- a/app/javascript/mastodon/components/dropdown_menu.js
+++ b/app/javascript/mastodon/components/dropdown_menu.js
@@ -23,6 +23,7 @@ class DropdownMenu extends React.PureComponent {
     placement: PropTypes.string,
     arrowOffsetLeft: PropTypes.string,
     arrowOffsetTop: PropTypes.string,
+    openedViaKeyboard: PropTypes.bool,
   };
 
   static defaultProps = {
@@ -42,13 +43,15 @@ class DropdownMenu extends React.PureComponent {
 
   componentDidMount () {
     document.addEventListener('click', this.handleDocumentClick, false);
+    document.addEventListener('keydown', this.handleKeyDown, false);
     document.addEventListener('touchend', this.handleDocumentClick, listenerOptions);
-    if (this.focusedItem) this.focusedItem.focus();
+    if (this.focusedItem && this.props.openedViaKeyboard) this.focusedItem.focus();
     this.setState({ mounted: true });
   }
 
   componentWillUnmount () {
     document.removeEventListener('click', this.handleDocumentClick, false);
+    document.removeEventListener('keydown', this.handleKeyDown, false);
     document.removeEventListener('touchend', this.handleDocumentClick, listenerOptions);
   }
 
@@ -62,13 +65,10 @@ class DropdownMenu extends React.PureComponent {
 
   handleKeyDown = e => {
     const items = Array.from(this.node.getElementsByTagName('a'));
-    const index = items.indexOf(e.currentTarget);
+    const index = items.indexOf(document.activeElement);
     let element;
 
     switch(e.key) {
-    case 'Enter':
-      this.handleClick(e);
-      break;
     case 'ArrowDown':
       element = items[index+1];
       if (element) {
@@ -96,6 +96,12 @@ class DropdownMenu extends React.PureComponent {
     }
   }
 
+  handleItemKeyDown = e => {
+    if (e.key === 'Enter') {
+      this.handleClick(e);
+    }
+  }
+
   handleClick = e => {
     const i = Number(e.currentTarget.getAttribute('data-index'));
     const { action, to } = this.props.items[i];
@@ -120,7 +126,7 @@ class DropdownMenu extends React.PureComponent {
 
     return (
       <li className='dropdown-menu__item' key={`${text}-${i}`}>
-        <a href={href} target='_blank' rel='noopener' role='button' tabIndex='0' ref={i === 0 ? this.setFocusRef : null} onClick={this.handleClick} onKeyDown={this.handleKeyDown} data-index={i}>
+        <a href={href} target='_blank' rel='noopener' role='button' tabIndex='0' ref={i === 0 ? this.setFocusRef : null} onClick={this.handleClick} onKeyDown={this.handleItemKeyDown} data-index={i}>
           {text}
         </a>
       </li>
@@ -170,6 +176,7 @@ export default class Dropdown extends React.PureComponent {
     onClose: PropTypes.func.isRequired,
     dropdownPlacement: PropTypes.string,
     openDropdownId: PropTypes.number,
+    openedViaKeyboard: PropTypes.bool,
   };
 
   static defaultProps = {
@@ -180,14 +187,14 @@ export default class Dropdown extends React.PureComponent {
     id: id++,
   };
 
-  handleClick = ({ target }) => {
+  handleClick = ({ target, type }) => {
     if (this.state.id === this.props.openDropdownId) {
       this.handleClose();
     } else {
       const { top } = target.getBoundingClientRect();
       const placement = top * 2 < innerHeight ? 'bottom' : 'top';
 
-      this.props.onOpen(this.state.id, this.handleItemClick, placement);
+      this.props.onOpen(this.state.id, this.handleItemClick, placement, type !== 'click');
     }
   }
 
@@ -197,6 +204,11 @@ export default class Dropdown extends React.PureComponent {
 
   handleKeyDown = e => {
     switch(e.key) {
+    case ' ':
+    case 'Enter':
+      this.handleClick(e);
+      e.preventDefault();
+      break;
     case 'Escape':
       this.handleClose();
       break;
@@ -233,7 +245,7 @@ export default class Dropdown extends React.PureComponent {
   }
 
   render () {
-    const { icon, items, size, title, disabled, dropdownPlacement, openDropdownId } = this.props;
+    const { icon, items, size, title, disabled, dropdownPlacement, openDropdownId, openedViaKeyboard } = this.props;
     const open = this.state.id === openDropdownId;
 
     return (
@@ -249,7 +261,7 @@ export default class Dropdown extends React.PureComponent {
         />
 
         <Overlay show={open} placement={dropdownPlacement} target={this.findTarget}>
-          <DropdownMenu items={items} onClose={this.handleClose} />
+          <DropdownMenu items={items} onClose={this.handleClose} openedViaKeyboard={openedViaKeyboard} />
         </Overlay>
       </div>
     );
diff --git a/app/javascript/mastodon/components/load_gap.js b/app/javascript/mastodon/components/load_gap.js
index 012303ae1..ed4d445d0 100644
--- a/app/javascript/mastodon/components/load_gap.js
+++ b/app/javascript/mastodon/components/load_gap.js
@@ -6,8 +6,8 @@ const messages = defineMessages({
   load_more: { id: 'status.load_more', defaultMessage: 'Load more' },
 });
 
-@injectIntl
-export default class LoadGap extends React.PureComponent {
+export default @injectIntl
+class LoadGap extends React.PureComponent {
 
   static propTypes = {
     disabled: PropTypes.bool,
diff --git a/app/javascript/mastodon/components/media_gallery.js b/app/javascript/mastodon/components/media_gallery.js
index 6e1310cd6..a1785196f 100644
--- a/app/javascript/mastodon/components/media_gallery.js
+++ b/app/javascript/mastodon/components/media_gallery.js
@@ -179,8 +179,8 @@ class Item extends React.PureComponent {
 
 }
 
-@injectIntl
-export default class MediaGallery extends React.PureComponent {
+export default @injectIntl
+class MediaGallery extends React.PureComponent {
 
   static propTypes = {
     sensitive: PropTypes.bool,
diff --git a/app/javascript/mastodon/components/relative_timestamp.js b/app/javascript/mastodon/components/relative_timestamp.js
index 9609714a1..57d99dd19 100644
--- a/app/javascript/mastodon/components/relative_timestamp.js
+++ b/app/javascript/mastodon/components/relative_timestamp.js
@@ -86,8 +86,8 @@ export const timeAgoString = (intl, date, now, year) => {
   return relativeTime;
 };
 
-@injectIntl
-export default class RelativeTimestamp extends React.Component {
+export default @injectIntl
+class RelativeTimestamp extends React.Component {
 
   static propTypes = {
     intl: PropTypes.object.isRequired,
diff --git a/app/javascript/mastodon/components/status.js b/app/javascript/mastodon/components/status.js
index 43647acc0..6c595c712 100644
--- a/app/javascript/mastodon/components/status.js
+++ b/app/javascript/mastodon/components/status.js
@@ -35,8 +35,8 @@ export const textForScreenReader = (intl, status, rebloggedByText = false) => {
   return values.join(', ');
 };
 
-@injectIntl
-export default class Status extends ImmutablePureComponent {
+export default @injectIntl
+class Status extends ImmutablePureComponent {
 
   static contextTypes = {
     router: PropTypes.object,
diff --git a/app/javascript/mastodon/components/status_action_bar.js b/app/javascript/mastodon/components/status_action_bar.js
index 6d44a4b45..e7e5b0a6c 100644
--- a/app/javascript/mastodon/components/status_action_bar.js
+++ b/app/javascript/mastodon/components/status_action_bar.js
@@ -42,8 +42,8 @@ const obfuscatedCount = count => {
   }
 };
 
-@injectIntl
-export default class StatusActionBar extends ImmutablePureComponent {
+export default @injectIntl
+class StatusActionBar extends ImmutablePureComponent {
 
   static contextTypes = {
     router: PropTypes.object,
diff --git a/app/javascript/mastodon/containers/dropdown_menu_container.js b/app/javascript/mastodon/containers/dropdown_menu_container.js
index 7cbcdcd35..73c8a1e53 100644
--- a/app/javascript/mastodon/containers/dropdown_menu_container.js
+++ b/app/javascript/mastodon/containers/dropdown_menu_container.js
@@ -8,15 +8,16 @@ const mapStateToProps = state => ({
   isModalOpen: state.get('modal').modalType === 'ACTIONS',
   dropdownPlacement: state.getIn(['dropdown_menu', 'placement']),
   openDropdownId: state.getIn(['dropdown_menu', 'openId']),
+  openedViaKeyboard: state.getIn(['dropdown_menu', 'keyboard']),
 });
 
 const mapDispatchToProps = (dispatch, { status, items }) => ({
-  onOpen(id, onItemClick, dropdownPlacement) {
+  onOpen(id, onItemClick, dropdownPlacement, keyboard) {
     dispatch(isUserTouching() ? openModal('ACTIONS', {
       status,
       actions: items,
       onClick: onItemClick,
-    }) : openDropdownMenu(id, dropdownPlacement));
+    }) : openDropdownMenu(id, dropdownPlacement, keyboard));
   },
   onClose(id) {
     dispatch(closeModal());
diff --git a/app/javascript/mastodon/features/account/components/action_bar.js b/app/javascript/mastodon/features/account/components/action_bar.js
index bc6f86628..c9ae2df98 100644
--- a/app/javascript/mastodon/features/account/components/action_bar.js
+++ b/app/javascript/mastodon/features/account/components/action_bar.js
@@ -2,7 +2,7 @@ import React from 'react';
 import ImmutablePropTypes from 'react-immutable-proptypes';
 import PropTypes from 'prop-types';
 import DropdownMenuContainer from '../../../containers/dropdown_menu_container';
-import { Link } from 'react-router-dom';
+import { NavLink } from 'react-router-dom';
 import { defineMessages, injectIntl, FormattedMessage } from 'react-intl';
 import { me } from '../../../initial_state';
 import { shortNumberFormat } from '../../../utils/numbers';
@@ -36,8 +36,8 @@ const messages = defineMessages({
   unendorse: { id: 'account.unendorse', defaultMessage: 'Don\'t feature on profile' },
 });
 
-@injectIntl
-export default class ActionBar extends React.PureComponent {
+export default @injectIntl
+class ActionBar extends React.PureComponent {
 
   static propTypes = {
     account: ImmutablePropTypes.map.isRequired,
@@ -60,6 +60,13 @@ export default class ActionBar extends React.PureComponent {
     });
   }
 
+  isStatusesPageActive = (match, location) => {
+    if (!match) {
+      return false;
+    }
+    return !location.pathname.match(/\/(followers|following)\/?$/);
+  }
+
   render () {
     const { account, intl } = this.props;
 
@@ -147,20 +154,20 @@ 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')}`} title={intl.formatNumber(account.get('statuses_count'))}>
+            <NavLink isActive={this.isStatusesPageActive} activeClassName='active' className='account__action-bar__tab' to={`/accounts/${account.get('id')}`} title={intl.formatNumber(account.get('statuses_count'))}>
               <FormattedMessage id='account.posts' defaultMessage='Toots' />
               <strong>{shortNumberFormat(account.get('statuses_count'))}</strong>
-            </Link>
+            </NavLink>
 
-            <Link className='account__action-bar__tab' to={`/accounts/${account.get('id')}/following`} title={intl.formatNumber(account.get('following_count'))}>
+            <NavLink exact activeClassName='active' className='account__action-bar__tab' to={`/accounts/${account.get('id')}/following`} title={intl.formatNumber(account.get('following_count'))}>
               <FormattedMessage id='account.follows' defaultMessage='Follows' />
               <strong>{shortNumberFormat(account.get('following_count'))}</strong>
-            </Link>
+            </NavLink>
 
-            <Link className='account__action-bar__tab' to={`/accounts/${account.get('id')}/followers`} title={intl.formatNumber(account.get('followers_count'))}>
+            <NavLink exact activeClassName='active' className='account__action-bar__tab' to={`/accounts/${account.get('id')}/followers`} title={intl.formatNumber(account.get('followers_count'))}>
               <FormattedMessage id='account.followers' defaultMessage='Followers' />
               <strong>{shortNumberFormat(account.get('followers_count'))}</strong>
-            </Link>
+            </NavLink>
           </div>
 
           <div className='account__action-bar-dropdown'>
diff --git a/app/javascript/mastodon/features/account/components/header.js b/app/javascript/mastodon/features/account/components/header.js
index eb9236aeb..11ae58905 100644
--- a/app/javascript/mastodon/features/account/components/header.js
+++ b/app/javascript/mastodon/features/account/components/header.js
@@ -15,8 +15,18 @@ const messages = defineMessages({
   requested: { id: 'account.requested', defaultMessage: 'Awaiting approval. Click to cancel follow request' },
   unblock: { id: 'account.unblock', defaultMessage: 'Unblock @{name}' },
   edit_profile: { id: 'account.edit_profile', defaultMessage: 'Edit profile' },
+  linkVerifiedOn: { id: 'account.link_verified_on', defaultMessage: 'Ownership of this link was checked on {date}' },
 });
 
+const dateFormatOptions = {
+  month: 'short',
+  day: 'numeric',
+  year: 'numeric',
+  hour12: false,
+  hour: '2-digit',
+  minute: '2-digit',
+};
+
 class Avatar extends ImmutablePureComponent {
 
   static propTypes = {
@@ -65,8 +75,8 @@ class Avatar extends ImmutablePureComponent {
 
 }
 
-@injectIntl
-export default class Header extends ImmutablePureComponent {
+export default @injectIntl
+class Header extends ImmutablePureComponent {
 
   static propTypes = {
     account: ImmutablePropTypes.map,
@@ -163,7 +173,10 @@ export default class Header extends ImmutablePureComponent {
               {fields.map((pair, i) => (
                 <dl key={i}>
                   <dt dangerouslySetInnerHTML={{ __html: pair.get('name_emojified') }} title={pair.get('name')} />
-                  <dd dangerouslySetInnerHTML={{ __html: pair.get('value_emojified') }} title={pair.get('value_plain')} />
+
+                  <dd className={pair.get('verified_at') && 'verified'} title={pair.get('value_plain')}>
+                    {pair.get('verified_at') && <span title={intl.formatMessage(messages.linkVerifiedOn, { date: intl.formatDate(pair.get('verified_at'), dateFormatOptions) })}><i className='fa fa-check verified__mark' /></span>} <span dangerouslySetInnerHTML={{ __html: pair.get('value_emojified') }} />
+                  </dd>
                 </dl>
               ))}
             </div>
diff --git a/app/javascript/mastodon/features/account_gallery/index.js b/app/javascript/mastodon/features/account_gallery/index.js
index a6c464aff..32cb5ebdc 100644
--- a/app/javascript/mastodon/features/account_gallery/index.js
+++ b/app/javascript/mastodon/features/account_gallery/index.js
@@ -43,8 +43,8 @@ class LoadMoreMedia extends ImmutablePureComponent {
 
 }
 
-@connect(mapStateToProps)
-export default class AccountGallery extends ImmutablePureComponent {
+export default @connect(mapStateToProps)
+class AccountGallery extends ImmutablePureComponent {
 
   static propTypes = {
     params: PropTypes.object.isRequired,
diff --git a/app/javascript/mastodon/features/account_timeline/index.js b/app/javascript/mastodon/features/account_timeline/index.js
index 934513cd7..6055af51d 100644
--- a/app/javascript/mastodon/features/account_timeline/index.js
+++ b/app/javascript/mastodon/features/account_timeline/index.js
@@ -23,8 +23,8 @@ const mapStateToProps = (state, { params: { accountId }, withReplies = false })
   };
 };
 
-@connect(mapStateToProps)
-export default class AccountTimeline extends ImmutablePureComponent {
+export default @connect(mapStateToProps)
+class AccountTimeline extends ImmutablePureComponent {
 
   static propTypes = {
     params: PropTypes.object.isRequired,
diff --git a/app/javascript/mastodon/features/blocks/index.js b/app/javascript/mastodon/features/blocks/index.js
index 68661a37c..ca7ce6f8e 100644
--- a/app/javascript/mastodon/features/blocks/index.js
+++ b/app/javascript/mastodon/features/blocks/index.js
@@ -20,9 +20,9 @@ const mapStateToProps = state => ({
   accountIds: state.getIn(['user_lists', 'blocks', 'items']),
 });
 
-@connect(mapStateToProps)
+export default @connect(mapStateToProps)
 @injectIntl
-export default class Blocks extends ImmutablePureComponent {
+class Blocks extends ImmutablePureComponent {
 
   static propTypes = {
     params: PropTypes.object.isRequired,
diff --git a/app/javascript/mastodon/features/community_timeline/components/column_settings.js b/app/javascript/mastodon/features/community_timeline/components/column_settings.js
index f4325f58d..8250190a7 100644
--- a/app/javascript/mastodon/features/community_timeline/components/column_settings.js
+++ b/app/javascript/mastodon/features/community_timeline/components/column_settings.js
@@ -4,8 +4,8 @@ import ImmutablePropTypes from 'react-immutable-proptypes';
 import { injectIntl, FormattedMessage } from 'react-intl';
 import SettingToggle from '../../notifications/components/setting_toggle';
 
-@injectIntl
-export default class ColumnSettings extends React.PureComponent {
+export default @injectIntl
+class ColumnSettings extends React.PureComponent {
 
   static propTypes = {
     settings: ImmutablePropTypes.map.isRequired,
diff --git a/app/javascript/mastodon/features/community_timeline/index.js b/app/javascript/mastodon/features/community_timeline/index.js
index 48d2b3f68..7d26c98b0 100644
--- a/app/javascript/mastodon/features/community_timeline/index.js
+++ b/app/javascript/mastodon/features/community_timeline/index.js
@@ -25,9 +25,9 @@ const mapStateToProps = (state, { onlyMedia, columnId }) => {
   };
 };
 
-@connect(mapStateToProps)
+export default @connect(mapStateToProps)
 @injectIntl
-export default class CommunityTimeline extends React.PureComponent {
+class CommunityTimeline extends React.PureComponent {
 
   static contextTypes = {
     router: PropTypes.object,
diff --git a/app/javascript/mastodon/features/compose/components/action_bar.js b/app/javascript/mastodon/features/compose/components/action_bar.js
index daee18552..95d6eeb06 100644
--- a/app/javascript/mastodon/features/compose/components/action_bar.js
+++ b/app/javascript/mastodon/features/compose/components/action_bar.js
@@ -17,8 +17,8 @@ const messages = defineMessages({
   filters: { id: 'navigation_bar.filters', defaultMessage: 'Muted words' },
 });
 
-@injectIntl
-export default class ActionBar extends React.PureComponent {
+export default @injectIntl
+class ActionBar extends React.PureComponent {
 
   static propTypes = {
     account: ImmutablePropTypes.map.isRequired,
diff --git a/app/javascript/mastodon/features/compose/components/compose_form.js b/app/javascript/mastodon/features/compose/components/compose_form.js
index cc9145683..eec93fc28 100644
--- a/app/javascript/mastodon/features/compose/components/compose_form.js
+++ b/app/javascript/mastodon/features/compose/components/compose_form.js
@@ -28,8 +28,8 @@ const messages = defineMessages({
   publishLoud: { id: 'compose_form.publish_loud', defaultMessage: '{publish}!' },
 });
 
-@injectIntl
-export default class ComposeForm extends ImmutablePureComponent {
+export default @injectIntl
+class ComposeForm extends ImmutablePureComponent {
 
   static propTypes = {
     intl: PropTypes.object.isRequired,
diff --git a/app/javascript/mastodon/features/compose/components/emoji_picker_dropdown.js b/app/javascript/mastodon/features/compose/components/emoji_picker_dropdown.js
index 4fc32db8a..c1429c756 100644
--- a/app/javascript/mastodon/features/compose/components/emoji_picker_dropdown.js
+++ b/app/javascript/mastodon/features/compose/components/emoji_picker_dropdown.js
@@ -261,6 +261,7 @@ class EmojiPickerMenu extends React.PureComponent {
           skin={skinTone}
           showPreview={false}
           backgroundImageFn={backgroundImageFn}
+          autoFocus
           emojiTooltip
         />
 
@@ -277,8 +278,8 @@ class EmojiPickerMenu extends React.PureComponent {
 
 }
 
-@injectIntl
-export default class EmojiPickerDropdown extends React.PureComponent {
+export default @injectIntl
+class EmojiPickerDropdown extends React.PureComponent {
 
   static propTypes = {
     custom_emojis: ImmutablePropTypes.list,
diff --git a/app/javascript/mastodon/features/compose/components/privacy_dropdown.js b/app/javascript/mastodon/features/compose/components/privacy_dropdown.js
index e19778fd2..7b5482f05 100644
--- a/app/javascript/mastodon/features/compose/components/privacy_dropdown.js
+++ b/app/javascript/mastodon/features/compose/components/privacy_dropdown.js
@@ -149,8 +149,8 @@ class PrivacyDropdownMenu extends React.PureComponent {
 
 }
 
-@injectIntl
-export default class PrivacyDropdown extends React.PureComponent {
+export default @injectIntl
+class PrivacyDropdown extends React.PureComponent {
 
   static propTypes = {
     isUserTouching: PropTypes.func,
diff --git a/app/javascript/mastodon/features/compose/components/reply_indicator.js b/app/javascript/mastodon/features/compose/components/reply_indicator.js
index 6f358a98b..142223f3d 100644
--- a/app/javascript/mastodon/features/compose/components/reply_indicator.js
+++ b/app/javascript/mastodon/features/compose/components/reply_indicator.js
@@ -12,8 +12,8 @@ const messages = defineMessages({
   cancel: { id: 'reply_indicator.cancel', defaultMessage: 'Cancel' },
 });
 
-@injectIntl
-export default class ReplyIndicator extends ImmutablePureComponent {
+export default @injectIntl
+class ReplyIndicator extends ImmutablePureComponent {
 
   static contextTypes = {
     router: PropTypes.object,
diff --git a/app/javascript/mastodon/features/compose/components/search.js b/app/javascript/mastodon/features/compose/components/search.js
index 71c0a203f..d203d8780 100644
--- a/app/javascript/mastodon/features/compose/components/search.js
+++ b/app/javascript/mastodon/features/compose/components/search.js
@@ -43,8 +43,8 @@ class SearchPopout extends React.PureComponent {
 
 }
 
-@injectIntl
-export default class Search extends React.PureComponent {
+export default @injectIntl
+class Search extends React.PureComponent {
 
   static propTypes = {
     value: PropTypes.string.isRequired,
diff --git a/app/javascript/mastodon/features/compose/components/upload.js b/app/javascript/mastodon/features/compose/components/upload.js
index 3d09217dc..e377da90c 100644
--- a/app/javascript/mastodon/features/compose/components/upload.js
+++ b/app/javascript/mastodon/features/compose/components/upload.js
@@ -11,8 +11,8 @@ const messages = defineMessages({
   description: { id: 'upload_form.description', defaultMessage: 'Describe for the visually impaired' },
 });
 
-@injectIntl
-export default class Upload extends ImmutablePureComponent {
+export default @injectIntl
+class Upload extends ImmutablePureComponent {
 
   static propTypes = {
     media: ImmutablePropTypes.map.isRequired,
diff --git a/app/javascript/mastodon/features/compose/components/upload_button.js b/app/javascript/mastodon/features/compose/components/upload_button.js
index 8b9609138..b6fe770ea 100644
--- a/app/javascript/mastodon/features/compose/components/upload_button.js
+++ b/app/javascript/mastodon/features/compose/components/upload_button.js
@@ -23,9 +23,9 @@ const iconStyle = {
   lineHeight: '27px',
 };
 
-@connect(makeMapStateToProps)
+export default @connect(makeMapStateToProps)
 @injectIntl
-export default class UploadButton extends ImmutablePureComponent {
+class UploadButton extends ImmutablePureComponent {
 
   static propTypes = {
     disabled: PropTypes.bool,
diff --git a/app/javascript/mastodon/features/compose/index.js b/app/javascript/mastodon/features/compose/index.js
index b7394a39e..cf1714b71 100644
--- a/app/javascript/mastodon/features/compose/index.js
+++ b/app/javascript/mastodon/features/compose/index.js
@@ -30,9 +30,9 @@ const mapStateToProps = (state, ownProps) => ({
   showSearch: ownProps.multiColumn ? state.getIn(['search', 'submitted']) && !state.getIn(['search', 'hidden']) : ownProps.isSearchPage,
 });
 
-@connect(mapStateToProps)
+export default @connect(mapStateToProps)
 @injectIntl
-export default class Compose extends React.PureComponent {
+class Compose extends React.PureComponent {
 
   static propTypes = {
     dispatch: PropTypes.func.isRequired,
diff --git a/app/javascript/mastodon/features/compose/util/url_regex.js b/app/javascript/mastodon/features/compose/util/url_regex.js
index d5e39e0d5..7f1e17620 100644
--- a/app/javascript/mastodon/features/compose/util/url_regex.js
+++ b/app/javascript/mastodon/features/compose/util/url_regex.js
@@ -170,7 +170,7 @@ export const urlRegex = (function() {
       ')'                                   +
     '\\)',
     'i');
-  // Valid end-of-path chracters (so /foo. does not gobble the period).
+  // Valid end-of-path characters (so /foo. does not gobble the period).
   // 1. Allow =&# for empty URL parameters and other URL-join artifacts
   regexen.validUrlPathEndingChars = regexSupplant(/[^#{spaces_group}\(\)\?!\*';:=\,\.\$%\[\]#{pd}~&\|@]|(?:#{validUrlBalancedParens})/i);
   // Allow @ in a url, but only in the middle. Catch things like http://example.com/@user/
diff --git a/app/javascript/mastodon/features/direct_timeline/components/column_settings.js b/app/javascript/mastodon/features/direct_timeline/components/column_settings.js
index a992b27bb..b629c128d 100644
--- a/app/javascript/mastodon/features/direct_timeline/components/column_settings.js
+++ b/app/javascript/mastodon/features/direct_timeline/components/column_settings.js
@@ -9,8 +9,8 @@ const messages = defineMessages({
   settings: { id: 'home.settings', defaultMessage: 'Column settings' },
 });
 
-@injectIntl
-export default class ColumnSettings extends React.PureComponent {
+export default @injectIntl
+class ColumnSettings extends React.PureComponent {
 
   static propTypes = {
     settings: ImmutablePropTypes.map.isRequired,
diff --git a/app/javascript/mastodon/features/direct_timeline/index.js b/app/javascript/mastodon/features/direct_timeline/index.js
index dd289ce56..3c7e2d007 100644
--- a/app/javascript/mastodon/features/direct_timeline/index.js
+++ b/app/javascript/mastodon/features/direct_timeline/index.js
@@ -17,9 +17,9 @@ const mapStateToProps = state => ({
   hasUnread: state.getIn(['timelines', 'direct', 'unread']) > 0,
 });
 
-@connect(mapStateToProps)
+export default @connect(mapStateToProps)
 @injectIntl
-export default class DirectTimeline extends React.PureComponent {
+class DirectTimeline extends React.PureComponent {
 
   static propTypes = {
     dispatch: PropTypes.func.isRequired,
diff --git a/app/javascript/mastodon/features/domain_blocks/index.js b/app/javascript/mastodon/features/domain_blocks/index.js
index 2c40bf72d..5c1bd1161 100644
--- a/app/javascript/mastodon/features/domain_blocks/index.js
+++ b/app/javascript/mastodon/features/domain_blocks/index.js
@@ -21,9 +21,9 @@ const mapStateToProps = state => ({
   domains: state.getIn(['domain_lists', 'blocks', 'items']),
 });
 
-@connect(mapStateToProps)
+export default @connect(mapStateToProps)
 @injectIntl
-export default class Blocks extends ImmutablePureComponent {
+class Blocks extends ImmutablePureComponent {
 
   static propTypes = {
     params: PropTypes.object.isRequired,
diff --git a/app/javascript/mastodon/features/favourited_statuses/index.js b/app/javascript/mastodon/features/favourited_statuses/index.js
index 499530cd9..fa9401b90 100644
--- a/app/javascript/mastodon/features/favourited_statuses/index.js
+++ b/app/javascript/mastodon/features/favourited_statuses/index.js
@@ -21,9 +21,9 @@ const mapStateToProps = state => ({
   hasMore: !!state.getIn(['status_lists', 'favourites', 'next']),
 });
 
-@connect(mapStateToProps)
+export default @connect(mapStateToProps)
 @injectIntl
-export default class Favourites extends ImmutablePureComponent {
+class Favourites extends ImmutablePureComponent {
 
   static propTypes = {
     dispatch: PropTypes.func.isRequired,
diff --git a/app/javascript/mastodon/features/favourites/index.js b/app/javascript/mastodon/features/favourites/index.js
index 74a683ccc..d1ac229a2 100644
--- a/app/javascript/mastodon/features/favourites/index.js
+++ b/app/javascript/mastodon/features/favourites/index.js
@@ -15,8 +15,8 @@ const mapStateToProps = (state, props) => ({
   accountIds: state.getIn(['user_lists', 'favourited_by', props.params.statusId]),
 });
 
-@connect(mapStateToProps)
-export default class Favourites extends ImmutablePureComponent {
+export default @connect(mapStateToProps)
+class Favourites extends ImmutablePureComponent {
 
   static propTypes = {
     params: PropTypes.object.isRequired,
diff --git a/app/javascript/mastodon/features/follow_requests/components/account_authorize.js b/app/javascript/mastodon/features/follow_requests/components/account_authorize.js
index 4fc5638d9..a3b524db1 100644
--- a/app/javascript/mastodon/features/follow_requests/components/account_authorize.js
+++ b/app/javascript/mastodon/features/follow_requests/components/account_authorize.js
@@ -13,8 +13,8 @@ const messages = defineMessages({
   reject: { id: 'follow_request.reject', defaultMessage: 'Reject' },
 });
 
-@injectIntl
-export default class AccountAuthorize extends ImmutablePureComponent {
+export default @injectIntl
+class AccountAuthorize extends ImmutablePureComponent {
 
   static propTypes = {
     account: ImmutablePropTypes.map.isRequired,
diff --git a/app/javascript/mastodon/features/follow_requests/index.js b/app/javascript/mastodon/features/follow_requests/index.js
index cb574e08d..56ae8764b 100644
--- a/app/javascript/mastodon/features/follow_requests/index.js
+++ b/app/javascript/mastodon/features/follow_requests/index.js
@@ -20,9 +20,9 @@ const mapStateToProps = state => ({
   accountIds: state.getIn(['user_lists', 'follow_requests', 'items']),
 });
 
-@connect(mapStateToProps)
+export default @connect(mapStateToProps)
 @injectIntl
-export default class FollowRequests extends ImmutablePureComponent {
+class FollowRequests extends ImmutablePureComponent {
 
   static propTypes = {
     params: PropTypes.object.isRequired,
diff --git a/app/javascript/mastodon/features/followers/index.js b/app/javascript/mastodon/features/followers/index.js
index 97d59cc4a..b9ca7f3dd 100644
--- a/app/javascript/mastodon/features/followers/index.js
+++ b/app/javascript/mastodon/features/followers/index.js
@@ -22,8 +22,8 @@ const mapStateToProps = (state, props) => ({
   hasMore: !!state.getIn(['user_lists', 'followers', props.params.accountId, 'next']),
 });
 
-@connect(mapStateToProps)
-export default class Followers extends ImmutablePureComponent {
+export default @connect(mapStateToProps)
+class Followers extends ImmutablePureComponent {
 
   static propTypes = {
     params: PropTypes.object.isRequired,
diff --git a/app/javascript/mastodon/features/following/index.js b/app/javascript/mastodon/features/following/index.js
index 17bc7ec6e..b3e160240 100644
--- a/app/javascript/mastodon/features/following/index.js
+++ b/app/javascript/mastodon/features/following/index.js
@@ -22,8 +22,8 @@ const mapStateToProps = (state, props) => ({
   hasMore: !!state.getIn(['user_lists', 'following', props.params.accountId, 'next']),
 });
 
-@connect(mapStateToProps)
-export default class Following extends ImmutablePureComponent {
+export default @connect(mapStateToProps)
+class Following extends ImmutablePureComponent {
 
   static propTypes = {
     params: PropTypes.object.isRequired,
diff --git a/app/javascript/mastodon/features/getting_started/index.js b/app/javascript/mastodon/features/getting_started/index.js
index 97c726f62..d5ba5cbce 100644
--- a/app/javascript/mastodon/features/getting_started/index.js
+++ b/app/javascript/mastodon/features/getting_started/index.js
@@ -53,9 +53,9 @@ const badgeDisplay = (number, limit) => {
   }
 };
 
-@connect(mapStateToProps, mapDispatchToProps)
+export default @connect(mapStateToProps, mapDispatchToProps)
 @injectIntl
-export default class GettingStarted extends ImmutablePureComponent {
+class GettingStarted extends ImmutablePureComponent {
 
   static propTypes = {
     intl: PropTypes.object.isRequired,
diff --git a/app/javascript/mastodon/features/hashtag_timeline/index.js b/app/javascript/mastodon/features/hashtag_timeline/index.js
index b67486f07..63efdf1bd 100644
--- a/app/javascript/mastodon/features/hashtag_timeline/index.js
+++ b/app/javascript/mastodon/features/hashtag_timeline/index.js
@@ -13,8 +13,8 @@ const mapStateToProps = (state, props) => ({
   hasUnread: state.getIn(['timelines', `hashtag:${props.params.id}`, 'unread']) > 0,
 });
 
-@connect(mapStateToProps)
-export default class HashtagTimeline extends React.PureComponent {
+export default @connect(mapStateToProps)
+class HashtagTimeline extends React.PureComponent {
 
   static propTypes = {
     params: PropTypes.object.isRequired,
diff --git a/app/javascript/mastodon/features/home_timeline/components/column_settings.js b/app/javascript/mastodon/features/home_timeline/components/column_settings.js
index 932ac2049..455e21881 100644
--- a/app/javascript/mastodon/features/home_timeline/components/column_settings.js
+++ b/app/javascript/mastodon/features/home_timeline/components/column_settings.js
@@ -4,8 +4,8 @@ import ImmutablePropTypes from 'react-immutable-proptypes';
 import { injectIntl, FormattedMessage } from 'react-intl';
 import SettingToggle from '../../notifications/components/setting_toggle';
 
-@injectIntl
-export default class ColumnSettings extends React.PureComponent {
+export default @injectIntl
+class ColumnSettings extends React.PureComponent {
 
   static propTypes = {
     settings: ImmutablePropTypes.map.isRequired,
diff --git a/app/javascript/mastodon/features/home_timeline/index.js b/app/javascript/mastodon/features/home_timeline/index.js
index 12dab0e44..3ffa7a681 100644
--- a/app/javascript/mastodon/features/home_timeline/index.js
+++ b/app/javascript/mastodon/features/home_timeline/index.js
@@ -19,9 +19,9 @@ const mapStateToProps = state => ({
   isPartial: state.getIn(['timelines', 'home', 'items', 0], null) === null,
 });
 
-@connect(mapStateToProps)
+export default @connect(mapStateToProps)
 @injectIntl
-export default class HomeTimeline extends React.PureComponent {
+class HomeTimeline extends React.PureComponent {
 
   static propTypes = {
     dispatch: PropTypes.func.isRequired,
diff --git a/app/javascript/mastodon/features/keyboard_shortcuts/index.js b/app/javascript/mastodon/features/keyboard_shortcuts/index.js
index 2d86953c6..ab1ac511e 100644
--- a/app/javascript/mastodon/features/keyboard_shortcuts/index.js
+++ b/app/javascript/mastodon/features/keyboard_shortcuts/index.js
@@ -9,8 +9,8 @@ const messages = defineMessages({
   heading: { id: 'keyboard_shortcuts.heading', defaultMessage: 'Keyboard Shortcuts' },
 });
 
-@injectIntl
-export default class KeyboardShortcuts extends ImmutablePureComponent {
+export default @injectIntl
+class KeyboardShortcuts extends ImmutablePureComponent {
 
   static propTypes = {
     intl: PropTypes.object.isRequired,
diff --git a/app/javascript/mastodon/features/list_editor/components/account.js b/app/javascript/mastodon/features/list_editor/components/account.js
index c78c58e24..48085af43 100644
--- a/app/javascript/mastodon/features/list_editor/components/account.js
+++ b/app/javascript/mastodon/features/list_editor/components/account.js
@@ -31,9 +31,9 @@ const mapDispatchToProps = (dispatch, { accountId }) => ({
   onAdd: () => dispatch(addToListEditor(accountId)),
 });
 
-@connect(makeMapStateToProps, mapDispatchToProps)
+export default @connect(makeMapStateToProps, mapDispatchToProps)
 @injectIntl
-export default class Account extends ImmutablePureComponent {
+class Account extends ImmutablePureComponent {
 
   static propTypes = {
     account: ImmutablePropTypes.map.isRequired,
diff --git a/app/javascript/mastodon/features/list_editor/components/search.js b/app/javascript/mastodon/features/list_editor/components/search.js
index 45c4d0f2e..f7617fe58 100644
--- a/app/javascript/mastodon/features/list_editor/components/search.js
+++ b/app/javascript/mastodon/features/list_editor/components/search.js
@@ -19,9 +19,9 @@ const mapDispatchToProps = dispatch => ({
   onChange: value => dispatch(changeListSuggestions(value)),
 });
 
-@connect(mapStateToProps, mapDispatchToProps)
+export default @connect(mapStateToProps, mapDispatchToProps)
 @injectIntl
-export default class Search extends React.PureComponent {
+class Search extends React.PureComponent {
 
   static propTypes = {
     intl: PropTypes.object.isRequired,
diff --git a/app/javascript/mastodon/features/list_editor/index.js b/app/javascript/mastodon/features/list_editor/index.js
index 65f7420de..aab0cdd0c 100644
--- a/app/javascript/mastodon/features/list_editor/index.js
+++ b/app/javascript/mastodon/features/list_editor/index.js
@@ -22,9 +22,9 @@ const mapDispatchToProps = dispatch => ({
   onReset: () => dispatch(resetListEditor()),
 });
 
-@connect(mapStateToProps, mapDispatchToProps)
+export default @connect(mapStateToProps, mapDispatchToProps)
 @injectIntl
-export default class ListEditor extends ImmutablePureComponent {
+class ListEditor extends ImmutablePureComponent {
 
   static propTypes = {
     listId: PropTypes.string.isRequired,
diff --git a/app/javascript/mastodon/features/list_timeline/index.js b/app/javascript/mastodon/features/list_timeline/index.js
index a655451b1..5b047ace4 100644
--- a/app/javascript/mastodon/features/list_timeline/index.js
+++ b/app/javascript/mastodon/features/list_timeline/index.js
@@ -25,9 +25,9 @@ const mapStateToProps = (state, props) => ({
   hasUnread: state.getIn(['timelines', `list:${props.params.id}`, 'unread']) > 0,
 });
 
-@connect(mapStateToProps)
+export default @connect(mapStateToProps)
 @injectIntl
-export default class ListTimeline extends React.PureComponent {
+class ListTimeline extends React.PureComponent {
 
   static contextTypes = {
     router: PropTypes.object,
diff --git a/app/javascript/mastodon/features/lists/components/new_list_form.js b/app/javascript/mastodon/features/lists/components/new_list_form.js
index eed6efc25..739246640 100644
--- a/app/javascript/mastodon/features/lists/components/new_list_form.js
+++ b/app/javascript/mastodon/features/lists/components/new_list_form.js
@@ -20,9 +20,9 @@ const mapDispatchToProps = dispatch => ({
   onSubmit: () => dispatch(submitListEditor(true)),
 });
 
-@connect(mapStateToProps, mapDispatchToProps)
+export default @connect(mapStateToProps, mapDispatchToProps)
 @injectIntl
-export default class NewListForm extends React.PureComponent {
+class NewListForm extends React.PureComponent {
 
   static propTypes = {
     value: PropTypes.string.isRequired,
diff --git a/app/javascript/mastodon/features/lists/index.js b/app/javascript/mastodon/features/lists/index.js
index 127347730..24f40c16b 100644
--- a/app/javascript/mastodon/features/lists/index.js
+++ b/app/javascript/mastodon/features/lists/index.js
@@ -31,9 +31,9 @@ const mapStateToProps = state => ({
   lists: getOrderedLists(state),
 });
 
-@connect(mapStateToProps)
+export default @connect(mapStateToProps)
 @injectIntl
-export default class Lists extends ImmutablePureComponent {
+class Lists extends ImmutablePureComponent {
 
   static propTypes = {
     params: PropTypes.object.isRequired,
diff --git a/app/javascript/mastodon/features/mutes/index.js b/app/javascript/mastodon/features/mutes/index.js
index 7bf9c1464..f979ef72f 100644
--- a/app/javascript/mastodon/features/mutes/index.js
+++ b/app/javascript/mastodon/features/mutes/index.js
@@ -20,9 +20,9 @@ const mapStateToProps = state => ({
   accountIds: state.getIn(['user_lists', 'mutes', 'items']),
 });
 
-@connect(mapStateToProps)
+export default @connect(mapStateToProps)
 @injectIntl
-export default class Mutes extends ImmutablePureComponent {
+class Mutes extends ImmutablePureComponent {
 
   static propTypes = {
     params: PropTypes.object.isRequired,
diff --git a/app/javascript/mastodon/features/notifications/components/notification.js b/app/javascript/mastodon/features/notifications/components/notification.js
index 07fec84b2..ed4a44ca6 100644
--- a/app/javascript/mastodon/features/notifications/components/notification.js
+++ b/app/javascript/mastodon/features/notifications/components/notification.js
@@ -16,8 +16,8 @@ const notificationForScreenReader = (intl, message, timestamp) => {
   return output.join(', ');
 };
 
-@injectIntl
-export default class Notification extends ImmutablePureComponent {
+export default @injectIntl
+class Notification extends ImmutablePureComponent {
 
   static contextTypes = {
     router: PropTypes.object,
diff --git a/app/javascript/mastodon/features/notifications/index.js b/app/javascript/mastodon/features/notifications/index.js
index b7d7f361c..66af0baaf 100644
--- a/app/javascript/mastodon/features/notifications/index.js
+++ b/app/javascript/mastodon/features/notifications/index.js
@@ -31,9 +31,9 @@ const mapStateToProps = state => ({
   hasMore: state.getIn(['notifications', 'hasMore']),
 });
 
-@connect(mapStateToProps)
+export default @connect(mapStateToProps)
 @injectIntl
-export default class Notifications extends React.PureComponent {
+class Notifications extends React.PureComponent {
 
   static propTypes = {
     columnId: PropTypes.string,
diff --git a/app/javascript/mastodon/features/pinned_statuses/index.js b/app/javascript/mastodon/features/pinned_statuses/index.js
index c6eb689d2..98cdbda3c 100644
--- a/app/javascript/mastodon/features/pinned_statuses/index.js
+++ b/app/javascript/mastodon/features/pinned_statuses/index.js
@@ -18,9 +18,9 @@ const mapStateToProps = state => ({
   hasMore: !!state.getIn(['status_lists', 'pins', 'next']),
 });
 
-@connect(mapStateToProps)
+export default @connect(mapStateToProps)
 @injectIntl
-export default class PinnedStatuses extends ImmutablePureComponent {
+class PinnedStatuses extends ImmutablePureComponent {
 
   static propTypes = {
     dispatch: PropTypes.func.isRequired,
diff --git a/app/javascript/mastodon/features/public_timeline/index.js b/app/javascript/mastodon/features/public_timeline/index.js
index 6d5c4118d..46d972251 100644
--- a/app/javascript/mastodon/features/public_timeline/index.js
+++ b/app/javascript/mastodon/features/public_timeline/index.js
@@ -25,9 +25,9 @@ const mapStateToProps = (state, { onlyMedia, columnId }) => {
   };
 };
 
-@connect(mapStateToProps)
+export default @connect(mapStateToProps)
 @injectIntl
-export default class PublicTimeline extends React.PureComponent {
+class PublicTimeline extends React.PureComponent {
 
   static contextTypes = {
     router: PropTypes.object,
diff --git a/app/javascript/mastodon/features/reblogs/index.js b/app/javascript/mastodon/features/reblogs/index.js
index acb9b40f9..c05d21c74 100644
--- a/app/javascript/mastodon/features/reblogs/index.js
+++ b/app/javascript/mastodon/features/reblogs/index.js
@@ -15,8 +15,8 @@ const mapStateToProps = (state, props) => ({
   accountIds: state.getIn(['user_lists', 'reblogged_by', props.params.statusId]),
 });
 
-@connect(mapStateToProps)
-export default class Reblogs extends ImmutablePureComponent {
+export default @connect(mapStateToProps)
+class Reblogs extends ImmutablePureComponent {
 
   static propTypes = {
     params: PropTypes.object.isRequired,
diff --git a/app/javascript/mastodon/features/standalone/community_timeline/index.js b/app/javascript/mastodon/features/standalone/community_timeline/index.js
index c8ae9b304..f917f41c9 100644
--- a/app/javascript/mastodon/features/standalone/community_timeline/index.js
+++ b/app/javascript/mastodon/features/standalone/community_timeline/index.js
@@ -12,9 +12,9 @@ const messages = defineMessages({
   title: { id: 'standalone.public_title', defaultMessage: 'A look inside...' },
 });
 
-@connect()
+export default @connect()
 @injectIntl
-export default class CommunityTimeline extends React.PureComponent {
+class CommunityTimeline extends React.PureComponent {
 
   static propTypes = {
     dispatch: PropTypes.func.isRequired,
diff --git a/app/javascript/mastodon/features/standalone/hashtag_timeline/index.js b/app/javascript/mastodon/features/standalone/hashtag_timeline/index.js
index 931ca2a32..45c263257 100644
--- a/app/javascript/mastodon/features/standalone/hashtag_timeline/index.js
+++ b/app/javascript/mastodon/features/standalone/hashtag_timeline/index.js
@@ -7,8 +7,8 @@ import Column from '../../../components/column';
 import ColumnHeader from '../../../components/column_header';
 import { connectHashtagStream } from '../../../actions/streaming';
 
-@connect()
-export default class HashtagTimeline extends React.PureComponent {
+export default @connect()
+class HashtagTimeline extends React.PureComponent {
 
   static propTypes = {
     dispatch: PropTypes.func.isRequired,
diff --git a/app/javascript/mastodon/features/standalone/public_timeline/index.js b/app/javascript/mastodon/features/standalone/public_timeline/index.js
index 115c51d85..618696eb1 100644
--- a/app/javascript/mastodon/features/standalone/public_timeline/index.js
+++ b/app/javascript/mastodon/features/standalone/public_timeline/index.js
@@ -12,9 +12,9 @@ const messages = defineMessages({
   title: { id: 'standalone.public_title', defaultMessage: 'A look inside...' },
 });
 
-@connect()
+export default @connect()
 @injectIntl
-export default class PublicTimeline extends React.PureComponent {
+class PublicTimeline extends React.PureComponent {
 
   static propTypes = {
     dispatch: PropTypes.func.isRequired,
diff --git a/app/javascript/mastodon/features/status/components/action_bar.js b/app/javascript/mastodon/features/status/components/action_bar.js
index f5977c02c..fa6fd56e5 100644
--- a/app/javascript/mastodon/features/status/components/action_bar.js
+++ b/app/javascript/mastodon/features/status/components/action_bar.js
@@ -28,8 +28,8 @@ const messages = defineMessages({
   embed: { id: 'status.embed', defaultMessage: 'Embed' },
 });
 
-@injectIntl
-export default class ActionBar extends React.PureComponent {
+export default @injectIntl
+class ActionBar extends React.PureComponent {
 
   static contextTypes = {
     router: PropTypes.object,
diff --git a/app/javascript/mastodon/features/status/index.js b/app/javascript/mastodon/features/status/index.js
index 48931b2d6..7d1bc2ca4 100644
--- a/app/javascript/mastodon/features/status/index.js
+++ b/app/javascript/mastodon/features/status/index.js
@@ -104,9 +104,9 @@ const makeMapStateToProps = () => {
   return mapStateToProps;
 };
 
-@injectIntl
+export default @injectIntl
 @connect(makeMapStateToProps)
-export default class Status extends ImmutablePureComponent {
+class Status extends ImmutablePureComponent {
 
   static contextTypes = {
     router: PropTypes.object,
diff --git a/app/javascript/mastodon/features/ui/components/boost_modal.js b/app/javascript/mastodon/features/ui/components/boost_modal.js
index 1c90d10dd..b128e67d2 100644
--- a/app/javascript/mastodon/features/ui/components/boost_modal.js
+++ b/app/javascript/mastodon/features/ui/components/boost_modal.js
@@ -13,8 +13,8 @@ const messages = defineMessages({
   reblog: { id: 'status.reblog', defaultMessage: 'Boost' },
 });
 
-@injectIntl
-export default class BoostModal extends ImmutablePureComponent {
+export default @injectIntl
+class BoostModal extends ImmutablePureComponent {
 
   static contextTypes = {
     router: PropTypes.object,
diff --git a/app/javascript/mastodon/features/ui/components/columns_area.js b/app/javascript/mastodon/features/ui/components/columns_area.js
index a72ba06ab..ed338c2eb 100644
--- a/app/javascript/mastodon/features/ui/components/columns_area.js
+++ b/app/javascript/mastodon/features/ui/components/columns_area.js
@@ -35,8 +35,8 @@ const messages = defineMessages({
 
 const shouldHideFAB = path => path.match(/^\/statuses\//);
 
-@component => injectIntl(component, { withRef: true })
-export default class ColumnsArea extends ImmutablePureComponent {
+export default @(component => injectIntl(component, { withRef: true }))
+class ColumnsArea extends ImmutablePureComponent {
 
   static contextTypes = {
     router: PropTypes.object.isRequired,
diff --git a/app/javascript/mastodon/features/ui/components/confirmation_modal.js b/app/javascript/mastodon/features/ui/components/confirmation_modal.js
index 86588c46a..f0f3ad134 100644
--- a/app/javascript/mastodon/features/ui/components/confirmation_modal.js
+++ b/app/javascript/mastodon/features/ui/components/confirmation_modal.js
@@ -3,8 +3,8 @@ import PropTypes from 'prop-types';
 import { injectIntl, FormattedMessage } from 'react-intl';
 import Button from '../../../components/button';
 
-@injectIntl
-export default class ConfirmationModal extends React.PureComponent {
+export default @injectIntl
+class ConfirmationModal extends React.PureComponent {
 
   static propTypes = {
     message: PropTypes.node.isRequired,
diff --git a/app/javascript/mastodon/features/ui/components/embed_modal.js b/app/javascript/mastodon/features/ui/components/embed_modal.js
index 52aab00d0..2afb6f3d7 100644
--- a/app/javascript/mastodon/features/ui/components/embed_modal.js
+++ b/app/javascript/mastodon/features/ui/components/embed_modal.js
@@ -4,8 +4,8 @@ import ImmutablePureComponent from 'react-immutable-pure-component';
 import { FormattedMessage, injectIntl } from 'react-intl';
 import api from '../../../api';
 
-@injectIntl
-export default class EmbedModal extends ImmutablePureComponent {
+export default @injectIntl
+class EmbedModal extends ImmutablePureComponent {
 
   static propTypes = {
     url: PropTypes.string.isRequired,
diff --git a/app/javascript/mastodon/features/ui/components/focal_point_modal.js b/app/javascript/mastodon/features/ui/components/focal_point_modal.js
index 21bf6d81b..7488a3598 100644
--- a/app/javascript/mastodon/features/ui/components/focal_point_modal.js
+++ b/app/javascript/mastodon/features/ui/components/focal_point_modal.js
@@ -19,8 +19,8 @@ const mapDispatchToProps = (dispatch, { id }) => ({
 
 });
 
-@connect(mapStateToProps, mapDispatchToProps)
-export default class FocalPointModal extends ImmutablePureComponent {
+export default @connect(mapStateToProps, mapDispatchToProps)
+class FocalPointModal extends ImmutablePureComponent {
 
   static propTypes = {
     media: ImmutablePropTypes.map.isRequired,
diff --git a/app/javascript/mastodon/features/ui/components/media_modal.js b/app/javascript/mastodon/features/ui/components/media_modal.js
index 83b9e1b50..d29a4a6a7 100644
--- a/app/javascript/mastodon/features/ui/components/media_modal.js
+++ b/app/javascript/mastodon/features/ui/components/media_modal.js
@@ -18,8 +18,8 @@ const messages = defineMessages({
 
 export const previewState = 'previewMediaModal';
 
-@injectIntl
-export default class MediaModal extends ImmutablePureComponent {
+export default @injectIntl
+class MediaModal extends ImmutablePureComponent {
 
   static propTypes = {
     media: ImmutablePropTypes.list.isRequired,
@@ -149,7 +149,7 @@ export default class MediaModal extends ImmutablePureComponent {
             startTime={time || 0}
             onCloseVideo={onClose}
             detailed
-            description={image.get('description')}
+            alt={image.get('description')}
             key={image.get('url')}
           />
         );
diff --git a/app/javascript/mastodon/features/ui/components/mute_modal.js b/app/javascript/mastodon/features/ui/components/mute_modal.js
index 73e48cf09..ac356b42a 100644
--- a/app/javascript/mastodon/features/ui/components/mute_modal.js
+++ b/app/javascript/mastodon/features/ui/components/mute_modal.js
@@ -33,9 +33,9 @@ const mapDispatchToProps = dispatch => {
   };
 };
 
-@connect(mapStateToProps, mapDispatchToProps)
+export default @connect(mapStateToProps, mapDispatchToProps)
 @injectIntl
-export default class MuteModal extends React.PureComponent {
+class MuteModal extends React.PureComponent {
 
   static propTypes = {
     isSubmitting: PropTypes.bool.isRequired,
diff --git a/app/javascript/mastodon/features/ui/components/onboarding_modal.js b/app/javascript/mastodon/features/ui/components/onboarding_modal.js
index 9b713cf9e..25241bcd0 100644
--- a/app/javascript/mastodon/features/ui/components/onboarding_modal.js
+++ b/app/javascript/mastodon/features/ui/components/onboarding_modal.js
@@ -177,9 +177,9 @@ const mapStateToProps = state => ({
   domain: state.getIn(['meta', 'domain']),
 });
 
-@connect(mapStateToProps)
+export default @connect(mapStateToProps)
 @injectIntl
-export default class OnboardingModal extends React.PureComponent {
+class OnboardingModal extends React.PureComponent {
 
   static propTypes = {
     onClose: PropTypes.func.isRequired,
diff --git a/app/javascript/mastodon/features/ui/components/report_modal.js b/app/javascript/mastodon/features/ui/components/report_modal.js
index 90f001319..bc6b18664 100644
--- a/app/javascript/mastodon/features/ui/components/report_modal.js
+++ b/app/javascript/mastodon/features/ui/components/report_modal.js
@@ -37,9 +37,9 @@ const makeMapStateToProps = () => {
   return mapStateToProps;
 };
 
-@connect(makeMapStateToProps)
+export default @connect(makeMapStateToProps)
 @injectIntl
-export default class ReportModal extends ImmutablePureComponent {
+class ReportModal extends ImmutablePureComponent {
 
   static propTypes = {
     isSubmitting: PropTypes.bool,
@@ -106,6 +106,7 @@ export default class ReportModal extends ImmutablePureComponent {
               onChange={this.handleCommentChange}
               onKeyDown={this.handleKeyDown}
               disabled={isSubmitting}
+              autoFocus
             />
 
             {domain && (
diff --git a/app/javascript/mastodon/features/ui/components/tabs_bar.js b/app/javascript/mastodon/features/ui/components/tabs_bar.js
index 60bc56eef..16236ea51 100644
--- a/app/javascript/mastodon/features/ui/components/tabs_bar.js
+++ b/app/javascript/mastodon/features/ui/components/tabs_bar.js
@@ -24,9 +24,9 @@ export function getLink (index) {
   return links[index].props.to;
 }
 
-@injectIntl
+export default @injectIntl
 @withRouter
-export default class TabsBar extends React.PureComponent {
+class TabsBar extends React.PureComponent {
 
   static propTypes = {
     intl: PropTypes.object.isRequired,
diff --git a/app/javascript/mastodon/features/ui/components/video_modal.js b/app/javascript/mastodon/features/ui/components/video_modal.js
index 9ed4a43ad..7cf3eb4d4 100644
--- a/app/javascript/mastodon/features/ui/components/video_modal.js
+++ b/app/javascript/mastodon/features/ui/components/video_modal.js
@@ -24,7 +24,7 @@ export default class VideoModal extends ImmutablePureComponent {
             startTime={time}
             onCloseVideo={onClose}
             detailed
-            description={media.get('description')}
+            alt={media.get('description')}
           />
         </div>
       </div>
diff --git a/app/javascript/mastodon/features/ui/components/zoomable_image.js b/app/javascript/mastodon/features/ui/components/zoomable_image.js
index 0a0a4d41a..3f6562bc9 100644
--- a/app/javascript/mastodon/features/ui/components/zoomable_image.js
+++ b/app/javascript/mastodon/features/ui/components/zoomable_image.js
@@ -137,6 +137,7 @@ export default class ZoomableImage extends React.PureComponent {
           role='presentation'
           ref={this.setImageRef}
           alt={alt}
+          title={alt}
           src={src}
           style={{
             transform: `scale(${scale})`,
diff --git a/app/javascript/mastodon/features/ui/index.js b/app/javascript/mastodon/features/ui/index.js
index 91eb37900..2781c5d64 100644
--- a/app/javascript/mastodon/features/ui/index.js
+++ b/app/javascript/mastodon/features/ui/index.js
@@ -187,10 +187,10 @@ class SwitchingColumnsArea extends React.PureComponent {
 
 }
 
-@connect(mapStateToProps)
+export default @connect(mapStateToProps)
 @injectIntl
 @withRouter
-export default class UI extends React.PureComponent {
+class UI extends React.PureComponent {
 
   static contextTypes = {
     router: PropTypes.object.isRequired,
diff --git a/app/javascript/mastodon/features/ui/util/react_router_helpers.js b/app/javascript/mastodon/features/ui/util/react_router_helpers.js
index 32dfe320b..d452b871f 100644
--- a/app/javascript/mastodon/features/ui/util/react_router_helpers.js
+++ b/app/javascript/mastodon/features/ui/util/react_router_helpers.js
@@ -26,7 +26,7 @@ WrappedSwitch.propTypes = {
   children: PropTypes.node,
 };
 
-// Small Wraper to extract the params from the route and pass
+// Small Wrapper to extract the params from the route and pass
 // them to the rendered component, together with the content to
 // be rendered inside (the children)
 export class WrappedRoute extends React.Component {
diff --git a/app/javascript/mastodon/features/video/index.js b/app/javascript/mastodon/features/video/index.js
index 52b395f88..d17253957 100644
--- a/app/javascript/mastodon/features/video/index.js
+++ b/app/javascript/mastodon/features/video/index.js
@@ -84,8 +84,8 @@ export const getPointerPosition = (el, event) => {
   return position;
 };
 
-@injectIntl
-export default class Video extends React.PureComponent {
+export default @injectIntl
+class Video extends React.PureComponent {
 
   static propTypes = {
     preview: PropTypes.string,
@@ -252,11 +252,12 @@ export default class Video extends React.PureComponent {
   }
 
   handleOpenVideo = () => {
-    const { src, preview, width, height } = this.props;
+    const { src, preview, width, height, alt } = this.props;
     const media = fromJS({
       type: 'video',
       url: src,
       preview_url: preview,
+      description: alt,
       width,
       height,
     });
diff --git a/app/javascript/mastodon/locales/ar.json b/app/javascript/mastodon/locales/ar.json
index 677911e4e..56d78ae64 100644
--- a/app/javascript/mastodon/locales/ar.json
+++ b/app/javascript/mastodon/locales/ar.json
@@ -15,6 +15,7 @@
   "account.follows.empty": "هذا المستخدِم لا يتبع أحدًا بعد.",
   "account.follows_you": "يتابعك",
   "account.hide_reblogs": "إخفاء ترقيات @{name}",
+  "account.link_verified_on": "Ownership of this link was checked on {date}",
   "account.media": "وسائط",
   "account.mention": "أُذكُر @{name}",
   "account.moved_to": "{name} إنتقل إلى :",
diff --git a/app/javascript/mastodon/locales/ast.json b/app/javascript/mastodon/locales/ast.json
index da1ab62e6..e3cfabee3 100644
--- a/app/javascript/mastodon/locales/ast.json
+++ b/app/javascript/mastodon/locales/ast.json
@@ -1,174 +1,175 @@
 {
-  "account.badges.bot": "Bot",
-  "account.block": "Block @{name}",
+  "account.badges.bot": "Robó",
+  "account.block": "Bloquiar a @{name}",
   "account.block_domain": "Hide everything from {domain}",
   "account.blocked": "Blocked",
-  "account.direct": "Direct message @{name}",
+  "account.direct": "Unviar un mensaxe direutu a @{name}",
   "account.disclaimer_full": "Information below may reflect the user's profile incompletely.",
   "account.domain_blocked": "Domain hidden",
-  "account.edit_profile": "Edit profile",
+  "account.edit_profile": "Editar perfil",
   "account.endorse": "Feature on profile",
   "account.follow": "Follow",
-  "account.followers": "Followers",
+  "account.followers": "Siguidores",
   "account.followers.empty": "No one follows this user yet.",
   "account.follows": "Follows",
-  "account.follows.empty": "This user doesn't follow anyone yet.",
+  "account.follows.empty": "Esti usuariu entá nun sigue a naide.",
   "account.follows_you": "Follows you",
   "account.hide_reblogs": "Hide boosts from @{name}",
+  "account.link_verified_on": "Ownership of this link was checked on {date}",
   "account.media": "Media",
-  "account.mention": "Mention @{name}",
+  "account.mention": "Mentar a @{name}",
   "account.moved_to": "{name} has moved to:",
-  "account.mute": "Mute @{name}",
+  "account.mute": "Silenciar a @{name}",
   "account.mute_notifications": "Mute notifications from @{name}",
   "account.muted": "Muted",
   "account.posts": "Toots",
-  "account.posts_with_replies": "Toots and replies",
+  "account.posts_with_replies": "Toots y rempuestes",
   "account.report": "Report @{name}",
   "account.requested": "Awaiting approval. Click to cancel follow request",
   "account.share": "Share @{name}'s profile",
   "account.show_reblogs": "Show boosts from @{name}",
-  "account.unblock": "Unblock @{name}",
+  "account.unblock": "Desbloquiar a @{name}",
   "account.unblock_domain": "Unhide {domain}",
   "account.unendorse": "Don't feature on profile",
   "account.unfollow": "Unfollow",
   "account.unmute": "Unmute @{name}",
   "account.unmute_notifications": "Unmute notifications from @{name}",
   "account.view_full_profile": "View full profile",
-  "alert.unexpected.message": "An unexpected error occurred.",
-  "alert.unexpected.title": "Oops!",
-  "boost_modal.combo": "You can press {combo} to skip this next time",
+  "alert.unexpected.message": "Asocedió un fallu inesperáu.",
+  "alert.unexpected.title": "¡Ups!",
+  "boost_modal.combo": "Pues primir {combo} pa saltar esto la próxima vegada",
   "bundle_column_error.body": "Something went wrong while loading this component.",
   "bundle_column_error.retry": "Try again",
   "bundle_column_error.title": "Network error",
   "bundle_modal_error.close": "Close",
   "bundle_modal_error.message": "Something went wrong while loading this component.",
   "bundle_modal_error.retry": "Try again",
-  "column.blocks": "Blocked users",
+  "column.blocks": "Usuarios bloquiaos",
   "column.community": "Local timeline",
-  "column.direct": "Direct messages",
-  "column.domain_blocks": "Hidden domains",
-  "column.favourites": "Favourites",
-  "column.follow_requests": "Follow requests",
-  "column.home": "Home",
-  "column.lists": "Lists",
-  "column.mutes": "Muted users",
-  "column.notifications": "Notifications",
-  "column.pins": "Pinned toot",
-  "column.public": "Federated timeline",
-  "column_back_button.label": "Back",
+  "column.direct": "Mensaxes direutos",
+  "column.domain_blocks": "Dominios anubríos",
+  "column.favourites": "Favoritos",
+  "column.follow_requests": "Solicitúes de siguimientu",
+  "column.home": "Aniciu",
+  "column.lists": "Llistes",
+  "column.mutes": "Usuarios silenciaos",
+  "column.notifications": "Avisos",
+  "column.pins": "Toots fixaos",
+  "column.public": "Llinia temporal federada",
+  "column_back_button.label": "Atrás",
   "column_header.hide_settings": "Hide settings",
-  "column_header.moveLeft_settings": "Move column to the left",
-  "column_header.moveRight_settings": "Move column to the right",
+  "column_header.moveLeft_settings": "Mover la columna a la esquierda",
+  "column_header.moveRight_settings": "Mover la columna a la drecha",
   "column_header.pin": "Pin",
   "column_header.show_settings": "Show settings",
-  "column_header.unpin": "Unpin",
-  "column_subheading.settings": "Settings",
+  "column_header.unpin": "Desfixar",
+  "column_subheading.settings": "Axustes",
   "community.column_settings.media_only": "Media Only",
-  "compose_form.direct_message_warning": "This toot will only be sent to all the mentioned users.",
+  "compose_form.direct_message_warning": "Esti toot namái va unviase a los usuarios mentaos.",
   "compose_form.direct_message_warning_learn_more": "Learn more",
   "compose_form.hashtag_warning": "This toot won't be listed under any hashtag as it is unlisted. Only public toots can be searched by hashtag.",
   "compose_form.lock_disclaimer": "Your account is not {locked}. Anyone can follow you to view your follower-only posts.",
   "compose_form.lock_disclaimer.lock": "locked",
-  "compose_form.placeholder": "What is on your mind?",
+  "compose_form.placeholder": "¿En qué pienses?",
   "compose_form.publish": "Toot",
   "compose_form.publish_loud": "{publish}!",
   "compose_form.sensitive.marked": "Media is marked as sensitive",
   "compose_form.sensitive.unmarked": "Media is not marked as sensitive",
-  "compose_form.spoiler.marked": "Text is hidden behind warning",
-  "compose_form.spoiler.unmarked": "Text is not hidden",
-  "compose_form.spoiler_placeholder": "Write your warning here",
-  "confirmation_modal.cancel": "Cancel",
+  "compose_form.spoiler.marked": "El testu nun va anubrise darrera d'una alvertencia",
+  "compose_form.spoiler.unmarked": "El testu va anubrise",
+  "compose_form.spoiler_placeholder": "Escribi equí l'avertencia",
+  "confirmation_modal.cancel": "Encaboxar",
   "confirmations.block.confirm": "Block",
-  "confirmations.block.message": "Are you sure you want to block {name}?",
+  "confirmations.block.message": "¿De xuru que quies bloquiar a {name}?",
   "confirmations.delete.confirm": "Delete",
-  "confirmations.delete.message": "Are you sure you want to delete this status?",
+  "confirmations.delete.message": "¿De xuru que quies desaniciar esti estáu?",
   "confirmations.delete_list.confirm": "Delete",
-  "confirmations.delete_list.message": "Are you sure you want to permanently delete this list?",
+  "confirmations.delete_list.message": "¿De xuru que quies desaniciar dafechu esta llista?",
   "confirmations.domain_block.confirm": "Hide entire domain",
   "confirmations.domain_block.message": "Are you really, really sure you want to block the entire {domain}? In most cases a few targeted blocks or mutes are sufficient and preferable. You will not see content from that domain in any public timelines or your notifications. Your followers from that domain will be removed.",
   "confirmations.mute.confirm": "Mute",
-  "confirmations.mute.message": "Are you sure you want to mute {name}?",
+  "confirmations.mute.message": "¿De xuru que quies silenciar a {name}?",
   "confirmations.redraft.confirm": "Delete & redraft",
   "confirmations.redraft.message": "Are you sure you want to delete this status and re-draft it? You will lose all replies, boosts and favourites to it.",
   "confirmations.unfollow.confirm": "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.activity": "Actividá",
   "emoji_button.custom": "Custom",
-  "emoji_button.flags": "Flags",
-  "emoji_button.food": "Food & Drink",
+  "emoji_button.flags": "Banderes",
+  "emoji_button.food": "Comída y bébora",
   "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.nature": "Natura",
+  "emoji_button.not_found": "¡Nun hai fustaxes! (╯°□°)╯︵ ┻━┻",
+  "emoji_button.objects": "Oxetos",
+  "emoji_button.people": "Xente",
   "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.blocks": "You haven't blocked any users yet.",
+  "emoji_button.symbols": "Símbolos",
+  "emoji_button.travel": "Viaxes y llugares",
+  "empty_column.blocks": "Entá nun bloquiesti a dengún usuariu.",
   "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.domain_blocks": "There are no hidden domains yet.",
+  "empty_column.direct": "Entá nun tienes dengún mensaxe direutu. Cuando unvies o recibas dalgún, va apaecer equí",
+  "empty_column.domain_blocks": "Entá nun hai dominios anubríos.",
   "empty_column.favourited_statuses": "You don't have any favourite toots yet. When you favourite one, it will show up here.",
   "empty_column.favourites": "No one has favourited this toot yet. When someone does, they will show up here.",
-  "empty_column.follow_requests": "You don't have any follow requests yet. When you receive one, it will show up here.",
+  "empty_column.follow_requests": "Entá nun tienes denguna solicitú de siguimientu. Cuando recibas una, va amosase equí.",
   "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.home.public_timeline": "la llinia temporal pública",
   "empty_column.list": "There is nothing in this list yet. When members of this list post new statuses, they will appear here.",
-  "empty_column.lists": "You don't have any lists yet. When you create one, it will show up here.",
-  "empty_column.mutes": "You haven't muted any users yet.",
-  "empty_column.notifications": "You don't have any notifications yet. Interact with others to start the conversation.",
+  "empty_column.lists": "Entá nun tienes denguna llista. Cuando crees una, va amosase equí.",
+  "empty_column.mutes": "Enta nun silenciesti a dengún usuariu.",
+  "empty_column.notifications": "Entá nun tienes dengún avisu. Interactua con otros p'aniciar la conversación.",
   "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",
-  "getting_started.documentation": "Documentation",
-  "getting_started.find_friends": "Find friends from Twitter",
+  "follow_request.authorize": "Autorizar",
+  "follow_request.reject": "Refugar",
+  "getting_started.developers": "Desendolcadores",
+  "getting_started.documentation": "Documentación",
+  "getting_started.find_friends": "Alcontrar collacios de 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",
+  "getting_started.invite": "Convidar xente",
+  "getting_started.open_source_notice": "Mastodon ye software de códigu abiertu. Pues collaborar o informar de fallos en {github} (GitHub).",
+  "getting_started.security": "Seguranza",
+  "getting_started.terms": "Términos del serviciu",
   "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.blocked": "to open blocked users list",
+  "keyboard_shortcuts.back": "pa dir p'atrás",
+  "keyboard_shortcuts.blocked": "p'abrir la llista d'usuarios bloquiaos",
   "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.direct": "to open direct messages column",
-  "keyboard_shortcuts.down": "to move down in the list",
+  "keyboard_shortcuts.description": "Descripción",
+  "keyboard_shortcuts.direct": "p'abrir la columna de los mensaxes direutos",
+  "keyboard_shortcuts.down": "pa baxar na llista",
   "keyboard_shortcuts.enter": "to open status",
   "keyboard_shortcuts.favourite": "to favourite",
-  "keyboard_shortcuts.favourites": "to open favourites list",
-  "keyboard_shortcuts.federated": "to open federated timeline",
-  "keyboard_shortcuts.heading": "Keyboard Shortcuts",
-  "keyboard_shortcuts.home": "to open home timeline",
-  "keyboard_shortcuts.hotkey": "Hotkey",
-  "keyboard_shortcuts.legend": "to display this legend",
-  "keyboard_shortcuts.local": "to open local timeline",
-  "keyboard_shortcuts.mention": "to mention author",
-  "keyboard_shortcuts.muted": "to open muted users list",
+  "keyboard_shortcuts.favourites": "p'abrir la llista de favoritos",
+  "keyboard_shortcuts.federated": "p'abrir la llinia temporal federada",
+  "keyboard_shortcuts.heading": "Atayos del tecláu",
+  "keyboard_shortcuts.home": "p'abrir la llinia temporal d'aniciu",
+  "keyboard_shortcuts.hotkey": "Atayu",
+  "keyboard_shortcuts.legend": "p'amosar esta lleenda",
+  "keyboard_shortcuts.local": "p'abrir la llinia temporal llocal",
+  "keyboard_shortcuts.mention": "pa mentar al autor",
+  "keyboard_shortcuts.muted": "p'abrir la llista d'usuarios silenciaos",
   "keyboard_shortcuts.my_profile": "to open your profile",
-  "keyboard_shortcuts.notifications": "to open notifications column",
-  "keyboard_shortcuts.pinned": "to open pinned toots list",
-  "keyboard_shortcuts.profile": "to open author's profile",
-  "keyboard_shortcuts.reply": "to reply",
-  "keyboard_shortcuts.requests": "to open follow requests list",
+  "keyboard_shortcuts.notifications": "p'abrir la columna d'avisos",
+  "keyboard_shortcuts.pinned": "p'abrir la llista de toots fixaos",
+  "keyboard_shortcuts.profile": "p'abrir el perfil del autor",
+  "keyboard_shortcuts.reply": "pa responder",
+  "keyboard_shortcuts.requests": "p'abrir la llista de solicitúes de siguimientu",
   "keyboard_shortcuts.search": "to focus search",
-  "keyboard_shortcuts.start": "to open \"get started\" column",
+  "keyboard_shortcuts.start": "p'abrir la columna «entamar»",
   "keyboard_shortcuts.toggle_hidden": "to show/hide text behind CW",
-  "keyboard_shortcuts.toot": "to start a brand new toot",
+  "keyboard_shortcuts.toot": "p'apenzar un toot nuevu",
   "keyboard_shortcuts.unfocus": "to un-focus compose textarea/search",
-  "keyboard_shortcuts.up": "to move up in the list",
+  "keyboard_shortcuts.up": "pa xubir na llista",
   "lightbox.close": "Close",
-  "lightbox.next": "Next",
+  "lightbox.next": "Siguiente",
   "lightbox.previous": "Previous",
   "lists.account.add": "Add to list",
   "lists.account.remove": "Remove from list",
@@ -180,55 +181,55 @@
   "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",
+  "missing_indicator.label": "Nun s'alcontró",
+  "missing_indicator.sublabel": "Esti recursu nun pudo alcontrase",
   "mute_modal.hide_notifications": "Hide notifications from this user?",
-  "navigation_bar.apps": "Mobile apps",
-  "navigation_bar.blocks": "Blocked users",
+  "navigation_bar.apps": "Aplicaciones móviles",
+  "navigation_bar.blocks": "Usuarios bloquiaos",
   "navigation_bar.community_timeline": "Local timeline",
   "navigation_bar.compose": "Compose new toot",
-  "navigation_bar.direct": "Direct messages",
+  "navigation_bar.direct": "Mensaxes direutos",
   "navigation_bar.discover": "Discover",
-  "navigation_bar.domain_blocks": "Hidden domains",
-  "navigation_bar.edit_profile": "Edit profile",
-  "navigation_bar.favourites": "Favourites",
+  "navigation_bar.domain_blocks": "Dominios anubríos",
+  "navigation_bar.edit_profile": "Editar perfil",
+  "navigation_bar.favourites": "Favoritos",
   "navigation_bar.filters": "Muted words",
-  "navigation_bar.follow_requests": "Follow requests",
-  "navigation_bar.info": "About this instance",
-  "navigation_bar.keyboard_shortcuts": "Hotkeys",
+  "navigation_bar.follow_requests": "Solicitúes de siguimientu",
+  "navigation_bar.info": "Tocante a esta instancia",
+  "navigation_bar.keyboard_shortcuts": "Atayos",
   "navigation_bar.lists": "Lists",
-  "navigation_bar.logout": "Logout",
-  "navigation_bar.mutes": "Muted users",
+  "navigation_bar.logout": "Zarrar sesión",
+  "navigation_bar.mutes": "Usuarios silenciaos",
   "navigation_bar.personal": "Personal",
-  "navigation_bar.pins": "Pinned toots",
-  "navigation_bar.preferences": "Preferences",
-  "navigation_bar.public_timeline": "Federated timeline",
-  "navigation_bar.security": "Security",
+  "navigation_bar.pins": "Toots fixaos",
+  "navigation_bar.preferences": "Preferencies",
+  "navigation_bar.public_timeline": "Llinia temporal federada",
+  "navigation_bar.security": "Seguranza",
   "notification.favourite": "{name} favourited your status",
-  "notification.follow": "{name} followed you",
-  "notification.mention": "{name} mentioned you",
+  "notification.follow": "{name} siguióte",
+  "notification.mention": "{name} mentóte",
   "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.clear": "Llimpiar avisos",
+  "notifications.clear_confirmation": "¿De xuru que quies llimpiar dafechu tolos avisos?",
+  "notifications.column_settings.alert": "Avisos d'escritoriu",
   "notifications.column_settings.favourite": "Favourites:",
-  "notifications.column_settings.follow": "New followers:",
-  "notifications.column_settings.mention": "Mentions:",
+  "notifications.column_settings.follow": "Siguidores nuevos:",
+  "notifications.column_settings.mention": "Menciones:",
   "notifications.column_settings.push": "Push notifications",
-  "notifications.column_settings.push_meta": "This device",
+  "notifications.column_settings.push_meta": "Esti preséu",
   "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",
+  "notifications.column_settings.show": "Amosar en columna",
+  "notifications.column_settings.sound": "Reproducir soníu",
+  "notifications.group": "{count} avisos",
+  "onboarding.done": "Fecho",
+  "onboarding.next": "Siguiente",
   "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.home": "La llinia temporal d'aniciu amuesa artículos de xente a la que sigues.",
   "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.federation": "Mastodon ye una rede de sividores independientes xuníos pa facer una rede social grande. Nós llamamos instancies a esos sirvidores.",
   "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_one.welcome": "¡Afáyate en Mastodon!",
   "onboarding.page_six.admin": "Your instance's admin is {admin}.",
   "onboarding.page_six.almost_done": "Almost done...",
   "onboarding.page_six.appetoot": "Bon Appetoot!",
@@ -236,7 +237,7 @@
   "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_six.various_app": "aplicaciones móviles",
   "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.",
@@ -245,7 +246,7 @@
   "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.private.short": "Namái siguidores",
   "privacy.public.long": "Post to public timelines",
   "privacy.public.short": "Public",
   "privacy.unlisted.long": "Do not show in public timelines",
@@ -254,44 +255,44 @@
   "regeneration_indicator.sublabel": "Your home feed is being prepared!",
   "relative_time.days": "{number}d",
   "relative_time.hours": "{number}h",
-  "relative_time.just_now": "now",
+  "relative_time.just_now": "agora",
   "relative_time.minutes": "{number}m",
   "relative_time.seconds": "{number}s",
-  "reply_indicator.cancel": "Cancel",
+  "reply_indicator.cancel": "Encaboxar",
   "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.placeholder": "Comentarios adicionales",
   "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.",
-  "search_popout.tips.hashtag": "hashtag",
-  "search_popout.tips.status": "status",
+  "search_popout.tips.hashtag": "etiqueta",
+  "search_popout.tips.status": "estáu",
   "search_popout.tips.text": "Simple text returns matching display names, usernames and hashtags",
-  "search_popout.tips.user": "user",
-  "search_results.accounts": "People",
+  "search_popout.tips.user": "usuariu",
+  "search_results.accounts": "Xente",
   "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.block": "Bloquiar a @{name}",
   "status.cancel_reblog_private": "Unboost",
   "status.cannot_reblog": "This post cannot be boosted",
   "status.delete": "Delete",
   "status.detailed_status": "Detailed conversation view",
-  "status.direct": "Direct message @{name}",
-  "status.embed": "Embed",
+  "status.direct": "Unviar un mensaxe direutu a @{name}",
+  "status.embed": "Empotrar",
   "status.favourite": "Favourite",
   "status.filtered": "Filtered",
-  "status.load_more": "Load more",
+  "status.load_more": "Cargar más",
   "status.media_hidden": "Media hidden",
-  "status.mention": "Mention @{name}",
-  "status.more": "More",
-  "status.mute": "Mute @{name}",
+  "status.mention": "Mentar a @{name}",
+  "status.more": "Más",
+  "status.mute": "Silenciar a @{name}",
   "status.mute_conversation": "Mute conversation",
-  "status.open": "Expand this status",
+  "status.open": "Espander esti estáu",
   "status.pin": "Pin on profile",
   "status.pinned": "Pinned toot",
   "status.reblog": "Boost",
@@ -299,25 +300,25 @@
   "status.reblogged_by": "{name} boosted",
   "status.reblogs.empty": "No one has boosted this toot yet. When someone does, they will show up here.",
   "status.redraft": "Delete & re-draft",
-  "status.reply": "Reply",
+  "status.reply": "Responder",
   "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": "Amosar menos",
   "status.show_less_all": "Show less for all",
-  "status.show_more": "Show more",
+  "status.show_more": "Amosar más",
   "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.home": "Aniciu",
   "tabs_bar.local_timeline": "Local",
-  "tabs_bar.notifications": "Notifications",
+  "tabs_bar.notifications": "Avisos",
   "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.",
+  "ui.beforeunload": "El borrador va perdese si coles de Mastodon.",
   "upload_area.title": "Drag & drop to upload",
   "upload_button.label": "Add media",
   "upload_form.description": "Describe for the visually impaired",
diff --git a/app/javascript/mastodon/locales/bg.json b/app/javascript/mastodon/locales/bg.json
index 725bbed41..5730c1354 100644
--- a/app/javascript/mastodon/locales/bg.json
+++ b/app/javascript/mastodon/locales/bg.json
@@ -15,6 +15,7 @@
   "account.follows.empty": "This user doesn't follow anyone yet.",
   "account.follows_you": "Твой последовател",
   "account.hide_reblogs": "Hide boosts from @{name}",
+  "account.link_verified_on": "Ownership of this link was checked on {date}",
   "account.media": "Media",
   "account.mention": "Споменаване",
   "account.moved_to": "{name} has moved to:",
diff --git a/app/javascript/mastodon/locales/ca.json b/app/javascript/mastodon/locales/ca.json
index 3d8f7bae2..0364d0bba 100644
--- a/app/javascript/mastodon/locales/ca.json
+++ b/app/javascript/mastodon/locales/ca.json
@@ -15,6 +15,7 @@
   "account.follows.empty": "Aquest usuari encara no segueix a ningú.",
   "account.follows_you": "Et segueix",
   "account.hide_reblogs": "Amaga els impulsos de @{name}",
+  "account.link_verified_on": "Ownership of this link was checked on {date}",
   "account.media": "Media",
   "account.mention": "Esmentar @{name}",
   "account.moved_to": "{name} s'ha mogut a:",
diff --git a/app/javascript/mastodon/locales/co.json b/app/javascript/mastodon/locales/co.json
index d5aeab9f2..8bf083235 100644
--- a/app/javascript/mastodon/locales/co.json
+++ b/app/javascript/mastodon/locales/co.json
@@ -15,6 +15,7 @@
   "account.follows.empty": "St'utilizatore ùn seguita nisunu.",
   "account.follows_you": "Vi seguita",
   "account.hide_reblogs": "Piattà spartere da @{name}",
+  "account.link_verified_on": "Ownership of this link was checked on {date}",
   "account.media": "Media",
   "account.mention": "Mintuvà @{name}",
   "account.moved_to": "{name} hè partutu nant'à:",
diff --git a/app/javascript/mastodon/locales/cs.json b/app/javascript/mastodon/locales/cs.json
index c6c3095a7..46aa954e8 100644
--- a/app/javascript/mastodon/locales/cs.json
+++ b/app/javascript/mastodon/locales/cs.json
@@ -15,6 +15,7 @@
   "account.follows.empty": "Tento uživatel ještě nikoho nesleduje.",
   "account.follows_you": "Sleduje vás",
   "account.hide_reblogs": "Skrýt boosty od uživatele @{name}",
+  "account.link_verified_on": "Ownership of this link was checked on {date}",
   "account.media": "Média",
   "account.mention": "Zmínit uživatele @{name}",
   "account.moved_to": "{name} se přesunul/a na:",
diff --git a/app/javascript/mastodon/locales/cy.json b/app/javascript/mastodon/locales/cy.json
index 26af4d8f0..a2eea600a 100644
--- a/app/javascript/mastodon/locales/cy.json
+++ b/app/javascript/mastodon/locales/cy.json
@@ -1,121 +1,122 @@
 {
   "account.badges.bot": "Bot",
-  "account.block": "Block @{name}",
-  "account.block_domain": "Hide everything from {domain}",
-  "account.blocked": "Blocked",
-  "account.direct": "Direct message @{name}",
-  "account.disclaimer_full": "Information below may reflect the user's profile incompletely.",
+  "account.block": "Blociwch @{name}",
+  "account.block_domain": "Cuddiwch bopeth rhag {domain}",
+  "account.blocked": "Blociwyd",
+  "account.direct": "Neges breifat @{name}",
+  "account.disclaimer_full": "Gall y wybodaeth isod adlewyrchu darlun anghyflawn o broffil defnyddiwr.",
   "account.domain_blocked": "Domain hidden",
-  "account.edit_profile": "Edit profile",
+  "account.edit_profile": "Golygu proffil",
   "account.endorse": "Feature on profile",
-  "account.follow": "Follow",
-  "account.followers": "Followers",
-  "account.followers.empty": "No one follows this user yet.",
-  "account.follows": "Follows",
-  "account.follows.empty": "This user doesn't follow anyone yet.",
-  "account.follows_you": "Follows you",
+  "account.follow": "Dilyn",
+  "account.followers": "Dilynwyr",
+  "account.followers.empty": "Nid oes neb yn dilyn y defnyddiwr hwn eto.",
+  "account.follows": "Yn dilyn",
+  "account.follows.empty": "Nid yw'r defnyddiwr hwn yn dilyn unrhyw un eto.",
+  "account.follows_you": "Yn eich dilyn chi",
   "account.hide_reblogs": "Hide boosts from @{name}",
-  "account.media": "Media",
-  "account.mention": "Mention @{name}",
-  "account.moved_to": "{name} has moved to:",
+  "account.link_verified_on": "Ownership of this link was checked on {date}",
+  "account.media": "Cyfryngau",
+  "account.mention": "Crybwyll @{name}",
+  "account.moved_to": "Mae @{name} wedi symud i:",
   "account.mute": "Mute @{name}",
   "account.mute_notifications": "Mute notifications from @{name}",
-  "account.muted": "Muted",
-  "account.posts": "Toots",
+  "account.muted": "Distewyd",
+  "account.posts": "Tŵtiau",
   "account.posts_with_replies": "Toots and replies",
-  "account.report": "Report @{name}",
+  "account.report": "Adroddwch @{name}",
   "account.requested": "Awaiting approval. Click to cancel follow request",
-  "account.share": "Share @{name}'s profile",
+  "account.share": "Rhannwch broffil @{name}",
   "account.show_reblogs": "Show boosts from @{name}",
-  "account.unblock": "Unblock @{name}",
-  "account.unblock_domain": "Unhide {domain}",
+  "account.unblock": "Dadflociwch @{name}",
+  "account.unblock_domain": "Dadguddiwch {domain}",
   "account.unendorse": "Don't feature on profile",
-  "account.unfollow": "Unfollow",
+  "account.unfollow": "Daddilynwch",
   "account.unmute": "Unmute @{name}",
   "account.unmute_notifications": "Unmute notifications from @{name}",
   "account.view_full_profile": "View full profile",
-  "alert.unexpected.message": "An unexpected error occurred.",
-  "alert.unexpected.title": "Oops!",
+  "alert.unexpected.message": "Digwyddodd gwall annisgwyl.",
+  "alert.unexpected.title": "Wps!",
   "boost_modal.combo": "You can press {combo} to skip this next time",
-  "bundle_column_error.body": "Something went wrong while loading this component.",
-  "bundle_column_error.retry": "Try again",
-  "bundle_column_error.title": "Network error",
+  "bundle_column_error.body": "Aeth rhywbeth o'i le tra'n llwytho'r elfen hon.",
+  "bundle_column_error.retry": "Ceisiwch eto",
+  "bundle_column_error.title": "Gwall rhwydwaith",
   "bundle_modal_error.close": "Close",
-  "bundle_modal_error.message": "Something went wrong while loading this component.",
-  "bundle_modal_error.retry": "Try again",
-  "column.blocks": "Blocked users",
-  "column.community": "Local timeline",
-  "column.direct": "Direct messages",
-  "column.domain_blocks": "Hidden domains",
-  "column.favourites": "Favourites",
-  "column.follow_requests": "Follow requests",
+  "bundle_modal_error.message": "Aeth rhywbeth o'i le tra'n llwytho'r elfen hon.",
+  "bundle_modal_error.retry": "Ceiswich eto",
+  "column.blocks": "Defnyddwyr a flociwyd",
+  "column.community": "Llinell amser lleol",
+  "column.direct": "Negeseuon preifat",
+  "column.domain_blocks": "Parthau cuddiedig",
+  "column.favourites": "Ffefrynnau",
+  "column.follow_requests": "Ceisiadau dilyn",
   "column.home": "Hafan",
-  "column.lists": "Lists",
-  "column.mutes": "Muted users",
-  "column.notifications": "Notifications",
+  "column.lists": "Rhestrau",
+  "column.mutes": "Defnyddwyr a ddistewyd",
+  "column.notifications": "Hysbysiadau",
   "column.pins": "Pinned toot",
   "column.public": "Federated timeline",
   "column_back_button.label": "Nôl",
   "column_header.hide_settings": "Hide settings",
-  "column_header.moveLeft_settings": "Move column to the left",
-  "column_header.moveRight_settings": "Move column to the right",
-  "column_header.pin": "Pin",
-  "column_header.show_settings": "Show settings",
-  "column_header.unpin": "Unpin",
-  "column_subheading.settings": "Settings",
-  "community.column_settings.media_only": "Media Only",
-  "compose_form.direct_message_warning": "This toot will only be sent to all the mentioned users.",
-  "compose_form.direct_message_warning_learn_more": "Learn more",
-  "compose_form.hashtag_warning": "This toot won't be listed under any hashtag as it is unlisted. Only public toots can be searched by hashtag.",
-  "compose_form.lock_disclaimer": "Your account is not {locked}. Anyone can follow you to view your follower-only posts.",
-  "compose_form.lock_disclaimer.lock": "locked",
-  "compose_form.placeholder": "What is on your mind?",
-  "compose_form.publish": "Toot",
+  "column_header.moveLeft_settings": "Symudwch y golofn i'r chwith",
+  "column_header.moveRight_settings": "Symudwch y golofn i'r dde",
+  "column_header.pin": "Piniwch",
+  "column_header.show_settings": "Dangos gosodiadau",
+  "column_header.unpin": "Dadbiniwch",
+  "column_subheading.settings": "Gosodiadau",
+  "community.column_settings.media_only": "Cyfryngau yn unig",
+  "compose_form.direct_message_warning": "Mi fydd y tŵt hwn ond yn cael ei anfon at y defnyddwyr sy'n cael eu crybwyll.",
+  "compose_form.direct_message_warning_learn_more": "Dysgwch fwy",
+  "compose_form.hashtag_warning": "Ni fydd y tŵt hwn wedi ei restru o dan unrhyw hashnod gan ei fod heb ei restru. Dim ond tŵtiau cyhoeddus gellid chwilota amdanynt drwy hashnod.",
+  "compose_form.lock_disclaimer": "Nid yw eich cyfri wedi'i {locked}. Gall unrhyw un eich dilyn i weld eich POSTS dilynwyr-yn-unig.",
+  "compose_form.lock_disclaimer.lock": "wedi ei gloi",
+  "compose_form.placeholder": "Be syd ar eich meddwl?",
+  "compose_form.publish": "Tŵt",
   "compose_form.publish_loud": "{publish}!",
   "compose_form.sensitive.marked": "Media is marked as sensitive",
   "compose_form.sensitive.unmarked": "Media is not marked as sensitive",
-  "compose_form.spoiler.marked": "Text is hidden behind warning",
-  "compose_form.spoiler.unmarked": "Text is not hidden",
-  "compose_form.spoiler_placeholder": "Write your warning here",
+  "compose_form.spoiler.marked": "Testun wedi ei guddio gan rybudd",
+  "compose_form.spoiler.unmarked": "Nid yw'r testun wedi ei guddio",
+  "compose_form.spoiler_placeholder": "Ysgrifenwch eich rhybudd yma",
   "confirmation_modal.cancel": "Cancel",
-  "confirmations.block.confirm": "Block",
-  "confirmations.block.message": "Are you sure you want to block {name}?",
-  "confirmations.delete.confirm": "Delete",
-  "confirmations.delete.message": "Are you sure you want to delete this status?",
-  "confirmations.delete_list.confirm": "Delete",
-  "confirmations.delete_list.message": "Are you sure you want to permanently delete this list?",
+  "confirmations.block.confirm": "Blociwch",
+  "confirmations.block.message": "Ydych chi'n sicr eich bod eisiau blocio {name}?",
+  "confirmations.delete.confirm": "Dileu",
+  "confirmations.delete.message": "Ydych chi'n sicr eich bod eisiau dileu y statws hwn?",
+  "confirmations.delete_list.confirm": "Dileu",
+  "confirmations.delete_list.message": "Ydych chi'n sicr eich bod eisiau dileu y rhestr hwn am byth?",
   "confirmations.domain_block.confirm": "Hide entire domain",
   "confirmations.domain_block.message": "Are you really, really sure you want to block the entire {domain}? In most cases a few targeted blocks or mutes are sufficient and preferable. You will not see content from that domain in any public timelines or your notifications. Your followers from that domain will be removed.",
   "confirmations.mute.confirm": "Mute",
-  "confirmations.mute.message": "Are you sure you want to mute {name}?",
+  "confirmations.mute.message": "Ydych chi'n sicr eich bod am ddistewi {name}?",
   "confirmations.redraft.confirm": "Delete & redraft",
   "confirmations.redraft.message": "Are you sure you want to delete this status and re-draft it? Favourites and boosts will be lost, and replies to the original post will be orphaned.",
-  "confirmations.unfollow.confirm": "Unfollow",
-  "confirmations.unfollow.message": "Are you sure you want to unfollow {name}?",
+  "confirmations.unfollow.confirm": "Dad-ddilynwch",
+  "confirmations.unfollow.message": "Ydych chi'n sicr eich bod am ddad-ddilyn {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",
+  "embed.preview": "Dyma sut olwg fydd arno:",
+  "emoji_button.activity": "Gweithgarwch",
   "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.blocks": "You haven't blocked any users yet.",
+  "emoji_button.flags": "Baneri",
+  "emoji_button.food": "Bwyd a Diod",
+  "emoji_button.label": "Mewnosodwch emoji",
+  "emoji_button.nature": "Natur",
+  "emoji_button.not_found": "Dim emojos!! (╯°□°)╯︵ ┻━┻",
+  "emoji_button.objects": "Gwrthrychau",
+  "emoji_button.people": "Pobl",
+  "emoji_button.recent": "Defnyddir yn aml",
+  "emoji_button.search": "Chwilio...",
+  "emoji_button.search_results": "Canlyniadau chwilio",
+  "emoji_button.symbols": "Symbolau",
+  "emoji_button.travel": "Teithio & Llefydd",
+  "empty_column.blocks": "Nid ydych wedi blocio unrhyw ddefnyddwyr eto.",
   "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.domain_blocks": "There are no hidden domains yet.",
-  "empty_column.favourited_statuses": "You don't have any favourite toots yet. When you favourite one, it will show up here.",
-  "empty_column.favourites": "No one has favourited this toot yet. When someone does, they will show up here.",
+  "empty_column.direct": "Nid oes gennych unrhyw negeseuon preifat eto. Pan y byddwch yn anfon neu derbyn un, mi fydd yn ymddangos yma.",
+  "empty_column.domain_blocks": "Nid oes yna unrhyw barthau cuddiedig eto.",
+  "empty_column.favourited_statuses": "Nid oes gennych unrhyw hoff dwtiau eto. Pan y byddwch yn hoffi un, mi fydd yn ymddangos yma.",
+  "empty_column.favourites": "Nid oes neb wedi hoffi'r tŵt yma eto. Pan bydd rhywun yn ei hoffi, mi fyddent yn ymddangos yma.",
   "empty_column.follow_requests": "You don't have any follow requests yet. When you receive one, it will show up here.",
-  "empty_column.hashtag": "There is nothing in this hashtag yet.",
+  "empty_column.hashtag": "Nid oes dim ar yr hashnod hwn eto.",
   "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.",
@@ -123,120 +124,120 @@
   "empty_column.mutes": "You haven't muted any users yet.",
   "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",
-  "getting_started.documentation": "Documentation",
-  "getting_started.find_friends": "Find friends from Twitter",
-  "getting_started.heading": "Getting started",
-  "getting_started.invite": "Invite people",
+  "follow_request.authorize": "Caniatau",
+  "follow_request.reject": "Gwrthod",
+  "getting_started.developers": "Datblygwyr",
+  "getting_started.documentation": "Dogfennaeth",
+  "getting_started.find_friends": "Canfod ffrindiau o Twitter",
+  "getting_started.heading": "Dechrau",
+  "getting_started.invite": "Gwahoddwch bobl",
   "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.security": "Diogelwch",
   "getting_started.terms": "Terms of service",
-  "home.column_settings.basic": "Basic",
+  "home.column_settings.basic": "Syml",
   "home.column_settings.show_reblogs": "Show boosts",
-  "home.column_settings.show_replies": "Show replies",
+  "home.column_settings.show_replies": "Dangoswch ymatebion",
   "keyboard_shortcuts.back": "to navigate back",
   "keyboard_shortcuts.blocked": "to open blocked users list",
   "keyboard_shortcuts.boost": "to boost",
   "keyboard_shortcuts.column": "to focus a status in one of the columns",
   "keyboard_shortcuts.compose": "to focus the compose textarea",
-  "keyboard_shortcuts.description": "Description",
-  "keyboard_shortcuts.direct": "to open direct messages column",
-  "keyboard_shortcuts.down": "to move down in the list",
-  "keyboard_shortcuts.enter": "to open status",
-  "keyboard_shortcuts.favourite": "to favourite",
-  "keyboard_shortcuts.favourites": "to open favourites list",
+  "keyboard_shortcuts.description": "Disgrifiad",
+  "keyboard_shortcuts.direct": "i agor colofn negeseuon preifat",
+  "keyboard_shortcuts.down": "i symud lawr yn y rhestr",
+  "keyboard_shortcuts.enter": "i agor statws",
+  "keyboard_shortcuts.favourite": "i hoffi",
+  "keyboard_shortcuts.favourites": "i agor rhestr hoffi",
   "keyboard_shortcuts.federated": "to open federated timeline",
   "keyboard_shortcuts.heading": "Keyboard Shortcuts",
   "keyboard_shortcuts.home": "to open home timeline",
   "keyboard_shortcuts.hotkey": "Hotkey",
   "keyboard_shortcuts.legend": "to display this legend",
   "keyboard_shortcuts.local": "to open local timeline",
-  "keyboard_shortcuts.mention": "to mention author",
+  "keyboard_shortcuts.mention": "i grybwyll yr awdur",
   "keyboard_shortcuts.muted": "to open muted users list",
-  "keyboard_shortcuts.my_profile": "to open your profile",
-  "keyboard_shortcuts.notifications": "to open notifications column",
+  "keyboard_shortcuts.my_profile": "i agor eich proffil",
+  "keyboard_shortcuts.notifications": "i agor colofn hysbysiadau",
   "keyboard_shortcuts.pinned": "to open pinned toots list",
-  "keyboard_shortcuts.profile": "to open author's profile",
-  "keyboard_shortcuts.reply": "to reply",
+  "keyboard_shortcuts.profile": "i agor proffil yr awdur",
+  "keyboard_shortcuts.reply": "i ateb",
   "keyboard_shortcuts.requests": "to open follow requests list",
   "keyboard_shortcuts.search": "to focus search",
   "keyboard_shortcuts.start": "to open \"get started\" column",
   "keyboard_shortcuts.toggle_hidden": "to show/hide text behind CW",
-  "keyboard_shortcuts.toot": "to start a brand new toot",
+  "keyboard_shortcuts.toot": "i ddechrau tŵt newydd sbon",
   "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.close": "Cau",
+  "lightbox.next": "Nesaf",
   "lightbox.previous": "Previous",
-  "lists.account.add": "Add to list",
+  "lists.account.add": "Ychwanegwch at restr",
   "lists.account.remove": "Remove from list",
-  "lists.delete": "Delete list",
-  "lists.edit": "Edit list",
-  "lists.new.create": "Add list",
+  "lists.delete": "Dileu rhestr",
+  "lists.edit": "Golygwch restr",
+  "lists.new.create": "Ychwanegwch restr",
   "lists.new.title_placeholder": "New list title",
   "lists.search": "Search among people you follow",
-  "lists.subheading": "Your lists",
-  "loading_indicator.label": "Loading...",
+  "lists.subheading": "Eich rhestrau",
+  "loading_indicator.label": "Llwytho...",
   "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.apps": "Mobile apps",
-  "navigation_bar.blocks": "Blocked users",
+  "missing_indicator.label": "Heb ei ganfod",
+  "missing_indicator.sublabel": "Ni ellid canfod yr adnodd hwn",
+  "mute_modal.hide_notifications": "Cuddiwch hysbysiadau rhag y defnyddiwr hwn?",
+  "navigation_bar.apps": "Apiau symudol",
+  "navigation_bar.blocks": "Defnyddwyr wedi eu blocio",
   "navigation_bar.community_timeline": "Local timeline",
-  "navigation_bar.compose": "Compose new toot",
-  "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.compose": "Cyfansoddwch dŵt newydd",
+  "navigation_bar.direct": "Negeseuon preifat",
+  "navigation_bar.discover": "Darganfyddwch",
+  "navigation_bar.domain_blocks": "Parthau cuddiedig",
+  "navigation_bar.edit_profile": "Golygu proffil",
+  "navigation_bar.favourites": "Ffefrynnau",
   "navigation_bar.filters": "Muted words",
-  "navigation_bar.follow_requests": "Follow requests",
+  "navigation_bar.follow_requests": "Ceisiadau dilyn",
   "navigation_bar.info": "About this instance",
   "navigation_bar.keyboard_shortcuts": "Hotkeys",
-  "navigation_bar.lists": "Lists",
-  "navigation_bar.logout": "Logout",
+  "navigation_bar.lists": "Rhestrau",
+  "navigation_bar.logout": "Allgofnodi",
   "navigation_bar.mutes": "Muted users",
-  "navigation_bar.personal": "Personal",
-  "navigation_bar.pins": "Pinned toots",
-  "navigation_bar.preferences": "Preferences",
+  "navigation_bar.personal": "Personol",
+  "navigation_bar.pins": "Tŵtiau wedi eu pinio",
+  "navigation_bar.preferences": "Dewisiadau",
   "navigation_bar.public_timeline": "Federated timeline",
-  "navigation_bar.security": "Security",
-  "notification.favourite": "{name} favourited your status",
-  "notification.follow": "{name} followed you",
+  "navigation_bar.security": "Diogelwch",
+  "notification.favourite": "hoffodd {name} eich statws",
+  "notification.follow": "dilynodd {name} chi",
   "notification.mention": "{name} mentioned you",
   "notification.reblog": "{name} boosted your status",
-  "notifications.clear": "Clear notifications",
+  "notifications.clear": "Clirio hysbysiadau",
   "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.favourite": "Ffefrynnau:",
+  "notifications.column_settings.follow": "Dilynwyr newydd:",
   "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",
+  "notifications.column_settings.sound": "Chwarae sain",
+  "notifications.group": "{count} o hysbysiadau",
   "onboarding.done": "Done",
-  "onboarding.next": "Next",
+  "onboarding.next": "Nesaf",
   "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_one.welcome": "Croeso i 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.appetoot": "Bon Apetŵt!",
   "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.guidelines": "canllawiau cymunedol",
   "onboarding.page_six.read_guidelines": "Please read {domain}'s {guidelines}!",
-  "onboarding.page_six.various_app": "mobile apps",
+  "onboarding.page_six.various_app": "apiau symudol",
   "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.",
@@ -245,50 +246,50 @@
   "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.private.short": "Dilynwyr-yn-unig",
   "privacy.public.long": "Post to public timelines",
-  "privacy.public.short": "Public",
+  "privacy.public.short": "Cyhoeddus",
   "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": "Heb ei restru",
+  "regeneration_indicator.label": "Llwytho…",
+  "regeneration_indicator.sublabel": "Mae eich ffrwd cartref yn cael ei baratoi!",
   "relative_time.days": "{number}d",
   "relative_time.hours": "{number}h",
-  "relative_time.just_now": "now",
+  "relative_time.just_now": "nawr",
   "relative_time.minutes": "{number}m",
   "relative_time.seconds": "{number}s",
-  "reply_indicator.cancel": "Cancel",
+  "reply_indicator.cancel": "Canslo",
   "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.placeholder": "Sylwadau ychwanegol",
   "report.submit": "Submit",
   "report.target": "Report {target}",
-  "search.placeholder": "Search",
+  "search.placeholder": "Chwilio",
   "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.",
-  "search_popout.tips.hashtag": "hashtag",
-  "search_popout.tips.status": "status",
+  "search_popout.tips.hashtag": "hashnod",
+  "search_popout.tips.status": "statws",
   "search_popout.tips.text": "Simple text returns matching display names, usernames and hashtags",
-  "search_popout.tips.user": "user",
-  "search_results.accounts": "People",
-  "search_results.hashtags": "Hashtags",
-  "search_results.statuses": "Toots",
+  "search_popout.tips.user": "defnyddiwr",
+  "search_results.accounts": "Pobl",
+  "search_results.hashtags": "Hanshnodau",
+  "search_results.statuses": "Twtiau",
   "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",
-  "status.delete": "Delete",
+  "status.delete": "Dileu",
   "status.detailed_status": "Detailed conversation view",
-  "status.direct": "Direct message @{name}",
-  "status.embed": "Embed",
+  "status.direct": "Neges breifat @{name}",
+  "status.embed": "Plannu",
   "status.favourite": "Favourite",
   "status.filtered": "Filtered",
-  "status.load_more": "Load more",
+  "status.load_more": "Llwythwch mwy",
   "status.media_hidden": "Media hidden",
   "status.mention": "Mention @{name}",
-  "status.more": "More",
+  "status.more": "Mwy",
   "status.mute": "Mute @{name}",
   "status.mute_conversation": "Mute conversation",
   "status.open": "Expand this status",
@@ -299,23 +300,23 @@
   "status.reblogged_by": "{name} boosted",
   "status.reblogs.empty": "No one has boosted this toot yet. When someone does, they will show up here.",
   "status.redraft": "Delete & re-draft",
-  "status.reply": "Reply",
-  "status.replyAll": "Reply to thread",
+  "status.reply": "Ateb",
+  "status.replyAll": "Ateb i edefyn",
   "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.sensitive_warning": "Cynnwys sensitif",
+  "status.share": "Rhannwch",
+  "status.show_less": "Dangoswch lai",
+  "status.show_less_all": "Dangoswch lai i bawb",
+  "status.show_more": "Dangoswch fwy",
   "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",
+  "tabs_bar.home": "Hafan",
+  "tabs_bar.local_timeline": "Lleol",
+  "tabs_bar.notifications": "Hysbysiadau",
+  "tabs_bar.search": "Chwilio",
   "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",
@@ -323,7 +324,7 @@
   "upload_form.description": "Describe for the visually impaired",
   "upload_form.focus": "Crop",
   "upload_form.undo": "Delete",
-  "upload_progress.label": "Uploading...",
+  "upload_progress.label": "Uwchlwytho...",
   "video.close": "Close video",
   "video.exit_fullscreen": "Exit full screen",
   "video.expand": "Expand video",
@@ -331,6 +332,6 @@
   "video.hide": "Hide video",
   "video.mute": "Mute sound",
   "video.pause": "Pause",
-  "video.play": "Play",
+  "video.play": "Chwarae",
   "video.unmute": "Unmute sound"
 }
diff --git a/app/javascript/mastodon/locales/da.json b/app/javascript/mastodon/locales/da.json
index f5ce7d0b9..959a50377 100644
--- a/app/javascript/mastodon/locales/da.json
+++ b/app/javascript/mastodon/locales/da.json
@@ -15,6 +15,7 @@
   "account.follows.empty": "Denne bruger følger endnu ikke nogen.",
   "account.follows_you": "Følger dig",
   "account.hide_reblogs": "Skjul fremhævelserne fra @{name}",
+  "account.link_verified_on": "Ownership of this link was checked on {date}",
   "account.media": "Medie",
   "account.mention": "Nævn @{name}",
   "account.moved_to": "{name} er flyttet til:",
@@ -200,7 +201,7 @@
   "navigation_bar.logout": "Logud",
   "navigation_bar.mutes": "Dæmpede brugere",
   "navigation_bar.personal": "Personligt",
-  "navigation_bar.pins": "Fastgjorte toots",
+  "navigation_bar.pins": "Fastgjorte trut",
   "navigation_bar.preferences": "Præferencer",
   "navigation_bar.public_timeline": "Fælles tidslinje",
   "navigation_bar.security": "Sikkerhed",
@@ -273,7 +274,7 @@
   "search_popout.tips.user": "bruger",
   "search_results.accounts": "Folk",
   "search_results.hashtags": "Emnetags",
-  "search_results.statuses": "Toote",
+  "search_results.statuses": "Trut",
   "search_results.total": "{count, number} {count, plural, et {result} andre {results}}",
   "standalone.public_title": "Et kig indenfor...",
   "status.block": "Bloker @{name}",
diff --git a/app/javascript/mastodon/locales/de.json b/app/javascript/mastodon/locales/de.json
index 0bfdfc46a..4f1b2c8a0 100644
--- a/app/javascript/mastodon/locales/de.json
+++ b/app/javascript/mastodon/locales/de.json
@@ -15,6 +15,7 @@
   "account.follows.empty": "Dieses Profil folgt noch niemandem.",
   "account.follows_you": "Folgt dir",
   "account.hide_reblogs": "Geteilte Beiträge von @{name} verbergen",
+  "account.link_verified_on": "Ownership of this link was checked on {date}",
   "account.media": "Medien",
   "account.mention": "@{name} erwähnen",
   "account.moved_to": "{name} ist umgezogen auf:",
@@ -113,7 +114,7 @@
   "empty_column.direct": "Du hast noch keine Direktnachrichten erhalten. Wenn du eine sendest oder empfängst, wird sie hier zu sehen sein.",
   "empty_column.domain_blocks": "Es ist noch keine versteckten Domains.",
   "empty_column.favourited_statuses": "Du hast noch keine favorisierten Tröts. Wenn du einen favorisierst, wird er hier erscheinen.",
-  "empty_column.favourites": "Noch niemand hat diesen Tröt favorisiert. Sobald es jemand tut, wird das hier angezeigt.",
+  "empty_column.favourites": "Noch niemand hat diesen Beitrag favorisiert. Sobald es jemand tut, wird das hier angezeigt.",
   "empty_column.follow_requests": "Du hast noch keine Folge-Anfragen. Sobald du eine erhältst, wird sie hier angezeigt.",
   "empty_column.hashtag": "Unter diesem Hashtag gibt es noch nichts.",
   "empty_column.home": "Deine Startseite ist leer! Besuche {public} oder nutze die Suche, um loszulegen und andere Leute zu finden.",
@@ -140,32 +141,32 @@
   "keyboard_shortcuts.blocked": "Liste blockierter Profile öffnen",
   "keyboard_shortcuts.boost": "boosten",
   "keyboard_shortcuts.column": "einen Status in einer der Spalten fokussieren",
-  "keyboard_shortcuts.compose": "um das Textfeld zu fokussieren",
+  "keyboard_shortcuts.compose": "fokussiere das Tröt-Eingabefeld",
   "keyboard_shortcuts.description": "Beschreibung",
   "keyboard_shortcuts.direct": "Direct-Message-Spalte öffnen",
   "keyboard_shortcuts.down": "sich in der Liste hinunter bewegen",
-  "keyboard_shortcuts.enter": "um den Status zu öffnen",
+  "keyboard_shortcuts.enter": "Status öffnen",
   "keyboard_shortcuts.favourite": "um zu favorisieren",
   "keyboard_shortcuts.favourites": "Favoriten-Liste öffnen",
   "keyboard_shortcuts.federated": "Förderierte Zeitleiste öffnen",
   "keyboard_shortcuts.heading": "Tastenkombinationen",
   "keyboard_shortcuts.home": "Startseite öffnen",
   "keyboard_shortcuts.hotkey": "Tastenkürzel",
-  "keyboard_shortcuts.legend": "um diese Übersicht anzuzeigen",
+  "keyboard_shortcuts.legend": "diese Übersicht anzeigen",
   "keyboard_shortcuts.local": "Lokale Zeitleiste öffnen",
   "keyboard_shortcuts.mention": "um Autor_in zu erwähnen",
   "keyboard_shortcuts.muted": "Liste stummgeschalteter Profile öffnen",
   "keyboard_shortcuts.my_profile": "Dein Profil öffnen",
   "keyboard_shortcuts.notifications": "Benachrichtigungsspalte öffnen",
   "keyboard_shortcuts.pinned": "Liste angehefteter Tröts öffnen",
-  "keyboard_shortcuts.profile": "um Profil des Autors zu öffnen",
-  "keyboard_shortcuts.reply": "um zu antworten",
+  "keyboard_shortcuts.profile": "Profil des Autors öffnen",
+  "keyboard_shortcuts.reply": "antworten",
   "keyboard_shortcuts.requests": "Liste der Folge-Anfragen  öffnen",
-  "keyboard_shortcuts.search": "um die Suche zu fokussieren",
+  "keyboard_shortcuts.search": "Suche fokussieren",
   "keyboard_shortcuts.start": "\"Erste Schritte-Spalte öffnen",
-  "keyboard_shortcuts.toggle_hidden": "um den Text hinter einer Inhaltswarnung zu verstecken oder ihn anzuzeigen",
-  "keyboard_shortcuts.toot": "um einen neuen Toot zu beginnen",
-  "keyboard_shortcuts.unfocus": "um das Textfeld/die Suche nicht mehr zu fokussieren",
+  "keyboard_shortcuts.toggle_hidden": "Text hinter einer Inhaltswarnung verstecken/anzeigen",
+  "keyboard_shortcuts.toot": "einen neuen Toot beginnen",
+  "keyboard_shortcuts.unfocus": "Textfeld/die Suche nicht mehr fokussieren",
   "keyboard_shortcuts.up": "sich in der Liste hinauf bewegen",
   "lightbox.close": "Schließen",
   "lightbox.next": "Weiter",
@@ -186,7 +187,7 @@
   "navigation_bar.apps": "Mobile Apps",
   "navigation_bar.blocks": "Blockierte Profile",
   "navigation_bar.community_timeline": "Lokale Zeitleiste",
-  "navigation_bar.compose": "Neuen Tröt verfassen",
+  "navigation_bar.compose": "Neuen Beitrag verfassen",
   "navigation_bar.direct": "Direktnachrichten",
   "navigation_bar.discover": "Entdecken",
   "navigation_bar.domain_blocks": "Versteckte Domains",
@@ -297,7 +298,7 @@
   "status.reblog": "Teilen",
   "status.reblog_private": "An das eigentliche Publikum teilen",
   "status.reblogged_by": "{name} teilte",
-  "status.reblogs.empty": "Diesen Tröt hat noch niemand geboostet. Sobald es jemand tut, wird er hier angezeigt.",
+  "status.reblogs.empty": "Diesen Beitrag hat noch niemand geboostet. Sobald es jemand tun, wird er hier angezeigt.",
   "status.redraft": "Löschen und neu erstellen",
   "status.reply": "Antworten",
   "status.replyAll": "Auf Thread antworten",
diff --git a/app/javascript/mastodon/locales/defaultMessages.json b/app/javascript/mastodon/locales/defaultMessages.json
index aef1f5ea1..5215bfb4e 100644
--- a/app/javascript/mastodon/locales/defaultMessages.json
+++ b/app/javascript/mastodon/locales/defaultMessages.json
@@ -611,6 +611,10 @@
         "id": "account.edit_profile"
       },
       {
+        "defaultMessage": "Ownership of this link was checked on {date}",
+        "id": "account.link_verified_on"
+      },
+      {
         "defaultMessage": "Follows you",
         "id": "account.follows_you"
       },
@@ -1837,6 +1841,15 @@
   {
     "descriptors": [
       {
+        "defaultMessage": "Toot",
+        "id": "compose_form.publish"
+      }
+    ],
+    "path": "app/javascript/mastodon/features/ui/components/columns_area.json"
+  },
+  {
+    "descriptors": [
+      {
         "defaultMessage": "Cancel",
         "id": "confirmation_modal.cancel"
       }
diff --git a/app/javascript/mastodon/locales/el.json b/app/javascript/mastodon/locales/el.json
index ad7f040d6..9c2a31722 100644
--- a/app/javascript/mastodon/locales/el.json
+++ b/app/javascript/mastodon/locales/el.json
@@ -15,6 +15,7 @@
   "account.follows.empty": "This user doesn't follow anyone yet.",
   "account.follows_you": "Σε ακολουθεί",
   "account.hide_reblogs": "Απόκρυψη προωθήσεων από @{name}",
+  "account.link_verified_on": "Ownership of this link was checked on {date}",
   "account.media": "Πολυμέσα",
   "account.mention": "Ανάφερε @{name}",
   "account.moved_to": "{name} μεταφέρθηκε στο:",
diff --git a/app/javascript/mastodon/locales/en.json b/app/javascript/mastodon/locales/en.json
index def1e0a56..b117dad95 100644
--- a/app/javascript/mastodon/locales/en.json
+++ b/app/javascript/mastodon/locales/en.json
@@ -15,6 +15,7 @@
   "account.follows.empty": "This user doesn't follow anyone yet.",
   "account.follows_you": "Follows you",
   "account.hide_reblogs": "Hide boosts from @{name}",
+  "account.link_verified_on": "Ownership of this link was checked on {date}",
   "account.media": "Media",
   "account.mention": "Mention @{name}",
   "account.moved_to": "{name} has moved to:",
diff --git a/app/javascript/mastodon/locales/eo.json b/app/javascript/mastodon/locales/eo.json
index ab584840e..dcc565eb9 100644
--- a/app/javascript/mastodon/locales/eo.json
+++ b/app/javascript/mastodon/locales/eo.json
@@ -15,6 +15,7 @@
   "account.follows.empty": "This user doesn't follow anyone yet.",
   "account.follows_you": "Sekvas vin",
   "account.hide_reblogs": "Kaŝi diskonigojn de @{name}",
+  "account.link_verified_on": "Ownership of this link was checked on {date}",
   "account.media": "Aŭdovidaĵoj",
   "account.mention": "Mencii @{name}",
   "account.moved_to": "{name} moviĝis al:",
diff --git a/app/javascript/mastodon/locales/es.json b/app/javascript/mastodon/locales/es.json
index 07e110048..355c901fa 100644
--- a/app/javascript/mastodon/locales/es.json
+++ b/app/javascript/mastodon/locales/es.json
@@ -7,14 +7,15 @@
   "account.disclaimer_full": "La siguiente información del usuario puede estar incompleta.",
   "account.domain_blocked": "Dominio oculto",
   "account.edit_profile": "Editar perfil",
-  "account.endorse": "Feature on profile",
+  "account.endorse": "Mostrar en perfil",
   "account.follow": "Seguir",
   "account.followers": "Seguidores",
-  "account.followers.empty": "No one follows this user yet.",
+  "account.followers.empty": "Nadie sigue a este usuario todavía.",
   "account.follows": "Sigue",
-  "account.follows.empty": "This user doesn't follow anyone yet.",
+  "account.follows.empty": "Este usuario todavía no sigue a nadie.",
   "account.follows_you": "Te sigue",
   "account.hide_reblogs": "Ocultar retoots de @{name}",
+  "account.link_verified_on": "Ownership of this link was checked on {date}",
   "account.media": "Media",
   "account.mention": "Mencionar a @{name}",
   "account.moved_to": "{name} se ha mudado a:",
@@ -29,12 +30,12 @@
   "account.show_reblogs": "Mostrar retoots de @{name}",
   "account.unblock": "Desbloquear a @{name}",
   "account.unblock_domain": "Mostrar a {domain}",
-  "account.unendorse": "Don't feature on profile",
+  "account.unendorse": "No mostrar en el perfil",
   "account.unfollow": "Dejar de seguir",
   "account.unmute": "Dejar de silenciar a @{name}",
   "account.unmute_notifications": "Dejar de silenciar las notificaciones de @{name}",
   "account.view_full_profile": "Ver perfil completo",
-  "alert.unexpected.message": "An unexpected error occurred.",
+  "alert.unexpected.message": "Hubo un error inesperado.",
   "alert.unexpected.title": "Oops!",
   "boost_modal.combo": "Puedes presionar {combo} para saltear este aviso la próxima vez",
   "bundle_column_error.body": "Algo salió mal al cargar este componente.",
@@ -45,8 +46,8 @@
   "bundle_modal_error.retry": "Inténtalo de nuevo",
   "column.blocks": "Usuarios bloqueados",
   "column.community": "Línea de tiempo local",
-  "column.direct": "Direct messages",
-  "column.domain_blocks": "Hidden domains",
+  "column.direct": "Mensajes directos",
+  "column.domain_blocks": "Dominios ocultos",
   "column.favourites": "Favoritos",
   "column.follow_requests": "Solicitudes de seguimiento",
   "column.home": "Inicio",
@@ -63,9 +64,9 @@
   "column_header.show_settings": "Mostrar ajustes",
   "column_header.unpin": "Dejar de fijar",
   "column_subheading.settings": "Ajustes",
-  "community.column_settings.media_only": "Media Only",
-  "compose_form.direct_message_warning": "This toot will only be visible to all the mentioned users.",
-  "compose_form.direct_message_warning_learn_more": "Learn more",
+  "community.column_settings.media_only": "Solo media",
+  "compose_form.direct_message_warning": "Este toot solo será enviado a los usuarios mencionados.",
+  "compose_form.direct_message_warning_learn_more": "Aprender mas",
   "compose_form.hashtag_warning": "Este toot no se mostrará bajo hashtags porque no es público. Sólo los toots públicos se pueden buscar por hashtag.",
   "compose_form.lock_disclaimer": "Tu cuenta no está bloqueada. Todos pueden seguirte para ver tus toots solo para seguidores.",
   "compose_form.lock_disclaimer.lock": "bloqueado",
@@ -85,11 +86,11 @@
   "confirmations.delete_list.confirm": "Delete",
   "confirmations.delete_list.message": "¿Seguro que quieres borrar esta lista permanentemente?",
   "confirmations.domain_block.confirm": "Ocultar dominio entero",
-  "confirmations.domain_block.message": "¿Seguro de que quieres bloquear al dominio entero? En algunos casos es preferible bloquear o silenciar objetivos determinados.",
+  "confirmations.domain_block.message": "¿Seguro de que quieres bloquear al dominio {domain} entero? En general unos cuantos bloqueos y silenciados concretos es suficiente y preferible.",
   "confirmations.mute.confirm": "Silenciar",
   "confirmations.mute.message": "¿Estás seguro de que quieres silenciar a {name}?",
-  "confirmations.redraft.confirm": "Delete & redraft",
-  "confirmations.redraft.message": "Are you sure you want to delete this status and re-draft it? You will lose all replies, boosts and favourites to it.",
+  "confirmations.redraft.confirm": "Borrar y volver a borrador",
+  "confirmations.redraft.message": "Estás seguro de que quieres borrar este estado y volverlo a borrador? Perderás todas las respuestas, impulsos y favoritos asociados a él, y las respuestas a la publicación original quedarán huérfanos.",
   "confirmations.unfollow.confirm": "Dejar de seguir",
   "confirmations.unfollow.message": "¿Estás seguro de que quieres dejar de seguir a {name}?",
   "embed.instructions": "Añade este toot a tu sitio web con el siguiente código.",
@@ -108,62 +109,62 @@
   "emoji_button.search_results": "Resultados de búsqueda",
   "emoji_button.symbols": "Símbolos",
   "emoji_button.travel": "Viajes y lugares",
-  "empty_column.blocks": "You haven't blocked any users yet.",
+  "empty_column.blocks": "Aún no has bloqueado a ningún usuario.",
   "empty_column.community": "La línea de tiempo local está vacía. ¡Escribe algo para empezar la fiesta!",
-  "empty_column.direct": "You don't have any direct messages yet. When you send or receive one, it will show up here.",
-  "empty_column.domain_blocks": "There are no hidden domains yet.",
-  "empty_column.favourited_statuses": "You don't have any favourite toots yet. When you favourite one, it will show up here.",
-  "empty_column.favourites": "No one has favourited this toot yet. When someone does, they will show up here.",
-  "empty_column.follow_requests": "You don't have any follow requests yet. When you receive one, it will show up here.",
+  "empty_column.direct": "Aún no tienes ningún mensaje directo. Cuando envíes o recibas uno, se mostrará aquí.",
+  "empty_column.domain_blocks": "Todavía no hay dominios ocultos.",
+  "empty_column.favourited_statuses": "Aún no tienes toots preferidos. Cuando marques uno como favorito, aparecerá aquí.",
+  "empty_column.favourites": "Nadie ha marcado este toot como preferido. Cuando alguien lo haga, aparecerá aquí.",
+  "empty_column.follow_requests": "No tienes ninguna petición de seguidor. Cuando recibas una, se mostrará aquí.",
   "empty_column.hashtag": "No hay nada en este hashtag aún.",
   "empty_column.home": "No estás siguiendo a nadie aún. Visita {public} o haz búsquedas para empezar y conocer gente nueva.",
   "empty_column.home.public_timeline": "la línea de tiempo pública",
   "empty_column.list": "No hay nada en esta lista aún. Cuando miembros de esta lista publiquen nuevos estatus, estos aparecerán qui.",
-  "empty_column.lists": "You don't have any lists yet. When you create one, it will show up here.",
-  "empty_column.mutes": "You haven't muted any users yet.",
+  "empty_column.lists": "No tienes ninguna lista. cuando crees una, se mostrará aquí.",
+  "empty_column.mutes": "Aún no has silenciado a ningún usuario.",
   "empty_column.notifications": "No tienes ninguna notificación aún. Interactúa con otros para empezar una conversación.",
   "empty_column.public": "¡No hay nada aquí! Escribe algo públicamente, o sigue usuarios de otras instancias manualmente para llenarlo",
   "follow_request.authorize": "Autorizar",
   "follow_request.reject": "Rechazar",
-  "getting_started.developers": "Developers",
+  "getting_started.developers": "Desarrolladores",
   "getting_started.documentation": "Documentation",
-  "getting_started.find_friends": "Find friends from Twitter",
+  "getting_started.find_friends": "Encuentra a tus amigos desde Twitter",
   "getting_started.heading": "Primeros pasos",
-  "getting_started.invite": "Invite people",
+  "getting_started.invite": "Invitar usuarios",
   "getting_started.open_source_notice": "Mastodon es software libre. Puedes contribuir o reportar errores en {github}.",
-  "getting_started.security": "Security",
-  "getting_started.terms": "Terms of service",
+  "getting_started.security": "Seguridad",
+  "getting_started.terms": "Términos de servicio",
   "home.column_settings.basic": "Básico",
   "home.column_settings.show_reblogs": "Mostrar retoots",
   "home.column_settings.show_replies": "Mostrar respuestas",
   "keyboard_shortcuts.back": "volver atrás",
-  "keyboard_shortcuts.blocked": "to open blocked users list",
+  "keyboard_shortcuts.blocked": "abrir una lista de usuarios bloqueados",
   "keyboard_shortcuts.boost": "retootear",
   "keyboard_shortcuts.column": "enfocar un estado en una de las columnas",
   "keyboard_shortcuts.compose": "enfocar el área de texto de redacción",
   "keyboard_shortcuts.description": "Description",
-  "keyboard_shortcuts.direct": "to open direct messages column",
+  "keyboard_shortcuts.direct": "abrir la columna de mensajes directos",
   "keyboard_shortcuts.down": "mover hacia abajo en la lista",
   "keyboard_shortcuts.enter": "to open status",
   "keyboard_shortcuts.favourite": "añadir a favoritos",
-  "keyboard_shortcuts.favourites": "to open favourites list",
-  "keyboard_shortcuts.federated": "to open federated timeline",
+  "keyboard_shortcuts.favourites": "abrir la lista de favoritos",
+  "keyboard_shortcuts.federated": "abrir el timeline federado",
   "keyboard_shortcuts.heading": "Keyboard Shortcuts",
-  "keyboard_shortcuts.home": "to open home timeline",
+  "keyboard_shortcuts.home": "abrir el timeline propio",
   "keyboard_shortcuts.hotkey": "Tecla caliente",
   "keyboard_shortcuts.legend": "para mostrar esta leyenda",
-  "keyboard_shortcuts.local": "to open local timeline",
+  "keyboard_shortcuts.local": "abrir el timeline local",
   "keyboard_shortcuts.mention": "para mencionar al autor",
-  "keyboard_shortcuts.muted": "to open muted users list",
-  "keyboard_shortcuts.my_profile": "to open your profile",
-  "keyboard_shortcuts.notifications": "to open notifications column",
-  "keyboard_shortcuts.pinned": "to open pinned toots list",
-  "keyboard_shortcuts.profile": "to open author's profile",
+  "keyboard_shortcuts.muted": "abrir la lista de usuarios silenciados",
+  "keyboard_shortcuts.my_profile": "abrir tu perfil",
+  "keyboard_shortcuts.notifications": "abrir la columna de notificaciones",
+  "keyboard_shortcuts.pinned": "abrir la lista de toots destacados",
+  "keyboard_shortcuts.profile": "abrir el perfil del autor",
   "keyboard_shortcuts.reply": "para responder",
-  "keyboard_shortcuts.requests": "to open follow requests list",
+  "keyboard_shortcuts.requests": "abrir la lista de peticiones de seguidores",
   "keyboard_shortcuts.search": "para poner el foco en la búsqueda",
-  "keyboard_shortcuts.start": "to open \"get started\" column",
-  "keyboard_shortcuts.toggle_hidden": "to show/hide text behind CW",
+  "keyboard_shortcuts.start": "abrir la columna \"comenzar\"",
+  "keyboard_shortcuts.toggle_hidden": "mostrar/ocultar texto tras aviso de contenido (CW)",
   "keyboard_shortcuts.toot": "para comenzar un nuevo toot",
   "keyboard_shortcuts.unfocus": "para retirar el foco de la caja de redacción/búsqueda",
   "keyboard_shortcuts.up": "para ir hacia arriba en la lista",
@@ -183,19 +184,19 @@
   "missing_indicator.label": "No encontrado",
   "missing_indicator.sublabel": "No se encontró este recurso",
   "mute_modal.hide_notifications": "Ocultar notificaciones de este usuario?",
-  "navigation_bar.apps": "Mobile apps",
+  "navigation_bar.apps": "Aplicaciones móviles",
   "navigation_bar.blocks": "Usuarios bloqueados",
   "navigation_bar.community_timeline": "Historia local",
-  "navigation_bar.compose": "Compose new toot",
-  "navigation_bar.direct": "Direct messages",
-  "navigation_bar.discover": "Discover",
-  "navigation_bar.domain_blocks": "Hidden domains",
+  "navigation_bar.compose": "Escribir un nuevo toot",
+  "navigation_bar.direct": "Mensajes directos",
+  "navigation_bar.discover": "Descubrir",
+  "navigation_bar.domain_blocks": "Dominios ocultos",
   "navigation_bar.edit_profile": "Editar perfil",
   "navigation_bar.favourites": "Favoritos",
-  "navigation_bar.filters": "Muted words",
+  "navigation_bar.filters": "Palabras silenciadas",
   "navigation_bar.follow_requests": "Solicitudes para seguirte",
   "navigation_bar.info": "Información adicional",
-  "navigation_bar.keyboard_shortcuts": "Atajos de teclado",
+  "navigation_bar.keyboard_shortcuts": "Atajos",
   "navigation_bar.lists": "Listas",
   "navigation_bar.logout": "Cerrar sesión",
   "navigation_bar.mutes": "Usuarios silenciados",
@@ -203,7 +204,7 @@
   "navigation_bar.pins": "Toots fijados",
   "navigation_bar.preferences": "Preferencias",
   "navigation_bar.public_timeline": "Historia federada",
-  "navigation_bar.security": "Security",
+  "navigation_bar.security": "Seguridad",
   "notification.favourite": "{name} marcó tu estado como favorito",
   "notification.follow": "{name} te empezó a seguir",
   "notification.mention": "{name} te ha mencionado",
@@ -219,7 +220,7 @@
   "notifications.column_settings.reblog": "Retoots:",
   "notifications.column_settings.show": "Mostrar en columna",
   "notifications.column_settings.sound": "Reproducir sonido",
-  "notifications.group": "{count} notifications",
+  "notifications.group": "{count} notificaciones",
   "onboarding.done": "Listo",
   "onboarding.next": "Siguiente",
   "onboarding.page_five.public_timelines": "La línea de tiempo local muestra toots públicos de todos en {domain}. La línea de tiempo federada muestra toots públicos de cualquiera a quien la gente de {domain} siga. Estas son las líneas de tiempo públicas, una buena forma de conocer gente nueva.",
@@ -272,19 +273,19 @@
   "search_popout.tips.text": "El texto simple devuelve correspondencias de nombre, usuario y hashtag",
   "search_popout.tips.user": "usuario",
   "search_results.accounts": "Gente",
-  "search_results.hashtags": "Hashtags",
+  "search_results.hashtags": "Etiquetas",
   "search_results.statuses": "Toots",
   "search_results.total": "{count, number} {count, plural, one {resultado} other {resultados}}",
   "standalone.public_title": "Un pequeño vistazo...",
   "status.block": "Block @{name}",
-  "status.cancel_reblog_private": "Unboost",
+  "status.cancel_reblog_private": "Des-impulsar",
   "status.cannot_reblog": "Este toot no puede retootearse",
   "status.delete": "Borrar",
-  "status.detailed_status": "Detailed conversation view",
-  "status.direct": "Direct message @{name}",
+  "status.detailed_status": "Vista de conversación detallada",
+  "status.direct": "Mensaje directo a @{name}",
   "status.embed": "Incrustado",
   "status.favourite": "Favorito",
-  "status.filtered": "Filtered",
+  "status.filtered": "Filtrado",
   "status.load_more": "Cargar más",
   "status.media_hidden": "Contenido multimedia oculto",
   "status.mention": "Mencionar",
@@ -295,10 +296,10 @@
   "status.pin": "Fijar",
   "status.pinned": "Toot fijado",
   "status.reblog": "Retootear",
-  "status.reblog_private": "Boost to original audience",
+  "status.reblog_private": "Implusar a la audiencia original",
   "status.reblogged_by": "Retooteado por {name}",
-  "status.reblogs.empty": "No one has boosted this toot yet. When someone does, they will show up here.",
-  "status.redraft": "Delete & re-draft",
+  "status.reblogs.empty": "Nadie impulsó este toot todavía. Cuando alguien lo haga, aparecerá aqui.",
+  "status.redraft": "Borrar y volver a borrador",
   "status.reply": "Responder",
   "status.replyAll": "Responder al hilo",
   "status.report": "Reportar",
@@ -315,14 +316,14 @@
   "tabs_bar.home": "Inicio",
   "tabs_bar.local_timeline": "Local",
   "tabs_bar.notifications": "Notificaciones",
-  "tabs_bar.search": "Search",
+  "tabs_bar.search": "Buscar",
   "trends.count_by_accounts": "{count} {rawCount, plural, one {person} other {people}} talking",
   "ui.beforeunload": "Tu borrador se perderá si sales de Mastodon.",
   "upload_area.title": "Arrastra y suelta para subir",
-  "upload_button.label": "Subir multimedia",
+  "upload_button.label": "Subir multimedia (JPEG, PNG, GIF, WebM, MP4, MOV)",
   "upload_form.description": "Describir para los usuarios con dificultad visual",
   "upload_form.focus": "Recortar",
-  "upload_form.undo": "Deshacer",
+  "upload_form.undo": "Borrar",
   "upload_progress.label": "Subiendo…",
   "video.close": "Cerrar video",
   "video.exit_fullscreen": "Salir de pantalla completa",
diff --git a/app/javascript/mastodon/locales/eu.json b/app/javascript/mastodon/locales/eu.json
index 433815c66..1dc42ae68 100644
--- a/app/javascript/mastodon/locales/eu.json
+++ b/app/javascript/mastodon/locales/eu.json
@@ -15,6 +15,7 @@
   "account.follows.empty": "Erabiltzaile honek ez du inor jarraitzen oraindik.",
   "account.follows_you": "Jarraitzen zaitu",
   "account.hide_reblogs": "Ezkutatu @{name}(r)en bultzadak",
+  "account.link_verified_on": "Ownership of this link was checked on {date}",
   "account.media": "Media",
   "account.mention": "Aipatu @{name}",
   "account.moved_to": "{name} hona lekualdatu da:",
diff --git a/app/javascript/mastodon/locales/fa.json b/app/javascript/mastodon/locales/fa.json
index 44956aeb3..2e3999918 100644
--- a/app/javascript/mastodon/locales/fa.json
+++ b/app/javascript/mastodon/locales/fa.json
@@ -15,6 +15,7 @@
   "account.follows.empty": "این کاربر هنوز هیچ کسی را پی نمی‌گیرد.",
   "account.follows_you": "پیگیر شماست",
   "account.hide_reblogs": "پنهان کردن بازبوق‌های @{name}",
+  "account.link_verified_on": "Ownership of this link was checked on {date}",
   "account.media": "عکس و ویدیو",
   "account.mention": "نام‌بردن از @{name}",
   "account.moved_to": "{name} منتقل شده است به:",
diff --git a/app/javascript/mastodon/locales/fi.json b/app/javascript/mastodon/locales/fi.json
index fd23e7ff5..f6c0469be 100644
--- a/app/javascript/mastodon/locales/fi.json
+++ b/app/javascript/mastodon/locales/fi.json
@@ -15,6 +15,7 @@
   "account.follows.empty": "This user doesn't follow anyone yet.",
   "account.follows_you": "Seuraa sinua",
   "account.hide_reblogs": "Piilota buustaukset käyttäjältä @{name}",
+  "account.link_verified_on": "Ownership of this link was checked on {date}",
   "account.media": "Media",
   "account.mention": "Mainitse @{name}",
   "account.moved_to": "{name} on muuttanut instanssiin:",
diff --git a/app/javascript/mastodon/locales/fr.json b/app/javascript/mastodon/locales/fr.json
index e77d00286..075bdcf30 100644
--- a/app/javascript/mastodon/locales/fr.json
+++ b/app/javascript/mastodon/locales/fr.json
@@ -15,6 +15,7 @@
   "account.follows.empty": "Cet utilisateur ne suit personne pour l'instant.",
   "account.follows_you": "Vous suit",
   "account.hide_reblogs": "Masquer les partages de @{name}",
+  "account.link_verified_on": "Ownership of this link was checked on {date}",
   "account.media": "Média",
   "account.mention": "Mentionner",
   "account.moved_to": "{name} a déménagé vers :",
@@ -147,22 +148,22 @@
   "keyboard_shortcuts.enter": "pour ouvrir le statut",
   "keyboard_shortcuts.favourite": "vers les favoris",
   "keyboard_shortcuts.favourites": "pour ouvrir une liste de favoris",
-  "keyboard_shortcuts.federated": "to open federated timeline",
+  "keyboard_shortcuts.federated": "pour ouvrir le fil public global",
   "keyboard_shortcuts.heading": "Raccourcis clavier",
-  "keyboard_shortcuts.home": "to open home timeline",
+  "keyboard_shortcuts.home": "pour ouvrir l'accueil",
   "keyboard_shortcuts.hotkey": "Raccourci",
   "keyboard_shortcuts.legend": "pour afficher cette légende",
-  "keyboard_shortcuts.local": "to open local timeline",
+  "keyboard_shortcuts.local": "pour ouvrir le fil public local",
   "keyboard_shortcuts.mention": "pour mentionner l’auteur·rice",
   "keyboard_shortcuts.muted": "pour ouvrir la liste des utilisateurs rendus muets",
   "keyboard_shortcuts.my_profile": "pour ouvrir votre profil",
   "keyboard_shortcuts.notifications": "pour ouvrir votre colonne de notifications",
-  "keyboard_shortcuts.pinned": "to open pinned toots list",
+  "keyboard_shortcuts.pinned": "pour ouvrir une liste des pouets épinglés",
   "keyboard_shortcuts.profile": "pour ouvrir le profil de l’auteur·rice",
   "keyboard_shortcuts.reply": "pour répondre",
   "keyboard_shortcuts.requests": "pour ouvrir la liste de demandes de suivi",
   "keyboard_shortcuts.search": "pour cibler la recherche",
-  "keyboard_shortcuts.start": "to open \"get started\" column",
+  "keyboard_shortcuts.start": "pour ouvrir la colonne \"pour commencer\"",
   "keyboard_shortcuts.toggle_hidden": "pour afficher/cacher un texte derrière CW",
   "keyboard_shortcuts.toot": "pour démarrer un tout nouveau pouet",
   "keyboard_shortcuts.unfocus": "pour recentrer composer textarea/search",
diff --git a/app/javascript/mastodon/locales/gl.json b/app/javascript/mastodon/locales/gl.json
index c550306ac..8b830ae7b 100644
--- a/app/javascript/mastodon/locales/gl.json
+++ b/app/javascript/mastodon/locales/gl.json
@@ -15,6 +15,7 @@
   "account.follows.empty": "This user doesn't follow anyone yet.",
   "account.follows_you": "Séguena",
   "account.hide_reblogs": "Ocultar repeticións de @{name}",
+  "account.link_verified_on": "Ownership of this link was checked on {date}",
   "account.media": "Medios",
   "account.mention": "Mencionar @{name}",
   "account.moved_to": "{name} marchou a:",
diff --git a/app/javascript/mastodon/locales/he.json b/app/javascript/mastodon/locales/he.json
index e9a13b02d..4aee82212 100644
--- a/app/javascript/mastodon/locales/he.json
+++ b/app/javascript/mastodon/locales/he.json
@@ -15,6 +15,7 @@
   "account.follows.empty": "This user doesn't follow anyone yet.",
   "account.follows_you": "במעקב אחריך",
   "account.hide_reblogs": "להסתיר הידהודים מאת @{name}",
+  "account.link_verified_on": "Ownership of this link was checked on {date}",
   "account.media": "מדיה",
   "account.mention": "אזכור של @{name}",
   "account.moved_to": "החשבון {name} הועבר אל:",
diff --git a/app/javascript/mastodon/locales/hr.json b/app/javascript/mastodon/locales/hr.json
index 7da45c3a4..a138cf589 100644
--- a/app/javascript/mastodon/locales/hr.json
+++ b/app/javascript/mastodon/locales/hr.json
@@ -15,6 +15,7 @@
   "account.follows.empty": "This user doesn't follow anyone yet.",
   "account.follows_you": "te slijedi",
   "account.hide_reblogs": "Hide boosts from @{name}",
+  "account.link_verified_on": "Ownership of this link was checked on {date}",
   "account.media": "Media",
   "account.mention": "Spomeni @{name}",
   "account.moved_to": "{name} has moved to:",
diff --git a/app/javascript/mastodon/locales/hu.json b/app/javascript/mastodon/locales/hu.json
index c9d32135a..6a4d0ecf0 100644
--- a/app/javascript/mastodon/locales/hu.json
+++ b/app/javascript/mastodon/locales/hu.json
@@ -15,6 +15,7 @@
   "account.follows.empty": "This user doesn't follow anyone yet.",
   "account.follows_you": "Követnek téged",
   "account.hide_reblogs": "Rejtsd el a tülkölést @{name}-tól/től",
+  "account.link_verified_on": "Ownership of this link was checked on {date}",
   "account.media": "Média",
   "account.mention": "@{name} említése",
   "account.moved_to": "{name} átköltözött:",
diff --git a/app/javascript/mastodon/locales/hy.json b/app/javascript/mastodon/locales/hy.json
index 1376f6894..7d7090236 100644
--- a/app/javascript/mastodon/locales/hy.json
+++ b/app/javascript/mastodon/locales/hy.json
@@ -15,6 +15,7 @@
   "account.follows.empty": "This user doesn't follow anyone yet.",
   "account.follows_you": "Հետեւում է քեզ",
   "account.hide_reblogs": "Թաքցնել @{name}֊ի տարածածները",
+  "account.link_verified_on": "Ownership of this link was checked on {date}",
   "account.media": "Մեդիա",
   "account.mention": "Նշել @{name}֊ին",
   "account.moved_to": "{name}֊ը տեղափոխվել է՝",
diff --git a/app/javascript/mastodon/locales/id.json b/app/javascript/mastodon/locales/id.json
index e8b087e9d..c8ed00e9f 100644
--- a/app/javascript/mastodon/locales/id.json
+++ b/app/javascript/mastodon/locales/id.json
@@ -15,6 +15,7 @@
   "account.follows.empty": "This user doesn't follow anyone yet.",
   "account.follows_you": "Mengikuti anda",
   "account.hide_reblogs": "Sembunyikan boosts dari @{name}",
+  "account.link_verified_on": "Ownership of this link was checked on {date}",
   "account.media": "Media",
   "account.mention": "Balasan @{name}",
   "account.moved_to": "{name} telah pindah ke:",
diff --git a/app/javascript/mastodon/locales/io.json b/app/javascript/mastodon/locales/io.json
index a3ea121e4..c92ceccd1 100644
--- a/app/javascript/mastodon/locales/io.json
+++ b/app/javascript/mastodon/locales/io.json
@@ -15,6 +15,7 @@
   "account.follows.empty": "This user doesn't follow anyone yet.",
   "account.follows_you": "Sequas tu",
   "account.hide_reblogs": "Hide boosts from @{name}",
+  "account.link_verified_on": "Ownership of this link was checked on {date}",
   "account.media": "Media",
   "account.mention": "Mencionar @{name}",
   "account.moved_to": "{name} has moved to:",
diff --git a/app/javascript/mastodon/locales/it.json b/app/javascript/mastodon/locales/it.json
index fa0956fe3..e9eb62e71 100644
--- a/app/javascript/mastodon/locales/it.json
+++ b/app/javascript/mastodon/locales/it.json
@@ -7,14 +7,15 @@
   "account.disclaimer_full": "Il profilo dell'utente mostrato qui sotto potrebbe essere incompleto.",
   "account.domain_blocked": "Dominio nascosto",
   "account.edit_profile": "Modifica profilo",
-  "account.endorse": "Feature on profile",
+  "account.endorse": "Metti in evidenza sul profilo",
   "account.follow": "Segui",
   "account.followers": "Seguaci",
-  "account.followers.empty": "No one follows this user yet.",
+  "account.followers.empty": "Ancora nessuno segue questo utente.",
   "account.follows": "Segue",
-  "account.follows.empty": "This user doesn't follow anyone yet.",
+  "account.follows.empty": "Questo utente non segue ancora nessuno.",
   "account.follows_you": "Ti segue",
   "account.hide_reblogs": "Nascondi condivisioni da @{name}",
+  "account.link_verified_on": "Ownership of this link was checked on {date}",
   "account.media": "Media",
   "account.mention": "Menziona @{name}",
   "account.moved_to": "{name} si è trasferito su:",
@@ -29,7 +30,7 @@
   "account.show_reblogs": "Mostra condivisioni da @{name}",
   "account.unblock": "Sblocca @{name}",
   "account.unblock_domain": "Non nascondere {domain}",
-  "account.unendorse": "Don't feature on profile",
+  "account.unendorse": "Non mettere in evidenza sul profilo",
   "account.unfollow": "Non seguire",
   "account.unmute": "Non silenziare @{name}",
   "account.unmute_notifications": "Non silenziare più le notifiche da @{name}",
@@ -108,19 +109,19 @@
   "emoji_button.search_results": "Risultati della ricerca",
   "emoji_button.symbols": "Simboli",
   "emoji_button.travel": "Viaggi e luoghi",
-  "empty_column.blocks": "You haven't blocked any users yet.",
+  "empty_column.blocks": "Non hai ancora bloccato nessun utente.",
   "empty_column.community": "La timeline locale è vuota. Condividi qualcosa pubblicamente per dare inizio alla festa!",
   "empty_column.direct": "Non hai ancora nessun messaggio diretto. Quando ne manderai o riceverai qualcuno, apparirà qui.",
-  "empty_column.domain_blocks": "There are no hidden domains yet.",
-  "empty_column.favourited_statuses": "You don't have any favourite toots yet. When you favourite one, it will show up here.",
-  "empty_column.favourites": "No one has favourited this toot yet. When someone does, they will show up here.",
-  "empty_column.follow_requests": "You don't have any follow requests yet. When you receive one, it will show up here.",
+  "empty_column.domain_blocks": "Non vi sono domini nascosti.",
+  "empty_column.favourited_statuses": "Non hai ancora segnato nessun toot come apprezzato. Quando lo farai, comparirà qui.",
+  "empty_column.favourites": "Nessuno ha ancora segnato questo toot come apprezzato. Quando qualcuno lo farà, apparirà qui.",
+  "empty_column.follow_requests": "Non hai ancora ricevuto nessuna richiesta di seguirti. Quando ne arriveranno, saranno mostrate qui.",
   "empty_column.hashtag": "Non c'è ancora nessun post con questo hashtag.",
   "empty_column.home": "Non stai ancora seguendo nessuno. Visita {public} o usa la ricerca per incontrare nuove persone.",
   "empty_column.home.public_timeline": "la timeline pubblica",
   "empty_column.list": "Non c'è niente in questo elenco ancora. Quando i membri di questo elenco postano nuovi stati, questi appariranno qui.",
-  "empty_column.lists": "You don't have any lists yet. When you create one, it will show up here.",
-  "empty_column.mutes": "You haven't muted any users yet.",
+  "empty_column.lists": "Non hai ancora nessuna lista. Quando ne creerai qualcuna, comparirà qui.",
+  "empty_column.mutes": "Non hai ancora silenziato nessun utente.",
   "empty_column.notifications": "Non hai ancora nessuna notifica. Interagisci con altri per iniziare conversazioni.",
   "empty_column.public": "Qui non c'è nulla! Scrivi qualcosa pubblicamente, o aggiungi utenti da altri server per riempire questo spazio",
   "follow_request.authorize": "Autorizza",
@@ -137,32 +138,32 @@
   "home.column_settings.show_reblogs": "Mostra post condivisi",
   "home.column_settings.show_replies": "Mostra risposte",
   "keyboard_shortcuts.back": "per tornare indietro",
-  "keyboard_shortcuts.blocked": "to open blocked users list",
+  "keyboard_shortcuts.blocked": "per aprire l'elenco degli utenti bloccati",
   "keyboard_shortcuts.boost": "per condividere",
   "keyboard_shortcuts.column": "per portare il focus su uno status in una delle colonne",
   "keyboard_shortcuts.compose": "per portare il focus nell'area di composizione",
   "keyboard_shortcuts.description": "Descrizione",
-  "keyboard_shortcuts.direct": "to open direct messages column",
+  "keyboard_shortcuts.direct": "per aprire la colonna dei messaggi diretti",
   "keyboard_shortcuts.down": "per spostarsi in basso nella lista",
   "keyboard_shortcuts.enter": "per aprire lo status",
   "keyboard_shortcuts.favourite": "per segnare come apprezzato",
-  "keyboard_shortcuts.favourites": "to open favourites list",
-  "keyboard_shortcuts.federated": "to open federated timeline",
+  "keyboard_shortcuts.favourites": "per aprire l'elenco dei toot apprezzati",
+  "keyboard_shortcuts.federated": "per aprire la timeline federata",
   "keyboard_shortcuts.heading": "Tasti di scelta rapida",
-  "keyboard_shortcuts.home": "to open home timeline",
+  "keyboard_shortcuts.home": "per aprire la timeline home",
   "keyboard_shortcuts.hotkey": "Tasto di scelta rapida",
   "keyboard_shortcuts.legend": "per mostrare questa spiegazione",
-  "keyboard_shortcuts.local": "to open local timeline",
+  "keyboard_shortcuts.local": "per aprire la timeline locale",
   "keyboard_shortcuts.mention": "per menzionare l'autore",
-  "keyboard_shortcuts.muted": "to open muted users list",
-  "keyboard_shortcuts.my_profile": "to open your profile",
-  "keyboard_shortcuts.notifications": "to open notifications column",
-  "keyboard_shortcuts.pinned": "to open pinned toots list",
+  "keyboard_shortcuts.muted": "per aprire l'elenco degli utenti silenziati",
+  "keyboard_shortcuts.my_profile": "per aprire il tuo profilo",
+  "keyboard_shortcuts.notifications": "per aprire la colonna delle notifiche",
+  "keyboard_shortcuts.pinned": "per aprire l'elenco dei toot fissati in cima",
   "keyboard_shortcuts.profile": "per aprire il profilo dell'autore",
   "keyboard_shortcuts.reply": "per rispondere",
-  "keyboard_shortcuts.requests": "to open follow requests list",
+  "keyboard_shortcuts.requests": "per aprire l'elenco delle richieste di seguirti",
   "keyboard_shortcuts.search": "per spostare il focus sulla ricerca",
-  "keyboard_shortcuts.start": "to open \"get started\" column",
+  "keyboard_shortcuts.start": "per aprire la colonna \"Come iniziare\"",
   "keyboard_shortcuts.toggle_hidden": "per mostrare/nascondere il testo dei CW",
   "keyboard_shortcuts.toot": "per iniziare a scrivere un toot completamente nuovo",
   "keyboard_shortcuts.unfocus": "per uscire dall'area di composizione o dalla ricerca",
@@ -183,10 +184,10 @@
   "missing_indicator.label": "Non trovato",
   "missing_indicator.sublabel": "Risorsa non trovata",
   "mute_modal.hide_notifications": "Nascondere le notifiche da quest'utente?",
-  "navigation_bar.apps": "Mobile apps",
+  "navigation_bar.apps": "App per dispositivi mobili",
   "navigation_bar.blocks": "Utenti bloccati",
   "navigation_bar.community_timeline": "Timeline locale",
-  "navigation_bar.compose": "Compose new toot",
+  "navigation_bar.compose": "Componi nuovo toot",
   "navigation_bar.direct": "Messaggi diretti",
   "navigation_bar.discover": "Scopri",
   "navigation_bar.domain_blocks": "Domini nascosti",
@@ -280,7 +281,7 @@
   "status.cancel_reblog_private": "Annulla condivisione",
   "status.cannot_reblog": "Questo post non può essere condiviso",
   "status.delete": "Elimina",
-  "status.detailed_status": "Detailed conversation view",
+  "status.detailed_status": "Vista conversazione dettagliata",
   "status.direct": "Messaggio diretto @{name}",
   "status.embed": "Incorpora",
   "status.favourite": "Apprezzato",
@@ -297,7 +298,7 @@
   "status.reblog": "Condividi",
   "status.reblog_private": "Condividi con i destinatari iniziali",
   "status.reblogged_by": "{name} ha condiviso",
-  "status.reblogs.empty": "No one has boosted this toot yet. When someone does, they will show up here.",
+  "status.reblogs.empty": "Nessuno ha ancora condiviso questo toot. Quando qualcuno lo farà, comparirà qui.",
   "status.redraft": "Cancella e riscrivi",
   "status.reply": "Rispondi",
   "status.replyAll": "Rispondi alla conversazione",
diff --git a/app/javascript/mastodon/locales/ja.json b/app/javascript/mastodon/locales/ja.json
index 6ec9321de..04a2e4692 100644
--- a/app/javascript/mastodon/locales/ja.json
+++ b/app/javascript/mastodon/locales/ja.json
@@ -15,6 +15,7 @@
   "account.follows.empty": "まだ誰もフォローしていません。",
   "account.follows_you": "フォローされています",
   "account.hide_reblogs": "@{name}さんからのブーストを非表示",
+  "account.link_verified_on": "Ownership of this link was checked on {date}",
   "account.media": "メディア",
   "account.mention": "@{name}さんにトゥート",
   "account.moved_to": "{name}さんは引っ越しました:",
diff --git a/app/javascript/mastodon/locales/ka.json b/app/javascript/mastodon/locales/ka.json
index 6ad129254..ec6e211c6 100644
--- a/app/javascript/mastodon/locales/ka.json
+++ b/app/javascript/mastodon/locales/ka.json
@@ -15,6 +15,7 @@
   "account.follows.empty": "This user doesn't follow anyone yet.",
   "account.follows_you": "მოგყვებათ",
   "account.hide_reblogs": "დაიმალოს ბუსტები @{name}-სგან",
+  "account.link_verified_on": "Ownership of this link was checked on {date}",
   "account.media": "მედია",
   "account.mention": "ასახელეთ @{name}",
   "account.moved_to": "{name} გადავიდა:",
diff --git a/app/javascript/mastodon/locales/ko.json b/app/javascript/mastodon/locales/ko.json
index 50f785c1a..15e8524e0 100644
--- a/app/javascript/mastodon/locales/ko.json
+++ b/app/javascript/mastodon/locales/ko.json
@@ -15,6 +15,7 @@
   "account.follows.empty": "이 유저는 아직 아무도 팔로우 하고 있지 않습니다.",
   "account.follows_you": "날 팔로우합니다",
   "account.hide_reblogs": "@{name}의 부스트를 숨기기",
+  "account.link_verified_on": "Ownership of this link was checked on {date}",
   "account.media": "미디어",
   "account.mention": "@{name}에게 글쓰기",
   "account.moved_to": "{name}는 계정을 이동했습니다:",
diff --git a/app/javascript/mastodon/locales/nl.json b/app/javascript/mastodon/locales/nl.json
index 5623bc54f..f829146f1 100644
--- a/app/javascript/mastodon/locales/nl.json
+++ b/app/javascript/mastodon/locales/nl.json
@@ -15,6 +15,7 @@
   "account.follows.empty": "Deze gebruiker volgt nog niemand.",
   "account.follows_you": "Volgt jou",
   "account.hide_reblogs": "Verberg boosts van @{name}",
+  "account.link_verified_on": "Ownership of this link was checked on {date}",
   "account.media": "Media",
   "account.mention": "Vermeld @{name}",
   "account.moved_to": "{name} is verhuisd naar:",
diff --git a/app/javascript/mastodon/locales/no.json b/app/javascript/mastodon/locales/no.json
index d533ac315..e531789a9 100644
--- a/app/javascript/mastodon/locales/no.json
+++ b/app/javascript/mastodon/locales/no.json
@@ -15,6 +15,7 @@
   "account.follows.empty": "This user doesn't follow anyone yet.",
   "account.follows_you": "Følger deg",
   "account.hide_reblogs": "Skjul fremhevinger fra @{name}",
+  "account.link_verified_on": "Ownership of this link was checked on {date}",
   "account.media": "Media",
   "account.mention": "Nevn @{name}",
   "account.moved_to": "{name} har flyttet til:",
diff --git a/app/javascript/mastodon/locales/oc.json b/app/javascript/mastodon/locales/oc.json
index 254e9a2a5..182710038 100644
--- a/app/javascript/mastodon/locales/oc.json
+++ b/app/javascript/mastodon/locales/oc.json
@@ -15,6 +15,7 @@
   "account.follows.empty": "Aqueste utilizaire sèc pas degun pel moment.",
   "account.follows_you": "Vos sèc",
   "account.hide_reblogs": "Rescondre los partatges de @{name}",
+  "account.link_verified_on": "Ownership of this link was checked on {date}",
   "account.media": "Mèdias",
   "account.mention": "Mencionar @{name}",
   "account.moved_to": "{name} a mudat los catons a :",
diff --git a/app/javascript/mastodon/locales/pl.json b/app/javascript/mastodon/locales/pl.json
index c5f28c2d0..aa2535bf7 100644
--- a/app/javascript/mastodon/locales/pl.json
+++ b/app/javascript/mastodon/locales/pl.json
@@ -15,6 +15,7 @@
   "account.follows.empty": "Ten użytkownik nie śledzi jeszcze nikogo.",
   "account.follows_you": "Śledzi Cię",
   "account.hide_reblogs": "Ukryj podbicia od @{name}",
+  "account.link_verified_on": "Ownership of this link was checked on {date}",
   "account.media": "Zawartość multimedialna",
   "account.mention": "Wspomnij o @{name}",
   "account.moved_to": "{name} przeniósł(-osła) się do:",
diff --git a/app/javascript/mastodon/locales/pt-BR.json b/app/javascript/mastodon/locales/pt-BR.json
index ed6ea3674..9c48f0bc1 100644
--- a/app/javascript/mastodon/locales/pt-BR.json
+++ b/app/javascript/mastodon/locales/pt-BR.json
@@ -15,6 +15,7 @@
   "account.follows.empty": "This user doesn't follow anyone yet.",
   "account.follows_you": "Segue você",
   "account.hide_reblogs": "Esconder compartilhamentos de @{name}",
+  "account.link_verified_on": "Ownership of this link was checked on {date}",
   "account.media": "Mídia",
   "account.mention": "Mencionar @{name}",
   "account.moved_to": "{name} se mudou para:",
diff --git a/app/javascript/mastodon/locales/pt.json b/app/javascript/mastodon/locales/pt.json
index 2f601cb32..096fded95 100644
--- a/app/javascript/mastodon/locales/pt.json
+++ b/app/javascript/mastodon/locales/pt.json
@@ -15,6 +15,7 @@
   "account.follows.empty": "This user doesn't follow anyone yet.",
   "account.follows_you": "É teu seguidor",
   "account.hide_reblogs": "Esconder partilhas de @{name}",
+  "account.link_verified_on": "Ownership of this link was checked on {date}",
   "account.media": "Media",
   "account.mention": "Mencionar @{name}",
   "account.moved_to": "{name} mudou a sua conta para:",
diff --git a/app/javascript/mastodon/locales/ro.json b/app/javascript/mastodon/locales/ro.json
index f3c540f2e..fda82136e 100644
--- a/app/javascript/mastodon/locales/ro.json
+++ b/app/javascript/mastodon/locales/ro.json
@@ -1,145 +1,146 @@
 {
   "account.badges.bot": "Bot",
-  "account.block": "Blocheaza @{name}",
+  "account.block": "Blochează @{name}",
   "account.block_domain": "Ascunde tot de la {domain}",
   "account.blocked": "Blocat",
   "account.direct": "Mesaj direct @{name}",
-  "account.disclaimer_full": "Informatiile de la jos pot reflecta profilul incomplet al utilizatorului.",
+  "account.disclaimer_full": "Informațiile de mai jos pot reflecta profilul incomplet al utilizatorului.",
   "account.domain_blocked": "Domeniu ascuns",
-  "account.edit_profile": "Editeaza profilul",
-  "account.endorse": "Promoveaza pe profil",
-  "account.follow": "Urmareste",
-  "account.followers": "Urmaritori",
-  "account.followers.empty": "Nimeni nu urmareste acest utilizator inca.",
-  "account.follows": "Urmareste",
-  "account.follows.empty": "Acest utilizator nu urmareste pe nimeni inca.",
-  "account.follows_you": "Te urmareste",
-  "account.hide_reblogs": "Ascunde promovarile de la @{name}",
+  "account.edit_profile": "Editează profilul",
+  "account.endorse": "Redistribuie pe profil",
+  "account.follow": "Urmărește",
+  "account.followers": "Urmăritori",
+  "account.followers.empty": "Nimeni nu urmărește acest utilizator incă.",
+  "account.follows": "Urmărește",
+  "account.follows.empty": "Acest utilizator nu urmărește pe nimeni incă.",
+  "account.follows_you": "Te urmărește",
+  "account.hide_reblogs": "Ascunde redistribuirile de la @{name}",
+  "account.link_verified_on": "Ownership of this link was checked on {date}",
   "account.media": "Media",
-  "account.mention": "Mentioneaza @{name}",
+  "account.mention": "Menționează @{name}",
   "account.moved_to": "{name} a fost mutat la:",
-  "account.mute": "Opreste @{name}",
-  "account.mute_notifications": "Opreste notificarile de la @{name}",
+  "account.mute": "Oprește @{name}",
+  "account.mute_notifications": "Oprește notificările de la @{name}",
   "account.muted": "Oprit",
-  "account.posts": "Postare",
-  "account.posts_with_replies": "Postari si replici",
-  "account.report": "Raporteaza @{name}",
-  "account.requested": "Asteapta aprobare. Apasa pentru a anula cererea de urmarire",
+  "account.posts": "Postări",
+  "account.posts_with_replies": "Postări și replici",
+  "account.report": "Raportează @{name}",
+  "account.requested": "Așteaptă aprobare. Apasă pentru a anula cererea de urmărire",
   "account.share": "Distribuie profilul lui @{name}",
-  "account.show_reblogs": "Arata promovarile de la @{name}",
-  "account.unblock": "Deblocheaza @{name}",
-  "account.unblock_domain": "Arata {domain}",
+  "account.show_reblogs": "Arată redistribuirile de la @{name}",
+  "account.unblock": "Deblochează @{name}",
+  "account.unblock_domain": "Arată {domain}",
   "account.unendorse": "Nu promova pe profil",
-  "account.unfollow": "Nu mai urmari",
-  "account.unmute": "Porneste notificarile @{name}",
-  "account.unmute_notifications": "Porneste notificarile de la @{name}",
+  "account.unfollow": "Nu mai urmări",
+  "account.unmute": "Pornește notificările @{name}",
+  "account.unmute_notifications": "Pornește notificările de la @{name}",
   "account.view_full_profile": "Vezi profilul complet",
-  "alert.unexpected.message": "A aparut o eroare neasteptata.",
+  "alert.unexpected.message": "A apărut o eroare neașteptată.",
   "alert.unexpected.title": "Hopa!",
-  "boost_modal.combo": "Poti apasa {combo} pentru a sari peste asta data viitoare",
-  "bundle_column_error.body": "Ceva nu a functionat la incarcarea acestui component.",
-  "bundle_column_error.retry": "Incearca din nou",
-  "bundle_column_error.title": "Eoare de retea",
-  "bundle_modal_error.close": "Inchis",
-  "bundle_modal_error.message": "Ceva nu a functionat in timupul incacarii acestui component.",
-  "bundle_modal_error.retry": "Incearca din nou",
-  "column.blocks": "Utilizatori blocati",
+  "boost_modal.combo": "Poți apăsa {combo} pentru a sări peste asta data viitoare",
+  "bundle_column_error.body": "Ceva nu a funcționat la încărcarea acestui component.",
+  "bundle_column_error.retry": "Încearcă din nou",
+  "bundle_column_error.title": "Eoare de rețea",
+  "bundle_modal_error.close": "Închide",
+  "bundle_modal_error.message": "Ceva nu a funcționat în timupul încărcării acestui component.",
+  "bundle_modal_error.retry": "Încearcă din nou",
+  "column.blocks": "Utilizatori blocați",
   "column.community": "Fluxul Local",
   "column.direct": "Mesaje directe",
   "column.domain_blocks": "Domenii ascunse",
   "column.favourites": "Favorite",
-  "column.follow_requests": "Cereri de urmarire",
-  "column.home": "Acasa",
+  "column.follow_requests": "Cereri de urmărire",
+  "column.home": "Acasă",
   "column.lists": "Liste",
-  "column.mutes": "Utilizatori opriti",
-  "column.notifications": "Notificari",
-  "column.pins": "Postari fixate",
+  "column.mutes": "Utilizatori opriți",
+  "column.notifications": "Notificări",
+  "column.pins": "Postări fixate",
   "column.public": "Flux global",
-  "column_back_button.label": "Inapoi",
-  "column_header.hide_settings": "Ascunde setarile",
-  "column_header.moveLeft_settings": "Muta coloana la stanga",
-  "column_header.moveRight_settings": "Muta coloaba la dreapta",
-  "column_header.pin": "Fixeaza",
-  "column_header.show_settings": "Arata setarile",
-  "column_header.unpin": "Elibereaza",
-  "column_subheading.settings": "Setari",
+  "column_back_button.label": "Înapoi",
+  "column_header.hide_settings": "Ascunde setările",
+  "column_header.moveLeft_settings": "Mută coloana la stânga",
+  "column_header.moveRight_settings": "Mută coloana la dreapta",
+  "column_header.pin": "Fixează",
+  "column_header.show_settings": "Arată setările",
+  "column_header.unpin": "Eliberează",
+  "column_subheading.settings": "Setări",
   "community.column_settings.media_only": "Doar media",
-  "compose_form.direct_message_warning": "Aceasta postare va fi trimisa doar utilizatorilor mentionati.",
-  "compose_form.direct_message_warning_learn_more": "Afla mai multe",
-  "compose_form.hashtag_warning": "Aceasta postare nu va fi listata sub nici un hastag. Doar postarile publice pot fi gasite dupa un hastag.",
-  "compose_form.lock_disclaimer": "Contul tau nu este {locked}. Toata lumea te poate urmari pentru a vedea postarile doar pentru utilizatori.",
-  "compose_form.lock_disclaimer.lock": "blocat",
-  "compose_form.placeholder": "La ce te gandesti?",
-  "compose_form.publish": "Postare",
+  "compose_form.direct_message_warning": "Această postare va fi trimisă doar utilizatorilor menționați.",
+  "compose_form.direct_message_warning_learn_more": "Află mai multe",
+  "compose_form.hashtag_warning": "Această postare nu va fi listată sub nici un hastag. Doar postările publice pot fi găsite dupa un hastag.",
+  "compose_form.lock_disclaimer": "Contul tău nu este {locked}. Toată lumea te poate urmări pentru a vedea postările doar pentru urmăritori.",
+  "compose_form.lock_disclaimer.lock": "privat",
+  "compose_form.placeholder": "La ce te gândești?",
+  "compose_form.publish": "Postează",
   "compose_form.publish_loud": "{publish}!",
-  "compose_form.sensitive.marked": "Continutul media este marcat ca sensibil",
-  "compose_form.sensitive.unmarked": "Continutul media nu este marcat ca sensibil",
+  "compose_form.sensitive.marked": "Conținutul media este marcat ca sensibil",
+  "compose_form.sensitive.unmarked": "Conținutul media nu este marcat ca sensibil",
   "compose_form.spoiler.marked": "Textul este ascuns sub advertizare",
   "compose_form.spoiler.unmarked": "Textul nu este ascuns",
   "compose_form.spoiler_placeholder": "Scrie adveritzarea aici",
-  "confirmation_modal.cancel": "Anuleaza",
-  "confirmations.block.confirm": "Blocheaza",
-  "confirmations.block.message": "Esti sigur ca vrei sa blochezi {name}?",
-  "confirmations.delete.confirm": "Sterge",
-  "confirmations.delete.message": "Esti sigur ca vrei sa stergi asta?",
-  "confirmations.delete_list.confirm": "Sterge",
-  "confirmations.delete_list.message": "Esti sigur ca vrei sa stergi permanent aceasta lista?",
+  "confirmation_modal.cancel": "Anulează",
+  "confirmations.block.confirm": "Blochează",
+  "confirmations.block.message": "Ești sigur că vrei să blochezi {name}?",
+  "confirmations.delete.confirm": "Șterge",
+  "confirmations.delete.message": "Ești șigur că vrei să ștergi asta?",
+  "confirmations.delete_list.confirm": "Șterge",
+  "confirmations.delete_list.message": "Ești sigur că vrei să ștergi permanent această listă?",
   "confirmations.domain_block.confirm": "Ascunde tot domeniul",
-  "confirmations.domain_block.message": "Esti absolut sigur ca vrei sa blochezi complet {domain}? In cele mai multe cazuti raportarea sau oprirea anumitor lucruri este sufucienta si de preferat. Nu vei mai vedea nici un continut de la acest domeniu in nici un flux public sau in notificarile tale. Urmaritorii tai de la acele domenii vor fi retrasi.",
-  "confirmations.mute.confirm": "Opreste",
-  "confirmations.mute.message": "Esti sigur ca vrei sa opresti {name}?",
-  "confirmations.redraft.confirm": "Strge si salveaza din nou",
-  "confirmations.redraft.message": "Esti sigur ca vrei sa faci asta? Tot ce tine de aceasta postare, inclusiv raspunsurile vor fi deconectate.",
-  "confirmations.unfollow.confirm": "Nu mai urmari",
-  "confirmations.unfollow.message": "Esti sigur ca nu mai vrei sa urmaresti {name}?",
-  "embed.instructions": "Insereaza aceasta postare pe site-ul tau adaugand codul de mai jos.",
-  "embed.preview": "Cam asa va arata:",
+  "confirmations.domain_block.message": "Ești absolut sigur că vrei să blochezi complet {domain}? În cele mai multe cazuri raportarea sau oprirea anumitor lucruri este suficientă și de preferat. Nu vei mai vedea nici un conținut de la acest domeniu in nici un flux public sau în notificările tale. Urmăritorii tăi de la acele domenii vor fi retrași.",
+  "confirmations.mute.confirm": "Oprește",
+  "confirmations.mute.message": "Ești sigur că vrei să oprești {name}?",
+  "confirmations.redraft.confirm": "Șterge și salvează ca ciornă",
+  "confirmations.redraft.message": "Ești sigur că vrei să faci asta? Tot ce ține de această postare, inclusiv răspunsurile vor fi deconectate.",
+  "confirmations.unfollow.confirm": "Nu mai urmări",
+  "confirmations.unfollow.message": "Ești sigur că nu mai vrei să îl urmărești pe {name}?",
+  "embed.instructions": "Inserează această postare pe site-ul tău adăugând codul de mai jos.",
+  "embed.preview": "Cam așa va arăta:",
   "emoji_button.activity": "Activitate",
   "emoji_button.custom": "Personalizat",
   "emoji_button.flags": "Marcaje",
-  "emoji_button.food": "Mancare si Bauturi",
-  "emoji_button.label": "Insereaza un emoji",
-  "emoji_button.nature": "Natura",
-  "emoji_button.not_found": "Fara emojiuri (╯°□°)╯︵ ┻━┻",
+  "emoji_button.food": "Mâncare și Băuturi",
+  "emoji_button.label": "Inserează un emoji",
+  "emoji_button.nature": "Natură",
+  "emoji_button.not_found": "Fară emojiuri (╯°□°)╯︵ ┻━┻",
   "emoji_button.objects": "Obiecte",
   "emoji_button.people": "Persoane",
   "emoji_button.recent": "Utilizate frecvent",
-  "emoji_button.search": "Cauta...",
-  "emoji_button.search_results": "Rezultatele cautarii",
+  "emoji_button.search": "Caută...",
+  "emoji_button.search_results": "Rezultatele căutării",
   "emoji_button.symbols": "Simboluri",
-  "emoji_button.travel": "Calatorii si Locuri",
-  "empty_column.blocks": "Nu ai blocat nici un utilizator inca.",
-  "empty_column.community": "Nimic in fluxul local. Scrie ceva public pentru a impinge bila la deal!",
-  "empty_column.direct": "Nu ai nici un mesaj direct inca. Cand trimiti sau primesti unul, vor fi afisare aici.",
-  "empty_column.domain_blocks": "Nu sunt domenii ascunse inca.",
-  "empty_column.favourited_statuses": "Nu ai nici o postare favorita inca. Cand vei avea, vor fi afisare inca.",
-  "empty_column.favourites": "Nimeni nu are inca nici o postare favorita. Cand cineva va adauga la favorite, vor aparea aici.",
-  "empty_column.follow_requests": "Nu ai inca nici o cerete de urmarire. Cand vei primi una, va fi afisata aici.",
-  "empty_column.hashtag": "Acest hastag nu a fost folosit in nici o postare inca.",
-  "empty_column.home": "Fluxul tau este gol. Viziteaza {public} sau fa o cautare pentru a incepe a incepe si a cunoaste alti oameni.",
+  "emoji_button.travel": "Călătorii si Locuri",
+  "empty_column.blocks": "Nu ai blocat nici un utilizator incă.",
+  "empty_column.community": "Fluxul local este gol. Scrie ceva public pentru a împinge bila la vale!",
+  "empty_column.direct": "Nu ai nici un mesaj direct incă. Când trimiți sau primești unul, vor fi afișate aici.",
+  "empty_column.domain_blocks": "Nu sunt domenii ascunse incă.",
+  "empty_column.favourited_statuses": "Nu ai nici o postare favorită încă. Când vei avea, vor fi afișate aici.",
+  "empty_column.favourites": "Nimeni nu are această postare adăugată la favorite. Când cineva o va face va fi afișat aici.",
+  "empty_column.follow_requests": "Nu ai încă nici o cerere de urmărire. Când vei primi una, va fi afișată aici.",
+  "empty_column.hashtag": "Acest hastag nu a fost folosit încă nicăieri.",
+  "empty_column.home": "Fluxul tău este gol. Vizitează {public} sau fă o căutare pentru a începe să cunoști oameni noi.",
   "empty_column.home.public_timeline": "fluxul public",
-  "empty_column.list": "Nu este nimic inca in aceasta lista. Cand membri acestei liste vor incepe sa posteze, va aparea aici.",
-  "empty_column.lists": "Nu ai inca nici o lista. Cand vei crea una, va aparea aici.",
-  "empty_column.mutes": "Nu ai oprit nici un utilizator inca.",
-  "empty_column.notifications": "Nu ai nici o notificare inca. Interactioneaza cu altii pentru a incepe o conversatie.",
-  "empty_column.public": "Nu este nimci aici inca! Scrie ceva public, sau urmareste alti utilizatori din alte medii pentru a porni fluxul",
-  "follow_request.authorize": "Autorizeaza",
+  "empty_column.list": "Nu este nimic încă în această listă. Când membrii acestei liste vor începe să posteze, va apărea aici.",
+  "empty_column.lists": "Nu ai încă nici o listă. Când vei crea una, va apărea aici.",
+  "empty_column.mutes": "Nu ai oprit nici un utilizator incă.",
+  "empty_column.notifications": "Nu ai nici o notificare încă. Interacționează cu alții pentru a începe o conversație.",
+  "empty_column.public": "Nu este nimci aici încă! Scrie ceva public, sau urmărește alți utilizatori din alte instanțe pentru a porni fluxul",
+  "follow_request.authorize": "Autorizează",
   "follow_request.reject": "Respinge",
-  "getting_started.developers": "Dezvolatori",
-  "getting_started.documentation": "Documentatie",
-  "getting_started.find_friends": "Gaseste prietenii de pe Twitter",
-  "getting_started.heading": "Incepe",
-  "getting_started.invite": "Invita oameni",
-  "getting_started.open_source_notice": "Mastodon este o retea de socializare de tip open source. Poti contribui la dezvoltarea ei sau sa semnalezi erorirle pe GitHub la {github}.",
+  "getting_started.developers": "Dezvoltatori",
+  "getting_started.documentation": "Documentație",
+  "getting_started.find_friends": "Importă din Twitter",
+  "getting_started.heading": "Începe",
+  "getting_started.invite": "Invită oameni",
+  "getting_started.open_source_notice": "Mastodon este o rețea de socializare de tip open source. Puteți contribuii la dezvoltarea ei sau să semnalați erorile pe GitHub la {github}.",
   "getting_started.security": "Securitate",
   "getting_started.terms": "Termenii de Utilizare",
-  "home.column_settings.basic": "De baza",
-  "home.column_settings.show_reblogs": "Arata promovarile",
-  "home.column_settings.show_replies": "Arata raspunsurile",
-  "keyboard_shortcuts.back": "navigheaza inapoi",
-  "keyboard_shortcuts.blocked": "sa deschida lista utilizatorilor blocati",
-  "keyboard_shortcuts.boost": "sa promoveze",
-  "keyboard_shortcuts.column": "sa focuzeze o postare in una dintre coloane",
+  "home.column_settings.basic": "De bază",
+  "home.column_settings.show_reblogs": "Arată redistribuirile",
+  "home.column_settings.show_replies": "Arată răspunsurile",
+  "keyboard_shortcuts.back": "navighează inapoi",
+  "keyboard_shortcuts.blocked": "să deschidă lista utilizatorilor blocați",
+  "keyboard_shortcuts.boost": "să redistribuie",
+  "keyboard_shortcuts.column": "să focuzeze o postare in una dintre coloane",
   "keyboard_shortcuts.compose": "sa focuzeze zona de compunere",
   "keyboard_shortcuts.description": "Descriere",
   "keyboard_shortcuts.direct": "sa deschida coloane de mesaje directe",
@@ -148,9 +149,9 @@
   "keyboard_shortcuts.favourite": "sa adauge la favorite",
   "keyboard_shortcuts.favourites": "sa deschida lista cu favorite",
   "keyboard_shortcuts.federated": "sa deschida fluxul global",
-  "keyboard_shortcuts.heading": "Comenzi din tastature",
+  "keyboard_shortcuts.heading": "Comenzi din tastatură",
   "keyboard_shortcuts.home": "sa deschida fluxul principal",
-  "keyboard_shortcuts.hotkey": "Prescurtari",
+  "keyboard_shortcuts.hotkey": "Prescurtări",
   "keyboard_shortcuts.legend": "sa afiseze aceasta legenda",
   "keyboard_shortcuts.local": "sa deschida fluxul local",
   "keyboard_shortcuts.mention": "sa mentioneze autorul",
@@ -167,170 +168,170 @@
   "keyboard_shortcuts.toot": "sa inceapa o noua postare",
   "keyboard_shortcuts.unfocus": "sa dezactiveze compunerea/cautarea",
   "keyboard_shortcuts.up": "sa mute mai sus in lista",
-  "lightbox.close": "Inchide",
-  "lightbox.next": "Urmatorul",
+  "lightbox.close": "Închide",
+  "lightbox.next": "Următorul",
   "lightbox.previous": "Precedentul",
-  "lists.account.add": "Adauga in lista",
-  "lists.account.remove": "Elimina din lista",
-  "lists.delete": "Sterge lista",
-  "lists.edit": "Editeaza lista",
-  "lists.new.create": "Adauga lista",
-  "lists.new.title_placeholder": "Titlul pentru noua lista",
-  "lists.search": "Cauta printre persoanale pe care le urmaresti",
+  "lists.account.add": "Adaugă în listă",
+  "lists.account.remove": "Elimină din listă",
+  "lists.delete": "Șterge listă",
+  "lists.edit": "Editează lista",
+  "lists.new.create": "Adaugă listă",
+  "lists.new.title_placeholder": "Titlu pentru noua listă",
+  "lists.search": "Caută printre persoanale pe care le urmărești",
   "lists.subheading": "Listele tale",
-  "loading_indicator.label": "Incarcare...",
-  "media_gallery.toggle_visible": "Comutati vizibilitatea",
-  "missing_indicator.label": "Nu a fost gasit",
-  "missing_indicator.sublabel": "Aceasta resursa nu a putut fi gasita",
-  "mute_modal.hide_notifications": "Ascunzi notificarile de la acest utilizator?",
-  "navigation_bar.apps": "Aplicatii mobile",
-  "navigation_bar.blocks": "Utilizatori blocati",
+  "loading_indicator.label": "Încărcare...",
+  "media_gallery.toggle_visible": "Comutați vizibilitatea",
+  "missing_indicator.label": "Nu a fost găsit",
+  "missing_indicator.sublabel": "Această resursă nu a putut fi găsită",
+  "mute_modal.hide_notifications": "Ascunzi notificările de la acest utilizator?",
+  "navigation_bar.apps": "Aplicații mobile",
+  "navigation_bar.blocks": "Utilizatori blocați",
   "navigation_bar.community_timeline": "Flux local",
-  "navigation_bar.compose": "Compune o noua postare",
+  "navigation_bar.compose": "Compune o nouă postare",
   "navigation_bar.direct": "Mesaje directe",
-  "navigation_bar.discover": "Descopera",
+  "navigation_bar.discover": "Descoperă",
   "navigation_bar.domain_blocks": "Domenii ascunse",
-  "navigation_bar.edit_profile": "Editeaza profilul",
+  "navigation_bar.edit_profile": "Editează profilul",
   "navigation_bar.favourites": "Favorite",
   "navigation_bar.filters": "Cuvinte oprite",
-  "navigation_bar.follow_requests": "Cereri de urmarire",
-  "navigation_bar.info": "Despre aceasta instanta",
-  "navigation_bar.keyboard_shortcuts": "Prescurtari",
+  "navigation_bar.follow_requests": "Cereri de urmărire",
+  "navigation_bar.info": "Despre această instanță",
+  "navigation_bar.keyboard_shortcuts": "Prescurtări",
   "navigation_bar.lists": "Liste",
   "navigation_bar.logout": "Deconectare",
-  "navigation_bar.mutes": "Utilizatori opriti",
+  "navigation_bar.mutes": "Utilizatori opriți",
   "navigation_bar.personal": "Personal",
-  "navigation_bar.pins": "Postari fixate",
-  "navigation_bar.preferences": "Preferinte",
+  "navigation_bar.pins": "Postări fixate",
+  "navigation_bar.preferences": "Preferințe",
   "navigation_bar.public_timeline": "Flux global",
   "navigation_bar.security": "Securitate",
-  "notification.favourite": "{name} a adaugat statusul tau la favorite",
-  "notification.follow": "{name} te urmareste",
-  "notification.mention": "{name} te-a mentionat",
+  "notification.favourite": "{name} a adăugat statusul tău la favorite",
+  "notification.follow": "{name} te urmărește",
+  "notification.mention": "{name} te-a menționat",
   "notification.reblog": "{name} a redistribuit postarea ta",
-  "notifications.clear": "Sterge notificarile",
-  "notifications.clear_confirmation": "Esti sigur ca vrei sa stergi toate notificarile?",
-  "notifications.column_settings.alert": "Notificari desktop",
+  "notifications.clear": "Șterge notificările",
+  "notifications.clear_confirmation": "Ești sigur că vrei să ștergi toate notificările?",
+  "notifications.column_settings.alert": "Notificări pe desktop",
   "notifications.column_settings.favourite": "Favorite:",
-  "notifications.column_settings.follow": "Noi urmaritori:",
-  "notifications.column_settings.mention": "Mentiuni:",
-  "notifications.column_settings.push": "Notificari push",
+  "notifications.column_settings.follow": "Noi urmăritori:",
+  "notifications.column_settings.mention": "Mențiuni:",
+  "notifications.column_settings.push": "Notificări push",
   "notifications.column_settings.push_meta": "Acest dispozitiv",
   "notifications.column_settings.reblog": "Redistribuite:",
-  "notifications.column_settings.show": "Arata in coloana",
-  "notifications.column_settings.sound": "Reda sunet",
-  "notifications.group": "{count} notificari",
+  "notifications.column_settings.show": "Arată în coloană",
+  "notifications.column_settings.sound": "Redă sunet",
+  "notifications.group": "{count} notificări",
   "onboarding.done": "Gata",
-  "onboarding.next": "Urmatorul",
-  "onboarding.page_five.public_timelines": "Fluxul local afiseaza postarile publice de la toti utilizatorii pe {domain}. Fluxul global afiseaza postarile publice de la toti utilizatorii din reteaua mastodon pe care utilizatorii de pe {domain} ii urmaresc. Acestea sunt fluxurile publice, un mod grozav de a descoperi oameni noi.",
-  "onboarding.page_four.home": "Fluxul Acasa arata postarile celor pe care ii urmaresti.",
-  "onboarding.page_four.notifications": "Coloana de notificari arata cand cineva interactioneaza cu tine.",
-  "onboarding.page_one.federation": "Mastodon este o retea independenta de servere care impreuna formeaza o imensa retea de socializare. Noi numim aceste servere istante.",
-  "onboarding.page_one.full_handle": "Id-ul tau complet",
-  "onboarding.page_one.handle_hint": "Aceasta este ceea ce trebuie sa le spuneti prietenilor cand vor sa va caute.",
+  "onboarding.next": "Următorul",
+  "onboarding.page_five.public_timelines": "Fluxul local afișează postările publice de la toți utilizatorii pe {domain}. Fluxul global afișează postările publice de la toți utilizatorii din rețeaua mastodon pe care utilizatorii de pe {domain} ii urmăresc. Acestea sunt fluxurile publice, un mod grozav de a descoperi oameni noi.",
+  "onboarding.page_four.home": "Fluxul Acasă arată postarile celor pe care ii urmărești.",
+  "onboarding.page_four.notifications": "Coloana de notificări arată când cineva interacționează cu tine.",
+  "onboarding.page_one.federation": "Mastodon este o rețea independentă de servere care împreună formează o imensă retea de socializare. Noi numim aceste servere istanțe.",
+  "onboarding.page_one.full_handle": "Id-ul tău complet",
+  "onboarding.page_one.handle_hint": "Asta este ceea ce trebuie să le spuneți prietenilor când vor să vă caute.",
   "onboarding.page_one.welcome": "Bun venit la Mastodon!",
-  "onboarding.page_six.admin": "Administatorul acestei instante este {admin}.",
+  "onboarding.page_six.admin": "Administatorul acestei instanțe este {admin}.",
   "onboarding.page_six.almost_done": "Aproape gata...",
-  "onboarding.page_six.appetoot": "Distractie placuta!",
-  "onboarding.page_six.apps_available": "Acestea sunt {apps} disponibile pentru iOS, Android si alte platforme.",
-  "onboarding.page_six.github": "Mastodon este un software de tip open source. Poti raporta erori, cere facilitati, sau sa contribuiti pe {github}.",
-  "onboarding.page_six.guidelines": "instructiunile comunitatii",
-  "onboarding.page_six.read_guidelines": "Va rugam cititi {domain} {guidelines}!",
-  "onboarding.page_six.various_app": "aplicatii mobile",
-  "onboarding.page_three.profile": "Editeaza poriflul pentru a schimba avatarul, bio si numele. Tot acolo vei gasi si alte preferinte.",
-  "onboarding.page_three.search": "Utilizeaza bara de cautare pentru a gasi oameni sau hastaguri precum {illustration} si {introductions}. Pentru a gasi o persoana care nu este inscrisa pe aceasta instanta foloseste id-ul lor complet.",
-  "onboarding.page_two.compose": "Scrie postari din coloana pentru compunere. Poti incarca imagini, schimba setarile de confidentialitate, si adauga advertisemente asupra continutului cu ajutorul iconitelor.",
+  "onboarding.page_six.appetoot": "Distracție plăcută!",
+  "onboarding.page_six.apps_available": "Acestea sunt {apps} disponibile pentru iOS, Android și alte platforme.",
+  "onboarding.page_six.github": "Mastodon este un software de tip open source. Puteți raporta erori, cere facilități, sau să contribuiți pe {github}.",
+  "onboarding.page_six.guidelines": "regulamentul comunității",
+  "onboarding.page_six.read_guidelines": "Vă rugăm citiți {domain} {guidelines}!",
+  "onboarding.page_six.various_app": "aplicații mobile",
+  "onboarding.page_three.profile": "Editează profilul pentru a modifica fotografia de profil, descrierea si numele. Tot acolo vei găsi și alte preferințe.",
+  "onboarding.page_three.search": "Utilizează bara de căutare pentru a găsi oameni sau hastaguri precum {illustration} și {introductions}. Pentru a găsi o persoană care nu este înscrisă pe această instanță folosește id-ul lui complet.",
+  "onboarding.page_two.compose": "Scrie postări din coloana pentru compunere. Poți încărca imagini, schimba setările de confidențialitate, și adăuga advertisemente asupra conținutului.",
   "onboarding.skip": "Omite",
-  "privacy.change": "Ajusteaza confidentialitatea statusului",
-  "privacy.direct.long": "Posteaza doar pentru utilizatorii mentionati",
+  "privacy.change": "Cine vede asta",
+  "privacy.direct.long": "Postează doar pentru utilizatorii menționați",
   "privacy.direct.short": "Direct",
-  "privacy.private.long": "Posteaza doar pentru urmaritori",
-  "privacy.private.short": "Doar urmaritori",
-  "privacy.public.long": "Posteaza in fluxul public",
+  "privacy.private.long": "Postează doar pentru urmăritori",
+  "privacy.private.short": "Doar urmăritorii",
+  "privacy.public.long": "Postează în fluxul public",
   "privacy.public.short": "Public",
   "privacy.unlisted.long": "Nu afisa in fluxul public",
   "privacy.unlisted.short": "Nelistat",
-  "regeneration_indicator.label": "Incarcare…",
-  "regeneration_indicator.sublabel": "Fluxul tau este in preparare!",
+  "regeneration_indicator.label": "Încărcare…",
+  "regeneration_indicator.sublabel": "Fluxul tău este în preparare!",
   "relative_time.days": "{number}z",
   "relative_time.hours": "{number}h",
   "relative_time.just_now": "acum",
-  "relative_time.minutes": "{number}l",
+  "relative_time.minutes": "{number}m",
   "relative_time.seconds": "{number}s",
-  "reply_indicator.cancel": "Anuleaza",
-  "report.forward": "Redirectioneaza catre {target}",
-  "report.forward_hint": "Acest cont este de pe un alt server. Trimitem o copie anonima a raportului si acolo?",
-  "report.hint": "Sesizarea va fi trimsa catre moderatorii acestei instante. Poti oferi o explicatie pentru aceasta sesizare mai jos:",
-  "report.placeholder": "Comentarii optionale",
+  "reply_indicator.cancel": "Anulează",
+  "report.forward": "Redirecționează catre {target}",
+  "report.forward_hint": "Acest cont este de pe un alt server. Trimitem o copie anonimă a raportului și acolo?",
+  "report.hint": "Sesizarea va fi trimsă către moderatorii acestei instanțe. Poți oferi o explicație pentru această sesizare mai jos:",
+  "report.placeholder": "Comentarii opționale",
   "report.submit": "Trimite",
-  "report.target": "Raporteaza {target}",
-  "search.placeholder": "Cauta",
-  "search_popout.search_format": "Formate pentru cautare avansata",
-  "search_popout.tips.full_text": "Textele simple returneaza statusuri pe care le-ai scris, favorizat, redistribuit, sau in care au fost mentionate, deasmenea si utilizatorii sau hastagurile care se potrivesc.",
+  "report.target": "Raportează {target}",
+  "search.placeholder": "Caută",
+  "search_popout.search_format": "Formate pentru căutare avansată",
+  "search_popout.tips.full_text": "Textele simple returnează statusuri pe care le-ai scris, favorizat, redistribuit, sau în care sunt menționate , deasmenea și utilizatorii sau hastagurile care se potrivesc.",
   "search_popout.tips.hashtag": "hashtag",
   "search_popout.tips.status": "status",
-  "search_popout.tips.text": "Textele simple returneaza numele, numele de utilizarori si hastagurile care se potrivesc",
+  "search_popout.tips.text": "Textele simple returnează nume, nume de utilizarori și hastagurile care se potrivesc",
   "search_popout.tips.user": "utilizator",
   "search_results.accounts": "Oameni",
   "search_results.hashtags": "Hashtaguri",
-  "search_results.statuses": "Postari",
+  "search_results.statuses": "Postări",
   "search_results.total": "{count, number} {count, plural, one {result} other {results}}",
-  "standalone.public_title": "O privire in interior...",
-  "status.block": "Blocheaza @{name}",
+  "standalone.public_title": "Se întâmplă acum",
+  "status.block": "Blochează @{name}",
   "status.cancel_reblog_private": "Nedistribuit",
-  "status.cannot_reblog": "Aceasta postare nu poate fi redistribuita",
-  "status.delete": "Sterge",
-  "status.detailed_status": "Conversatia detailata",
+  "status.cannot_reblog": "Această postare nu poate fi redistribuită",
+  "status.delete": "Șterge",
+  "status.detailed_status": "Conversația detailată",
   "status.direct": "Mesaj direct @{name}",
-  "status.embed": "Incorporare",
+  "status.embed": "Încorporare",
   "status.favourite": "Favorite",
   "status.filtered": "Sortate",
-  "status.load_more": "Incarca mai multe",
-  "status.media_hidden": "Media ascunsa",
-  "status.mention": "Mentioneaza @{name}",
+  "status.load_more": "Încarcă mai multe",
+  "status.media_hidden": "Media ascunsă",
+  "status.mention": "Mentionează @{name}",
   "status.more": "Mai mult",
-  "status.mute": "Opreste @{name}",
-  "status.mute_conversation": "Opreste conversatia",
+  "status.mute": "Oprește @{name}",
+  "status.mute_conversation": "Oprește conversația",
   "status.open": "Extinde acest status",
-  "status.pin": "Fixeaza pe profil",
-  "status.pinned": "Postare fixata",
+  "status.pin": "Fixează pe profil",
+  "status.pinned": "Postare fixată",
   "status.reblog": "Redistribuie",
-  "status.reblog_private": "Redistribuie la audienta originala",
+  "status.reblog_private": "Redistribuie către audiența originală",
   "status.reblogged_by": "{name} redistribuit",
-  "status.reblogs.empty": "Nimeni nu a redistribuit aceasta postare inca. Cand cineva o va face, va aparea aici.",
-  "status.redraft": "Sterge si adauga la ciorne",
-  "status.reply": "Raspunde",
-  "status.replyAll": "Raspunde la topic",
-  "status.report": "Raporteaza @{name}",
-  "status.sensitive_toggle": "Afiseaza",
-  "status.sensitive_warning": "Continut sensibil",
+  "status.reblogs.empty": "Nimeni nu a redistribuit această postare până acum. Când cineva o va face, va apărea aici.",
+  "status.redraft": "Șterge și adaugă la ciorne",
+  "status.reply": "Răspunde",
+  "status.replyAll": "Răspunde la topic",
+  "status.report": "Raportează @{name}",
+  "status.sensitive_toggle": "Afișează",
+  "status.sensitive_warning": "Conținut sensibil",
   "status.share": "Distribuie",
-  "status.show_less": "Arata mai putin",
-  "status.show_less_all": "Arata mai putin pentru toti",
-  "status.show_more": "Arata mai mult",
-  "status.show_more_all": "Arata mai mult pentru toti",
-  "status.unmute_conversation": "Reporneste conversatia",
-  "status.unpin": "Elibereaza din profil",
+  "status.show_less": "Arată mai puțin",
+  "status.show_less_all": "Arată mai puțin pentru toți",
+  "status.show_more": "Arată mai mult",
+  "status.show_more_all": "Arată mai mult pentru toți",
+  "status.unmute_conversation": "Repornește conversația",
+  "status.unpin": "Eliberează din profil",
   "tabs_bar.federated_timeline": "Global",
-  "tabs_bar.home": "Acasa",
+  "tabs_bar.home": "Acasă",
   "tabs_bar.local_timeline": "Local",
-  "tabs_bar.notifications": "Notificari",
-  "tabs_bar.search": "Cautare",
+  "tabs_bar.notifications": "Notificări",
+  "tabs_bar.search": "Căutare",
   "trends.count_by_accounts": "{count} {rawCount, plural, one {person} other {people}} vorbesc",
-  "ui.beforeunload": "Ciorna se va priede daca parasesti pagina.",
-  "upload_area.title": "Trage si elibereaza pentru a incarca",
-  "upload_button.label": "Adauga media (JPEG, PNG, GIF, WebM, MP4, MOV)",
-  "upload_form.description": "Adauga o descriere pentru persoanele cu deficiente de vedere",
+  "ui.beforeunload": "Postarea se va pierde dacă părăsești pagina.",
+  "upload_area.title": "Trage și eliberează pentru a încărca",
+  "upload_button.label": "Adaugă media (JPEG, PNG, GIF, WebM, MP4, MOV)",
+  "upload_form.description": "Adaugă o descriere pentru persoanele cu deficiențe de vedere",
   "upload_form.focus": "Taie",
-  "upload_form.undo": "Sterge",
-  "upload_progress.label": "Se Incarca...",
-  "video.close": "Inchide video",
-  "video.exit_fullscreen": "Inchide",
+  "upload_form.undo": "Șterge",
+  "upload_progress.label": "Se Încarcă...",
+  "video.close": "Închide video",
+  "video.exit_fullscreen": "Închide",
   "video.expand": "Extinde video",
-  "video.fullscreen": "Ecran intreg",
+  "video.fullscreen": "Ecran întreg",
   "video.hide": "Ascunde video",
-  "video.mute": "Opreste sonorul",
-  "video.pause": "Pauza",
+  "video.mute": "Oprește sonorul",
+  "video.pause": "Pauză",
   "video.play": "Redare",
-  "video.unmute": "Reporneste sunetul"
+  "video.unmute": "Repornește sunetul"
 }
diff --git a/app/javascript/mastodon/locales/ru.json b/app/javascript/mastodon/locales/ru.json
index 7499f03ea..8961136a3 100644
--- a/app/javascript/mastodon/locales/ru.json
+++ b/app/javascript/mastodon/locales/ru.json
@@ -15,6 +15,7 @@
   "account.follows.empty": "Этот пользователь ни на кого не подписан.",
   "account.follows_you": "Подписан(а) на Вас",
   "account.hide_reblogs": "Скрыть продвижения от @{name}",
+  "account.link_verified_on": "Ownership of this link was checked on {date}",
   "account.media": "Медиа",
   "account.mention": "Упомянуть",
   "account.moved_to": "Ищите {name} здесь:",
diff --git a/app/javascript/mastodon/locales/sk.json b/app/javascript/mastodon/locales/sk.json
index edfd69a25..1264b6d08 100644
--- a/app/javascript/mastodon/locales/sk.json
+++ b/app/javascript/mastodon/locales/sk.json
@@ -15,6 +15,7 @@
   "account.follows.empty": "Tento užívateľ ešte nikoho nenásleduje.",
   "account.follows_you": "Následuje ťa",
   "account.hide_reblogs": "Skryť povýšenia od @{name}",
+  "account.link_verified_on": "Ownership of this link was checked on {date}",
   "account.media": "Médiá",
   "account.mention": "Spomeň @{name}",
   "account.moved_to": "{name} sa presunul/a na:",
@@ -89,7 +90,7 @@
   "confirmations.mute.confirm": "Ignoruj",
   "confirmations.mute.message": "Naozaj chcete ignorovať {name}?",
   "confirmations.redraft.confirm": "Vyčistiť a prepísať",
-  "confirmations.redraft.message": "Si si istý/á, že chceš vymazať a prepísať tento príspevok? Jeho nadobudnuté odpovede, povýšenia a obľúbenia, ale i odpovede na pôvodný príspevok budú odlúčené.",
+  "confirmations.redraft.message": "Si si istý/á, že chceš premazať a prepísať tento príspevok? Jeho nadobudnuté odpovede, povýšenia a obľúbenia, ale i odpovede na pôvodný príspevok budú odlúčené.",
   "confirmations.unfollow.confirm": "Nesledovať",
   "confirmations.unfollow.message": "Naozaj chcete prestať sledovať {name}?",
   "embed.instructions": "Umiestni kód uvedený nižšie pre pridanie tohto statusu na tvoju web stránku.",
@@ -111,16 +112,16 @@
   "empty_column.blocks": "Ešte si nikoho nezablokoval/a.",
   "empty_column.community": "Lokálna časová os je prázdna. Napíšte niečo, aby sa to tu začalo hýbať!",
   "empty_column.direct": "Ešte nemáš žiadne súkromné správy. Keď nejakú pošleš, alebo dostaneš, ukáže sa tu.",
-  "empty_column.domain_blocks": "There are no hidden domains yet.",
-  "empty_column.favourited_statuses": "You don't have any favourite toots yet. When you favourite one, it will show up here.",
+  "empty_column.domain_blocks": "Žiadne domény ešte niesú skryté.",
+  "empty_column.favourited_statuses": "Nemáš obľúbené ešte žiadne príspevky. Keď si nejaký obľúbiš, bude zobrazený práve tu.",
   "empty_column.favourites": "Tento toot si ešte nikto neobľúbil. Ten kto si ho obľúbi, bude zobrazený tu.",
-  "empty_column.follow_requests": "You don't have any follow requests yet. When you receive one, it will show up here.",
+  "empty_column.follow_requests": "Ešte nemáš žiadne požiadavky o následovanie. Keď nejaké dostaneš, budú tu zobrazené.",
   "empty_column.hashtag": "Pod týmto hashtagom sa ešte nič nenachádza.",
   "empty_column.home": "Tvoja lokálna osa je zatiaľ prázdna! Pre začiatok navštív {public}, alebo použi vyhľadávanie a nájdi tak aj iných užívateľov.",
   "empty_column.home.public_timeline": "verejná časová os",
   "empty_column.list": "Tento zoznam je ešte prázdny. Keď ale členovia tohoto zoznamu napíšu nové správy, tak tie sa objavia priamo tu.",
-  "empty_column.lists": "You don't have any lists yet. When you create one, it will show up here.",
-  "empty_column.mutes": "You haven't muted any users yet.",
+  "empty_column.lists": "Nemáš ešte žiadne zoznamy. Keď nejaký vytvoríš, bude zobrazený práve tu.",
+  "empty_column.mutes": "Ešte si nestĺmil žiadných užívateľov.",
   "empty_column.notifications": "Nemáš ešte žiadne oznámenia. Zapoj sa s niekym do debaty a komunikuj s ostatnými aby diskusia mohla začať.",
   "empty_column.public": "Ešte tu nič nie je. Napíš niečo verejne alebo začnite sledovať užívateľov z iných Mastodon serverov, aby tu tak niečo pribudlo",
   "follow_request.authorize": "Povoľ prístup",
@@ -137,32 +138,32 @@
   "home.column_settings.show_reblogs": "Zobraziť povýšené",
   "home.column_settings.show_replies": "Ukázať odpovede",
   "keyboard_shortcuts.back": "dostať sa naspäť",
-  "keyboard_shortcuts.blocked": "to open blocked users list",
+  "keyboard_shortcuts.blocked": "otvor zoznam blokovaných užívateľov",
   "keyboard_shortcuts.boost": "vyzdvihnúť",
   "keyboard_shortcuts.column": "zamerať sa na status v jednom zo stĺpcov",
   "keyboard_shortcuts.compose": "zamerať sa na písaciu plochu",
   "keyboard_shortcuts.description": "Popis",
-  "keyboard_shortcuts.direct": "to open direct messages column",
+  "keyboard_shortcuts.direct": "otvor panel súkromných správ",
   "keyboard_shortcuts.down": "posunúť sa dole v zozname",
   "keyboard_shortcuts.enter": "otvoriť správu",
   "keyboard_shortcuts.favourite": "pridať do obľúbených",
-  "keyboard_shortcuts.favourites": "to open favourites list",
-  "keyboard_shortcuts.federated": "to open federated timeline",
+  "keyboard_shortcuts.favourites": "otvor zoznam obľúbených",
+  "keyboard_shortcuts.federated": "otvor federovanú časovú os",
   "keyboard_shortcuts.heading": "Klávesové skratky",
-  "keyboard_shortcuts.home": "to open home timeline",
+  "keyboard_shortcuts.home": "otvor domácu časovú os",
   "keyboard_shortcuts.hotkey": "Klávesa",
   "keyboard_shortcuts.legend": "zobraziť túto legendu",
-  "keyboard_shortcuts.local": "to open local timeline",
+  "keyboard_shortcuts.local": "otvor miestnu časovú os",
   "keyboard_shortcuts.mention": "spomenúť autora",
-  "keyboard_shortcuts.muted": "to open muted users list",
-  "keyboard_shortcuts.my_profile": "to open your profile",
-  "keyboard_shortcuts.notifications": "to open notifications column",
-  "keyboard_shortcuts.pinned": "to open pinned toots list",
-  "keyboard_shortcuts.profile": "to open author's profile",
+  "keyboard_shortcuts.muted": "otvor zoznam stíšených užívateľov",
+  "keyboard_shortcuts.my_profile": "otvor svoj profil",
+  "keyboard_shortcuts.notifications": "otvor panel oboznámení",
+  "keyboard_shortcuts.pinned": "otvor zoznam pripnutých príspevkov",
+  "keyboard_shortcuts.profile": "otvor autorov profil",
   "keyboard_shortcuts.reply": "odpovedať",
-  "keyboard_shortcuts.requests": "to open follow requests list",
+  "keyboard_shortcuts.requests": "otvor zoznam požiadavok k následovaniu",
   "keyboard_shortcuts.search": "zamerať sa na vyhľadávanie",
-  "keyboard_shortcuts.start": "to open \"get started\" column",
+  "keyboard_shortcuts.start": "otvor panel ''začíname''",
   "keyboard_shortcuts.toggle_hidden": "ukáž/skry text za CW",
   "keyboard_shortcuts.toot": "začať úplne novú hlášku",
   "keyboard_shortcuts.unfocus": "nesústrediť sa na písaciu plochu, alebo hľadanie",
@@ -183,10 +184,10 @@
   "missing_indicator.label": "Nenájdené",
   "missing_indicator.sublabel": "Tento zdroj sa nepodarilo nájsť",
   "mute_modal.hide_notifications": "Skryť notifikácie od tohoto užívateľa?",
-  "navigation_bar.apps": "Mobile apps",
+  "navigation_bar.apps": "Mobilné aplikácie",
   "navigation_bar.blocks": "Blokovaní užívatelia",
   "navigation_bar.community_timeline": "Lokálna časová os",
-  "navigation_bar.compose": "Compose new toot",
+  "navigation_bar.compose": "Napíš nový príspevok",
   "navigation_bar.direct": "Súkromné správy",
   "navigation_bar.discover": "Objavuj",
   "navigation_bar.domain_blocks": "Skryté domény",
@@ -280,7 +281,7 @@
   "status.cancel_reblog_private": "Nezdieľaj",
   "status.cannot_reblog": "Tento príspevok nemôže byť re-tootnutý",
   "status.delete": "Zmazať",
-  "status.detailed_status": "Detailed conversation view",
+  "status.detailed_status": "Podrobný náhľad celej konverzácie",
   "status.direct": "Súkromná správa @{name}",
   "status.embed": "Vložiť",
   "status.favourite": "Páči sa mi",
@@ -297,7 +298,7 @@
   "status.reblog": "Povýšiť",
   "status.reblog_private": "Povýš k pôvodnému publiku",
   "status.reblogged_by": "{name} povýšil/a",
-  "status.reblogs.empty": "No one has boosted this toot yet. When someone does, they will show up here.",
+  "status.reblogs.empty": "Nikto ešte nepovýšil tento príspevok. Keď tak niekto urobí, bude to zobrazené práve tu.",
   "status.redraft": "Vymaž a prepíš",
   "status.reply": "Odpovedať",
   "status.replyAll": "Odpovedať na diskusiu",
diff --git a/app/javascript/mastodon/locales/sl.json b/app/javascript/mastodon/locales/sl.json
index 8f6c2e3d5..6250aab62 100644
--- a/app/javascript/mastodon/locales/sl.json
+++ b/app/javascript/mastodon/locales/sl.json
@@ -15,6 +15,7 @@
   "account.follows.empty": "This user doesn't follow anyone yet.",
   "account.follows_you": "Ti sledi",
   "account.hide_reblogs": "Skrij napuhke od @{name}",
+  "account.link_verified_on": "Ownership of this link was checked on {date}",
   "account.media": "Mediji",
   "account.mention": "Omeni @{name}",
   "account.moved_to": "{name} se je premaknil na:",
diff --git a/app/javascript/mastodon/locales/sr-Latn.json b/app/javascript/mastodon/locales/sr-Latn.json
index 0f56f642a..0ef07a170 100644
--- a/app/javascript/mastodon/locales/sr-Latn.json
+++ b/app/javascript/mastodon/locales/sr-Latn.json
@@ -15,6 +15,7 @@
   "account.follows.empty": "This user doesn't follow anyone yet.",
   "account.follows_you": "Prati Vas",
   "account.hide_reblogs": "Sakrij podrške koje daje korisnika @{name}",
+  "account.link_verified_on": "Ownership of this link was checked on {date}",
   "account.media": "Mediji",
   "account.mention": "Pomeni korisnika @{name}",
   "account.moved_to": "{name} se pomerio na:",
diff --git a/app/javascript/mastodon/locales/sr.json b/app/javascript/mastodon/locales/sr.json
index 81a37cc4c..ca2c1b225 100644
--- a/app/javascript/mastodon/locales/sr.json
+++ b/app/javascript/mastodon/locales/sr.json
@@ -1,6 +1,6 @@
 {
   "account.badges.bot": "Бот",
-  "account.block": "Блокирај корисника @{name}",
+  "account.block": "Блокирај @{name}",
   "account.block_domain": "Сакриј све са домена {domain}",
   "account.blocked": "Блокиран",
   "account.direct": "Директна порука @{name}",
@@ -9,12 +9,13 @@
   "account.edit_profile": "Измени профил",
   "account.endorse": "Приказати на профилу",
   "account.follow": "Запрати",
-  "account.followers": "Пратиоца",
-  "account.followers.empty": "Нико још увек не прати овог корисника.",
+  "account.followers": "Пратиоци",
+  "account.followers.empty": "Тренутно нико не прати овог корисника.",
   "account.follows": "Прати",
-  "account.follows.empty": "Овај корисник не прати никога за сад.",
+  "account.follows.empty": "Корисник тренутно не прати никога.",
   "account.follows_you": "Прати Вас",
   "account.hide_reblogs": "Сакриј подршке које даје корисника @{name}",
+  "account.link_verified_on": "Ownership of this link was checked on {date}",
   "account.media": "Медији",
   "account.mention": "Помени корисника @{name}",
   "account.moved_to": "{name} се померио на:",
@@ -22,7 +23,7 @@
   "account.mute_notifications": "Искључи обавештења од корисника @{name}",
   "account.muted": "Ућуткан",
   "account.posts": "Трубе",
-  "account.posts_with_replies": "Трубе са одговорима",
+  "account.posts_with_replies": "Трубе и одговори",
   "account.report": "Пријави @{name}",
   "account.requested": "Чекам одобрење. Кликните да поништите захтев за праћење",
   "account.share": "Подели профил корисника @{name}",
@@ -44,17 +45,17 @@
   "bundle_modal_error.message": "Нешто није било у реду при учитавању ове компоненте.",
   "bundle_modal_error.retry": "Покушајте поново",
   "column.blocks": "Блокирани корисници",
-  "column.community": "Локална лајна",
+  "column.community": "Локална временска линија",
   "column.direct": "Директне поруке",
   "column.domain_blocks": "Скривени домени",
-  "column.favourites": "Омиљени",
+  "column.favourites": "Омиљене",
   "column.follow_requests": "Захтеви за праћење",
   "column.home": "Почетна",
   "column.lists": "Листе",
   "column.mutes": "Ућуткани корисници",
   "column.notifications": "Обавештења",
-  "column.pins": "Прикачени тутови",
-  "column.public": "Федерисана лајна",
+  "column.pins": "Прикачене трубе",
+  "column.public": "Здружена временска линија",
   "column_back_button.label": "Назад",
   "column_header.hide_settings": "Сакриј поставке",
   "column_header.moveLeft_settings": "Помери колону улево",
@@ -70,12 +71,12 @@
   "compose_form.lock_disclaimer": "Ваш налог није {locked}. Свако може да Вас запрати и да види објаве намењене само Вашим пратиоцима.",
   "compose_form.lock_disclaimer.lock": "закључан",
   "compose_form.placeholder": "Шта Вам је на уму?",
-  "compose_form.publish": "Тутни",
+  "compose_form.publish": "Труби",
   "compose_form.publish_loud": "{publish}!",
   "compose_form.sensitive.marked": "Медији су означени као осетљиви",
   "compose_form.sensitive.unmarked": "Медији су означени као не-осетљиви",
-  "compose_form.spoiler.marked": "Текст је скривен иза упозорења",
-  "compose_form.spoiler.unmarked": "Текст није скривен",
+  "compose_form.spoiler.marked": "Текст је сакривен иза упозорења",
+  "compose_form.spoiler.unmarked": "Текст није сакривен",
   "compose_form.spoiler_placeholder": "Овде упишите упозорење",
   "confirmation_modal.cancel": "Поништи",
   "confirmations.block.confirm": "Блокирај",
@@ -89,7 +90,7 @@
   "confirmations.mute.confirm": "Ућуткај",
   "confirmations.mute.message": "Да ли стварно желите да ућуткате корисника {name}?",
   "confirmations.redraft.confirm": "Избриши и преправи",
-  "confirmations.redraft.message": "Да ли сте сигурно да желите да избришете овај статус и да га преправите*? Омиљеновање и подршке ће бити изгубљене, а одговори на оригинални пост ће бити поништени.",
+  "confirmations.redraft.message": "Да ли сте сигурни да желите да избришете овај статус и да га преправите? Сва стављања у омиљене трубе, као и подршке ће бити изгубљене, а одговори на оригинални пост ће бити поништени.",
   "confirmations.unfollow.confirm": "Отпрати",
   "confirmations.unfollow.message": "Да ли сте сигурни да желите да отпратите корисника {name}?",
   "embed.instructions": "Угради овај статус на Ваш веб сајт копирањем кода испод.",
@@ -97,25 +98,25 @@
   "emoji_button.activity": "Активност",
   "emoji_button.custom": "Произвољно",
   "emoji_button.flags": "Заставе",
-  "emoji_button.food": "Храна & пиће",
-  "emoji_button.label": "Убаци смајли",
+  "emoji_button.food": "Храна и пиће",
+  "emoji_button.label": "Убаци емоџи",
   "emoji_button.nature": "Природа",
-  "emoji_button.not_found": "Нема смајлија!! (╯°□°)╯︵ ┻━┻",
+  "emoji_button.not_found": "Нема емоџија!! (╯°□°)╯︵ ┻━┻",
   "emoji_button.objects": "Објекти",
   "emoji_button.people": "Људи",
   "emoji_button.recent": "Најчешће коришћени",
   "emoji_button.search": "Претрага...",
   "emoji_button.search_results": "Резултати претраге",
   "emoji_button.symbols": "Симболи",
-  "emoji_button.travel": "Путовања & места",
+  "emoji_button.travel": "Путовања и места",
   "empty_column.blocks": "Још увек немате блокираних корисника.",
-  "empty_column.community": "Локална лајна је празна. Напишите нешто јавно да лајна продува!",
+  "empty_column.community": "Локална временска линија је празна. Напишите нешто јавно да започнете!",
   "empty_column.direct": "Још увек немате директних порука. Када пошаљете или примите једну, појавиће се овде.",
   "empty_column.domain_blocks": "Још увек нема сакривених домена.",
   "empty_column.favourited_statuses": "Још увек немате труба које су вам се свиделе. Када вам се једна свиди, појавиће се овде.",
   "empty_column.favourites": "Још увек се никоме није свидела ова труба. Када се некоме свиди, појавиће се овде.",
   "empty_column.follow_requests": "Још увек немате захтева за праћење. Када примите захтев, појавиће се овде.",
-  "empty_column.hashtag": "Тренутно нема ништа на овом хештегу.",
+  "empty_column.hashtag": "Тренутно нема ништа на овој означеној тараби.",
   "empty_column.home": "Ваша временска линија је празна! Посетите {public} или користите претрагу да почнете и да упознате нове људе.",
   "empty_column.home.public_timeline": "јавна временска линија",
   "empty_column.list": "У овој листи још нема ничега. Када чланови листе објаве нове статусе, они ће се појавити овде.",
@@ -147,7 +148,7 @@
   "keyboard_shortcuts.enter": "да отворите статус",
   "keyboard_shortcuts.favourite": "да означите као омиљено",
   "keyboard_shortcuts.favourites": "да отворите листу фаворита",
-  "keyboard_shortcuts.federated": "да отворите федерализовану временску линију",
+  "keyboard_shortcuts.federated": "да отворите здружену временску линију",
   "keyboard_shortcuts.heading": "Пречице на тастатури",
   "keyboard_shortcuts.home": "да отворите временску линију почетне",
   "keyboard_shortcuts.hotkey": "Пречица",
@@ -185,13 +186,13 @@
   "mute_modal.hide_notifications": "Сакриј обавештења од овог корисника?",
   "navigation_bar.apps": "Мобилне апликације",
   "navigation_bar.blocks": "Блокирани корисници",
-  "navigation_bar.community_timeline": "Локална лајна",
+  "navigation_bar.community_timeline": "Локална временска линија",
   "navigation_bar.compose": "Саставите нову трубу",
   "navigation_bar.direct": "Директне поруке",
   "navigation_bar.discover": "Откриј",
   "navigation_bar.domain_blocks": "Сакривени домени",
   "navigation_bar.edit_profile": "Измени профил",
-  "navigation_bar.favourites": "Омиљени",
+  "navigation_bar.favourites": "Омиљене",
   "navigation_bar.filters": "Пригушене речи",
   "navigation_bar.follow_requests": "Захтеви за праћење",
   "navigation_bar.info": "О овој инстанци",
@@ -200,14 +201,14 @@
   "navigation_bar.logout": "Одјава",
   "navigation_bar.mutes": "Ућуткани корисници",
   "navigation_bar.personal": "Personal",
-  "navigation_bar.pins": "Прикачени тутови",
+  "navigation_bar.pins": "Прикачене трубе",
   "navigation_bar.preferences": "Подешавања",
-  "navigation_bar.public_timeline": "Федерисана лајна",
-  "navigation_bar.security": "Сигурност",
-  "notification.favourite": "{name} је ставио Ваш статус као омиљени",
-  "notification.follow": "{name} Вас је запратио",
-  "notification.mention": "{name} Вас је поменуо",
-  "notification.reblog": "{name} је подржао(ла) Ваш статус",
+  "navigation_bar.public_timeline": "Здружена временска линија",
+  "navigation_bar.security": "Безбедност",
+  "notification.favourite": "{name} је ставио/ла Ваш статус као омиљени",
+  "notification.follow": "{name} Вас је запратио/ла",
+  "notification.mention": "{name} Вас је поменуо/ла",
+  "notification.reblog": "{name} је подржао/ла Ваш статус",
   "notifications.clear": "Очисти обавештења",
   "notifications.clear_confirmation": "Да ли сте сигурно да трајно желите да очистите Ваша обавештења?",
   "notifications.column_settings.alert": "Обавештења на радној површини",
@@ -222,18 +223,18 @@
   "notifications.group": "{count} обавештења",
   "onboarding.done": "Готово",
   "onboarding.next": "Следеће",
-  "onboarding.page_five.public_timelines": "Локална лајна приказује све јавне статусе од свих на домену {domain}. Федерисана лајна приказује јавне статусе од свих људи које прате корисници са домена {domain}. Ово су јавне лајне, сјајан начин да откријете нове људе.",
-  "onboarding.page_four.home": "Почетна лајна приказује статусе људи које Ви пратите.",
+  "onboarding.page_five.public_timelines": "Локална временска линија приказује све јавне статусе од свих на домену {domain}. Здружена временска линија приказује јавне статусе од свих људи које прате корисници са домена {domain}. Ово су јавне временске линије, сјајан начин да откријете нове људе.",
+  "onboarding.page_four.home": "Почетна временска линија приказује статусе људи које Ви пратите.",
   "onboarding.page_four.notifications": "Колона са обавештењима Вам приказује када неко прича са Вама.",
   "onboarding.page_one.federation": "Мастодонт је мрежа независних сервера који се увезују да направе једну већу друштвену мрежу. Ове сервере зовемо инстанцама.",
   "onboarding.page_one.full_handle": "Ваш пун надимак",
   "onboarding.page_one.handle_hint": "Ово бисте рекли својим пријатељима да траже.",
-  "onboarding.page_one.welcome": "Добродошли на Мастодонт!",
+  "onboarding.page_one.welcome": "Добродошли на Мастодон!",
   "onboarding.page_six.admin": "Администратор Ваше инстанце је {admin}.",
   "onboarding.page_six.almost_done": "Још мало, па готово...",
   "onboarding.page_six.appetoot": "Пријатутно!",
   "onboarding.page_six.apps_available": "Постоје {apps} доступне за iOS, Андроид и друге платформе.",
-  "onboarding.page_six.github": "Мастодонт је слободан софтвер отвореног кода. Можете пријављивати грешке, потраживати нове фунцкионалности, или учествујући у програмирању. Наш изворни код је овде: {github}.",
+  "onboarding.page_six.github": "Мастодон је слободан софтвер отвореног кода. Можете пријављивати грешке, потраживати нове фунцкионалности, или учествујући у програмирању. Наш изворни код је овде {github}.",
   "onboarding.page_six.guidelines": "смернице заједнице",
   "onboarding.page_six.read_guidelines": "Прочитејте {guidelines} домена {domain}!",
   "onboarding.page_six.various_app": "мобилне апликације",
@@ -248,7 +249,7 @@
   "privacy.private.short": "Само за пратиоце",
   "privacy.public.long": "Објави на јавној лајни",
   "privacy.public.short": "Јавно",
-  "privacy.unlisted.long": "Не објављуј на јавним лајнама",
+  "privacy.unlisted.long": "Не објављуј на јавним временским линијама",
   "privacy.unlisted.short": "Неизлистано",
   "regeneration_indicator.label": "Учитавање…",
   "regeneration_indicator.sublabel": "Ваша почетна страница се припрема!",
@@ -306,23 +307,23 @@
   "status.sensitive_warning": "Осетљив садржај",
   "status.share": "Подели",
   "status.show_less": "Прикажи мање",
-  "status.show_less_all": "Show less for all",
+  "status.show_less_all": "Прикажи мање за све",
   "status.show_more": "Прикажи више",
-  "status.show_more_all": "Show more for all",
+  "status.show_more_all": "Прикажи више за све",
   "status.unmute_conversation": "Укључи преписку",
   "status.unpin": "Откачи са профила",
   "tabs_bar.federated_timeline": "Федерисано",
   "tabs_bar.home": "Почетна",
   "tabs_bar.local_timeline": "Локално",
   "tabs_bar.notifications": "Обавештења",
-  "tabs_bar.search": "Search",
-  "trends.count_by_accounts": "{count} {rawCount, plural, one {person} other {people}} talking",
+  "tabs_bar.search": "Претрага",
+  "trends.count_by_accounts": "{count} {rawCount, plural, one {човек} other {људи}} прича",
   "ui.beforeunload": "Ако напустите Мастодонт, изгубићете написани нацрт.",
   "upload_area.title": "Превуците овде да отпремите",
   "upload_button.label": "Додај мултимедију (JPEG, PNG, GIF, WebM, MP4, MOV)",
   "upload_form.description": "Опишите за особе са оштећеним видом",
   "upload_form.focus": "Подесите",
-  "upload_form.undo": "Избриши",
+  "upload_form.undo": "Обриши",
   "upload_progress.label": "Отпремам...",
   "video.close": "Затвори видео",
   "video.exit_fullscreen": "Напусти цео екран",
diff --git a/app/javascript/mastodon/locales/sv.json b/app/javascript/mastodon/locales/sv.json
index 498f6b411..c7df96cf5 100644
--- a/app/javascript/mastodon/locales/sv.json
+++ b/app/javascript/mastodon/locales/sv.json
@@ -15,6 +15,7 @@
   "account.follows.empty": "This user doesn't follow anyone yet.",
   "account.follows_you": "Följer dig",
   "account.hide_reblogs": "Dölj knuffar från @{name}",
+  "account.link_verified_on": "Ownership of this link was checked on {date}",
   "account.media": "Media",
   "account.mention": "Nämna @{name}",
   "account.moved_to": "{name} har flyttat till:",
diff --git a/app/javascript/mastodon/locales/ta.json b/app/javascript/mastodon/locales/ta.json
index d80eba2c1..e0237c023 100644
--- a/app/javascript/mastodon/locales/ta.json
+++ b/app/javascript/mastodon/locales/ta.json
@@ -15,6 +15,7 @@
   "account.follows.empty": "This user doesn't follow anyone yet.",
   "account.follows_you": "Follows you",
   "account.hide_reblogs": "Hide boosts from @{name}",
+  "account.link_verified_on": "Ownership of this link was checked on {date}",
   "account.media": "Media",
   "account.mention": "Mention @{name}",
   "account.moved_to": "{name} has moved to:",
diff --git a/app/javascript/mastodon/locales/te.json b/app/javascript/mastodon/locales/te.json
index bbe575fde..49f3ce2d9 100644
--- a/app/javascript/mastodon/locales/te.json
+++ b/app/javascript/mastodon/locales/te.json
@@ -7,14 +7,15 @@
   "account.disclaimer_full": "క్రింది సమాచారం వాడుకరి యొక్క ప్రొఫైల్ను అసంపూర్తిగా ప్రతిబింబించవచ్చు.",
   "account.domain_blocked": "డొమైన్ దాచిపెట్టబడినది",
   "account.edit_profile": "ప్రొఫైల్ని సవరించండి",
-  "account.endorse": "Feature on profile",
+  "account.endorse": "ప్రొఫైల్లో చూపించు",
   "account.follow": "అనుసరించు",
   "account.followers": "అనుచరులు",
-  "account.followers.empty": "No one follows this user yet.",
+  "account.followers.empty": "ఈ వినియోగదారుడిని ఇంకా ఎవరూ అనుసరించడంలేదు.",
   "account.follows": "అనుసరిస్తున్నవి",
-  "account.follows.empty": "This user doesn't follow anyone yet.",
+  "account.follows.empty": "ఈ వినియోగదారి ఇంకా ఎవరినీ అనుసరించడంలేదు.",
   "account.follows_you": "మిమ్మల్ని అనుసరిస్తున్నారు",
   "account.hide_reblogs": "@{name} నుంచి బూస్ట్ లను దాచిపెట్టు",
+  "account.link_verified_on": "Ownership of this link was checked on {date}",
   "account.media": "మీడియా",
   "account.mention": "@{name}ను ప్రస్తావించు",
   "account.moved_to": "{name} ఇక్కడికి మారారు:",
@@ -29,7 +30,7 @@
   "account.show_reblogs": "@{name}నుంచి బూస్ట్ లను చూపించు",
   "account.unblock": "@{name}పై బ్లాక్ ను తొలగించు",
   "account.unblock_domain": "{domain}ను దాచవద్దు",
-  "account.unendorse": "Don't feature on profile",
+  "account.unendorse": "ప్రొఫైల్లో చూపించవద్దు",
   "account.unfollow": "అనుసరించవద్దు",
   "account.unmute": "@{name}పై మ్యూట్ ని తొలగించు",
   "account.unmute_notifications": "@{name} నుంచి ప్రకటనలపై మ్యూట్ ని తొలగించు",
@@ -89,7 +90,7 @@
   "confirmations.mute.confirm": "మ్యూట్ చేయి",
   "confirmations.mute.message": "{name}ను మీరు ఖచ్చితంగా మ్యూట్ చేయాలనుకుంటున్నారా?",
   "confirmations.redraft.confirm": "తొలగించు & తిరగరాయు",
-  "confirmations.redraft.message": "మీరు ఖచ్చితంగా ఈ స్టేటస్ ని తొలగించి తిరగరాయాలనుకుంటున్నారా? మీరు అన్ని ప్రత్యుత్తరాలను, బూస్ట్ లను మరియు ఇష్టపడినవి కోల్పోతారు.",
+  "confirmations.redraft.message": "మీరు ఖచ్చితంగా ఈ స్టేటస్ ని తొలగించి తిరగరాయాలనుకుంటున్నారా? ఈ స్టేటస్ యొక్క బూస్ట్ లు మరియు ఇష్టాలు పోతాయి,మరియు ప్రత్యుత్తరాలు అనాధలు అయిపోతాయి.",
   "confirmations.unfollow.confirm": "అనుసరించవద్దు",
   "confirmations.unfollow.message": "{name}ను మీరు ఖచ్చితంగా అనుసరించవద్దనుకుంటున్నారా?",
   "embed.instructions": "దిగువ కోడ్ను కాపీ చేయడం ద్వారా మీ వెబ్సైట్లో ఈ స్టేటస్ ని పొందుపరచండి.",
@@ -108,19 +109,19 @@
   "emoji_button.search_results": "శోధన ఫలితాలు",
   "emoji_button.symbols": "చిహ్నాలు",
   "emoji_button.travel": "ప్రయాణం & ప్రదేశాలు",
-  "empty_column.blocks": "You haven't blocked any users yet.",
+  "empty_column.blocks": "మీరు ఇంకా ఏ వినియోగదారులనూ బ్లాక్ చేయలేదు.",
   "empty_column.community": "స్థానిక కాలక్రమం ఖాళీగా ఉంది. మొదలుపెట్టడానికి బహిరంగంగా ఏదో ఒకటి వ్రాయండి!",
   "empty_column.direct": "మీకు ఇంకా ఏ ప్రత్యక్ష సందేశాలు లేవు. మీరు ఒకదాన్ని పంపినప్పుడు లేదా స్వీకరించినప్పుడు, అది ఇక్కడ చూపబడుతుంది.",
-  "empty_column.domain_blocks": "There are no hidden domains yet.",
-  "empty_column.favourited_statuses": "You don't have any favourite toots yet. When you favourite one, it will show up here.",
-  "empty_column.favourites": "No one has favourited this toot yet. When someone does, they will show up here.",
-  "empty_column.follow_requests": "You don't have any follow requests yet. When you receive one, it will show up here.",
+  "empty_column.domain_blocks": "దాచబడిన డొమైన్లు ఇంకా ఏమీ లేవు.",
+  "empty_column.favourited_statuses": "మీకు ఇష్టపడిన టూట్లు ఇంకా ఎమీ లేవు. మీరు ఒకదానిని ఇష్టపడినప్పుడు, అది ఇక్కడ కనిపిస్తుంది.",
+  "empty_column.favourites": "ఈ టూట్ను ఇంకా ఎవరూ ఇష్టపడలేదు. ఎవరైనా అలా చేసినప్పుడు, అవి ఇక్కడ కనబడతాయి.",
+  "empty_column.follow_requests": "మీకు ఇంకా ఫాలో రిక్వెస్టులు ఏమీ రాలేదు. మీకు ఒకటి రాగానే, అది ఇక్కడ కనబడుతుంది.",
   "empty_column.hashtag": "ఇంకా హాష్ ట్యాగ్లో ఏమీ లేదు.",
   "empty_column.home": "మీ హోమ్ కాలక్రమం ఖాళీగా ఉంది! {Public} ను సందర్శించండి లేదా ఇతర వినియోగదారులను కలుసుకోవడానికి మరియు అన్వేషణ కోసం శోధనను ఉపయోగించండి.",
   "empty_column.home.public_timeline": "ప్రజా కాలక్రమం",
   "empty_column.list": "ఇంకా ఈ జాబితాలో ఏదీ లేదు. ఈ జాబితాలోని సభ్యులు కొత్త స్టేటస్ లను పోస్ట్ చేసినప్పుడు, అవి ఇక్కడ కనిపిస్తాయి.",
-  "empty_column.lists": "You don't have any lists yet. When you create one, it will show up here.",
-  "empty_column.mutes": "You haven't muted any users yet.",
+  "empty_column.lists": "మీకు ఇంకా జాబితాలు ఏమీ లేవు. మీరు ఒకటి సృష్టించగానే, అది ఇక్కడ కనబడుతుంది.",
+  "empty_column.mutes": "మీరు ఇంకా ఏ వినియోగదారులనూ మ్యూట్ చేయలేదు.",
   "empty_column.notifications": "మీకు ఇంకా ఏ నోటిఫికేషన్లు లేవు. సంభాషణను ప్రారంభించడానికి ఇతరులతో ప్రతిస్పందించండి.",
   "empty_column.public": "ఇక్కడ ఏమీ లేదు! దీన్ని నింపడానికి బహిరంగంగా ఏదైనా వ్రాయండి, లేదా ఇతర దృష్టాంతాల్లోని వినియోగదారులను అనుసరించండి",
   "follow_request.authorize": "అనుమతించు",
@@ -137,32 +138,32 @@
   "home.column_settings.show_reblogs": "బూస్ట్ లను చూపించు",
   "home.column_settings.show_replies": "ప్రత్యుత్తరాలను చూపించు",
   "keyboard_shortcuts.back": "వెనక్కి తిరిగి వెళ్ళడానికి",
-  "keyboard_shortcuts.blocked": "to open blocked users list",
+  "keyboard_shortcuts.blocked": "బ్లాక్ చేయబడిన వినియోగదారుల జాబితాను తెరవడానికి",
   "keyboard_shortcuts.boost": "బూస్ట్ చేయడానికి",
   "keyboard_shortcuts.column": "నిలువు వరుసలలో ఒకదానిపై దృష్టి పెట్టడానికి",
   "keyboard_shortcuts.compose": "కంపోజ్ టెక్స్ట్ఏరియా పై దృష్టి పెట్టడానికి",
   "keyboard_shortcuts.description": "Description",
-  "keyboard_shortcuts.direct": "to open direct messages column",
+  "keyboard_shortcuts.direct": "నేరుగా పంపిన సందేశాల నిలువు వరుసను తెరువడానికి",
   "keyboard_shortcuts.down": "జాబితాలో క్రిందికి వెళ్ళడానికి",
   "keyboard_shortcuts.enter": "to open status",
   "keyboard_shortcuts.favourite": "ఇష్టపడడానికి",
-  "keyboard_shortcuts.favourites": "to open favourites list",
-  "keyboard_shortcuts.federated": "to open federated timeline",
+  "keyboard_shortcuts.favourites": "ఇష్టాల జాబితాను తెరవడానికి",
+  "keyboard_shortcuts.federated": "సమాఖ్య కాలక్రమాన్ని తెరవడానికి",
   "keyboard_shortcuts.heading": "కీబోర్డ్ సత్వరమార్గాలు",
-  "keyboard_shortcuts.home": "to open home timeline",
+  "keyboard_shortcuts.home": "హోమ్ కాలక్రమాన్ని తెరవడానికి",
   "keyboard_shortcuts.hotkey": "హాట్ కీ",
   "keyboard_shortcuts.legend": "ఈ లెజెండ్ ప్రదర్శించడానికి",
-  "keyboard_shortcuts.local": "to open local timeline",
+  "keyboard_shortcuts.local": "లోకల్ కాలక్రమాన్ని తెరవడానికి",
   "keyboard_shortcuts.mention": "రచయితను ప్రస్తావించడానికి",
-  "keyboard_shortcuts.muted": "to open muted users list",
-  "keyboard_shortcuts.my_profile": "to open your profile",
-  "keyboard_shortcuts.notifications": "to open notifications column",
-  "keyboard_shortcuts.pinned": "to open pinned toots list",
+  "keyboard_shortcuts.muted": "మ్యూట్ చేయబడిన వినియోగదారుల జాబితాను తెరవడానికి",
+  "keyboard_shortcuts.my_profile": "మీ ప్రొఫైల్ను తెరవడానికి",
+  "keyboard_shortcuts.notifications": "నోటిఫికేషన్ల నిలువు వరుసను తెరవడానికి",
+  "keyboard_shortcuts.pinned": "అతికించబడిన టూట్ల జాబితాను తెరవడానికి",
   "keyboard_shortcuts.profile": "రచయిత ప్రొఫైల్ ను తెరవాలంటే",
   "keyboard_shortcuts.reply": "ప్రత్యుత్తరం ఇవ్వడానికి",
-  "keyboard_shortcuts.requests": "to open follow requests list",
+  "keyboard_shortcuts.requests": "ఫాలో రిక్వెస్ట్ల జాబితాను తెరవడానికి",
   "keyboard_shortcuts.search": "శోధనపై దృష్టి పెట్టండి",
-  "keyboard_shortcuts.start": "to open \"get started\" column",
+  "keyboard_shortcuts.start": "\"ఇక్కడ ప్రారంభించండి\" నిలువు వరుసను తెరవడానికి",
   "keyboard_shortcuts.toggle_hidden": "CW వెనుక ఉన్న పాఠ్యాన్ని చూపడానికి / దాచడానికి",
   "keyboard_shortcuts.toot": "ఒక సరికొత్త టూట్ను ప్రారంభించడానికి",
   "keyboard_shortcuts.unfocus": "పాఠ్యం వ్రాసే ఏరియా/శోధన పట్టిక నుండి బయటకు రావడానికి",
@@ -183,10 +184,10 @@
   "missing_indicator.label": "దొరకలేదు",
   "missing_indicator.sublabel": "ఈ వనరు కనుగొనబడలేదు",
   "mute_modal.hide_notifications": "ఈ వినియోగదారు నుండి నోటిఫికేషన్లను దాచాలా?",
-  "navigation_bar.apps": "Mobile apps",
+  "navigation_bar.apps": "మొబైల్ ఆప్ లు",
   "navigation_bar.blocks": "బ్లాక్ చేయబడిన వినియోగదారులు",
   "navigation_bar.community_timeline": "స్థానిక కాలక్రమం",
-  "navigation_bar.compose": "Compose new toot",
+  "navigation_bar.compose": "కొత్త టూట్ను రాయండి",
   "navigation_bar.direct": "ప్రత్యక్ష సందేశాలు",
   "navigation_bar.discover": "కనుగొను",
   "navigation_bar.domain_blocks": "దాచిన డొమైన్లు",
@@ -280,7 +281,7 @@
   "status.cancel_reblog_private": "బూస్ట్ను తొలగించు",
   "status.cannot_reblog": "ఈ పోస్ట్ను బూస్ట్ చేయడం సాధ్యం కాదు",
   "status.delete": "తొలగించు",
-  "status.detailed_status": "Detailed conversation view",
+  "status.detailed_status": "వివరణాత్మక సంభాషణ వీక్షణ",
   "status.direct": "@{name}కు నేరుగా సందేశం పంపు",
   "status.embed": "ఎంబెడ్",
   "status.favourite": "ఇష్టపడు",
@@ -297,7 +298,7 @@
   "status.reblog": "బూస్ట్",
   "status.reblog_private": "అసలు ప్రేక్షకులకు బూస్ట్ చేయి",
   "status.reblogged_by": "{name} బూస్ట్ చేసారు",
-  "status.reblogs.empty": "No one has boosted this toot yet. When someone does, they will show up here.",
+  "status.reblogs.empty": "ఈ టూట్ను ఇంకా ఎవరూ బూస్ట్ చేయలేదు. ఎవరైనా చేసినప్పుడు, అవి ఇక్కడ కనబడతాయి.",
   "status.redraft": "తొలగించు & తిరగరాయు",
   "status.reply": "ప్రత్యుత్తరం",
   "status.replyAll": "సంభాషణకు ప్రత్యుత్తరం ఇవ్వండి",
@@ -319,7 +320,7 @@
   "trends.count_by_accounts": "{count} {rawCount, plural, one {person} other {people}} మాట్లాడుతున్నారు",
   "ui.beforeunload": "మీరు మాస్టొడొన్ను వదిలివేస్తే మీ డ్రాఫ్ట్లు పోతాయి.",
   "upload_area.title": "అప్లోడ్ చేయడానికి డ్రాగ్ & డ్రాప్ చేయండి",
-  "upload_button.label": "మీడియాను జోడించండి",
+  "upload_button.label": "మీడియాను జోడించండి (JPEG, PNG, GIF, WebM, MP4, MOV)",
   "upload_form.description": "దృష్టి లోపమున్న వారి కోసం వివరించండి",
   "upload_form.focus": "కత్తిరించు",
   "upload_form.undo": "తొలగించు",
diff --git a/app/javascript/mastodon/locales/th.json b/app/javascript/mastodon/locales/th.json
index 5340fda92..2af5bfca1 100644
--- a/app/javascript/mastodon/locales/th.json
+++ b/app/javascript/mastodon/locales/th.json
@@ -15,6 +15,7 @@
   "account.follows.empty": "This user doesn't follow anyone yet.",
   "account.follows_you": "Follows you",
   "account.hide_reblogs": "Hide boosts from @{name}",
+  "account.link_verified_on": "Ownership of this link was checked on {date}",
   "account.media": "Media",
   "account.mention": "Mention @{name}",
   "account.moved_to": "{name} has moved to:",
diff --git a/app/javascript/mastodon/locales/tr.json b/app/javascript/mastodon/locales/tr.json
index cec07b87e..68dc37e6b 100644
--- a/app/javascript/mastodon/locales/tr.json
+++ b/app/javascript/mastodon/locales/tr.json
@@ -15,6 +15,7 @@
   "account.follows.empty": "This user doesn't follow anyone yet.",
   "account.follows_you": "Seni takip ediyor",
   "account.hide_reblogs": "Hide boosts from @{name}",
+  "account.link_verified_on": "Ownership of this link was checked on {date}",
   "account.media": "Media",
   "account.mention": "Bahset @{name}",
   "account.moved_to": "{name} has moved to:",
diff --git a/app/javascript/mastodon/locales/uk.json b/app/javascript/mastodon/locales/uk.json
index 9a2c18e36..5517abdf8 100644
--- a/app/javascript/mastodon/locales/uk.json
+++ b/app/javascript/mastodon/locales/uk.json
@@ -15,6 +15,7 @@
   "account.follows.empty": "This user doesn't follow anyone yet.",
   "account.follows_you": "Підписаний(-а) на Вас",
   "account.hide_reblogs": "Сховати передмухи від @{name}",
+  "account.link_verified_on": "Ownership of this link was checked on {date}",
   "account.media": "Медіа",
   "account.mention": "Згадати @{name}",
   "account.moved_to": "{name} переїхав на:",
diff --git a/app/javascript/mastodon/locales/zh-CN.json b/app/javascript/mastodon/locales/zh-CN.json
index cf2e1a640..254beab42 100644
--- a/app/javascript/mastodon/locales/zh-CN.json
+++ b/app/javascript/mastodon/locales/zh-CN.json
@@ -15,6 +15,7 @@
   "account.follows.empty": "This user doesn't follow anyone yet.",
   "account.follows_you": "关注了你",
   "account.hide_reblogs": "隐藏来自 @{name} 的转嘟",
+  "account.link_verified_on": "Ownership of this link was checked on {date}",
   "account.media": "媒体",
   "account.mention": "提及 @{name}",
   "account.moved_to": "{name} 已经迁移到:",
diff --git a/app/javascript/mastodon/locales/zh-HK.json b/app/javascript/mastodon/locales/zh-HK.json
index dbad69191..ce141a8a7 100644
--- a/app/javascript/mastodon/locales/zh-HK.json
+++ b/app/javascript/mastodon/locales/zh-HK.json
@@ -15,6 +15,7 @@
   "account.follows.empty": "This user doesn't follow anyone yet.",
   "account.follows_you": "關注你",
   "account.hide_reblogs": "隱藏 @{name} 的轉推",
+  "account.link_verified_on": "Ownership of this link was checked on {date}",
   "account.media": "媒體",
   "account.mention": "提及 @{name}",
   "account.moved_to": "{name} 已經遷移到:",
diff --git a/app/javascript/mastodon/locales/zh-TW.json b/app/javascript/mastodon/locales/zh-TW.json
index 4e437f0e0..fe4a81170 100644
--- a/app/javascript/mastodon/locales/zh-TW.json
+++ b/app/javascript/mastodon/locales/zh-TW.json
@@ -10,11 +10,12 @@
   "account.endorse": "在個人資訊頁面上推薦對方",
   "account.follow": "關注",
   "account.followers": "關注者",
-  "account.followers.empty": "還沒有人關注這個使用者",
+  "account.followers.empty": "還沒有人關注這個使用者。",
   "account.follows": "正在關注",
-  "account.follows.empty": "這個使用者還沒有關注任何人",
+  "account.follows.empty": "這個使用者還沒有關注任何人。",
   "account.follows_you": "關注你",
   "account.hide_reblogs": "隱藏來自 @{name} 的轉推",
+  "account.link_verified_on": "Ownership of this link was checked on {date}",
   "account.media": "媒體",
   "account.mention": "提到 @{name}",
   "account.moved_to": "{name} 已經移至:",
@@ -89,7 +90,7 @@
   "confirmations.mute.confirm": "消音",
   "confirmations.mute.message": "你確定要消音 {name} ?",
   "confirmations.redraft.confirm": "刪除 & 編輯",
-  "confirmations.redraft.message": "你確定要刪除這條嘟文並重新編輯它嗎? 所有相關的回覆、轉嘟與最愛都會被刪除。",
+  "confirmations.redraft.message": "你確定要刪除這條嘟文並重新編輯它嗎?所有相關的轉嘟與最愛都會被刪除,而對原始嘟文的回覆將會變成孤兒。",
   "confirmations.unfollow.confirm": "取消關注",
   "confirmations.unfollow.message": "真的不要繼續關注 {name} 了嗎?",
   "embed.instructions": "要內嵌此嘟文,請將以下代碼貼進你的網站。",
@@ -183,7 +184,7 @@
   "missing_indicator.label": "找不到",
   "missing_indicator.sublabel": "找不到此資源",
   "mute_modal.hide_notifications": "隱藏來自這個使用者的通知?",
-  "navigation_bar.apps": "Mobile apps",
+  "navigation_bar.apps": "行動應用程式",
   "navigation_bar.blocks": "封鎖的使用者",
   "navigation_bar.community_timeline": "本地時間軸",
   "navigation_bar.compose": "寫新的嘟文",
@@ -284,7 +285,7 @@
   "status.direct": "發送私訊給 @{name}",
   "status.embed": "嵌入",
   "status.favourite": "最愛",
-  "status.filtered": "Filtered",
+  "status.filtered": "已過濾",
   "status.load_more": "載入更多",
   "status.media_hidden": "隱藏媒體內容",
   "status.mention": "提到 @{name}",
@@ -319,7 +320,7 @@
   "trends.count_by_accounts": "{count} 位使用者在討論",
   "ui.beforeunload": "如果離開 Mastodon,你的草稿將會不見。",
   "upload_area.title": "拖放來上傳",
-  "upload_button.label": "上傳媒體檔案",
+  "upload_button.label": "上傳媒體檔案 (JPEG, PNG, GIF, WebM, MP4, MOV)",
   "upload_form.description": "為視障人士增加文字說明",
   "upload_form.focus": "裁切",
   "upload_form.undo": "刪除",
diff --git a/app/javascript/mastodon/reducers/dropdown_menu.js b/app/javascript/mastodon/reducers/dropdown_menu.js
index 5449884cc..36fd4f132 100644
--- a/app/javascript/mastodon/reducers/dropdown_menu.js
+++ b/app/javascript/mastodon/reducers/dropdown_menu.js
@@ -4,12 +4,12 @@ import {
   DROPDOWN_MENU_CLOSE,
 } from '../actions/dropdown_menu';
 
-const initialState = Immutable.Map({ openId: null, placement: null });
+const initialState = Immutable.Map({ openId: null, placement: null, keyboard: false });
 
 export default function dropdownMenu(state = initialState, action) {
   switch (action.type) {
   case DROPDOWN_MENU_OPEN:
-    return state.merge({ openId: action.id, placement: action.placement });
+    return state.merge({ openId: action.id, placement: action.placement, keyboard: action.keyboard });
   case DROPDOWN_MENU_CLOSE:
     return state.get('openId') === action.id ? state.set('openId', null) : state;
   default:
diff --git a/app/javascript/packs/public.js b/app/javascript/packs/public.js
index 1cb491e17..a62974ec0 100644
--- a/app/javascript/packs/public.js
+++ b/app/javascript/packs/public.js
@@ -52,6 +52,7 @@ function main() {
     });
 
     const reactComponents = document.querySelectorAll('[data-component]');
+
     if (reactComponents.length > 0) {
       import(/* webpackChunkName: "containers/media_container" */ '../mastodon/containers/media_container')
         .then(({ default: MediaContainer }) => {
@@ -64,6 +65,7 @@ function main() {
     }
 
     const parallaxComponents = document.querySelectorAll('.parallax');
+
     if (parallaxComponents.length > 0 ) {
       new Rellax('.parallax', { speed: -1 });
     }
@@ -71,6 +73,7 @@ function main() {
     const history = createHistory();
     const detailedStatuses = document.querySelectorAll('.public-layout .detailed-status');
     const location = history.location;
+
     if (detailedStatuses.length === 1 && (!location.state || !location.state.scrolledToDetailedStatus)) {
       detailedStatuses[0].scrollIntoView();
       history.replace(location.pathname, { ...location.state, scrolledToDetailedStatus: true });
diff --git a/app/javascript/styles/mastodon/accounts.scss b/app/javascript/styles/mastodon/accounts.scss
index c27bc0df3..06effbdb2 100644
--- a/app/javascript/styles/mastodon/accounts.scss
+++ b/app/javascript/styles/mastodon/accounts.scss
@@ -265,6 +265,20 @@
     }
   }
 
+  .verified {
+    border: 1px solid rgba($valid-value-color, 0.5);
+    background: rgba($valid-value-color, 0.25);
+
+    a {
+      color: $valid-value-color;
+      font-weight: 500;
+    }
+
+    &__mark {
+      color: $valid-value-color;
+    }
+  }
+
   dl:last-child {
     border-bottom: 0;
   }
diff --git a/app/javascript/styles/mastodon/admin.scss b/app/javascript/styles/mastodon/admin.scss
index 42f507296..9dfd89dc2 100644
--- a/app/javascript/styles/mastodon/admin.scss
+++ b/app/javascript/styles/mastodon/admin.scss
@@ -1,3 +1,5 @@
+$no-columns-breakpoint: 600px;
+
 .admin-wrapper {
   display: flex;
   justify-content: center;
@@ -24,12 +26,22 @@
       height: 100px;
     }
 
+    @media screen and (max-width: $no-columns-breakpoint) {
+      & > a:first-child {
+        display: none;
+      }
+    }
+
     ul {
       list-style: none;
       border-radius: 4px 0 0 4px;
       overflow: hidden;
       margin-bottom: 20px;
 
+      @media screen and (max-width: $no-columns-breakpoint) {
+        margin-bottom: 0;
+      }
+
       a {
         display: block;
         padding: 15px;
@@ -62,20 +74,24 @@
         a {
           border: 0;
           padding: 15px 35px;
+        }
+      }
 
-          &.selected {
-            color: $primary-text-color;
-            background-color: $ui-highlight-color;
-            border-bottom: 0;
-            border-radius: 0;
+      .simple-navigation-active-leaf a {
+        color: $primary-text-color;
+        background-color: $ui-highlight-color;
+        border-bottom: 0;
+        border-radius: 0;
 
-            &:hover {
-              background-color: lighten($ui-highlight-color, 5%);
-            }
-          }
+        &:hover {
+          background-color: lighten($ui-highlight-color, 5%);
         }
       }
     }
+
+    & > ul > .simple-navigation-active-leaf a {
+      border-radius: 4px 0 0 4px;
+    }
   }
 
   .content-wrapper {
@@ -89,11 +105,19 @@
     padding-top: 60px;
     padding-left: 25px;
 
+    @media screen and (max-width: $no-columns-breakpoint) {
+      max-width: none;
+      padding: 15px;
+      padding-top: 30px;
+    }
+
     h2 {
       color: $secondary-text-color;
       font-size: 24px;
       line-height: 28px;
       font-weight: 400;
+      padding-bottom: 40px;
+      border-bottom: 1px solid lighten($ui-base-color, 8%);
       margin-bottom: 40px;
     }
 
@@ -108,7 +132,7 @@
     h4 {
       text-transform: uppercase;
       font-size: 13px;
-      font-weight: 500;
+      font-weight: 700;
       color: $darker-text-color;
       padding-bottom: 8px;
       margin-bottom: 8px;
@@ -122,6 +146,11 @@
       font-weight: 400;
     }
 
+    .fields-group h6 {
+      color: $primary-text-color;
+      font-weight: 500;
+    }
+
     & > p {
       font-size: 14px;
       line-height: 18px;
@@ -172,30 +201,7 @@
     }
   }
 
-  .simple_form {
-    max-width: 400px;
-
-    &.edit_user,
-    &.new_form_admin_settings,
-    &.new_form_two_factor_confirmation,
-    &.new_form_delete_confirmation,
-    &.new_import,
-    &.new_domain_block,
-    &.edit_domain_block {
-      max-width: none;
-    }
-
-    .form_two_factor_confirmation_code,
-    .form_delete_confirmation_password {
-      max-width: 400px;
-    }
-
-    .actions {
-      max-width: 400px;
-    }
-  }
-
-  @media screen and (max-width: 600px) {
+  @media screen and (max-width: $no-columns-breakpoint) {
     display: block;
     overflow-y: auto;
     -webkit-overflow-scrolling: touch;
@@ -209,16 +215,8 @@
 
     .sidebar {
       width: 100%;
-      padding: 10px 0;
+      padding: 0;
       height: auto;
-
-      .logo {
-        margin: 20px auto;
-      }
-    }
-
-    .content {
-      padding-top: 20px;
     }
   }
 }
@@ -567,3 +565,102 @@ a.name-tag,
     color: $dark-text-color;
   }
 }
+
+.report-card {
+  background: $ui-base-color;
+  border-radius: 4px;
+  margin-bottom: 20px;
+
+  &__profile {
+    display: flex;
+    justify-content: space-between;
+    align-items: center;
+    padding: 15px;
+
+    .account {
+      padding: 0;
+      border: 0;
+
+      &__avatar-wrapper {
+        margin-left: 0;
+      }
+    }
+
+    &__stats {
+      flex: 0 0 auto;
+      font-weight: 500;
+      color: $darker-text-color;
+      text-transform: uppercase;
+      text-align: right;
+
+      a {
+        color: inherit;
+        text-decoration: none;
+
+        &:focus,
+        &:hover,
+        &:active {
+          color: lighten($darker-text-color, 8%);
+        }
+      }
+
+      .red {
+        color: $error-value-color;
+      }
+    }
+  }
+
+  &__summary {
+    &__item {
+      display: flex;
+      justify-content: flex-start;
+      border-top: 1px solid darken($ui-base-color, 4%);
+
+      &:hover {
+        background: lighten($ui-base-color, 2%);
+      }
+
+      &__reported-by,
+      &__assigned {
+        padding: 15px;
+        flex: 0 0 auto;
+        box-sizing: border-box;
+        width: 150px;
+        color: $darker-text-color;
+
+        &,
+        .username {
+          white-space: nowrap;
+          overflow: hidden;
+          text-overflow: ellipsis;
+        }
+      }
+
+      &__content {
+        flex: 1 1 auto;
+        max-width: calc(100% - 300px);
+
+        &__icon {
+          color: $dark-text-color;
+          margin-right: 4px;
+          font-weight: 500;
+        }
+      }
+
+      &__content a {
+        display: block;
+        box-sizing: border-box;
+        width: 100%;
+        padding: 15px;
+        text-decoration: none;
+        color: $darker-text-color;
+      }
+    }
+  }
+}
+
+.one-line {
+  white-space: nowrap;
+  overflow: hidden;
+  text-overflow: ellipsis;
+}
diff --git a/app/javascript/styles/mastodon/basics.scss b/app/javascript/styles/mastodon/basics.scss
index 7a6a1c490..3bbb31e6e 100644
--- a/app/javascript/styles/mastodon/basics.scss
+++ b/app/javascript/styles/mastodon/basics.scss
@@ -1,3 +1,10 @@
+@function hex-color($color) {
+  @if type-of($color) == 'color' {
+    $color: str-slice(ie-hex-str($color), 4);
+  }
+  @return '%23' + unquote($color)
+}
+
 body {
   font-family: 'mastodon-font-sans-serif', sans-serif;
   background: darken($ui-base-color, 8%);
diff --git a/app/javascript/styles/mastodon/boost.scss b/app/javascript/styles/mastodon/boost.scss
index 8e11cb596..5a6d6ae40 100644
--- a/app/javascript/styles/mastodon/boost.scss
+++ b/app/javascript/styles/mastodon/boost.scss
@@ -1,10 +1,3 @@
-@function hex-color($color) {
-  @if type-of($color) == 'color' {
-    $color: str-slice(ie-hex-str($color), 4);
-  }
-  @return '%23' + unquote($color)
-}
-
 button.icon-button i.fa-retweet {
   background-image: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' width='22' height='209'><path d='M4.97 3.16c-.1.03-.17.1-.22.18L.8 8.24c-.2.3.03.78.4.8H3.6v2.68c0 4.26-.55 3.62 3.66 3.62h7.66l-2.3-2.84c-.03-.02-.03-.04-.05-.06H7.27c-.44 0-.72-.3-.72-.72v-2.7h2.5c.37.03.63-.48.4-.77L5.5 3.35c-.12-.17-.34-.25-.53-.2zm12.16.43c-.55-.02-1.32.02-2.4.02H7.1l2.32 2.85.03.06h5.25c.42 0 .72.28.72.72v2.7h-2.5c-.36.02-.56.54-.3.8l3.92 4.9c.18.25.6.25.78 0l3.94-4.9c.26-.28 0-.83-.37-.8H18.4v-2.7c0-3.15.4-3.62-1.25-3.66z' fill='#{hex-color($action-button-color)}' stroke-width='0'/><path d='M7.78 19.66c-.24.02-.44.25-.44.5v2.46h-.06c-1.08 0-1.86-.03-2.4-.03-1.64 0-1.25.43-1.25 3.65v4.47c0 4.26-.56 3.62 3.65 3.62H8.5l-1.3-1.06c-.1-.08-.18-.2-.2-.3-.02-.17.06-.35.2-.45l1.33-1.1H7.28c-.44 0-.72-.3-.72-.7v-4.48c0-.44.28-.72.72-.72h.06v2.5c0 .38.54.63.82.38l4.9-3.93c.25-.18.25-.6 0-.78l-4.9-3.92c-.1-.1-.24-.14-.38-.12zm9.34 2.93c-.54-.02-1.3.02-2.4.02h-1.25l1.3 1.07c.1.07.18.2.2.33.02.16-.06.3-.2.4l-1.33 1.1h1.28c.42 0 .72.28.72.72v4.47c0 .42-.3.72-.72.72h-.1v-2.47c0-.3-.3-.53-.6-.47-.07 0-.14.05-.2.1l-4.9 3.93c-.26.18-.26.6 0 .78l4.9 3.92c.27.25.82 0 .8-.38v-2.5h.1c4.27 0 3.65.67 3.65-3.62v-4.47c0-3.15.4-3.62-1.25-3.66zM10.34 38.66c-.24.02-.44.25-.43.5v2.47H7.3c-1.08 0-1.86-.04-2.4-.04-1.64 0-1.25.43-1.25 3.65v4.47c0 3.66-.23 3.7 2.34 3.66l-1.34-1.1c-.1-.08-.18-.2-.2-.3 0-.17.07-.35.2-.45l1.96-1.6c-.03-.06-.04-.13-.04-.2v-4.48c0-.44.28-.72.72-.72H9.9v2.5c0 .36.5.6.8.38l4.93-3.93c.24-.18.24-.6 0-.78l-4.94-3.92c-.1-.08-.23-.13-.36-.12zm5.63 2.93l1.34 1.1c.1.07.18.2.2.33.02.16-.03.3-.16.4l-1.96 1.6c.02.07.06.13.06.22v4.47c0 .42-.3.72-.72.72h-2.66v-2.47c0-.3-.3-.53-.6-.47-.06.02-.12.05-.18.1l-4.94 3.93c-.24.18-.24.6 0 .78l4.94 3.92c.28.22.78-.02.78-.38v-2.5h2.66c4.27 0 3.65.67 3.65-3.62v-4.47c0-3.66.34-3.7-2.4-3.66zM13.06 57.66c-.23.03-.4.26-.4.5v2.47H7.28c-1.08 0-1.86-.04-2.4-.04-1.64 0-1.25.43-1.25 3.65v4.87l2.93-2.37v-2.5c0-.44.28-.72.72-.72h5.38v2.5c0 .36.5.6.78.38l4.94-3.93c.24-.18.24-.6 0-.78l-4.94-3.92c-.1-.1-.24-.14-.38-.12zm5.3 6.15l-2.92 2.4v2.52c0 .42-.3.72-.72.72h-5.4v-2.47c0-.3-.32-.53-.6-.47-.07.02-.13.05-.2.1L3.6 70.52c-.25.18-.25.6 0 .78l4.93 3.92c.28.22.78-.02.78-.38v-2.5h5.42c4.27 0 3.65.67 3.65-3.62v-4.47-.44zM19.25 78.8c-.1.03-.2.1-.28.17l-.9.9c-.44-.3-1.36-.25-3.35-.25H7.28c-1.08 0-1.86-.03-2.4-.03-1.64 0-1.25.43-1.25 3.65v.7l2.93.3v-1c0-.44.28-.72.72-.72h7.44c.2 0 .37.08.5.2l-1.8 1.8c-.25.26-.08.76.27.8l6.27.7c.28.03.56-.25.53-.53l-.7-6.25c0-.27-.3-.48-.55-.44zm-17.2 6.1c-.2.07-.36.3-.33.54l.7 6.25c.02.36.58.55.83.27l.8-.8c.02 0 .04-.02.04 0 .46.24 1.37.17 3.18.17h7.44c4.27 0 3.65.67 3.65-3.62v-.75l-2.93-.3v1.05c0 .42-.3.72-.72.72H7.28c-.15 0-.3-.03-.4-.1L8.8 86.4c.3-.24.1-.8-.27-.84l-6.28-.65h-.2zM4.88 98.6c-1.33 0-1.34.48-1.3 2.3l1.14-1.37c.08-.1.22-.17.34-.2.16 0 .34.08.44.2l1.66 2.03c.04 0 .07-.03.12-.03h7.44c.34 0 .57.2.65.5h-2.43c-.34.05-.53.52-.3.78l3.92 4.95c.18.24.6.24.78 0l3.94-4.94c.22-.27-.02-.76-.37-.77H18.4c.02-3.9.6-3.4-3.66-3.4H7.28c-1.08 0-1.86-.04-2.4-.04zm.15 2.46c-.1.03-.2.1-.28.2l-3.94 4.9c-.2.28.03.77.4.78H3.6c-.02 3.94-.45 3.4 3.66 3.4h7.44c3.65 0 3.74.3 3.7-2.25l-1.1 1.34c-.1.1-.2.17-.32.2-.16 0-.34-.08-.44-.2l-1.65-2.03c-.06.02-.1.04-.18.04H7.28c-.35 0-.57-.2-.66-.5h2.44c.37 0 .63-.5.4-.78l-3.96-4.9c-.1-.15-.3-.23-.47-.2zM4.88 117.6c-1.16 0-1.3.3-1.3 1.56l1.14-1.38c.08-.1.22-.14.34-.16.16 0 .34.04.44.16l2.22 2.75h7c.42 0 .72.28.72.72v.53h-2.6c-.3.1-.43.54-.2.78l3.92 4.9c.18.25.6.25.78 0l3.94-4.9c.22-.28-.02-.77-.37-.78H18.4v-.53c0-4.2.72-3.63-3.66-3.63H7.28c-1.08 0-1.86-.03-2.4-.03zm.1 1.74c-.1.03-.17.1-.23.16L.8 124.44c-.2.28.03.77.4.78H3.6v.5c0 4.26-.55 3.62 3.66 3.62h7.44c1.03 0 1.74.02 2.28 0-.16.02-.34-.03-.44-.15l-2.22-2.76H7.28c-.44 0-.72-.3-.72-.72v-.5h2.5c.37.02.63-.5.4-.78L5.5 119.5c-.12-.15-.34-.22-.53-.16zm12.02 10c1.2-.02 1.4-.25 1.4-1.53l-1.1 1.36c-.07.1-.17.17-.3.18zM5.94 136.6l2.37 2.93h6.42c.42 0 .72.28.72.72v1.25h-2.6c-.3.1-.43.54-.2.78l3.92 4.9c.18.25.6.25.78 0l3.94-4.9c.22-.28-.02-.77-.37-.78H18.4v-1.25c0-4.2.72-3.63-3.66-3.63H7.28c-.6 0-.92-.02-1.34-.03zm-1.72.06c-.4.08-.54.3-.6.75l.6-.74zm.84.93c-.12 0-.24.08-.3.18l-3.95 4.9c-.24.3 0 .83.4.82H3.6v1.22c0 4.26-.55 3.62 3.66 3.62h7.44c.63 0 .97.02 1.4.03l-2.37-2.93H7.28c-.44 0-.72-.3-.72-.72v-1.22h2.5c.4.04.67-.53.4-.8l-3.96-4.92c-.1-.13-.27-.2-.44-.2zm13.28 10.03l-.56.7c.36-.07.5-.3.56-.7zM17.13 155.6c-.55-.02-1.32.03-2.4.03h-8.2l2.38 2.9h5.82c.42 0 .72.28.72.72v1.97H12.9c-.32.06-.48.52-.28.78l3.94 4.94c.2.23.6.22.78-.03l3.94-4.9c.22-.28-.02-.77-.37-.78H18.4v-1.97c0-3.15.4-3.62-1.25-3.66zm-12.1.28c-.1.02-.2.1-.28.18l-3.94 4.9c-.2.3.03.78.4.8H3.6v1.96c0 4.26-.55 3.62 3.66 3.62h8.24l-2.36-2.9H7.28c-.44 0-.72-.3-.72-.72v-1.97h2.5c.37.02.63-.5.4-.78l-3.96-4.9c-.1-.15-.3-.22-.47-.2zM5.13 174.5c-.15 0-.3.07-.38.2L.8 179.6c-.24.27 0 .82.4.8H3.6v2.32c0 4.26-.55 3.62 3.66 3.62h7.94l-2.35-2.9h-5.6c-.43 0-.7-.3-.7-.72v-2.3h2.5c.38.03.66-.54.4-.83l-3.97-4.9c-.1-.13-.23-.2-.38-.2zm12 .1c-.55-.02-1.32.03-2.4.03H6.83l2.35 2.9h5.52c.42 0 .72.28.72.72v2.34h-2.6c-.3.1-.43.53-.2.78l3.92 4.9c.18.24.6.24.78 0l3.94-4.9c.22-.3-.02-.78-.37-.8H18.4v-2.33c0-3.15.4-3.62-1.25-3.66zM4.97 193.16c-.1.03-.17.1-.22.18l-3.94 4.9c-.2.3.03.78.4.8H3.6v2.68c0 4.26-.55 3.62 3.66 3.62h7.66l-2.3-2.84c-.03-.02-.03-.04-.05-.06H7.27c-.44 0-.72-.3-.72-.72v-2.7h2.5c.37.03.63-.48.4-.77l-3.96-4.9c-.12-.17-.34-.25-.53-.2zm12.16.43c-.55-.02-1.32.03-2.4.03H7.1l2.32 2.84.03.06h5.25c.42 0 .72.28.72.72v2.7h-2.5c-.36.02-.56.54-.3.8l3.92 4.9c.18.25.6.25.78 0l3.94-4.9c.26-.28 0-.83-.37-.8H18.4v-2.7c0-3.15.4-3.62-1.25-3.66z' fill='#{hex-color($highlight-text-color)}' stroke-width='0'/></svg>");
 
diff --git a/app/javascript/styles/mastodon/components.scss b/app/javascript/styles/mastodon/components.scss
index c6b3ed0e2..490e26ccc 100644
--- a/app/javascript/styles/mastodon/components.scss
+++ b/app/javascript/styles/mastodon/components.scss
@@ -1297,6 +1297,11 @@ a .account__avatar {
   flex: 0 1 100%;
   border-right: 1px solid lighten($ui-base-color, 8%);
   padding: 10px 0;
+  border-bottom: 4px solid transparent;
+
+  &.active {
+    border-bottom: 4px solid $ui-highlight-color;
+  }
 
   & > span {
     display: block;
@@ -5358,9 +5363,11 @@ noscript {
   overflow: hidden;
   margin: 20px -10px -20px;
   border-bottom: 0;
+  border-top: 0;
 
   dl {
-    border-top: 1px solid lighten($ui-base-color, 8%);
+    border-top: 1px solid lighten($ui-base-color, 4%);
+    border-bottom: 0;
     display: flex;
   }
 
@@ -5387,6 +5394,11 @@ noscript {
     flex: 1 1 auto;
     color: $primary-text-color;
     background: $ui-base-color;
+
+    &.verified {
+      border: 1px solid rgba($valid-value-color, 0.5);
+      background: rgba($valid-value-color, 0.25);
+    }
   }
 }
 
diff --git a/app/javascript/styles/mastodon/containers.scss b/app/javascript/styles/mastodon/containers.scss
index 2c2ce5d3b..47582f323 100644
--- a/app/javascript/styles/mastodon/containers.scss
+++ b/app/javascript/styles/mastodon/containers.scss
@@ -718,6 +718,14 @@
       a {
         color: lighten($ui-highlight-color, 8%);
       }
+
+      dl:first-child .verified {
+        border-radius: 0 4px 0 0;
+      }
+
+      .verified a {
+        color: $valid-value-color;
+      }
     }
 
     .account__header__content {
diff --git a/app/javascript/styles/mastodon/forms.scss b/app/javascript/styles/mastodon/forms.scss
index 144b4a519..cbd3de94c 100644
--- a/app/javascript/styles/mastodon/forms.scss
+++ b/app/javascript/styles/mastodon/forms.scss
@@ -1,3 +1,5 @@
+$no-columns-breakpoint: 600px;
+
 code {
   font-family: 'mastodon-font-monospace', monospace;
   font-weight: 400;
@@ -13,6 +15,60 @@ code {
   .input {
     margin-bottom: 15px;
     overflow: hidden;
+
+    &.hidden {
+      margin: 0;
+    }
+
+    &.radio_buttons {
+      .radio {
+        margin-bottom: 15px;
+
+        &:last-child {
+          margin-bottom: 0;
+        }
+      }
+
+      .radio > label {
+        position: relative;
+        padding-left: 28px;
+
+        input {
+          position: absolute;
+          top: -2px;
+          left: 0;
+        }
+      }
+    }
+
+    &.boolean {
+      position: relative;
+      margin-bottom: 0;
+
+      .label_input > label {
+        font-family: inherit;
+        font-size: 14px;
+        padding-top: 5px;
+        color: $primary-text-color;
+        display: block;
+        width: auto;
+      }
+
+      .label_input,
+      .hint {
+        padding-left: 28px;
+      }
+
+      .label_input__wrapper {
+        position: static;
+      }
+
+      label.checkbox {
+        position: absolute;
+        top: 2px;
+        left: 0;
+      }
+    }
   }
 
   .row {
@@ -27,9 +83,22 @@ code {
     }
   }
 
+  .hint {
+    color: $darker-text-color;
+
+    a {
+      color: $highlight-text-color;
+    }
+
+    code {
+      border-radius: 3px;
+      padding: 0.2em 0.4em;
+      background: darken($ui-base-color, 12%);
+    }
+  }
+
   span.hint {
     display: block;
-    color: $darker-text-color;
     font-size: 12px;
     margin-top: 4px;
   }
@@ -44,17 +113,6 @@ code {
       line-height: 18px;
       margin-top: 15px;
       margin-bottom: 0;
-      color: $darker-text-color;
-
-      a {
-        color: $highlight-text-color;
-      }
-    }
-
-    code {
-      border-radius: 3px;
-      padding: 0.2em 0.4em;
-      background: darken($ui-base-color, 12%);
     }
   }
 
@@ -72,87 +130,60 @@ code {
     }
   }
 
-  .label_input {
-    display: flex;
+  .input.with_floating_label {
+    .label_input {
+      display: flex;
 
-    label {
-      flex: 0 0 auto;
+      & > label {
+        font-family: inherit;
+        font-size: 14px;
+        color: $primary-text-color;
+        font-weight: 500;
+        min-width: 150px;
+        flex: 0 0 auto;
+      }
+
+      input,
+      select {
+        flex: 1 1 auto;
+      }
     }
 
-    input {
-      flex: 1 1 auto;
+    &.select .hint {
+      margin-top: 6px;
+      margin-left: 150px;
     }
   }
 
   .input.with_label {
-    padding: 15px 0;
-    margin-bottom: 0;
-
-    .label_input {
-      flex-wrap: wrap;
-      align-items: flex-start;
-    }
-
-    &.file .label_input {
-      flex-wrap: nowrap;
-    }
-
-    &.select .label_input {
-      align-items: initial;
-    }
-
     .label_input > label {
       font-family: inherit;
-      font-size: 16px;
+      font-size: 14px;
       color: $primary-text-color;
       display: block;
-      padding-top: 5px;
-      margin-bottom: 5px;
-      flex: 1;
-      min-width: 150px;
+      margin-bottom: 8px;
       word-wrap: break-word;
+      font-weight: 500;
+    }
 
-      &.select {
-        flex: 0;
-      }
-
-      & ~ * {
-        margin-left: 10px;
-      }
+    .hint {
+      margin-top: 6px;
     }
 
     ul {
       flex: 390px;
     }
-
-    &.boolean {
-      padding: initial;
-      margin-bottom: initial;
-
-      .label_input > label {
-        font-family: inherit;
-        font-size: 14px;
-        color: $primary-text-color;
-        display: block;
-        width: auto;
-      }
-
-      label.checkbox {
-        position: relative;
-        padding-left: 25px;
-        flex: 1 1 auto;
-      }
-    }
   }
 
   .input.with_block_label {
-    padding-top: 15px;
+    max-width: none;
 
     & > label {
       font-family: inherit;
       font-size: 16px;
       color: $primary-text-color;
       display: block;
+      font-weight: 500;
       padding-top: 5px;
     }
 
@@ -165,49 +196,70 @@ code {
     }
   }
 
+  .required abbr {
+    text-decoration: none;
+    color: lighten($error-value-color, 12%);
+  }
+
   .fields-group {
     margin-bottom: 25px;
-  }
 
-  .input.radio_buttons .radio label {
-    margin-bottom: 5px;
-    font-family: inherit;
-    font-size: 14px;
-    color: $primary-text-color;
-    display: block;
-    width: auto;
+    .input:last-child {
+      margin-bottom: 0;
+    }
   }
 
-  .input.boolean {
-    margin-bottom: 5px;
+  .fields-row {
+    display: flex;
+    margin: 0 -10px;
+    padding-top: 5px;
+    margin-bottom: 25px;
 
-    label {
-      font-family: inherit;
-      font-size: 14px;
-      color: $primary-text-color;
-      display: block;
-      width: auto;
+    .input {
+      max-width: none;
     }
 
-    label.checkbox {
-      position: relative;
-      padding-left: 25px;
+    &__column {
+      box-sizing: border-box;
+      padding: 0 10px;
       flex: 1 1 auto;
+      min-height: 1px;
+
+      &-6 {
+        max-width: 50%;
+      }
     }
 
-    input[type=checkbox] {
-      position: absolute;
-      left: 0;
-      top: 5px;
-      margin: 0;
+    .fields-group:last-child,
+    .fields-row__column.fields-group {
+      margin-bottom: 0;
     }
 
-    .hint {
-      padding-left: 25px;
-      margin-left: 0;
+    @media screen and (max-width: $no-columns-breakpoint) {
+      display: block;
+      margin-bottom: 0;
+
+      &__column {
+        max-width: none;
+      }
+
+      .fields-group:last-child,
+      .fields-row__column.fields-group,
+      .fields-row__column {
+        margin-bottom: 25px;
+      }
     }
   }
 
+  .input.radio_buttons .radio label {
+    margin-bottom: 5px;
+    font-family: inherit;
+    font-size: 14px;
+    color: $primary-text-color;
+    display: block;
+    width: auto;
+  }
+
   .check_boxes {
     .checkbox {
       label {
@@ -236,12 +288,7 @@ code {
   input[type=email],
   input[type=password],
   textarea {
-    background: transparent;
     box-sizing: border-box;
-    border: 0;
-    border-bottom: 2px solid $ui-primary-color;
-    border-radius: 2px 2px 0 0;
-    padding: 7px 4px;
     font-size: 16px;
     color: $primary-text-color;
     display: block;
@@ -249,23 +296,31 @@ code {
     outline: 0;
     font-family: inherit;
     resize: vertical;
+    background: darken($ui-base-color, 10%);
+    border: 1px solid darken($ui-base-color, 14%);
+    border-radius: 4px;
+    padding: 10px;
 
     &:invalid {
       box-shadow: none;
     }
 
     &:focus:invalid {
-      border-bottom-color: lighten($error-red, 12%);
+      border-color: lighten($error-red, 12%);
     }
 
     &:required:valid {
-      border-bottom-color: $valid-value-color;
+      border-color: $valid-value-color;
+    }
+
+    &:hover {
+      border-color: darken($ui-base-color, 20%);
     }
 
     &:active,
     &:focus {
-      border-bottom-color: $highlight-text-color;
-      background: rgba($base-overlay-background, 0.1);
+      border-color: $highlight-text-color;
+      background: darken($ui-base-color, 8%);
     }
   }
 
@@ -349,22 +404,32 @@ code {
   }
 
   select {
+    appearance: none;
+    box-sizing: border-box;
     font-size: 16px;
-    max-height: 29px;
+    color: $primary-text-color;
+    display: block;
+    width: 100%;
+    outline: 0;
+    font-family: inherit;
+    resize: vertical;
+    background: darken($ui-base-color, 10%) url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 14.933 18.467' height='19.698' width='15.929'><path d='M3.467 14.967l-3.393-3.5H14.86l-3.392 3.5c-1.866 1.925-3.666 3.5-4 3.5-.335 0-2.135-1.575-4-3.5zm.266-11.234L7.467 0 11.2 3.733l3.733 3.734H0l3.733-3.734z' fill='#{hex-color(lighten($ui-base-color, 12%))}'/></svg>") no-repeat right 8px center / auto 16px;
+    border: 1px solid darken($ui-base-color, 14%);
+    border-radius: 4px;
+    padding: 10px;
+    height: 41px;
   }
 
-  .input-with-append {
-    position: relative;
-
-    .input input {
-      padding-right: 142px;
+  .label_input {
+    &__wrapper {
+      position: relative;
     }
 
-    .append {
+    &__append {
       position: absolute;
-      right: 0;
-      top: 0;
-      padding: 7px 4px;
+      right: 1px;
+      top: 1px;
+      padding: 10px;
       padding-bottom: 9px;
       font-size: 16px;
       color: $dark-text-color;
@@ -383,7 +448,7 @@ code {
         right: 0;
         bottom: 1px;
         width: 5px;
-        background-image: linear-gradient(to right, rgba($ui-base-color, 0), $ui-base-color);
+        background-image: linear-gradient(to right, rgba(darken($ui-base-color, 10%), 0), darken($ui-base-color, 10%));
       }
     }
   }
@@ -459,6 +524,30 @@ code {
   }
 }
 
+.quick-nav {
+  list-style: none;
+  margin-bottom: 25px;
+  font-size: 14px;
+
+  li {
+    display: inline-block;
+    margin-right: 10px;
+  }
+
+  a {
+    color: $highlight-text-color;
+    text-transform: uppercase;
+    text-decoration: none;
+    font-weight: 700;
+
+    &:hover,
+    &:focus,
+    &:active {
+      color: lighten($highlight-text-color, 8%);
+    }
+  }
+}
+
 .oauth-prompt,
 .follow-prompt {
   margin-bottom: 30px;
@@ -632,3 +721,49 @@ code {
     font-family: 'mastodon-font-monospace', monospace;
   }
 }
+
+.input-copy {
+  background: darken($ui-base-color, 10%);
+  border: 1px solid darken($ui-base-color, 14%);
+  border-radius: 4px;
+  display: flex;
+  align-items: center;
+  padding-right: 4px;
+  position: relative;
+  top: 1px;
+  transition: border-color 300ms linear;
+
+  &__wrapper {
+    flex: 1 1 auto;
+  }
+
+  input[type=text] {
+    background: transparent;
+    border: 0;
+    padding: 10px;
+    font-size: 14px;
+    font-family: 'mastodon-font-monospace', monospace;
+  }
+
+  button {
+    flex: 0 0 auto;
+    margin: 4px;
+    text-transform: none;
+    font-weight: 400;
+    font-size: 14px;
+    padding: 7px 18px;
+    padding-bottom: 6px;
+    width: auto;
+    transition: background 300ms linear;
+  }
+
+  &.copied {
+    border-color: $valid-value-color;
+    transition: none;
+
+    button {
+      background: $valid-value-color;
+      transition: none;
+    }
+  }
+}
diff --git a/app/lib/activitypub/activity/update.rb b/app/lib/activitypub/activity/update.rb
index 6eebc3b5c..67dae3f81 100644
--- a/app/lib/activitypub/activity/update.rb
+++ b/app/lib/activitypub/activity/update.rb
@@ -11,6 +11,7 @@ class ActivityPub::Activity::Update < ActivityPub::Activity
 
   def update_account
     return if @account.uri != object_uri
+
     ActivityPub::ProcessAccountService.new.call(@account.username, @account.domain, @object, signed_with_known_key: true)
   end
 end
diff --git a/app/models/account.rb b/app/models/account.rb
index c84a7406d..d0c4c1a6d 100644
--- a/app/models/account.rb
+++ b/app/models/account.rb
@@ -226,11 +226,19 @@ class Account < ApplicationRecord
   end
 
   def fields_attributes=(attributes)
-    fields = []
+    fields     = []
+    old_fields = self[:fields] || []
 
     if attributes.is_a?(Hash)
       attributes.each_value do |attr|
         next if attr[:name].blank?
+
+        previous = old_fields.find { |item| item['value'] == attr[:value] }
+
+        if previous && previous['verified_at'].present?
+          attr[:verified_at] = previous['verified_at']
+        end
+
         fields << attr
       end
     end
@@ -238,13 +246,18 @@ class Account < ApplicationRecord
     self[:fields] = fields
   end
 
+  DEFAULT_FIELDS_SIZE = 4
+
   def build_fields
-    return if fields.size >= 4
+    return if fields.size >= DEFAULT_FIELDS_SIZE
+
+    tmp = self[:fields] || []
+
+    (DEFAULT_FIELDS_SIZE - tmp.size).times do
+      tmp << { name: '', value: '' }
+    end
 
-    raw_fields = self[:fields] || []
-    add_fields = 4 - raw_fields.size
-    add_fields.times { raw_fields << { name: '', value: '' } }
-    self.fields = raw_fields
+    self.fields = tmp
   end
 
   def magic_key
@@ -297,17 +310,32 @@ class Account < ApplicationRecord
   end
 
   class Field < ActiveModelSerializers::Model
-    attributes :name, :value, :account, :errors
+    attributes :name, :value, :verified_at, :account, :errors
+
+    def initialize(account, attributes)
+      @account     = account
+      @attributes  = attributes
+      @name        = attributes['name'].strip[0, 255]
+      @value       = attributes['value'].strip[0, 255]
+      @verified_at = attributes['verified_at']&.to_datetime
+      @errors      = {}
+    end
+
+    def verified?
+      verified_at.present?
+    end
+
+    def verifiable?
+      value.present? && value.start_with?('http://', 'https://')
+    end
 
-    def initialize(account, attr)
-      @account = account
-      @name    = attr['name'].strip[0, 255]
-      @value   = attr['value'].strip[0, 255]
-      @errors  = {}
+    def mark_verified!
+      @verified_at = Time.now.utc
+      @attributes['verified_at'] = @verified_at
     end
 
     def to_h
-      { name: @name, value: @value }
+      { name: @name, value: @value, verified_at: @verified_at }
     end
   end
 
diff --git a/app/models/status.rb b/app/models/status.rb
index f9c0c68d9..028927cc3 100644
--- a/app/models/status.rb
+++ b/app/models/status.rb
@@ -248,7 +248,7 @@ class Status < ApplicationRecord
 
     def as_direct_timeline(account, limit = 20, max_id = nil, since_id = nil, cache_ids = false)
       # direct timeline is mix of direct message from_me and to_me.
-      # 2 querys are executed with pagination.
+      # 2 queries are executed with pagination.
       # constant expression using arel_table is required for partial index
 
       # _from_me part does not require any timeline filters
diff --git a/app/serializers/rest/account_serializer.rb b/app/serializers/rest/account_serializer.rb
index 3a724aa7c..d84b48afb 100644
--- a/app/serializers/rest/account_serializer.rb
+++ b/app/serializers/rest/account_serializer.rb
@@ -13,6 +13,10 @@ class REST::AccountSerializer < ActiveModel::Serializer
   class FieldSerializer < ActiveModel::Serializer
     attributes :name, :value
 
+    attribute :verified_at, if: :verifiable?
+
+    delegate :verifiable?, to: :object
+
     def value
       Formatter.instance.format_field(object.account, object.value)
     end
diff --git a/app/services/activitypub/process_account_service.rb b/app/services/activitypub/process_account_service.rb
index 670a0e4d6..c77858f1d 100644
--- a/app/services/activitypub/process_account_service.rb
+++ b/app/services/activitypub/process_account_service.rb
@@ -34,6 +34,7 @@ class ActivityPub::ProcessAccountService < BaseService
     after_protocol_change! if protocol_changed?
     after_key_change! if key_changed? && !@options[:signed_with_known_key]
     check_featured_collection! if @account.featured_collection_url.present?
+    check_links! unless @account.fields.empty?
 
     @account
   rescue Oj::ParseError
@@ -99,6 +100,10 @@ class ActivityPub::ProcessAccountService < BaseService
     ActivityPub::SynchronizeFeaturedCollectionWorker.perform_async(@account.id)
   end
 
+  def check_links!
+    VerifyAccountLinksWorker.perform_async(@account.id)
+  end
+
   def actor_type
     if @json['type'].is_a?(Array)
       @json['type'].find { |type| ActivityPub::FetchRemoteAccountService::SUPPORTED_TYPES.include?(type) }
diff --git a/app/services/fetch_link_card_service.rb b/app/services/fetch_link_card_service.rb
index ea94e2491..4169c685b 100644
--- a/app/services/fetch_link_card_service.rb
+++ b/app/services/fetch_link_card_service.rb
@@ -29,7 +29,7 @@ class FetchLinkCardService < BaseService
     end
 
     attach_card if @card&.persisted?
-  rescue HTTP::Error, Addressable::URI::InvalidURIError, Mastodon::LengthValidationError => e
+  rescue HTTP::Error, Addressable::URI::InvalidURIError, Mastodon::HostValidationError, Mastodon::LengthValidationError => e
     Rails.logger.debug "Error fetching link #{@url}: #{e}"
     nil
   end
diff --git a/app/services/update_account_service.rb b/app/services/update_account_service.rb
index 09ea377e7..ec69d944a 100644
--- a/app/services/update_account_service.rb
+++ b/app/services/update_account_service.rb
@@ -2,20 +2,26 @@
 
 class UpdateAccountService < BaseService
   def call(account, params, raise_error: false)
-    was_locked = account.locked
+    was_locked    = account.locked
     update_method = raise_error ? :update! : :update
+
     account.send(update_method, params).tap do |ret|
       next unless ret
+
       authorize_all_follow_requests(account) if was_locked && !account.locked
+      check_links(account)
     end
   end
 
   private
 
   def authorize_all_follow_requests(account)
-    follow_requests = FollowRequest.where(target_account: account)
-    AuthorizeFollowWorker.push_bulk(follow_requests) do |req|
+    AuthorizeFollowWorker.push_bulk(FollowRequest.where(target_account: account).select(:account_id, :target_account_id)) do |req|
       [req.account_id, req.target_account_id]
     end
   end
+
+  def check_links(account)
+    VerifyAccountLinksWorker.perform_async(account.id)
+  end
 end
diff --git a/app/services/verify_link_service.rb b/app/services/verify_link_service.rb
new file mode 100644
index 000000000..846751cd5
--- /dev/null
+++ b/app/services/verify_link_service.rb
@@ -0,0 +1,32 @@
+# frozen_string_literal: true
+
+class VerifyLinkService < BaseService
+  def call(field)
+    @link_back = ActivityPub::TagManager.instance.url_for(field.account)
+    @url       = field.value
+
+    perform_request!
+
+    return unless link_back_present?
+
+    field.mark_verified!
+    field.account.save!
+  rescue HTTP::Error, Addressable::URI::InvalidURIError, Mastodon::HostValidationError, Mastodon::LengthValidationError => e
+    Rails.logger.debug "Error fetching link #{@url}: #{e}"
+    nil
+  end
+
+  private
+
+  def perform_request!
+    @body = Request.new(:get, @url).add_headers('Accept' => 'text/html').perform do |res|
+      res.code != 200 ? nil : res.body_with_limit
+    end
+  end
+
+  def link_back_present?
+    return false if @body.empty?
+
+    Nokogiri::HTML(@body).xpath('//a[contains(concat(" ", normalize-space(@rel), " "), " me ")]|//link[contains(concat(" ", normalize-space(@rel), " "), " me ")]').any? { |link| link['href'] == @link_back }
+  end
+end
diff --git a/app/views/about/_registration.html.haml b/app/views/about/_registration.html.haml
index 6ca1d7129..ee4f8fe2e 100644
--- a/app/views/about/_registration.html.haml
+++ b/app/views/about/_registration.html.haml
@@ -1,13 +1,10 @@
 = simple_form_for(new_user, url: user_registration_path) do |f|
   = f.simple_fields_for :account do |account_fields|
-    .input-with-append
-      = account_fields.input :username, autofocus: true, placeholder: t('simple_form.labels.defaults.username'), required: true, input_html: { 'aria-label' => t('simple_form.labels.defaults.username'), :autocomplete => 'off' }
-      .append
-        = "@#{site_hostname}"
+    = account_fields.input :username, wrapper: :with_label, autofocus: true, label: false, required: true, input_html: { 'aria-label' => t('simple_form.labels.defaults.username'), :autocomplete => 'off', placeholder: t('simple_form.labels.defaults.username') }, append: "@#{site_hostname}", hint: false
 
-  = f.input :email, placeholder: t('simple_form.labels.defaults.email'), required: true, input_html: { 'aria-label' => t('simple_form.labels.defaults.email'), :autocomplete => 'off' }
-  = f.input :password, placeholder: t('simple_form.labels.defaults.password'), required: true, input_html: { 'aria-label' => t('simple_form.labels.defaults.password'), :autocomplete => 'off' }
-  = f.input :password_confirmation, placeholder: t('simple_form.labels.defaults.confirm_password'), required: true, input_html: { 'aria-label' => t('simple_form.labels.defaults.confirm_password'), :autocomplete => 'off' }
+  = f.input :email, placeholder: t('simple_form.labels.defaults.email'), required: true, input_html: { 'aria-label' => t('simple_form.labels.defaults.email'), :autocomplete => 'off' }, hint: false
+  = f.input :password, placeholder: t('simple_form.labels.defaults.password'), required: true, input_html: { 'aria-label' => t('simple_form.labels.defaults.password'), :autocomplete => 'off' }, hint: false
+  = f.input :password_confirmation, placeholder: t('simple_form.labels.defaults.confirm_password'), required: true, input_html: { 'aria-label' => t('simple_form.labels.defaults.confirm_password'), :autocomplete => 'off' }, hint: false
 
   .actions
     = f.button :button, t('auth.register'), type: :submit, class: 'button button-primary'
diff --git a/app/views/about/more.html.haml b/app/views/about/more.html.haml
index 46eb17cf7..99028935f 100644
--- a/app/views/about/more.html.haml
+++ b/app/views/about/more.html.haml
@@ -24,7 +24,7 @@
             %span= t 'about.status_count_after', count: @instance_presenter.status_count
         .row__mascot
           .landing-page__mascot
-            = image_tag asset_pack_path('elephant_ui_plane.svg')
+            = image_tag asset_pack_path('elephant_ui_plane.svg'), alt: ''
 
   .column-2
     .landing-page__information.contact-widget
diff --git a/app/views/about/show.html.haml b/app/views/about/show.html.haml
index fd76a6b7d..48435fe9c 100644
--- a/app/views/about/show.html.haml
+++ b/app/views/about/show.html.haml
@@ -62,7 +62,7 @@
                   %span= t 'about.status_count_after', count: @instance_presenter.status_count
               .row__mascot
                 .landing-page__mascot
-                  = image_tag asset_pack_path('elephant_ui_plane.svg')
+                  = image_tag asset_pack_path('elephant_ui_plane.svg'), alt: ''
 
       - else
         .column-2.non-preview
@@ -94,7 +94,7 @@
                   %span= t 'about.status_count_after', count: @instance_presenter.status_count
               .row__mascot
                 .landing-page__mascot
-                  = image_tag asset_pack_path('elephant_ui_plane.svg')
+                  = image_tag asset_pack_path('elephant_ui_plane.svg'), alt: ''
 
       - if Setting.timeline_preview
         .column-3
diff --git a/app/views/accounts/_bio.html.haml b/app/views/accounts/_bio.html.haml
index 4e674beff..2ea34a048 100644
--- a/app/views/accounts/_bio.html.haml
+++ b/app/views/accounts/_bio.html.haml
@@ -4,8 +4,11 @@
       - account.fields.each do |field|
         %dl
           %dt.emojify{ title: field.name }= Formatter.instance.format_field(account, field.name, custom_emojify: true)
-          %dd.emojify{ title: field.value }= Formatter.instance.format_field(account, field.value, custom_emojify: true)
-
+          %dd{ title: field.value, class: custom_field_classes(field) }
+            - if field.verified?
+              %span.verified__mark{ title: t('accounts.link_verified_on', date: l(field.verified_at)) }
+                = fa_icon 'check'
+            = Formatter.instance.format_field(account, field.value, custom_emojify: true)
   = account_badge(account)
 
   - if account.note.present?
diff --git a/app/views/accounts/_header.html.haml b/app/views/accounts/_header.html.haml
index bfad49b6c..3da270d27 100644
--- a/app/views/accounts/_header.html.haml
+++ b/app/views/accounts/_header.html.haml
@@ -16,7 +16,7 @@
             = fa_icon('lock') if account.locked?
       .public-account-header__tabs__tabs
         .details-counters
-          .counter{ class: active_nav_class(short_account_url(account)) }
+          .counter{ class: active_nav_class(short_account_url(account)) + active_nav_class(short_account_with_replies_url(account)) + active_nav_class(short_account_media_url(account)) }
             = link_to short_account_url(account), class: 'u-url u-uid', title: number_with_delimiter(account.statuses_count) do
               %span.counter-number= number_to_human account.statuses_count, strip_insignificant_zeros: true
               %span.counter-label= t('accounts.posts', count: account.statuses_count)
diff --git a/app/views/admin/change_emails/show.html.haml b/app/views/admin/change_emails/show.html.haml
index a661b1ad6..6febef9b1 100644
--- a/app/views/admin/change_emails/show.html.haml
+++ b/app/views/admin/change_emails/show.html.haml
@@ -2,6 +2,11 @@
   = t('admin.accounts.change_email.title', username: @account.acct)
 
 = simple_form_for @user, url: admin_account_change_email_path(@account.id) do |f|
-  = f.input :email, wrapper: :with_label, disabled: true, label: t('admin.accounts.change_email.current_email')
-  = f.input :unconfirmed_email, wrapper: :with_label, label: t('admin.accounts.change_email.new_email')
-  = f.button :submit, class: "button", value: t('admin.accounts.change_email.submit')
+  .fields-group
+    = f.input :email, wrapper: :with_label, disabled: true, label: t('admin.accounts.change_email.current_email')
+
+  .fields-group
+    = f.input :unconfirmed_email, wrapper: :with_label, label: t('admin.accounts.change_email.new_email')
+
+  .actions
+    = f.button :submit, class: "button", value: t('admin.accounts.change_email.submit')
diff --git a/app/views/admin/custom_emojis/new.html.haml b/app/views/admin/custom_emojis/new.html.haml
index 672afe435..e15a07cb8 100644
--- a/app/views/admin/custom_emojis/new.html.haml
+++ b/app/views/admin/custom_emojis/new.html.haml
@@ -5,8 +5,9 @@
   = render 'shared/error_messages', object: @custom_emoji
 
   .fields-group
-    = f.input :shortcode, placeholder: t('admin.custom_emojis.shortcode'), hint: t('admin.custom_emojis.shortcode_hint')
-    = f.input :image, input_html: { accept: 'image/png' }, hint: t('admin.custom_emojis.image_hint')
+    = f.input :shortcode, wrapper: :with_label, label: t('admin.custom_emojis.shortcode'), hint: t('admin.custom_emojis.shortcode_hint')
+  .fields-group
+    = f.input :image, wrapper: :with_label, input_html: { accept: 'image/png' }, hint: t('admin.custom_emojis.image_hint')
 
   .actions
     = f.button :button, t('admin.custom_emojis.upload'), type: :submit
diff --git a/app/views/admin/domain_blocks/new.html.haml b/app/views/admin/domain_blocks/new.html.haml
index 38fa90169..6e514f833 100644
--- a/app/views/admin/domain_blocks/new.html.haml
+++ b/app/views/admin/domain_blocks/new.html.haml
@@ -4,14 +4,15 @@
 = simple_form_for @domain_block, url: admin_domain_blocks_path do |f|
   = render 'shared/error_messages', object: @domain_block
 
-  %p.hint= t('.hint')
+  .fields-row
+    .fields-row__column.fields-row__column-6.fields-group
+      = f.input :domain, wrapper: :with_label, label: t('admin.domain_blocks.domain'), hint: t('.hint'), required: true
 
-  = f.input :domain, placeholder: t('admin.domain_blocks.domain')
-  = f.input :severity, collection: DomainBlock.severities.keys, wrapper: :with_label, include_blank: false, label_method: lambda { |type| t(".severity.#{type}") }
+    .fields-row__column.fields-row__column-6.fields-group
+      = f.input :severity, collection: DomainBlock.severities.keys, wrapper: :with_label, include_blank: false, label_method: lambda { |type| t(".severity.#{type}") }, hint: t('.severity.desc_html')
 
-  %p.hint= t('.severity.desc_html')
-
-  = f.input :reject_media, as: :boolean, wrapper: :with_label, label: I18n.t('admin.domain_blocks.reject_media'), hint: I18n.t('admin.domain_blocks.reject_media_hint')
+  .fields-group
+    = f.input :reject_media, as: :boolean, wrapper: :with_label, label: I18n.t('admin.domain_blocks.reject_media'), hint: I18n.t('admin.domain_blocks.reject_media_hint')
 
   .actions
     = f.button :button, t('.create'), type: :submit
diff --git a/app/views/admin/email_domain_blocks/new.html.haml b/app/views/admin/email_domain_blocks/new.html.haml
index bcae867d9..f372fa512 100644
--- a/app/views/admin/email_domain_blocks/new.html.haml
+++ b/app/views/admin/email_domain_blocks/new.html.haml
@@ -4,7 +4,8 @@
 = simple_form_for @email_domain_block, url: admin_email_domain_blocks_path do |f|
   = render 'shared/error_messages', object: @email_domain_block
 
-  = f.input :domain, placeholder: t('admin.email_domain_blocks.domain')
+  .fields-group
+    = f.input :domain, wrapper: :with_label, label: t('admin.email_domain_blocks.domain')
 
   .actions
     = f.button :button, t('.create'), type: :submit
diff --git a/app/views/admin/reports/_account.html.haml b/app/views/admin/reports/_account.html.haml
deleted file mode 100644
index 9ac161c9c..000000000
--- a/app/views/admin/reports/_account.html.haml
+++ /dev/null
@@ -1,19 +0,0 @@
-- size ||= 36
-
-.account.compact
-  .account__wrapper
-    - if account.nil?
-      .account__display-name
-        .account__avatar-wrapper
-          .account__avatar{ style: "background-image: url(#{full_asset_url('avatars/original/missing.png', skip_pipeline: true)}); width: #{size}px; height: #{size}px; background-size: #{size}px #{size}px" }
-        %span.display-name
-          %strong= t 'about.contact_missing'
-          %span.display-name__account= t 'about.contact_unavailable'
-    - else
-      = link_to TagManager.instance.url_for(account), class: 'account__display-name' do
-        .account__avatar-wrapper
-          .account__avatar{ style: "background-image: url(#{account.avatar.url}); width: #{size}px; height: #{size}px; background-size: #{size}px #{size}px" }
-        %span.display-name
-          %bdi
-            %strong.display-name__html.emojify= display_name(account, custom_emojify: true)
-          %span.display-name__account @#{account.acct}
diff --git a/app/views/admin/reports/_report.html.haml b/app/views/admin/reports/_report.html.haml
deleted file mode 100644
index 7b25c924b..000000000
--- a/app/views/admin/reports/_report.html.haml
+++ /dev/null
@@ -1,29 +0,0 @@
-%tr
-  %td.id
-    = "##{report.id}"
-  %td.target
-    = admin_account_link_to report.target_account
-  %td.reporter
-    - if report.account.local?
-      = admin_account_link_to report.account
-    - else
-      = report.account.domain
-  %td
-    %div{ title: report.comment }
-      = truncate(report.comment, length: 30, separator: ' ')
-    %div
-      - unless report.statuses.empty?
-        %span{ title: t('admin.accounts.statuses') }
-          = fa_icon('comment')
-          = report.statuses.count
-      - unless report.media_attachments.empty?
-        %span{ title: t('admin.accounts.media_attachments') }
-          = fa_icon('camera')
-          = report.media_attachments.count
-  %td
-    - if report.assigned_account.nil?
-      \-
-    - else
-      = admin_account_link_to report.assigned_account
-  %td
-    = table_link_to 'circle', t('admin.reports.view'), admin_report_path(report)
diff --git a/app/views/admin/reports/index.html.haml b/app/views/admin/reports/index.html.haml
index 44a531f2c..d73faccb0 100644
--- a/app/views/admin/reports/index.html.haml
+++ b/app/views/admin/reports/index.html.haml
@@ -8,17 +8,45 @@
       %li= filter_link_to t('admin.reports.unresolved'), resolved: nil
       %li= filter_link_to t('admin.reports.resolved'), resolved: '1'
 
-.table-wrapper
-  %table.table
-    %thead
-      %tr
-        %th= t('admin.reports.id')
-        %th= t('admin.reports.target')
-        %th= t('admin.reports.reported_by')
-        %th= t('admin.reports.report_contents')
-        %th= t('admin.reports.assigned')
-        %th
-    %tbody
-      = render @reports
+- @reports.group_by(&:target_account_id).each do |target_account_id, reports|
+  - target_account = reports.first.target_account
+  .report-card
+    .report-card__profile
+      = account_link_to target_account, '', size: 36, path: admin_account_path(target_account.id)
+      .report-card__profile__stats
+        = link_to pluralize(target_account.targeted_moderation_notes.count, t('admin.reports.account.note')), admin_account_path(target_account.id)
+        %br/
+        - if target_account.suspended?
+          %span.red= t('admin.accounts.suspended')
+        - elsif target_account.silenced?
+          %span.red= t('admin.accounts.silenced')
+        - elsif target_account.user&.disabled?
+          %span.red= t('admin.accounts.disabled')
+        - else
+          %span.neutral= t('admin.accounts.no_limits_imposed')
+    .report-card__summary
+      - reports.each do |report|
+        .report-card__summary__item
+          .report-card__summary__item__reported-by
+            - if report.account.local?
+              = admin_account_link_to report.account
+            - else
+              = report.account.domain
+          .report-card__summary__item__content
+            = link_to admin_report_path(report) do
+              .one-line= report.comment.presence || t('admin.reports.comment.none')
 
+              %span.report-card__summary__item__content__icon{ title: t('admin.accounts.statuses') }
+                = fa_icon('comment')
+                = report.statuses.count
+
+              %span.report-card__summary__item__content__icon{ title: t('admin.accounts.media_attachments') }
+                = fa_icon('camera')
+                = report.media_attachments.count
+
+          .report-card__summary__item__assigned
+            - if report.assigned_account.present?
+              = admin_account_link_to report.assigned_account
+            - else
+              \-
 = paginate @reports
diff --git a/app/views/admin/settings/edit.html.haml b/app/views/admin/settings/edit.html.haml
index abe7ecf32..b4abbf815 100644
--- a/app/views/admin/settings/edit.html.haml
+++ b/app/views/admin/settings/edit.html.haml
@@ -2,24 +2,37 @@
   = t('admin.settings.title')
 
 = simple_form_for @admin_settings, url: admin_settings_path, html: { method: :patch } do |f|
-  .actions.actions--top
-    = f.button :button, t('generic.save_changes'), type: :submit
 
   .fields-group
-    = f.input :site_title, placeholder: t('admin.settings.site_title')
-    = f.input :site_short_description, wrapper: :with_block_label, as: :text, label: t('admin.settings.site_short_description.title'), hint: t('admin.settings.site_short_description.desc_html'), input_html: { rows: 2 }
+    = f.input :site_title, wrapper: :with_label, label: t('admin.settings.site_title')
+
+  .fields-group
+    = f.input :flavour, collection: Themes.instance.flavours, label_method: lambda { |flavour| I18n.t("flavours.#{flavour}.name", default: flavour) }, wrapper: :with_label, include_blank: false
+
+  .fields-row
+    .fields-row__column.fields-row__column-6.fields-group
+      = f.input :site_contact_username, wrapper: :with_label, label: t('admin.settings.contact_information.username')
+    .fields-row__column.fields-row__column-6.fields-group
+      = f.input :site_contact_email, wrapper: :with_label, label: t('admin.settings.contact_information.email')
+
+  .fields-group
     = f.input :site_description, wrapper: :with_block_label, as: :text, label: t('admin.settings.site_description.title'), hint: t('admin.settings.site_description.desc_html'), input_html: { rows: 4 }
-    = f.input :site_contact_username, placeholder: t('admin.settings.contact_information.username')
-    = f.input :site_contact_email, placeholder: t('admin.settings.contact_information.email')
 
-  %hr/
+  .fields-group
+    = f.input :site_short_description, wrapper: :with_block_label, as: :text, label: t('admin.settings.site_short_description.title'), hint: t('admin.settings.site_short_description.desc_html'), input_html: { rows: 2 }
+
+  .fields-row
+    .fields-row__column.fields-row__column-6.fields-group
+      = f.input :thumbnail, as: :file, wrapper: :with_block_label, label: t('admin.settings.thumbnail.title'), hint: t('admin.settings.thumbnail.desc_html')
+    .fields-row__column.fields-row__column-6.fields-group
+      = f.input :hero, as: :file, wrapper: :with_block_label, label: t('admin.settings.hero.title'), hint: t('admin.settings.hero.desc_html')
+
+  %hr.spacer/
 
   .fields-group
-    = f.input :flavour, collection: Themes.instance.flavours, label_method: lambda { |flavour| I18n.t("flavours.#{flavour}.name", default: flavour) }, wrapper: :with_label, include_blank: false
-    = f.input :thumbnail, as: :file, wrapper: :with_block_label, label: t('admin.settings.thumbnail.title'), hint: t('admin.settings.thumbnail.desc_html')
-    = f.input :hero, as: :file, wrapper: :with_block_label, label: t('admin.settings.hero.title'), hint: t('admin.settings.hero.desc_html')
+    = f.input :bootstrap_timeline_accounts, wrapper: :with_block_label, label: t('admin.settings.bootstrap_timeline_accounts.title'), hint: t('admin.settings.bootstrap_timeline_accounts.desc_html')
 
-  %hr/
+  %hr.spacer/
 
   .fields-group
     = f.input :timeline_preview, as: :boolean, wrapper: :with_label, label: t('admin.settings.timeline_preview.title'), hint: t('admin.settings.timeline_preview.desc_html')
@@ -37,34 +50,24 @@
     = f.input :open_deletion, as: :boolean, wrapper: :with_label, label: t('admin.settings.registrations.deletion.title'), hint: t('admin.settings.registrations.deletion.desc_html')
 
   .fields-group
-    = f.input :closed_registrations_message, as: :text, wrapper: :with_block_label, label: t('admin.settings.registrations.closed_message.title'), hint: t('admin.settings.registrations.closed_message.desc_html'), input_html: { rows: 8 }
-
-  %hr/
-
-  .fields-group
-    = f.input :min_invite_role, wrapper: :with_label, collection: %i(disabled user moderator admin), label: t('admin.settings.registrations.min_invite_role.title'), label_method: lambda { |role| role == :disabled ? t('admin.settings.registrations.min_invite_role.disabled') : t("admin.accounts.roles.#{role}") }, as: :radio_buttons, include_blank: false, collection_wrapper_tag: 'ul', item_wrapper_tag: 'li'
-
-  %hr/
+    = f.input :activity_api_enabled, as: :boolean, wrapper: :with_label, label: t('admin.settings.activity_api_enabled.title'), hint: t('admin.settings.activity_api_enabled.desc_html')
 
   .fields-group
-    = f.input :site_extended_description, wrapper: :with_block_label, as: :text, label: t('admin.settings.site_description_extended.title'), hint: t('admin.settings.site_description_extended.desc_html'), input_html: { rows: 8 }
-    = f.input :site_terms, wrapper: :with_block_label, as: :text, label: t('admin.settings.site_terms.title'), hint: t('admin.settings.site_terms.desc_html'), input_html: { rows: 8 }
-    = f.input :custom_css, wrapper: :with_block_label, as: :text, input_html: { rows: 8 }, label: t('admin.settings.custom_css.title'), hint: t('admin.settings.custom_css.desc_html')
-  %hr/
+    = f.input :peers_api_enabled, as: :boolean, wrapper: :with_label, label: t('admin.settings.peers_api_enabled.title'), hint: t('admin.settings.peers_api_enabled.desc_html')
 
   .fields-group
-    = f.input :bootstrap_timeline_accounts, wrapper: :with_block_label, label: t('admin.settings.bootstrap_timeline_accounts.title'), hint: t('admin.settings.bootstrap_timeline_accounts.desc_html')
+    = f.input :preview_sensitive_media, as: :boolean, wrapper: :with_label, label: t('admin.settings.preview_sensitive_media.title'), hint: t('admin.settings.preview_sensitive_media.desc_html')
 
-  %hr/
+  %hr.spacer/
 
   .fields-group
-    = f.input :activity_api_enabled, as: :boolean, wrapper: :with_label, label: t('admin.settings.activity_api_enabled.title'), hint: t('admin.settings.activity_api_enabled.desc_html')
+    = f.input :min_invite_role, wrapper: :with_label, collection: %i(disabled user moderator admin), label: t('admin.settings.registrations.min_invite_role.title'), label_method: lambda { |role| role == :disabled ? t('admin.settings.registrations.min_invite_role.disabled') : t("admin.accounts.roles.#{role}") }, include_blank: false, collection_wrapper_tag: 'ul', item_wrapper_tag: 'li'
 
   .fields-group
-    = f.input :peers_api_enabled, as: :boolean, wrapper: :with_label, label: t('admin.settings.peers_api_enabled.title'), hint: t('admin.settings.peers_api_enabled.desc_html')
-
-  .fields-group
-    = f.input :preview_sensitive_media, as: :boolean, wrapper: :with_label, label: t('admin.settings.preview_sensitive_media.title'), hint: t('admin.settings.preview_sensitive_media.desc_html')
+    = f.input :closed_registrations_message, as: :text, wrapper: :with_block_label, label: t('admin.settings.registrations.closed_message.title'), hint: t('admin.settings.registrations.closed_message.desc_html'), input_html: { rows: 8 }
+    = f.input :site_extended_description, wrapper: :with_block_label, as: :text, label: t('admin.settings.site_description_extended.title'), hint: t('admin.settings.site_description_extended.desc_html'), input_html: { rows: 8 }
+    = f.input :site_terms, wrapper: :with_block_label, as: :text, label: t('admin.settings.site_terms.title'), hint: t('admin.settings.site_terms.desc_html'), input_html: { rows: 8 }
+    = f.input :custom_css, wrapper: :with_block_label, as: :text, input_html: { rows: 8 }, label: t('admin.settings.custom_css.title'), hint: t('admin.settings.custom_css.desc_html')
 
   .actions
     = f.button :button, t('generic.save_changes'), type: :submit
diff --git a/app/views/auth/confirmations/finish_signup.html.haml b/app/views/auth/confirmations/finish_signup.html.haml
index 4b5161d6b..9d09b74e1 100644
--- a/app/views/auth/confirmations/finish_signup.html.haml
+++ b/app/views/auth/confirmations/finish_signup.html.haml
@@ -8,7 +8,8 @@
         = msg
         %br
 
-  = f.input :email
+  .fields-group
+    = f.input :email, wrapper: :with_label, required: true, hint: false
 
   .actions
     = f.submit t('auth.confirm_email'), class: 'button'
diff --git a/app/views/auth/confirmations/new.html.haml b/app/views/auth/confirmations/new.html.haml
index 07ca4a7da..4a1bedaa4 100644
--- a/app/views/auth/confirmations/new.html.haml
+++ b/app/views/auth/confirmations/new.html.haml
@@ -4,7 +4,8 @@
 = simple_form_for(resource, as: resource_name, url: confirmation_path(resource_name), html: { method: :post }) do |f|
   = render 'shared/error_messages', object: resource
 
-  = f.input :email, autofocus: true, required: true, placeholder: t('simple_form.labels.defaults.email'), input_html: { 'aria-label' => t('simple_form.labels.defaults.email') }
+  .fields-group
+    = f.input :email, autofocus: true, wrapper: :with_label, label: t('simple_form.labels.defaults.email'), input_html: { 'aria-label' => t('simple_form.labels.defaults.email') }, hint: false
 
   .actions
     = f.button :button, t('auth.resend_confirmation'), type: :submit
diff --git a/app/views/auth/passwords/edit.html.haml b/app/views/auth/passwords/edit.html.haml
index 53d1769d6..383d44f00 100644
--- a/app/views/auth/passwords/edit.html.haml
+++ b/app/views/auth/passwords/edit.html.haml
@@ -7,8 +7,10 @@
   - if !use_seamless_external_login? || resource.encrypted_password.present?
     = f.input :reset_password_token, as: :hidden
 
-    = f.input :password, autofocus: true, placeholder: t('simple_form.labels.defaults.new_password'), input_html: { 'aria-label' => t('simple_form.labels.defaults.new_password'), :autocomplete => 'off' }
-    = f.input :password_confirmation, placeholder: t('simple_form.labels.defaults.confirm_new_password'), input_html: { 'aria-label' => t('simple_form.labels.defaults.confirm_new_password'), :autocomplete => 'off' }
+    .fields-group
+      = f.input :password, wrapper: :with_label, autofocus: true, label: t('simple_form.labels.defaults.new_password'), input_html: { 'aria-label' => t('simple_form.labels.defaults.new_password'), :autocomplete => 'off' }, required: true
+    .fields-group
+      = f.input :password_confirmation, wrapper: :with_label, label: t('simple_form.labels.defaults.confirm_new_password'), input_html: { 'aria-label' => t('simple_form.labels.defaults.confirm_new_password'), :autocomplete => 'off' }, required: true
 
     .actions
       = f.button :button, t('auth.set_new_password'), type: :submit
diff --git a/app/views/auth/passwords/new.html.haml b/app/views/auth/passwords/new.html.haml
index f4d22031a..bae5b24ba 100644
--- a/app/views/auth/passwords/new.html.haml
+++ b/app/views/auth/passwords/new.html.haml
@@ -4,7 +4,8 @@
 = simple_form_for(resource, as: resource_name, url: password_path(resource_name), html: { method: :post }) do |f|
   = render 'shared/error_messages', object: resource
 
-  = f.input :email, autofocus: true, required: true, placeholder: t('simple_form.labels.defaults.email'), input_html: { 'aria-label' => t('simple_form.labels.defaults.email') }
+  .fields-group
+    = f.input :email, autofocus: true, wrapper: :with_label, label: t('simple_form.labels.defaults.email'), input_html: { 'aria-label' => t('simple_form.labels.defaults.email') }, hint: false
 
   .actions
     = f.button :button, t('auth.reset_password'), type: :submit
diff --git a/app/views/auth/registrations/edit.html.haml b/app/views/auth/registrations/edit.html.haml
index 05fc7df31..7fc08a23b 100644
--- a/app/views/auth/registrations/edit.html.haml
+++ b/app/views/auth/registrations/edit.html.haml
@@ -1,24 +1,32 @@
 - content_for :page_title do
   = t('auth.security')
 
-%h4= t('auth.change_password')
 = simple_form_for(resource, as: resource_name, url: registration_path(resource_name), html: { method: :put, class: 'auth_edit' }) do |f|
   = render 'shared/error_messages', object: resource
 
   - if !use_seamless_external_login? || resource.encrypted_password.present?
-    = f.input :email, placeholder: t('simple_form.labels.defaults.email'), input_html: { 'aria-label' => t('simple_form.labels.defaults.email') }
-    = f.input :password, placeholder: t('simple_form.labels.defaults.new_password'), input_html: { 'aria-label' => t('simple_form.labels.defaults.new_password'), :autocomplete => 'off' }
-    = f.input :password_confirmation, placeholder: t('simple_form.labels.defaults.confirm_new_password'), input_html: { 'aria-label' => t('simple_form.labels.defaults.confirm_new_password'), :autocomplete => 'off' }
-    = f.input :current_password, placeholder: t('simple_form.labels.defaults.current_password'), input_html: { 'aria-label' => t('simple_form.labels.defaults.current_password'), :autocomplete => 'off' }
+    .fields-group
+      = f.input :email, wrapper: :with_label, input_html: { 'aria-label' => t('simple_form.labels.defaults.email') }, required: true, hint: false
+
+    .fields-group
+      = f.input :password, wrapper: :with_label, input_html: { 'aria-label' => t('simple_form.labels.defaults.new_password'), :autocomplete => 'off' }, hint: false
+
+    .fields-group
+      = f.input :password_confirmation, wrapper: :with_label, label: t('simple_form.labels.defaults.confirm_new_password'), input_html: { 'aria-label' => t('simple_form.labels.defaults.confirm_new_password'), :autocomplete => 'off' }
+
+    .fields-group
+      = f.input :current_password, wrapper: :with_label, input_html: { 'aria-label' => t('simple_form.labels.defaults.current_password'), :autocomplete => 'off' }, required: true
 
     .actions
       = f.button :button, t('generic.save_changes'), type: :submit
   - else
     %p.hint= t('users.seamless_external_login')
 
+%hr.spacer/
+
 = render 'sessions'
 
 - if open_deletion?
-
+  %hr.spacer/
   %h4= t('auth.delete_account')
   %p.muted-hint= t('auth.delete_account_html', path: settings_delete_path)
diff --git a/app/views/auth/registrations/new.html.haml b/app/views/auth/registrations/new.html.haml
index 200ed42de..72ce8e531 100644
--- a/app/views/auth/registrations/new.html.haml
+++ b/app/views/auth/registrations/new.html.haml
@@ -13,18 +13,22 @@
       = render 'application/card', account: @invite.user.account
 
   = f.simple_fields_for :account do |ff|
-    .input-with-append
-      = ff.input :username, autofocus: true, placeholder: t('simple_form.labels.defaults.username'), required: true, input_html: { 'aria-label' => t('simple_form.labels.defaults.username'), :autocomplete => 'off' }
-      .append
-        = "@#{site_hostname}"
-
-  = f.input :email, placeholder: t('simple_form.labels.defaults.email'), required: true, input_html: { 'aria-label' => t('simple_form.labels.defaults.email'), :autocomplete => 'off' }
-  = f.input :password, placeholder: t('simple_form.labels.defaults.password'), required: true, input_html: { 'aria-label' => t('simple_form.labels.defaults.password'), :autocomplete => 'off' }
-  = f.input :password_confirmation, placeholder: t('simple_form.labels.defaults.confirm_password'), required: true, input_html: { 'aria-label' => t('simple_form.labels.defaults.confirm_password'), :autocomplete => 'off' }
+    .fields-group
+      = ff.input :username, wrapper: :with_label, autofocus: true, label: t('simple_form.labels.defaults.username'), required: true, input_html: { 'aria-label' => t('simple_form.labels.defaults.username'), :autocomplete => 'off' }, append: "@#{site_hostname}", hint: t('simple_form.hints.defaults.username', domain: site_hostname)
+
+  .fields-group
+    = f.input :email, wrapper: :with_label, label: t('simple_form.labels.defaults.email'), required: true, input_html: { 'aria-label' => t('simple_form.labels.defaults.email'), :autocomplete => 'off' }
+
+  .fields-group
+    = f.input :password, wrapper: :with_label, label: t('simple_form.labels.defaults.password'), required: true, input_html: { 'aria-label' => t('simple_form.labels.defaults.password'), :autocomplete => 'off' }
+  .fields-group
+    = f.input :password_confirmation, wrapper: :with_label, label: t('simple_form.labels.defaults.confirm_password'), required: true, input_html: { 'aria-label' => t('simple_form.labels.defaults.confirm_password'), :autocomplete => 'off' }
+
   = f.input :invite_code, as: :hidden
 
+  %p.hint= t('auth.agreement_html', rules_path: about_more_path, terms_path: terms_path)
+
   .actions
     = f.button :button, t('auth.register'), type: :submit
 
-  %p.hint.subtle-hint=t('auth.agreement_html', rules_path: about_more_path, terms_path: terms_path)
 .form-footer= render 'auth/shared/links'
diff --git a/app/views/auth/sessions/new.html.haml b/app/views/auth/sessions/new.html.haml
index 0c9f9d5fe..ceb169408 100644
--- a/app/views/auth/sessions/new.html.haml
+++ b/app/views/auth/sessions/new.html.haml
@@ -5,11 +5,13 @@
   = render partial: 'shared/og'
 
 = simple_form_for(resource, as: resource_name, url: session_path(resource_name)) do |f|
-  - if use_seamless_external_login?
-    = f.input :email, autofocus: true, placeholder: t('simple_form.labels.defaults.username_or_email'), required: true, input_html: { 'aria-label' => t('simple_form.labels.defaults.username_or_email') }
-  - else
-    = f.input :email, autofocus: true, placeholder: t('simple_form.labels.defaults.email'), required: true, input_html: { 'aria-label' => t('simple_form.labels.defaults.email') }
-  = f.input :password, placeholder: t('simple_form.labels.defaults.password'), required: true, input_html: { 'aria-label' => t('simple_form.labels.defaults.password'), :autocomplete => 'off' }
+  .fields-group
+    - if use_seamless_external_login?
+      = f.input :email, autofocus: true, wrapper: :with_label, label: t('simple_form.labels.defaults.username_or_email'), input_html: { 'aria-label' => t('simple_form.labels.defaults.username_or_email') }, hint: false
+    - else
+      = f.input :email, autofocus: true, wrapper: :with_label, label: t('simple_form.labels.defaults.email'), input_html: { 'aria-label' => t('simple_form.labels.defaults.email') }, hint: false
+  .fields-group
+    = f.input :password, wrapper: :with_label, label: t('simple_form.labels.defaults.password'), input_html: { 'aria-label' => t('simple_form.labels.defaults.password'), :autocomplete => 'off' }, hint: false
 
   .actions
     = f.button :button, t('auth.login'), type: :submit
diff --git a/app/views/auth/sessions/two_factor.html.haml b/app/views/auth/sessions/two_factor.html.haml
index 1af3193ae..4e6bbd7a9 100644
--- a/app/views/auth/sessions/two_factor.html.haml
+++ b/app/views/auth/sessions/two_factor.html.haml
@@ -4,7 +4,8 @@
 = simple_form_for(resource, as: resource_name, url: session_path(resource_name), method: :post) do |f|
   %p.hint{ style: 'margin-bottom: 25px' }= t('simple_form.hints.sessions.otp')
 
-  = f.input :otp_attempt, type: :number, placeholder: t('simple_form.labels.defaults.otp_attempt'), input_html: { 'aria-label' => t('simple_form.labels.defaults.otp_attempt'), :autocomplete => 'off' }, required: true, autofocus: true
+  .fields-group
+    = f.input :otp_attempt, type: :number, wrapper: :with_label, label: t('simple_form.labels.defaults.otp_attempt'), input_html: { 'aria-label' => t('simple_form.labels.defaults.otp_attempt'), :autocomplete => 'off' }, autofocus: true
 
   .actions
     = f.button :button, t('auth.login'), type: :submit
diff --git a/app/views/filters/_fields.html.haml b/app/views/filters/_fields.html.haml
index a5a3f0337..fb94a07fc 100644
--- a/app/views/filters/_fields.html.haml
+++ b/app/views/filters/_fields.html.haml
@@ -1,14 +1,16 @@
-.fields-group
-  = f.input :phrase, as: :string, wrapper: :with_block_label
+.fields-row
+  .fields-row__column.fields-row__column-6.fields-group
+    = f.input :phrase, as: :string, wrapper: :with_label, hint: false
+  .fields-row__column.fields-row__column-6.fields-group
+    = f.input :expires_in, wrapper: :with_label, collection: [30.minutes, 1.hour, 6.hours, 12.hours, 1.day, 1.week].map(&:to_i), label_method: lambda { |i| I18n.t("invites.expires_in.#{i}") }, prompt: I18n.t('invites.expires_in_prompt')
 
 .fields-group
   = f.input :context, wrapper: :with_block_label, collection: CustomFilter::VALID_CONTEXTS, as: :check_boxes, collection_wrapper_tag: 'ul', item_wrapper_tag: 'li', label_method: lambda { |context| I18n.t("filters.contexts.#{context}") }, include_blank: false
 
+%hr.spacer/
+
 .fields-group
   = f.input :irreversible, wrapper: :with_label
 
 .fields-group
   = f.input :whole_word, wrapper: :with_label
-
-.fields-group
-  = f.input :expires_in, wrapper: :with_label, collection: [30.minutes, 1.hour, 6.hours, 12.hours, 1.day, 1.week].map(&:to_i), label_method: lambda { |i| I18n.t("invites.expires_in.#{i}") }, prompt: I18n.t('invites.expires_in_prompt')
diff --git a/app/views/invites/_form.html.haml b/app/views/invites/_form.html.haml
index 42a107bb2..3a2a5ef0e 100644
--- a/app/views/invites/_form.html.haml
+++ b/app/views/invites/_form.html.haml
@@ -1,9 +1,11 @@
 = simple_form_for(@invite, url: controller.is_a?(Admin::InvitesController) ? admin_invites_path : invites_path) do |f|
   = render 'shared/error_messages', object: @invite
 
-  .fields-group
-    = f.input :max_uses, wrapper: :with_label, collection: [1, 5, 10, 25, 50, 100], label_method: lambda { |num| I18n.t('invites.max_uses', count: num) }, prompt: I18n.t('invites.max_uses_prompt')
-    = f.input :expires_in, wrapper: :with_label, collection: [30.minutes, 1.hour, 6.hours, 12.hours, 1.day, 1.week].map(&:to_i), label_method: lambda { |i| I18n.t("invites.expires_in.#{i}") }, prompt: I18n.t('invites.expires_in_prompt')
+  .fields-row
+    .fields-row__column.fields-row__column-6.fields-group
+      = f.input :max_uses, wrapper: :with_label, collection: [1, 5, 10, 25, 50, 100], label_method: lambda { |num| I18n.t('invites.max_uses', count: num) }, prompt: I18n.t('invites.max_uses_prompt')
+    .fields-row__column.fields-row__column-6.fields-group
+      = f.input :expires_in, wrapper: :with_label, collection: [30.minutes, 1.hour, 6.hours, 12.hours, 1.day, 1.week].map(&:to_i), label_method: lambda { |i| I18n.t("invites.expires_in.#{i}") }, prompt: I18n.t('invites.expires_in_prompt')
 
   .fields-group
     = f.input :autofollow, wrapper: :with_label
diff --git a/app/views/invites/index.html.haml b/app/views/invites/index.html.haml
index f4c5047fa..fb827f6e6 100644
--- a/app/views/invites/index.html.haml
+++ b/app/views/invites/index.html.haml
@@ -6,7 +6,7 @@
 
   = render 'form'
 
-  %hr/
+  %hr.spacer/
 
 %table.table
   %thead
diff --git a/app/views/settings/applications/_fields.html.haml b/app/views/settings/applications/_fields.html.haml
index db90df349..6a2863b20 100644
--- a/app/views/settings/applications/_fields.html.haml
+++ b/app/views/settings/applications/_fields.html.haml
@@ -1,6 +1,8 @@
 .fields-group
-  = f.input :name, placeholder: t('activerecord.attributes.doorkeeper/application.name')
-  = f.input :website, placeholder: t('activerecord.attributes.doorkeeper/application.website')
+  = f.input :name, wrapper: :with_label, label: t('activerecord.attributes.doorkeeper/application.name')
+
+.fields-group
+  = f.input :website, wrapper: :with_label, label: t('activerecord.attributes.doorkeeper/application.website')
 
 .fields-group
   = f.input :redirect_uri, wrapper: :with_block_label, label: t('activerecord.attributes.doorkeeper/application.redirect_uri'), hint: t('doorkeeper.applications.help.redirect_uri')
diff --git a/app/views/settings/exports/show.html.haml b/app/views/settings/exports/show.html.haml
index 792dccd9e..6c030b1ab 100644
--- a/app/views/settings/exports/show.html.haml
+++ b/app/views/settings/exports/show.html.haml
@@ -9,7 +9,7 @@
         %td= number_to_human_size @export.total_storage
         %td
       %tr
-        %th= t('accounts.statuses', count: @export.total_statuses)
+        %th= t('accounts.posts', count: @export.total_statuses)
         %td= number_with_delimiter @export.total_statuses
         %td
       %tr
diff --git a/app/views/settings/imports/show.html.haml b/app/views/settings/imports/show.html.haml
index 2b43cb134..4512fc714 100644
--- a/app/views/settings/imports/show.html.haml
+++ b/app/views/settings/imports/show.html.haml
@@ -2,10 +2,8 @@
   = t('settings.import')
 
 = simple_form_for @import, url: settings_import_path do |f|
-  %p.hint= t('imports.preface')
-
   .field-group
-    = f.input :type, collection: Import.types.keys, wrapper: :with_label, include_blank: false, label_method: lambda { |type| I18n.t("imports.types.#{type}") }, as: :radio_buttons, collection_wrapper_tag: 'ul', item_wrapper_tag: 'li'
+    = f.input :type, collection: Import.types.keys, wrapper: :with_block_label, include_blank: false, label_method: lambda { |type| I18n.t("imports.types.#{type}") }, hint: t('imports.preface')
 
   .field-group
     = f.input :data, wrapper: :with_block_label, hint: t('simple_form.hints.imports.data')
diff --git a/app/views/settings/preferences/show.html.haml b/app/views/settings/preferences/show.html.haml
index 9092780c3..bb267db8a 100644
--- a/app/views/settings/preferences/show.html.haml
+++ b/app/views/settings/preferences/show.html.haml
@@ -1,29 +1,32 @@
 - content_for :page_title do
   = t('settings.preferences')
 
+%ul.quick-nav
+  %li= link_to t('preferences.languages'), '#settings_languages'
+  %li= link_to t('preferences.publishing'), '#settings_publishing'
+  %li= link_to t('preferences.other'), '#settings_other'
+  %li= link_to t('preferences.web'), '#settings_web'
+
 = simple_form_for current_user, url: settings_preferences_path, html: { method: :put } do |f|
   = render 'shared/error_messages', object: current_user
 
-  .actions.actions--top
-    = f.button :button, t('generic.save_changes'), type: :submit
-
-  %h4= t 'preferences.languages'
+  .fields-row#settings_languages
+    .fields-group.fields-row__column.fields-row__column-6
+      = f.input :locale, collection: I18n.available_locales, wrapper: :with_label, include_blank: false, label_method: lambda { |locale| human_locale(locale) }, selected: I18n.locale
+    .fields-group.fields-row__column.fields-row__column-6
+      = f.input :setting_default_language, collection: [nil] + filterable_languages.sort, wrapper: :with_label, label_method: lambda { |locale| locale.nil? ? I18n.t('statuses.language_detection') : human_locale(locale) }, required: false, include_blank: false
 
   .fields-group
-    = f.input :locale, collection: I18n.available_locales, wrapper: :with_label, include_blank: false, label_method: lambda { |locale| human_locale(locale) }, selected: I18n.locale
-
-    = f.input :setting_default_language, collection: [nil] + filterable_languages.sort, wrapper: :with_label, label_method: lambda { |locale| locale.nil? ? I18n.t('statuses.language_detection') : human_locale(locale) }, required: false, include_blank: false
-
     = f.input :chosen_languages, collection: filterable_languages.sort, wrapper: :with_block_label, include_blank: false, label_method: lambda { |locale| human_locale(locale) }, required: false, as: :check_boxes, collection_wrapper_tag: 'ul', item_wrapper_tag: 'li'
 
-  %h4= t 'preferences.publishing'
+  %hr#settings_publishing/
 
   .fields-group
-    = f.input :setting_default_privacy, collection: Status.visibilities.keys - ['direct'], wrapper: :with_label, include_blank: false, label_method: lambda { |visibility| safe_join([I18n.t("statuses.visibilities.#{visibility}"), content_tag(:span, I18n.t("statuses.visibilities.#{visibility}_long"), class: 'hint')]) }, required: false, as: :radio_buttons, collection_wrapper_tag: 'ul', item_wrapper_tag: 'li'
+    = f.input :setting_default_privacy, collection: Status.visibilities.keys - ['direct'], wrapper: :with_floating_label, include_blank: false, label_method: lambda { |visibility| safe_join([I18n.t("statuses.visibilities.#{visibility}"), content_tag(:span, I18n.t("statuses.visibilities.#{visibility}_long"), class: 'hint')]) }, required: false, as: :radio_buttons, collection_wrapper_tag: 'ul', item_wrapper_tag: 'li'
 
     = f.input :setting_default_sensitive, as: :boolean, wrapper: :with_label
 
-  %h4= t 'preferences.other'
+  %hr#settings_other/
 
   .fields-group
     = f.input :setting_noindex, as: :boolean, wrapper: :with_label
@@ -31,7 +34,7 @@
   .fields-group
     = f.input :setting_hide_network, as: :boolean, wrapper: :with_label
 
-  %h4= t 'preferences.web'
+  %hr#settings_web/
 
   .fields-group
     = f.input :setting_unfollow_modal, as: :boolean, wrapper: :with_label
diff --git a/app/views/settings/profiles/show.html.haml b/app/views/settings/profiles/show.html.haml
index 1acbb9b8a..6b61fa9c9 100644
--- a/app/views/settings/profiles/show.html.haml
+++ b/app/views/settings/profiles/show.html.haml
@@ -4,16 +4,21 @@
 = simple_form_for @account, url: settings_profile_path, html: { method: :put } do |f|
   = render 'shared/error_messages', object: @account
 
-  .fields-group
-    = 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
+  .fields-row
+    .fields-row__column.fields-group.fields-row__column-6
+      = f.input :display_name, wrapper: :with_label, hint: t('simple_form.hints.defaults.display_name', count: 30 - @account.display_name.size).html_safe
+      = f.input :note, wrapper: :with_label, hint: t('simple_form.hints.defaults.note', count: 500 - @account.note.size).html_safe
 
-  = render 'application/card', account: @account
+  .fields-row
+    .fields-row__column.fields-row__column-6
+      = 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', dimensions: '400x400', size: number_to_human_size(AccountAvatar::LIMIT))
+    .fields-row__column.fields-group.fields-row__column-6
+      = 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', dimensions: '1500x500', size: number_to_human_size(AccountHeader::LIMIT))
 
-    = 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))
+  %hr.spacer/
 
   .fields-group
     = f.input :locked, as: :boolean, wrapper: :with_label, hint: t('simple_form.hints.defaults.locked')
@@ -21,15 +26,27 @@
   .fields-group
     = f.input :bot, as: :boolean, wrapper: :with_label, hint: t('simple_form.hints.defaults.bot')
 
-  .fields-group
-    .input.with_block_label
-      %label= t('simple_form.labels.defaults.fields')
-      %span.hint= t('simple_form.hints.defaults.fields')
+  %hr.spacer/
+
+  .fields-row
+    .fields-row__column.fields-group.fields-row__column-6
+      .input.with_block_label
+        %label= t('simple_form.labels.defaults.fields')
+        %span.hint= t('simple_form.hints.defaults.fields')
 
-      = f.simple_fields_for :fields do |fields_f|
-        .row
-          = fields_f.input :name, placeholder: t('simple_form.labels.account.fields.name')
-          = fields_f.input :value, placeholder: t('simple_form.labels.account.fields.value')
+        = f.simple_fields_for :fields do |fields_f|
+          .row
+            = fields_f.input :name, placeholder: t('simple_form.labels.account.fields.name')
+            = fields_f.input :value, placeholder: t('simple_form.labels.account.fields.value')
+
+    .fields-row__column.fields-group.fields-row__column-6
+      %h6= t('verification.verification')
+      %p.hint= t('verification.explanation_html')
+
+      .input-copy
+        .input-copy__wrapper
+          %input{ type: :text, maxlength: '999', spellcheck: 'false', readonly: 'true', value: link_to('Mastodon', ActivityPub::TagManager.instance.url_for(@account), rel: 'me').to_str }
+        %button{ type: :button }= t('generic.copy')
 
   .actions
     = f.button :button, t('generic.save_changes'), type: :submit
@@ -38,3 +55,9 @@
 
 %h6= t('auth.migrate_account')
 %p.muted-hint= t('auth.migrate_account_html', path: settings_migration_path)
+
+- if open_deletion?
+  %hr.spacer/
+
+  %h6= t('auth.delete_account')
+  %p.muted-hint= t('auth.delete_account_html', path: settings_delete_path)
diff --git a/app/views/settings/two_factor_authentication/confirmations/new.html.haml b/app/views/settings/two_factor_authentication/confirmations/new.html.haml
index fd4a3e768..e64155299 100644
--- a/app/views/settings/two_factor_authentication/confirmations/new.html.haml
+++ b/app/views/settings/two_factor_authentication/confirmations/new.html.haml
@@ -11,7 +11,8 @@
       %p.hint= t('two_factor_authentication.manual_instructions')
       %samp.qr-alternative__code= current_user.otp_secret.scan(/.{4}/).join(' ')
 
-  = f.input :code, hint: t('two_factor_authentication.code_hint'), placeholder: t('simple_form.labels.defaults.otp_attempt'), input_html: { :autocomplete => 'off' }
+  .fields-group
+    = f.input :code, wrapper: :with_label, hint: t('two_factor_authentication.code_hint'), label: t('simple_form.labels.defaults.otp_attempt'), input_html: { :autocomplete => 'off' }, required: true
 
   .actions
     = f.button :button, t('two_factor_authentication.enable'), type: :submit
diff --git a/app/views/settings/two_factor_authentications/show.html.haml b/app/views/settings/two_factor_authentications/show.html.haml
index 67a64a046..259bcd1ef 100644
--- a/app/views/settings/two_factor_authentications/show.html.haml
+++ b/app/views/settings/two_factor_authentications/show.html.haml
@@ -10,7 +10,7 @@
   %hr/
 
   = simple_form_for @confirmation, url: settings_two_factor_authentication_path, method: :delete do |f|
-    = f.input :code, hint: t('two_factor_authentication.code_hint'), placeholder: t('simple_form.labels.defaults.otp_attempt'), input_html: { :autocomplete => 'off' }
+    = f.input :code, wrapper: :with_label, hint: t('two_factor_authentication.code_hint'), label: t('simple_form.labels.defaults.otp_attempt'), input_html: { :autocomplete => 'off' }, required: true
 
     .actions
       = f.button :button, t('two_factor_authentication.disable'), type: :submit
diff --git a/app/workers/verify_account_links_worker.rb b/app/workers/verify_account_links_worker.rb
new file mode 100644
index 000000000..901498583
--- /dev/null
+++ b/app/workers/verify_account_links_worker.rb
@@ -0,0 +1,20 @@
+# frozen_string_literal: true
+
+class VerifyAccountLinksWorker
+  include Sidekiq::Worker
+
+  sidekiq_options queue: 'pull', retry: false, unique: :until_executed
+
+  def perform(account_id)
+    account = Account.find(account_id)
+
+    account.fields.each do |field|
+      next unless !field.verified? && field.verifiable?
+      VerifyLinkService.new.call(field)
+    end
+
+    account.save! if account.changed?
+  rescue ActiveRecord::RecordNotFound
+    true
+  end
+end