solid_queue_web 1.5.0 → 1.6.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (34) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +179 -5
  3. data/app/assets/stylesheets/solid_queue_web/_04_table.css +28 -0
  4. data/app/controllers/solid_queue_web/application_controller.rb +10 -0
  5. data/app/controllers/solid_queue_web/blocked_jobs_controller.rb +2 -2
  6. data/app/controllers/solid_queue_web/failed_jobs/arguments_controller.rb +3 -3
  7. data/app/controllers/solid_queue_web/failed_jobs/selections_controller.rb +4 -4
  8. data/app/controllers/solid_queue_web/failed_jobs_controller.rb +2 -2
  9. data/app/controllers/solid_queue_web/jobs/selections_controller.rb +3 -3
  10. data/app/controllers/solid_queue_web/jobs_controller.rb +4 -3
  11. data/app/controllers/solid_queue_web/queues/jobs_controller.rb +5 -5
  12. data/app/controllers/solid_queue_web/queues/pauses_controller.rb +4 -4
  13. data/app/controllers/solid_queue_web/recurring_tasks/runs_controller.rb +4 -4
  14. data/app/controllers/solid_queue_web/retry_failed_jobs_controller.rb +4 -5
  15. data/app/controllers/solid_queue_web/scheduled_jobs_controller.rb +5 -5
  16. data/app/views/layouts/solid_queue_web/application.html.erb +20 -17
  17. data/app/views/solid_queue_web/audit/index.html.erb +15 -15
  18. data/app/views/solid_queue_web/dashboard/index.html.erb +67 -46
  19. data/app/views/solid_queue_web/failed_jobs/errors/index.html.erb +7 -7
  20. data/app/views/solid_queue_web/failed_jobs/index.html.erb +31 -31
  21. data/app/views/solid_queue_web/history/index.html.erb +14 -14
  22. data/app/views/solid_queue_web/jobs/index.html.erb +42 -42
  23. data/app/views/solid_queue_web/jobs/show.html.erb +20 -20
  24. data/app/views/solid_queue_web/performance/index.html.erb +16 -14
  25. data/app/views/solid_queue_web/processes/index.html.erb +16 -16
  26. data/app/views/solid_queue_web/queues/index.html.erb +16 -16
  27. data/app/views/solid_queue_web/queues/jobs/index.html.erb +21 -21
  28. data/app/views/solid_queue_web/recurring_tasks/index.html.erb +15 -15
  29. data/app/views/solid_queue_web/search/index.html.erb +13 -13
  30. data/config/locales/en.yml +330 -0
  31. data/lib/solid_queue_web/engine.rb +1 -0
  32. data/lib/solid_queue_web/version.rb +1 -1
  33. data/lib/solid_queue_web.rb +13 -1
  34. metadata +2 -1
@@ -1,9 +1,9 @@
1
1
  <div class="sqd-page-header">
2
2
  <div>
3
3
  <div class="sqd-breadcrumb">
4
- <%= link_to "Queues", queues_path %> &rsaquo; <%= @queue %>
4
+ <%= link_to t("solid_queue_web.queue_jobs.breadcrumb_queues"), queues_path %> &rsaquo; <%= @queue %>
5
5
  </div>
6
- <h1 class="sqd-page-title">Jobs</h1>
6
+ <h1 class="sqd-page-title"><%= t("solid_queue_web.queue_jobs.title") %></h1>
7
7
  </div>
8
8
  </div>
9
9
 
@@ -12,19 +12,19 @@
12
12
 
13
13
  <div class="sqd-page-header">
14
14
  <div class="sqd-filters">
15
- <%= link_to "Ready", queue_jobs_path(queue_name: @queue, status: "ready", q: @search), class: @status == "ready" ? "active" : "" %>
16
- <%= link_to "Scheduled", queue_jobs_path(queue_name: @queue, status: "scheduled", q: @search), class: @status == "scheduled" ? "active" : "" %>
17
- <%= link_to "Running", queue_jobs_path(queue_name: @queue, status: "claimed", q: @search), class: @status == "claimed" ? "active" : "" %>
18
- <%= link_to "Blocked", queue_jobs_path(queue_name: @queue, status: "blocked", q: @search), class: @status == "blocked" ? "active" : "" %>
19
- <%= link_to "Failed", queue_jobs_path(queue_name: @queue, status: "failed", q: @search), class: @status == "failed" ? "active" : "" %>
15
+ <%= link_to t("solid_queue_web.queue_jobs.tab_ready"), queue_jobs_path(queue_name: @queue, status: "ready", q: @search), class: @status == "ready" ? "active" : "" %>
16
+ <%= link_to t("solid_queue_web.queue_jobs.tab_scheduled"), queue_jobs_path(queue_name: @queue, status: "scheduled", q: @search), class: @status == "scheduled" ? "active" : "" %>
17
+ <%= link_to t("solid_queue_web.queue_jobs.tab_running"), queue_jobs_path(queue_name: @queue, status: "claimed", q: @search), class: @status == "claimed" ? "active" : "" %>
18
+ <%= link_to t("solid_queue_web.queue_jobs.tab_blocked"), queue_jobs_path(queue_name: @queue, status: "blocked", q: @search), class: @status == "blocked" ? "active" : "" %>
19
+ <%= link_to t("solid_queue_web.queue_jobs.tab_failed"), queue_jobs_path(queue_name: @queue, status: "failed", q: @search), class: @status == "failed" ? "active" : "" %>
20
20
  </div>
21
21
  <% if discardable && @jobs.any? %>
22
22
  <div class="sqd-actions">
23
- <%= button_to "Discard All", discard_all_queue_jobs_path(queue_name: @queue),
23
+ <%= button_to t("solid_queue_web.queue_jobs.discard_all"), discard_all_queue_jobs_path(queue_name: @queue),
24
24
  method: :post,
25
25
  params: { status: @status },
26
26
  class: "sqd-btn sqd-btn--danger",
27
- data: { confirm: "Discard all #{@jobs.size} #{@status} jobs in #{@queue}? This cannot be undone." } %>
27
+ data: { confirm: t("solid_queue_web.queue_jobs.confirm_discard_all", count: @jobs.size, status: @status, queue: @queue) } %>
28
28
  </div>
29
29
  <% end %>
30
30
  </div>
@@ -32,26 +32,26 @@
32
32
  <form class="sqd-search" action="<%= queue_jobs_path(queue_name: @queue) %>" method="get" data-controller="search">
33
33
  <input type="hidden" name="status" value="<%= @status %>">
34
34
  <input class="sqd-search__input" type="search" name="q" value="<%= @search %>"
35
- placeholder="Filter by job class…" autocomplete="off" aria-label="Filter by job class"
35
+ placeholder="<%= t("solid_queue_web.queue_jobs.placeholder_job_class") %>" autocomplete="off" aria-label="<%= t("solid_queue_web.queue_jobs.aria_filter_job_class") %>"
36
36
  data-action="input->search#filter">
37
- <button type="submit" class="sqd-btn sqd-btn--muted">Search</button>
37
+ <button type="submit" class="sqd-btn sqd-btn--muted"><%= t("solid_queue_web.queue_jobs.search_button") %></button>
38
38
  <% if @search.present? %>
39
- <%= link_to "Clear", queue_jobs_path(queue_name: @queue, status: @status), class: "sqd-btn sqd-btn--muted" %>
39
+ <%= link_to t("solid_queue_web.shared.clear"), queue_jobs_path(queue_name: @queue, status: @status), class: "sqd-btn sqd-btn--muted" %>
40
40
  <% end %>
41
41
  </form>
42
42
 
43
43
  <div class="sqd-card" id="jobs-list">
44
44
  <% if @jobs.empty? %>
45
- <div class="sqd-empty">No <%= @status %> jobs in <%= @queue %>.</div>
45
+ <div class="sqd-empty"><%= t("solid_queue_web.queue_jobs.no_jobs", status: @status, queue: @queue) %></div>
46
46
  <% else %>
47
47
  <table>
48
48
  <thead>
49
49
  <tr>
50
- <th scope="col">Job Class</th>
51
- <th scope="col">Priority</th>
52
- <th scope="col">Scheduled At</th>
53
- <th scope="col">Enqueued At</th>
54
- <% if discardable %><th scope="col"><span class="sqd-sr-only">Actions</span></th><% end %>
50
+ <th scope="col"><%= t("solid_queue_web.queue_jobs.col_job_class") %></th>
51
+ <th scope="col"><%= t("solid_queue_web.queue_jobs.col_priority") %></th>
52
+ <th scope="col"><%= t("solid_queue_web.queue_jobs.col_scheduled_at") %></th>
53
+ <th scope="col"><%= t("solid_queue_web.queue_jobs.col_enqueued_at") %></th>
54
+ <% if discardable %><th scope="col"><span class="sqd-sr-only"><%= t("solid_queue_web.queue_jobs.actions") %></span></th><% end %>
55
55
  </tr>
56
56
  </thead>
57
57
  <tbody>
@@ -69,11 +69,11 @@
69
69
  <td class="sqd-mono"><%= format_timestamp(job.created_at) %></td>
70
70
  <% if discardable %>
71
71
  <td class="sqd-row-actions">
72
- <%= button_to "Discard", queue_job_path(queue_name: @queue, id: execution),
72
+ <%= button_to t("solid_queue_web.queue_jobs.discard"), queue_job_path(queue_name: @queue, id: execution),
73
73
  method: :delete,
74
74
  params: { status: @status },
75
75
  class: "sqd-btn sqd-btn--danger sqd-btn--sm",
76
- data: { confirm: "Discard this job?" } %>
76
+ data: { confirm: t("solid_queue_web.queue_jobs.confirm_discard") } %>
77
77
  </td>
78
78
  <% end %>
79
79
  </tr>
@@ -86,4 +86,4 @@
86
86
  <% if @pagy.last > 1 %>
87
87
  <%= @pagy.series_nav.html_safe %>
88
88
  <% end %>
89
- <% end %>
89
+ <% end %>
@@ -1,20 +1,20 @@
1
- <h1 class="sqd-page-title">Recurring Tasks</h1>
1
+ <h1 class="sqd-page-title"><%= t("solid_queue_web.recurring_tasks.title") %></h1>
2
2
 
3
3
  <div class="sqd-card" style="margin-top: 1.5rem;">
4
4
  <% if @recurring_tasks.empty? %>
5
- <div class="sqd-empty">No recurring tasks configured.</div>
5
+ <div class="sqd-empty"><%= t("solid_queue_web.recurring_tasks.empty") %></div>
6
6
  <% else %>
7
7
  <table>
8
8
  <thead>
9
9
  <tr>
10
- <th scope="col">Key</th>
11
- <th scope="col">Schedule</th>
12
- <th scope="col">Job / Command</th>
13
- <th scope="col">Queue</th>
14
- <th scope="col">Next Run</th>
15
- <th scope="col">Last Run</th>
16
- <th scope="col">Type</th>
17
- <th scope="col"><span class="sqd-sr-only">Actions</span></th>
10
+ <th scope="col"><%= t("solid_queue_web.recurring_tasks.col_key") %></th>
11
+ <th scope="col"><%= t("solid_queue_web.recurring_tasks.col_schedule") %></th>
12
+ <th scope="col"><%= t("solid_queue_web.recurring_tasks.col_job_command") %></th>
13
+ <th scope="col"><%= t("solid_queue_web.recurring_tasks.col_queue") %></th>
14
+ <th scope="col"><%= t("solid_queue_web.recurring_tasks.col_next_run") %></th>
15
+ <th scope="col"><%= t("solid_queue_web.recurring_tasks.col_last_run") %></th>
16
+ <th scope="col"><%= t("solid_queue_web.recurring_tasks.col_type") %></th>
17
+ <th scope="col"><span class="sqd-sr-only"><%= t("solid_queue_web.shared.actions") %></span></th>
18
18
  </tr>
19
19
  </thead>
20
20
  <tbody>
@@ -56,20 +56,20 @@
56
56
  </td>
57
57
  <td>
58
58
  <% if task.static? %>
59
- <span class="sqd-badge sqd-badge--static">Static</span>
59
+ <span class="sqd-badge sqd-badge--static"><%= t("solid_queue_web.recurring_tasks.type_static") %></span>
60
60
  <% else %>
61
- <span class="sqd-badge sqd-badge--dynamic">Dynamic</span>
61
+ <span class="sqd-badge sqd-badge--dynamic"><%= t("solid_queue_web.recurring_tasks.type_dynamic") %></span>
62
62
  <% end %>
63
63
  </td>
64
64
  <td class="sqd-row-actions">
65
- <%= button_to "Run Now", recurring_task_run_path(task.key),
65
+ <%= button_to t("solid_queue_web.recurring_tasks.run_now"), recurring_task_run_path(task.key),
66
66
  method: :post,
67
67
  class: "sqd-btn sqd-btn--primary sqd-btn--sm",
68
- data: { confirm: "Run \"#{task.key}\" immediately?" } %>
68
+ data: { confirm: t("solid_queue_web.recurring_tasks.confirm_run_now", key: task.key) } %>
69
69
  </td>
70
70
  </tr>
71
71
  <% end %>
72
72
  </tbody>
73
73
  </table>
74
74
  <% end %>
75
- </div>
75
+ </div>
@@ -1,4 +1,4 @@
1
- <h1 class="sqd-page-title" style="margin-bottom: 1.5rem;">Search Jobs</h1>
1
+ <h1 class="sqd-page-title" style="margin-bottom: 1.5rem;"><%= t("solid_queue_web.search.title") %></h1>
2
2
 
3
3
  <datalist id="job-class-list">
4
4
  <% @job_classes.each do |klass| %>
@@ -8,42 +8,42 @@
8
8
 
9
9
  <form class="sqd-search sqd-search--global" action="<%= search_path %>" method="get" data-controller="search">
10
10
  <input class="sqd-search__input sqd-search__input--lg" type="search" name="q"
11
- value="<%= @query %>" placeholder="Search by job class name…"
11
+ value="<%= @query %>" placeholder="<%= t("solid_queue_web.search.placeholder") %>"
12
12
  list="job-class-list" autocomplete="off"
13
- aria-label="Search all jobs by class name"
13
+ aria-label="<%= t("solid_queue_web.search.aria_label") %>"
14
14
  data-action="change->search#select">
15
15
  <% if @query.present? %>
16
- <%= link_to "Clear", search_path, class: "sqd-btn sqd-btn--muted" %>
16
+ <%= link_to t("solid_queue_web.search.clear"), search_path, class: "sqd-btn sqd-btn--muted" %>
17
17
  <% end %>
18
18
  </form>
19
19
 
20
20
  <% if @query.present? %>
21
21
  <% if @results.empty? %>
22
- <div class="sqd-empty" style="margin-top: 1rem;">No jobs found matching &ldquo;<%= @query %>&rdquo;.</div>
22
+ <div class="sqd-empty" style="margin-top: 1rem;"><%= t("solid_queue_web.search.no_results", query: @query) %></div>
23
23
  <% else %>
24
24
  <% @results.each do |status, data| %>
25
25
  <div class="sqd-search-group">
26
26
  <div class="sqd-search-group__header">
27
27
  <span class="sqd-badge sqd-badge--<%= status %>"><%= status %></span>
28
28
  <span class="sqd-muted-text">
29
- <%= pluralize(data[:total], "match", "matches") %>
29
+ <%= t("solid_queue_web.search.matches", count: data[:total]) %>
30
30
  <% if data[:total] > SolidQueueWeb.search_results_limit %>
31
- &mdash; showing first <%= SolidQueueWeb.search_results_limit %>
31
+ <%= t("solid_queue_web.search.showing_first", limit: SolidQueueWeb.search_results_limit) %>
32
32
  <% end %>
33
33
  </span>
34
34
  <% if status == "failed" %>
35
- <%= link_to "View all →", failed_jobs_path(q: @query), class: "sqd-btn sqd-btn--muted sqd-btn--sm" %>
35
+ <%= link_to t("solid_queue_web.search.view_all"), failed_jobs_path(q: @query), class: "sqd-btn sqd-btn--muted sqd-btn--sm" %>
36
36
  <% else %>
37
- <%= link_to "View all →", jobs_path(status: status, q: @query), class: "sqd-btn sqd-btn--muted sqd-btn--sm" %>
37
+ <%= link_to t("solid_queue_web.search.view_all"), jobs_path(status: status, q: @query), class: "sqd-btn sqd-btn--muted sqd-btn--sm" %>
38
38
  <% end %>
39
39
  </div>
40
40
  <div class="sqd-card">
41
41
  <table>
42
42
  <thead>
43
43
  <tr>
44
- <th scope="col">Job Class</th>
45
- <th scope="col">Queue</th>
46
- <th scope="col">Enqueued At</th>
44
+ <th scope="col"><%= t("solid_queue_web.search.col_job_class") %></th>
45
+ <th scope="col"><%= t("solid_queue_web.search.col_queue") %></th>
46
+ <th scope="col"><%= t("solid_queue_web.search.col_enqueued_at") %></th>
47
47
  </tr>
48
48
  </thead>
49
49
  <tbody>
@@ -61,4 +61,4 @@
61
61
  </div>
62
62
  <% end %>
63
63
  <% end %>
64
- <% end %>
64
+ <% end %>
@@ -0,0 +1,330 @@
1
+ en:
2
+ solid_queue_web:
3
+ layout:
4
+ title: "Solid Queue Dashboard"
5
+ logo: "Solid Queue"
6
+ theme_toggle: "Switch to dark mode"
7
+ nav:
8
+ main_navigation: "Main navigation"
9
+ toggle: "Toggle navigation"
10
+ dashboard: "Dashboard"
11
+ queues: "Queues"
12
+ jobs: "Jobs"
13
+ history: "History"
14
+ performance: "Performance"
15
+ failed: "Failed"
16
+ recurring: "Recurring"
17
+ processes: "Processes"
18
+ search: "Search"
19
+ audit: "Audit"
20
+ shared:
21
+ actions: "Actions"
22
+ period_filter:
23
+ label: "Time period"
24
+ all: "All"
25
+ one_hour: "1h"
26
+ twenty_four_hours: "24h"
27
+ seven_days: "7d"
28
+ clear: "Clear"
29
+ export_csv: "Export CSV"
30
+ select_all: "Select all"
31
+ filtering_by_queue: "Filtering by queue:"
32
+ clear_filter: "Clear filter"
33
+ dashboard:
34
+ title: "Dashboard"
35
+ ready: "Ready"
36
+ scheduled: "Scheduled"
37
+ running: "Running"
38
+ blocked: "Blocked"
39
+ failed: "Failed"
40
+ queues: "Queues"
41
+ recurring: "Recurring"
42
+ processes: "Processes"
43
+ done_1h: "Done (1h)"
44
+ done_24h: "Done (24h)"
45
+ throughput_label: "Throughput — Last 12 Hours"
46
+ queue_depth_label: "Queue Depth — Last 12 Hours"
47
+ failures_label: "Failures — Last 12 Hours"
48
+ throughput_1h: "1h:"
49
+ throughput_24h: "24h:"
50
+ queue_depth_now: "Now:"
51
+ failures_total: "Total:"
52
+ no_completed_jobs: "No completed jobs in the last 24 hours"
53
+ no_active_jobs: "No active jobs in the last 12 hours"
54
+ no_failures: "No failures in the last 12 hours"
55
+ quick_links: "Quick Links"
56
+ view_ready_jobs: "View all ready jobs"
57
+ view_scheduled_jobs: "View scheduled jobs"
58
+ view_failed_jobs: "View failed jobs"
59
+ manage_queues: "Manage queues"
60
+ view_recurring_tasks: "View recurring tasks"
61
+ failed_jobs_card: "Failed Jobs"
62
+ need_attention:
63
+ one: "1 failed job needs attention."
64
+ other: "%{count} failed jobs need attention."
65
+ retry_all_failed: "Retry All Failed"
66
+ confirm_retry_all_failed:
67
+ one: "Retry all 1 failed job?"
68
+ other: "Retry all %{count} failed jobs?"
69
+ review: "Review →"
70
+ slow_jobs_card: "Slow Jobs"
71
+ slow_jobs_warning:
72
+ one: "1 job running longer than %{threshold}."
73
+ other: "%{count} jobs running longer than %{threshold}."
74
+ blocked_jobs_card: "Blocked Jobs"
75
+ blocked_jobs_count:
76
+ one: "1 blocked job."
77
+ other: "%{count} blocked jobs."
78
+ discard_all_blocked: "Discard All Blocked"
79
+ confirm_discard_all_blocked:
80
+ one: "Discard 1 blocked job? This cannot be undone."
81
+ other: "Discard all %{count} blocked jobs? This cannot be undone."
82
+ axis_now: "now"
83
+ jobs:
84
+ title: "Jobs"
85
+ export_csv: "Export CSV"
86
+ tab_ready: "Ready"
87
+ tab_scheduled: "Scheduled"
88
+ tab_running: "Running"
89
+ tab_blocked: "Blocked"
90
+ tab_failed: "Failed"
91
+ placeholder_job_class: "Filter by job class…"
92
+ aria_filter_job_class: "Filter by job class"
93
+ aria_filter_priority: "Filter by priority"
94
+ all_priorities: "All priorities"
95
+ priority_option: "Priority %{n}"
96
+ clear_search: "Clear"
97
+ col_job_class: "Job Class"
98
+ col_queue: "Queue"
99
+ col_priority: "Priority"
100
+ col_scheduled_at: "Scheduled At"
101
+ col_enqueued_at: "Enqueued At"
102
+ col_running_for: "Running For"
103
+ col_wait_time: "Wait Time"
104
+ actions: "Actions"
105
+ run_all_now: "Run All Now"
106
+ discard_all: "Discard All"
107
+ run_now: "Run Now"
108
+ discard: "Discard"
109
+ discard_selected: "Discard Selected"
110
+ confirm_run_all_now: "Run all %{count} scheduled jobs immediately?"
111
+ confirm_run_now: "Run this job immediately?"
112
+ confirm_discard: "Discard this job?"
113
+ confirm_discard_all: "Discard all %{count} %{status} jobs? This cannot be undone."
114
+ confirm_discard_selected: "Discard selected jobs? This cannot be undone."
115
+ no_jobs: "No %{status} jobs."
116
+ select_job: "Select job %{class_name}"
117
+ select_all_jobs: "Select all jobs"
118
+ selected_label: "selected"
119
+ jobs_show:
120
+ breadcrumb: "Jobs"
121
+ detail: "Detail"
122
+ section_details: "Details"
123
+ section_arguments: "Arguments"
124
+ section_error: "Error"
125
+ retry: "Retry"
126
+ discard: "Discard"
127
+ confirm_discard: "Discard this job?"
128
+ field_status: "Status"
129
+ field_queue: "Queue"
130
+ field_priority: "Priority"
131
+ field_active_job_id: "Active Job ID"
132
+ field_concurrency_key: "Concurrency Key"
133
+ field_blocked_until: "Blocked Until"
134
+ field_enqueued_at: "Enqueued At"
135
+ field_scheduled_at: "Scheduled At"
136
+ field_finished_at: "Finished At"
137
+ arguments_aria_label: "Job arguments JSON"
138
+ retry_with_args: "Retry with these arguments"
139
+ failed_jobs:
140
+ title: "Failed Jobs"
141
+ export_csv: "Export CSV"
142
+ error_summary: "Error Summary"
143
+ retry_all: "Retry All"
144
+ discard_all: "Discard All"
145
+ confirm_retry_all: "Retry all %{count} failed jobs?"
146
+ confirm_discard_all: "Discard all %{count} failed jobs? This cannot be undone."
147
+ confirm_discard: "Discard this job?"
148
+ confirm_discard_selected: "Discard selected jobs? This cannot be undone."
149
+ col_job_class: "Job Class"
150
+ col_queue: "Queue"
151
+ col_error: "Error"
152
+ col_failed_at: "Failed At"
153
+ retry: "Retry"
154
+ discard: "Discard"
155
+ retry_selected: "Retry Selected"
156
+ discard_selected: "Discard Selected"
157
+ select_all: "Select all failed jobs"
158
+ select_job: "Select job %{class_name}"
159
+ empty: "No failed jobs. All clear!"
160
+ stagger_title: "Retry all, staggered %{interval} apart"
161
+ confirm_stagger: "Retry %{count} failed jobs staggered %{interval} apart?"
162
+ failed_job_errors:
163
+ title: "Error Summary"
164
+ back: "← Failed Jobs"
165
+ col_error_class: "Error Class"
166
+ col_message: "Message"
167
+ col_count: "Count"
168
+ empty: "No failed jobs. All clear!"
169
+ queues:
170
+ title: "Queues"
171
+ col_name: "Name"
172
+ col_size: "Size"
173
+ col_latency: "Latency"
174
+ col_done_24h: "Done (24h)"
175
+ col_failed_24h: "Failed (24h)"
176
+ col_failure_rate: "Failure Rate (12h)"
177
+ col_status: "Status"
178
+ actions: "Actions"
179
+ status_paused: "Paused"
180
+ status_running: "Running"
181
+ pause: "Pause"
182
+ resume: "Resume"
183
+ confirm_pause: "Pause queue \"%{name}\"?"
184
+ empty: "No queues found."
185
+ failure_rate_aria: "Failure rate last 12 hours for %{queue}"
186
+ queue_jobs:
187
+ title: "Jobs"
188
+ breadcrumb_queues: "Queues"
189
+ tab_ready: "Ready"
190
+ tab_scheduled: "Scheduled"
191
+ tab_running: "Running"
192
+ tab_blocked: "Blocked"
193
+ tab_failed: "Failed"
194
+ discard_all: "Discard All"
195
+ confirm_discard_all: "Discard all %{count} %{status} jobs in %{queue}? This cannot be undone."
196
+ col_job_class: "Job Class"
197
+ col_priority: "Priority"
198
+ col_scheduled_at: "Scheduled At"
199
+ col_enqueued_at: "Enqueued At"
200
+ actions: "Actions"
201
+ discard: "Discard"
202
+ confirm_discard: "Discard this job?"
203
+ search_button: "Search"
204
+ placeholder_job_class: "Filter by job class…"
205
+ aria_filter_job_class: "Filter by job class"
206
+ no_jobs: "No %{status} jobs in %{queue}."
207
+ processes:
208
+ title: "Processes"
209
+ col_kind: "Kind"
210
+ col_name: "Name"
211
+ col_pid: "PID"
212
+ col_host: "Host"
213
+ col_details: "Details"
214
+ col_last_heartbeat: "Last Heartbeat"
215
+ col_status: "Status"
216
+ status_stale: "Stale"
217
+ status_healthy: "Healthy"
218
+ threads: "%{count} threads"
219
+ polling_interval: "every %{interval}s"
220
+ last_heartbeat_ago: "%{time} ago"
221
+ queues_title: "Queues"
222
+ empty: "No processes registered."
223
+ recurring_tasks:
224
+ title: "Recurring Tasks"
225
+ col_key: "Key"
226
+ col_schedule: "Schedule"
227
+ col_job_command: "Job / Command"
228
+ col_queue: "Queue"
229
+ col_next_run: "Next Run"
230
+ col_last_run: "Last Run"
231
+ col_type: "Type"
232
+ type_static: "Static"
233
+ type_dynamic: "Dynamic"
234
+ run_now: "Run Now"
235
+ confirm_run_now: "Run \"%{key}\" immediately?"
236
+ empty: "No recurring tasks configured."
237
+ history:
238
+ title: "Job History"
239
+ export_csv: "Export CSV"
240
+ col_job_class: "Job Class"
241
+ col_queue: "Queue"
242
+ col_duration: "Duration"
243
+ col_finished_at: "Finished At"
244
+ placeholder_filter: "Filter by job class…"
245
+ aria_filter: "Filter by job class"
246
+ clear: "Clear"
247
+ empty: "No finished jobs found."
248
+ performance:
249
+ title: "Performance"
250
+ col_job_class: "Job Class"
251
+ col_runs: "Runs"
252
+ col_avg: "Avg"
253
+ col_p50: "p50"
254
+ col_p95: "p95"
255
+ col_p99: "p99"
256
+ col_std_dev: "Std Dev"
257
+ col_min: "Min"
258
+ col_max: "Max"
259
+ empty: "No finished jobs found."
260
+ empty_with_period: "No finished jobs found in the last %{period}."
261
+ audit:
262
+ title: "Audit Log"
263
+ export_csv: "Export CSV"
264
+ all_actions: "All actions"
265
+ aria_filter_action: "Filter by action"
266
+ actor_label: "Actor:"
267
+ queue_label: "Queue:"
268
+ clear_all: "Clear"
269
+ col_time: "Time"
270
+ col_action: "Action"
271
+ col_actor: "Actor"
272
+ col_job_class: "Job Class"
273
+ col_queue: "Queue"
274
+ col_count: "Count"
275
+ empty: "No audit events recorded."
276
+ search:
277
+ title: "Search Jobs"
278
+ placeholder: "Search by job class name…"
279
+ aria_label: "Search all jobs by class name"
280
+ clear: "Clear"
281
+ no_results: "No jobs found matching \"%{query}\"."
282
+ matches:
283
+ one: "1 match"
284
+ other: "%{count} matches"
285
+ showing_first: "— showing first %{limit}"
286
+ view_all: "View all →"
287
+ col_job_class: "Job Class"
288
+ col_queue: "Queue"
289
+ col_enqueued_at: "Enqueued At"
290
+ flash:
291
+ job_discarded: "Job discarded."
292
+ jobs_discarded:
293
+ one: "1 job discarded."
294
+ other: "%{count} jobs discarded."
295
+ blocked_jobs_discarded:
296
+ one: "1 blocked job discarded."
297
+ other: "%{count} blocked jobs discarded."
298
+ job_run_immediately: "Job scheduled to run immediately."
299
+ jobs_run_immediately:
300
+ one: "1 job scheduled to run immediately."
301
+ other: "%{count} jobs scheduled to run immediately."
302
+ job_rescheduled: "Job rescheduled by +%{offset}."
303
+ jobs_retried:
304
+ one: "1 job queued for retry."
305
+ other: "%{count} jobs queued for retry."
306
+ jobs_retried_staggered:
307
+ one: "1 job queued for retry, staggered %{stagger} apart."
308
+ other: "%{count} jobs queued for retry, staggered %{stagger} apart."
309
+ arguments_updated: "Job arguments updated and queued for retry."
310
+ task_queued: "\"%{key}\" queued for immediate execution."
311
+ queue_paused: "Queue \"%{name}\" paused."
312
+ queue_resumed: "Queue \"%{name}\" resumed."
313
+ cannot_discard: "Cannot discard %{status} jobs."
314
+ cannot_discard_from_queue: "Cannot discard %{status} jobs from this page."
315
+ cannot_discard_job: "Could not discard job: %{error}"
316
+ cannot_discard_jobs: "Could not discard jobs: %{error}"
317
+ cannot_discard_blocked_jobs: "Could not discard blocked jobs: %{error}"
318
+ cannot_retry_jobs: "Could not retry jobs: %{error}"
319
+ cannot_retry_job: "Could not retry job: %{error}"
320
+ cannot_run_jobs: "Could not run jobs: %{error}"
321
+ cannot_reschedule_job: "Could not reschedule job: %{error}"
322
+ cannot_update_job: "Could not update job: %{error}"
323
+ cannot_pause_queue: "Could not pause queue: %{error}"
324
+ cannot_resume_queue: "Could not resume queue: %{error}"
325
+ cannot_enqueue_task: "Could not enqueue \"%{key}\" — it may have just run."
326
+ task_not_found: "Recurring task not found."
327
+ cannot_run_task: "Could not run task: %{error}"
328
+ invalid_json: "Invalid JSON: could not parse arguments."
329
+ invalid_offset: "Invalid offset."
330
+ invalid_stagger: "Invalid stagger interval."
@@ -8,6 +8,7 @@ module SolidQueueWeb
8
8
  isolate_namespace SolidQueueWeb
9
9
 
10
10
  config.i18n.load_path += Gem.find_files("pagy/locales/en.yml")
11
+ config.i18n.load_path += Dir[root.join("config/locales/*.yml").to_s]
11
12
 
12
13
  initializer "solid_queue_web.assets" do |app|
13
14
  if app.config.respond_to?(:assets)
@@ -1,3 +1,3 @@
1
1
  module SolidQueueWeb
2
- VERSION = "1.5.0"
2
+ VERSION = "1.6.0"
3
3
  end
@@ -7,7 +7,7 @@ module SolidQueueWeb
7
7
  attr_writer :page_size, :dashboard_refresh_interval, :default_refresh_interval, :search_results_limit,
8
8
  :slow_job_threshold, :alert_webhook_url, :alert_failure_threshold, :alert_webhook_cooldown,
9
9
  :alert_queue_thresholds, :alert_slow_job_count_threshold, :alert_stale_process_threshold,
10
- :connects_to, :time_zone
10
+ :connects_to, :time_zone, :available_locales, :nav_links, :dashboard_cards
11
11
 
12
12
  def page_size
13
13
  @page_size || 25
@@ -61,6 +61,18 @@ module SolidQueueWeb
61
61
  @time_zone
62
62
  end
63
63
 
64
+ def available_locales
65
+ @available_locales || %i[en]
66
+ end
67
+
68
+ def nav_links
69
+ @nav_links || []
70
+ end
71
+
72
+ def dashboard_cards
73
+ @dashboard_cards || []
74
+ end
75
+
64
76
  def configure
65
77
  yield self
66
78
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: solid_queue_web
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.5.0
4
+ version: 1.6.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Chuck Smith
@@ -181,6 +181,7 @@ files:
181
181
  - app/views/solid_queue_web/scheduled_jobs/update.turbo_stream.erb
182
182
  - app/views/solid_queue_web/search/index.html.erb
183
183
  - config/importmap.rb
184
+ - config/locales/en.yml
184
185
  - config/routes.rb
185
186
  - db/migrate/01_create_solid_queue_web_audit_events.rb
186
187
  - lib/generators/solid_queue_web/install/migrations_generator.rb