about summary refs log tree commit diff
path: root/app
diff options
context:
space:
mode:
authorClaire <claire.github-309c@sitedethib.com>2023-04-09 11:40:14 +0200
committerClaire <claire.github-309c@sitedethib.com>2023-04-09 11:45:08 +0200
commitce12934f5b1804cc144014d9d0a93fdd16d13bf1 (patch)
treee6cb0c166392c28b38d86abe8f27344ce1d7752f /app
parentff168ef2024626f37fa776fde5739dcd58ecb9f2 (diff)
parent99e3e152cd2180cfa9a5bcafae208d44f31078f8 (diff)
Merge branch 'main' into glitch-soc/merge-upstream
Conflicts:
- `package.json`:
  Upstream removed a dependency that was textually close to a glitch-soc-only
  dependency.
  Removed the dependency as upstream did, while keeping the glitch-soc-only
  dependency.
Diffstat (limited to 'app')
-rw-r--r--app/controllers/backups_controller.rb2
-rw-r--r--app/controllers/settings/two_factor_authentication/otp_authentication_controller.rb9
-rw-r--r--app/javascript/mastodon/actions/markers.js2
-rw-r--r--app/javascript/mastodon/base_polyfills.js5
-rw-r--r--app/javascript/mastodon/components/admin/ReportReasonSelector.jsx4
-rw-r--r--app/javascript/mastodon/components/autosuggest_input.jsx2
-rw-r--r--app/javascript/mastodon/components/autosuggest_textarea.jsx2
-rw-r--r--app/javascript/mastodon/components/column_back_button_slim.jsx2
-rw-r--r--app/javascript/mastodon/components/dropdown_menu.jsx2
-rw-r--r--app/javascript/mastodon/components/gifv.jsx4
-rw-r--r--app/javascript/mastodon/components/icon_button.jsx4
-rw-r--r--app/javascript/mastodon/components/intersection_observer_article.jsx4
-rw-r--r--app/javascript/mastodon/components/picture_in_picture_placeholder.jsx2
-rw-r--r--app/javascript/mastodon/components/poll.jsx2
-rw-r--r--app/javascript/mastodon/components/status.jsx4
-rw-r--r--app/javascript/mastodon/components/status_content.jsx6
-rw-r--r--app/javascript/mastodon/containers/media_container.jsx2
-rw-r--r--app/javascript/mastodon/features/about/index.jsx2
-rw-r--r--app/javascript/mastodon/features/audio/index.jsx8
-rw-r--r--app/javascript/mastodon/features/compose/components/language_dropdown.jsx2
-rw-r--r--app/javascript/mastodon/features/compose/components/poll_form.jsx2
-rw-r--r--app/javascript/mastodon/features/compose/components/privacy_dropdown.jsx2
-rw-r--r--app/javascript/mastodon/features/compose/components/search.jsx2
-rw-r--r--app/javascript/mastodon/features/compose/components/upload.jsx2
-rw-r--r--app/javascript/mastodon/features/direct_timeline/components/conversation.jsx2
-rw-r--r--app/javascript/mastodon/features/direct_timeline/components/conversations_list.jsx4
-rw-r--r--app/javascript/mastodon/features/direct_timeline/index.jsx2
-rw-r--r--app/javascript/mastodon/features/emoji/emoji.js4
-rw-r--r--app/javascript/mastodon/features/filters/select_filter.jsx4
-rw-r--r--app/javascript/mastodon/features/getting_started/components/announcements.jsx2
-rw-r--r--app/javascript/mastodon/features/list_editor/components/search.jsx2
-rw-r--r--app/javascript/mastodon/features/list_editor/index.jsx2
-rw-r--r--app/javascript/mastodon/features/list_timeline/index.jsx4
-rw-r--r--app/javascript/mastodon/features/notifications/components/clear_column_button.jsx2
-rw-r--r--app/javascript/mastodon/features/notifications/components/grant_permission_button.jsx2
-rw-r--r--app/javascript/mastodon/features/notifications/components/notification.jsx18
-rw-r--r--app/javascript/mastodon/features/report/components/option.jsx2
-rw-r--r--app/javascript/mastodon/features/status/index.jsx2
-rw-r--r--app/javascript/mastodon/features/ui/components/actions_modal.jsx2
-rw-r--r--app/javascript/mastodon/features/ui/components/media_modal.jsx4
-rw-r--r--app/javascript/mastodon/features/ui/components/modal_root.jsx2
-rw-r--r--app/javascript/mastodon/features/video/index.jsx6
-rw-r--r--app/javascript/mastodon/initial_state.js2
-rw-r--r--app/javascript/mastodon/load_polyfills.js1
-rw-r--r--app/javascript/mastodon/locales/ast.json14
-rw-r--r--app/javascript/mastodon/locales/be.json18
-rw-r--r--app/javascript/mastodon/locales/ca.json16
-rw-r--r--app/javascript/mastodon/locales/ckb.json94
-rw-r--r--app/javascript/mastodon/locales/cs.json30
-rw-r--r--app/javascript/mastodon/locales/da.json16
-rw-r--r--app/javascript/mastodon/locales/de.json16
-rw-r--r--app/javascript/mastodon/locales/el.json16
-rw-r--r--app/javascript/mastodon/locales/eo.json18
-rw-r--r--app/javascript/mastodon/locales/es-AR.json16
-rw-r--r--app/javascript/mastodon/locales/es-MX.json16
-rw-r--r--app/javascript/mastodon/locales/es.json28
-rw-r--r--app/javascript/mastodon/locales/et.json18
-rw-r--r--app/javascript/mastodon/locales/eu.json16
-rw-r--r--app/javascript/mastodon/locales/fa.json38
-rw-r--r--app/javascript/mastodon/locales/fi.json24
-rw-r--r--app/javascript/mastodon/locales/fo.json16
-rw-r--r--app/javascript/mastodon/locales/fy.json16
-rw-r--r--app/javascript/mastodon/locales/gl.json16
-rw-r--r--app/javascript/mastodon/locales/he.json16
-rw-r--r--app/javascript/mastodon/locales/hi.json16
-rw-r--r--app/javascript/mastodon/locales/hu.json16
-rw-r--r--app/javascript/mastodon/locales/is.json16
-rw-r--r--app/javascript/mastodon/locales/it.json16
-rw-r--r--app/javascript/mastodon/locales/ja.json16
-rw-r--r--app/javascript/mastodon/locales/ko.json16
-rw-r--r--app/javascript/mastodon/locales/lv.json16
-rw-r--r--app/javascript/mastodon/locales/my.json34
-rw-r--r--app/javascript/mastodon/locales/nl.json22
-rw-r--r--app/javascript/mastodon/locales/pl.json16
-rw-r--r--app/javascript/mastodon/locales/pt-BR.json16
-rw-r--r--app/javascript/mastodon/locales/pt-PT.json16
-rw-r--r--app/javascript/mastodon/locales/sq.json16
-rw-r--r--app/javascript/mastodon/locales/th.json18
-rw-r--r--app/javascript/mastodon/locales/tr.json20
-rw-r--r--app/javascript/mastodon/locales/uk.json16
-rw-r--r--app/javascript/mastodon/locales/vi.json16
-rw-r--r--app/javascript/mastodon/locales/zh-CN.json42
-rw-r--r--app/javascript/mastodon/locales/zh-TW.json16
-rw-r--r--app/javascript/packs/public.jsx9
-rw-r--r--app/javascript/styles/mastodon/accounts.scss8
-rw-r--r--app/javascript/styles/mastodon/admin.scss6
-rw-r--r--app/javascript/styles/mastodon/components.scss26
-rw-r--r--app/javascript/styles/mastodon/rich_text.scss2
-rw-r--r--app/javascript/styles/mastodon/rtl.scss12
-rw-r--r--app/javascript/styles/mastodon/tables.scss4
-rw-r--r--app/services/notify_service.rb1
91 files changed, 515 insertions, 518 deletions
diff --git a/app/controllers/backups_controller.rb b/app/controllers/backups_controller.rb
index 0687b62c5..5891da6f6 100644
--- a/app/controllers/backups_controller.rb
+++ b/app/controllers/backups_controller.rb
@@ -13,7 +13,7 @@ class BackupsController < ApplicationController
     when :s3
       redirect_to @backup.dump.expiring_url(10)
     when :fog
-      if Paperclip::Attachment.default_options.dig(:storage, :fog_credentials, :openstack_temp_url_key).present?
+      if Paperclip::Attachment.default_options.dig(:fog_credentials, :openstack_temp_url_key).present?
         redirect_to @backup.dump.expiring_url(Time.now.utc + 10)
       else
         redirect_to full_asset_url(@backup.dump.url)
diff --git a/app/controllers/settings/two_factor_authentication/otp_authentication_controller.rb b/app/controllers/settings/two_factor_authentication/otp_authentication_controller.rb
index cbba842a9..0bff01ec2 100644
--- a/app/controllers/settings/two_factor_authentication/otp_authentication_controller.rb
+++ b/app/controllers/settings/two_factor_authentication/otp_authentication_controller.rb
@@ -22,18 +22,9 @@ module Settings
 
       private
 
-      def confirmation_params
-        params.require(:form_two_factor_confirmation).permit(:otp_attempt)
-      end
-
       def verify_otp_not_enabled
         redirect_to settings_two_factor_authentication_methods_path if current_user.otp_enabled?
       end
-
-      def acceptable_code?
-        current_user.validate_and_consume_otp!(confirmation_params[:otp_attempt]) ||
-          current_user.invalidate_otp_backup_code!(confirmation_params[:otp_attempt])
-      end
     end
   end
 end
diff --git a/app/javascript/mastodon/actions/markers.js b/app/javascript/mastodon/actions/markers.js
index 16ec7fe77..ca246dce7 100644
--- a/app/javascript/mastodon/actions/markers.js
+++ b/app/javascript/mastodon/actions/markers.js
@@ -55,7 +55,7 @@ export const synchronouslySubmitMarkers = () => (dispatch, getState) => {
     client.open('POST', '/api/v1/markers', false);
     client.setRequestHeader('Content-Type', 'application/json');
     client.setRequestHeader('Authorization', `Bearer ${accessToken}`);
-    client.SUBMIT(JSON.stringify(params));
+    client.send(JSON.stringify(params));
   } catch (e) {
     // Do not make the BeforeUnload handler error out
   }
diff --git a/app/javascript/mastodon/base_polyfills.js b/app/javascript/mastodon/base_polyfills.js
index d3ac0d510..91bc5d6dc 100644
--- a/app/javascript/mastodon/base_polyfills.js
+++ b/app/javascript/mastodon/base_polyfills.js
@@ -1,16 +1,11 @@
 import 'intl';
 import 'intl/locale-data/jsonp/en';
 import 'es6-symbol/implement';
-import includes from 'array-includes';
 import assign from 'object-assign';
 import values from 'object.values';
 import { decode as decodeBase64 } from './utils/base64';
 import promiseFinally from 'promise.prototype.finally';
 
-if (!Array.prototype.includes) {
-  includes.shim();
-}
-
 if (!Object.assign) {
   Object.assign = assign;
 }
diff --git a/app/javascript/mastodon/components/admin/ReportReasonSelector.jsx b/app/javascript/mastodon/components/admin/ReportReasonSelector.jsx
index 58a861fde..cd14dac4e 100644
--- a/app/javascript/mastodon/components/admin/ReportReasonSelector.jsx
+++ b/app/javascript/mastodon/components/admin/ReportReasonSelector.jsx
@@ -33,7 +33,7 @@ class Category extends React.PureComponent {
     const { id, text, disabled, selected, children } = this.props;
 
     return (
-      <div tabIndex='0' role='button' className={classNames('report-reason-selector__category', { selected, disabled })} onClick={this.handleClick}>
+      <div tabIndex={0} role='button' className={classNames('report-reason-selector__category', { selected, disabled })} onClick={this.handleClick}>
         {selected && <input type='hidden' name='report[category]' value={id} />}
 
         <div className='report-reason-selector__category__label'>
@@ -74,7 +74,7 @@ class Rule extends React.PureComponent {
     const { id, text, disabled, selected } = this.props;
 
     return (
-      <div tabIndex='0' role='button' className={classNames('report-reason-selector__rule', { selected, disabled })} onClick={this.handleClick}>
+      <div tabIndex={0} role='button' className={classNames('report-reason-selector__rule', { selected, disabled })} onClick={this.handleClick}>
         <span className={classNames('poll__input', { checkbox: true, active: selected, disabled })} />
         {selected && <input type='hidden' name='report[rule_ids][]' value={id} />}
         {text}
diff --git a/app/javascript/mastodon/components/autosuggest_input.jsx b/app/javascript/mastodon/components/autosuggest_input.jsx
index f9616c581..a68e2a01b 100644
--- a/app/javascript/mastodon/components/autosuggest_input.jsx
+++ b/app/javascript/mastodon/components/autosuggest_input.jsx
@@ -180,7 +180,7 @@ export default class AutosuggestInput extends ImmutablePureComponent {
     }
 
     return (
-      <div role='button' tabIndex='0' key={key} data-index={i} className={classNames('autosuggest-textarea__suggestions__item', { selected: i === selectedSuggestion })} onMouseDown={this.onSuggestionClick}>
+      <div role='button' tabIndex={0} key={key} data-index={i} className={classNames('autosuggest-textarea__suggestions__item', { selected: i === selectedSuggestion })} onMouseDown={this.onSuggestionClick}>
         {inner}
       </div>
     );
diff --git a/app/javascript/mastodon/components/autosuggest_textarea.jsx b/app/javascript/mastodon/components/autosuggest_textarea.jsx
index c04491298..a627bc1ec 100644
--- a/app/javascript/mastodon/components/autosuggest_textarea.jsx
+++ b/app/javascript/mastodon/components/autosuggest_textarea.jsx
@@ -186,7 +186,7 @@ export default class AutosuggestTextarea extends ImmutablePureComponent {
     }
 
     return (
-      <div role='button' tabIndex='0' key={key} data-index={i} className={classNames('autosuggest-textarea__suggestions__item', { selected: i === selectedSuggestion })} onMouseDown={this.onSuggestionClick}>
+      <div role='button' tabIndex={0} key={key} data-index={i} className={classNames('autosuggest-textarea__suggestions__item', { selected: i === selectedSuggestion })} onMouseDown={this.onSuggestionClick}>
         {inner}
       </div>
     );
diff --git a/app/javascript/mastodon/components/column_back_button_slim.jsx b/app/javascript/mastodon/components/column_back_button_slim.jsx
index cc8bfb151..46ac23736 100644
--- a/app/javascript/mastodon/components/column_back_button_slim.jsx
+++ b/app/javascript/mastodon/components/column_back_button_slim.jsx
@@ -8,7 +8,7 @@ export default class ColumnBackButtonSlim extends ColumnBackButton {
   render () {
     return (
       <div className='column-back-button--slim'>
-        <div role='button' tabIndex='0' onClick={this.handleClick} className='column-back-button column-back-button--slim-button'>
+        <div role='button' tabIndex={0} onClick={this.handleClick} className='column-back-button column-back-button--slim-button'>
           <Icon id='chevron-left' className='column-back-button__icon' fixedWidth />
           <FormattedMessage id='column_back_button.label' defaultMessage='Back' />
         </div>
diff --git a/app/javascript/mastodon/components/dropdown_menu.jsx b/app/javascript/mastodon/components/dropdown_menu.jsx
index c04c513fb..eaaa72fd8 100644
--- a/app/javascript/mastodon/components/dropdown_menu.jsx
+++ b/app/javascript/mastodon/components/dropdown_menu.jsx
@@ -119,7 +119,7 @@ class DropdownMenu extends React.PureComponent {
 
     return (
       <li className='dropdown-menu__item' key={`${text}-${i}`}>
-        <a href={href} target={target} data-method={method} rel='noopener noreferrer' role='button' tabIndex='0' ref={i === 0 ? this.setFocusRef : null} onClick={this.handleClick} onKeyPress={this.handleItemKeyPress} data-index={i}>
+        <a href={href} target={target} data-method={method} rel='noopener noreferrer' role='button' tabIndex={0} ref={i === 0 ? this.setFocusRef : null} onClick={this.handleClick} onKeyPress={this.handleItemKeyPress} data-index={i}>
           {text}
         </a>
       </li>
diff --git a/app/javascript/mastodon/components/gifv.jsx b/app/javascript/mastodon/components/gifv.jsx
index 9ec201c6c..1ce7e7c29 100644
--- a/app/javascript/mastodon/components/gifv.jsx
+++ b/app/javascript/mastodon/components/gifv.jsx
@@ -46,7 +46,7 @@ export default class GIFV extends React.PureComponent {
             width={width}
             height={height}
             role='button'
-            tabIndex='0'
+            tabIndex={0}
             aria-label={alt}
             title={alt}
             lang={lang}
@@ -57,7 +57,7 @@ export default class GIFV extends React.PureComponent {
         <video
           src={src}
           role='button'
-          tabIndex='0'
+          tabIndex={0}
           aria-label={alt}
           title={alt}
           lang={lang}
diff --git a/app/javascript/mastodon/components/icon_button.jsx b/app/javascript/mastodon/components/icon_button.jsx
index 003692373..989cae440 100644
--- a/app/javascript/mastodon/components/icon_button.jsx
+++ b/app/javascript/mastodon/components/icon_button.jsx
@@ -23,7 +23,7 @@ export default class IconButton extends React.PureComponent {
     inverted: PropTypes.bool,
     animate: PropTypes.bool,
     overlay: PropTypes.bool,
-    tabIndex: PropTypes.string,
+    tabIndex: PropTypes.number,
     counter: PropTypes.number,
     obfuscateCount: PropTypes.bool,
     href: PropTypes.string,
@@ -36,7 +36,7 @@ export default class IconButton extends React.PureComponent {
     disabled: false,
     animate: false,
     overlay: false,
-    tabIndex: '0',
+    tabIndex: 0,
     ariaHidden: false,
   };
 
diff --git a/app/javascript/mastodon/components/intersection_observer_article.jsx b/app/javascript/mastodon/components/intersection_observer_article.jsx
index c2feb003a..77957a21d 100644
--- a/app/javascript/mastodon/components/intersection_observer_article.jsx
+++ b/app/javascript/mastodon/components/intersection_observer_article.jsx
@@ -113,7 +113,7 @@ export default class IntersectionObserverArticle extends React.Component {
           aria-setsize={listLength}
           style={{ height: `${this.height || cachedHeight}px`, opacity: 0, overflow: 'hidden' }}
           data-id={id}
-          tabIndex='0'
+          tabIndex={0}
         >
           {children && React.cloneElement(children, { hidden: true })}
         </article>
@@ -121,7 +121,7 @@ export default class IntersectionObserverArticle extends React.Component {
     }
 
     return (
-      <article ref={this.handleRef} aria-posinset={index + 1} aria-setsize={listLength} data-id={id} tabIndex='0'>
+      <article ref={this.handleRef} aria-posinset={index + 1} aria-setsize={listLength} data-id={id} tabIndex={0}>
         {children && React.cloneElement(children, { hidden: false })}
       </article>
     );
diff --git a/app/javascript/mastodon/components/picture_in_picture_placeholder.jsx b/app/javascript/mastodon/components/picture_in_picture_placeholder.jsx
index c8aa8f757..6322b1c66 100644
--- a/app/javascript/mastodon/components/picture_in_picture_placeholder.jsx
+++ b/app/javascript/mastodon/components/picture_in_picture_placeholder.jsx
@@ -58,7 +58,7 @@ class PictureInPicturePlaceholder extends React.PureComponent {
     const { height } = this.state;
 
     return (
-      <div ref={this.setRef} className='picture-in-picture-placeholder' style={{ height }} role='button' tabIndex='0' onClick={this.handleClick}>
+      <div ref={this.setRef} className='picture-in-picture-placeholder' style={{ height }} role='button' tabIndex={0} onClick={this.handleClick}>
         <Icon id='window-restore' />
         <FormattedMessage id='picture_in_picture.restore' defaultMessage='Put it back' />
       </div>
diff --git a/app/javascript/mastodon/components/poll.jsx b/app/javascript/mastodon/components/poll.jsx
index 360557d00..b9b96a700 100644
--- a/app/javascript/mastodon/components/poll.jsx
+++ b/app/javascript/mastodon/components/poll.jsx
@@ -154,7 +154,7 @@ class Poll extends ImmutablePureComponent {
           {!showResults && (
             <span
               className={classNames('poll__input', { checkbox: poll.get('multiple'), active })}
-              tabIndex='0'
+              tabIndex={0}
               role={poll.get('multiple') ? 'checkbox' : 'radio'}
               onKeyPress={this.handleOptionKeyPress}
               aria-checked={active}
diff --git a/app/javascript/mastodon/components/status.jsx b/app/javascript/mastodon/components/status.jsx
index 281e69874..923dc892d 100644
--- a/app/javascript/mastodon/components/status.jsx
+++ b/app/javascript/mastodon/components/status.jsx
@@ -337,7 +337,7 @@ class Status extends ImmutablePureComponent {
     if (hidden) {
       return (
         <HotKeys handlers={handlers}>
-          <div ref={this.handleRef} className={classNames('status__wrapper', { focusable: !this.props.muted })} tabIndex='0'>
+          <div ref={this.handleRef} className={classNames('status__wrapper', { focusable: !this.props.muted })} tabIndex={0}>
             <span>{status.getIn(['account', 'display_name']) || status.getIn(['account', 'username'])}</span>
             <span>{status.get('content')}</span>
           </div>
@@ -354,7 +354,7 @@ class Status extends ImmutablePureComponent {
 
       return (
         <HotKeys handlers={minHandlers}>
-          <div className='status__wrapper status__wrapper--filtered focusable' tabIndex='0' ref={this.handleRef}>
+          <div className='status__wrapper status__wrapper--filtered focusable' tabIndex={0} ref={this.handleRef}>
             <FormattedMessage id='status.filtered' defaultMessage='Filtered' />: {matchedFilters.join(', ')}.
             {' '}
             <button className='status__wrapper--filtered__button' onClick={this.handleUnfilterClick}>
diff --git a/app/javascript/mastodon/components/status_content.jsx b/app/javascript/mastodon/components/status_content.jsx
index 8d3a80248..fb953b9dd 100644
--- a/app/javascript/mastodon/components/status_content.jsx
+++ b/app/javascript/mastodon/components/status_content.jsx
@@ -268,7 +268,7 @@ class StatusContent extends React.PureComponent {
       }
 
       return (
-        <div className={classNames} ref={this.setRef} tabIndex='0' onMouseDown={this.handleMouseDown} onMouseUp={this.handleMouseUp} onMouseEnter={this.handleMouseEnter} onMouseLeave={this.handleMouseLeave}>
+        <div className={classNames} ref={this.setRef} tabIndex={0} onMouseDown={this.handleMouseDown} onMouseUp={this.handleMouseUp} onMouseEnter={this.handleMouseEnter} onMouseLeave={this.handleMouseLeave}>
           <p style={{ marginBottom: hidden && status.get('mentions').isEmpty() ? '0px' : null }}>
             <span dangerouslySetInnerHTML={spoilerContent} className='translate' lang={lang} />
             {' '}
@@ -286,7 +286,7 @@ class StatusContent extends React.PureComponent {
     } else if (this.props.onClick) {
       return (
         <>
-          <div className={classNames} ref={this.setRef} tabIndex='0' onMouseDown={this.handleMouseDown} onMouseUp={this.handleMouseUp} key='status-content' onMouseEnter={this.handleMouseEnter} onMouseLeave={this.handleMouseLeave}>
+          <div className={classNames} ref={this.setRef} tabIndex={0} onMouseDown={this.handleMouseDown} onMouseUp={this.handleMouseUp} key='status-content' onMouseEnter={this.handleMouseEnter} onMouseLeave={this.handleMouseLeave}>
             <div className='status__content__text status__content__text--visible translate' lang={lang} dangerouslySetInnerHTML={content} />
 
             {poll}
@@ -298,7 +298,7 @@ class StatusContent extends React.PureComponent {
       );
     } else {
       return (
-        <div className={classNames} ref={this.setRef} tabIndex='0' onMouseEnter={this.handleMouseEnter} onMouseLeave={this.handleMouseLeave}>
+        <div className={classNames} ref={this.setRef} tabIndex={0} onMouseEnter={this.handleMouseEnter} onMouseLeave={this.handleMouseLeave}>
           <div className='status__content__text status__content__text--visible translate' lang={lang} dangerouslySetInnerHTML={content} />
 
           {poll}
diff --git a/app/javascript/mastodon/containers/media_container.jsx b/app/javascript/mastodon/containers/media_container.jsx
index 25dc17444..f9244f8dd 100644
--- a/app/javascript/mastodon/containers/media_container.jsx
+++ b/app/javascript/mastodon/containers/media_container.jsx
@@ -54,7 +54,7 @@ export default class MediaContainer extends PureComponent {
 
   handleCloseMedia = () => {
     document.body.classList.remove('with-modals--active');
-    document.documentElement.style.marginRight = 0;
+    document.documentElement.style.marginRight = '0';
 
     this.setState({
       media: null,
diff --git a/app/javascript/mastodon/features/about/index.jsx b/app/javascript/mastodon/features/about/index.jsx
index 2804c4a21..bb35f3203 100644
--- a/app/javascript/mastodon/features/about/index.jsx
+++ b/app/javascript/mastodon/features/about/index.jsx
@@ -67,7 +67,7 @@ class Section extends React.PureComponent {
 
     return (
       <div className={classNames('about__section', { active: !collapsed })}>
-        <div className='about__section__title' role='button' tabIndex='0' onClick={this.handleClick}>
+        <div className='about__section__title' role='button' tabIndex={0} onClick={this.handleClick}>
           <Icon id={collapsed ? 'chevron-right' : 'chevron-down'} fixedWidth /> {title}
         </div>
 
diff --git a/app/javascript/mastodon/features/audio/index.jsx b/app/javascript/mastodon/features/audio/index.jsx
index b0c6eeee6..df40b48f0 100644
--- a/app/javascript/mastodon/features/audio/index.jsx
+++ b/app/javascript/mastodon/features/audio/index.jsx
@@ -470,7 +470,7 @@ class Audio extends React.PureComponent {
     }
 
     return (
-      <div className={classNames('audio-player', { editable, inactive: !revealed })} ref={this.setPlayerRef} style={{ backgroundColor: this._getBackgroundColor(), color: this._getForegroundColor(), width: '100%', height: this.props.fullscreen ? '100%' : (this.state.height || this.props.height) }} onMouseEnter={this.handleMouseEnter} onMouseLeave={this.handleMouseLeave} tabIndex='0' onKeyDown={this.handleKeyDown}>
+      <div className={classNames('audio-player', { editable, inactive: !revealed })} ref={this.setPlayerRef} style={{ backgroundColor: this._getBackgroundColor(), color: this._getForegroundColor(), width: '100%', height: this.props.fullscreen ? '100%' : (this.state.height || this.props.height) }} onMouseEnter={this.handleMouseEnter} onMouseLeave={this.handleMouseLeave} tabIndex={0} onKeyDown={this.handleKeyDown}>
 
         <Blurhash
           hash={blurhash}
@@ -493,7 +493,7 @@ class Audio extends React.PureComponent {
 
         <canvas
           role='button'
-          tabIndex='0'
+          tabIndex={0}
           className='audio-player__canvas'
           width={this.state.width}
           height={this.state.height}
@@ -526,7 +526,7 @@ class Audio extends React.PureComponent {
 
           <span
             className={classNames('video-player__seek__handle', { active: dragging })}
-            tabIndex='0'
+            tabIndex={0}
             style={{ left: `${progress}%`, backgroundColor: this._getAccentColor() }}
             onKeyDown={this.handleAudioKeyDown}
           />
@@ -543,7 +543,7 @@ class Audio extends React.PureComponent {
 
                 <span
                   className='video-player__volume__handle'
-                  tabIndex='0'
+                  tabIndex={0}
                   style={{ left: `${volume * 100}%`, backgroundColor: this._getAccentColor() }}
                 />
               </div>
diff --git a/app/javascript/mastodon/features/compose/components/language_dropdown.jsx b/app/javascript/mastodon/features/compose/components/language_dropdown.jsx
index 908cb61a7..08542e3a9 100644
--- a/app/javascript/mastodon/features/compose/components/language_dropdown.jsx
+++ b/app/javascript/mastodon/features/compose/components/language_dropdown.jsx
@@ -209,7 +209,7 @@ class LanguageDropdownMenu extends React.PureComponent {
     const { value } = this.props;
 
     return (
-      <div key={lang[0]} role='option' tabIndex='0' data-index={lang[0]} className={classNames('language-dropdown__dropdown__results__item', { active: lang[0] === value })} aria-selected={lang[0] === value} onClick={this.handleClick} onKeyDown={this.handleKeyDown}>
+      <div key={lang[0]} role='option' tabIndex={0} data-index={lang[0]} className={classNames('language-dropdown__dropdown__results__item', { active: lang[0] === value })} aria-selected={lang[0] === value} onClick={this.handleClick} onKeyDown={this.handleKeyDown}>
         <span className='language-dropdown__dropdown__results__item__native-name' lang={lang[0]}>{lang[2]}</span> <span className='language-dropdown__dropdown__results__item__common-name'>({lang[1]})</span>
       </div>
     );
diff --git a/app/javascript/mastodon/features/compose/components/poll_form.jsx b/app/javascript/mastodon/features/compose/components/poll_form.jsx
index 967d9321b..f81d7355a 100644
--- a/app/javascript/mastodon/features/compose/components/poll_form.jsx
+++ b/app/javascript/mastodon/features/compose/components/poll_form.jsx
@@ -82,7 +82,7 @@ class OptionIntl extends React.PureComponent {
             onClick={this.handleToggleMultiple}
             onKeyPress={this.handleCheckboxKeypress}
             role='button'
-            tabIndex='0'
+            tabIndex={0}
             title={intl.formatMessage(isPollMultiple ? messages.switchToSingle : messages.switchToMultiple)}
             aria-label={intl.formatMessage(isPollMultiple ? messages.switchToSingle : messages.switchToMultiple)}
           />
diff --git a/app/javascript/mastodon/features/compose/components/privacy_dropdown.jsx b/app/javascript/mastodon/features/compose/components/privacy_dropdown.jsx
index 6c4b1064e..e65c9cb72 100644
--- a/app/javascript/mastodon/features/compose/components/privacy_dropdown.jsx
+++ b/app/javascript/mastodon/features/compose/components/privacy_dropdown.jsx
@@ -115,7 +115,7 @@ class PrivacyDropdownMenu extends React.PureComponent {
     return (
       <div style={{ ...style }} role='listbox' ref={this.setRef}>
         {items.map(item => (
-          <div role='option' tabIndex='0' key={item.value} data-index={item.value} onKeyDown={this.handleKeyDown} onClick={this.handleClick} className={classNames('privacy-dropdown__option', { active: item.value === value })} aria-selected={item.value === value} ref={item.value === value ? this.setFocusRef : null}>
+          <div role='option' tabIndex={0} key={item.value} data-index={item.value} onKeyDown={this.handleKeyDown} onClick={this.handleClick} className={classNames('privacy-dropdown__option', { active: item.value === value })} aria-selected={item.value === value} ref={item.value === value ? this.setFocusRef : null}>
             <div className='privacy-dropdown__option__icon'>
               <Icon id={item.icon} fixedWidth />
             </div>
diff --git a/app/javascript/mastodon/features/compose/components/search.jsx b/app/javascript/mastodon/features/compose/components/search.jsx
index 717ecea37..46723f5cc 100644
--- a/app/javascript/mastodon/features/compose/components/search.jsx
+++ b/app/javascript/mastodon/features/compose/components/search.jsx
@@ -287,7 +287,7 @@ class Search extends React.PureComponent {
           onBlur={this.handleBlur}
         />
 
-        <div role='button' tabIndex='0' className='search__icon' onClick={this.handleClear}>
+        <div role='button' tabIndex={0} className='search__icon' onClick={this.handleClear}>
           <Icon id='search' className={hasValue ? '' : 'active'} />
           <Icon id='times-circle' className={hasValue ? 'active' : ''} aria-label={intl.formatMessage(messages.placeholder)} />
         </div>
diff --git a/app/javascript/mastodon/features/compose/components/upload.jsx b/app/javascript/mastodon/features/compose/components/upload.jsx
index f114680b9..e3651c229 100644
--- a/app/javascript/mastodon/features/compose/components/upload.jsx
+++ b/app/javascript/mastodon/features/compose/components/upload.jsx
@@ -42,7 +42,7 @@ export default class Upload extends ImmutablePureComponent {
     const y = ((focusY / -2) + .5) * 100;
 
     return (
-      <div className='compose-form__upload' tabIndex='0' role='button'>
+      <div className='compose-form__upload' tabIndex={0} role='button'>
         <Motion defaultStyle={{ scale: 0.8 }} style={{ scale: spring(1, { stiffness: 180, damping: 12 }) }}>
           {({ scale }) => (
             <div className='compose-form__upload-thumbnail' style={{ transform: `scale(${scale})`, backgroundImage: `url(${media.get('preview_url')})`, backgroundPosition: `${x}% ${y}%` }}>
diff --git a/app/javascript/mastodon/features/direct_timeline/components/conversation.jsx b/app/javascript/mastodon/features/direct_timeline/components/conversation.jsx
index 5996dd666..d0dbffe65 100644
--- a/app/javascript/mastodon/features/direct_timeline/components/conversation.jsx
+++ b/app/javascript/mastodon/features/direct_timeline/components/conversation.jsx
@@ -144,7 +144,7 @@ class Conversation extends ImmutablePureComponent {
 
     return (
       <HotKeys handlers={handlers}>
-        <div className={classNames('conversation focusable muted', { 'conversation--unread': unread })} tabIndex='0'>
+        <div className={classNames('conversation focusable muted', { 'conversation--unread': unread })} tabIndex={0}>
           <div className='conversation__avatar' onClick={this.handleClick} role='presentation'>
             <AvatarComposite accounts={accounts} size={48} />
           </div>
diff --git a/app/javascript/mastodon/features/direct_timeline/components/conversations_list.jsx b/app/javascript/mastodon/features/direct_timeline/components/conversations_list.jsx
index 27e9a593f..04c404e1d 100644
--- a/app/javascript/mastodon/features/direct_timeline/components/conversations_list.jsx
+++ b/app/javascript/mastodon/features/direct_timeline/components/conversations_list.jsx
@@ -55,10 +55,10 @@ export default class ConversationsList extends ImmutablePureComponent {
   }, 300, { leading: true });
 
   render () {
-    const { conversations, onLoadMore, ...other } = this.props;
+    const { conversations, isLoading, onLoadMore, ...other } = this.props;
 
     return (
-      <ScrollableList {...other} onLoadMore={onLoadMore && this.handleLoadOlder} ref={this.setRef}>
+      <ScrollableList {...other} isLoading={isLoading} showLoading={isLoading && conversations.isEmpty()} onLoadMore={onLoadMore && this.handleLoadOlder} ref={this.setRef}>
         {conversations.map(item => (
           <ConversationContainer
             key={item.get('id')}
diff --git a/app/javascript/mastodon/features/direct_timeline/index.jsx b/app/javascript/mastodon/features/direct_timeline/index.jsx
index 5d4a7c49a..fc45ea69a 100644
--- a/app/javascript/mastodon/features/direct_timeline/index.jsx
+++ b/app/javascript/mastodon/features/direct_timeline/index.jsx
@@ -89,8 +89,10 @@ class DirectTimeline extends React.PureComponent {
           trackScroll={!pinned}
           scrollKey={`direct_timeline-${columnId}`}
           timelineId='direct'
+          bindToDocument={!multiColumn}
           onLoadMore={this.handleLoadMore}
           prepend={<div className='follow_requests-unlocked_explanation'><span><FormattedMessage id='compose_form.encryption_warning' defaultMessage='Posts on Mastodon are not end-to-end encrypted. Do not share any dangerous information over Mastodon.' /> <a href='/terms' target='_blank'><FormattedMessage id='compose_form.direct_message_warning_learn_more' defaultMessage='Learn more' /></a></span></div>}
+          alwaysPrepend
           emptyMessage={<FormattedMessage id='empty_column.direct' defaultMessage="You don't have any private mentions yet. When you send or receive one, it will show up here." />}
         />
 
diff --git a/app/javascript/mastodon/features/emoji/emoji.js b/app/javascript/mastodon/features/emoji/emoji.js
index bc3dd8c60..6ae406624 100644
--- a/app/javascript/mastodon/features/emoji/emoji.js
+++ b/app/javascript/mastodon/features/emoji/emoji.js
@@ -50,7 +50,7 @@ const emojifyTextNode = (node, customEmojis) => {
         if (shortname in customEmojis) {
           const filename = autoPlayGif ? customEmojis[shortname].url : customEmojis[shortname].static_url;
           replacement = document.createElement('img');
-          replacement.setAttribute('draggable', false);
+          replacement.setAttribute('draggable', 'false');
           replacement.setAttribute('class', 'emojione custom-emoji');
           replacement.setAttribute('alt', shortname);
           replacement.setAttribute('title', shortname);
@@ -65,7 +65,7 @@ const emojifyTextNode = (node, customEmojis) => {
       const { filename, shortCode } = unicodeMapping[match];
       const title = shortCode ? `:${shortCode}:` : '';
       replacement = document.createElement('img');
-      replacement.setAttribute('draggable', false);
+      replacement.setAttribute('draggable', 'false');
       replacement.setAttribute('class', 'emojione');
       replacement.setAttribute('alt', match);
       replacement.setAttribute('title', title);
diff --git a/app/javascript/mastodon/features/filters/select_filter.jsx b/app/javascript/mastodon/features/filters/select_filter.jsx
index b0aede187..5778eec8e 100644
--- a/app/javascript/mastodon/features/filters/select_filter.jsx
+++ b/app/javascript/mastodon/features/filters/select_filter.jsx
@@ -65,7 +65,7 @@ class SelectFilter extends React.PureComponent {
     }
 
     return (
-      <div key={filter[0]} role='button' tabIndex='0' data-index={filter[0]} className='language-dropdown__dropdown__results__item' onClick={this.handleItemClick} onKeyDown={this.handleKeyDown}>
+      <div key={filter[0]} role='button' tabIndex={0} data-index={filter[0]} className='language-dropdown__dropdown__results__item' onClick={this.handleItemClick} onKeyDown={this.handleKeyDown}>
         <span className='language-dropdown__dropdown__results__item__native-name'>{filter[1]}</span> {warning}
       </div>
     );
@@ -73,7 +73,7 @@ class SelectFilter extends React.PureComponent {
 
   renderCreateNew (name) {
     return (
-      <div key='add-new-filter' role='button' tabIndex='0' className='language-dropdown__dropdown__results__item' onClick={this.handleNewFilterClick} onKeyDown={this.handleKeyDown}>
+      <div key='add-new-filter' role='button' tabIndex={0} className='language-dropdown__dropdown__results__item' onClick={this.handleNewFilterClick} onKeyDown={this.handleKeyDown}>
         <Icon id='plus' fixedWidth /> <FormattedMessage id='filter_modal.select_filter.prompt_new' defaultMessage='New category: {name}' values={{ name }} />
       </div>
     );
diff --git a/app/javascript/mastodon/features/getting_started/components/announcements.jsx b/app/javascript/mastodon/features/getting_started/components/announcements.jsx
index 954f407f5..5f993d2c5 100644
--- a/app/javascript/mastodon/features/getting_started/components/announcements.jsx
+++ b/app/javascript/mastodon/features/getting_started/components/announcements.jsx
@@ -418,7 +418,7 @@ class Announcements extends ImmutablePureComponent {
         <img className='announcements__mastodon' alt='' draggable='false' src={mascot || elephantUIPlane} />
 
         <div className='announcements__container'>
-          <ReactSwipeableViews animateHeight={!reduceMotion} adjustHeight={reduceMotion} index={index} onChangeIndex={this.handleChangeIndex}>
+          <ReactSwipeableViews animateHeight animateTransitions={!reduceMotion} index={index} onChangeIndex={this.handleChangeIndex}>
             {announcements.map((announcement, idx) => (
               <Announcement
                 key={announcement.get('id')}
diff --git a/app/javascript/mastodon/features/list_editor/components/search.jsx b/app/javascript/mastodon/features/list_editor/components/search.jsx
index b9745e0a8..f70e272f7 100644
--- a/app/javascript/mastodon/features/list_editor/components/search.jsx
+++ b/app/javascript/mastodon/features/list_editor/components/search.jsx
@@ -63,7 +63,7 @@ class Search extends React.PureComponent {
           />
         </label>
 
-        <div role='button' tabIndex='0' className='search__icon' onClick={this.handleClear}>
+        <div role='button' tabIndex={0} className='search__icon' onClick={this.handleClear}>
           <Icon id='search' className={classNames({ active: !hasValue })} />
           <Icon id='times-circle' aria-label={intl.formatMessage(messages.search)} className={classNames({ active: hasValue })} />
         </div>
diff --git a/app/javascript/mastodon/features/list_editor/index.jsx b/app/javascript/mastodon/features/list_editor/index.jsx
index 65cebbdc8..ed9d09132 100644
--- a/app/javascript/mastodon/features/list_editor/index.jsx
+++ b/app/javascript/mastodon/features/list_editor/index.jsx
@@ -60,7 +60,7 @@ class ListEditor extends ImmutablePureComponent {
             {accountIds.map(accountId => <Account key={accountId} accountId={accountId} added />)}
           </div>
 
-          {showSearch && <div role='button' tabIndex='-1' className='drawer__backdrop' onClick={onClear} />}
+          {showSearch && <div role='button' tabIndex={-1} className='drawer__backdrop' onClick={onClear} />}
 
           <Motion defaultStyle={{ x: -100 }} style={{ x: spring(showSearch ? 0 : -100, { stiffness: 210, damping: 20 }) }}>
             {({ x }) => (
diff --git a/app/javascript/mastodon/features/list_timeline/index.jsx b/app/javascript/mastodon/features/list_timeline/index.jsx
index d0ba2a186..c0b9a62ff 100644
--- a/app/javascript/mastodon/features/list_timeline/index.jsx
+++ b/app/javascript/mastodon/features/list_timeline/index.jsx
@@ -176,11 +176,11 @@ class ListTimeline extends React.PureComponent {
           multiColumn={multiColumn}
         >
           <div className='column-settings__row column-header__links'>
-            <button type='button' className='text-btn column-header__setting-btn' tabIndex='0' onClick={this.handleEditClick}>
+            <button type='button' className='text-btn column-header__setting-btn' tabIndex={0} onClick={this.handleEditClick}>
               <Icon id='pencil' /> <FormattedMessage id='lists.edit' defaultMessage='Edit list' />
             </button>
 
-            <button type='button' className='text-btn column-header__setting-btn' tabIndex='0' onClick={this.handleDeleteClick}>
+            <button type='button' className='text-btn column-header__setting-btn' tabIndex={0} onClick={this.handleDeleteClick}>
               <Icon id='trash' /> <FormattedMessage id='lists.delete' defaultMessage='Delete list' />
             </button>
           </div>
diff --git a/app/javascript/mastodon/features/notifications/components/clear_column_button.jsx b/app/javascript/mastodon/features/notifications/components/clear_column_button.jsx
index b82fd092f..9a076ce5e 100644
--- a/app/javascript/mastodon/features/notifications/components/clear_column_button.jsx
+++ b/app/javascript/mastodon/features/notifications/components/clear_column_button.jsx
@@ -11,7 +11,7 @@ export default class ClearColumnButton extends React.PureComponent {
 
   render () {
     return (
-      <button className='text-btn column-header__setting-btn' tabIndex='0' onClick={this.props.onClick}><Icon id='eraser' /> <FormattedMessage id='notifications.clear' defaultMessage='Clear notifications' /></button>
+      <button className='text-btn column-header__setting-btn' tabIndex={0} onClick={this.props.onClick}><Icon id='eraser' /> <FormattedMessage id='notifications.clear' defaultMessage='Clear notifications' /></button>
     );
   }
 
diff --git a/app/javascript/mastodon/features/notifications/components/grant_permission_button.jsx b/app/javascript/mastodon/features/notifications/components/grant_permission_button.jsx
index 798e4c787..5b2db48fd 100644
--- a/app/javascript/mastodon/features/notifications/components/grant_permission_button.jsx
+++ b/app/javascript/mastodon/features/notifications/components/grant_permission_button.jsx
@@ -10,7 +10,7 @@ export default class GrantPermissionButton extends React.PureComponent {
 
   render () {
     return (
-      <button className='text-btn column-header__permission-btn' tabIndex='0' onClick={this.props.onClick}>
+      <button className='text-btn column-header__permission-btn' tabIndex={0} onClick={this.props.onClick}>
         <FormattedMessage id='notifications.grant_permission' defaultMessage='Grant permission.' />
       </button>
     );
diff --git a/app/javascript/mastodon/features/notifications/components/notification.jsx b/app/javascript/mastodon/features/notifications/components/notification.jsx
index cf9d9f72c..f3104cee0 100644
--- a/app/javascript/mastodon/features/notifications/components/notification.jsx
+++ b/app/javascript/mastodon/features/notifications/components/notification.jsx
@@ -123,7 +123,7 @@ class Notification extends ImmutablePureComponent {
 
     return (
       <HotKeys handlers={this.getHandlers()}>
-        <div className={classNames('notification notification-follow focusable', { unread })} tabIndex='0' aria-label={notificationForScreenReader(intl, intl.formatMessage(messages.follow, { name: account.get('acct') }), notification.get('created_at'))}>
+        <div className={classNames('notification notification-follow focusable', { unread })} tabIndex={0} aria-label={notificationForScreenReader(intl, intl.formatMessage(messages.follow, { name: account.get('acct') }), notification.get('created_at'))}>
           <div className='notification__message'>
             <div className='notification__favourite-icon-wrapper'>
               <Icon id='user-plus' fixedWidth />
@@ -145,7 +145,7 @@ class Notification extends ImmutablePureComponent {
 
     return (
       <HotKeys handlers={this.getHandlers()}>
-        <div className={classNames('notification notification-follow-request focusable', { unread })} tabIndex='0' aria-label={notificationForScreenReader(intl, intl.formatMessage({ id: 'notification.follow_request', defaultMessage: '{name} has requested to follow you' }, { name: account.get('acct') }), notification.get('created_at'))}>
+        <div className={classNames('notification notification-follow-request focusable', { unread })} tabIndex={0} aria-label={notificationForScreenReader(intl, intl.formatMessage({ id: 'notification.follow_request', defaultMessage: '{name} has requested to follow you' }, { name: account.get('acct') }), notification.get('created_at'))}>
           <div className='notification__message'>
             <div className='notification__favourite-icon-wrapper'>
               <Icon id='user' fixedWidth />
@@ -185,7 +185,7 @@ class Notification extends ImmutablePureComponent {
 
     return (
       <HotKeys handlers={this.getHandlers()}>
-        <div className={classNames('notification notification-favourite focusable', { unread })} tabIndex='0' aria-label={notificationForScreenReader(intl, intl.formatMessage(messages.favourite, { name: notification.getIn(['account', 'acct']) }), notification.get('created_at'))}>
+        <div className={classNames('notification notification-favourite focusable', { unread })} tabIndex={0} aria-label={notificationForScreenReader(intl, intl.formatMessage(messages.favourite, { name: notification.getIn(['account', 'acct']) }), notification.get('created_at'))}>
           <div className='notification__message'>
             <div className='notification__favourite-icon-wrapper'>
               <Icon id='star' className='star-icon' fixedWidth />
@@ -217,7 +217,7 @@ class Notification extends ImmutablePureComponent {
 
     return (
       <HotKeys handlers={this.getHandlers()}>
-        <div className={classNames('notification notification-reblog focusable', { unread })} tabIndex='0' aria-label={notificationForScreenReader(intl, intl.formatMessage(messages.reblog, { name: notification.getIn(['account', 'acct']) }), notification.get('created_at'))}>
+        <div className={classNames('notification notification-reblog focusable', { unread })} tabIndex={0} aria-label={notificationForScreenReader(intl, intl.formatMessage(messages.reblog, { name: notification.getIn(['account', 'acct']) }), notification.get('created_at'))}>
           <div className='notification__message'>
             <div className='notification__favourite-icon-wrapper'>
               <Icon id='retweet' fixedWidth />
@@ -253,7 +253,7 @@ class Notification extends ImmutablePureComponent {
 
     return (
       <HotKeys handlers={this.getHandlers()}>
-        <div className={classNames('notification notification-status focusable', { unread })} tabIndex='0' aria-label={notificationForScreenReader(intl, intl.formatMessage(messages.status, { name: notification.getIn(['account', 'acct']) }), notification.get('created_at'))}>
+        <div className={classNames('notification notification-status focusable', { unread })} tabIndex={0} aria-label={notificationForScreenReader(intl, intl.formatMessage(messages.status, { name: notification.getIn(['account', 'acct']) }), notification.get('created_at'))}>
           <div className='notification__message'>
             <div className='notification__favourite-icon-wrapper'>
               <Icon id='home' fixedWidth />
@@ -290,7 +290,7 @@ class Notification extends ImmutablePureComponent {
 
     return (
       <HotKeys handlers={this.getHandlers()}>
-        <div className={classNames('notification notification-update focusable', { unread })} tabIndex='0' aria-label={notificationForScreenReader(intl, intl.formatMessage(messages.update, { name: notification.getIn(['account', 'acct']) }), notification.get('created_at'))}>
+        <div className={classNames('notification notification-update focusable', { unread })} tabIndex={0} aria-label={notificationForScreenReader(intl, intl.formatMessage(messages.update, { name: notification.getIn(['account', 'acct']) }), notification.get('created_at'))}>
           <div className='notification__message'>
             <div className='notification__favourite-icon-wrapper'>
               <Icon id='pencil' fixedWidth />
@@ -329,7 +329,7 @@ class Notification extends ImmutablePureComponent {
 
     return (
       <HotKeys handlers={this.getHandlers()}>
-        <div className={classNames('notification notification-poll focusable', { unread })} tabIndex='0' aria-label={notificationForScreenReader(intl, message, notification.get('created_at'))}>
+        <div className={classNames('notification notification-poll focusable', { unread })} tabIndex={0} aria-label={notificationForScreenReader(intl, message, notification.get('created_at'))}>
           <div className='notification__message'>
             <div className='notification__favourite-icon-wrapper'>
               <Icon id='tasks' fixedWidth />
@@ -366,7 +366,7 @@ class Notification extends ImmutablePureComponent {
 
     return (
       <HotKeys handlers={this.getHandlers()}>
-        <div className={classNames('notification notification-admin-sign-up focusable', { unread })} tabIndex='0' aria-label={notificationForScreenReader(intl, intl.formatMessage(messages.adminSignUp, { name: account.get('acct') }), notification.get('created_at'))}>
+        <div className={classNames('notification notification-admin-sign-up focusable', { unread })} tabIndex={0} aria-label={notificationForScreenReader(intl, intl.formatMessage(messages.adminSignUp, { name: account.get('acct') }), notification.get('created_at'))}>
           <div className='notification__message'>
             <div className='notification__favourite-icon-wrapper'>
               <Icon id='user-plus' fixedWidth />
@@ -396,7 +396,7 @@ class Notification extends ImmutablePureComponent {
 
     return (
       <HotKeys handlers={this.getHandlers()}>
-        <div className={classNames('notification notification-admin-report focusable', { unread })} tabIndex='0' aria-label={notificationForScreenReader(intl, intl.formatMessage(messages.adminReport, { name: account.get('acct'), target: notification.getIn(['report', 'target_account', 'acct']) }), notification.get('created_at'))}>
+        <div className={classNames('notification notification-admin-report focusable', { unread })} tabIndex={0} aria-label={notificationForScreenReader(intl, intl.formatMessage(messages.adminReport, { name: account.get('acct'), target: notification.getIn(['report', 'target_account', 'acct']) }), notification.get('created_at'))}>
           <div className='notification__message'>
             <div className='notification__favourite-icon-wrapper'>
               <Icon id='flag' fixedWidth />
diff --git a/app/javascript/mastodon/features/report/components/option.jsx b/app/javascript/mastodon/features/report/components/option.jsx
index 42c04b018..342204e22 100644
--- a/app/javascript/mastodon/features/report/components/option.jsx
+++ b/app/javascript/mastodon/features/report/components/option.jsx
@@ -40,7 +40,7 @@ export default class Option extends React.PureComponent {
 
         <span
           className={classNames('poll__input', { active: checked, checkbox: multiple })}
-          tabIndex='0'
+          tabIndex={0}
           role='radio'
           onKeyPress={this.handleKeyPress}
           aria-checked={checked}
diff --git a/app/javascript/mastodon/features/status/index.jsx b/app/javascript/mastodon/features/status/index.jsx
index 1d7cb685f..2d18c6e9d 100644
--- a/app/javascript/mastodon/features/status/index.jsx
+++ b/app/javascript/mastodon/features/status/index.jsx
@@ -630,7 +630,7 @@ class Status extends ImmutablePureComponent {
             {ancestors}
 
             <HotKeys handlers={handlers}>
-              <div className={classNames('focusable', 'detailed-status__wrapper', `detailed-status__wrapper-${status.get('visibility')}`)} tabIndex='0' aria-label={textForScreenReader(intl, status, false)}>
+              <div className={classNames('focusable', 'detailed-status__wrapper', `detailed-status__wrapper-${status.get('visibility')}`)} tabIndex={0} aria-label={textForScreenReader(intl, status, false)}>
                 <DetailedStatus
                   key={`details-${status.get('id')}`}
                   status={status}
diff --git a/app/javascript/mastodon/features/ui/components/actions_modal.jsx b/app/javascript/mastodon/features/ui/components/actions_modal.jsx
index fd59c1e20..35090e242 100644
--- a/app/javascript/mastodon/features/ui/components/actions_modal.jsx
+++ b/app/javascript/mastodon/features/ui/components/actions_modal.jsx
@@ -23,7 +23,7 @@ export default class ActionsModal extends ImmutablePureComponent {
     return (
       <li key={`${text}-${i}`}>
         <a href={href} target='_blank' rel='noopener noreferrer' onClick={this.props.onClick} data-index={i} className={classNames({ active })}>
-          {icon && <IconButton title={text} icon={icon} role='presentation' tabIndex='-1' inverted />}
+          {icon && <IconButton title={text} icon={icon} role='presentation' tabIndex={-1} inverted />}
           <div>
             <div className={classNames({ 'actions-modal__item-label': !!meta })}>{text}</div>
             <div>{meta}</div>
diff --git a/app/javascript/mastodon/features/ui/components/media_modal.jsx b/app/javascript/mastodon/features/ui/components/media_modal.jsx
index aa179a965..52bd75453 100644
--- a/app/javascript/mastodon/features/ui/components/media_modal.jsx
+++ b/app/javascript/mastodon/features/ui/components/media_modal.jsx
@@ -138,8 +138,8 @@ class MediaModal extends ImmutablePureComponent {
 
     const index = this.getIndex();
 
-    const leftNav  = media.size > 1 && <button tabIndex='0' className='media-modal__nav media-modal__nav--left' onClick={this.handlePrevClick} aria-label={intl.formatMessage(messages.previous)}><Icon id='chevron-left' fixedWidth /></button>;
-    const rightNav = media.size > 1 && <button tabIndex='0' className='media-modal__nav  media-modal__nav--right' onClick={this.handleNextClick} aria-label={intl.formatMessage(messages.next)}><Icon id='chevron-right' fixedWidth /></button>;
+    const leftNav  = media.size > 1 && <button tabIndex={0} className='media-modal__nav media-modal__nav--left' onClick={this.handlePrevClick} aria-label={intl.formatMessage(messages.previous)}><Icon id='chevron-left' fixedWidth /></button>;
+    const rightNav = media.size > 1 && <button tabIndex={0} className='media-modal__nav  media-modal__nav--right' onClick={this.handleNextClick} aria-label={intl.formatMessage(messages.next)}><Icon id='chevron-right' fixedWidth /></button>;
 
     const content = media.map((image) => {
       const width  = image.getIn(['meta', 'original', 'width']) || null;
diff --git a/app/javascript/mastodon/features/ui/components/modal_root.jsx b/app/javascript/mastodon/features/ui/components/modal_root.jsx
index 5a1734977..c252e6caa 100644
--- a/app/javascript/mastodon/features/ui/components/modal_root.jsx
+++ b/app/javascript/mastodon/features/ui/components/modal_root.jsx
@@ -73,7 +73,7 @@ export default class ModalRoot extends React.PureComponent {
       document.documentElement.style.marginRight = `${getScrollbarWidth()}px`;
     } else {
       document.body.classList.remove('with-modals--active');
-      document.documentElement.style.marginRight = 0;
+      document.documentElement.style.marginRight = '0';
     }
   }
 
diff --git a/app/javascript/mastodon/features/video/index.jsx b/app/javascript/mastodon/features/video/index.jsx
index 58bb45908..e2637e0be 100644
--- a/app/javascript/mastodon/features/video/index.jsx
+++ b/app/javascript/mastodon/features/video/index.jsx
@@ -582,7 +582,7 @@ class Video extends React.PureComponent {
           poster={preview}
           preload={preload}
           role='button'
-          tabIndex='0'
+          tabIndex={0}
           aria-label={alt}
           title={alt}
           lang={lang}
@@ -611,7 +611,7 @@ class Video extends React.PureComponent {
 
             <span
               className={classNames('video-player__seek__handle', { active: dragging })}
-              tabIndex='0'
+              tabIndex={0}
               style={{ left: `${progress}%` }}
               onKeyDown={this.handleVideoKeyDown}
             />
@@ -627,7 +627,7 @@ class Video extends React.PureComponent {
 
                 <span
                   className={classNames('video-player__volume__handle')}
-                  tabIndex='0'
+                  tabIndex={0}
                   style={{ left: `${volume * 100}%` }}
                 />
               </div>
diff --git a/app/javascript/mastodon/initial_state.js b/app/javascript/mastodon/initial_state.js
index af022e16b..56b2f4eb2 100644
--- a/app/javascript/mastodon/initial_state.js
+++ b/app/javascript/mastodon/initial_state.js
@@ -55,7 +55,7 @@
  * @property {boolean=} delete_modal
  * @property {boolean=} disable_swiping
  * @property {string=} disabled_account_id
- * @property {boolean} display_media
+ * @property {string} display_media
  * @property {string} domain
  * @property {boolean=} expand_spoilers
  * @property {boolean} limited_federation_mode
diff --git a/app/javascript/mastodon/load_polyfills.js b/app/javascript/mastodon/load_polyfills.js
index b2c41303a..7909dc4ea 100644
--- a/app/javascript/mastodon/load_polyfills.js
+++ b/app/javascript/mastodon/load_polyfills.js
@@ -12,7 +12,6 @@ function importExtraPolyfills() {
 
 function loadPolyfills() {
   const needsBasePolyfills = !(
-    Array.prototype.includes &&
     HTMLCanvasElement.prototype.toBlob &&
     window.Intl &&
     Object.assign &&
diff --git a/app/javascript/mastodon/locales/ast.json b/app/javascript/mastodon/locales/ast.json
index fd4959185..c0920bbec 100644
--- a/app/javascript/mastodon/locales/ast.json
+++ b/app/javascript/mastodon/locales/ast.json
@@ -20,7 +20,7 @@
   "account.blocked": "Blocked",
   "account.browse_more_on_origin_server": "Restolar más nel perfil orixinal",
   "account.cancel_follow_request": "Withdraw follow request",
-  "account.direct": "Privately mention @{name}",
+  "account.direct": "Mentar a @{name} per privao",
   "account.disable_notifications": "Dexar d'avisame cuando @{name} espublice artículos",
   "account.domain_blocked": "Domain blocked",
   "account.edit_profile": "Editar el perfil",
@@ -102,7 +102,7 @@
   "column.blocks": "Perfiles bloquiaos",
   "column.bookmarks": "Marcadores",
   "column.community": "Llinia de tiempu llocal",
-  "column.direct": "Private mentions",
+  "column.direct": "Menciones privaes",
   "column.directory": "Browse profiles",
   "column.domain_blocks": "Dominios bloquiaos",
   "column.favourites": "Favoritos",
@@ -216,7 +216,7 @@
   "empty_column.blocks": "Entá nun bloquiesti a nengún perfil.",
   "empty_column.bookmarked_statuses": "Entá nun tienes nengún artículu en Marcadores. Cuando amiestes dalgún, apaez equí.",
   "empty_column.community": "La llinia de tiempu llocal ta balera. ¡Espubliza daqué públicamente pa comenzar l'alderique!",
-  "empty_column.direct": "You don't have any private mentions yet. When you send or receive one, it will show up here.",
+  "empty_column.direct": "Entá nun tienes nenguna mención privada. Cuando unvies o recibas dalguna, apaez equí.",
   "empty_column.domain_blocks": "Entá nun hai nengún dominiu bloquiáu.",
   "empty_column.explore_statuses": "Agora nun hai nada en tendencia. ¡Volvi equí dempués!",
   "empty_column.favourited_statuses": "Entá nun marquesti nengún artículu como favoritu. Cuando marques dalgún, apaez equí.",
@@ -314,7 +314,7 @@
   "keyboard_shortcuts.column": "Enfocar una columna",
   "keyboard_shortcuts.compose": "Enfocar l'área de composición",
   "keyboard_shortcuts.description": "Descripción",
-  "keyboard_shortcuts.direct": "to open direct messages column",
+  "keyboard_shortcuts.direct": "p'abrir la columna de les menciones privaes",
   "keyboard_shortcuts.down": "Baxar na llista",
   "keyboard_shortcuts.enter": "Abrir un artículu",
   "keyboard_shortcuts.favourite": "Marcar un artículu como favoritu",
@@ -376,7 +376,7 @@
   "navigation_bar.bookmarks": "Marcadores",
   "navigation_bar.community_timeline": "Llinia de tiempu llocal",
   "navigation_bar.compose": "Compose new post",
-  "navigation_bar.direct": "Private mentions",
+  "navigation_bar.direct": "Menciones privaes",
   "navigation_bar.discover": "Discover",
   "navigation_bar.domain_blocks": "Dominios bloquiaos",
   "navigation_bar.edit_profile": "Editar el perfil",
@@ -559,8 +559,8 @@
   "status.copy": "Copiar l'enllaz al artículu",
   "status.delete": "Desaniciar",
   "status.detailed_status": "Detailed conversation view",
-  "status.direct": "Privately mention @{name}",
-  "status.direct_indicator": "Private mention",
+  "status.direct": "Mentar a @{name} per privao",
+  "status.direct_indicator": "Mención privada",
   "status.edit": "Edit",
   "status.edited": "Editóse'l {date}",
   "status.edited_x_times": "Editóse {count, plural, one {{count} vegada} other {{count} vegaes}}",
diff --git a/app/javascript/mastodon/locales/be.json b/app/javascript/mastodon/locales/be.json
index 6af78717a..72224a71c 100644
--- a/app/javascript/mastodon/locales/be.json
+++ b/app/javascript/mastodon/locales/be.json
@@ -522,17 +522,17 @@
   "report_notification.categories.spam": "Спам",
   "report_notification.categories.violation": "Парушэнне правілаў",
   "report_notification.open": "Адкрыць скаргу",
-  "search.no_recent_searches": "No recent searches",
+  "search.no_recent_searches": "Гісторыя пошуку пустая",
   "search.placeholder": "Пошук",
-  "search.quick_action.account_search": "Profiles matching {x}",
-  "search.quick_action.go_to_account": "Go to profile {x}",
-  "search.quick_action.go_to_hashtag": "Go to hashtag {x}",
-  "search.quick_action.open_url": "Open URL in Mastodon",
-  "search.quick_action.status_search": "Posts matching {x}",
+  "search.quick_action.account_search": "Супадзенне профіляў {x}",
+  "search.quick_action.go_to_account": "Перайсці да профілю {x}",
+  "search.quick_action.go_to_hashtag": "Перайсці да хэштэгу {x}",
+  "search.quick_action.open_url": "Адкрыць спасылку ў Mastodon",
+  "search.quick_action.status_search": "Супадзенне паведамленняў {x}",
   "search.search_or_paste": "Увядзіце спасылку або пошукавы запыт",
-  "search_popout.quick_actions": "Quick actions",
-  "search_popout.recent": "Recent searches",
-  "search_results.accounts": "Profiles",
+  "search_popout.quick_actions": "Хуткія дзеянні",
+  "search_popout.recent": "Нядаўнія запыты",
+  "search_results.accounts": "Профілі",
   "search_results.all": "Усё",
   "search_results.hashtags": "Хэштэгі",
   "search_results.nothing_found": "Па дадзенаму запыту нічога не знойдзена",
diff --git a/app/javascript/mastodon/locales/ca.json b/app/javascript/mastodon/locales/ca.json
index f8a7767d5..dd30da215 100644
--- a/app/javascript/mastodon/locales/ca.json
+++ b/app/javascript/mastodon/locales/ca.json
@@ -522,16 +522,16 @@
   "report_notification.categories.spam": "Brossa",
   "report_notification.categories.violation": "Violació de norma",
   "report_notification.open": "Obre un informe",
-  "search.no_recent_searches": "No recent searches",
+  "search.no_recent_searches": "No hi ha cerques recents",
   "search.placeholder": "Cerca",
-  "search.quick_action.account_search": "Profiles matching {x}",
-  "search.quick_action.go_to_account": "Go to profile {x}",
-  "search.quick_action.go_to_hashtag": "Go to hashtag {x}",
-  "search.quick_action.open_url": "Open URL in Mastodon",
-  "search.quick_action.status_search": "Posts matching {x}",
+  "search.quick_action.account_search": "Perfils coincidents {x}",
+  "search.quick_action.go_to_account": "Anar al perfil {x}",
+  "search.quick_action.go_to_hashtag": "Anar a la etiqueta {x}",
+  "search.quick_action.open_url": "Obrir URL a Mastodon",
+  "search.quick_action.status_search": "Tuts coincidents {x}",
   "search.search_or_paste": "Cerca o escriu l'URL",
-  "search_popout.quick_actions": "Quick actions",
-  "search_popout.recent": "Recent searches",
+  "search_popout.quick_actions": "Accions ràpides",
+  "search_popout.recent": "Cerques recents",
   "search_results.accounts": "Perfils",
   "search_results.all": "Tots",
   "search_results.hashtags": "Etiquetes",
diff --git a/app/javascript/mastodon/locales/ckb.json b/app/javascript/mastodon/locales/ckb.json
index 45e8df0b0..ca0ca6f19 100644
--- a/app/javascript/mastodon/locales/ckb.json
+++ b/app/javascript/mastodon/locales/ckb.json
@@ -20,7 +20,7 @@
   "account.blocked": "بلۆککرا",
   "account.browse_more_on_origin_server": "گەڕانی فرەتر لە سەر پرۆفایلی سەرەکی",
   "account.cancel_follow_request": "داواکاری فۆڵۆو بکشێنەوە",
-  "account.direct": "Privately mention @{name}",
+  "account.direct": "بە شێوەیەکی تایبەت باسی @{name} بکە",
   "account.disable_notifications": "ئاگانامە مەنێرە بۆم کاتێک @{name} پۆست دەکرێت",
   "account.domain_blocked": "دۆمەین قەپاتکرا",
   "account.edit_profile": "دەستکاری پرۆفایل",
@@ -29,14 +29,14 @@
   "account.featured_tags.last_status_at": "دوایین پۆست لە {date}",
   "account.featured_tags.last_status_never": "هیچ پۆستێک نییە",
   "account.featured_tags.title": "هاشتاگە تایبەتەکانی {name}",
-  "account.follow": "شوێنکەوتن",
+  "account.follow": "بەدواداچوون",
   "account.followers": "شوێنکەوتووان",
   "account.followers.empty": "کەسێک شوێن ئەم بەکارهێنەرە نەکەوتووە",
   "account.followers_counter": "{count, plural, one {{counter} شوێنکەوتوو} other {{counter} شوێنکەوتوو}}",
-  "account.following": "دواکەوتن",
+  "account.following": "بەدوادا",
   "account.following_counter": "{count, plural, one {{counter} شوێنکەوتوو} other {{counter} شوێنکەوتوو}}",
   "account.follows.empty": "ئەم بەکارهێنەرە تا ئێستا شوێن کەس نەکەوتووە.",
-  "account.follows_you": "شوێنکەوتووەکانت",
+  "account.follows_you": "شوێنت دەکەوێت",
   "account.go_to_profile": "بڕۆ بۆ پڕۆفایلی",
   "account.hide_reblogs": "داشاردنی بووستەکان لە @{name}",
   "account.joined_short": "بەشداری کردووە",
@@ -50,7 +50,7 @@
   "account.mute_notifications": "هۆشیارکەرەوەکان لاببە لە @{name}",
   "account.muted": "بێ دەنگ",
   "account.open_original_page": "لاپەڕەی ئەسڵی بکەرەوە",
-  "account.posts": "توتس",
+  "account.posts": "نووسراوەکان",
   "account.posts_with_replies": "توتس و وەڵامەکان",
   "account.report": "گوزارشت @{name}",
   "account.requested": "چاوەڕێی ڕەزامەندین. کرتە بکە بۆ هەڵوەشاندنەوەی داواکاری شوێنکەوتن",
@@ -102,7 +102,7 @@
   "column.blocks": "بەکارهێنەرە بلۆککراوەکان",
   "column.bookmarks": "نیشانەکان",
   "column.community": "هێڵی کاتی ناوخۆیی",
-  "column.direct": "Private mentions",
+  "column.direct": "ئاماژەی تایبەت",
   "column.directory": "گەڕان لە پرۆفایلەکان",
   "column.domain_blocks": "دۆمەینە داخراوەکان",
   "column.favourites": "دڵخوازترینەکان",
@@ -216,7 +216,7 @@
   "empty_column.blocks": "تۆ هێشتا هیچ بەکارهێنەرێکت بلۆک نەکردووە.",
   "empty_column.bookmarked_statuses": "تۆ هێشتا هیچ توتێکی دیاریکراوت نیە کاتێک نیشانەیەک نیشان دەکەیت، لێرە دەرئەکەویت.",
   "empty_column.community": "هێڵی کاتی ناوخۆیی بەتاڵە. شتێک بە ئاشکرا بنووسە بۆ ئەوەی تۆپەکە بسووڕێت!",
-  "empty_column.direct": "You don't have any private mentions yet. When you send or receive one, it will show up here.",
+  "empty_column.direct": "تا ئێستا هیچ نامەیەکی ڕاستەوخۆت نییە. کاتێک یەکێکیان دەنێری یان وەریدەگریت، لێرە دەردەکەوێت.",
   "empty_column.domain_blocks": "هێشتا هیچ دۆمەینێکی بلۆک کراو نییە.",
   "empty_column.explore_statuses": "لە ئێستادا هیچ شتێک ترێند نییە. دواتر سەیری بکە!",
   "empty_column.favourited_statuses": "تۆ هێشتا هیچ توتێکی دڵخوازت نییە، کاتێک حەزت لە دانەیەکی باشە، لێرە دەرئەکەویت.",
@@ -299,12 +299,12 @@
   "interaction_modal.description.reply": "بە هەژمارێک لەسەر ماستدۆن، ئەتوانیت وەڵامی ئەم بڵاوکراوەیە بدەیتەوە.",
   "interaction_modal.on_another_server": "لەسەر ڕاژەیەکی جیا",
   "interaction_modal.on_this_server": "لەسەر ئەم ڕاژەیە",
-  "interaction_modal.other_server_instructions": "Copy and paste this URL into the search field of your favourite Mastodon app or the web interface of your Mastodon server.",
-  "interaction_modal.preamble": "Since Mastodon is decentralized, you can use your existing account hosted by another Mastodon server or compatible platform if you don't have an account on this one.",
-  "interaction_modal.title.favourite": "Favourite {name}'s post",
-  "interaction_modal.title.follow": "Follow {name}",
-  "interaction_modal.title.reblog": "Boost {name}'s post",
-  "interaction_modal.title.reply": "Reply to {name}'s post",
+  "interaction_modal.other_server_instructions": "ئەم URLە کۆپی بکە و بیخە ناو بواری گەڕانی ئەپی دڵخوازت لە ماستۆدۆن یان ڕووکاری وێبی سێرڤەری ماستۆدۆنەکەت.",
+  "interaction_modal.preamble": "بەو پێیەی ماستۆدۆن لامەرکەزییە، دەتوانیت ئەکاونتی ئێستات بەکاربهێنیت کە لەلایەن سێرڤەرێکی تری ماستۆدۆن یان پلاتفۆرمی گونجاوەوە هۆست کراوە ئەگەر ئەکاونتێکت لەسەر ئەم ئەکاونتە نەبێت.",
+  "interaction_modal.title.favourite": "پۆستی {name}ی دڵخواز",
+  "interaction_modal.title.follow": "دوای {name} بکەوە",
+  "interaction_modal.title.reblog": "پۆستی {name} زیاد بکە",
+  "interaction_modal.title.reply": "وەڵامی پۆستەکەی {name} بدەرەوە",
   "intervals.full.days": "{number, plural, one {# ڕۆژ} other {# ڕۆژەک}}",
   "intervals.full.hours": "{number, plural, one {# کات} other {# کات}}",
   "intervals.full.minutes": "{number, plural, one {# خولەک} other {# خولەک}}",
@@ -314,7 +314,7 @@
   "keyboard_shortcuts.column": "بۆ ئەوەی تیشک بخاتە سەر توتێک لە یەکێک لە ستوونەکان",
   "keyboard_shortcuts.compose": "بۆ سەرنجدان بە نووسینی ناوچەی دەق",
   "keyboard_shortcuts.description": "وه‌سف",
-  "keyboard_shortcuts.direct": "to open direct messages column",
+  "keyboard_shortcuts.direct": "بۆ کردنەوەی ستوونی ئاماژەی تایبەت",
   "keyboard_shortcuts.down": "بۆ چوونە خوارەوە لە لیستەکەدا",
   "keyboard_shortcuts.enter": "بۆ کردنەوەی توت",
   "keyboard_shortcuts.favourite": "بۆ دڵخواز",
@@ -348,7 +348,7 @@
   "lightbox.next": "داهاتوو",
   "lightbox.previous": "پێشوو",
   "limited_account_hint.action": "بەهەر حاڵ پڕۆفایلی پیشان بدە",
-  "limited_account_hint.title": "This profile has been hidden by the moderators of {domain}.",
+  "limited_account_hint.title": "ئەم پرۆفایلە لەلایەن بەڕێوەبەرانی {domain} شاراوەتەوە.",
   "lists.account.add": "زیادکردن بۆ لیست",
   "lists.account.remove": "لابردن لە لیست",
   "lists.delete": "سڕینەوەی لیست",
@@ -367,16 +367,16 @@
   "media_gallery.toggle_visible": "شاردنەوەی {number, plural, one {image} other {images}}",
   "missing_indicator.label": "نەدۆزرایەوە",
   "missing_indicator.sublabel": "ئەو سەرچاوەیە نادۆزرێتەوە",
-  "moved_to_account_banner.text": "Your account {disabledAccount} is currently disabled because you moved to {movedToAccount}.",
+  "moved_to_account_banner.text": "ئەکاونتەکەت {disabledAccount} لە ئێستادا لەکارخراوە چونکە تۆ چوویتە {movedToAccount}.",
   "mute_modal.duration": "ماوە",
   "mute_modal.hide_notifications": "شاردنەوەی ئاگانامەکان لەم بەکارهێنەرە؟ ",
   "mute_modal.indefinite": "نادیار",
-  "navigation_bar.about": "About",
+  "navigation_bar.about": "دەربارە",
   "navigation_bar.blocks": "بەکارهێنەرە بلۆککراوەکان",
   "navigation_bar.bookmarks": "نیشانکراوەکان",
   "navigation_bar.community_timeline": "دەمنامەی ناوخۆیی",
   "navigation_bar.compose": "نووسینی توتی نوێ",
-  "navigation_bar.direct": "Private mentions",
+  "navigation_bar.direct": "ئاماژەی تایبەت",
   "navigation_bar.discover": "دۆزینەوە",
   "navigation_bar.domain_blocks": "دۆمەینە بلۆک کراوەکان",
   "navigation_bar.edit_profile": "دەستکاری پرۆفایل بکە",
@@ -384,7 +384,7 @@
   "navigation_bar.favourites": "دڵخوازەکان",
   "navigation_bar.filters": "وشە کپەکان",
   "navigation_bar.follow_requests": "بەدواداچوی داواکاریەکان بکە",
-  "navigation_bar.followed_tags": "Followed hashtags",
+  "navigation_bar.followed_tags": "هاشتاگی بەدوادا هات",
   "navigation_bar.follows_and_followers": "شوێنکەوتوو و شوێنکەوتوان",
   "navigation_bar.lists": "لیستەکان",
   "navigation_bar.logout": "دەرچوون",
@@ -393,10 +393,10 @@
   "navigation_bar.pins": "توتی چەسپاو",
   "navigation_bar.preferences": "پەسەندەکان",
   "navigation_bar.public_timeline": "نووسراوەکانی هەمووشوێنێک",
-  "navigation_bar.search": "Search",
+  "navigation_bar.search": "گەڕان",
   "navigation_bar.security": "ئاسایش",
-  "not_signed_in_indicator.not_signed_in": "You need to sign in to access this resource.",
-  "notification.admin.report": "{name} reported {target}",
+  "not_signed_in_indicator.not_signed_in": "پێویستە بچیتە ژوورەوە بۆ دەستگەیشتن بەم سەرچاوەیە.",
+  "notification.admin.report": "{name} ڕاپۆرت کراوە {target}",
   "notification.admin.sign_up": "{name} تۆمارکرا",
   "notification.favourite": "{name} نووسراوەکەتی پەسەند کرد",
   "notification.follow": "{name} دوای تۆ کەوت",
@@ -409,7 +409,7 @@
   "notification.update": "{name} پۆستێکی دەستکاریکرد",
   "notifications.clear": "ئاگانامەکان بسڕیەوە",
   "notifications.clear_confirmation": "ئایا دڵنیایت لەوەی دەتەوێت بە هەمیشەیی هەموو ئاگانامەکانت بسڕیتەوە?",
-  "notifications.column_settings.admin.report": "New reports:",
+  "notifications.column_settings.admin.report": "ڕاپۆرتە نوێیەکان:",
   "notifications.column_settings.admin.sign_up": "چوونەژوورەوەی نوێ:",
   "notifications.column_settings.alert": "ئاگانامەکانی پیشانگەرر ڕومێزی",
   "notifications.column_settings.favourite": "دڵخوازترین:",
@@ -463,8 +463,8 @@
   "privacy.public.short": "گشتی",
   "privacy.unlisted.long": "بۆ هەمووان دیارە، بەڵام لە تایبەتمەندییەکانی دۆزینەوە دەرچووە",
   "privacy.unlisted.short": "لە لیست نەکراو",
-  "privacy_policy.last_updated": "Last updated {date}",
-  "privacy_policy.title": "Privacy Policy",
+  "privacy_policy.last_updated": "دوایین نوێکردنەوە {date}",
+  "privacy_policy.title": "سیاسەتی تایبەتێتی",
   "refresh": "نوێکردنەوە",
   "regeneration_indicator.label": "بارکردن…",
   "regeneration_indicator.sublabel": "ڕاگەیەنەری ماڵەوەت ئامادە دەکرێت!",
@@ -518,29 +518,29 @@
   "report.unfollow": "بەدوادانەچوو@{name}",
   "report.unfollow_explanation": "تۆ شوێنکەوتووی ئەم هەژماررەی دەکەیت. بۆ ئەوەی چیتر نووسراوەکانیان لە هۆم فیدی خۆت نەبینی، بەدوایان مەچۆ.",
   "report_notification.attached_statuses": "{count, plural, one {{count} post} other {{count} posts}} attached",
-  "report_notification.categories.other": "Other",
-  "report_notification.categories.spam": "Spam",
-  "report_notification.categories.violation": "Rule violation",
-  "report_notification.open": "Open report",
-  "search.no_recent_searches": "No recent searches",
+  "report_notification.categories.other": "هی تر",
+  "report_notification.categories.spam": "سپام",
+  "report_notification.categories.violation": "پێشێلکردنی یاسا",
+  "report_notification.open": "ڕاپۆرتەکان بکەوە",
+  "search.no_recent_searches": "گەڕانەکانی ئەم دواییە",
   "search.placeholder": "گەڕان",
-  "search.quick_action.account_search": "Profiles matching {x}",
-  "search.quick_action.go_to_account": "Go to profile {x}",
-  "search.quick_action.go_to_hashtag": "Go to hashtag {x}",
-  "search.quick_action.open_url": "Open URL in Mastodon",
-  "search.quick_action.status_search": "Posts matching {x}",
-  "search.search_or_paste": "Search or paste URL",
-  "search_popout.quick_actions": "Quick actions",
-  "search_popout.recent": "Recent searches",
-  "search_results.accounts": "Profiles",
+  "search.quick_action.account_search": "پڕۆفایلی هاوتا لەگەڵ {x}",
+  "search.quick_action.go_to_account": "بڕۆ بۆ پڕۆفایلی{x}",
+  "search.quick_action.go_to_hashtag": "بڕۆ بۆ هاشتاگی {x}",
+  "search.quick_action.open_url": "بەستەرەکان لەناو ماستۆدۆن بکەوە",
+  "search.quick_action.status_search": "پڕۆفایلی هاوتا لەگەڵ {x}",
+  "search.search_or_paste": "گەڕان یان لێدانی URL",
+  "search_popout.quick_actions": "کرداری خێرا",
+  "search_popout.recent": "گەڕانەکانی ئەم دواییە",
+  "search_results.accounts": "پرۆفایلەکان",
   "search_results.all": "هەموو",
   "search_results.hashtags": "هەشتاگ",
-  "search_results.nothing_found": "Could not find anything for these search terms",
+  "search_results.nothing_found": "هیچ بۆ ئەم زاراوە گەڕانانە نەدۆزراوەتەوە",
   "search_results.statuses": "توتەکان",
   "search_results.statuses_fts_disabled": "گەڕانی توتەکان بە ناوەڕۆکیان لەسەر ئەم ڕاژەی ماستۆدۆن چالاک نەکراوە.",
-  "search_results.title": "Search for {q}",
+  "search_results.title": "گەڕان بەدوای {q}",
   "search_results.total": "{count, number} {count, plural, one {دەرئەنجام} other {دەرئەنجام}}",
-  "server_banner.about_active_users": "People using this server during the last 30 days (Monthly Active Users)",
+  "server_banner.about_active_users": "ئەو کەسانەی لە ماوەی ٣٠ ڕۆژی ڕابردوودا ئەم سێرڤەرە بەکاردەهێنن (بەکارهێنەرانی چالاک مانگانە)",
   "server_banner.active_users": "بەکارهێنەرانی چالاک",
   "server_banner.administered_by": "بەڕێوەبردن لەلایەن:",
   "server_banner.introduction": "{domain} بەشێکە لەو تۆڕە کۆمەڵایەتییە لامەرکەزییەی کە لەلایەن {mastodon}ەوە بەهێز دەکرێت.",
@@ -548,9 +548,9 @@
   "server_banner.server_stats": "دۆخی ڕاژەکار:",
   "sign_in_banner.create_account": "هەژمار دروستبکە",
   "sign_in_banner.sign_in": "بچۆ ژوورەوە",
-  "sign_in_banner.text": "Sign in to follow profiles or hashtags, favourite, share and reply to posts. You can also interact from your account on a different server.",
+  "sign_in_banner.text": "چوونەژوورەوە بۆ فۆڵۆوکردنی پڕۆفایلی یان هاشتاگەکان، دڵخوازەکان، شەیرکردن و وەڵامدانەوەی پۆستەکان. هەروەها دەتوانیت لە ئەکاونتەکەتەوە لەسەر سێرڤەرێکی جیاواز کارلێک بکەیت.",
   "status.admin_account": "کردنەوەی میانڕەوی بەڕێوەبەر بۆ @{name}",
-  "status.admin_domain": "Open moderation interface for {domain}",
+  "status.admin_domain": "ڕووکاری مامناوەندی بکەرەوە بۆ {domain}",
   "status.admin_status": "ئەم توتە بکەوە لە ناو ڕووکاری بەڕیوەبەر",
   "status.block": "@{name} ئاستەنگ بکە",
   "status.bookmark": "نیشانه",
@@ -559,8 +559,8 @@
   "status.copy": "ڕوونووسی بەستەر بۆ توت",
   "status.delete": "سڕینەوە",
   "status.detailed_status": "ڕوانگەی گفتوگۆ بە وردەکاری",
-  "status.direct": "Privately mention @{name}",
-  "status.direct_indicator": "Private mention",
+  "status.direct": "بە شێوەیەکی تایبەت باسی @{name} بکە",
+  "status.direct_indicator": "ئاماژەی تایبەت",
   "status.edit": "دەستکاری",
   "status.edited": "بەشداری {date}",
   "status.edited_x_times": "دەستکاریکراوە {count, plural, one {{count} کات} other {{count} کات}}",
@@ -568,7 +568,7 @@
   "status.favourite": "دڵخواز",
   "status.filter": "ئەم پۆستە فلتەر بکە",
   "status.filtered": "پاڵاوتن",
-  "status.hide": "Hide post",
+  "status.hide": "شاردنەوەی پۆست",
   "status.history.created": "{name} دروستکراوە لە{date}",
   "status.history.edited": "{name} دروستکاریکراوە لە{date}",
   "status.load_more": "زیاتر بار بکە",
diff --git a/app/javascript/mastodon/locales/cs.json b/app/javascript/mastodon/locales/cs.json
index 29b5e3a46..a8cc9a5b2 100644
--- a/app/javascript/mastodon/locales/cs.json
+++ b/app/javascript/mastodon/locales/cs.json
@@ -20,7 +20,7 @@
   "account.blocked": "Blokovaný",
   "account.browse_more_on_origin_server": "Více na původním profilu",
   "account.cancel_follow_request": "Zrušit žádost o sledování",
-  "account.direct": "Privately mention @{name}",
+  "account.direct": "Soukromě zmínit @{name}",
   "account.disable_notifications": "Přestat mě upozorňovat, když @{name} zveřejní příspěvek",
   "account.domain_blocked": "Doména blokována",
   "account.edit_profile": "Upravit profil",
@@ -102,7 +102,7 @@
   "column.blocks": "Blokovaní uživatelé",
   "column.bookmarks": "Záložky",
   "column.community": "Místní časová osa",
-  "column.direct": "Private mentions",
+  "column.direct": "Soukromé zmínky",
   "column.directory": "Prozkoumat profily",
   "column.domain_blocks": "Blokované domény",
   "column.favourites": "Oblíbené",
@@ -163,7 +163,7 @@
   "confirmations.domain_block.confirm": "Blokovat celou doménu",
   "confirmations.domain_block.message": "Opravdu chcete blokovat celou doménu {domain}? Ve většině případů stačí blokovat nebo skrýt pár konkrétních uživatelů, což také doporučujeme. Z této domény neuvidíte obsah v žádné veřejné časové ose ani v oznámeních. Vaši sledující z této domény budou odstraněni.",
   "confirmations.edit.confirm": "Upravit",
-  "confirmations.edit.message": "Editing now will overwrite the message you are currently composing. Are you sure you want to proceed?",
+  "confirmations.edit.message": "Editovat teď znamená přepsání zprávy, kterou právě tvoříte. Opravdu chcete pokračovat?",
   "confirmations.logout.confirm": "Odhlásit se",
   "confirmations.logout.message": "Opravdu se chcete odhlásit?",
   "confirmations.mute.confirm": "Skrýt",
@@ -216,7 +216,7 @@
   "empty_column.blocks": "Ještě jste nezablokovali žádného uživatele.",
   "empty_column.bookmarked_statuses": "Zatím v záložkách nemáte žádné příspěvky. Až si do nich nějaký přidáte, zobrazí se zde.",
   "empty_column.community": "Místní časová osa je prázdná. Napište něco veřejně a rozhýbejte to tu!",
-  "empty_column.direct": "You don't have any private mentions yet. When you send or receive one, it will show up here.",
+  "empty_column.direct": "Zatím nemáte žádné soukromé zmínky. Až nějakou pošlete nebo dostanete, zobrazí se zde.",
   "empty_column.domain_blocks": "Ještě nemáte žádné zablokované domény.",
   "empty_column.explore_statuses": "Momentálně není nic populární. Vraťte se později!",
   "empty_column.favourited_statuses": "Zatím nemáte žádné oblíbené příspěvky. Až si nějaký oblíbíte, zobrazí se zde.",
@@ -376,7 +376,7 @@
   "navigation_bar.bookmarks": "Záložky",
   "navigation_bar.community_timeline": "Místní časová osa",
   "navigation_bar.compose": "Vytvořit nový příspěvek",
-  "navigation_bar.direct": "Private mentions",
+  "navigation_bar.direct": "Soukromé zmínky",
   "navigation_bar.discover": "Objevit",
   "navigation_bar.domain_blocks": "Blokované domény",
   "navigation_bar.edit_profile": "Upravit profil",
@@ -522,17 +522,17 @@
   "report_notification.categories.spam": "Spam",
   "report_notification.categories.violation": "Porušení pravidla",
   "report_notification.open": "Otevřít hlášení",
-  "search.no_recent_searches": "No recent searches",
+  "search.no_recent_searches": "Žádná nedávná vyhledávání",
   "search.placeholder": "Hledat",
-  "search.quick_action.account_search": "Profiles matching {x}",
-  "search.quick_action.go_to_account": "Go to profile {x}",
-  "search.quick_action.go_to_hashtag": "Go to hashtag {x}",
-  "search.quick_action.open_url": "Open URL in Mastodon",
-  "search.quick_action.status_search": "Posts matching {x}",
+  "search.quick_action.account_search": "Profily odpovídající {x}",
+  "search.quick_action.go_to_account": "Přejít na profil {x}",
+  "search.quick_action.go_to_hashtag": "Přejít na hashtag {x}",
+  "search.quick_action.open_url": "Otevřít URL v Mastodonu",
+  "search.quick_action.status_search": "Příspěvky odpovídající {x}",
   "search.search_or_paste": "Hledat nebo vložit URL",
-  "search_popout.quick_actions": "Quick actions",
-  "search_popout.recent": "Recent searches",
-  "search_results.accounts": "Profiles",
+  "search_popout.quick_actions": "Rychlé akce",
+  "search_popout.recent": "Nedávná vyhledávání",
+  "search_results.accounts": "Profily",
   "search_results.all": "Vše",
   "search_results.hashtags": "Hashtagy",
   "search_results.nothing_found": "Pro tyto hledané výrazy nebylo nic nenalezeno",
@@ -560,7 +560,7 @@
   "status.delete": "Smazat",
   "status.detailed_status": "Podrobné zobrazení konverzace",
   "status.direct": "Privately mention @{name}",
-  "status.direct_indicator": "Private mention",
+  "status.direct_indicator": "Soukromá zmínka",
   "status.edit": "Upravit",
   "status.edited": "Upraveno {date}",
   "status.edited_x_times": "Upraveno {count, plural, one {{count}krát} few {{count}krát} many {{count}krát} other {{count}krát}}",
diff --git a/app/javascript/mastodon/locales/da.json b/app/javascript/mastodon/locales/da.json
index 0116221e0..ca9caf79d 100644
--- a/app/javascript/mastodon/locales/da.json
+++ b/app/javascript/mastodon/locales/da.json
@@ -522,16 +522,16 @@
   "report_notification.categories.spam": "Spam",
   "report_notification.categories.violation": "Regelovertrædelse",
   "report_notification.open": "Åbn anmeldelse",
-  "search.no_recent_searches": "No recent searches",
+  "search.no_recent_searches": "Ingen seneste søgninger",
   "search.placeholder": "Søg",
-  "search.quick_action.account_search": "Profiles matching {x}",
-  "search.quick_action.go_to_account": "Go to profile {x}",
-  "search.quick_action.go_to_hashtag": "Go to hashtag {x}",
-  "search.quick_action.open_url": "Open URL in Mastodon",
-  "search.quick_action.status_search": "Posts matching {x}",
+  "search.quick_action.account_search": "Profiler matchende {x}",
+  "search.quick_action.go_to_account": "Gå til profilen {x}",
+  "search.quick_action.go_to_hashtag": "Gå til hashtagget {x}",
+  "search.quick_action.open_url": "Åbn URL i Mastodon",
+  "search.quick_action.status_search": "Indlæg matchende {x}",
   "search.search_or_paste": "Søg efter eller angiv URL",
-  "search_popout.quick_actions": "Quick actions",
-  "search_popout.recent": "Recent searches",
+  "search_popout.quick_actions": "Hurtige handlinger",
+  "search_popout.recent": "Seneste søgninger",
   "search_results.accounts": "Profiler",
   "search_results.all": "Alle",
   "search_results.hashtags": "Hashtags",
diff --git a/app/javascript/mastodon/locales/de.json b/app/javascript/mastodon/locales/de.json
index f06954790..2312ca2fb 100644
--- a/app/javascript/mastodon/locales/de.json
+++ b/app/javascript/mastodon/locales/de.json
@@ -522,16 +522,16 @@
   "report_notification.categories.spam": "Spam",
   "report_notification.categories.violation": "Regelverstoß",
   "report_notification.open": "Meldung öffnen",
-  "search.no_recent_searches": "No recent searches",
+  "search.no_recent_searches": "Keine kürzlichen Suchanfragen",
   "search.placeholder": "Suche",
-  "search.quick_action.account_search": "Profiles matching {x}",
-  "search.quick_action.go_to_account": "Go to profile {x}",
-  "search.quick_action.go_to_hashtag": "Go to hashtag {x}",
-  "search.quick_action.open_url": "Open URL in Mastodon",
-  "search.quick_action.status_search": "Posts matching {x}",
+  "search.quick_action.account_search": "Profile passend zu {x}",
+  "search.quick_action.go_to_account": "Profil {x} aufrufen",
+  "search.quick_action.go_to_hashtag": "Hashtag {x} aufrufen",
+  "search.quick_action.open_url": "URL in Mastodon öffnen",
+  "search.quick_action.status_search": "Beiträge passend zu {x}",
   "search.search_or_paste": "Suchen oder URL einfügen",
-  "search_popout.quick_actions": "Quick actions",
-  "search_popout.recent": "Recent searches",
+  "search_popout.quick_actions": "Schnellaktionen",
+  "search_popout.recent": "Kürzliche Suchanfragen",
   "search_results.accounts": "Profile",
   "search_results.all": "Alles",
   "search_results.hashtags": "Hashtags",
diff --git a/app/javascript/mastodon/locales/el.json b/app/javascript/mastodon/locales/el.json
index f59cd38d7..cefc86853 100644
--- a/app/javascript/mastodon/locales/el.json
+++ b/app/javascript/mastodon/locales/el.json
@@ -522,16 +522,16 @@
   "report_notification.categories.spam": "Ανεπιθύμητα",
   "report_notification.categories.violation": "Παραβίαση κανόνα",
   "report_notification.open": "Ανοικτό",
-  "search.no_recent_searches": "No recent searches",
+  "search.no_recent_searches": "Καμμία πρόσφατη αναζήτηση",
   "search.placeholder": "Αναζήτηση",
-  "search.quick_action.account_search": "Profiles matching {x}",
-  "search.quick_action.go_to_account": "Go to profile {x}",
-  "search.quick_action.go_to_hashtag": "Go to hashtag {x}",
-  "search.quick_action.open_url": "Open URL in Mastodon",
-  "search.quick_action.status_search": "Posts matching {x}",
+  "search.quick_action.account_search": "Προφίλ που ταιριάζουν με {x}",
+  "search.quick_action.go_to_account": "Μετάβαση στο προφίλ {x}",
+  "search.quick_action.go_to_hashtag": "Μετάβαση στην ετικέτα {x}",
+  "search.quick_action.open_url": "Άνοιγμα διεύθυνσης URL στο Mastodon",
+  "search.quick_action.status_search": "Αναρτήσεις που ταιριάζουν με {x}",
   "search.search_or_paste": "Αναζήτηση ή εισαγωγή URL",
-  "search_popout.quick_actions": "Quick actions",
-  "search_popout.recent": "Recent searches",
+  "search_popout.quick_actions": "Γρήγορες ενέργειες",
+  "search_popout.recent": "Πρόσφατες αναζητήσεις",
   "search_results.accounts": "Προφίλ",
   "search_results.all": "Όλα",
   "search_results.hashtags": "Ετικέτες",
diff --git a/app/javascript/mastodon/locales/eo.json b/app/javascript/mastodon/locales/eo.json
index 27b33c31f..be5ec1dc7 100644
--- a/app/javascript/mastodon/locales/eo.json
+++ b/app/javascript/mastodon/locales/eo.json
@@ -522,17 +522,17 @@
   "report_notification.categories.spam": "Trudmesaĝo",
   "report_notification.categories.violation": "Malobservo de la regulo",
   "report_notification.open": "Malfermi la raporton",
-  "search.no_recent_searches": "No recent searches",
+  "search.no_recent_searches": "Neniuj lastaj serĉoj",
   "search.placeholder": "Serĉi",
-  "search.quick_action.account_search": "Profiles matching {x}",
-  "search.quick_action.go_to_account": "Go to profile {x}",
-  "search.quick_action.go_to_hashtag": "Go to hashtag {x}",
-  "search.quick_action.open_url": "Open URL in Mastodon",
-  "search.quick_action.status_search": "Posts matching {x}",
+  "search.quick_action.account_search": "Profiloj kiuj kongruas kun {x}",
+  "search.quick_action.go_to_account": "Iri al profilo {x}",
+  "search.quick_action.go_to_hashtag": "Iri al kradvorto {x}",
+  "search.quick_action.open_url": "Malfermi URL en Mastodono",
+  "search.quick_action.status_search": "Afiŝoj kiuj kongruas kun {x}",
   "search.search_or_paste": "Serĉu aŭ algluu URL-on",
-  "search_popout.quick_actions": "Quick actions",
-  "search_popout.recent": "Recent searches",
-  "search_results.accounts": "Profiles",
+  "search_popout.quick_actions": "Rapidaj agoj",
+  "search_popout.recent": "Lastaj serĉoj",
+  "search_results.accounts": "Profiloj",
   "search_results.all": "Ĉiuj",
   "search_results.hashtags": "Kradvortoj",
   "search_results.nothing_found": "Povis trovi nenion por ĉi tiuj serĉaj terminoj",
diff --git a/app/javascript/mastodon/locales/es-AR.json b/app/javascript/mastodon/locales/es-AR.json
index 1636229ed..a577cec79 100644
--- a/app/javascript/mastodon/locales/es-AR.json
+++ b/app/javascript/mastodon/locales/es-AR.json
@@ -522,16 +522,16 @@
   "report_notification.categories.spam": "Spam",
   "report_notification.categories.violation": "Violación de regla",
   "report_notification.open": "Abrir denuncia",
-  "search.no_recent_searches": "No recent searches",
+  "search.no_recent_searches": "Sin búsquedas recientes",
   "search.placeholder": "Buscar",
-  "search.quick_action.account_search": "Profiles matching {x}",
-  "search.quick_action.go_to_account": "Go to profile {x}",
-  "search.quick_action.go_to_hashtag": "Go to hashtag {x}",
-  "search.quick_action.open_url": "Open URL in Mastodon",
-  "search.quick_action.status_search": "Posts matching {x}",
+  "search.quick_action.account_search": "Perfiles que coinciden con {x}",
+  "search.quick_action.go_to_account": "Ir al perfil de {x}",
+  "search.quick_action.go_to_hashtag": "Ir a la etiqueta {x}",
+  "search.quick_action.open_url": "Abrir enlace en Mastodon",
+  "search.quick_action.status_search": "Mensajes que coinciden con {x}",
   "search.search_or_paste": "Buscar o pegar dirección web",
-  "search_popout.quick_actions": "Quick actions",
-  "search_popout.recent": "Recent searches",
+  "search_popout.quick_actions": "Acciones rápidas",
+  "search_popout.recent": "Búsquedas recientes",
   "search_results.accounts": "Perfiles",
   "search_results.all": "Todos",
   "search_results.hashtags": "Etiquetas",
diff --git a/app/javascript/mastodon/locales/es-MX.json b/app/javascript/mastodon/locales/es-MX.json
index 4fc226b96..1338b8b46 100644
--- a/app/javascript/mastodon/locales/es-MX.json
+++ b/app/javascript/mastodon/locales/es-MX.json
@@ -522,16 +522,16 @@
   "report_notification.categories.spam": "Spam",
   "report_notification.categories.violation": "Infracción de regla",
   "report_notification.open": "Abrir denuncia",
-  "search.no_recent_searches": "No recent searches",
+  "search.no_recent_searches": "Sin búsquedas recientes",
   "search.placeholder": "Buscar",
-  "search.quick_action.account_search": "Profiles matching {x}",
-  "search.quick_action.go_to_account": "Go to profile {x}",
-  "search.quick_action.go_to_hashtag": "Go to hashtag {x}",
-  "search.quick_action.open_url": "Open URL in Mastodon",
-  "search.quick_action.status_search": "Posts matching {x}",
+  "search.quick_action.account_search": "Perfiles que coinciden con {x}",
+  "search.quick_action.go_to_account": "Ir al perfil {x}",
+  "search.quick_action.go_to_hashtag": "Ir a la etiqueta {x}",
+  "search.quick_action.open_url": "Abrir enlace en Mastodon",
+  "search.quick_action.status_search": "Publicaciones que coinciden con {x}",
   "search.search_or_paste": "Buscar o pegar URL",
-  "search_popout.quick_actions": "Quick actions",
-  "search_popout.recent": "Recent searches",
+  "search_popout.quick_actions": "Acciones rápidas",
+  "search_popout.recent": "Búsquedas recientes",
   "search_results.accounts": "Perfiles",
   "search_results.all": "Todos",
   "search_results.hashtags": "Etiquetas",
diff --git a/app/javascript/mastodon/locales/es.json b/app/javascript/mastodon/locales/es.json
index 5eb68c4f8..d9f254055 100644
--- a/app/javascript/mastodon/locales/es.json
+++ b/app/javascript/mastodon/locales/es.json
@@ -59,13 +59,13 @@
   "account.show_reblogs": "Mostrar impulsos de @{name}",
   "account.statuses_counter": "{count, plural, one {{counter} Publicación} other {{counter} Publicaciones}}",
   "account.unblock": "Desbloquear a @{name}",
-  "account.unblock_domain": "Mostrar {domain}",
+  "account.unblock_domain": "Desbloquear dominio {domain}",
   "account.unblock_short": "Desbloquear",
   "account.unendorse": "No destacar 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.unmute_short": "Desilenciar",
+  "account.unmute_short": "Dejar de silenciar",
   "account_note.placeholder": "Clic para añadir nota",
   "admin.dashboard.daily_retention": "Tasa de retención de usuarios por día después del registro",
   "admin.dashboard.monthly_retention": "Tasa de retención de usuarios por mes después del registro",
@@ -76,7 +76,7 @@
   "alert.rate_limited.title": "Tráfico limitado",
   "alert.unexpected.message": "Hubo un error inesperado.",
   "alert.unexpected.title": "¡Ups!",
-  "announcement.announcement": "Comunicación",
+  "announcement.announcement": "Anuncio",
   "attachments_list.unprocessed": "(sin procesar)",
   "audio.hide": "Ocultar audio",
   "autosuggest_hashtag.per_week": "{count} por semana",
@@ -140,12 +140,12 @@
   "compose_form.poll.switch_to_single": "Modificar encuesta para permitir una única opción",
   "compose_form.publish": "Publicar",
   "compose_form.publish_form": "Publicar",
-  "compose_form.publish_loud": "{publish}!",
+  "compose_form.publish_loud": "¡{publish}!",
   "compose_form.save_changes": "Guardar cambios",
   "compose_form.sensitive.hide": "{count, plural, one {Marcar material como sensible} other {Marcar material como sensible}}",
   "compose_form.sensitive.marked": "{count, plural, one {Material marcado como sensible} other {Material marcado como sensible}}",
   "compose_form.sensitive.unmarked": "{count, plural, one {Material no marcado como sensible} other {Material no marcado como sensible}}",
-  "compose_form.spoiler.marked": "Texto oculto tras la advertencia",
+  "compose_form.spoiler.marked": "Quitar advertencia de contenido",
   "compose_form.spoiler.unmarked": "Añadir advertencia de contenido",
   "compose_form.spoiler_placeholder": "Escribe aquí tu advertencia",
   "confirmation_modal.cancel": "Cancelar",
@@ -160,7 +160,7 @@
   "confirmations.delete_list.message": "¿Seguro que quieres borrar esta lista permanentemente?",
   "confirmations.discard_edit_media.confirm": "Descartar",
   "confirmations.discard_edit_media.message": "Tienes cambios sin guardar en la descripción o vista previa del archivo audiovisual, ¿descartarlos de todos modos?",
-  "confirmations.domain_block.confirm": "Ocultar dominio entero",
+  "confirmations.domain_block.confirm": "Bloquear dominio entero",
   "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.edit.confirm": "Editar",
   "confirmations.edit.message": "Editar ahora reemplazará el mensaje que está escribiendo. ¿Está seguro que quiere proceder?",
@@ -522,16 +522,16 @@
   "report_notification.categories.spam": "Spam",
   "report_notification.categories.violation": "Infracción de regla",
   "report_notification.open": "Abrir informe",
-  "search.no_recent_searches": "No recent searches",
+  "search.no_recent_searches": "Sin búsquedas recientes",
   "search.placeholder": "Buscar",
-  "search.quick_action.account_search": "Profiles matching {x}",
-  "search.quick_action.go_to_account": "Go to profile {x}",
-  "search.quick_action.go_to_hashtag": "Go to hashtag {x}",
-  "search.quick_action.open_url": "Open URL in Mastodon",
-  "search.quick_action.status_search": "Posts matching {x}",
+  "search.quick_action.account_search": "Perfiles que coinciden con {x}",
+  "search.quick_action.go_to_account": "Ir al perfil {x}",
+  "search.quick_action.go_to_hashtag": "Ir a la etiqueta {x}",
+  "search.quick_action.open_url": "Abrir enlace en Mastodon",
+  "search.quick_action.status_search": "Publicaciones que coinciden con {x}",
   "search.search_or_paste": "Buscar o pegar URL",
-  "search_popout.quick_actions": "Quick actions",
-  "search_popout.recent": "Recent searches",
+  "search_popout.quick_actions": "Acciones rápidas",
+  "search_popout.recent": "Búsquedas recientes",
   "search_results.accounts": "Perfiles",
   "search_results.all": "Todos",
   "search_results.hashtags": "Etiquetas",
diff --git a/app/javascript/mastodon/locales/et.json b/app/javascript/mastodon/locales/et.json
index 7e39386aa..a61a577d6 100644
--- a/app/javascript/mastodon/locales/et.json
+++ b/app/javascript/mastodon/locales/et.json
@@ -224,7 +224,7 @@
   "empty_column.follow_recommendations": "Tundub, et sinu jaoks ei ole võimalik soovitusi luua. Proovi kasutada otsingut, et leida tuttavaid inimesi, või sirvi populaarseid silte.",
   "empty_column.follow_requests": "Pole hetkel ühtegi jälgimistaotlust. Kui saad mõne, näed neid siin.",
   "empty_column.followed_tags": "Sa ei jälgi veel ühtegi märksõna. Kui jälgid, ilmuvad need siia.",
-  "empty_column.hashtag": "Seda sildi all ei ole ühtegi postitust.",
+  "empty_column.hashtag": "Selle sildi all ei ole ühtegi postitust.",
   "empty_column.home": "Su koduajajoon on tühi. Jälgi rohkemaid inimesi, et seda täita {suggestions}",
   "empty_column.home.suggestions": "Vaata mõndasid soovitusi",
   "empty_column.list": "Siin loetelus pole veel midagi. Kui loetelu liikmed teevad uusi postitusi, näed neid siin.",
@@ -522,16 +522,16 @@
   "report_notification.categories.spam": "Rämpspost",
   "report_notification.categories.violation": "Reeglite rikkumine",
   "report_notification.open": "Ava teavitus",
-  "search.no_recent_searches": "No recent searches",
+  "search.no_recent_searches": "Pole viimatisi otsinguid",
   "search.placeholder": "Otsi",
-  "search.quick_action.account_search": "Profiles matching {x}",
-  "search.quick_action.go_to_account": "Go to profile {x}",
-  "search.quick_action.go_to_hashtag": "Go to hashtag {x}",
-  "search.quick_action.open_url": "Open URL in Mastodon",
-  "search.quick_action.status_search": "Posts matching {x}",
+  "search.quick_action.account_search": "Sobivaid profiile {x}",
+  "search.quick_action.go_to_account": "Mine profiili {x}",
+  "search.quick_action.go_to_hashtag": "Ava silt {x}",
+  "search.quick_action.open_url": "Ava URL Mastodonis",
+  "search.quick_action.status_search": "Sobivad postitused {x}",
   "search.search_or_paste": "Otsi või kleebi URL",
-  "search_popout.quick_actions": "Quick actions",
-  "search_popout.recent": "Recent searches",
+  "search_popout.quick_actions": "Kiirtegevused",
+  "search_popout.recent": "Viimatised otsingud",
   "search_results.accounts": "Profiilid",
   "search_results.all": "Kõik",
   "search_results.hashtags": "Sildid",
diff --git a/app/javascript/mastodon/locales/eu.json b/app/javascript/mastodon/locales/eu.json
index 11ed5be8c..597f4fb50 100644
--- a/app/javascript/mastodon/locales/eu.json
+++ b/app/javascript/mastodon/locales/eu.json
@@ -522,16 +522,16 @@
   "report_notification.categories.spam": "Spam",
   "report_notification.categories.violation": "Arau haustea",
   "report_notification.open": "Ireki salaketa",
-  "search.no_recent_searches": "No recent searches",
+  "search.no_recent_searches": "Duela gutxiko bilaketarik ez",
   "search.placeholder": "Bilatu",
-  "search.quick_action.account_search": "Profiles matching {x}",
-  "search.quick_action.go_to_account": "Go to profile {x}",
-  "search.quick_action.go_to_hashtag": "Go to hashtag {x}",
-  "search.quick_action.open_url": "Open URL in Mastodon",
-  "search.quick_action.status_search": "Posts matching {x}",
+  "search.quick_action.account_search": "{x}-(r)ekin bat datozen profilak",
+  "search.quick_action.go_to_account": "Joan {x} profilera",
+  "search.quick_action.go_to_hashtag": "Joan {x} traolara",
+  "search.quick_action.open_url": "Ireki URLa Mastodonen",
+  "search.quick_action.status_search": "{x}-(r)ekin bat datozen argitalpenak",
   "search.search_or_paste": "Bilatu edo itsatsi URLa",
-  "search_popout.quick_actions": "Quick actions",
-  "search_popout.recent": "Recent searches",
+  "search_popout.quick_actions": "Ekintza azkarrak",
+  "search_popout.recent": "Duela gutxiko bilaketak",
   "search_results.accounts": "Profilak",
   "search_results.all": "Guztiak",
   "search_results.hashtags": "Traolak",
diff --git a/app/javascript/mastodon/locales/fa.json b/app/javascript/mastodon/locales/fa.json
index 2fdee7bca..37e213c01 100644
--- a/app/javascript/mastodon/locales/fa.json
+++ b/app/javascript/mastodon/locales/fa.json
@@ -20,7 +20,7 @@
   "account.blocked": "مسدود",
   "account.browse_more_on_origin_server": "مرور بیش‌تر روی نمایهٔ اصلی",
   "account.cancel_follow_request": "رد کردن درخواست پی‌گیری",
-  "account.direct": "Privately mention @{name}",
+  "account.direct": "خصوصی از @{name} نام ببرید",
   "account.disable_notifications": "آگاه کردن من هنگام فرسته‌های ‎@{name} را متوقّف کن",
   "account.domain_blocked": "دامنه مسدود شد",
   "account.edit_profile": "ویرایش نمایه",
@@ -102,7 +102,7 @@
   "column.blocks": "کاربران مسدود شده",
   "column.bookmarks": "نشانک‌ها",
   "column.community": "خط زمانی محلّی",
-  "column.direct": "Private mentions",
+  "column.direct": "خصوصی نام ببرید",
   "column.directory": "مرور نمایه‌ها",
   "column.domain_blocks": "دامنه‌های مسدود شده",
   "column.favourites": "پسندیده‌ها",
@@ -163,7 +163,7 @@
   "confirmations.domain_block.confirm": "مسدود کردن تمام دامنه",
   "confirmations.domain_block.message": "آیا جدی جدی می‌خواهید تمام دامنهٔ {domain} را مسدود کنید؟ در بیشتر موارد مسدود کردن یا خموشاندن چند حساب خاص کافی است و توصیه می‌شود. پس از این کار شما هیچ محتوایی را از این دامنه در خط زمانی عمومی یا آگاهی‌هایتان نخواهید دید. پی‌گیرانتان از این دامنه هم برداشته خواهند شد.",
   "confirmations.edit.confirm": "ویرایش",
-  "confirmations.edit.message": "Editing now will overwrite the message you are currently composing. Are you sure you want to proceed?",
+  "confirmations.edit.message": "در صورت ویرایش، پیامی که در حال نوشتنش بودید از بین خواهد رفت. می‌خواهید ادامه دهید؟",
   "confirmations.logout.confirm": "خروج از حساب",
   "confirmations.logout.message": "مطمئنید می‌خواهید خارج شوید؟",
   "confirmations.mute.confirm": "خموش",
@@ -216,14 +216,14 @@
   "empty_column.blocks": "هنوز کسی را مسدود نکرده‌اید.",
   "empty_column.bookmarked_statuses": "هنوز هیچ فرستهٔ نشانه‌گذاری شده‌ای ندارید. هنگامی که فرسته‌ای را نشانه‌گذاری کنید، این‌جا نشان داده خواهد شد.",
   "empty_column.community": "خط زمانی محلّی خالی است. چیزی بنویسید تا چرخش بچرخد!",
-  "empty_column.direct": "You don't have any private mentions yet. When you send or receive one, it will show up here.",
+  "empty_column.direct": "هنوز هیچ اشاره خصوصی‌ای ندارید. هنگامی که چنین پیامی بگیرید یا بفرستید این‌جا نشان داده خواهد شد.",
   "empty_column.domain_blocks": "هنوز هیچ دامنه‌ای مسدود نشده است.",
   "empty_column.explore_statuses": "الآن چیزی پرطرفدار نیست. بعداً دوباره بررسی کنید!",
   "empty_column.favourited_statuses": "شما هنوز هیچ فرسته‌ای را نپسندیده‌اید. هنگامی که فرسته‌ای را بپسندید، این‌جا نشان داده خواهد شد.",
   "empty_column.favourites": "هنوز هیچ کسی این فرسته را نپسندیده است. هنگامی که کسی آن را بپسندد، این‌جا نشان داده خواهد شد.",
   "empty_column.follow_recommendations": "به نظر نمی‌توان هیچ پیشنهادی برایتان ایجاد کرد. می‌توانید برای یافتن افرادی که ممکن است بشناسید از جست‌وجو یا کاوش برچسب‌های داغ استفاده کنید.",
   "empty_column.follow_requests": "شما هنوز هیچ درخواست پی‌گیری‌ای ندارید. هنگامی که چنین درخواستی بگیرید، این‌جا نشان داده خواهد شد.",
-  "empty_column.followed_tags": "You have not followed any hashtags yet. When you do, they will show up here.",
+  "empty_column.followed_tags": "شما هیچ برچسبی را پی‌نگرفتید. هنگامی که برچسبی را پی‌گیری کنید اینجا نمایان می‌شوند.",
   "empty_column.hashtag": "هنوز هیچ چیزی در این برچسب نیست.",
   "empty_column.home": "خط زمانی خانگیتان خالی است! برای پر کردنش، افراد بیشتری را پی بگیرید. {suggestions}",
   "empty_column.home.suggestions": "چند پیشنهاد را ببینید",
@@ -314,7 +314,7 @@
   "keyboard_shortcuts.column": "برای تمرکز روی یک فرسته در یکی از ستون‌ها",
   "keyboard_shortcuts.compose": "تمرکز روی محیط نوشتن",
   "keyboard_shortcuts.description": "توضیح",
-  "keyboard_shortcuts.direct": "to open direct messages column",
+  "keyboard_shortcuts.direct": "باز کردن ستون اشاره‌های خصوصی",
   "keyboard_shortcuts.down": "پایین بردن در سیاهه",
   "keyboard_shortcuts.enter": "گشودن فرسته",
   "keyboard_shortcuts.favourite": "پسندیدن فرسته",
@@ -376,7 +376,7 @@
   "navigation_bar.bookmarks": "نشانک‌ها",
   "navigation_bar.community_timeline": "خط زمانی محلّی",
   "navigation_bar.compose": "نوشتن فرستهٔ تازه",
-  "navigation_bar.direct": "Private mentions",
+  "navigation_bar.direct": "اشاره‌های خصوصی",
   "navigation_bar.discover": "گشت و گذار",
   "navigation_bar.domain_blocks": "دامنه‌های مسدود شده",
   "navigation_bar.edit_profile": "ویرایش نمایه",
@@ -522,17 +522,17 @@
   "report_notification.categories.spam": "هرزنامه",
   "report_notification.categories.violation": "تخطّی از قانون",
   "report_notification.open": "گشودن گزارش",
-  "search.no_recent_searches": "No recent searches",
+  "search.no_recent_searches": "جست‌وجوی اخیری نیست",
   "search.placeholder": "جست‌وجو",
-  "search.quick_action.account_search": "Profiles matching {x}",
-  "search.quick_action.go_to_account": "Go to profile {x}",
-  "search.quick_action.go_to_hashtag": "Go to hashtag {x}",
-  "search.quick_action.open_url": "Open URL in Mastodon",
-  "search.quick_action.status_search": "Posts matching {x}",
+  "search.quick_action.account_search": "نمایه‌های جور با {x}",
+  "search.quick_action.go_to_account": "برو به نمایه {x}",
+  "search.quick_action.go_to_hashtag": "برو به برچسب {x}",
+  "search.quick_action.open_url": "باز کردن پیوند در ماستودون",
+  "search.quick_action.status_search": "فرسته‌های جور با {x}",
   "search.search_or_paste": "جست‌وجو یا جایگذاری نشانی",
-  "search_popout.quick_actions": "Quick actions",
-  "search_popout.recent": "Recent searches",
-  "search_results.accounts": "Profiles",
+  "search_popout.quick_actions": "کنش‌های سریع",
+  "search_popout.recent": "جست‌وجوهای اخیر",
+  "search_results.accounts": "نمایه‌ها",
   "search_results.all": "همه",
   "search_results.hashtags": "برچسب‌ها",
   "search_results.nothing_found": "چیزی برای این عبارت جست‌وجو یافت نشد",
@@ -548,7 +548,7 @@
   "server_banner.server_stats": "آمار کارساز:",
   "sign_in_banner.create_account": "ایجاد حساب",
   "sign_in_banner.sign_in": "ورود",
-  "sign_in_banner.text": "Sign in to follow profiles or hashtags, favourite, share and reply to posts. You can also interact from your account on a different server.",
+  "sign_in_banner.text": "برای پی‌گیری نمایه‌ها یا برچسب‌ها، پسندیدن، هم‌رسانی و یا پاسخ به فرسته‌ها وارد شوید. همچنین می‌توانید این کارها را با حسابتان در کارسازی دیگر انجام دهید.",
   "status.admin_account": "گشودن واسط مدیریت برای ‎@{name}",
   "status.admin_domain": "گشودن واسط مدیریت برای ‎{domain}",
   "status.admin_status": "گشودن این فرسته در واسط مدیریت",
@@ -559,8 +559,8 @@
   "status.copy": "رونوشت از پیوند فرسته",
   "status.delete": "حذف",
   "status.detailed_status": "نمایش کامل گفتگو",
-  "status.direct": "Privately mention @{name}",
-  "status.direct_indicator": "Private mention",
+  "status.direct": "خصوصی به @{name} اشاره کنید",
+  "status.direct_indicator": "اشاره خصوصی",
   "status.edit": "ویرایش",
   "status.edited": "ویرایش شده در {date}",
   "status.edited_x_times": "{count, plural, one {{count} مرتبه} other {{count} مرتبه}} ویرایش شد",
diff --git a/app/javascript/mastodon/locales/fi.json b/app/javascript/mastodon/locales/fi.json
index eaed4906f..a086e0e21 100644
--- a/app/javascript/mastodon/locales/fi.json
+++ b/app/javascript/mastodon/locales/fi.json
@@ -153,14 +153,14 @@
   "confirmations.block.confirm": "Estä",
   "confirmations.block.message": "Haluatko varmasti estää käyttäjän {name}?",
   "confirmations.cancel_follow_request.confirm": "Peruuta pyyntö",
-  "confirmations.cancel_follow_request.message": "Haluatko varmasti peruuttaa pyyntösi seurata käyttäjää {name}?",
+  "confirmations.cancel_follow_request.message": "Haluatko varmasti peruuttaa pyyntösi seurata profiilia {name}?",
   "confirmations.delete.confirm": "Poista",
   "confirmations.delete.message": "Haluatko varmasti poistaa tämän viestin?",
   "confirmations.delete_list.confirm": "Poista",
   "confirmations.delete_list.message": "Haluatko varmasti poistaa tämän listan kokonaan?",
   "confirmations.discard_edit_media.confirm": "Hylkää",
   "confirmations.discard_edit_media.message": "Sinulla on tallentamattomia muutoksia median kuvaukseen tai esikatseluun, hylätäänkö ne silti?",
-  "confirmations.domain_block.confirm": "Estä koko palvelu",
+  "confirmations.domain_block.confirm": "Estä koko verkkotunnus",
   "confirmations.domain_block.message": "Haluatko aivan varmasti estää palvelun {domain} täysin? Useimmiten muutama kohdistettu esto tai mykistys on riittävä ja suositeltava toimenpide. Et näe kyseisen sisältöä kyseiseltä verkkoalueelta missään julkisissa aikajanoissa tai ilmoituksissa. Tälle verkkoalueelle kuuluvat seuraajasi poistetaan.",
   "confirmations.edit.confirm": "Muokkaa",
   "confirmations.edit.message": "Muokkaaminen nyt korvaa viestin, jota paraikaa työstät. Haluatko varmasti jatkaa?",
@@ -168,13 +168,13 @@
   "confirmations.logout.message": "Haluatko varmasti kirjautua ulos?",
   "confirmations.mute.confirm": "Mykistä",
   "confirmations.mute.explanation": "Tämä toiminto piilottaa heidän julkaisunsa sinulta – mukaan lukien ne, joissa heidät mainitaan – sallien heidän yhä nähdä julkaisusi ja seurata sinua.",
-  "confirmations.mute.message": "Haluatko varmasti mykistää käyttäjän {name}?",
+  "confirmations.mute.message": "Haluatko varmasti mykistää profiilin {name}?",
   "confirmations.redraft.confirm": "Poista & palauta muokattavaksi",
   "confirmations.redraft.message": "Oletko varma että haluat poistaa tämän julkaisun ja tehdä siitä uuden luonnoksen? Suosikit ja tehostukset menetään, alkuperäisen julkaisusi vastaukset jäävät orvoiksi.",
   "confirmations.reply.confirm": "Vastaa",
   "confirmations.reply.message": "Jos vastaat nyt, vastaus korvaa tällä hetkellä työstämäsi viestin. Oletko varma, että haluat jatkaa?",
   "confirmations.unfollow.confirm": "Lopeta seuraaminen",
-  "confirmations.unfollow.message": "Haluatko varmasti lakata seuraamasta käyttäjää {name}?",
+  "confirmations.unfollow.message": "Haluatko varmasti lakata seuraamasta profiilia {name}?",
   "conversation.delete": "Poista keskustelu",
   "conversation.mark_as_read": "Merkitse luetuksi",
   "conversation.open": "Näytä keskustelu",
@@ -522,16 +522,16 @@
   "report_notification.categories.spam": "Roskaposti",
   "report_notification.categories.violation": "Sääntöjen rikkominen",
   "report_notification.open": "Avaa ilmoitus",
-  "search.no_recent_searches": "No recent searches",
+  "search.no_recent_searches": "Edellisiä hakuja ei ole",
   "search.placeholder": "Hae",
-  "search.quick_action.account_search": "Profiles matching {x}",
-  "search.quick_action.go_to_account": "Go to profile {x}",
-  "search.quick_action.go_to_hashtag": "Go to hashtag {x}",
-  "search.quick_action.open_url": "Open URL in Mastodon",
-  "search.quick_action.status_search": "Posts matching {x}",
+  "search.quick_action.account_search": "Profiilit, jotka vastaavat \"{x}\"",
+  "search.quick_action.go_to_account": "Avaa profiili {x}",
+  "search.quick_action.go_to_hashtag": "Avaa aihetunniste {x}",
+  "search.quick_action.open_url": "Avaa URL-osoite Mastodonissa",
+  "search.quick_action.status_search": "Julkaisut, jotka vastaavat \"{x}\"",
   "search.search_or_paste": "Etsi tai kirjoita URL-osoite",
-  "search_popout.quick_actions": "Quick actions",
-  "search_popout.recent": "Recent searches",
+  "search_popout.quick_actions": "Pikatoiminnot",
+  "search_popout.recent": "Edelliset haut",
   "search_results.accounts": "Profiilit",
   "search_results.all": "Kaikki",
   "search_results.hashtags": "Aihetunnisteet",
diff --git a/app/javascript/mastodon/locales/fo.json b/app/javascript/mastodon/locales/fo.json
index 714d405f8..29a2f7bc2 100644
--- a/app/javascript/mastodon/locales/fo.json
+++ b/app/javascript/mastodon/locales/fo.json
@@ -522,16 +522,16 @@
   "report_notification.categories.spam": "Ruskpostur",
   "report_notification.categories.violation": "Brotin regla",
   "report_notification.open": "Opna melding",
-  "search.no_recent_searches": "No recent searches",
+  "search.no_recent_searches": "Ongar nýggjar leitingar",
   "search.placeholder": "Leita",
-  "search.quick_action.account_search": "Profiles matching {x}",
-  "search.quick_action.go_to_account": "Go to profile {x}",
-  "search.quick_action.go_to_hashtag": "Go to hashtag {x}",
-  "search.quick_action.open_url": "Open URL in Mastodon",
-  "search.quick_action.status_search": "Posts matching {x}",
+  "search.quick_action.account_search": "Vangar, ið samsvara {x}",
+  "search.quick_action.go_to_account": "Far til vanga {x}",
+  "search.quick_action.go_to_hashtag": "Far til frámerki {x}",
+  "search.quick_action.open_url": "Lat URL upp í Mastodon",
+  "search.quick_action.status_search": "Postar, ið samsvara {x}",
   "search.search_or_paste": "Leita ella set URL inn",
-  "search_popout.quick_actions": "Quick actions",
-  "search_popout.recent": "Recent searches",
+  "search_popout.quick_actions": "Skjótar atgerðir",
+  "search_popout.recent": "Nýggjar leitingar",
   "search_results.accounts": "Vangar",
   "search_results.all": "Alt",
   "search_results.hashtags": "Frámerki",
diff --git a/app/javascript/mastodon/locales/fy.json b/app/javascript/mastodon/locales/fy.json
index f0e5cf982..d4dfe35a2 100644
--- a/app/javascript/mastodon/locales/fy.json
+++ b/app/javascript/mastodon/locales/fy.json
@@ -522,16 +522,16 @@
   "report_notification.categories.spam": "Spam",
   "report_notification.categories.violation": "Skeinde regels",
   "report_notification.open": "Rapport iepenje",
-  "search.no_recent_searches": "No recent searches",
+  "search.no_recent_searches": "Gjin resinte sykopdrachten",
   "search.placeholder": "Sykje",
-  "search.quick_action.account_search": "Profiles matching {x}",
-  "search.quick_action.go_to_account": "Go to profile {x}",
-  "search.quick_action.go_to_hashtag": "Go to hashtag {x}",
-  "search.quick_action.open_url": "Open URL in Mastodon",
-  "search.quick_action.status_search": "Posts matching {x}",
+  "search.quick_action.account_search": "Accounts dy’t oerienkomme mei {x}",
+  "search.quick_action.go_to_account": "Gean nei account {x}",
+  "search.quick_action.go_to_hashtag": "Gean nei hashtag {x}",
+  "search.quick_action.open_url": "URL yn Mastodon iepenje",
+  "search.quick_action.status_search": "Berjochten dy’t oerienkomme mei {x}",
   "search.search_or_paste": "Sykje of fier URL yn",
-  "search_popout.quick_actions": "Quick actions",
-  "search_popout.recent": "Recent searches",
+  "search_popout.quick_actions": "Flugge aksjes",
+  "search_popout.recent": "Resinte sykopdrachten",
   "search_results.accounts": "Profilen",
   "search_results.all": "Alles",
   "search_results.hashtags": "Hashtags",
diff --git a/app/javascript/mastodon/locales/gl.json b/app/javascript/mastodon/locales/gl.json
index a2e6716c9..20279e71f 100644
--- a/app/javascript/mastodon/locales/gl.json
+++ b/app/javascript/mastodon/locales/gl.json
@@ -522,16 +522,16 @@
   "report_notification.categories.spam": "Spam",
   "report_notification.categories.violation": "Faltou ás regras",
   "report_notification.open": "Abrir a denuncia",
-  "search.no_recent_searches": "No recent searches",
+  "search.no_recent_searches": "Non hai buscas recentes",
   "search.placeholder": "Procurar",
-  "search.quick_action.account_search": "Profiles matching {x}",
-  "search.quick_action.go_to_account": "Go to profile {x}",
-  "search.quick_action.go_to_hashtag": "Go to hashtag {x}",
-  "search.quick_action.open_url": "Open URL in Mastodon",
-  "search.quick_action.status_search": "Posts matching {x}",
+  "search.quick_action.account_search": "Perfís coincidentes {x}",
+  "search.quick_action.go_to_account": "Ir ao perfil {x}",
+  "search.quick_action.go_to_hashtag": "Ir ao cancelo {x}",
+  "search.quick_action.open_url": "Abrir URL en Mastodon",
+  "search.quick_action.status_search": "Publicacións coincidentes {x}",
   "search.search_or_paste": "Busca ou insire URL",
-  "search_popout.quick_actions": "Quick actions",
-  "search_popout.recent": "Recent searches",
+  "search_popout.quick_actions": "Accións rápidas",
+  "search_popout.recent": "Buscas recentes",
   "search_results.accounts": "Perfís",
   "search_results.all": "Todo",
   "search_results.hashtags": "Cancelos",
diff --git a/app/javascript/mastodon/locales/he.json b/app/javascript/mastodon/locales/he.json
index 25fdb28dd..17b97ca74 100644
--- a/app/javascript/mastodon/locales/he.json
+++ b/app/javascript/mastodon/locales/he.json
@@ -522,16 +522,16 @@
   "report_notification.categories.spam": "ספאם (דואר זבל)",
   "report_notification.categories.violation": "הפרת כלל",
   "report_notification.open": "פתח דו\"ח",
-  "search.no_recent_searches": "No recent searches",
+  "search.no_recent_searches": "לא נמצאו חיפושים אחרונים",
   "search.placeholder": "חיפוש",
-  "search.quick_action.account_search": "Profiles matching {x}",
-  "search.quick_action.go_to_account": "Go to profile {x}",
-  "search.quick_action.go_to_hashtag": "Go to hashtag {x}",
-  "search.quick_action.open_url": "Open URL in Mastodon",
-  "search.quick_action.status_search": "Posts matching {x}",
+  "search.quick_action.account_search": "פרופילים המכילים {x}",
+  "search.quick_action.go_to_account": "לצפיה בפרופיל {x}",
+  "search.quick_action.go_to_hashtag": "לצפיה בתגית {x}",
+  "search.quick_action.open_url": "לפתיחת {x} במסטודון",
+  "search.quick_action.status_search": "הודעות המכילות {x}",
   "search.search_or_paste": "חפש או הזן קישור",
-  "search_popout.quick_actions": "Quick actions",
-  "search_popout.recent": "Recent searches",
+  "search_popout.quick_actions": "פעולות זריזות",
+  "search_popout.recent": "חיפושים אחרונים",
   "search_results.accounts": "פרופילים",
   "search_results.all": "כל התוצאות",
   "search_results.hashtags": "תגיות",
diff --git a/app/javascript/mastodon/locales/hi.json b/app/javascript/mastodon/locales/hi.json
index 2803c8417..186de8129 100644
--- a/app/javascript/mastodon/locales/hi.json
+++ b/app/javascript/mastodon/locales/hi.json
@@ -522,16 +522,16 @@
   "report_notification.categories.spam": "Spam",
   "report_notification.categories.violation": "Rule violation",
   "report_notification.open": "Open report",
-  "search.no_recent_searches": "No recent searches",
+  "search.no_recent_searches": "कोई हालिया खोज नहीं",
   "search.placeholder": "खोजें",
-  "search.quick_action.account_search": "Profiles matching {x}",
-  "search.quick_action.go_to_account": "Go to profile {x}",
-  "search.quick_action.go_to_hashtag": "Go to hashtag {x}",
-  "search.quick_action.open_url": "Open URL in Mastodon",
-  "search.quick_action.status_search": "Posts matching {x}",
+  "search.quick_action.account_search": "प्रोफ़ाइल मिले {x}",
+  "search.quick_action.go_to_account": "प्रोफ़ाइल पर जाएँ {x}",
+  "search.quick_action.go_to_hashtag": "हैशटैग पर जाएं {x}",
+  "search.quick_action.open_url": "URL मॅस्टोडॉन में खोलें",
+  "search.quick_action.status_search": "पोस्ट मिलें {x}",
   "search.search_or_paste": "Search or paste URL",
-  "search_popout.quick_actions": "Quick actions",
-  "search_popout.recent": "Recent searches",
+  "search_popout.quick_actions": "त्वरित क्रियाएं",
+  "search_popout.recent": "हालिया खोजें",
   "search_results.accounts": "प्रोफ़ाइल",
   "search_results.all": "All",
   "search_results.hashtags": "Hashtags",
diff --git a/app/javascript/mastodon/locales/hu.json b/app/javascript/mastodon/locales/hu.json
index 6b16f47b3..4cd7ebde7 100644
--- a/app/javascript/mastodon/locales/hu.json
+++ b/app/javascript/mastodon/locales/hu.json
@@ -522,16 +522,16 @@
   "report_notification.categories.spam": "Kéretlen üzenet",
   "report_notification.categories.violation": "Szabálysértés",
   "report_notification.open": "Bejelentés megnyitása",
-  "search.no_recent_searches": "No recent searches",
+  "search.no_recent_searches": "Nincsenek keresési előzmények",
   "search.placeholder": "Keresés",
-  "search.quick_action.account_search": "Profiles matching {x}",
-  "search.quick_action.go_to_account": "Go to profile {x}",
-  "search.quick_action.go_to_hashtag": "Go to hashtag {x}",
-  "search.quick_action.open_url": "Open URL in Mastodon",
-  "search.quick_action.status_search": "Posts matching {x}",
+  "search.quick_action.account_search": "Profilok a következő keresésre: {x}",
+  "search.quick_action.go_to_account": "Ugrás a következő profilhoz: {x}",
+  "search.quick_action.go_to_hashtag": "Ugrás a következő hashtaghez: {x}",
+  "search.quick_action.open_url": "Webcím megnyitása a Mastodonon",
+  "search.quick_action.status_search": "Bejegyzések a következő keresésre: {x}",
   "search.search_or_paste": "Keresés vagy webcím beillesztése",
-  "search_popout.quick_actions": "Quick actions",
-  "search_popout.recent": "Recent searches",
+  "search_popout.quick_actions": "Gyors műveletek",
+  "search_popout.recent": "Legutóbbi keresések",
   "search_results.accounts": "Profilok",
   "search_results.all": "Összes",
   "search_results.hashtags": "#Címkék",
diff --git a/app/javascript/mastodon/locales/is.json b/app/javascript/mastodon/locales/is.json
index 5127978b0..b9d650473 100644
--- a/app/javascript/mastodon/locales/is.json
+++ b/app/javascript/mastodon/locales/is.json
@@ -522,16 +522,16 @@
   "report_notification.categories.spam": "Ruslpóstur",
   "report_notification.categories.violation": "Brot á reglum",
   "report_notification.open": "Opin kæra",
-  "search.no_recent_searches": "No recent searches",
+  "search.no_recent_searches": "Engar nýlegar leitir",
   "search.placeholder": "Leita",
-  "search.quick_action.account_search": "Profiles matching {x}",
-  "search.quick_action.go_to_account": "Go to profile {x}",
-  "search.quick_action.go_to_hashtag": "Go to hashtag {x}",
-  "search.quick_action.open_url": "Open URL in Mastodon",
-  "search.quick_action.status_search": "Posts matching {x}",
+  "search.quick_action.account_search": "Notandasnið sem samsvara {x}",
+  "search.quick_action.go_to_account": "Fara á notandasnið {x}",
+  "search.quick_action.go_to_hashtag": "Fara á myllumerkið {x}",
+  "search.quick_action.open_url": "Opna slóð í Mastodon",
+  "search.quick_action.status_search": "Færslur sem samsvara {x}",
   "search.search_or_paste": "Leita eða líma slóð",
-  "search_popout.quick_actions": "Quick actions",
-  "search_popout.recent": "Recent searches",
+  "search_popout.quick_actions": "Flýtiaðgerðir",
+  "search_popout.recent": "Nýlegar leitir",
   "search_results.accounts": "Notendasnið",
   "search_results.all": "Allt",
   "search_results.hashtags": "Myllumerki",
diff --git a/app/javascript/mastodon/locales/it.json b/app/javascript/mastodon/locales/it.json
index 7ac0dfacd..ab1cc02af 100644
--- a/app/javascript/mastodon/locales/it.json
+++ b/app/javascript/mastodon/locales/it.json
@@ -522,16 +522,16 @@
   "report_notification.categories.spam": "Spam",
   "report_notification.categories.violation": "Violazione delle regole",
   "report_notification.open": "Apri segnalazione",
-  "search.no_recent_searches": "No recent searches",
+  "search.no_recent_searches": "Nessuna ricerca recente",
   "search.placeholder": "Cerca",
-  "search.quick_action.account_search": "Profiles matching {x}",
-  "search.quick_action.go_to_account": "Go to profile {x}",
-  "search.quick_action.go_to_hashtag": "Go to hashtag {x}",
-  "search.quick_action.open_url": "Open URL in Mastodon",
-  "search.quick_action.status_search": "Posts matching {x}",
+  "search.quick_action.account_search": "Profili corrispondenti a {x}",
+  "search.quick_action.go_to_account": "Vai al profilo {x}",
+  "search.quick_action.go_to_hashtag": "Vai all'hashtag {x}",
+  "search.quick_action.open_url": "Apri URL in Mastodon",
+  "search.quick_action.status_search": "Post corrispondenti a {x}",
   "search.search_or_paste": "Cerca o incolla URL",
-  "search_popout.quick_actions": "Quick actions",
-  "search_popout.recent": "Recent searches",
+  "search_popout.quick_actions": "Azioni rapide",
+  "search_popout.recent": "Ricerche recenti",
   "search_results.accounts": "Profili",
   "search_results.all": "Tutto",
   "search_results.hashtags": "Hashtag",
diff --git a/app/javascript/mastodon/locales/ja.json b/app/javascript/mastodon/locales/ja.json
index d1fb586f3..dee4baea9 100644
--- a/app/javascript/mastodon/locales/ja.json
+++ b/app/javascript/mastodon/locales/ja.json
@@ -526,16 +526,16 @@
   "report_notification.categories.spam": "スパム",
   "report_notification.categories.violation": "ルール違反",
   "report_notification.open": "通報を開く",
-  "search.no_recent_searches": "No recent searches",
+  "search.no_recent_searches": "検索履歴はありません",
   "search.placeholder": "検索",
-  "search.quick_action.account_search": "Profiles matching {x}",
-  "search.quick_action.go_to_account": "Go to profile {x}",
-  "search.quick_action.go_to_hashtag": "Go to hashtag {x}",
-  "search.quick_action.open_url": "Open URL in Mastodon",
-  "search.quick_action.status_search": "Posts matching {x}",
+  "search.quick_action.account_search": "{x} に該当するプロフィール",
+  "search.quick_action.go_to_account": "{x} のプロフィールを見る",
+  "search.quick_action.go_to_hashtag": "{x} に該当するハッシュタグ",
+  "search.quick_action.open_url": "MastodonでURLを開く",
+  "search.quick_action.status_search": "{x} に該当する投稿",
   "search.search_or_paste": "検索またはURLを入力",
-  "search_popout.quick_actions": "Quick actions",
-  "search_popout.recent": "Recent searches",
+  "search_popout.quick_actions": "クイック操作",
+  "search_popout.recent": "最近の検索",
   "search_results.accounts": "ユーザー",
   "search_results.all": "すべて",
   "search_results.hashtags": "ハッシュタグ",
diff --git a/app/javascript/mastodon/locales/ko.json b/app/javascript/mastodon/locales/ko.json
index b08e0b45c..7d7659569 100644
--- a/app/javascript/mastodon/locales/ko.json
+++ b/app/javascript/mastodon/locales/ko.json
@@ -522,16 +522,16 @@
   "report_notification.categories.spam": "스팸",
   "report_notification.categories.violation": "규칙 위반",
   "report_notification.open": "신고 열기",
-  "search.no_recent_searches": "No recent searches",
+  "search.no_recent_searches": "최근 검색 기록이 없습니다",
   "search.placeholder": "검색",
-  "search.quick_action.account_search": "Profiles matching {x}",
-  "search.quick_action.go_to_account": "Go to profile {x}",
-  "search.quick_action.go_to_hashtag": "Go to hashtag {x}",
-  "search.quick_action.open_url": "Open URL in Mastodon",
-  "search.quick_action.status_search": "Posts matching {x}",
+  "search.quick_action.account_search": "{x}에 맞는 프로필",
+  "search.quick_action.go_to_account": "{x} 프로필로 이동",
+  "search.quick_action.go_to_hashtag": "{x} 해시태그로 이동",
+  "search.quick_action.open_url": "마스토돈에서 URL 열기",
+  "search.quick_action.status_search": "{x}에 맞는 게시물",
   "search.search_or_paste": "검색하거나 URL 붙여넣기",
-  "search_popout.quick_actions": "Quick actions",
-  "search_popout.recent": "Recent searches",
+  "search_popout.quick_actions": "빠른 작업",
+  "search_popout.recent": "최근 검색",
   "search_results.accounts": "프로필",
   "search_results.all": "전부",
   "search_results.hashtags": "해시태그",
diff --git a/app/javascript/mastodon/locales/lv.json b/app/javascript/mastodon/locales/lv.json
index c3d82bd16..4f1032ae2 100644
--- a/app/javascript/mastodon/locales/lv.json
+++ b/app/javascript/mastodon/locales/lv.json
@@ -522,16 +522,16 @@
   "report_notification.categories.spam": "Spams",
   "report_notification.categories.violation": "Noteikumu pārkāpums",
   "report_notification.open": "Atvērt sūdzību",
-  "search.no_recent_searches": "No recent searches",
+  "search.no_recent_searches": "Nav nesen veiktu meklējumu",
   "search.placeholder": "Meklēšana",
-  "search.quick_action.account_search": "Profiles matching {x}",
-  "search.quick_action.go_to_account": "Go to profile {x}",
-  "search.quick_action.go_to_hashtag": "Go to hashtag {x}",
-  "search.quick_action.open_url": "Open URL in Mastodon",
-  "search.quick_action.status_search": "Posts matching {x}",
+  "search.quick_action.account_search": "Profili atbilst {x}",
+  "search.quick_action.go_to_account": "Doties uz profilu {x}",
+  "search.quick_action.go_to_hashtag": "Doties uz tēmturi {x}",
+  "search.quick_action.open_url": "Atvērt URL Mastodonā",
+  "search.quick_action.status_search": "Ziņas atbilst {x}",
   "search.search_or_paste": "Meklē vai iekopē URL",
-  "search_popout.quick_actions": "Quick actions",
-  "search_popout.recent": "Recent searches",
+  "search_popout.quick_actions": "Ātrās darbības",
+  "search_popout.recent": "Nesen meklētais",
   "search_results.accounts": "Profili",
   "search_results.all": "Visi",
   "search_results.hashtags": "Tēmturi",
diff --git a/app/javascript/mastodon/locales/my.json b/app/javascript/mastodon/locales/my.json
index 838e18da1..197addd1b 100644
--- a/app/javascript/mastodon/locales/my.json
+++ b/app/javascript/mastodon/locales/my.json
@@ -20,7 +20,7 @@
   "account.blocked": "ဘလော့ထားသည်",
   "account.browse_more_on_origin_server": "မူရင်းပရိုဖိုင်တွင် ပိုမိုကြည့်ရှုပါ။",
   "account.cancel_follow_request": "ဖောလိုးပယ်ဖျက်ခြင်း",
-  "account.direct": "Privately mention @{name}",
+  "account.direct": "@{name} သာသိရှိနိုင်အောင်မန်းရှင်းခေါ်မည်",
   "account.disable_notifications": "@{name} ပို့စ်တင်သည့်အခါ ကျွန်ုပ်ကို အသိပေးခြင်းရပ်ပါ။",
   "account.domain_blocked": "ဒိုမိန်း ပိတ်ပင်ထားခဲ့သည်\n",
   "account.edit_profile": "ကိုယ်ရေးမှတ်တမ်းပြင်ဆင်မည်",
@@ -102,7 +102,7 @@
   "column.blocks": "ဘလော့ထားသောအကောင့်များ",
   "column.bookmarks": "မှတ်တမ်းများ",
   "column.community": "ဒေသတွင်း အချိန်ဇယား",
-  "column.direct": "Private mentions",
+  "column.direct": "သီးသန့်ဖော်ပြခြင်း",
   "column.directory": "ပရိုဖိုင်များကို ရှာဖွေမည်\n",
   "column.domain_blocks": "  ဒိုမိန်းကိုပိတ်မည်",
   "column.favourites": "အကြိုက်ဆုံးများ",
@@ -216,7 +216,7 @@
   "empty_column.blocks": "ပိတ်ထားသောအကောင့်များမရှိသေးပါ",
   "empty_column.bookmarked_statuses": "သင့်တွင် မှတ်သားထားသော ပို့စ်များ မရှိသေးပါ။ တစ်ခုကို အမှတ်အသားပြုလိုက်ပါက ၎င်းကို ဤနေရာတွင် ပြထားပါမည်။",
   "empty_column.community": "ဒေသတွင်းစာမျက်နှာမှာ အလွတ်ဖြစ်နေသည်။ အများမြင်နိုင်ရန်အတွက် တစ်ခုခုရေးပါ။",
-  "empty_column.direct": "You don't have any private mentions yet. When you send or receive one, it will show up here.",
+  "empty_column.direct": "သင့်တွင် သီးသန့်ဖော်ပြချက်များ မရှိသေးပါ။ ပေးပို့ခြင်း သို့မဟုတ် လက်ခံသောအခါ၊ ၎င်းသည် ဤနေရာတွင် ပေါ်လာလိမ့်မည်။",
   "empty_column.domain_blocks": "သင်ပိတ်ထားသော ဒိုမိန်းမရှိသေးပါ",
   "empty_column.explore_statuses": "အခုလောလောဆယ်တွင် ရေပန်းစားနေသောပို့စ်များ မရှိသေးပါ။ နောက်မှ ပြန်စစ်ဆေးပါရန်။",
   "empty_column.favourited_statuses": "သင့်တွင် အကြိုက်ဆုံးပို့စ်များ မရှိသေးပါ။ တစ်ခုကို သင်နှစ်သက်ထားပါက ၎င်းကို ဤနေရာတွင် ပြထားပါမည်။",
@@ -314,7 +314,7 @@
   "keyboard_shortcuts.column": "to focus a status in one of the columns",
   "keyboard_shortcuts.compose": "to focus the compose textarea",
   "keyboard_shortcuts.description": "ဖော်ပြချက်",
-  "keyboard_shortcuts.direct": "to open direct messages column",
+  "keyboard_shortcuts.direct": "သီးသန့်ဖော်ပြချက်များကော်လံကိုဖွင့်ရန်",
   "keyboard_shortcuts.down": "to move down in the list",
   "keyboard_shortcuts.enter": "to open status",
   "keyboard_shortcuts.favourite": "to favourite",
@@ -376,7 +376,7 @@
   "navigation_bar.bookmarks": "မှတ်ထားသည်များ",
   "navigation_bar.community_timeline": "ဒေသစံတော်ချိန်",
   "navigation_bar.compose": "ပို့စ်အသစ်ရေးပါ",
-  "navigation_bar.direct": "Private mentions",
+  "navigation_bar.direct": "သီးသန့်ဖော်ပြချက်များ",
   "navigation_bar.discover": "ရှာဖွေပါ",
   "navigation_bar.domain_blocks": "Hidden domains",
   "navigation_bar.edit_profile": "ကိုယ်ရေးမှတ်တမ်းပြင်ဆင်မည်",
@@ -522,17 +522,17 @@
   "report_notification.categories.spam": "Spam",
   "report_notification.categories.violation": "စည်းကမ်းဖောက်ဖျက်ခြင်း",
   "report_notification.open": "အစီရင်ခံစာကိုဖွင့်ပါ",
-  "search.no_recent_searches": "No recent searches",
+  "search.no_recent_searches": "လတ်တလောရှာဖွေမှုများမရှိပါ။",
   "search.placeholder": "ရှာဖွေရန်",
-  "search.quick_action.account_search": "Profiles matching {x}",
-  "search.quick_action.go_to_account": "Go to profile {x}",
-  "search.quick_action.go_to_hashtag": "Go to hashtag {x}",
-  "search.quick_action.open_url": "Open URL in Mastodon",
-  "search.quick_action.status_search": "Posts matching {x}",
+  "search.quick_action.account_search": "{x} နှင့် ကိုက်ညီသော ပရိုဖိုင်များ",
+  "search.quick_action.go_to_account": "ပရိုဖိုင် {x} သို့သွားမည်",
+  "search.quick_action.go_to_hashtag": "hashtag {x} သို့သွားမည်",
+  "search.quick_action.open_url": "Mastodon တွင် URL ကိုဖွင့်မည်",
+  "search.quick_action.status_search": "{x} နှင့် ကိုက်ညီသော ပို့စ်များ",
   "search.search_or_paste": "URL ရိုက်ထည့်ပါ သို့မဟုတ် ရှာဖွေပါ",
-  "search_popout.quick_actions": "Quick actions",
-  "search_popout.recent": "Recent searches",
-  "search_results.accounts": "Profiles",
+  "search_popout.quick_actions": "အမြန်လုပ်ဆောင်မှုများ",
+  "search_popout.recent": "လတ်တလော ရှာဖွေမှုများ",
+  "search_results.accounts": "စာမျက်နှာ",
   "search_results.all": "အားလုံး",
   "search_results.hashtags": "ဟက်ရှ်တက်များ",
   "search_results.nothing_found": "ရှာဖွေလိုသောအရာမရှိပါ",
@@ -559,8 +559,8 @@
   "status.copy": "Copy link to status",
   "status.delete": "ဖျက်ရန်",
   "status.detailed_status": "အသေးစိတ်စကားပြောဆိုမှုမြင်ကွင်း",
-  "status.direct": "Privately mention @{name}",
-  "status.direct_indicator": "Private mention",
+  "status.direct": "@{name} ကို သီးသန့်ဖော်ပြမည်\n",
+  "status.direct_indicator": "သီးသန့်ဖော်ပြခြင်း။",
   "status.edit": "ပြင်ဆင်ရန်",
   "status.edited": "{date} ကို ပြင်ဆင်ပြီးပါပြီ",
   "status.edited_x_times": "{count, plural, one {{count} time} other {{count} times}} ပြင်ဆင်ခဲ့သည်",
@@ -646,7 +646,7 @@
   "upload_modal.description_placeholder": "သီဟိုဠ်မှ ဉာဏ်ကြီးရှင်သည် အာယုဝဍ္ဎနဆေးညွှန်းစာကို ဇလွန်ဈေးဘေး ဗာဒံပင်ထက် အဓိဋ္ဌာန်လျက် ဂဃနဏဖတ်ခဲ့သည်",
   "upload_modal.detect_text": "ပုံမှစာသားကို ရှာဖွေပါ",
   "upload_modal.edit_media": "မီဒီယာကို ပြင်ဆင်ရန်",
-  "upload_modal.hint": "Click or drag the circle on the preview to choose the focal point which will always be in view on all thumbnails.",
+  "upload_modal.hint": "ပုံသေးအားလုံးတွင် အမြဲတမ်းကြည့်ရှုနိုင်သည့် focal point ကို ရွေးချယ်ရန် Preview ပေါ်ရှိ စက်ဝိုင်းကို နှိပ်ပါ သို့မဟုတ် ဖိဆွဲပါ။",
   "upload_modal.preparing_ocr": "OCR ပြင်ဆင်နေသည်…",
   "upload_modal.preview_label": "({ratio}) အစမ်းကြည့်ရှုရန်",
   "upload_progress.label": "တင်နေသည်...",
diff --git a/app/javascript/mastodon/locales/nl.json b/app/javascript/mastodon/locales/nl.json
index 6e080da9b..bb33a6f0c 100644
--- a/app/javascript/mastodon/locales/nl.json
+++ b/app/javascript/mastodon/locales/nl.json
@@ -55,7 +55,7 @@
   "account.report": "@{name} rapporteren",
   "account.requested": "Wachten op goedkeuring. Klik om het volgverzoek te annuleren",
   "account.requested_follow": "{name} wil je graag volgen",
-  "account.share": "Profiel van @{name} delen",
+  "account.share": "Account van @{name} delen",
   "account.show_reblogs": "Boosts van @{name} tonen",
   "account.statuses_counter": "{count, plural, one {{counter} bericht} other {{counter} berichten}}",
   "account.unblock": "@{name} deblokkeren",
@@ -487,7 +487,7 @@
   "report.categories.violation": "De inhoud overtreedt een of meerdere serverregels",
   "report.category.subtitle": "Kies wat het beste overeenkomt",
   "report.category.title": "Vertel ons wat er met dit {type} aan de hand is",
-  "report.category.title_account": "profiel",
+  "report.category.title_account": "account",
   "report.category.title_status": "bericht",
   "report.close": "Klaar",
   "report.comment.title": "Zijn er nog andere dingen waarvan je denkt dat wij dat moeten weten?",
@@ -522,17 +522,17 @@
   "report_notification.categories.spam": "Spam",
   "report_notification.categories.violation": "Overtreden regel(s)",
   "report_notification.open": "Rapportage openen",
-  "search.no_recent_searches": "No recent searches",
+  "search.no_recent_searches": "Geen recente zoekopdrachten",
   "search.placeholder": "Zoeken",
-  "search.quick_action.account_search": "Profiles matching {x}",
-  "search.quick_action.go_to_account": "Go to profile {x}",
-  "search.quick_action.go_to_hashtag": "Go to hashtag {x}",
-  "search.quick_action.open_url": "Open URL in Mastodon",
-  "search.quick_action.status_search": "Posts matching {x}",
+  "search.quick_action.account_search": "Accounts die overeenkomen met {x}",
+  "search.quick_action.go_to_account": "Ga naar account {x}",
+  "search.quick_action.go_to_hashtag": "Ga naar hashtag {x}",
+  "search.quick_action.open_url": "URL in Mastodon openen",
+  "search.quick_action.status_search": "Berichten die overeenkomen met {x}",
   "search.search_or_paste": "Zoek of voer een URL in",
-  "search_popout.quick_actions": "Quick actions",
-  "search_popout.recent": "Recent searches",
-  "search_results.accounts": "Profielen",
+  "search_popout.quick_actions": "Snelle acties",
+  "search_popout.recent": "Recente zoekopdrachten",
+  "search_results.accounts": "Accounts",
   "search_results.all": "Alles",
   "search_results.hashtags": "Hashtags",
   "search_results.nothing_found": "Deze zoektermen leveren geen resultaat op",
diff --git a/app/javascript/mastodon/locales/pl.json b/app/javascript/mastodon/locales/pl.json
index e26c592ed..4df5d8431 100644
--- a/app/javascript/mastodon/locales/pl.json
+++ b/app/javascript/mastodon/locales/pl.json
@@ -527,16 +527,16 @@
   "report_notification.categories.spam": "Spam",
   "report_notification.categories.violation": "Naruszenie zasad",
   "report_notification.open": "Otwórz raport",
-  "search.no_recent_searches": "No recent searches",
+  "search.no_recent_searches": "Brak ostatnich wyszukiwań",
   "search.placeholder": "Szukaj",
-  "search.quick_action.account_search": "Profiles matching {x}",
-  "search.quick_action.go_to_account": "Go to profile {x}",
-  "search.quick_action.go_to_hashtag": "Go to hashtag {x}",
-  "search.quick_action.open_url": "Open URL in Mastodon",
-  "search.quick_action.status_search": "Posts matching {x}",
+  "search.quick_action.account_search": "Profile pasujące do {x}",
+  "search.quick_action.go_to_account": "Przejdź do profilu {x}",
+  "search.quick_action.go_to_hashtag": "Przejdź do hasztaga {x}",
+  "search.quick_action.open_url": "Otwórz adres URL w Mastodonie",
+  "search.quick_action.status_search": "Wpisy pasujące do {x}",
   "search.search_or_paste": "Wyszukaj lub wklej adres",
-  "search_popout.quick_actions": "Quick actions",
-  "search_popout.recent": "Recent searches",
+  "search_popout.quick_actions": "Szybkie akcje",
+  "search_popout.recent": "Ostatnie wyszukiwania",
   "search_results.accounts": "Profile",
   "search_results.all": "Wszystkie",
   "search_results.hashtags": "Hasztagi",
diff --git a/app/javascript/mastodon/locales/pt-BR.json b/app/javascript/mastodon/locales/pt-BR.json
index 1c8bf8b04..d10c9a8f7 100644
--- a/app/javascript/mastodon/locales/pt-BR.json
+++ b/app/javascript/mastodon/locales/pt-BR.json
@@ -522,16 +522,16 @@
   "report_notification.categories.spam": "Spam",
   "report_notification.categories.violation": "Violação de regra",
   "report_notification.open": "Abrir denúncia",
-  "search.no_recent_searches": "No recent searches",
+  "search.no_recent_searches": "Nenhuma busca recente",
   "search.placeholder": "Pesquisar",
-  "search.quick_action.account_search": "Profiles matching {x}",
-  "search.quick_action.go_to_account": "Go to profile {x}",
-  "search.quick_action.go_to_hashtag": "Go to hashtag {x}",
-  "search.quick_action.open_url": "Open URL in Mastodon",
-  "search.quick_action.status_search": "Posts matching {x}",
+  "search.quick_action.account_search": "Perfis correspondentes a {x}",
+  "search.quick_action.go_to_account": "Ir para a página do perfil {x}",
+  "search.quick_action.go_to_hashtag": "Ir para a hashtag {x}",
+  "search.quick_action.open_url": "Abrir link no Mastodon",
+  "search.quick_action.status_search": "Publicações correspondentes a {x}",
   "search.search_or_paste": "Buscar ou colar URL",
-  "search_popout.quick_actions": "Quick actions",
-  "search_popout.recent": "Recent searches",
+  "search_popout.quick_actions": "Ações rápidas",
+  "search_popout.recent": "Buscas Recentes",
   "search_results.accounts": "Perfis",
   "search_results.all": "Tudo",
   "search_results.hashtags": "Hashtags",
diff --git a/app/javascript/mastodon/locales/pt-PT.json b/app/javascript/mastodon/locales/pt-PT.json
index 496551a87..e93ff73cf 100644
--- a/app/javascript/mastodon/locales/pt-PT.json
+++ b/app/javascript/mastodon/locales/pt-PT.json
@@ -522,16 +522,16 @@
   "report_notification.categories.spam": "Spam",
   "report_notification.categories.violation": "Violação de regra",
   "report_notification.open": "Abrir denúncia",
-  "search.no_recent_searches": "No recent searches",
+  "search.no_recent_searches": "Nenhuma pesquisa recente",
   "search.placeholder": "Pesquisar",
-  "search.quick_action.account_search": "Profiles matching {x}",
-  "search.quick_action.go_to_account": "Go to profile {x}",
-  "search.quick_action.go_to_hashtag": "Go to hashtag {x}",
-  "search.quick_action.open_url": "Open URL in Mastodon",
-  "search.quick_action.status_search": "Posts matching {x}",
+  "search.quick_action.account_search": "Perfis com correspondência a {x}",
+  "search.quick_action.go_to_account": "Ir para o perfil {x}",
+  "search.quick_action.go_to_hashtag": "Ir para a hashtag {x}",
+  "search.quick_action.open_url": "Abrir ligação no Mastodon",
+  "search.quick_action.status_search": "Publicações com correspondência a {x}",
   "search.search_or_paste": "Pesquisar ou introduzir URL",
-  "search_popout.quick_actions": "Quick actions",
-  "search_popout.recent": "Recent searches",
+  "search_popout.quick_actions": "Ações rápidas",
+  "search_popout.recent": "Pesquisas recentes",
   "search_results.accounts": "Perfis",
   "search_results.all": "Tudo",
   "search_results.hashtags": "Etiquetas",
diff --git a/app/javascript/mastodon/locales/sq.json b/app/javascript/mastodon/locales/sq.json
index c0064eb7e..93a00e51e 100644
--- a/app/javascript/mastodon/locales/sq.json
+++ b/app/javascript/mastodon/locales/sq.json
@@ -522,16 +522,16 @@
   "report_notification.categories.spam": "I padëshiruar",
   "report_notification.categories.violation": "Cenim rregullash",
   "report_notification.open": "Hape raportimin",
-  "search.no_recent_searches": "No recent searches",
+  "search.no_recent_searches": "Pa kërkime së fundi",
   "search.placeholder": "Kërkoni",
-  "search.quick_action.account_search": "Profiles matching {x}",
-  "search.quick_action.go_to_account": "Go to profile {x}",
-  "search.quick_action.go_to_hashtag": "Go to hashtag {x}",
-  "search.quick_action.open_url": "Open URL in Mastodon",
-  "search.quick_action.status_search": "Posts matching {x}",
+  "search.quick_action.account_search": "Profile me përputhje me {x}",
+  "search.quick_action.go_to_account": "Kalo te profili {x}",
+  "search.quick_action.go_to_hashtag": "Kalo te hashtag-u {x}",
+  "search.quick_action.open_url": "Hape URL-në në Mastodon",
+  "search.quick_action.status_search": "Postime me përputhje me {x}",
   "search.search_or_paste": "Kërkoni, ose hidhni një URL",
-  "search_popout.quick_actions": "Quick actions",
-  "search_popout.recent": "Recent searches",
+  "search_popout.quick_actions": "Veprime të shpejta",
+  "search_popout.recent": "Kërkime së fundi",
   "search_results.accounts": "Profile",
   "search_results.all": "Krejt",
   "search_results.hashtags": "Hashtag-ë",
diff --git a/app/javascript/mastodon/locales/th.json b/app/javascript/mastodon/locales/th.json
index c460b5e1b..cd4c92351 100644
--- a/app/javascript/mastodon/locales/th.json
+++ b/app/javascript/mastodon/locales/th.json
@@ -522,17 +522,17 @@
   "report_notification.categories.spam": "สแปม",
   "report_notification.categories.violation": "การละเมิดกฎ",
   "report_notification.open": "รายงานที่เปิด",
-  "search.no_recent_searches": "No recent searches",
+  "search.no_recent_searches": "ไม่มีการค้นหาล่าสุด",
   "search.placeholder": "ค้นหา",
-  "search.quick_action.account_search": "Profiles matching {x}",
-  "search.quick_action.go_to_account": "Go to profile {x}",
-  "search.quick_action.go_to_hashtag": "Go to hashtag {x}",
-  "search.quick_action.open_url": "Open URL in Mastodon",
-  "search.quick_action.status_search": "Posts matching {x}",
+  "search.quick_action.account_search": "โปรไฟล์ที่ตรงกับ {x}",
+  "search.quick_action.go_to_account": "ไปยังโปรไฟล์ {x}",
+  "search.quick_action.go_to_hashtag": "ไปยังแฮชแท็ก {x}",
+  "search.quick_action.open_url": "เปิด URL ใน Mastodon",
+  "search.quick_action.status_search": "โพสต์ที่ตรงกับ {x}",
   "search.search_or_paste": "ค้นหาหรือวาง URL",
-  "search_popout.quick_actions": "Quick actions",
-  "search_popout.recent": "Recent searches",
-  "search_results.accounts": "Profiles",
+  "search_popout.quick_actions": "การกระทำด่วน",
+  "search_popout.recent": "การค้นหาล่าสุด",
+  "search_results.accounts": "โปรไฟล์",
   "search_results.all": "ทั้งหมด",
   "search_results.hashtags": "แฮชแท็ก",
   "search_results.nothing_found": "ไม่พบสิ่งใดสำหรับคำค้นหาเหล่านี้",
diff --git a/app/javascript/mastodon/locales/tr.json b/app/javascript/mastodon/locales/tr.json
index b3cbed024..a7b8cd916 100644
--- a/app/javascript/mastodon/locales/tr.json
+++ b/app/javascript/mastodon/locales/tr.json
@@ -72,8 +72,8 @@
   "admin.dashboard.retention.average": "Ortalama",
   "admin.dashboard.retention.cohort": "Kayıt ayı",
   "admin.dashboard.retention.cohort_size": "Yeni kullanıcılar",
-  "alert.rate_limited.message": "Lütfen {retry_time, time, medium} süresinden sonra tekrar deneyin.",
-  "alert.rate_limited.title": "Oran sınırlıdır",
+  "alert.rate_limited.message": "Lütfen {retry_time, time, medium} saatinden sonra tekrar deneyin.",
+  "alert.rate_limited.title": "Aşırı istek gönderildi",
   "alert.unexpected.message": "Beklenmedik bir hata oluştu.",
   "alert.unexpected.title": "Hay aksi!",
   "announcement.announcement": "Duyuru",
@@ -522,16 +522,16 @@
   "report_notification.categories.spam": "İstenmeyen",
   "report_notification.categories.violation": "Kural ihlali",
   "report_notification.open": "Bildirim aç",
-  "search.no_recent_searches": "No recent searches",
+  "search.no_recent_searches": "Son arama yok",
   "search.placeholder": "Ara",
-  "search.quick_action.account_search": "Profiles matching {x}",
-  "search.quick_action.go_to_account": "Go to profile {x}",
-  "search.quick_action.go_to_hashtag": "Go to hashtag {x}",
-  "search.quick_action.open_url": "Open URL in Mastodon",
-  "search.quick_action.status_search": "Posts matching {x}",
+  "search.quick_action.account_search": "Eşleşen profiller {x}",
+  "search.quick_action.go_to_account": "Profile git {x}",
+  "search.quick_action.go_to_hashtag": "Etikete git {x}",
+  "search.quick_action.open_url": "URL'yi Mastodon'da Aç",
+  "search.quick_action.status_search": "Eşleşen gönderiler {x}",
   "search.search_or_paste": "Ara veya URL gir",
-  "search_popout.quick_actions": "Quick actions",
-  "search_popout.recent": "Recent searches",
+  "search_popout.quick_actions": "Hızlı eylemler",
+  "search_popout.recent": "Son aramalar",
   "search_results.accounts": "Profiller",
   "search_results.all": "Tümü",
   "search_results.hashtags": "Etiketler",
diff --git a/app/javascript/mastodon/locales/uk.json b/app/javascript/mastodon/locales/uk.json
index 9cbf8ad6b..5278f845f 100644
--- a/app/javascript/mastodon/locales/uk.json
+++ b/app/javascript/mastodon/locales/uk.json
@@ -522,16 +522,16 @@
   "report_notification.categories.spam": "Спам",
   "report_notification.categories.violation": "Порушення правил",
   "report_notification.open": "Відкрити скаргу",
-  "search.no_recent_searches": "No recent searches",
+  "search.no_recent_searches": "Немає останніх пошуків",
   "search.placeholder": "Пошук",
-  "search.quick_action.account_search": "Profiles matching {x}",
-  "search.quick_action.go_to_account": "Go to profile {x}",
-  "search.quick_action.go_to_hashtag": "Go to hashtag {x}",
-  "search.quick_action.open_url": "Open URL in Mastodon",
-  "search.quick_action.status_search": "Posts matching {x}",
+  "search.quick_action.account_search": "Збіг профілів {x}",
+  "search.quick_action.go_to_account": "Перейти до профілю {x}",
+  "search.quick_action.go_to_hashtag": "Перейти до хештегу {x}",
+  "search.quick_action.open_url": "Відкрити URL-адресу в Mastodon",
+  "search.quick_action.status_search": "Збіг дописів {x}",
   "search.search_or_paste": "Введіть адресу або пошуковий запит",
-  "search_popout.quick_actions": "Quick actions",
-  "search_popout.recent": "Recent searches",
+  "search_popout.quick_actions": "Швидкі дії",
+  "search_popout.recent": "Нещодавні запити",
   "search_results.accounts": "Профілі",
   "search_results.all": "Усі",
   "search_results.hashtags": "Хештеґи",
diff --git a/app/javascript/mastodon/locales/vi.json b/app/javascript/mastodon/locales/vi.json
index 7096268ea..7d51c7055 100644
--- a/app/javascript/mastodon/locales/vi.json
+++ b/app/javascript/mastodon/locales/vi.json
@@ -522,16 +522,16 @@
   "report_notification.categories.spam": "Spam",
   "report_notification.categories.violation": "Vi phạm nội quy",
   "report_notification.open": "Mở báo cáo",
-  "search.no_recent_searches": "No recent searches",
+  "search.no_recent_searches": "Không có tìm kiếm gần đây",
   "search.placeholder": "Tìm kiếm",
-  "search.quick_action.account_search": "Profiles matching {x}",
-  "search.quick_action.go_to_account": "Go to profile {x}",
-  "search.quick_action.go_to_hashtag": "Go to hashtag {x}",
-  "search.quick_action.open_url": "Open URL in Mastodon",
-  "search.quick_action.status_search": "Posts matching {x}",
+  "search.quick_action.account_search": "Người trùng khớp {x}",
+  "search.quick_action.go_to_account": "Xem trang {x}",
+  "search.quick_action.go_to_hashtag": "Xem hashtag {x}",
+  "search.quick_action.open_url": "Mở liên kết trong Mastodon",
+  "search.quick_action.status_search": "Tút trùng khớp {x}",
   "search.search_or_paste": "Tìm kiếm hoặc nhập URL",
-  "search_popout.quick_actions": "Quick actions",
-  "search_popout.recent": "Recent searches",
+  "search_popout.quick_actions": "Thao tác nhanh",
+  "search_popout.recent": "Tìm kiếm gần đây",
   "search_results.accounts": "Mọi người",
   "search_results.all": "Toàn bộ",
   "search_results.hashtags": "Hashtags",
diff --git a/app/javascript/mastodon/locales/zh-CN.json b/app/javascript/mastodon/locales/zh-CN.json
index 3b6aa203f..f9e31c450 100644
--- a/app/javascript/mastodon/locales/zh-CN.json
+++ b/app/javascript/mastodon/locales/zh-CN.json
@@ -37,7 +37,7 @@
   "account.following_counter": "正在关注 {counter} 人",
   "account.follows.empty": "此用户目前尚未关注任何人。",
   "account.follows_you": "关注了你",
-  "account.go_to_profile": "转到个人资料界面",
+  "account.go_to_profile": "转到个人资料页",
   "account.hide_reblogs": "隐藏来自 @{name} 的转贴",
   "account.joined_short": "加入于",
   "account.languages": "更改订阅语言",
@@ -53,7 +53,7 @@
   "account.posts": "嘟文",
   "account.posts_with_replies": "嘟文和回复",
   "account.report": "举报 @{name}",
-  "account.requested": "正在等待对方同意。点击以取消发送关注请求",
+  "account.requested": "正在等待对方同意。点击取消发送关注请求",
   "account.requested_follow": "{name} 已经向你发送了关注请求",
   "account.share": "分享 @{name} 的个人资料页",
   "account.show_reblogs": "显示来自 @{name} 的转嘟",
@@ -202,7 +202,7 @@
   "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": "常用",
@@ -246,18 +246,18 @@
   "explore.trending_tags": "话题标签",
   "filter_modal.added.context_mismatch_explanation": "此过滤器分类不适用访问过嘟文的环境中。如果你想要在环境中过滤嘟文,你必须编辑此过滤器。",
   "filter_modal.added.context_mismatch_title": "环境不匹配!",
-  "filter_modal.added.expired_explanation": "此过滤器分类已过期,你需要修改到期日期才能应用。",
+  "filter_modal.added.expired_explanation": "此过滤器类别已过期,你需要修改到期日期才能应用。",
   "filter_modal.added.expired_title": "过滤器已过期!",
   "filter_modal.added.review_and_configure": "要审核并进一步配置此过滤器分类,请前往{settings_link}。",
   "filter_modal.added.review_and_configure_title": "过滤器设置",
   "filter_modal.added.settings_link": "设置页面",
-  "filter_modal.added.short_explanation": "此嘟文已添加到以下过滤器分类:{title}。",
+  "filter_modal.added.short_explanation": "此嘟文已添加到以下过滤器类别:{title}。",
   "filter_modal.added.title": "过滤器已添加 !",
-  "filter_modal.select_filter.context_mismatch": "不适用于此环境",
+  "filter_modal.select_filter.context_mismatch": "不适用于这个情境",
   "filter_modal.select_filter.expired": "已过期",
-  "filter_modal.select_filter.prompt_new": "新分类:{name}",
+  "filter_modal.select_filter.prompt_new": "新类别:{name}",
   "filter_modal.select_filter.search": "搜索或创建",
-  "filter_modal.select_filter.subtitle": "使用一个已存在分类,或创建一个新分类",
+  "filter_modal.select_filter.subtitle": "使用一个已存在分类,或创建一个新类别",
   "filter_modal.select_filter.title": "过滤此嘟文",
   "filter_modal.title.status": "过滤一条嘟文",
   "follow_recommendations.done": "完成",
@@ -269,7 +269,7 @@
   "followed_tags": "关注的话题标签",
   "footer.about": "关于",
   "footer.directory": "用户目录",
-  "footer.get_app": "获取应用程序",
+  "footer.get_app": "获取应用",
   "footer.invite": "邀请",
   "footer.keyboard_shortcuts": "快捷键列表",
   "footer.privacy_policy": "隐私政策",
@@ -363,8 +363,8 @@
   "lists.search": "搜索你关注的人",
   "lists.subheading": "你的列表",
   "load_pending": "{count} 项",
-  "loading_indicator.label": "加载中……",
-  "media_gallery.toggle_visible": "隐藏图片",
+  "loading_indicator.label": "加载中…",
+  "media_gallery.toggle_visible": "{number, plural, other {隐藏图像}}",
   "missing_indicator.label": "找不到内容",
   "missing_indicator.sublabel": "无法找到此资源",
   "moved_to_account_banner.text": "您的账号 {disabledAccount} 已停用,因为您已迁移到 {movedToAccount} 。",
@@ -387,7 +387,7 @@
   "navigation_bar.followed_tags": "关注的话题标签",
   "navigation_bar.follows_and_followers": "关注管理",
   "navigation_bar.lists": "列表",
-  "navigation_bar.logout": "登出",
+  "navigation_bar.logout": "退出登录",
   "navigation_bar.mutes": "已隐藏的用户",
   "navigation_bar.personal": "个人",
   "navigation_bar.pins": "置顶嘟文",
@@ -503,7 +503,7 @@
   "report.reasons.other_description": "该问题不符合其他类别",
   "report.reasons.spam": "它是垃圾信息",
   "report.reasons.spam_description": "恶意链接,虚假互动和重复回复",
-  "report.reasons.violation": "它违反了服务器规则",
+  "report.reasons.violation": "违反服务器规则",
   "report.reasons.violation_description": "你清楚它违反了特定的规则",
   "report.rules.subtitle": "选择所有适用选项",
   "report.rules.title": "哪些规则被违反了?",
@@ -522,16 +522,16 @@
   "report_notification.categories.spam": "骚扰",
   "report_notification.categories.violation": "违反规则",
   "report_notification.open": "打开举报",
-  "search.no_recent_searches": "No recent searches",
+  "search.no_recent_searches": "无最近搜索",
   "search.placeholder": "搜索",
-  "search.quick_action.account_search": "Profiles matching {x}",
-  "search.quick_action.go_to_account": "Go to profile {x}",
-  "search.quick_action.go_to_hashtag": "Go to hashtag {x}",
-  "search.quick_action.open_url": "Open URL in Mastodon",
-  "search.quick_action.status_search": "Posts matching {x}",
+  "search.quick_action.account_search": "匹配 {x} 的个人资料",
+  "search.quick_action.go_to_account": "转到 {x} 个人资料",
+  "search.quick_action.go_to_hashtag": "转到标签 {x}",
+  "search.quick_action.open_url": "在 Mastodon 中打开链接",
+  "search.quick_action.status_search": "匹配 {x} 的帖子",
   "search.search_or_paste": "搜索或输入链接",
-  "search_popout.quick_actions": "Quick actions",
-  "search_popout.recent": "Recent searches",
+  "search_popout.quick_actions": "快捷操作",
+  "search_popout.recent": "最近搜索",
   "search_results.accounts": "个人资料",
   "search_results.all": "全部",
   "search_results.hashtags": "话题标签",
diff --git a/app/javascript/mastodon/locales/zh-TW.json b/app/javascript/mastodon/locales/zh-TW.json
index 5245c59d8..55f709340 100644
--- a/app/javascript/mastodon/locales/zh-TW.json
+++ b/app/javascript/mastodon/locales/zh-TW.json
@@ -522,16 +522,16 @@
   "report_notification.categories.spam": "垃圾訊息",
   "report_notification.categories.violation": "違反規則",
   "report_notification.open": "開啟檢舉報告",
-  "search.no_recent_searches": "No recent searches",
+  "search.no_recent_searches": "尚無最近的搜尋紀錄",
   "search.placeholder": "搜尋",
-  "search.quick_action.account_search": "Profiles matching {x}",
-  "search.quick_action.go_to_account": "Go to profile {x}",
-  "search.quick_action.go_to_hashtag": "Go to hashtag {x}",
-  "search.quick_action.open_url": "Open URL in Mastodon",
-  "search.quick_action.status_search": "Posts matching {x}",
+  "search.quick_action.account_search": "符合的個人檔案 {x}",
+  "search.quick_action.go_to_account": "前往個人檔案 {x}",
+  "search.quick_action.go_to_hashtag": "前往主題標籤 {x}",
+  "search.quick_action.open_url": "於 Mastodon 中開啟連結",
+  "search.quick_action.status_search": "符合的嘟文 {x}",
   "search.search_or_paste": "搜尋或輸入網址",
-  "search_popout.quick_actions": "Quick actions",
-  "search_popout.recent": "Recent searches",
+  "search_popout.quick_actions": "快捷操作",
+  "search_popout.recent": "最近的搜尋紀錄",
   "search_results.accounts": "個人檔案",
   "search_results.all": "全部",
   "search_results.hashtags": "主題標籤",
diff --git a/app/javascript/packs/public.jsx b/app/javascript/packs/public.jsx
index 8017734d5..ad6bf237f 100644
--- a/app/javascript/packs/public.jsx
+++ b/app/javascript/packs/public.jsx
@@ -100,11 +100,12 @@ function main() {
       const datetime = new Date(content.getAttribute('datetime'));
       const now      = new Date();
 
-      content.title = dateTimeFormat.format(datetime);
+      const timeGiven = content.getAttribute('datetime').includes('T');
+      content.title = timeGiven ? dateTimeFormat.format(datetime) : dateFormat.format(datetime);
       content.textContent = timeAgoString({
         formatMessage: ({ id, defaultMessage }, values) => (new IntlMessageFormat(messages[id] || defaultMessage, locale)).format(values),
         formatDate: (date, options) => (new Intl.DateTimeFormat(locale, options)).format(date),
-      }, datetime, now, now.getFullYear(), content.getAttribute('datetime').includes('T'));
+      }, datetime, now, now.getFullYear(), timeGiven);
     });
 
     const reactComponents = document.querySelectorAll('[data-component]');
@@ -188,10 +189,10 @@ function main() {
 
     if (sidebar.classList.contains('visible')) {
       document.body.style.overflow = null;
-      toggleButton.setAttribute('aria-expanded', false);
+      toggleButton.setAttribute('aria-expanded', 'false');
     } else {
       document.body.style.overflow = 'hidden';
-      toggleButton.setAttribute('aria-expanded', true);
+      toggleButton.setAttribute('aria-expanded', 'true');
     }
 
     toggleButton.classList.toggle('active');
diff --git a/app/javascript/styles/mastodon/accounts.scss b/app/javascript/styles/mastodon/accounts.scss
index af0d8b5ed..853d7f70d 100644
--- a/app/javascript/styles/mastodon/accounts.scss
+++ b/app/javascript/styles/mastodon/accounts.scss
@@ -36,10 +36,6 @@
     @media screen and (max-width: 600px) {
       height: 200px;
     }
-
-    @media screen and (max-width: $no-gap-breakpoint) {
-      display: none;
-    }
   }
 
   &__bar {
@@ -138,7 +134,7 @@
   }
 
   .older {
-    float: inline-start;
+    float: left;
     padding-inline-start: 0;
 
     .fa {
@@ -148,7 +144,7 @@
   }
 
   .newer {
-    float: inline-end;
+    float: right;
     padding-inline-end: 0;
 
     .fa {
diff --git a/app/javascript/styles/mastodon/admin.scss b/app/javascript/styles/mastodon/admin.scss
index 1c74de256..acb4baf4f 100644
--- a/app/javascript/styles/mastodon/admin.scss
+++ b/app/javascript/styles/mastodon/admin.scss
@@ -651,7 +651,7 @@ body,
     .button {
       overflow: visible;
       margin: 0 0 5px 5px;
-      float: inline-end;
+      float: right;
     }
   }
 }
@@ -799,7 +799,7 @@ a.name-tag,
 
 .speech-bubble {
   margin-bottom: 20px;
-  border-inset-inline-start: 4px solid $ui-highlight-color;
+  border-inline-start: 4px solid $ui-highlight-color;
 
   &.positive {
     border-left-color: $success-green;
@@ -1678,7 +1678,7 @@ a.sparkline {
 }
 
 .section-skip-link {
-  float: inline-end;
+  float: right;
 
   a {
     color: $ui-highlight-color;
diff --git a/app/javascript/styles/mastodon/components.scss b/app/javascript/styles/mastodon/components.scss
index fb6cb4a39..862252781 100644
--- a/app/javascript/styles/mastodon/components.scss
+++ b/app/javascript/styles/mastodon/components.scss
@@ -826,7 +826,7 @@ body > [data-popper-placement] {
 }
 
 .reply-indicator__cancel {
-  float: inline-end;
+  float: right;
   line-height: 24px;
 }
 
@@ -841,7 +841,7 @@ body > [data-popper-placement] {
 }
 
 .reply-indicator__display-avatar {
-  float: inline-start;
+  float: left;
   margin-inline-end: 5px;
 }
 
@@ -1159,7 +1159,7 @@ body > [data-popper-placement] {
 
 .notification__relative_time {
   color: $dark-text-color;
-  float: inline-end;
+  float: right;
   font-size: 14px;
   padding-bottom: 1px;
 }
@@ -1507,7 +1507,7 @@ body > [data-popper-placement] {
     position: relative;
 
     & > div {
-      float: inline-start;
+      float: left;
       position: relative;
       box-sizing: border-box;
     }
@@ -1622,7 +1622,7 @@ a .account__avatar {
   text-decoration: none;
   overflow: hidden;
   flex: 0 1 100%;
-  border-inset-inline-end: 1px solid lighten($ui-base-color, 8%);
+  border-inline-end: 1px solid lighten($ui-base-color, 8%);
   padding: 10px 0;
   border-bottom: 4px solid transparent;
 
@@ -1662,7 +1662,7 @@ a .account__avatar {
 }
 
 .account-authorize__avatar {
-  float: inline-start;
+  float: left;
   margin-inline-end: 10px;
 }
 
@@ -2642,7 +2642,7 @@ $ui-header-height: 55px;
     .navigation-panel {
       margin: 0;
       background: $ui-base-color;
-      border-inset-inline-start: 1px solid lighten($ui-base-color, 8%);
+      border-inline-start: 1px solid lighten($ui-base-color, 8%);
       height: 100vh;
     }
 
@@ -2941,7 +2941,6 @@ $ui-header-height: 55px;
     width: 85%;
     height: 100%;
     pointer-events: none;
-    user-drag: none;
     user-select: none;
   }
 
@@ -3879,7 +3878,7 @@ a.status-card.compact:hover {
 }
 
 .column-header__setting-arrows {
-  float: inline-end;
+  float: right;
 
   .column-header__setting-btn {
     padding: 5px;
@@ -4340,6 +4339,7 @@ a.status-card.compact:hover {
 .follow_requests-unlocked_explanation {
   background: darken($ui-base-color, 4%);
   contain: initial;
+  flex-grow: 0;
 }
 
 .error-column {
@@ -5753,7 +5753,7 @@ a.status-card.compact:hover {
 
 .report-modal__comment {
   padding: 20px;
-  border-inset-inline-end: 1px solid $ui-secondary-color;
+  border-inline-end: 1px solid $ui-secondary-color;
   max-width: 320px;
 
   p {
@@ -6044,7 +6044,7 @@ a.status-card.compact:hover {
     color: $dark-text-color;
     padding: 8px 18px;
     cursor: default;
-    border-inset-inline-end: 1px solid lighten($ui-base-color, 8%);
+    border-inline-end: 1px solid lighten($ui-base-color, 8%);
     display: flex;
     flex-direction: column;
     align-items: center;
@@ -6109,7 +6109,7 @@ a.status-card.compact:hover {
   border: 0;
   box-sizing: border-box;
   display: block;
-  float: inline-start;
+  float: left;
   position: relative;
   border-radius: 4px;
   overflow: hidden;
@@ -7930,7 +7930,7 @@ noscript {
       inset-inline-start: 0;
       width: 100%;
       height: 100%;
-      border-inset-inline-start: 4px solid $highlight-text-color;
+      border-inline-start: 4px solid $highlight-text-color;
       pointer-events: none;
     }
   }
diff --git a/app/javascript/styles/mastodon/rich_text.scss b/app/javascript/styles/mastodon/rich_text.scss
index aa41e4ad3..c77c23bc4 100644
--- a/app/javascript/styles/mastodon/rich_text.scss
+++ b/app/javascript/styles/mastodon/rich_text.scss
@@ -14,7 +14,7 @@
 
   blockquote {
     padding-inline-start: 10px;
-    border-inset-inline-start: 3px solid $darker-text-color;
+    border-inline-start: 3px solid $darker-text-color;
     color: $darker-text-color;
     white-space: normal;
 
diff --git a/app/javascript/styles/mastodon/rtl.scss b/app/javascript/styles/mastodon/rtl.scss
index 726135c58..8d3d32665 100644
--- a/app/javascript/styles/mastodon/rtl.scss
+++ b/app/javascript/styles/mastodon/rtl.scss
@@ -19,10 +19,22 @@ body.rtl {
     direction: rtl;
   }
 
+  .account__avatar-wrapper {
+    float: right;
+  }
+
+  .column-header__setting-arrows {
+    float: left;
+  }
+
   .admin-wrapper {
     direction: rtl;
   }
 
+  .react-swipeable-view-container > * {
+    direction: rtl;
+  }
+
   .simple_form .label_input__append {
     &::after {
       background-image: linear-gradient(
diff --git a/app/javascript/styles/mastodon/tables.scss b/app/javascript/styles/mastodon/tables.scss
index fb1ff0781..49e5bbf9f 100644
--- a/app/javascript/styles/mastodon/tables.scss
+++ b/app/javascript/styles/mastodon/tables.scss
@@ -91,12 +91,12 @@
 
       &:first-child {
         border-radius: 4px 0 0;
-        border-inset-inline-start: 1px solid darken($ui-base-color, 8%);
+        border-inline-start: 1px solid darken($ui-base-color, 8%);
       }
 
       &:last-child {
         border-radius: 0 4px 0 0;
-        border-inset-inline-end: 1px solid darken($ui-base-color, 8%);
+        border-inline-end: 1px solid darken($ui-base-color, 8%);
       }
     }
   }
diff --git a/app/services/notify_service.rb b/app/services/notify_service.rb
index 994ca588a..069f370cf 100644
--- a/app/services/notify_service.rb
+++ b/app/services/notify_service.rb
@@ -6,6 +6,7 @@ class NotifyService < BaseService
   NON_EMAIL_TYPES = %i(
     admin.report
     admin.sign_up
+    update
   ).freeze
 
   def call(recipient, type, activity)