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/features/ui/index.js2
-rw-r--r--app/javascript/mastodon/locales/cs.json2
-rw-r--r--app/javascript/mastodon/locales/es-MX.json28
-rw-r--r--app/javascript/mastodon/locales/es.json18
-rw-r--r--app/javascript/mastodon/locales/hu.json2
-rw-r--r--app/javascript/mastodon/locales/it.json2
-rw-r--r--app/javascript/mastodon/locales/th.json70
-rw-r--r--app/javascript/mastodon/locales/vi.json4
-rw-r--r--app/javascript/mastodon/locales/zh-CN.json2
-rw-r--r--app/javascript/mastodon/reducers/notifications.js2
-rw-r--r--app/javascript/styles/mailer.scss1
-rw-r--r--app/javascript/styles/mastodon/about.scss1
-rw-r--r--app/javascript/styles/mastodon/components.scss1
-rw-r--r--app/javascript/styles/mastodon/widgets.scss1
-rw-r--r--app/lib/activitypub/activity.rb4
-rw-r--r--app/services/activitypub/process_account_service.rb2
-rw-r--r--app/services/fetch_link_card_service.rb2
-rw-r--r--app/services/remove_status_service.rb2
-rw-r--r--app/services/resolve_account_service.rb2
-rw-r--r--app/workers/distribution_worker.rb2
21 files changed, 74 insertions, 77 deletions
diff --git a/app/helpers/settings_helper.rb b/app/helpers/settings_helper.rb
index b60901040..0ebfab75d 100644
--- a/app/helpers/settings_helper.rb
+++ b/app/helpers/settings_helper.rb
@@ -18,6 +18,7 @@ module SettingsHelper
     en: 'English',
     eo: 'Esperanto',
     'es-AR': 'Español (Argentina)',
+    'es-MX': 'Español (México)',
     es: 'Español',
     et: 'Eesti',
     eu: 'Euskara',
diff --git a/app/javascript/mastodon/features/ui/index.js b/app/javascript/mastodon/features/ui/index.js
index 2b9fe1603..c1c6ac739 100644
--- a/app/javascript/mastodon/features/ui/index.js
+++ b/app/javascript/mastodon/features/ui/index.js
@@ -361,9 +361,9 @@ class UI extends React.PureComponent {
       this.props.dispatch(closeOnboarding());
     }
 
+    this.props.dispatch(fetchMarkers());
     this.props.dispatch(expandHomeTimeline());
     this.props.dispatch(expandNotifications());
-    setTimeout(() => this.props.dispatch(fetchMarkers()), 500);
     setTimeout(() => this.props.dispatch(fetchFilters()), 500);
 
     this.hotkeys.__mousetrap__.stopCallback = (e, element) => {
diff --git a/app/javascript/mastodon/locales/cs.json b/app/javascript/mastodon/locales/cs.json
index 607e31348..ca0a34b33 100644
--- a/app/javascript/mastodon/locales/cs.json
+++ b/app/javascript/mastodon/locales/cs.json
@@ -31,7 +31,7 @@
   "account.moved_to": "Uživatel {name} se přesunul na:",
   "account.mute": "Skrýt @{name}",
   "account.mute_notifications": "Skrýt oznámení od @{name}",
-  "account.muted": "Účet skryt",
+  "account.muted": "Skryt",
   "account.never_active": "Nikdy",
   "account.posts": "Příspěvky",
   "account.posts_with_replies": "Příspěvky a odpovědi",
diff --git a/app/javascript/mastodon/locales/es-MX.json b/app/javascript/mastodon/locales/es-MX.json
index 2551cdaee..f0fbee142 100644
--- a/app/javascript/mastodon/locales/es-MX.json
+++ b/app/javascript/mastodon/locales/es-MX.json
@@ -22,7 +22,7 @@
   "account.follows.empty": "Este usuario todavía no sigue a nadie.",
   "account.follows_you": "Te sigue",
   "account.hide_reblogs": "Ocultar retoots de @{name}",
-  "account.joined": "Joined {date}",
+  "account.joined": "Se unió el {date}",
   "account.last_status": "Última actividad",
   "account.link_verified_on": "El proprietario de este link fue comprobado el {date}",
   "account.locked_info": "El estado de privacidad de esta cuenta està configurado como bloqueado. El proprietario debe revisar manualmente quien puede seguirle.",
@@ -98,7 +98,7 @@
   "compose_form.poll.switch_to_multiple": "Modificar encuesta para permitir múltiples opciones",
   "compose_form.poll.switch_to_single": "Modificar encuesta para permitir una única opción",
   "compose_form.publish": "Tootear",
-  "compose_form.publish_loud": "{publish}!",
+  "compose_form.publish_loud": "¡{publish}!",
   "compose_form.sensitive.hide": "Marcar multimedia como sensible",
   "compose_form.sensitive.marked": "Material marcado como sensible",
   "compose_form.sensitive.unmarked": "Material no marcado como sensible",
@@ -160,11 +160,11 @@
   "empty_column.domain_blocks": "Todavía no hay dominios ocultos.",
   "empty_column.favourited_statuses": "Aún no tienes toots preferidos. Cuando marques uno como favorito, aparecerá aquí.",
   "empty_column.favourites": "Nadie ha marcado este toot como preferido. Cuando alguien lo haga, aparecerá aquí.",
-  "empty_column.follow_recommendations": "Looks like no suggestions could be generated for you. You can try using search to look for people you might know or explore trending hashtags.",
+  "empty_column.follow_recommendations": "Parece que no se ha podido generar ninguna sugerencia para ti. Puedes probar a buscar a gente que quizá conozcas o explorar los hashtags que están en tendencia.",
   "empty_column.follow_requests": "No tienes ninguna petición de seguidor. Cuando recibas una, se mostrará aquí.",
   "empty_column.hashtag": "No hay nada en este hashtag aún.",
   "empty_column.home": "No estás siguiendo a nadie aún. Visita {public} o haz búsquedas para empezar y conocer gente nueva.",
-  "empty_column.home.suggestions": "See some suggestions",
+  "empty_column.home.suggestions": "Ver algunas sugerencias",
   "empty_column.list": "No hay nada en esta lista aún. Cuando miembros de esta lista publiquen nuevos estatus, estos aparecerán qui.",
   "empty_column.lists": "No tienes ninguna lista. cuando crees una, se mostrará aquí.",
   "empty_column.mutes": "Aún no has silenciado a ningún usuario.",
@@ -177,8 +177,8 @@
   "errors.unexpected_crash.copy_stacktrace": "Copiar el seguimiento de pila en el portapapeles",
   "errors.unexpected_crash.report_issue": "Informar de un problema/error",
   "follow_recommendations.done": "Hecho",
-  "follow_recommendations.heading": "¡Sigue a la gente cuyas publicaciones te gustaría ver! Aquí tienes algunas sugerencias.",
-  "follow_recommendations.lead": "Los mensajes de las personas que sigues aparecerán en orden cronológico en el Inicio. No tengas miedo de cometer errores, ¡puedes dejar de seguir a la gente fácilmente en cualquier momento!",
+  "follow_recommendations.heading": "¡Sigue a gente que publique cosas que te gusten! Aquí tienes algunas sugerencias.",
+  "follow_recommendations.lead": "Las publicaciones de la gente a la que sigas aparecerán ordenadas cronológicamente en Inicio. No tengas miedo de cometer errores, ¡puedes dejarles de seguir en cualquier momento con la misma facilidad!",
   "follow_request.authorize": "Autorizar",
   "follow_request.reject": "Rechazar",
   "follow_requests.unlocked_explanation": "A pesar de que tu cuenta no es privada, el personal de {domain} ha pensado que quizás deberías revisar manualmente las solicitudes de seguimiento de estas cuentas.",
@@ -335,7 +335,7 @@
   "picture_in_picture.restore": "Restaurar",
   "poll.closed": "Cerrada",
   "poll.refresh": "Actualizar",
-  "poll.total_people": "{count, plural, one {# person} other {# people}}",
+  "poll.total_people": "{count, plural, one {# persona} other {# personas}}",
   "poll.total_votes": "{count, plural, one {# voto} other {# votos}}",
   "poll.vote": "Votar",
   "poll.voted": "Has votado a favor de esta respuesta",
@@ -353,11 +353,11 @@
   "refresh": "Actualizar",
   "regeneration_indicator.label": "Cargando…",
   "regeneration_indicator.sublabel": "¡Tu historia de inicio se está preparando!",
-  "relative_time.days": "{number}d",
-  "relative_time.hours": "{number}h",
+  "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",
+  "relative_time.minutes": "{number} m",
+  "relative_time.seconds": "{number} s",
   "relative_time.today": "hoy",
   "reply_indicator.cancel": "Cancelar",
   "report.forward": "Reenviar a {target}",
@@ -439,9 +439,9 @@
   "trends.counter_by_accounts": "{count, plural, one {{counter} persona} other {{counter} personas}} hablando",
   "trends.trending_now": "Tendencia ahora",
   "ui.beforeunload": "Tu borrador se perderá si sales de Mastodon.",
-  "units.short.billion": "{count}B",
-  "units.short.million": "{count}M",
-  "units.short.thousand": "{count}K",
+  "units.short.billion": "{count} MM",
+  "units.short.million": "{count} M",
+  "units.short.thousand": "{count} K",
   "upload_area.title": "Arrastra y suelta para subir",
   "upload_button.label": "Subir multimedia (JPEG, PNG, GIF, WebM, MP4, MOV)",
   "upload_error.limit": "Límite de subida de archivos excedido.",
diff --git a/app/javascript/mastodon/locales/es.json b/app/javascript/mastodon/locales/es.json
index 37ce004f1..fa0838a31 100644
--- a/app/javascript/mastodon/locales/es.json
+++ b/app/javascript/mastodon/locales/es.json
@@ -98,7 +98,7 @@
   "compose_form.poll.switch_to_multiple": "Modificar encuesta para permitir múltiples opciones",
   "compose_form.poll.switch_to_single": "Modificar encuesta para permitir una única opción",
   "compose_form.publish": "Tootear",
-  "compose_form.publish_loud": "{publish}!",
+  "compose_form.publish_loud": "¡{publish}!",
   "compose_form.sensitive.hide": "Marcar multimedia como sensible",
   "compose_form.sensitive.marked": "Material marcado como sensible",
   "compose_form.sensitive.unmarked": "Material no marcado como sensible",
@@ -335,7 +335,7 @@
   "picture_in_picture.restore": "Restaurar",
   "poll.closed": "Cerrada",
   "poll.refresh": "Actualizar",
-  "poll.total_people": "{count, plural, one {# person} other {# people}}",
+  "poll.total_people": "{count, plural, one {# persona} other {# personas}}",
   "poll.total_votes": "{count, plural, one {# voto} other {# votos}}",
   "poll.vote": "Votar",
   "poll.voted": "Has votado a favor de esta respuesta",
@@ -353,11 +353,11 @@
   "refresh": "Actualizar",
   "regeneration_indicator.label": "Cargando…",
   "regeneration_indicator.sublabel": "¡Tu historia de inicio se está preparando!",
-  "relative_time.days": "{number}d",
-  "relative_time.hours": "{number}h",
+  "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",
+  "relative_time.minutes": "{number} m",
+  "relative_time.seconds": "{number} s",
   "relative_time.today": "hoy",
   "reply_indicator.cancel": "Cancelar",
   "report.forward": "Reenviar a {target}",
@@ -439,9 +439,9 @@
   "trends.counter_by_accounts": "{count, plural, one {{counter} persona} other {{counter} personas}} hablando",
   "trends.trending_now": "Tendencia ahora",
   "ui.beforeunload": "Tu borrador se perderá si sales de Mastodon.",
-  "units.short.billion": "{count}B",
-  "units.short.million": "{count}M",
-  "units.short.thousand": "{count}K",
+  "units.short.billion": "{count} MM",
+  "units.short.million": "{count} M",
+  "units.short.thousand": "{count} K",
   "upload_area.title": "Arrastra y suelta para subir",
   "upload_button.label": "Subir multimedia (JPEG, PNG, GIF, WebM, MP4, MOV)",
   "upload_error.limit": "Límite de subida de archivos excedido.",
diff --git a/app/javascript/mastodon/locales/hu.json b/app/javascript/mastodon/locales/hu.json
index 71a494610..07f8b5f10 100644
--- a/app/javascript/mastodon/locales/hu.json
+++ b/app/javascript/mastodon/locales/hu.json
@@ -51,7 +51,7 @@
   "alert.rate_limited.title": "Forgalomkorlátozás",
   "alert.unexpected.message": "Váratlan hiba történt.",
   "alert.unexpected.title": "Hoppá!",
-  "announcement.announcement": "Bejelentés",
+  "announcement.announcement": "Közlemény",
   "autosuggest_hashtag.per_week": "{count} hetente",
   "boost_modal.combo": "Hogy átugord ezt következő alkalommal, használd {combo}",
   "bundle_column_error.body": "Valami hiba történt a komponens betöltése közben.",
diff --git a/app/javascript/mastodon/locales/it.json b/app/javascript/mastodon/locales/it.json
index a87963784..23b7c0d86 100644
--- a/app/javascript/mastodon/locales/it.json
+++ b/app/javascript/mastodon/locales/it.json
@@ -5,7 +5,7 @@
   "account.badges.group": "Gruppo",
   "account.block": "Blocca @{name}",
   "account.block_domain": "Blocca dominio {domain}",
-  "account.blocked": "Bloccat*",
+  "account.blocked": "Bloccato",
   "account.browse_more_on_origin_server": "Sfoglia ulteriormente sul profilo originale",
   "account.cancel_follow_request": "Annulla richiesta di seguire",
   "account.direct": "Messaggio diretto a @{name}",
diff --git a/app/javascript/mastodon/locales/th.json b/app/javascript/mastodon/locales/th.json
index a36586fcd..cc3af6493 100644
--- a/app/javascript/mastodon/locales/th.json
+++ b/app/javascript/mastodon/locales/th.json
@@ -121,7 +121,7 @@
   "confirmations.mute.explanation": "นี่จะซ่อนโพสต์จากเขาและโพสต์ที่กล่าวถึงเขา แต่จะยังอนุญาตให้เขาเห็นโพสต์ของคุณและติดตามคุณ",
   "confirmations.mute.message": "คุณแน่ใจหรือไม่ว่าต้องการซ่อน {name}?",
   "confirmations.redraft.confirm": "ลบแล้วร่างใหม่",
-  "confirmations.redraft.message": "คุณแน่ใจหรือไม่ว่าต้องการลบโพสต์นี้แล้วร่างใหม่? รายการโปรดและการดันจะหายไป และการตอบกลับโพสต์ดั้งเดิมจะไม่มีความเกี่ยวพัน",
+  "confirmations.redraft.message": "คุณแน่ใจหรือไม่ว่าต้องการลบโพสต์นี้แล้วร่างโพสต์ใหม่? รายการโปรดและการดันจะหายไป และการตอบกลับโพสต์ดั้งเดิมจะไม่มีความเกี่ยวพัน",
   "confirmations.reply.confirm": "ตอบกลับ",
   "confirmations.reply.message": "การตอบกลับตอนนี้จะเขียนทับข้อความที่คุณกำลังเขียน คุณแน่ใจหรือไม่ว่าต้องการดำเนินการต่อ?",
   "confirmations.unfollow.confirm": "เลิกติดตาม",
@@ -163,12 +163,12 @@
   "empty_column.follow_recommendations": "Looks like no suggestions could be generated for you. You can try using search to look for people you might know or explore trending hashtags.",
   "empty_column.follow_requests": "คุณยังไม่มีคำขอติดตามใด ๆ เมื่อคุณได้รับคำขอ คำขอจะปรากฏที่นี่",
   "empty_column.hashtag": "ยังไม่มีสิ่งใดในแฮชแท็กนี้",
-  "empty_column.home": "เส้นเวลาหน้าแรกของคุณว่างเปล่า! เยี่ยมชม {public} หรือใช้การค้นหาเพื่อเริ่มต้นใช้งานและพบปะผู้ใช้อื่น ๆ",
+  "empty_column.home": "เส้นเวลาหน้าแรกของคุณว่างเปล่า! ติดตามผู้คนเพิ่มเติมเพื่อเติมเส้นเวลาให้เต็ม {suggestions}",
   "empty_column.home.suggestions": "ดูข้อเสนอแนะบางอย่าง",
   "empty_column.list": "ยังไม่มีสิ่งใดในรายการนี้ เมื่อสมาชิกของรายการนี้โพสต์โพสต์ใหม่ โพสต์จะปรากฏที่นี่",
   "empty_column.lists": "คุณยังไม่มีรายการใด ๆ เมื่อคุณสร้างรายการ รายการจะปรากฏที่นี่",
   "empty_column.mutes": "คุณยังไม่ได้ซ่อนผู้ใช้ใด ๆ",
-  "empty_column.notifications": "คุณยังไม่มีการแจ้งเตือนใด ๆ โต้ตอบกับผู้อื่นเพื่อเริ่มการสนทนา",
+  "empty_column.notifications": "คุณยังไม่มีการแจ้งเตือนใด ๆ เมื่อผู้คนอื่น ๆ โต้ตอบกับคุณ คุณจะเห็นการแจ้งเตือนที่นี่",
   "empty_column.public": "ไม่มีสิ่งใดที่นี่! เขียนบางอย่างเป็นสาธารณะ หรือติดตามผู้ใช้จากเซิร์ฟเวอร์อื่น ๆ ด้วยตนเองเพื่อเติมให้เต็ม",
   "error.unexpected_crash.explanation": "เนื่องจากข้อบกพร่องในโค้ดของเราหรือปัญหาความเข้ากันได้ของเบราว์เซอร์ จึงไม่สามารถแสดงหน้านี้ได้อย่างถูกต้อง",
   "error.unexpected_crash.explanation_addons": "ไม่สามารถแสดงหน้านี้ได้อย่างถูกต้อง ข้อผิดพลาดนี้เป็นไปได้ว่าเกิดจากส่วนเสริมของเบราว์เซอร์หรือเครื่องมือการแปลอัตโนมัติ",
@@ -208,40 +208,40 @@
   "intervals.full.days": "{number, plural, other {# วัน}}",
   "intervals.full.hours": "{number, plural, other {# ชั่วโมง}}",
   "intervals.full.minutes": "{number, plural, other {# นาที}}",
-  "keyboard_shortcuts.back": "เพื่อนำทางย้อนกลับ",
-  "keyboard_shortcuts.blocked": "เพื่อเปิดรายการผู้ใช้ที่ปิดกั้นอยู่",
-  "keyboard_shortcuts.boost": "เพื่อดัน",
-  "keyboard_shortcuts.column": "เพื่อโฟกัสโพสต์ในหนึ่งในคอลัมน์",
-  "keyboard_shortcuts.compose": "เพื่อโฟกัสพื้นที่เขียนข้อความ",
+  "keyboard_shortcuts.back": "นำทางย้อนกลับ",
+  "keyboard_shortcuts.blocked": "เปิดรายการผู้ใช้ที่ปิดกั้นอยู่",
+  "keyboard_shortcuts.boost": "ดันโพสต์",
+  "keyboard_shortcuts.column": "โฟกัสคอลัมน์",
+  "keyboard_shortcuts.compose": "โฟกัสพื้นที่เขียนข้อความ",
   "keyboard_shortcuts.description": "คำอธิบาย",
-  "keyboard_shortcuts.direct": "เพื่อเปิดคอลัมน์ข้อความโดยตรง",
-  "keyboard_shortcuts.down": "เพื่อย้ายลงในรายการ",
-  "keyboard_shortcuts.enter": "เพื่อเปิดโพสต์",
-  "keyboard_shortcuts.favourite": "เพื่อชื่นชอบ",
-  "keyboard_shortcuts.favourites": "เพื่อเปิดรายการโปรด",
-  "keyboard_shortcuts.federated": "เพื่อเปิดเส้นเวลาที่ติดต่อกับภายนอก",
+  "keyboard_shortcuts.direct": "เปิดคอลัมน์ข้อความโดยตรง",
+  "keyboard_shortcuts.down": "ย้ายลงในรายการ",
+  "keyboard_shortcuts.enter": "เปิดโพสต์",
+  "keyboard_shortcuts.favourite": "ชื่นชอบโพสต์",
+  "keyboard_shortcuts.favourites": "เปิดรายการโปรด",
+  "keyboard_shortcuts.federated": "เปิดเส้นเวลาที่ติดต่อกับภายนอก",
   "keyboard_shortcuts.heading": "แป้นพิมพ์ลัด",
-  "keyboard_shortcuts.home": "เพื่อเปิดเส้นเวลาหน้าแรก",
+  "keyboard_shortcuts.home": "เปิดเส้นเวลาหน้าแรก",
   "keyboard_shortcuts.hotkey": "ปุ่มลัด",
-  "keyboard_shortcuts.legend": "เพื่อแสดงคำอธิบายนี้",
-  "keyboard_shortcuts.local": "เพื่อเปิดเส้นเวลาในเซิร์ฟเวอร์",
-  "keyboard_shortcuts.mention": "เพื่อกล่าวถึงผู้สร้าง",
-  "keyboard_shortcuts.muted": "เพื่อเปิดรายการผู้ใช้ที่ซ่อนอยู่",
-  "keyboard_shortcuts.my_profile": "เพื่อเปิดโปรไฟล์ของคุณ",
-  "keyboard_shortcuts.notifications": "เพื่อเปิดคอลัมน์การแจ้งเตือน",
-  "keyboard_shortcuts.open_media": "เพื่อเปิดสื่อ",
-  "keyboard_shortcuts.pinned": "เพื่อเปิดรายการโพสต์ที่ปักหมุด",
-  "keyboard_shortcuts.profile": "เพื่อเปิดโปรไฟล์ของผู้สร้าง",
-  "keyboard_shortcuts.reply": "เพื่อตอบกลับ",
-  "keyboard_shortcuts.requests": "เพื่อเปิดรายการคำขอติดตาม",
-  "keyboard_shortcuts.search": "เพื่อโฟกัสการค้นหา",
-  "keyboard_shortcuts.spoilers": "เพื่อแสดง/ซ่อนช่องกรอกคำเตือนเนื้อหา",
-  "keyboard_shortcuts.start": "เพื่อเปิดคอลัมน์ \"เริ่มต้นใช้งาน\"",
-  "keyboard_shortcuts.toggle_hidden": "เพื่อแสดง/ซ่อนข้อความที่อยู่หลังคำเตือนเนื้อหา",
-  "keyboard_shortcuts.toggle_sensitivity": "เพื่อแสดง/ซ่อนสื่อ",
-  "keyboard_shortcuts.toot": "เพื่อเริ่มโพสต์ใหม่",
-  "keyboard_shortcuts.unfocus": "เพื่อเลิกโฟกัสพื้นที่เขียนข้อความ/การค้นหา",
-  "keyboard_shortcuts.up": "เพื่อย้ายขึ้นในรายการ",
+  "keyboard_shortcuts.legend": "แสดงคำอธิบายนี้",
+  "keyboard_shortcuts.local": "เปิดเส้นเวลาในเซิร์ฟเวอร์",
+  "keyboard_shortcuts.mention": "กล่าวถึงผู้สร้าง",
+  "keyboard_shortcuts.muted": "เปิดรายการผู้ใช้ที่ซ่อนอยู่",
+  "keyboard_shortcuts.my_profile": "เปิดโปรไฟล์ของคุณ",
+  "keyboard_shortcuts.notifications": "เปิดคอลัมน์การแจ้งเตือน",
+  "keyboard_shortcuts.open_media": "เปิดสื่อ",
+  "keyboard_shortcuts.pinned": "เปิดรายการโพสต์ที่ปักหมุด",
+  "keyboard_shortcuts.profile": "เปิดโปรไฟล์ของผู้สร้าง",
+  "keyboard_shortcuts.reply": "ตอบกลับโพสต์",
+  "keyboard_shortcuts.requests": "เปิดรายการคำขอติดตาม",
+  "keyboard_shortcuts.search": "โฟกัสแถบค้นหา",
+  "keyboard_shortcuts.spoilers": "แสดง/ซ่อนช่องกรอกคำเตือนเนื้อหา",
+  "keyboard_shortcuts.start": "เปิดคอลัมน์ “เริ่มต้นใช้งาน”",
+  "keyboard_shortcuts.toggle_hidden": "แสดง/ซ่อนข้อความที่อยู่หลังคำเตือนเนื้อหา",
+  "keyboard_shortcuts.toggle_sensitivity": "แสดง/ซ่อนสื่อ",
+  "keyboard_shortcuts.toot": "เริ่มโพสต์ใหม่",
+  "keyboard_shortcuts.unfocus": "เลิกโฟกัสพื้นที่เขียนข้อความ/การค้นหา",
+  "keyboard_shortcuts.up": "ย้ายขึ้นในรายการ",
   "lightbox.close": "ปิด",
   "lightbox.compress": "บีบอัดกล่องดูภาพ",
   "lightbox.expand": "ขยายกล่องดูภาพ",
@@ -262,7 +262,7 @@
   "lists.subheading": "รายการของคุณ",
   "load_pending": "{count, plural, other {# รายการใหม่}}",
   "loading_indicator.label": "กำลังโหลด...",
-  "media_gallery.toggle_visible": "ซ่อน {number, plural, other {ภาพ}}",
+  "media_gallery.toggle_visible": "{number, plural, other {ซ่อนภาพ}}",
   "missing_indicator.label": "ไม่พบ",
   "missing_indicator.sublabel": "ไม่พบทรัพยากรนี้",
   "mute_modal.duration": "ระยะเวลา",
diff --git a/app/javascript/mastodon/locales/vi.json b/app/javascript/mastodon/locales/vi.json
index 3a02cc080..26ee75cf0 100644
--- a/app/javascript/mastodon/locales/vi.json
+++ b/app/javascript/mastodon/locales/vi.json
@@ -354,7 +354,7 @@
   "regeneration_indicator.label": "Đang tải…",
   "regeneration_indicator.sublabel": "Bảng tin của bạn đang được cập nhật!",
   "relative_time.days": "{number}d",
-  "relative_time.hours": "{number}h",
+  "relative_time.hours": "{number} giờ",
   "relative_time.just_now": "vừa xong",
   "relative_time.minutes": "{number}m",
   "relative_time.seconds": "{number}s",
@@ -431,7 +431,7 @@
   "time_remaining.hours": "{number, plural, other {# giờ}}",
   "time_remaining.minutes": "{number, plural, other {# phút}}",
   "time_remaining.moments": "Còn lại",
-  "time_remaining.seconds": "còn {number, plural, other {# giây}}",
+  "time_remaining.seconds": "{number, plural, other {# giây}}",
   "timeline_hint.remote_resource_not_displayed": "{resource} từ máy chủ khác sẽ không hiển thị.",
   "timeline_hint.resources.followers": "Người theo dõi",
   "timeline_hint.resources.follows": "Đang theo dõi",
diff --git a/app/javascript/mastodon/locales/zh-CN.json b/app/javascript/mastodon/locales/zh-CN.json
index 45bc1e7d3..9e1352282 100644
--- a/app/javascript/mastodon/locales/zh-CN.json
+++ b/app/javascript/mastodon/locales/zh-CN.json
@@ -163,7 +163,7 @@
   "empty_column.follow_recommendations": "似乎无法为你生成任何建议。你可以尝试使用搜索寻找你可能知道的人或探索热门标签。",
   "empty_column.follow_requests": "你没有收到新的关注请求。收到了之后就会显示在这里。",
   "empty_column.hashtag": "这个话题标签下暂时没有内容。",
-  "empty_column.home": "你还没有关注任何用户。快看看{public},向其他人问个好吧。",
+  "empty_column.home": "你的主页时间线是空的!快去关注更多人吧。 {suggestions}",
   "empty_column.home.suggestions": "查看一些建议",
   "empty_column.list": "此列表中暂时没有内容。列表中用户所发送的的新嘟文将会在这里显示。",
   "empty_column.lists": "你还没有创建过列表。你创建的列表会在这里显示。",
diff --git a/app/javascript/mastodon/reducers/notifications.js b/app/javascript/mastodon/reducers/notifications.js
index 1d4874717..b587b6d0f 100644
--- a/app/javascript/mastodon/reducers/notifications.js
+++ b/app/javascript/mastodon/reducers/notifications.js
@@ -106,7 +106,7 @@ const expandNormalizedNotifications = (state, notifications, next, isLoadingRece
     }
 
     if (shouldCountUnreadNotifications(state)) {
-      mutable.update('unread', unread => unread + items.count(item => compareId(item.get('id'), lastReadId) > 0));
+      mutable.set('unread', mutable.get('pendingItems').count(item => item !== null) + mutable.get('items').count(item => item && compareId(item.get('id'), lastReadId) > 0));
     } else {
       const mostRecent = items.find(item => item !== null);
       if (mostRecent && compareId(lastReadId, mostRecent.get('id')) < 0) {
diff --git a/app/javascript/styles/mailer.scss b/app/javascript/styles/mailer.scss
index 55ebd3091..92c02e847 100644
--- a/app/javascript/styles/mailer.scss
+++ b/app/javascript/styles/mailer.scss
@@ -258,7 +258,6 @@ h5 {
     padding: 16px;
     line-height: 20px;
     mso-line-height-rule: exactly;
-    border-radius: 4px;
     text-align: center;
     font-weight: 500;
     font-size: 17px;
diff --git a/app/javascript/styles/mastodon/about.scss b/app/javascript/styles/mastodon/about.scss
index 281f5b2bf..9f2a1a3af 100644
--- a/app/javascript/styles/mastodon/about.scss
+++ b/app/javascript/styles/mastodon/about.scss
@@ -322,7 +322,6 @@ $small-breakpoint: 960px;
     font-family: $font-sans-serif, sans-serif;
     font-size: 16px;
     font-weight: 400;
-    font-size: 16px;
     line-height: 30px;
     margin-bottom: 12px;
     color: $darker-text-color;
diff --git a/app/javascript/styles/mastodon/components.scss b/app/javascript/styles/mastodon/components.scss
index c1dd63bc3..2ca844076 100644
--- a/app/javascript/styles/mastodon/components.scss
+++ b/app/javascript/styles/mastodon/components.scss
@@ -3611,7 +3611,6 @@ a.status-card.compact:hover {
   span {
     display: block;
     float: left;
-    margin-left: 50%;
     transform: translateX(-50%);
     margin: 82px 0 0 50%;
     white-space: nowrap;
diff --git a/app/javascript/styles/mastodon/widgets.scss b/app/javascript/styles/mastodon/widgets.scss
index 5ee4d104b..f76ff18b3 100644
--- a/app/javascript/styles/mastodon/widgets.scss
+++ b/app/javascript/styles/mastodon/widgets.scss
@@ -593,7 +593,6 @@ $fluid-breakpoint: $maximum-width + 20px;
     display: block;
     font-weight: 500;
     padding: 15px;
-    overflow: hidden;
     white-space: nowrap;
     overflow: hidden;
     text-overflow: ellipsis;
diff --git a/app/lib/activitypub/activity.rb b/app/lib/activitypub/activity.rb
index 3baee4ca4..d2ec122a4 100644
--- a/app/lib/activitypub/activity.rb
+++ b/app/lib/activitypub/activity.rb
@@ -216,8 +216,8 @@ class ActivityPub::Activity
     redis.del(key)
   end
 
-  def lock_or_fail(key)
-    RedisLock.acquire({ redis: Redis.current, key: key }) do |lock|
+  def lock_or_fail(key, expire_after = 15.minutes.seconds)
+    RedisLock.acquire({ redis: Redis.current, key: key, autorelease: expire_after }) do |lock|
       if lock.acquired?
         yield
       else
diff --git a/app/services/activitypub/process_account_service.rb b/app/services/activitypub/process_account_service.rb
index 7e268f4d4..4ab6912e5 100644
--- a/app/services/activitypub/process_account_service.rb
+++ b/app/services/activitypub/process_account_service.rb
@@ -290,7 +290,7 @@ class ActivityPub::ProcessAccountService < BaseService
   end
 
   def lock_options
-    { redis: Redis.current, key: "process_account:#{@uri}" }
+    { redis: Redis.current, key: "process_account:#{@uri}", autorelease: 15.minutes.seconds }
   end
 
   def process_tags
diff --git a/app/services/fetch_link_card_service.rb b/app/services/fetch_link_card_service.rb
index fa1636e41..5732ce8ac 100644
--- a/app/services/fetch_link_card_service.rb
+++ b/app/services/fetch_link_card_service.rb
@@ -175,6 +175,6 @@ class FetchLinkCardService < BaseService
   end
 
   def lock_options
-    { redis: Redis.current, key: "fetch:#{@url}" }
+    { redis: Redis.current, key: "fetch:#{@url}", autorelease: 15.minutes.seconds }
   end
 end
diff --git a/app/services/remove_status_service.rb b/app/services/remove_status_service.rb
index 5cc1dba06..20c17e6df 100644
--- a/app/services/remove_status_service.rb
+++ b/app/services/remove_status_service.rb
@@ -149,6 +149,6 @@ class RemoveStatusService < BaseService
   end
 
   def lock_options
-    { redis: Redis.current, key: "distribute:#{@status.id}" }
+    { redis: Redis.current, key: "distribute:#{@status.id}", autorelease: 5.minutes.seconds }
   end
 end
diff --git a/app/services/resolve_account_service.rb b/app/services/resolve_account_service.rb
index 493995447..5400612bf 100644
--- a/app/services/resolve_account_service.rb
+++ b/app/services/resolve_account_service.rb
@@ -146,6 +146,6 @@ class ResolveAccountService < BaseService
   end
 
   def lock_options
-    { redis: Redis.current, key: "resolve:#{@username}@#{@domain}" }
+    { redis: Redis.current, key: "resolve:#{@username}@#{@domain}", autorelease: 15.minutes.seconds }
   end
 end
diff --git a/app/workers/distribution_worker.rb b/app/workers/distribution_worker.rb
index 4e20ef31b..e85cd7e95 100644
--- a/app/workers/distribution_worker.rb
+++ b/app/workers/distribution_worker.rb
@@ -4,7 +4,7 @@ class DistributionWorker
   include Sidekiq::Worker
 
   def perform(status_id)
-    RedisLock.acquire(redis: Redis.current, key: "distribute:#{status_id}") do |lock|
+    RedisLock.acquire(redis: Redis.current, key: "distribute:#{status_id}", autorelease: 5.minutes.seconds) do |lock|
       if lock.acquired?
         FanOutOnWriteService.new.call(Status.find(status_id))
       else