about summary refs log tree commit diff
path: root/app
diff options
context:
space:
mode:
Diffstat (limited to 'app')
-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
68 files changed, 549 insertions, 105 deletions
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