Browse Source

Merge branch 'master' into glitch-soc/merge-upstream

Conflicts:
	app/views/layouts/application.html.haml

Edited:
        app/helpers/application_helper.rb
        app/views/admin/domain_blocks/new.html.haml

Conflict wasn't really one, just two changes too close to one another.
Edition was to adapt the class names for themes to class names for
skins and flavours.

Also edited app/views/admin/domain_blocks/new.html.haml to strip the
duplicate admin pack inclusion thing.
Thibaut Girka 7 months ago
parent
commit
36393e1d2b
97 changed files with 326 additions and 94 deletions
  1. 2
    2
      .env.nanobox
  2. 2
    2
      .env.production.sample
  3. 1
    1
      Gemfile
  4. 3
    3
      Gemfile.lock
  5. 10
    5
      app/helpers/application_helper.rb
  6. 7
    0
      app/javascript/core/admin.js
  7. 1
    0
      app/javascript/mastodon/components/extended_video_player.js
  8. 1
    0
      app/javascript/mastodon/components/media_gallery.js
  9. 1
    0
      app/javascript/mastodon/components/status.js
  10. 1
    1
      app/javascript/mastodon/containers/status_container.js
  11. 3
    1
      app/javascript/mastodon/features/account/components/header.js
  12. 1
    1
      app/javascript/mastodon/features/compose/components/upload_button.js
  13. 1
    0
      app/javascript/mastodon/features/report/components/status_check_box.js
  14. 1
    0
      app/javascript/mastodon/features/status/components/detailed_status.js
  15. 1
    1
      app/javascript/mastodon/features/status/index.js
  16. 1
    0
      app/javascript/mastodon/features/video/index.js
  17. 2
    0
      app/javascript/mastodon/locales/ar.json
  18. 2
    0
      app/javascript/mastodon/locales/ast.json
  19. 2
    0
      app/javascript/mastodon/locales/bg.json
  20. 2
    0
      app/javascript/mastodon/locales/ca.json
  21. 2
    0
      app/javascript/mastodon/locales/co.json
  22. 3
    1
      app/javascript/mastodon/locales/cs.json
  23. 9
    7
      app/javascript/mastodon/locales/da.json
  24. 2
    0
      app/javascript/mastodon/locales/de.json
  25. 10
    2
      app/javascript/mastodon/locales/defaultMessages.json
  26. 2
    0
      app/javascript/mastodon/locales/el.json
  27. 4
    2
      app/javascript/mastodon/locales/en.json
  28. 2
    0
      app/javascript/mastodon/locales/eo.json
  29. 2
    0
      app/javascript/mastodon/locales/es.json
  30. 2
    0
      app/javascript/mastodon/locales/eu.json
  31. 2
    0
      app/javascript/mastodon/locales/fa.json
  32. 2
    0
      app/javascript/mastodon/locales/fi.json
  33. 4
    2
      app/javascript/mastodon/locales/fr.json
  34. 2
    0
      app/javascript/mastodon/locales/gl.json
  35. 2
    0
      app/javascript/mastodon/locales/he.json
  36. 2
    0
      app/javascript/mastodon/locales/hr.json
  37. 2
    0
      app/javascript/mastodon/locales/hu.json
  38. 2
    0
      app/javascript/mastodon/locales/hy.json
  39. 2
    0
      app/javascript/mastodon/locales/id.json
  40. 2
    0
      app/javascript/mastodon/locales/io.json
  41. 2
    0
      app/javascript/mastodon/locales/it.json
  42. 3
    1
      app/javascript/mastodon/locales/ja.json
  43. 2
    0
      app/javascript/mastodon/locales/ka.json
  44. 5
    3
      app/javascript/mastodon/locales/ko.json
  45. 2
    0
      app/javascript/mastodon/locales/nl.json
  46. 2
    0
      app/javascript/mastodon/locales/no.json
  47. 6
    4
      app/javascript/mastodon/locales/oc.json
  48. 2
    0
      app/javascript/mastodon/locales/pl.json
  49. 5
    3
      app/javascript/mastodon/locales/pt-BR.json
  50. 2
    0
      app/javascript/mastodon/locales/pt.json
  51. 2
    0
      app/javascript/mastodon/locales/ru.json
  52. 2
    0
      app/javascript/mastodon/locales/sk.json
  53. 2
    0
      app/javascript/mastodon/locales/sl.json
  54. 2
    0
      app/javascript/mastodon/locales/sr-Latn.json
  55. 2
    0
      app/javascript/mastodon/locales/sr.json
  56. 2
    0
      app/javascript/mastodon/locales/sv.json
  57. 2
    0
      app/javascript/mastodon/locales/te.json
  58. 2
    0
      app/javascript/mastodon/locales/th.json
  59. 2
    0
      app/javascript/mastodon/locales/tr.json
  60. 2
    0
      app/javascript/mastodon/locales/uk.json
  61. 2
    0
      app/javascript/mastodon/locales/zh-CN.json
  62. 2
    0
      app/javascript/mastodon/locales/zh-HK.json
  63. 2
    0
      app/javascript/mastodon/locales/zh-TW.json
  64. 4
    1
      app/javascript/packs/public.js
  65. 3
    1
      app/lib/activitypub/activity.rb
  66. 15
    1
      app/lib/activitypub/activity/create.rb
  67. 1
    1
      app/views/admin/reports/_status.html.haml
  68. 1
    5
      app/views/layouts/application.html.haml
  69. 1
    1
      app/views/stream_entries/_detailed_status.html.haml
  70. 1
    1
      app/views/stream_entries/_simple_status.html.haml
  71. 1
    1
      app/workers/maintenance/destroy_media_worker.rb
  72. 1
    1
      app/workers/maintenance/redownload_account_media_worker.rb
  73. 1
    1
      app/workers/maintenance/uncache_media_worker.rb
  74. 1
    1
      app/workers/scheduler/backup_cleanup_scheduler.rb
  75. 1
    1
      app/workers/scheduler/doorkeeper_cleanup_scheduler.rb
  76. 1
    1
      app/workers/scheduler/email_scheduler.rb
  77. 1
    1
      app/workers/scheduler/feed_cleanup_scheduler.rb
  78. 1
    1
      app/workers/scheduler/ip_cleanup_scheduler.rb
  79. 1
    1
      app/workers/scheduler/media_cleanup_scheduler.rb
  80. 1
    1
      app/workers/scheduler/subscriptions_cleanup_scheduler.rb
  81. 1
    1
      app/workers/scheduler/subscriptions_scheduler.rb
  82. 1
    1
      app/workers/scheduler/user_cleanup_scheduler.rb
  83. 4
    0
      bin/tootctl
  84. 2
    2
      config/initializers/paperclip.rb
  85. 3
    0
      config/locales/cs.yml
  86. 2
    0
      config/locales/doorkeeper.da.yml
  87. 3
    0
      config/locales/en.yml
  88. 15
    6
      config/locales/ja.yml
  89. 6
    0
      config/locales/ka.yml
  90. 1
    1
      config/locales/ko.yml
  91. 1
    1
      config/locales/simple_form.fr.yml
  92. 2
    2
      config/webpack/production.js
  93. 11
    0
      lib/cli.rb
  94. 47
    0
      lib/mastodon/media_cli.rb
  95. 4
    9
      lib/tasks/mastodon.rake
  96. 5
    5
      spec/helpers/application_helper_spec.rb
  97. 20
    3
      streaming/index.js

+ 2
- 2
.env.nanobox View File

@@ -136,8 +136,8 @@ SMTP_FROM_ADDRESS=notifications@${APP_NAME}.nanoapp.io
136 136
 # Defaults to 60 seconds. Set to 0 to disable
137 137
 # SWIFT_CACHE_TTL=
138 138
 
139
-# Optional alias for S3 if you want to use Cloudfront or Cloudflare in front
140
-# S3_CLOUDFRONT_HOST=
139
+# Optional alias for S3 (e.g. to serve files on a custom domain, possibly using Cloudfront or Cloudflare)
140
+# S3_ALIAS_HOST=
141 141
 
142 142
 # Streaming API integration
143 143
 # STREAMING_API_BASE_URL=

+ 2
- 2
.env.production.sample View File

@@ -134,8 +134,8 @@ SMTP_FROM_ADDRESS=notifications@example.com
134 134
 # Defaults to 60 seconds. Set to 0 to disable
135 135
 # SWIFT_CACHE_TTL=
136 136
 
137
-# Optional alias for S3 if you want to use Cloudfront or Cloudflare in front
138
-# S3_CLOUDFRONT_HOST=
137
+# Optional alias for S3 (e.g. to serve files on a custom domain, possibly using Cloudfront or Cloudflare)
138
+# S3_ALIAS_HOST=
139 139
 
140 140
 # Streaming API integration
141 141
 # STREAMING_API_BASE_URL=

+ 1
- 1
Gemfile View File

@@ -41,7 +41,7 @@ gem 'omniauth-cas', '~> 1.1'
41 41
 gem 'omniauth-saml', '~> 1.10'
42 42
 gem 'omniauth', '~> 1.2'
43 43
 
44
-gem 'doorkeeper', '~> 4.4'
44
+gem 'doorkeeper', '~> 5.0'
45 45
 gem 'fast_blank', '~> 1.0'
46 46
 gem 'fastimage'
47 47
 gem 'goldfinger', '~> 2.1'

+ 3
- 3
Gemfile.lock View File

@@ -174,14 +174,14 @@ GEM
174 174
       devise (~> 4.0)
175 175
       railties (< 5.3)
176 176
       rotp (~> 2.0)
177
-    devise_pam_authenticatable2 (9.1.0)
177
+    devise_pam_authenticatable2 (9.1.1)
178 178
       devise (>= 4.0.0)
179 179
       rpam2 (~> 4.0)
180 180
     diff-lcs (1.3)
181 181
     docile (1.3.0)
182 182
     domain_name (0.5.20180417)
183 183
       unf (>= 0.0.5, < 1.0.0)
184
-    doorkeeper (4.4.2)
184
+    doorkeeper (5.0.0)
185 185
       railties (>= 4.2)
186 186
     dotenv (2.2.2)
187 187
     dotenv-rails (2.2.2)
@@ -672,7 +672,7 @@ DEPENDENCIES
672 672
   devise (~> 4.4)
673 673
   devise-two-factor (~> 3.0)
674 674
   devise_pam_authenticatable2 (~> 9.1)
675
-  doorkeeper (~> 4.4)
675
+  doorkeeper (~> 5.0)
676 676
   dotenv-rails (~> 2.2, < 2.3)
677 677
   fabrication (~> 2.20)
678 678
   faker (~> 1.8)

+ 10
- 5
app/helpers/application_helper.rb View File

@@ -27,11 +27,6 @@ module ApplicationHelper
27 27
     Setting.open_deletion
28 28
   end
29 29
 
30
-  def add_rtl_body_class(other_classes)
31
-    other_classes = "#{other_classes} rtl" if locale_direction == 'rtl'
32
-    other_classes
33
-  end
34
-
35 30
   def locale_direction
36 31
     if [:ar, :fa, :he].include?(I18n.locale)
37 32
       'rtl'
@@ -77,4 +72,14 @@ module ApplicationHelper
77 72
   def react_component(name, props = {})
78 73
     content_tag(:div, nil, data: { component: name.to_s.camelcase, props: Oj.dump(props) })
79 74
   end
75
+
76
+  def body_classes
77
+    output = (@body_classes || '').split(' ')
78
+    output << "flavour-#{current_flavour.parameterize}"
79
+    output << "skin-#{current_skin.parameterize}"
80
+    output << 'system-font' if current_account&.user&.setting_system_font_ui
81
+    output << current_account&.user&.setting_reduce_motion ? 'reduce-motion' : 'no-reduce-motion'
82
+    output << 'rtl' if locale_direction == 'rtl'
83
+    output.reject(&:blank?).join(' ')
84
+  end
80 85
 end

+ 7
- 0
app/javascript/core/admin.js View File

@@ -41,3 +41,10 @@ delegate(document, '.media-spoiler-hide-button', 'click', () => {
41 41
     element.click();
42 42
   });
43 43
 });
44
+
45
+delegate(document, '#domain_block_severity', 'change', ({ target }) => {
46
+  const rejectMediaDiv = document.querySelector('.input.with_label.domain_block_reject_media');
47
+  if (rejectMediaDiv) {
48
+    rejectMediaDiv.style.display = (target.value === 'suspend') ? 'none' : 'block';
49
+  }
50
+});

+ 1
- 0
app/javascript/mastodon/components/extended_video_player.js View File

@@ -50,6 +50,7 @@ export default class ExtendedVideoPlayer extends React.PureComponent {
50 50
           role='button'
51 51
           tabIndex='0'
52 52
           aria-label={alt}
53
+          title={alt}
53 54
           muted={muted}
54 55
           controls={controls}
55 56
           loop={!controls}

+ 1
- 0
app/javascript/mastodon/components/media_gallery.js View File

@@ -154,6 +154,7 @@ class Item extends React.PureComponent {
154 154
           <video
155 155
             className='media-gallery__item-gifv-thumbnail'
156 156
             aria-label={attachment.get('description')}
157
+            title={attachment.get('description')}
157 158
             role='application'
158 159
             src={attachment.get('url')}
159 160
             onClick={this.handleClick}

+ 1
- 0
app/javascript/mastodon/components/status.js View File

@@ -230,6 +230,7 @@ export default class Status extends ImmutablePureComponent {
230 230
               <Component
231 231
                 preview={video.get('preview_url')}
232 232
                 src={video.get('url')}
233
+                alt={video.get('description')}
233 234
                 width={239}
234 235
                 height={110}
235 236
                 inline

+ 1
- 1
app/javascript/mastodon/containers/status_container.js View File

@@ -34,7 +34,7 @@ const messages = defineMessages({
34 34
   deleteConfirm: { id: 'confirmations.delete.confirm', defaultMessage: 'Delete' },
35 35
   deleteMessage: { id: 'confirmations.delete.message', defaultMessage: 'Are you sure you want to delete this status?' },
36 36
   redraftConfirm: { id: 'confirmations.redraft.confirm', defaultMessage: 'Delete & redraft' },
37
-  redraftMessage: { id: 'confirmations.redraft.message', defaultMessage: 'Are you sure you want to delete this status and re-draft it? You will lose all replies, boosts and favourites to it.' },
37
+  redraftMessage: { id: 'confirmations.redraft.message', defaultMessage: 'Are you sure you want to delete this status and re-draft it? Favourites and boosts will be lost, and replies to the original post will be orphaned.' },
38 38
   blockConfirm: { id: 'confirmations.block.confirm', defaultMessage: 'Block' },
39 39
 });
40 40
 

+ 3
- 1
app/javascript/mastodon/features/account/components/header.js View File

@@ -104,7 +104,9 @@ export default class Header extends ImmutablePureComponent {
104 104
     }
105 105
 
106 106
     if (me !== account.get('id')) {
107
-      if (account.getIn(['relationship', 'requested'])) {
107
+      if (!account.get('relationship')) { // Wait until the relationship is loaded
108
+        actionBtn = '';
109
+      } else if (account.getIn(['relationship', 'requested'])) {
108 110
         actionBtn = (
109 111
           <div className='account--action-button'>
110 112
             <IconButton size={26} active icon='hourglass' title={intl.formatMessage(messages.requested)} onClick={this.props.onFollow} />

+ 1
- 1
app/javascript/mastodon/features/compose/components/upload_button.js View File

@@ -7,7 +7,7 @@ import ImmutablePureComponent from 'react-immutable-pure-component';
7 7
 import ImmutablePropTypes from 'react-immutable-proptypes';
8 8
 
9 9
 const messages = defineMessages({
10
-  upload: { id: 'upload_button.label', defaultMessage: 'Add media' },
10
+  upload: { id: 'upload_button.label', defaultMessage: 'Add media (JPEG, PNG, GIF, WebM, MP4)' },
11 11
 });
12 12
 
13 13
 const makeMapStateToProps = () => {

+ 1
- 0
app/javascript/mastodon/features/report/components/status_check_box.js View File

@@ -36,6 +36,7 @@ export default class StatusCheckBox extends React.PureComponent {
36 36
               <Component
37 37
                 preview={video.get('preview_url')}
38 38
                 src={video.get('url')}
39
+                alt={video.get('description')}
39 40
                 width={239}
40 41
                 height={110}
41 42
                 inline

+ 1
- 0
app/javascript/mastodon/features/status/components/detailed_status.js View File

@@ -60,6 +60,7 @@ export default class DetailedStatus extends ImmutablePureComponent {
60 60
           <Video
61 61
             preview={video.get('preview_url')}
62 62
             src={video.get('url')}
63
+            alt={video.get('description')}
63 64
             width={300}
64 65
             height={150}
65 66
             inline

+ 1
- 1
app/javascript/mastodon/features/status/index.js View File

@@ -49,7 +49,7 @@ const messages = defineMessages({
49 49
   deleteConfirm: { id: 'confirmations.delete.confirm', defaultMessage: 'Delete' },
50 50
   deleteMessage: { id: 'confirmations.delete.message', defaultMessage: 'Are you sure you want to delete this status?' },
51 51
   redraftConfirm: { id: 'confirmations.redraft.confirm', defaultMessage: 'Delete & redraft' },
52
-  redraftMessage: { id: 'confirmations.redraft.message', defaultMessage: 'Are you sure you want to delete this status and re-draft it? You will lose all replies, boosts and favourites to it.' },
52
+  redraftMessage: { id: 'confirmations.redraft.message', defaultMessage: 'Are you sure you want to delete this status and re-draft it? Favourites and boosts will be lost, and replies to the original post will be orphaned.' },
53 53
   blockConfirm: { id: 'confirmations.block.confirm', defaultMessage: 'Block' },
54 54
   revealAll: { id: 'status.show_more_all', defaultMessage: 'Show more for all' },
55 55
   hideAll: { id: 'status.show_less_all', defaultMessage: 'Show less for all' },

+ 1
- 0
app/javascript/mastodon/features/video/index.js View File

@@ -315,6 +315,7 @@ export default class Video extends React.PureComponent {
315 315
           role='button'
316 316
           tabIndex='0'
317 317
           aria-label={alt}
318
+          title={alt}
318 319
           width={width}
319 320
           height={height}
320 321
           onClick={this.togglePlay}

+ 2
- 0
app/javascript/mastodon/locales/ar.json View File

@@ -165,6 +165,7 @@
165 165
   "navigation_bar.apps": "Mobile apps",
166 166
   "navigation_bar.blocks": "الحسابات المحجوبة",
167 167
   "navigation_bar.community_timeline": "الخيط العام المحلي",
168
+  "navigation_bar.compose": "Compose new toot",
168 169
   "navigation_bar.direct": "الرسائل المباشِرة",
169 170
   "navigation_bar.discover": "إكتشف",
170 171
   "navigation_bar.domain_blocks": "النطاقات المخفية",
@@ -258,6 +259,7 @@
258 259
   "status.cancel_reblog_private": "إلغاء الترقية",
259 260
   "status.cannot_reblog": "تعذرت ترقية هذا المنشور",
260 261
   "status.delete": "إحذف",
262
+  "status.detailed_status": "Detailed conversation view",
261 263
   "status.direct": "رسالة خاصة إلى @{name}",
262 264
   "status.embed": "إدماج",
263 265
   "status.favourite": "أضف إلى المفضلة",

+ 2
- 0
app/javascript/mastodon/locales/ast.json View File

@@ -165,6 +165,7 @@
165 165
   "navigation_bar.apps": "Mobile apps",
166 166
   "navigation_bar.blocks": "Blocked users",
167 167
   "navigation_bar.community_timeline": "Local timeline",
168
+  "navigation_bar.compose": "Compose new toot",
168 169
   "navigation_bar.direct": "Direct messages",
169 170
   "navigation_bar.discover": "Discover",
170 171
   "navigation_bar.domain_blocks": "Hidden domains",
@@ -258,6 +259,7 @@
258 259
   "status.cancel_reblog_private": "Unboost",
259 260
   "status.cannot_reblog": "This post cannot be boosted",
260 261
   "status.delete": "Delete",
262
+  "status.detailed_status": "Detailed conversation view",
261 263
   "status.direct": "Direct message @{name}",
262 264
   "status.embed": "Embed",
263 265
   "status.favourite": "Favourite",

+ 2
- 0
app/javascript/mastodon/locales/bg.json View File

@@ -165,6 +165,7 @@
165 165
   "navigation_bar.apps": "Mobile apps",
166 166
   "navigation_bar.blocks": "Blocked users",
167 167
   "navigation_bar.community_timeline": "Local timeline",
168
+  "navigation_bar.compose": "Compose new toot",
168 169
   "navigation_bar.direct": "Direct messages",
169 170
   "navigation_bar.discover": "Discover",
170 171
   "navigation_bar.domain_blocks": "Hidden domains",
@@ -258,6 +259,7 @@
258 259
   "status.cancel_reblog_private": "Unboost",
259 260
   "status.cannot_reblog": "This post cannot be boosted",
260 261
   "status.delete": "Изтриване",
262
+  "status.detailed_status": "Detailed conversation view",
261 263
   "status.direct": "Direct message @{name}",
262 264
   "status.embed": "Embed",
263 265
   "status.favourite": "Предпочитани",

+ 2
- 0
app/javascript/mastodon/locales/ca.json View File

@@ -165,6 +165,7 @@
165 165
   "navigation_bar.apps": "Mobile apps",
166 166
   "navigation_bar.blocks": "Usuaris bloquejats",
167 167
   "navigation_bar.community_timeline": "Línia de temps Local",
168
+  "navigation_bar.compose": "Compose new toot",
168 169
   "navigation_bar.direct": "Missatges directes",
169 170
   "navigation_bar.discover": "Descobreix",
170 171
   "navigation_bar.domain_blocks": "Dominis ocults",
@@ -258,6 +259,7 @@
258 259
   "status.cancel_reblog_private": "Desfer l'impuls",
259 260
   "status.cannot_reblog": "Aquesta publicació no pot ser retootejada",
260 261
   "status.delete": "Esborrar",
262
+  "status.detailed_status": "Detailed conversation view",
261 263
   "status.direct": "Missatge directe @{name}",
262 264
   "status.embed": "Incrustar",
263 265
   "status.favourite": "Favorit",

+ 2
- 0
app/javascript/mastodon/locales/co.json View File

@@ -165,6 +165,7 @@
165 165
   "navigation_bar.apps": "Mobile apps",
166 166
   "navigation_bar.blocks": "Utilizatori bluccati",
167 167
   "navigation_bar.community_timeline": "Linea pubblica lucale",
168
+  "navigation_bar.compose": "Compose new toot",
168 169
   "navigation_bar.direct": "Missaghji diretti",
169 170
   "navigation_bar.discover": "Scopre",
170 171
   "navigation_bar.domain_blocks": "Duminii piattati",
@@ -258,6 +259,7 @@
258 259
   "status.cancel_reblog_private": "Ùn sparte più",
259 260
   "status.cannot_reblog": "Stu statutu ùn pò micca esse spartutu",
260 261
   "status.delete": "Toglie",
262
+  "status.detailed_status": "Detailed conversation view",
261 263
   "status.direct": "Mandà un missaghju @{name}",
262 264
   "status.embed": "Integrà",
263 265
   "status.favourite": "Aghjunghje à i favuriti",

+ 3
- 1
app/javascript/mastodon/locales/cs.json View File

@@ -162,9 +162,10 @@
162 162
   "missing_indicator.label": "Nenalezeno",
163 163
   "missing_indicator.sublabel": "Tento zdroj se nepodařilo najít",
164 164
   "mute_modal.hide_notifications": "Skrýt oznámení před tímto uživatelem?",
165
-  "navigation_bar.apps": "Mobile apps",
165
+  "navigation_bar.apps": "Mobilní aplikace",
166 166
   "navigation_bar.blocks": "Blokovaní uživatelé",
167 167
   "navigation_bar.community_timeline": "Místní časová osa",
168
+  "navigation_bar.compose": "Compose new toot",
168 169
   "navigation_bar.direct": "Přímé zprávy",
169 170
   "navigation_bar.discover": "Objevujte",
170 171
   "navigation_bar.domain_blocks": "Skryté domény",
@@ -258,6 +259,7 @@
258 259
   "status.cancel_reblog_private": "Zrušit boost",
259 260
   "status.cannot_reblog": "Tento příspěvek nemůže být boostnutý",
260 261
   "status.delete": "Delete",
262
+  "status.detailed_status": "Detailed conversation view",
261 263
   "status.direct": "Poslat přímou zprávu uživateli @{name}",
262 264
   "status.embed": "Vložit",
263 265
   "status.favourite": "Oblíbit",

+ 9
- 7
app/javascript/mastodon/locales/da.json View File

@@ -20,7 +20,7 @@
20 20
   "account.mute_notifications": "Dæmp notifikationer fra @{name}",
21 21
   "account.muted": "Dæmpet",
22 22
   "account.posts": "Trut",
23
-  "account.posts_with_replies": "Trut samt svar",
23
+  "account.posts_with_replies": "Trut og svar",
24 24
   "account.report": "Rapporter @{name}",
25 25
   "account.requested": "Afventer godkendelse. Tryk for at annullere følgeanmodning",
26 26
   "account.share": "Del @{name}s profil",
@@ -51,7 +51,7 @@
51 51
   "column.lists": "Lister",
52 52
   "column.mutes": "Dæmpede brugere",
53 53
   "column.notifications": "Notifikationer",
54
-  "column.pins": "Fastgjorte toots",
54
+  "column.pins": "Fastgjorte trut",
55 55
   "column.public": "Fælles tidslinje",
56 56
   "column_back_button.label": "Tilbage",
57 57
   "column_header.hide_settings": "Skjul indstillinger",
@@ -61,7 +61,7 @@
61 61
   "column_header.show_settings": "Vis indstillinger",
62 62
   "column_header.unpin": "Fastgør ikke længere",
63 63
   "column_subheading.settings": "Indstillinger",
64
-  "community.column_settings.media_only": "Kun multimedier",
64
+  "community.column_settings.media_only": "Kun medie",
65 65
   "compose_form.direct_message_warning": "Dette trut vil kun blive sendt til de nævnte brugere.",
66 66
   "compose_form.direct_message_warning_learn_more": "Lær mere",
67 67
   "compose_form.hashtag_warning": "Dette trut vil ikke blive vist under noget hashtag da det ikke er listet. Kun offentlige trut kan blive vist under søgninger med hashtags.",
@@ -70,8 +70,8 @@
70 70
   "compose_form.placeholder": "Hvad har du på hjertet?",
71 71
   "compose_form.publish": "Trut",
72 72
   "compose_form.publish_loud": "{publish}!",
73
-  "compose_form.sensitive.marked": "Multimedie er markeret som værende følsomt",
74
-  "compose_form.sensitive.unmarked": "Multimediet er ikke markeret som værende følsomt",
73
+  "compose_form.sensitive.marked": "Medie er markeret som værende følsomt",
74
+  "compose_form.sensitive.unmarked": "Mediet er ikke markeret som værende følsomt",
75 75
   "compose_form.spoiler.marked": "Teksten er skjult bag en advarsel",
76 76
   "compose_form.spoiler.unmarked": "Teksten er ikke skjult",
77 77
   "compose_form.spoiler_placeholder": "Skriv din advarsel her",
@@ -162,9 +162,10 @@
162 162
   "missing_indicator.label": "Ikke fundet",
163 163
   "missing_indicator.sublabel": "Denne ressource kunne ikke blive fundet",
164 164
   "mute_modal.hide_notifications": "Skjul notifikationer fra denne bruger?",
165
-  "navigation_bar.apps": "Mobile apps",
165
+  "navigation_bar.apps": "Mobil apps",
166 166
   "navigation_bar.blocks": "Blokerede brugere",
167 167
   "navigation_bar.community_timeline": "Lokal tidslinje",
168
+  "navigation_bar.compose": "Compose new toot",
168 169
   "navigation_bar.direct": "Direkte beskeder",
169 170
   "navigation_bar.discover": "Opdag",
170 171
   "navigation_bar.domain_blocks": "Skjulte domæner",
@@ -258,12 +259,13 @@
258 259
   "status.cancel_reblog_private": "Fremhæv ikke længere",
259 260
   "status.cannot_reblog": "Denne post kan ikke fremhæves",
260 261
   "status.delete": "Slet",
262
+  "status.detailed_status": "Detailed conversation view",
261 263
   "status.direct": "Send direkte besked til @{name}",
262 264
   "status.embed": "Indlejre",
263 265
   "status.favourite": "Favorit",
264 266
   "status.filtered": "Filtreret",
265 267
   "status.load_more": "Indlæs mere",
266
-  "status.media_hidden": "Multimedia skjult",
268
+  "status.media_hidden": "Medie skjult",
267 269
   "status.mention": "Nævn @{name}",
268 270
   "status.more": "Mere",
269 271
   "status.mute": "Dæmp @{name}",

+ 2
- 0
app/javascript/mastodon/locales/de.json View File

@@ -165,6 +165,7 @@
165 165
   "navigation_bar.apps": "Mobile apps",
166 166
   "navigation_bar.blocks": "Blockierte Profile",
167 167
   "navigation_bar.community_timeline": "Lokale Zeitleiste",
168
+  "navigation_bar.compose": "Compose new toot",
168 169
   "navigation_bar.direct": "Direktnachrichten",
169 170
   "navigation_bar.discover": "Entdecken",
170 171
   "navigation_bar.domain_blocks": "Versteckte Domains",
@@ -258,6 +259,7 @@
258 259
   "status.cancel_reblog_private": "Nicht mehr teilen",
259 260
   "status.cannot_reblog": "Dieser Beitrag kann nicht geteilt werden",
260 261
   "status.delete": "Löschen",
262
+  "status.detailed_status": "Detailed conversation view",
261 263
   "status.direct": "Direktnachricht @{name}",
262 264
   "status.embed": "Einbetten",
263 265
   "status.favourite": "Favorisieren",

+ 10
- 2
app/javascript/mastodon/locales/defaultMessages.json View File

@@ -390,7 +390,7 @@
390 390
         "id": "confirmations.redraft.confirm"
391 391
       },
392 392
       {
393
-        "defaultMessage": "Are you sure you want to delete this status and re-draft it? You will lose all replies, boosts and favourites to it.",
393
+        "defaultMessage": "Are you sure you want to delete this status and re-draft it? Favourites and boosts will be lost, and replies to the original post will be orphaned.",
394 394
         "id": "confirmations.redraft.message"
395 395
       },
396 396
       {
@@ -1019,6 +1019,10 @@
1019 1019
       {
1020 1020
         "defaultMessage": "Logout",
1021 1021
         "id": "navigation_bar.logout"
1022
+      },
1023
+      {
1024
+        "defaultMessage": "Compose new toot",
1025
+        "id": "navigation_bar.compose"
1022 1026
       }
1023 1027
     ],
1024 1028
     "path": "app/javascript/mastodon/features/compose/index.json"
@@ -1636,7 +1640,7 @@
1636 1640
         "id": "confirmations.redraft.confirm"
1637 1641
       },
1638 1642
       {
1639
-        "defaultMessage": "Are you sure you want to delete this status and re-draft it? You will lose all replies, boosts and favourites to it.",
1643
+        "defaultMessage": "Are you sure you want to delete this status and re-draft it? Favourites and boosts will be lost, and replies to the original post will be orphaned.",
1640 1644
         "id": "confirmations.redraft.message"
1641 1645
       },
1642 1646
       {
@@ -1652,6 +1656,10 @@
1652 1656
         "id": "status.show_less_all"
1653 1657
       },
1654 1658
       {
1659
+        "defaultMessage": "Detailed conversation view",
1660
+        "id": "status.detailed_status"
1661
+      },
1662
+      {
1655 1663
         "defaultMessage": "Are you sure you want to block {name}?",
1656 1664
         "id": "confirmations.block.message"
1657 1665
       }

+ 2
- 0
app/javascript/mastodon/locales/el.json View File

@@ -165,6 +165,7 @@
165 165
   "navigation_bar.apps": "Mobile apps",
166 166
   "navigation_bar.blocks": "Αποκλεισμένοι χρήστες",
167 167
   "navigation_bar.community_timeline": "Τοπική ροή",
168
+  "navigation_bar.compose": "Compose new toot",
168 169
   "navigation_bar.direct": "Προσωπικά μηνύματα",
169 170
   "navigation_bar.discover": "Ανακάλυψη",
170 171
   "navigation_bar.domain_blocks": "Κρυμμένοι τομείς",
@@ -258,6 +259,7 @@
258 259
   "status.cancel_reblog_private": "Ακύρωσε την προώθηση",
259 260
   "status.cannot_reblog": "Αυτή η δημοσίευση δεν μπορεί να προωθηθεί",
260 261
   "status.delete": "Διαγραφή",
262
+  "status.detailed_status": "Detailed conversation view",
261 263
   "status.direct": "Προσωπικό μήνυμα προς @{name}",
262 264
   "status.embed": "Ενσωμάτωσε",
263 265
   "status.favourite": "Σημείωσε ως αγαπημένο",

+ 4
- 2
app/javascript/mastodon/locales/en.json View File

@@ -91,7 +91,7 @@
91 91
   "confirmations.mute.confirm": "Mute",
92 92
   "confirmations.mute.message": "Are you sure you want to mute {name}?",
93 93
   "confirmations.redraft.confirm": "Delete & redraft",
94
-  "confirmations.redraft.message": "Are you sure you want to delete this status and re-draft it? You will lose all replies, boosts and favourites to it.",
94
+  "confirmations.redraft.message": "Are you sure you want to delete this status and re-draft it? Favourites and boosts will be lost, and replies to the original post will be orphaned.",
95 95
   "confirmations.unfollow.confirm": "Unfollow",
96 96
   "confirmations.unfollow.message": "Are you sure you want to unfollow {name}?",
97 97
   "embed.instructions": "Embed this status on your website by copying the code below.",
@@ -169,6 +169,7 @@
169 169
   "navigation_bar.apps": "Mobile apps",
170 170
   "navigation_bar.blocks": "Blocked users",
171 171
   "navigation_bar.community_timeline": "Local timeline",
172
+  "navigation_bar.compose": "Compose new toot",
172 173
   "navigation_bar.direct": "Direct messages",
173 174
   "navigation_bar.discover": "Discover",
174 175
   "navigation_bar.domain_blocks": "Hidden domains",
@@ -263,6 +264,7 @@
263 264
   "status.cancel_reblog_private": "Unboost",
264 265
   "status.cannot_reblog": "This post cannot be boosted",
265 266
   "status.delete": "Delete",
267
+  "status.detailed_status": "Detailed conversation view",
266 268
   "status.direct": "Direct message @{name}",
267 269
   "status.embed": "Embed",
268 270
   "status.favourite": "Favourite",
@@ -300,7 +302,7 @@
300 302
   "trends.count_by_accounts": "{count} {rawCount, plural, one {person} other {people}} talking",
301 303
   "ui.beforeunload": "Your draft will be lost if you leave Mastodon.",
302 304
   "upload_area.title": "Drag & drop to upload",
303
-  "upload_button.label": "Add media",
305
+  "upload_button.label": "Add media (JPEG, PNG, GIF, WebM, MP4)",
304 306
   "upload_form.description": "Describe for the visually impaired",
305 307
   "upload_form.focus": "Crop",
306 308
   "upload_form.undo": "Delete",

+ 2
- 0
app/javascript/mastodon/locales/eo.json View File

@@ -165,6 +165,7 @@
165 165
   "navigation_bar.apps": "Mobile apps",
166 166
   "navigation_bar.blocks": "Blokitaj uzantoj",
167 167
   "navigation_bar.community_timeline": "Loka tempolinio",
168
+  "navigation_bar.compose": "Compose new toot",
168 169
   "navigation_bar.direct": "Rektaj mesaĝoj",
169 170
   "navigation_bar.discover": "Esplori",
170 171
   "navigation_bar.domain_blocks": "Kaŝitaj domajnoj",
@@ -258,6 +259,7 @@
258 259
   "status.cancel_reblog_private": "Eksdiskonigi",
259 260
   "status.cannot_reblog": "Ĉi tiu mesaĝo ne diskonigeblas",
260 261
   "status.delete": "Forigi",
262
+  "status.detailed_status": "Detailed conversation view",
261 263
   "status.direct": "Rekte mesaĝi @{name}",
262 264
   "status.embed": "Enkorpigi",
263 265
   "status.favourite": "Stelumi",

+ 2
- 0
app/javascript/mastodon/locales/es.json View File

@@ -165,6 +165,7 @@
165 165
   "navigation_bar.apps": "Mobile apps",
166 166
   "navigation_bar.blocks": "Usuarios bloqueados",
167 167
   "navigation_bar.community_timeline": "Historia local",
168
+  "navigation_bar.compose": "Compose new toot",
168 169
   "navigation_bar.direct": "Direct messages",
169 170
   "navigation_bar.discover": "Discover",
170 171
   "navigation_bar.domain_blocks": "Hidden domains",
@@ -258,6 +259,7 @@
258 259
   "status.cancel_reblog_private": "Unboost",
259 260
   "status.cannot_reblog": "Este toot no puede retootearse",
260 261
   "status.delete": "Borrar",
262
+  "status.detailed_status": "Detailed conversation view",
261 263
   "status.direct": "Direct message @{name}",
262 264
   "status.embed": "Incrustado",
263 265
   "status.favourite": "Favorito",

+ 2
- 0
app/javascript/mastodon/locales/eu.json View File

@@ -165,6 +165,7 @@
165 165
   "navigation_bar.apps": "Mobile apps",
166 166
   "navigation_bar.blocks": "Blokeatutako erabiltzaileak",
167 167
   "navigation_bar.community_timeline": "Denbora-lerro lokala",
168
+  "navigation_bar.compose": "Compose new toot",
168 169
   "navigation_bar.direct": "Mezu zuzenak",
169 170
   "navigation_bar.discover": "Aurkitu",
170 171
   "navigation_bar.domain_blocks": "Ezkutatutako domeinuak",
@@ -258,6 +259,7 @@
258 259
   "status.cancel_reblog_private": "Kendu bultzada",
259 260
   "status.cannot_reblog": "Mezu honi ezin zaio bultzada eman",
260 261
   "status.delete": "Ezabatu",
262
+  "status.detailed_status": "Detailed conversation view",
261 263
   "status.direct": "Mezu zuzena @{name}(r)i",
262 264
   "status.embed": "Txertatu",
263 265
   "status.favourite": "Gogokoa",

+ 2
- 0
app/javascript/mastodon/locales/fa.json View File

@@ -165,6 +165,7 @@
165 165
   "navigation_bar.apps": "Mobile apps",
166 166
   "navigation_bar.blocks": "کاربران مسدودشده",
167 167
   "navigation_bar.community_timeline": "نوشته‌های محلی",
168
+  "navigation_bar.compose": "Compose new toot",
168 169
   "navigation_bar.direct": "پیغام‌های خصوصی",
169 170
   "navigation_bar.discover": "گشت و گذار",
170 171
   "navigation_bar.domain_blocks": "دامین‌های پنهان‌شده",
@@ -258,6 +259,7 @@
258 259
   "status.cancel_reblog_private": "حذف بازبوق",
259 260
   "status.cannot_reblog": "این نوشته را نمی‌شود بازبوقید",
260 261
   "status.delete": "پاک‌کردن",
262
+  "status.detailed_status": "Detailed conversation view",
261 263
   "status.direct": "پیغام مستقیم به @{name}",
262 264
   "status.embed": "جاگذاری",
263 265
   "status.favourite": "پسندیدن",

+ 2
- 0
app/javascript/mastodon/locales/fi.json View File

@@ -165,6 +165,7 @@
165 165
   "navigation_bar.apps": "Mobile apps",
166 166
   "navigation_bar.blocks": "Estetyt käyttäjät",
167 167
   "navigation_bar.community_timeline": "Paikallinen aikajana",
168
+  "navigation_bar.compose": "Compose new toot",
168 169
   "navigation_bar.direct": "Viestit",
169 170
   "navigation_bar.discover": "Discover",
170 171
   "navigation_bar.domain_blocks": "Piilotetut verkkotunnukset",
@@ -258,6 +259,7 @@
258 259
   "status.cancel_reblog_private": "Peru buustaus",
259 260
   "status.cannot_reblog": "Tätä julkaisua ei voi buustata",
260 261
   "status.delete": "Poista",
262
+  "status.detailed_status": "Detailed conversation view",
261 263
   "status.direct": "Viesti käyttäjälle @{name}",
262 264
   "status.embed": "Upota",
263 265
   "status.favourite": "Tykkää",

+ 4
- 2
app/javascript/mastodon/locales/fr.json View File

@@ -87,7 +87,7 @@
87 87
   "confirmations.mute.confirm": "Masquer",
88 88
   "confirmations.mute.message": "Confirmez-vous le masquage de {name} ?",
89 89
   "confirmations.redraft.confirm": "Effacer et ré-écrire",
90
-  "confirmations.redraft.message": "Êtes-vous sûr·e de vouloir effacer ce statut pour le ré-écrire ? Vous perdrez toutes ses réponses, ses repartages et ses mises en favori.",
90
+  "confirmations.redraft.message": "Êtes-vous sûr·e de vouloir effacer ce statut pour le ré-écrire ? Ses partages ainsi que ses mises en favori seront perdu·e·s et ses réponses seront orphelines.",
91 91
   "confirmations.unfollow.confirm": "Ne plus suivre",
92 92
   "confirmations.unfollow.message": "Voulez-vous arrêter de suivre {name} ?",
93 93
   "embed.instructions": "Intégrez ce statut à votre site en copiant le code ci-dessous.",
@@ -162,9 +162,10 @@
162 162
   "missing_indicator.label": "Non trouvé",
163 163
   "missing_indicator.sublabel": "Ressource introuvable",
164 164
   "mute_modal.hide_notifications": "Masquer les notifications de cette personne ?",
165
-  "navigation_bar.apps": "Mobile apps",
165
+  "navigation_bar.apps": "Applications mobiles",
166 166
   "navigation_bar.blocks": "Comptes bloqués",
167 167
   "navigation_bar.community_timeline": "Fil public local",
168
+  "navigation_bar.compose": "Compose new toot",
168 169
   "navigation_bar.direct": "Messages directs",
169 170
   "navigation_bar.discover": "Découvrir",
170 171
   "navigation_bar.domain_blocks": "Domaines cachés",
@@ -258,6 +259,7 @@
258 259
   "status.cancel_reblog_private": "Dé-booster",
259 260
   "status.cannot_reblog": "Cette publication ne peut être boostée",
260 261
   "status.delete": "Effacer",
262
+  "status.detailed_status": "Detailed conversation view",
261 263
   "status.direct": "Envoyer un message direct à @{name}",
262 264
   "status.embed": "Intégrer",
263 265
   "status.favourite": "Ajouter aux favoris",

+ 2
- 0
app/javascript/mastodon/locales/gl.json View File

@@ -165,6 +165,7 @@
165 165
   "navigation_bar.apps": "Mobile apps",
166 166
   "navigation_bar.blocks": "Usuarias bloqueadas",
167 167
   "navigation_bar.community_timeline": "Liña temporal local",
168
+  "navigation_bar.compose": "Compose new toot",
168 169
   "navigation_bar.direct": "Mensaxes directas",
169 170
   "navigation_bar.discover": "Discover",
170 171
   "navigation_bar.domain_blocks": "Dominios agochados",
@@ -258,6 +259,7 @@
258 259
   "status.cancel_reblog_private": "Non promover",
259 260
   "status.cannot_reblog": "Esta mensaxe non pode ser promovida",
260 261
   "status.delete": "Eliminar",
262
+  "status.detailed_status": "Detailed conversation view",
261 263
   "status.direct": "Mensaxe directa @{name}",
262 264
   "status.embed": "Incrustar",
263 265
   "status.favourite": "Favorita",

+ 2
- 0
app/javascript/mastodon/locales/he.json View File

@@ -165,6 +165,7 @@
165 165
   "navigation_bar.apps": "Mobile apps",
166 166
   "navigation_bar.blocks": "חסימות",
167 167
   "navigation_bar.community_timeline": "ציר זמן מקומי",
168
+  "navigation_bar.compose": "Compose new toot",
168 169
   "navigation_bar.direct": "Direct messages",
169 170
   "navigation_bar.discover": "Discover",
170 171
   "navigation_bar.domain_blocks": "Hidden domains",
@@ -258,6 +259,7 @@
258 259
   "status.cancel_reblog_private": "Unboost",
259 260
   "status.cannot_reblog": "לא ניתן להדהד הודעה זו",
260 261
   "status.delete": "מחיקה",
262
+  "status.detailed_status": "Detailed conversation view",
261 263
   "status.direct": "Direct message @{name}",
262 264
   "status.embed": "הטמעה",
263 265
   "status.favourite": "חיבוב",

+ 2
- 0
app/javascript/mastodon/locales/hr.json View File

@@ -165,6 +165,7 @@
165 165
   "navigation_bar.apps": "Mobile apps",
166 166
   "navigation_bar.blocks": "Blokirani korisnici",
167 167
   "navigation_bar.community_timeline": "Lokalni timeline",
168
+  "navigation_bar.compose": "Compose new toot",
168 169
   "navigation_bar.direct": "Direct messages",
169 170
   "navigation_bar.discover": "Discover",
170 171
   "navigation_bar.domain_blocks": "Hidden domains",
@@ -258,6 +259,7 @@
258 259
   "status.cancel_reblog_private": "Unboost",
259 260
   "status.cannot_reblog": "Ovaj post ne može biti boostan",
260 261
   "status.delete": "Obriši",
262
+  "status.detailed_status": "Detailed conversation view",
261 263
   "status.direct": "Direct message @{name}",
262 264
   "status.embed": "Embed",
263 265
   "status.favourite": "Označi omiljenim",

+ 2
- 0
app/javascript/mastodon/locales/hu.json View File

@@ -165,6 +165,7 @@
165 165
   "navigation_bar.apps": "Mobile apps",
166 166
   "navigation_bar.blocks": "Tiltott felhasználók",
167 167
   "navigation_bar.community_timeline": "Helyi idővonal",
168
+  "navigation_bar.compose": "Compose new toot",
168 169
   "navigation_bar.direct": "Direct messages",
169 170
   "navigation_bar.discover": "Discover",
170 171
   "navigation_bar.domain_blocks": "Hidden domains",
@@ -258,6 +259,7 @@
258 259
   "status.cancel_reblog_private": "Unboost",
259 260
   "status.cannot_reblog": "Ezen státusz nem rebloggolható",
260 261
   "status.delete": "Törlés",
262
+  "status.detailed_status": "Detailed conversation view",
261 263
   "status.direct": "Direct message @{name}",
262 264
   "status.embed": "Beágyaz",
263 265
   "status.favourite": "Kedvenc",

+ 2
- 0
app/javascript/mastodon/locales/hy.json View File

@@ -165,6 +165,7 @@
165 165
   "navigation_bar.apps": "Mobile apps",
166 166
   "navigation_bar.blocks": "Արգելափակված օգտատերեր",
167 167
   "navigation_bar.community_timeline": "Տեղական հոսք",
168
+  "navigation_bar.compose": "Compose new toot",
168 169
   "navigation_bar.direct": "Direct messages",
169 170
   "navigation_bar.discover": "Discover",
170 171
   "navigation_bar.domain_blocks": "Hidden domains",
@@ -258,6 +259,7 @@
258 259
   "status.cancel_reblog_private": "Unboost",
259 260
   "status.cannot_reblog": "Այս թութը չի կարող տարածվել",
260 261
   "status.delete": "Ջնջել",
262
+  "status.detailed_status": "Detailed conversation view",
261 263
   "status.direct": "Direct message @{name}",
262 264
   "status.embed": "Ներդնել",
263 265
   "status.favourite": "Հավանել",

+ 2
- 0
app/javascript/mastodon/locales/id.json View File

@@ -165,6 +165,7 @@
165 165
   "navigation_bar.apps": "Mobile apps",
166 166
   "navigation_bar.blocks": "Pengguna diblokir",
167 167
   "navigation_bar.community_timeline": "Linimasa lokal",
168
+  "navigation_bar.compose": "Compose new toot",
168 169
   "navigation_bar.direct": "Direct messages",
169 170
   "navigation_bar.discover": "Discover",
170 171
   "navigation_bar.domain_blocks": "Hidden domains",
@@ -258,6 +259,7 @@
258 259
   "status.cancel_reblog_private": "Unboost",
259 260
   "status.cannot_reblog": "This post cannot be boosted",
260 261
   "status.delete": "Hapus",
262
+  "status.detailed_status": "Detailed conversation view",
261 263
   "status.direct": "Direct message @{name}",
262 264
   "status.embed": "Embed",
263 265
   "status.favourite": "Difavoritkan",

+ 2
- 0
app/javascript/mastodon/locales/io.json View File

@@ -165,6 +165,7 @@
165 165
   "navigation_bar.apps": "Mobile apps",
166 166
   "navigation_bar.blocks": "Blokusita uzeri",
167 167
   "navigation_bar.community_timeline": "Lokala tempolineo",
168
+  "navigation_bar.compose": "Compose new toot",
168 169
   "navigation_bar.direct": "Direct messages",
169 170
   "navigation_bar.discover": "Discover",
170 171
   "navigation_bar.domain_blocks": "Hidden domains",
@@ -258,6 +259,7 @@
258 259
   "status.cancel_reblog_private": "Unboost",
259 260
   "status.cannot_reblog": "This post cannot be boosted",
260 261
   "status.delete": "Efacar",
262
+  "status.detailed_status": "Detailed conversation view",
261 263
   "status.direct": "Direct message @{name}",
262 264
   "status.embed": "Embed",
263 265
   "status.favourite": "Favorizar",

+ 2
- 0
app/javascript/mastodon/locales/it.json View File

@@ -165,6 +165,7 @@
165 165
   "navigation_bar.apps": "Mobile apps",
166 166
   "navigation_bar.blocks": "Utenti bloccati",
167 167
   "navigation_bar.community_timeline": "Timeline locale",
168
+  "navigation_bar.compose": "Compose new toot",
168 169
   "navigation_bar.direct": "Messaggi diretti",
169 170
   "navigation_bar.discover": "Scopri",
170 171
   "navigation_bar.domain_blocks": "Domini nascosti",
@@ -258,6 +259,7 @@
258 259
   "status.cancel_reblog_private": "Annulla condivisione",
259 260
   "status.cannot_reblog": "Questo post non può essere condiviso",
260 261
   "status.delete": "Elimina",
262
+  "status.detailed_status": "Detailed conversation view",
261 263
   "status.direct": "Messaggio diretto @{name}",
262 264
   "status.embed": "Incorpora",
263 265
   "status.favourite": "Apprezzato",

+ 3
- 1
app/javascript/mastodon/locales/ja.json View File

@@ -166,9 +166,10 @@
166 166
   "missing_indicator.label": "見つかりません",
167 167
   "missing_indicator.sublabel": "見つかりませんでした",
168 168
   "mute_modal.hide_notifications": "このユーザーからの通知を隠しますか?",
169
-  "navigation_bar.apps": "Mobile apps",
169
+  "navigation_bar.apps": "アプリ",
170 170
   "navigation_bar.blocks": "ブロックしたユーザー",
171 171
   "navigation_bar.community_timeline": "ローカルタイムライン",
172
+  "navigation_bar.compose": "Compose new toot",
172 173
   "navigation_bar.direct": "ダイレクトメッセージ",
173 174
   "navigation_bar.discover": "見つける",
174 175
   "navigation_bar.domain_blocks": "非表示にしたドメイン",
@@ -263,6 +264,7 @@
263 264
   "status.cancel_reblog_private": "ブースト解除",
264 265
   "status.cannot_reblog": "この投稿はブーストできません",
265 266
   "status.delete": "削除",
267
+  "status.detailed_status": "Detailed conversation view",
266 268
   "status.direct": "@{name}さんにダイレクトメッセージ",
267 269
   "status.embed": "埋め込み",
268 270
   "status.favourite": "お気に入り",

+ 2
- 0
app/javascript/mastodon/locales/ka.json View File

@@ -165,6 +165,7 @@
165 165
   "navigation_bar.apps": "Mobile apps",
166 166
   "navigation_bar.blocks": "დაბლოკილი მომხმარებლები",
167 167
   "navigation_bar.community_timeline": "ლოკალური თაიმლაინი",
168
+  "navigation_bar.compose": "Compose new toot",
168 169
   "navigation_bar.direct": "პირდაპირი წერილები",
169 170
   "navigation_bar.discover": "აღმოაჩინე",
170 171
   "navigation_bar.domain_blocks": "დამალული დომენები",
@@ -258,6 +259,7 @@
258 259
   "status.cancel_reblog_private": "ბუსტის მოშორება",
259 260
   "status.cannot_reblog": "ეს პოსტი ვერ დაიბუსტება",
260 261
   "status.delete": "წაშლა",
262
+  "status.detailed_status": "Detailed conversation view",
261 263
   "status.direct": "პირდაპირი წერილი @{name}-ს",
262 264
   "status.embed": "ჩართვა",
263 265
   "status.favourite": "ფავორიტი",

+ 5
- 3
app/javascript/mastodon/locales/ko.json View File

@@ -7,7 +7,7 @@
7 7
   "account.disclaimer_full": "여기 있는 정보는 유저의 프로파일을 정확히 반영하지 못 할 수도 있습니다.",
8 8
   "account.domain_blocked": "도메인 숨겨짐",
9 9
   "account.edit_profile": "프로필 편집",
10
-  "account.endorse": "Feature on profile",
10
+  "account.endorse": "프로필에 나타내기",
11 11
   "account.follow": "팔로우",
12 12
   "account.followers": "팔로워",
13 13
   "account.follows": "팔로우",
@@ -27,7 +27,7 @@
27 27
   "account.show_reblogs": "@{name}의 부스트 보기",
28 28
   "account.unblock": "차단 해제",
29 29
   "account.unblock_domain": "{domain} 숨김 해제",
30
-  "account.unendorse": "Don't feature on profile",
30
+  "account.unendorse": "프로필에 나타내지 않기",
31 31
   "account.unfollow": "팔로우 해제",
32 32
   "account.unmute": "뮤트 해제",
33 33
   "account.unmute_notifications": "@{name}의 알림 뮤트 해제",
@@ -162,9 +162,10 @@
162 162
   "missing_indicator.label": "찾을 수 없습니다",
163 163
   "missing_indicator.sublabel": "이 리소스를 찾을 수 없었습니다",
164 164
   "mute_modal.hide_notifications": "이 사용자로부터의 알림을 뮤트하시겠습니까?",
165
-  "navigation_bar.apps": "Mobile apps",
165
+  "navigation_bar.apps": "모바일 앱",
166 166
   "navigation_bar.blocks": "차단한 사용자",
167 167
   "navigation_bar.community_timeline": "로컬 타임라인",
168
+  "navigation_bar.compose": "Compose new toot",
168 169
   "navigation_bar.direct": "다이렉트 메시지",
169 170
   "navigation_bar.discover": "발견하기",
170 171
   "navigation_bar.domain_blocks": "숨겨진 도메인",
@@ -258,6 +259,7 @@
258 259
   "status.cancel_reblog_private": "부스트 취소",
259 260
   "status.cannot_reblog": "이 포스트는 부스트 할 수 없습니다",
260 261
   "status.delete": "삭제",
262
+  "status.detailed_status": "Detailed conversation view",
261 263
   "status.direct": "@{name}에게 다이렉트 메시지",
262 264
   "status.embed": "공유하기",
263 265
   "status.favourite": "즐겨찾기",

+ 2
- 0
app/javascript/mastodon/locales/nl.json View File

@@ -165,6 +165,7 @@
165 165
   "navigation_bar.apps": "Mobile apps",
166 166
   "navigation_bar.blocks": "Geblokkeerde gebruikers",
167 167
   "navigation_bar.community_timeline": "Lokale tijdlijn",
168
+  "navigation_bar.compose": "Compose new toot",
168 169
   "navigation_bar.direct": "Directe berichten",
169 170
   "navigation_bar.discover": "Ontdekken",
170 171
   "navigation_bar.domain_blocks": "Verborgen domeinen",
@@ -258,6 +259,7 @@
258 259
   "status.cancel_reblog_private": "Niet langer boosten",
259 260
   "status.cannot_reblog": "Deze toot kan niet geboost worden",
260 261
   "status.delete": "Verwijderen",
262
+  "status.detailed_status": "Detailed conversation view",
261 263
   "status.direct": "Directe toot @{name}",
262 264
   "status.embed": "Embed",
263 265
   "status.favourite": "Favoriet",

+ 2
- 0
app/javascript/mastodon/locales/no.json View File

@@ -165,6 +165,7 @@
165 165
   "navigation_bar.apps": "Mobile apps",
166 166
   "navigation_bar.blocks": "Blokkerte brukere",
167 167
   "navigation_bar.community_timeline": "Lokal tidslinje",
168
+  "navigation_bar.compose": "Compose new toot",
168 169
   "navigation_bar.direct": "Direct messages",
169 170
   "navigation_bar.discover": "Discover",
170 171
   "navigation_bar.domain_blocks": "Hidden domains",
@@ -258,6 +259,7 @@
258 259
   "status.cancel_reblog_private": "Unboost",
259 260
   "status.cannot_reblog": "Denne posten kan ikke fremheves",
260 261
   "status.delete": "Slett",
262
+  "status.detailed_status": "Detailed conversation view",
261 263
   "status.direct": "Direct message @{name}",
262 264
   "status.embed": "Bygge inn",
263 265
   "status.favourite": "Lik",

+ 6
- 4
app/javascript/mastodon/locales/oc.json View File

@@ -7,7 +7,7 @@
7 7
   "account.disclaimer_full": "Aquelas informacions de perfil pòdon èsser incomplètas.",
8 8
   "account.domain_blocked": "Domeni amagat",
9 9
   "account.edit_profile": "Modificar lo perfil",
10
-  "account.endorse": "Feature on profile",
10
+  "account.endorse": "Mostrar pel perfil",
11 11
   "account.follow": "Sègre",
12 12
   "account.followers": "Seguidors",
13 13
   "account.follows": "Abonaments",
@@ -27,7 +27,7 @@
27 27
   "account.show_reblogs": "Mostrar los partatges de @{name}",
28 28
   "account.unblock": "Desblocar @{name}",
29 29
   "account.unblock_domain": "Desblocar {domain}",
30
-  "account.unendorse": "Don't feature on profile",
30
+  "account.unendorse": "Mostrar pas pel perfil",
31 31
   "account.unfollow": "Quitar de sègre",
32 32
   "account.unmute": "Quitar de rescondre @{name}",
33 33
   "account.unmute_notifications": "Mostrar las notificacions de @{name}",
@@ -139,7 +139,7 @@
139 139
   "keyboard_shortcuts.hotkey": "Acorchis",
140 140
   "keyboard_shortcuts.legend": "mostrar aquesta legenda",
141 141
   "keyboard_shortcuts.mention": "mencionar l’autor",
142
-  "keyboard_shortcuts.profile": "to open author's profile",
142
+  "keyboard_shortcuts.profile": "per dobrir lo perfil de l’autor",
143 143
   "keyboard_shortcuts.reply": "respondre",
144 144
   "keyboard_shortcuts.search": "anar a la recèrca",
145 145
   "keyboard_shortcuts.toggle_hidden": "mostrar/amagar lo tèxte dels avertiments",
@@ -162,9 +162,10 @@
162 162
   "missing_indicator.label": "Pas trobat",
163 163
   "missing_indicator.sublabel": "Aquesta ressorsa es pas estada trobada",
164 164
   "mute_modal.hide_notifications": "Rescondre las notificacions d’aquesta persona ?",
165
-  "navigation_bar.apps": "Mobile apps",
165
+  "navigation_bar.apps": "Aplicacions mobil",
166 166
   "navigation_bar.blocks": "Personas blocadas",
167 167
   "navigation_bar.community_timeline": "Flux public local",
168
+  "navigation_bar.compose": "Compose new toot",
168 169
   "navigation_bar.direct": "Messatges dirèctes",
169 170
   "navigation_bar.discover": "Trobar",
170 171
   "navigation_bar.domain_blocks": "Domenis resconduts",
@@ -258,6 +259,7 @@
258 259
   "status.cancel_reblog_private": "Quitar de partejar",
259 260
   "status.cannot_reblog": "Aqueste estatut pòt pas èsser partejat",
260 261
   "status.delete": "Escafar",
262
+  "status.detailed_status": "Detailed conversation view",
261 263
   "status.direct": "Messatge per @{name}",
262 264
   "status.embed": "Embarcar",
263 265
   "status.favourite": "Apondre als favorits",

+ 2
- 0
app/javascript/mastodon/locales/pl.json View File

@@ -169,6 +169,7 @@
169 169
   "navigation_bar.apps": "Mobile apps",
170 170
   "navigation_bar.blocks": "Zablokowani użytkownicy",
171 171
   "navigation_bar.community_timeline": "Lokalna oś czasu",
172
+  "navigation_bar.compose": "Compose new toot",
172 173
   "navigation_bar.direct": "Wiadomości bezpośrednie",
173 174
   "navigation_bar.discover": "Odkrywaj",
174 175
   "navigation_bar.domain_blocks": "Ukryte domeny",
@@ -263,6 +264,7 @@
263 264
   "status.cancel_reblog_private": "Cofnij podbicie",
264 265
   "status.cannot_reblog": "Ten wpis nie może zostać podbity",
265 266
   "status.delete": "Usuń",
267
+  "status.detailed_status": "Detailed conversation view",
266 268
   "status.direct": "Wyślij wiadomość bezpośrednią do @{name}",
267 269
   "status.embed": "Osadź",
268 270
   "status.favourite": "Dodaj do ulubionych",

+ 5
- 3
app/javascript/mastodon/locales/pt-BR.json View File

@@ -7,7 +7,7 @@
7 7
   "account.disclaimer_full": "As informações abaixo podem refletir o perfil do usuário de maneira incompleta.",
8 8
   "account.domain_blocked": "Domínio escondido",
9 9
   "account.edit_profile": "Editar perfil",
10
-  "account.endorse": "Feature on profile",
10
+  "account.endorse": "Destacar no perfil",
11 11
   "account.follow": "Seguir",
12 12
   "account.followers": "Seguidores",
13 13
   "account.follows": "Segue",
@@ -27,7 +27,7 @@
27 27
   "account.show_reblogs": "Mostra compartilhamentos de @{name}",
28 28
   "account.unblock": "Desbloquear @{name}",
29 29
   "account.unblock_domain": "Desbloquear {domain}",
30
-  "account.unendorse": "Don't feature on profile",
30
+  "account.unendorse": "Não destacar no perfil",
31 31
   "account.unfollow": "Deixar de seguir",
32 32
   "account.unmute": "Não silenciar @{name}",
33 33
   "account.unmute_notifications": "Retirar silêncio das notificações vindas de @{name}",
@@ -162,9 +162,10 @@
162 162
   "missing_indicator.label": "Não encontrado",
163 163
   "missing_indicator.sublabel": "Esse recurso não pôde ser encontrado",
164 164
   "mute_modal.hide_notifications": "Esconder notificações deste usuário?",
165
-  "navigation_bar.apps": "Mobile apps",
165
+  "navigation_bar.apps": "Apps",
166 166
   "navigation_bar.blocks": "Usuários bloqueados",
167 167
   "navigation_bar.community_timeline": "Local",
168
+  "navigation_bar.compose": "Compose new toot",
168 169
   "navigation_bar.direct": "Mensagens diretas",
169 170
   "navigation_bar.discover": "Descobrir",
170 171
   "navigation_bar.domain_blocks": "Domínios escondidos",
@@ -258,6 +259,7 @@
258 259
   "status.cancel_reblog_private": "Desfazer compartilhamento",
259 260
   "status.cannot_reblog": "Esta postagem não pode ser compartilhada",
260 261
   "status.delete": "Excluir",
262
+  "status.detailed_status": "Detailed conversation view",
261 263
   "status.direct": "Enviar mensagem direta a @{name}",
262 264
   "status.embed": "Incorporar",
263 265
   "status.favourite": "Adicionar aos favoritos",

+ 2
- 0
app/javascript/mastodon/locales/pt.json View File

@@ -165,6 +165,7 @@
165 165
   "navigation_bar.apps": "Mobile apps",
166 166
   "navigation_bar.blocks": "Utilizadores bloqueados",
167 167
   "navigation_bar.community_timeline": "Local",
168
+  "navigation_bar.compose": "Compose new toot",
168 169
   "navigation_bar.direct": "Direct messages",
169 170
   "navigation_bar.discover": "Discover",
170 171
   "navigation_bar.domain_blocks": "Hidden domains",
@@ -258,6 +259,7 @@
258 259
   "status.cancel_reblog_private": "Unboost",
259 260
   "status.cannot_reblog": "Este post não pode ser partilhado",
260 261
   "status.delete": "Eliminar",
262
+  "status.detailed_status": "Detailed conversation view",
261 263
   "status.direct": "Direct message @{name}",
262 264
   "status.embed": "Incorporar",
263 265
   "status.favourite": "Adicionar aos favoritos",

+ 2
- 0
app/javascript/mastodon/locales/ru.json View File

@@ -165,6 +165,7 @@
165 165
   "navigation_bar.apps": "Mobile apps",
166 166
   "navigation_bar.blocks": "Список блокировки",
167 167
   "navigation_bar.community_timeline": "Локальная лента",
168
+  "navigation_bar.compose": "Compose new toot",
168 169
   "navigation_bar.direct": "Личные сообщения",
169 170
   "navigation_bar.discover": "Изучайте",
170 171
   "navigation_bar.domain_blocks": "Скрытые домены",
@@ -258,6 +259,7 @@
258 259
   "status.cancel_reblog_private": "Не продвигать",
259 260
   "status.cannot_reblog": "Этот статус не может быть продвинут",
260 261
   "status.delete": "Удалить",
262
+  "status.detailed_status": "Detailed conversation view",
261 263
   "status.direct": "Написать @{name}",
262 264
   "status.embed": "Встроить",
263 265
   "status.favourite": "Нравится",

+ 2
- 0
app/javascript/mastodon/locales/sk.json View File

@@ -165,6 +165,7 @@
165 165
   "navigation_bar.apps": "Mobile apps",
166 166
   "navigation_bar.blocks": "Blokovaní užívatelia",
167 167
   "navigation_bar.community_timeline": "Lokálna časová os",
168
+  "navigation_bar.compose": "Compose new toot",
168 169
   "navigation_bar.direct": "Súkromné správy",
169 170
   "navigation_bar.discover": "Objavuj",
170 171
   "navigation_bar.domain_blocks": "Skryté domény",
@@ -258,6 +259,7 @@
258 259
   "status.cancel_reblog_private": "Nezdieľaj",
259 260
   "status.cannot_reblog": "Tento príspevok nemôže byť re-tootnutý",
260 261
   "status.delete": "Zmazať",
262
+  "status.detailed_status": "Detailed conversation view",
261 263
   "status.direct": "Súkromná správa @{name}",
262 264
   "status.embed": "Vložiť",
263 265
   "status.favourite": "Páči sa mi",

+ 2
- 0
app/javascript/mastodon/locales/sl.json View File

@@ -165,6 +165,7 @@
165 165
   "navigation_bar.apps": "Mobile apps",
166 166
   "navigation_bar.blocks": "Blocked users",
167 167
   "navigation_bar.community_timeline": "Local timeline",
168
+  "navigation_bar.compose": "Compose new toot",
168 169
   "navigation_bar.direct": "Direct messages",
169 170
   "navigation_bar.discover": "Discover",
170 171
   "navigation_bar.domain_blocks": "Hidden domains",
@@ -258,6 +259,7 @@
258 259
   "status.cancel_reblog_private": "Unboost",
259 260
   "status.cannot_reblog": "This post cannot be boosted",
260 261
   "status.delete": "Delete",
262
+  "status.detailed_status": "Detailed conversation view",
261 263
   "status.direct": "Direct message @{name}",
262 264
   "status.embed": "Embed",
263 265
   "status.favourite": "Favourite",

+ 2
- 0
app/javascript/mastodon/locales/sr-Latn.json View File

@@ -165,6 +165,7 @@
165 165
   "navigation_bar.apps": "Mobile apps",
166 166
   "navigation_bar.blocks": "Blokirani korisnici",
167 167
   "navigation_bar.community_timeline": "Lokalna lajna",
168
+  "navigation_bar.compose": "Compose new toot",
168 169
   "navigation_bar.direct": "Direct messages",
169 170
   "navigation_bar.discover": "Discover",
170 171
   "navigation_bar.domain_blocks": "Hidden domains",
@@ -258,6 +259,7 @@
258 259
   "status.cancel_reblog_private": "Unboost",
259 260
   "status.cannot_reblog": "Ovaj status ne može da se podrži",
260 261
   "status.delete": "Obriši",
262
+  "status.detailed_status": "Detailed conversation view",
261 263
   "status.direct": "Direct message @{name}",
262 264
   "status.embed": "Ugradi na sajt",
263 265
   "status.favourite": "Omiljeno",

+ 2
- 0
app/javascript/mastodon/locales/sr.json View File

@@ -165,6 +165,7 @@
165 165
   "navigation_bar.apps": "Mobile apps",
166 166
   "navigation_bar.blocks": "Блокирани корисници",
167 167
   "navigation_bar.community_timeline": "Локална лајна",
168
+  "navigation_bar.compose": "Compose new toot",
168 169
   "navigation_bar.direct": "Direct messages",
169 170
   "navigation_bar.discover": "Discover",
170 171
   "navigation_bar.domain_blocks": "Hidden domains",
@@ -258,6 +259,7 @@
258 259
   "status.cancel_reblog_private": "Unboost",
259 260
   "status.cannot_reblog": "Овај статус не може да се подржи",
260 261
   "status.delete": "Обриши",
262
+  "status.detailed_status": "Detailed conversation view",
261 263
   "status.direct": "Direct message @{name}",
262 264
   "status.embed": "Угради на сајт",
263 265
   "status.favourite": "Омиљено",

+ 2
- 0
app/javascript/mastodon/locales/sv.json View File

@@ -165,6 +165,7 @@
165 165
   "navigation_bar.apps": "Mobile apps",
166 166
   "navigation_bar.blocks": "Blockerade användare",
167 167
   "navigation_bar.community_timeline": "Lokal tidslinje",
168
+  "navigation_bar.compose": "Compose new toot",
168 169
   "navigation_bar.direct": "Direktmeddelanden",
169 170
   "navigation_bar.discover": "Upptäck",
170 171
   "navigation_bar.domain_blocks": "Dolda domäner",
@@ -258,6 +259,7 @@
258 259
   "status.cancel_reblog_private": "Ta bort knuff",
259 260
   "status.cannot_reblog": "Detta inlägg kan inte knuffas",
260 261
   "status.delete": "Ta bort",
262
+  "status.detailed_status": "Detailed conversation view",
261 263
   "status.direct": "Direktmeddela @{name}",
262 264
   "status.embed": "Bädda in",
263 265
   "status.favourite": "Favorit",

+ 2
- 0
app/javascript/mastodon/locales/te.json View File

@@ -165,6 +165,7 @@
165 165
   "navigation_bar.apps": "Mobile apps",
166 166
   "navigation_bar.blocks": "బ్లాక్ చేయబడిన వినియోగదారులు",
167 167
   "navigation_bar.community_timeline": "స్థానిక కాలక్రమం",
168
+  "navigation_bar.compose": "Compose new toot",
168 169
   "navigation_bar.direct": "ప్రత్యక్ష సందేశాలు",
169 170
   "navigation_bar.discover": "కనుగొను",
170 171
   "navigation_bar.domain_blocks": "దాచిన డొమైన్లు",
@@ -258,6 +259,7 @@
258 259
   "status.cancel_reblog_private": "బూస్ట్ను తొలగించు",
259 260
   "status.cannot_reblog": "ఈ పోస్ట్ను బూస్ట్ చేయడం సాధ్యం కాదు",
260 261
   "status.delete": "తొలగించు",
262
+  "status.detailed_status": "Detailed conversation view",
261 263
   "status.direct": "@{name}కు నేరుగా సందేశం పంపు",
262 264
   "status.embed": "ఎంబెడ్",
263 265
   "status.favourite": "ఇష్టపడు",

+ 2
- 0
app/javascript/mastodon/locales/th.json View File

@@ -165,6 +165,7 @@
165 165
   "navigation_bar.apps": "Mobile apps",
166 166
   "navigation_bar.blocks": "Blocked users",
167 167
   "navigation_bar.community_timeline": "Local timeline",
168
+  "navigation_bar.compose": "Compose new toot",
168 169
   "navigation_bar.direct": "Direct messages",
169 170
   "navigation_bar.discover": "Discover",
170 171
   "navigation_bar.domain_blocks": "Hidden domains",
@@ -258,6 +259,7 @@
258 259
   "status.cancel_reblog_private": "Unboost",
259 260
   "status.cannot_reblog": "This post cannot be boosted",
260 261
   "status.delete": "Delete",
262
+  "status.detailed_status": "Detailed conversation view",
261 263
   "status.direct": "Direct message @{name}",
262 264
   "status.embed": "Embed",
263 265
   "status.favourite": "Favourite",

+ 2
- 0
app/javascript/mastodon/locales/tr.json View File

@@ -165,6 +165,7 @@
165 165
   "navigation_bar.apps": "Mobile apps",
166 166
   "navigation_bar.blocks": "Engellenen kullanıcılar",
167 167
   "navigation_bar.community_timeline": "Yerel zaman tüneli",
168
+  "navigation_bar.compose": "Compose new toot",
168 169
   "navigation_bar.direct": "Direct messages",
169 170
   "navigation_bar.discover": "Discover",
170 171
   "navigation_bar.domain_blocks": "Hidden domains",
@@ -258,6 +259,7 @@
258 259
   "status.cancel_reblog_private": "Unboost",
259 260
   "status.cannot_reblog": "Bu gönderi boost edilemez",
260 261
   "status.delete": "Sil",
262
+  "status.detailed_status": "Detailed conversation view",
261 263
   "status.direct": "Direct message @{name}",
262 264
   "status.embed": "Embed",
263 265
   "status.favourite": "Favorilere ekle",

+ 2
- 0
app/javascript/mastodon/locales/uk.json View File

@@ -165,6 +165,7 @@
165 165
   "navigation_bar.apps": "Mobile apps",
166 166
   "navigation_bar.blocks": "Заблоковані користувачі",
167 167
   "navigation_bar.community_timeline": "Локальна стрічка",
168
+  "navigation_bar.compose": "Compose new toot",
168 169
   "navigation_bar.direct": "Прямі повідомлення",
169 170
   "navigation_bar.discover": "Знайти",
170 171
   "navigation_bar.domain_blocks": "Приховані домени",
@@ -258,6 +259,7 @@
258 259
   "status.cancel_reblog_private": "Unboost",
259 260
   "status.cannot_reblog": "Цей допис не може бути передмухнутий",
260 261
   "status.delete": "Видалити",
262
+  "status.detailed_status": "Detailed conversation view",
261 263
   "status.direct": "Direct message @{name}",
262 264
   "status.embed": "Embed",
263 265
   "status.favourite": "Подобається",

+ 2
- 0
app/javascript/mastodon/locales/zh-CN.json View File

@@ -165,6 +165,7 @@
165 165
   "navigation_bar.apps": "Mobile apps",
166 166
   "navigation_bar.blocks": "已屏蔽的用户",
167 167
   "navigation_bar.community_timeline": "本站时间轴",
168
+  "navigation_bar.compose": "Compose new toot",
168 169
   "navigation_bar.direct": "私信",
169 170
   "navigation_bar.discover": "发现",
170 171
   "navigation_bar.domain_blocks": "已屏蔽的网站",
@@ -258,6 +259,7 @@
258 259
   "status.cancel_reblog_private": "取消转嘟",
259 260
   "status.cannot_reblog": "无法转嘟这条嘟文",
260 261
   "status.delete": "删除",
262
+  "status.detailed_status": "Detailed conversation view",
261 263
   "status.direct": "发送私信给 @{name}",
262 264
   "status.embed": "嵌入",
263 265
   "status.favourite": "收藏",

+ 2
- 0
app/javascript/mastodon/locales/zh-HK.json View File

@@ -165,6 +165,7 @@
165 165
   "navigation_bar.apps": "Mobile apps",
166 166
   "navigation_bar.blocks": "被你封鎖的用戶",
167 167
   "navigation_bar.community_timeline": "本站時間軸",
168
+  "navigation_bar.compose": "Compose new toot",
168 169
   "navigation_bar.direct": "個人訊息",
169 170
   "navigation_bar.discover": "探索",
170 171
   "navigation_bar.domain_blocks": "隱藏的服務站",
@@ -258,6 +259,7 @@
258 259
   "status.cancel_reblog_private": "取消轉推",
259 260
   "status.cannot_reblog": "這篇文章無法被轉推",
260 261
   "status.delete": "刪除",
262
+  "status.detailed_status": "Detailed conversation view",
261 263
   "status.direct": "私訊 @{name}",
262 264
   "status.embed": "鑲嵌",
263 265
   "status.favourite": "收藏",

+ 2
- 0
app/javascript/mastodon/locales/zh-TW.json View File

@@ -165,6 +165,7 @@
165 165
   "navigation_bar.apps": "Mobile apps",
166 166
   "navigation_bar.blocks": "封鎖的使用者",
167 167
   "navigation_bar.community_timeline": "本地時間軸",
168
+  "navigation_bar.compose": "Compose new toot",
168 169
   "navigation_bar.direct": "私訊",
169 170
   "navigation_bar.discover": "探索",
170 171
   "navigation_bar.domain_blocks": "隱藏的站點",
@@ -258,6 +259,7 @@
258 259
   "status.cancel_reblog_private": "取消轉嘟",
259 260
   "status.cannot_reblog": "這篇嘟文無法被轉嘟",
260 261
   "status.delete": "刪除",
262
+  "status.detailed_status": "Detailed conversation view",
261 263
   "status.direct": "發送私訊給 @{name}",
262 264
   "status.embed": "嵌入",
263 265
   "status.favourite": "最愛",

+ 4
- 1
app/javascript/packs/public.js View File

@@ -63,7 +63,10 @@ function main() {
63 63
         .catch(error => console.error(error));
64 64
     }
65 65
 
66
-    new Rellax('.parallax', { speed: -1 });
66
+    const parallaxComponents = document.querySelectorAll('.parallax');
67
+    if (parallaxComponents.length > 0 ) {
68
+      new Rellax('.parallax', { speed: -1 });
69
+    }
67 70
 
68 71
     const history = createHistory();
69 72
     const detailedStatuses = document.querySelectorAll('.public-layout .detailed-status');

+ 3
- 1
app/lib/activitypub/activity.rb View File

@@ -104,7 +104,9 @@ class ActivityPub::Activity
104 104
 
105 105
   def crawl_links(status)
106 106
     return if status.spoiler_text?
107
-    LinkCrawlWorker.perform_async(status.id)
107
+
108
+    # Spread out crawling randomly to avoid DDoSing the link
109
+    LinkCrawlWorker.perform_in(rand(1..59).seconds, status.id)
108 110
   end
109 111
 
110 112
   def distribute_to_followers(status)

+ 15
- 1
app/lib/activitypub/activity/create.rb View File

@@ -48,7 +48,7 @@ class ActivityPub::Activity::Create < ActivityPub::Activity
48 48
       account: @account,
49 49
       text: text_from_content || '',
50 50
       language: detected_language,
51
-      spoiler_text: @object['summary'] || '',
51
+      spoiler_text: text_from_summary || '',
52 52
       created_at: @object['published'],
53 53
       override_timestamps: @options[:override_timestamps],
54 54
       reply: @object['inReplyTo'].present?,
@@ -193,6 +193,14 @@ class ActivityPub::Activity::Create < ActivityPub::Activity
193 193
     end
194 194
   end
195 195
 
196
+  def text_from_summary
197
+    if @object['summary'].present?
198
+      @object['summary']
199
+    elsif summary_language_map?
200
+      @object['summaryMap'].values.first
201
+    end
202
+  end
203
+
196 204
   def text_from_name
197 205
     if @object['name'].present?
198 206
       @object['name']
@@ -206,6 +214,8 @@ class ActivityPub::Activity::Create < ActivityPub::Activity
206 214
       @object['contentMap'].keys.first
207 215
     elsif name_language_map?
208 216
       @object['nameMap'].keys.first
217
+    elsif summary_language_map?
218
+      @object['summaryMap'].keys.first
209 219
     elsif supported_object_type?
210 220
       LanguageDetector.instance.detect(text_from_content, @account)
211 221
     end
@@ -223,6 +233,10 @@ class ActivityPub::Activity::Create < ActivityPub::Activity
223 233
     end
224 234
   end
225 235
 
236
+  def summary_language_map?
237
+    @object['summaryMap'].is_a?(Hash) && !@object['summaryMap'].empty?
238
+  end
239
+
226 240
   def content_language_map?
227 241
     @object['contentMap'].is_a?(Hash) && !@object['contentMap'].empty?
228 242
   end

+ 1
- 1
app/views/admin/reports/_status.html.haml View File

@@ -14,7 +14,7 @@
14 14
     - unless status.proper.media_attachments.empty?
15 15
       - if status.proper.media_attachments.first.video?
16 16
         - video = status.proper.media_attachments.first
17
-        = react_component :video, src: video.file.url(:original), preview: video.file.url(:small), sensitive: status.proper.sensitive? && !current_account&.user&.setting_display_sensitive_media, width: 610, height: 343, inline: true
17
+        = react_component :video, src: video.file.url(:original), preview: video.file.url(:small), sensitive: status.proper.sensitive? && !current_account&.user&.setting_display_sensitive_media, width: 610, height: 343, inline: true, alt: video.description
18 18
       - else
19 19
         = react_component :media_gallery, height: 343, sensitive: status.proper.sensitive? && !current_account&.user&.setting_display_sensitive_media, 'autoPlayGif': current_account&.user&.setting_auto_play_gif, media: status.proper.media_attachments.map { |a| ActiveModelSerializers::SerializableResource.new(a, serializer: REST::MediaAttachmentSerializer).as_json }
20 20
 

+ 1
- 5
app/views/layouts/application.html.haml View File

@@ -30,9 +30,5 @@
30 30
     = render partial: 'layouts/theme', object: @core
31 31
     = render partial: 'layouts/theme', object: @theme
32 32
 
33
-  - body_classes ||= @body_classes || ''
34
-  - body_classes += ' system-font' if current_account&.user&.setting_system_font_ui
35
-  - body_classes += current_account&.user&.setting_reduce_motion ? ' reduce-motion' : ' no-reduce-motion'
36
-
37
-  %body{ class: add_rtl_body_class(body_classes) }
33
+  %body{ class: body_classes }
38 34
     = content_for?(:content) ? yield(:content) : yield

+ 1
- 1
app/views/stream_entries/_detailed_status.html.haml View File

@@ -21,7 +21,7 @@
21 21
   - if !status.media_attachments.empty?
22 22
     - if status.media_attachments.first.video?
23 23
       - video = status.media_attachments.first
24
-      = react_component :video, src: video.file.url(:original), preview: video.file.url(:small), sensitive: status.sensitive? && !current_account&.user&.setting_display_sensitive_media, width: 670, height: 380, detailed: true, inline: true
24
+      = react_component :video, src: video.file.url(:original), preview: video.file.url(:small), sensitive: status.sensitive? && !current_account&.user&.setting_display_sensitive_media, width: 670, height: 380, detailed: true, inline: true, alt: video.description
25 25
     - else
26 26
       = react_component :media_gallery, height: 380, sensitive: status.sensitive? && !current_account&.user&.setting_display_sensitive_media, standalone: true, 'autoPlayGif': current_account&.user&.setting_auto_play_gif, 'reduceMotion': current_account&.user&.setting_reduce_motion, media: status.media_attachments.map { |a| ActiveModelSerializers::SerializableResource.new(a, serializer: REST::MediaAttachmentSerializer).as_json }
27 27
   - elsif status.preview_cards.first

+ 1
- 1
app/views/stream_entries/_simple_status.html.haml View File

@@ -25,7 +25,7 @@
25 25
   - unless status.media_attachments.empty?
26 26
     - if status.media_attachments.first.video?
27 27
       - video = status.media_attachments.first
28
-      = react_component :video, src: video.file.url(:original), preview: video.file.url(:small), sensitive: status.sensitive? && !current_account&.user&.setting_display_sensitive_media, width: 610, height: 343, inline: true
28
+      = react_component :video, src: video.file.url(:original), preview: video.file.url(:small), sensitive: status.sensitive? && !current_account&.user&.setting_display_sensitive_media, width: 610, height: 343, inline: true, alt: video.description
29 29
     - else
30 30
       = react_component :media_gallery, height: 343, sensitive: status.sensitive? && !current_account&.user&.setting_display_sensitive_media, 'autoPlayGif': current_account&.user&.setting_auto_play_gif, media: status.media_attachments.map { |a| ActiveModelSerializers::SerializableResource.new(a, serializer: REST::MediaAttachmentSerializer).as_json }
31 31
 

+ 1
- 1
app/workers/maintenance/destroy_media_worker.rb View File

@@ -6,7 +6,7 @@ class Maintenance::DestroyMediaWorker
6 6
   sidekiq_options queue: 'pull'
7 7
 
8 8
   def perform(media_attachment_id)
9
-    media = MediaAttachment.find(media_attachment_id)
9
+    media = media_attachment_id.is_a?(MediaAttachment) ? media_attachment_id : MediaAttachment.find(media_attachment_id)
10 10
     media.destroy
11 11
   rescue ActiveRecord::RecordNotFound
12 12
     true

+ 1
- 1
app/workers/maintenance/redownload_account_media_worker.rb View File

@@ -6,7 +6,7 @@ class Maintenance::RedownloadAccountMediaWorker
6 6
   sidekiq_options queue: 'pull', retry: false
7 7
 
8 8
   def perform(account_id)
9
-    account = Account.find(account_id)
9
+    account = account_id.is_a?(Account) ? account_id : Account.find(account_id)
10 10
     account.reset_avatar!
11 11
     account.reset_header!
12 12
     account.save

+ 1
- 1
app/workers/maintenance/uncache_media_worker.rb View File

@@ -6,7 +6,7 @@ class Maintenance::UncacheMediaWorker
6 6
   sidekiq_options queue: 'pull'
7 7
 
8 8
   def perform(media_attachment_id)
9
-    media = MediaAttachment.find(media_attachment_id)
9
+    media = media_attachment_id.is_a?(MediaAttachment) ? media_attachment_id : MediaAttachment.find(media_attachment_id)
10 10
 
11 11
     return if media.file.blank?
12 12
 

+ 1
- 1
app/workers/scheduler/backup_cleanup_scheduler.rb View File

@@ -3,7 +3,7 @@
3 3
 class Scheduler::BackupCleanupScheduler
4 4
   include Sidekiq::Worker
5 5
 
6
-  sidekiq_options unique: :until_executed
6
+  sidekiq_options unique: :until_executed, retry: 0
7 7
 
8 8
   def perform
9 9
     old_backups.reorder(nil).find_each(&:destroy!)

+ 1
- 1
app/workers/scheduler/doorkeeper_cleanup_scheduler.rb View File

@@ -3,7 +3,7 @@
3 3
 class Scheduler::DoorkeeperCleanupScheduler
4 4
   include Sidekiq::Worker
5 5
 
6
-  sidekiq_options unique: :until_executed
6
+  sidekiq_options unique: :until_executed, retry: 0
7 7
 
8 8
   def perform
9 9
     Doorkeeper::AccessToken.where('revoked_at IS NOT NULL').where('revoked_at < NOW()').delete_all

+ 1
- 1
app/workers/scheduler/email_scheduler.rb View File

@@ -3,7 +3,7 @@
3 3
 class Scheduler::EmailScheduler
4 4
   include Sidekiq::Worker
5 5
 
6
-  sidekiq_options unique: :until_executed
6
+  sidekiq_options unique: :until_executed, retry: 0
7 7
 
8 8
   def perform
9 9
     eligible_users.reorder(nil).find_each do |user|

+ 1
- 1
app/workers/scheduler/feed_cleanup_scheduler.rb View File

@@ -3,7 +3,7 @@
3 3
 class Scheduler::FeedCleanupScheduler
4 4
   include Sidekiq::Worker
5 5
 
6
-  sidekiq_options unique: :until_executed
6
+  sidekiq_options unique: :until_executed, retry: 0
7 7
 
8 8
   def perform
9 9
     clean_home_feeds!

+ 1
- 1
app/workers/scheduler/ip_cleanup_scheduler.rb View File

@@ -5,7 +5,7 @@ class Scheduler::IpCleanupScheduler
5 5
 
6 6
   RETENTION_PERIOD = 1.year
7 7
 
8
-  sidekiq_options unique: :until_executed
8
+  sidekiq_options unique: :until_executed, retry: 0
9 9
 
10 10
   def perform
11 11
     time_ago = RETENTION_PERIOD.ago

+ 1
- 1
app/workers/scheduler/media_cleanup_scheduler.rb View File

@@ -3,7 +3,7 @@
3 3
 class Scheduler::MediaCleanupScheduler
4 4
   include Sidekiq::Worker
5 5
 
6
-  sidekiq_options unique: :until_executed
6
+  sidekiq_options unique: :until_executed, retry: 0
7 7
 
8 8
   def perform
9 9
     unattached_media.find_each(&:destroy)

+ 1
- 1
app/workers/scheduler/subscriptions_cleanup_scheduler.rb View File

@@ -3,7 +3,7 @@
3 3
 class Scheduler::SubscriptionsCleanupScheduler
4 4
   include Sidekiq::Worker
5 5
 
6
-  sidekiq_options unique: :until_executed
6
+  sidekiq_options unique: :until_executed, retry: 0
7 7
 
8 8
   def perform
9 9
     Subscription.expired.in_batches.delete_all

+ 1
- 1
app/workers/scheduler/subscriptions_scheduler.rb View File

@@ -3,7 +3,7 @@
3 3
 class Scheduler::SubscriptionsScheduler
4 4
   include Sidekiq::Worker
5 5
 
6
-  sidekiq_options unique: :until_executed
6
+  sidekiq_options unique: :until_executed, retry: 0
7 7
 
8 8
   def perform
9 9
     Pubsubhubbub::SubscribeWorker.push_bulk(expiring_accounts.pluck(:id))

+ 1
- 1
app/workers/scheduler/user_cleanup_scheduler.rb View File

@@ -3,7 +3,7 @@
3 3
 class Scheduler::UserCleanupScheduler
4 4
   include Sidekiq::Worker
5 5
 
6
-  sidekiq_options unique: :until_executed
6
+  sidekiq_options unique: :until_executed, retry: 0
7 7
 
8 8
   def perform
9 9
     User.where('confirmed_at is NULL AND confirmation_sent_at <= ?', 2.days.ago).reorder(nil).find_in_batches do |batch|

+ 4
- 0
bin/tootctl View File

@@ -0,0 +1,4 @@
1
+#!/usr/bin/env ruby
2
+APP_PATH = File.expand_path('../config/application', __dir__)
3
+require_relative '../lib/cli'
4
+Mastodon::CLI.start(ARGV)

+ 2
- 2
config/initializers/paperclip.rb View File

@@ -47,10 +47,10 @@ if ENV['S3_ENABLED'] == 'true'
47 47
     Paperclip::Attachment.default_options[:url] = ':s3_path_url'
48 48
   end
49 49
 
50
-  if ENV.has_key?('S3_CLOUDFRONT_HOST')
50
+  if ENV.has_key?('S3_ALIAS_HOST') || ENV.has_key?('S3_CLOUDFRONT_HOST')
51 51
     Paperclip::Attachment.default_options.merge!(
52 52
       url: ':s3_alias_url',
53
-      s3_host_alias: ENV['S3_CLOUDFRONT_HOST']
53
+      s3_host_alias: ENV['S3_ALIAS_HOST'] || ENV['S3_CLOUDFRONT_HOST']
54 54
     )
55 55
   end
56 56
 elsif ENV['SWIFT_ENABLED'] == 'true'

+ 3
- 0
config/locales/cs.yml View File

@@ -414,6 +414,9 @@ cs:
414 414
       last_delivery: Poslední doručení
415 415
       title: WebSub
416 416
       topic: Téma
417
+    suspensions:
418
+      proceed: Pokračovat
419
+      title: Suspendovat účet %{acct}
417 420
     title: Administrace
418 421
   admin_mailer:
419 422
     new_report:

+ 2
- 0
config/locales/doorkeeper.da.yml View File

@@ -91,7 +91,9 @@ da:
91 91
           unknown: Adgangs-beviset er ugyldigt
92 92
         resource_owner_authenticator_not_configured: Ressource ejeren kunne ikke blive fundet grundet Doorkeeper.configure.resource_owner_authenticator ikke er konfigureret.
93 93
         server_error: Autoriserings serveren blev mødt med en uventet betingelse der forhindrede den i at færdiggøre anmodningen.
94
+        temporarily_unavailable: Autoriserings serveren er på nuværende tidspunkt ikke i stand til at håndtere anmodningen grundet midlertidig overlast eller serveren er ved at blive opdateret.
94 95
         unauthorized_client: Klienten er ikke godkendt til at udføre denne anmodning ved at bruge denne metode.
96
+        unsupported_grant_type: Autoriserings typen understøttes ikke af autoriserings serveren.
95 97
         unsupported_response_type: Godkendelses serveren understøtter ikke denne type respons.
96 98
     flash:
97 99
       applications:

+ 3
- 0
config/locales/en.yml View File

@@ -350,6 +350,9 @@ en:
350 350
       contact_information:
351 351
         email: Business e-mail
352 352
         username: Contact username
353
+      custom_css:
354
+        desc_html: Modify the look with CSS loaded on every page
355
+        title: Custom CSS
353 356
       hero:
354 357
         desc_html: Displayed on the frontpage. At least 600x100px recommended. When not set, falls back to instance thumbnail
355 358
         title: Hero image

+ 15
- 6
config/locales/ja.yml View File

@@ -30,10 +30,14 @@ ja:
30 30
     other_instances: 他のインスタンス
31 31
     privacy_policy: プライバシーポリシー
32 32
     source_code: ソースコード
33
-    status_count_after: トゥート
33
+    status_count_after:
34
+      one: トゥート
35
+      other: トゥート
34 36
     status_count_before: トゥート数
35 37
     terms: 利用規約
36
-    user_count_after: 人
38
+    user_count_after:
39
+      one: 人
40
+      other: 人
37 41
     user_count_before: ユーザー数
38 42
     what_is_mastodon: Mastodon とは?
39 43
   accounts:
@@ -49,7 +53,7 @@ ja:
49 53
     people_followed_by: "%{name} さんがフォロー中のアカウント"
50 54
     people_who_follow: "%{name} さんをフォロー中のアカウント"
51 55
     pin_errors:
52
-      following: 推薦したい人はあなたが既にフォローしている必要があります
56
+      following: おすすめしたい人はあなたが既にフォローしている必要があります
53 57
     posts: トゥート
54 58
     posts_with_replies: トゥートと返信
55 59
     reserved_username: このユーザー名は予約されています
@@ -185,7 +189,7 @@ ja:
185 189
         unsuspend_account: "%{name} さんが %{target} さんの停止を解除しました"
186 190
         update_custom_emoji: "%{name} さんがカスタム絵文字 %{target} を更新しました"
187 191
         update_status: "%{name} さんが %{target} さんの投稿を更新しました"
188
-      deleted_status: "(削除されました)"
192
+      deleted_status: "(削除)"
189 193
       title: 操作履歴
190 194
     custom_emojis:
191 195
       by_domain: ドメイン
@@ -414,6 +418,12 @@ ja:
414 418
       last_delivery: 最終配送
415 419
       title: WebSub
416 420
       topic: トピック
421
+    suspensions:
422
+      bad_acct_msg: 値が一致しませんでした。停止しようとしているアカウントに間違いはありませんか?
423
+      hint_html: 'アカウントの停止を確認するには、以下のフィールドに %{value} と入力してください:'
424
+      proceed: 完全に活動停止させる
425
+      title: "%{acct} を停止"
426
+      warning_html: 'このアカウントを停止すると、このアカウントから次のようなデータが<strong>不可逆的に</strong>削除されます:'
417 427
     title: 管理
418 428
   admin_mailer:
419 429
     new_report:
@@ -645,7 +655,6 @@ ja:
645 655
           quadrillion: Q
646 656
           thousand: K
647 657
           trillion: T
648
-          unit: ''
649 658
   pagination:
650 659
     newer: 新しいトゥート
651 660
     next: 次
@@ -868,7 +877,7 @@ ja:
868 877
     recovery_codes_regenerated: リカバリーコードが再生成されました
869 878
     recovery_instructions_html: 携帯電話を紛失した場合、以下の内どれかのリカバリーコードを使用してアカウントへアクセスすることができます。<strong>リカバリーコードは大切に保全してください。</strong>たとえば印刷してほかの重要な書類と一緒に保管することができます。
870 879
     setup: 初期設定
871
-    wrong_code: コードが間違っています。サーバー上の時間とデバイス上の時間が一致していることを確認してください。
880
+    wrong_code: コードが間違っています。サーバー上の時間とデバイス上の時間が一致していますか?
872 881
   user_mailer:
873 882
     backup_ready:
874 883
       explanation: Mastodonアカウントのアーカイブを受け付けました。今すぐダウンロードできます!

+ 6
- 0
config/locales/ka.yml View File

@@ -6,6 +6,7 @@ ka:
6 6
     about_this: შესახებ
7 7
     administered_by: 'ადმინისტრატორი:'
8 8
     api: აპი
9
+    apps: მობილური აპლიკაციები
9 10
     closed_registrations: რეგისტრაციები ამჟამად ინსტანციაზე დახურულია. თუმცა! ანგარიშის შესაქმნელად შეგიძლიათ იპოვოთ სხვა ინსტანცია და იმავე ქსელზე იქონიოთ წვდომა იქიდან.
10 11
     contact: კონტაქტი
11 12
     contact_missing: არაა დაყენებული
@@ -281,6 +282,7 @@ ka:
281 282
       search: ძებნა
282 283
       title: ცნობილი ინსტანციები
283 284
     invites:
285
+      deactivate_all: ყველას დეაქტივაცია
284 286
       filter:
285 287
         all: ყველა
286 288
         available: ხელმისაწვდომი
@@ -660,6 +662,9 @@ ka:
660 662
     no_account_html: არ გაქვთ ანგარიში? შეგიძლიათ <a href='%{sign_up_path}' target='_blank'>დარეგისტრირდეთ აქ</a>
661 663
     proceed: გააგრძელეთ გასაყოლად
662 664
     prompt: 'თქვენ გაჰყვებით:'
665
+  remote_interaction:
666
+    proceed: გააგრძელეთ ურთიერთქმედება
667
+    prompt: 'თქვენ გსურთ ურთიერთქმედება ამ ტუტთან:'
663 668
   remote_unfollow:
664 669
     error: შეცდომა
665 670
     title: სათაური
@@ -743,6 +748,7 @@ ka:
743 748
       private: არა-საჯარო ტუტი ვერ აიპინება
744 749
       reblog: ბუსტი ვერ აიპინება
745 750
     show_more: მეტის ჩვენება
751
+    sign_in_to_participate: საუბარში მონაწილეობისთვის გაიარეთ ავტორიზაცია
746 752
     title: '%{name}: "%{quote}"'
747 753
     visibilities:
748 754
       private: მხოლოდ-მიმდევრები

+ 1
- 1
config/locales/ko.yml View File

@@ -640,7 +640,7 @@ ko:
640 640
     publishing: 퍼블리싱
641 641
     web: 웹
642 642
   remote_follow:
643
-    acct: 아이디@도메인을 입력해 주십시오
643
+    acct: 당신이 사용하는 아이디@도메인을 입력해 주십시오
644 644
     missing_resource: 리디렉션 대상을 찾을 수 없습니다
645 645
     no_account_html: 계정이 없나요? <a href='%{sign_up_path}' target='_blank'>여기에서 가입 할 수 있습니다</a>
646 646
     proceed: 팔로우 하기

+ 1
- 1
config/locales/simple_form.fr.yml View File

@@ -30,7 +30,7 @@ fr:
30 30
       imports:
31 31
         data: Un fichier CSV généré par une autre instance de Mastodon
32 32
       sessions:
33
-        otp: 'Entrez le code d’authentification à deux facteurs généré par votre téléphone ou utilisez un de vos codes de récupération :'
33
+        otp: 'Entrez le code d’authentification à deux facteurs généré par l''application de votre téléphone ou utilisez un de vos codes de récupération :'
34 34
       user:
35 35
         chosen_languages: Lorsque coché, seuls les pouets dans les langues sélectionnées seront affichés sur les fils publics
36 36
     labels:

+ 2
- 2
config/webpack/production.js View File

@@ -23,8 +23,8 @@ try {
23 23
 let attachmentHost;
24 24
 
25 25
 if (process.env.S3_ENABLED === 'true') {
26
-  if (process.env.S3_CLOUDFRONT_HOST) {
27
-    attachmentHost = process.env.S3_CLOUDFRONT_HOST;
26
+  if (process.env.S3_ALIAS_HOST || process.env.S3_CLOUDFRONT_HOST) {
27
+    attachmentHost = process.env.S3_ALIAS_HOST || process.env.S3_CLOUDFRONT_HOST;
28 28
   } else {
29 29
     attachmentHost = process.env.S3_HOSTNAME || `s3-${process.env.S3_REGION || 'us-east-1'}.amazonaws.com`;
30 30
   }

+ 11
- 0
lib/cli.rb View File

@@ -0,0 +1,11 @@
1
+# frozen_string_literal: true
2
+
3
+require 'thor'
4
+require_relative 'mastodon/media_cli'
5
+
6
+module Mastodon
7
+  class CLI < Thor
8
+    desc 'media SUBCOMMAND ...ARGS', 'manage media files'
9
+    subcommand 'media', Mastodon::MediaCLI
10
+  end
11
+end

+ 47
- 0
lib/mastodon/media_cli.rb View File

@@ -0,0 +1,47 @@
1
+# frozen_string_literal: true
2
+
3
+require_relative '../../config/boot'
4
+require_relative '../../config/environment'
5
+
6
+# rubocop:disable Rails/Output
7
+
8
+module Mastodon
9
+  class MediaCLI < Thor
10
+    option :days, type: :numeric, default: 7
11
+    option :background, type: :boolean, default: false
12
+    desc 'remove', 'remove remote media files'
13
+    long_desc <<-DESC
14
+      Removes locally cached copies of media attachments from other servers.
15
+
16
+      The --days option specifies how old media attachments have to be before
17
+      they are removed. It defaults to 7 days.
18
+
19
+      With the --background option, instead of deleting the files sequentially,
20
+      they will be queued into Sidekiq and the command will exit as soon as
21
+      possible. In Sidekiq they will be processed with higher concurrency, but
22
+      it may impact other operations of the Mastodon server, and it may overload
23
+      the underlying file storage.
24
+    DESC
25
+    def remove
26
+      time_ago = options[:days].days.ago
27
+      queued   = 0
28
+
29
+      MediaAttachment.where.not(remote_url: '').where.not(file_file_name: nil).where('created_at < ?', time_ago).select(:id).reorder(nil).find_in_batches do |media_attachments|
30
+        if options[:background]
31
+          queued += media_attachments.size
32
+          Maintenance::UncacheMediaWorker.push_bulk(media_attachments.map(&:id))
33
+        else
34
+          media_attachments.each do |m|
35
+            Maintenance::UncacheMediaWorker.new.perform(m)
36
+            print '.'
37
+          end
38
+        end
39
+      end
40
+
41
+      puts
42
+      puts "Scheduled the deletion of #{queued} media attachments" if options[:background]
43
+    end
44
+  end
45
+end
46
+
47
+# rubocop:enable Rails/Output

+ 4
- 9
lib/tasks/mastodon.rake View File

@@ -222,7 +222,7 @@ namespace :mastodon do
222 222
         end
223 223
 
224 224
         if prompt.yes?('Do you want to access the uploaded files from your own domain?')
225
-          env['S3_CLOUDFRONT_HOST'] = prompt.ask('Domain for uploaded files:') do |q|
225
+          env['S3_ALIAS_HOST'] = prompt.ask('Domain for uploaded files:') do |q|
226 226
             q.required true
227 227
             q.default "files.#{env['LOCAL_DOMAIN']}"
228 228
             q.modify :strip
@@ -512,14 +512,9 @@ namespace :mastodon do
512 512
 
513 513
     desc 'Remove cached remote media attachments that are older than NUM_DAYS. By default 7 (week)'
514 514
     task remove_remote: :environment do
515
-      time_ago = ENV.fetch('NUM_DAYS') { 7 }.to_i.days.ago
516
-      nb_media_attachments = 0
517
-
518
-      MediaAttachment.where.not(remote_url: '').where.not(file_file_name: nil).where('created_at < ?', time_ago).select(:id).reorder(nil).find_in_batches do |media_attachments|
519
-        nb_media_attachments += media_attachments.length
520
-        Maintenance::UncacheMediaWorker.push_bulk(media_attachments.map(&:id))
521
-      end
522
-      puts "Scheduled the deletion of #{nb_media_attachments} media attachments"
515
+      require_relative '../mastodon/media_cli'
516
+      cli = Mastodon::MediaCLI.new([], days: ENV['NUM_DAYS'] || 7)
517
+      cli.invoke(:remove)
523 518
     end
524 519
 
525 520
     desc 'Set unknown attachment type for remote-only attachments'

+ 5
- 5
spec/helpers/application_helper_spec.rb View File

@@ -17,7 +17,7 @@ describe ApplicationHelper do
17 17
     end
18 18
   end
19 19
 
20
-  describe 'add_rtl_body_class' do
20
+  describe 'locale_direction' do
21 21
     around do |example|
22 22
       current_locale = I18n.locale
23 23
       example.run
@@ -26,22 +26,22 @@ describe ApplicationHelper do
26 26
 
27 27
     it 'adds rtl body class if locale is Arabic' do
28 28
       I18n.locale = :ar
29
-      expect(helper.add_rtl_body_class('other classes')).to eq 'other classes rtl'
29
+      expect(helper.locale_direction).to eq 'rtl'
30 30
     end
31 31
 
32 32
     it 'adds rtl body class if locale is Farsi' do
33 33
       I18n.locale = :fa
34
-      expect(helper.add_rtl_body_class('other classes')).to eq 'other classes rtl'
34
+      expect(helper.locale_direction).to eq 'rtl'
35 35
     end
36 36
 
37 37
     it 'adds rtl if locale is Hebrew' do
38 38
       I18n.locale = :he
39
-      expect(helper.add_rtl_body_class('other classes')).to eq 'other classes rtl'
39
+      expect(helper.locale_direction).to eq 'rtl'
40 40
     end
41 41
 
42 42
     it 'does not add rtl if locale is Thai' do
43 43
       I18n.locale = :th
44
-      expect(helper.add_rtl_body_class('other classes')).to eq 'other classes'
44
+      expect(helper.locale_direction).to_not eq 'rtl'
45 45
     end
46 46
   end
47 47
 

+ 20
- 3
streaming/index.js View File

@@ -9,6 +9,7 @@ const log = require('npmlog');
9 9
 const url = require('url');
10 10
 const WebSocket = require('uws');
11 11
 const uuid = require('uuid');
12
+const fs = require('fs');
12 13
 
13 14
 const env = process.env.NODE_ENV || 'development';
14 15
 
@@ -70,6 +71,9 @@ const redisUrlToClient = (defaultConfig, redisUrl) => {
70 71
 const numWorkers = +process.env.STREAMING_CLUSTER_NUM || (env === 'development' ? 1 : Math.max(os.cpus().length - 1, 1));
71 72
 
72 73
 const startMaster = () => {
74
+  if (!process.env.SOCKET && process.env.PORT && isNaN(+process.env.PORT)) {
75
+    log.warn('UNIX domain socket is now supported by using SOCKET. Please migrate from PORT hack.');
76
+  }
73 77
   log.info(`Starting streaming API server master with ${numWorkers} workers`);
74 78
 };
75 79
 
@@ -448,6 +452,12 @@ const startWorker = (workerId) => {
448 452
   app.use(setRequestId);
449 453
   app.use(setRemoteAddress);
450 454
   app.use(allowCrossDomain);
455
+
456
+  app.get('/api/v1/streaming/health', (req, res) => {
457
+    res.writeHead(200, { 'Content-Type': 'text/plain' });
458
+    res.end('OK');
459
+  });
460
+
451 461
   app.use(authenticationMiddleware);
452 462
   app.use(errorMiddleware);
453 463
 
@@ -574,9 +584,16 @@ const startWorker = (workerId) => {
574 584
     });
575 585
   }, 30000);
576 586
 
577
-  server.listen(process.env.PORT || 4000, process.env.BIND || '0.0.0.0', () => {
578
-    log.info(`Worker ${workerId} now listening on ${server.address().address}:${server.address().port}`);
579
-  });
587
+  if (process.env.SOCKET || process.env.PORT && isNaN(+process.env.PORT)) {
588
+    server.listen(process.env.SOCKET || process.env.PORT, () => {
589
+      fs.chmodSync(server.address(), 0o666);
590
+      log.info(`Worker ${workerId} now listening on ${server.address()}`);
591
+    });
592
+  } else {
593
+    server.listen(+process.env.PORT || 4000, process.env.BIND || '0.0.0.0', () => {
594
+      log.info(`Worker ${workerId} now listening on ${server.address().address}:${server.address().port}`);
595
+    });
596
+  }
580 597
 
581 598
   const onExit = () => {
582 599
     log.info(`Worker ${workerId} exiting, bye bye`);

Loading…
Cancel
Save