about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--.travis.yml2
-rw-r--r--app/helpers/settings_helper.rb1
-rw-r--r--app/javascript/mastodon/components/status_content.js3
-rw-r--r--app/javascript/mastodon/locales/ar.json7
-rw-r--r--app/javascript/mastodon/locales/bg.json7
-rw-r--r--app/javascript/mastodon/locales/ca.json11
-rw-r--r--app/javascript/mastodon/locales/de.json7
-rw-r--r--app/javascript/mastodon/locales/defaultMessages.json10
-rw-r--r--app/javascript/mastodon/locales/en.json6
-rw-r--r--app/javascript/mastodon/locales/eo.json7
-rw-r--r--app/javascript/mastodon/locales/es.json6
-rw-r--r--app/javascript/mastodon/locales/fa.json7
-rw-r--r--app/javascript/mastodon/locales/fi.json7
-rw-r--r--app/javascript/mastodon/locales/fr.json8
-rw-r--r--app/javascript/mastodon/locales/he.json7
-rw-r--r--app/javascript/mastodon/locales/hr.json7
-rw-r--r--app/javascript/mastodon/locales/hu.json7
-rw-r--r--app/javascript/mastodon/locales/id.json7
-rw-r--r--app/javascript/mastodon/locales/io.json7
-rw-r--r--app/javascript/mastodon/locales/it.json7
-rw-r--r--app/javascript/mastodon/locales/ja.json2
-rw-r--r--app/javascript/mastodon/locales/ko.json7
-rw-r--r--app/javascript/mastodon/locales/nl.json7
-rw-r--r--app/javascript/mastodon/locales/no.json7
-rw-r--r--app/javascript/mastodon/locales/oc.json6
-rw-r--r--app/javascript/mastodon/locales/pl.json6
-rw-r--r--app/javascript/mastodon/locales/pt-BR.json15
-rw-r--r--app/javascript/mastodon/locales/pt.json7
-rw-r--r--app/javascript/mastodon/locales/ru.json7
-rw-r--r--app/javascript/mastodon/locales/sv.json217
-rw-r--r--app/javascript/mastodon/locales/th.json7
-rw-r--r--app/javascript/mastodon/locales/tr.json7
-rw-r--r--app/javascript/mastodon/locales/uk.json7
-rw-r--r--app/javascript/mastodon/locales/zh-CN.json7
-rw-r--r--app/javascript/mastodon/locales/zh-HK.json7
-rw-r--r--app/javascript/mastodon/locales/zh-TW.json7
-rw-r--r--app/javascript/mastodon/middleware/sounds.js6
-rw-r--r--app/javascript/mastodon/reducers/timelines.js10
-rw-r--r--app/javascript/styles/application.scss39
-rw-r--r--app/javascript/styles/mastodon/_mixins.scss (renamed from app/javascript/styles/_mixins.scss)0
-rw-r--r--app/javascript/styles/mastodon/about.scss (renamed from app/javascript/styles/about.scss)0
-rw-r--r--app/javascript/styles/mastodon/accounts.scss (renamed from app/javascript/styles/accounts.scss)0
-rw-r--r--app/javascript/styles/mastodon/admin.scss (renamed from app/javascript/styles/admin.scss)0
-rw-r--r--app/javascript/styles/mastodon/basics.scss (renamed from app/javascript/styles/basics.scss)2
-rw-r--r--app/javascript/styles/mastodon/boost.scss (renamed from app/javascript/styles/boost.scss)0
-rw-r--r--app/javascript/styles/mastodon/compact_header.scss (renamed from app/javascript/styles/compact_header.scss)0
-rw-r--r--app/javascript/styles/mastodon/components.scss (renamed from app/javascript/styles/components.scss)8
-rw-r--r--app/javascript/styles/mastodon/containers.scss (renamed from app/javascript/styles/containers.scss)0
-rw-r--r--app/javascript/styles/mastodon/emoji_picker.scss (renamed from app/javascript/styles/emoji_picker.scss)0
-rw-r--r--app/javascript/styles/mastodon/footer.scss (renamed from app/javascript/styles/footer.scss)0
-rw-r--r--app/javascript/styles/mastodon/forms.scss (renamed from app/javascript/styles/forms.scss)0
-rw-r--r--app/javascript/styles/mastodon/landing_strip.scss (renamed from app/javascript/styles/landing_strip.scss)0
-rw-r--r--app/javascript/styles/mastodon/lists.scss (renamed from app/javascript/styles/lists.scss)0
-rw-r--r--app/javascript/styles/mastodon/reset.scss (renamed from app/javascript/styles/reset.scss)0
-rw-r--r--app/javascript/styles/mastodon/rtl.scss (renamed from app/javascript/styles/rtl.scss)0
-rw-r--r--app/javascript/styles/mastodon/stream_entries.scss (renamed from app/javascript/styles/stream_entries.scss)0
-rw-r--r--app/javascript/styles/mastodon/tables.scss (renamed from app/javascript/styles/tables.scss)0
-rw-r--r--app/javascript/styles/mastodon/variables.scss (renamed from app/javascript/styles/variables.scss)0
-rw-r--r--app/lib/activitypub/activity.rb7
-rw-r--r--app/lib/feed_manager.rb49
-rw-r--r--app/lib/ostatus/activity/creation.rb2
-rw-r--r--app/services/fetch_link_card_service.rb2
-rw-r--r--app/views/user_mailer/confirmation_instructions.sv.html.erb15
-rw-r--r--app/views/user_mailer/confirmation_instructions.sv.text.erb12
-rw-r--r--app/views/user_mailer/password_change.sv.html.erb3
-rw-r--r--app/views/user_mailer/password_change.sv.text.erb3
-rw-r--r--app/views/user_mailer/reset_password_instructions.sv.html.erb8
-rw-r--r--app/views/user_mailer/reset_password_instructions.sv.text.erb8
-rw-r--r--app/workers/scheduler/feed_cleanup_scheduler.rb28
-rw-r--r--config/application.rb1
-rw-r--r--config/database.yml4
-rw-r--r--config/locales/de.yml16
-rw-r--r--config/locales/devise.sv.yml61
-rw-r--r--config/locales/devise.tr.yml9
-rw-r--r--config/locales/doorkeeper.sv.yml119
-rw-r--r--config/locales/en.yml18
-rw-r--r--config/locales/fa.yml18
-rw-r--r--config/locales/fr.yml42
-rw-r--r--config/locales/ko.yml2
-rw-r--r--config/locales/nl.yml18
-rw-r--r--config/locales/oc.yml36
-rw-r--r--config/locales/pl.yml16
-rw-r--r--config/locales/pt-BR.yml22
-rw-r--r--config/locales/simple_form.de.yml1
-rw-r--r--config/locales/simple_form.fr.yml1
-rw-r--r--config/locales/simple_form.ja.yml1
-rw-r--r--config/locales/simple_form.nl.yml7
-rw-r--r--config/locales/simple_form.oc.yml2
-rw-r--r--config/locales/simple_form.sv.yml67
-rw-r--r--config/locales/sv.yml614
-rw-r--r--jest.config.js8
-rw-r--r--lib/mastodon/version.rb2
-rw-r--r--package.json2
-rw-r--r--spec/lib/feed_manager_spec.rb68
-rw-r--r--spec/workers/scheduler/feed_cleanup_scheduler_spec.rb8
-rw-r--r--streaming/index.js2
96 files changed, 1592 insertions, 229 deletions
diff --git a/.travis.yml b/.travis.yml
index 71b3a6069..5c2c2c889 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -54,4 +54,4 @@ before_script:
 script:
   - travis_retry bundle exec parallel_test spec/ --group-by filesize --type rspec
   - yarn test
-  - bundle exec i18n-tasks unused
+  - bundle exec i18n-tasks check-normalized && bundle exec i18n-tasks unused
diff --git a/app/helpers/settings_helper.rb b/app/helpers/settings_helper.rb
index 14776b354..abce85812 100644
--- a/app/helpers/settings_helper.rb
+++ b/app/helpers/settings_helper.rb
@@ -27,6 +27,7 @@ module SettingsHelper
     pt: 'Português',
     'pt-BR': 'Português do Brasil',
     ru: 'Русский',
+    sv: 'Svenska',
     th: 'ภาษาไทย',
     tr: 'Türkçe',
     uk: 'Українська',
diff --git a/app/javascript/mastodon/components/status_content.js b/app/javascript/mastodon/components/status_content.js
index 8ad60b9d6..0f7f15dfc 100644
--- a/app/javascript/mastodon/components/status_content.js
+++ b/app/javascript/mastodon/components/status_content.js
@@ -125,6 +125,7 @@ export default class StatusContent extends React.PureComponent {
     const directionStyle = { direction: 'ltr' };
     const classNames = classnames('status__content', {
       'status__content--with-action': this.props.onClick && this.context.router,
+      'status__content--with-spoiler': status.get('spoiler_text').length > 0,
     });
 
     if (isRtl(status.get('search_index'))) {
@@ -156,7 +157,7 @@ export default class StatusContent extends React.PureComponent {
 
           {mentionsPlaceholder}
 
-          <div tabIndex={!hidden && 0} className={`status__content__text ${!hidden ? 'status__content__text--visible' : ''}`} style={directionStyle} dangerouslySetInnerHTML={content} />
+          <div tabIndex={!hidden ? 0 : null} className={`status__content__text ${!hidden ? 'status__content__text--visible' : ''}`} style={directionStyle} dangerouslySetInnerHTML={content} />
         </div>
       );
     } else if (this.props.onClick) {
diff --git a/app/javascript/mastodon/locales/ar.json b/app/javascript/mastodon/locales/ar.json
index 799819c7c..7cc8ea237 100644
--- a/app/javascript/mastodon/locales/ar.json
+++ b/app/javascript/mastodon/locales/ar.json
@@ -82,7 +82,6 @@
   "empty_column.community": "الخط الزمني المحلي فارغ. اكتب شيئا ما للعامة كبداية.",
   "empty_column.hashtag": "ليس هناك بعدُ أي محتوى ذو علاقة بهذا الوسم.",
   "empty_column.home": "إنك لا تتبع بعد أي شخص إلى حد الآن. زر {public} أو استخدام حقل البحث لكي تبدأ على التعرف على مستخدمين آخرين.",
-  "empty_column.home.inactivity": "صفحتك فارغة. لقد كنت غائبا لفترة طويلة عن الشبكة. سوف تملأ تلقائيا في وقت قريب.",
   "empty_column.home.public_timeline": "الخيط العام",
   "empty_column.notifications": "لم تتلق أي إشعار بعدُ. تفاعل مع المستخدمين الآخرين لإنشاء محادثة.",
   "empty_column.public": "لا يوجد شيء هنا ! قم بتحرير شيء ما بشكل عام، أو اتبع مستخدمين آخرين في الخوادم المثيلة الأخرى لملء خيط المحادثات العام.",
@@ -160,6 +159,11 @@
   "privacy.public.short": "للعامة",
   "privacy.unlisted.long": "لا تقم بإدراجه على الخيوط العامة",
   "privacy.unlisted.short": "غير مدرج",
+  "relative_time.days": "{number}d",
+  "relative_time.hours": "{number}h",
+  "relative_time.just_now": "now",
+  "relative_time.minutes": "{number}m",
+  "relative_time.seconds": "{number}s",
   "reply_indicator.cancel": "إلغاء",
   "report.placeholder": "تعليقات إضافية",
   "report.submit": "إرسال",
@@ -179,6 +183,7 @@
   "status.load_more": "حمّل المزيد",
   "status.media_hidden": "الصورة مستترة",
   "status.mention": "أذكُر @{name}",
+  "status.more": "More",
   "status.mute_conversation": "كتم المحادثة",
   "status.open": "وسع هذه المشاركة",
   "status.pin": "تدبيس على الملف الشخصي",
diff --git a/app/javascript/mastodon/locales/bg.json b/app/javascript/mastodon/locales/bg.json
index eeded31b7..da2372cff 100644
--- a/app/javascript/mastodon/locales/bg.json
+++ b/app/javascript/mastodon/locales/bg.json
@@ -82,7 +82,6 @@
   "empty_column.community": "The local timeline is empty. Write something publicly to get the ball rolling!",
   "empty_column.hashtag": "There is nothing in this hashtag yet.",
   "empty_column.home": "Your home timeline is empty! Visit {public} or use search to get started and meet other users.",
-  "empty_column.home.inactivity": "Your home feed is empty. If you have been inactive for a while, it will be regenerated for you soon.",
   "empty_column.home.public_timeline": "the public timeline",
   "empty_column.notifications": "You don't have any notifications yet. Interact with others to start the conversation.",
   "empty_column.public": "There is nothing here! Write something publicly, or manually follow users from other instances to fill it up",
@@ -160,6 +159,11 @@
   "privacy.public.short": "Public",
   "privacy.unlisted.long": "Do not show in public timelines",
   "privacy.unlisted.short": "Unlisted",
+  "relative_time.days": "{number}d",
+  "relative_time.hours": "{number}h",
+  "relative_time.just_now": "now",
+  "relative_time.minutes": "{number}m",
+  "relative_time.seconds": "{number}s",
   "reply_indicator.cancel": "Отказ",
   "report.placeholder": "Additional comments",
   "report.submit": "Submit",
@@ -179,6 +183,7 @@
   "status.load_more": "Load more",
   "status.media_hidden": "Media hidden",
   "status.mention": "Споменаване",
+  "status.more": "More",
   "status.mute_conversation": "Mute conversation",
   "status.open": "Expand this status",
   "status.pin": "Pin on profile",
diff --git a/app/javascript/mastodon/locales/ca.json b/app/javascript/mastodon/locales/ca.json
index 1130e6c09..af732921d 100644
--- a/app/javascript/mastodon/locales/ca.json
+++ b/app/javascript/mastodon/locales/ca.json
@@ -82,7 +82,6 @@
   "empty_column.community": "La línia de temps local és buida. Escriu alguna cosa públicament per fer rodar la pilota!",
   "empty_column.hashtag": "Encara no hi ha res amb aquesta etiqueta.",
   "empty_column.home": "Encara no segueixes ningú. Visita {public} o fes cerca per començar i conèixer altres usuaris.",
-  "empty_column.home.inactivity": "La línia Inici és buida. si has estat inactiu durant un temps es regenerarà aviat.",
   "empty_column.home.public_timeline": "la línia de temps pública",
   "empty_column.notifications": "Encara no tens notificacions. Interactua amb altres per iniciar la conversa.",
   "empty_column.public": "No hi ha res aquí! Escriu alguna cosa públicament o segueix manualment usuaris d'altres instàncies per omplir-ho",
@@ -160,11 +159,11 @@
   "privacy.public.short": "Públic",
   "privacy.unlisted.long": "No publicar en línies de temps públiques",
   "privacy.unlisted.short": "No llistat",
-  "relative_time.days": "{number}d",
-  "relative_time.hours": "{number}h",
-  "relative_time.just_now": "now",
-  "relative_time.minutes": "{number}m",
-  "relative_time.seconds": "{number}s",
+  "relative_time.days": "fa {number} jorns",
+  "relative_time.hours": "fa {number} hores",
+  "relative_time.just_now": "ara",
+  "relative_time.minutes": "fa {number} minutes",
+  "relative_time.seconds": "fa {number} segondes",
   "reply_indicator.cancel": "Cancel·lar",
   "report.placeholder": "Comentaris addicionals",
   "report.submit": "Enviar",
diff --git a/app/javascript/mastodon/locales/de.json b/app/javascript/mastodon/locales/de.json
index 9d9853236..283a2946f 100644
--- a/app/javascript/mastodon/locales/de.json
+++ b/app/javascript/mastodon/locales/de.json
@@ -82,7 +82,6 @@
   "empty_column.community": "Die lokale Zeitleiste ist leer. Schreibe einen öffentlichen Beitrag, um den Ball ins Rollen zu bringen!",
   "empty_column.hashtag": "Unter diesem Hashtag gibt es noch nichts.",
   "empty_column.home": "Deine Startseite ist leer! Besuche {public} oder nutze die Suche, um loszulegen und andere Leute zu finden.",
-  "empty_column.home.inactivity": "Deine Zeitleiste ist leer. Falls du eine längere Zeit inaktiv warst, wird sie für dich so schnell wie möglich neu erstellt.",
   "empty_column.home.public_timeline": "die öffentliche Zeitleiste",
   "empty_column.notifications": "Du hast noch keine Mitteilungen. Interagiere mit anderen, um ins Gespräch zu kommen.",
   "empty_column.public": "Hier ist nichts zu sehen! Schreibe etwas öffentlich oder folge Profilen von anderen Instanzen, um die Zeitleiste aufzufüllen",
@@ -160,6 +159,11 @@
   "privacy.public.short": "Öffentlich",
   "privacy.unlisted.long": "Nicht in öffentlichen Zeitleisten anzeigen",
   "privacy.unlisted.short": "Nicht gelistet",
+  "relative_time.days": "{number}d",
+  "relative_time.hours": "{number}h",
+  "relative_time.just_now": "now",
+  "relative_time.minutes": "{number}m",
+  "relative_time.seconds": "{number}s",
   "reply_indicator.cancel": "Abbrechen",
   "report.placeholder": "Zusätzliche Kommentare",
   "report.submit": "Absenden",
@@ -179,6 +183,7 @@
   "status.load_more": "Weitere laden",
   "status.media_hidden": "Medien versteckt",
   "status.mention": "@{name} erwähnen",
+  "status.more": "Mehr",
   "status.mute_conversation": "Thread stummschalten",
   "status.open": "Diesen Beitrag öffnen",
   "status.pin": "Im Profil anheften",
diff --git a/app/javascript/mastodon/locales/defaultMessages.json b/app/javascript/mastodon/locales/defaultMessages.json
index 99ff3b35b..f400b283f 100644
--- a/app/javascript/mastodon/locales/defaultMessages.json
+++ b/app/javascript/mastodon/locales/defaultMessages.json
@@ -184,6 +184,10 @@
         "id": "status.share"
       },
       {
+        "defaultMessage": "More",
+        "id": "status.more"
+      },
+      {
         "defaultMessage": "Reply to thread",
         "id": "status.replyAll"
       },
@@ -908,10 +912,6 @@
         "id": "column.home"
       },
       {
-        "defaultMessage": "Your home feed is empty. If you have been inactive for a while, it will be regenerated for you soon.",
-        "id": "empty_column.home.inactivity"
-      },
-      {
         "defaultMessage": "Your home timeline is empty! Visit {public} or use search to get started and meet other users.",
         "id": "empty_column.home"
       },
@@ -1408,4 +1408,4 @@
     ],
     "path": "app/javascript/mastodon/features/video/index.json"
   }
-]
+]
\ No newline at end of file
diff --git a/app/javascript/mastodon/locales/en.json b/app/javascript/mastodon/locales/en.json
index 7e8d30c64..1d0bbcee5 100644
--- a/app/javascript/mastodon/locales/en.json
+++ b/app/javascript/mastodon/locales/en.json
@@ -82,7 +82,6 @@
   "empty_column.community": "The local timeline is empty. Write something publicly to get the ball rolling!",
   "empty_column.hashtag": "There is nothing in this hashtag yet.",
   "empty_column.home": "Your home timeline is empty! Visit {public} or use search to get started and meet other users.",
-  "empty_column.home.inactivity": "Your home feed is empty. If you have been inactive for a while, it will be regenerated for you soon.",
   "empty_column.home.public_timeline": "the public timeline",
   "empty_column.notifications": "You don't have any notifications yet. Interact with others to start the conversation.",
   "empty_column.public": "There is nothing here! Write something publicly, or manually follow users from other instances to fill it up",
@@ -160,6 +159,11 @@
   "privacy.public.short": "Public",
   "privacy.unlisted.long": "Do not post to public timelines",
   "privacy.unlisted.short": "Unlisted",
+  "relative_time.days": "{number}d",
+  "relative_time.hours": "{number}h",
+  "relative_time.just_now": "now",
+  "relative_time.minutes": "{number}m",
+  "relative_time.seconds": "{number}s",
   "reply_indicator.cancel": "Cancel",
   "report.placeholder": "Additional comments",
   "report.submit": "Submit",
diff --git a/app/javascript/mastodon/locales/eo.json b/app/javascript/mastodon/locales/eo.json
index 8f90bdf78..22639f6f9 100644
--- a/app/javascript/mastodon/locales/eo.json
+++ b/app/javascript/mastodon/locales/eo.json
@@ -82,7 +82,6 @@
   "empty_column.community": "The local timeline is empty. Write something publicly to get the ball rolling!",
   "empty_column.hashtag": "There is nothing in this hashtag yet.",
   "empty_column.home": "Your home timeline is empty! Visit {public} or use search to get started and meet other users.",
-  "empty_column.home.inactivity": "Your home feed is empty. If you have been inactive for a while, it will be regenerated for you soon.",
   "empty_column.home.public_timeline": "the public timeline",
   "empty_column.notifications": "You don't have any notifications yet. Interact with others to start the conversation.",
   "empty_column.public": "There is nothing here! Write something publicly, or manually follow users from other instances to fill it up",
@@ -160,6 +159,11 @@
   "privacy.public.short": "Public",
   "privacy.unlisted.long": "Do not show in public timelines",
   "privacy.unlisted.short": "Unlisted",
+  "relative_time.days": "{number}d",
+  "relative_time.hours": "{number}h",
+  "relative_time.just_now": "now",
+  "relative_time.minutes": "{number}m",
+  "relative_time.seconds": "{number}s",
   "reply_indicator.cancel": "Rezigni",
   "report.placeholder": "Additional comments",
   "report.submit": "Submit",
@@ -179,6 +183,7 @@
   "status.load_more": "Load more",
   "status.media_hidden": "Media hidden",
   "status.mention": "Mencii @{name}",
+  "status.more": "More",
   "status.mute_conversation": "Mute conversation",
   "status.open": "Expand this status",
   "status.pin": "Pin on profile",
diff --git a/app/javascript/mastodon/locales/es.json b/app/javascript/mastodon/locales/es.json
index 03dd9ce02..6e8e94700 100644
--- a/app/javascript/mastodon/locales/es.json
+++ b/app/javascript/mastodon/locales/es.json
@@ -82,7 +82,6 @@
   "empty_column.community": "La línea de tiempo local está vacía. ¡Escribe algo para empezar la fiesta!",
   "empty_column.hashtag": "No hay nada en este hashtag aún.",
   "empty_column.home": "No estás siguiendo a nadie aún. Visita {public} o haz búsquedas para empezar y conocer gente nueva.",
-  "empty_column.home.inactivity": "Tus notificaciones están vacías. Si has estado inactivo por un tiempo, se regenerará para ti pronto.",
   "empty_column.home.public_timeline": "la línea de tiempo pública",
   "empty_column.notifications": "No tienes ninguna notificación aún. Interactúa con otros para empezar una conversación.",
   "empty_column.public": "¡No hay nada aquí! Escribe algo públicamente, o sigue usuarios de otras instancias manualmente para llenarlo.",
@@ -160,6 +159,11 @@
   "privacy.public.short": "Público",
   "privacy.unlisted.long": "No mostrar en la historia federada",
   "privacy.unlisted.short": "Sin federar",
+  "relative_time.days": "{number}d",
+  "relative_time.hours": "{number}h",
+  "relative_time.just_now": "ahora",
+  "relative_time.minutes": "{number}m",
+  "relative_time.seconds": "{number}s",
   "reply_indicator.cancel": "Cancelar",
   "report.placeholder": "Comentarios adicionales",
   "report.submit": "Publicar",
diff --git a/app/javascript/mastodon/locales/fa.json b/app/javascript/mastodon/locales/fa.json
index 9df0dec42..995d1b5ae 100644
--- a/app/javascript/mastodon/locales/fa.json
+++ b/app/javascript/mastodon/locales/fa.json
@@ -82,7 +82,6 @@
   "empty_column.community": "فهرست نوشته‌های محلی خالی است. چیزی بنویسید تا چرخش بچرخد!",
   "empty_column.hashtag": "هنوز هیچ چیزی با این هشتگ نیست.",
   "empty_column.home": "شما هنوز پیگیر کسی نیستید. {public} را ببینید یا چیزی را جستجو کنید تا کاربران دیگر را ببینید.",
-  "empty_column.home.inactivity": "فهرست پی‌گیری‌های شما خالی است. اگر مدتی است که غیرفعال بودید، این فهرست به زودی برایتان پر می‌شود.",
   "empty_column.home.public_timeline": "فهرست نوشته‌های همه‌جا",
   "empty_column.notifications": "هنوز هیچ اعلانی ندارید. به نوشته‌های دیگران واکنش نشان دهید تا گفتگو آغاز شود.",
   "empty_column.public": "این‌جا هنوز چیزی نیست! خودتان چیزی بنویسید یا کاربران دیگر را پی بگیرید تا این‌جا پر شود",
@@ -160,6 +159,11 @@
   "privacy.public.short": "عمومی",
   "privacy.unlisted.long": "عمومی، ولی فهرست نکن",
   "privacy.unlisted.short": "فهرست‌نشده",
+  "relative_time.days": "{number}d",
+  "relative_time.hours": "{number}h",
+  "relative_time.just_now": "now",
+  "relative_time.minutes": "{number}m",
+  "relative_time.seconds": "{number}s",
   "reply_indicator.cancel": "لغو",
   "report.placeholder": "توضیح اضافه",
   "report.submit": "بفرست",
@@ -179,6 +183,7 @@
   "status.load_more": "بیشتر نشان بده",
   "status.media_hidden": "تصویر پنهان شده",
   "status.mention": "نام‌بردن از @{name}",
+  "status.more": "More",
   "status.mute_conversation": "بی‌صداکردن گفتگو",
   "status.open": "این نوشته را باز کن",
   "status.pin": "نوشتهٔ ثابت نمایه",
diff --git a/app/javascript/mastodon/locales/fi.json b/app/javascript/mastodon/locales/fi.json
index 0f6554595..af08be5d1 100644
--- a/app/javascript/mastodon/locales/fi.json
+++ b/app/javascript/mastodon/locales/fi.json
@@ -82,7 +82,6 @@
   "empty_column.community": "The local timeline is empty. Write something publicly to get the ball rolling!",
   "empty_column.hashtag": "There is nothing in this hashtag yet.",
   "empty_column.home": "Your home timeline is empty! Visit {public} or use search to get started and meet other users.",
-  "empty_column.home.inactivity": "Your home feed is empty. If you have been inactive for a while, it will be regenerated for you soon.",
   "empty_column.home.public_timeline": "the public timeline",
   "empty_column.notifications": "You don't have any notifications yet. Interact with others to start the conversation.",
   "empty_column.public": "There is nothing here! Write something publicly, or manually follow users from other instances to fill it up",
@@ -160,6 +159,11 @@
   "privacy.public.short": "Public",
   "privacy.unlisted.long": "Do not show in public timelines",
   "privacy.unlisted.short": "Unlisted",
+  "relative_time.days": "{number}d",
+  "relative_time.hours": "{number}h",
+  "relative_time.just_now": "now",
+  "relative_time.minutes": "{number}m",
+  "relative_time.seconds": "{number}s",
   "reply_indicator.cancel": "Peruuta",
   "report.placeholder": "Additional comments",
   "report.submit": "Submit",
@@ -179,6 +183,7 @@
   "status.load_more": "Load more",
   "status.media_hidden": "Media hidden",
   "status.mention": "Mainitse @{name}",
+  "status.more": "More",
   "status.mute_conversation": "Mute conversation",
   "status.open": "Expand this status",
   "status.pin": "Pin on profile",
diff --git a/app/javascript/mastodon/locales/fr.json b/app/javascript/mastodon/locales/fr.json
index f192f3cfc..219bf4da1 100644
--- a/app/javascript/mastodon/locales/fr.json
+++ b/app/javascript/mastodon/locales/fr.json
@@ -63,7 +63,7 @@
   "confirmations.mute.message": "Confirmez-vous le masquage de {name} ?",
   "confirmations.unfollow.confirm": "Ne plus suivre",
   "confirmations.unfollow.message": "Voulez-vous arrêter de suivre {name} ?",
-  "embed.instructions": "Intégrez ce statut à votre site en copiant ce code ci-dessous.",
+  "embed.instructions": "Intégrez ce statut à votre site en copiant le code ci-dessous.",
   "embed.preview": "Il apparaîtra comme cela : ",
   "emoji_button.activity": "Activités",
   "emoji_button.custom": "Personnalisés",
@@ -82,7 +82,6 @@
   "empty_column.community": "Le fil public local est vide. Écrivez donc quelque chose pour le remplir !",
   "empty_column.hashtag": "Il n’y a encore aucun contenu associé à ce hashtag",
   "empty_column.home": "Vous ne suivez encore personne. Visitez {public} ou bien utilisez la recherche pour vous connecter à d’autres utilisateur⋅ice⋅s.",
-  "empty_column.home.inactivity": "Votre accueil est vide. Si vous ne vous êtes pas connecté⋅e depuis un moment, il se remplira automatiquement très bientôt.",
   "empty_column.home.public_timeline": "le fil public",
   "empty_column.notifications": "Vous n’avez pas encore de notification. Interagissez avec d’autres utilisateur⋅ice⋅s pour débuter la conversation.",
   "empty_column.public": "Il n’y a rien ici ! Écrivez quelque chose publiquement, ou bien suivez manuellement des utilisateur⋅ice⋅s d’autres instances pour remplir le fil public.",
@@ -160,6 +159,11 @@
   "privacy.public.short": "Public",
   "privacy.unlisted.long": "Ne pas afficher dans les fils publics",
   "privacy.unlisted.short": "Non-listé",
+  "relative_time.days": "{number} j",
+  "relative_time.hours": "{number} h",
+  "relative_time.just_now": "à l’instant",
+  "relative_time.minutes": "{number} min",
+  "relative_time.seconds": "{number} s",
   "reply_indicator.cancel": "Annuler",
   "report.placeholder": "Commentaires additionnels",
   "report.submit": "Envoyer",
diff --git a/app/javascript/mastodon/locales/he.json b/app/javascript/mastodon/locales/he.json
index beaa4fd3a..a260f0968 100644
--- a/app/javascript/mastodon/locales/he.json
+++ b/app/javascript/mastodon/locales/he.json
@@ -82,7 +82,6 @@
   "empty_column.community": "טור הסביבה ריק. יש לפרסם משהו כדי שדברים יתרחילו להתגלגל!",
   "empty_column.hashtag": "אין כלום בהאשתג הזה עדיין.",
   "empty_column.home": "אף אחד לא במעקב עדיין. אפשר לבקר ב{public} או להשתמש בחיפוש כדי להתחיל ולהכיר חצוצרנים אחרים.",
-  "empty_column.home.inactivity": "ציר זמן הבית שלך ריק. אם לא הייתה פעילות מצידך לאחרונה, הוא יתמלא מחדש בקרוב.",
   "empty_column.home.public_timeline": "ציר זמן בין-קהילתי",
   "empty_column.notifications": "אין התראות עדיין. יאללה, הגיע הזמן להתחיל להתערבב!",
   "empty_column.public": "אין פה כלום! כדי למלא את הטור הזה אפשר לכתוב משהו, או להתחיל לעקוב אחרי אנשים מקהילות אחרות.",
@@ -160,6 +159,11 @@
   "privacy.public.short": "פומבי",
   "privacy.unlisted.long": "לא יופיע בפידים הציבוריים המשותפים",
   "privacy.unlisted.short": "לא לפיד הכללי",
+  "relative_time.days": "{number}d",
+  "relative_time.hours": "{number}h",
+  "relative_time.just_now": "now",
+  "relative_time.minutes": "{number}m",
+  "relative_time.seconds": "{number}s",
   "reply_indicator.cancel": "ביטול",
   "report.placeholder": "הערות נוספות",
   "report.submit": "שליחה",
@@ -179,6 +183,7 @@
   "status.load_more": "עוד",
   "status.media_hidden": "מדיה מוסתרת",
   "status.mention": "פניה אל @{name}",
+  "status.more": "More",
   "status.mute_conversation": "השתקת שיחה",
   "status.open": "הרחבת הודעה",
   "status.pin": "Pin on profile",
diff --git a/app/javascript/mastodon/locales/hr.json b/app/javascript/mastodon/locales/hr.json
index cef61f15e..6ac7fc3b4 100644
--- a/app/javascript/mastodon/locales/hr.json
+++ b/app/javascript/mastodon/locales/hr.json
@@ -82,7 +82,6 @@
   "empty_column.community": "Lokalni timeline je prazan. Napiši nešto javno kako bi pokrenuo stvari!",
   "empty_column.hashtag": "Još ne postoji ništa s ovim hashtagom.",
   "empty_column.home": "Još ne slijediš nikoga. Posjeti {public} ili koristi tražilicu kako bi počeo i upoznao druge korisnike.",
-  "empty_column.home.inactivity": "Tvoj home feed je prazan. Ako si neko vrijeme bio neaktivan, uskoro ćese regenerirati.",
   "empty_column.home.public_timeline": "javni timeline",
   "empty_column.notifications": "Još nemaš notifikacija. Komuniciraj sa drugima kako bi započeo razgovor.",
   "empty_column.public": "Ovdje nema ništa! Napiši nešto javno, ili ručno slijedi korisnike sa drugih instanci kako bi popunio",
@@ -160,6 +159,11 @@
   "privacy.public.short": "Javno",
   "privacy.unlisted.long": "Ne prikazuj u javnim timelineovima",
   "privacy.unlisted.short": "Unlisted",
+  "relative_time.days": "{number}d",
+  "relative_time.hours": "{number}h",
+  "relative_time.just_now": "now",
+  "relative_time.minutes": "{number}m",
+  "relative_time.seconds": "{number}s",
   "reply_indicator.cancel": "Otkaži",
   "report.placeholder": "Dodatni komentari",
   "report.submit": "Pošalji",
@@ -179,6 +183,7 @@
   "status.load_more": "Učitaj više",
   "status.media_hidden": "Sakriven media sadržaj",
   "status.mention": "Spomeni @{name}",
+  "status.more": "More",
   "status.mute_conversation": "Utišaj razgovor",
   "status.open": "Proširi ovaj status",
   "status.pin": "Pin on profile",
diff --git a/app/javascript/mastodon/locales/hu.json b/app/javascript/mastodon/locales/hu.json
index 2296ea71e..5892e606e 100644
--- a/app/javascript/mastodon/locales/hu.json
+++ b/app/javascript/mastodon/locales/hu.json
@@ -82,7 +82,6 @@
   "empty_column.community": "The local timeline is empty. Write something publicly to get the ball rolling!",
   "empty_column.hashtag": "There is nothing in this hashtag yet.",
   "empty_column.home": "Your home timeline is empty! Visit {public} or use search to get started and meet other users.",
-  "empty_column.home.inactivity": "Your home feed is empty. If you have been inactive for a while, it will be regenerated for you soon.",
   "empty_column.home.public_timeline": "the public timeline",
   "empty_column.notifications": "You don't have any notifications yet. Interact with others to start the conversation.",
   "empty_column.public": "There is nothing here! Write something publicly, or manually follow users from other instances to fill it up",
@@ -160,6 +159,11 @@
   "privacy.public.short": "Public",
   "privacy.unlisted.long": "Do not show in public timelines",
   "privacy.unlisted.short": "Unlisted",
+  "relative_time.days": "{number}d",
+  "relative_time.hours": "{number}h",
+  "relative_time.just_now": "now",
+  "relative_time.minutes": "{number}m",
+  "relative_time.seconds": "{number}s",
   "reply_indicator.cancel": "Mégsem",
   "report.placeholder": "Additional comments",
   "report.submit": "Submit",
@@ -179,6 +183,7 @@
   "status.load_more": "Load more",
   "status.media_hidden": "Media hidden",
   "status.mention": "Említés",
+  "status.more": "More",
   "status.mute_conversation": "Mute conversation",
   "status.open": "Expand this status",
   "status.pin": "Pin on profile",
diff --git a/app/javascript/mastodon/locales/id.json b/app/javascript/mastodon/locales/id.json
index cc48aa996..f73ef0e19 100644
--- a/app/javascript/mastodon/locales/id.json
+++ b/app/javascript/mastodon/locales/id.json
@@ -82,7 +82,6 @@
   "empty_column.community": "Linimasa lokal masih kosong. Tulis sesuatu secara publik dan buat roda berputar!",
   "empty_column.hashtag": "Tidak ada apapun dalam hashtag ini.",
   "empty_column.home": "Anda sedang tidak mengikuti siapapun. Kunjungi {public} atau gunakan pencarian untuk memulai dan bertemu pengguna lain.",
-  "empty_column.home.inactivity": "Your home feed is empty. If you have been inactive for a while, it will be regenerated for you soon.",
   "empty_column.home.public_timeline": "linimasa publik",
   "empty_column.notifications": "Anda tidak memiliki notifikasi apapun. Berinteraksi dengan orang lain untuk memulai percakapan.",
   "empty_column.public": "Tidak ada apapun disini! Tulis sesuatu, atau ikuti pengguna lain dari server lain untuk mengisinya secara manual",
@@ -160,6 +159,11 @@
   "privacy.public.short": "Publik",
   "privacy.unlisted.long": "Tidak ditampilkan di linimasa publik",
   "privacy.unlisted.short": "Tak Terdaftar",
+  "relative_time.days": "{number}d",
+  "relative_time.hours": "{number}h",
+  "relative_time.just_now": "now",
+  "relative_time.minutes": "{number}m",
+  "relative_time.seconds": "{number}s",
   "reply_indicator.cancel": "Batal",
   "report.placeholder": "Komentar tambahan",
   "report.submit": "Kirim",
@@ -179,6 +183,7 @@
   "status.load_more": "Tampilkan semua",
   "status.media_hidden": "Media disembunyikan",
   "status.mention": "Balasan @{name}",
+  "status.more": "More",
   "status.mute_conversation": "Mute conversation",
   "status.open": "Tampilkan status ini",
   "status.pin": "Pin on profile",
diff --git a/app/javascript/mastodon/locales/io.json b/app/javascript/mastodon/locales/io.json
index b484bebc7..53371bece 100644
--- a/app/javascript/mastodon/locales/io.json
+++ b/app/javascript/mastodon/locales/io.json
@@ -82,7 +82,6 @@
   "empty_column.community": "La lokala tempolineo esas vakua. Skribez ulo publike por iniciar la agiveso!",
   "empty_column.hashtag": "Esas ankore nulo en ta gretovorto.",
   "empty_column.home": "Tu sequas ankore nulu. Vizitez {public} od uzez la serchilo por komencar e renkontrar altra uzeri.",
-  "empty_column.home.inactivity": "Your home feed is empty. If you have been inactive for a while, it will be regenerated for you soon.",
   "empty_column.home.public_timeline": "la publika tempolineo",
   "empty_column.notifications": "Tu havas ankore nula savigo. Komunikez kun altri por debutar la konverso.",
   "empty_column.public": "Esas nulo hike! Skribez ulo publike, o manuale sequez uzeri de altra instaluri por plenigar ol.",
@@ -160,6 +159,11 @@
   "privacy.public.short": "Publike",
   "privacy.unlisted.long": "Ne montrar en publika tempolinei",
   "privacy.unlisted.short": "Ne enlistigota",
+  "relative_time.days": "{number}d",
+  "relative_time.hours": "{number}h",
+  "relative_time.just_now": "now",
+  "relative_time.minutes": "{number}m",
+  "relative_time.seconds": "{number}s",
   "reply_indicator.cancel": "Nihiligar",
   "report.placeholder": "Plusa komenti",
   "report.submit": "Sendar",
@@ -179,6 +183,7 @@
   "status.load_more": "Kargar pluse",
   "status.media_hidden": "Kontenajo celita",
   "status.mention": "Mencionar @{name}",
+  "status.more": "More",
   "status.mute_conversation": "Mute conversation",
   "status.open": "Detaligar ca mesajo",
   "status.pin": "Pin on profile",
diff --git a/app/javascript/mastodon/locales/it.json b/app/javascript/mastodon/locales/it.json
index 4d73fbea8..3873d797e 100644
--- a/app/javascript/mastodon/locales/it.json
+++ b/app/javascript/mastodon/locales/it.json
@@ -82,7 +82,6 @@
   "empty_column.community": "La timeline locale è vuota. Condividi qualcosa pubblicamente per dare inizio alla festa!",
   "empty_column.hashtag": "Non c'è ancora nessun post con questo hashtag.",
   "empty_column.home": "Non stai ancora seguendo nessuno. Visita {public} o usa la ricerca per incontrare nuove persone.",
-  "empty_column.home.inactivity": "Your home feed is empty. If you have been inactive for a while, it will be regenerated for you soon.",
   "empty_column.home.public_timeline": "la timeline pubblica",
   "empty_column.notifications": "Non hai ancora nessuna notifica. Interagisci con altri per iniziare conversazioni.",
   "empty_column.public": "Qui non c'è nulla! Scrivi qualcosa pubblicamente, o aggiungi utenti da altri server per riempire questo spazio.",
@@ -160,6 +159,11 @@
   "privacy.public.short": "Pubblico",
   "privacy.unlisted.long": "Non mostrare sulla timeline pubblica",
   "privacy.unlisted.short": "Non elencato",
+  "relative_time.days": "{number}d",
+  "relative_time.hours": "{number}h",
+  "relative_time.just_now": "now",
+  "relative_time.minutes": "{number}m",
+  "relative_time.seconds": "{number}s",
   "reply_indicator.cancel": "Annulla",
   "report.placeholder": "Commenti aggiuntivi",
   "report.submit": "Invia",
@@ -179,6 +183,7 @@
   "status.load_more": "Mostra di più",
   "status.media_hidden": "Allegato nascosto",
   "status.mention": "Nomina @{name}",
+  "status.more": "More",
   "status.mute_conversation": "Mute conversation",
   "status.open": "Espandi questo post",
   "status.pin": "Pin on profile",
diff --git a/app/javascript/mastodon/locales/ja.json b/app/javascript/mastodon/locales/ja.json
index ce797a7c7..fb6d11ebe 100644
--- a/app/javascript/mastodon/locales/ja.json
+++ b/app/javascript/mastodon/locales/ja.json
@@ -82,7 +82,6 @@
   "empty_column.community": "ローカルタイムラインはまだ使われていません。何か書いてみましょう!",
   "empty_column.hashtag": "このハッシュタグはまだ使われていません。",
   "empty_column.home": "まだ誰もフォローしていません。{public}を見に行くか、検索を使って他のユーザーを見つけましょう。",
-  "empty_column.home.inactivity": "あなたのホームフィードにはなにもありません。あなたがしばらくの間アクティブではなかった場合はすぐ元通りになります。",
   "empty_column.home.public_timeline": "連合タイムライン",
   "empty_column.notifications": "まだ通知がありません。他の人とふれ合って会話を始めましょう。",
   "empty_column.public": "ここにはまだ何もありません!公開で何かを投稿したり、他のインスタンスのユーザーをフォローしたりしていっぱいにしましょう!",
@@ -184,6 +183,7 @@
   "status.load_more": "もっと見る",
   "status.media_hidden": "非表示のメディア",
   "status.mention": "返信",
+  "status.more": "もっと見る",
   "status.mute_conversation": "会話をミュート",
   "status.open": "詳細を表示",
   "status.pin": "プロフィールに固定表示",
diff --git a/app/javascript/mastodon/locales/ko.json b/app/javascript/mastodon/locales/ko.json
index 637acfab6..d99dacd59 100644
--- a/app/javascript/mastodon/locales/ko.json
+++ b/app/javascript/mastodon/locales/ko.json
@@ -183,6 +183,7 @@
   "status.load_more": "더 보기",
   "status.media_hidden": "미디어 숨겨짐",
   "status.mention": "답장",
+  "status.more": "More",
   "status.mute_conversation": "이 대화를 뮤트",
   "status.open": "상세 정보 표시",
   "status.pin": "고정",
@@ -216,9 +217,5 @@
   "video.mute": "Mute sound",
   "video.pause": "Pause",
   "video.play": "Play",
-  "video.unmute": "Unmute sound",
-  "video_player.expand": "Expand video",
-  "video_player.toggle_sound": "Toggle sound",
-  "video_player.toggle_visible": "Toggle visibility",
-  "video_player.video_error": "Video could not be played"
+  "video.unmute": "Unmute sound"
 }
diff --git a/app/javascript/mastodon/locales/nl.json b/app/javascript/mastodon/locales/nl.json
index 04b88da34..d0727a24d 100644
--- a/app/javascript/mastodon/locales/nl.json
+++ b/app/javascript/mastodon/locales/nl.json
@@ -82,7 +82,6 @@
   "empty_column.community": "De lokale tijdlijn is nog leeg. Toot iets in het openbaar om de bal aan het rollen te krijgen!",
   "empty_column.hashtag": "Er is nog niks te vinden onder deze hashtag.",
   "empty_column.home": "Jij volgt nog niemand. Bezoek {public} of gebruik het zoekvenster om andere mensen te ontmoeten.",
-  "empty_column.home.inactivity": "Deze tijdlijn is leeg. Wanneer je een tijdje inactief bent geweest wordt deze snel opnieuw aangemaakt.",
   "empty_column.home.public_timeline": "de globale tijdlijn",
   "empty_column.notifications": "Je hebt nog geen meldingen. Heb interactie met andere mensen om het gesprek aan te gaan.",
   "empty_column.public": "Er is hier helemaal niks! Toot iets in het openbaar of volg mensen van andere Mastodon-servers om het te vullen.",
@@ -160,6 +159,11 @@
   "privacy.public.short": "Openbaar",
   "privacy.unlisted.long": "Niet op openbare tijdlijnen tonen",
   "privacy.unlisted.short": "Minder openbaar",
+  "relative_time.days": "{number}d",
+  "relative_time.hours": "{number}h",
+  "relative_time.just_now": "now",
+  "relative_time.minutes": "{number}m",
+  "relative_time.seconds": "{number}s",
   "reply_indicator.cancel": "Annuleren",
   "report.placeholder": "Extra opmerkingen",
   "report.submit": "Verzenden",
@@ -179,6 +183,7 @@
   "status.load_more": "Meer laden",
   "status.media_hidden": "Media verborgen",
   "status.mention": "Vermeld @{name}",
+  "status.more": "Meer",
   "status.mute_conversation": "Negeer conversatie",
   "status.open": "Toot volledig tonen",
   "status.pin": "Aan profielpagina vastmaken",
diff --git a/app/javascript/mastodon/locales/no.json b/app/javascript/mastodon/locales/no.json
index 26556b290..d74ae0091 100644
--- a/app/javascript/mastodon/locales/no.json
+++ b/app/javascript/mastodon/locales/no.json
@@ -82,7 +82,6 @@
   "empty_column.community": "Den lokale tidslinjen er tom. Skriv noe offentlig for å få snøballen til å rulle!",
   "empty_column.hashtag": "Det er ingenting i denne hashtagen ennå.",
   "empty_column.home": "Du har ikke fulgt noen ennå. Besøk {publlic} eller bruk søk for å komme i gang og møte andre brukere.",
-  "empty_column.home.inactivity": "Your home feed is empty. If you have been inactive for a while, it will be regenerated for you soon.",
   "empty_column.home.public_timeline": "en offentlig tidslinje",
   "empty_column.notifications": "Du har ingen varsler ennå. Kommuniser med andre for å begynne samtalen.",
   "empty_column.public": "Det er ingenting her! Skriv noe offentlig, eller følg brukere manuelt fra andre instanser for å fylle den opp",
@@ -160,6 +159,11 @@
   "privacy.public.short": "Offentlig",
   "privacy.unlisted.long": "Ikke vis i offentlige tidslinjer",
   "privacy.unlisted.short": "Uoppført",
+  "relative_time.days": "{number}d",
+  "relative_time.hours": "{number}h",
+  "relative_time.just_now": "now",
+  "relative_time.minutes": "{number}m",
+  "relative_time.seconds": "{number}s",
   "reply_indicator.cancel": "Avbryt",
   "report.placeholder": "Tilleggskommentarer",
   "report.submit": "Send inn",
@@ -179,6 +183,7 @@
   "status.load_more": "Last mer",
   "status.media_hidden": "Media skjult",
   "status.mention": "Nevn @{name}",
+  "status.more": "More",
   "status.mute_conversation": "Demp samtale",
   "status.open": "Utvid denne statusen",
   "status.pin": "Pin on profile",
diff --git a/app/javascript/mastodon/locales/oc.json b/app/javascript/mastodon/locales/oc.json
index 773f2d1e4..1e0849d95 100644
--- a/app/javascript/mastodon/locales/oc.json
+++ b/app/javascript/mastodon/locales/oc.json
@@ -82,7 +82,6 @@
   "empty_column.community": "Lo flux public local es void. Escrivètz quicòm per lo garnir !",
   "empty_column.hashtag": "I a pas encara de contengut ligat a aqueste hashtag",
   "empty_column.home": "Vòstre flux d’acuèlh es void. Visitatz {public} o utilizatz la recèrca per vos connectar a d’autras personas.",
-  "empty_column.home.inactivity": "Vòstra pagina d’acuèlh es voida. Se sètz estat inactiu per un moment, serà tornada generar per vos dins una estona.",
   "empty_column.home.public_timeline": "lo flux public",
   "empty_column.notifications": "Avètz pas encara de notificacions. Respondètz a qualqu’un per començar una conversacion.",
   "empty_column.public": "I a pas res aquí ! Escrivètz quicòm de public, o seguètz de personas d’autras instàncias per garnir lo flux public.",
@@ -160,6 +159,11 @@
   "privacy.public.short": "Public",
   "privacy.unlisted.long": "Mostrar pas dins los fluxes publics",
   "privacy.unlisted.short": "Pas-listat",
+  "relative_time.days": "fa {number}j",
+  "relative_time.hours": "fa {number}h",
+  "relative_time.just_now": "ara",
+  "relative_time.minutes": "fa {number} minutas",
+  "relative_time.seconds": "fa {number} segondas",
   "reply_indicator.cancel": "Anullar",
   "report.placeholder": "Comentaris addicionals",
   "report.submit": "Mandar",
diff --git a/app/javascript/mastodon/locales/pl.json b/app/javascript/mastodon/locales/pl.json
index 77da77e10..c0776dfc9 100644
--- a/app/javascript/mastodon/locales/pl.json
+++ b/app/javascript/mastodon/locales/pl.json
@@ -82,7 +82,6 @@
   "empty_column.community": "Lokalna oś czasu jest pusta. Napisz coś publicznie, aby zagaić!",
   "empty_column.hashtag": "Nie ma wpisów oznaczonych tym hashtagiem. Możesz napisać pierwszy!",
   "empty_column.home": "Nie śledzisz nikogo. Odwiedź publiczną oś czasu lub użyj wyszukiwarki, aby znaleźć interesujące Cię profile.",
-  "empty_column.home.inactivity": "Strumień jest pusty. Jeżeli nie było Cię tu ostatnio, zostanie on wypełniony wkrótce.",
   "empty_column.home.public_timeline": "publiczna oś czasu",
   "empty_column.notifications": "Nie masz żadnych powiadomień. Rozpocznij interakcje z innymi użytkownikami.",
   "empty_column.public": "Tu nic nie ma! Napisz coś publicznie, lub dodaj ludzi z innych instancji, aby to wyświetlić.",
@@ -160,6 +159,11 @@
   "privacy.public.short": "Publiczny",
   "privacy.unlisted.long": "Niewidoczny na publicznych osiach czasu",
   "privacy.unlisted.short": "Niewidoczny",
+  "relative_time.days": "{number}d",
+  "relative_time.hours": "{number}h",
+  "relative_time.just_now": "now",
+  "relative_time.minutes": "{number}m",
+  "relative_time.seconds": "{number}s",
   "reply_indicator.cancel": "Anuluj",
   "report.placeholder": "Dodatkowe komentarze",
   "report.submit": "Wyślij",
diff --git a/app/javascript/mastodon/locales/pt-BR.json b/app/javascript/mastodon/locales/pt-BR.json
index 2c79a7509..ddb8b83f5 100644
--- a/app/javascript/mastodon/locales/pt-BR.json
+++ b/app/javascript/mastodon/locales/pt-BR.json
@@ -82,7 +82,6 @@
   "empty_column.community": "A timeline local está vazia. Escreva algo publicamente para começar!",
   "empty_column.hashtag": "Ainda não há qualquer conteúdo com essa hashtag",
   "empty_column.home": "Você ainda não segue usuário algo. Visite a timeline {public} ou use o buscador para procurar e conhecer outros usuários.",
-  "empty_column.home.inactivity": "A sua página inicial está vazia. Se você esteve inativo por um tempo, ela irá se regenerar em alguns intantes.",
   "empty_column.home.public_timeline": "global",
   "empty_column.notifications": "Você ainda não possui notificações. Interaja com outros usuários para começar a conversar!",
   "empty_column.public": "Não há nada aqui! Escreva algo publicamente ou siga manualmente usuários de outras instâncias.",
@@ -160,16 +159,21 @@
   "privacy.public.short": "Pública",
   "privacy.unlisted.long": "Não publicar em feeds públicos",
   "privacy.unlisted.short": "Não listada",
+  "relative_time.days": "{number}d",
+  "relative_time.hours": "{number}h",
+  "relative_time.just_now": "now",
+  "relative_time.minutes": "{number}m",
+  "relative_time.seconds": "{number}s",
   "reply_indicator.cancel": "Cancelar",
   "report.placeholder": "Comentários adicionais",
   "report.submit": "Enviar",
   "report.target": "Denunciar",
   "search.placeholder": "Pesquisar",
-"search_popout.search_format": "Advanced search format",
-"search_popout.tips.hashtag": "hashtag",
-"search_popout.tips.status": "status",
+  "search_popout.search_format": "Formato de busca avançado",
+  "search_popout.tips.hashtag": "hashtag",
+  "search_popout.tips.status": "status",
   "search_popout.tips.text": "Texto simples retorna nomes de exibição, usuários e hashtags correspondentes",
-  "search_popout.tips.user": "user",
+  "search_popout.tips.user": "usuário",
   "search_results.total": "{count, number} {count, plural, one {resultado} other {resultados}}",
   "standalone.public_title": "Dê uma espiada...",
   "status.cannot_reblog": "Esta postagem não pode ser compartilhada",
@@ -179,6 +183,7 @@
   "status.load_more": "Carregar mais",
   "status.media_hidden": "Mídia escondida",
   "status.mention": "Mencionar @{name}",
+  "status.more": "More",
   "status.mute_conversation": "Silenciar conversa",
   "status.open": "Expandir",
   "status.pin": "Fixar no perfil",
diff --git a/app/javascript/mastodon/locales/pt.json b/app/javascript/mastodon/locales/pt.json
index ecd0689df..9ae140df9 100644
--- a/app/javascript/mastodon/locales/pt.json
+++ b/app/javascript/mastodon/locales/pt.json
@@ -82,7 +82,6 @@
   "empty_column.community": "Ainda não existem conteúdo local para mostrar!",
   "empty_column.hashtag": "Ainda não existe qualquer conteúdo com essa hashtag",
   "empty_column.home": "Ainda não segues qualquer utilizador. Visita {public} ou utiliza a pesquisa para procurar outros utilizadores.",
-  "empty_column.home.inactivity": "Your home feed is empty. If you have been inactive for a while, it will be regenerated for you soon.",
   "empty_column.home.public_timeline": "global",
   "empty_column.notifications": "Não tens notificações. Interage com outros utilizadores para iniciar uma conversa.",
   "empty_column.public": "Não há nada aqui! Escreve algo publicamente ou segue outros utilizadores para ver aqui os conteúdos públicos.",
@@ -160,6 +159,11 @@
   "privacy.public.short": "Público",
   "privacy.unlisted.long": "Não publicar nos feeds públicos",
   "privacy.unlisted.short": "Não listar",
+  "relative_time.days": "{number}d",
+  "relative_time.hours": "{number}h",
+  "relative_time.just_now": "now",
+  "relative_time.minutes": "{number}m",
+  "relative_time.seconds": "{number}s",
   "reply_indicator.cancel": "Cancelar",
   "report.placeholder": "Comentários adicionais",
   "report.submit": "Enviar",
@@ -179,6 +183,7 @@
   "status.load_more": "Carregar mais",
   "status.media_hidden": "Media escondida",
   "status.mention": "Mencionar @{name}",
+  "status.more": "More",
   "status.mute_conversation": "Mute conversation",
   "status.open": "Expandir",
   "status.pin": "Pin on profile",
diff --git a/app/javascript/mastodon/locales/ru.json b/app/javascript/mastodon/locales/ru.json
index bf32c820d..104b063f5 100644
--- a/app/javascript/mastodon/locales/ru.json
+++ b/app/javascript/mastodon/locales/ru.json
@@ -82,7 +82,6 @@
   "empty_column.community": "Локальная лента пуста. Напишите что-нибудь, чтобы разогреть народ!",
   "empty_column.hashtag": "Статусов с таким хэштегом еще не существует.",
   "empty_column.home": "Пока Вы ни на кого не подписаны. Полистайте {public} или используйте поиск, чтобы освоиться и завести новые знакомства.",
-  "empty_column.home.inactivity": "Ваша домашняя лента пуста. Если Вы некоторое время были неактивны, она будет сгенерирована для Вас в ближайшее время.",
   "empty_column.home.public_timeline": "публичные ленты",
   "empty_column.notifications": "У Вас еще нет уведомлений. Заведите знакомство с другими пользователями, чтобы начать разговор.",
   "empty_column.public": "Здесь ничего нет! Опубликуйте что-нибудь или подпишитесь на пользователей с других узлов, чтобы заполнить ленту.",
@@ -160,6 +159,11 @@
   "privacy.public.short": "Публичный",
   "privacy.unlisted.long": "Не показывать в лентах",
   "privacy.unlisted.short": "Скрытый",
+  "relative_time.days": "{number}d",
+  "relative_time.hours": "{number}h",
+  "relative_time.just_now": "now",
+  "relative_time.minutes": "{number}m",
+  "relative_time.seconds": "{number}s",
   "reply_indicator.cancel": "Отмена",
   "report.placeholder": "Комментарий",
   "report.submit": "Отправить",
@@ -179,6 +183,7 @@
   "status.load_more": "Показать еще",
   "status.media_hidden": "Медиаконтент скрыт",
   "status.mention": "Упомянуть @{name}",
+  "status.more": "More",
   "status.mute_conversation": "Заглушить тред",
   "status.open": "Развернуть статус",
   "status.pin": "Pin on profile",
diff --git a/app/javascript/mastodon/locales/sv.json b/app/javascript/mastodon/locales/sv.json
new file mode 100644
index 000000000..70beb70f7
--- /dev/null
+++ b/app/javascript/mastodon/locales/sv.json
@@ -0,0 +1,217 @@
+{
+  "account.block": "Blockera @{name}",
+  "account.block_domain": "Dölj allt från {domain}",
+  "account.disclaimer_full": "Informationen nedan kan spegla användarens profil ofullständigt.",
+  "account.edit_profile": "Redigera profil",
+  "account.follow": "Följ",
+  "account.followers": "Följare",
+  "account.follows": "Följer",
+  "account.follows_you": "Följer dig",
+  "account.media": "Media",
+  "account.mention": "Nämna @{name}",
+  "account.mute": "Tysta @{name}",
+  "account.posts": "Inlägg",
+  "account.report": "Rapportera @{name}",
+  "account.requested": "Inväntar godkännande. Klicka för att avbryta följförfrågan",
+  "account.share": "Dela @{name}'s profil",
+  "account.unblock": "Avblockera @{name}",
+  "account.unblock_domain": "Ta fram {domain}",
+  "account.unfollow": "Sluta följa",
+  "account.unmute": "Ta bort tystad @{name}",
+  "account.view_full_profile": "Visa hela profilen",
+  "boost_modal.combo": "Du kan trycka {combo} för att slippa denna nästa gång",
+  "bundle_column_error.body": "Något gick fel när du laddade denna komponent.",
+  "bundle_column_error.retry": "Försök igen",
+  "bundle_column_error.title": "Nätverksfel",
+  "bundle_modal_error.close": "Stäng",
+  "bundle_modal_error.message": "Något gick fel när du laddade denna komponent.",
+  "bundle_modal_error.retry": "Försök igen",
+  "column.blocks": "Blockerade användare",
+  "column.community": "Lokal tidslinje",
+  "column.favourites": "Favoriter",
+  "column.follow_requests": "Följ förfrågningar",
+  "column.home": "Hem",
+  "column.mutes": "Tystade användare",
+  "column.notifications": "Meddelanden",
+  "column.pins": "Nålade toots",
+  "column.public": "Förenad tidslinje",
+  "column_back_button.label": "Tillbaka",
+  "column_header.hide_settings": "Dölj inställningar",
+  "column_header.moveLeft_settings": "Flytta kolumnen till vänster",
+  "column_header.moveRight_settings": "Flytta kolumnen till höger",
+  "column_header.pin": "Fäst",
+  "column_header.show_settings": "Visa inställningar",
+  "column_header.unpin": "Ångra fäst",
+  "column_subheading.navigation": "Navigation",
+  "column_subheading.settings": "Inställningar",
+  "compose_form.lock_disclaimer": "Ditt konto är inte {locked}. Vemsomhelst kan följa dig och även se dina inlägg skrivna för endast dina följare.",
+  "compose_form.lock_disclaimer.lock": "låst",
+  "compose_form.placeholder": "Vad funderar du på?",
+  "compose_form.publish": "Toot",
+  "compose_form.publish_loud": "{publish}!",
+  "compose_form.sensitive": "Markera media som känslig",
+  "compose_form.spoiler": "Dölj text bakom varning",
+  "compose_form.spoiler_placeholder": "Skriv din varning här",
+  "confirmation_modal.cancel": "Ångra",
+  "confirmations.block.confirm": "Blockera",
+  "confirmations.block.message": "Är du säker att du vill blockera {name}?",
+  "confirmations.delete.confirm": "Ta bort",
+  "confirmations.delete.message": "Är du säker att du vill ta bort denna status?",
+  "confirmations.domain_block.confirm": "Blockera hela domänen",
+  "confirmations.domain_block.message": "Är du verkligen, verkligen säker på att du vill blockera hela {domain}? I de flesta fall är några riktade blockeringar eller nedtystade tillräckligt och föredras.",
+  "confirmations.mute.confirm": "Tysta",
+  "confirmations.mute.message": "Är du säker du vill tysta ner {name}?",
+  "confirmations.unfollow.confirm": "Sluta följa",
+  "confirmations.unfollow.message": "Är du säker på att du vill sluta följa {name}?",
+  "embed.instructions": "Bädda in den här statusen på din webbplats genom att kopiera koden nedan.",
+  "embed.preview": "Här ser du hur det kommer att se ut:",
+  "emoji_button.activity": "Aktivitet",
+  "emoji_button.custom": "Specialgjord",
+  "emoji_button.flags": "Flaggor",
+  "emoji_button.food": "Mat & Dryck",
+  "emoji_button.label": "Lägg till emoji",
+  "emoji_button.nature": "Natur",
+  "emoji_button.not_found": "Inga emojos!! (╯°□°)╯︵ ┻━┻",
+  "emoji_button.objects": "Objekt",
+  "emoji_button.people": "Människor",
+  "emoji_button.recent": "Ofta använda",
+  "emoji_button.search": "Sök...",
+  "emoji_button.search_results": "Sökresultat",
+  "emoji_button.symbols": "Symboler",
+  "emoji_button.travel": "Resor & Platser",
+  "empty_column.community": "Den lokala tidslinjen är tom. Skriv något offentligt för att få bollen att rulla!",
+  "empty_column.hashtag": "Det finns inget i denna hashtag ännu.",
+  "empty_column.home": "Din hemma-tidslinje är tom! Besök {public} eller använd sökning för att komma igång och träffa andra användare.",
+  "empty_column.home.inactivity": "Ditt hemmafeed är tomt. Om du har varit inaktiv ett tag kommer det att regenereras för dig snart.",
+  "empty_column.home.public_timeline": "den publika tidslinjen",
+  "empty_column.notifications": "Du har inga meddelanden än. Interagera med andra för att starta konversationen.",
+  "empty_column.public": "Det finns inget här! Skriv något offentligt, eller följ manuellt användarna från andra instanser för att fylla på det",
+  "follow_request.authorize": "Godkänn",
+  "follow_request.reject": "Avvisa",
+  "getting_started.appsshort": "Appar",
+  "getting_started.faq": "FAQ",
+  "getting_started.heading": "Kom igång",
+  "getting_started.open_source_notice": "Mastodon är programvara med öppen källkod. Du kan bidra eller rapportera problem på GitHub på {github}.",
+  "getting_started.userguide": "Användarguide",
+  "home.column_settings.advanced": "Avancerad",
+  "home.column_settings.basic": "Grundläggande",
+  "home.column_settings.filter_regex": "Filtrera ut med regelbundna uttryck",
+  "home.column_settings.show_reblogs": "Visa knuffar",
+  "home.column_settings.show_replies": "Visa svar",
+  "home.settings": "Kolumninställningar",
+  "lightbox.close": "Stäng",
+  "lightbox.next": "Nästa",
+  "lightbox.previous": "Tidigare",
+  "loading_indicator.label": "Laddar...",
+  "media_gallery.toggle_visible": "Växla synlighet",
+  "missing_indicator.label": "Hittades inte",
+  "navigation_bar.blocks": "Blockerade användare",
+  "navigation_bar.community_timeline": "Lokal tidslinje",
+  "navigation_bar.edit_profile": "Redigera profil",
+  "navigation_bar.favourites": "Favoriter",
+  "navigation_bar.follow_requests": "Följförfrågningar",
+  "navigation_bar.info": "Om denna instans",
+  "navigation_bar.logout": "Logga ut",
+  "navigation_bar.mutes": "Tystade användare",
+  "navigation_bar.pins": "Nålade inlägg (toots)",
+
+  "navigation_bar.preferences": "Inställningar",
+  "navigation_bar.public_timeline": "Förenad tidslinje",
+  "notification.favourite": "{name} favoriserade din status",
+  "notification.follow": "{name} följer dig",
+  "notification.mention": "{name} nämnde dig",
+  "notification.reblog": "{name} knuffade din status",
+  "notifications.clear": "Rensa meddelanden",
+  "notifications.clear_confirmation": "Är du säker på att du vill radera alla dina meddelanden permanent?",
+  "notifications.column_settings.alert": "Skrivbordsmeddelanden",
+  "notifications.column_settings.favourite": "Favoriter:",
+  "notifications.column_settings.follow": "Nya följare:",
+  "notifications.column_settings.mention": "Omnämningar:",
+  "notifications.column_settings.push": "Push meddelanden",
+  "notifications.column_settings.push_meta": "Denna anordning",
+  "notifications.column_settings.reblog": "Knuffar:",
+  "notifications.column_settings.show": "Visa i kolumnen",
+  "notifications.column_settings.sound": "Spela upp ljud",
+  "onboarding.done": "Klart",
+  "onboarding.next": "Nästa",
+  "onboarding.page_five.public_timelines": "Den lokala tidslinjen visar offentliga inlägg från alla på {domain}. Den förenade tidslinjen visar offentliga inlägg från alla personer på {domain} som följer. Dom här offentliga tidslinjerna är ett bra sätt att upptäcka nya människor.",
+  "onboarding.page_four.home": "Hemmatidslinjen visar inlägg från personer du följer.",
+  "onboarding.page_four.notifications": "Meddelandekolumnen visar när någon interagerar med dig.",
+  "onboarding.page_one.federation": "Mastodon är ett nätverk av oberoende servrar som ansluter för att skapa ett större socialt nätverk. Vi kallar dessa servrar instanser.",
+  "onboarding.page_one.handle": "Du är på {domain}, så din fulla hantering är {handle}",
+  "onboarding.page_one.welcome": "Välkommen till Mastodon!",
+  "onboarding.page_six.admin": "Din instansadmin är {admin}.",
+  "onboarding.page_six.almost_done": "Snart klart...",
+  "onboarding.page_six.appetoot": "Bon Appetoot!",
+  "onboarding.page_six.apps_available": "Det finns {apps} tillgängligt för iOS, Android och andra plattformar.",
+  "onboarding.page_six.github": "Mastodon är fri programvara med öppen källkod. Du kan rapportera fel, efterfråga funktioner eller bidra till koden på {github}.",
+  "onboarding.page_six.guidelines": "gemenskapsriktlinjer",
+  "onboarding.page_six.read_guidelines": "Vänligen läs {domain}'s {guidelines}!",
+  "onboarding.page_six.various_app": "mobilappar",
+  "onboarding.page_three.profile": "Redigera din profil för att ändra ditt avatar, bio och visningsnamn. Där hittar du även andra inställningar.",
+  "onboarding.page_three.search": "Använd sökfältet för att hitta personer och titta på hashtags, till exempel {illustration} och {introductions}. För att leta efter en person som inte befinner sig i detta fall använd deras fulla handhavande.",
+  "onboarding.page_two.compose": "Skriv inlägg från skrivkolumnen. Du kan ladda upp bilder, ändra integritetsinställningar och lägga till varningar med ikonerna nedan.",
+  "onboarding.skip": "Hoppa över",
+  "privacy.change": "Justera status sekretess",
+  "privacy.direct.long": "Skicka endast till nämnda användare",
+  "privacy.direct.short": "Direkt",
+  "privacy.private.long": "Skicka endast till följare",
+  "privacy.private.short": "Endast följare",
+  "privacy.public.long": "Skicka till publik tidslinje",
+  "privacy.public.short": "Publik",
+  "privacy.unlisted.long": "Skicka inte till publik tidslinje",
+  "privacy.unlisted.short": "Olistad",
+  "reply_indicator.cancel": "Ångra",
+  "report.placeholder": "Ytterligare kommentarer",
+  "report.submit": "Skicka",
+  "report.target": "Rapporterar {target}",
+  "search.placeholder": "Sök",
+  "search_popout.search_format": "Avancerat sökformat",
+  "search_popout.tips.hashtag": "hashtag",
+  "search_popout.tips.status": "status",
+  "search_popout.tips.text": "Enkel text returnerar matchande visningsnamn, användarnamn och hashtags",
+  "search_popout.tips.user": "användare",
+  "search_results.total": "{count, number} {count, plural, ett {result} andra {results}}",
+  "standalone.public_title": "En titt inuti...",
+  "status.cannot_reblog": "Detta inlägg kan inte knuffas",
+  "status.delete": "Ta bort",
+  "status.embed": "Bädda in",
+  "status.favourite": "Favorit",
+  "status.load_more": "Ladda fler",
+  "status.media_hidden": "Media dold",
+  "status.mention": "Omnämn @{name}",
+  "status.mute_conversation": "Tysta konversation",
+  "status.open": "Utvidga denna status",
+  "status.pin": "Fäst i profil",
+  "status.reblog": "Knuff",
+  "status.reblogged_by": "{name} knuffade",
+  "status.reply": "Svara",
+  "status.replyAll": "Svara på tråden",
+  "status.report": "Rapportera @{name}",
+  "status.sensitive_toggle": "Klicka för att se",
+  "status.sensitive_warning": "Känsligt innehåll",
+  "status.share": "Dela",
+  "status.show_less": "Visa mindre",
+  "status.show_more": "Visa mer",
+  "status.unmute_conversation": "Öppna konversation",
+  "status.unpin": "Ångra fäst i profil",
+  "tabs_bar.compose": "Skriv",
+  "tabs_bar.federated_timeline": "Förenad",
+  "tabs_bar.home": "Hem",
+  "tabs_bar.local_timeline": "Lokal",
+  "tabs_bar.notifications": "Meddelanden",
+  "upload_area.title": "Dra & släpp för att ladda upp",
+  "upload_button.label": "Lägg till media",
+  "upload_form.description": "Beskriv för synskadade",
+  "upload_form.undo": "Ångra",
+  "upload_progress.label": "Laddar upp...",
+  "video.close": "Stäng video",
+  "video.exit_fullscreen": "Stäng helskärm",
+  "video.expand": "Expandera video",
+  "video.fullscreen": "Helskärm",
+  "video.hide": "Dölj video",
+  "video.mute": "Tysta ljud",
+  "video.pause": "Pause",
+  "video.play": "Spela upp",
+  "video.unmute": "Spela upp ljud"
+}
diff --git a/app/javascript/mastodon/locales/th.json b/app/javascript/mastodon/locales/th.json
index 4339d1497..db3f3dd0d 100644
--- a/app/javascript/mastodon/locales/th.json
+++ b/app/javascript/mastodon/locales/th.json
@@ -82,7 +82,6 @@
   "empty_column.community": "The local timeline is empty. Write something publicly to get the ball rolling!",
   "empty_column.hashtag": "There is nothing in this hashtag yet.",
   "empty_column.home": "Your home timeline is empty! Visit {public} or use search to get started and meet other users.",
-  "empty_column.home.inactivity": "Your home feed is empty. If you have been inactive for a while, it will be regenerated for you soon.",
   "empty_column.home.public_timeline": "the public timeline",
   "empty_column.notifications": "You don't have any notifications yet. Interact with others to start the conversation.",
   "empty_column.public": "There is nothing here! Write something publicly, or manually follow users from other instances to fill it up",
@@ -160,6 +159,11 @@
   "privacy.public.short": "Public",
   "privacy.unlisted.long": "Do not post to public timelines",
   "privacy.unlisted.short": "Unlisted",
+  "relative_time.days": "{number}d",
+  "relative_time.hours": "{number}h",
+  "relative_time.just_now": "now",
+  "relative_time.minutes": "{number}m",
+  "relative_time.seconds": "{number}s",
   "reply_indicator.cancel": "Cancel",
   "report.placeholder": "Additional comments",
   "report.submit": "Submit",
@@ -179,6 +183,7 @@
   "status.load_more": "Load more",
   "status.media_hidden": "Media hidden",
   "status.mention": "Mention @{name}",
+  "status.more": "More",
   "status.mute_conversation": "Mute conversation",
   "status.open": "Expand this status",
   "status.pin": "Pin on profile",
diff --git a/app/javascript/mastodon/locales/tr.json b/app/javascript/mastodon/locales/tr.json
index afc6383b4..cdd3581da 100644
--- a/app/javascript/mastodon/locales/tr.json
+++ b/app/javascript/mastodon/locales/tr.json
@@ -82,7 +82,6 @@
   "empty_column.community": "Yerel zaman tüneliniz boş. Daha fazla eğlence için herkese açık bir gönderi paylaşın.",
   "empty_column.hashtag": "Henüz bu hashtag’e sahip hiçbir gönderi yok.",
   "empty_column.home": "Henüz kimseyi takip etmiyorsunuz. {public} ziyaret edebilir veya arama kısmını kullanarak diğer kullanıcılarla iletişime geçebilirsiniz.",
-  "empty_column.home.inactivity": "Your home feed is empty. If you have been inactive for a while, it will be regenerated for you soon.",
   "empty_column.home.public_timeline": "herkese açık zaman tüneli",
   "empty_column.notifications": "Henüz hiçbir bildiriminiz yok. Diğer insanlarla sobhet edebilmek için etkileşime geçebilirsiniz.",
   "empty_column.public": "Burada hiçbir gönderi yok! Herkese açık bir şeyler yazın, veya diğer sunucudaki insanları takip ederek bu alanın dolmasını sağlayın",
@@ -160,6 +159,11 @@
   "privacy.public.short": "Herkese açık",
   "privacy.unlisted.long": "Herkese açık zaman tüneline gönderme",
   "privacy.unlisted.short": "Listelenmemiş",
+  "relative_time.days": "{number}d",
+  "relative_time.hours": "{number}h",
+  "relative_time.just_now": "now",
+  "relative_time.minutes": "{number}m",
+  "relative_time.seconds": "{number}s",
   "reply_indicator.cancel": "İptal",
   "report.placeholder": "Ek yorumlar",
   "report.submit": "Gönder",
@@ -179,6 +183,7 @@
   "status.load_more": "Daha fazla",
   "status.media_hidden": "Gizli görsel",
   "status.mention": "Bahset @{name}",
+  "status.more": "More",
   "status.mute_conversation": "Mute conversation",
   "status.open": "Bu gönderiyi genişlet",
   "status.pin": "Pin on profile",
diff --git a/app/javascript/mastodon/locales/uk.json b/app/javascript/mastodon/locales/uk.json
index d0aae032b..930529f15 100644
--- a/app/javascript/mastodon/locales/uk.json
+++ b/app/javascript/mastodon/locales/uk.json
@@ -82,7 +82,6 @@
   "empty_column.community": "Локальна стрічка пуста. Напишіть щось, щоб розігріти народ!",
   "empty_column.hashtag": "Дописів з цим хештегом поки не існує.",
   "empty_column.home": "Ви поки ні на кого не підписані. Погортайте {public}, або скористуйтесь пошуком, щоб освоїтися та познайомитися з іншими користувачами.",
-  "empty_column.home.inactivity": "Ваша домашня стрічка пуста. Якщо ви були неактивні протягом деякого часу, вона скоро буде згенерована для Вас.",
   "empty_column.home.public_timeline": "публічні стрічки",
   "empty_column.notifications": "У вас ще немає сповіщень. Переписуйтесь з іншими користувачами, щоб почати розмову.",
   "empty_column.public": "Тут поки нічого немає! Опублікуйте щось, або вручну підпишіться на користувачів інших інстанцій, щоб заповнити стрічку.",
@@ -160,6 +159,11 @@
   "privacy.public.short": "Публічний",
   "privacy.unlisted.long": "Не показувати у публічних стрічках",
   "privacy.unlisted.short": "Прихований",
+  "relative_time.days": "{number}d",
+  "relative_time.hours": "{number}h",
+  "relative_time.just_now": "now",
+  "relative_time.minutes": "{number}m",
+  "relative_time.seconds": "{number}s",
   "reply_indicator.cancel": "Відмінити",
   "report.placeholder": "Додаткові коментарі",
   "report.submit": "Відправити",
@@ -179,6 +183,7 @@
   "status.load_more": "Завантажити більше",
   "status.media_hidden": "Медіаконтент приховано",
   "status.mention": "Згадати",
+  "status.more": "More",
   "status.mute_conversation": "Заглушити діалог",
   "status.open": "Розгорнути допис",
   "status.pin": "Pin on profile",
diff --git a/app/javascript/mastodon/locales/zh-CN.json b/app/javascript/mastodon/locales/zh-CN.json
index e0ffc16df..827c815cf 100644
--- a/app/javascript/mastodon/locales/zh-CN.json
+++ b/app/javascript/mastodon/locales/zh-CN.json
@@ -82,7 +82,6 @@
   "empty_column.community": "本站时间轴暂时未有内容,快嘟几个来抢头香啊!",
   "empty_column.hashtag": "这个标签暂时未有内容。",
   "empty_column.home": "你还没有关注任何用户。快看看{public},向其他用户搭讪吧。",
-  "empty_column.home.inactivity": "你的主页暂时没有内容。也许你太久没有来了?如果是这样,文章会慢慢出来,请稍后再看。",
   "empty_column.home.public_timeline": "公共时间轴",
   "empty_column.notifications": "你没有任何通知纪录,快向其他用户搭讪吧。",
   "empty_column.public": "跨站公共时间轴暂时没有内容!快写一些公共的嘟文,或者关注另一些服务器实例的用户吧!你和本站、友站的交流,将决定这里出现的内容。",
@@ -160,6 +159,11 @@
   "privacy.public.short": "公共",
   "privacy.unlisted.long": "公开,但不在公共时间轴显示",
   "privacy.unlisted.short": "公开",
+  "relative_time.days": "{number}d",
+  "relative_time.hours": "{number}h",
+  "relative_time.just_now": "now",
+  "relative_time.minutes": "{number}m",
+  "relative_time.seconds": "{number}s",
   "reply_indicator.cancel": "取消",
   "report.placeholder": "额外消息",
   "report.submit": "提交",
@@ -179,6 +183,7 @@
   "status.load_more": "加载更多",
   "status.media_hidden": "隐藏媒体内容",
   "status.mention": "提及 @{name}",
+  "status.more": "More",
   "status.mute_conversation": "静音对话",
   "status.open": "展开嘟文",
   "status.pin": "置顶到资料",
diff --git a/app/javascript/mastodon/locales/zh-HK.json b/app/javascript/mastodon/locales/zh-HK.json
index 053e971aa..f6f56fee1 100644
--- a/app/javascript/mastodon/locales/zh-HK.json
+++ b/app/javascript/mastodon/locales/zh-HK.json
@@ -82,7 +82,6 @@
   "empty_column.community": "本站時間軸暫時未有內容,快文章來搶頭香啊!",
   "empty_column.hashtag": "這個標籤暫時未有內容。",
   "empty_column.home": "你還沒有關注任何用戶。快看看{public},向其他用戶搭訕吧。",
-  "empty_column.home.inactivity": "你的主頁暫時沒有內容。也許你太久沒有來?如果是這樣,文章會慢慢出來,請稍後再看。",
   "empty_column.home.public_timeline": "公共時間軸",
   "empty_column.notifications": "你沒有任何通知紀錄,快向其他用戶搭訕吧。",
   "empty_column.public": "跨站時間軸暫時沒有內容!快寫一些公共的文章,或者關注另一些服務站的用戶吧!你和本站、友站的交流,將決定這裏出現的內容。",
@@ -160,6 +159,11 @@
   "privacy.public.short": "公共",
   "privacy.unlisted.long": "公開,但不在公共時間軸顯示",
   "privacy.unlisted.short": "公開",
+  "relative_time.days": "{number}d",
+  "relative_time.hours": "{number}h",
+  "relative_time.just_now": "now",
+  "relative_time.minutes": "{number}m",
+  "relative_time.seconds": "{number}s",
   "reply_indicator.cancel": "取消",
   "report.placeholder": "額外訊息",
   "report.submit": "提交",
@@ -179,6 +183,7 @@
   "status.load_more": "載入更多",
   "status.media_hidden": "隱藏媒體內容",
   "status.mention": "提及 @{name}",
+  "status.more": "More",
   "status.mute_conversation": "靜音對話",
   "status.open": "展開文章",
   "status.pin": "置頂到資料頁",
diff --git a/app/javascript/mastodon/locales/zh-TW.json b/app/javascript/mastodon/locales/zh-TW.json
index a22d66fa1..1f43c6a20 100644
--- a/app/javascript/mastodon/locales/zh-TW.json
+++ b/app/javascript/mastodon/locales/zh-TW.json
@@ -82,7 +82,6 @@
   "empty_column.community": "本地時間軸是空的。公開寫點什麼吧!",
   "empty_column.hashtag": "這個主題標籤下什麼都沒有。",
   "empty_column.home": "你還沒關注任何人。造訪{public}或利用搜尋功能找到其他用者。",
-  "empty_column.home.inactivity": "你家的訊息摘要是空的。如果你很久沒活動了,很快它就會重新產生。",
   "empty_column.home.public_timeline": "公開時間軸",
   "empty_column.notifications": "還沒有任何通知。和別的使用者互動來開始對話。",
   "empty_column.public": "這裡什麼都沒有!公開寫些什麼,或是關注其他副本的使用者。",
@@ -160,6 +159,11 @@
   "privacy.public.short": "公開貼",
   "privacy.unlisted.long": "不要貼到公開時間軸",
   "privacy.unlisted.short": "不列出來",
+  "relative_time.days": "{number}d",
+  "relative_time.hours": "{number}h",
+  "relative_time.just_now": "now",
+  "relative_time.minutes": "{number}m",
+  "relative_time.seconds": "{number}s",
   "reply_indicator.cancel": "取消",
   "report.placeholder": "更多訊息",
   "report.submit": "送出",
@@ -179,6 +183,7 @@
   "status.load_more": "載入更多",
   "status.media_hidden": "媒體已隱藏",
   "status.mention": "提到 @{name}",
+  "status.more": "More",
   "status.mute_conversation": "消音對話",
   "status.open": "展開這個狀態",
   "status.pin": "置頂到個人資訊頁",
diff --git a/app/javascript/mastodon/middleware/sounds.js b/app/javascript/mastodon/middleware/sounds.js
index 372e7c835..3d1e3eaba 100644
--- a/app/javascript/mastodon/middleware/sounds.js
+++ b/app/javascript/mastodon/middleware/sounds.js
@@ -12,7 +12,11 @@ const createAudio = sources => {
 const play = audio => {
   if (!audio.paused) {
     audio.pause();
-    audio.fastSeek(0);
+    if (typeof audio.fastSeek === 'function') {
+      audio.fastSeek(0);
+    } else {
+      audio.seek(0);
+    }
   }
 
   audio.play();
diff --git a/app/javascript/mastodon/reducers/timelines.js b/app/javascript/mastodon/reducers/timelines.js
index c3f117647..bee4c4ef9 100644
--- a/app/javascript/mastodon/reducers/timelines.js
+++ b/app/javascript/mastodon/reducers/timelines.js
@@ -75,15 +75,9 @@ const updateTimeline = (state, timeline, status, references) => {
   }));
 };
 
-const deleteStatus = (state, id, accountId, references, reblogOf) => {
+const deleteStatus = (state, id, accountId, references) => {
   state.keySeq().forEach(timeline => {
-    state = state.updateIn([timeline, 'items'], list => {
-      if (reblogOf && !list.includes(reblogOf)) {
-        return list.map(item => item === id ? reblogOf : item);
-      } else {
-        return list.filterNot(item => item === id);
-      }
-    });
+    state = state.updateIn([timeline, 'items'], list => list.filterNot(item => item === id));
   });
 
   // Remove reblogs of deleted status
diff --git a/app/javascript/styles/application.scss b/app/javascript/styles/application.scss
index e35937be1..efd34393f 100644
--- a/app/javascript/styles/application.scss
+++ b/app/javascript/styles/application.scss
@@ -1,20 +1,23 @@
-@import 'mixins';
-@import 'variables';
+@import 'mastodon/mixins';
+@import 'mastodon/variables';
 @import 'variables-glitch';
+@import 'fonts/roboto';
+@import 'fonts/roboto-mono';
+@import 'fonts/montserrat';
 
-@import 'reset';
-@import 'basics';
-@import 'containers';
-@import 'lists';
-@import 'footer';
-@import 'compact_header';
-@import 'landing_strip';
-@import 'forms';
-@import 'accounts';
-@import 'stream_entries';
-@import 'components';
-@import 'emoji_picker';
-@import 'about';
-@import 'tables';
-@import 'admin';
-@import 'rtl';
+@import 'mastodon/reset';
+@import 'mastodon/basics';
+@import 'mastodon/containers';
+@import 'mastodon/lists';
+@import 'mastodon/footer';
+@import 'mastodon/compact_header';
+@import 'mastodon/landing_strip';
+@import 'mastodon/forms';
+@import 'mastodon/accounts';
+@import 'mastodon/stream_entries';
+@import 'mastodon/components';
+@import 'mastodon/emoji_picker';
+@import 'mastodon/about';
+@import 'mastodon/tables';
+@import 'mastodon/admin';
+@import 'mastodon/rtl';
diff --git a/app/javascript/styles/_mixins.scss b/app/javascript/styles/mastodon/_mixins.scss
index 7412991b8..7412991b8 100644
--- a/app/javascript/styles/_mixins.scss
+++ b/app/javascript/styles/mastodon/_mixins.scss
diff --git a/app/javascript/styles/about.scss b/app/javascript/styles/mastodon/about.scss
index 4ec689427..4ec689427 100644
--- a/app/javascript/styles/about.scss
+++ b/app/javascript/styles/mastodon/about.scss
diff --git a/app/javascript/styles/accounts.scss b/app/javascript/styles/mastodon/accounts.scss
index b00dd8c1e..b00dd8c1e 100644
--- a/app/javascript/styles/accounts.scss
+++ b/app/javascript/styles/mastodon/accounts.scss
diff --git a/app/javascript/styles/admin.scss b/app/javascript/styles/mastodon/admin.scss
index 87bc710af..87bc710af 100644
--- a/app/javascript/styles/admin.scss
+++ b/app/javascript/styles/mastodon/admin.scss
diff --git a/app/javascript/styles/basics.scss b/app/javascript/styles/mastodon/basics.scss
index 43c32c8bc..b5d77ff63 100644
--- a/app/javascript/styles/basics.scss
+++ b/app/javascript/styles/mastodon/basics.scss
@@ -30,7 +30,7 @@ body {
   }
 
   &.app-body {
-    position: fixed;
+    position: absolute;
     width: 100%;
     height: 100%;
     padding: 0;
diff --git a/app/javascript/styles/boost.scss b/app/javascript/styles/mastodon/boost.scss
index b07b72f8e..b07b72f8e 100644
--- a/app/javascript/styles/boost.scss
+++ b/app/javascript/styles/mastodon/boost.scss
diff --git a/app/javascript/styles/compact_header.scss b/app/javascript/styles/mastodon/compact_header.scss
index 90d98cc8c..90d98cc8c 100644
--- a/app/javascript/styles/compact_header.scss
+++ b/app/javascript/styles/mastodon/compact_header.scss
diff --git a/app/javascript/styles/components.scss b/app/javascript/styles/mastodon/components.scss
index 119e9feb0..6fe179581 100644
--- a/app/javascript/styles/components.scss
+++ b/app/javascript/styles/mastodon/components.scss
@@ -551,6 +551,14 @@
   overflow: visible;
   white-space: pre-wrap;
 
+  &.status__content--with-spoiler {
+    white-space: normal;
+
+    .status__content__text {
+      white-space: pre-wrap;
+    }
+  }
+
   .emojione {
     width: 18px;
     height: 18px;
diff --git a/app/javascript/styles/containers.scss b/app/javascript/styles/mastodon/containers.scss
index af2589e23..af2589e23 100644
--- a/app/javascript/styles/containers.scss
+++ b/app/javascript/styles/mastodon/containers.scss
diff --git a/app/javascript/styles/emoji_picker.scss b/app/javascript/styles/mastodon/emoji_picker.scss
index 2b46d30fc..2b46d30fc 100644
--- a/app/javascript/styles/emoji_picker.scss
+++ b/app/javascript/styles/mastodon/emoji_picker.scss
diff --git a/app/javascript/styles/footer.scss b/app/javascript/styles/mastodon/footer.scss
index 2d953b34e..2d953b34e 100644
--- a/app/javascript/styles/footer.scss
+++ b/app/javascript/styles/mastodon/footer.scss
diff --git a/app/javascript/styles/forms.scss b/app/javascript/styles/mastodon/forms.scss
index 61fcf286f..61fcf286f 100644
--- a/app/javascript/styles/forms.scss
+++ b/app/javascript/styles/mastodon/forms.scss
diff --git a/app/javascript/styles/landing_strip.scss b/app/javascript/styles/mastodon/landing_strip.scss
index 15ff84912..15ff84912 100644
--- a/app/javascript/styles/landing_strip.scss
+++ b/app/javascript/styles/mastodon/landing_strip.scss
diff --git a/app/javascript/styles/lists.scss b/app/javascript/styles/mastodon/lists.scss
index 6019cd800..6019cd800 100644
--- a/app/javascript/styles/lists.scss
+++ b/app/javascript/styles/mastodon/lists.scss
diff --git a/app/javascript/styles/reset.scss b/app/javascript/styles/mastodon/reset.scss
index cc5ba9d7c..cc5ba9d7c 100644
--- a/app/javascript/styles/reset.scss
+++ b/app/javascript/styles/mastodon/reset.scss
diff --git a/app/javascript/styles/rtl.scss b/app/javascript/styles/mastodon/rtl.scss
index 67bfa8a38..67bfa8a38 100644
--- a/app/javascript/styles/rtl.scss
+++ b/app/javascript/styles/mastodon/rtl.scss
diff --git a/app/javascript/styles/stream_entries.scss b/app/javascript/styles/mastodon/stream_entries.scss
index 453070b7c..453070b7c 100644
--- a/app/javascript/styles/stream_entries.scss
+++ b/app/javascript/styles/mastodon/stream_entries.scss
diff --git a/app/javascript/styles/tables.scss b/app/javascript/styles/mastodon/tables.scss
index ad46f5f9f..ad46f5f9f 100644
--- a/app/javascript/styles/tables.scss
+++ b/app/javascript/styles/mastodon/tables.scss
diff --git a/app/javascript/styles/variables.scss b/app/javascript/styles/mastodon/variables.scss
index 090706ff5..090706ff5 100644
--- a/app/javascript/styles/variables.scss
+++ b/app/javascript/styles/mastodon/variables.scss
diff --git a/app/lib/activitypub/activity.rb b/app/lib/activitypub/activity.rb
index 9688f57a6..01144f595 100644
--- a/app/lib/activitypub/activity.rb
+++ b/app/lib/activitypub/activity.rb
@@ -67,9 +67,14 @@ class ActivityPub::Activity
   end
 
   def distribute(status)
+    crawl_links(status)
+
+    # Only continue if the status is supposed to have
+    # arrived in real-time
+    return unless @options[:override_timestamps]
+
     notify_about_reblog(status) if reblog_of_local_account?(status)
     notify_about_mentions(status)
-    crawl_links(status)
     distribute_to_followers(status)
   end
 
diff --git a/app/lib/feed_manager.rb b/app/lib/feed_manager.rb
index 9a64d58bd..39d3333da 100644
--- a/app/lib/feed_manager.rb
+++ b/app/lib/feed_manager.rb
@@ -56,7 +56,17 @@ class FeedManager
     falloff_rank = FeedManager::REBLOG_FALLOFF - 1
     falloff_range = redis.zrevrange(timeline_key, falloff_rank, falloff_rank, with_scores: true)
     falloff_score = falloff_range&.first&.last&.to_i || 0
-    redis.zremrangebyscore(reblog_key, 0, falloff_score)
+
+    # Get any reblogs we might have to clean up after.
+    redis.zrangebyscore(reblog_key, 0, falloff_score).each do |reblogged_id|
+      # Remove it from the set of reblogs we're tracking *first* to avoid races.
+      redis.zrem(reblog_key, reblogged_id)
+      # Just drop any set we might have created to track additional reblogs.
+      # This means that if this reblog is deleted, we won't automatically insert
+      # another reblog, but also that any new reblog can be inserted into the
+      # feed.
+      redis.del(key(type, account_id, "reblogs:#{reblogged_id}"))
+    end
   end
 
   def push_update_required?(timeline_type, account_id)
@@ -183,23 +193,28 @@ class FeedManager
     reblog_key   = key(timeline_type, account.id, 'reblogs')
 
     if status.reblog?
-      reblog_set_key = key(timeline_type, account.id, "reblogs:#{status.reblog_of_id}")
-
       # If the original status or a reblog of it is within
       # REBLOG_FALLOFF statuses from the top, do not re-insert it into
       # the feed
       rank = redis.zrevrank(timeline_key, status.reblog_of_id)
 
-      redis.sadd(reblog_set_key, status.reblog_of_id) unless rank.nil?
-      redis.sadd(reblog_set_key, status.id)
-
       return false if !rank.nil? && rank < FeedManager::REBLOG_FALLOFF
 
       reblog_rank = redis.zrevrank(reblog_key, status.reblog_of_id)
-      return false unless reblog_rank.nil?
-
-      redis.zadd(timeline_key, status.id, status.id)
-      redis.zadd(reblog_key, status.id, status.reblog_of_id)
+      if reblog_rank.nil?
+        # This is not something we've already seen reblogged, so we
+        # can just add it to the feed (and note that we're
+        # reblogging it).
+        redis.zadd(timeline_key, status.id, status.id)
+        redis.zadd(reblog_key, status.id, status.reblog_of_id)
+      else
+        # Another reblog of the same status was already in the
+        # REBLOG_FALLOFF most recent statuses, so we note that this
+        # is an "extra" reblog, by storing it in reblog_set_key.
+        reblog_set_key = key(timeline_type, account.id, "reblogs:#{status.reblog_of_id}")
+        redis.sadd(reblog_set_key, status.id)
+        return false
+      end
     else
       redis.zadd(timeline_key, status.id, status.id)
     end
@@ -213,23 +228,21 @@ class FeedManager
   # do so if appropriate.
   def remove_from_feed(timeline_type, account, status)
     timeline_key = key(timeline_type, account.id)
-    reblog_key   = key(timeline_type, account.id, 'reblogs')
 
     if status.reblog?
       # 1. If the reblogging status is not in the feed, stop.
       status_rank = redis.zrevrank(timeline_key, status.id)
       return false if status_rank.nil?
 
-      # 2. Remove the reblogged status from the `:reblogs` zset.
-      redis.zrem(reblog_key, status.reblog_of_id)
-
-      # 3. Remove reblog from set of this status's reblogs, and
-      # re-insert another reblog or original into the feed if
-      # one remains in the set
+      # 2. Remove reblog from set of this status's reblogs.
       reblog_set_key = key(timeline_type, account.id, "reblogs:#{status.reblog_of_id}")
 
       redis.srem(reblog_set_key, status.id)
-      other_reblog = redis.srandmember(reblog_set_key)
+      # 3. Re-insert another reblog or original into the feed if one
+      # remains in the set. We could pick a random element, but this
+      # set should generally be small, and it seems ideal to show the
+      # oldest potential such reblog.
+      other_reblog = redis.smembers(reblog_set_key).map(&:to_i).sort.first
 
       redis.zadd(timeline_key, other_reblog, other_reblog) if other_reblog
 
diff --git a/app/lib/ostatus/activity/creation.rb b/app/lib/ostatus/activity/creation.rb
index a1ab522e2..3418e2420 100644
--- a/app/lib/ostatus/activity/creation.rb
+++ b/app/lib/ostatus/activity/creation.rb
@@ -56,7 +56,7 @@ class OStatus::Activity::Creation < OStatus::Activity::Base
     Rails.logger.debug "Queuing remote status #{status.id} (#{id}) for distribution"
 
     LinkCrawlWorker.perform_async(status.id) unless status.spoiler_text?
-    DistributionWorker.perform_async(status.id)
+    DistributionWorker.perform_async(status.id) if @options[:override_timestamps]
 
     status
   end
diff --git a/app/services/fetch_link_card_service.rb b/app/services/fetch_link_card_service.rb
index 7029c4d75..14c21b6cc 100644
--- a/app/services/fetch_link_card_service.rb
+++ b/app/services/fetch_link_card_service.rb
@@ -3,7 +3,7 @@
 class FetchLinkCardService < BaseService
   URL_PATTERN = %r{
     (                                                                                                 #   $1 URL
-      (https?:\/\/)?                                                                                  #   $2 Protocol (optional)
+      (https?:\/\/)                                                                                   #   $2 Protocol (required)
       (#{Twitter::Regex[:valid_domain]})                                                              #   $3 Domain(s)
       (?::(#{Twitter::Regex[:valid_port_number]}))?                                                   #   $4 Port number (optional)
       (/#{Twitter::Regex[:valid_url_path]}*)?                                                         #   $5 URL Path and anchor
diff --git a/app/views/user_mailer/confirmation_instructions.sv.html.erb b/app/views/user_mailer/confirmation_instructions.sv.html.erb
new file mode 100644
index 000000000..e0ad611a7
--- /dev/null
+++ b/app/views/user_mailer/confirmation_instructions.sv.html.erb
@@ -0,0 +1,15 @@
+<p>Välkommen <%= @resource.email %> !</p>
+
+<p>Du har precis startat upp ett konto på <%= @instance %>.</p>
+
+<p>För att bekräfta din inskrift, vänligen klicka på följande länk : <br>
+<%= link_to 'Confirm my account', confirmation_url(@resource, confirmation_token: @token) %></p>
+
+<p>Om länken ovan inte fungerar, kopiera och klistra in den här webbadressen i adressfältet: <br>
+<span><%= confirmation_url(@resource, confirmation_token: @token) %></span>
+
+<p>Vänligen kolla även våra <%= link_to 'terms and conditions', terms_url %>.</p>
+
+<p>Vänliga hälsningar,<p>
+
+<p>Teamet på <%= @instance %></p>
diff --git a/app/views/user_mailer/confirmation_instructions.sv.text.erb b/app/views/user_mailer/confirmation_instructions.sv.text.erb
new file mode 100644
index 000000000..64ffb9799
--- /dev/null
+++ b/app/views/user_mailer/confirmation_instructions.sv.text.erb
@@ -0,0 +1,12 @@
+Välkommen <%= @resource.email %> !
+
+Du har precis skapat ett konto på <%= @instance %>.
+
+För att bekräfta din inskrift, vänligen klicka på följande länk :
+<%= confirmation_url(@resource, confirmation_token: @token) %>
+
+Vänligen läs även våra användarvillkor <%= terms_url %>
+
+Vänliga hälsningar,
+
+Teamet på <%= @instance %>
diff --git a/app/views/user_mailer/password_change.sv.html.erb b/app/views/user_mailer/password_change.sv.html.erb
new file mode 100644
index 000000000..f6168c638
--- /dev/null
+++ b/app/views/user_mailer/password_change.sv.html.erb
@@ -0,0 +1,3 @@
+<p>Hej <%= @resource.email %>!</p>
+
+<p>Vi kontaktar dig för att meddela dig att ditt lösenord på <%= @instance %> har blivit ändrat.</p>
diff --git a/app/views/user_mailer/password_change.sv.text.erb b/app/views/user_mailer/password_change.sv.text.erb
new file mode 100644
index 000000000..b6df73226
--- /dev/null
+++ b/app/views/user_mailer/password_change.sv.text.erb
@@ -0,0 +1,3 @@
+Hej <%= @resource.email %>!
+
+Vi kontaktar dig för att meddela dig att ditt lösenord på <%= @instance %> har blivit ändrat.
diff --git a/app/views/user_mailer/reset_password_instructions.sv.html.erb b/app/views/user_mailer/reset_password_instructions.sv.html.erb
new file mode 100644
index 000000000..f38d2a39f
--- /dev/null
+++ b/app/views/user_mailer/reset_password_instructions.sv.html.erb
@@ -0,0 +1,8 @@
+<p>Hej <%= @resource.email %>!</p>
+
+<p>SNågon har begärt en länk för att ändra ditt lösenord på <%= @instance %>. Du kan göra det genom länken nedan.</p>
+
+<p><%= link_to 'Change my password', edit_password_url(@resource, reset_password_token: @token) %></p>
+
+<p>Om du inte begärt detta, ignorerar du det här e-postmeddelandet.</p>
+<p>Ditt lösenord ändras inte förrän du öppnar länken ovan och skapar en ny.</p>
diff --git a/app/views/user_mailer/reset_password_instructions.sv.text.erb b/app/views/user_mailer/reset_password_instructions.sv.text.erb
new file mode 100644
index 000000000..946426119
--- /dev/null
+++ b/app/views/user_mailer/reset_password_instructions.sv.text.erb
@@ -0,0 +1,8 @@
+Hej <%= @resource.email %>!
+
+Någon har begärt en länk för att ändra ditt lösenord på <%= @instance %>. Du kan göra det genom länken nedan.
+
+<%= edit_password_url(@resource, reset_password_token: @token) %>
+
+Om du inte begärt detta, ignorerar du det här e-postmeddelandet.
+Ditt lösenord ändras inte förrän du öppnar länken ovan och skapar ett nytt.
diff --git a/app/workers/scheduler/feed_cleanup_scheduler.rb b/app/workers/scheduler/feed_cleanup_scheduler.rb
index 222f5ed84..cfa2d31a4 100644
--- a/app/workers/scheduler/feed_cleanup_scheduler.rb
+++ b/app/workers/scheduler/feed_cleanup_scheduler.rb
@@ -5,18 +5,36 @@ class Scheduler::FeedCleanupScheduler
   include Sidekiq::Worker
 
   def perform
+    reblogged_id_sets = {}
+    feedmanager = FeedManager.instance
+
+    redis.pipelined do
+      inactive_user_ids.each do |account_id|
+        redis.del(feedmanager.key(:home, account_id))
+        reblog_key = feedmanager.key(:home, account_id, 'reblogs')
+        # We collect a future for this: we don't block while getting
+        # it, but we can iterate over it later.
+        reblogged_id_sets[account_id] = redis.zrange(reblog_key, 0, -1)
+        redis.del(reblog_key)
+      end
+    end
+
+    # Remove all of the reblog tracking keys we just removed the
+    # references to.
     redis.pipelined do
-      inactive_users.each do |account_id|
-        redis.del(FeedManager.instance.key(:home, account_id))
-        redis.del(FeedManager.instance.key(:home, account_id, 'reblogs'))
+      reblogged_id_sets.each do |account_id, future|
+        future.value.each do |reblogged_id|
+          reblog_set_key = feedmanager.key(:home, account_id, "reblogs:#{reblogged_id}")
+          redis.del(reblog_set_key)
+        end
       end
     end
   end
 
   private
 
-  def inactive_users
-    @inactive_users ||= User.confirmed.inactive.pluck(:account_id)
+  def inactive_user_ids
+    @inactive_user_ids ||= User.confirmed.inactive.pluck(:account_id)
   end
 
   def redis
diff --git a/config/application.rb b/config/application.rb
index 4e8a5875d..b54ea1c40 100644
--- a/config/application.rb
+++ b/config/application.rb
@@ -55,6 +55,7 @@ module Mastodon
       :pt,
       :'pt-BR',
       :ru,
+      :sv,
       :th,
       :tr,
       :uk,
diff --git a/config/database.yml b/config/database.yml
index f74635a36..82e560515 100644
--- a/config/database.yml
+++ b/config/database.yml
@@ -6,7 +6,7 @@ default: &default
 
 development:
   <<: *default
-  database: mastodon_development
+  database: <%= ENV['DB_NAME'] || 'mastodon_development' %>
   username: <%= ENV['DB_USER'] %>
   password: <%= ENV['DB_PASS'] %>
   host: <%= ENV['DB_HOST'] %>
@@ -17,7 +17,7 @@ development:
 # Do not set this db to the same as development or production.
 test:
   <<: *default
-  database: mastodon_test<%= ENV['TEST_ENV_NUMBER'] %>
+  database: <%= ENV['DB_NAME'] || 'mastodon' %>_test<%= ENV['TEST_ENV_NUMBER'] %>
   username: <%= ENV['DB_USER'] %>
   password: <%= ENV['DB_PASS'] %>
   host: <%= ENV['DB_HOST'] %>
diff --git a/config/locales/de.yml b/config/locales/de.yml
index a54d9734f..169af50ff 100644
--- a/config/locales/de.yml
+++ b/config/locales/de.yml
@@ -1,8 +1,8 @@
 ---
 de:
   about:
-    about_mastodon_html: Mastodon ist ein soziales Netzwerk. Es basiert auf offenen Web-Protokollen und freier, quelloffener Software. Es ist dezentral (so wie E-Mail!).
     about_hashtag_html: Dies sind öffentliche Beiträge, die mit <strong>#%{hashtag}</strong> getaggt wurden. Wenn du ein Konto irgendwo im Fediversum besitzt, kannst du mit ihnen interagieren.
+    about_mastodon_html: Mastodon ist ein soziales Netzwerk. Es basiert auf offenen Web-Protokollen und freier, quelloffener Software. Es ist dezentral (so wie E-Mail!).
     about_this: Über diese Instanz
     closed_registrations: Die Registrierung auf dieser Instanz ist momentan geschlossen. Aber du kannst dein Konto auch auf einer anderen Instanz erstellen! Von dort hast du genauso Zugriff auf das Mastodon-Netzwerk.
     contact: Kontakt
@@ -50,6 +50,13 @@ de:
       admin: Admin
     unfollow: Entfolgen
   admin:
+    account_moderation_notes:
+      account: Moderator*in
+      create: Erstellen
+      created_at: Datum
+      created_msg: Moderationsnotiz erfolgreich erstellt!
+      delete: Löschen
+      destroyed_msg: Moderationsnotiz erfolgreich gelöscht!
     accounts:
       are_you_sure: Bist du sicher?
       confirm: Bestätigen
@@ -110,13 +117,6 @@ de:
       unsubscribe: Abbestellen
       username: Profilname
       web: Web
-    account_moderation_notes:
-      account: Moderator*in
-      created_at: Datum
-      create: Erstellen
-      created_msg: Moderationsnotiz erfolgreich erstellt!
-      delete: Löschen
-      destroyed_msg: Moderationsnotiz erfolgreich gelöscht!
     custom_emojis:
       copied_msg: Eine lokale Kopie des Emojis wurde erstellt
       copy: Kopieren
diff --git a/config/locales/devise.sv.yml b/config/locales/devise.sv.yml
new file mode 100644
index 000000000..3ac0c6d10
--- /dev/null
+++ b/config/locales/devise.sv.yml
@@ -0,0 +1,61 @@
+---
+sv:
+  devise:
+    confirmations:
+      confirmed: Din e-postadress har bekräftats.
+      send_instructions: Du kommer att få ett mail med instruktioner för hur du bekräftar din e-postadress om några minuter. Kontrollera din spammapp om du inte fick det här e-postmeddelandet.
+      send_paranoid_instructions: Om din e-postadress finns i vår databas får du ett mail med instruktioner för hur du bekräftar din e-postadress inom några minuter. Kontrollera din spammapp om du inte fick det här e-postmeddelandet.
+    failure:
+      already_authenticated: Du är redan inloggad.
+      inactive: Ditt konto är inte aktiverat än..
+      invalid: Ogiltigt %{authentication_keys} eller lösenord.
+      last_attempt: Du har ytterligare ett försök innan ditt konto blir låst.
+      locked: Ditt konto är låst.
+      not_found_in_database: Ogiltigt %{authentication_keys} eller lösenord.
+      timeout: Din session löpte ut. Vänligen logga in igen för att fortsätta.
+      unauthenticated: Du måste logga in eller registrera dig innan du fortsätter.
+      unconfirmed: Du måste bekräfta din e-postadress innan du fortsätter.
+    mailer:
+      confirmation_instructions:
+        subject: 'Mastodon: Bekräftelsesinstruktioner för %{instance}'
+      password_change:
+        subject: 'Mastodon: Lösenord ändrat'
+      reset_password_instructions:
+        subject: 'Mastodon: Instruktioner för återställning av lösenord'
+      unlock_instructions:
+        subject: 'Mastodon: Lås upp instruktioner'
+    omniauth_callbacks:
+      failure: Det gick inte att autentisera dig från %{kind} för "%{reason}".
+      success: Autentiserad från %{kind} konto.
+    passwords:
+      no_token: Du kan inte komma åt den här sidan utan att komma från ett e-postmeddelande för lösenordsåterställning. Om du kommer från ett lösenordsåterställt e-postmeddelande, var vänlig och se till att du använde hela webbadressen.
+      send_instructions: Om din e-postadress finns i vår databas, får du en länk för återställning av lösenord på din e-postadress om några minuter. Kontrollera din spammapp om du inte fick det här e-postmeddelandet.
+      send_paranoid_instructions: Om din e-postadress finns i vår databas, får du en länk för återställning av lösenord på din e-postadress om några minuter. Kontrollera din spammapp om du inte fick det här e-postmeddelandet.
+      updated: Your password has been changed successfully. You are now signed in.
+      updated_not_active: Ditt lösenord har ändrats. Du är nu inloggad.
+    registrations:
+      destroyed: Adjö! Ditt konto har blivit nerstängt. Vi hoppas att vi ses snart igen.
+      signed_up: Välkommen! Du har nu registrerat dig.
+      signed_up_but_inactive: Du har nu registrerat dig. Vi kunde dock inte logga in dig eftersom ditt konto ännu inte är aktiverat.
+      signed_up_but_locked: Du har nu registrerat dig. Vi kunde dock inte logga in eftersom ditt konto är låst.
+      signed_up_but_unconfirmed: Ett meddelande med en bekräftelse länk har skickats till din e-postadress. Vänligen följ länken för att aktivera ditt konto. Kontrollera din spammapp om du inte fick det här e-postmeddelandet.
+      update_needs_confirmation: Du har uppdaterat ditt konto med framgång, men vi måste verifiera din nya e-postadress. Vänligen kolla din email och följ bekräfta länken för att bekräfta din nya e-postadress. Kontrollera din spammapp om du inte fick det här e-postmeddelandet.
+      updated: Ditt konto har uppdaterats utan problem.
+    sessions:
+      already_signed_out: Utloggad.
+      signed_in: Inloggad.
+      signed_out: Utloggad.
+    unlocks:
+      send_instructions: Du kommer att få ett mail med instruktioner om hur du låser upp ditt konto inom några minuter. Kontrollera din spammapp om du inte fick det här e-postmeddelandet.
+      send_paranoid_instructions: Om ditt konto finns, får du ett mail med instruktioner om hur du låser upp det på några minuter. Kontrollera din spammapp om du inte fick det här e-postmeddelandet.
+      unlocked: Ditt konto ha låsts upp. Vänligen logga in för att fortsätta.
+  errors:
+    messages:
+      already_confirmed: var redan bekräftad, var god försök att logga in
+      confirmation_period_expired: måste bekräftas inom %{period}, var god be om en ny
+      expired: har gått ut, vänligen be om en ny
+      not_found: hittades inte
+      not_locked: var inte låst
+      not_saved:
+        one: '1 fel förbjöd denna %{resource} att sparas:'
+        other: "%{count} fel förbjöd dessa %{resource} från att sparas:"
diff --git a/config/locales/devise.tr.yml b/config/locales/devise.tr.yml
index f00dd2a95..ade23769d 100644
--- a/config/locales/devise.tr.yml
+++ b/config/locales/devise.tr.yml
@@ -1,14 +1,13 @@
-
 ---
 tr:
   simple_form:
     hints:
       defaults:
         avatar: En fazla 2MB olacak şekilde PNG, GIF veya JPG formatında yükleyiniz. 120x120px büyüklüğüne indirgenecektir
-        display_name: '%{count} karakter kaldı'
+        display_name: "%{count} karakter kaldı"
         header: En fazla 2MB olacak şekilde PNG, GIF veya JPG formatında yükleyiniz. 700x335px büyüklüğüne indirgenecektir.
         locked: Takipçilerinizi manuel olarak kabul etmenizi ve gönderilerinizi varsayılan olarak sadece takipçilerinizin göreceği şekilde paylaşmanızı sağlar.
-        note: '%{count} karakter kaldı'
+        note: "%{count} karakter kaldı"
       imports:
         data: Diğer Mastodon sunucusundan dışarı aktardığınız CSV dosyası
       sessions:
@@ -45,8 +44,8 @@ tr:
         follow_request: Biri bana takip isteği gönderdiğinde, bana e-posta gönder
         mention: Biri benden bahsettiğinde, bana e-posta gönder
         reblog: Biri durumumu paylaştığında, bana e-posta gönder
-    'no': 'Hayır'
+    'no': Hayır
     required:
       mark: "*"
       text: gerekli
-    'yes': 'Evet'
+    'yes': Evet
diff --git a/config/locales/doorkeeper.sv.yml b/config/locales/doorkeeper.sv.yml
new file mode 100644
index 000000000..19a457427
--- /dev/null
+++ b/config/locales/doorkeeper.sv.yml
@@ -0,0 +1,119 @@
+---
+sv:
+  activerecord:
+    attributes:
+      doorkeeper/application:
+        name: Applikationsnamn
+        redirect_uri: Omdirigera URI
+        scopes: Omfattning
+        website: Applikationswebbplats
+    errors:
+      models:
+        doorkeeper/application:
+          attributes:
+            redirect_uri:
+              fragment_present: kan inte innehålla ett fragment.
+              invalid_uri: måste vara en giltig URI.
+              relative_uri: måste vara en absolut URI.
+              secured_uri: måste vara en HTTPS/SSL URI.
+  doorkeeper:
+    applications:
+      buttons:
+        authorize: Godkänna
+        cancel: Ångra
+        destroy: Förstöra
+        edit: Redigera
+        submit: Skicka
+      confirmations:
+        destroy: Äre du säker?
+      edit:
+        title: Redigera applikation
+      form:
+        error: Hoppsan! Kontrollera i formuläret efter eventuella fel
+      help:
+        native_redirect_uri: Använd %{native_redirect_uri} för lokalt test
+        redirect_uri: Använd en per rad URI
+        scopes: Separera omfattningen med mellanslag. Lämna tomt för att använda standardomfattning.
+      index:
+        application: Applikation
+        callback_url: Callback URL
+        delete: Ta bort
+        name: Namn
+        new: Ny applikation
+        scopes: Omfattning
+        show: Visa
+        title: Dina applikationer
+      new:
+        title: Ny applikation
+      show:
+        actions: Handlingar
+        application_id: Klientnyckel
+        callback_urls: Callback URLs
+        scopes: Omfattning
+        secret: Kundhemlighet
+        title: 'Application: %{name}'
+    authorizations:
+      buttons:
+        authorize: Godkänna
+        deny: Neka
+      error:
+        title: Ett fel har uppstått
+      new:
+        able_to: Det kommer att kunna
+        prompt: Applikation %{client_name} begär tillgång till ditt konto
+        title: Godkännande krävs
+      show:
+        title: Kopiera denna behörighetskod och klistra in den i programmet.
+    authorized_applications:
+      buttons:
+        revoke: Återkalla
+      confirmations:
+        revoke: Är du säker?
+      index:
+        application: Applikation
+        created_at: Auktoriserad
+        date_format: "%Y-%m-%d %H:%M:%S"
+        scopes: Omfattning
+        title: Dina behöriga ansökningar
+    errors:
+      messages:
+        access_denied: Resursägaren eller behörighetsservern nekade begäran.
+        credential_flow_not_configured: Resurs Ägare Lösenord Credentials flöde misslyckades på grund av att Doorkeeper.configure.resource_owner_from_credentials är okonfigurerad.
+        invalid_client: Klientautentisering misslyckades på grund av okänd klient, ingen klientautentisering inkluderad eller icke godkänd autentiseringsmetod.
+        invalid_grant: Det beviljade godkännandetillskottet är ogiltigt, upphört, återkallat, matchar inte den omdirigering URI som användes i auktorisationsförfrågan eller har utfärdats till en annan klient.
+        invalid_redirect_uri: Den omdirigerade uri är inte giltig.
+        invalid_request: Förfrågan saknar en obligatorisk parameter, innehåller ett icke-stödt parametervärde eller är annars felaktigt.
+        invalid_resource_owner: De angivna resursägarnas referenser är inte giltiga, eller resursägare kan inte hittas
+        invalid_scope: Det begärda räckvidden är ogiltigt, okänt eller felaktigt.
+        invalid_token:
+          expired: The access token utgången
+          revoked: The access token är återkallad
+          unknown: The access token är ogiltig
+        resource_owner_authenticator_not_configured: Resursägaren hittade fel på grund av Doorkeeper.configure.resource_owner_authenticator är okonfigurerad.
+        server_error: Tillståndsservern stötte på ett oväntat villkor som hindrade det från att uppfylla förfrågan.
+        temporarily_unavailable: Autorisationsservern kan inte hantera begäran på grund av tillfällig överbelastning eller underhåll av servern.
+        unauthorized_client: Klienten är inte behörig att utföra denna förfrågan med den här metoden.
+        unsupported_grant_type: Typgodkännandet för godkännande beviljas inte av behörighetsservern.
+        unsupported_response_type: Autorisationsservern stöder inte den här svarstypen.
+    flash:
+      applications:
+        create:
+          notice: Applikation skapad.
+        destroy:
+          notice: Applikation borttagen.
+        update:
+          notice: Applikation uppdaterad.
+      authorized_applications:
+        destroy:
+          notice: Applikation återkallas.
+    layouts:
+      admin:
+        nav:
+          applications: Applikationer
+          oauth2_provider: OAuth2 Provider
+      application:
+        title: OAuth-behörighet krävs
+    scopes:
+      follow: följ, blockera, ta bort blockering och sluta följa konton
+      read: läs dina kontodata
+      write: posta på dina vägnar
diff --git a/config/locales/en.yml b/config/locales/en.yml
index 7d2596fc6..45929e97d 100644
--- a/config/locales/en.yml
+++ b/config/locales/en.yml
@@ -1,8 +1,8 @@
 ---
 en:
   about:
-    about_mastodon_html: Mastodon is a social network based on open web protocols and free, open-source software. It is decentralized like e-mail.
     about_hashtag_html: These are public toots tagged with <strong>#%{hashtag}</strong>. You can interact with them if you have an account anywhere in the fediverse.
+    about_mastodon_html: Mastodon is a social network based on open web protocols and free, open-source software. It is decentralized like e-mail.
     about_this: About
     closed_registrations: Registrations are currently closed on this instance. However! You can find a different instance to make an account on and get access to the very same network from there.
     contact: Contact
@@ -50,6 +50,13 @@ en:
       admin: Admin
     unfollow: Unfollow
   admin:
+    account_moderation_notes:
+      account: Moderator
+      create: Create
+      created_at: Date
+      created_msg: Moderation note successfully created!
+      delete: Delete
+      destroyed_msg: Moderation note successfully destroyed!
     accounts:
       are_you_sure: Are you sure?
       confirm: Confirm
@@ -110,15 +117,6 @@ en:
       unsubscribe: Unsubscribe
       username: Username
       web: Web
-
-    account_moderation_notes:
-      account: Moderator
-      created_at: Date
-      create: Create
-      created_msg: Moderation note successfully created!
-      delete: Delete
-      destroyed_msg: Moderation note successfully destroyed!
-
     custom_emojis:
       copied_msg: Successfully created local copy of the emoji
       copy: Copy
diff --git a/config/locales/fa.yml b/config/locales/fa.yml
index 8cb84c7ae..24a2ddd51 100644
--- a/config/locales/fa.yml
+++ b/config/locales/fa.yml
@@ -1,8 +1,8 @@
 ---
 fa:
   about:
-    about_mastodon_html: ماستدون (Mastodon) یک شبکهٔ اجتماعی است که بر اساس پروتکل‌های آزاد وب و نرم‌افزارهای آزاد و کدباز ساخته شده است. این شبکه مانند ایمیل غیرمتمرکز است.
     about_hashtag_html: این‌ها نوشته‌های عمومی هستند که برچسب (هشتگ) <strong>#%{hashtag}</strong> را دارند. اگر شما روی هر سروری حساب داشته باشید می‌توانید به این نوشته‌ها واکنش نشان دهید.
+    about_mastodon_html: ماستدون (Mastodon) یک شبکهٔ اجتماعی است که بر اساس پروتکل‌های آزاد وب و نرم‌افزارهای آزاد و کدباز ساخته شده است. این شبکه مانند ایمیل غیرمتمرکز است.
     about_this: درباره
     closed_registrations: ثبت‌نام روی این سرور هم‌اینک فعال نیست. اما شما می‌توانید سرور دیگری بیابید و با حسابی که آن‌جا می‌سازید دقیقاً به همین شبکه دسترسی داشته باشید.
     contact: تماس
@@ -50,6 +50,13 @@ fa:
       admin: مدیر
     unfollow: پایان پیگیری
   admin:
+    account_moderation_notes:
+      account: مدیر
+      create: نوشتن
+      created_at: تاریخ
+      created_msg: یادداشت مدیر با موفقیت ساخته شد!
+      delete: پاک کردن
+      destroyed_msg: یادداشت مدیر با موفقیت پاک شد!
     accounts:
       are_you_sure: آیا مطمئن هستید؟
       confirm: تأیید
@@ -110,15 +117,6 @@ fa:
       unsubscribe: لغو اشتراک
       username: نام کاربری
       web: وب
-
-    account_moderation_notes:
-      account: مدیر
-      created_at: تاریخ
-      create: نوشتن
-      created_msg: یادداشت مدیر با موفقیت ساخته شد!
-      delete: پاک کردن
-      destroyed_msg: یادداشت مدیر با موفقیت پاک شد!
-
     custom_emojis:
       copied_msg: نسخهٔ محلی شکلک با موفقیت ساخته شد
       copy: نسخه‌برداری
diff --git a/config/locales/fr.yml b/config/locales/fr.yml
index 712724ffa..0d9c227f3 100644
--- a/config/locales/fr.yml
+++ b/config/locales/fr.yml
@@ -1,8 +1,8 @@
 ---
 fr:
   about:
-    about_mastodon_html: Mastodon est un réseau social utilisant des formats ouverts et des logiciels libres. Comme le courriel, il est décentralisé.
     about_hashtag_html: Figurent ci-dessous les pouets tagués avec <strong>#%{hashtag}</strong>. Vous pouvez interagir avec eux si vous avez un compte n’importe où dans le Fediverse.
+    about_mastodon_html: Mastodon est un réseau social utilisant des formats ouverts et des logiciels libres. Comme le courriel, il est décentralisé.
     about_this: À propos
     closed_registrations: Les inscriptions sont actuellement fermées sur cette instance. Cependant, vous pouvez trouver une autre instance sur laquelle vous créer un compte et à partir de laquelle vous pourrez accéder au même réseau.
     contact: Contact
@@ -50,6 +50,13 @@ fr:
       admin: Admin
     unfollow: Ne plus suivre
   admin:
+    account_moderation_notes:
+      account: Modérateur·ice
+      create: Créer
+      created_at: Date
+      created_msg: Note de modération créée avec succès !
+      delete: Supprimer
+      destroyed_msg: Note de modération supprimée avec succès !
     accounts:
       are_you_sure: Êtes-vous certain⋅e ?
       confirm: Confirmer
@@ -110,15 +117,6 @@ fr:
       unsubscribe: Se désabonner
       username: Nom d’utilisateur⋅ice
       web: Web
-
-    account_moderation_notes:
-      account: Modérateur·ice
-      created_at: Date
-      create: Créer
-      created_msg: Note de modération créée avec succès !
-      delete: Supprimer
-      destroyed_msg: Note de modération supprimée avec succès !
-
     custom_emojis:
       copied_msg: Copie locale de l’émoji créée avec succès !
       copy: Copier
@@ -523,7 +521,7 @@ fr:
     body_html: |
       <h2>Politique de confidentialité</h2>
 
-      <h3 id=\"collect\">Quelles données collectons-nous ?</h3>
+      <h3 id="collect">Quelles données collectons-nous ?</h3>
 
       <p>Nous collectons des données lorsque vous vous enregistrez sur notre site et les récoltons lorsque vous participez dans le forum en lisant, écrivant, et évaluant le contenu partagé ici.</p>
 
@@ -531,7 +529,7 @@ fr:
 
       <p>Lors de l’inscription et de la publication de statuts, nous enregistrons l’adresse IP de laquelle les statuts proviennent. Nous pouvons également conserver des historiques serveurs qui contiendront l’adresse IP de chaque requête adressée à notre serveur.</p>
 
-      <h3 id=\"use\">Que faisons-nous avec vos données ?</h3>
+      <h3 id="use">Que faisons-nous avec vos données ?</h3>
 
       <p>Toute information que nous collectons pourra être utilisée d’une des manières suivantes :</p>
 
@@ -542,11 +540,11 @@ fr:
         <li>Afin d’envoyer des courriels à intervalles réguliers &mdash; l’adresse électronique que vous renseignez peut être utilisée pour vous envoyer des données et notifications concernant des changements ou en réponse à votre nom d’utilisateur⋅ice, en réponse à vos demandes et/ou autres requêtes ou questions</li>
       </ul>
 
-      <h3 id=\"protect\">Comment protégeons-nous vos données ?</h3>
+      <h3 id="protect">Comment protégeons-nous vos données ?</h3>
 
       <p>Nous appliquons une multitude de mesures afin de maintenir la sécurité de vos données personnelles lorsque vous entrez, soumettez, ou accédez à ces dernières.</p>
 
-      <h3 id=\"data-retention\">Quelle est notre politique de conservation des données ?</h3>
+      <h3 id="data-retention">Quelle est notre politique de conservation des données ?</h3>
 
       <p>Nous nous efforçons de :</p>
 
@@ -555,39 +553,39 @@ fr:
         <li>ne pas conserver les adresses IP associées aux utilisateur⋅trices et leur contenu plus de 5 ans.</li>
       </ul>
 
-      <h3 id=\"cookies\">Utilisons-nous des « cookies » ?</h3>
+      <h3 id="cookies">Utilisons-nous des « cookies » ?</h3>
 
       <p>Oui. Les cookies sont de petits fichiers qu’un site ou prestataires de services transfèrent sur le disque dur de votre ordinateur par le biais de votre navigateur Web (si ce dernier le permet). Ces cookies permettent au site de reconnaître votre navigateur et, si vous disposez d’un compte, de l’associer à celui-ci.</p>
 
       <p>Nous utilisons les cookies pour enregistrer vos préférences pour de futures visites, compiler des données agrégées à propos du trafic et des interactions effectuées sur le site afin de proposer une meilleure expérience dans le futur. Nous pouvons contracter les services de tiers afin de nous aider à mieux comprendre les visiteurs de notre site. Ces tiers ont l’autorisation d’utiliser ces données seulement à des fins d’améliorations.</p>
 
-      <h3 id=\"disclose\">Divulguons-nous des données à des tiers ?</h3>
+      <h3 id="disclose">Divulguons-nous des données à des tiers ?</h3>
 
       <p>Nous n’échangeons pas, ne vendons pas ni effectuons de quelconques transferts avec des tiers d’informations permettant de vous identifier personnellement. Cela n’inclut pas les tiers de confiance qui nous aident à gérer notre entreprise et à vous servir tant que ces tiers s’accordent à garder lesdites informations confidentielles. Nous pouvons être amenés à délivrer vos informations lorsque jugé adéquat afin de respecter la loi, d’appliquer la politique de notre site, ou afin de protéger nos droits, ceux des autres, notre propriété ou sécurité. Cependant, aucune information permettant l’identification de nos visiteur⋅euse⋅s ne sera divulguée à des fins publicitaires, commerciales ou tout autre usage.</p>
 
-      <h3 id=\"third-party\">Liens vers des tiers</h3>
+      <h3 id="third-party">Liens vers des tiers</h3>
 
       <p>Nous pouvons être amenés à inclure ou offrir les services ou produits de tiers sur notre site. Ces tiers possèdent leur propre politique de confidentialité. Nous ne sommes donc pas responsables du contenu ou activités desdits tiers. Néanmoins, nous cherchons à protéger l’intégrité de notre site et sommes ouverts à toute remarque concernant ces tiers.</p>
 
-      <h3 id=\"coppa\" lang=\"en\">Children's Online Privacy Protection Act</h3>
+      <h3 id="coppa" lang="en">Children's Online Privacy Protection Act</h3>
 
-      <p>Notre site, nos produits et services sont tous destinés à l’usage de personnes âgées de 13 ans ou plus. Si ce serveur est hébergé aux États-Unis et que vous êtes âgé⋅e de moins de 13 ans, au vu du COPPA (<a href=\"https://fr.wikipedia.org/wiki/Children%27s_Online_Privacy_Protection_Act\"><i lang=\"en\">Children's Online Privacy Protection Act</i></a>) n’utilisez pas ce site.</p>
+      <p>Notre site, nos produits et services sont tous destinés à l’usage de personnes âgées de 13 ans ou plus. Si ce serveur est hébergé aux États-Unis et que vous êtes âgé⋅e de moins de 13 ans, au vu du COPPA (<a href="https://fr.wikipedia.org/wiki/Children%27s_Online_Privacy_Protection_Act"><i lang="en">Children's Online Privacy Protection Act</i></a>) n’utilisez pas ce site.</p>
 
       <h3 id="online">Politique de confidentialité en ligne</h3>
 
       <p>Cette politique de confidentialité en ligne s'applique uniquement aux informations collectées par le biais de notre site et non aux informations collectées hors ligne.</p>
 
-      <h3 id=\"consent\">Votre consentement</h3>
+      <h3 id="consent">Votre consentement</h3>
 
       <p>En utilisant notre site, vous consentez à la présente politique de confidentialité.</p>
 
-      <h3 id=\"changes\">Changements de notre politique de confidentialité</h3>
+      <h3 id="changes">Changements de notre politique de confidentialité</h3>
 
       <p>Si nous décidons d’apporter des changements à notre politique de confidentialité, nous les publierons sur cette page.</p>
 
       <p>Ce document est distribué sous licence CC-BY-SA. Il a été mis à jour pour la dernière fois le 31 mai 2013. Il a été traduit en français en juillet 2017.</p>
 
-      <p>Originellement adapté à partir de la politique de confidentialité de <a href=\"https://github.com/discourse/discourse\">Discourse</a>.</p>
+      <p>Originellement adapté à partir de la politique de confidentialité de <a href="https://github.com/discourse/discourse">Discourse</a>.</p>
     title: "%{instance} Conditions d’utilisations et politique de confidentialité"
   themes:
     default: Mastodon
diff --git a/config/locales/ko.yml b/config/locales/ko.yml
index 35cec6b15..abf5f0ea4 100644
--- a/config/locales/ko.yml
+++ b/config/locales/ko.yml
@@ -1,7 +1,7 @@
 ---
 ko:
   about:
-    about_hashtag_html: <strong>#%{hashtag}</strong> 라는 해시태그가 붙은 공개 툿 입니다. 같은 연합에 속한 임의의 인스턴스에 계정을 생성하면 당신도 대화에 참여할 수 있습니다.
+    about_hashtag_html: "<strong>#%{hashtag}</strong> 라는 해시태그가 붙은 공개 툿 입니다. 같은 연합에 속한 임의의 인스턴스에 계정을 생성하면 당신도 대화에 참여할 수 있습니다."
     about_mastodon_html: Mastodon은 <em>오픈 소스 기반의</em> 소셜 네트워크 서비스 입니다. 상용 플랫폼의 대체로서 <em>분산형 구조</em>를 채택해, 여러분의 대화가 한 회사에 독점되는 것을 방지합니다. 신뢰할 수 있는 인스턴스를 선택하세요 &mdash; 어떤 인스턴스를 고르더라도, 누구와도 대화할 수 있습니다. 누구나 자신만의 Mastodon 인스턴스를 만들 수 있으며, 아주 매끄럽게 <em>소셜 네트워크</em>에 참가할 수 있습니다.
     about_this: 이 인스턴스에 대해서
     closed_registrations: 현재 이 인스턴스에서는 신규 등록을 받고 있지 않습니다.
diff --git a/config/locales/nl.yml b/config/locales/nl.yml
index fa66d14ef..501ec013d 100644
--- a/config/locales/nl.yml
+++ b/config/locales/nl.yml
@@ -1,8 +1,8 @@
 ---
 nl:
   about:
-    about_mastodon_html: Mastodon is een <em>vrij, gratis en open-source</em> sociaal netwerk. Een <em>gedecentraliseerd</em> alternatief voor commerciële platforms. Het voorkomt de risico's van een enkel bedrijf dat jouw communicatie monopoliseert. Kies een server die je vertrouwt &mdash; welke je ook kiest, je kunt met elke andere server communiceren. Iedereen kan een eigen Mastodon-server draaien en naadloos deelnemen in het <em>sociale netwerk</em>.
     about_hashtag_html: Dit zijn openbare toots die getagged zijn met <strong>#%{hashtag}</strong>. Je kunt er op reageren of iets anders mee doen als je op Mastodon (of ergens anders in de fediverse) een account hebt.
+    about_mastodon_html: Mastodon is een <em>vrij, gratis en open-source</em> sociaal netwerk. Een <em>gedecentraliseerd</em> alternatief voor commerciële platforms. Het voorkomt de risico's van een enkel bedrijf dat jouw communicatie monopoliseert. Kies een server die je vertrouwt &mdash; welke je ook kiest, je kunt met elke andere server communiceren. Iedereen kan een eigen Mastodon-server draaien en naadloos deelnemen in het <em>sociale netwerk</em>.
     about_this: Over deze server
     closed_registrations: Registreren op deze server is momenteel uitgeschakeld.
     contact: Contact
@@ -50,6 +50,13 @@ nl:
       admin: Beheerder
     unfollow: Ontvolgen
   admin:
+    account_moderation_notes:
+      account: Moderator
+      create: Aanmaken
+      created_at: Datum
+      created_msg: Aanmaken van opmerking voor moderatoren geslaagd!
+      delete: Verwijderen
+      destroyed_msg: Verwijderen van opmerking voor moderatoren geslaagd!
     accounts:
       are_you_sure: Weet je het zeker?
       confirm: Bevestigen
@@ -110,15 +117,6 @@ nl:
       unsubscribe: Opzeggen
       username: Gebruikersnaam
       web: Webapp
-
-    account_moderation_notes:
-      account: Moderator
-      created_at: Datum
-      create: Aanmaken
-      created_msg: Aanmaken van opmerking voor moderatoren geslaagd!
-      delete: Verwijderen
-      destroyed_msg: Verwijderen van opmerking voor moderatoren geslaagd!
-
     custom_emojis:
       copied_msg: Lokale kopie van emoji maken geslaagd
       copy: Kopiëren
diff --git a/config/locales/oc.yml b/config/locales/oc.yml
index b30f797c7..0d2a8c2f6 100644
--- a/config/locales/oc.yml
+++ b/config/locales/oc.yml
@@ -1,8 +1,8 @@
 ---
 oc:
   about:
-    about_mastodon_html: Mastodon es un malhum social bastit amb de protocòls liures e gratuits. Es descentralizat coma los corrièls.
     about_hashtag_html: Vaquí los estatuts publics ligats a <strong>#%{hashtag}</strong>. Podètz interagir amb eles s’avètz un compte ont que siasque sul fediverse.
+    about_mastodon_html: Mastodon es un malhum social bastit amb de protocòls liures e gratuits. Es descentralizat coma los corrièls.
     about_this: A prepaus d’aquesta instància
     closed_registrations: Las inscripcions son clavadas pel moment sus aquesta instància.
     contact: Contacte
@@ -50,6 +50,13 @@ oc:
       admin: Admin
     unfollow: Quitar de sègre
   admin:
+    account_moderation_notes:
+      account: Moderator
+      create: Crear
+      created_at: Data
+      created_msg: Nòta de moderacion ben creada !
+      delete: Suprimir
+      destroyed_msg: Nòta de moderacion ben suprimida !
     accounts:
       are_you_sure: Sètz segur ?
       confirm: Confirmar
@@ -110,15 +117,6 @@ oc:
       unsubscribe: Se desabonar
       username: Nom d’utilizaire
       web: Web
-
-    account_moderation_notes:
-      account: Moderator
-      created_at: Data
-      create: Crear
-      created_msg: Nòta de moderacion ben creada !
-      delete: Suprimir
-      destroyed_msg: Nòta de moderacion ben suprimida !
-
     custom_emojis:
       copied_msg: Còpia locala de l’emoji ben creada
       copy: Copiar
@@ -171,15 +169,15 @@ oc:
       title: Blòc de domeni
       undo: Restablir
     email_domain_blocks:
-       add_new: Ajustar
-       created_msg: Blocatge del domeni de corrièl ben plaçat
-       delete: Suprimir
-       destroyed_msg: Blocatge del domeni de corrièl ben levat
-       domain: Domeni
-       new:
-         create: Crear un blocatge
-         title: Nòu blocatge de domeni de corrièl
-       title: Blocatge de domeni de corrièl      
+      add_new: Ajustar
+      created_msg: Blocatge del domeni de corrièl ben plaçat
+      delete: Suprimir
+      destroyed_msg: Blocatge del domeni de corrièl ben levat
+      domain: Domeni
+      new:
+        create: Crear un blocatge
+        title: Nòu blocatge de domeni de corrièl
+      title: Blocatge de domeni de corrièl
     instances:
       account_count: Comptes coneguts
       domain_name: Domeni
diff --git a/config/locales/pl.yml b/config/locales/pl.yml
index 8e2a9780c..c58c1c2f8 100644
--- a/config/locales/pl.yml
+++ b/config/locales/pl.yml
@@ -1,8 +1,8 @@
 ---
 pl:
   about:
-    about_mastodon_html: Mastodon jest wolną i otwartą siecią społecznościową, zdecentralizowaną alternatywą dla zamkniętych, komercyjnych platform.
     about_hashtag_html: Znajdują się tu publiczne wpisy oznaczone hashtagiem <strong>#%{hashtag}</strong>. Możesz dołączyć do dyskusji, jeżeli posiadasz konto gdziekolwiek w Fediwersum.
+    about_mastodon_html: Mastodon jest wolną i otwartą siecią społecznościową, zdecentralizowaną alternatywą dla zamkniętych, komercyjnych platform.
     about_this: O tej instancji
     closed_registrations: Rejestracja na tej instancji jest obecnie zamknięta. Możesz jednak zarejestrować się na innej instancji, uzyskując dostęp do tej samej sieci.
     contact: Kontakt
@@ -50,6 +50,13 @@ pl:
       admin: Administrator
     unfollow: Przestań śledzić
   admin:
+    account_moderation_notes:
+      account: Autor
+      create: Dodaj
+      created_at: Data
+      created_msg: Pomyślnie dodano notatkę moderacyjną!
+      delete: Usuń
+      destroyed_msg: Pomyślnie usunięto notatkę moderacyjną!
     accounts:
       are_you_sure: Jesteś tego pewien?
       confirm: Potwierdź
@@ -110,13 +117,6 @@ pl:
       unsubscribe: Przestań subskrybować
       username: Nazwa użytkownika
       web: Sieć
-    account_moderation_notes:
-      account: Autor
-      created_at: Data
-      create: Dodaj
-      created_msg: Pomyślnie dodano notatkę moderacyjną!
-      delete: Usuń
-      destroyed_msg: Pomyślnie usunięto notatkę moderacyjną!
     custom_emojis:
       copied_msg: Pomyślnie utworzono lokalną kopię emoji
       copy: Kopiuj
diff --git a/config/locales/pt-BR.yml b/config/locales/pt-BR.yml
index 060fd3112..4b9ea152f 100644
--- a/config/locales/pt-BR.yml
+++ b/config/locales/pt-BR.yml
@@ -1,8 +1,8 @@
 ---
 pt-BR:
   about:
-    about_mastodon_html: Mastodon é uma rede social baseada em protocolos abertos e software gratuito e de código aberto. É descentralizada como e-mail.
     about_hashtag_html: Estes são toots públicos com a hashtag <strong>#%{hashtag}</strong>. Voce pode interagir com eles se tiver uma conta em qualquer lugar no fediverso.
+    about_mastodon_html: Mastodon é uma rede social baseada em protocolos abertos e software gratuito e de código aberto. É descentralizada como e-mail.
     about_this: Sobre
     closed_registrations: Cadastros estão atualmente fechados nesta instância. No entanto! Você pode procurar uma instância diferente na qual possa criar uma conta e acessar a mesma rede por lá.
     contact: Contato
@@ -11,7 +11,7 @@ pt-BR:
     description_headline: O que é %{domain}?
     domain_count_after: outras instâncias
     domain_count_before: Conectado a
-    extended_description_html:
+    extended_description_html: |
       <h3>Um bom lugar para regras</h3>
       <p>A descrição da instância ainda não foi feita.</p>
     features:
@@ -50,6 +50,13 @@ pt-BR:
       admin: Administrador
     unfollow: Deixar de seguir
   admin:
+    account_moderation_notes:
+      account: Moderador
+      create: Criar
+      created_at: Data
+      created_msg: Nota de moderação criada com sucesso!
+      delete: Excluir
+      destroyed_msg: Nota de moderação excluída com sucesso!
     accounts:
       are_you_sure: Você tem certeza?
       confirm: Confirmar
@@ -110,15 +117,6 @@ pt-BR:
       unsubscribe: Desinscrever-se
       username: Nome de usuário
       web: Web
-
-    account_moderation_notes:
-      account: Moderador
-      created_at: Data
-      create: Criar
-      created_msg: Nota de moderação criada com sucesso!
-      delete: Excluir
-      destroyed_msg: Nota de moderação excluída com sucesso!
-
     custom_emojis:
       copied_msg: Cópia local do emoji criada com sucesso!
       copy: Copiar
@@ -520,7 +518,7 @@ pt-BR:
     reblogged: compartilhado
     sensitive_content: Conteúdo sensível
   terms:
-    body_html:
+    body_html: |
       <h2>Política de privacidade</h2>
 
       <h3 id="collect">Que informações nós coletamos?</h3>
diff --git a/config/locales/simple_form.de.yml b/config/locales/simple_form.de.yml
index 4064aa5f2..9933093ca 100644
--- a/config/locales/simple_form.de.yml
+++ b/config/locales/simple_form.de.yml
@@ -44,6 +44,7 @@ de:
         setting_default_sensitive: Medien immer als heikel markieren
         setting_delete_modal: Bestätigungsdialog anzeigen, bevor ein Beitrag gelöscht wird
         setting_noindex: Suchmaschinen-Indexierung verhindern
+        setting_reduce_motion: Bewegung in Animationen verringern
         setting_system_font_ui: Standardschriftart des Systems verwenden
         setting_theme: Theme der Website
         setting_unfollow_modal: Bestätigungsdialog anzeigen, bevor jemand entfolgt wird
diff --git a/config/locales/simple_form.fr.yml b/config/locales/simple_form.fr.yml
index 40fed9675..06ab018a7 100644
--- a/config/locales/simple_form.fr.yml
+++ b/config/locales/simple_form.fr.yml
@@ -44,6 +44,7 @@ fr:
         setting_default_sensitive: Toujours marquer les médias comme sensibles
         setting_delete_modal: Afficher une fenêtre de confirmation avant de supprimer un pouet
         setting_noindex: Demander aux moteurs de recherche de ne pas indexer vos informations personnelles
+        setting_reduce_motion: Réduire la vitesse des animations
         setting_system_font_ui: Utiliser la police par défaut du système
         setting_theme: Thème du site
         setting_unfollow_modal: Afficher une fenêtre de confirmation avant de vous désabonner d’un compte
diff --git a/config/locales/simple_form.ja.yml b/config/locales/simple_form.ja.yml
index c889a882e..993eae706 100644
--- a/config/locales/simple_form.ja.yml
+++ b/config/locales/simple_form.ja.yml
@@ -40,6 +40,7 @@ ja:
         setting_default_sensitive: メディアを常に閲覧注意としてマークする
         setting_delete_modal: トゥートを削除する前に確認ダイアログを表示する
         setting_noindex: 検索エンジンによるインデックスを拒否する
+        setting_reduce_motion: アニメーションの動きを減らす
         setting_system_font_ui: システムのデフォルトフォントを使う
         setting_theme: サイトテーマ
         setting_unfollow_modal: フォロー解除する前に確認ダイアログを表示する
diff --git a/config/locales/simple_form.nl.yml b/config/locales/simple_form.nl.yml
index fabb5840a..5637bd848 100644
--- a/config/locales/simple_form.nl.yml
+++ b/config/locales/simple_form.nl.yml
@@ -4,13 +4,17 @@ nl:
     hints:
       defaults:
         avatar: PNG, GIF of JPG. Maximaal 2MB. Wordt teruggeschaald naar 120x120px
-        display_name: Maximaal 30 tekens
+        digest: Wordt na een lange periode van inactiviteit verzonden, met een samenvatting van vermeldingen tijdens je afwezigheid.
+        display_name:
+          one: <span class="name-counter">1</span> teken over
+          other: <span class="name-counter">%{count}</span> tekens over
         header: PNG, GIF of JPG. Maximaal 2MB. Wordt teruggeschaald naar 700x335px
         locked: Vereist dat je handmatig volgers moet accepteren en stelt de privacy van toots standaard in op alleen volgers
         note:
           one: <span class="note-counter">1</span> teken over
           other: <span class="note-counter">%{count}</span> tekens over
         setting_noindex: Heeft invloed op jouw openbare profiel en toots
+        setting_theme: Heeft invloed op hoe de webapp van Mastodon er uit ziet, op elk apparaat waarmee je inlogt.
       imports:
         data: CSV-bestand dat op een andere Mastodon-server werd geëxporteerd
       sessions:
@@ -40,6 +44,7 @@ nl:
         setting_default_sensitive: Media altijd als gevoelig markeren
         setting_delete_modal: Vraag voor het verwijderen van een toot een bevestiging
         setting_noindex: Jouw toots niet door zoekmachines laten indexeren
+        setting_reduce_motion: Langzamere animaties
         setting_system_font_ui: Standaardlettertype van jouw systeem gebruiken
         setting_unfollow_modal: Vraag voor het ontvolgen van iemand een bevestiging
         type: Importtype
diff --git a/config/locales/simple_form.oc.yml b/config/locales/simple_form.oc.yml
index c1d5e2008..d43c0d7eb 100644
--- a/config/locales/simple_form.oc.yml
+++ b/config/locales/simple_form.oc.yml
@@ -38,12 +38,12 @@ oc:
         otp_attempt: Còdi Two-factor
         password: Senhal
         setting_auto_play_gif: Lectura automatica dels GIFS animats
-        setting_reduce_motion: Reduire la velocitat de las animacions
         setting_boost_modal: Afichar una fenèstra de confirmacion abans de partejar un estatut
         setting_default_privacy: Confidencialitat de las publicacions
         setting_default_sensitive: Totjorn marcar los mèdias coma sensibles
         setting_delete_modal: Afichar una fenèstra de confirmacion abans de suprimir un estatut
         setting_noindex: Èsser pas indexat pels motors de recèrca
+        setting_reduce_motion: Reduire la velocitat de las animacions
         setting_system_font_ui: Utilizar la policia Font del sisèma
         setting_theme: Tèma del site
         setting_unfollow_modal: Afichar una confirmacion abans de quitar de sègre qualqu’un
diff --git a/config/locales/simple_form.sv.yml b/config/locales/simple_form.sv.yml
new file mode 100644
index 000000000..ca5771085
--- /dev/null
+++ b/config/locales/simple_form.sv.yml
@@ -0,0 +1,67 @@
+---
+sv:
+  simple_form:
+    hints:
+      defaults:
+        avatar: Högst 2 MB. Kommer nedskalas till 120x120px
+        digest: Skickas efter en lång period av inaktivitet med en sammanfattning av anmärkningar du har fått under din frånvaro
+        display_name:
+          one: <span class="name-counter">1</span> tecken kvar
+          other: <span class="name-counter">%{count}</span> tecken kvar
+        header: NG, GIF eller JPG. Högst 2 MB. Kommer nedskalas till 700x335px
+        locked: Kräver dig att manuellt godkänna följare
+        note:
+          one: <span class="note-counter">1</span> tecken kvar
+          other: <span class="note-counter">%{count}</span> tecken kvar
+        setting_noindex: Påverkar din offentliga profil och status sidor
+        setting_theme: Påverkar hur Mastodon ser ut när du är inloggad från vilken enhet som helst.
+      imports:
+        data: CSV-fil som exporteras från en annan Mastodon-instans
+      sessions:
+        otp: Ange tvåfaktorkoden från din telefon eller använd någon av dina återställningskoder.
+      user:
+        filtered_languages: Kontrollerade språk filtreras från offentliga tidslinjer för dig
+    labels:
+      defaults:
+        avatar: Avatar
+        confirm_new_password: Bekräfta nytt lösenord
+        confirm_password: Bekräfta lösenord
+        current_password: Nuvarande lösenord
+        data: Data
+        display_name: Visningsnamn
+        email: E-postadress
+        filtered_languages: Filtrerade språk
+        header: Rubrik
+        locale: Språk
+        locked: Lås konto
+        new_password: Nytt lösenord
+        note: Biografi
+        otp_attempt: Tvåfaktorkod
+        password: Lösenord
+        setting_auto_play_gif: Auto-play animerade GIF-filer
+        setting_boost_modal: Visa bekräftelsedialog innan du knuffar
+        setting_default_privacy: Postintegritet
+        setting_default_sensitive: Markera alltid media som känsligt
+        setting_delete_modal: Visa bekräftelse innan du raderar en toot
+        setting_noindex: Uteslutning av sökmotorindexering
+        setting_system_font_ui: Använd systemets standardfont
+        setting_theme: Sidans tema
+        setting_unfollow_modal: Visa bekräftelse innan du slutar följa någon
+        severity: Strikthet
+        type: Importtyp
+        username: Användarnamn
+      interactions:
+        must_be_follower: Blockera meddelanden från icke-följare
+        must_be_following: Blockera meddelanden från personer du inte följer
+      notification_emails:
+        digest: Skicka sammandrag via e-post
+        favourite: Skicka e-post när någon favoriterar din status
+        follow: Skicka e-post när någon följer dig
+        follow_request: Skicka e-post när någon begär att följa dig
+        mention: Skicka e-post när någon nämner dig
+        reblog: Skicka e-post när någon knuffar din status
+    'no': Nej
+    required:
+      mark: "*"
+      text: obligatorisk
+    'yes': Ja
diff --git a/config/locales/sv.yml b/config/locales/sv.yml
new file mode 100644
index 000000000..260b44666
--- /dev/null
+++ b/config/locales/sv.yml
@@ -0,0 +1,614 @@
+---
+sv:
+  about:
+    about_hashtag_html: Dessa är offentliga toots märkta med <strong>#%{hashtag}</strong>. Du kan interagera med dem om du har ett konto någonstans i federationen.
+    about_mastodon_html: Mastodon är ett socialt nätverk baserat på öppna webbprotokoll och gratis, öppen källkodsprogramvara. Det är decentraliserat som e-post
+    about_this: Om
+    closed_registrations: Registreringar är för närvarande stängda i denna instans. Dock så kan du hitta en annan instans för att skapa ett konto och få tillgång till samma nätverk från det.
+    contact: Kontakt
+    contact_missing: Inte inställd
+    contact_unavailable: N/A
+    description_headline: Vad är %{domain}?
+    domain_count_after: annan instans
+    domain_count_before: Uppkopplad mot
+    extended_description_html: |
+      <h3>En bra plats för regler</h3>
+      <p>Den utökade beskrivningen har inte konfigurerats ännu.</p>
+    features:
+      humane_approach_body: Mastodon, har lärt sig från tidigare misslyckanden i andra nätverk och syftar till att göra etiska designval i Mastodon för att bekämpa missbruk av sociala medier.
+      humane_approach_title: En mer human inställning
+      not_a_product_body: Mastodon är inte ett kommersiellt nätverk. Ingen reklam, ingen datautvinning, inga muromgärdade trädgårdar. Det finns ingen central myndighet.
+      not_a_product_title: Du är en person, inte en produkt
+      real_conversation_body: Med 500 tecken till ditt förfogande och stöd för granulärt innehåll och mediavarningar så kan du uttrycka dig själv, som du vill.
+      real_conversation_title: Byggd för riktiga konversationer
+      within_reach_body: Flera appar för iOS, Android och andra plattformar tack vare ett utvecklingsvänligt API-ekosystem gör att du kan hålla kontakten med dina vänner var som helst.
+      within_reach_title: Alltid inom räckhåll
+    find_another_instance: Hitta en annan instans
+    generic_description: "%{domain} är en server i nätverket"
+    hosted_on: Mastodon värd på %{domain}
+    learn_more: Lär dig mer
+    other_instances: Instanslista
+    source_code: Källkod
+    status_count_after: statusar
+    status_count_before: Vem författade
+    user_count_after: användare
+    user_count_before: Hem till
+    what_is_mastodon: Vad är Mastodon?
+  accounts:
+    follow: Följa
+    followers: Följare
+    following: Följer
+    media: Media
+    nothing_here: Det finns inget här!
+    people_followed_by: Personer som %{name} följer
+    people_who_follow: Personer som följer %{name}
+    posts: Toots
+    posts_with_replies: Toots med svar
+    remote_follow: Avlägsen följare
+    reserved_username: Användarnamnet är reserverat
+    roles:
+      admin: Admin
+    unfollow: Sluta följa
+  admin:
+    account_moderation_notes:
+      account: Moderator
+      create: Skapa
+      created_at: Datum
+      created_msg: Modereringsnotering skapad utan problem!
+      delete: Ta bort
+      destroyed_msg: Modereringsnotering borttagen utan problem!
+    accounts:
+      are_you_sure: Är du säker?
+      confirm: Bekräfta
+      confirmed: Bekräftad
+      disable_two_factor_authentication: Inaktivera 2FA
+      display_name: Visningsnamn
+      domain: Domän
+      edit: Redigera
+      email: E-post
+      feed_url: Feed URL
+      followers: Följare
+      followers_url: Följare URL
+      follows: Följs
+      inbox_url: Inbox URL
+      ip: IP
+      location:
+        all: Alla
+        local: Lokal
+        remote: Avlägsen
+        title: Plats
+      media_attachments: Media bifogade filer
+      moderation:
+        all: Alla
+        silenced: Tystas
+        suspended: Avstängd
+        title: Moderering
+      moderation_notes: Moderation anteckning
+      most_recent_activity: Senaste aktivitet
+      most_recent_ip: Senaste IP
+      not_subscribed: Inte prenumererat
+      order:
+        alphabetic: Alfabetiskt
+        most_recent: Senaste
+        title: Ordning
+      outbox_url: Utkorg URL
+      perform_full_suspension: Utför full avstängning
+      profile_url: Profil URL
+      protocol: Protokoll
+      public: Offentlig
+      push_subscription_expires: PuSH-prenumerationen löper ut
+      redownload: Uppdatera avatar
+      reset: Återställ
+      reset_password: Återställ lösenord
+      resubscribe: Starta en ny prenumeration
+      salmon_url: Lax URL
+      search: Sök
+      shared_inbox_url: Delad inkorg URL
+      show:
+        created_reports: Rapporter som skapats av det här kontot
+        report: rapport
+        targeted_reports: Rapporter gjorda om detta konto
+      silence: Tystnad
+      statuses: Status
+      subscribe: Prenumerera
+      title: Konton
+      undo_silenced: Ångra tystnad
+      undo_suspension: Ångra avstängning
+      unsubscribe: Säga upp
+      username: Användarnamn
+      web: Webb
+    custom_emojis:
+      copied_msg: Skapade en lokal kopia av emoji utan problem
+      copy: Kopia
+      copy_failed_msg: Kunde inte skapa en lokal kopia av den emoji
+      created_msg: Emoji skapades utan problem!
+      delete: Ta bort
+      destroyed_msg: Emojo borttagen utan problem!
+      disable: Inaktivera
+      disabled_msg: Inaktiverade emoji utan problem
+      emoji: Emoji
+      enable: Aktivera
+      enabled_msg: Aktiverade den emoji utan problem
+      image_hint: PNG upp till 50KB
+      new:
+        title: Lägg till ny egen emoji
+      shortcode: Kortkod
+      shortcode_hint: Minst 2 tecken, endast alfanumeriska tecken och understreck
+      title: Custom emojis
+      upload: Ladda upp
+    domain_blocks:
+      add_new: Lägg till ny
+      created_msg: Domänblocket behandlas nu
+      destroyed_msg: Domänblocket är ogjord
+      domain: Domän
+      new:
+        create: Skapa block
+        hint: Domänblocket hindrar inte skapandet av kontoposter i databasen, men kommer retroaktivt, automatiskt att tillämpa specifika modereringsmetoder på dessa konton.
+        severity:
+          desc_html: "<strong>Tystnad</strong> kommer att göra kontoinlägg osynliga för alla som inte följer dem. <strong>Suspendera</strong> tar bort allt kontons innehåll, media och profildata. Använd <strong>Ingen</strong> om du bara vill avvisa mediefiler."
+          noop: Ingen
+          silence: Tystnad
+          suspend: Suspendera
+        title: Nytt domänblock
+      reject_media: Avvisa mediafiler
+      reject_media_hint: Ta bort lokalt lagrade mediefiler och tar bort möjligheten att ladda ner något i framtiden. Irrelevant för suspensioner
+      severities:
+        noop: Ingen
+        silence: Tystnad
+        suspend: Suspendera
+      severity: Svårighet
+      show:
+        affected_accounts:
+          one: Ett konto i databasen drabbades
+          other: "%{count} konton i databasen drabbades"
+        retroactive:
+          silence: Ta bort tystnad från alla befintliga konton från den här domänen
+          suspend: Ta bort suspendering från alla befintliga konton i den här domänen
+        title: Ångra domänblockering för %{domain}
+        undo: Ångra
+      title: Domänblockering
+      undo: Ångra
+    email_domain_blocks:
+      add_new: Lägg till ny
+      created_msg: E-postdomänblocket har skapats
+      delete: Ta bort
+      destroyed_msg: E-postdomänblocket har tagits bort
+      domain: Domän
+      new:
+        create: Skapa block
+        title: Nytt E-postdomänblock
+      title: E-postdomänblock
+    instances:
+      account_count: Kända konton
+      domain_name: Domän
+      reset: Återställa
+      search: Sök
+      title: Kända instanser
+    reports:
+      action_taken_by: Åtgärder vidtagna av
+      are_you_sure: Är du säker?
+      comment:
+        label: Kommentar
+        none: Ingen
+      delete: Ta bort
+      id: ID
+      mark_as_resolved: Markera som löst
+      nsfw:
+        'false': Visa bifogade mediafiler
+        'true': Dölj bifogade mediafiler
+      report: 'Rapportera #%{id}'
+      report_contents: Innehåll
+      reported_account: Rapporterat konto
+      reported_by: Rapporterad av
+      resolved: Löst
+      silence_account: Tystat konto
+      status: Status
+      suspend_account: Suspenderat konto
+      target: Mål
+      title: Rapporter
+      unresolved: Olösta
+      view: Granska
+    settings:
+      bootstrap_timeline_accounts:
+        desc_html: Separera flera användarnamn med kommatecken. Endast lokala och olåsta konton kommer att fungera. Standard när det är tomt och alla är lokala administratörer.
+        title: Standard att följa för nya användare
+      contact_information:
+        email: Företag E-post
+        username: Kontakten användarnamn
+      registrations:
+        closed_message:
+          desc_html: Visas på framsidan när registreringen är stängd. Du kan använda HTML-taggar
+          title: Stängt registreringsmeddelande
+        deletion:
+          desc_html: Tillåt alla att ta bort sitt konto
+          title: Open account deletion
+        open:
+          desc_html: Tillåt alla att skapa ett konto
+          title: Öppen registrering
+      site_description:
+        desc_html: Inledande stycke på framsidan och i metataggar. Du kan använda HTML-taggar, i synnerhet <code>&lt;a&gt;</code> och <code>&lt;em&gt;</code>.
+        title: Instansbeskrivning
+      site_description_extended:
+        desc_html: Ett bra ställe för din uppförandekod, regler, riktlinjer och andra saker som stämmer med din instans. Du kan använda HTML-taggar
+        title: Custom utökad information
+      site_terms:
+        desc_html: Du kan skriva din egen integritetspolicy, användarvillkor eller andra regler. Du kan använda HTML-taggar
+        title: Custom Villkor för tjänster
+      site_title: Namn på instans
+      thumbnail:
+        desc_html: Används för förhandsgranskningar via OpenGraph och API. 1200x630px rekommenderas
+        title: Instans tumnagelbild
+      timeline_preview:
+        desc_html: Visa offentlig tidslinje på landingsidan
+        title: Förhandsgranska tidslinje
+      title: Sidans inställningar
+    statuses:
+      back_to_account: Tillbaka till kontosidan
+      batch:
+        delete: Ta bort
+        nsfw_off: NSFW AV
+        nsfw_on: NSFW PÅ
+      execute: Kör
+      failed_to_execute: Misslyckades att köra
+      media:
+        hide: Dölj media
+        show: Visa media
+        title: Media
+      no_media: Ingen media
+      title: Kontostatus
+      with_media: med media
+    subscriptions:
+      callback_url: Återanrop URL
+      confirmed: Bekräftad
+      expires_in: Går ut om
+      last_delivery: Sista leverans
+      title: WebSub
+      topic: Ämne
+    title: Administration
+  admin_mailer:
+    new_report:
+      body: "%{reporter} har rapporterat %{target}"
+      subject: Ny rapport för %{instance} (#%{id})
+  application_mailer:
+    salutation: "%{name},"
+    settings: 'Change e-mail preferences: %{link}'
+    signature: Mastodon meddelande från %{instance}
+    view: 'Granska:'
+  applications:
+    created: Ansökan är framgångsrikt skapad
+    destroyed: Ansökan är framgångsrikt borttagen
+    invalid_url: Den angivna webbadressen är ogiltig
+    regenerate_token: Regenerera access token
+    token_regenerated: Access token lyckades regenereras
+    warning: Var mycket försiktig med denna data. Dela aldrig den med någon!
+    your_token: Din access token
+  auth:
+    agreement_html: Genom att registrera dig godkänner du <a href="%{rules_path}">våra användarvillkor</a> och <a href="%{terms_path}">sekretesspolicy</a>.
+    change_password: Säkerhet
+    delete_account: Ta bort konto
+    delete_account_html: Om du vill radera ditt konto kan du <a href="%{path}">fortsätta här</a>. Du kommer att bli ombedd att bekräfta.
+    didnt_get_confirmation: Fick inte instruktioner om bekräftelse?
+    forgot_password: Glömt ditt lösenord?
+    invalid_reset_password_token: Lösenordsåterställningstoken är ogiltig eller utgått. Vänligen be om en ny.
+    login: Logga in
+    logout: Logga ut
+    register: Registrera
+    resend_confirmation: Skicka instruktionerna om bekräftelse igen
+    reset_password: Återställ lösenord
+    set_new_password: Skriv in nytt lösenord
+  authorize_follow:
+    error: Tyvärr inträffade ett fel när vi kontrollerade fjärrkontot
+    follow: Följ
+    follow_request: 'Du har skickat en följaförfrågan till:'
+    following: 'Succé! Du följer nu:'
+    post_follow:
+      close: Eller så kan du stänga detta fönster.
+      return: Återgå till användarens profil
+      web: Gå till webb
+    title: Följ %{acct}
+  datetime:
+    distance_in_words:
+      about_x_hours: "%{count}tim"
+      about_x_months: "%{count}mån"
+      about_x_years: "%{count}år"
+      almost_x_years: "%{count}år"
+      half_a_minute: Just nu
+      less_than_x_minutes: "%{count}min"
+      less_than_x_seconds: Just nu
+      over_x_years: "%{count}år"
+      x_days: "%{count}d"
+      x_minutes: "%{count}min"
+      x_months: "%{count}mån"
+      x_seconds: "%{count}sek"
+  deletes:
+    bad_password_msg: Bra försök, hackare! Fel lösenord
+    confirm_password: Ange ditt lösenord för att verifiera din identitet
+    description_html: Detta vill <strong>permanent, irreversibelt</strong> ta bort innehåll från ditt konto och avaktivera det. Ditt användarnamn kommer att förbli reserverat för att förhindra framtida efterföljare.
+    proceed: Ta bort konto
+    success_msg: Ditt konto har tagits bort
+    warning_html: Endast borttagning av innehåll från denna speciella instans garanteras. Innehåll som har delats i stor utsträckning kommer sannolikt att lämna spår. Offline-servrar och servrar som har avstängt från dina uppdateringar uppdaterar inte sina databaser.
+    warning_title: Spridet innehåll och tillgänglighet
+  errors:
+    '403': Du har inte behörighet att visa den här sidan.
+    '404': Sidan du letade efter existerar inte.
+    '410': Sidan du letade efter existerar inte längre.
+    '422':
+      content: Säkerhetsverifiering misslyckades Blockerar du cookies?
+      title: Säkerhetsverifiering misslyckades
+    '429': Strypt
+    '500':
+      content: Vi är ledsna, men något gick fel från vårat håll.
+      title: Den här sidan är inte korrekt
+    noscript_html: För att använda Mastodon webbapplikationen, vänligen aktivera JavaScript. Alternativt kan du prova en av <a href="https://github.com/tootsuite/documentation/blob/master/Using-Mastodon/Apps.md">inhemska appar</a> för Mastodon för din plattform.
+  exports:
+    blocks: Du blockerar
+    csv: CSV
+    follows: Du följer
+    mutes: Du tystar
+    storage: Media lagring
+  followers:
+    domain: Domän
+    explanation_html: Om du vill se integriteten för dina statusar måste du vara medveten om vem som följer dig. <strong>Dina privata statusar levereras till alla instanser där du har följare</strong>. Du kanske vill granska dem och ta bort följare om du inte litar på att din integritet respekteras av staff eller programvaran i instanserna.
+    followers_count: Antal följare
+    lock_link: Lås ditt konto
+    purge: Ta bort från följare
+    success:
+      one: I processen med soft-blocking följare från en domän ...
+      other: I processen med soft-blocking följare från %{count} domäner...
+    true_privacy_html: Kom ihåg att <strong>sann integritet kan bara uppnås med end-to-end kryptering</strong>.
+    unlocked_warning_html: Vem som helst kan följa dig omedelbart se dina privata statusar. %{lock_link} för att kunna granska och avvisa följare.
+    unlocked_warning_title: Ditt konto är inte låst
+  generic:
+    changes_saved_msg: Ändringar sparades framgångsrikt!
+    powered_by: powered by %{link}
+    save_changes: Spara ändringar
+    validation_errors:
+      one: Något är inte riktigt rätt ännu! Kontrollera felet nedan
+      other: Något är inte riktigt rätt ännu! Kontrollera dom %{count} felen nedan
+  imports:
+    preface: Du kan importera data som du exporterat från en annan instans, till exempel en lista över personer du följer eller blockerar.
+    success: Dina uppgifter har laddats upp och kommer nu att behandlas snarast
+    types:
+      blocking: Blockering lista
+      following: Följare lista
+      muting: Tystade lista
+    upload: Ladda upp
+  landing_strip_html: "<strong>%{name}</strong> är en användare på %{link_to_root_path}. Du kan följa dem eller interagera med dem om du har ett konto någonstans i federationen."
+  landing_strip_signup_html: Om du inte gör det, så kan du <a href="%{sign_up_path}">registrera dig här</a>.
+  media_attachments:
+    validations:
+      images_and_video: Det går inte att bifoga en video till en status som redan innehåller bilder
+      too_many: Det går inte att bifoga mer än 4 filer
+  notification_mailer:
+    digest:
+      body: 'Här är en kort sammanfattning av vad du missat på %{instance} sedan ditt senaste besök på %{since}:'
+      mention: "%{name} nämnde dig i:"
+      new_followers_summary:
+        one: Du har förvärvat en ny följare! Jippie!
+        other: Du har fått %{count} nya följare! Otroligt!
+      subject:
+        one: "1 nytt meddelande sedan ditt senaste besök \U0001F418"
+        other: "%{count} nya meddelanden sedan ditt senaste besök \U0001F418"
+    favourite:
+      body: 'Din status favoriserades av %{name}:'
+      subject: "%{name} favoriserade din status"
+    follow:
+      body: "%{name} följer nu dig!"
+      subject: "%{name} följer nu dig"
+    follow_request:
+      body: "%{name} har begärt att följa dig"
+      subject: 'Pending follower: %{name}'
+    mention:
+      body: 'Du nämndes av %{name} in:'
+      subject: Du nämndes av %{name}
+    reblog:
+      body: 'Din status boostades av %{name}:'
+      subject: "%{name} boostade din status"
+  number:
+    human:
+      decimal_units:
+        format: "%n%u"
+        units:
+          billion: B
+          million: M
+          quadrillion: Q
+          thousand: K
+          trillion: T
+          unit: ''
+  pagination:
+    next: Nästa
+    prev: Tidigare
+    truncate: "&hellip;"
+  preferences:
+    languages: Språk
+    other: Annat
+    publishing: Publicering
+    web: Webb
+  push_notifications:
+    favourite:
+      title: "%{name} favoriserade din status"
+    follow:
+      title: "%{name} följer nu dig"
+    group:
+      title: "%{count} meddelanden"
+    mention:
+      action_boost: Boosta
+      action_expand: Visa mer
+      action_favourite: Favoriter
+      title: "%{name} nämnde dig"
+    reblog:
+      title: "%{name} boostade din status"
+  remote_follow:
+    acct: Ange ditt användarnamn@domän du vill följa från
+    missing_resource: Det gick inte att hitta den begärda omdirigeringsadressen för ditt konto
+    proceed: Fortsätt för att följa
+    prompt: 'Du kommer att följa:'
+  sessions:
+    activity: Senaste aktivitet
+    browser: Webbläsare
+    browsers:
+      alipay: Alipay
+      blackberry: Blackberry
+      chrome: Chrome
+      edge: Microsoft Edge
+      firefox: Firefox
+      generic: Okänd browser
+      ie: Internet Explorer
+      micro_messenger: MicroMessenger
+      nokia: Nokia S40 Ovi Browser
+      opera: Opera
+      phantom_js: PhantomJS
+      qq: QQ Browser
+      safari: Safari
+      uc_browser: UCBrowser
+      weibo: Weibo
+    current_session: Nuvarande session
+    description: "%{browser} på %{platform}"
+    explanation: Detta är inloggade webbläsare på Mastodon just nu
+    ip: IP
+    platforms:
+      adobe_air: Adobe Air
+      android: Android
+      blackberry: Blackberry
+      chrome_os: ChromeOS
+      firefox_os: Firefox OS
+      ios: iOS
+      linux: Linux
+      mac: Mac
+      other: okänd plattform
+      windows: Windows
+      windows_mobile: Windows Mobile
+      windows_phone: Windows Phone
+    revoke: Återkalla
+    revoke_success: Sessionen återkallas framgångsrikt
+    title: Sessioner
+  settings:
+    authorized_apps: Godkända appar
+    back: Tillbaka till Mastodon
+    delete: Konto radering
+    development: Utveckling
+    edit_profile: Redigera profil
+    export: Data export
+    followers: Auktoriserade följare
+    import: Import
+    notifications: Meddelanden
+    preferences: Inställningar
+    settings: Inställningar
+    two_factor_authentication: Två-faktor autentisering
+    your_apps: Dina applikationer
+  statuses:
+    open_in_web: Öppna på webben
+    over_character_limit: teckengräns på %{max} har överskridits
+    pin_errors:
+      limit: För många tootar fästa
+      ownership: Någon annans toot kan inte fästas
+      private: Icke-offentliga toot kan inte fästas
+      reblog: En boost kan inte fästas
+    show_more: Visa mer
+    visibilities:
+      private: Endast följare
+      private_long: Visa endast till följare
+      public: Offentlig
+      public_long: Alla kan se
+      unlisted: Olistade
+      unlisted_long: Alla kan se, men inte listade på offentliga tidslinjer
+  stream_entries:
+    click_to_show: Klicka för att visa
+    pinned: Fäst toot
+    reblogged: boostad
+    sensitive_content: Känsligt innehåll
+  terms:
+    body_html: |
+      <h2>Integritetspolicy</h2>
+
+      <h3 id="collect">Vilken information samlar vi in</h3>
+
+      <p>Vi samlar in information från dig när du registrerar dig på vår webbplats och samlar in data när du deltar i forumet genom att läsa, skriva och utvärdera innehållet som delas här.</p>
+
+      <p>När du registrerar dig på vår webbplats kan du bli ombedd att ange ditt namn och din e-postadress. Du kan dock besöka vår webbplats utan att registrera dig. Din e-postadress kommer att verifieras med ett e-postmeddelande som innehåller en unik länk. Om den länken besöks vet vi att du kontrollerar e-postadressen.</p>
+
+      <p>När vi registrerar och postar registrerar vi den IP-adress som posten härstammar från. Vi kan också behålla serverns loggar som innehåller IP-adress för varje begäran till vår server.</p>
+
+      <h3 id="use">Vad använder vi din information för?</h3>
+
+      <p>Vilken som helst information vi samlar in från dig kan användas på något av följande sätt:</p>
+
+      <ul>
+        <li>För att personifiera din upplevelse & mdash; Din information hjälper oss att bättre svara på dina individuella behov.</li>
+        <li>För att förbättra vår webbplats & mdash; Vi strävar kontinuerligt efter att förbättra våra erbjudanden på webbplatsen baserat på information och feedback vi mottar från dig.</li>
+        <li>För att förbättra kundtjänst & mdash; Din information hjälper oss att effektivt svara på dina kundserviceförfrågningar och supportbehov.</li>
+        <li>För att skicka periodiska e-postmeddelanden & mdash; Den e-postadress du anger kan användas för att skicka information, meddelanden som du begär om ändringar i ämnen eller som svar på ditt användarnamn, svara på förfrågningar och / eller andra förfrågningar eller frågor.</li>
+      </ul>
+
+      <h3 id="protect">Hur skyddar vi din information?</h3>
+
+      <p>Vi genomför en rad säkerhetsåtgärder för att upprätthålla säkerheten för din personliga information när du anger, lämnar in eller har tillgång till din personliga information.</p>
+
+      <h3 id="data-retention">Vad är policyn för lagring av data?</h3>
+
+      <p>Vi kommer att göra en ansträngning för:</p>
+
+      <ul>
+        <li>Behåll serverloggar som innehåller IP-adressen för alla förfrågningar till den här servern inte mer än 90 dagar.</li>
+        <li>Behåll IP-adresserna i samband med registrerade användare och deras inlägg inte längre än 5 år.</li>
+      </ul>
+
+      <h3 id="cookies">Använder vi cookies?</h3>
+
+      <p>Ja. Cookies är små filer som en webbplats eller tjänstleverantör överför till datorns hårddisk via din webbläsare (om du tillåter). Dessa cookies tillåter webbplatsen att känna igen din webbläsare och, om du har ett registrerat konto, associerar det med ditt registrerade konto.</p>
+
+      <p>Vi använder cookies för att förstå och spara dina inställningar för framtida besök och sammanställa sammanlagda data om webbplatsstrafik och webbplatsinteraktion så att vi kan erbjuda bättre sajtupplevelser och verktyg i framtiden. Vi kan komma överens med tredje parts tjänsteleverantörer för att hjälpa oss att bättre förstå våra besökare. Dessa tjänsteleverantörer får inte använda den information som samlas in för vår räkning utom för att hjälpa oss att bedriva och förbättra vår verksamhet.</p>
+
+      <h3 id="disclose">Avslöjar vi information till utomstående parter?</h3>
+
+      <p>Vi säljer inte, handlar eller på annat sätt överför dina personuppgifter till utomstående parter. Det här omfattar inte betrodda tredje parter som hjälper oss att driva vår webbplats, bedriva vår verksamhet eller service dig, så länge dessa parter är överens om att hålla denna information konfidentiell. Vi kan också släppa din information när vi anser att utgåvan är lämplig för att följa lagen, tillämpa vår webbplatspolicy eller skydda vår eller andra rättigheter, egendom eller säkerhet. Däremot kan personuppgifter som inte identifieras personligen lämnas till andra parter för marknadsföring, reklam eller annan användning.</p>
+
+      <h3 id="third-party">Tredjepartslänkar</h3>
+
+      <p>Ibland kan vi, efter eget gottfinnande, inkludera eller erbjuda produkter från tredje part eller tjänster på vår webbplats. Dessa tredje parts webbplatser har separata och oberoende sekretesspolicyer. Vi har därför inget ansvar eller ansvar för innehållet och aktiviteterna för dessa länkade webbplatser. Ändå försöker vi skydda integriteten på vår webbplats och välkomna eventuella återkopplingar om dessa webbplatser.</p>
+
+      <h3 id="coppa">Children's Online Privacy Protection Act Compliance</h3>
+
+      <p>Vår webbplats, produkter och tjänster riktas alla till personer som är minst 13 år gamla. Om den här servern är i USA, och du är under 13 år, enligt kraven i COPPA (<a href="https://en.wikipedia.org/wiki/Children%27s_Online_Privacy_Protection_Act">Children's Online Privacy Protection Act</a>) ska du inte använda denna sida.</p>
+
+      <h3 id="online">Endast online sekretesspolicy</h3>
+
+      <p>Denna online sekretesspolicy gäller endast information som samlas in via vår webbplats och inte till information som samlas in offline.</p>
+
+      <h3 id="consent">Ditt samtycke</h3>
+
+      <p>Genom att använda vår webbplats godkänner du vår hemsida sekretesspolicy.</p>
+
+      <h3 id="changes">Ändringar i vår sekretesspolicy</h3>
+
+      <p>Om vi bestämmer oss för att ändra vår integritetspolicy, lägger vi in de ändringar på den här sidan.</p>
+
+      <p>This document is CC-BY-SA. It was last updated May 31, 2013.</p>
+
+      <p>Ursprungligen anpassad från <a href="https://github.com/discourse/discourse">Discourse integritetspolicy</a>.</p>
+    title: "%{instance} Användarvillkor och Sekretesspolicy"
+  themes:
+    default: Mastodon
+  time:
+    formats:
+      default: "%b %d, %Y, %H:%M"
+  two_factor_authentication:
+    code_hint: Ange koden som genererats av din autentiseringsapp för att bekräfta
+    description_html: Om du aktiverar <strong>tvåfaktors autentisering</strong>, loggar in kommer att kräva att du är i besittning av din telefon, vilket kommer att generera tokens för dig att uppge.
+    disable: Avaktivera
+    enable: Aktivera
+    enabled: Tvåfaktorsautentisering är aktiverad
+    enabled_success: Tvåfaktors autentisering aktiverad
+    generate_recovery_codes: Generera återställningskoder
+    instructions_html: "<strong>Skanna den här QR-koden i Google Authenticator eller en liknande TOTP-app på din telefon </strong>. Från och med nu genererar den appen tokens som du måste ange när du loggar in."
+    lost_recovery_codes: Återställningskoder tillåter dig att få tillgång till ditt konto om du förlorar din telefon. Om du har förlorat dina återställningskoder kan du regenerera dem här. Dina gamla återställningskoder kommer att ogiltigförklaras.
+    manual_instructions: 'Om du inte kan skanna QR-koden och behöver skriva in den manuellt, här är den enkla texten:'
+    recovery_codes: Backup återställningskod
+    recovery_codes_regenerated: Återställningskoder regenererades framgångsrikt
+    recovery_instructions_html: Om du någonsin tappar åtkomst till din telefon kan du använda någon av återställningskoderna nedan för att återställa åtkomst till ditt konto. <strong> Håll återställningskoderna säkra </strong>. Du kan till exempel skriva ut dem och lagra dem med andra viktiga dokument.
+    setup: Ställ in
+    wrong_code: Den angivna koden var ogiltig! Är servertid och enhetstid korrekt?
+  users:
+    invalid_email: E-postadressen är ogiltig
+    invalid_otp_token: Ogiltig tvåfaktorkod
+    signed_in_as: 'Inloggad som:'
diff --git a/jest.config.js b/jest.config.js
index dd9dadf87..50bde57e6 100644
--- a/jest.config.js
+++ b/jest.config.js
@@ -14,4 +14,12 @@ module.exports = {
     'raf/polyfill',
   ],
   setupTestFrameworkScriptFile: '<rootDir>/app/javascript/mastodon/test_setup.js',
+  collectCoverageFrom: [
+    'app/javascript/mastodon/**/*.js',
+    '!app/javascript/mastodon/features/emoji/emoji_compressed.js',
+    '!app/javascript/mastodon/locales/locale-data/*.js',
+    '!app/javascript/mastodon/service_worker/entry.js',
+    '!app/javascript/mastodon/test_setup.js',
+  ],
+  coverageDirectory: '<rootDir>/coverage',
 };
diff --git a/lib/mastodon/version.rb b/lib/mastodon/version.rb
index e7b3085e5..f10ace13e 100644
--- a/lib/mastodon/version.rb
+++ b/lib/mastodon/version.rb
@@ -21,7 +21,7 @@ module Mastodon
     end
 
     def flags
-      'rc3'
+      ''
     end
 
     def to_a
diff --git a/package.json b/package.json
index 0863412eb..5856b56db 100644
--- a/package.json
+++ b/package.json
@@ -9,7 +9,7 @@
     "start": "node ./streaming/index.js",
     "test": "npm run test:lint && npm run test:jest",
     "test:lint": "eslint -c .eslintrc.yml --ext=js app/javascript/ config/webpack/ spec/javascript/ streaming/",
-    "test:jest": "cross-env NODE_ENV=test jest",
+    "test:jest": "cross-env NODE_ENV=test jest --coverage",
     "postinstall": "npm rebuild node-sass"
   },
   "repository": {
diff --git a/spec/lib/feed_manager_spec.rb b/spec/lib/feed_manager_spec.rb
index 454c3afec..0f97a579e 100644
--- a/spec/lib/feed_manager_spec.rb
+++ b/spec/lib/feed_manager_spec.rb
@@ -211,6 +211,22 @@ RSpec.describe FeedManager do
         expect(FeedManager.instance.push('type', account, reblogs.last)).to be false
       end
 
+      it 'does not save a new reblog of a multiply-reblogged-then-unreblogged status' do
+        account   = Fabricate(:account)
+        reblogged = Fabricate(:status)
+        reblogs = 3.times.map { Fabricate(:status, reblog: reblogged) }
+
+        # Accept the reblogs
+        FeedManager.instance.push('type', account, reblogs[0])
+        FeedManager.instance.push('type', account, reblogs[1])
+
+        # Unreblog the first one
+        FeedManager.instance.unpush('type', account, reblogs[0])
+
+        # The last reblog should still be ignored
+        expect(FeedManager.instance.push('type', account, reblogs.last)).to be false
+      end
+
       it 'saves a new reblog of a long-ago-reblogged status' do
         account = Fabricate(:account)
         reblogged = Fabricate(:status)
@@ -230,6 +246,38 @@ RSpec.describe FeedManager do
     end
   end
 
+  describe '#trim' do
+    let(:receiver) { Fabricate(:account) }
+
+    it 'cleans up reblog tracking keys' do
+      reblogged      = Fabricate(:status)
+      status         = Fabricate(:status, reblog: reblogged)
+      another_status = Fabricate(:status, reblog: reblogged)
+      reblogs_key    = FeedManager.instance.key('type', receiver.id, 'reblogs')
+      reblog_set_key = FeedManager.instance.key('type', receiver.id, "reblogs:#{reblogged.id}")
+
+      FeedManager.instance.push('type', receiver, status)
+      FeedManager.instance.push('type', receiver, another_status)
+
+      # We should have a tracking set and an entry in reblogs.
+      expect(Redis.current.exists(reblog_set_key)).to be true
+      expect(Redis.current.zrange(reblogs_key, 0, -1)).to eq [reblogged.id.to_s]
+
+      # Push everything off the end of the feed.
+      FeedManager::MAX_ITEMS.times do
+        FeedManager.instance.push('type', receiver, Fabricate(:status))
+      end
+
+      # `trim` should be called automatically, but do it anyway, as
+      # we're testing `trim`, not side effects of `push`.
+      FeedManager.instance.trim('type', receiver.id)
+
+      # We should not have any reblog tracking data.
+      expect(Redis.current.exists(reblog_set_key)).to be false
+      expect(Redis.current.zrange(reblogs_key, 0, -1)).to be_empty
+    end
+  end
+
   describe '#unpush' do
     let(:receiver) { Fabricate(:account) }
 
@@ -265,20 +313,22 @@ RSpec.describe FeedManager do
       expect(Redis.current.zrange("feed:type:#{receiver.id}", 0, -1)).to be_empty
     end
 
-    it 'leaves a reblogged status if another reblog was in feed' do
-      reblogged      = Fabricate(:status)
-      status         = Fabricate(:status, reblog: reblogged)
-      another_status = Fabricate(:status, reblog: reblogged)
+    it 'leaves a multiply-reblogged status if another reblog was in feed' do
+      reblogged = Fabricate(:status)
+      reblogs   = 3.times.map { Fabricate(:status, reblog: reblogged) }
 
-      FeedManager.instance.push('type', receiver, status)
-      FeedManager.instance.push('type', receiver, another_status)
+      reblogs.each do |reblog|
+        FeedManager.instance.push('type', receiver, reblog)
+      end
 
       # The reblogging status should show up under normal conditions.
-      expect(Redis.current.zrange("feed:type:#{receiver.id}", 0, -1)).to eq [status.id.to_s]
+      expect(Redis.current.zrange("feed:type:#{receiver.id}", 0, -1)).to eq [reblogs.first.id.to_s]
 
-      FeedManager.instance.unpush('type', receiver, status)
+      reblogs[0...-1].each do |reblog|
+        FeedManager.instance.unpush('type', receiver, reblog)
+      end
 
-      expect(Redis.current.zrange("feed:type:#{receiver.id}", 0, -1)).to eq [another_status.id.to_s]
+      expect(Redis.current.zrange("feed:type:#{receiver.id}", 0, -1)).to eq [reblogs.last.id.to_s]
     end
 
     it 'sends push updates' do
diff --git a/spec/workers/scheduler/feed_cleanup_scheduler_spec.rb b/spec/workers/scheduler/feed_cleanup_scheduler_spec.rb
index b8487b03f..7fae680ba 100644
--- a/spec/workers/scheduler/feed_cleanup_scheduler_spec.rb
+++ b/spec/workers/scheduler/feed_cleanup_scheduler_spec.rb
@@ -9,14 +9,18 @@ describe Scheduler::FeedCleanupScheduler do
   it 'clears feeds of inactives' do
     Redis.current.zadd(feed_key_for(inactive_user), 1, 1)
     Redis.current.zadd(feed_key_for(active_user), 1, 1)
+    Redis.current.zadd(feed_key_for(inactive_user, 'reblogs'), 2, 2)
+    Redis.current.sadd(feed_key_for(inactive_user, 'reblogs:2'), 3)
 
     subject.perform
 
     expect(Redis.current.zcard(feed_key_for(inactive_user))).to eq 0
     expect(Redis.current.zcard(feed_key_for(active_user))).to eq 1
+    expect(Redis.current.exists(feed_key_for(inactive_user, 'reblogs'))).to be false
+    expect(Redis.current.exists(feed_key_for(inactive_user, 'reblogs:2'))).to be false
   end
 
-  def feed_key_for(user)
-    FeedManager.instance.key(:home, user.account_id)
+  def feed_key_for(user, subtype = nil)
+    FeedManager.instance.key(:home, user.account_id, subtype)
   end
 end
diff --git a/streaming/index.js b/streaming/index.js
index 017073fa1..83903b89b 100644
--- a/streaming/index.js
+++ b/streaming/index.js
@@ -80,7 +80,7 @@ const startWorker = (workerId) => {
     development: {
       user:     process.env.DB_USER || pg.defaults.user,
       password: process.env.DB_PASS || pg.defaults.password,
-      database: 'mastodon_development',
+      database: process.env.DB_NAME || 'mastodon_development',
       host:     process.env.DB_HOST || pg.defaults.host,
       port:     process.env.DB_PORT || pg.defaults.port,
       max:      10,